5

Judging by Vulkan barriers explained, it seems like each vkCmdPipelineBarrier introduces a dependency between two subsequent pipeline “runs”. For a typical scenario of a shader A that writes an image and a shader B that samples the same image, it might look like this:

  1. dispatch shader that writes to image A
  2. vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, ...);
  3. dispatch shader that reads from image A

This defines a dependency from the first shader execution's color attachment stage to the second shader execution's fragment stage. But what to do if I want to run independent commands in between? For example

  1. dispatch shader that writes to image A
  2. dispatch unrelated shader that doesn't touch image A
  3. vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, ...);
  4. dispatch shader that reads from image A

This still works, but is inefficient: because the fragment shader stage now has to wait for the color attachment output stage of the previous, unrelated shader. How do I specify a dependency on the shader before it?

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
haasn
  • 53
  • 3

1 Answers1

4

You are looking for Events. https://vulkan.lunarg.com/doc/view/1.0.57.0/windows/vkspec.html#synchronization-events

Events are a synchronization primitive that can be used to insert a fine-grained dependency between commands submitted to the same queue, or between the host and a queue. Events have two states - signaled and unsignaled. An application can signal an event, or unsignal it, on either the host or the device. A device can wait for an event to become signaled before executing further operations. No command exists to wait for an event to become signaled on the host, but the current state of an event can be queried.

When recording the command buffer, you signal the event via vkCmdSetEvent after an operation. Thereafter vkCmdWaitEvents can be used to define a memory dependency between prior event signal operations and subsequent commands. See https://vulkan.lunarg.com/doc/view/1.0.57.0/windows/vkspec.html#vkCmdWaitEvents.

Make sure to reset the event before using it again via vkCmdResetEvent. And note:

Applications should be careful to avoid race conditions when using events. There is no direct ordering guarantee between a vkCmdResetEvent command and a vkCmdWaitEvents command submitted after it, so some other execution dependency must be included between these commands (e.g. a semaphore).

unexpectedvalue
  • 6,079
  • 3
  • 38
  • 62
  • Thanks. This seems to answer my question, but unfortunately it also leaves me stuck because I don't know ahead of time whether I will re-use the texture immediately or whether I will re-use it at some later point in the future - so I don't know ahead of time whether I will need to signal an event or not. So I believe I will just always use vmCmdPipeline and live with the inefficiency. – haasn Aug 14 '17 at 18:33
  • As far as I know, events are sort of more advanced semaphores as they are used for synchronization. Barriers on the other hand define memory dependency. So I think using events in this situation would be an overkill. Wouldn't reordering operations help here? If command doesn't touch the mentioned image, can't it be submitted earlier? – Ekzuzy Aug 14 '17 at 18:34
  • 1
    Events are as lightweight as it gets. It isn't semaphores, nor "advanced semaphores". Read the docs. – unexpectedvalue Aug 14 '17 at 18:35
  • 1
    @haasn Well, you can have an event anyway. It is fine if you end up never waiting for it, or waiting upon it immediately, just make sure to reset it properly before using it next time. – unexpectedvalue Aug 14 '17 at 18:36
  • As far as I remember events can be used to synchronize both queues and an application. So they gather properties of both semaphores and fences. That's why I think they are "more advanced". That's why I also think using them is an overkill because whenever synchronization with the CPU is involved it may introduce unnecessary stalls in the pipeline. But maybe there are other usages for events that I'm not aware of. – Ekzuzy Aug 14 '17 at 18:44
  • 1
    Events CAN be (re)set from the client, but that doesn't make them inherently heavy. Events are pretty much as fast as pipeline barriers and haasn's issue is exactly a place where you want events, stalling via a premature barrier is worse. Events also work across command buffers, but it is the developer's job to avoid race-conditions. Those are not fences, and, unlike fences, you can not wait upon events on client-side. – unexpectedvalue Aug 14 '17 at 18:53
  • Again read the docs, and know your synchronization primitives. – unexpectedvalue Aug 14 '17 at 18:53
  • I know the spec quite well but I didn't dig too much into events. Thanks for the info! – Ekzuzy Aug 14 '17 at 19:07