Named uniform blocks

Hi everyone,
The below code draws a triangle…

int m_loc=glGetUniformLocation(program,"model_marrix);
Int v_loc=glGetUniformLocation(program,"view_matrix);
int p_loc=glGetUniformLocation(program,"proj_matrix);
glUniformMatrix4fv(m_location,1,GL_FALSE,my_model);
glUniformMatrix4fv(v_location,1,GL_FALSE,my_view);
glUniformMatrix4fv(p_location,1,GL_FALSE,my_proj);

//Vertex shader

uniform mat4 proj_matrix;
uniform mat4 view_matrix;
uniform mat4 model_matrix;
void main()
{
const vec4 position[3]=blah blah blah;
gl_Position=proj_matrix*view_matrix*model_matrix*position[gl_VertexID];
}

while the below one doesn’t

GLuint uboHandle;
glGenBuffer(1,&uboHandle);
glBindBufferBase(GL_UNIFORM_BUFFER,4,uboHandle);
GLfloat my_data[48]={xxxxx....};
glBufferData(GL_UNIFORM_BUFFER,48*sizeof(GLfloat),my_data,GL_DYNAMIC_DRAW);

//Vertex shader

layout(std140,binding=4) uniform matrices
{
mat4 model_matrix;
mat4 view_matrix;
mat4 proj_matrix;
};
void main()
{
const vec4 position[3]=blah blah blah;
gl_Position=proj_matrix*view_matrix*model_matrix*position[gl_VertexID];
}

Data in the buffer is the same data sent in first code. I checked it using glGetBufferSubData. Anyway they are all mat4s. So layout is trivial. So data and matrices are all fine since the first code worked.Matrices declaration order is not the same but I took care of it while filling the buffer. Somehow my shader fails to access data from named uniform block. Wondering what might be the problem.

You cannot call glBindBufferBase (or glBindBufferRange for that matter) on a buffer object for which storage has not yet been created. After all, it doesn’t know how big a size to use yet, since it has no size.

So put that call after the glBufferData call.

I will remember that. It did not solve the problem though. Btw I placed glBindBuffer(GL_UNIFORM_BUFFER,uboHandle) after glGenBuffer followed by glBufferData and glBindBufferBase. To further zero in on the issue, I modified my vertex shader. Since I know my matrices beforehand, I added a long if statement checking each element of the view matrix to see if it is the same which I fed into the buffer. Inside the if block, a simple triangle is specified directly in clip space. Negating the if statement draws this clip space triangle implying that what i fed is not what is inside the shader.

Alright. For the named uniform block “matrices” I used glGetActiveUniformBlockiv and glGetActiveUniformsiv and sent every parameter except name lengths. I printed all the answers in a file. It looks exactly like this.(parameter followed by value)

Binding index 4
size 2222
num of act uniforms 3
indices 0 1 2
Referenced by vertex shader? 1
types 35676 35676 35676
Sizes 1 1 1
block index 0 0 0
Offsets 0 1079 2158
Array stride 0 0 0
Matrix stride 16 16 16

All those value beside are what i got from those calls. Of all these size and offsets look suspicious. What’s 2222? Bytes? Bits? What is type 35676? Why are those offsets so apart? I guess I messed something with std140

Well, maybe you could explain what those “parameters” actually are. Like, the actual OpenGL enumerators.

The first five lines are related to glGetActiveUniformBlockiv with enums

GL_UNIFORM_BLOCK_BINDING,
GL_UNIFORM_BLOCK_DATA_SIZE,
GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, GL_UNIFORM_REFERENCED_BY_VERTEX_SHADER

Ofcourse, I first got block index with glGetUniformBlockIndex(program,“matrices”);

The next 6 lines are related to glGetActiveUniformsiv with the following enums

GL_UNIFORM_TYPE
GL_UNIFORM_SIZE
GL_UNIFORM_BLOCK_INDEX
GL_UNIFORM_OFFSET
GL_UNIFORM_ARRAY_STRIDE
GL_UNIFORM_MATRIX_STRIDE

I removed layout(std140) from my vertex shader. The file looks exactly the same except that ‘size’ now shows 192 and ‘Offsets’ show 0 64 128. Everything is working fine. It draws my triangle. Wondering if I should conclude that a bug exists in my driver which messes with std140 layout.

Bytes. Which actually makes sense given the offsets (2222=2158+64). It’s the offsets which don’t make sense; they’re not even multiples of 4 when they should be multiples of 16 (std140 expands everything to at least a multiple of the size of a float, i.e. 4, and most things get expanded to the size of a vec4).

35676 == 0x8B5C == GL_FLOAT_MAT4.

I think the driver has to be lying to you regarding the offsets. Because it’s not necessary to query offsets for std140 (they can be determined from the structure itself by the programmer, that’s the point), it’s possible that they got that wrong and no-one ever noticed.

With std140, you should be able to simply pack the matrices into a 192-byte buffer and expect it to work. If it was actually using those offset for a std140 block, nothing using std140 would work. And that’s true in practice even without std140; even when the layout is chosen by the implementation, no implementation is going to use an offset of 1079 for anything.