Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Page 1 of 5 123 ... LastLast
Results 1 to 10 of 42

Thread: VBO to VAO

  1. #1
    Intern Contributor
    Join Date
    Jan 2008
    Location
    phobos, mars
    Posts
    75

    VBO to VAO

    VBO: All our geometry is currently drawn from the bound IBO and VBO with glDraw[Range]Elements(). I never did understand why, but we could not make our code work unless we specified the offsets/types/normalizations of every vertex attribute every time we switched to another IBO/VBO pair. Does anyone understand why? Note: the vertices in all our VBOs are identical (same attributes, same offsets, same types, etc).

    VAO: After reading the OpenGL v3.10 specification, I have a few questions about VAOs. The description of VAOs led did not make it clear to me that the VAO remembers and restores the VBO attributes and their offsets/types/normalizations when they are bound. However, table 6.3 and 6.4 seems to clearly state this information is stored with the VAO.

    Here are my VAO questions:

    #1: Does binding the VAO make all this VBO state active too? And does it also somehow make clear to the GPU whether the indices in the corresponding IBO are 16-bits or 32-bits (I don't see that)?

    #2: Why do I not see an IBO or VBO identifier in the VAO state (in tables 6.3 and 6.4)? How can binding the VAO also bind the IBO and VBO if they are not identified in the VAO state?

    ---------------

    context: upgrading cross platform 3D engine from OpenGL210/GLSL120 to OpenGL310/GLSL140 (with 185.85 drivers).

    computers: CPU = phenom + 4GB RAM : video = nvidia GTX285 + 2GB VRAM : OS #1 = ubuntu64 v9.04 : OS #2 = winxp64

  2. #2
    Member Regular Contributor
    Join Date
    May 2001
    Posts
    348

    Re: VBO to VAO

    Quote Originally Posted by bootstrap
    I never did understand why, but we could not make our code work unless we specified the offsets/types/normalizations of every vertex attribute every time we switched to another IBO/VBO pair. Does anyone understand why?
    Because GL_ARRAY_BUFFER_BINDING is a latched state. You never bind a buffer for a certain vertex attribute directly, instead you bind a buffer to GL_ARRAY_BUFFER, then call glVertexAttribPointer (or one of the deprecated gl*Pointer functions). Only at that point is GL_ARRAY_BUFFER_BINDING copied to GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING for the specific vertex attribute.

    You cannot switch to another buffer by calling glBindBuffer(GL_ARRAY_BUFFER, x) without subsequent calls to gl*Pointer(). GL_ARRAY_BUFFER_BINDING is never used for rendering.

    #1: Does binding the VAO make all this VBO state active too? And does it also somehow make clear to the GPU whether the indices in the corresponding IBO are 16-bits or 32-bits (I don't see that)?
    Yes, no. The index type remains a parameter of glDrawElements and is not stored in a VAO.

    #2: Why do I not see an IBO or VBO identifier in the VAO state (in tables 6.3 and 6.4)? How can binding the VAO also bind the IBO and VBO if they are not identified in the VAO state?
    It's right there in table 6.4. GL_ELEMENT_ARRAY_BUFFER_BINDING for the index buffer binding, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING for each vertex attribute binding.

  3. #3
    Intern Contributor
    Join Date
    Jan 2008
    Location
    phobos, mars
    Posts
    75

    Re: VBO to VAO

    Quote Originally Posted by Xmas
    Quote Originally Posted by bootstrap
    #2: Why do I not see an IBO or VBO identifier in the VAO state (in tables 6.3 and 6.4)? How can binding the VAO also bind the IBO and VBO if they are not identified in the VAO state?
    It's right there in table 6.4. GL_ELEMENT_ARRAY_BUFFER_BINDING for the index buffer binding, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING for each vertex attribute binding.
    If that's what GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING means, why are there 16 of them?

  4. #4
    Member Regular Contributor
    Join Date
    May 2001
    Posts
    348

    Re: VBO to VAO

    Because you can use a different buffer for each vertex attribute.

  5. #5
    Intern Contributor
    Join Date
    Jan 2008
    Location
    phobos, mars
    Posts
    75

    re: VBO to VAO

    Quote Originally Posted by Xmas
    Because you can use a different buffer for each vertex attribute.
    Wait. So the VAO doesn't know which VBO is attached? It only knows the offsets of the <= 16 attributes in the first vertex of the VBO? I assume you're not saying you can have <= 16 VBOs attached to the VAO, right? After all, a VBO is a VERTEX buffer object, not an ATTRIBUTE buffer object.

    This leaves me a bit confused. What does the driver do when we call the glDrawElements() function? How does the driver convert this VAO information into something the GPU understands? I would imagine the GPU needs the 64-bit starting address in *GPU* memory of each attribute, plus the rest of the information in the VAO state. But how does the driver know this if it does not keep track of which VBO is attached?

    I'm missing something. Does the VAO know which IBO and VBO are attached to it, or not? If so, how (where is that state)? If not, how can the driver send sufficient information to the GPU when the glDrawElements() is called?

  6. #6
    Senior Member OpenGL Guru Dark Photon's Avatar
    Join Date
    Oct 2004
    Location
    Druidia
    Posts
    3,213

    Re: re: VBO to VAO

    Quote Originally Posted by bootstrap
    Quote Originally Posted by Xmas
    Because you can use a different buffer for each vertex attribute.
    Wait. So the VAO doesn't know which VBO is attached? It only knows the offsets of the <= 16 attributes in the first vertex of the VBO?
    I think we're in desperate need of a concrete example at this point.

    Here are two batches using VAOs and VBOs, supposing 1) you don't need to change any state between the batches except to change a texture, and 2) the VAOs to be used are already built:

    Code :
      glBindTexture
      glBindVertexArray
      glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, ...)
      glDrawRangeElements
      ...
      glBindTexture
      glBindVertexArray
      glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, ...)
      glDrawRangeElements
      ...
    As you can see, no vertex attribute VBO binds, vertex attribute pointer calls, or vertex attribute enables/disables. All cached in the VAO.

  7. #7
    Member Regular Contributor
    Join Date
    May 2001
    Posts
    348

    Re: re: VBO to VAO

    Quote Originally Posted by bootstrap
    I assume you're not saying you can have <= 16 VBOs attached to the VAO, right?
    That is indeed exactly what I am saying.

    After all, a VBO is a VERTEX buffer object, not an ATTRIBUTE buffer object.
    OpenGL only knows a single type of buffer object.

    Vertex buffer objects, index buffer objects, pixel buffer objects, uniform buffer objects, or texture buffer objects are just descriptions based on the usage of a particular buffer object. They all are the same type of object: a buffer object. And you can indeed use a single buffer object for all these purposes. I wouldn't recommend it, though.

    So yes, it is entirely possible that you use one buffer object for normals, another for vertex positions, a third one for texture coordinates, and so on. Or you can mix those attributes in whatever way you like.

    And all the information that is needed for each attribute (buffer binding, size, type, stride, offset, enabled, normalized, and integer flags) plus the binding for a buffer object containing vertex indices (ELEMENT_ARRAY_BUFFER) is stored in a VAO. Thus it's not even necessary to re-bind to GL_ELEMENT_ARRAY_BUFFER, Dark Photon.

  8. #8
    Intern Contributor
    Join Date
    Jan 2008
    Location
    phobos, mars
    Posts
    75

    re: VBO to VAO

    Quote Originally Posted by Dark Photon
    I think we're in desperate need of a concrete example at this point.

    Here are two batches using VAOs and VBOs, supposing 1) you don't need to change any state between the batches except to change a texture, and 2) the VAOs to be used are already built:

    Code :
      glBindTexture(...)
      glBindVertexArray(...)
      glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, ...)
      glDrawRangeElements(...)
      ...
      glBindTexture(...)
      glBindVertexArray(...)
      glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, ...)
      glDrawRangeElements(...)
      ...
    As you can see, no vertex attribute VBO binds, vertex attribute pointer calls, or vertex attribute enables/disables. All cached in the VAO.
    Sorry, but I'm still missing something here.

    When you say "no VBO binds", are you saying there IS no VBO? Are you saying the VAO replaces the VBO... that the VAO is essentially a VBO plus attached attribute information?

    If so, please explain the first sentence of the "Vertex Array Objects" section in the OpenGL v3.10 specification, which states:

    "The buffer objects that are to be used by the vertex stage of GL are collected together to form a vertex array object. All state related to the definition of data used by the vertex processor is encapsulated in a vertex array object."

    When I read the above, I hear them saying "the VBO and any other buffer objects needed by the vertex stage are part of the VAO". It does not say "the VAO ***is*** the buffer object". I am not saying you are wrong. But I am saying that is terribly misleading wording if you are correct.

    Also, if the VAO ***is*** a buffer object itself, and is not just a collection of buffer objects (like they say it is above), then why is the VAO not bound with:

    glBindBuffer (GL_ARRAY_BUFFER, vaoID); // ???

    Instead, according to you *and* the OpenGL v3.10 specification, the VAO is bound not as a buffer object, but as a "vertex array" with:

    glBindVertexArray (vaoID);

    The above implies to me that the VAO does not contain vertex data, and does not correspond to a buffer object. So I ask again, if we don't bind a VAO, an IBO, ***and*** a VBO, then how does the vertex data get into the VRAM, and how does a given glDrawElements() know where the vertex data is?

    -----

    Separately, in your example, why must you glBindVertexArray() and glBindBuffer(GL_ELEMENT_ARRAY_BUFFER...) before the second glDrawElements(...) call? Aren't they still bound?

    -----

    In our current code, we bind an IBO, bind a VBO, call glVertexAttribPointer() 5 times, then call glDrawElements(). Therefore I understand how the GPU knows where to get vertex-indices from (the bound IBO), and how the GPU knows where to get vertex-data from (the bound VBO).

    In your code I see how the GPU knows which IBO to fetch from, but I do NOT see how the GPU knows which VBO to fetch from. I'm not saying your code is wrong, I'm just saying I don't see how sufficient information gets to the driver or GPU.

  9. #9
    Intern Contributor
    Join Date
    Jan 2008
    Location
    phobos, mars
    Posts
    75

    Re: re: VBO to VAO

    Quote Originally Posted by Xmas
    Quote Originally Posted by bootstrap
    I assume you're not saying you can have <= 16 VBOs attached to the VAO, right?
    That is indeed exactly what I am saying.
    Okay, then how do you attach (say) 5 VBOs to a VAO? Let me guess - you call glVertexAttribPointer() 5 times. But that is not a VBO, that is just a vertex attribute specification. True, this does provide the stride too, so it knows how far to the next instance of the same attribute, but glVertexAttribPointer() does NOT say how many of these attributes follow. It also doesn't transfer these attributes anywhere either. So how do all 5 sets of vertex attributes get into VRAM? And when glDrawElements() gets called, how does the GPU know where those 5 arrays of attributes are?

    After all, a VBO is a VERTEX buffer object, not an ATTRIBUTE buffer object.
    OpenGL only knows a single type of buffer object.

    Vertex buffer objects, index buffer objects, pixel buffer objects, uniform buffer objects, or texture buffer objects are just descriptions based on the usage of a particular buffer object. They all are the same type of object: a buffer object. And you can indeed use a single buffer object for all these purposes. I wouldn't recommend it, though.

    So yes, it is entirely possible that you use one buffer object for normals, another for vertex positions, a third one for texture coordinates, and so on. Or you can mix those attributes in whatever way you like. And all the information that is needed for each attribute (buffer binding, size, type, stride, offset, enabled, normalized, and integer flags) plus the binding for a buffer object containing vertex indices (ELEMENT_ARRAY_BUFFER) is stored in a VAO. Thus it's not even necessary to re-bind to GL_ELEMENT_ARRAY_BUFFER, Dark Photon.
    Then what does the setup code look like? Maybe that's what I need to see, to understand how this works?

    If I have 5 attributes, do I need to create 5 VBOs? Do I then glBuffer[Sub]Data() the vertex data from CPU memory into these 5 VBOs in VRAM? This is a total disaster, because my vertice are interleaved (per usual practice)! My code would need to call glBufferSubData() once for each attribute in each vertex, which would be thousands to millions of excess function calls!!!!!

    What does the code look like to attach 5 VBOs to a VAO?

    Yup, I think I need to see what comes first, what comes second, what comes third, etc - including setup code. Until I see how the GPU knows what to do (and where to get the vertex data) when glDrawElements() is called, I am confused. Remember, the data is in VRAM, not in CPU memory.

  10. #10
    Member Regular Contributor
    Join Date
    May 2001
    Posts
    348

    Re: re: VBO to VAO

    A VAO contains:
    - a bind point for a buffer object containing vertex indices
    - for each vertex attribute (at least 16):
    -- a bind point for a buffer object
    -- enable flag
    -- integer flag
    -- normalize flag
    -- size
    -- type
    -- stride
    -- offset

    There is always a VAO bound to the context. The default VAO has the name 0 and is created along with the context, similar to textures 0 and framebuffer 0. When you bind a VAO, all the state stored in it will become active. Calls to glVertexAttribPointer, or glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, ...), modify the currently bound VAO.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •