Suppose I have the following vertex shader code:
#version 330
uniform mat4 ProjectionMatrix, CameraMatrix, SingleModelMatrix;
uniform uint SingleModel;
layout (std140) uniform ModelBlock {
mat4 ModelMatrices[128];
};
void main(void) {
... something that uses ModelMatrices
}
If in my program I issue the following OpenGL call for a program object representing the shader above:
getUniformBlockParameter(GL_UNIFORM_BLOCK_DATA_SIZE)
I find out the following with an Intel HD Graphics 4000 card:
GLUniformBlock[
name: ModelBlock,
blockSize: 8192,
buffer: java.nio.HeapByteBuffer[pos=0 lim=8192 cap=8192],
metadata: {
ModelMatrices=GLUniformBlockAttributeMetadata[
name: ModelMatrices,
offset: 0,
arrayStride: 64,
matrixStride: 16,
matrixOrder: 0
]},
uniforms: GLUniformInterface[
uniforms: {
ModelMatrices=GLUFloatMat4 [
name:ModelMatrices,
idx:2,
loc:-1,
size:128,
glType:8b5c]
}
]
]
How should I interpret the blockSize
parameter? The OpenGL 3 sdk docs state that:
If pname is
GL_UNIFORM_BLOCK_DATA_SIZE
, the implementation-dependent minimum total buffer object size, in basic machine units, required to hold all active uniforms in the uniform block identified by uniformBlockIndex is returned. It is neither guaranteed nor expected that a given implementation will arrange uniform values as tightly packed in a buffer object. The exception to this is the std140 uniform block layout, which guarantees specific packing behavior and does not require the application to query for offsets and strides. In this case the minimum size may still be queried, even though it is determined in advance based only on the uniform block declaration.
So in this case how should I measure that 8192 number in blockSize
? In float
s? In byte
s?
If I do the numbers, a 4x4 matrix mat4
uniform has a total of 16 float
components, which fit into 64 bytes
, so at the very least I need about 16 x 4 x 128
bytes to store 128 matrices which is indeed, 8192
.
Why then is the hardware also asking for 64 (bytes
?) for array stride and 16 (bytes
?) of matrix stride, yet requesting only 8192 bytes? Shouldn't getUniformBlockParameter(GL_UNIFORM_BLOCK_DATA_SIZE)
have requested more space for alignment/padding purposes?
The array stride is the byte offset from the start of one array element to the start of the next. The array elements in this case are mat4
s, which are 64 bytes in size. So the array stride is as small as it can be.
The matrix stride is the byte offset from one column/row of matrix data to the next. Each mat4
has a column or row size of a vec4
, which means it is 16 bytes in size. So again, the matrix columns/rows are tightly packed.
So 8KiB is the expected size of such storage.
That being said, this is entirely irrelevant. You shouldn't be bothering to query this stuff at all. By using std140
layout, you have already forced OpenGL to adopt a specific layout. One that notably requires mat4
s to have an array stride of 64 bytes and to have a matrix stride of 16 bytes. You don't have to ask the implementation for this; it's required by the standard.
You only need to ask if you're using shared
or packed
.