3

When created, do VAOs track just VBO indices (via glBindVertexBuffer), or also which VBO names are bound to those indices? If I specify a binding index of, say, 0 using glVertexAttribBinding during VAO creation, can I bind a different VBO to index 0 just prior to a draw call and have it use the contents of that VBO, or will it always use whatever VBO was bound to index 0 at the time the VAO was created?

I ask because a lot of examples I find precede calls to glVertexAttribFormat and glVertexAttribBinding with a call to glBindVertexBuffer, which should not be necessary if the VAO tracks only indices (since the binding index is given in glVertexAttribBinding).

Reto Koradi
  • 49,246
  • 7
  • 76
  • 116
jorgander
  • 540
  • 1
  • 4
  • 12

2 Answers2

4

As you're probably aware, this is fairly new functionality introduced in OpenGL 4.3. The way I read the spec, the mapping between attributes and buffers now has a level of indirection:

  1. Each attribute has a property that specifies which binding index it uses.
  2. Buffers are bound to binding indices.

You can look at this as two tables, one defining a mapping from attribute index to binding index, the other one from binding index to buffer name. Both of these tables are part of the VAO state.

I believe these can be specified completely independently, and in any order. glVertexAttribBinding() establishes the first association, between attribute index and binding index. glBindVertexBuffer() establishes the association between binding index and buffer name.

This understanding is confirmed by the state table in the spec. Table 23.4 in the GL 4.4 spec, captioned "Vertex Array Object State", lists:

  • VERTEX_ATTRIB_BINDING, which can be queried with glGetVertexAttribiv(), is the value of the binding index of a given attribute index.
  • VERTEX_BINDING_BUFFER, which can be queried with glGetIntegeri_v(), is the value of the buffer name for a given binding index.

Based on this, addressing your specific questions:

When created, do VAOs track just VBO indices (via glBindVertexBuffer), or also which VBO names are bound to those indices?

They track both.

can I bind a different VBO to index 0 just prior to a draw call and have it use the contents of that VBO

Yes, if you bind a different VBO to binding index 0, all attributes with binding index 0 will use the content of that VBO.

a lot of examples I find precede calls to glVertexAttribFormat and glVertexAttribBinding with a call to glBindVertexBuffer, which should not be necessary if the VAO tracks only indices

The VAO tracks the state set by all these calls, so it does make sense to use all of them as part of setting up the VAO. Tracking the entire vertex setup state in a VAO is the main purpose of having VAOs in the first place. It allows you to set up the state once during initialization, and then you need only a single call to glBindVertexArray() before your draw calls to set up the entire state again.

Reto Koradi
  • 49,246
  • 7
  • 76
  • 116
  • If the VAO tracks the VBO name assigned to an index, then it doesn't need to keep track of the index. After creation of the VAO, any vertex attribute that referenced that buffer index can now forget the buffer index value and remember only the buffer index name (actually, after `glVertexAttribBinding` is called it can forget the index value). Either way, my confusion arose from this section of the 'official' opengl docs: https://www.opengl.org/wiki/Vertex_Specification#Multibind_and_separation. From that: "... maintain the same format while quickly switching between multiple buffers ..." – jorgander Nov 07 '14 at 01:07
  • I'm not sure how to explain it more clearly. You're saying that "it doesn't need to keep track of the index." Well, you might think that it's not necessary, but that's the way it's specified, and so it works that way. It enables the functionality you found described. The indirection allows you to assign the same buffer index to a number of attributes, and then change which buffer all these attributes use with a single call that binds a different buffer to this index. – Reto Koradi Nov 10 '14 at 01:18
  • I guess the terminology is unclear, plus some of the tutorial/docs seem to conflict. From your response: "Buffers are bound to binding indices." - are the words 'bound' and 'binding' redundant here? If not, what makes 'binding indices' binding other than that VBOs are bound to them? Is the phrase "buffers are bound to indices" equivalent to what you want to say? – jorgander Nov 10 '14 at 06:36
  • From my previous comment: "it is often useful as a developer to maintain the same format while quickly switching between multiple buffers to pull data from. To achieve this...". This implies that you can bind a different buffer to an index after VAO creation, and the VAO will recognize it during draw calls. However, from http://www.arcsynthesis.org/gltut/Positioning/Tutorial%2005.html: "When you call glVertexAttribPointer, OpenGL takes whatever buffer is *at the moment of this call* bound to GL_ARRAY_BUFFER and associates it with the given vertex attribute.". These two seem contradictory. – jorgander Nov 10 '14 at 06:45
  • "binding index" is the term used for these indices in the spec and the man pages. I did my best to follow official terminology in my answer. I might try to add another approach of explaining this later, even though what I wrote seems quite clear to me. – Reto Koradi Nov 10 '14 at 07:12
  • `glVertexAttribPointer()` is the traditional way of defining attributes. What we're discussing here is the new and more flexible approach introduced in OpenGL 4.3. You can obviously use the simpler `glVertexAttribPointer()` if it meets your needs, it's still available in the latest OpenGL versions. – Reto Koradi Nov 10 '14 at 07:16
-1

The answer is that they DO NOT store vertex names, only indices. If you bind a different VBO to the same index in a different VAO, you must re-bind the first VBO again before any glDraw call that uses the first VAO.

At least on my Macbook Pro with:

Renderer: NVidia GeForce GT 650M OpenGL Engine

Version: 4.1 NVIDIA-10.0.43 310.41.05f01

jorgander
  • 540
  • 1
  • 4
  • 12
  • 2
    Your question was about functionality that is only available in OpenGL 4.3 and later. How did you test it on a configuration that only supports OpenGL 4.1? – Reto Koradi Dec 19 '14 at 19:23
  • Correct, I did not test on 4.3+ and as such could not bind a vertex buffer to an index other than 0. However, I assume that if VAOs do not track VBO names in 4.1, they won't track them in 4.3+ either. But it's why I included the specs for my system; YMMV. – jorgander Dec 19 '14 at 23:44