A pipeline barrier inserts an execution dependency and a set of memory dependencies between a set of commands earlier in the command buffer and a set of commands later in the command buffer.
To record a pipeline barrier, call:
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 a set of source pipeline stages (see
Section 6.5.2, “Pipeline Stage Flags”).
dstStageMask
is a bitmask specifying a set of destination pipeline
stages.
The pipeline barrier specifies an execution dependency such that all
work performed by the set of pipeline stages included in
srcStageMask
of the first set of commands completes before any
work performed by the set of pipeline stages included in
dstStageMask
of the second set of commands begins.
dependencyFlags
is a bitmask of VkDependencyFlagBits
. The
execution dependency is by-region if the mask includes
VK_DEPENDENCY_BY_REGION_BIT
.
memoryBarrierCount
is the length of the pMemoryBarriers
array.
pMemoryBarriers
is a pointer to an array of VkMemoryBarrier
structures.
bufferMemoryBarrierCount
is the length of the
pBufferMemoryBarriers
array.
pBufferMemoryBarriers
is a pointer to an array of
VkBufferMemoryBarrier
structures.
imageMemoryBarrierCount
is the length of the
pImageMemoryBarriers
array.
pImageMemoryBarriers
is a pointer to an array of
VkImageMemoryBarrier
structures.
Each element of the pMemoryBarriers
, pBufferMemoryBarriers
and
pImageMemoryBarriers
arrays specifies two halves of a memory
dependency, as defined above. Specifics of each type of memory barrier and
the memory access types are defined further in
Memory Barriers.
If vkCmdPipelineBarrier
is called outside a render pass instance, then
the first set of commands is all prior commands submitted to the queue and
recorded in the command buffer and the second set of commands is all
subsequent commands recorded in the command buffer and submitted to the
queue. If vkCmdPipelineBarrier
is called inside a render pass
instance, then the first set of commands is all prior commands in the same
subpass and the second set of commands is all subsequent commands in the
same subpass.
If vkCmdPipelineBarrier
is called inside a render pass instance,
the following restrictions apply. For a given subpass to allow a pipeline
barrier, the render pass must declare a self-dependency from that subpass
to itself. That is, there must exist a VkSubpassDependency
in the
subpass dependency list for the render pass with srcSubpass
and
dstSubpass
equal to that subpass index. More than one self-dependency
can be declared for each subpass. Self-dependencies must only include
pipeline stage bits that are graphics stages. Self-dependencies must not
have any earlier pipeline stages depend on any later pipeline stages. More
precisely, this means that whatever is the last pipeline stage in
srcStageMask
must be no later than whatever is the first pipeline
stage in dstStageMask
(the latest source stage can be equal to the
earliest destination stage). If the source and destination stage masks both
include framebuffer-space stages, then dependencyFlags
must include
VK_DEPENDENCY_BY_REGION_BIT
.
A vkCmdPipelineBarrier
command inside a render pass instance must be
a subset of one of the self-dependencies of the subpass it is used in,
meaning that the stage masks and access masks must each include only a
subset of the bits of the corresponding mask in that self-dependency. If the
self-dependency has VK_DEPENDENCY_BY_REGION_BIT
set, then so must the
pipeline barrier. Pipeline barriers within a render pass instance can only
be types VkMemoryBarrier
or VkImageMemoryBarrier
. If a
VkImageMemoryBarrier
is used, the image and image subresource range
specified in the barrier must be a subset of one of the image views used by
the framebuffer in the current subpass. Additionally, oldLayout
must
be equal to newLayout
, and both the srcQueueFamilyIndex
and
dstQueueFamilyIndex
must be VK_QUEUE_FAMILY_IGNORED
.
Several of the event commands, vkCmdPipelineBarrier
, and
VkSubpassDependency
depend on being able to specify where in the
logical pipeline events can be signaled, or the source and destination of an
execution dependency. These pipeline stages are specified using a bitmask:
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, } VkPipelineStageFlagBits;
The meaning of each bit is:
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT
:
Stage of the pipeline where commands are initially received by the
queue.
VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT
:
Stage of the pipeline where Draw/DispatchIndirect data structures are
consumed.
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT
:
Stage of the pipeline where vertex and index buffers are consumed.
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT
:
Vertex shader stage.
VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT
:
Tessellation control shader stage.
VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT
:
Tessellation evaluation shader stage.
VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT
:
Geometry shader stage.
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
:
Fragment shader stage.
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
:
Stage of the pipeline where early fragment tests (depth and stencil
tests before fragment shading) are performed.
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT
:
Stage of the pipeline where late fragment tests (depth and stencil tests
after fragment shading) are performed.
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
:
Stage of the pipeline after blending where the final color values are
output from the pipeline. This stage also includes resolve operations
that occur at the end of a subpass. Note that this does not necessarily
indicate that the values have been committed to memory.
VK_PIPELINE_STAGE_TRANSFER_BIT
:
Execution of copy commands. This includes the operations resulting from
all transfer commands. The set of transfer commands comprises
vkCmdCopyBuffer
, vkCmdCopyImage
, vkCmdBlitImage
,
vkCmdCopyBufferToImage
, vkCmdCopyImageToBuffer
,
vkCmdUpdateBuffer
, vkCmdFillBuffer
,
vkCmdClearColorImage
, vkCmdClearDepthStencilImage
,
vkCmdResolveImage
, and vkCmdCopyQueryPoolResults
.
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT
:
Execution of a compute shader.
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT
:
Final stage in the pipeline where commands complete execution.
VK_PIPELINE_STAGE_HOST_BIT
:
A pseudo-stage indicating execution on the host of reads/writes of
device memory.
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT
:
Execution of all graphics pipeline stages.
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
:
Execution of all stages supported on the queue.
![]() | Note |
---|---|
The |
![]() | Note |
---|---|
If an implementation is unable to update the state of an event at any specific stage of the pipeline, it may instead update the event at any logically later stage. For example, if an implementation is unable to signal an event immediately after vertex shader execution is complete, it may instead signal the event after color attachment output has completed. In the limit, an event may be signaled after all graphics stages complete. If an implementation is unable to wait on an event at any specific stage of the pipeline, it may instead wait on it at any logically earlier stage. Similarly, if an implementation is unable to implement an execution dependency at specific stages of the pipeline, it may implement the dependency in a way where additional source pipeline stages complete and/or where additional destination pipeline stages' execution is blocked to satisfy the dependency. If an implementation makes such a substitution, it must not affect the semantics of execution or memory dependencies or image and buffer memory barriers. |
Certain pipeline stages are only available on queues that support a particular set of operations. The following table lists, for each pipeline stage flag, which queue capability flag must be supported by the queue. When multiple flags are enumerated in the second column of the table, it means that the pipeline stage is supported on the queue if it supports any of the listed capability flags. For further details on queue capabilities see Physical Device Enumeration and Queues.
Table 6.2. Supported pipeline stage flags
Pipeline stage flag | Required queue capability flag |
---|---|
| None |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| None |
| None |
|
|
| None |
Memory barriers express the two halves of a memory dependency between an earlier set of memory accesses against a later set of memory accesses. Vulkan provides three types of memory barriers: global memory, buffer memory, and image memory.
The global memory barrier type is specified with an instance of the
VkMemoryBarrier
structure. This type of barrier applies to memory
accesses involving all memory objects that exist at the time of its
execution.
The VkMemoryBarrier
structure is defined as:
typedef struct VkMemoryBarrier { VkStructureType sType; const void* pNext; VkAccessFlags srcAccessMask; VkAccessFlags dstAccessMask; } VkMemoryBarrier;
sType
is the type of this structure.
pNext
is NULL
or a pointer to an extension-specific structure.
srcAccessMask
is a bitmask of the classes of memory accesses
performed by the first set of commands that will participate in
the dependency.
dstAccessMask
is a bitmask of the classes of memory accesses
performed by the second set of commands that will participate in
the dependency.
srcAccessMask
and dstAccessMask
, along with srcStageMask
and dstStageMask
from vkCmdPipelineBarrier
, define the two
halves of a memory dependency and an execution dependency. Memory accesses
using the set of access types in srcAccessMask
performed in pipeline
stages in srcStageMask
by the first set of commands must complete and
be available to later commands. The side effects of the first set of
commands will be visible to memory accesses using the set of access types in
dstAccessMask
performed in pipeline stages in dstStageMask
by
the second set of commands. If the barrier is by-region, these requirements
only apply to invocations within the same framebuffer-space region, for
pipeline stages that perform framebuffer-space work. The execution
dependency guarantees that execution of work by the destination stages of
the second set of commands will not begin until execution of work by the
source stages of the first set of commands has completed.
A common type of memory dependency is to avoid a read-after-write hazard. In this case, the source access mask and stages will include writes from a particular stage, and the destination access mask and stages will indicate how those writes will be read in subsequent commands. However, barriers can also express write-after-read dependencies and write-after-write dependencies, and are even useful to express read-after-read dependencies across an image layout change.
Bits which can be set in VkMemoryBarrier
::srcAccessMask
and
VkMemoryBarrier
::dstAccessMask
include:
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, } VkAccessFlagBits;
VK_ACCESS_INDIRECT_COMMAND_READ_BIT
indicates that the access is
an indirect command structure read as part of an indirect drawing
command.
VK_ACCESS_INDEX_READ_BIT
indicates that the access is an index
buffer read.
VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT
indicates that the access is a
read via the vertex input bindings.
VK_ACCESS_UNIFORM_READ_BIT
indicates that the access is a read via
a uniform buffer or dynamic uniform buffer descriptor.
VK_ACCESS_INPUT_ATTACHMENT_READ_BIT
indicates that the access is a
read via an input attachment descriptor.
VK_ACCESS_SHADER_READ_BIT
indicates that the access is a read from
a shader via any other descriptor type.
VK_ACCESS_SHADER_WRITE_BIT
indicates that the access is a write
or atomic from a shader via the same descriptor types as in
VK_ACCESS_SHADER_READ_BIT
.
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
indicates that the access is a
read via a color attachment.
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
indicates that the access is
a write via a color or resolve attachment.
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
indicates that the
access is a read via a depth/stencil attachment.
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT
indicates that the
access is a write via a depth/stencil attachment.
VK_ACCESS_TRANSFER_READ_BIT
indicates that the access is a read
from a transfer (copy, blit, resolve, etc.) operation. For the complete
set of transfer operations, see
VK_PIPELINE_STAGE_TRANSFER_BIT
.
VK_ACCESS_TRANSFER_WRITE_BIT
indicates that the access is a write
from a transfer (copy, blit, resolve, etc.) operation. For the complete
set of transfer operations, see
VK_PIPELINE_STAGE_TRANSFER_BIT
.
VK_ACCESS_HOST_READ_BIT
indicates that the access is a read via
the host.
VK_ACCESS_HOST_WRITE_BIT
indicates that the access is a write via
the host.
VK_ACCESS_MEMORY_READ_BIT
indicates that the access is a read via
a non-specific unit attached to the memory. This unit may be external
to the Vulkan device or otherwise not part of the core Vulkan pipeline.
When included in dstAccessMask
, all writes using access types in
srcAccessMask
performed by pipeline stages in srcStageMask
must be visible in memory.
VK_ACCESS_MEMORY_WRITE_BIT
indicates that the access is a write
via a non-specific unit attached to the memory. This unit may be
external to the Vulkan device or otherwise not part of the core Vulkan
pipeline. When included in srcAccessMask
, all access types in
dstAccessMask
from pipeline stages in dstStageMask
will
observe the side effects of commands that executed before the barrier.
When included in dstAccessMask
all writes using access types in
srcAccessMask
performed by pipeline stages in srcStageMask
must be visible in memory.
Color attachment reads and writes are automatically (without memory or execution dependencies) coherent and ordered against themselves and each other for a given sample within a subpass of a render pass instance, executing in rasterization order. Similarly, depth/stencil attachment reads and writes are automatically coherent and ordered against themselves and each other in the same circumstances.
Shader reads and/or writes through two variables (in the same or different
shader invocations) decorated with Coherent
and which use the same
image view or buffer view are automatically coherent with each other, but
require execution dependencies if a specific order is desired. Similarly,
shader atomic operations are coherent with each other and with Coherent
variables. Non-Coherent
shader memory accesses require memory
dependencies for writes to be available and reads to be visible.
Certain memory access types are only supported on queues that support a particular set of operations. The following table lists, for each access 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 access type 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.
Table 6.3. Supported access flags
Access flag | Required queue capability flag |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| None |
| None |
| None |
| None |
The buffer memory barrier type is specified with an instance of the
VkBufferMemoryBarrier
structure. This type of barrier only applies to
memory accesses involving a specific range of the specified buffer object.
That is, a memory dependency formed from a buffer memory barrier is
scoped to the
specified range of the buffer. It is also used to transfer ownership of a
buffer range from one queue family to another, as described in the
Resource Sharing section.
The VkBufferMemoryBarrier
structure is defined as:
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 the type of this structure.
pNext
is NULL
or a pointer to an extension-specific structure.
srcAccessMask
is a bitmask of the classes of memory accesses
performed by the first set of commands that will participate in
the dependency.
dstAccessMask
is a bitmask of the classes of memory accesses
performed by the second set of commands that will participate in
the dependency.
srcQueueFamilyIndex
is the queue family that is relinquishing
ownership of the range of buffer
to another queue, or
VK_QUEUE_FAMILY_IGNORED
if there is no transfer of ownership.
dstQueueFamilyIndex
is the queue family that is acquiring
ownership of the range of buffer
from another queue, or
VK_QUEUE_FAMILY_IGNORED
if there is no transfer of ownership.
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 for
buffer
; 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 for
buffer
, or VK_WHOLE_SIZE
to use the range from offset
to the end of the buffer.
The image memory barrier type is specified with an instance of the
VkImageMemoryBarrier
structure. This type of barrier only applies to
memory accesses involving a specific image subresource range of the
specified image object. That is, a memory dependency formed from an image
memory barrier is
scoped to the
specified image subresources of the image. It is also used to perform a
layout transition for an image subresource range, or to transfer ownership
of an image subresource range from one queue family to another as described
in the Resource Sharing section.
The VkImageMemoryBarrier
structure is defined as:
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 the type of this structure.
pNext
is NULL
or a pointer to an extension-specific structure.
srcAccessMask
is a bitmask of the classes of memory accesses
performed by the first set of commands that will participate in
the dependency.
dstAccessMask
is a bitmask of the classes of memory accesses
performed by the second set of commands that will participate in
the dependency.
oldLayout
describes the current layout of the image
subresource(s).
newLayout
describes the new layout of the image subresource(s).
srcQueueFamilyIndex
is the queue family that is relinquishing
ownership of the image subresource(s) to another queue, or
VK_QUEUE_FAMILY_IGNORED
if there is no transfer of ownership).
dstQueueFamilyIndex
is the queue family that is acquiring
ownership of the image subresource(s) from another queue, or
VK_QUEUE_FAMILY_IGNORED
if there is no transfer of ownership).
image
is a handle to the image whose backing memory is affected by
the barrier.
subresourceRange
describes an area of the backing memory for
image
(see Section 11.5, “Image Views” for the description of
VkImageSubresourceRange
), as well as the set of image subresources
whose image layouts are modified.
If oldLayout
differs from newLayout
, a layout transition occurs
as part of the image memory barrier, affecting the data contained in the
region of the image defined by the subresourceRange
. If
oldLayout
is VK_IMAGE_LAYOUT_UNDEFINED
, then the data is
undefined after the layout transition. This may allow a more efficient
transition, since the data may be discarded. The layout transition must
occur after all operations using the old layout are completed and before all
operations using the new layout are started. This is achieved by ensuring
that there is a memory dependency between previous accesses and the layout
transition, as well as between the layout transition and subsequent
accesses, where the layout transition occurs between the two halves of a
memory dependency in an image memory barrier.
Layout transitions that are performed via image memory barriers are automatically ordered against other layout transitions, including those that occur as part of a render pass instance.
![]() | Note |
---|---|
See Section 11.4, “Image Layouts” for details on available image layouts and their usages. |
To wait on the host for the completion of outstanding queue operations for a given queue, call:
VkResult vkQueueWaitIdle( VkQueue queue);
queue
is the queue on which to wait.
vkQueueWaitIdle
is equivalent to submitting a fence to a queue and
waiting with an infinite timeout for that fence to signal.
To wait on the host for the completion of outstanding queue operations for all queues on a given logical device, call:
VkResult vkDeviceWaitIdle( VkDevice device);
device
is the logical device to idle.
vkDeviceWaitIdle
is equivalent to calling vkQueueWaitIdle
for
all queues owned by device
.