Map Multiple Separate Ranges in a Single VBO

Hey all,

I’m trying to reduce the amount of draw calls in my voxel map rendering code. The map is divided into chunks of 32x32x32 blocks, and each chunk has its own VAO+VBO.

A map can have up to ~2000 visible chunks each frame, which equals ~2000 glDrawArrays calls per frame.

I’ve changed to a large single VBO and render the visible chunks using glMultiDrawArrays.

This is working well, but when two chunks need to be re-meshed, two separate ranges of the VBO need to be mapped with glMapBufferRange. The 2nd call is failing with INVALID_OPERATION as the buffer is already mapped. I’m mapping them with the MAP_WRITE_BIT and MAP_FLUSH_EXPLICIT_BIT.

I can get around this by keeping the entire buffer mapped with GL_MAP_PERSISTENT_BIT and managing the synchronization myself, but I’m wondering if there’s another approach for OpenGL versions earlier than 4.4.

I don’t think you have much of a way around this. It’s in the spec: GL_INVALID_OPERATION if the buffer object is already in a mapped state. Supposedly you could upload the remeshed chunks sequentially, perhaps doing the actual remeshing somewhere else meanwhile. Or you could try coalescing the mappings.

And if you’re after maximum performance, persistent mapping and manual synchronization is your best bet anyway.

1 Like

Thank you for the reply.

Yeah I’m happy to use persistent mapping, and it sounds like for versions below 4.4 it’s also viable to build the new mesh on the CPU, then copy it via glBufferSubData into an unused part of the buffer?

Just confirming glBufferSubData shouldn’t cause any CPU-GPU sync points as long as I’m not rendering this new part of the buffer before the copy operation completes? i.e. wait a few frames before rendering it or use glQueryCounter

If you don’t have access to persistent mapping, there are other alternatives, none of which involve mapping small subranges.

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.