2886 lines
134 KiB
Plaintext
2886 lines
134 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 do not 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 between 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-command-types, 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 in
|
|
different sets of <<synchronization-pipeline-stages-types,pipeline stages>>.
|
|
|
|
Execution of operations across pipeline stages must: adhere to
|
|
<<synchronization-implicit, implicit ordering guarantees>>, particularly
|
|
including <<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 synchronization commands include pipeline stage parameters,
|
|
restricting the <<synchronization-dependencies-scopes, synchronization
|
|
scopes>> for that command to just 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.
|
|
|
|
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 does not 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
|
|
[cols="60%,40%",options="header"]
|
|
|====
|
|
|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
|
|
[cols="50,50",options="header"]
|
|
|====
|
|
|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-host-access-types]]
|
|
If a memory object does not have the
|
|
ename:VK_MEMORY_PROPERTY_HOST_COHERENT_BIT property, then
|
|
flink:vkFlushMappedMemoryRanges must: be called in order to guarantee that
|
|
writes to the memory object from the host are made visible to the
|
|
ename:VK_ACCESS_HOST_WRITE_BIT <<synchronization-access-types, access
|
|
type>>, where it can: be further made available to the device by
|
|
<<synchronization, synchronization commands>>.
|
|
Similarly, flink:vkInvalidateMappedMemoryRanges must: be called to guarantee
|
|
that writes which are visible to the ename:VK_ACCESS_HOST_READ_BIT
|
|
<<synchronization-access-types, access type>> are made visible to host
|
|
operations.
|
|
|
|
If the memory object does have the
|
|
ename:VK_MEMORY_PROPERTY_HOST_COHERENT_BIT property flag, writes to the
|
|
memory object from the host are automatically made visible to the
|
|
ename:VK_ACCESS_HOST_WRITE_BIT <<synchronization-access-types,access type>>.
|
|
Similarly, writes made visible to the ename:VK_ACCESS_HOST_READ_BIT
|
|
<<synchronization-access-types, access type>> are automatically made visible
|
|
to the host.
|
|
|
|
.Note
|
|
[NOTE]
|
|
====
|
|
The flink:vkQueueSubmit command <<synchronization-submission-host-writes,
|
|
automatically guarantees that host writes flushed to
|
|
ename:VK_ACCESS_HOST_WRITE_BIT are made available>> if they were flushed
|
|
before the command executed, so in most cases an explicit memory barrier is
|
|
not needed for this case.
|
|
In the few circumstances where a submit does not occur between the host
|
|
write and the device read access, writes can: be made available by using an
|
|
explicit memory barrier.
|
|
====
|
|
|
|
|
|
[[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.
|
|
====
|
|
|
|
|
|
ifdef::VK_KHX_multiview[]
|
|
|
|
[[synchronization-view-local-dependencies]]
|
|
=== View-Local Dependencies
|
|
|
|
In a render pass instance that has <<renderpass-multiview,multiview>>
|
|
enabled, dependencies can be either view-local or view-global.
|
|
|
|
A view-local dependency only includes operations from a single
|
|
<<renderpass-multiview-view-local,source view>> from the source subpass in
|
|
the first synchronization scope, and only includes operations from a single
|
|
<<renderpass-multiview-view-local,destination view>> from the destination
|
|
subpass in the second synchronization scope.
|
|
A view-global dependency includes all views in the view mask of the source
|
|
and destination subpasses in the corresponding synchronization scopes.
|
|
|
|
If a synchronization command includes a pname:dependencyFlags parameter and
|
|
specifies the ename:VK_DEPENDENCY_VIEW_LOCAL_BIT_KHX flag, then it defines
|
|
view-local dependencies for that synchronization command, for all views.
|
|
If no pname:dependencyFlags parameter is included or the
|
|
ename:VK_DEPENDENCY_VIEW_LOCAL_BIT_KHX flag is not specified, then a
|
|
view-global dependency is specified.
|
|
|
|
endif::VK_KHX_multiview[]
|
|
|
|
|
|
ifdef::VK_KHX_device_group[]
|
|
|
|
[[synchronization-device-local-dependencies]]
|
|
=== Device-Local Dependencies
|
|
|
|
Dependencies can: be either device-local or non-device-local.
|
|
A device-local dependency acts as multiple separate dependencies, one for
|
|
each physical device that executes the synchronization command, where each
|
|
dependency only includes operations from that physical device in both
|
|
synchronization scopes.
|
|
A non-device-local dependency is a single dependency where both
|
|
synchronization scopes include operations from all physical devices that
|
|
participate in the synchronization command.
|
|
For subpass dependencies, all physical devices in the
|
|
slink:VkDeviceGroupRenderPassBeginInfoKHX::pname:deviceMask participate in
|
|
the dependency, and for pipeline barriers all physical devices that are set
|
|
in the command buffer's current device mask participate in the dependency.
|
|
|
|
If a synchronization command includes a pname:dependencyFlags parameter and
|
|
specifies the ename:VK_DEPENDENCY_DEVICE_GROUP_BIT_KHX flag, then it defines
|
|
a non-device-local dependency for that synchronization command.
|
|
If no pname:dependencyFlags parameter is included or the
|
|
ename:VK_DEPENDENCY_DEVICE_GROUP_BIT_KHX flag is not specified, then it
|
|
defines device-local dependencies for that synchronization command, for all
|
|
participating physical devices.
|
|
|
|
Semaphore and event dependencies are device-local and only execute on the
|
|
one physical device that performs the dependency.
|
|
|
|
endif::VK_KHX_device_group[]
|
|
|
|
|
|
[[synchronization-implicit]]
|
|
== Implicit Synchronization Guarantees
|
|
|
|
A small number of implicit ordering guarantees are provided by Vulkan,
|
|
ensuring that the order in which commands are submitted is meaningful, and
|
|
avoiding unnecessary complexity in common operations.
|
|
|
|
[[synchronization-submission-order]]
|
|
_Submission order_ is a fundamental ordering in Vulkan, giving meaning to
|
|
the order in which <<fundamentals-queueoperation-command-types, action and
|
|
synchronization commands>> are recorded and submitted to a single queue.
|
|
Explicit and implicit ordering guarantees between commands in Vulkan all
|
|
work on the premise that this ordering is meaningful.
|
|
|
|
Submission order for any given set of commands is based on the order in
|
|
which they were recorded to command buffers and then submitted.
|
|
This order is determined as follows:
|
|
|
|
. The initial order is determined by the order in which
|
|
flink:vkQueueSubmit commands are executed on the host, for a single
|
|
queue, from first to last.
|
|
. The order in which slink:VkSubmitInfo structures are specified in the
|
|
pname:pSubmits parameter of flink:vkQueueSubmit, from lowest index to
|
|
highest.
|
|
. The order in which command buffers are specified in the
|
|
pname:pCommandBuffers member of slink:VkSubmitInfo, from lowest index to
|
|
highest.
|
|
. The order in which commands were recorded to a command buffer on the
|
|
host, from first to last:
|
|
** For commands recorded outside a render pass, this includes all other
|
|
commands recorded outside a renderpass, including
|
|
flink:vkCmdBeginRenderPass and flink:vkCmdEndRenderPass commands; it
|
|
does not directly include commands inside a render pass.
|
|
** For commands recorded inside a render pass, this includes all other
|
|
commands recorded inside the same subpass, including the
|
|
flink:vkCmdBeginRenderPass and flink:vkCmdEndRenderPass commands that
|
|
delimit the same renderpass instance; it does not include commands
|
|
recorded to other subpasses.
|
|
|
|
<<fundamentals-queueoperation-command-types, Action and synchronization
|
|
commands>> recorded to a command buffer execute the
|
|
ename:VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT pipeline stage in
|
|
<<synchronization-submission-order, submission order>> - forming an implicit
|
|
execution dependency between this stage in each command.
|
|
|
|
<<fundamentals-queueoperation-command-types, State commands>> do not execute
|
|
any operations on the device, instead they set the state of the command
|
|
buffer when they execute on the host, in the order that they are recorded.
|
|
<<fundamentals-queueoperation-command-types, Action commands>> consume the
|
|
current state of the command buffer when they are recorded, and will execute
|
|
state changes on the device as required to match the recorded state.
|
|
|
|
<<queries-order, Query commands>>, <<drawing-primitive-order, the order of
|
|
primitives passing through the graphics pipeline>> and
|
|
<<synchronization-image-barrier-layout-transition-order, image layout
|
|
transitions as part of an image memory barrier>> provide additional
|
|
guarantees based on submission order.
|
|
|
|
Execution of <<synchronization-pipeline-stages-order, pipeline stages>>
|
|
within a given command also has a loose ordering, dependent only on a single
|
|
command.
|
|
|
|
|
|
[[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
|
|
****
|
|
* [[VUID-vkDestroyFence-fence-01120]] All <<devsandqueues-submission, queue submission>> commands that refer
|
|
to pname:fence must: have completed execution
|
|
* [[VUID-vkDestroyFence-fence-01121]] If sname:VkAllocationCallbacks were provided when pname:fence was
|
|
created, a compatible set of callbacks must: be provided here
|
|
* [[VUID-vkDestroyFence-fence-01122]] 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.
|
|
| ename:VK_DEVICE_LOST | The device has been lost. See <<devsandqueues-lost-device,Lost Device>>.
|
|
|====
|
|
|
|
If a <<devsandqueues-submission, queue submission>> command is pending
|
|
execution, then the value returned by this command may: immediately be out
|
|
of date.
|
|
|
|
If the device has been lost (see <<devsandqueues-lost-device,Lost Device>>),
|
|
fname:vkGetFenceStatus may: return any of the above status codes.
|
|
If the device has been lost and fname:vkGetFenceStatus is called repeatedly,
|
|
it will eventually return either ename:VK_SUCCESS or ename:VK_DEVICE_LOST.
|
|
|
|
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
|
|
****
|
|
* [[VUID-vkResetFences-pFences-01123]] 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 in the first synchronization scope all previous queue submissions to
|
|
the same queue via flink:vkQueueSubmit.
|
|
|
|
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.
|
|
|
|
If device loss occurs (see <<devsandqueues-lost-device,Lost Device>>) before
|
|
the timeout has expired, fname:vkWaitForFences must: return in finite time
|
|
with either ename:VK_SUCCESS or ename:VK_DEVICE_LOST.
|
|
|
|
.Note
|
|
[NOTE]
|
|
====
|
|
While we guarantee that fname:vkWaitForFences must: return in finite time,
|
|
no guarantees are made that it returns immediately upon device loss.
|
|
However, the client can reasonably expect that the delay will be on the
|
|
order of seconds and that calling fname:vkWaitForFences will not result in a
|
|
permanently (or seemingly permanently) dead process.
|
|
====
|
|
|
|
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, as the access scope
|
|
of a memory dependency defined by a fence only includes device access.
|
|
A <<synchronization-memory-barriers, memory barrier>> or other memory
|
|
dependency must: be used to guarantee this.
|
|
See the description of <<synchronization-host-access-types, host access
|
|
types>> for more information.
|
|
====
|
|
|
|
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[]
|
|
|
|
ifdef::VK_KHX_external_semaphore[]
|
|
|
|
// refBegin VkExportSemaphoreCreateInfoKHX Structure specifying handle types that can be exported from a semaphore
|
|
|
|
To create a semaphore object that can be exported to external handles, add
|
|
the slink:VkExportSemaphoreCreateInfoKHX structure to the pname:pNext chain
|
|
of the slink:VkSemaphoreCreateInfo structure.
|
|
The sname:VkExportSemaphoreCreateInfoKHX structure is defined as:
|
|
|
|
include::../api/structs/VkExportSemaphoreCreateInfoKHX.txt[]
|
|
|
|
* pname:sType is the type of this structure.
|
|
* pname:pNext is `NULL` or a pointer to an extension-specific structure.
|
|
* pname:handleTypes is a bitmask of
|
|
elink:VkExternalSemaphoreHandleTypeFlagBitsKHX specifying one or more
|
|
semaphore handle types the application can: export from the resulting
|
|
allocation.
|
|
The application can: request multiple handle types for the same
|
|
semaphore.
|
|
|
|
.Valid Usage
|
|
****
|
|
* [[VUID-VkExportSemaphoreCreateInfoKHX-handleTypes-01124]] The bits in pname:handleTypes must: be supported and compatible, as
|
|
reported by slink:VkExternalSemaphorePropertiesKHX.
|
|
****
|
|
|
|
include::../validity/structs/VkExportSemaphoreCreateInfoKHX.txt[]
|
|
|
|
endif::VK_KHX_external_semaphore[]
|
|
|
|
ifdef::VK_KHX_external_semaphore_win32[]
|
|
|
|
// refBegin VkExportSemaphoreWin32HandleInfoKHX Structure specifying additional attributes of Windows handles exported from a semaphore
|
|
|
|
To specify additional attributes of NT handles exported from a semaphore,
|
|
add the slink:VkExportSemaphoreWin32HandleInfoKHX structure to the
|
|
pname:pNext chain of the slink:VkSemaphoreCreateInfo structure.
|
|
The sname:VkExportSemaphoreWin32HandleInfoKHX structure is defined as:
|
|
|
|
include::../api/structs/VkExportSemaphoreWin32HandleInfoKHX.txt[]
|
|
|
|
* pname:sType is the type of this structure.
|
|
* pname:pNext is `NULL` or a pointer to an extension-specific structure.
|
|
* pname:pAttributes is a pointer to a Windows ename:SECURITY_ATTRIBUTES
|
|
structure specifying security attributes of the handle.
|
|
* pname:dwAccess is a ename:DWORD specifying access rights of the handle.
|
|
* pname:name is a NULL-terminated UNICODE string to associate with the
|
|
underlying synchronization primitive referenced by NT handles exported
|
|
from the created semaphore.
|
|
|
|
If this structure is not present, or if pname:pAttributes is set to `NULL`,
|
|
default security descriptor values will be used, and child processes created
|
|
by the application will not inherit the handle, as described in the MSDN
|
|
documentation for "`Synchronization Object Security and Access Rights`"^1^.
|
|
Further, if the structure is not present, the access rights will be
|
|
|
|
code:DXGI_SHARED_RESOURCE_READ | code:DXGI_SHARED_RESOURCE_WRITE
|
|
|
|
for handles of the following types:
|
|
|
|
ename:VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHX
|
|
|
|
And
|
|
|
|
code:GENERIC_ALL
|
|
|
|
for handles of the following types:
|
|
|
|
ename:VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT_KHX
|
|
|
|
1::
|
|
https://msdn.microsoft.com/en-us/library/windows/desktop/ms686670.aspx
|
|
|
|
.Valid Usage
|
|
****
|
|
* [[VUID-VkExportSemaphoreWin32HandleInfoKHX-handleTypes-01125]] If slink:VkExportSemaphoreCreateInfoKHX::pname:handleTypes does not
|
|
include ename:VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHX or
|
|
VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT_KHX,
|
|
VkExportSemaphoreWin32HandleInfoKHX must: not be in the pname:pNext
|
|
chain of slink:VkSemaphoreCreateInfo.
|
|
****
|
|
|
|
include::../validity/structs/VkExportSemaphoreWin32HandleInfoKHX.txt[]
|
|
|
|
// refBegin vkGetSemaphoreWin32HandleKHX Get a Windows HANDLE for a semaphore
|
|
|
|
To export a Windows handle representing the state of a semaphore, call:
|
|
|
|
include::../api/protos/vkGetSemaphoreWin32HandleKHX.txt[]
|
|
|
|
* pname:device is the logical device that created pname:semaphore.
|
|
* pname:semaphore is the semaphore from which state will be exported.
|
|
* pname:handleType is the type of handle requested.
|
|
* pname:pHandle will return the Windows handle representing the semaphore
|
|
state.
|
|
|
|
The properties of the handle returned depend on the value of
|
|
pname:handleType.
|
|
See elink:VkExternalSemaphoreHandleTypeFlagBitsKHX for a description of the
|
|
properties of the defined external semaphore handle types.
|
|
|
|
For handle types defined as NT handles, the handles returned by
|
|
fname:vkGetSemaphoreWin32HandleKHX are owned by the application.
|
|
To avoid leaking resources, the application must: release ownership of them
|
|
using the fname:CloseHandle system call when they are no longer needed.
|
|
|
|
.Valid Usage
|
|
****
|
|
* [[VUID-vkGetSemaphoreWin32HandleKHX-handleType-01126]] pname:handleType must: have been included in
|
|
slink:VkExportSemaphoreCreateInfoKHX::pname:handleTypes when
|
|
pname:semaphore's current state was created.
|
|
* [[VUID-vkGetSemaphoreWin32HandleKHX-handleType-01127]] If pname:handleType is defined as an NT handle,
|
|
flink:vkGetSemaphoreWin32HandleKHX must: be called no more than once for
|
|
each valid unique combination of pname:semaphore and pname:handleType.
|
|
* [[VUID-vkGetSemaphoreWin32HandleKHX-semaphore-01128]] pname:semaphore must: not currently have its state replaced by imported
|
|
semaphore state as described below in
|
|
<<synchronization-semaphores-importing,Importing Semaphore State>>
|
|
unless that imported semaphore state's handle type was included in
|
|
slink:VkExternalSemaphorePropertiesKHX::pname:exportFromImportedHandleTypes.
|
|
* [[VUID-vkGetSemaphoreWin32HandleKHX-handleType-01129]] If pname:handleType refers to a handle type with temporary import
|
|
semantics, as defined below in
|
|
<<synchronization-semaphores-importing,Importing Semaphore State>>,
|
|
there must: be no queue waiting on pname:semaphore.
|
|
* [[VUID-vkGetSemaphoreWin32HandleKHX-handleType-01130]] If pname:handleType refers to a handle type with temporary import
|
|
semantics, pname:semaphore must: be signaled, or have an associated
|
|
<<synchronization-semaphores-signaling,semaphore signal operation>>
|
|
pending execution.
|
|
* [[VUID-vkGetSemaphoreWin32HandleKHX-handleType-01131]] pname:handleType must: be defined as an NT handle or a global share
|
|
handle.
|
|
****
|
|
|
|
include::../validity/protos/vkGetSemaphoreWin32HandleKHX.txt[]
|
|
|
|
endif::VK_KHX_external_semaphore_win32[]
|
|
|
|
ifdef::VK_KHX_external_semaphore_fd[]
|
|
|
|
// refBegin vkGetSemaphoreFdKHX Get a POSIX file descriptor handle for a semaphore
|
|
|
|
To export a POSIX file descriptor representing the state of a semaphore,
|
|
call:
|
|
|
|
include::../api/protos/vkGetSemaphoreFdKHX.txt[]
|
|
|
|
* pname:device is the logical device that created pname:semaphore.
|
|
* pname:semaphore is the semaphore from which state will be exported.
|
|
* pname:handleType is the type of handle requested.
|
|
* pname:pFd will return the file descriptor representing the semaphore
|
|
state.
|
|
|
|
The properties of the file descriptor returned depend on the value of
|
|
pname:handleType.
|
|
See elink:VkExternalSemaphoreHandleTypeFlagBitsKHX for a description of the
|
|
properties of the defined external semaphore handle types.
|
|
|
|
Each call to fname:vkGetSemaphoreFdKHX must: create a new file descriptor
|
|
and transfer ownership of it to the application.
|
|
To avoid leaking resources, the application must: release ownership of the
|
|
file descriptor using the fname:close system call when it is no longer
|
|
needed, or by importing Vulkan semaphore state from it.
|
|
|
|
.Valid Usage
|
|
****
|
|
* [[VUID-vkGetSemaphoreFdKHX-handleType-01132]] pname:handleType must: have been included in
|
|
slink:VkExportSemaphoreCreateInfoKHX::pname:handleTypes when
|
|
pname:semaphore's current state was created.
|
|
* [[VUID-vkGetSemaphoreFdKHX-semaphore-01133]] pname:semaphore must: not currently have its state replaced by imported
|
|
semaphore state as described below in
|
|
<<synchronization-semaphores-importing,Importing Semaphore State>>
|
|
unless that imported semaphore state's handle type was included in
|
|
slink:VkExternalSemaphorePropertiesKHX::pname:exportFromImportedHandleTypes.
|
|
* [[VUID-vkGetSemaphoreFdKHX-handleType-01134]] If pname:handleType refers to a handle type with temporary import
|
|
semantics, as defined below in
|
|
<<synchronization-semaphores-importing,Importing Semaphore State>>,
|
|
there must: be no queue waiting on pname:semaphore.
|
|
* [[VUID-vkGetSemaphoreFdKHX-handleType-01135]] If pname:handleType refers to a handle type with temporary import
|
|
semantics, pname:semaphore must: be signaled, or have an associated
|
|
<<synchronization-semaphores-signaling,semaphore signal operation>>
|
|
pending execution.
|
|
* [[VUID-vkGetSemaphoreFdKHX-handleType-01136]] pname:handleType must: be defined as a POSIX file descriptor handle.
|
|
****
|
|
|
|
include::../validity/protos/vkGetSemaphoreFdKHX.txt[]
|
|
|
|
endif::VK_KHX_external_semaphore_fd[]
|
|
|
|
// 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
|
|
****
|
|
* [[VUID-vkDestroySemaphore-semaphore-01137]] All submitted batches that refer to pname:semaphore must: have completed
|
|
execution
|
|
* [[VUID-vkDestroySemaphore-semaphore-01138]] If sname:VkAllocationCallbacks were provided when pname:semaphore was
|
|
created, a compatible set of callbacks must: be provided here
|
|
* [[VUID-vkDestroySemaphore-semaphore-01139]] 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 presentable 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, the semaphore wait stalls the
|
|
ename:VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT stage, and there is a
|
|
dependency from that same stage to itself with the layout transition
|
|
performed in between.
|
|
====
|
|
endif::VK_KHR_swapchain[]
|
|
|
|
[[synchronization-semaphores-waiting-state]]
|
|
=== Semaphore State Requirements For Wait Operations
|
|
|
|
Before waiting on a semaphore, the application must: ensure the semaphore is
|
|
in a valid state for a wait operation.
|
|
Specifically, when a <<synchronization-semaphores-waiting,semaphore wait and
|
|
unsignal operation>> is submitted to a queue:
|
|
|
|
* The semaphore must: be signaled, or have an associated
|
|
<<synchronization-semaphores-signaling,semaphore signal operation>> that
|
|
is pending execution.
|
|
* There must: be no other queue waiting on the same semaphore when the
|
|
operation executes.
|
|
|
|
ifdef::VK_KHX_external_semaphore[]
|
|
|
|
Generally, the implementation behavior will be undefined when applications
|
|
fail to ensure these requirements are met.
|
|
However, to avoid requiring Vulkan instances that import semaphore state to
|
|
trust the source of that state, the side effects of violating the
|
|
requirements are better defined in certain cases.
|
|
When the semaphore that violates the requirements is using imported state at
|
|
the time of the violation, the implementation must: ensure side effects are
|
|
limited to one or more of the following:
|
|
|
|
* Returning the error code ename:VK_ERROR_INITIALIZATION_FAILED from the
|
|
command which resulted in the violation.
|
|
* Allowing the logical device on which the violation occured to enter an
|
|
undefined state immediately or in the future and returning the error
|
|
code VK_ERROR_DEVICE_LOST from any subsequent command, including the one
|
|
causing the violation, after the device enters such a state.
|
|
* Continuing execution of the violating command or operation as if the
|
|
semaphore wait completed successfully after an implementation-dependent
|
|
timeout.
|
|
In this case, the state of the semaphore becomes undefined.
|
|
The semaphore must: be destroyed or have its state replaced by an import
|
|
operation to again meet valid usage requirements.
|
|
|
|
[[synchronization-semaphores-importing]]
|
|
=== Importing Semaphore State
|
|
Applications may: import semaphore state into an existing semaphore using an
|
|
external semaphore handle.
|
|
Doing so releases any existing state as if flink:vkDestroySemaphore had been
|
|
called on the target semaphore.
|
|
As such, similar usage restrictions to those applied to
|
|
fname:vkDestroySemaphore are applied to any command that imports semaphore
|
|
state.
|
|
The effects of the import operation will be either temporary or permanent,
|
|
depending on the type of handle used to perform the import.
|
|
If the import is temporary, the implementation must: restore the semaphore
|
|
to its prior permanent state when executing the next semaphore signal
|
|
operation.
|
|
If the import is permanent, the signaled status of all semaphores sharing
|
|
the same semaphore state must: be equivalent.
|
|
Semaphore signaling and waiting operations performed on any semaphore in the
|
|
set of semaphores sharing semaphore state must: behave the same as if the
|
|
set were a single semaphore.
|
|
ifdef::VK_KHR_swapchain[]
|
|
Passing a semaphore to flink:vkAcquireNextImageKHR is equivalent to
|
|
temporarily importing semaphore state to that semaphore.
|
|
endif::VK_KHR_swapchain[]
|
|
When a semaphore is using imported state, its
|
|
slink:VkExportSemaphoreCreateInfoKHX::pname:handleTypes value is that
|
|
specified when creating the semaphore from which the state was exported,
|
|
rather than that specified when creating the semaphore.
|
|
|
|
ifdef::VK_KHR_swapchain[]
|
|
[NOTE]
|
|
.Note
|
|
====
|
|
Because the exportable handle types of an imported semaphore correspond to
|
|
its current imported state, and flink:vkAcquireNextImageKHR behaves the same
|
|
as a temporary import operation for which the source semaphore is opaque to
|
|
the application, applications have no way of determining whether any
|
|
external handle types can: be exported from a semaphore in this state.
|
|
Therefore, applications must: not attempt to export external handles from
|
|
semaphores using temporarily imported state from
|
|
flink:vkAcquireNextImageKHR.
|
|
====
|
|
endif::VK_KHR_swapchain[]
|
|
|
|
When importing semaphore state, it is the responsibility of the application
|
|
to ensure the external handles meet all valid usage requirements.
|
|
However, implementations must: perform sufficient validation of external
|
|
handles to ensure that the operation results in valid semaphore state which
|
|
will not cause program termination, device loss, queue stalls, or corruption
|
|
of other resources when used as allowed according to its import parameters,
|
|
and excepting those side effects allowed for violations of the
|
|
<<synchronization-semaphores-waiting-state,valid semaphore state for wait
|
|
operations>> rules.
|
|
If the external handle provided does not meet these requirements, the
|
|
implementation must: fail the semaphore state import operation with the
|
|
error code VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX.
|
|
|
|
endif::VK_KHX_external_semaphore[]
|
|
|
|
ifdef::VK_KHX_external_semaphore_win32[]
|
|
|
|
// refBegin vkImportSemaphoreWin32HandleKHX Import a semaphore from a Windows HANDLE
|
|
|
|
To import semaphore state from a Windows handle, call:
|
|
|
|
include::../api/protos/vkImportSemaphoreWin32HandleKHX.txt[]
|
|
|
|
* pname:device is the logical device that created the semaphore.
|
|
* pname:pImportSemaphoreWin32HandleInfo points to a
|
|
slink:VkImportSemaphoreWin32HandleInfoKHX structure specifying the
|
|
semaphore and import parameters.
|
|
|
|
Importing semaphore state from Windows handles does not transfer ownership
|
|
of the handle to the Vulkan implementation.
|
|
For handle types defined as NT handles, the application must: release
|
|
ownership using the fname:CloseHandle system call when the handle is no
|
|
longer needed.
|
|
|
|
include::../validity/protos/vkImportSemaphoreWin32HandleKHX.txt[]
|
|
|
|
The sname:VkImportSemaphoreWin32HandleInfoKHX structure is defined as:
|
|
|
|
include::../api/structs/VkImportSemaphoreWin32HandleInfoKHX.txt[]
|
|
|
|
* pname:sType is the type of this structure.
|
|
* pname:pNext is `NULL` or a pointer to an extension-specific structure.
|
|
* pname:semaphore is the semaphore into which the state will be imported.
|
|
* pname:handleType specifies the type of pname:handle.
|
|
* pname:handle is the external handle to import.
|
|
|
|
The handle types supported by pname:handleType are:
|
|
|
|
[[synchronization-handletypes-win32]]
|
|
.Handle Type Permanence for VkImportSemaphoreWin32HandleInfoKHX
|
|
[width="80%",options="header"]
|
|
|====
|
|
| Handle Type | Permanence
|
|
| VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT_KHX | Permanent
|
|
| VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_KHX | Permanent
|
|
| VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT_KHX | Permanent
|
|
|====
|
|
|
|
.Valid Usage
|
|
****
|
|
* [[VUID-VkImportSemaphoreWin32HandleInfoKHX-handleType-01140]] pname:handleType must: be a value included in the
|
|
<<synchronization-handletypes-win32,Handle Type Permanence for
|
|
VkImportSemaphoreWin32HandleInfoKHX>> table.
|
|
* [[VUID-VkImportSemaphoreWin32HandleInfoKHX-handleType-01141]] The semaphore from which pname:handleType was exported must: have been
|
|
created on the same underlying physical device as pname:semaphore.
|
|
****
|
|
|
|
include::../validity/structs/VkImportSemaphoreWin32HandleInfoKHX.txt[]
|
|
|
|
endif::VK_KHX_external_semaphore_win32[]
|
|
|
|
ifdef::VK_KHX_external_semaphore_fd[]
|
|
|
|
// refBegin vkImportSemaphoreFdKHX Import a semaphore from a POSIX file descriptor
|
|
|
|
To import semaphore state from a POSIX file descriptor, call:
|
|
|
|
include::../api/protos/vkImportSemaphoreFdKHX.txt[]
|
|
|
|
* pname:device is the logical device that created the semaphore.
|
|
* pname:pImportSemaphoreFdInfo points to a
|
|
slink:VkImportSemaphoreFdInfoKHX structure specifying the semaphore and
|
|
import parameters.
|
|
|
|
Importing semaphore state from a file descriptor transfers ownership of the
|
|
file descriptor from the application to the Vulkan implementation.
|
|
The application must: not perform any operations on the file descriptor
|
|
after a successful import.
|
|
|
|
.Valid Usage
|
|
****
|
|
* [[VUID-vkImportSemaphoreFdKHX-semaphore-01142]] pname:semaphore must: not be associated with any queue command that has
|
|
not yet completed execution on that queue
|
|
****
|
|
|
|
include::../validity/protos/vkImportSemaphoreFdKHX.txt[]
|
|
|
|
The sname:VkImportSemaphoreFdInfoKHX structure is defined as:
|
|
|
|
include::../api/structs/VkImportSemaphoreFdInfoKHX.txt[]
|
|
|
|
* pname:sType is the type of this structure.
|
|
* pname:pNext is `NULL` or a pointer to an extension-specific structure.
|
|
* pname:semaphore is the semaphore into which the state will be imported.
|
|
* pname:handleType specifies the type of pname:fd.
|
|
* pname:fd is the external handle to import.
|
|
|
|
The handle types supported by pname:handleType are:
|
|
|
|
[[synchronization-handletypes-fd]]
|
|
.Handle Type Permanence for VkImportSemaphoreFdInfoKHX
|
|
[width="80%",options="header"]
|
|
|====
|
|
| Handle Type | Permanence
|
|
| VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHX | Permanent
|
|
| VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FENCE_FD_BIT_KHX | Temporary
|
|
|====
|
|
|
|
.Valid Usage
|
|
****
|
|
* [[VUID-VkImportSemaphoreFdInfoKHX-handleType-01143]] pname:handleType must: be a value included in the
|
|
<<synchronization-handletypes-fd,Handle Type Permanence for
|
|
VkImportSemaphoreFdInfoKHX>> table.
|
|
* [[VUID-VkImportSemaphoreFdInfoKHX-handleType-01144]] The semaphore from which pname:handleType was exported must: have been
|
|
created on the same underlying physical device as pname:semaphore.
|
|
****
|
|
|
|
include::../validity/structs/VkImportSemaphoreFdInfoKHX.txt[]
|
|
|
|
endif::VK_KHX_external_semaphore_fd[]
|
|
|
|
|
|
[[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
|
|
****
|
|
* [[VUID-vkDestroyEvent-event-01145]] All submitted commands that refer to pname:event must: have completed
|
|
execution
|
|
* [[VUID-vkDestroyEvent-event-01146]] If sname:VkAllocationCallbacks were provided when pname:event was
|
|
created, a compatible set of callbacks must: be provided here
|
|
* [[VUID-vkDestroyEvent-event-01147]] 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 in a command
|
|
buffer that is in the <<commandbuffers-lifecycle, pending state>>, 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
|
|
****
|
|
* [[VUID-vkResetEvent-event-01148]] 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
|
|
****
|
|
* [[VUID-vkCmdSetEvent-stageMask-01149]] pname:stageMask must: not include ename:VK_PIPELINE_STAGE_HOST_BIT
|
|
* [[VUID-vkCmdSetEvent-stageMask-01150]] If the <<features-features-geometryShader,geometry shaders>> feature is
|
|
not enabled, pname:stageMask must: not contain
|
|
ename:VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT
|
|
* [[VUID-vkCmdSetEvent-stageMask-01151]] 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
|
|
ifdef::VK_KHX_device_group[]
|
|
* [[VUID-vkCmdSetEvent-commandBuffer-01152]] pname:commandBuffer's current device mask must: include exactly one
|
|
physical device.
|
|
endif::VK_KHX_device_group[]
|
|
****
|
|
|
|
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
|
|
****
|
|
* [[VUID-vkCmdResetEvent-stageMask-01153]] pname:stageMask must: not include ename:VK_PIPELINE_STAGE_HOST_BIT
|
|
* [[VUID-vkCmdResetEvent-stageMask-01154]] If the <<features-features-geometryShader,geometry shaders>> feature is
|
|
not enabled, pname:stageMask must: not contain
|
|
ename:VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT
|
|
* [[VUID-vkCmdResetEvent-stageMask-01155]] 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
|
|
* [[VUID-vkCmdResetEvent-event-01156]] When this command executes, pname:event must: not be waited on by a
|
|
fname:vkCmdWaitEvents command that is currently executing
|
|
ifdef::VK_KHX_device_group[]
|
|
* [[VUID-vkCmdResetEvent-commandBuffer-01157]] pname:commandBuffer's current device mask must: include exactly one
|
|
physical device.
|
|
endif::VK_KHX_device_group[]
|
|
****
|
|
|
|
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
|
|
****
|
|
* [[VUID-vkCmdWaitEvents-srcStageMask-01158]] 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
|
|
* [[VUID-vkCmdWaitEvents-srcStageMask-01159]] If the <<features-features-geometryShader,geometry shaders>> feature is
|
|
not enabled, pname:srcStageMask must: not contain
|
|
ename:VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT
|
|
* [[VUID-vkCmdWaitEvents-dstStageMask-01160]] If the <<features-features-geometryShader,geometry shaders>> feature is
|
|
not enabled, pname:dstStageMask must: not contain
|
|
ename:VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT
|
|
* [[VUID-vkCmdWaitEvents-srcStageMask-01161]] 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
|
|
* [[VUID-vkCmdWaitEvents-dstStageMask-01162]] 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
|
|
* [[VUID-vkCmdWaitEvents-pEvents-01163]] 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
|
|
* [[VUID-vkCmdWaitEvents-srcStageMask-01164]] 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>>.
|
|
* [[VUID-vkCmdWaitEvents-pMemoryBarriers-01165]] 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>>.
|
|
* [[VUID-vkCmdWaitEvents-pMemoryBarriers-01166]] 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>>.
|
|
ifdef::VK_KHX_device_group[]
|
|
* [[VUID-vkCmdWaitEvents-commandBuffer-01167]] pname:commandBuffer's current device mask must: include exactly one
|
|
physical device.
|
|
endif::VK_KHX_device_group[]
|
|
****
|
|
|
|
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[]
|
|
|
|
ifdef::editing-notes[]
|
|
[NOTE]
|
|
.editing-note
|
|
====
|
|
(Jon) Missing a description of some of the enums here.
|
|
====
|
|
endif::editing-notes[]
|
|
|
|
** 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
|
|
****
|
|
* [[VUID-vkCmdPipelineBarrier-srcStageMask-01168]] If the <<features-features-geometryShader,geometry shaders>> feature is
|
|
not enabled, pname:srcStageMask must: not contain
|
|
ename:VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT
|
|
* [[VUID-vkCmdPipelineBarrier-dstStageMask-01169]] If the <<features-features-geometryShader,geometry shaders>> feature is
|
|
not enabled, pname:dstStageMask must: not contain
|
|
ename:VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT
|
|
* [[VUID-vkCmdPipelineBarrier-srcStageMask-01170]] 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
|
|
* [[VUID-vkCmdPipelineBarrier-dstStageMask-01171]] 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
|
|
* [[VUID-vkCmdPipelineBarrier-pDependencies-01172]] 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:
|
|
** [[VUID-vkCmdPipelineBarrier-srcStageMask-01173]] pname:srcStageMask must: contain a subset of the bit values in the
|
|
pname:srcStageMask member of that instance of sname:VkSubpassDependency
|
|
** [[VUID-vkCmdPipelineBarrier-dstStageMask-01174]] pname:dstStageMask must: contain a subset of the bit values in the
|
|
pname:dstStageMask member of that instance of sname:VkSubpassDependency
|
|
** [[VUID-vkCmdPipelineBarrier-srcAccessMask-01175]] 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
|
|
** [[VUID-vkCmdPipelineBarrier-dstAccessMask-01176]] 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
|
|
** [[VUID-vkCmdPipelineBarrier-dependencyFlags-01177]] pname:dependencyFlags must: be equal to the pname:dependencyFlags
|
|
member of that instance of sname:VkSubpassDependency
|
|
* [[VUID-vkCmdPipelineBarrier-bufferMemoryBarrierCount-01178]] If fname:vkCmdPipelineBarrier is called within a render pass instance,
|
|
pname:bufferMemoryBarrierCount must: be `0`
|
|
* [[VUID-vkCmdPipelineBarrier-image-01179]] 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
|
|
* [[VUID-vkCmdPipelineBarrier-oldLayout-01180]] 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
|
|
* [[VUID-vkCmdPipelineBarrier-oldLayout-01181]] 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
|
|
* [[VUID-vkCmdPipelineBarrier-srcQueueFamilyIndex-01182]] 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
|
|
* [[VUID-vkCmdPipelineBarrier-srcStageMask-01183]] 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>>.
|
|
* [[VUID-vkCmdPipelineBarrier-pMemoryBarriers-01184]] 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>>.
|
|
* [[VUID-vkCmdPipelineBarrier-pMemoryBarriers-01185]] 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>>.
|
|
ifdef::VK_KHX_multiview[]
|
|
* [[VUID-vkCmdPipelineBarrier-dependencyFlags-01186]] If fname:vkCmdPipelineBarrier is called outside of a render pass
|
|
instance, pname:dependencyFlags must: not include
|
|
ename:VK_DEPENDENCY_VIEW_LOCAL_BIT_KHX
|
|
endif::VK_KHX_multiview[]
|
|
****
|
|
|
|
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 (according to the order of
|
|
<<synchronization-pipeline-stages-types,graphics pipeline stages>>), unless
|
|
all of the stages are
|
|
<<synchronization-framebuffer-regions,framebuffer-space stages>>.
|
|
If the source and destination stage masks both include framebuffer-space
|
|
stages, then pname:dependencyFlags must: include
|
|
ename:VK_DEPENDENCY_BY_REGION_BIT.
|
|
ifdef::VK_KHX_multiview[]
|
|
If the subpass has more than one view, then pname:dependencyFlags must:
|
|
include ename:VK_DEPENDENCY_VIEW_LOCAL_BIT_KHX.
|
|
endif::VK_KHX_multiview[]
|
|
|
|
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
|
|
ifdef::VK_KHX_multiview[]
|
|
or ename:VK_DEPENDENCY_VIEW_LOCAL_BIT_KHX
|
|
endif::VK_KHX_multiview[]
|
|
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
|
|
****
|
|
* [[VUID-VkBufferMemoryBarrier-offset-01187]] pname:offset must: be less than the size of pname:buffer
|
|
* [[VUID-VkBufferMemoryBarrier-size-01188]] If pname:size is not equal to ename:VK_WHOLE_SIZE, pname:size must: be
|
|
greater than `0`
|
|
* [[VUID-VkBufferMemoryBarrier-size-01189]] 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
|
|
ifndef::VK_KHX_external_memory[]
|
|
* [[VUID-VkBufferMemoryBarrier-buffer-01190]] 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
|
|
endif::VK_KHX_external_memory[]
|
|
ifdef::VK_KHX_external_memory[]
|
|
* [[VUID-VkBufferMemoryBarrier-buffer-01191]] If pname:buffer was created with a sharing mode of
|
|
ename:VK_SHARING_MODE_CONCURRENT, at least one of
|
|
pname:srcQueueFamilyIndex and pname:dstQueueFamilyIndex must: be
|
|
ename:VK_QUEUE_FAMILY_IGNORED
|
|
* [[VUID-VkBufferMemoryBarrier-buffer-01380]] If pname:buffer was created with a sharing mode of
|
|
ename:VK_SHARING_MODE_CONCURRENT, and one of pname:srcQueueFamilyIndex
|
|
and pname:dstQueueFamilyIndex is ename:VK_QUEUE_FAMILY_IGNORED, the
|
|
other must: be ename:VK_QUEUE_FAMILY_IGNORED or
|
|
ename:VK_QUEUE_FAMILY_EXTERNAL_KHX
|
|
endif::VK_KHX_external_memory[]
|
|
ifndef::VK_KHX_external_memory[]
|
|
* [[VUID-VkBufferMemoryBarrier-buffer-01192]] 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>>)
|
|
endif::VK_KHX_external_memory[]
|
|
ifdef::VK_KHX_external_memory[]
|
|
* [[VUID-VkBufferMemoryBarrier-buffer-01193]] If pname:buffer was created with a sharing mode of
|
|
ename:VK_SHARING_MODE_EXCLUSIVE and pname:srcQueueFamilyIndex is
|
|
ename:VK_QUEUE_FAMILY_IGNORED, pname:dstQueueFamilyIndex must: also be
|
|
ename:VK_QUEUE_FAMILY_IGNORED
|
|
* [[VUID-VkBufferMemoryBarrier-buffer-01194]] If pname:buffer was created with a sharing mode of
|
|
ename:VK_SHARING_MODE_EXCLUSIVE and pname:srcQueueFamilyIndex is not
|
|
ename:VK_QUEUE_FAMILY_IGNORED, it must: be a valid queue family or
|
|
VK_QUEUE_FAMILY_EXTERNAL_KHX (see <<devsandqueues-queueprops>>)
|
|
* [[VUID-VkBufferMemoryBarrier-buffer-01195]] If pname:buffer was created with a sharing mode of
|
|
ename:VK_SHARING_MODE_EXCLUSIVE and pname:dstQueueFamilyIndex is not
|
|
ename:VK_QUEUE_FAMILY_IGNORED, it must: be a valid queue family or
|
|
VK_QUEUE_FAMILY_EXTERNAL_KHX (see <<devsandqueues-queueprops>>)
|
|
endif::VK_KHX_external_memory[]
|
|
* [[VUID-VkBufferMemoryBarrier-buffer-01196]] 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.
|
|
|
|
[[synchronization-image-barrier-layout-transition-order]]
|
|
Layout transitions that are performed via image memory barriers execute in
|
|
their entirety in <<synchronization-submission-order, submission order>>,
|
|
relative to other image layout transitions submitted to the same queue,
|
|
including those performed by <<renderpass, render passes>>.
|
|
In effect there is an implicit execution dependency from each such layout
|
|
transition to all layout transitions previously submitted to the same queue.
|
|
|
|
.Valid Usage
|
|
****
|
|
* [[VUID-VkImageMemoryBarrier-oldLayout-01197]] pname:oldLayout must: be ename:VK_IMAGE_LAYOUT_UNDEFINED or the current
|
|
layout of the image subresources affected by the barrier
|
|
* [[VUID-VkImageMemoryBarrier-newLayout-01198]] pname:newLayout must: not be ename:VK_IMAGE_LAYOUT_UNDEFINED or
|
|
ename:VK_IMAGE_LAYOUT_PREINITIALIZED
|
|
ifndef::VK_KHX_external_memory[]
|
|
* [[VUID-VkImageMemoryBarrier-image-01199]] 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
|
|
endif::VK_KHX_external_memory[]
|
|
ifdef::VK_KHX_external_memory[]
|
|
* [[VUID-VkImageMemoryBarrier-image-01381]] If pname:image was created with a sharing mode of
|
|
ename:VK_SHARING_MODE_CONCURRENT, at least one of
|
|
pname:srcQueueFamilyIndex and pname:dstQueueFamilyIndex must: be
|
|
ename:VK_QUEUE_FAMILY_IGNORED
|
|
* [[VUID-VkImageMemoryBarrier-image-01382]] If pname:image was created with a sharing mode of
|
|
ename:VK_SHARING_MODE_CONCURRENT, and one of pname:srcQueueFamilyIndex
|
|
and pname:dstQueueFamilyIndex is ename:VK_QUEUE_FAMILY_IGNORED, the
|
|
other must: be ename:VK_QUEUE_FAMILY_IGNORED or
|
|
ename:VK_QUEUE_FAMILY_EXTERNAL_KHX
|
|
endif::VK_KHX_external_memory[]
|
|
ifndef::VK_KHX_external_memory[]
|
|
* [[VUID-VkImageMemoryBarrier-image-01200]] 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>>).
|
|
endif::VK_KHX_external_memory[]
|
|
ifdef::VK_KHX_external_memory[]
|
|
* [[VUID-VkImageMemoryBarrier-image-01201]] If pname:image was created with a sharing mode of
|
|
ename:VK_SHARING_MODE_EXCLUSIVE and pname:srcQueueFamilyIndex is
|
|
ename:VK_QUEUE_FAMILY_IGNORED, pname:dstQueueFamilyIndex must: also be
|
|
ename:VK_QUEUE_FAMILY_IGNORED.
|
|
* [[VUID-VkImageMemoryBarrier-image-01202]] If pname:image was created with a sharing mode of
|
|
ename:VK_SHARING_MODE_EXCLUSIVE and pname:srcQueueFamilyIndex is not
|
|
ename:VK_QUEUE_FAMILY_IGNORED, it must: be a valid queue family or
|
|
VK_QUEUE_FAMILY_EXTERNAL_KHX (see <<devsandqueues-queueprops>>).
|
|
* [[VUID-VkImageMemoryBarrier-image-01203]] If pname:image was created with a sharing mode of
|
|
ename:VK_SHARING_MODE_EXCLUSIVE and pname:dstQueueFamilyIndex is not
|
|
ename:VK_QUEUE_FAMILY_IGNORED, it must: be a valid queue family or
|
|
VK_QUEUE_FAMILY_EXTERNAL_KHX (see <<devsandqueues-queueprops>>).
|
|
endif::VK_KHX_external_memory[]
|
|
* [[VUID-VkImageMemoryBarrier-image-01204]] 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>>)
|
|
* [[VUID-VkImageMemoryBarrier-image-01205]] 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
|
|
* [[VUID-VkImageMemoryBarrier-subresourceRange-01206]] pname:subresourceRange must: be a valid image subresource range for the
|
|
image (see <<resources-image-views>>)
|
|
* [[VUID-VkImageMemoryBarrier-image-01207]] 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
|
|
* [[VUID-VkImageMemoryBarrier-oldLayout-01208]] 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
|
|
* [[VUID-VkImageMemoryBarrier-oldLayout-01209]] 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
|
|
* [[VUID-VkImageMemoryBarrier-oldLayout-01210]] 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
|
|
* [[VUID-VkImageMemoryBarrier-oldLayout-01211]] 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
|
|
* [[VUID-VkImageMemoryBarrier-oldLayout-01212]] 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
|
|
* [[VUID-VkImageMemoryBarrier-oldLayout-01213]] 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.
|
|
ifdef::VK_KHX_external_memory[]
|
|
Resources shared with external APIs or instances using external memory must:
|
|
also explicitly manage ownership transfers between local and external queues
|
|
(or equivalent constructs in external APIs) regardless of the
|
|
elink:VkSharingMode specified when creating them.
|
|
The special queue family index ename:VK_QUEUE_FAMILY_EXTERNAL_KHX represents
|
|
any queue external to the resource's current Vulkan instance.
|
|
endif::VK_KHX_external_memory[]
|
|
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.
|
|
These masks should: be 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.
|
|
|
|
|
|
ifdef::VK_KHX_device_group[]
|
|
|
|
[[synchronization-device-group]]
|
|
== Synchronization and Multiple Physical Devices
|
|
|
|
If a logical device includes more than one physical device, then fences,
|
|
semaphores, and events all still have a single instance of the signaled
|
|
state.
|
|
|
|
A fence becomes signaled when all physical devices complete the necessary
|
|
queue operations.
|
|
|
|
Semaphore wait and signal operations all include a device index that is the
|
|
sole physical device that performs the operation.
|
|
These indices are provided in the slink:VkDeviceGroupSubmitInfoKHX and
|
|
slink:VkDeviceGroupBindSparseInfoKHX structures.
|
|
Semaphores are not exclusively owned by any physical device.
|
|
For example, a semaphore can be signaled by one physical device and then
|
|
waited on by a different physical device.
|
|
|
|
An event can: only be waited on by the same physical device that signaled it
|
|
(or the host).
|
|
|
|
endif::VK_KHX_device_group[]
|