Semaphores in PVRVk

Semaphores impose an order on queue submissions

A command buffer imposes some order on submissions. When a command buffer is submitted to a queue, the Vulkan API allows considerable freedom to determine when the command buffer's commands will actually be executed. This is either in relation to other command buffers submitted before or after it, or compared to other command buffers submitted together in the same batch (queue submission). The typical way to order these submissions is with semaphores.

Without using semaphores, the only guarantee imposed by Vulkan is that when two command buffer submissions happen, the commands of the second submission will not finish executing before the commands in the first submission have begun. This is not the strongest guarantee in the world.

The basic use of a semaphore is as follows:

  • Create a semaphore.
  • Add it to the SignalSemaphores list of the command buffer submission that needs to execute first.
  • Add it in the WaitSemaphores list of the command buffer that is to be executed second.
  • Set the Source Mask as the operations of the first command buffer that must be completed before the Destination Mask operations of the second command buffer begin. The more precise these are, the more overlap is allowed. Avoid blanket wait-for-everything statements, as this can impose considerable overhead by starving the GPU.

For example, by adding a semaphore with FragmentShader as the source and GeometryShader as the destination, this ensures that the FragmentShader of the first will have finished before the GeometryShader of the second begins. This implies that, for example, the VertexShaders might be executed simultaneously, or even in reverse order.

The above needs to be done whenever there are multiple command buffer submissions. In any case, it is usually recommended to do one big submission per frame whenever practical. The same semaphore can be used on different sides of the same command buffer submission - for instance in the wait list of one command buffer and the signal list of another, in the same queue submission. This is quite useful for reducing the number of queue submissions.