## 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 C1 is said to happen-before an execution dependency D2 for a pipeline stage S if all the following conditions are true:

- C1 is in the first set of commands for an execution dependency D1 that includes S in its `srcStageMask`. And,
- there exists an execution dependency chain that includes D1 and D2, where D2 follows D1 in the execution dependency sequence.

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

- C2 is in the second set of commands for an execution dependency D2 that includes S in its `dstStageMask`. And,
- there exists an execution dependency chain that includes D1 and D2, where D2 follows D1 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.