OpenGL VAO with GL_DYNAMIC_DRAW - opengl

I am working with OpenGL and while developing I found this GL_DYNAMIC_DRAW buffers mode that states that buffer data may be changed, and I thought if I call glBufferData(...) while being bound to some VAO does it means that every time I will bing again this VAO all data that was in my memory will be automatically reuploaded to GPU?
Same idea in code:
data = [...] # List of arrays (actual data)
buffers = glGenBuffers(4) # Create buffers
vao = glGenVertexArrays(1) # Create VAO
glBindVertexArray(vao) # Bind VAO
for i, (buf, data) in enumerate(zip(buffers, data)):
glBindBuffer(GL_ARRAY_BUFFER, buf)
glBufferData(GL_ARRAY_BUFFER, data.nbytes, data, GL_DYNAMIC_DRAW)
glEnableVertexAttribArray(i)
glVertexAttribPointer(i, 3, GL_FLOAT, GL_FALSE, some_straid, ctypes.c_void_p(0))
glBindVertexArray(0) # unbind every thing ...
...
def on_render():
glClear(...) # clear screen
glUseProgram(...) # enable shader
glBindVertexArray(vao) # will this call upload new data to gpu?
glDrawArrays(GL_TRIANGLES, 0, 3) # draw
glBindVertexArray(0) # unbind VAO
glUseProgram(0) # unbind shader
glutSwapBuffers()
And if not, what is the best way to update those buffers (calling every time glBufferData?)?

Buffer usage:
usage is a hint to the GL implementation as to how a buffer object's data store will be accessed. This enables the GL implementation to make more intelligent decisions that may significantly impact buffer object performance. It does not, however, constrain the actual usage of the data store. usage can be broken down into two parts: first, the frequency of access (modification and usage), and second, the nature of that access. The frequency of access may be one of these:
For your specific case
DYNAMIC - The data store contents will be modified repeatedly and used many times.
If you want to update the buffer you have to call glBufferData or any of the other methods example: glBufferSubData, glMapBuffer. This has to be done when the buffer is bound ( Not the VAO, but the buffer )

Related

OpenGL - Properly updating the Vertex Buffer binding of a Vertex Array Object

I have noticed a strange error in my program, which occurs when I bind a VAO multiple times after calling glVertexArrayVertexBuffer. In my frame loop, I usually have one VAO for one draw call, but sometimes I would like to use the same VAO for multiple draw calls with different shaders. But this does not work in my implementation:
while(RUN){
updateBuffers();//updates VAO
drawThis();//binds and unbinds VAO
drawThat();//binds and unbinds VAO -> OpenGL Invalid Operation error at draw call
}
Whereas this works:
while(RUN){
updateBuffers();//updates VAO
drawThis();//binds and unbinds VAO
updateBuffers();//updates VAO
drawThat();//binds and unbinds VAO -> works
}
Also this doesn´t work:
updateBuffers();
while(RUN){
drawThis();//OpenGL Invalid Operation error in second frame
}
but this would work
updateBuffers();
glBindVertexArray(VAO);
while(RUN){
drawThis();//only makes the draw call
}
glBindVertexArray(0);
... but that is not an option because I also want to use other VAOs in my frame loop (and I would like to stay flexible with the order).
So what are these functions doing internally?
The draw functions simply bind a VAO and a shader, make a draw call (usually glDrawElementsInstanced) and then unbind the shader and the VAO.
The updateBuffers function usually writes to a buffer object (initialized with glNamedBufferStorage) through a pointer which maps the entire buffer using the GL_MAP_WRITE_BIT, GL_MAP_PERSISTENT_BIT and GL_MAP_COHERENT_BIT flags. To ensure that I am not overwriting any data that is still being used by the GPU, I always write to a different partition of the buffer. So before each update I increase the write offset by the size of the previous update (or set it to 0 if the update would exceed the storage size).
And because the updated data should be visible to shaders, I have to update the binding points that the shaders bind to, too. I do this by calling glBindBufferRange for uniform buffers (used by uniform blocks) and glVertexArrayVertexBuffer for vertex buffers (for vertex attributes) with each update, to make the binding offsets for each buffer start at the position of the updated data.
This always works fine for uniform buffer bindings (offset is updated with glBindBufferRange) but when I update the binding for a vertex buffer of a VAO (with glVertexArrayVertexBuffer) and then bind and unbind that VAO more than once before calling glVertexArrayVertexBuffer again, I get an Invalid Operation error.
Why does glVertexArrayVertexBuffer cause a VAO to behave like this? What would be the proper approach to update the offset of a VAOs binding to a vertex buffer?

