2

I'm struggling to understand when exactly execution dependency chains are formed.

  1. The vulkan spec states:

    An execution dependency chain is a sequence of execution dependencies that form a happens-before relation between the first dependency’s ScopedOps1 and the final dependency’s ScopedOps2. For each consecutive pair of execution dependencies, a chain exists if the intersection of Scope2nd in the first dependency and Scope1st in the second dependency is not an empty set.

    and:

    Including a particular pipeline stage in the first synchronization scope of a command implicitly includes logically earlier pipeline stages in the synchronization scope. Similarly, the second synchronization scope includes logically later pipeline stages.

    Now consider slide 11 of this presentation.

    The second synchronization scope of Barrier1 includes logically later stages as per spec. So if Barrier1.dstMask is DRAW_INDIRECT, it DOES include COMPUTE_SHADER. Similarly, the first synchronization scope of Barrier2 includes logically earlier stages as per spec. So if Barrier2.srcMask is COMPUTE_SHADER, it DOES include DRAW_INDIRECT. Then why is it, according to this slide, that this configuration DOES NOT constitute a execution dependency chain between the two barriers?

    Also, if I set Barrier1.dstMask to BOTTOM_OF_PIPE, how does it suddenly form a chain with anything other than BOTTOM_OF_PIPE in the srcMask of the next barrier? The spec clearly states BOTTOM_OF_PIPE is equivalent to ALL_COMMANDS_BIT with access flags set to 0 when specified in the first scope, not the second??

    Is the linked presentation wrong?

  1. I was wondering how to synchronize separate render passes, or synchronize something from inside a render pass with something outside a render pass. After scouring the internet I found you can specify BOTTOM_OF_PIPE in the second scope and chain onto it with either BOTTOM_OF_PIPE or ALL_COMMANDS in the first scope of a next dependency (as suggested here, and slide 12 in the presentation linked above).

    Is this correct? I can find nothing in the spec to support this.

2
  • People are allowed to be wrong. When commenting other people work, should probably request comment from them first. It becomes tiresome to be constantly proxy-debuging other people's documents and code, while they should be the one resposible for maintaining it. If one has to decide between random person and the specification, then by default the specification is right. Sorry, bit tired of frequent "why does this person's work says\does X" questions. Seems like a trivial error in the presentation where the two columns are swapped there. Commented Sep 22, 2022 at 1:29
  • Sorry to add to the pile of these questions. Did not actually notice the trivial error. It got pretty clouded for me due to all the confusion. Commented Sep 22, 2022 at 14:47

1 Answer 1

3

Execution dependency chaining applies universally to all the synchronization primitives. Of which VK_SUBPASS_EXTERNAL Subpass Dependencies are nearly the same thing as regular Pipeline Barriers.

Execution dependency chains are formed whenever it is satisfiable to match both the scopes at the same time. That is, if you can hypothetically imagine some queue operation that could match both the second sync scope of first sync command, and the first sync scope of the second sync command, then execution dependency chain is formed. The imaginary operation need not be real, actually recorded, nor executed.

For example if I have two Pipeline Barriers and barr1.dstStageMask is STAGE_COMPUTE, and barr2.srcStageMask is also STAGE_COMPUTE, then it is an execution dependency chain. I could imagine there is a vkCmdDispatch recorded between the two. That command would match both the scopes, therefore it is a chain.

If barr1.dstStageMask is VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT and barr2.srcStageMask is VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, then there is no chain. Both the scopes are not satisfiable at the same time. It is impossible to imagine any operation that would match both of them, therefore no execution dependency chain is formed.

(It is explained above in terms of pipeline stages at the risk of losing completeness, but keep in mind the pipeline stage is only a one part of the description of the synchronization scope as it is specified per each synchronization primitive in the specification. For example, a Fence would chain with nearly everything despite not really being specified in terms of pipeline stages)


ad nr. 1, seems like a trivial error in the presentation where the two columns are swapped there:

enter image description here

VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT is not the equivalent of VK_PIPELINE_STAGE_ALL_COMMANDS_BIT in the context of dstStageMask. It would be interpreted as VK_PIPELINE_STAGE_NONE in that context. So that's a tell.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for the answer. Did not actually notice the columns could be swapped due to my confusion, that clears it up beautifully. As for my second question, I still don't quite understand. I understand how the stages can be used to chain if they're anything other than BOTTOM_OF_PIPE or TOP_OF_PIPE. But if both barr1.dstMask and barr2.srcMask are BOTTOM_OF_PIPE (neither are top of pipe), how does that form a chain? As I understand it bottom/top of pipe don't match any actual (or imagined?) commands?
@Invalid Well, it works because the specification says it works. Something like a Fence needs to chain with nearly everything, or if it didn't that would be a decent specification hole (vkWaitIdle would not ensure device is idle). All the commands go through BOTTOM_OF_PIPE, they just nominaly do not do any useful work in it. I can imagine a fake command vkCmdBogus() which is specified that it laser prints "Hello, world!" onto your baguette in the BOTTOM_OF_PIPE stage. Therefore it can match both scopes. The predicate is satisfiable, so a chain is established.
I see, I think the confusion lies in that the spec says bottom/top of pipe may specify "no stage of execution", implying it is not a stage in and of itself where commands may happen (even imaginary). But I guess it can actually be seen as a stage. Thanks for taking the time to answer!
@Invalid It is a stage for sure, though a special one mostly for the purposes of expressing the end and beginning. More confusingly though new Vulkan added STAGE_NONE, which presumably should still chain with these old stages and work the same way.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.