Setting shader uniforms

It appears there are two ways of setting shader uniforms:

  • Using one or more uniform buffers.

  • Using vkCmdPushConstants to set an entire structure containing all your uniform values. As I understand it, this requires creation (or resetting) of a command buffer each frame, re-recording the action, and executing it.

Which is the correct approach for setting shader uniforms that change each frame?

According to this, push constants are better for frequently updated data. This is consistent with my experience in OpenGL:

Using a UBO this way is not the most efficient way to pass frequently changing values to the shader. A more efficient way to pass a small buffer of data to shaders are push constants . We may look at these in a future chapter.

So which is it?

In any real scene, you’re going to have to be rebuilding most of your command buffers every frame anyway. So there’s no need to attribute that cost to push constant usage.

Also, it’s unlikely that the push constant storage will be sufficiently large for all of your per-frame data. Most implementations give either 128 or 256 bytes for push constants, no more. 128 bytes is barely enough for two matrices.

So either way, you’re going to have to do some buffer work. The real question is how you go about telling the shader which buffer to use. Do you use a dynamic UBO binding, where you change the UBO offset on a per-object basis? Or do you pass an index via a push constant?

Or do you avoid UBOs and push constants, in favor of using the DrawID and multi-draw rendering? The index is the DrawID, and you fetch from an SSBO (since if you’re drawing most of your scene from a single draw call, you will almost certainly exceed the limits of a UBO).

Pick the one you feel works best for your needs.