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, five explicit synchronization mechanisms are exposed by Vulkan:
- Fences
-
Fences can be used to communicate to the host that execution of some task on the device has completed, controlling resource access between host and device.
- Semaphores
-
Semaphores can be used to control resource access across multiple queues.
- 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. Events can be used to control resource access within a single queue.
- 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. Pipeline barriers can be used to control resource access within a single queue.
- Render Pass Objects
-
Render pass objects provide a synchronization framework for rendering tasks, built upon the concepts in this chapter. Many cases that would otherwise need an application to use other synchronization primitives can be expressed more efficiently as part of a render pass. Render pass objects can be used to control resource access within a single queue.
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.
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 pipeline stages, which allows other pipeline stages to be excluded from a dependency. Other scoping options are possible, depending on the particular command.
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 Ops1 and Ops2 be separate sets of operations.
-
Let Sync be a synchronization command.
-
Let Scope1st and Scope2nd be the synchronization scopes of Sync.
-
Let ScopedOps1 be the intersection of sets Ops1 and Scope1st.
-
Let ScopedOps2 be the intersection of sets Ops2 and Scope2nd.
-
Submitting Ops1, Sync and Ops2 for execution, in that order, will result in execution dependency ExeDep between ScopedOps1 and ScopedOps2.
-
Execution dependency ExeDep guarantees that ScopedOps1 happen-before ScopedOps2.
An execution dependency chain is a sequence of execution dependencies that form a happens-before relation between the first dependency’s ScopedOps1 and the final dependency’s ScopedOps2. For each consecutive pair of execution dependencies, a chain exists if the intersection of Scope2nd in the first dependency and Scope1st 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 Sync be a set of synchronization commands that generate an execution dependency chain.
-
Let Scope1st be the first synchronization scope of the first command in Sync.
-
Let Scope2nd be the second synchronization scope of the last command in Sync.
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.
Three additional types of operations are used to control memory access. Availability operations cause the values generated by specified memory write accesses to become available to a memory domain 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. Memory domain operations cause writes that are available to a source memory domain to become available to a destination memory domain (an example of this is making writes available to the host domain available to the device domain). Visibility operations cause values available to a memory domain to become visible to specified memory accesses.
Availability, visibility, memory domains, and memory domain operations are formally defined in the Availability and Visibility section of the Memory Model chapter. Which API operations perform each of these operations is defined in Availability, Visibility, and Domain Operations.
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.
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 ScopedOps1 is made available. Any type of access that is in a memory dependency’s second access scope and occurs in ScopedOps2 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 execution dependency chains:
-
Let MemOps1 be the set of memory accesses performed by ScopedOps1.
-
Let MemOps2 be the set of memory accesses performed by ScopedOps2.
-
Let AccessScope1st be the first access scope of the first command in the Sync chain.
-
Let AccessScope2nd be the second access scope of the last command in the Sync chain.
-
Let ScopedMemOps1 be the intersection of sets MemOps1 and AccessScope1st.
-
Let ScopedMemOps2 be the intersection of sets MemOps2 and AccessScope2nd.
-
Submitting Ops1, Sync, and Ops2 for execution, in that order, will result in a memory dependency MemDep between ScopedOps1 and ScopedOps2.
-
Memory dependency MemDep guarantees that:
-
Memory writes in ScopedMemOps1 are made available.
-
Available memory writes, including those from ScopedMemOps1, are made visible to ScopedMemOps2.
-
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. |
Image Layout Transitions
Image subresources can be transitioned from one layout to another as part of a memory dependency (e.g. by using an 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 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.
The old layout must either be VK_IMAGE_LAYOUT_UNDEFINED
, or match the
current layout of the image subresource range.
If the old layout matches the current layout of the image subresource range,
the transition preserves the contents of that range.
If the old layout is VK_IMAGE_LAYOUT_UNDEFINED
, the contents of that
range may be discarded.
Image layout transitions with If the contents of an attachment are not needed after a render pass
completes, then applications should use
|
As image layout transitions may perform read and write accesses on the
memory bound to the image, if the image subresource affected by the layout
transition is bound to peer memory for any device in the current device mask
then the memory heap the bound memory comes from must support the
VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT
and
VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT
capabilities as returned by
vkGetDeviceGroupPeerMemoryFeatures.
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. |
Image layout transitions interact with memory aliasing.
Layout transitions that are performed via image memory barriers execute in their entirety in submission order, relative to other image layout transitions submitted to the same queue, including those performed by 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.
The image layout of each image subresource of a depth/stencil image created
with VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT
is
dependent on the last sample locations used to render to the image
subresource as a depth/stencil attachment, thus when the image
member
of an image memory barrier is an
image created with this flag the application can chain a
VkSampleLocationsInfoEXT structure to the pNext
chain of
VkImageMemoryBarrier2 or
VkImageMemoryBarrier to specify the sample locations to use during any
image layout transition.
If the VkSampleLocationsInfoEXT
structure does not match the sample
location state last used to render to the image subresource range specified
by subresourceRange
, or if no VkSampleLocationsInfoEXT
structure
is present, then the contents of the given image subresource range becomes
undefined as if oldLayout
would equal
VK_IMAGE_LAYOUT_UNDEFINED
.
Pipeline Stages
The work performed by an action command consists of multiple operations, which are performed as a sequence of logically independent steps known as pipeline stages. The exact pipeline stages executed depend on the particular command that is used, and current command buffer state when the command was recorded.
Operations performed by synchronization commands (e.g. availability and visibility operations) are not executed by a defined pipeline stage. However other commands can still synchronize with them by using the synchronization scopes to create a dependency chain. |
Execution of operations across pipeline stages must adhere to implicit ordering guarantees, particularly including 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.
Several of the synchronization commands include pipeline stage parameters, restricting the 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.
Bits which can be set in a VkPipelineStageFlags2 mask, specifying stages of execution, are:
// Provided by VK_VERSION_1_3
// Flag bits for VkPipelineStageFlagBits2
typedef VkFlags64 VkPipelineStageFlagBits2;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_NONE = 0ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT = 0x00000001ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT = 0x00000002ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT = 0x00000004ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT = 0x00000008ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT = 0x00000010ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT = 0x00000020ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT = 0x00000040ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT = 0x00000080ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT = 0x00000100ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT = 0x00000200ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT = 0x00000400ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT = 0x00000800ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT = 0x00001000ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TRANSFER_BIT = 0x00001000ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT = 0x00002000ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_HOST_BIT = 0x00004000ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT = 0x00008000ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT = 0x00010000ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COPY_BIT = 0x100000000ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_RESOLVE_BIT = 0x200000000ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_BLIT_BIT = 0x400000000ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_CLEAR_BIT = 0x800000000ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT = 0x1000000000ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT = 0x2000000000ULL;
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT = 0x4000000000ULL;
// Provided by VK_KHR_video_decode_queue
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR = 0x04000000ULL;
// Provided by VK_KHR_video_encode_queue
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR = 0x08000000ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_NONE_KHR = 0ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR = 0x00000001ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT_KHR = 0x00000002ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT_KHR = 0x00000004ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT_KHR = 0x00000008ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT_KHR = 0x00000010ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT_KHR = 0x00000020ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT_KHR = 0x00000040ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT_KHR = 0x00000080ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT_KHR = 0x00000100ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT_KHR = 0x00000200ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR = 0x00000400ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT_KHR = 0x00000800ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT_KHR = 0x00001000ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR = 0x00001000ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR = 0x00002000ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_HOST_BIT_KHR = 0x00004000ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT_KHR = 0x00008000ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT_KHR = 0x00010000ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COPY_BIT_KHR = 0x100000000ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_RESOLVE_BIT_KHR = 0x200000000ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_BLIT_BIT_KHR = 0x400000000ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_CLEAR_BIT_KHR = 0x800000000ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT_KHR = 0x1000000000ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT_KHR = 0x2000000000ULL;
// Provided by VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT_KHR = 0x4000000000ULL;
// Provided by VK_KHR_synchronization2 with VK_EXT_transform_feedback
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT = 0x01000000ULL;
// Provided by VK_KHR_synchronization2 with VK_EXT_conditional_rendering
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_CONDITIONAL_RENDERING_BIT_EXT = 0x00040000ULL;
// Provided by VK_KHR_synchronization2 with VK_NV_device_generated_commands
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_NV = 0x00020000ULL;
// Provided by VK_KHR_synchronization2 with VK_EXT_device_generated_commands
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_EXT = 0x00020000ULL;
// Provided by VK_KHR_fragment_shading_rate with VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x00400000ULL;
// Provided by VK_KHR_synchronization2 with VK_NV_shading_rate_image
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_SHADING_RATE_IMAGE_BIT_NV = 0x00400000ULL;
// Provided by VK_KHR_acceleration_structure with VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR = 0x02000000ULL;
// Provided by VK_KHR_ray_tracing_pipeline with VK_KHR_synchronization2
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR = 0x00200000ULL;
// Provided by VK_KHR_synchronization2 with VK_NV_ray_tracing
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_NV = 0x00200000ULL;
// Provided by VK_KHR_synchronization2 with VK_NV_ray_tracing
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_NV = 0x02000000ULL;
// Provided by VK_KHR_synchronization2 with VK_EXT_fragment_density_map
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_FRAGMENT_DENSITY_PROCESS_BIT_EXT = 0x00800000ULL;
// Provided by VK_KHR_synchronization2 with VK_NV_mesh_shader
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_NV = 0x00080000ULL;
// Provided by VK_KHR_synchronization2 with VK_NV_mesh_shader
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_NV = 0x00100000ULL;
// Provided by VK_KHR_synchronization2 with VK_EXT_mesh_shader
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_EXT = 0x00080000ULL;
// Provided by VK_KHR_synchronization2 with VK_EXT_mesh_shader
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_EXT = 0x00100000ULL;
// Provided by VK_HUAWEI_subpass_shading
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_SUBPASS_SHADER_BIT_HUAWEI = 0x8000000000ULL;
// VK_PIPELINE_STAGE_2_SUBPASS_SHADING_BIT_HUAWEI is a deprecated alias
// Provided by VK_HUAWEI_subpass_shading
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_SUBPASS_SHADING_BIT_HUAWEI = 0x8000000000ULL;
// Provided by VK_HUAWEI_invocation_mask
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_INVOCATION_MASK_BIT_HUAWEI = 0x10000000000ULL;
// Provided by VK_KHR_ray_tracing_maintenance1 with VK_KHR_synchronization2 or VK_VERSION_1_3
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHR = 0x10000000ULL;
// Provided by VK_EXT_opacity_micromap
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_MICROMAP_BUILD_BIT_EXT = 0x40000000ULL;
// Provided by VK_HUAWEI_cluster_culling_shader
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_CLUSTER_CULLING_SHADER_BIT_HUAWEI = 0x20000000000ULL;
// Provided by VK_NV_optical_flow
static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_OPTICAL_FLOW_BIT_NV = 0x20000000ULL;
or the equivalent
// Provided by VK_KHR_synchronization2
typedef VkPipelineStageFlagBits2 VkPipelineStageFlagBits2KHR;
-
VK_PIPELINE_STAGE_2_NONE
specifies no stages of execution. -
VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT
specifies the stage of the pipeline where indirect command parameters are consumed. This stage also includes reading commands written by vkCmdPreprocessGeneratedCommandsNV. This stage also includes reading commands written by vkCmdPreprocessGeneratedCommandsEXT. -
VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_EXT
specifies the task shader stage. -
VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_EXT
specifies the mesh shader stage. -
VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT
specifies the stage of the pipeline where index buffers are consumed. -
VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT
specifies the stage of the pipeline where vertex buffers are consumed. -
VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT
is equivalent to the logical OR of:-
VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT
-
VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT
-
-
VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT
specifies the vertex shader stage. -
VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT
specifies the tessellation control shader stage. -
VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT
specifies the tessellation evaluation shader stage. -
VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT
specifies the geometry shader stage. -
VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT
is equivalent to specifying all supported pre-rasterization shader stages:-
VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT
-
VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT
-
VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT
-
VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT
-
VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_EXT
-
VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_EXT
-
VK_PIPELINE_STAGE_2_CLUSTER_CULLING_SHADER_BIT_HUAWEI
-
-
VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT
specifies the fragment shader stage. -
VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT
specifies the stage of the pipeline where early fragment tests (depth and stencil tests before fragment shading) are performed. This stage also includes render pass load operations for framebuffer attachments with a depth/stencil format. -
VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT
specifies the stage of the pipeline where late fragment tests (depth and stencil tests after fragment shading) are performed. This stage also includes render pass store operations for framebuffer attachments with a depth/stencil format. -
VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT
specifies the stage of the pipeline where final color values are output from the pipeline. This stage includes blending, logic operations, render pass load and store operations for color attachments, render pass multisample resolve operations, and vkCmdClearAttachments. -
VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT
specifies the compute shader stage. -
VK_PIPELINE_STAGE_2_HOST_BIT
specifies 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. -
VK_PIPELINE_STAGE_2_COPY_BIT
specifies the execution of all copy commands, including vkCmdCopyQueryPoolResults. -
VK_PIPELINE_STAGE_2_BLIT_BIT
specifies the execution of vkCmdBlitImage. -
VK_PIPELINE_STAGE_2_RESOLVE_BIT
specifies the execution of vkCmdResolveImage. -
VK_PIPELINE_STAGE_2_CLEAR_BIT
specifies the execution of clear commands, with the exception of vkCmdClearAttachments. -
VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT
is equivalent to specifying all of:-
VK_PIPELINE_STAGE_2_COPY_BIT
-
VK_PIPELINE_STAGE_2_BLIT_BIT
-
VK_PIPELINE_STAGE_2_RESOLVE_BIT
-
VK_PIPELINE_STAGE_2_CLEAR_BIT
-
VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHR
-
-
VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR
specifies the execution of the ray tracing shader stages. -
VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR
specifies the execution of acceleration structure commands or acceleration structure copy commands. -
VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHR
specifies the execution of acceleration structure copy commands. -
VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT
specifies the execution of all graphics pipeline stages, and is equivalent to the logical OR of:-
VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT
-
VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_EXT
-
VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_EXT
-
VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT
-
VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT
-
VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT
-
VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT
-
VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT
-
VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT
-
VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT
-
VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT
-
VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT
-
VK_PIPELINE_STAGE_2_CONDITIONAL_RENDERING_BIT_EXT
-
VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT
-
VK_PIPELINE_STAGE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR
-
VK_PIPELINE_STAGE_2_FRAGMENT_DENSITY_PROCESS_BIT_EXT
-
VK_PIPELINE_STAGE_2_SUBPASS_SHADER_BIT_HUAWEI
-
VK_PIPELINE_STAGE_2_INVOCATION_MASK_BIT_HUAWEI
-
VK_PIPELINE_STAGE_2_CLUSTER_CULLING_SHADER_BIT_HUAWEI
-
-
VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT
specifies all operations performed by all commands supported on the queue it is used with. -
VK_PIPELINE_STAGE_2_CONDITIONAL_RENDERING_BIT_EXT
specifies the stage of the pipeline where the predicate of conditional rendering is consumed. -
VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT
specifies the stage of the pipeline where vertex attribute output values are written to the transform feedback buffers. -
VK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_NV
specifies the stage of the pipeline where device-side generation of commands via vkCmdPreprocessGeneratedCommandsNV is handled. -
VK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_EXT
specifies the stage of the pipeline where device-side generation of commands via vkCmdPreprocessGeneratedCommandsEXT is handled. -
VK_PIPELINE_STAGE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR
specifies the stage of the pipeline where the fragment shading rate attachment or shading rate image is read to determine the fragment shading rate for portions of a rasterized primitive. -
VK_PIPELINE_STAGE_2_FRAGMENT_DENSITY_PROCESS_BIT_EXT
specifies the stage of the pipeline where the fragment density map is read to generate the fragment areas. -
VK_PIPELINE_STAGE_2_INVOCATION_MASK_BIT_HUAWEI
specifies the stage of the pipeline where the invocation mask image is read by the implementation to optimize the ray dispatch. -
VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR
specifies the execution of video decode operations. -
VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR
specifies the execution of video encode operations. -
VK_PIPELINE_STAGE_2_OPTICAL_FLOW_BIT_NV
specifies the stage of the pipeline where optical flow operation are performed. -
VK_PIPELINE_STAGE_2_SUBPASS_SHADER_BIT_HUAWEI
specifies the subpass shading shader stage. -
VK_PIPELINE_STAGE_2_MICROMAP_BUILD_BIT_EXT
specifies the execution of micromap commands. -
VK_PIPELINE_STAGE_2_CLUSTER_CULLING_SHADER_BIT_HUAWEI
specifies the cluster culling shader stage. -
VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT
is equivalent toVK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT
with VkAccessFlags2 set to0
when specified in the second synchronization scope, but equivalent toVK_PIPELINE_STAGE_2_NONE
in the first scope. -
VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT
is equivalent toVK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT
with VkAccessFlags2 set to0
when specified in the first synchronization scope, but equivalent toVK_PIPELINE_STAGE_2_NONE
in the second scope.
The |
The |
VkPipelineStageFlags2
is a bitmask type for setting a mask of zero or
more VkPipelineStageFlagBits2 flags:
// Provided by VK_VERSION_1_3
typedef VkFlags64 VkPipelineStageFlags2;
or the equivalent
// Provided by VK_KHR_synchronization2
typedef VkPipelineStageFlags2 VkPipelineStageFlags2KHR;
Bits which can be set in a VkPipelineStageFlags mask, specifying stages of execution, are:
// Provided by VK_VERSION_1_0
typedef enum VkPipelineStageFlagBits {
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT = 0x00000001,
VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT = 0x00000002,
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT = 0x00000004,
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT = 0x00000008,
VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT = 0x00000010,
VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT = 0x00000020,
VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT = 0x00000040,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT = 0x00000080,
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT = 0x00000100,
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT = 0x00000200,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT = 0x00000400,
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT = 0x00000800,
VK_PIPELINE_STAGE_TRANSFER_BIT = 0x00001000,
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT = 0x00002000,
VK_PIPELINE_STAGE_HOST_BIT = 0x00004000,
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT = 0x00008000,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT = 0x00010000,
// Provided by VK_VERSION_1_3
VK_PIPELINE_STAGE_NONE = 0,
// Provided by VK_EXT_transform_feedback
VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT = 0x01000000,
// Provided by VK_EXT_conditional_rendering
VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT = 0x00040000,
// Provided by VK_KHR_acceleration_structure
VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR = 0x02000000,
// Provided by VK_KHR_ray_tracing_pipeline
VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR = 0x00200000,
// Provided by VK_EXT_fragment_density_map
VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT = 0x00800000,
// Provided by VK_KHR_fragment_shading_rate
VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR = 0x00400000,
// Provided by VK_NV_device_generated_commands
VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_NV = 0x00020000,
// Provided by VK_EXT_mesh_shader
VK_PIPELINE_STAGE_TASK_SHADER_BIT_EXT = 0x00080000,
// Provided by VK_EXT_mesh_shader
VK_PIPELINE_STAGE_MESH_SHADER_BIT_EXT = 0x00100000,
// Provided by VK_NV_shading_rate_image
VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV = VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR,
// Provided by VK_NV_ray_tracing
VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_NV = VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR,
// Provided by VK_NV_ray_tracing
VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV = VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR,
// Provided by VK_NV_mesh_shader
VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV = VK_PIPELINE_STAGE_TASK_SHADER_BIT_EXT,
// Provided by VK_NV_mesh_shader
VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV = VK_PIPELINE_STAGE_MESH_SHADER_BIT_EXT,
// Provided by VK_KHR_synchronization2
VK_PIPELINE_STAGE_NONE_KHR = VK_PIPELINE_STAGE_NONE,
// Provided by VK_EXT_device_generated_commands
VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_EXT = VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_NV,
} VkPipelineStageFlagBits;
These values all have the same meaning as the equivalently named values for VkPipelineStageFlags2.
-
VK_PIPELINE_STAGE_NONE
specifies no stages of execution. -
VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT
specifies the stage of the pipeline whereVkDrawIndirect*
/VkDispatchIndirect*
/VkTraceRaysIndirect*
data structures are consumed. This stage also includes reading commands written by vkCmdExecuteGeneratedCommandsNV. This stage also includes reading commands written by vkCmdExecuteGeneratedCommandsEXT. -
VK_PIPELINE_STAGE_TASK_SHADER_BIT_EXT
specifies the task shader stage. -
VK_PIPELINE_STAGE_MESH_SHADER_BIT_EXT
specifies the mesh shader stage. -
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT
specifies the stage of the pipeline where vertex and index buffers are consumed. -
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT
specifies the vertex shader stage. -
VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT
specifies the tessellation control shader stage. -
VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT
specifies the tessellation evaluation shader stage. -
VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT
specifies the geometry shader stage. -
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
specifies the fragment shader stage. -
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
specifies the stage of the pipeline where early fragment tests (depth and stencil tests before fragment shading) are performed. This stage also includes render pass load operations for framebuffer attachments with a depth/stencil format. -
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT
specifies the stage of the pipeline where late fragment tests (depth and stencil tests after fragment shading) are performed. This stage also includes render pass store operations for framebuffer attachments with a depth/stencil format. -
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
specifies the stage of the pipeline after blending where the final color values are output from the pipeline. This stage includes blending, logic operations, render pass load and store operations for color attachments, render pass multisample resolve operations, and vkCmdClearAttachments. -
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT
specifies the execution of a compute shader. -
VK_PIPELINE_STAGE_TRANSFER_BIT
specifies the following commands:-
All copy commands, including vkCmdCopyQueryPoolResults
-
All clear commands, with the exception of vkCmdClearAttachments
-
-
VK_PIPELINE_STAGE_HOST_BIT
specifies 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. -
VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR
specifies the execution of vkCmdBuildAccelerationStructureNV, vkCmdCopyAccelerationStructureNV, vkCmdWriteAccelerationStructuresPropertiesNV , vkCmdBuildAccelerationStructuresKHR, vkCmdBuildAccelerationStructuresIndirectKHR, vkCmdCopyAccelerationStructureKHR, vkCmdCopyAccelerationStructureToMemoryKHR, vkCmdCopyMemoryToAccelerationStructureKHR, and vkCmdWriteAccelerationStructuresPropertiesKHR. -
VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR
specifies the execution of the ray tracing shader stages, via vkCmdTraceRaysNV , vkCmdTraceRaysKHR, or vkCmdTraceRaysIndirectKHR -
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT
specifies the execution of all graphics pipeline stages, and is equivalent to the logical OR of:-
VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT
-
VK_PIPELINE_STAGE_TASK_SHADER_BIT_EXT
-
VK_PIPELINE_STAGE_MESH_SHADER_BIT_EXT
-
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT
-
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT
-
VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT
-
VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT
-
VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT
-
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
-
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
-
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT
-
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
-
VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT
-
VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT
-
VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR
-
VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT
-
-
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
specifies all operations performed by all commands supported on the queue it is used with. -
VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT
specifies the stage of the pipeline where the predicate of conditional rendering is consumed. -
VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT
specifies the stage of the pipeline where vertex attribute output values are written to the transform feedback buffers. -
VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_NV
specifies the stage of the pipeline where device-side preprocessing for generated commands via vkCmdPreprocessGeneratedCommandsNV is handled. -
VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_EXT
specifies the stage of the pipeline where device-side preprocessing for generated commands via vkCmdPreprocessGeneratedCommandsEXT is handled. -
VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR
specifies the stage of the pipeline where the fragment shading rate attachment or shading rate image is read to determine the fragment shading rate for portions of a rasterized primitive. -
VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT
specifies the stage of the pipeline where the fragment density map is read to generate the fragment areas. -
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT
is equivalent toVK_PIPELINE_STAGE_ALL_COMMANDS_BIT
with VkAccessFlags set to0
when specified in the second synchronization scope, but specifies no stage of execution when specified in the first scope. -
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT
is equivalent toVK_PIPELINE_STAGE_ALL_COMMANDS_BIT
with VkAccessFlags set to0
when specified in the first synchronization scope, but specifies no stage of execution when specified in the second scope.
// Provided by VK_VERSION_1_0
typedef VkFlags VkPipelineStageFlags;
VkPipelineStageFlags
is a bitmask type for setting a mask of zero or
more VkPipelineStageFlagBits.
If a synchronization command includes a source stage mask, its first synchronization scope only includes execution of the pipeline stages specified in that mask and any logically earlier stages. Its first access scope only includes memory accesses performed by pipeline stages explicitly specified in the source stage mask.
If a synchronization command includes a destination stage mask, its second synchronization scope only includes execution of the pipeline stages specified in that mask and any logically later stages. Its second access scope only includes memory accesses performed by pipeline stages explicitly specified in the destination stage mask.
Note that access scopes do not interact with the logically earlier or later stages for either scope - only the stages the application specifies are considered part of each access scope. |
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 Physical Device Enumeration and Queues.
Pipeline stage flag | Required queue capability flag |
---|---|
|
None required |
|
None required |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
None required |
|
None required |
|
|
|
None required |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 stage in the source stage mask for a particular synchronization command also implies that any logically earlier stages are included in Scope1st 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 Scope2nd for that command.
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, it may substitute any logically later stage in its place for the first synchronization scope. If a pipeline stage that an implementation does not support synchronization for appears in a destination stage mask, it may substitute any logically earlier stage in its place for the second synchronization scope. 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. |
Graphics pipelines are executable on queues
supporting VK_QUEUE_GRAPHICS_BIT
.
Stages executed by graphics pipelines can only be specified in commands
recorded for queues supporting VK_QUEUE_GRAPHICS_BIT
.
The graphics primitive pipeline executes the following stages, with the logical ordering of the stages matching the order specified here:
-
VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT
-
VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT
-
VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT
-
VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT
-
VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT
-
VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT
-
VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT
-
VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT
-
VK_PIPELINE_STAGE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR
-
VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT
-
VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT
-
VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT
-
VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT
The graphics mesh pipeline executes the following stages, with the logical ordering of the stages matching the order specified here:
-
VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT
-
VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_EXT
-
VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_EXT
-
VK_PIPELINE_STAGE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR
-
VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT
-
VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT
-
VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT
-
VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT
For the compute pipeline, the following stages occur in this order:
-
VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT
-
VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT
For the subpass shading pipeline, the following stages occur in this order:
-
VK_PIPELINE_STAGE_2_SUBPASS_SHADER_BIT_HUAWEI
For graphics pipeline commands executing in a render pass with a fragment
density map attachment, the following pipeline stage where the fragment
density map read happens has no particular order relative to the other
stages, except that it is logically earlier than
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
:
-
VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT
-
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
The conditional rendering stage is formally part of both the graphics, and the compute pipeline. The pipeline stage where the predicate read happens has unspecified order relative to other stages of these pipelines:
-
VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT
For the transfer pipeline, the following stages occur in this order:
-
VK_PIPELINE_STAGE_2_TRANSFER_BIT
For host operations, only one pipeline stage occurs, so no order is guaranteed:
-
VK_PIPELINE_STAGE_2_HOST_BIT
For the command preprocessing pipeline, the following stages occur in this order:
-
VK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_EXT
For acceleration structure build operations, only one pipeline stage occurs, so no order is guaranteed:
-
VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR
For acceleration structure copy operations, only one pipeline stage occurs, so no order is guaranteed:
-
VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHR
For opacity micromap build operations, only one pipeline stage occurs, so no order is guaranteed:
-
VK_PIPELINE_STAGE_2_MICROMAP_BUILD_BIT_EXT
For the ray tracing pipeline, the following stages occur in this order:
-
VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT
-
VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR
For the video decode pipeline, the following stages occur in this order:
-
VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR
For the video encode pipeline, the following stages occur in this order:
-
VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR
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 descriptor type used, or how a fixed-function stage accesses memory.
Some synchronization commands take sets of access types as parameters to define the access scopes of a memory dependency. If a synchronization command includes a source access mask, its first 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 access scope only includes accesses via the access types specified in that mask.
Bits which can be set in the srcAccessMask
and dstAccessMask
members of VkMemoryBarrier2KHR, VkImageMemoryBarrier2KHR, and
VkBufferMemoryBarrier2KHR, specifying access behavior, are:
// Provided by VK_VERSION_1_3
// Flag bits for VkAccessFlagBits2
typedef VkFlags64 VkAccessFlagBits2;
static const VkAccessFlagBits2 VK_ACCESS_2_NONE = 0ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT = 0x00000001ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_INDEX_READ_BIT = 0x00000002ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT = 0x00000004ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_UNIFORM_READ_BIT = 0x00000008ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT = 0x00000010ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_READ_BIT = 0x00000020ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_WRITE_BIT = 0x00000040ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT = 0x00000080ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT = 0x00000100ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT = 0x00000200ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT = 0x00000400ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFER_READ_BIT = 0x00000800ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFER_WRITE_BIT = 0x00001000ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_HOST_READ_BIT = 0x00002000ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_HOST_WRITE_BIT = 0x00004000ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_MEMORY_READ_BIT = 0x00008000ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_MEMORY_WRITE_BIT = 0x00010000ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_SAMPLED_READ_BIT = 0x100000000ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_STORAGE_READ_BIT = 0x200000000ULL;
static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT = 0x400000000ULL;
// Provided by VK_KHR_video_decode_queue
static const VkAccessFlagBits2 VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR = 0x800000000ULL;
// Provided by VK_KHR_video_decode_queue
static const VkAccessFlagBits2 VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR = 0x1000000000ULL;
// Provided by VK_KHR_video_encode_queue
static const VkAccessFlagBits2 VK_ACCESS_2_VIDEO_ENCODE_READ_BIT_KHR = 0x2000000000ULL;
// Provided by VK_KHR_video_encode_queue
static const VkAccessFlagBits2 VK_ACCESS_2_VIDEO_ENCODE_WRITE_BIT_KHR = 0x4000000000ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_NONE_KHR = 0ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT_KHR = 0x00000001ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_INDEX_READ_BIT_KHR = 0x00000002ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT_KHR = 0x00000004ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_UNIFORM_READ_BIT_KHR = 0x00000008ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT_KHR = 0x00000010ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_READ_BIT_KHR = 0x00000020ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_WRITE_BIT_KHR = 0x00000040ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT_KHR = 0x00000080ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR = 0x00000100ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT_KHR = 0x00000200ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT_KHR = 0x00000400ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFER_READ_BIT_KHR = 0x00000800ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR = 0x00001000ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_HOST_READ_BIT_KHR = 0x00002000ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_HOST_WRITE_BIT_KHR = 0x00004000ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_MEMORY_READ_BIT_KHR = 0x00008000ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_MEMORY_WRITE_BIT_KHR = 0x00010000ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_SAMPLED_READ_BIT_KHR = 0x100000000ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_STORAGE_READ_BIT_KHR = 0x200000000ULL;
// Provided by VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT_KHR = 0x400000000ULL;
// Provided by VK_KHR_synchronization2 with VK_EXT_transform_feedback
static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFORM_FEEDBACK_WRITE_BIT_EXT = 0x02000000ULL;
// Provided by VK_KHR_synchronization2 with VK_EXT_transform_feedback
static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT = 0x04000000ULL;
// Provided by VK_KHR_synchronization2 with VK_EXT_transform_feedback
static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT = 0x08000000ULL;
// Provided by VK_KHR_synchronization2 with VK_EXT_conditional_rendering
static const VkAccessFlagBits2 VK_ACCESS_2_CONDITIONAL_RENDERING_READ_BIT_EXT = 0x00100000ULL;
// Provided by VK_KHR_synchronization2 with VK_NV_device_generated_commands
static const VkAccessFlagBits2 VK_ACCESS_2_COMMAND_PREPROCESS_READ_BIT_NV = 0x00020000ULL;
// Provided by VK_KHR_synchronization2 with VK_NV_device_generated_commands
static const VkAccessFlagBits2 VK_ACCESS_2_COMMAND_PREPROCESS_WRITE_BIT_NV = 0x00040000ULL;
// Provided by VK_KHR_synchronization2 with VK_EXT_device_generated_commands
static const VkAccessFlagBits2 VK_ACCESS_2_COMMAND_PREPROCESS_READ_BIT_EXT = 0x00020000ULL;
// Provided by VK_KHR_synchronization2 with VK_EXT_device_generated_commands
static const VkAccessFlagBits2 VK_ACCESS_2_COMMAND_PREPROCESS_WRITE_BIT_EXT = 0x00040000ULL;
// Provided by VK_KHR_fragment_shading_rate with VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR = 0x00800000ULL;
// Provided by VK_KHR_synchronization2 with VK_NV_shading_rate_image
static const VkAccessFlagBits2 VK_ACCESS_2_SHADING_RATE_IMAGE_READ_BIT_NV = 0x00800000ULL;
// Provided by VK_KHR_acceleration_structure with VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR = 0x00200000ULL;
// Provided by VK_KHR_acceleration_structure with VK_KHR_synchronization2
static const VkAccessFlagBits2 VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR = 0x00400000ULL;
// Provided by VK_KHR_synchronization2 with VK_NV_ray_tracing
static const VkAccessFlagBits2 VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_NV = 0x00200000ULL;
// Provided by VK_KHR_synchronization2 with VK_NV_ray_tracing
static const VkAccessFlagBits2 VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_NV = 0x00400000ULL;
// Provided by VK_KHR_synchronization2 with VK_EXT_fragment_density_map
static const VkAccessFlagBits2 VK_ACCESS_2_FRAGMENT_DENSITY_MAP_READ_BIT_EXT = 0x01000000ULL;
// Provided by VK_KHR_synchronization2 with VK_EXT_blend_operation_advanced
static const VkAccessFlagBits2 VK_ACCESS_2_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT = 0x00080000ULL;
// Provided by VK_EXT_descriptor_buffer
static const VkAccessFlagBits2 VK_ACCESS_2_DESCRIPTOR_BUFFER_READ_BIT_EXT = 0x20000000000ULL;
// Provided by VK_HUAWEI_invocation_mask
static const VkAccessFlagBits2 VK_ACCESS_2_INVOCATION_MASK_READ_BIT_HUAWEI = 0x8000000000ULL;
// Provided by VK_KHR_ray_tracing_maintenance1 with (VK_KHR_synchronization2 or VK_VERSION_1_3) and VK_KHR_ray_tracing_pipeline
static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_BINDING_TABLE_READ_BIT_KHR = 0x10000000000ULL;
// Provided by VK_EXT_opacity_micromap
static const VkAccessFlagBits2 VK_ACCESS_2_MICROMAP_READ_BIT_EXT = 0x100000000000ULL;
// Provided by VK_EXT_opacity_micromap
static const VkAccessFlagBits2 VK_ACCESS_2_MICROMAP_WRITE_BIT_EXT = 0x200000000000ULL;
// Provided by VK_NV_optical_flow
static const VkAccessFlagBits2 VK_ACCESS_2_OPTICAL_FLOW_READ_BIT_NV = 0x40000000000ULL;
// Provided by VK_NV_optical_flow
static const VkAccessFlagBits2 VK_ACCESS_2_OPTICAL_FLOW_WRITE_BIT_NV = 0x80000000000ULL;
or the equivalent
// Provided by VK_KHR_synchronization2
typedef VkAccessFlagBits2 VkAccessFlagBits2KHR;
-
VK_ACCESS_2_NONE
specifies no accesses. -
VK_ACCESS_2_MEMORY_READ_BIT
specifies all read accesses. It is always valid in any access mask, and is treated as equivalent to setting allREAD
access flags that are valid where it is used. -
VK_ACCESS_2_MEMORY_WRITE_BIT
specifies all write accesses. It is always valid in any access mask, and is treated as equivalent to setting allWRITE
access flags that are valid where it is used. -
VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT
specifies read access to command data read from indirect buffers as part of an indirect build, trace, drawing or dispatch command. Such access occurs in theVK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT
pipeline stage. -
VK_ACCESS_2_INDEX_READ_BIT
specifies read access to an index buffer as part of an indexed drawing command, bound by vkCmdBindIndexBuffer2 and vkCmdBindIndexBuffer. Such access occurs in theVK_PIPELINE_STAGE_2_INDEX_INPUT_BIT
pipeline stage. -
VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT
specifies read access to a vertex buffer as part of a drawing command, bound by vkCmdBindVertexBuffers. Such access occurs in theVK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT
pipeline stage. -
VK_ACCESS_2_UNIFORM_READ_BIT
specifies read access to a uniform buffer in any shader pipeline stage. -
VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT
specifies read access to an input attachment within a render pass during subpass shading or fragment shading. Such access occurs in theVK_PIPELINE_STAGE_2_SUBPASS_SHADER_BIT_HUAWEI
orVK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT
pipeline stage. -
VK_ACCESS_2_SHADER_SAMPLED_READ_BIT
specifies read access to a uniform texel buffer or sampled image in any shader pipeline stage. -
VK_ACCESS_2_SHADER_STORAGE_READ_BIT
specifies read access to a storage buffer, physical storage buffer, storage texel buffer, or storage image in any shader pipeline stage. -
VK_ACCESS_2_SHADER_BINDING_TABLE_READ_BIT_KHR
specifies read access to a shader binding table in any shader pipeline stage. -
VK_ACCESS_2_SHADER_READ_BIT
is equivalent to the logical OR of:-
VK_ACCESS_2_SHADER_SAMPLED_READ_BIT
-
VK_ACCESS_2_SHADER_STORAGE_READ_BIT
-
-
VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT
specifies write access to a storage buffer, physical storage buffer, storage texel buffer, or storage image in any shader pipeline stage. -
VK_ACCESS_2_SHADER_WRITE_BIT
is equivalent toVK_ACCESS_2_SHADER_STORAGE_WRITE_BIT
. -
VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT
specifies read access to a color attachment, such as via blending (other than advanced blend operations), logic operations or certain render pass load operations in theVK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT
pipeline stage or via fragment shader tile image reads in theVK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT
pipeline stage. -
VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT
specifies write access to a color attachment during a render pass or via certain render pass load, store, and multisample resolve operations. Such access occurs in theVK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT
pipeline stage. -
VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT
specifies read access to a depth/stencil attachment, via depth or stencil operations or certain render pass load operations in theVK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT
orVK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT
pipeline stages or via fragment shader tile image reads in theVK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT
pipeline stage. -
VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT
specifies write access to a depth/stencil attachment, via depth or stencil operations or certain render pass load and store operations. Such access occurs in theVK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT
orVK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT
pipeline stages. -
VK_ACCESS_2_TRANSFER_READ_BIT
specifies read access to an image or buffer in a copy operation. Such access occurs in theVK_PIPELINE_STAGE_2_COPY_BIT
,VK_PIPELINE_STAGE_2_BLIT_BIT
, orVK_PIPELINE_STAGE_2_RESOLVE_BIT
pipeline stages. -
VK_ACCESS_2_TRANSFER_WRITE_BIT
specifies write access to an image or buffer in a clear or copy operation. Such access occurs in theVK_PIPELINE_STAGE_2_COPY_BIT
,VK_PIPELINE_STAGE_2_BLIT_BIT
,VK_PIPELINE_STAGE_2_CLEAR_BIT
, orVK_PIPELINE_STAGE_2_RESOLVE_BIT
pipeline stages. -
VK_ACCESS_2_HOST_READ_BIT
specifies read access by a host operation. Accesses of this type are not performed through a resource, but directly on memory. Such access occurs in theVK_PIPELINE_STAGE_2_HOST_BIT
pipeline stage. -
VK_ACCESS_2_HOST_WRITE_BIT
specifies write access by a host operation. Accesses of this type are not performed through a resource, but directly on memory. Such access occurs in theVK_PIPELINE_STAGE_2_HOST_BIT
pipeline stage. -
VK_ACCESS_2_CONDITIONAL_RENDERING_READ_BIT_EXT
specifies read access to a predicate as part of conditional rendering. Such access occurs in theVK_PIPELINE_STAGE_2_CONDITIONAL_RENDERING_BIT_EXT
pipeline stage. -
VK_ACCESS_2_TRANSFORM_FEEDBACK_WRITE_BIT_EXT
specifies write access to a transform feedback buffer made when transform feedback is active. Such access occurs in theVK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT
pipeline stage. -
VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT
specifies read access to a transform feedback counter buffer which is read when vkCmdBeginTransformFeedbackEXT executes. Such access occurs in theVK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT
pipeline stage. -
VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT
specifies write access to a transform feedback counter buffer which is written when vkCmdEndTransformFeedbackEXT executes. Such access occurs in theVK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT
pipeline stage. -
VK_ACCESS_2_COMMAND_PREPROCESS_READ_BIT_NV
specifies reads from buffer inputs to vkCmdPreprocessGeneratedCommandsNV. Such access occurs in theVK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_NV
pipeline stage. -
VK_ACCESS_2_COMMAND_PREPROCESS_WRITE_BIT_NV
specifies writes to the target command buffer preprocess outputs. Such access occurs in theVK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_NV
pipeline stage. -
VK_ACCESS_2_COMMAND_PREPROCESS_READ_BIT_EXT
specifies reads from buffer inputs to vkCmdPreprocessGeneratedCommandsEXT. Such access occurs in theVK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_EXT
pipeline stage. -
VK_ACCESS_2_COMMAND_PREPROCESS_WRITE_BIT_EXT
specifies writes to the target command buffer preprocess outputs. Such access occurs in theVK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_EXT
pipeline stage. -
VK_ACCESS_2_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT
specifies read access to color attachments, including advanced blend operations. Such access occurs in theVK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT
pipeline stage. -
VK_ACCESS_2_INVOCATION_MASK_READ_BIT_HUAWEI
specifies read access to an invocation mask image in theVK_PIPELINE_STAGE_2_INVOCATION_MASK_BIT_HUAWEI
pipeline stage. -
VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR
specifies read access to an acceleration structure as part of a trace, build, or copy command, or to an acceleration structure scratch buffer as part of a build command. Such access occurs in theVK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR
pipeline stage orVK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR
pipeline stage. -
VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR
specifies write access to an acceleration structure or acceleration structure scratch buffer as part of a build or copy command. Such access occurs in theVK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR
pipeline stage. -
VK_ACCESS_2_FRAGMENT_DENSITY_MAP_READ_BIT_EXT
specifies read access to a fragment density map attachment during dynamic fragment density map operations. Such access occurs in theVK_PIPELINE_STAGE_2_FRAGMENT_DENSITY_PROCESS_BIT_EXT
pipeline stage. -
VK_ACCESS_2_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR
specifies read access to a fragment shading rate attachment during rasterization. Such access occurs in theVK_PIPELINE_STAGE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR
pipeline stage. -
VK_ACCESS_2_SHADING_RATE_IMAGE_READ_BIT_NV
specifies read access to a shading rate image during rasterization. Such access occurs in theVK_PIPELINE_STAGE_2_SHADING_RATE_IMAGE_BIT_NV
pipeline stage. It is equivalent toVK_ACCESS_2_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR
. -
VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR
specifies read access to an image or buffer resource in a video decode operation. Such access occurs in theVK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR
pipeline stage. -
VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR
specifies write access to an image or buffer resource in a video decode operation. Such access occurs in theVK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR
pipeline stage. -
VK_ACCESS_2_VIDEO_ENCODE_READ_BIT_KHR
specifies read access to an image or buffer resource in a video encode operation. Such access occurs in theVK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR
pipeline stage. -
VK_ACCESS_2_VIDEO_ENCODE_WRITE_BIT_KHR
specifies write access to an image or buffer resource in a video encode operation. Such access occurs in theVK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR
pipeline stage. -
VK_ACCESS_2_DESCRIPTOR_BUFFER_READ_BIT_EXT
specifies read access to a descriptor buffer in any shader pipeline stage. -
VK_ACCESS_2_OPTICAL_FLOW_READ_BIT_NV
specifies read access to an image or buffer resource as part of a optical flow operation. Such access occurs in theVK_PIPELINE_STAGE_2_OPTICAL_FLOW_BIT_NV
pipeline stage. -
VK_ACCESS_2_OPTICAL_FLOW_WRITE_BIT_NV
specifies write access to an image or buffer resource as part of a optical flow operation. Such access occurs in theVK_PIPELINE_STAGE_2_OPTICAL_FLOW_BIT_NV
pipeline stage. -
VK_ACCESS_2_MICROMAP_WRITE_BIT_EXT
specifies write access to a micromap object. Such access occurs in theVK_PIPELINE_STAGE_2_MICROMAP_BUILD_BIT_EXT
pipeline stage. -
VK_ACCESS_2_MICROMAP_READ_BIT_EXT
specifies read access to a micromap object. Such access occurs in theVK_PIPELINE_STAGE_2_MICROMAP_BUILD_BIT_EXT
andVK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR
pipeline stages.
In situations where an application wishes to select all access types for a
given set of pipeline stages, |
The |
VkAccessFlags2
is a bitmask type for setting a mask of zero or more
VkAccessFlagBits2:
// Provided by VK_VERSION_1_3
typedef VkFlags64 VkAccessFlags2;
or the equivalent
// Provided by VK_KHR_synchronization2
typedef VkAccessFlags2 VkAccessFlags2KHR;
Bits which can be set in the srcAccessMask
and dstAccessMask
members of VkSubpassDependency,
VkSubpassDependency2,
VkMemoryBarrier, VkBufferMemoryBarrier, and
VkImageMemoryBarrier, specifying access behavior, are:
// Provided by VK_VERSION_1_0
typedef enum VkAccessFlagBits {
VK_ACCESS_INDIRECT_COMMAND_READ_BIT = 0x00000001,
VK_ACCESS_INDEX_READ_BIT = 0x00000002,
VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT = 0x00000004,
VK_ACCESS_UNIFORM_READ_BIT = 0x00000008,
VK_ACCESS_INPUT_ATTACHMENT_READ_BIT = 0x00000010,
VK_ACCESS_SHADER_READ_BIT = 0x00000020,
VK_ACCESS_SHADER_WRITE_BIT = 0x00000040,
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT = 0x00000080,
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT = 0x00000100,
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT = 0x00000200,
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT = 0x00000400,
VK_ACCESS_TRANSFER_READ_BIT = 0x00000800,
VK_ACCESS_TRANSFER_WRITE_BIT = 0x00001000,
VK_ACCESS_HOST_READ_BIT = 0x00002000,
VK_ACCESS_HOST_WRITE_BIT = 0x00004000,
VK_ACCESS_MEMORY_READ_BIT = 0x00008000,
VK_ACCESS_MEMORY_WRITE_BIT = 0x00010000,
// Provided by VK_VERSION_1_3
VK_ACCESS_NONE = 0,
// Provided by VK_EXT_transform_feedback
VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT = 0x02000000,
// Provided by VK_EXT_transform_feedback
VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT = 0x04000000,
// Provided by VK_EXT_transform_feedback
VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT = 0x08000000,
// Provided by VK_EXT_conditional_rendering
VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT = 0x00100000,
// Provided by VK_EXT_blend_operation_advanced
VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT = 0x00080000,
// Provided by VK_KHR_acceleration_structure
VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR = 0x00200000,
// Provided by VK_KHR_acceleration_structure
VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR = 0x00400000,
// Provided by VK_EXT_fragment_density_map
VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT = 0x01000000,
// Provided by VK_KHR_fragment_shading_rate
VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR = 0x00800000,
// Provided by VK_NV_device_generated_commands
VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_NV = 0x00020000,
// Provided by VK_NV_device_generated_commands
VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_NV = 0x00040000,
// Provided by VK_NV_shading_rate_image
VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV = VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR,
// Provided by VK_NV_ray_tracing
VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR,
// Provided by VK_NV_ray_tracing
VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NV = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
// Provided by VK_KHR_synchronization2
VK_ACCESS_NONE_KHR = VK_ACCESS_NONE,
// Provided by VK_EXT_device_generated_commands
VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_EXT = VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_NV,
// Provided by VK_EXT_device_generated_commands
VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_EXT = VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_NV,
} VkAccessFlagBits;
These values all have the same meaning as the equivalently named values for VkAccessFlags2.
-
VK_ACCESS_NONE
specifies no accesses. -
VK_ACCESS_MEMORY_READ_BIT
specifies all read accesses. It is always valid in any access mask, and is treated as equivalent to setting allREAD
access flags that are valid where it is used. -
VK_ACCESS_MEMORY_WRITE_BIT
specifies all write accesses. It is always valid in any access mask, and is treated as equivalent to setting allWRITE
access flags that are valid where it is used. -
VK_ACCESS_INDIRECT_COMMAND_READ_BIT
specifies read access to indirect command data read as part of an indirect build, trace, drawing or dispatching command. Such access occurs in theVK_PIPELINE_STAGE_DRAW_INDIRECT_BIT
pipeline stage. -
VK_ACCESS_INDEX_READ_BIT
specifies read access to an index buffer as part of an indexed drawing command, bound by vkCmdBindIndexBuffer2 and vkCmdBindIndexBuffer. Such access occurs in theVK_PIPELINE_STAGE_VERTEX_INPUT_BIT
pipeline stage. -
VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT
specifies read access to a vertex buffer as part of a drawing command, bound by vkCmdBindVertexBuffers. Such access occurs in theVK_PIPELINE_STAGE_VERTEX_INPUT_BIT
pipeline stage. -
VK_ACCESS_UNIFORM_READ_BIT
specifies read access to a uniform buffer in any shader pipeline stage. -
VK_ACCESS_INPUT_ATTACHMENT_READ_BIT
specifies read access to an input attachment within a render pass during subpass shading or fragment shading. Such access occurs in theVK_PIPELINE_STAGE_2_SUBPASS_SHADER_BIT_HUAWEI
orVK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
pipeline stage. -
VK_ACCESS_SHADER_READ_BIT
specifies read access to a uniform texel buffer, sampled image, storage buffer, physical storage buffer, shader binding table, storage texel buffer, or storage image in any shader pipeline stage. -
VK_ACCESS_SHADER_WRITE_BIT
specifies write access to a storage buffer, physical storage buffer, storage texel buffer, or storage image in any shader pipeline stage. -
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
specifies read access to a color attachment, such as via blending (other than advanced blend operations), logic operations or certain render pass load operations in theVK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
pipeline stage or via fragment shader tile image reads in theVK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
pipeline stage. -
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
specifies write access to a color, resolve, or depth/stencil resolve attachment during a render pass or via certain render pass load and store operations. Such access occurs in theVK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
pipeline stage. -
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
specifies read access to a depth/stencil attachment, via depth or stencil operations or certain render pass load operations in theVK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
orVK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT
pipeline stages or via fragment shader tile image reads in theVK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
pipeline stage. -
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT
specifies write access to a depth/stencil attachment, via depth or stencil operations or certain render pass load and store operations. Such access occurs in theVK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
orVK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT
pipeline stages. -
VK_ACCESS_TRANSFER_READ_BIT
specifies read access to an image or buffer in a copy operation. Such access occurs in theVK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT
pipeline stage. -
VK_ACCESS_TRANSFER_WRITE_BIT
specifies write access to an image or buffer in a clear or copy operation. Such access occurs in theVK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT
pipeline stage. -
VK_ACCESS_HOST_READ_BIT
specifies read access by a host operation. Accesses of this type are not performed through a resource, but directly on memory. Such access occurs in theVK_PIPELINE_STAGE_HOST_BIT
pipeline stage. -
VK_ACCESS_HOST_WRITE_BIT
specifies write access by a host operation. Accesses of this type are not performed through a resource, but directly on memory. Such access occurs in theVK_PIPELINE_STAGE_HOST_BIT
pipeline stage. -
VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT
specifies read access to a predicate as part of conditional rendering. Such access occurs in theVK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT
pipeline stage. -
VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT
specifies write access to a transform feedback buffer made when transform feedback is active. Such access occurs in theVK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT
pipeline stage. -
VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT
specifies read access to a transform feedback counter buffer which is read whenvkCmdBeginTransformFeedbackEXT
executes. Such access occurs in theVK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT
pipeline stage. -
VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT
specifies write access to a transform feedback counter buffer which is written whenvkCmdEndTransformFeedbackEXT
executes. Such access occurs in theVK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT
pipeline stage. -
VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_NV
specifies reads from buffer inputs to vkCmdPreprocessGeneratedCommandsNV. Such access occurs in theVK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_NV
pipeline stage. -
VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_NV
specifies writes to the target command buffer preprocess outputs in vkCmdPreprocessGeneratedCommandsNV. Such access occurs in theVK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_NV
pipeline stage. -
VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_EXT
specifies reads from buffer inputs to vkCmdPreprocessGeneratedCommandsEXT. Such access occurs in theVK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_EXT
pipeline stage. -
VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_EXT
specifies writes to the target command buffer preprocess outputs in vkCmdPreprocessGeneratedCommandsEXT. Such access occurs in theVK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_EXT
pipeline stage. -
VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT
specifies read access to color attachments, including advanced blend operations. Such access occurs in theVK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
pipeline stage. -
VK_ACCESS_2_INVOCATION_MASK_READ_BIT_HUAWEI
specifies read access to an invocation mask image in theVK_PIPELINE_STAGE_2_INVOCATION_MASK_BIT_HUAWEI
pipeline stage. -
VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR
specifies read access to an acceleration structure as part of a trace, build, or copy command, or to an acceleration structure scratch buffer as part of a build command. Such access occurs in theVK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR
pipeline stage orVK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR
pipeline stage. -
VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR
specifies write access to an acceleration structure or acceleration structure scratch buffer as part of a build or copy command. Such access occurs in theVK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR
pipeline stage. -
VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT
specifies read access to a fragment density map attachment during dynamic fragment density map operations Such access occurs in theVK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT
pipeline stage. -
VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR
specifies read access to a fragment shading rate attachment during rasterization. Such access occurs in theVK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR
pipeline stage. -
VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV
specifies read access to a shading rate image during rasterization. Such access occurs in theVK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV
pipeline stage. It is equivalent toVK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR
.
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 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.
Access flag | Supported pipeline stages |
---|---|
|
Any |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Any |
|
Any |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Provided by VK_VERSION_1_0
typedef VkFlags VkAccessFlags;
VkAccessFlags
is a bitmask type for setting a mask of zero or more
VkAccessFlagBits.
If a memory object does not have the
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
property, then
vkFlushMappedMemoryRanges must be called in order to guarantee that
writes to the memory object from the host are made available to the host
domain, where they can be further made available to the device domain via a
domain operation.
Similarly, vkInvalidateMappedMemoryRanges must be called to guarantee
that writes which are available to the host domain are made visible to host
operations.
If the memory object does have the
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
property flag, writes to the
memory object from the host are automatically made available to the host
domain.
Similarly, writes made available to the host domain are automatically made
visible to the host.
Queue submission commands automatically perform a domain operation from host to device for all writes performed before the command executes, 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. |
Framebuffer Region Dependencies
Pipeline stages that operate on, or with respect to, the framebuffer are collectively the framebuffer-space pipeline stages. These stages are:
-
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
-
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
-
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT
-
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 subset of the entire framebuffer, and can either be:
-
A sample region, which is set of sample (x, y, layer, sample) coordinates that is a subset of the entire framebuffer, or
-
A fragment region, which is a set of fragment (x, y, layer) coordinates that is a subset of the entire framebuffer.
Both synchronization scopes of a framebuffer-local dependency include only the operations performed within corresponding framebuffer regions (as defined below). No ordering guarantees are made between different framebuffer regions for a framebuffer-local dependency.
Both synchronization scopes of a framebuffer-global dependency include operations on all framebuffer-regions.
If the first synchronization scope includes operations on pixels/fragments
with N samples and the second synchronization scope includes operations on
pixels/fragments with M samples, where N does not equal M, then a
framebuffer region containing all samples at a given (x, y, layer)
coordinate in the first synchronization scope corresponds to a region
containing all samples at the same coordinate in the second synchronization
scope.
In other words, the framebuffer region is a fragment region and it is a
pixel granularity dependency.
If N equals M,
and if the VkSubpassDescription
::flags
does not specify the
VK_SUBPASS_DESCRIPTION_FRAGMENT_REGION_BIT_QCOM
flag,
then a framebuffer region containing a single (x, y, layer, sample)
coordinate in the first synchronization scope corresponds to a region
containing the same sample at the same coordinate in the second
synchronization scope.
In other words, the framebuffer region is a sample region and it is a sample
granularity dependency.
If the pipeline performing the operation was created with
VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_EXT
,
VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_EXT
,
or
VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_EXT
,
the framebuffer region is a fragment region and it is a pixel granularity
dependency.
Since fragment shader 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 specified above. |
Practically, the pixel vs. sample granularity dependency means that if an
input attachment has a different number of samples than the pipeline’s
|
If a synchronization command includes a dependencyFlags
parameter, and
specifies the 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 dependencyFlags
parameter is included, or the
VK_DEPENDENCY_BY_REGION_BIT
flag is not specified, then a
framebuffer-global dependency is specified for those stages.
The 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.
Framebuffer-local dependencies are more efficient 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. |
View-Local Dependencies
In a render pass instance that has multiview enabled, dependencies can be either view-local or view-global.
A view-local dependency only includes operations from a single source view from the source subpass in the first synchronization scope, and only includes operations from a single 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 dependencyFlags
parameter and
specifies the VK_DEPENDENCY_VIEW_LOCAL_BIT
flag, then it defines
view-local dependencies for that synchronization command, for all views.
If no dependencyFlags
parameter is included or the
VK_DEPENDENCY_VIEW_LOCAL_BIT
flag is not specified, then a view-global
dependency is specified.
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
VkDeviceGroupRenderPassBeginInfo::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 dependencyFlags
parameter and
specifies the VK_DEPENDENCY_DEVICE_GROUP_BIT
flag, then it defines a
non-device-local dependency for that synchronization command.
If no dependencyFlags
parameter is included or the
VK_DEPENDENCY_DEVICE_GROUP_BIT
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.
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.
Submission order is a fundamental ordering in Vulkan, giving meaning to the order in which 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. This order does not itself define any execution or memory dependencies; synchronization commands and other orderings within the API use this ordering to define their scopes.
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 vkQueueSubmit and vkQueueSubmit2 commands are executed on the host, for a single queue, from first to last.
-
The order in which VkSubmitInfo structures are specified in the
pSubmits
parameter of vkQueueSubmit, or in which VkSubmitInfo2 structures are specified in thepSubmits
parameter of vkQueueSubmit2, from lowest index to highest. -
The order in which command buffers are specified in the
pCommandBuffers
member of VkSubmitInfo or VkSubmitInfo2 from lowest index to highest. -
The order in which commands outside of a render pass were recorded to a command buffer on the host, from first to last.
-
The order in which commands inside a single subpass were recorded to a command buffer on the host, from first to last.
When using a render pass object with multiple subpasses, commands in different subpasses have no defined submission order relative to each other, regardless of the order in which the subpasses were recorded. Commands within a subpass are still ordered relative to other commands in the same subpass, and those outside of the render pass. |
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. 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.
The order of primitives passing through the graphics pipeline and image layout transitions as part of an image memory barrier provide additional guarantees based on submission order.
Execution of pipeline stages within a given command also has a loose ordering, dependent only on a single command.
Signal operation order is a fundamental ordering in Vulkan, giving meaning to the order in which semaphore and fence signal operations occur when submitted to a single queue. The signal operation order for queue operations is determined as follows:
-
The initial order is determined by the order in which vkQueueSubmit and vkQueueSubmit2 commands are executed on the host, for a single queue, from first to last.
-
The order in which VkSubmitInfo structures are specified in the
pSubmits
parameter of vkQueueSubmit, or in which VkSubmitInfo2 structures are specified in thepSubmits
parameter of vkQueueSubmit2, from lowest index to highest. -
The fence signal operation defined by the
fence
parameter of a vkQueueSubmit or vkQueueSubmit2 or vkQueueBindSparse command is ordered after all semaphore signal operations defined by that command.
Semaphore signal operations defined by a single VkSubmitInfo or VkSubmitInfo2 or VkBindSparseInfo structure are unordered with respect to other semaphore signal operations defined within the same structure.
The vkSignalSemaphore command does not execute on a queue but instead performs the signal operation from the host. The semaphore signal operation defined by executing a vkSignalSemaphore command happens-after the vkSignalSemaphore command is invoked and happens-before the command returns.
When signaling timeline semaphores, it is the responsibility of the application to ensure that they are ordered such that the semaphore value is strictly increasing. Because the first synchronization scope for a semaphore signal operation contains all semaphore signal operations which occur earlier in submission order, all semaphore signal operations contained in any given batch are guaranteed to happen-after all semaphore signal operations contained in any previous batches. However, no ordering guarantee is provided between the semaphore signal operations defined within a single batch. This, combined with the requirement that timeline semaphore values strictly increase, means that it is invalid to signal the same timeline semaphore twice within a single batch. If an application wishes to ensure that some semaphore signal operation happens-after some other semaphore signal operation, it can submit a separate batch containing only semaphore signal operations, which will happen-after the semaphore signal operations in any earlier batches. When signaling a semaphore from the host, the only ordering guarantee is
that the signal operation happens-after when vkSignalSemaphore is
called and happens-before it returns.
Therefore, it is invalid to call |
Fences
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 queue submission command. Fences can be unsignaled on the host with vkResetFences. Fences can be waited on by the host with the vkWaitForFences command, and the current state can be queried with vkGetFenceStatus.
The internal data of a fence may include a reference to any resources and pending work associated with signal or unsignal operations performed on that fence object, collectively referred to as the fence’s payload. Mechanisms to import and export that internal data to and from fences are provided below. These mechanisms indirectly enable applications to share fence state between two or more fences and other synchronization primitives across process and API boundaries.
Fences are represented by VkFence
handles:
// Provided by VK_VERSION_1_0
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkFence)
To create a fence, call:
// Provided by VK_VERSION_1_0
VkResult vkCreateFence(
VkDevice device,
const VkFenceCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkFence* pFence);
-
device
is the logical device that creates the fence. -
pCreateInfo
is a pointer to a VkFenceCreateInfo structure containing information about how the fence is to be created. -
pAllocator
controls host memory allocation as described in the Memory Allocation chapter. -
pFence
is a pointer to a handle in which the resulting fence object is returned.
The VkFenceCreateInfo
structure is defined as:
// Provided by VK_VERSION_1_0
typedef struct VkFenceCreateInfo {
VkStructureType sType;
const void* pNext;
VkFenceCreateFlags flags;
} VkFenceCreateInfo;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
flags
is a bitmask of VkFenceCreateFlagBits specifying the initial state and behavior of the fence.
// Provided by VK_VERSION_1_0
typedef enum VkFenceCreateFlagBits {
VK_FENCE_CREATE_SIGNALED_BIT = 0x00000001,
} VkFenceCreateFlagBits;
-
VK_FENCE_CREATE_SIGNALED_BIT
specifies that the fence object is created in the signaled state. Otherwise, it is created in the unsignaled state.
// Provided by VK_VERSION_1_0
typedef VkFlags VkFenceCreateFlags;
VkFenceCreateFlags
is a bitmask type for setting a mask of zero or
more VkFenceCreateFlagBits.
To create a fence whose payload can be exported to external handles, add a
VkExportFenceCreateInfo structure to the pNext
chain of the
VkFenceCreateInfo structure.
The VkExportFenceCreateInfo
structure is defined as:
// Provided by VK_VERSION_1_1
typedef struct VkExportFenceCreateInfo {
VkStructureType sType;
const void* pNext;
VkExternalFenceHandleTypeFlags handleTypes;
} VkExportFenceCreateInfo;
or the equivalent
// Provided by VK_KHR_external_fence
typedef VkExportFenceCreateInfo VkExportFenceCreateInfoKHR;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
handleTypes
is a bitmask of VkExternalFenceHandleTypeFlagBits specifying one or more fence handle types the application can export from the resulting fence. The application can request multiple handle types for the same fence.
To specify additional attributes of NT handles exported from a fence, add a
VkExportFenceWin32HandleInfoKHR structure to the pNext
chain of
the VkFenceCreateInfo structure.
The VkExportFenceWin32HandleInfoKHR
structure is defined as:
// Provided by VK_KHR_external_fence_win32
typedef struct VkExportFenceWin32HandleInfoKHR {
VkStructureType sType;
const void* pNext;
const SECURITY_ATTRIBUTES* pAttributes;
DWORD dwAccess;
LPCWSTR name;
} VkExportFenceWin32HandleInfoKHR;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
pAttributes
is a pointer to a WindowsSECURITY_ATTRIBUTES
structure specifying security attributes of the handle. -
dwAccess
is aDWORD
specifying access rights of the handle. -
name
is a null-terminated UTF-16 string to associate with the underlying synchronization primitive referenced by NT handles exported from the created fence.
If VkExportFenceCreateInfo is not included in the same pNext
chain, this structure is ignored.
If VkExportFenceCreateInfo is included in the pNext
chain of
VkFenceCreateInfo with a Windows handleType
, but either
VkExportFenceWin32HandleInfoKHR
is not included in the pNext
chain, or it is included but pAttributes
is 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
DXGI_SHARED_RESOURCE_READ
| DXGI_SHARED_RESOURCE_WRITE
for handles of the following types:
VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT
To export a Windows handle representing the state of a fence, call:
// Provided by VK_KHR_external_fence_win32
VkResult vkGetFenceWin32HandleKHR(
VkDevice device,
const VkFenceGetWin32HandleInfoKHR* pGetWin32HandleInfo,
HANDLE* pHandle);
-
device
is the logical device that created the fence being exported. -
pGetWin32HandleInfo
is a pointer to a VkFenceGetWin32HandleInfoKHR structure containing parameters of the export operation. -
pHandle
will return the Windows handle representing the fence state.
For handle types defined as NT handles, the handles returned by
vkGetFenceWin32HandleKHR
are owned by the application.
To avoid leaking resources, the application must release ownership of them
using the CloseHandle
system call when they are no longer needed.
Exporting a Windows handle from a fence may have side effects depending on the transference of the specified handle type, as described in Importing Fence Payloads.
The VkFenceGetWin32HandleInfoKHR
structure is defined as:
// Provided by VK_KHR_external_fence_win32
typedef struct VkFenceGetWin32HandleInfoKHR {
VkStructureType sType;
const void* pNext;
VkFence fence;
VkExternalFenceHandleTypeFlagBits handleType;
} VkFenceGetWin32HandleInfoKHR;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
fence
is the fence from which state will be exported. -
handleType
is a VkExternalFenceHandleTypeFlagBits value specifying the type of handle requested.
The properties of the handle returned depend on the value of
handleType
.
See VkExternalFenceHandleTypeFlagBits for a description of the
properties of the defined external fence handle types.
To export a POSIX file descriptor representing the payload of a fence, call:
// Provided by VK_KHR_external_fence_fd
VkResult vkGetFenceFdKHR(
VkDevice device,
const VkFenceGetFdInfoKHR* pGetFdInfo,
int* pFd);
-
device
is the logical device that created the fence being exported. -
pGetFdInfo
is a pointer to a VkFenceGetFdInfoKHR structure containing parameters of the export operation. -
pFd
will return the file descriptor representing the fence payload.
Each call to vkGetFenceFdKHR
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 when it is no longer needed.
Ownership can be released in many ways.
For example, the application can call |
If pGetFdInfo->handleType
is
VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT
and the fence is signaled at
the time vkGetFenceFdKHR
is called, pFd
may return the value
-1
instead of a valid file descriptor.
Where supported by the operating system, the implementation must set the
file descriptor to be closed automatically when an execve
system call
is made.
Exporting a file descriptor from a fence may have side effects depending on the transference of the specified handle type, as described in Importing Fence State.
The VkFenceGetFdInfoKHR
structure is defined as:
// Provided by VK_KHR_external_fence_fd
typedef struct VkFenceGetFdInfoKHR {
VkStructureType sType;
const void* pNext;
VkFence fence;
VkExternalFenceHandleTypeFlagBits handleType;
} VkFenceGetFdInfoKHR;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
fence
is the fence from which state will be exported. -
handleType
is a VkExternalFenceHandleTypeFlagBits value specifying the type of handle requested.
The properties of the file descriptor returned depend on the value of
handleType
.
See VkExternalFenceHandleTypeFlagBits for a description of the
properties of the defined external fence handle types.
To destroy a fence, call:
// Provided by VK_VERSION_1_0
void vkDestroyFence(
VkDevice device,
VkFence fence,
const VkAllocationCallbacks* pAllocator);
-
device
is the logical device that destroys the fence. -
fence
is the handle of the fence to destroy. -
pAllocator
controls host memory allocation as described in the Memory Allocation chapter.
To query the status of a fence from the host, call:
// Provided by VK_VERSION_1_0
VkResult vkGetFenceStatus(
VkDevice device,
VkFence fence);
-
device
is the logical device that owns the fence. -
fence
is the handle of the fence to query.
Upon success, vkGetFenceStatus
returns the status of the fence object,
with the following return codes:
Status | Meaning |
---|---|
|
The fence specified by |
|
The fence specified by |
|
The device has been lost. See Lost Device. |
If a 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 Lost Device),
vkGetFenceStatus
may return any of the above status codes.
If the device has been lost and vkGetFenceStatus
is called repeatedly,
it will eventually return either VK_SUCCESS
or
VK_ERROR_DEVICE_LOST
.
To set the state of fences to unsignaled from the host, call:
// Provided by VK_VERSION_1_0
VkResult vkResetFences(
VkDevice device,
uint32_t fenceCount,
const VkFence* pFences);
-
device
is the logical device that owns the fences. -
fenceCount
is the number of fences to reset. -
pFences
is a pointer to an array of fence handles to reset.
If any member of pFences
currently has its
payload imported with temporary
permanence, that fence’s prior permanent payload is first restored.
The remaining operations described therefore operate on the restored
payload.
When 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 pFences
is already in the unsignaled state when
vkResetFences is executed, then vkResetFences has no effect on
that fence.
When a fence is submitted to a queue as part of a 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 scope includes every batch submitted in the same queue submission command. Fence signal operations that are defined by vkQueueSubmit or vkQueueSubmit2 additionally include in the first synchronization scope all commands that occur earlier in submission order. Fence signal operations that are defined by vkQueueSubmit or vkQueueSubmit2 or vkQueueBindSparse additionally include in the first synchronization scope any semaphore and fence signal operations that occur earlier in signal operation order.
The second synchronization scope only includes the fence signal operation.
The first access scope includes all memory access performed by the device.
The second access scope is empty.
To wait for one or more fences to enter the signaled state on the host, call:
// Provided by VK_VERSION_1_0
VkResult vkWaitForFences(
VkDevice device,
uint32_t fenceCount,
const VkFence* pFences,
VkBool32 waitAll,
uint64_t timeout);
-
device
is the logical device that owns the fences. -
fenceCount
is the number of fences to wait on. -
pFences
is a pointer to an array offenceCount
fence handles. -
waitAll
is the condition that must be satisfied to successfully unblock the wait. IfwaitAll
isVK_TRUE
, then the condition is that all fences inpFences
are signaled. Otherwise, the condition is that at least one fence inpFences
is signaled. -
timeout
is the timeout period in units of nanoseconds.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 vkWaitForFences
is called, then
vkWaitForFences
returns immediately.
If the condition is not satisfied at the time vkWaitForFences
is
called, then vkWaitForFences
will block and wait until the condition
is satisfied or the timeout
has expired, whichever is sooner.
If timeout
is zero, then vkWaitForFences
does not wait, but
simply returns the current state of the fences.
VK_TIMEOUT
will be returned in this case if the condition is not
satisfied, even though no actual wait was performed.
If the condition is satisfied before the timeout
has expired,
vkWaitForFences
returns VK_SUCCESS
.
Otherwise, vkWaitForFences
returns VK_TIMEOUT
after the
timeout
has expired.
If device loss occurs (see Lost Device) before
the timeout has expired, vkWaitForFences
must return in finite time
with either VK_SUCCESS
or VK_ERROR_DEVICE_LOST
.
While we guarantee that |
An execution dependency is defined by waiting for a fence to become signaled, either via vkWaitForFences or by polling on vkGetFenceStatus.
The first synchronization scope includes only the fence signal operation.
The second synchronization scope includes the host operations of vkWaitForFences or vkGetFenceStatus indicating that the fence has become signaled.
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 memory barrier or other memory dependency must be used to guarantee this. See the description of host access types for more information. |
Alternate Methods to Signal Fences
Besides submitting a fence to a queue as part of a queue submission command, a fence may also be signaled when a particular event occurs on a device or display.
To create a fence that will be signaled when an event occurs on a device, call:
// Provided by VK_EXT_display_control
VkResult vkRegisterDeviceEventEXT(
VkDevice device,
const VkDeviceEventInfoEXT* pDeviceEventInfo,
const VkAllocationCallbacks* pAllocator,
VkFence* pFence);
-
device
is a logical device on which the event may occur. -
pDeviceEventInfo
is a pointer to a VkDeviceEventInfoEXT structure describing the event of interest to the application. -
pAllocator
controls host memory allocation as described in the Memory Allocation chapter. -
pFence
is a pointer to a handle in which the resulting fence object is returned.
The VkDeviceEventInfoEXT
structure is defined as:
// Provided by VK_EXT_display_control
typedef struct VkDeviceEventInfoEXT {
VkStructureType sType;
const void* pNext;
VkDeviceEventTypeEXT deviceEvent;
} VkDeviceEventInfoEXT;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
device
is a VkDeviceEventTypeEXT value specifying when the fence will be signaled.
Possible values of VkDeviceEventInfoEXT::device
, specifying when
a fence will be signaled, are:
// Provided by VK_EXT_display_control
typedef enum VkDeviceEventTypeEXT {
VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT = 0,
} VkDeviceEventTypeEXT;
-
VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT
specifies that the fence is signaled when a display is plugged into or unplugged from the specified device. Applications can use this notification to determine when they need to re-enumerate the available displays on a device.
To create a fence that will be signaled when an event occurs on a VkDisplayKHR object, call:
// Provided by VK_EXT_display_control
VkResult vkRegisterDisplayEventEXT(
VkDevice device,
VkDisplayKHR display,
const VkDisplayEventInfoEXT* pDisplayEventInfo,
const VkAllocationCallbacks* pAllocator,
VkFence* pFence);
-
device
is a logical device associated withdisplay
-
display
is the display on which the event may occur. -
pDisplayEventInfo
is a pointer to a VkDisplayEventInfoEXT structure describing the event of interest to the application. -
pAllocator
controls host memory allocation as described in the Memory Allocation chapter. -
pFence
is a pointer to a handle in which the resulting fence object is returned.
The VkDisplayEventInfoEXT
structure is defined as:
// Provided by VK_EXT_display_control
typedef struct VkDisplayEventInfoEXT {
VkStructureType sType;
const void* pNext;
VkDisplayEventTypeEXT displayEvent;
} VkDisplayEventInfoEXT;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
displayEvent
is a VkDisplayEventTypeEXT specifying when the fence will be signaled.
Possible values of VkDisplayEventInfoEXT::displayEvent
,
specifying when a fence will be signaled, are:
// Provided by VK_EXT_display_control
typedef enum VkDisplayEventTypeEXT {
VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT = 0,
} VkDisplayEventTypeEXT;
-
VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT
specifies that the fence is signaled when the first pixel of the next display refresh cycle leaves the display engine for the display.
Importing Fence Payloads
Applications can import a fence payload into an existing fence using an external fence handle. The effects of the import operation will be either temporary or permanent, as specified by the application. If the import is temporary, the fence will be restored to its permanent state the next time that fence is passed to vkResetFences.
Restoring a fence to its prior permanent payload is a distinct operation from resetting a fence payload. See vkResetFences for more detail. |
Performing a subsequent temporary import on a fence before resetting it has
no effect on this requirement; the next unsignal of the fence must still
restore its last permanent state.
A permanent payload import behaves as if the target fence was destroyed, and
a new fence was created with the same handle but the imported payload.
Because importing a fence payload temporarily or permanently detaches the
existing payload from a fence, similar usage restrictions to those applied
to vkDestroyFence
are applied to any command that imports a fence
payload.
Which of these import types is used is referred to as the import operation’s
permanence.
Each handle type supports either one or both types of permanence.
The implementation must perform the import operation by either referencing or copying the payload referred to by the specified external fence handle, depending on the handle’s type. The import method used is referred to as the handle type’s transference. When using handle types with reference transference, importing a payload to a fence adds the fence to the set of all fences sharing that payload. This set includes the fence from which the payload was exported. Fence signaling, waiting, and resetting operations performed on any fence in the set must behave as if the set were a single fence. Importing a payload using handle types with copy transference creates a duplicate copy of the payload at the time of import, but makes no further reference to it. Fence signaling, waiting, and resetting operations performed on the target of copy imports must not affect any other fence or payload.
Export operations have the same transference as the specified handle type’s import operations. Additionally, exporting a fence payload to a handle with copy transference has the same side effects on the source fence’s payload as executing a fence reset operation. If the fence was using a temporarily imported payload, the fence’s prior permanent payload will be restored.
The
tables
Handle Types Supported by |
External synchronization allows
implementations to modify an object’s internal state, i.e. payload, without
internal synchronization.
However, for fences sharing a payload across processes, satisfying the
external synchronization requirements of VkFence
parameters as if all
fences in the set were the same object is sometimes infeasible.
Satisfying valid usage constraints on the state of a fence would similarly
require impractical coordination or levels of trust between processes.
Therefore, these constraints only apply to a specific fence handle, not to
its payload.
For distinct fence objects which share a payload:
-
If multiple commands which queue a signal operation, or which unsignal a fence, are called concurrently, behavior will be as if the commands were called in an arbitrary sequential order.
-
If a queue submission command is called with a fence that is sharing a payload, and the payload is already associated with another queue command that has not yet completed execution, either one or both of the commands will cause the fence to become signaled when they complete execution.
-
If a fence payload is reset while it is associated with a queue command that has not yet completed execution, the payload will become unsignaled, but may become signaled again when the command completes execution.
-
In the preceding cases, any of the devices associated with the fences sharing the payload may be lost, or any of the queue submission or fence reset commands may return
VK_ERROR_INITIALIZATION_FAILED
.
Other than these non-deterministic results, behavior is well defined. In particular:
-
The implementation must not crash or enter an internally inconsistent state where future valid Vulkan commands might cause undefined results,
-
Timeouts on future wait commands on fences sharing the payload must be effective.
These rules allow processes to synchronize access to shared memory without trusting each other. However, such processes must still be cautious not to use the shared fence for more than synchronizing access to the shared memory. For example, a process should not use a fence with shared payload to tell when commands it submitted to a queue have completed and objects used by those commands may be destroyed, since the other process can accidentally or maliciously cause the fence to signal before the commands actually complete. |
When a fence is using an imported payload, its
VkExportFenceCreateInfo::handleTypes
value is specified when
creating the fence from which the payload was exported, rather than
specified when creating the fence.
Additionally,
VkExternalFenceProperties::exportFromImportedHandleTypes
restricts which handle types can be exported from such a fence based on the
specific handle type used to import the current payload.
Passing a fence to vkAcquireNextImageKHR is equivalent to temporarily
importing a fence payload to that fence.
Because the exportable handle types of an imported fence correspond to its current imported payload, and vkAcquireNextImageKHR behaves the same as a temporary import operation for which the source fence is opaque to the application, applications have no way of determining whether any external handle types can be exported from a fence in this state. Therefore, applications must not attempt to export handles from fences using a temporarily imported payload from vkAcquireNextImageKHR. |
When importing a fence payload, 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 a valid fence which will not
cause program termination, device loss, queue stalls, host thread stalls, or
corruption of other resources when used as allowed according to its import
parameters.
If the external handle provided does not meet these requirements, the
implementation must fail the fence payload import operation with the error
code VK_ERROR_INVALID_EXTERNAL_HANDLE
.
To import a fence payload from a Windows handle, call:
// Provided by VK_KHR_external_fence_win32
VkResult vkImportFenceWin32HandleKHR(
VkDevice device,
const VkImportFenceWin32HandleInfoKHR* pImportFenceWin32HandleInfo);
-
device
is the logical device that created the fence. -
pImportFenceWin32HandleInfo
is a pointer to a VkImportFenceWin32HandleInfoKHR structure specifying the fence and import parameters.
Importing a fence payload 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 CloseHandle
system call when the handle is no
longer needed.
Applications can import the same fence payload into multiple instances of Vulkan, into the same instance from which it was exported, and multiple times into a given Vulkan instance.
The VkImportFenceWin32HandleInfoKHR
structure is defined as:
// Provided by VK_KHR_external_fence_win32
typedef struct VkImportFenceWin32HandleInfoKHR {
VkStructureType sType;
const void* pNext;
VkFence fence;
VkFenceImportFlags flags;
VkExternalFenceHandleTypeFlagBits handleType;
HANDLE handle;
LPCWSTR name;
} VkImportFenceWin32HandleInfoKHR;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
fence
is the fence into which the state will be imported. -
flags
is a bitmask of VkFenceImportFlagBits specifying additional parameters for the fence payload import operation. -
handleType
is a VkExternalFenceHandleTypeFlagBits value specifying the type ofhandle
. -
handle
isNULL
or the external handle to import. -
name
isNULL
or a null-terminated UTF-16 string naming the underlying synchronization primitive to import.
The handle types supported by handleType
are:
Handle Type | Transference | Permanence Supported |
---|---|---|
|
Reference |
Temporary,Permanent |
|
Reference |
Temporary,Permanent |
To import a fence payload from a POSIX file descriptor, call:
// Provided by VK_KHR_external_fence_fd
VkResult vkImportFenceFdKHR(
VkDevice device,
const VkImportFenceFdInfoKHR* pImportFenceFdInfo);
-
device
is the logical device that created the fence. -
pImportFenceFdInfo
is a pointer to a VkImportFenceFdInfoKHR structure specifying the fence and import parameters.
Importing a fence payload 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.
Applications can import the same fence payload into multiple instances of Vulkan, into the same instance from which it was exported, and multiple times into a given Vulkan instance.
The VkImportFenceFdInfoKHR
structure is defined as:
// Provided by VK_KHR_external_fence_fd
typedef struct VkImportFenceFdInfoKHR {
VkStructureType sType;
const void* pNext;
VkFence fence;
VkFenceImportFlags flags;
VkExternalFenceHandleTypeFlagBits handleType;
int fd;
} VkImportFenceFdInfoKHR;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
fence
is the fence into which the payload will be imported. -
flags
is a bitmask of VkFenceImportFlagBits specifying additional parameters for the fence payload import operation. -
handleType
is a VkExternalFenceHandleTypeFlagBits value specifying the type offd
. -
fd
is the external handle to import.
The handle types supported by handleType
are:
Handle Type | Transference | Permanence Supported |
---|---|---|
|
Reference |
Temporary,Permanent |
|
Copy |
Temporary |
If handleType
is VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT
, the
special value -1
for fd
is treated like a valid sync file descriptor
referring to an object that has already signaled.
The import operation will succeed and the VkFence
will have a
temporarily imported payload as if a valid file descriptor had been
provided.
This special behavior for importing an invalid sync file descriptor allows
easier interoperability with other system APIs which use the convention that
an invalid sync file descriptor represents work that has already completed
and does not need to be waited for.
It is consistent with the option for implementations to return a |
Bits which can be set in
-
VkImportFenceFdInfoKHR::
flags
specifying additional parameters of a fence import operation are:
// Provided by VK_VERSION_1_1
typedef enum VkFenceImportFlagBits {
VK_FENCE_IMPORT_TEMPORARY_BIT = 0x00000001,
// Provided by VK_KHR_external_fence
VK_FENCE_IMPORT_TEMPORARY_BIT_KHR = VK_FENCE_IMPORT_TEMPORARY_BIT,
} VkFenceImportFlagBits;
or the equivalent
// Provided by VK_KHR_external_fence
typedef VkFenceImportFlagBits VkFenceImportFlagBitsKHR;
-
VK_FENCE_IMPORT_TEMPORARY_BIT
specifies that the fence payload will be imported only temporarily, as described in Importing Fence Payloads, regardless of the permanence ofhandleType
.
// Provided by VK_VERSION_1_1
typedef VkFlags VkFenceImportFlags;
or the equivalent
// Provided by VK_KHR_external_fence
typedef VkFenceImportFlags VkFenceImportFlagsKHR;
VkFenceImportFlags
is a bitmask type for setting a mask of zero or
more VkFenceImportFlagBits.
Semaphores
Semaphores are a synchronization primitive that can be used to insert a dependency between queue operations or between a queue operation and the host. Binary semaphores have two states - signaled and unsignaled. Timeline semaphores have a strictly increasing 64-bit unsigned integer payload and are signaled with respect to a particular reference value. A semaphore can be signaled after execution of a queue operation is completed, and a queue operation can wait for a semaphore to become signaled before it begins execution. A timeline semaphore can additionally be signaled from the host with the vkSignalSemaphore command and waited on from the host with the vkWaitSemaphores command.
The internal data of a semaphore may include a reference to any resources and pending work associated with signal or unsignal operations performed on that semaphore object, collectively referred to as the semaphore’s payload. Mechanisms to import and export that internal data to and from semaphores are provided below. These mechanisms indirectly enable applications to share semaphore state between two or more semaphores and other synchronization primitives across process and API boundaries.
Semaphores are represented by VkSemaphore
handles:
// Provided by VK_VERSION_1_0
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSemaphore)
To create a semaphore, call:
// Provided by VK_VERSION_1_0
VkResult vkCreateSemaphore(
VkDevice device,
const VkSemaphoreCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkSemaphore* pSemaphore);
-
device
is the logical device that creates the semaphore. -
pCreateInfo
is a pointer to a VkSemaphoreCreateInfo structure containing information about how the semaphore is to be created. -
pAllocator
controls host memory allocation as described in the Memory Allocation chapter. -
pSemaphore
is a pointer to a handle in which the resulting semaphore object is returned.
The VkSemaphoreCreateInfo
structure is defined as:
// Provided by VK_VERSION_1_0
typedef struct VkSemaphoreCreateInfo {
VkStructureType sType;
const void* pNext;
VkSemaphoreCreateFlags flags;
} VkSemaphoreCreateInfo;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
flags
is reserved for future use.
// Provided by VK_VERSION_1_0
typedef VkFlags VkSemaphoreCreateFlags;
VkSemaphoreCreateFlags
is a bitmask type for setting a mask, but is
currently reserved for future use.
The VkSemaphoreTypeCreateInfo
structure is defined as:
// Provided by VK_VERSION_1_2
typedef struct VkSemaphoreTypeCreateInfo {
VkStructureType sType;
const void* pNext;
VkSemaphoreType semaphoreType;
uint64_t initialValue;
} VkSemaphoreTypeCreateInfo;
or the equivalent
// Provided by VK_KHR_timeline_semaphore
typedef VkSemaphoreTypeCreateInfo VkSemaphoreTypeCreateInfoKHR;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
semaphoreType
is a VkSemaphoreType value specifying the type of the semaphore. -
initialValue
is the initial payload value ifsemaphoreType
isVK_SEMAPHORE_TYPE_TIMELINE
.
To create a semaphore of a specific type, add a
VkSemaphoreTypeCreateInfo
structure to the
VkSemaphoreCreateInfo::pNext
chain.
If no VkSemaphoreTypeCreateInfo
structure is included in the
pNext
chain of VkSemaphoreCreateInfo, then the created semaphore
will have a default VkSemaphoreType of VK_SEMAPHORE_TYPE_BINARY
.
Possible values of VkSemaphoreTypeCreateInfo::semaphoreType
,
specifying the type of a semaphore, are:
// Provided by VK_VERSION_1_2
typedef enum VkSemaphoreType {
VK_SEMAPHORE_TYPE_BINARY = 0,
VK_SEMAPHORE_TYPE_TIMELINE = 1,
// Provided by VK_KHR_timeline_semaphore
VK_SEMAPHORE_TYPE_BINARY_KHR = VK_SEMAPHORE_TYPE_BINARY,
// Provided by VK_KHR_timeline_semaphore
VK_SEMAPHORE_TYPE_TIMELINE_KHR = VK_SEMAPHORE_TYPE_TIMELINE,
} VkSemaphoreType;
or the equivalent
// Provided by VK_KHR_timeline_semaphore
typedef VkSemaphoreType VkSemaphoreTypeKHR;
-
VK_SEMAPHORE_TYPE_BINARY
specifies a binary semaphore type that has a boolean payload indicating whether the semaphore is currently signaled or unsignaled. When created, the semaphore is in the unsignaled state. -
VK_SEMAPHORE_TYPE_TIMELINE
specifies a timeline semaphore type that has a strictly increasing 64-bit unsigned integer payload indicating whether the semaphore is signaled with respect to a particular reference value. When created, the semaphore payload has the value given by theinitialValue
field of VkSemaphoreTypeCreateInfo.
To create a semaphore whose payload can be exported to external handles,
add a VkExportSemaphoreCreateInfo structure to the pNext
chain
of the VkSemaphoreCreateInfo structure.
The VkExportSemaphoreCreateInfo
structure is defined as:
// Provided by VK_VERSION_1_1
typedef struct VkExportSemaphoreCreateInfo {
VkStructureType sType;
const void* pNext;
VkExternalSemaphoreHandleTypeFlags handleTypes;
} VkExportSemaphoreCreateInfo;
or the equivalent
// Provided by VK_KHR_external_semaphore
typedef VkExportSemaphoreCreateInfo VkExportSemaphoreCreateInfoKHR;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
handleTypes
is a bitmask of VkExternalSemaphoreHandleTypeFlagBits specifying one or more semaphore handle types the application can export from the resulting semaphore. The application can request multiple handle types for the same semaphore.
To specify additional attributes of NT handles exported from a semaphore,
add a VkExportSemaphoreWin32HandleInfoKHR
structure to the pNext
chain of the VkSemaphoreCreateInfo structure.
The VkExportSemaphoreWin32HandleInfoKHR
structure is defined as:
// Provided by VK_KHR_external_semaphore_win32
typedef struct VkExportSemaphoreWin32HandleInfoKHR {
VkStructureType sType;
const void* pNext;
const SECURITY_ATTRIBUTES* pAttributes;
DWORD dwAccess;
LPCWSTR name;
} VkExportSemaphoreWin32HandleInfoKHR;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
pAttributes
is a pointer to a WindowsSECURITY_ATTRIBUTES
structure specifying security attributes of the handle. -
dwAccess
is aDWORD
specifying access rights of the handle. -
name
is a null-terminated UTF-16 string to associate with the underlying synchronization primitive referenced by NT handles exported from the created semaphore.
If VkExportSemaphoreCreateInfo is not included in the same pNext
chain, this structure is ignored.
If VkExportSemaphoreCreateInfo is included in the pNext
chain of
VkSemaphoreCreateInfo with a Windows handleType
, but either
VkExportSemaphoreWin32HandleInfoKHR
is not included in the pNext
chain, or it is included but pAttributes
is 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 used depend on
the handle type.
For handles of the following types:
VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
The implementation must ensure the access rights allow both signal and wait operations on the semaphore.
For handles of the following types:
VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT
The access rights must be:
GENERIC_ALL
To export a Windows handle representing the payload of a semaphore, call:
// Provided by VK_KHR_external_semaphore_win32
VkResult vkGetSemaphoreWin32HandleKHR(
VkDevice device,
const VkSemaphoreGetWin32HandleInfoKHR* pGetWin32HandleInfo,
HANDLE* pHandle);
-
device
is the logical device that created the semaphore being exported. -
pGetWin32HandleInfo
is a pointer to a VkSemaphoreGetWin32HandleInfoKHR structure containing parameters of the export operation. -
pHandle
will return the Windows handle representing the semaphore state.
For handle types defined as NT handles, the handles returned by
vkGetSemaphoreWin32HandleKHR
are owned by the application.
To avoid leaking resources, the application must release ownership of them
using the CloseHandle
system call when they are no longer needed.
Exporting a Windows handle from a semaphore may have side effects depending on the transference of the specified handle type, as described in Importing Semaphore Payloads.
The VkSemaphoreGetWin32HandleInfoKHR
structure is defined as:
// Provided by VK_KHR_external_semaphore_win32
typedef struct VkSemaphoreGetWin32HandleInfoKHR {
VkStructureType sType;
const void* pNext;
VkSemaphore semaphore;
VkExternalSemaphoreHandleTypeFlagBits handleType;
} VkSemaphoreGetWin32HandleInfoKHR;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
semaphore
is the semaphore from which state will be exported. -
handleType
is a VkExternalSemaphoreHandleTypeFlagBits value specifying the type of handle requested.
The properties of the handle returned depend on the value of
handleType
.
See VkExternalSemaphoreHandleTypeFlagBits for a description of the
properties of the defined external semaphore handle types.
The VkQueryLowLatencySupportNV
structure is defined as:
// Provided by VK_NV_low_latency
typedef struct VkQueryLowLatencySupportNV {
VkStructureType sType;
const void* pNext;
void* pQueriedLowLatencyData;
} VkQueryLowLatencySupportNV;
This structure describes the following feature:
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
pQueriedLowLatencyData
is used for NVIDIA Reflex Support.
To export a POSIX file descriptor representing the payload of a semaphore, call:
// Provided by VK_KHR_external_semaphore_fd
VkResult vkGetSemaphoreFdKHR(
VkDevice device,
const VkSemaphoreGetFdInfoKHR* pGetFdInfo,
int* pFd);
-
device
is the logical device that created the semaphore being exported. -
pGetFdInfo
is a pointer to a VkSemaphoreGetFdInfoKHR structure containing parameters of the export operation. -
pFd
will return the file descriptor representing the semaphore payload.
Each call to vkGetSemaphoreFdKHR
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 when it is no longer needed.
Ownership can be released in many ways.
For example, the application can call |
Where supported by the operating system, the implementation must set the
file descriptor to be closed automatically when an execve
system call
is made.
Exporting a file descriptor from a semaphore may have side effects depending on the transference of the specified handle type, as described in Importing Semaphore State.
The VkSemaphoreGetFdInfoKHR
structure is defined as:
// Provided by VK_KHR_external_semaphore_fd
typedef struct VkSemaphoreGetFdInfoKHR {
VkStructureType sType;
const void* pNext;
VkSemaphore semaphore;
VkExternalSemaphoreHandleTypeFlagBits handleType;
} VkSemaphoreGetFdInfoKHR;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
semaphore
is the semaphore from which state will be exported. -
handleType
is a VkExternalSemaphoreHandleTypeFlagBits value specifying the type of handle requested.
The properties of the file descriptor returned depend on the value of
handleType
.
See VkExternalSemaphoreHandleTypeFlagBits for a description of the
properties of the defined external semaphore handle types.
To export a Zircon event handle representing the payload of a semaphore, call:
// Provided by VK_FUCHSIA_external_semaphore
VkResult vkGetSemaphoreZirconHandleFUCHSIA(
VkDevice device,
const VkSemaphoreGetZirconHandleInfoFUCHSIA* pGetZirconHandleInfo,
zx_handle_t* pZirconHandle);
-
device
is the logical device that created the semaphore being exported. -
pGetZirconHandleInfo
is a pointer to a VkSemaphoreGetZirconHandleInfoFUCHSIA structure containing parameters of the export operation. -
pZirconHandle
will return the Zircon event handle representing the semaphore payload.
Each call to vkGetSemaphoreZirconHandleFUCHSIA
must create a Zircon
event handle and transfer ownership of it to the application.
To avoid leaking resources, the application must release ownership of the
Zircon event handle when it is no longer needed.
Ownership can be released in many ways. For example, the application can call zx_handle_close() on the file descriptor, or transfer ownership back to Vulkan by using the file descriptor to import a semaphore payload. |
Exporting a Zircon event handle from a semaphore may have side effects depending on the transference of the specified handle type, as described in Importing Semaphore State.
The VkSemaphoreGetZirconHandleInfoFUCHSIA
structure is defined as:
// Provided by VK_FUCHSIA_external_semaphore
typedef struct VkSemaphoreGetZirconHandleInfoFUCHSIA {
VkStructureType sType;
const void* pNext;
VkSemaphore semaphore;
VkExternalSemaphoreHandleTypeFlagBits handleType;
} VkSemaphoreGetZirconHandleInfoFUCHSIA;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
semaphore
is the semaphore from which state will be exported. -
handleType
is a VkExternalSemaphoreHandleTypeFlagBits value specifying the type of handle requested.
The properties of the Zircon event handle returned depend on the value of
handleType
.
See VkExternalSemaphoreHandleTypeFlagBits for a description of the
properties of the defined external semaphore handle types.
To destroy a semaphore, call:
// Provided by VK_VERSION_1_0
void vkDestroySemaphore(
VkDevice device,
VkSemaphore semaphore,
const VkAllocationCallbacks* pAllocator);
-
device
is the logical device that destroys the semaphore. -
semaphore
is the handle of the semaphore to destroy. -
pAllocator
controls host memory allocation as described in the Memory Allocation chapter.
Semaphore Signaling
When a batch is submitted to a queue via a 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.
In case of semaphores created with a VkSemaphoreType of
VK_SEMAPHORE_TYPE_TIMELINE
the semaphore is considered signaled with
respect to the counter value set to be signaled as specified in
VkTimelineSemaphoreSubmitInfo or VkSemaphoreSignalInfo.
The first synchronization scope
includes every command submitted in the same batch.
In the case of vkQueueSubmit2, the first synchronization scope is
limited to the pipeline stage specified by
VkSemaphoreSubmitInfo::stageMask
.
Semaphore signal operations that are defined by vkQueueSubmit
or vkQueueSubmit2
additionally include all commands that occur earlier in
submission order.
Semaphore signal operations that are defined by vkQueueSubmit
or vkQueueSubmit2
or vkQueueBindSparse
additionally include in the first synchronization scope any semaphore and
fence signal operations that occur earlier in
signal operation order.
The second synchronization scope includes only the semaphore signal operation.
The first access scope includes all memory access performed by the device.
The second access scope is empty.
Semaphore Waiting
When a batch is submitted to a queue via a 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 wait operations.
Such semaphore wait operations set the semaphores
created with a VkSemaphoreType of VK_SEMAPHORE_TYPE_BINARY
to the unsignaled state.
In case of semaphores created with a VkSemaphoreType of
VK_SEMAPHORE_TYPE_TIMELINE
a prior semaphore signal operation defines
a memory dependency with a semaphore wait operation if the value the
semaphore is signaled with is greater than or equal to the value the
semaphore is waited with, thus the semaphore will continue to be considered
signaled with respect to the counter value waited on as specified in
VkTimelineSemaphoreSubmitInfo.
The first synchronization scope includes one semaphore signal operation for each semaphore waited on by this batch. The specific signal operation waited on for each semaphore must meet the following criteria:
-
for binary semaphores, the signal operation is either earlier in submission order on the same queue, or is submitted by a command whose host operation happens-before this batch is submitted on the host
-
for binary semaphores, no wait operation exists that happens-after the signal operation and happens-before this wait operation
-
the signal operation is not guaranteed to happen-after the semaphore wait operation in this batch
-
for timeline semaphores, the signal value is greater than or equal to the wait value
If multiple semaphore signal operations meet these criteria, any of those operations may be included in the first synchronization scope. When waiting on a binary semaphore, applications must ensure that exactly one semaphore signal operation meets these criteria.
The second synchronization scope
includes every command submitted in the same batch.
In the case of vkQueueSubmit, the second synchronization scope is
limited to operations on the pipeline stages determined by the
destination stage mask specified
by the corresponding element of pWaitDstStageMask
.
In the case of vkQueueSubmit2, the second synchronization scope is
limited to the pipeline stage specified by
VkSemaphoreSubmitInfo::stageMask
.
Also, in the case of
either vkQueueSubmit2 or
vkQueueSubmit, the second synchronization scope additionally includes
all commands that occur later in
submission order.
The first access scope is empty.
The second access scope includes all memory access performed by the device.
The semaphore wait operation happens-after the first set of operations in the execution dependency, and happens-before the second set of operations in the execution dependency.
Unlike timeline semaphores, fences or events, waiting for a binary semaphore also unsignals that semaphore when the wait completes. Applications must ensure that between two such wait operations, the semaphore is signaled again, with execution dependencies used to ensure these occur in order. Binary semaphore waits and signals should thus occur in discrete 1:1 pairs. |
A common scenario for using 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
Alternatively, 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
pre-rasterization shader stages.
More precisely, the semaphore signals after the presentation operation
completes, the semaphore wait stalls the
|
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 semaphore wait operation is submitted to a queue:
-
A binary semaphore must be signaled, or have an associated semaphore signal operation that is pending execution.
-
Any semaphore signal operations on which the pending binary semaphore signal operation depends must also be completed or pending execution.
-
There must be no other queue waiting on the same binary semaphore when the operation executes.
Host Operations on Semaphores
In addition to semaphore signal operations and semaphore wait operations submitted to device queues, timeline semaphores support the following host operations:
-
Query the current counter value of the semaphore using the vkGetSemaphoreCounterValue command.
-
Wait for a set of semaphores to reach particular counter values using the vkWaitSemaphores command.
-
Signal the semaphore with a particular counter value from the host using the vkSignalSemaphore command.
To query the current counter value of a semaphore created with a
VkSemaphoreType of VK_SEMAPHORE_TYPE_TIMELINE
from the host,
call:
// Provided by VK_VERSION_1_2
VkResult vkGetSemaphoreCounterValue(
VkDevice device,
VkSemaphore semaphore,
uint64_t* pValue);
or the equivalent command
// Provided by VK_KHR_timeline_semaphore
VkResult vkGetSemaphoreCounterValueKHR(
VkDevice device,
VkSemaphore semaphore,
uint64_t* pValue);
-
device
is the logical device that owns the semaphore. -
semaphore
is the handle of the semaphore to query. -
pValue
is a pointer to a 64-bit integer value in which the current counter value of the semaphore is returned.
If a queue submission command is pending execution, then the value returned by this command may immediately be out of date. |
To wait for a set of semaphores created with a VkSemaphoreType of
VK_SEMAPHORE_TYPE_TIMELINE
to reach particular counter values on the
host, call:
// Provided by VK_VERSION_1_2
VkResult vkWaitSemaphores(
VkDevice device,
const VkSemaphoreWaitInfo* pWaitInfo,
uint64_t timeout);
or the equivalent command
// Provided by VK_KHR_timeline_semaphore
VkResult vkWaitSemaphoresKHR(
VkDevice device,
const VkSemaphoreWaitInfo* pWaitInfo,
uint64_t timeout);
-
device
is the logical device that owns the semaphores. -
pWaitInfo
is a pointer to a VkSemaphoreWaitInfo structure containing information about the wait condition. -
timeout
is the timeout period in units of nanoseconds.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 vkWaitSemaphores
is called, then
vkWaitSemaphores
returns immediately.
If the condition is not satisfied at the time vkWaitSemaphores
is
called, then vkWaitSemaphores
will block and wait until the condition
is satisfied or the timeout
has expired, whichever is sooner.
If timeout
is zero, then vkWaitSemaphores
does not wait, but
simply returns information about the current state of the semaphores.
VK_TIMEOUT
will be returned in this case if the condition is not
satisfied, even though no actual wait was performed.
If the condition is satisfied before the timeout
has expired,
vkWaitSemaphores
returns VK_SUCCESS
.
Otherwise, vkWaitSemaphores
returns VK_TIMEOUT
after the
timeout
has expired.
If device loss occurs (see Lost Device) before
the timeout has expired, vkWaitSemaphores
must return in finite time
with either VK_SUCCESS
or VK_ERROR_DEVICE_LOST
.
The VkSemaphoreWaitInfo
structure is defined as:
// Provided by VK_VERSION_1_2
typedef struct VkSemaphoreWaitInfo {
VkStructureType sType;
const void* pNext;
VkSemaphoreWaitFlags flags;
uint32_t semaphoreCount;
const VkSemaphore* pSemaphores;
const uint64_t* pValues;
} VkSemaphoreWaitInfo;
or the equivalent
// Provided by VK_KHR_timeline_semaphore
typedef VkSemaphoreWaitInfo VkSemaphoreWaitInfoKHR;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
flags
is a bitmask of VkSemaphoreWaitFlagBits specifying additional parameters for the semaphore wait operation. -
semaphoreCount
is the number of semaphores to wait on. -
pSemaphores
is a pointer to an array ofsemaphoreCount
semaphore handles to wait on. -
pValues
is a pointer to an array ofsemaphoreCount
timeline semaphore values.
Bits which can be set in VkSemaphoreWaitInfo::flags
, specifying
additional parameters of a semaphore wait operation, are:
// Provided by VK_VERSION_1_2
typedef enum VkSemaphoreWaitFlagBits {
VK_SEMAPHORE_WAIT_ANY_BIT = 0x00000001,
// Provided by VK_KHR_timeline_semaphore
VK_SEMAPHORE_WAIT_ANY_BIT_KHR = VK_SEMAPHORE_WAIT_ANY_BIT,
} VkSemaphoreWaitFlagBits;
or the equivalent
// Provided by VK_KHR_timeline_semaphore
typedef VkSemaphoreWaitFlagBits VkSemaphoreWaitFlagBitsKHR;
-
VK_SEMAPHORE_WAIT_ANY_BIT
specifies that the semaphore wait condition is that at least one of the semaphores inVkSemaphoreWaitInfo
::pSemaphores
has reached the value specified by the corresponding element ofVkSemaphoreWaitInfo
::pValues
. IfVK_SEMAPHORE_WAIT_ANY_BIT
is not set, the semaphore wait condition is that all of the semaphores inVkSemaphoreWaitInfo
::pSemaphores
have reached the value specified by the corresponding element ofVkSemaphoreWaitInfo
::pValues
.
// Provided by VK_VERSION_1_2
typedef VkFlags VkSemaphoreWaitFlags;
or the equivalent
// Provided by VK_KHR_timeline_semaphore
typedef VkSemaphoreWaitFlags VkSemaphoreWaitFlagsKHR;
VkSemaphoreWaitFlags
is a bitmask type for setting a mask of zero or
more VkSemaphoreWaitFlagBits.
To signal a semaphore created with a VkSemaphoreType of
VK_SEMAPHORE_TYPE_TIMELINE
with a particular counter value, on the
host, call:
// Provided by VK_VERSION_1_2
VkResult vkSignalSemaphore(
VkDevice device,
const VkSemaphoreSignalInfo* pSignalInfo);
or the equivalent command
// Provided by VK_KHR_timeline_semaphore
VkResult vkSignalSemaphoreKHR(
VkDevice device,
const VkSemaphoreSignalInfo* pSignalInfo);
-
device
is the logical device that owns the semaphore. -
pSignalInfo
is a pointer to a VkSemaphoreSignalInfo structure containing information about the signal operation.
When vkSignalSemaphore
is executed on the host, it defines and
immediately executes a semaphore signal operation which sets the timeline semaphore to the given value.
The first synchronization scope is defined by the host execution model, but
includes execution of vkSignalSemaphore
on the host and anything that
happened-before it.
The second synchronization scope is empty.
The VkSemaphoreSignalInfo
structure is defined as:
// Provided by VK_VERSION_1_2
typedef struct VkSemaphoreSignalInfo {
VkStructureType sType;
const void* pNext;
VkSemaphore semaphore;
uint64_t value;
} VkSemaphoreSignalInfo;
or the equivalent
// Provided by VK_KHR_timeline_semaphore
typedef VkSemaphoreSignalInfo VkSemaphoreSignalInfoKHR;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
semaphore
is the handle of the semaphore to signal. -
value
is the value to signal.
Importing Semaphore Payloads
Applications can import a semaphore payload into an existing semaphore
using an external semaphore handle.
The effects of the import operation will be either temporary or permanent,
as specified by the application.
If the import is temporary, the implementation must restore the semaphore
to its prior permanent state after submitting the next semaphore wait
operation.
Performing a subsequent temporary import on a semaphore before performing a
semaphore wait has no effect on this requirement; the next wait submitted on
the semaphore must still restore its last permanent state.
A permanent payload import behaves as if the target semaphore was destroyed,
and a new semaphore was created with the same handle but the imported
payload.
Because importing a semaphore payload temporarily or permanently detaches
the existing payload from a semaphore, similar usage restrictions to those
applied to vkDestroySemaphore
are applied to any command that imports
a semaphore payload.
Which of these import types is used is referred to as the import operation’s
permanence.
Each handle type supports either one or both types of permanence.
The implementation must perform the import operation by either referencing or copying the payload referred to by the specified external semaphore handle, depending on the handle’s type. The import method used is referred to as the handle type’s transference. When using handle types with reference transference, importing a payload to a semaphore adds the semaphore to the set of all semaphores sharing that payload. This set includes the semaphore from which the payload was exported. Semaphore signaling and waiting operations performed on any semaphore in the set must behave as if the set were a single semaphore. Importing a payload using handle types with copy transference creates a duplicate copy of the payload at the time of import, but makes no further reference to it. Semaphore signaling and waiting operations performed on the target of copy imports must not affect any other semaphore or payload.
Export operations have the same transference as the specified handle type’s import operations. Additionally, exporting a semaphore payload to a handle with copy transference has the same side effects on the source semaphore’s payload as executing a semaphore wait operation. If the semaphore was using a temporarily imported payload, the semaphore’s prior permanent payload will be restored.
The permanence and transference of handle types can be found in: |
External synchronization allows
implementations to modify an object’s internal state, i.e. payload, without
internal synchronization.
However, for semaphores sharing a payload across processes, satisfying the
external synchronization requirements of VkSemaphore
parameters as if
all semaphores in the set were the same object is sometimes infeasible.
Satisfying the wait operation state requirements would similarly require impractical coordination or
levels of trust between processes.
Therefore, these constraints only apply to a specific semaphore handle, not
to its payload.
For distinct semaphore objects which share a payload, if the semaphores are
passed to separate queue submission commands concurrently, behavior will be
as if the commands were called in an arbitrary sequential order.
If the wait operation state requirements are violated for the shared payload by a queue submission
command, or if a signal operation is queued for a shared payload that is
already signaled or has a pending signal operation, effects must be limited
to one or more of the following:
-
Returning
VK_ERROR_INITIALIZATION_FAILED
from the command which resulted in the violation. -
Losing the logical device on which the violation occurred immediately or at a future time, resulting in a
VK_ERROR_DEVICE_LOST
error from subsequent commands, including the one causing the violation. -
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 payload becomes undefined, and future operations on semaphores sharing the payload will be subject to these same rules. The semaphore must be destroyed or have its payload replaced by an import operation to again have a well-defined state.
These rules allow processes to synchronize access to shared memory without trusting each other. However, such processes must still be cautious not to use the shared semaphore for more than synchronizing access to the shared memory. For example, a process should not use a shared semaphore as part of an execution dependency chain that, when complete, leads to objects being destroyed, if it does not trust other processes sharing the semaphore payload. |
When a semaphore is using an imported payload, its
VkExportSemaphoreCreateInfo::handleTypes
value is specified when
creating the semaphore from which the payload was exported, rather than
specified when creating the semaphore.
Additionally,
VkExternalSemaphoreProperties::exportFromImportedHandleTypes
restricts which handle types can be exported from such a semaphore based on
the specific handle type used to import the current payload.
Passing a semaphore to vkAcquireNextImageKHR is equivalent to
temporarily importing a semaphore payload to that semaphore.
Because the exportable handle types of an imported semaphore correspond to its current imported payload, and 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 a temporarily imported payload from vkAcquireNextImageKHR. |
When importing a semaphore payload, 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 a valid semaphore 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
valid semaphore state for wait operations rules.
If the external handle provided does not meet these requirements, the
implementation must fail the semaphore payload import operation with the
error code VK_ERROR_INVALID_EXTERNAL_HANDLE
.
In addition, when importing a semaphore payload that is not compatible with
the payload type corresponding to the VkSemaphoreType the semaphore
was created with, the implementation may fail the semaphore payload import
operation with the error code VK_ERROR_INVALID_EXTERNAL_HANDLE
.
As the introduction of the external semaphore handle type
|
To import a semaphore payload from a Windows handle, call:
// Provided by VK_KHR_external_semaphore_win32
VkResult vkImportSemaphoreWin32HandleKHR(
VkDevice device,
const VkImportSemaphoreWin32HandleInfoKHR* pImportSemaphoreWin32HandleInfo);
-
device
is the logical device that created the semaphore. -
pImportSemaphoreWin32HandleInfo
is a pointer to a VkImportSemaphoreWin32HandleInfoKHR structure specifying the semaphore and import parameters.
Importing a semaphore payload 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 CloseHandle
system call when the handle is no
longer needed.
Applications can import the same semaphore payload into multiple instances of Vulkan, into the same instance from which it was exported, and multiple times into a given Vulkan instance.
The VkImportSemaphoreWin32HandleInfoKHR
structure is defined as:
// Provided by VK_KHR_external_semaphore_win32
typedef struct VkImportSemaphoreWin32HandleInfoKHR {
VkStructureType sType;
const void* pNext;
VkSemaphore semaphore;
VkSemaphoreImportFlags flags;
VkExternalSemaphoreHandleTypeFlagBits handleType;
HANDLE handle;
LPCWSTR name;
} VkImportSemaphoreWin32HandleInfoKHR;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
semaphore
is the semaphore into which the payload will be imported. -
flags
is a bitmask of VkSemaphoreImportFlagBits specifying additional parameters for the semaphore payload import operation. -
handleType
is a VkExternalSemaphoreHandleTypeFlagBits value specifying the type ofhandle
. -
handle
isNULL
or the external handle to import. -
name
isNULL
or a null-terminated UTF-16 string naming the underlying synchronization primitive to import.
The handle types supported by handleType
are:
Handle Type | Transference | Permanence Supported |
---|---|---|
|
Reference |
Temporary,Permanent |
|
Reference |
Temporary,Permanent |
|
Reference |
Temporary,Permanent |
To import a semaphore payload from a POSIX file descriptor, call:
// Provided by VK_KHR_external_semaphore_fd
VkResult vkImportSemaphoreFdKHR(
VkDevice device,
const VkImportSemaphoreFdInfoKHR* pImportSemaphoreFdInfo);
-
device
is the logical device that created the semaphore. -
pImportSemaphoreFdInfo
is a pointer to a VkImportSemaphoreFdInfoKHR structure specifying the semaphore and import parameters.
Importing a semaphore payload 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.
Applications can import the same semaphore payload into multiple instances of Vulkan, into the same instance from which it was exported, and multiple times into a given Vulkan instance.
The VkImportSemaphoreFdInfoKHR
structure is defined as:
// Provided by VK_KHR_external_semaphore_fd
typedef struct VkImportSemaphoreFdInfoKHR {
VkStructureType sType;
const void* pNext;
VkSemaphore semaphore;
VkSemaphoreImportFlags flags;
VkExternalSemaphoreHandleTypeFlagBits handleType;
int fd;
} VkImportSemaphoreFdInfoKHR;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
semaphore
is the semaphore into which the payload will be imported. -
flags
is a bitmask of VkSemaphoreImportFlagBits specifying additional parameters for the semaphore payload import operation. -
handleType
is a VkExternalSemaphoreHandleTypeFlagBits value specifying the type offd
. -
fd
is the external handle to import.
The handle types supported by handleType
are:
Handle Type | Transference | Permanence Supported |
---|---|---|
|
Reference |
Temporary,Permanent |
|
Copy |
Temporary |
If handleType
is VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT
,
the special value -1
for fd
is treated like a valid sync file
descriptor referring to an object that has already signaled.
The import operation will succeed and the VkSemaphore
will have a
temporarily imported payload as if a valid file descriptor had been
provided.
This special behavior for importing an invalid sync file descriptor allows
easier interoperability with other system APIs which use the convention that
an invalid sync file descriptor represents work that has already completed
and does not need to be waited for.
It is consistent with the option for implementations to return a |
To import a semaphore payload from a Zircon event handle, call:
// Provided by VK_FUCHSIA_external_semaphore
VkResult vkImportSemaphoreZirconHandleFUCHSIA(
VkDevice device,
const VkImportSemaphoreZirconHandleInfoFUCHSIA* pImportSemaphoreZirconHandleInfo);
-
device
is the logical device that created the semaphore. -
pImportSemaphoreZirconHandleInfo
is a pointer to a VkImportSemaphoreZirconHandleInfoFUCHSIA structure specifying the semaphore and import parameters.
Importing a semaphore payload from a Zircon event handle transfers ownership of the handle from the application to the Vulkan implementation. The application must not perform any operations on the handle after a successful import.
Applications can import the same semaphore payload into multiple instances of Vulkan, into the same instance from which it was exported, and multiple times into a given Vulkan instance.
The VkImportSemaphoreZirconHandleInfoFUCHSIA
structure is defined as:
// Provided by VK_FUCHSIA_external_semaphore
typedef struct VkImportSemaphoreZirconHandleInfoFUCHSIA {
VkStructureType sType;
const void* pNext;
VkSemaphore semaphore;
VkSemaphoreImportFlags flags;
VkExternalSemaphoreHandleTypeFlagBits handleType;
zx_handle_t zirconHandle;
} VkImportSemaphoreZirconHandleInfoFUCHSIA;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
semaphore
is the semaphore into which the payload will be imported. -
flags
is a bitmask of VkSemaphoreImportFlagBits specifying additional parameters for the semaphore payload import operation. -
handleType
is a VkExternalSemaphoreHandleTypeFlagBits value specifying the type ofzirconHandle
. -
zirconHandle
is the external handle to import.
The handle types supported by handleType
are:
Handle Type | Transference | Permanence Supported |
---|---|---|
|
Reference |
Temporary,Permanent |
Bits which can be set in
specifying additional parameters of a semaphore import operation are:
// Provided by VK_VERSION_1_1
typedef enum VkSemaphoreImportFlagBits {
VK_SEMAPHORE_IMPORT_TEMPORARY_BIT = 0x00000001,
// Provided by VK_KHR_external_semaphore
VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT,
} VkSemaphoreImportFlagBits;
or the equivalent
// Provided by VK_KHR_external_semaphore
typedef VkSemaphoreImportFlagBits VkSemaphoreImportFlagBitsKHR;
These bits have the following meanings:
-
VK_SEMAPHORE_IMPORT_TEMPORARY_BIT
specifies that the semaphore payload will be imported only temporarily, as described in Importing Semaphore Payloads, regardless of the permanence ofhandleType
.
// Provided by VK_VERSION_1_1
typedef VkFlags VkSemaphoreImportFlags;
or the equivalent
// Provided by VK_KHR_external_semaphore
typedef VkSemaphoreImportFlags VkSemaphoreImportFlagsKHR;
VkSemaphoreImportFlags
is a bitmask type for setting a mask of zero or
more VkSemaphoreImportFlagBits.
Events
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 must not be used to insert a dependency between commands submitted to different queues. Events have two states - signaled and unsignaled. An application can signal or unsignal an event either on the host or on the device. A device can be made to 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 VkEvent
handles:
// Provided by VK_VERSION_1_0
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkEvent)
To create an event, call:
// Provided by VK_VERSION_1_0
VkResult vkCreateEvent(
VkDevice device,
const VkEventCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkEvent* pEvent);
-
device
is the logical device that creates the event. -
pCreateInfo
is a pointer to a VkEventCreateInfo structure containing information about how the event is to be created. -
pAllocator
controls host memory allocation as described in the Memory Allocation chapter. -
pEvent
is a pointer to a handle in which the resulting event object is returned.
When created, the event object is in the unsignaled state.
The VkEventCreateInfo
structure is defined as:
// Provided by VK_VERSION_1_0
typedef struct VkEventCreateInfo {
VkStructureType sType;
const void* pNext;
VkEventCreateFlags flags;
} VkEventCreateInfo;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
flags
is a bitmask of VkEventCreateFlagBits defining additional creation parameters.
// Provided by VK_VERSION_1_0
typedef enum VkEventCreateFlagBits {
// Provided by VK_VERSION_1_3
VK_EVENT_CREATE_DEVICE_ONLY_BIT = 0x00000001,
// Provided by VK_KHR_synchronization2
VK_EVENT_CREATE_DEVICE_ONLY_BIT_KHR = VK_EVENT_CREATE_DEVICE_ONLY_BIT,
} VkEventCreateFlagBits;
-
VK_EVENT_CREATE_DEVICE_ONLY_BIT
specifies that host event commands will not be used with this event.
// Provided by VK_VERSION_1_0
typedef VkFlags VkEventCreateFlags;
VkEventCreateFlags
is a bitmask type for setting a mask of
VkEventCreateFlagBits.
To destroy an event, call:
// Provided by VK_VERSION_1_0
void vkDestroyEvent(
VkDevice device,
VkEvent event,
const VkAllocationCallbacks* pAllocator);
-
device
is the logical device that destroys the event. -
event
is the handle of the event to destroy. -
pAllocator
controls host memory allocation as described in the Memory Allocation chapter.
To query the state of an event from the host, call:
// Provided by VK_VERSION_1_0
VkResult vkGetEventStatus(
VkDevice device,
VkEvent event);
-
device
is the logical device that owns the event. -
event
is the handle of the event to query.
Upon success, vkGetEventStatus
returns the state of the event object
with the following return codes:
Status | Meaning |
---|---|
|
The event specified by |
|
The event specified by |
If a vkCmdSetEvent
or vkCmdResetEvent
command is in a command
buffer that is in the 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
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.
To set the state of an event to signaled from the host, call:
// Provided by VK_VERSION_1_0
VkResult vkSetEvent(
VkDevice device,
VkEvent event);
-
device
is the logical device that owns the event. -
event
is the event to set.
When vkSetEvent is executed on the host, it defines an event signal operation which sets the event to the signaled state.
If event
is already in the signaled state when vkSetEvent is
executed, then vkSetEvent has no effect, and no event signal operation
occurs.
If a command buffer is waiting for an event to be signaled from the host, the application must signal the event before submitting the command buffer, as described in the queue forward progress section. |
To set the state of an event to unsignaled from the host, call:
// Provided by VK_VERSION_1_0
VkResult vkResetEvent(
VkDevice device,
VkEvent event);
-
device
is the logical device that owns the event. -
event
is the event to reset.
When vkResetEvent is executed on the host, it defines an event unsignal operation which resets the event to the unsignaled state.
If event
is already in the unsignaled state when vkResetEvent is
executed, then vkResetEvent has no effect, and no event unsignal
operation occurs.
The state of an event can also be updated on the device by commands inserted in command buffers.
To signal an event from a device, call:
// Provided by VK_VERSION_1_3
void vkCmdSetEvent2(
VkCommandBuffer commandBuffer,
VkEvent event,
const VkDependencyInfo* pDependencyInfo);
or the equivalent command
// Provided by VK_KHR_synchronization2
void vkCmdSetEvent2KHR(
VkCommandBuffer commandBuffer,
VkEvent event,
const VkDependencyInfo* pDependencyInfo);
-
commandBuffer
is the command buffer into which the command is recorded. -
event
is the event that will be signaled. -
pDependencyInfo
is a pointer to a VkDependencyInfo structure defining the first scopes of this operation.
When vkCmdSetEvent2 is submitted to a queue, it defines the first half
of memory dependencies defined by pDependencyInfo
, as well as an event
signal operation which sets the event to the signaled state.
A memory dependency is defined between the event signal operation and
commands that occur earlier in submission order.
The first synchronization scope and
access scope are defined by
the union of all the memory dependencies defined by pDependencyInfo
,
and are applied to all operations that occur earlier in
submission order.
Queue family ownership transfers and
image layout transitions
defined by pDependencyInfo
are also included in the first scopes.
The second synchronization scope
includes only the event signal operation, and any
queue family ownership transfers and
image layout transitions
defined by pDependencyInfo
.
The second access scope includes only queue family ownership transfers and image layout transitions.
Future vkCmdWaitEvents2 commands rely on all values of each element in
pDependencyInfo
matching exactly with those used to signal the
corresponding event.
vkCmdWaitEvents must not be used to wait on the result of a signal
operation defined by vkCmdSetEvent2
.
The extra information provided by vkCmdSetEvent2 compared to vkCmdSetEvent allows implementations to more efficiently schedule the operations required to satisfy the requested dependencies. With vkCmdSetEvent, the full dependency information is not known until vkCmdWaitEvents is recorded, forcing implementations to insert the required operations at that point and not before. |
If event
is already in the signaled state when vkCmdSetEvent2 is
executed on the device, then vkCmdSetEvent2 has no effect, no event
signal operation occurs, and no dependency is generated.
The VkDependencyInfo
structure is defined as:
// Provided by VK_VERSION_1_3
typedef struct VkDependencyInfo {
VkStructureType sType;
const void* pNext;
VkDependencyFlags dependencyFlags;
uint32_t memoryBarrierCount;
const VkMemoryBarrier2* pMemoryBarriers;
uint32_t bufferMemoryBarrierCount;
const VkBufferMemoryBarrier2* pBufferMemoryBarriers;
uint32_t imageMemoryBarrierCount;
const VkImageMemoryBarrier2* pImageMemoryBarriers;
} VkDependencyInfo;
or the equivalent
// Provided by VK_KHR_synchronization2
typedef VkDependencyInfo VkDependencyInfoKHR;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
dependencyFlags
is a bitmask of VkDependencyFlagBits specifying how execution and memory dependencies are formed. -
memoryBarrierCount
is the length of thepMemoryBarriers
array. -
pMemoryBarriers
is a pointer to an array of VkMemoryBarrier2 structures defining memory dependencies between any memory accesses. -
bufferMemoryBarrierCount
is the length of thepBufferMemoryBarriers
array. -
pBufferMemoryBarriers
is a pointer to an array of VkBufferMemoryBarrier2 structures defining memory dependencies between buffer ranges. -
imageMemoryBarrierCount
is the length of thepImageMemoryBarriers
array. -
pImageMemoryBarriers
is a pointer to an array of VkImageMemoryBarrier2 structures defining memory dependencies between image subresources.
This structure defines a set of memory dependencies, as well as queue family ownership transfer operations and image layout transitions.
Each member of pMemoryBarriers
, pBufferMemoryBarriers
, and
pImageMemoryBarriers
defines a separate
memory dependency.
To set the state of an event to signaled from a device, call:
// Provided by VK_VERSION_1_0
void vkCmdSetEvent(
VkCommandBuffer commandBuffer,
VkEvent event,
VkPipelineStageFlags stageMask);
-
commandBuffer
is the command buffer into which the command is recorded. -
event
is the event that will be signaled. -
stageMask
specifies the source stage mask used to determine the first synchronization scope.
vkCmdSetEvent
behaves identically to vkCmdSetEvent2, except that
it does not define an access scope, and must only be used with
vkCmdWaitEvents, not vkCmdWaitEvents2.
To unsignal the event from a device, call:
// Provided by VK_VERSION_1_3
void vkCmdResetEvent2(
VkCommandBuffer commandBuffer,
VkEvent event,
VkPipelineStageFlags2 stageMask);
or the equivalent command
// Provided by VK_KHR_synchronization2
void vkCmdResetEvent2KHR(
VkCommandBuffer commandBuffer,
VkEvent event,
VkPipelineStageFlags2 stageMask);
-
commandBuffer
is the command buffer into which the command is recorded. -
event
is the event that will be unsignaled. -
stageMask
is a VkPipelineStageFlags2 mask of pipeline stages used to determine the first synchronization scope.
When vkCmdResetEvent2 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 scope
includes all commands that occur earlier in
submission order.
The synchronization scope is limited to operations by stageMask
or
stages that are logically earlier
than stageMask
.
The second synchronization scope includes only the event unsignal operation.
If event
is already in the unsignaled state when
vkCmdResetEvent2 is executed on the device, then this command has no
effect, no event unsignal operation occurs, and no execution dependency is
generated.
To set the state of an event to unsignaled from a device, call:
// Provided by VK_VERSION_1_0
void vkCmdResetEvent(
VkCommandBuffer commandBuffer,
VkEvent event,
VkPipelineStageFlags stageMask);
-
commandBuffer
is the command buffer into which the command is recorded. -
event
is the event that will be unsignaled. -
stageMask
is a bitmask of VkPipelineStageFlagBits specifying the source stage mask used to determine when theevent
is unsignaled.
vkCmdResetEvent
behaves identically to vkCmdResetEvent2.
To wait for one or more events to enter the signaled state on a device, call:
// Provided by VK_VERSION_1_3
void vkCmdWaitEvents2(
VkCommandBuffer commandBuffer,
uint32_t eventCount,
const VkEvent* pEvents,
const VkDependencyInfo* pDependencyInfos);
or the equivalent command
// Provided by VK_KHR_synchronization2
void vkCmdWaitEvents2KHR(
VkCommandBuffer commandBuffer,
uint32_t eventCount,
const VkEvent* pEvents,
const VkDependencyInfo* pDependencyInfos);
-
commandBuffer
is the command buffer into which the command is recorded. -
eventCount
is the length of thepEvents
array. -
pEvents
is a pointer to an array ofeventCount
events to wait on. -
pDependencyInfos
is a pointer to an array ofeventCount
VkDependencyInfo structures, defining the second synchronization scope.
When vkCmdWaitEvents2
is submitted to a queue, it inserts memory
dependencies according to the elements of pDependencyInfos
and each
corresponding element of pEvents
.
vkCmdWaitEvents2
must not be used to wait on event signal operations
occurring on other queues, or signal operations executed by
vkCmdSetEvent.
The first synchronization scope and
access scope of each memory
dependency defined by any element i of pDependencyInfos
are
applied to operations that occurred earlier in
submission order than the last event
signal operation on element i of pEvents
.
Signal operations for an event at index i are only included if:
-
The event was signaled by a vkCmdSetEvent2 command that occurred earlier in submission order with a
dependencyInfo
parameter exactly equal to the element ofpDependencyInfos
at index i ; or -
The event was created without
VK_EVENT_CREATE_DEVICE_ONLY_BIT
, and the first synchronization scope defined by the element ofpDependencyInfos
at index i only includes host operations (VK_PIPELINE_STAGE_2_HOST_BIT
).
The second synchronization scope
and access scope of each
memory dependency defined by any element i of pDependencyInfos
are applied to operations that occurred later in
submission order than
vkCmdWaitEvents2
.
vkCmdWaitEvents2 is used with vkCmdSetEvent2 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. |
Applications should be careful to avoid race conditions when using events.
There is no direct ordering guarantee between |
To wait for one or more events to enter the signaled state on a device, call:
// Provided by VK_VERSION_1_0
void vkCmdWaitEvents(
VkCommandBuffer commandBuffer,
uint32_t eventCount,
const VkEvent* pEvents,
VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
uint32_t memoryBarrierCount,
const VkMemoryBarrier* pMemoryBarriers,
uint32_t bufferMemoryBarrierCount,
const VkBufferMemoryBarrier* pBufferMemoryBarriers,
uint32_t imageMemoryBarrierCount,
const VkImageMemoryBarrier* pImageMemoryBarriers);
-
commandBuffer
is the command buffer into which the command is recorded. -
eventCount
is the length of thepEvents
array. -
pEvents
is a pointer to an array of event object handles to wait on. -
srcStageMask
is a bitmask of VkPipelineStageFlagBits specifying the source stage mask. -
dstStageMask
is a bitmask of VkPipelineStageFlagBits specifying the destination stage mask. -
memoryBarrierCount
is the length of thepMemoryBarriers
array. -
pMemoryBarriers
is a pointer to an array of VkMemoryBarrier structures. -
bufferMemoryBarrierCount
is the length of thepBufferMemoryBarriers
array. -
pBufferMemoryBarriers
is a pointer to an array of VkBufferMemoryBarrier structures. -
imageMemoryBarrierCount
is the length of thepImageMemoryBarriers
array. -
pImageMemoryBarriers
is a pointer to an array of VkImageMemoryBarrier structures.
vkCmdWaitEvents
is largely similar to vkCmdWaitEvents2, but can
only wait on signal operations defined by vkCmdSetEvent.
As vkCmdSetEvent does not define any access scopes,
vkCmdWaitEvents
defines the first access scope for each event signal
operation in addition to its own access scopes.
Since vkCmdSetEvent does not have any dependency information beyond a stage mask, implementations do not have the same opportunity to perform availability and visibility operations or image layout transitions in advance as they do with vkCmdSetEvent2 and vkCmdWaitEvents2. |
When vkCmdWaitEvents
is submitted to a queue, it defines a memory
dependency between prior event signal operations on the same queue or the
host, and subsequent commands.
vkCmdWaitEvents
must not be used to wait on event signal operations
occurring on other queues.
The first synchronization scope only includes event signal operations that
operate on members of pEvents
, and the operations that happened-before
the event signal operations.
Event signal operations performed by vkCmdSetEvent that occur earlier
in submission order are included in the
first synchronization scope, if the logically latest pipeline stage in their stageMask
parameter is
logically earlier than or equal
to the logically latest pipeline
stage in srcStageMask
.
Event signal operations performed by vkSetEvent are only included in
the first synchronization scope if VK_PIPELINE_STAGE_HOST_BIT
is
included in srcStageMask
.
The second synchronization scope
includes all commands that occur later in
submission order.
The second synchronization scope is limited to operations on the pipeline
stages determined by the destination stage mask specified by dstStageMask
.
The first access scope is
limited to accesses in the pipeline stages determined by the
source stage mask specified by
srcStageMask
.
Within that, the first access scope only includes the first access scopes
defined by elements of the pMemoryBarriers
,
pBufferMemoryBarriers
and pImageMemoryBarriers
arrays, which
each define a set of memory barriers.
If no memory barriers are specified, then the first access scope includes no
accesses.
The second access scope is
limited to accesses in the pipeline stages determined by the
destination stage mask specified
by dstStageMask
.
Within that, the second access scope only includes the second access scopes
defined by elements of the pMemoryBarriers
,
pBufferMemoryBarriers
and pImageMemoryBarriers
arrays, which
each define a set of memory barriers.
If no memory barriers are specified, then the second access scope includes
no accesses.
Pipeline Barriers
To record a pipeline barrier, call:
// Provided by VK_VERSION_1_3
void vkCmdPipelineBarrier2(
VkCommandBuffer commandBuffer,
const VkDependencyInfo* pDependencyInfo);
or the equivalent command
// Provided by VK_KHR_synchronization2
void vkCmdPipelineBarrier2KHR(
VkCommandBuffer commandBuffer,
const VkDependencyInfo* pDependencyInfo);
-
commandBuffer
is the command buffer into which the command is recorded. -
pDependencyInfo
is a pointer to a VkDependencyInfo structure defining the scopes of this operation.
When vkCmdPipelineBarrier2 is submitted to a queue, it defines memory dependencies between commands that were submitted to the same queue before it, and those submitted to the same queue after it.
The first synchronization scope and
access scope of each memory
dependency defined by pDependencyInfo
are applied to operations that
occurred earlier in submission order.
The second synchronization scope
and access scope of each
memory dependency defined by pDependencyInfo
are applied to operations
that occurred later in submission order.
If vkCmdPipelineBarrier2
is recorded within a render pass instance,
the synchronization scopes are limited to a subset of operations within the
same subpass or render pass instance.
To record a pipeline barrier, call:
// Provided by VK_VERSION_1_0
void vkCmdPipelineBarrier(
VkCommandBuffer commandBuffer,
VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
VkDependencyFlags dependencyFlags,
uint32_t memoryBarrierCount,
const VkMemoryBarrier* pMemoryBarriers,
uint32_t bufferMemoryBarrierCount,
const VkBufferMemoryBarrier* pBufferMemoryBarriers,
uint32_t imageMemoryBarrierCount,
const VkImageMemoryBarrier* pImageMemoryBarriers);
-
commandBuffer
is the command buffer into which the command is recorded. -
srcStageMask
is a bitmask of VkPipelineStageFlagBits specifying the source stages. -
dstStageMask
is a bitmask of VkPipelineStageFlagBits specifying the destination stages. -
dependencyFlags
is a bitmask of VkDependencyFlagBits specifying how execution and memory dependencies are formed. -
memoryBarrierCount
is the length of thepMemoryBarriers
array. -
pMemoryBarriers
is a pointer to an array of VkMemoryBarrier structures. -
bufferMemoryBarrierCount
is the length of thepBufferMemoryBarriers
array. -
pBufferMemoryBarriers
is a pointer to an array of VkBufferMemoryBarrier structures. -
imageMemoryBarrierCount
is the length of thepImageMemoryBarriers
array. -
pImageMemoryBarriers
is a pointer to an array of VkImageMemoryBarrier structures.
vkCmdPipelineBarrier
operates almost identically to
vkCmdPipelineBarrier2, except that the scopes and barriers are defined
as direct parameters rather than being defined by a VkDependencyInfo.
When vkCmdPipelineBarrier is submitted to a queue, it defines a memory dependency between commands that were submitted to the same queue before it, and those submitted to the same queue after it.
If vkCmdPipelineBarrier was recorded outside a render pass instance,
the first synchronization scope
includes all commands that occur earlier in
submission order.
If vkCmdPipelineBarrier was recorded inside a render pass instance,
the first synchronization scope includes only commands that occur earlier in
submission order within the same
subpass.
In either case, the first synchronization scope is limited to operations on
the pipeline stages determined by the
source stage mask specified by
srcStageMask
.
If vkCmdPipelineBarrier was recorded outside a render pass instance,
the second synchronization scope
includes all commands that occur later in
submission order.
If vkCmdPipelineBarrier was recorded inside a render pass instance,
the second synchronization scope includes only commands that occur later in
submission order within the same
subpass.
In either case, the second synchronization scope is limited to operations on
the pipeline stages determined by the
destination stage mask specified
by dstStageMask
.
The first access scope is
limited to accesses in the pipeline stages determined by the
source stage mask specified by
srcStageMask
.
Within that, the first access scope only includes the first access scopes
defined by elements of the pMemoryBarriers
,
pBufferMemoryBarriers
and pImageMemoryBarriers
arrays, which
each define a set of memory barriers.
If no memory barriers are specified, then the first access scope includes no
accesses.
The second access scope is
limited to accesses in the pipeline stages determined by the
destination stage mask specified
by dstStageMask
.
Within that, the second access scope only includes the second access scopes
defined by elements of the pMemoryBarriers
,
pBufferMemoryBarriers
and pImageMemoryBarriers
arrays, which
each define a set of memory barriers.
If no memory barriers are specified, then the second access scope includes
no accesses.
If dependencyFlags
includes VK_DEPENDENCY_BY_REGION_BIT
, then
any dependency between framebuffer-space pipeline stages is
framebuffer-local - otherwise it is
framebuffer-global.
Bits which can be set in vkCmdPipelineBarrier
::dependencyFlags
,
specifying how execution and memory dependencies are formed, are:
// Provided by VK_VERSION_1_0
typedef enum VkDependencyFlagBits {
VK_DEPENDENCY_BY_REGION_BIT = 0x00000001,
// Provided by VK_VERSION_1_1
VK_DEPENDENCY_DEVICE_GROUP_BIT = 0x00000004,
// Provided by VK_VERSION_1_1
VK_DEPENDENCY_VIEW_LOCAL_BIT = 0x00000002,
// Provided by VK_EXT_attachment_feedback_loop_layout
VK_DEPENDENCY_FEEDBACK_LOOP_BIT_EXT = 0x00000008,
// Provided by VK_KHR_multiview
VK_DEPENDENCY_VIEW_LOCAL_BIT_KHR = VK_DEPENDENCY_VIEW_LOCAL_BIT,
// Provided by VK_KHR_device_group
VK_DEPENDENCY_DEVICE_GROUP_BIT_KHR = VK_DEPENDENCY_DEVICE_GROUP_BIT,
} VkDependencyFlagBits;
-
VK_DEPENDENCY_BY_REGION_BIT
specifies that dependencies will be framebuffer-local. -
VK_DEPENDENCY_VIEW_LOCAL_BIT
specifies that dependencies will be view-local. -
VK_DEPENDENCY_DEVICE_GROUP_BIT
specifies that dependencies are non-device-local. -
VK_DEPENDENCY_FEEDBACK_LOOP_BIT_EXT
specifies that the render pass will write to and read from the same image using theVK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT
layout.
// Provided by VK_VERSION_1_0
typedef VkFlags VkDependencyFlags;
VkDependencyFlags
is a bitmask type for setting a mask of zero or more
VkDependencyFlagBits.
Memory Barriers
Memory barriers are used to explicitly control access to buffer and image subresource ranges. Memory barriers are used to transfer ownership between queue families, change image layouts, and define availability and visibility operations. They explicitly define the access types and buffer and image subresource ranges that are included in the access scopes of a memory dependency that is created by a synchronization command that includes them.
Global Memory Barriers
Global memory barriers apply to memory accesses involving all memory objects that exist at the time of its execution.
The VkMemoryBarrier2
structure is defined as:
// Provided by VK_VERSION_1_3
typedef struct VkMemoryBarrier2 {
VkStructureType sType;
const void* pNext;
VkPipelineStageFlags2 srcStageMask;
VkAccessFlags2 srcAccessMask;
VkPipelineStageFlags2 dstStageMask;
VkAccessFlags2 dstAccessMask;
} VkMemoryBarrier2;
or the equivalent
// Provided by VK_KHR_synchronization2
typedef VkMemoryBarrier2 VkMemoryBarrier2KHR;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
srcStageMask
is a VkPipelineStageFlags2 mask of pipeline stages to be included in the first synchronization scope. -
srcAccessMask
is a VkAccessFlags2 mask of access flags to be included in the first access scope. -
dstStageMask
is a VkPipelineStageFlags2 mask of pipeline stages to be included in the second synchronization scope. -
dstAccessMask
is a VkAccessFlags2 mask of access flags to be included in the second access scope.
This structure defines a memory dependency affecting all device memory.
The first synchronization scope and
access scope described by
this structure include only operations and memory accesses specified by
srcStageMask
and srcAccessMask
.
The second synchronization scope
and access scope described
by this structure include only operations and memory accesses specified by
dstStageMask
and dstAccessMask
.
The VkMemoryBarrier
structure is defined as:
// Provided by VK_VERSION_1_0
typedef struct VkMemoryBarrier {
VkStructureType sType;
const void* pNext;
VkAccessFlags srcAccessMask;
VkAccessFlags dstAccessMask;
} VkMemoryBarrier;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
srcAccessMask
is a bitmask of VkAccessFlagBits specifying a source access mask. -
dstAccessMask
is a bitmask of VkAccessFlagBits specifying a destination access mask.
The first access scope is
limited to access types in the source access mask specified by srcAccessMask
.
The second access scope is
limited to access types in the destination access mask specified by dstAccessMask
.
Buffer Memory Barriers
Buffer memory barriers only apply to memory accesses involving a specific buffer range. That is, a memory dependency formed from a buffer memory barrier is scoped to access via the specified buffer range. Buffer memory barriers can also be used to define a queue family ownership transfer for the specified buffer range.
The VkBufferMemoryBarrier2
structure is defined as:
// Provided by VK_VERSION_1_3
typedef struct VkBufferMemoryBarrier2 {
VkStructureType sType;
const void* pNext;
VkPipelineStageFlags2 srcStageMask;
VkAccessFlags2 srcAccessMask;
VkPipelineStageFlags2 dstStageMask;
VkAccessFlags2 dstAccessMask;
uint32_t srcQueueFamilyIndex;
uint32_t dstQueueFamilyIndex;
VkBuffer buffer;
VkDeviceSize offset;
VkDeviceSize size;
} VkBufferMemoryBarrier2;
or the equivalent
// Provided by VK_KHR_synchronization2
typedef VkBufferMemoryBarrier2 VkBufferMemoryBarrier2KHR;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
srcStageMask
is a VkPipelineStageFlags2 mask of pipeline stages to be included in the first synchronization scope. -
srcAccessMask
is a VkAccessFlags2 mask of access flags to be included in the first access scope. -
dstStageMask
is a VkPipelineStageFlags2 mask of pipeline stages to be included in the second synchronization scope. -
dstAccessMask
is a VkAccessFlags2 mask of access flags to be included in the second access scope. -
srcQueueFamilyIndex
is the source queue family for a queue family ownership transfer. -
dstQueueFamilyIndex
is the destination queue family for a queue family ownership transfer. -
buffer
is a handle to the buffer whose backing memory is affected by the barrier. -
offset
is an offset in bytes into the backing memory forbuffer
; this is relative to the base offset as bound to the buffer (see vkBindBufferMemory). -
size
is a size in bytes of the affected area of backing memory forbuffer
, orVK_WHOLE_SIZE
to use the range fromoffset
to the end of the buffer.
This structure defines a memory dependency limited to a range of a buffer, and can define a queue family ownership transfer operation for that range.
The first synchronization scope and
access scope described by
this structure include only operations and memory accesses specified by
srcStageMask
and srcAccessMask
.
The second synchronization scope
and access scope described
by this structure include only operations and memory accesses specified by
dstStageMask
and dstAccessMask
.
Both access scopes are
limited to only memory accesses to buffer
in the range defined by
offset
and size
.
If buffer
was created with VK_SHARING_MODE_EXCLUSIVE
, and
srcQueueFamilyIndex
is not equal to dstQueueFamilyIndex
, this
memory barrier defines a queue family ownership transfer operation.
When executed on a queue in the family identified by
srcQueueFamilyIndex
, this barrier defines a
queue family release operation
for the specified buffer range, and the second synchronization scope does
not apply to this operation.
When executed on a queue in the family identified by
dstQueueFamilyIndex
, this barrier defines a
queue family acquire operation
for the specified buffer range, and the first synchronization scope does not
apply to this operation.
A queue family ownership transfer operation is also defined if the values are not equal, and either is one
of the special queue family values reserved for external memory ownership
transfers, as described in Queue Family Ownership Transfer.
A queue family release operation is defined when dstQueueFamilyIndex
is one of those
values, and a queue family acquire operation is defined when srcQueueFamilyIndex
is one of
those values.
The VkBufferMemoryBarrier
structure is defined as:
// Provided by VK_VERSION_1_0
typedef struct VkBufferMemoryBarrier {
VkStructureType sType;
const void* pNext;
VkAccessFlags srcAccessMask;
VkAccessFlags dstAccessMask;
uint32_t srcQueueFamilyIndex;
uint32_t dstQueueFamilyIndex;
VkBuffer buffer;
VkDeviceSize offset;
VkDeviceSize size;
} VkBufferMemoryBarrier;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
srcAccessMask
is a bitmask of VkAccessFlagBits specifying a source access mask. -
dstAccessMask
is a bitmask of VkAccessFlagBits specifying a destination access mask. -
srcQueueFamilyIndex
is the source queue family for a queue family ownership transfer. -
dstQueueFamilyIndex
is the destination queue family for a queue family ownership transfer. -
buffer
is a handle to the buffer whose backing memory is affected by the barrier. -
offset
is an offset in bytes into the backing memory forbuffer
; this is relative to the base offset as bound to the buffer (see vkBindBufferMemory). -
size
is a size in bytes of the affected area of backing memory forbuffer
, orVK_WHOLE_SIZE
to use the range fromoffset
to the end of the buffer.
The first access scope is
limited to access to memory through the specified buffer range, via access
types in the source access mask specified
by srcAccessMask
.
If srcAccessMask
includes VK_ACCESS_HOST_WRITE_BIT
, a
memory domain operation is performed where available memory in the host domain is also
made available to the device domain.
The second access scope is
limited to access to memory through the specified buffer range, via access
types in the destination access mask
specified by dstAccessMask
.
If dstAccessMask
includes VK_ACCESS_HOST_WRITE_BIT
or
VK_ACCESS_HOST_READ_BIT
, a
memory domain operation is performed where available memory in the device domain is also
made available to the host domain.
When |
If srcQueueFamilyIndex
is not equal to dstQueueFamilyIndex
, and
srcQueueFamilyIndex
is equal to the current queue family, then the
memory barrier defines a queue family release operation for the specified buffer range, and the second
synchronization scope of the calling command does not apply to this
operation.
If dstQueueFamilyIndex
is not equal to srcQueueFamilyIndex
, and
dstQueueFamilyIndex
is equal to the current queue family, then the
memory barrier defines a queue family acquire operation for the specified buffer range, and the first
synchronization scope of the calling command does not apply to this
operation.
VK_WHOLE_SIZE
is a special value indicating that the entire remaining
length of a buffer following a given offset
should be used.
It can be specified for VkBufferMemoryBarrier::size
and other
structures.
#define VK_WHOLE_SIZE (~0ULL)
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 scoped to access via the specified image subresource range. Image memory barriers can also be used to define image layout transitions or a queue family ownership transfer for the specified image subresource range.
The VkImageMemoryBarrier2
structure is defined as:
// Provided by VK_VERSION_1_3
typedef struct VkImageMemoryBarrier2 {
VkStructureType sType;
const void* pNext;
VkPipelineStageFlags2 srcStageMask;
VkAccessFlags2 srcAccessMask;
VkPipelineStageFlags2 dstStageMask;
VkAccessFlags2 dstAccessMask;
VkImageLayout oldLayout;
VkImageLayout newLayout;
uint32_t srcQueueFamilyIndex;
uint32_t dstQueueFamilyIndex;
VkImage image;
VkImageSubresourceRange subresourceRange;
} VkImageMemoryBarrier2;
or the equivalent
// Provided by VK_KHR_synchronization2
typedef VkImageMemoryBarrier2 VkImageMemoryBarrier2KHR;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
srcStageMask
is a VkPipelineStageFlags2 mask of pipeline stages to be included in the first synchronization scope. -
srcAccessMask
is a VkAccessFlags2 mask of access flags to be included in the first access scope. -
dstStageMask
is a VkPipelineStageFlags2 mask of pipeline stages to be included in the second synchronization scope. -
dstAccessMask
is a VkAccessFlags2 mask of access flags to be included in the second access scope. -
oldLayout
is the old layout in an image layout transition. -
newLayout
is the new layout in an image layout transition. -
srcQueueFamilyIndex
is the source queue family for a queue family ownership transfer. -
dstQueueFamilyIndex
is the destination queue family for a queue family ownership transfer. -
image
is a handle to the image affected by this barrier. -
subresourceRange
describes the image subresource range withinimage
that is affected by this barrier.
This structure defines a memory dependency limited to an image subresource range, and can define a queue family ownership transfer operation and image layout transition for that subresource range.
The first synchronization scope and
access scope described by
this structure include only operations and memory accesses specified by
srcStageMask
and srcAccessMask
.
The second synchronization scope
and access scope described
by this structure include only operations and memory accesses specified by
dstStageMask
and dstAccessMask
.
Both access scopes are
limited to only memory accesses to image
in the subresource range
defined by subresourceRange
.
If image
was created with VK_SHARING_MODE_EXCLUSIVE
, and
srcQueueFamilyIndex
is not equal to dstQueueFamilyIndex
, this
memory barrier defines a queue family ownership transfer operation.
When executed on a queue in the family identified by
srcQueueFamilyIndex
, this barrier defines a
queue family release operation
for the specified image subresource range, and the second synchronization
scope does not apply to this operation.
When executed on a queue in the family identified by
dstQueueFamilyIndex
, this barrier defines a
queue family acquire operation
for the specified image subresource range, and the first synchronization,
the first synchronization scope does not apply to this operation.
A queue family ownership transfer operation is also defined if the values are not equal, and either is one
of the special queue family values reserved for external memory ownership
transfers, as described in Queue Family Ownership Transfer.
A queue family release operation is defined when dstQueueFamilyIndex
is one of those
values, and a queue family acquire operation is defined when srcQueueFamilyIndex
is one of
those values.
If oldLayout
is not equal to newLayout
, then the memory barrier
defines an image layout transition for the specified image subresource range.
If this memory barrier defines a queue family ownership transfer operation, the layout transition is only
executed once between the queues.
When the old and new layout are equal, the layout values are ignored - data is preserved no matter what values are specified, or what layout the image is currently in. |
If image
has a multi-planar format and the image is disjoint, then
including VK_IMAGE_ASPECT_COLOR_BIT
in the aspectMask
member of
subresourceRange
is equivalent to including
VK_IMAGE_ASPECT_PLANE_0_BIT
, VK_IMAGE_ASPECT_PLANE_1_BIT
, and
(for three-plane formats only) VK_IMAGE_ASPECT_PLANE_2_BIT
.
The VkImageMemoryBarrier
structure is defined as:
// Provided by VK_VERSION_1_0
typedef struct VkImageMemoryBarrier {
VkStructureType sType;
const void* pNext;
VkAccessFlags srcAccessMask;
VkAccessFlags dstAccessMask;
VkImageLayout oldLayout;
VkImageLayout newLayout;
uint32_t srcQueueFamilyIndex;
uint32_t dstQueueFamilyIndex;
VkImage image;
VkImageSubresourceRange subresourceRange;
} VkImageMemoryBarrier;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
srcAccessMask
is a bitmask of VkAccessFlagBits specifying a source access mask. -
dstAccessMask
is a bitmask of VkAccessFlagBits specifying a destination access mask. -
oldLayout
is the old layout in an image layout transition. -
newLayout
is the new layout in an image layout transition. -
srcQueueFamilyIndex
is the source queue family for a queue family ownership transfer. -
dstQueueFamilyIndex
is the destination queue family for a queue family ownership transfer. -
image
is a handle to the image affected by this barrier. -
subresourceRange
describes the image subresource range withinimage
that is affected by this barrier.
The first access scope is
limited to access to memory through the specified image subresource range,
via access types in the source access mask
specified by srcAccessMask
.
If srcAccessMask
includes 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 access scope is
limited to access to memory through the specified image subresource range,
via access types in the destination access mask specified by dstAccessMask
.
If dstAccessMask
includes VK_ACCESS_HOST_WRITE_BIT
or
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 srcQueueFamilyIndex
is not equal to dstQueueFamilyIndex
, and
srcQueueFamilyIndex
is equal to the current queue family, then the
memory barrier defines a queue family release operation for the specified image subresource range, and
the second synchronization scope of the calling command does not apply to
this operation.
If dstQueueFamilyIndex
is not equal to srcQueueFamilyIndex
, and
dstQueueFamilyIndex
is equal to the current queue family, then the
memory barrier defines a queue family acquire operation for the specified image subresource range, and
the first synchronization scope of the calling command does not apply to
this operation.
If the synchronization2
feature is not
enabled or oldLayout
is not equal to newLayout
,
oldLayout
and newLayout
define an
image layout transition for
the specified image subresource range.
If the |
If image
has a multi-planar format and the image is disjoint, then
including VK_IMAGE_ASPECT_COLOR_BIT
in the aspectMask
member of
subresourceRange
is equivalent to including
VK_IMAGE_ASPECT_PLANE_0_BIT
, VK_IMAGE_ASPECT_PLANE_1_BIT
, and
(for three-plane formats only) VK_IMAGE_ASPECT_PLANE_2_BIT
.
To facilitate usage of images whose memory is initialized on the host, Vulkan allows image layout transitions to be performed by the host as well, albeit supporting limited layouts.
To perform an image layout transition on the host, call:
// Provided by VK_VERSION_1_4
VkResult vkTransitionImageLayout(
VkDevice device,
uint32_t transitionCount,
const VkHostImageLayoutTransitionInfo* pTransitions);
or the equivalent command
// Provided by VK_EXT_host_image_copy
VkResult vkTransitionImageLayoutEXT(
VkDevice device,
uint32_t transitionCount,
const VkHostImageLayoutTransitionInfo* pTransitions);
-
device
is the device which ownspTransitions
[i].image
. -
transitionCount
is the number of image layout transitions to perform. -
pTransitions
is a pointer to an array of VkHostImageLayoutTransitionInfo structures specifying the image and subresource ranges within them to transition.
The VkHostImageLayoutTransitionInfo
structure is defined as:
// Provided by VK_VERSION_1_4
typedef struct VkHostImageLayoutTransitionInfo {
VkStructureType sType;
const void* pNext;
VkImage image;
VkImageLayout oldLayout;
VkImageLayout newLayout;
VkImageSubresourceRange subresourceRange;
} VkHostImageLayoutTransitionInfo;
or the equivalent
// Provided by VK_EXT_host_image_copy
typedef VkHostImageLayoutTransitionInfo VkHostImageLayoutTransitionInfoEXT;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
image
is a handle to the image affected by this layout transition. -
oldLayout
is the old layout in an image layout transition. -
newLayout
is the new layout in an image layout transition. -
subresourceRange
describes the image subresource range withinimage
that is affected by this layout transition.
vkTransitionImageLayout
does not check whether the device memory
associated with an image is currently in use before performing the layout
transition.
The application must guarantee that any previously submitted command that
reads from or writes to this subresource has completed before the host
performs the layout transition.
The memory of image
is accessed by the host as if coherent.
Image layout transitions performed on the host do not require queue family ownership transfers as the physical layout of the image will not vary between queue families for the layouts supported by this function. |
If the device has written to the image memory, it is not automatically made
available to the host.
Before this command can be called, a memory barrier for this image must
have been issued on the device with the second
synchronization scope including
Because queue submissions automatically make host memory visible to the device, there would not be a need for a memory barrier before using the results of this layout transition on the device. |
Queue Family Ownership Transfer
Resources created with a VkSharingMode of
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.
The special queue family index VK_QUEUE_FAMILY_IGNORED
indicates that
a queue family parameter or member is ignored.
#define VK_QUEUE_FAMILY_IGNORED (~0U)
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 VkSharingMode specified when creating them.
The special queue family index VK_QUEUE_FAMILY_EXTERNAL
represents any
queue external to the resource’s current Vulkan instance, as long as the
queue uses the same underlying
device group or
physical device, and the same driver version as the resource’s
VkDevice, as indicated by
VkPhysicalDeviceIDProperties::deviceUUID
and
VkPhysicalDeviceIDProperties::driverUUID
.
#define VK_QUEUE_FAMILY_EXTERNAL (~1U)
or the equivalent
#define VK_QUEUE_FAMILY_EXTERNAL_KHR VK_QUEUE_FAMILY_EXTERNAL
The special queue family index VK_QUEUE_FAMILY_FOREIGN_EXT
represents
any queue external to the resource’s current Vulkan instance, regardless of
the queue’s underlying physical device or driver version.
This includes, for example, queues for fixed-function image processing
devices, media codec devices, and display devices, as well as all queues
that use the same underlying
device group or
physical device, and the same driver version as the resource’s
VkDevice.
#define VK_QUEUE_FAMILY_FOREIGN_EXT (~2U)
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.
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. |
Applications should expect transfers to/from
|
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.
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
buffer memory barrier (for a
buffer range) or an image memory barrier (for an image subresource range) using a pipeline barrier command,
on a queue from the source queue family.
The srcQueueFamilyIndex
parameter of the barrier must be the source
queue family index, and the dstQueueFamilyIndex
parameter to the
destination queue family index.
dstAccessMask
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.
dstStageMask
is also ignored for such a barrier as defined by
buffer memory ownership transfer and image memory ownership transfer.
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
buffer memory barrier (for a
buffer range) or an image memory barrier (for an image subresource range) using a pipeline barrier command,
on a queue from the destination queue family.
The buffer range or image subresource range specified in an acquire
operation must match exactly that of a previous release operation.
The srcQueueFamilyIndex
parameter of the barrier must be the source
queue family index, and the dstQueueFamilyIndex
parameter to the
destination queue family index.
srcAccessMask
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.
srcStageMask
is also ignored for such a barrier as defined by
buffer memory ownership transfer and image memory ownership transfer.
As the first synchronization scope for an acquire operation is empty there
is no happens-before dependency.
Such a dependency can be introduced by using
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
.
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. |
Since a release and acquire operation does not synchronize with second and
first scopes respectively, the |
If the transfer is via an image memory barrier, and an
image layout transition is
desired, then the values of oldLayout
and newLayout
in the
release operation's memory barrier must be equal to values of
oldLayout
and newLayout
in the acquire operation's 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 srcQueueFamilyIndex
and dstQueueFamilyIndex
are
equal, no ownership transfer is performed, and the barrier operates as if
they were both set to 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 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 a 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.
Because events cannot be used directly for inter-queue synchronization, and because vkCmdSetEvent does not have the queue family index or memory barrier parameters needed by a release operation, the release and acquire operations of a queue family ownership transfer can only be performed using vkCmdPipelineBarrier. |
An acquire operation may have a performance penalty when acquiring
ownership of a subresource range from one of the special queue families
reserved for external memory ownership transfers described above.
The application can reduce the performance penalty in some cases by adding
a VkExternalMemoryAcquireUnmodifiedEXT structure to the pNext
chain of the acquire operation's memory barrier structure.
The VkExternalMemoryAcquireUnmodifiedEXT
structure is defined as:
// Provided by VK_EXT_external_memory_acquire_unmodified
typedef struct VkExternalMemoryAcquireUnmodifiedEXT {
VkStructureType sType;
const void* pNext;
VkBool32 acquireUnmodifiedMemory;
} VkExternalMemoryAcquireUnmodifiedEXT;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
acquireUnmodifiedMemory
specifies, ifVK_TRUE
, that no range of VkDeviceMemory bound to the resource of the memory barrier’s subresource range was modified at any time since the resource’s most recent release of ownership to the queue family specified by the memory barrier’ssrcQueueFamilyIndex
. IfVK_FALSE
, it specifies nothing.
If the application releases ownership of the subresource range to one of the
special queue families reserved for external memory ownership transfers with
a memory barrier structure, and later re-acquires ownership from the same
queue family with a memory barrier structure, and if no range of
VkDeviceMemory bound to the resource was modified at any time between
the release operation and the acquire operation, then the application
should add a VkExternalMemoryAcquireUnmodifiedEXT structure to the
pNext
chain of the acquire operation's memory barrier structure
because this may reduce the performance penalty.
This struct is ignored if acquireUnmodifiedMemory
is VK_FALSE
.
In particular, VK_FALSE
does not specify that memory was modified.
This struct is ignored if the memory barrier’s srcQueueFamilyIndex
is
not a special queue family reserved for external memory ownership transfers.
The method by which the application determines whether memory was modified between the release operation and acquire operation is outside the scope of Vulkan. For any Vulkan operation that accesses a resource, the application must not assume the implementation accesses the resource’s memory as read-only, even for apparently read-only operations such as transfer commands and shader reads. The validity of
VkExternalMemoryAcquireUnmodifiedEXT:: |
Wait Idle Operations
To wait on the host for the completion of outstanding queue operations for a given queue, call:
// Provided by VK_VERSION_1_0
VkResult vkQueueWaitIdle(
VkQueue queue);
-
queue
is the queue on which to wait.
vkQueueWaitIdle
is equivalent to having submitted a valid fence to
every previously executed queue submission command that accepts a fence, then waiting for all of those fences to
signal using vkWaitForFences with an infinite timeout and
waitAll
set to VK_TRUE
.
To wait on the host for the completion of outstanding queue operations for all queues on a given logical device, call:
// Provided by VK_VERSION_1_0
VkResult vkDeviceWaitIdle(
VkDevice device);
-
device
is the logical device to idle.
vkDeviceWaitIdle
is equivalent to calling vkQueueWaitIdle
for
all queues owned by device
.
Host Write Ordering Guarantees
When batches of command buffers are submitted to a queue via a queue submission command, it defines a memory dependency with prior host operations, and execution of command buffers submitted to the queue.
The first synchronization scope includes execution of vkQueueSubmit on the host and anything that happened-before it, as defined by the host memory model.
Some systems allow writes that do not directly integrate with the host
memory model; these have to be synchronized by the application manually.
One example of this is non-temporal store instructions on x86; to ensure
these happen-before submission, applications should call |
The second synchronization scope includes all commands submitted in the same queue submission, and all commands that occur later in submission order.
The first access scope includes all host writes to mappable device memory that are available to the host memory domain.
The second access scope includes all memory access performed by the device.
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 VkDeviceGroupSubmitInfo and VkDeviceGroupBindSparseInfo 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).
Calibrated Timestamps
In order to be able to correlate the time a particular operation took place at on timelines of different time domains (e.g. a device operation vs. a host operation), Vulkan allows querying calibrated timestamps from multiple time domains.
To query calibrated timestamps from a set of time domains, call:
// Provided by VK_KHR_calibrated_timestamps
VkResult vkGetCalibratedTimestampsKHR(
VkDevice device,
uint32_t timestampCount,
const VkCalibratedTimestampInfoKHR* pTimestampInfos,
uint64_t* pTimestamps,
uint64_t* pMaxDeviation);
or the equivalent command
// Provided by VK_EXT_calibrated_timestamps
VkResult vkGetCalibratedTimestampsEXT(
VkDevice device,
uint32_t timestampCount,
const VkCalibratedTimestampInfoKHR* pTimestampInfos,
uint64_t* pTimestamps,
uint64_t* pMaxDeviation);
-
device
is the logical device used to perform the query. -
timestampCount
is the number of timestamps to query. -
pTimestampInfos
is a pointer to an array oftimestampCount
VkCalibratedTimestampInfoKHR structures, describing the time domains the calibrated timestamps should be captured from. -
pTimestamps
is a pointer to an array oftimestampCount
64-bit unsigned integer values in which the requested calibrated timestamp values are returned. -
pMaxDeviation
is a pointer to a 64-bit unsigned integer value in which the strictly positive maximum deviation, in nanoseconds, of the calibrated timestamp values is returned.
The maximum deviation may vary between calls to
|
Calibrated timestamp values can be extrapolated to estimate future coinciding timestamp values, however, depending on the nature of the time domains and other properties of the platform extrapolating values over a sufficiently long period of time may no longer be accurate enough to fit any particular purpose, so applications are expected to re-calibrate the timestamps on a regular basis.
The VkCalibratedTimestampInfoKHR
structure is defined as:
// Provided by VK_KHR_calibrated_timestamps
typedef struct VkCalibratedTimestampInfoKHR {
VkStructureType sType;
const void* pNext;
VkTimeDomainKHR timeDomain;
} VkCalibratedTimestampInfoKHR;
or the equivalent
// Provided by VK_EXT_calibrated_timestamps
typedef VkCalibratedTimestampInfoKHR VkCalibratedTimestampInfoEXT;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
timeDomain
is a VkTimeDomainKHR value specifying the time domain from which the calibrated timestamp value should be returned.
The set of supported time domains consists of:
// Provided by VK_KHR_calibrated_timestamps
typedef enum VkTimeDomainKHR {
VK_TIME_DOMAIN_DEVICE_KHR = 0,
VK_TIME_DOMAIN_CLOCK_MONOTONIC_KHR = 1,
VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR = 2,
VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_KHR = 3,
// Provided by VK_EXT_calibrated_timestamps
VK_TIME_DOMAIN_DEVICE_EXT = VK_TIME_DOMAIN_DEVICE_KHR,
// Provided by VK_EXT_calibrated_timestamps
VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT = VK_TIME_DOMAIN_CLOCK_MONOTONIC_KHR,
// Provided by VK_EXT_calibrated_timestamps
VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT = VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR,
// Provided by VK_EXT_calibrated_timestamps
VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT = VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_KHR,
} VkTimeDomainKHR;
or the equivalent
// Provided by VK_EXT_calibrated_timestamps
typedef VkTimeDomainKHR VkTimeDomainEXT;
-
VK_TIME_DOMAIN_DEVICE_KHR
specifies the device time domain. Timestamp values in this time domain use the same units and are comparable with device timestamp values captured using vkCmdWriteTimestamp or vkCmdWriteTimestamp2 and are defined to be incrementing according to thetimestampPeriod
of the device. -
VK_TIME_DOMAIN_CLOCK_MONOTONIC_KHR
specifies the CLOCK_MONOTONIC time domain available on POSIX platforms. Timestamp values in this time domain are in units of nanoseconds and are comparable with platform timestamp values captured using the POSIX clock_gettime API as computed by this example:
An implementation supporting
|
struct timespec tv;
clock_gettime(CLOCK_MONOTONIC, &tv);
return tv.tv_nsec + tv.tv_sec*1000000000ull;
-
VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR
specifies the CLOCK_MONOTONIC_RAW time domain available on POSIX platforms. Timestamp values in this time domain are in units of nanoseconds and are comparable with platform timestamp values captured using the POSIX clock_gettime API as computed by this example:
struct timespec tv;
clock_gettime(CLOCK_MONOTONIC_RAW, &tv);
return tv.tv_nsec + tv.tv_sec*1000000000ull;
-
VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_KHR
specifies the performance counter (QPC) time domain available on Windows. Timestamp values in this time domain are in the same units as those provided by the Windows QueryPerformanceCounter API and are comparable with platform timestamp values captured using that API as computed by this example:
LARGE_INTEGER counter;
QueryPerformanceCounter(&counter);
return counter.QuadPart;