3
votes

I am writing a renderer and am at the point to pick a final way to handle vao/vbo/shader management. On the web I found highly contradictory information on what is actually recommended. Right now idea is as follow:

-One VBO stores all meshes consecutively.

-Per "shader mapping" create a VAO to store the specific pointer mapping into VBO. ("shader mapping", consistent throughout different shaders with identical inputs)

then sort entities by "shader mapping" and render using offsets in the main VBO, thus minimizing shader and VAO switches. Something like:

for(shaders by mapping)
    bindVAO(); //set pointers
    for(shader)
        for(entity using shader)
            entity.setUniforms();
            drawArrays(entity.offset, entity.size);

Since This would include a considerable amount of refactoring I wanted to ask if this solution is optimal at all. I'm also wondering if its possible to have multiple interleaved formats in a single VBO.

1
f this solution is optimal at all - no one knows. You have to profile it.Bartek Banachewicz
afaik reducing the amount of calls to binding vaos and programms is as good as it gets, I would be interested in some more expert opinions thoughBeyelerStudios
thx, then I'll just try it. I was just wondering whether my general line of thought on VBO/VAO was correct before implementing.Teris
"One VBO stores all meshes consecutively"... group data into buffers according to how often it changes. If some data changes every frame, maybe it shouldn't be in the same buffer as static data.Dietrich Epp

1 Answers

4
votes

Reusing the VAOs with different shaders is good practice.

However, switching VBOs and VAOs is usually very cheap compared to switching shaders. Which means that in your case, the bottleneck will probably be switching the shader anyway.

For the same reason, putting all your meshes in the same VBO is probably overkill (but it won't hurt as long as you don't need to update it).

Also, depending on what you are rendering, sorting the draw calls by depth / blend state or by depth (usually front to back) may be a better solution than sorting them per shader. But that need to be measured carefully. (More info on sorting here).

Edit: To answer your 2nd question, it may be possible to put vertices of different types in the same VBO, although I never tried it. It's tricky because you need to be careful about the vertex alignment. When calling glDrawArrays(mode, first, count) for example, you need to calculate first so that first * sizeof(YourCurrentVertexType) equals the offset at which you put your data in the VBO. Anyway, it's probably not a good idea to do that. Some drivers may not appreciate it and, like I said above it's probably not going to make a noticeable difference.