# VAO - Is it necessary to redo setup each time buffer data changes?

This topic is 2683 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I am a bit surprised that it seems like my VAOs get invalidated each time that I provide new buffer data. Are you really supposed to do glEnableClientState and setup gl*Pointers all over again after each glBufferSubData? That would make VAOs pretty useless for dynamic vertex data, wouldn't it?

I was hoping that it would be more like this:

 // Initialization (Once) glGenVertexArrays(1, &vao); glGenBuffers(1, &vbo); glBindVertexArray(vao); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, size * sizeof(vertex_t), vertices, GL_DYNAMIC_DRAW); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glVertexPointer(3, GL_FLOAT, sizeof(vertex_t), (GLvoid*)(0 * sizeof(vec3_t))); glNormalPointer(GL_FLOAT, sizeof(vertex_t), (GLvoid*)(1 * sizeof(vec3_t))); glColorPointer(4, GL_FLOAT, sizeof(vertex_t), (GLvoid*)(2 * sizeof(vec3_t))); glTexCoordPointer(2, GL_FLOAT, sizeof(vertex_t), (GLvoid*)(2 * sizeof(vec3_t) + sizeof(vec4_t))); glBindVertexArray(0); 
 // Update (Each Frame) glBindVertexArray(vao); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferSubData(GL_ARRAY_BUFFER, 0, size * sizeof(vertex_t), vertices); glBindVertexArray(0); 
 // Render (Each Frame) glBindVertexArray(vao); glBindTexture(GL_TEXTURE_2D, texture); glDrawArrays(GL_TRIANGLES, 0, size); glBindVertexArray(0); 
However, it seems like I need to do this in order for it to work:

 // Update (Each Frame) glBindVertexArray(vao); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferSubData(GL_ARRAY_BUFFER, 0, size * sizeof(vertex_t), vertices); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glVertexPointer(3, GL_FLOAT, sizeof(vertex_t), (GLvoid*)(0 * sizeof(vec3_t))); glNormalPointer(GL_FLOAT, sizeof(vertex_t), (GLvoid*)(1 * sizeof(vec3_t))); glColorPointer(4, GL_FLOAT, sizeof(vertex_t), (GLvoid*)(2 * sizeof(vec3_t))); glTexCoordPointer(2, GL_FLOAT, sizeof(vertex_t), (GLvoid*)(2 * sizeof(vec3_t) + sizeof(vec4_t))); glBindVertexArray(0); 
Is this reallly necessary or am I doing something else wrong?

##### Share on other sites
You probably destroying some bindings, because you bind the vao in your update function.

glBindVertexArray(vao); glBindBuffer(GL_ARRAY_BUFFER, vbo);

with this code you are overwriting some stuff in the vao. I'm not quite sure why it won't work after this, but I guess this is the cause.

just get rid of those two vao bindings in you update function.

##### Share on other sites
Thank you for your suggestion. Unfortunately, if I don't bind the VAO during update I get really glitchy output. It looks like the data in the buffer is scrambled or some invalid/faulty data is being read.

FYI, I also tried this version:

 // Initialization 1 (Once) glGenVertexArrays(1, &vao); glGenBuffers(1, &vbo); glBindVertexArray(vao); glBindBuffer(GL_ARRAY_BUFFER, vbo); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glVertexPointer(3, GL_FLOAT, sizeof(vertex_t), (GLvoid*)(0 * sizeof(vec3_t))); glNormalPointer(GL_FLOAT, sizeof(vertex_t), (GLvoid*)(1 * sizeof(vec3_t))); glColorPointer(4, GL_FLOAT, sizeof(vertex_t), (GLvoid*)(2 * sizeof(vec3_t))); glTexCoordPointer(2, GL_FLOAT, sizeof(vertex_t), (GLvoid*)(2 * sizeof(vec3_t) + sizeof(vec4_t))); glBindVertexArray(0); 
 // Initialization 2 (Once) glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, size * sizeof(vertex_t), vertices, GL_DYNAMIC_DRAW); 
 // Update (Each Frame) glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferSubData(GL_ARRAY_BUFFER, 0, size * sizeof(vertex_t), vertices); 
 // Render (Each Frame) glBindVertexArray(vao); glBindTexture(GL_TEXTURE_2D, texture); glDrawArrays(GL_TRIANGLES, 0, size); glBindVertexArray(0); 
