UBOs and instancing - nvidia driver bug?

Hi,

I recently tried to use uniform buffer objects for storing instance data, but had several problems along the way.

This is the current vertex shader, it works nicely now:


#version 150
layout(std140) uniform matrices1
{
  struct Mats { mat4 model_view_matrix; mat4 projection_matrix; } mats[4];
};

in vec3 position;
in vec3 color;
out vec3 vertex_color;

void main(void)
{
    gl_Position = mats[gl_InstanceID].model_view_matrix * vec4(position, 1.0);
    vertex_color = color;
}

The weird thing is the declaration of matrices1 here. Initially, I used this:

layout(std140) uniform matrices1
{
  mat4 model_view_matrix;
  mat4 projection_matrix;
} mats[4];

But this did not work at all. Offsets inside the uniform block were all wrong etc. even though this should be identical. My question now is: is there a difference between these two layouts I missed? Or is this a driver bug? Using Linux 64bit 190.29 nvidia drivers, with OpenCL support.

But this did not work at all.

I’m surprised that compiled. Uniform blocks are not struct definitions. So you don’t get to slip the “mats[4]” on the end of them.

BTW, since you’re using the std140 layout, you really don’t need to query the layout of the block. The whole point of using this form of layout is that the layout is defined by the specification. So you know exactly where each variable goes purely based on the definition of the layout.

I’m surprised that compiled. Uniform blocks are not struct definitions. So you don’t get to slip the “mats[4]” on the end of them.

Actually this syntax is shown as an example in the GLSL 1.50 specification, on page 36 (section 4.3.7 Interface Blocks). This is why I am puzzled - it seems to be a valid expression!

He’s saying you can’t define a struct in a uniform block, which is what your first snippet does. Your second snippet should work, but it will require a separate backing buffer for each array element (i.e. the array is flattened into “mats[0]”, “mats[1]”, …).

Ah, so, with the second snippet I need to bind the UBO several times, once per array element, to different binding points? I didn’t try that yet, I only used one binding point, and created one UBO with a flattened array.

EDIT: it is illegal to define the struct inside a block, but nothing forbids it to use a struct as a block member type. I can define the struct outside the block, this works as well. So the last question is, what about the first snippet?

Ah, so, with the second snippet I need to bind the UBO several times, once per array element, to different binding points?

What you’re asking for when you use that syntax is an array of uniform blocks, not a uniform block containing an array.

Just define a struct and stick an array of them inside the uniform block. It’s simpler.

So the last question is, what about the first snippet?

What about it? Don’t define structs in uniform blocks.