Why do OpenGL buffers (and objects in general) work?

Here is what I understand about how OpenGL buffers work: Sending data from the CPU to the GPU is slow, so we don't want to send, say, vertex data vertex by vertex. Instead, we send vertex data to the GPU all at once, and inform the GPU how to interpret what we send it. Buffers are involved in this process somehow (that's the point I do not understand).
So how to do this? We follow the OpenGL object creation model:
Generate a buffer ID
GLuint VBO;
glGenBuffers(1, &VBO);
Bind the buffer ID to a target buffer in the current state/context
glBindBuffer(GL_ARRAY_BUFFER, VBO);
Modify or query data. For instance, glBufferData() called on the target GL_ARRAY_BUFFER can be used to send the vertex data.
Set the target back to default
glBindBuffer(GL_ARRAY_BUFFER, 0);
De-allocate resources (edit: after the buffer has served its purpose; for instance, after the end of the game loop)
glDeleteBuffers(1, &VBO);
So at one hand I have the abstract idea of a block of GPU memory, and on the other hand I have a procedure to access that block, and I do not understand how those two correlate.

Is it necessary to bind all VBOs (and textures) each frame?

I'm following basic tutorial on OpenGL 3.0. What is not clear to me why/if I have to bind, enable and unbind/disable all vertex buffers and textures each frame.
To me it seems too much gl**** calls which I guess have some overhead. For example here you see each frame several blocks like:
// do this for each mesh in scene
// vertexes
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glVertexAttribPointer( 0, 3, GL_FLOAT,GL_FALSE,0,(void*)0);
// normals
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, normal_buffer );
glVertexAttribPointer( 1, 3, GL_FLOAT,GL_FALSE,0,(void*)0);
// UVs
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, uv_buffer );
glVertexAttribPointer( 2, 2, GL_FLOAT,GL_FALSE,0,(void*)0);
// ...
glDrawArrays(GL_TRIANGLES, 0, nVerts );
// ...
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
imagine you have not just one but 100 different meshes each with it's own VBOs for vertexes,normas,UVs. Should I really do this procedure each frame for each of them? Sure I can encapsulate that complexity into some function/objects, but I worry about overheads of this gl**** function calls.
Is it not possible some part of this machinery to move from per frame loop into scene setup ?
Also I read that VAO is a way how to pack corresponding VBOs for one object together. And that binding VAO automatically binds corresponding VBOs. So I was thinking that maybe one VAO for each mesh (not instance) is how it should be done - but according to this answer it does not seems so?
First things first: Your concerns about GL call overhead have been addressed with the introduction of Vertex Array Objects (see #Criss answer). However the real problem with your train of thought is, that you equate VBOs with geometry meshes, i.e. give each geometry its own VBO.
That's not how you should see and use VBOs. VBOs are chunks of memory and you can put the data of several objects into a single VBO; you don't have to draw the whole thing, you can limit draw calls to subsets of a VBO. And you can coalesce geometries with similar or even identical drawing setup and draw them all at once with a single draw call. Either by having the right vertex index list, or by use of instancing.
When it comes to the binding state of textures… well, yeah, that's a bit more annoying. You really have to do the whole binding dance when switching textures. That's why in general you sort geometry by texture/shader before drawing, so that the amount of texture switches is minimized.
The last 3 or 4 generations of GPUs (as of late 2016) do support bindless textures though, where you can access textures through a 64 bit handle (effectively the address of the relevant data structure in some address space) in the shader. However bindless textures did not yet make it into the core OpenGL standard and you have to use vendor extensions to make use of it.
Another interesting approach (popularized by Id Tech 4) is virtual textures. You can allocate sparsely populated texture objects that are huge in their addressable size, but only part of them actually populated with data. During program execution you determine which areas of the texture are required and swap in the required data on demand.
You should use vertex array object (generated by glGenVertexArrays). Thanks to it you don't have to perform those calls everytime. Vertex buffer object stores:
Calls to glEnableVertexAttribArray or glDisableVertexAttribArray.
Vertex attribute configurations via glVertexAttribPointer.
Vertex buffer objects associated with vertex attributes by calls to
glVertexAttribPointer.
Maybe this will be better tutorial.
So that you can generate vao object, then bind it, perform the calls and unbind. Now in drawing loop you just have to bind vao.
Example:
glUseProgram(shaderId);
glBindVertexArray(vaoId);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
glUseProgram(0);

When should glVertexAttribPointer be called?

It's not obvious from the documentation when glVertexAttribPointer should be called. It looks like it's part of VBO initialisation, but I notice example code calling it during rendering.
glVertexAttribPointer(vertexAttributeId, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex2D), reinterpret_cast<const GLvoid*>(offsetof(Vertex2D, m_x)));
Should glVertexAttribPointer be called during initialisation of a GL_ARRAY_BUFFER or should it be called during rendering (after a call to glBindBuffer)?
The function glVertexAttribPointer specifies the format and source buffer (ignoring the deprecated usage of client arrays) of a vertex attribute that is used when rendering something (i.e. the next glDraw... call).
Now there are two scenarios. You either use vertex array objects (VAOs) or you don't (though not using VAOs is deprecated and discouraged/prohibited in modern OpenGL). If you're not using VAOs, then you would usually call glVertexAttribPointer (and the corresponding glEnableVertexAttribArray) right before rendering to setup the state properly. If using VAOs though, you actually call it (and the enable function) inside the VAO creation code (which is usually part of some initialization or object creation), since its settings are stored inside the VAO and all you need to do when rendering is bind the VAO and call a draw function.
But no matter when you call glVertexAttribPointer, you should bind the corresponding buffer right before (no matter when that was actually created and filled), since the glVertexAttribPointer function sets the currently bound GL_ARRAY_BUFFER as source buffer for this attribute (and stores this setting, so afterwards you can freely bind another VBO).
So in modern OpenGL using VAOs (which is recommended), it's usually similar to this workflow:
//initialization
glGenVertexArrays
glBindVertexArray
glGenBuffers
glBindBuffer
glBufferData
glVertexAttribPointer
glEnableVertexAttribArray
glBindVertexArray(0)
glDeleteBuffers //you can already delete it after the VAO is unbound, since the
//VAO still references it, keeping it alive (see comments below).
...
//rendering
glBindVertexArray
glDrawWhatever
When not using VAOs it would be something like that:
//initialization
glGenBuffers
glBindBuffer
glBufferData
...
//rendering
glBindBuffer
glVertexAttribPointer
glEnableVertexAttribArray
glDrawWhatever
glVertexAttribPointer is something that does not really belong to the Buffer nor to the Program it is - let's say - the glue between them. (The functionality of this is splitten in Opengl 4.3 in different functions VertexAttrib*Format, VertexAttribBinding and BindVertexBuffer aviable through the ARB_vertex_attrib_binding )
But if you want to say that it is part of something i would say it is part of the VAO that stores the state of which Buffer objects are bound, which attribs are enabled and how the Buffer data has to be passed to the Program.
So it belongs to part where you setup your VAOs.
EDIT
Simple setup that illustrates the order:
creating/setup of Buffers and creating programs
create VAO define which attribs are enabled, which buffers should be bound when the VAO is used and how that data is passed to the program (glVertexAttribPointer)
The association of buffer, generic vertex attribute and shader attribute variable are quite subtle. glVertexAttribPointer establishes this association. See OpenGL-Terminology for a detailed explanation.
Also, the link OpenGL-VBO,shader,VAO shows a working example with the necessary sequence of API calls.
glVertexAttribPointer has to be called (in most cases) when the appropriate (i.e. the one you want to use) VBO is bound. Then last parameter to it is offset in said buffer.
The last parameter is defined particularly nice in the reference manual:
Specifies a offset of the first component of the first generic vertex
attribute in the array in the data store of the buffer currently bound
to the GL_ARRAY_BUFFER target. The initial value is 0.
Appropriate Vertex Pointer Bindings with VBO sources are stored inside VAO, and you should use that if possible.
Short example (excuse my pseudocode):
// Setup
CreateVAO(); BindVAO();
CreateVBO(); BindVBO();
VertexAttribPointer(/*id*/ 0, 3, GL_FLOAT, /*starting at offset*/ 0);
// We have specified Vertex attribute bound to location 0,
// with size of 3 floats, starting at offset 0 of VBO we've just created.
//Draw
BindVAO();
Draw();

