0
votes

My understanding is that when you submit a vkCmdPipelineBarrier command, then all the commands in the source synchronization scope must reach srcStage before any of the commands in the destination synchronization scope are allowed to begin the dstStage of their pipeline.

But what if srcStageMask specifies a stage which a command in the source synchronization scope doesn't contain? For example, if the command is vkCmdDispatch and srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT.

The spec seems to answer this question:

If a synchronization command includes a source stage mask, its first synchronization scope only includes execution of the pipeline stages specified in that mask

So then I would expect that none of the operations performed by any stages of that command (vkCmdDispatch in the previous example) would be included in the synchronization scope. But in yet another blog explaining Vulkan synchronization, the author says that this produces an execution dependency chain:

   1. vkCmdDispatch
   2. vkCmdDispatch
   3. vkCmdPipelineBarrier(srcStageMask = COMPUTE, dstStageMask = TRANSFER)
   4. vkCmdPipelineBarrier(srcStageMask = TRANSFER, dstStageMask = COMPUTE)
   5. vkCmdDispatch
   6. vkCmdDispatch

In this example we actually get a dependency between {1, 2} and {5, 6}. This is because we created a chain of dependencies between COMPUTE -> TRANSFER -> COMPUTE. When we wait for TRANSFER in 4. we must also wait for anything which is currently blocking TRANSFER.

But the spec says

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

In the blog post's example, wouldn't BS for the first pipeline barrier be the empty set since vkCmdDispatch doesn't contain a transfer stage? Then the intersection of BS and AS would be the empty set and no dependency chain should exist.

But apparently one does exist, so this lead me to believe that I have an incorrect understanding of what happens when srcStageMask or dstStageMask specifies a stage which is not in the pipeline of a command. So then what does happen?

Edit:

From Nicol's answer:

It was talking specifically about the set of stages involved. Bs lists TRANSFER. As include TRANSFER. The intersection of the two stage masks is TRANSFER and therefore not empty. Therefore, there is a dependency chain.

So then AS = {TRANSFER} union {stages logically earlier than TRANSFER}

and BS = {TRANSFER} union {stages logically later than TRANSFER}?

If this were the case, my confusion would be resolved. But... (From Nicol's answer)

The spec said nothing about what commands get executed.

This seems in contradiction with my interpretation of the spec. Chapter 6.6 says:

If vkCmdPipelineBarrier was recorded outside a render pass instance, the second synchronization scope includes all commands that occur later in submission order.

BS is another name the spec gives for the second synchronization scope. So then BS contains commands, not pipeline stages right? Then how can the TRANSFER stage be in BS?

I don't mean to be pedantic, I am genuinely trying to learn how to interpret the spec and come to this conclusion on my own so that I'm not dependent on stackoverflow.

1

1 Answers

2
votes

The specification states:

Pipeline stages that execute as a result of a command logically complete execution in a specific order, such that completion of a logically later pipeline stage must not happen-before completion of a logically earlier stage. This means that including any stage in the source stage mask for a particular synchronization command also implies that any logically earlier stages are included in AS for that command.

As for the rest:

In the blog post's example, wouldn't BS for the first pipeline barrier be the empty set since vkCmdDispatch doesn't contain a transfer stage?

No. The spec said nothing about what commands get executed. It was talking specifically about the set of stages involved. Bs lists TRANSFER. As include TRANSFER. The intersection of the two stage masks is TRANSFER and therefore not empty. Therefore, there is a dependency chain.


It seems you may not fully understand what a synchronization scope is, as separate from the actual operations bounded by that scope. The spec states:

The synchronization scopes define which other operations a synchronization command is able to create execution dependencies with. Any type of operation that is not in a synchronization command’s synchronization scopes will not be included in the resulting dependency. For example, for many synchronization commands, the synchronization scopes can be limited to just operations executing in specific pipeline stages, which allows other pipeline stages to be excluded from a dependency. Other scoping options are possible, depending on the particular command.

The specification also specifically makes a distinction between the synchronization scope and the commands that may be bound by that scope:

  • Let A and B be separate sets of operations.
  • Let S be a synchronization command.
  • Let AS and BS be the synchronization scopes of S.
  • Let A' be the intersection of sets A and AS.
  • Let B' be the intersection of sets B and BS.

A and B represent the actual commands that are part of the operations. AS and BS represent what parts of commands can take part in the dependency. When you put them together, you get A' and B': the actual stages from actual commands that get synchronized.

The section of the quote you cited about dependency chains bases the chain on the presence of matching scopes, not of matching commands within those scopes.