Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How should I update a Vertex Array Object when I update a Vertex Buffer Object it uses?

Tags:

opengl

Updating a VBO (especially its size) via glBufferData() can potentially change it's physical memory address, though not its buffer object name as set by glGenBuffers(). A VBO is linked to a VAO via a call to glVertexAttribPointer(), where information about the VBO (buffer object name? Memory address?) is stored in the VAO. The VAO becomes available for update and drawing when it is bound via glBindVertexArray(). Does GL recompute the VBO address at that time? The VAO may or may not be bound when a VBO it links to gets updated via glBufferData().

Depending on when the buffer object name is translated to a physical memory address, I can imagine that the VAO could be updated for the changed VBO merely by binding the VAO again after changing the VBO; or, it may be necessary to more thoroughly update the VAO with another call to glVertexAttribPointer().

So part of this question is: what information about the VBO is stored in the VAO? If it is just the buffer object name, then it shouldn't be necessary to call glVertexAttribPointer() again after changing the VBO contents.

Perhaps such details are not part of the API specification, and so the only safe practice is to update a VAO via glVertexAttribPointer() after every update of a linked VBO.

like image 730
PaulQ Avatar asked Jan 12 '15 22:01

PaulQ


1 Answers

You do not have to worry about that because VBOs never expose the underlying server memory space to you. Vertex attribute pointers are relative to the beginning of the object bound to GL_ARRAY_BUFFER at the time you set them.

Even if you re-allocate the buffer by calling glBufferData (...) (this creates a new data store, rather than updating it as your question suggests), your vertex attribute pointers are not going to be invalidated. This is because they are literally offsets into a named buffer's memory rather than arbitrary addresses; it takes two pieces of information (buffer name and offset) to establish a vertex pointer.


UPDATE: (Citing implementation details)

The following is from GL_ARB_vertex_attrib_binding:

Modify Section 2.9.6, "Vertex Arrays in Buffer Objects"

When an array is sourced from a buffer object, the vertex attribute's VERTEX_ATTRIB_BINDING indicates which vertex buffer binding is used. The sum of the attribute's VERTEX_ATTRIB_RELATIVE_OFFSET and the vertex buffer binding's VERTEX_BINDING_OFFSET is used as the offset (in basic machine units) of the first element in that buffer's data store.

    bindingIndex = VERTEX_ATTRIB_BINDING[attribIndex];
    buffer = VERTEX_BINDING_BUFFER[bindingIndex];

    if (buffer->name != 0) {
        address = buffer->baseAddress + 
                  VERTEX_BINDING_OFFSET[bindingIndex] + 
                  VERTEX_ATTRIB_RELATIVE_OFFSET[attribIndex];
    }

This code is from an extension / version of OpenGL (4.3) that is not part of the original discussion, but I thought it worth mentioning since for all intents and purposes this is how vertex attribute pointers worked under the hood anyway. The new API gives you the freedom to specify vertex attribute format independent of the vertex buffer (it does not care what is bound to GL_ARRAY_BUFFER at the time you setup the attribute format).

The address is computed indirectly when a command sources array memory (e.g. glDrawArrays (...)).

like image 50
Andon M. Coleman Avatar answered Sep 18 '22 17:09

Andon M. Coleman