I'm having a lot of trouble finding decent documentation about VAOs beyond how to use them, which is clear enough. I'm mostly concerned about the impact of changing a VAO state as I'm not sure how the driver is going to react to this.
The context of the problem:
I'm using meshes with a large amount of triangles which require some form of spatial subdivision. As a first design alternative, this is being implemented as a single VAO with the attached VBOs that contain the mesh information and an IBO with the whole index that would allow to draw the whole mesh, if necessary (rarely used in this case, but still).
The mesh is subdivided with an Octree-like structure and each node contains an IBO with the index data of the triangles stored in the node. There's obviously other data stored that's not used for rendering, including other topology data, which is irrelevant to the question.
When rendering, the sections that are to be drawn are culled, the IBOs gathered and finally the single VAO is bound and its IBO is reassigned before a glDrawElements call is issued. So it goes:
- Bind VAO
- Loop for each IBO
--- Bind IBO with glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,iboID)
--- Render with glDrawElements
What would be the expected impact of changing a VAO's state bind state? I understand this is a very relative question, but I'm ok with a relative answer as well. Is the impact expected to be the same as changing any other bind or is it going to cause something more expensive like a client side rebuilding of all the VAO data and subsequent upload to the GPU?
Two alternative implementations that come to mind are:
- Store each node's data into separate VAOs, so it would be interesting if I could get some insight in the cost of swaping a VAO compared to swaping a VAO's buffer.
- Create a huge single IBO that is generated as the mesh is split in pieces and store in each node only the starting index and element count then use glMultiDrawElements to send all the calls at once. Note that I have not used glMultiDraw* in any real situation yet, so I may perhaps be misunderstanding its usage.
I'm leaning towards reimplementing everything with the last method as it would seem intuitively a better choice, but I would like to get some insight on the actual performance difference between these design patterns.
Yes, I understand that it will all depend on what else my application does, so I'm not asking for hard numbers. If you can share your experience with this I'd be glad to hear it!