## 6.4. Execution And Memory Dependencies

Synchronization commands introduce explicit execution and memory dependencies between two sets of action commands, where the second set of commands depends on the first set of commands. The two sets can be:

• First set: commands before a vkCmdSetEvent command.

Second set: commands after a vkCmdWaitEvents command in the same queue, using the same event.

• First set: commands in a lower numbered subpass (or before a render pass instance).

Second set: commands in a higher numbered subpass (or after a render pass instance), where there is a subpass dependency between the two subpasses (or between a subpass and VK_SUBPASS_EXTERNAL).

• First set: commands before a pipeline barrier.

Second set: commands after that pipeline barrier in the same queue (possibly limited to within the same subpass).

An execution dependency is a single dependency between a set of source and destination pipeline stages, which guarantees that all work performed by the set of pipeline stages included in srcStageMask (see Pipeline Stage Flags) of the first set of commands completes before any work performed by the set of pipeline stages included in dstStageMask of the second set of commands begins.

An execution dependency chain from a set of source pipeline stages $A$ to a set of destination pipeline stages $B$ is a sequence of execution dependencies submitted to a queue in order between a first set of commands and a second set of commands, satisfying the following conditions:

• the first dependency includes $A$ or VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT or VK_PIPELINE_STAGE_ALL_COMMANDS_BIT in the srcStageMask. And,
• the final dependency includes $B$ or VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT or VK_PIPELINE_STAGE_ALL_COMMANDS_BIT in the dstStageMask. And,
• for each dependency in the sequence (except the first) at least one of the following conditions is true:

• srcStageMask of the current dependency includes at least one bit $C$ that is present in the dstStageMask of the previous dependency. Or,
• srcStageMask of the current dependency includes VK_PIPELINE_STAGE_ALL_COMMANDS_BIT or VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT. Or,
• dstStageMask of the previous dependency includes VK_PIPELINE_STAGE_ALL_COMMANDS_BIT or VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT. Or,
• srcStageMask of the current dependency includes VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, and dstStageMask of the previous dependency includes at least one graphics pipeline stage. Or,
• dstStageMask of the previous dependency includes VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, and srcStageMask of the current dependency includes at least one graphics pipeline stage.
• for each dependency in the sequence (except the first), at least one of the following conditions is true:

• the current dependency is a vkCmdSetEvent/vkCmdWaitEvents pair (where the vkCmdWaitEvents may be inside or outside a render pass instance), or a vkCmdPipelineBarrier outside of a render pass instance, or a subpass dependency with srcSubpass equal to VK_SUBPASS_EXTERNAL for a render pass instance that begins with a vkCmdBeginRenderPass command, and the previous dependency is any of:

• a vkCmdSetEvent/vkCmdWaitEvents pair or a vkCmdPipelineBarrier, either one outside of a render pass instance, that precedes the current dependency in the queue execution order. Or,
• a subpass dependency, with dstSubpass equal to VK_SUBPASS_EXTERNAL, for a renderpass instance that was ended with a vkCmdEndRenderPass command that precedes the current dependency in the queue execution order.
• the current dependency is a subpass dependency for a render pass instance, and the previous dependency is any of:

• another dependency for the same render pass instance, with a dstSubpass equal to the srcSubpass of the current dependency. Or,
• a vkCmdPipelineBarrier of the same render pass instance, recorded for the subpass indicated by the srcSubpass of the current dependency. Or,
• a vkCmdSetEvent/vkCmdWaitEvents pair, where the vkCmdWaitEvents is inside the same render pass instance, recorded for the subpass indicated by the srcSubpass of the current dependency.
• the current dependency is a vkCmdPipelineBarrier inside a subpass of a render pass instance, and the previous dependency is any of:

• a subpass dependency for the same render pass instance, with a dstSubpass equal to the subpass of the vkCmdPipelineBarrier. Or,
• a vkCmdPipelineBarrier of the same render pass instance, recorded for the same subpass, before the current dependency. Or,
• a vkCmdSetEvent/vkCmdWaitEvents pair, where the vkCmdWaitEvents is inside the same render pass instance, recorded for the same subpass, before the current dependency.

A pair of consecutive execution dependencies in an execution dependency chain accomplishes a dependency between the stages $A$ and $B$ via intermediate stages $C$ , even if no work is executed between them that uses the pipeline stages included in $C$ .

