Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can OpenGL vertex buffer binding points be reused across different VAOs?

Tags:

opengl

vao

Suppose I set up two VAOs, using the new (as of OpenGL 4.3) glBindVertexBuffer mechanism:

glGenVertexArrays(1, &vaoIndex0);
glGenVertexArrays(1, &vaoIndex1);

...

glBindVertexArray(vaoIndex0)
glBindVertexBuffer(bindingIndex0, ...)
glEnableVertexAttribArray(0)
glVertexAttribFormat(0, ...)
glVertexAttribBinding(0, bindingIndex0)
...
glBindVertexArray(0)

...

glBindVertexArray(vaoIndex1)
glBindVertexBuffer(bindingIndex1, ...)
glEnableVertexAttribArray(0)
glVertexAttribFormat(0, ...)
glVertexAttribBinding(0, bindingIndex1)
...
glBindVertexArray(0)

And suppose the two are independent, except insofar as they exist in the same OpenGL context; they bind different buffers and will be used to draw different things.

Does bindingIndex0 need to be different from bindingIndex1? Is there any significance at all in the equality (or inequality) of the two indices?

...

EDIT:

After receiving an answer I began to understand that to someone who actually knows what a "vertex buffer binding point" is, and particularly, what its scope is, my question might seem to be asking something different than what I intended. Maybe a better phrasing would have been "Does one need to go out of one's way to prevent OpenGL vertex buffer binding point indices from being reused, even across multiple VAOs, in order to prevent conflicts?" But anyway, it seems that both questions have now been answered: No you can't reuse the "binding points", and no you don't need to avoid index conflicts in that way.

like image 950
mjwach Avatar asked Mar 23 '15 21:03

mjwach


1 Answers

All of these calls modify VAO state. So no, you cannot reuse these settings across VAOs. You can of course set them the same in multiple VAOs, but you have to make the necessary state setup calls once when you set up each VAO.

The bindingIndex0 and bindingIndex1 values you use in your code fragment don't have any special meaning. They just establish the connection between the buffer you bind to the binding index with glBindVertexBuffer(), and the attributes you specify as using that binding index.

The only condition is that the binding index has to be smaller than the value you can query as MAX_VERTEX_ATTRIB_BINDINGS, which is guaranteed to be at least 16. Since these calls modify per-VAO state, you absolutely can use the same binding indices for multiple VAOs.

One way of looking at these newer state setup calls is that they introduce a level of indirection that was not previously available:

  • Without these calls, you establish a direct connection between vertex attribute and buffer, by calling glVertexAttribPointer() while the desired buffer is bound.
  • With these newer calls, a vertex attribute now has a connection to a binding index, which is established with glVertexAttribBinding(). The binding index is then connected to a buffer, which is established with glBindVertexBuffer().

In other words, in old style the connection is:

attribute index --> buffer

new style with these 4.3+ calls:

attribute index --> buffer index --> buffer

One advantage of this new flexibility is that you can bind a new buffer to multiple attributes with a single call. As long as all these attributes have the same buffer index, you need just one call to glBindVertexBuffer() to specify a new buffer for all the attributes.

Semi-formal Definition

The following is not official notation at all. I just made it up. But I thought it might be useful to define the relationships more formally, by writing down some pseudo data structures.

Let's say each VAO contains two arrays to capture the connections explained above:

struct VAO {
    ...
    uint bufferIndexBindings[MAX_VERTEX_ATTRIB_BINDINGS];
    uint attribBufferIndices[MAX_VERTEX_ATTRIBS];
}

The two calls discussed here would then modify this structure like this:

glBindVertexBuffer(uint bindingIndex, uint buffer, ...) {
    CurrentVAO.bufferIndexBindings[bindingIndex] = buffer;
}

glVertexAttribBinding(uint attribIndex, uint bindingIndex) {
    CurrentVAO.attribBufferIndices[attribIndex] = bindingIndex;
}

This state is then used to obtain the buffer for a given attribute with index attribIndex as:

CurrentVAO.bufferIndexBindings[CurrentVAO.attribBufferIndices[attribIndex]]

This also illustrates the indirection I explained above, which shows up here as two levels of lookup into the state tables.

like image 144
Reto Koradi Avatar answered Nov 07 '22 22:11

Reto Koradi