How to Handle Player's Uniforms

#1

It may be a very silly question, but I would like to know how do I handle my player’s uniform in a game using vulkan.

I have a scene rendered with a player they both share the same MVP’s (right now).

How do I separate the model matrix (and my view matrix since I will be look at my player) used for my Player and the model matrix used for the rest of my scene. Consedering that my player will move arround.

In openGL I would do it just by setting a shader uniform for my player then render the player (glDrawArrays…), then set a different uniform for my scene then render the scene.

However since the drawCommands are recorded, how do I do it in Vulkan?

Sorry if I did not make my self clear.

#2

Similar way in Vulkan. That commands are recorded only changes when they are executed.

Specifically, you would bind Descriptor Set for Player. Draw player. Bind Descriptor Set for Scene. Draw scene. (Then submit that command buffer.)

1 Like
#4

But each descriptor set should have a different uniform buffer?

#5

Yes, that is desirable. More specifically, it can be the same VkBuffer but different byte offset into it.

If the uniform buffers memory locations are separate, then they do not need to be synchronized.

Alternatively, vkCmdUpdateBuffer can be used, but it counts as VK_BUFFER_USAGE_TRANSFER_DST_BIT write for the purposes for synchronization (and it probably uses memory anyway).

Alternatively, the buffer can be updated from the host, which is probably way worse, because of the necessary synchronization overhead.

#6

Um, vkCmdUpdateBuffer requires synchronization too. And it’s not like you can call it during a renderpass or something.

Better to just write to a mapped buffer. If the hardware cannot read uniform data from mappable memory, then you have to do a transfer and sync with it. If it can, then all you need is a simple event to make the written data accessible to the GPU.

#7

Yes, so I said; perhaps clumsily.

Both require sync. But vkCmdCopyImage from host memory is probably worse. Write to mapped memory requires a fence, and every vkDraw being submitted separately, which is probably worse still. Meanwhile vkCmdUpdateBuffer data is probably already in GPU memory after vkQueueSubmit, or so I would think.

Of course, none of this matters if all you have is two draws in your whole app.

Still the way I recommended is to have two Descriptors. I think it is reasonably efficient, as well as leads to reasonably esthetical code.

#8

Writing to mapped memory does not require a fence. Not unless you are trying to write to memory being currently read by the GPU. That is, if you’re not double-buffering your writes properly.

But it doesn’t scale. This lack of scaling is precisely why dynamic UBO descriptors exist: so that you don’t have to switch whole descriptor sets for each object. You can just change a couple of pointers and move on.

#9

Which it is, AFAI understood the OP. He wants to:

  1. write an uniform buffer (MVP matrix) for player
  2. draw player
  3. write an uniform buffer for scene
  4. draw scene

With mapped memory that would mean a fence signal has to be after 2. Then host has to wait on that fence before it can touch the mapped memory. Then that write has to be synced (e.g. by submitting 4 as a separate vkQueueSubmit).

It doesn’t have to scale in this case, but for educational purposes can’t hurt to note alternatives.

1 Like