2190 lines
100 KiB
Plaintext
2190 lines
100 KiB
Plaintext
// Copyright (c) 2015-2017 The Khronos Group Inc.
|
|
// Copyright notice at https://www.khronos.org/registry/speccopyright.html
|
|
|
|
[[synchronization]]
|
|
= Synchronization and Cache Control
|
|
|
|
Synchronization of access to resources is primarily the responsibility of
|
|
the application in Vulkan.
|
|
The order of execution of commands with respect to the host and other
|
|
commands on the device has few implicit guarantees, and needs to be
|
|
explicitly specified.
|
|
Memory caches and other optimizations are also explicitly managed, requiring
|
|
that the flow of data through the system is largely under application
|
|
control.
|
|
|
|
Whilst some implicit guarantees exist between commands, four explicit
|
|
synchronization primitives are exposed by Vulkan:
|
|
|
|
<<synchronization-fences,Fences>>::
|
|
Fences can: be used to communicate to the host that execution of some
|
|
task on the device has completed.
|
|
|
|
<<synchronization-semaphores,Semaphores>>::
|
|
Semaphores can: be used to control resource access across multiple
|
|
queues.
|
|
|
|
<<synchronization-events,Events>>::
|
|
Events provide a fine-grained synchronization primitive which can: be
|
|
signaled either within a command buffer or by the host, and can: be
|
|
waited upon within a command buffer or queried on the host.
|
|
|
|
<<synchronization-pipeline-barriers,Pipeline Barriers>>::
|
|
Pipeline barriers also provide synchronization control within a command
|
|
buffer, but at a single point, rather than with separate signal and wait
|
|
operations.
|
|
|
|
In addition to the base primitives provided here, <<renderpass, Render
|
|
Passes>> provide a useful synchronization framework for most rendering
|
|
tasks, built upon the concepts in this chapter.
|
|
Many cases that would otherwise need an application to use synchronization
|
|
primitives in this chapter can: be expressed more efficiently as part of a
|
|
render pass.
|
|
|
|
|
|
[[synchronization-dependencies]]
|
|
== Execution and Memory Dependencies
|
|
|
|
An _operation_ is an arbitrary amount of work to be executed on the host, a
|
|
device, or an external entity such as a presentation engine.
|
|
Synchronization commands introduce explicit _execution dependencies_, and
|
|
_memory dependencies_ between two sets of operations defined by the
|
|
command's two _synchronization scopes_.
|
|
|
|
[[synchronization-dependencies-scopes]]
|
|
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
|
|
<<synchronization-pipeline-stages,pipeline stages>>, which allows other
|
|
pipeline stages to be excluded from a dependency.
|
|
Other scoping options are possible, depending on the particular command.
|
|
|
|
[[synchronization-dependencies-execution]]
|
|
An _execution dependency_ is a guarantee that for two sets of operations,
|
|
the first set must: _happen-before_ the second set.
|
|
If an operation happens-before another operation, then the first operation
|
|
must: complete before the second operation is initiated.
|
|
More precisely:
|
|
|
|
* Let *A* and *B* be separate sets of operations.
|
|
* Let *S* be a synchronization command.
|
|
* Let *A~S~* and *B~S~* be the synchronization scopes of *S*.
|
|
* Let *A'* be the intersection of sets *A* and *A~S~*.
|
|
* Let *B'* be the intersection of sets *B* and *B~S~*.
|
|
* Submitting *A*, *S* and *B* for execution, in that order, will result in
|
|
execution dependency *E* between *A'* and *B'*.
|
|
* Execution dependency *E* guarantees that *A'* happens-before *B'*.
|
|
|
|
[[synchronization-dependencies-chains]]
|
|
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 *B~S~* in the first dependency and *A~S~* in the second
|
|
dependency is not an empty set.
|
|
The formation of a single execution dependency from an execution dependency
|
|
chain can be described by substituting the following in the description of
|
|
execution dependencies:
|
|
|
|
* Let *S* be a set of synchronization commands that generate an execution
|
|
dependency chain.
|
|
* Let *A~S~* be the first synchronization scope of the first command in
|
|
*S*.
|
|
* Let *B~S~* be the second synchronization scope of the last command in
|
|
*S*.
|
|
|
|
.Note
|
|
[NOTE]
|
|
====
|
|
An execution dependency is inherently also multiple execution dependencies -
|
|
a dependency exists between each subset of *A'* and each subset of *B'*, and
|
|
the same is true for execution dependency chains.
|
|
For example, a synchronization command with multiple
|
|
<<synchronization-pipeline-stages,pipeline stages>> in its stage masks
|
|
effectively generates one dependency between each source stage and each
|
|
destination stage.
|
|
This can be useful to think about when considering how execution chains are
|
|
formed if they don't involve all parts of a synchronization command's
|
|
dependency.
|
|
Similarly, any set of adjacent dependencies in an execution dependency chain
|
|
can: be considered an execution dependency chain in its own right.
|
|
====
|
|
|
|
Execution dependencies alone are not sufficient to guarantee that values
|
|
resulting from writes in one set of operations can: be read from another set
|
|
of operations.
|
|
|
|
[[synchronization-dependencies-available-and-visible]]
|
|
Two additional types of operation are used to control memory access.
|
|
_Availability operations_ cause the values generated by specified memory
|
|
write accesses to become _available_ for future access.
|
|
Any available value remains available until a subsequent write to the same
|
|
memory location occurs (whether it is made available or not) or the memory
|
|
is freed.
|
|
_Visibility operations_ cause any available values to become _visible_ to
|
|
specified memory accesses.
|
|
|
|
[[synchronization-dependencies-memory]]
|
|
A _memory dependency_ is an execution dependency which includes availability
|
|
and visibility operations such that:
|
|
|
|
* The first set of operations happens-before the availability operation.
|
|
* The availability operation happens-before the visibility operation.
|
|
* The visibility operation happens-before the second set of operations.
|
|
|
|
Once written values are made visible to a particular type of memory access,
|
|
they can: be read or written by that type of memory access.
|
|
Most synchronization commands in Vulkan define a memory dependency.
|
|
|
|
[[synchronization-dependencies-access-scopes]]
|
|
The specific memory accesses that are made available and visible are defined
|
|
by the _access scopes_ of a memory dependency.
|
|
Any type of access that is in a memory dependency's first access scope and
|
|
occurs in *A'* is made available.
|
|
Any type of access that is in a memory dependency's second access scope and
|
|
occurs in *B'* has any available writes made visible to it.
|
|
Any type of operation that is not in a synchronization command's access
|
|
scopes will not be included in the resulting dependency.
|
|
|
|
A memory dependency enforces availability and visibility of memory accesses
|
|
and execution order two sets of operations.
|
|
Adding to the description of <<synchronization-dependencies-chains,
|
|
execution dependency chains>>:
|
|
|
|
* Let *a* be the set of memory accesses performed by *A'*.
|
|
* Let *b* be the set of memory accesses performed by *B'*.
|
|
* Let *a~S~* be the first access scope of the first command in *S*.
|
|
* Let *b~S~* be the second access scope of the last command in *S*.
|
|
* Let *a'* be the intersection of sets *a* and *a~S~*.
|
|
* Let *b'* be the intersection of sets *b* and *b~S~*.
|
|
* Submitting *A*, *S* and *B* for execution, in that order, will result in
|
|
a memory dependency *m* between *A'* and *B'*.
|
|
* Memory dependency *m* guarantees that:
|
|
** Memory writes in *a'* are made available.
|
|
** Available memory writes, including those from *a'*, are made visible to
|
|
*b'*.
|
|
|
|
[NOTE]
|
|
.Note
|
|
====
|
|
Execution and memory dependencies are used to solve data hazards, i.e. to
|
|
ensure that read and write operations occur in a well-defined order.
|
|
Write-after-read hazards can be solved with just an execution dependency,
|
|
but read-after-write and write-after-write hazards need appropriate memory
|
|
dependencies to be included between them.
|
|
If an application does not include dependencies to solve these hazards, the
|
|
results and execution orders of memory accesses are undefined.
|
|
====
|
|
|
|
|
|
[[synchronization-image-layout-transitions]]
|
|
=== Image Layout Transitions
|
|
|
|
Image subresources can: be transitioned from one <<resources-image-layouts,
|
|
layout>> to another as part of a <<synchronization-dependencies-memory,
|
|
memory dependency>> (e.g. by using an
|
|
<<synchronization-image-memory-barriers,image memory barrier>>).
|
|
When a layout transition is specified in a memory dependency, it
|
|
happens-after the availability operations in the memory dependency, and
|
|
happens-before the visibility operations.
|
|
Image layout transitions may: perform read and write accesses on all memory
|
|
bound to the image subresource range, so applications must: ensure that all
|
|
memory writes have been made
|
|
<<synchronization-dependencies-available-and-visible, available>> before a
|
|
layout transition is executed.
|
|
Available memory is automatically made visible to a layout transition, and
|
|
writes performed by a layout transition are automatically made available.
|
|
|
|
Layout transitions always apply to a particular image subresource range, and
|
|
specify both an old layout and new layout.
|
|
If the old layout does not match the new layout, a transition occurs.
|
|
The old layout must: match the current layout of the image subresource
|
|
range, with one exception.
|
|
The old layout can: always be specified as ename:VK_IMAGE_LAYOUT_UNDEFINED,
|
|
though doing so invalidates the contents of the image subresource range.
|
|
|
|
.Note
|
|
[NOTE]
|
|
====
|
|
Setting the old layout to ename:VK_IMAGE_LAYOUT_UNDEFINED implies that the
|
|
contents of the image subresource need not be preserved.
|
|
Implementations may: use this information to avoid performing expensive data
|
|
transition operations.
|
|
====
|
|
|
|
.Note
|
|
[NOTE]
|
|
====
|
|
Applications must: ensure that layout transitions happen-after all
|
|
operations accessing the image with the old layout, and happen-before any
|
|
operations that will access the image with the new layout.
|
|
Layout transitions are potentially read/write operations, so not defining
|
|
appropriate memory dependencies to guarantee this will result in a data
|
|
race.
|
|
====
|
|
|
|
The contents of any portion of another resource which aliases memory that is
|
|
bound to the transitioned image subresource range are undefined after an
|
|
image layout transition.
|
|
|
|
|
|
[[synchronization-pipeline-stages]]
|
|
=== Pipeline Stages
|
|
|
|
The work performed by an <<fundamentals-queueoperation-commandorder, action
|
|
command>> consists of multiple operations, which are performed by a sequence
|
|
of logically independent execution units known as _pipeline stages_.
|
|
The exact pipeline stages executed depend on the particular action command
|
|
that is used, and current command buffer state when the action command was
|
|
recorded.
|
|
<<drawing,Drawing commands>>, <<dispatch,dispatching commands>>,
|
|
<<copies,copy commands>>, and <<clears,clear commands>> all execute
|
|
<<synchronization-pipeline-stages-types,different sets of pipeline stages>>.
|
|
|
|
Execution of operations across pipeline stages must: adhere to
|
|
<<fundamentals-queueoperation-apiorder, API order>>,
|
|
<<fundamentals-queueoperation-commandorder, command order>>, and
|
|
<<synchronization-pipeline-stages-order, pipeline stage order>>.
|
|
Otherwise, execution across pipeline stages may: overlap or execute out of
|
|
order with regards to other stages, unless otherwise enforced by an
|
|
execution dependency.
|
|
|
|
// refBegin VkPipelineStageFlagBits - Bitmask specifying pipeline stages
|
|
|
|
Several of the <<fundamentals-queueoperation-commandorder, synchronization
|
|
commands>> include pipeline stage parameters, restricting the
|
|
<<synchronization-dependencies-scopes, synchronization scopes>> for that
|
|
command to those stages.
|
|
This allows fine grained control over the exact execution dependencies and
|
|
accesses performed by action commands.
|
|
Implementations should: use these pipeline stages to avoid unnecessary
|
|
stalls or cache flushing.
|
|
|
|
These pipeline stages are specified using a bitmask:
|
|
|
|
include::../api/enums/VkPipelineStageFlagBits.txt[]
|
|
|
|
The meaning of each bit is:
|
|
|
|
* ename:VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT: Stage of the pipeline where any
|
|
commands are initially received by the queue.
|
|
ifdef::VK_NVX_device_generated_commands[]
|
|
* ename:VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX: Stage of the pipeline
|
|
where device-side generation of commands via
|
|
flink:vkCmdProcessCommandsNVX is handled.
|
|
endif::VK_NVX_device_generated_commands[]
|
|
* ename:VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT: Stage of the pipeline where
|
|
Draw/DispatchIndirect data structures are consumed.
|
|
ifdef::VK_NVX_device_generated_commands[]
|
|
This stage also includes reading commands written by
|
|
flink:vkCmdProcessCommandsNVX.
|
|
endif::VK_NVX_device_generated_commands[]
|
|
* ename:VK_PIPELINE_STAGE_VERTEX_INPUT_BIT: Stage of the pipeline where
|
|
vertex and index buffers are consumed.
|
|
* ename:VK_PIPELINE_STAGE_VERTEX_SHADER_BIT: Vertex shader stage.
|
|
* ename:VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT: Tessellation
|
|
control shader stage.
|
|
* ename:VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT: Tessellation
|
|
evaluation shader stage.
|
|
* ename:VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT: Geometry shader stage.
|
|
* ename:VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT: Fragment shader stage.
|
|
* ename:VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT: Stage of the pipeline
|
|
where early fragment tests (depth and stencil tests before fragment
|
|
shading) are performed.
|
|
This stage also includes <<renderpass-load-store-ops, subpass load
|
|
operations>> for framebuffer attachments with a depth/stencil format.
|
|
* ename:VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT: Stage of the pipeline
|
|
where late fragment tests (depth and stencil tests after fragment
|
|
shading) are performed.
|
|
This stage also includes <<renderpass-load-store-ops, subpass store
|
|
operations>> for framebuffer attachments with a depth/stencil format.
|
|
* ename:VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT: Stage of the
|
|
pipeline after blending where the final color values are output from the
|
|
pipeline.
|
|
This stage also includes <<renderpass-load-store-ops, subpass load and
|
|
store operations>> and multisample resolve operations for framebuffer
|
|
attachments with a color format.
|
|
* [[synchronization-pipeline-stages-transfer]]
|
|
ename:VK_PIPELINE_STAGE_TRANSFER_BIT: Execution of copy commands.
|
|
This includes the operations resulting from all <<copies,copy
|
|
commands>>, <<clears,clear commands>> (with the exception of
|
|
flink:vkCmdClearAttachments), and flink:vkCmdCopyQueryPoolResults.
|
|
* ename:VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT: Execution of a compute
|
|
shader.
|
|
* ename:VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT: Final stage in the pipeline
|
|
where operations generated by all commands complete execution.
|
|
* ename:VK_PIPELINE_STAGE_HOST_BIT: A pseudo-stage indicating execution on
|
|
the host of reads/writes of device memory.
|
|
This stage is not invoked by any commands recorded in a command buffer.
|
|
* ename:VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT: Execution of all graphics
|
|
pipeline stages.
|
|
Equivalent to the logical or of:
|
|
|
|
** ename:VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT
|
|
** ename:VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT
|
|
** ename:VK_PIPELINE_STAGE_VERTEX_INPUT_BIT
|
|
** ename:VK_PIPELINE_STAGE_VERTEX_SHADER_BIT
|
|
** ename:VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT
|
|
** ename:VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT
|
|
** ename:VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT
|
|
** ename:VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
|
|
** ename:VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
|
|
** ename:VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT
|
|
** ename:VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
|
|
** ename:VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT
|
|
|
|
* ename:VK_PIPELINE_STAGE_ALL_COMMANDS_BIT: Equivalent to the logical or
|
|
of every other pipeline stage flag that is supported on the queue it is
|
|
used with.
|
|
|
|
[NOTE]
|
|
.Note
|
|
====
|
|
An execution dependency with only ename:VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT
|
|
in the destination stage mask will only prevent that stage from executing in
|
|
subsequently submitted commands.
|
|
As this stage doesn't perform any actual execution, this is not observable -
|
|
in effect, it does not delay processing of subsequent commands.
|
|
Similarly an execution dependency with only
|
|
ename:VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT in the source stage mask will
|
|
effectively not wait for any prior commands to complete.
|
|
|
|
When defining a memory dependency, using only
|
|
ename:VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT or
|
|
ename:VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT would never make any accesses
|
|
available and/or visible because these stages do not access memory.
|
|
|
|
ename:VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT and
|
|
ename:VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT are useful for accomplishing layout
|
|
transitions and queue ownership operations when the required execution
|
|
dependency is satisfied by other means - for example, semaphore operations
|
|
between queues.
|
|
====
|
|
|
|
// refEnd VkPipelineStageFlagBits
|
|
|
|
[[synchronization-pipeline-stages-masks]]
|
|
If a synchronization command includes a source stage mask, its first
|
|
<<synchronization-dependencies-scopes, synchronization scope>> only includes
|
|
execution of the pipeline stages specified in that mask, as well as any
|
|
<<synchronization-pipeline-stages-order, logically earlier>> stages.
|
|
If a synchronization command includes a destination stage mask, its second
|
|
<<synchronization-dependencies-scopes, synchronization scope>> only includes
|
|
execution of the pipeline stages specified in that mask, as well as any
|
|
<<synchronization-pipeline-stages-order, logically later>> stages.
|
|
|
|
<<synchronization-dependencies-access-scopes, Access scopes>> are affected
|
|
in a similar way.
|
|
If a synchronization command includes a source stage mask, its first
|
|
<<synchronization-dependencies-access-scopes, access scope>> only includes
|
|
memory access performed by pipeline stages specified in that mask.
|
|
If a synchronization command includes a destination stage mask, its second
|
|
<<synchronization-dependencies-access-scopes, access scope>> only includes
|
|
memory access performed by pipeline stages specified in that mask.
|
|
|
|
[NOTE]
|
|
.Note
|
|
====
|
|
Implementations may: not support synchronization at every pipeline stage for
|
|
every synchronization operation.
|
|
If a pipeline stage that an implementation does not support synchronization
|
|
for appears in a source stage mask, then it may: substitute that stage for
|
|
any logically later stage.
|
|
If a pipeline stage that an implementation does not support synchronization
|
|
for appears in a destination stage mask, then it may: substitute that stage
|
|
for any logically earlier stage.
|
|
|
|
For example, if an implementation is unable to signal an event immediately
|
|
after vertex shader execution is complete, it may: instead signal the event
|
|
after color attachment output has completed.
|
|
|
|
If an implementation makes such a substitution, it must: not affect the
|
|
semantics of execution or memory dependencies or image and buffer memory
|
|
barriers.
|
|
====
|
|
|
|
Certain pipeline stages are only available on queues that support a
|
|
particular set of operations.
|
|
The following table lists, for each pipeline stage flag, which queue
|
|
capability flag must: be supported by the queue.
|
|
When multiple flags are enumerated in the second column of the table, it
|
|
means that the pipeline stage is supported on the queue if it supports any
|
|
of the listed capability flags.
|
|
For further details on queue capabilities see
|
|
<<devsandqueues-physical-device-enumeration,Physical Device Enumeration>>
|
|
and <<devsandqueues-queues,Queues>>.
|
|
|
|
[[synchronization-pipeline-stages-supported]]
|
|
.Supported pipeline stage flags
|
|
[width="100%",cols="69%,31%",options="header",align="center"]
|
|
|====
|
|
|Pipeline stage flag | Required queue capability flag
|
|
|ename:VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | None required
|
|
|ename:VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT | ename:VK_QUEUE_GRAPHICS_BIT or ename:VK_QUEUE_COMPUTE_BIT
|
|
|ename:VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | ename:VK_QUEUE_GRAPHICS_BIT
|
|
|ename:VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | ename:VK_QUEUE_GRAPHICS_BIT
|
|
|ename:VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT | ename:VK_QUEUE_GRAPHICS_BIT
|
|
|ename:VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT | ename:VK_QUEUE_GRAPHICS_BIT
|
|
|ename:VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT | ename:VK_QUEUE_GRAPHICS_BIT
|
|
|ename:VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | ename:VK_QUEUE_GRAPHICS_BIT
|
|
|ename:VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | ename:VK_QUEUE_GRAPHICS_BIT
|
|
|ename:VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | ename:VK_QUEUE_GRAPHICS_BIT
|
|
|ename:VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | ename:VK_QUEUE_GRAPHICS_BIT
|
|
|ename:VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | ename:VK_QUEUE_COMPUTE_BIT
|
|
|ename:VK_PIPELINE_STAGE_TRANSFER_BIT | ename:VK_QUEUE_GRAPHICS_BIT, ename:VK_QUEUE_COMPUTE_BIT or ename:VK_QUEUE_TRANSFER_BIT
|
|
|ename:VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT | None required
|
|
|ename:VK_PIPELINE_STAGE_HOST_BIT | None required
|
|
|ename:VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | ename:VK_QUEUE_GRAPHICS_BIT
|
|
|ename:VK_PIPELINE_STAGE_ALL_COMMANDS_BIT | None required
|
|
ifdef::VK_NVX_device_generated_commands[]
|
|
|ename:VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX | ename:VK_QUEUE_GRAPHICS_BIT or ename:VK_QUEUE_COMPUTE_BIT
|
|
endif::VK_NVX_device_generated_commands[]
|
|
|====
|
|
|
|
[[synchronization-pipeline-stages-order]]
|
|
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 given stage in the source stage mask for a
|
|
particular synchronization command also implies that any logically earlier
|
|
stages are included in *A~S~* for that command.
|
|
|
|
Similarly, initiation of a logically earlier pipeline stage must: not
|
|
happen-after initiation of a logically later pipeline stage.
|
|
Including any given stage in the destination stage mask for a particular
|
|
synchronization command also implies that any logically later stages are
|
|
included in *B~S~* for that command.
|
|
|
|
.Note
|
|
[NOTE]
|
|
====
|
|
Logically earlier/later stages are not included when defining the
|
|
<<synchronization-dependencies-access-scopes, access scopes>> of a
|
|
<<synchronization-memory-barriers,memory barrier>>.
|
|
====
|
|
|
|
[[synchronization-pipeline-stages-types]]
|
|
The order of pipeline stages depends on the particular pipeline; graphics,
|
|
compute, transfer or host.
|
|
|
|
For the graphics pipeline, the following stages occur in this order:
|
|
|
|
* ename:VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT
|
|
* ename:VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT
|
|
* ename:VK_PIPELINE_STAGE_VERTEX_INPUT_BIT
|
|
* ename:VK_PIPELINE_STAGE_VERTEX_SHADER_BIT
|
|
* ename:VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT
|
|
* ename:VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT
|
|
* ename:VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT
|
|
* ename:VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
|
|
* ename:VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
|
|
* ename:VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT
|
|
* ename:VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
|
|
* ename:VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT
|
|
|
|
For the compute pipeline, the following stages occur in this order:
|
|
|
|
* ename:VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT
|
|
* ename:VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT
|
|
* ename:VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT
|
|
* ename:VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT
|
|
|
|
For the transfer pipeline, the following stages occur in this order:
|
|
|
|
* ename:VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT
|
|
* ename:VK_PIPELINE_STAGE_TRANSFER_BIT
|
|
* ename:VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT
|
|
|
|
For host operations, only one pipeline stage occurs, so no order is
|
|
guaranteed:
|
|
|
|
* ename:VK_PIPELINE_STAGE_HOST_BIT
|
|
|
|
ifdef::VK_NVX_device_generated_commands[]
|
|
For the command processing pipeline, the following stages occur in this
|
|
order:
|
|
|
|
* ename:VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT
|
|
* ename:VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX
|
|
* ename:VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT
|
|
endif::VK_NVX_device_generated_commands[]
|
|
|
|
[[synchronization-access-types]]
|
|
=== Access Types
|
|
|
|
Memory in Vulkan can: be accessed from within shader invocations and via
|
|
some fixed-function stages of the pipeline.
|
|
The _access type_ is a function of the <<descriptorsets, descriptor type>>
|
|
used, or how a fixed-function stage accesses memory.
|
|
Each access type corresponds to a bit flag in slink:VkAccessFlagBits.
|
|
|
|
[[synchronization-access-masks]]
|
|
Some synchronization commands take sets of access types as parameters to
|
|
define the <<synchronization-dependencies-access-scopes, access scopes>> of
|
|
a memory dependency.
|
|
If a synchronization command includes a source access mask, its first
|
|
<<synchronization-dependencies-access-scopes, access scope>> only includes
|
|
accesses via the access types specified in that mask.
|
|
Similarly, if a synchronization command includes a destination access mask,
|
|
its second <<synchronization-dependencies-access-scopes, access scope>> only
|
|
includes accesses via the access types specified in that mask.
|
|
|
|
// refBegin VkAccessFlagBits Bitmask specifying memory access types that will participate in a memory dependency
|
|
|
|
Access types that can be set in an access mask include:
|
|
|
|
[[synchronization-access-flags]]
|
|
include::../api/enums/VkAccessFlagBits.txt[]
|
|
|
|
* ename:VK_ACCESS_INDIRECT_COMMAND_READ_BIT: Read access to an indirect
|
|
command structure read as part of an indirect drawing or dispatch
|
|
command.
|
|
* ename:VK_ACCESS_INDEX_READ_BIT: Read access to an index buffer as part
|
|
of an indexed drawing command, bound by flink:vkCmdBindIndexBuffer.
|
|
* ename:VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT: Read access to a vertex
|
|
buffer as part of a drawing command, bound by
|
|
flink:vkCmdBindVertexBuffers.
|
|
* ename:VK_ACCESS_UNIFORM_READ_BIT: Read access to a
|
|
<<descriptorsets-uniformbuffer, uniform buffer>>.
|
|
* ename:VK_ACCESS_INPUT_ATTACHMENT_READ_BIT: Read access to an
|
|
<<renderpass, input attachment>> within a renderpass during fragment
|
|
shading.
|
|
* ename:VK_ACCESS_SHADER_READ_BIT: Read access to a
|
|
<<descriptorsets-storagebuffer, storage buffer>>,
|
|
<<descriptorsets-uniformtexelbuffer, uniform texel buffer>>,
|
|
<<descriptorsets-storagetexelbuffer, storage texel buffer>>,
|
|
<<descriptorsets-sampledimage, sampled image>>, or
|
|
<<descriptorsets-storageimage, storage image>>.
|
|
* ename:VK_ACCESS_SHADER_WRITE_BIT: Write access to a
|
|
<<descriptorsets-storagebuffer, storage buffer>>,
|
|
<<descriptorsets-storagetexelbuffer, storage texel buffer>>, or
|
|
<<descriptorsets-storageimage, storage image>>.
|
|
* ename:VK_ACCESS_COLOR_ATTACHMENT_READ_BIT: Read access to a
|
|
<<renderpass, color attachment>>, such as via <<framebuffer-blending,
|
|
blending>>, <<framebuffer-logicop, logic operations>>, or via certain
|
|
<<renderpass-load-store-ops, subpass load operations>>.
|
|
* ename:VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT: Write access to a
|
|
<<renderpass, color or resolve attachment>> during a <<renderpass,
|
|
render pass>> or via certain <<renderpass-load-store-ops, subpass load
|
|
and store operations>>.
|
|
* ename:VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT: Read access to a
|
|
<<renderpass, depth/stencil attachment>>, via <<fragops-ds-state, depth
|
|
or stencil operations>> or via certain <<renderpass-load-store-ops,
|
|
subpass load operations>>.
|
|
* ename:VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT: Write access to a
|
|
<<renderpass, depth/stencil attachment>>, via <<fragops-ds-state, depth
|
|
or stencil operations>> or via certain <<renderpass-load-store-ops,
|
|
subpass load and store operations>>.
|
|
* ename:VK_ACCESS_TRANSFER_READ_BIT: Read access to an image or buffer in
|
|
a <<copies, copy>> operation.
|
|
* ename:VK_ACCESS_TRANSFER_WRITE_BIT: Write access to an image or buffer
|
|
in a <<clears, clear>> or <<copies, copy>> operation.
|
|
* ename:VK_ACCESS_HOST_READ_BIT: Read access by a host operation.
|
|
Accesses of this type are not performed through a resource, but directly
|
|
on memory.
|
|
* ename:VK_ACCESS_HOST_WRITE_BIT: Write access by a host operation.
|
|
Accesses of this type are not performed through a resource, but directly
|
|
on memory.
|
|
* ename:VK_ACCESS_MEMORY_READ_BIT: Read access via non-specific entities.
|
|
These entities include the Vulkan device and host, but may: also include
|
|
entities external to the Vulkan device or otherwise not part of the core
|
|
Vulkan pipeline.
|
|
When included in a destination access mask, makes all available writes
|
|
visible to all future read accesses on entities known to the Vulkan
|
|
device.
|
|
* ename:VK_ACCESS_MEMORY_WRITE_BIT: Write access via non-specific
|
|
entities.
|
|
These entities include the Vulkan device and host, but may: also include
|
|
entities external to the Vulkan device or otherwise not part of the core
|
|
Vulkan pipeline.
|
|
When included in a source access mask, all writes that are performed by
|
|
entities known to the Vulkan device are made available.
|
|
When included in a destination access mask, makes all available writes
|
|
visible to all future write accesses on entities known to the Vulkan
|
|
device.
|
|
ifdef::VK_NVX_device_generated_commands[]
|
|
* ename:VK_ACCESS_COMMAND_PROCESS_READ_BIT_NVX: Reads from sname:VkBuffer
|
|
inputs to flink:vkCmdProcessCommandsNVX.
|
|
* ename:VK_ACCESS_COMMAND_PROCESS_WRITE_BIT_NVX: Writes to the target
|
|
command buffer in flink:vkCmdProcessCommandsNVX.
|
|
endif::VK_NVX_device_generated_commands[]
|
|
|
|
Certain access types are only performed by a subset of pipeline stages.
|
|
Any synchronization command that takes both stage masks and access masks
|
|
uses both to define the <<synchronization-dependencies-access-scopes, access
|
|
scopes>> - only the specified access types performed by the specified stages
|
|
are included in the access scope.
|
|
An application must: not specify an access flag in a synchronization command
|
|
if it does not include a pipeline stage in the corresponding stage mask that
|
|
is able to perform accesses of that type.
|
|
The following table lists, for each access flag, which pipeline stages can:
|
|
perform that type of access.
|
|
|
|
[[synchronization-access-types-supported]]
|
|
.Supported access types
|
|
[width="100%",cols="67%,33%",options="header",align="center"]
|
|
|====
|
|
|Access flag | Supported pipeline stages
|
|
|ename:VK_ACCESS_INDIRECT_COMMAND_READ_BIT | ename:VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT
|
|
|ename:VK_ACCESS_INDEX_READ_BIT | ename:VK_PIPELINE_STAGE_VERTEX_INPUT_BIT
|
|
|ename:VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT | ename:VK_PIPELINE_STAGE_VERTEX_INPUT_BIT
|
|
|ename:VK_ACCESS_UNIFORM_READ_BIT | ename:VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, ename:VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT, ename:VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT, ename:VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT, ename:VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, or ename:VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT
|
|
|ename:VK_ACCESS_INPUT_ATTACHMENT_READ_BIT | ename:VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
|
|
|ename:VK_ACCESS_SHADER_READ_BIT | ename:VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, ename:VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT, ename:VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT, ename:VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT, ename:VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, or ename:VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT
|
|
|ename:VK_ACCESS_SHADER_WRITE_BIT | ename:VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, ename:VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT, ename:VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT, ename:VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT, ename:VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, or ename:VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT
|
|
|ename:VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | ename:VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
|
|
|ename:VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | ename:VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
|
|
|ename:VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | ename:VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, or ename:VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT
|
|
|ename:VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | ename:VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, or ename:VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT
|
|
|ename:VK_ACCESS_TRANSFER_READ_BIT | ename:VK_PIPELINE_STAGE_TRANSFER_BIT
|
|
|ename:VK_ACCESS_TRANSFER_WRITE_BIT | ename:VK_PIPELINE_STAGE_TRANSFER_BIT
|
|
|ename:VK_ACCESS_HOST_READ_BIT | ename:VK_PIPELINE_STAGE_HOST_BIT
|
|
|ename:VK_ACCESS_HOST_WRITE_BIT | ename:VK_PIPELINE_STAGE_HOST_BIT
|
|
|ename:VK_ACCESS_MEMORY_READ_BIT | N/A
|
|
|ename:VK_ACCESS_MEMORY_WRITE_BIT | N/A
|
|
ifdef::VK_NVX_device_generated_commands[]
|
|
|ename:VK_ACCESS_COMMAND_PROCESS_READ_BIT_NVX | ename:VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX
|
|
|ename:VK_ACCESS_COMMAND_PROCESS_WRITE_BIT_NVX | ename:VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX
|
|
endif::VK_NVX_device_generated_commands[]
|
|
|====
|
|
|
|
|
|
[[synchronization-framebuffer-regions]]
|
|
=== Framebuffer Region Dependencies
|
|
|
|
<<synchronization-pipeline-stages, Pipeline stages>> that operate on, or
|
|
with respect to, the framebuffer are collectively the _framebuffer-space_
|
|
pipeline stages.
|
|
These stages are:
|
|
|
|
* ename:VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
|
|
* ename:VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
|
|
* ename:VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT
|
|
* ename:VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
|
|
|
|
For these pipeline stages, an execution or memory dependency from the first
|
|
set of operations to the second set can: either be a single
|
|
_framebuffer-global_ dependency, or split into multiple _framebuffer-local_
|
|
dependencies.
|
|
A dependency with non-framebuffer-space pipeline stages is neither
|
|
framebuffer-global nor framebuffer-local.
|
|
|
|
A _framebuffer region_ is a set of sample (x, y, layer, sample) coordinates
|
|
that is a subset of the entire framebuffer.
|
|
|
|
A single framebuffer-local dependency guarantees that only for a single
|
|
framebuffer region, the first set of operations and availability operations
|
|
happen-before visibility operations and the second set of operations.
|
|
No ordering guarantees are made between framebuffer regions for a
|
|
framebuffer-local dependency.
|
|
|
|
A framebuffer-global dependency guarantees that the first set of operations
|
|
for all framebuffer regions happens-before the second set of operations for
|
|
any framebuffer region.
|
|
|
|
.Note
|
|
[NOTE]
|
|
====
|
|
Since fragment invocations are not specified to run in any particular
|
|
groupings, the size of a framebuffer region is implementation-dependent, not
|
|
known to the application, and must: be assumed to be no larger than a single
|
|
sample.
|
|
====
|
|
|
|
If a synchronization command includes a pname:dependencyFlags parameter, and
|
|
specifies the ename:VK_DEPENDENCY_BY_REGION_BIT flag, then it defines
|
|
framebuffer-local dependencies for the framebuffer-space pipeline stages in
|
|
that synchronization command, for all framebuffer regions.
|
|
If no pname:dependencyFlags parameter is included, or the
|
|
ename:VK_DEPENDENCY_BY_REGION_BIT flag is not specified, then a
|
|
framebuffer-global dependency is specified for those stages.
|
|
The ename:VK_DEPENDENCY_BY_REGION_BIT flag does not affect the dependencies
|
|
between non-framebuffer-space pipeline stages, nor does it affect the
|
|
dependencies between framebuffer-space and non-framebuffer-space pipeline
|
|
stages.
|
|
|
|
.Note
|
|
[NOTE]
|
|
====
|
|
Framebuffer-local dependencies are more optimal for most architectures;
|
|
particularly tile-based architectures - which can keep framebuffer-regions
|
|
entirely in on-chip registers and thus avoid external bandwidth across such
|
|
a dependency.
|
|
Including a framebuffer-global dependency in your rendering will usually
|
|
force all implementations to flush data to memory, or to a higher level
|
|
cache, breaking any potential locality optimizations.
|
|
====
|
|
|
|
|
|
[[synchronization-fences]]
|
|
== Fences
|
|
|
|
// refBegin VkFence Opaque handle to a fence object
|
|
|
|
Fences are a synchronization primitive that can: be used to insert a
|
|
dependency from a queue to the host.
|
|
Fences have two states - signaled and unsignaled.
|
|
A fence can: be signaled as part of the execution of a
|
|
<<devsandqueues-submission, queue submission>> command.
|
|
Fences can: be unsignaled on the host with flink:vkResetFences.
|
|
Fences can: be waited on by the host with the flink:vkWaitForFences command,
|
|
and the current state can: be queried with flink:vkGetFenceStatus.
|
|
|
|
Fences are represented by sname:VkFence handles:
|
|
|
|
include::../api/handles/VkFence.txt[]
|
|
|
|
// refEnd VkFence
|
|
|
|
// refBegin vkCreateFence Create a new fence object
|
|
|
|
To create a fence, call:
|
|
|
|
include::../api/protos/vkCreateFence.txt[]
|
|
|
|
* pname:device is the logical device that creates the fence.
|
|
* pname:pCreateInfo is a pointer to an instance of the
|
|
sname:VkFenceCreateInfo structure which contains information about how
|
|
the fence is to be created.
|
|
* pname:pAllocator controls host memory allocation as described in the
|
|
<<memory-allocation, Memory Allocation>> chapter.
|
|
* pname:pFence points to a handle in which the resulting fence object is
|
|
returned.
|
|
|
|
include::../validity/protos/vkCreateFence.txt[]
|
|
|
|
// refBegin VkFenceCreateInfo Structure specifying parameters of a newly created fence
|
|
|
|
The sname:VkFenceCreateInfo structure is defined as:
|
|
|
|
include::../api/structs/VkFenceCreateInfo.txt[]
|
|
|
|
* pname:sType is the type of this structure.
|
|
* pname:pNext is `NULL` or a pointer to an extension-specific structure.
|
|
* pname:flags defines the initial state and behavior of the fence.
|
|
Bits which can: be set include:
|
|
+
|
|
--
|
|
// refBegin VkFenceCreateFlagBits Bitmask specifying initial state and behavior of a fence
|
|
include::../api/enums/VkFenceCreateFlagBits.txt[]
|
|
--
|
|
+
|
|
If pname:flags contains ename:VK_FENCE_CREATE_SIGNALED_BIT then the fence
|
|
object is created in the signaled state; otherwise it is created in the
|
|
unsignaled state.
|
|
|
|
include::../validity/structs/VkFenceCreateInfo.txt[]
|
|
|
|
// refBegin vkDestroyFence Destroy a fence object
|
|
|
|
To destroy a fence, call:
|
|
|
|
include::../api/protos/vkDestroyFence.txt[]
|
|
|
|
* pname:device is the logical device that destroys the fence.
|
|
* pname:fence is the handle of the fence to destroy.
|
|
* pname:pAllocator controls host memory allocation as described in the
|
|
<<memory-allocation, Memory Allocation>> chapter.
|
|
|
|
.Valid Usage
|
|
****
|
|
* All <<devsandqueues-submission, queue submission>> commands that refer
|
|
to pname:fence must: have completed execution
|
|
* If sname:VkAllocationCallbacks were provided when pname:fence was
|
|
created, a compatible set of callbacks must: be provided here
|
|
* If no sname:VkAllocationCallbacks were provided when pname:fence was
|
|
created, pname:pAllocator must: be `NULL`
|
|
****
|
|
|
|
include::../validity/protos/vkDestroyFence.txt[]
|
|
|
|
// refBegin vkGetFenceStatus Return the status of a fence
|
|
|
|
To query the status of a fence from the host, call:
|
|
|
|
include::../api/protos/vkGetFenceStatus.txt[]
|
|
|
|
* pname:device is the logical device that owns the fence.
|
|
* pname:fence is the handle of the fence to query.
|
|
|
|
Upon success, fname:vkGetFenceStatus returns the status of the fence object,
|
|
with the following return codes:
|
|
|
|
.Fence Object Status Codes
|
|
[width="80%",options="header"]
|
|
|====
|
|
| Status | Meaning
|
|
| ename:VK_SUCCESS | The fence specified by pname:fence is signaled.
|
|
| ename:VK_NOT_READY | The fence specified by pname:fence is unsignaled.
|
|
|====
|
|
|
|
If a <<devsandqueues-submission, queue submission>> command is pending
|
|
execution, then the value returned by this command may: immediately be out
|
|
of date.
|
|
|
|
include::../validity/protos/vkGetFenceStatus.txt[]
|
|
|
|
[[synchronization-fences-unsignaling]]
|
|
// refBegin vkResetFences Resets one or more fence objects
|
|
|
|
To set the state of fences to unsignaled from the host, call:
|
|
|
|
include::../api/protos/vkResetFences.txt[]
|
|
|
|
* pname:device is the logical device that owns the fences.
|
|
* pname:fenceCount is the number of fences to reset.
|
|
* pname:pFences is a pointer to an array of fence handles to reset.
|
|
|
|
When flink:vkResetFences is executed on the host, it defines a _fence
|
|
unsignal operation_ for each fence, which resets the fence to the unsignaled
|
|
state.
|
|
|
|
If any member of pname:pFences is already in the unsignaled state when
|
|
flink:vkResetFences is executed, then flink:vkResetFences has no effect on
|
|
that fence.
|
|
|
|
.Valid Usage
|
|
****
|
|
* Any given element of pname:pFences must: not currently be associated
|
|
with any queue command that has not yet completed execution on that
|
|
queue
|
|
****
|
|
|
|
include::../validity/protos/vkResetFences.txt[]
|
|
|
|
[[synchronization-fences-signaling]]
|
|
When a fence is submitted to a queue as part of a
|
|
<<devsandqueues-submission, queue submission>> command, it defines a memory
|
|
dependency on the batches that were submitted as part of that command, and
|
|
defines a _fence signal operation_ which sets the fence to the signaled
|
|
state.
|
|
|
|
The first <<synchronization-dependencies-scopes, synchronization scope>>
|
|
includes every batch submitted in the same <<devsandqueues-submission, queue
|
|
submission>> command.
|
|
Fence signal operations that are defined by flink:vkQueueSubmit additionally
|
|
include all previous queue submissions to the same queue via
|
|
flink:vkQueueSubmit in the first synchronization scope.
|
|
|
|
The second <<synchronization-dependencies-scopes, synchronization scope>>
|
|
only includes the fence signal operation.
|
|
|
|
The first <<synchronization-dependencies-access-scopes, access scope>>
|
|
includes all memory access performed by the device.
|
|
|
|
The second <<synchronization-dependencies-access-scopes, access scope>> is
|
|
empty.
|
|
|
|
// refBegin vkWaitForFences Wait for one or more fences to become signaled
|
|
|
|
To wait for one or more fences to enter the signaled state on the host,
|
|
call:
|
|
|
|
include::../api/protos/vkWaitForFences.txt[]
|
|
|
|
* pname:device is the logical device that owns the fences.
|
|
* pname:fenceCount is the number of fences to wait on.
|
|
* pname:pFences is a pointer to an array of pname:fenceCount fence
|
|
handles.
|
|
* pname:waitAll is the condition that must: be satisfied to successfully
|
|
unblock the wait.
|
|
If pname:waitAll is ename:VK_TRUE, then the condition is that all fences
|
|
in pname:pFences are signaled.
|
|
Otherwise, the condition is that at least one fence in pname:pFences is
|
|
signaled.
|
|
* pname:timeout is the timeout period in units of nanoseconds.
|
|
pname:timeout is adjusted to the closest value allowed by the
|
|
implementation-dependent timeout accuracy, which may: be substantially
|
|
longer than one nanosecond, and may: be longer than the requested
|
|
period.
|
|
|
|
If the condition is satisfied when fname:vkWaitForFences is called, then
|
|
fname:vkWaitForFences returns immediately.
|
|
If the condition is not satisfied at the time fname:vkWaitForFences is
|
|
called, then fname:vkWaitForFences will block and wait up to pname:timeout
|
|
nanoseconds for the condition to become satisfied.
|
|
|
|
If pname:timeout is zero, then fname:vkWaitForFences does not wait, but
|
|
simply returns the current state of the fences.
|
|
ename:VK_TIMEOUT will be returned in this case if the condition is not
|
|
satisfied, even though no actual wait was performed.
|
|
|
|
If the specified timeout period expires before the condition is satisfied,
|
|
fname:vkWaitForFences returns ename:VK_TIMEOUT.
|
|
If the condition is satisfied before pname:timeout nanoseconds has expired,
|
|
fname:vkWaitForFences returns ename:VK_SUCCESS.
|
|
|
|
include::../validity/protos/vkWaitForFences.txt[]
|
|
|
|
[[synchronization-fences-waiting]]
|
|
An execution dependency is defined by waiting for a fence to become
|
|
signaled, either via flink:vkWaitForFences or by polling on
|
|
flink:vkGetFenceStatus.
|
|
|
|
The first <<synchronization-dependencies-scopes, synchronization scope>>
|
|
includes only the fence signal operation.
|
|
|
|
The second <<synchronization-dependencies-scopes, synchronization scope>>
|
|
includes the host operations of flink:vkWaitForFences or
|
|
flink:vkGetFenceStatus indicating that the fence has become signaled.
|
|
|
|
.Note
|
|
[NOTE]
|
|
====
|
|
Signaling a fence and waiting on the host does not guarantee that the
|
|
results of memory accesses will be visible to the host.
|
|
To provide that guarantee, the application must: insert a memory barrier
|
|
between the device writes and the end of the submission that will signal the
|
|
fence, with pname:dstAccessMask having the ename:VK_ACCESS_HOST_READ_BIT bit
|
|
set, with pname:dstStageMask having the ename:VK_PIPELINE_STAGE_HOST_BIT bit
|
|
set, and with the appropriate pname:srcStageMask and pname:srcAccessMask
|
|
members set to guarantee completion of the writes.
|
|
If the memory was allocated without the
|
|
ename:VK_MEMORY_PROPERTY_HOST_COHERENT_BIT set, then
|
|
fname:vkInvalidateMappedMemoryRanges must: be called after the fence is
|
|
signaled in order to ensure the writes are visible to the host, as described
|
|
in <<memory-device-hostaccess,Host Access to Device Memory Objects>>.
|
|
====
|
|
|
|
ifdef::VK_EXT_display_control[]
|
|
include::VK_EXT_display_control/fence_events.txt[]
|
|
endif::VK_EXT_display_control[]
|
|
|
|
[[synchronization-semaphores]]
|
|
== Semaphores
|
|
|
|
// refBegin VkSemaphore Opaque handle to a semaphore object
|
|
|
|
Semaphores are a synchronization primitive that can: be used to insert a
|
|
dependency between batches submitted to queues.
|
|
Semaphores have two states - signaled and unsignaled.
|
|
The state of a semaphore can: be signaled after execution of a batch of
|
|
commands is completed.
|
|
A batch can: wait for a semaphore to become signaled before it begins
|
|
execution, and the semaphore is also unsignaled before the batch begins
|
|
execution.
|
|
|
|
Semaphores are represented by sname:VkSemaphore handles:
|
|
|
|
include::../api/handles/VkSemaphore.txt[]
|
|
|
|
// refEnd VkSemaphore
|
|
|
|
// refBegin vkCreateSemaphore Create a new queue semaphore object
|
|
|
|
To create a semaphore, call:
|
|
|
|
include::../api/protos/vkCreateSemaphore.txt[]
|
|
|
|
* pname:device is the logical device that creates the semaphore.
|
|
* pname:pCreateInfo is a pointer to an instance of the
|
|
sname:VkSemaphoreCreateInfo structure which contains information about
|
|
how the semaphore is to be created.
|
|
* pname:pAllocator controls host memory allocation as described in the
|
|
<<memory-allocation, Memory Allocation>> chapter.
|
|
* pname:pSemaphore points to a handle in which the resulting semaphore
|
|
object is returned.
|
|
|
|
When created, the semaphore is in the unsignaled state.
|
|
|
|
include::../validity/protos/vkCreateSemaphore.txt[]
|
|
|
|
// refBegin VkSemaphoreCreateInfo Structure specifying parameters of a newly created semaphore
|
|
|
|
The sname:VkSemaphoreCreateInfo structure is defined as:
|
|
|
|
include::../api/structs/VkSemaphoreCreateInfo.txt[]
|
|
|
|
* pname:sType is the type of this structure.
|
|
* pname:pNext is `NULL` or a pointer to an extension-specific structure.
|
|
* pname:flags is reserved for future use.
|
|
|
|
include::../validity/structs/VkSemaphoreCreateInfo.txt[]
|
|
|
|
// refBegin vkDestroySemaphore Destroy a semaphore object
|
|
|
|
To destroy a semaphore, call:
|
|
|
|
include::../api/protos/vkDestroySemaphore.txt[]
|
|
|
|
* pname:device is the logical device that destroys the semaphore.
|
|
* pname:semaphore is the handle of the semaphore to destroy.
|
|
* pname:pAllocator controls host memory allocation as described in the
|
|
<<memory-allocation, Memory Allocation>> chapter.
|
|
|
|
.Valid Usage
|
|
****
|
|
* All submitted batches that refer to pname:semaphore must: have completed
|
|
execution
|
|
* If sname:VkAllocationCallbacks were provided when pname:semaphore was
|
|
created, a compatible set of callbacks must: be provided here
|
|
* If no sname:VkAllocationCallbacks were provided when pname:semaphore was
|
|
created, pname:pAllocator must: be `NULL`
|
|
****
|
|
|
|
include::../validity/protos/vkDestroySemaphore.txt[]
|
|
|
|
|
|
[[synchronization-semaphores-signaling]]
|
|
=== Semaphore Signaling
|
|
|
|
When a batch is submitted to a queue via a <<devsandqueues-submission, queue
|
|
submission>>, and it includes semaphores to be signaled, it defines a memory
|
|
dependency on the batch, and defines _semaphore signal operations_ which set
|
|
the semaphores to the signaled state.
|
|
|
|
The first <<synchronization-dependencies-scopes, synchronization scope>>
|
|
includes every command submitted in the same batch.
|
|
Semaphore signal operations that are defined by flink:vkQueueSubmit
|
|
additionally include all batches previously submitted to the same queue via
|
|
flink:vkQueueSubmit, including batches that are submitted in the same
|
|
<<devsandqueues-submission, queue submission>> command, but at a lower index
|
|
within the array of batches.
|
|
|
|
The second <<synchronization-dependencies-scopes, synchronization scope>>
|
|
includes only the semaphore signal operation.
|
|
|
|
The first <<synchronization-dependencies-access-scopes, access scope>>
|
|
includes all memory access performed by the device.
|
|
|
|
The second <<synchronization-dependencies-access-scopes, access scope>> is
|
|
empty.
|
|
|
|
|
|
[[synchronization-semaphores-waiting]]
|
|
=== Semaphore Waiting & Unsignaling
|
|
|
|
When a batch is submitted to a queue via a <<devsandqueues-submission, queue
|
|
submission>>, and it includes semaphores to be waited on, it defines a
|
|
memory dependency between prior semaphore signal operations and the batch,
|
|
and defines _semaphore unsignal operations_ which set the semaphores to the
|
|
unsignaled state.
|
|
|
|
The first synchronization scope includes all semaphore signal operations
|
|
that operate on semaphores waited on in the same batch, and that
|
|
happen-before the wait completes.
|
|
|
|
The second <<synchronization-dependencies-scopes, synchronization scope>>
|
|
includes every command submitted in the same batch.
|
|
In the case of flink:vkQueueSubmit, the second synchronization scope is
|
|
limited to operations on the pipeline stages determined by the
|
|
<<synchronization-pipeline-stages-masks, destination stage mask>> specified
|
|
by the corresponding element of pname:pWaitDstStageMask.
|
|
Also, in the case of flink:vkQueueSubmit, the second synchronization scope
|
|
additionally includes all batches subsequently submitted to the same queue
|
|
via flink:vkQueueSubmit, including batches that are submitted in the same
|
|
<<devsandqueues-submission, queue submission>> command, but at a higher
|
|
index within the array of batches.
|
|
|
|
The first <<synchronization-dependencies-access-scopes, access scope>> is
|
|
empty.
|
|
|
|
The second <<synchronization-dependencies-access-scopes, access scope>>
|
|
includes all memory access performed by the device.
|
|
|
|
The semaphore unsignal operation happens-after the first set of operations
|
|
in the execution dependency, and happens-before the second set of operations
|
|
in the execution dependency.
|
|
|
|
.Note
|
|
[NOTE]
|
|
====
|
|
Unlike fences or events, the act of waiting for a semaphore also unsignals
|
|
that semaphore.
|
|
If two operations are separately specified to wait for the same semaphore,
|
|
and there are no other execution dependencies between those operations,
|
|
behaviour is undefined.
|
|
An execution dependency must: be present that guarantees that the semaphore
|
|
unsignal operation for the first of those waits, happens-before the
|
|
semaphore is signalled again, and before the second unsignal operation.
|
|
Semaphore waits and signals should thus occur in discrete 1:1 pairs.
|
|
====
|
|
|
|
ifdef::VK_KHR_swapchain[]
|
|
.Note
|
|
[NOTE]
|
|
====
|
|
A common scenario for using pname:pWaitDstStageMask with values other than
|
|
ename:VK_PIPELINE_STAGE_ALL_COMMANDS_BIT is when synchronizing a window
|
|
system presentation operation against subsequent command buffers which
|
|
render the next frame.
|
|
In this case, a presentation image must: not be overwritten until the
|
|
presentation operation completes, but other pipeline stages can: execute
|
|
without waiting.
|
|
A mask of ename:VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT prevents
|
|
subsequent color attachment writes from executing until the semaphore
|
|
signals.
|
|
Some implementations may: be able to execute transfer operations and/or
|
|
vertex processing work before the semaphore is signaled.
|
|
|
|
If an image layout transition needs to be performed on a swapchain image
|
|
before it is used in a framebuffer, that can: be performed as the first
|
|
operation submitted to the queue after acquiring the image, and should: not
|
|
prevent other work from overlapping with the presentation operation.
|
|
For example, a sname:VkImageMemoryBarrier could use:
|
|
|
|
* pname:srcStageMask = ename:VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
|
|
* pname:srcAccessMask = 0
|
|
* pname:dstStageMask = ename:VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
|
|
* pname:dstAccessMask = ename:VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
|
|
ename:VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT.
|
|
* pname:oldLayout = etext:VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
|
|
* pname:newLayout = ename:VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
|
|
|
|
Alternatively, pname:oldLayout can: be ename:VK_IMAGE_LAYOUT_UNDEFINED, if
|
|
the image's contents need not be preserved.
|
|
|
|
This barrier accomplishes a dependency chain between previous presentation
|
|
operations and subsequent color attachment output operations, with the
|
|
layout transition performed in between, and does not introduce a dependency
|
|
between previous work and any vertex processing stages.
|
|
More precisely, the semaphore signals after the presentation operation
|
|
completes, then the semaphore wait stalls the
|
|
ename:VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT stage, then there is a
|
|
dependency from that same stage to itself with the layout transition
|
|
performed in between.
|
|
====
|
|
endif::VK_KHR_swapchain[]
|
|
|
|
|
|
[[synchronization-events]]
|
|
== Events
|
|
|
|
// refBegin VkEvent Opaque handle to a event object
|
|
|
|
Events are a synchronization primitive that can: be used to insert a
|
|
fine-grained dependency between commands submitted to the same queue, or
|
|
between the host and a queue.
|
|
Events have two states - signaled and unsignaled.
|
|
An application can: signal an event, or unsignal it, on either the host or
|
|
the device.
|
|
A device can: wait for an event to become signaled before executing further
|
|
operations.
|
|
No command exists to wait for an event to become signaled on the host, but
|
|
the current state of an event can: be queried.
|
|
|
|
Events are represented by sname:VkEvent handles:
|
|
|
|
include::../api/handles/VkEvent.txt[]
|
|
|
|
// refEnd VkEvent
|
|
|
|
// refBegin vkCreateEvent Create a new event object
|
|
|
|
To create an event, call:
|
|
|
|
include::../api/protos/vkCreateEvent.txt[]
|
|
|
|
* pname:device is the logical device that creates the event.
|
|
* pname:pCreateInfo is a pointer to an instance of the
|
|
sname:VkEventCreateInfo structure which contains information about how
|
|
the event is to be created.
|
|
* pname:pAllocator controls host memory allocation as described in the
|
|
<<memory-allocation, Memory Allocation>> chapter.
|
|
* pname:pEvent points to a handle in which the resulting event object is
|
|
returned.
|
|
|
|
When created, the event object is in the unsignaled state.
|
|
|
|
include::../validity/protos/vkCreateEvent.txt[]
|
|
|
|
// refBegin VkEventCreateInfo Structure specifying parameters of a newly created event
|
|
|
|
The sname:VkEventCreateInfo structure is defined as:
|
|
|
|
include::../api/structs/VkEventCreateInfo.txt[]
|
|
|
|
* pname:sType is the type of this structure.
|
|
* pname:pNext is `NULL` or a pointer to an extension-specific structure.
|
|
* pname:flags is reserved for future use.
|
|
|
|
include::../validity/structs/VkEventCreateInfo.txt[]
|
|
|
|
// refBegin vkDestroyEvent Destroy an event object
|
|
|
|
To destroy an event, call:
|
|
|
|
include::../api/protos/vkDestroyEvent.txt[]
|
|
|
|
* pname:device is the logical device that destroys the event.
|
|
* pname:event is the handle of the event to destroy.
|
|
* pname:pAllocator controls host memory allocation as described in the
|
|
<<memory-allocation, Memory Allocation>> chapter.
|
|
|
|
.Valid Usage
|
|
****
|
|
* All submitted commands that refer to pname:event must: have completed
|
|
execution
|
|
* If sname:VkAllocationCallbacks were provided when pname:event was
|
|
created, a compatible set of callbacks must: be provided here
|
|
* If no sname:VkAllocationCallbacks were provided when pname:event was
|
|
created, pname:pAllocator must: be `NULL`
|
|
****
|
|
|
|
include::../validity/protos/vkDestroyEvent.txt[]
|
|
|
|
// refBegin vkGetEventStatus Retrieve the status of an event object
|
|
|
|
To query the state of an event from the host, call:
|
|
|
|
include::../api/protos/vkGetEventStatus.txt[]
|
|
|
|
* pname:device is the logical device that owns the event.
|
|
* pname:event is the handle of the event to query.
|
|
|
|
Upon success, fname:vkGetEventStatus returns the state of the event object
|
|
with the following return codes:
|
|
|
|
.Event Object Status Codes
|
|
[width="80%",options="header"]
|
|
|====
|
|
| Status | Meaning
|
|
| ename:VK_EVENT_SET | The event specified by pname:event is signaled.
|
|
| ename:VK_EVENT_RESET | The event specified by pname:event is unsignaled.
|
|
|====
|
|
|
|
If a fname:vkCmdSetEvent or fname:vkCmdResetEvent command is pending
|
|
execution, then the value returned by this command may: immediately be out
|
|
of date.
|
|
|
|
The state of an event can: be updated by the host.
|
|
The state of the event is immediately changed, and subsequent calls to
|
|
fname:vkGetEventStatus will return the new state.
|
|
If an event is already in the requested state, then updating it to the same
|
|
state has no effect.
|
|
|
|
include::../validity/protos/vkGetEventStatus.txt[]
|
|
|
|
[[synchronization-events-signaling-host]]
|
|
// refBegin vkSetEvent Set an event to signaled state
|
|
|
|
To set the state of an event to signaled from the host, call:
|
|
|
|
include::../api/protos/vkSetEvent.txt[]
|
|
|
|
* pname:device is the logical device that owns the event.
|
|
* pname:event is the event to set.
|
|
|
|
When flink:vkSetEvent is executed on the host, it defines an _event signal
|
|
operation_ which sets the event to the signaled state.
|
|
|
|
If pname:event is already in the signaled state when flink:vkSetEvent is
|
|
executed, then flink:vkSetEvent has no effect, and no event signal operation
|
|
occurs.
|
|
|
|
include::../validity/protos/vkSetEvent.txt[]
|
|
|
|
[[synchronization-events-unsignaling-host]]
|
|
// refBegin vkResetEvent Reset an event to non-signaled state
|
|
|
|
To set the state of an event to unsignaled from the host, call:
|
|
|
|
include::../api/protos/vkResetEvent.txt[]
|
|
|
|
* pname:device is the logical device that owns the event.
|
|
* pname:event is the event to reset.
|
|
|
|
When flink:vkResetEvent is executed on the host, it defines an _event
|
|
unsignal operation_ which resets the event to the unsignaled state.
|
|
|
|
If pname:event is already in the unsignaled state when flink:vkResetEvent is
|
|
executed, then flink:vkResetEvent has no effect, and no event unsignal
|
|
operation occurs.
|
|
|
|
.Valid Usage
|
|
****
|
|
* pname:event must: not be waited on by a fname:vkCmdWaitEvents command
|
|
that is currently executing
|
|
****
|
|
|
|
include::../validity/protos/vkResetEvent.txt[]
|
|
|
|
|
|
The state of an event can: also be updated on the device by commands
|
|
inserted in command buffers.
|
|
|
|
[[synchronization-events-signaling-device]]
|
|
// refBegin vkCmdSetEvent Set an event object to signaled state
|
|
|
|
To set the state of an event to signaled from a device, call:
|
|
|
|
include::../api/protos/vkCmdSetEvent.txt[]
|
|
|
|
* pname:commandBuffer is the command buffer into which the command is
|
|
recorded.
|
|
* pname:event is the event that will be signaled.
|
|
* pname:stageMask specifies the <<synchronization-pipeline-stages,source
|
|
stage mask>> used to determine when the pname:event is signaled.
|
|
|
|
When flink:vkCmdSetEvent is submitted to a queue, it defines an execution
|
|
dependency on commands that were submitted before it, and defines an event
|
|
signal operation which sets the event to the signaled state.
|
|
|
|
The first <<synchronization-dependencies-scopes, synchronization scope>>
|
|
includes every command previously submitted to the same queue, including
|
|
those in the same command buffer and batch.
|
|
The synchronization scope is limited to operations on the pipeline stages
|
|
determined by the <<synchronization-pipeline-stages-masks, source stage
|
|
mask>> specified by pname:stageMask.
|
|
|
|
The second <<synchronization-dependencies-scopes, synchronization scope>>
|
|
includes only the event signal operation.
|
|
|
|
If pname:event is already in the signaled state when flink:vkCmdSetEvent is
|
|
executed on the device, then flink:vkCmdSetEvent has no effect, no event
|
|
signal operation occurs, and no execution dependency is generated.
|
|
|
|
.Valid Usage
|
|
****
|
|
* pname:stageMask must: not include ename:VK_PIPELINE_STAGE_HOST_BIT
|
|
* If the <<features-features-geometryShader,geometry shaders>> feature is
|
|
not enabled, pname:stageMask must: not contain
|
|
ename:VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT
|
|
* If the <<features-features-tessellationShader,tessellation shaders>>
|
|
feature is not enabled, pname:stageMask must: not contain
|
|
ename:VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT or
|
|
ename:VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT
|
|
****
|
|
|
|
include::../validity/protos/vkCmdSetEvent.txt[]
|
|
|
|
[[synchronization-events-unsignaling-device]]
|
|
// refBegin vkCmdResetEvent Reset an event object to non-signaled state
|
|
|
|
To set the state of an event to unsignaled from a device, call:
|
|
|
|
include::../api/protos/vkCmdResetEvent.txt[]
|
|
|
|
* pname:commandBuffer is the command buffer into which the command is
|
|
recorded.
|
|
* pname:event is the event that will be unsignaled.
|
|
* pname:stageMask specifies the <<synchronization-pipeline-stages,source
|
|
stage mask>> used to determine when the pname:event is unsignaled.
|
|
|
|
When flink:vkCmdResetEvent is submitted to a queue, it defines an execution
|
|
dependency on commands that were submitted before it, and defines an event
|
|
unsignal operation which resets the event to the unsignaled state.
|
|
|
|
The first <<synchronization-dependencies-scopes, synchronization scope>>
|
|
includes every command previously submitted to the same queue, including
|
|
those in the same command buffer and batch.
|
|
The synchronization scope is limited to operations on the pipeline stages
|
|
determined by the <<synchronization-pipeline-stages-masks, source stage
|
|
mask>> specified by pname:stageMask.
|
|
|
|
The second <<synchronization-dependencies-scopes, synchronization scope>>
|
|
includes only the event unsignal operation.
|
|
|
|
If pname:event is already in the unsignaled state when flink:vkCmdResetEvent
|
|
is executed on the device, then flink:vkCmdResetEvent has no effect, no
|
|
event unsignal operation occurs, and no execution dependency is generated.
|
|
|
|
.Valid Usage
|
|
****
|
|
* pname:stageMask must: not include ename:VK_PIPELINE_STAGE_HOST_BIT
|
|
* If the <<features-features-geometryShader,geometry shaders>> feature is
|
|
not enabled, pname:stageMask must: not contain
|
|
ename:VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT
|
|
* If the <<features-features-tessellationShader,tessellation shaders>>
|
|
feature is not enabled, pname:stageMask must: not contain
|
|
ename:VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT or
|
|
ename:VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT
|
|
* When this command executes, pname:event must: not be waited on by a
|
|
fname:vkCmdWaitEvents command that is currently executing
|
|
****
|
|
|
|
include::../validity/protos/vkCmdResetEvent.txt[]
|
|
|
|
// refBegin vkCmdWaitEvents Wait for one or more events and insert a set of memory
|
|
|
|
To wait for one or more events to enter the signaled state on a device,
|
|
call:
|
|
|
|
[[synchronization-events-waiting-device]]
|
|
include::../api/protos/vkCmdWaitEvents.txt[]
|
|
|
|
* pname:commandBuffer is the command buffer into which the command is
|
|
recorded.
|
|
* pname:eventCount is the length of the pname:pEvents array.
|
|
* pname:pEvents is an array of event object handles to wait on.
|
|
* pname:srcStageMask is the <<synchronization-pipeline-stages, source
|
|
stage mask>>
|
|
* pname:dstStageMask is the <<synchronization-pipeline-stages, destination
|
|
stage mask>>.
|
|
* pname:memoryBarrierCount is the length of the pname:pMemoryBarriers
|
|
array.
|
|
* pname:pMemoryBarriers is a pointer to an array of slink:VkMemoryBarrier
|
|
structures.
|
|
* pname:bufferMemoryBarrierCount is the length of the
|
|
pname:pBufferMemoryBarriers array.
|
|
* pname:pBufferMemoryBarriers is a pointer to an array of
|
|
slink:VkBufferMemoryBarrier structures.
|
|
* pname:imageMemoryBarrierCount is the length of the
|
|
pname:pImageMemoryBarriers array.
|
|
* pname:pImageMemoryBarriers is a pointer to an array of
|
|
slink:VkImageMemoryBarrier structures.
|
|
|
|
When fname:vkCmdWaitEvents is submitted to a queue, it defines a memory
|
|
dependency between prior event signal operations, and subsequent commands.
|
|
|
|
The first synchronization scope only includes event signal operations that
|
|
operate on members of pname:pEvents, and the operations that happened-before
|
|
the event signal operations.
|
|
Event signal operations performed by flink:vkCmdSetEvent that were
|
|
previously submitted to the same queue are included in the first
|
|
synchronization scope, if the <<synchronization-pipeline-stages-order,
|
|
logically latest>> pipeline stage in their pname:stageMask parameter is
|
|
<<synchronization-pipeline-stages-order, logically earlier>> than or equal
|
|
to the <<synchronization-pipeline-stages-order, logically latest>> pipeline
|
|
stage in pname:srcStageMask.
|
|
Event signal operations performed by flink:vkSetEvent are only included in
|
|
the first synchronization scope if ename:VK_PIPELINE_STAGE_HOST_BIT is
|
|
included in pname:srcStageMask.
|
|
|
|
The second <<synchronization-dependencies-scopes, synchronization scope>>
|
|
includes commands subsequently submitted to the same queue, including those
|
|
in the same command buffer and batch.
|
|
The second synchronization scope is limited to operations on the pipeline
|
|
stages determined by the <<synchronization-pipeline-stages-masks,
|
|
destination stage mask>> specified by pname:dstStageMask.
|
|
|
|
The first <<synchronization-dependencies-access-scopes, access scope>> is
|
|
limited to access in the pipeline stages determined by the
|
|
<<synchronization-pipeline-stages-masks, source stage mask>> specified by
|
|
pname:srcStageMask.
|
|
Within that, the first access scope only includes the first access scopes
|
|
defined by elements of the pname:pMemoryBarriers,
|
|
pname:pBufferMemoryBarriers and pname:pImageMemoryBarriers arrays, which
|
|
each define a set of <<synchronization-memory-barriers, memory barriers>>.
|
|
If no memory barriers are specified, then the first access scope includes no
|
|
accesses.
|
|
|
|
The second <<synchronization-dependencies-access-scopes, access scope>> is
|
|
limited to access in the pipeline stages determined by the
|
|
<<synchronization-pipeline-stages-masks, destination stage mask>> specified
|
|
by pname:dstStageMask.
|
|
Within that, the second access scope only includes the second access scopes
|
|
defined by elements of the pname:pMemoryBarriers,
|
|
pname:pBufferMemoryBarriers and pname:pImageMemoryBarriers arrays, which
|
|
each define a set of <<synchronization-memory-barriers, memory barriers>>.
|
|
If no memory barriers are specified, then the second access scope includes
|
|
no accesses.
|
|
|
|
[NOTE]
|
|
.Note
|
|
====
|
|
flink:vkCmdWaitEvents is used with flink:vkCmdSetEvent to define a memory
|
|
dependency between two sets of action commands, roughly in the same way as
|
|
pipeline barriers, but split into two commands such that work between the
|
|
two may: execute unhindered.
|
|
====
|
|
|
|
[NOTE]
|
|
.Note
|
|
====
|
|
Applications should: be careful to avoid race conditions when using events.
|
|
There is no direct ordering guarantee between a flink:vkCmdResetEvent
|
|
command and a flink:vkCmdWaitEvents command submitted after it, so some
|
|
other execution dependency must: be included between these commands (e.g. a
|
|
semaphore).
|
|
====
|
|
|
|
.Valid Usage
|
|
****
|
|
* pname:srcStageMask must: be the bitwise OR of the pname:stageMask
|
|
parameter used in previous calls to fname:vkCmdSetEvent with any of the
|
|
members of pname:pEvents and ename:VK_PIPELINE_STAGE_HOST_BIT if any of
|
|
the members of pname:pEvents was set using fname:vkSetEvent
|
|
* If the <<features-features-geometryShader,geometry shaders>> feature is
|
|
not enabled, pname:srcStageMask must: not contain
|
|
ename:VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT
|
|
* If the <<features-features-geometryShader,geometry shaders>> feature is
|
|
not enabled, pname:dstStageMask must: not contain
|
|
ename:VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT
|
|
* If the <<features-features-tessellationShader,tessellation shaders>>
|
|
feature is not enabled, pname:srcStageMask must: not contain
|
|
ename:VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT or
|
|
ename:VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT
|
|
* If the <<features-features-tessellationShader,tessellation shaders>>
|
|
feature is not enabled, pname:dstStageMask must: not contain
|
|
ename:VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT or
|
|
ename:VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT
|
|
* If pname:pEvents includes one or more events that will be signaled by
|
|
fname:vkSetEvent after pname:commandBuffer has been submitted to a
|
|
queue, then fname:vkCmdWaitEvents must: not be called inside a render
|
|
pass instance
|
|
* Any pipeline stage included in pname:srcStageMask or pname:dstStageMask
|
|
must: be supported by the capabilities of the queue family specified by
|
|
the pname:queueFamilyIndex member of the slink:VkCommandPoolCreateInfo
|
|
structure that was used to create the sname:VkCommandPool that
|
|
pname:commandBuffer was allocated from, as specified in the
|
|
<<synchronization-pipeline-stages-supported, table of supported pipeline
|
|
stages>>.
|
|
* Any given element of pname:pMemoryBarriers, pname:pBufferMemoryBarriers
|
|
or pname:pImageMemoryBarriers must: not have any access flag included in
|
|
its pname:srcAccessMask member if that bit is not supported by any of
|
|
the pipeline stages in pname:srcStageMask, as specified in the
|
|
<<synchronization-access-types-supported, table of supported access
|
|
types>>.
|
|
* Any given element of pname:pMemoryBarriers, pname:pBufferMemoryBarriers
|
|
or pname:pImageMemoryBarriers must: not have any access flag included in
|
|
its pname:dstAccessMask member if that bit is not supported by any of
|
|
the pipeline stages in pname:dstStageMask, as specified in the
|
|
<<synchronization-access-types-supported, table of supported access
|
|
types>>.
|
|
****
|
|
|
|
include::../validity/protos/vkCmdWaitEvents.txt[]
|
|
|
|
|
|
[[synchronization-pipeline-barriers]]
|
|
== Pipeline Barriers
|
|
|
|
flink:vkCmdPipelineBarrier is a synchronization command that inserts a
|
|
dependency between commands submitted to the same queue, or between commands
|
|
in the same subpass.
|
|
|
|
// refBegin vkCmdPipelineBarrier Insert a memory dependency
|
|
|
|
To record a pipeline barrier, call:
|
|
|
|
include::../api/protos/vkCmdPipelineBarrier.txt[]
|
|
|
|
* pname:commandBuffer is the command buffer into which the command is
|
|
recorded.
|
|
* pname:srcStageMask defines a <<synchronization-pipeline-stages-masks,
|
|
source stage mask>>.
|
|
* pname:dstStageMask defines a <<synchronization-pipeline-stages-masks,
|
|
destination stage mask>>.
|
|
* pname:dependencyFlags is a bitmask of elink:VkDependencyFlagBits.
|
|
The bits that can: be included in pname:dependencyFlags are:
|
|
+
|
|
--
|
|
// refBegin VkDependencyFlagBits Bitmask specifying how execution and memory dependencies are formed
|
|
include::../api/enums/VkDependencyFlagBits.txt[]
|
|
--
|
|
** ename:VK_DEPENDENCY_BY_REGION_BIT signifies that dependencies will be
|
|
<<synchronization-framebuffer-regions, framebuffer-local>>.
|
|
|
|
* pname:memoryBarrierCount is the length of the pname:pMemoryBarriers
|
|
array.
|
|
* pname:pMemoryBarriers is a pointer to an array of slink:VkMemoryBarrier
|
|
structures.
|
|
* pname:bufferMemoryBarrierCount is the length of the
|
|
pname:pBufferMemoryBarriers array.
|
|
* pname:pBufferMemoryBarriers is a pointer to an array of
|
|
slink:VkBufferMemoryBarrier structures.
|
|
* pname:imageMemoryBarrierCount is the length of the
|
|
pname:pImageMemoryBarriers array.
|
|
* pname:pImageMemoryBarriers is a pointer to an array of
|
|
slink:VkImageMemoryBarrier structures.
|
|
|
|
When flink:vkCmdPipelineBarrier is submitted to a queue, it defines a memory
|
|
dependency between commands that were submitted before it, and those
|
|
submitted after it.
|
|
|
|
If flink:vkCmdPipelineBarrier was recorded outside a render pass instance,
|
|
the first <<synchronization-dependencies-scopes, synchronization scope>>
|
|
includes every command submitted to the same queue before it, including
|
|
those in the same command buffer and batch.
|
|
If flink:vkCmdPipelineBarrier was recorded inside a render pass instance,
|
|
the first synchronization scope includes only commands submitted before it
|
|
within the same subpass.
|
|
In either case, the first synchronization scope is limited to operations on
|
|
the pipeline stages determined by the
|
|
<<synchronization-pipeline-stages-masks, source stage mask>> specified by
|
|
pname:srcStageMask.
|
|
|
|
If flink:vkCmdPipelineBarrier was recorded outside a render pass instance,
|
|
the second <<synchronization-dependencies-scopes, synchronization scope>>
|
|
includes every command submitted to the same queue after it, including those
|
|
in the same command buffer and batch.
|
|
If flink:vkCmdPipelineBarrier was recorded inside a render pass instance,
|
|
the second synchronization scope includes only commands submitted after it
|
|
within the same subpass.
|
|
In either case, the second synchronization scope is limited to operations on
|
|
the pipeline stages determined by the
|
|
<<synchronization-pipeline-stages-masks, destination stage mask>> specified
|
|
by pname:dstStageMask.
|
|
|
|
The first <<synchronization-dependencies-access-scopes, access scope>> is
|
|
limited to access in the pipeline stages determined by the
|
|
<<synchronization-pipeline-stages-masks, source stage mask>> specified by
|
|
pname:srcStageMask.
|
|
Within that, the first access scope only includes the first access scopes
|
|
defined by elements of the pname:pMemoryBarriers,
|
|
pname:pBufferMemoryBarriers and pname:pImageMemoryBarriers arrays, which
|
|
each define a set of <<synchronization-memory-barriers, memory barriers>>.
|
|
If no memory barriers are specified, then the first access scope includes no
|
|
accesses.
|
|
|
|
The second <<synchronization-dependencies-access-scopes, access scope>> is
|
|
limited to access in the pipeline stages determined by the
|
|
<<synchronization-pipeline-stages-masks, destination stage mask>> specified
|
|
by pname:dstStageMask.
|
|
Within that, the second access scope only includes the second access scopes
|
|
defined by elements of the pname:pMemoryBarriers,
|
|
pname:pBufferMemoryBarriers and pname:pImageMemoryBarriers arrays, which
|
|
each define a set of <<synchronization-memory-barriers, memory barriers>>.
|
|
If no memory barriers are specified, then the second access scope includes
|
|
no accesses.
|
|
|
|
If pname:dependencyFlags includes ename:VK_DEPENDENCY_BY_REGION_BIT, then
|
|
any dependency between <<synchronization-framebuffer-regions,
|
|
framebuffer-space>> pipeline stages is
|
|
<<synchronization-framebuffer-regions, framebuffer-local>> - otherwise it is
|
|
<<synchronization-framebuffer-regions, framebuffer-global>>.
|
|
|
|
.Valid Usage
|
|
****
|
|
* If the <<features-features-geometryShader,geometry shaders>> feature is
|
|
not enabled, pname:srcStageMask must: not contain
|
|
ename:VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT
|
|
* If the <<features-features-geometryShader,geometry shaders>> feature is
|
|
not enabled, pname:dstStageMask must: not contain
|
|
ename:VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT
|
|
* If the <<features-features-tessellationShader,tessellation shaders>>
|
|
feature is not enabled, pname:srcStageMask must: not contain
|
|
ename:VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT or
|
|
ename:VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT
|
|
* If the <<features-features-tessellationShader,tessellation shaders>>
|
|
feature is not enabled, pname:dstStageMask must: not contain
|
|
ename:VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT or
|
|
ename:VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT
|
|
* If fname:vkCmdPipelineBarrier is called within a render pass instance,
|
|
the render pass must: have been created with a sname:VkSubpassDependency
|
|
instance in pname:pDependencies that expresses a dependency from the
|
|
current subpass to itself.
|
|
Additionally:
|
|
** pname:srcStageMask must: contain a subset of the bit values in the
|
|
pname:srcStageMask member of that instance of sname:VkSubpassDependency
|
|
** pname:dstStageMask must: contain a subset of the bit values in the
|
|
pname:dstStageMask member of that instance of sname:VkSubpassDependency
|
|
** The pname:srcAccessMask of any element of pname:pMemoryBarriers or
|
|
pname:pImageMemoryBarriers must: contain a subset of the bit values the
|
|
pname:srcAccessMask member of that instance of
|
|
sname:VkSubpassDependency
|
|
** The pname:dstAccessMask of any element of pname:pMemoryBarriers or
|
|
pname:pImageMemoryBarriers must: contain a subset of the bit values the
|
|
pname:dstAccessMask member of that instance of
|
|
sname:VkSubpassDependency
|
|
** pname:dependencyFlags must: be equal to the pname:dependencyFlags
|
|
member of that instance of sname:VkSubpassDependency
|
|
* If fname:vkCmdPipelineBarrier is called within a render pass instance,
|
|
pname:bufferMemoryBarrierCount must: be `0`
|
|
* If fname:vkCmdPipelineBarrier is called within a render pass instance,
|
|
the pname:image member of any element of pname:pImageMemoryBarriers
|
|
must: be equal to one of the elements of pname:pAttachments that the
|
|
current pname:framebuffer was created with, that is also referred to by
|
|
one of the elements of the pname:pColorAttachments,
|
|
pname:pResolveAttachments or pname:pDepthStencilAttachment members of
|
|
the sname:VkSubpassDescription instance that the current subpass was
|
|
created with
|
|
* If fname:vkCmdPipelineBarrier is called within a render pass instance,
|
|
the pname:oldLayout and pname:newLayout members of any element of
|
|
pname:pImageMemoryBarriers must: be equal to the pname:layout member of
|
|
an element of the pname:pColorAttachments, pname:pResolveAttachments or
|
|
pname:pDepthStencilAttachment members of the sname:VkSubpassDescription
|
|
instance that the current subpass was created with, that refers to the
|
|
same pname:image
|
|
* If fname:vkCmdPipelineBarrier is called within a render pass instance,
|
|
the pname:oldLayout and pname:newLayout members of an element of
|
|
pname:pImageMemoryBarriers must: be equal
|
|
* If fname:vkCmdPipelineBarrier is called within a render pass instance,
|
|
the pname:srcQueueFamilyIndex and pname:dstQueueFamilyIndex members of
|
|
any element of pname:pImageMemoryBarriers must: be
|
|
ename:VK_QUEUE_FAMILY_IGNORED
|
|
* Any pipeline stage included in pname:srcStageMask or pname:dstStageMask
|
|
must: be supported by the capabilities of the queue family specified by
|
|
the pname:queueFamilyIndex member of the slink:VkCommandPoolCreateInfo
|
|
structure that was used to create the sname:VkCommandPool that
|
|
pname:commandBuffer was allocated from, as specified in the
|
|
<<synchronization-pipeline-stages-supported, table of supported pipeline
|
|
stages>>.
|
|
* Any given element of pname:pMemoryBarriers, pname:pBufferMemoryBarriers
|
|
or pname:pImageMemoryBarriers must: not have any access flag included in
|
|
its pname:srcAccessMask member if that bit is not supported by any of
|
|
the pipeline stages in pname:srcStageMask, as specified in the
|
|
<<synchronization-access-types-supported, table of supported access
|
|
types>>.
|
|
* Any given element of pname:pMemoryBarriers, pname:pBufferMemoryBarriers
|
|
or pname:pImageMemoryBarriers must: not have any access flag included in
|
|
its pname:dstAccessMask member if that bit is not supported by any of
|
|
the pipeline stages in pname:dstStageMask, as specified in the
|
|
<<synchronization-access-types-supported, table of supported access
|
|
types>>.
|
|
****
|
|
|
|
include::../validity/protos/vkCmdPipelineBarrier.txt[]
|
|
|
|
|
|
[[synchronization-pipeline-barriers-subpass-self-dependencies]]
|
|
=== Subpass Self-dependency
|
|
|
|
If fname:vkCmdPipelineBarrier is called inside a render pass instance, the
|
|
following restrictions apply.
|
|
For a given subpass to allow a pipeline barrier, the render pass must:
|
|
declare a _self-dependency_ from that subpass to itself.
|
|
That is, there must: exist a sname:VkSubpassDependency in the subpass
|
|
dependency list for the render pass with pname:srcSubpass and
|
|
pname:dstSubpass equal to that subpass index.
|
|
More than one self-dependency can: be declared for each subpass.
|
|
Self-dependencies must: only include pipeline stage bits that are graphics
|
|
stages.
|
|
Self-dependencies must: not have any earlier pipeline stages depend on any
|
|
later pipeline stages.
|
|
More precisely, this means that whatever is the last pipeline stage in
|
|
pname:srcStageMask must: be no later than whatever is the first pipeline
|
|
stage in pname:dstStageMask (the latest source stage can: be equal to the
|
|
earliest destination stage).
|
|
If the source and destination stage masks both include framebuffer-space
|
|
stages, then pname:dependencyFlags must: include
|
|
ename:VK_DEPENDENCY_BY_REGION_BIT.
|
|
|
|
A fname:vkCmdPipelineBarrier command inside a render pass instance must: be
|
|
a _subset_ of one of the self-dependencies of the subpass it is used in,
|
|
meaning that the stage masks and access masks must: each include only a
|
|
subset of the bits of the corresponding mask in that self-dependency.
|
|
If the self-dependency has ename:VK_DEPENDENCY_BY_REGION_BIT set, then so
|
|
must: the pipeline barrier.
|
|
Pipeline barriers within a render pass instance can: only be types
|
|
sname:VkMemoryBarrier or sname:VkImageMemoryBarrier.
|
|
If a sname:VkImageMemoryBarrier is used, the image and image subresource
|
|
range specified in the barrier must: be a subset of one of the image views
|
|
used by the framebuffer in the current subpass.
|
|
Additionally, pname:oldLayout must: be equal to pname:newLayout, and both
|
|
the pname:srcQueueFamilyIndex and pname:dstQueueFamilyIndex must: be
|
|
ename:VK_QUEUE_FAMILY_IGNORED.
|
|
|
|
|
|
[[synchronization-memory-barriers]]
|
|
== Memory Barriers
|
|
|
|
_Memory barriers_ are used to explicitly control access to buffer and image
|
|
subresource ranges.
|
|
Memory barriers are used to <<synchronization-queue-transfers, transfer
|
|
ownership between queue families>>,
|
|
<<synchronization-image-layout-transitions, change image layouts>>, and
|
|
define <<synchronization-dependencies-available-and-visible, availability
|
|
and visibility operations>>.
|
|
They explicitly define the <<synchronization-access-types, access types>>
|
|
and buffer and image subresource ranges that are included in the
|
|
<<synchronization-dependencies-access-scopes, access scopes>> of a memory
|
|
dependency that is created by a synchronization command that includes them.
|
|
|
|
[[synchronization-global-memory-barriers]]
|
|
=== Global Memory Barriers
|
|
|
|
Global memory barriers apply to memory accesses involving all memory objects
|
|
that exist at the time of its execution.
|
|
|
|
// refBegin VkMemoryBarrier Structure specifying a global memory barrier
|
|
|
|
The sname:VkMemoryBarrier structure is defined as:
|
|
|
|
include::../api/structs/VkMemoryBarrier.txt[]
|
|
|
|
* pname:sType is the type of this structure.
|
|
* pname:pNext is `NULL` or a pointer to an extension-specific structure.
|
|
* pname:srcAccessMask defines a <<synchronization-access-masks, source
|
|
access mask>>.
|
|
* pname:dstAccessMask defines a <<synchronization-access-masks,
|
|
destination access mask>>.
|
|
|
|
The first <<synchronization-dependencies-access-scopes, access scope>> is
|
|
limited to access types in the <<synchronization-access-masks, source access
|
|
mask>> specified by pname:srcAccessMask.
|
|
|
|
The second <<synchronization-dependencies-access-scopes, access scope>> is
|
|
limited to access types in the <<synchronization-access-masks, destination
|
|
access mask>> specified by pname:dstAccessMask.
|
|
|
|
include::../validity/structs/VkMemoryBarrier.txt[]
|
|
|
|
|
|
|
|
[[synchronization-buffer-memory-barriers]]
|
|
=== Buffer Memory Barriers
|
|
|
|
Buffer memory barriers only apply to memory accesses involving a specific
|
|
buffer range.
|
|
That is, a memory dependency formed from an buffer memory barrier is
|
|
<<synchronization-dependencies-access-scopes, scoped>> to access via the
|
|
specified buffer range.
|
|
Buffer memory barriers can: also be used to define a
|
|
<<synchronization-queue-transfers, queue family ownership transfer>> for the
|
|
specified buffer range.
|
|
|
|
// refBegin VkBufferMemoryBarrier Structure specifying a buffer memory barrier
|
|
|
|
The sname:VkBufferMemoryBarrier structure is defined as:
|
|
|
|
include::../api/structs/VkBufferMemoryBarrier.txt[]
|
|
|
|
* pname:sType is the type of this structure.
|
|
* pname:pNext is `NULL` or a pointer to an extension-specific structure.
|
|
* pname:srcAccessMask defines a <<synchronization-access-masks, source
|
|
access mask>>.
|
|
* pname:dstAccessMask defines a <<synchronization-access-masks,
|
|
destination access mask>>.
|
|
* pname:srcQueueFamilyIndex is the source queue family for a
|
|
<<synchronization-queue-transfers, queue family ownership transfer>>.
|
|
* pname:dstQueueFamilyIndex is the destination queue family for a
|
|
<<synchronization-queue-transfers, queue family ownership transfer>>.
|
|
* pname:buffer is a handle to the buffer whose backing memory is affected
|
|
by the barrier.
|
|
* pname:offset is an offset in bytes into the backing memory for
|
|
pname:buffer; this is relative to the base offset as bound to the buffer
|
|
(see flink:vkBindBufferMemory).
|
|
* pname:size is a size in bytes of the affected area of backing memory for
|
|
pname:buffer, or ename:VK_WHOLE_SIZE to use the range from pname:offset
|
|
to the end of the buffer.
|
|
|
|
The first <<synchronization-dependencies-access-scopes, access scope>> is
|
|
limited to access to memory through the specified buffer range, via access
|
|
types in the <<synchronization-access-masks, source access mask>> specified
|
|
by pname:srcAccessMask.
|
|
If pname:srcAccessMask includes ename:VK_ACCESS_HOST_WRITE_BIT, memory
|
|
writes performed by that access type are also made visible, as that access
|
|
type is not performed through a resource.
|
|
|
|
The second <<synchronization-dependencies-access-scopes, access scope>> is
|
|
limited to access to memory through the specified buffer range, via access
|
|
types in the <<synchronization-access-masks, destination access mask>>
|
|
specified by pname:dstAccessMask.
|
|
If pname:dstAccessMask includes ename:VK_ACCESS_HOST_WRITE_BIT or
|
|
ename:VK_ACCESS_HOST_READ_BIT, available memory writes are also made visible
|
|
to accesses of those types, as those access types are not performed through
|
|
a resource.
|
|
|
|
If pname:srcQueueFamilyIndex is not equal to pname:dstQueueFamilyIndex, and
|
|
pname:srcQueueFamilyIndex is equal to the current queue family, then the
|
|
memory barrier defines a <<synchronization-queue-transfers-release, queue
|
|
family release operation>> for the specified buffer range, and the second
|
|
access scope includes no access, as if pname:dstAccessMask was `0`.
|
|
|
|
If pname:dstQueueFamilyIndex is not equal to pname:srcQueueFamilyIndex, and
|
|
pname:dstQueueFamilyIndex is equal to the current queue family, then the
|
|
memory barrier defines a <<synchronization-queue-transfers-acquire, queue
|
|
family acquire operation>> for the specified buffer range, and the first
|
|
access scope includes no access, as if pname:srcAccessMask was `0`.
|
|
|
|
.Valid Usage
|
|
****
|
|
* pname:offset must: be less than the size of pname:buffer
|
|
* If pname:size is not equal to ename:VK_WHOLE_SIZE, pname:size must: be
|
|
greater than `0`
|
|
* If pname:size is not equal to ename:VK_WHOLE_SIZE, pname:size must: be
|
|
less than or equal to than the size of pname:buffer minus pname:offset
|
|
* If pname:buffer was created with a sharing mode of
|
|
ename:VK_SHARING_MODE_CONCURRENT, pname:srcQueueFamilyIndex and
|
|
pname:dstQueueFamilyIndex must: both be ename:VK_QUEUE_FAMILY_IGNORED
|
|
* If pname:buffer was created with a sharing mode of
|
|
ename:VK_SHARING_MODE_EXCLUSIVE, pname:srcQueueFamilyIndex and
|
|
pname:dstQueueFamilyIndex must: either both be
|
|
ename:VK_QUEUE_FAMILY_IGNORED, or both be a valid queue family (see
|
|
<<devsandqueues-queueprops>>)
|
|
* If pname:buffer was created with a sharing mode of
|
|
ename:VK_SHARING_MODE_EXCLUSIVE, and pname:srcQueueFamilyIndex and
|
|
pname:dstQueueFamilyIndex are valid queue families, at least one of them
|
|
must: be the same as the family of the queue that will execute this
|
|
barrier
|
|
****
|
|
|
|
include::../validity/structs/VkBufferMemoryBarrier.txt[]
|
|
|
|
|
|
[[synchronization-image-memory-barriers]]
|
|
=== Image Memory Barriers
|
|
|
|
Image memory barriers only apply to memory accesses involving a specific
|
|
image subresource range.
|
|
That is, a memory dependency formed from an image memory barrier is
|
|
<<synchronization-dependencies-access-scopes, scoped>> to access via the
|
|
specified image subresource range.
|
|
Image memory barriers can: also be used to define
|
|
<<synchronization-image-layout-transitions, image layout transitions>> or a
|
|
<<synchronization-queue-transfers, queue family ownership transfer>> for the
|
|
specified image subresource range.
|
|
|
|
// refBegin VkImageMemoryBarrier Structure specifying the parameters of an image memory barrier
|
|
|
|
The sname:VkImageMemoryBarrier structure is defined as:
|
|
|
|
include::../api/structs/VkImageMemoryBarrier.txt[]
|
|
|
|
* pname:sType is the type of this structure.
|
|
* pname:pNext is `NULL` or a pointer to an extension-specific structure.
|
|
* pname:srcAccessMask defines a <<synchronization-access-masks, source
|
|
access mask>>.
|
|
* pname:dstAccessMask defines a <<synchronization-access-masks,
|
|
destination access mask>>.
|
|
* pname:oldLayout is the old layout in an
|
|
<<synchronization-image-layout-transitions, image layout transition>>.
|
|
* pname:newLayout is the new layout in an
|
|
<<synchronization-image-layout-transitions, image layout transition>>.
|
|
* pname:srcQueueFamilyIndex is the source queue family for a
|
|
<<synchronization-queue-transfers, queue family ownership transfer>>.
|
|
* pname:dstQueueFamilyIndex is the destination queue family for a
|
|
<<synchronization-queue-transfers, queue family ownership transfer>>.
|
|
* pname:image is a handle to the image affected by this barrier.
|
|
* pname:subresourceRange describes the <<resources-image-views, image
|
|
subresource range>> within pname:image that is affected by this barrier.
|
|
|
|
The first <<synchronization-dependencies-access-scopes, access scope>> is
|
|
limited to access to memory through the specified image subresource range,
|
|
via access types in the <<synchronization-access-masks, source access mask>>
|
|
specified by pname:srcAccessMask.
|
|
If pname:srcAccessMask includes ename:VK_ACCESS_HOST_WRITE_BIT, memory
|
|
writes performed by that access type are also made visible, as that access
|
|
type is not performed through a resource.
|
|
|
|
The second <<synchronization-dependencies-access-scopes, access scope>> is
|
|
limited to access to memory through the specified image subresource range,
|
|
via access types in the <<synchronization-access-masks, destination access
|
|
mask>> specified by pname:dstAccessMask.
|
|
If pname:dstAccessMask includes ename:VK_ACCESS_HOST_WRITE_BIT or
|
|
ename:VK_ACCESS_HOST_READ_BIT, available memory writes are also made visible
|
|
to accesses of those types, as those access types are not performed through
|
|
a resource.
|
|
|
|
If pname:srcQueueFamilyIndex is not equal to pname:dstQueueFamilyIndex, and
|
|
pname:srcQueueFamilyIndex is equal to the current queue family, then the
|
|
memory barrier defines a <<synchronization-queue-transfers-release, queue
|
|
family release operation>> for the specified image subresource range, and
|
|
the second access scope includes no access, as if pname:dstAccessMask was
|
|
`0`.
|
|
|
|
If pname:dstQueueFamilyIndex is not equal to pname:srcQueueFamilyIndex, and
|
|
pname:dstQueueFamilyIndex is equal to the current queue family, then the
|
|
memory barrier defines a <<synchronization-queue-transfers-acquire, queue
|
|
family acquire operation>> for the specified image subresource range, and
|
|
the first access scope includes no access, as if pname:srcAccessMask was
|
|
`0`.
|
|
|
|
If pname:oldLayout is not equal to pname:newLayout, then the memory barrier
|
|
defines an <<synchronization-image-layout-transitions, image layout
|
|
transition>> for the specified image subresource range.
|
|
Layout transitions that are performed via image memory barriers
|
|
automatically happen-after layout transitions previously submitted to the
|
|
same queue, and automatically happen-before layout transitions subsequently
|
|
submitted to the same queue; this includes layout transitions that occur as
|
|
part of a render pass instance, in both cases.
|
|
|
|
.Valid Usage
|
|
****
|
|
* pname:oldLayout must: be ename:VK_IMAGE_LAYOUT_UNDEFINED or the current
|
|
layout of the image subresources affected by the barrier
|
|
* pname:newLayout must: not be ename:VK_IMAGE_LAYOUT_UNDEFINED or
|
|
ename:VK_IMAGE_LAYOUT_PREINITIALIZED
|
|
* If pname:image was created with a sharing mode of
|
|
ename:VK_SHARING_MODE_CONCURRENT, pname:srcQueueFamilyIndex and
|
|
pname:dstQueueFamilyIndex must: both be ename:VK_QUEUE_FAMILY_IGNORED
|
|
* If pname:image was created with a sharing mode of
|
|
ename:VK_SHARING_MODE_EXCLUSIVE, pname:srcQueueFamilyIndex and
|
|
pname:dstQueueFamilyIndex must: either both be
|
|
ename:VK_QUEUE_FAMILY_IGNORED, or both be a valid queue family (see
|
|
<<devsandqueues-queueprops>>)
|
|
* If pname:image was created with a sharing mode of
|
|
ename:VK_SHARING_MODE_EXCLUSIVE, and pname:srcQueueFamilyIndex and
|
|
pname:dstQueueFamilyIndex are valid queue families, at least one of them
|
|
must: be the same as the family of the queue that will execute this
|
|
barrier
|
|
* pname:subresourceRange must: be a valid image subresource range for the
|
|
image (see <<resources-image-views>>)
|
|
* If pname:image has a depth/stencil format with both depth and stencil
|
|
components, then pname:aspectMask member of pname:subresourceRange must:
|
|
include both ename:VK_IMAGE_ASPECT_DEPTH_BIT and
|
|
ename:VK_IMAGE_ASPECT_STENCIL_BIT
|
|
* If either pname:oldLayout or pname:newLayout is
|
|
ename:VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL then pname:image must:
|
|
have been created with ename:VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT set
|
|
* If either pname:oldLayout or pname:newLayout is
|
|
ename:VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL then pname:image
|
|
must: have been created with
|
|
ename:VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT set
|
|
* If either pname:oldLayout or pname:newLayout is
|
|
ename:VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL then pname:image
|
|
must: have been created with
|
|
ename:VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT set
|
|
* If either pname:oldLayout or pname:newLayout is
|
|
ename:VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL then pname:image must:
|
|
have been created with ename:VK_IMAGE_USAGE_SAMPLED_BIT or
|
|
ename:VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT set
|
|
* If either pname:oldLayout or pname:newLayout is
|
|
ename:VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL then pname:image must: have
|
|
been created with ename:VK_IMAGE_USAGE_TRANSFER_SRC_BIT set
|
|
* If either pname:oldLayout or pname:newLayout is
|
|
ename:VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL then pname:image must: have
|
|
been created with ename:VK_IMAGE_USAGE_TRANSFER_DST_BIT set
|
|
****
|
|
|
|
include::../validity/structs/VkImageMemoryBarrier.txt[]
|
|
|
|
|
|
[[synchronization-queue-transfers]]
|
|
=== Queue Family Ownership Transfer
|
|
|
|
Resources created with a elink:VkSharingMode of
|
|
ename:VK_SHARING_MODE_EXCLUSIVE must: have their ownership explicitly
|
|
transferred from one queue family to another in order to access their
|
|
content in a well-defined manner on a queue in a different queue family.
|
|
If memory dependencies are correctly expressed between uses of such a
|
|
resource between two queues in different families, but no ownership transfer
|
|
is defined, the contents of that resource are undefined for any read
|
|
accesses performed by the second queue family.
|
|
|
|
.Note
|
|
[NOTE]
|
|
====
|
|
If an application does not need the contents of a resource to remain valid
|
|
when transferring from one queue family to another, then the ownership
|
|
transfer should: be skipped.
|
|
====
|
|
|
|
A queue family ownership transfer consists of two distinct parts:
|
|
|
|
. Release exclusive ownership from the source queue family
|
|
. Acquire exclusive ownership for the destination queue family
|
|
|
|
An application must: ensure that these operations occur in the correct order
|
|
by defining an execution dependency between them, e.g. using a semaphore.
|
|
|
|
[[synchronization-queue-transfers-release]] A _release operation_ is used to
|
|
release exclusive ownership of a range of a buffer or image subresource
|
|
range.
|
|
A release operation is defined by executing a
|
|
<<synchronization-buffer-memory-barriers, buffer memory barrier>> (for a
|
|
buffer range) or an <<synchronization-image-memory-barriers, image memory
|
|
barrier>> (for an image subresource range), on a queue from the source queue
|
|
family.
|
|
The pname:srcQueueFamilyIndex parameter of the barrier must: be set to the
|
|
source queue family index, and the pname:dstQueueFamilyIndex parameter to
|
|
the destination queue family index.
|
|
pname:dstStageMask is ignored for such a barrier, such that no visibility
|
|
operation is executed - the value of this mask does not affect the validity
|
|
of the barrier.
|
|
The release operation happens-after the availability operation.
|
|
|
|
[[synchronization-queue-transfers-acquire]] An _acquire operation_ is used
|
|
to acquire exclusive ownership of a range of a buffer or image subresource
|
|
range.
|
|
An acquire operation is defined by executing a
|
|
<<synchronization-buffer-memory-barriers, buffer memory barrier>> (for a
|
|
buffer range) or an <<synchronization-image-memory-barriers, image memory
|
|
barrier>> (for an image subresource range), on a queue from the destination
|
|
queue family.
|
|
The pname:srcQueueFamilyIndex parameter of the barrier must: be set to the
|
|
source queue family index, and the pname:dstQueueFamilyIndex parameter to
|
|
the destination queue family index.
|
|
pname:srcStageMask is ignored for such a barrier, such that no availability
|
|
operation is executed - the value of this mask does not affect the validity
|
|
of the barrier.
|
|
The acquire operation happens-before the visibility operation.
|
|
|
|
.Note
|
|
[NOTE]
|
|
====
|
|
Whilst it is not invalid to provide destination or source access masks for
|
|
memory barriers used for release or acquire operations, respectively, they
|
|
have no practical effect.
|
|
Access after a release operation has undefined results, and so visibility
|
|
for those accesses has no practical effect.
|
|
Similarly, write access before an acquire operation will produce undefined
|
|
results for future access, so availability of those writes has no practical
|
|
use.
|
|
In an earlier version of the specification, these were required to match on
|
|
both sides - but this was subsequently relaxed.
|
|
It is now recommended that these masks are simply set to 0.
|
|
====
|
|
|
|
If the transfer is via an image memory barrier, and an
|
|
<<synchronization-image-layout-transitions, image layout transition>> is
|
|
desired, then the values of pname:oldLayout and pname:newLayout in the
|
|
release memory barrier must: be equal to values of pname:oldLayout and
|
|
pname:newLayout in the acquire memory barrier.
|
|
Although the image layout transition is submitted twice, it will only be
|
|
executed once.
|
|
A layout transition specified in this way happens-after the release
|
|
operation and happens-before the acquire operation.
|
|
|
|
If the values of pname:srcQueueFamilyIndex and pname:dstQueueFamilyIndex are
|
|
equal, no ownership transfer is performed, and the barrier operates as if
|
|
they were both set to ename:VK_QUEUE_FAMILY_IGNORED.
|
|
|
|
Queue family ownership transfers may: perform read and write accesses on all
|
|
memory bound to the image subresource or buffer range, so applications must:
|
|
ensure that all memory writes have been made
|
|
<<synchronization-dependencies-available-and-visible, available>> before a
|
|
queue family ownership transfer is executed.
|
|
Available memory is automatically made visible to queue family release and
|
|
acquire operations, and writes performed by those operations are
|
|
automatically made available.
|
|
|
|
Once a queue family has acquired ownership of a buffer range or image
|
|
subresource range of an ename:VK_SHARING_MODE_EXCLUSIVE resource, its
|
|
contents are undefined to other queue families unless ownership is
|
|
transferred.
|
|
The contents of any portion of another resource which aliases memory that is
|
|
bound to the transferred buffer or image subresource range are undefined
|
|
after a release or acquire operation.
|
|
|
|
|
|
[[synchronization-wait-idle]]
|
|
== Wait Idle Operations
|
|
|
|
// refBegin vkQueueWaitIdle Wait for a queue to become idle
|
|
|
|
To wait on the host for the completion of outstanding queue operations for a
|
|
given queue, call:
|
|
|
|
include::../api/protos/vkQueueWaitIdle.txt[]
|
|
|
|
* pname:queue is the queue on which to wait.
|
|
|
|
fname:vkQueueWaitIdle is equivalent to submitting a fence to a queue and
|
|
waiting with an infinite timeout for that fence to signal.
|
|
|
|
include::../validity/protos/vkQueueWaitIdle.txt[]
|
|
|
|
// refBegin vkDeviceWaitIdle Wait for a device to become idle
|
|
|
|
To wait on the host for the completion of outstanding queue operations for
|
|
all queues on a given logical device, call:
|
|
|
|
include::../api/protos/vkDeviceWaitIdle.txt[]
|
|
|
|
* pname:device is the logical device to idle.
|
|
|
|
fname:vkDeviceWaitIdle is equivalent to calling fname:vkQueueWaitIdle for
|
|
all queues owned by pname:device.
|
|
|
|
include::../validity/protos/vkDeviceWaitIdle.txt[]
|
|
|
|
|
|
[[synchronization-submission-host-writes]]
|
|
== Host Write Ordering Guarantees
|
|
|
|
When batches of command buffers are submitted to a queue via
|
|
flink:vkQueueSubmit, it defines a memory dependency with prior host
|
|
operations, and execution of command buffers submitted to the queue.
|
|
|
|
The first <<synchronization-dependencies-scopes, synchronization scope>> is
|
|
defined by the host execution model, but includes execution of
|
|
flink:vkQueueSubmit on the host and anything that happened-before it.
|
|
|
|
The second <<synchronization-dependencies-scopes, synchronization scope>>
|
|
includes every command submitted in the same <<devsandqueues-submission,
|
|
queue submission>> command, and all future submissions to the same queue.
|
|
|
|
The first <<synchronization-dependencies-access-scopes, access scope>>
|
|
includes all host writes to mappable device memory that are either coherent,
|
|
or have been flushed with flink:vkFlushMappedMemoryRanges.
|
|
|
|
The second <<synchronization-dependencies-access-scopes, access scope>>
|
|
includes all memory access performed by the device.
|