Using this version, no geometry is visible at all (only the clear color). So it seems that the order of passing the data and setting up the VAO does matter.

##### Share on other sites
No more comments? Some input on the correct order of operations when using VAOs would already help a lot. Putting it in pseudo code, this is how I would expect things to work (but they don't):

 Initialization: Bind VAO Bind Buffer Upload Buffer Data Enable Client States Setup Pointers Unbind VAO Update/Render Loop: Bind Buffer Update Buffer Data Bind VAO Draw Unbind VAO 

##### Share on other sites
mm, dont really know whats wrong, but here some random stuff.

• There is no need to generate, bind and submit data to the VBO while the VAO is active, they don't have anything to do with the VAO state
• maybe check your stride and offset values(both are in bytes) again, look also at teh part of your code which fills your data array
• use Stream_Draw when you are updating the buffer every frame
• also when updating use this code, it's faster because the driver has less problems managing the memory
glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, size * sizeof(vertex_t), null, GL_STREAM_DRAW); glBufferSubData(GL_ARRAY_BUFFER, 0, size * sizeof(vertex_t), vertices); 

here is some pseudo code how I do it:
 Initialization: Generate n BOs Bind first upload index data Bind other BO upload vertex data to it Loop until all vertex BOs are filled Generate VAO Bind VAO Bind Index Buffer Enable Client States Bind a BO Set all its vertex pointers Loop until all Attributs are set Unbind VAO Update/Render Loop: Bind BO which data changed upload data Loop until each BO is updated Bind VAO Set up render state (Textures, Shader, Uniforms, Lighting ...) render Unbind VAO 

##### Share on other sites
Thanks again! It's very useful to have an example of how it should work. Unfortunately, I wont be able to implement all of your suggestions, because I am developing for iOS (OpenGL ES 1.1). This might also be the source of my problems - maybe there are some quirks with VAOs, which are only supported as an extension. However, I still find it more likely that the error is somewhere in my code.

I'm lead to believe that the stride and offset values are fine, because they work when I set them each time before rendering. Unfortunately GL_STREAM_DRAW is not available, so I can't try that. I'm really surprised that your suggested way of updating data should be faster - wouldn't it set all the data to zeros before writing the new data? (I'm not familiar with the effect of passing a null pointer in this context.)

In any case, I'll go through my code once again and compare it with the pseudo code you posted.

##### Share on other sites
GL ES 1.1 supports VAO?

##### Share on other sites
the thing with calling it with null is that it tells the driver that u don't care anymore about the data.
So the new data get uploaded to an other address space then the old one. And the old gets deleted any time in the future

If u just upload new data the driver has to make sure that every operation on the old data has finished, then he has to sync everything and so on, which can take quite some time in a worst case.

##### Share on other sites

GL ES 1.1 supports VAO?

No. As I mentioned, the older iOS devices (GL ES 1.1) support it through an extension (see OpenGL ES Programming Guide for iOS - Platform Notes).

I've gotten a little sidetracked, as this was only supposed to be a slight optimization (it's one of the "best practices" in the aforementioned guide). When I come back to this, it would probably make sense to write a minimal example program demonstrating the problem...

##### Share on other sites
I see.

As for VAO, from what I understand, you only need to setup a VAO once. Then you use it with

glBindVertexArray(vao);
glDrawArrays or glDrawRangeElements or glDrawElements

I imagine that anything else can be considered a driver bug. Unfortunately, my experience is limited. I just did a test with VAO. I rendered 2 triangles with 2 different VAO just to make sure it works as I expect.
I am surprised we don't even have a decent example on the Wiki.

1. 1
2. 2
Rutin
20
3. 3
khawk
16
4. 4
A4L
14
5. 5

• 11
• 16
• 26
• 10
• 11
• ### Forum Statistics

• Total Topics
633756
• Total Posts
3013710
×