Block binding clarifications

Both UBOs and SSBOs use block binding but I cannot find the answer regarding their correct generation. The numbers used in other tutorials seem to be hard coded and not generated or queried through OpenGL commands like the uniform location indices. What happens when 2 UBOs or 2 SSBOs use the same block binding index in the same shader? How should you use them?

On a lark, I decided to Google for “OpenGL tutorial UBO”. For me:

Hit #1 yielded a website that talks about to do block binding, going through all of the steps, including what to query from OpenGL.

Hit #2 was the OpenGL wiki article on UBOs. Probably because I curate the OpenGL Wiki…

Hit #3 was an ad for a book.

Hit #4 was the lighthouse3d.com tutorial on UBOs. It even has a great diagram showing the relationship and linking between things.

So all of the tutorials in thetop 4 hits explain this. Indeed, I really like the lighthouse3d.com explanation, with the diagram and so forth.

You said “when” as though that were something that could randomly happen. Block binding indices are not assigned randomly; they’re assigned by you. Block binding indices are not handled like uniform locations. They’re set by you (though nowadays, even uniform locations can be set by you). So if you set them to the same binding index, then you’ve screwed up.

Oh and rendering proceeds as normal. It’s a valid if unusual thing to do to assign two uniform blocks to the same binding index.

Block binding indices work a lot like texture binding indices. You use program introspection to convert the name of the interface block into a block index (note that this is not a binding index). Then you set the binding index for that block index with the appropriate function.

Or you just set it in GLSL and don’t bother with doing it from OpenGL code.

I had read the first link too but it doesn’t say anything regarding duplicate block binding indices.
So what happens if I just define all of the block bindings to number 2 in the same program or in different programs?
Should I increment the block binding index each time after I have used it for glShaderStorageBlockBinding(…)?

[QUOTE=EmJayJay;1267488]I had read the first link too but it doesn’t say anything regarding duplicate block binding indices.
So what happens if I just define all of the block bindings to number 2 in the same program or in different programs?[/quote]

For different programs… who cares? They’re different programs. The binding index just tells OpenGL which binding point that particular SSBO uses. If you switch programs, it’s a different SSBO reading from that index. That’s a perfectly normal thing to do, and semantically speaking, it would represent two different programs that read similar data.

For the same program… it’s just two SSBOs that use the same data storage. In C++ terms, think of it as two pointers that point to the same object.

Now that doesn’t mean it’s a good idea, since unless those two SSBO definitions are both identical and use a layout that requires sharing, you’ve done something wrong.

Generally speaking, you should develop your own convention for binding indices. You could decide that UBO index 0 is for general per-object parameters, 1 is for lighting information (which may or may not change per-model, depending on how you do your lighting), and so forth.

If you are calling glShaderStorageBlockBinding more than once per program per SSBO, you’re doing it wrong. And you should certainly not be calling it once per frame. Indeed, if you’re doing program introspection of any kind once per-frame (including querying uniform locations, SSBO indices, etc), you’re doing it wrong.

There’s a reason you’re allowed to set them binding indices the shader; it is a number who’s meaning comes from how the shader uses it, not from your code.

Using the first link’s example as base.
If the shader contains 2 buffer declaration like this

layout (std430, <b>binding=2</b>) buffer shader_data1
{
  ...
}
layout (std430, <b>binding=2</b>) buffer shader_data2
{
  ...
}

And after that you bind the buffers with this

glBindBufferBase(GL_SHADER_STORAGE_BUFFER, shader_data1_binding, ssbo1_id);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, shader_data2_binding, ssbo2_id);

Then which one is actually in use?

You’re really over-thinking this.

Consider this regular old C++ code:


Buffer *bufferArray[16] = {0}; //An array of 16 buffer pointers, initialized to NULL.

bufferArray[5] = some_buffer;
bufferArray[5] = some_other_buffer;

Which buffer does bufferArray[5] point to after this code?

OpenGL works the same way. SSBO binding indices are arrays of buffer binding points. If you bind the same buffer to an index that already contains a buffer, it overwrites the old binding with the new one. That’s how you unbind a buffer from a binding index; you bind 0 there, which binds nothing to that point. Just like setting a pointer to NULL in C++.

Also, as previously suggested, you should not be asking a program what SSBOs are associated with which binding points. You should already know it, by virtue of having written the program or by virtue of an established convention. It’s fine to confirm it explicitly later, but you shouldn’t be asking about it. Thus, your glBindBufferRange/Base call should not be refering to specific SSBO names per-program (like “shader_data1_binding” or “shader_data2_binding”); it should be using C++ enumerators or const(expr) numbers hardcoded into the source.

Instead of thinking, “I need to bind a buffer to binding point Y because the program says that it’s using that binding point”, your thinking should be, “I need to bind data X to binding point Y, because that’s what is expected when rendering.” That the program is using that binding point is understood by the nature of the rendering operation you’re doing, not because you queried into the program and discovered that it was looking at binding points X, Y, and Z.

Not unless your shader is attempting to work with a variety of data sources. But that’s a much harder problem generally to work with than this.

[QUOTE=Alfonse Reinheart;1267493]You’re really over-thinking this.

Consider this regular old C++ code:


Buffer *bufferArray[16] = {0}; //An array of 16 buffer pointers, initialized to NULL.

bufferArray[5] = some_buffer;
bufferArray[5] = some_other_buffer;

Which buffer does bufferArray[5] point to after this code?
[/QUOTE]
Yeah, yeah. some_other_buffer. And this is how I saw it too but didn’t get it from the explanations.

OpenGL works the same way. SSBO binding indices are arrays of buffer binding points. If you bind the same buffer to an index that already contains a buffer, it overwrites the old binding with the new one. That’s how you unbind a buffer from a binding index; you bind 0 there, which binds nothing to that point. Just like setting a pointer to NULL in C++.

Also, as previously suggested, you should not be asking a program what SSBOs are associated with which binding points. You should already know it, by virtue of having written the program or by virtue of an established convention. It’s fine to confirm it explicitly later, but you shouldn’t be asking about it. Thus, your glBindBufferRange/Base call should not be refering to specific SSBO names per-program (like “shader_data1_binding” or “shader_data2_binding”); it should be using C++ enumerators or const(expr) numbers hardcoded into the source.

Ok, got it. Hard code it is. Thanks for clearing up.