OpenGL, VAOs and multiple buffers

I am writing a little graphics engine using OpenGL ( via OpenTK with C# ).
To define vertex attributes, I have a VertexDeclaration class with an array of VertexElement structures that are mapped to glEnableVertexAttribArray/glVertexAttribPointer calls.
Also, to support multiple vertex streams, I have a special structure holding a vertex buffer, vertex declaration, vertex offset and instance frequency (like the XNA's VertexBufferBinding structure).
Currently, whenever a drawing call is invoked, I iterate over all the set vertex streams and
bind their vertex buffers, apply vertex declarations, disable unused vertex attributes and draw the primitives.
I would like to use VAOs to cache the glEnableVertexAttribArray calls into them,
and whenever a vertex stream is applied, bind the VAO and change its array buffer binding.
Is that a correct usage of VAOs?
Is that a correct usage of VAOs?
No1.
glVertexAttribPointer uses the buffer object that was bound to GL_ARRAY_BUFFER at the moment the function was called. So you can't do this:
glVertexAttribPointer(...);
glBindBuffer(GL_ARRAY_BUFFER, bufferObject);
glDrawArrays(...);
This will not use bufferObject; it will use whatever was bound to GL_ARRAY_BUFFER when glVertexAttribPointer was originally called.
VAOs capture this state. So the VAO will, for each vertex attribute, store whatever buffer object was bound to GL_ARRAY_BUFFER when it was called. This allows you to do things like this:
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, buffer1);
glVertexAttribPointer(0, ...);
glVertexAttribPointer(1, ...);
glBindBuffer(GL_ARRAY_BUFFER, buffer2);
glVertexAttribPointer(2, ...);
Attributes 0 and 1 will come from buffer1, and attribute 2 will come from buffer2. VAO now captures all of that state. To render, you just do this:
glBindVertexArray(VAO);
glDraw*();
In short, if you want to change where an attribute's storage comes from in OpenGL, you must also change it's format. Even if it's the same format, you must call glVertexAttribPointer again.
1: This discussion assumes you're not using the new ARB_vertex_attrib_binding. Or, as it is otherwise known, "Exactly how Direct3D does vertex attribute binding." If you happen to be using an implementation that offers this extension, you can effectively do what you're talking about, because the attribute format is not tied with the buffer object's storage. Also, the tortured logic of glVertexAttribPointer is gone.
In general, the way we solve this in the OpenGL world is to put as many things as possible in the same buffer object. Failing that, just use one VAO for each object.