What is the recommended way to handle uniform buffers

Currently I am in the process of writing a toy renderer for vulkan just to learn and I am a bit confused as to how to handle uniform buffers. The way I would handle drawing a basic rectangle in ogl would be to bind the vbo, ibo, vao, shader, set the uniforms, then draw. This works just fine for one or 100 rectangles, even though they have the same everything, except values in the uniform. This makes for a nice api that I am trying to replicate with vulkan. However to the best of my knowledge the drawcalls are not properly executed until after all drawcalls are queued. Thus the uniforms that I have written to get overwritten and only the last object is drawn with the correct uniforms. I am 99% sure this is an architecture thing, so what is the generally accepted way to handle uniforms for multiple objects, that don’t really have unique data?

Thanks :slight_smile:

But they do have unique data. If they didn’t, then you’d just be drawing the same thing over and over again.

Vulkan simply doesn’t allow you to pretend that they don’t have unique data.

There are many ways to go about the process of rendering rectangles, and which ones you use depend entirely on what kind of data you need to provide to each rectangle independently of the others.

Yes my bad I should have written that they don’t have unique data except for the uniform buffer, everything else is the same. What you are describing is what is happening despite that I am changing the uniform data, that said I am not really looking for an answer to a problem so much as a good example of architecture.

It sounds like you’ve got a:

  • update “the” uniforms,
  • draw
  • update “the” uniforms
  • draw

mindset, which was easy to fall into with OpenGL. If so, you need to shift your thinking to:

  • update uniforms (group A)
  • draw (with uniforms group A)
  • update uniforms (group B)
  • draw (with uniforms group B)

model.

Why?

Call the first Approach #1 and the 2nd Approach #2. With OpenGL, it was easier to get away with #1, because of all the techniques the driver employed under-the-covers (multibuffering, resource renaming, streaming updates in the command queue, etc.). And depending on exactly how you updated those uniforms, it might actually yield half-way decent performance too because of all those tricks (…or not, if you chose the wrong techniques for that driver). You’re in voodoo magic land now! However in Vulkan, if you want any of that voodoo, you have to implement it. And because you implement it, you know exactly how it’s going to work.

So how does Approach #2 help? The second makes it very clear that there are multiple distinct sets of uniform state, and which draw call uses which set. It’s a trivial step from this to realizing that all of these groups of uniforms (A,B,C,…) can exist side-by-side in separate sub-regions of a resource (UBO, SSBO, push constants, etc.), and the draw calls can just index into this array of uniform groups to pull data from the right set. This helps quite a bit because now you can just reorder the above and do all those “update uniforms” operations up-front as a group, but not have the problem that later, when the draw calls execute on the GPU, all but the last one see the wrong set of uniforms. They all “see” the set of uniforms that they need when they execute, based on the offsets they pull from in the resource.

I’ll post some links to Vulkan tutorials/articles/sample code below that illustrates how to do this buffer sub-resource updating and use. But if you understand the above, it’s just details.

Yep that sounds exactly like the solution, thanks for the in depth explanation, I really appreciate it :slight_smile:

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