An execution dependency chain guarantees that the work performed by the pipeline stages $A$ in the first set of commands completes before the work performed by pipeline stages $B$ in the second set of commands begins.

A command $C_1$ is said to happen-before an execution dependency $D_2$ for a pipeline stage $S$ if all the following conditions are true:

• $C_1$ is in the first set of commands for an execution dependency $D_1$ that includes $S$ in its srcStageMask. And,
• there exists an execution dependency chain that includes $D_1$ and $D_2$ , where $D_2$ follows $D_1$ in the execution dependency sequence.

Similarly, a command $C_2$ is said to happen-after an execution dependency $D_1$ for a pipeline stage $S$ if all the following conditions are true:

• $C_2$ is in the second set of commands for an execution dependency $D_2$ that includes $S$ in its dstStageMask. And,
• there exists an execution dependency chain that includes $D_1$ and $D_2$ , where $D_2$ follows $D_1$ in the execution dependency sequence.

An execution dependency is by-region if its dependencyFlags parameter includes VK_DEPENDENCY_BY_REGION_BIT. Such a barrier describes a per-region (x,y,layer) dependency. That is, for each region, the implementation must ensure that the source stages for the first set of commands complete execution before any destination stages begin execution in the second set of commands for the same region. Since fragment shader invocations are not specified to run in any particular groupings, the size of a region is implementation-dependent, not known to the application, and must be assumed to be no larger than a single pixel. If dependencyFlags does not include VK_DEPENDENCY_BY_REGION_BIT, it describes a global dependency, that is for all pixel regions, the source stages must have completed for preceding commands before any destination stages starts for subsequent commands.

Memory dependencies are coupled to execution dependencies, and synchronize accesses to memory between two sets of commands. They operate according to two “halves” of a dependency to synchronize two sets of commands, the commands that happen-before the execution dependency for the srcStageMask vs the commands that happen-after the execution dependency for the dstStageMask, as described above. The first half of the dependency makes memory accesses using the set of access types in srcAccessMask performed in pipeline stages in srcStageMask by the first set of commands complete and writes be available for subsequent commands. The second half of the dependency makes any available writes from previous commands visible to pipeline stages in dstStageMask using the set of access types in dstAccessMask for the second set of commands, if those writes have been made available with the first half of the same or a previous dependency. The two halves of a memory dependency can either be expressed as part of a single command, or can be part of separate barriers as long as there is an execution dependency chain between them. The application must use memory dependencies to make writes visible before subsequent reads can rely on them, and before subsequent writes can overwrite them. Failure to do so causes the result of the reads to be undefined, and the order of writes to be undefined.

Global memory barriers apply to all resources owned by the device. Buffer and image memory barriers apply to the buffer range(s) or image subresource(s) included in the command. For accesses to a byte of a buffer or image subresource of an image to be synchronized between two sets of commands, the byte or image subresource must be included in both the first and second halves of the dependencies described above, but need not be included in each step of the execution dependency chain between them.

An execution dependency chain is by-region if all stages in all dependencies in the chain are framebuffer-space pipeline stages, and if the VK_DEPENDENCY_BY_REGION_BIT bit is included in all dependencies in the chain. Otherwise, the execution dependency chain is not by-region. The two halves of a memory dependency form a by-region dependency if all execution dependency chains between them are by-region. In other words, if there is any execution dependency between two sets of commands that is not by-region, then the memory dependency is not by-region.

When an image memory barrier includes a layout transition, the barrier first makes writes via srcStageMask and srcAccessMask available, then performs the layout transition, then makes the contents of the image subresource(s) in the new layout visible to memory accesses in dstStageMask and dstAccessMask, as if there is an execution and memory dependency between the source masks and the transition, as well as between the transition and the destination masks. Any writes that have previously been made available are included in the layout transition, but any previous writes that have not been made available may become lost or corrupt the image.

All dependencies must include at least one bit in each of the srcStageMask and dstStageMask.

Memory dependencies are used to solve data hazards, e.g. to ensure that write operations are visible to subsequent read operations (read-after-write hazard), as well as write-after-write hazards. Write-after-read and read-after-read hazards only require execution dependencies to synchronize.