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:
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT
or
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
in the srcStageMask
.
And,
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:
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,
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:
dstSubpass
equal to the srcSubpass
of the current
dependency.
Or,
vkCmdPipelineBarrier
of the same render pass instance,
recorded for the subpass indicated by the srcSubpass
of the
current dependency.
Or,
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:
dstSubpass
equal to the subpass of the
vkCmdPipelineBarrier
.
Or,
vkCmdPipelineBarrier
of the same render pass instance,
recorded for the same subpass, before the current dependency.
Or,
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:
srcStageMask
.
And,
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:
dstStageMask
.
And,
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.