Resource Descriptors
A descriptor is an opaque data structure representing a shader resource
such as a buffer, buffer view, image view, sampler, or combined image
sampler.
Descriptors are organized into descriptor sets, which are bound during
command recording for use in subsequent drawing commands.
The arrangement of content in each descriptor set is determined by a
descriptor set layout, which determines what descriptors can be stored
within it.
The sequence of descriptor set layouts that can be used by a pipeline is
specified in a pipeline layout.
Each pipeline object can use up to maxBoundDescriptorSets
(see
Limits) descriptor sets.
If the descriptorBuffer
feature is
enabled, the implementation supports placing descriptors into
descriptor buffers which are bound during command
recording in a similar way to descriptor sets.
Shaders access resources via variables decorated with a descriptor set and binding number that link them to a descriptor in a descriptor set. The shader interface mapping to bound descriptor sets is described in the Shader Resource Interface section.
Shaders can also access buffers without going through descriptors by using Physical Storage Buffer Access to access them through 64-bit addresses.
Descriptor Types
There are a number of different types of descriptor supported by Vulkan, corresponding to different resources or usage. The following sections describe the API definitions of each descriptor type. The mapping of each type to SPIR-V is listed in the Shader Resource and Descriptor Type Correspondence and Shader Resource and Storage Class Correspondence tables in the Shader Interfaces chapter.
Storage Image
A storage image (VK_DESCRIPTOR_TYPE_STORAGE_IMAGE
) is a descriptor
type associated with an image resource via an
image view that load, store, and atomic
operations can be performed on.
Storage image loads are supported in all shader stages for image views whose
format features contain
VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT
.
Stores to storage images are supported in
task, mesh and
compute shaders for image views whose
format features contain
VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT
.
Atomic operations on storage images are supported in
task, mesh and
compute shaders for image views whose
format features contain
VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT
.
When the fragmentStoresAndAtomics
feature is enabled, stores and atomic
operations are also supported for storage images in fragment shaders with
the same set of image formats as supported in compute shaders.
When the vertexPipelineStoresAndAtomics
feature is enabled, stores and atomic
operations are also supported in vertex, tessellation, and geometry shaders
with the same set of image formats as supported in compute shaders.
The image subresources for a storage image must be in the
VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR
or
VK_IMAGE_LAYOUT_GENERAL
layout in order to access its data in a
shader.
Sampler
A sampler descriptor (VK_DESCRIPTOR_TYPE_SAMPLER
) is a descriptor
type associated with a sampler object, used to control the
behavior of sampling operations performed on a
sampled image.
Sampled Image
A sampled image (VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE
) is a descriptor
type associated with an image resource via an
image view that sampling operationscan be performed on.
Shaders combine a sampled image variable and a sampler variable to perform sampling operations.
Sampled images are supported in all shader stages for image views whose
format features contain
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT
.
An image subresources for a sampled image must be in one of the following layouts:
VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
VK_IMAGE_LAYOUT_GENERAL
VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR
VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL
VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL
VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL
VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL
VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR
VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT
Combined Image Sampler
A combined image sampler (VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
)
is a single descriptor type associated with both a sampler and
an image resource, combining both a
sampler and sampled image descriptor into a single descriptor.
If the descriptor refers to a sampler that performs Y′CBCR conversion or samples a subsampled image, the sampler must only be used to sample the image in the same descriptor. Otherwise, the sampler and image in this type of descriptor can be used freely with any other samplers and images.
An image subresources for a combined image sampler must be in one of the following layouts:
VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
VK_IMAGE_LAYOUT_GENERAL
VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR
VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL
VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL
VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL
VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL
VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR
VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT
On some implementations, it may be more efficient to sample from an image using a combination of sampler and sampled image that are stored together in the descriptor set in a combined descriptor.
Uniform Texel Buffer
A uniform texel buffer (VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER
) is
a descriptor type associated with a buffer resource
via a buffer view that image sampling
operations can be performed on.
Uniform texel buffers define a tightly-packed 1-dimensional linear array of texels, with texels going through format conversion when read in a shader in the same way as they are for an image.
Load operations from uniform texel buffers are supported in all shader
stages for buffer view formats which report
format features support for
VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT
Storage Texel Buffer
A storage texel buffer (VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER
) is
a descriptor type associated with a buffer resource
via a buffer view that image load,
store, and atomic operations can be performed on.
Storage texel buffers define a tightly-packed 1-dimensional linear array of texels, with texels going through format conversion when read in a shader in the same way as they are for an image. Unlike uniform texel buffers, these buffers can also be written to in the same way as for storage images.
Storage texel buffer loads are supported in all shader stages for texel
buffer view formats which report
format features support for
VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT
Stores to storage texel buffers are supported in
task, mesh and
compute shaders for texel buffer formats which report
format features support for
VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT
Atomic operations on storage texel buffers are supported in
task, mesh and
compute shaders for texel buffer formats which report
format features support for
VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT
When the fragmentStoresAndAtomics
feature is enabled, stores and atomic
operations are also supported for storage texel buffers in fragment shaders
with the same set of texel buffer formats as supported in compute shaders.
When the vertexPipelineStoresAndAtomics
feature is enabled, stores and atomic
operations are also supported in vertex, tessellation, and geometry shaders
with the same set of texel buffer formats as supported in compute shaders.
Storage Buffer
A storage buffer (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER
) is a descriptor
type associated with a buffer resource directly,
described in a shader as a structure with various members that load, store,
and atomic operations can be performed on.
Atomic operations can only be performed on members of certain types as defined in the SPIR-V environment appendix.
Uniform Buffer
A uniform buffer (VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER
) is a descriptor
type associated with a buffer resource directly,
described in a shader as a structure with various members that load
operations can be performed on.
Dynamic Uniform Buffer
A dynamic uniform buffer (VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC
)
is almost identical to a uniform buffer,
and differs only in how the offset into the buffer is specified.
The base offset calculated by the VkDescriptorBufferInfo when
initially updating the descriptor set is added
to a dynamic offset when binding
the descriptor set.
Dynamic Storage Buffer
A dynamic storage buffer (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC
)
is almost identical to a storage buffer,
and differs only in how the offset into the buffer is specified.
The base offset calculated by the VkDescriptorBufferInfo when
initially updating the descriptor set is added
to a dynamic offset when binding
the descriptor set.
Inline Uniform Block
An inline uniform block (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK
) is
almost identical to a uniform buffer, and
differs only in taking its storage directly from the encompassing descriptor
set instead of being backed by buffer memory.
It is typically used to access a small set of constant data that does not
require the additional flexibility provided by the indirection enabled when
using a uniform buffer where the descriptor and the referenced buffer memory
are decoupled.
Compared to push constants, they allow reusing the same set of constant data
across multiple disjoint sets of drawing and dispatching commands.
Inline uniform block descriptors cannot be aggregated into arrays. Instead, the array size specified for an inline uniform block descriptor binding specifies the binding’s capacity in bytes.
Sample Weight Image
A sample weight image (VK_DESCRIPTOR_TYPE_SAMPLE_WEIGHT_IMAGE_QCOM
)
is a descriptor type associated with an image resource
via an image view that can be used in
weight image sampling.
The image view must have been created with
VkImageViewSampleWeightCreateInfoQCOM.
Shaders can combine a weight image variable, a sampled image variable, and a sampler variable to perform weight image sampling.
Weight image sampling is supported in all shader stages if the weight image view specifies a format that supports format feature
VK_FORMAT_FEATURE_2_WEIGHT_IMAGE_BIT_QCOM
and
the sampled image view specifies a format that supports
format feature
VK_FORMAT_FEATURE_2_WEIGHT_SAMPLED_IMAGE_BIT_QCOM
The image subresources for the weight image must be in the
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
, or
VK_IMAGE_LAYOUT_GENERAL
layout in order to access its data in a
shader.
Block Matching Image
A block matching image (VK_DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM
)
is a descriptor type associated with an image resource
via an image view that can be used in
block matching.
Shaders can combine a target image variable, a reference image variable, and a sampler variable to perform block matching.
Block matching is supported in all shader stages for if both the target view and reference view specifies a format that supports format feature
VK_FORMAT_FEATURE_2_BLOCK_MATCHING_BIT_QCOM
The image subresources for block matching must be in the
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
, or
VK_IMAGE_LAYOUT_GENERAL
layout in order to access its data in a
shader.
Input Attachment
An input attachment (VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT
) is a
descriptor type associated with an image resource via
an image view that can be used for
framebuffer local load operations in
fragment shaders.
All image formats that are supported for color attachments
(VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT
or VK_FORMAT_FEATURE_2_LINEAR_COLOR_ATTACHMENT_BIT_NV
) or depth/stencil attachments
(VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT
) for a given image
tiling mode are also supported for input attachments.
An image view used as an input attachment must be in one of the following layouts:
VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
VK_IMAGE_LAYOUT_GENERAL
VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR
VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL
VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL
VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR
VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT
VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR
Acceleration Structure
An acceleration structure (
VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR
or
VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV
) is a descriptor type that is used to retrieve scene geometry from within
shaders that are used for ray traversal.
Shaders have read-only access to the memory.
Mutable
A descriptor of mutable (VK_DESCRIPTOR_TYPE_MUTABLE_EXT
) type
indicates that this descriptor can mutate to any of the descriptor types
given in the VkMutableDescriptorTypeListEXT::pDescriptorTypes
list of descriptor types in the pNext
chain of
VkDescriptorSetLayoutCreateInfo for this binding.
At any point, each individual descriptor of mutable type has an active
descriptor type.
The active descriptor type can be any one of the declared types in
pDescriptorTypes
.
Additionally, a mutable descriptor’s active descriptor type can be of the
VK_DESCRIPTOR_TYPE_MUTABLE_EXT
type, which is the initial active
descriptor type.
The active descriptor type can change when the descriptor is updated.
When a descriptor is consumed by binding a descriptor set, the active
descriptor type is considered, not VK_DESCRIPTOR_TYPE_MUTABLE_EXT
.
An active descriptor type of VK_DESCRIPTOR_TYPE_MUTABLE_EXT
is
considered an undefined: descriptor.
If a descriptor is consumed where the active descriptor type does not match
what the shader expects, the descriptor is considered an undefined:
descriptor.
To find which descriptor types are supported as
VK_DESCRIPTOR_TYPE_MUTABLE_EXT
, the application can use
vkGetDescriptorSetLayoutSupport with a
VK_DESCRIPTOR_TYPE_MUTABLE_EXT
binding, with the list of descriptor
types to query in the
VkMutableDescriptorTypeCreateInfoEXT::pDescriptorTypes
array for
that binding.
The intention of a mutable descriptor type is that implementations allocate N bytes per descriptor, where N is determined by the maximum descriptor size for a given descriptor binding. Implementations are not expected to keep track of the active descriptor type, and it should be considered a C-like union type.
A mutable descriptor type is not considered as efficient in terms of runtime performance as using a non-mutable descriptor type, and applications are not encouraged to use them outside API layering efforts. Mutable descriptor types can be more efficient if the alternative is using many different descriptors to emulate mutable descriptor types.
Descriptor Sets
Descriptors are grouped together into descriptor set objects. A descriptor set object is an opaque object containing storage for a set of descriptors, where the types and number of descriptors is defined by a descriptor set layout. The layout object may be used to define the association of each descriptor binding with memory or other implementation resources. The layout is used both for determining the resources that need to be associated with the descriptor set, and determining the interface between shader stages and shader resources.
Descriptor Set Layout
The following examples show a shader snippet using two descriptor sets, and application code that creates corresponding descriptor set layouts.
GLSL Example
//
// binding to a single sampled image descriptor in set 0
//
layout (set=0, binding=0) uniform texture2D mySampledImage;
//
// binding to an array of sampled image descriptors in set 0
//
layout (set=0, binding=1) uniform texture2D myArrayOfSampledImages[12];
//
// binding to a single uniform buffer descriptor in set 1
//
layout (set=1, binding=0) uniform myUniformBuffer
{
vec4 myElement[32];
};
SPIR-V Example
...
%1 = OpExtInstImport "GLSL.std.450"
...
OpName %9 "mySampledImage"
OpName %14 "myArrayOfSampledImages"
OpName %18 "myUniformBuffer"
OpMemberName %18 0 "myElement"
OpName %20 ""
OpDecorate %9 DescriptorSet 0
OpDecorate %9 Binding 0
OpDecorate %14 DescriptorSet 0
OpDecorate %14 Binding 1
OpDecorate %17 ArrayStride 16
OpMemberDecorate %18 0 Offset 0
OpDecorate %18 Block
OpDecorate %20 DescriptorSet 1
OpDecorate %20 Binding 0
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeFloat 32
%7 = OpTypeImage %6 2D 0 0 0 1 Unknown
%8 = OpTypePointer UniformConstant %7
%9 = OpVariable %8 UniformConstant
%10 = OpTypeInt 32 0
%11 = OpConstant %10 12
%12 = OpTypeArray %7 %11
%13 = OpTypePointer UniformConstant %12
%14 = OpVariable %13 UniformConstant
%15 = OpTypeVector %6 4
%16 = OpConstant %10 32
%17 = OpTypeArray %15 %16
%18 = OpTypeStruct %17
%19 = OpTypePointer Uniform %18
%20 = OpVariable %19 Uniform
...
API Example
VkResult myResult;
const VkDescriptorSetLayoutBinding myDescriptorSetLayoutBinding[] =
{
// binding to a single image descriptor
{
.binding = 0,
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
.descriptorCount = 1,
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
.pImmutableSamplers = NULL
},
// binding to an array of image descriptors
{
.binding = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
.descriptorCount = 12,
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
.pImmutableSamplers = NULL
},
// binding to a single uniform buffer descriptor
{
.binding = 0,
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.descriptorCount = 1,
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
.pImmutableSamplers = NULL
}
};
const VkDescriptorSetLayoutCreateInfo myDescriptorSetLayoutCreateInfo[] =
{
// Information for first descriptor set with two descriptor bindings
{
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
.pNext = NULL,
.flags = 0,
.bindingCount = 2,
.pBindings = &myDescriptorSetLayoutBinding[0]
},
// Information for second descriptor set with one descriptor binding
{
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
.pNext = NULL,
.flags = 0,
.bindingCount = 1,
.pBindings = &myDescriptorSetLayoutBinding[2]
}
};
VkDescriptorSetLayout myDescriptorSetLayout[2];
//
// Create first descriptor set layout
//
myResult = vkCreateDescriptorSetLayout(
myDevice,
&myDescriptorSetLayoutCreateInfo[0],
NULL,
&myDescriptorSetLayout[0]);
//
// Create second descriptor set layout
//
myResult = vkCreateDescriptorSetLayout(
myDevice,
&myDescriptorSetLayoutCreateInfo[1],
NULL,
&myDescriptorSetLayout[1]);
Pipeline Layouts
Once created, pipeline layouts are used as part of pipeline creation (see Pipelines), as part of binding descriptor sets (see Descriptor Set Binding), and as part of setting push constants (see Push Constant Updates). Pipeline creation accepts a pipeline layout as input, and the layout may be used to map (set, binding, arrayElement) tuples to implementation resources or memory locations within a descriptor set. The assignment of implementation resources depends only on the bindings defined in the descriptor sets that comprise the pipeline layout, and not on any shader source.
All resource variables statically used in all shaders
in a pipeline must be declared with a (set, binding, arrayElement) that
exists in the corresponding descriptor set layout and is of an appropriate
descriptor type and includes the set of shader stages it is used by in
stageFlags
.
The pipeline layout can include entries that are not used by a particular
pipeline.
The pipeline layout allows the application to provide a consistent set of
bindings across multiple pipeline compiles, which enables those pipelines to
be compiled in a way that the implementation may cheaply switch pipelines
without reprogramming the bindings.
Similarly, the push constant block declared in each shader (if present)
must only place variables at offsets that are each included in a push
constant range with stageFlags
including the bit corresponding to the
shader stage that uses it.
The pipeline layout can include ranges or portions of ranges that are not
used by a particular pipeline.
There is a limit on the total number of resources of each type that can be
included in bindings in all descriptor set layouts in a pipeline layout as
shown in Pipeline Layout Resource
Limits.
The Total Resources Available
column gives the limit on the number of
each type of resource that can be included in bindings in all descriptor
sets in the pipeline layout.
Some resource types count against multiple limits.
Additionally, there are limits on the total number of each type of resource
that can be used in any pipeline stage as described in
Shader Resource Limits.
Total Resources Available | Resource Types |
---|---|
sampler | |
combined image sampler | |
sampled image | |
combined image sampler | |
uniform texel buffer | |
storage image | |
storage texel buffer | |
uniform buffer | |
uniform buffer dynamic | |
uniform buffer dynamic | |
storage buffer | |
storage buffer dynamic | |
storage buffer dynamic | |
input attachment | |
inline uniform block | |
acceleration structure |
Pipeline Layout Compatibility
Two pipeline layouts are defined to be compatible for
push constants if they were created
with identical push constant ranges.
Two pipeline layouts are defined to be compatible for set N
if they were
created with identically defined descriptor set layouts for sets zero
through N,
if both of them either were or were not created with
VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT
,
and if they were created with identical push constant ranges.
When binding a descriptor set (see Descriptor Set Binding) to set number N, a previously bound descriptor set bound with lower index M than N is disturbed if the pipeline layouts for set M and N are not compatible for set M. Otherwise, the bound descriptor set in M is not disturbed.
If, additionally, the previously bound descriptor set for set N was bound using a pipeline layout not compatible for set N, then all bindings in sets numbered greater than N are disturbed.
When binding a pipeline, the pipeline can correctly access any previously bound descriptor set N if it was bound with compatible pipeline layout for set N, and it was not disturbed.
Layout compatibility means that descriptor sets can be bound to a command buffer for use by any pipeline created with a compatible pipeline layout, and without having bound a particular pipeline first. It also means that descriptor sets can remain valid across a pipeline change, and the same resources will be accessible to the newly bound pipeline.
When a descriptor set is disturbed by binding descriptor sets, the disturbed set is considered to contain undefined: descriptors bound with the same pipeline layout as the disturbing descriptor set.
Place the least frequently changing descriptor sets near the start of the pipeline layout, and place the descriptor sets representing the most frequently changing resources near the end. When pipelines are switched, only the descriptor set bindings that have been invalidated will need to be updated and the remainder of the descriptor set bindings will remain in place.
The maximum number of descriptor sets that can be bound to a pipeline
layout is queried from physical device properties (see
maxBoundDescriptorSets
in Limits).
API Example
const VkDescriptorSetLayout layouts[] = { layout1, layout2 };
const VkPushConstantRange ranges[] =
{
{
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
.offset = 0,
.size = 4
},
{
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
.offset = 4,
.size = 4
},
};
const VkPipelineLayoutCreateInfo createInfo =
{
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
.pNext = NULL,
.flags = 0,
.setLayoutCount = 2,
.pSetLayouts = layouts,
.pushConstantRangeCount = 2,
.pPushConstantRanges = ranges
};
VkPipelineLayout myPipelineLayout;
myResult = vkCreatePipelineLayout(
myDevice,
&createInfo,
NULL,
&myPipelineLayout);
Allocation of Descriptor Sets
Descriptor Set Updates
Descriptor Update Templates
Descriptor Set Updates With Templates
Descriptor Set Binding
Push Descriptor Updates
Push Descriptor Updates With Descriptor Update Templates
Push Constant Updates
As described above in section Pipeline Layouts, the pipeline layout defines shader push constants which are updated via Vulkan commands rather than via writes to memory or copy commands.
Push constants represent a high speed path to modify constant data in pipelines that is expected to outperform memory-backed resource updates.
Physical Storage Buffer Access
Descriptor Buffers
If the descriptorBuffer
feature is
enabled, an alternative way to specify descriptor sets is via buffers,
rather than descriptor set objects.
Putting Descriptors in Memory
Commands are provided to retrieve descriptor data, and also to locate where in memory that data must be written to match the given descriptor set layout.
Immutable samplers specified in a descriptor set layout through
pImmutableSamplers
must be provided by applications when obtaining
descriptor data.
Immutable samplers written in a descriptor buffer must have identical
parameters to the immutable samplers in the descriptor set layout that
consumes the sampler.
If the descriptor set layout was created with
VK_DESCRIPTOR_SET_LAYOUT_CREATE_EMBEDDED_IMMUTABLE_SAMPLERS_BIT_EXT
,
there is no buffer backing for the immutable sampler, so this requirement
does not exist.
The implementation handles allocation of these descriptors internally.
As descriptors are now in regular memory, drivers cannot hide copies of immutable samplers that end up in descriptor sets from the application. As such, applications are required to provide these samplers as if they were not provided immutably.
Binding Descriptor Buffers
Descriptor buffers have their own separate binding point on the command buffer, with buffers bound using vkCmdBindDescriptorBuffersEXT. vkCmdSetDescriptorBufferOffsetsEXT assigns pairs of buffer binding indices and buffer offsets to the same binding point on the command buffer as vkCmdBindDescriptorSets, allowing subsequent bound pipeline commands to use the specified descriptor buffers. Bindings applied via vkCmdBindDescriptorSets cannot exist simultaneously with those applied via calls to vkCmdSetDescriptorBufferOffsetsEXT or vkCmdBindDescriptorBufferEmbeddedSamplersEXT, as calls to vkCmdSetDescriptorBufferOffsetsEXT or vkCmdBindDescriptorBufferEmbeddedSamplersEXT invalidate any bindings by previous calls to vkCmdBindDescriptorSets and vice-versa.
Updating Descriptor Buffers
Updates to descriptor data in buffers can be performed by any operation on either the host or device that can access memory.
Descriptor buffer reads can be synchronized using
VK_ACCESS_2_DESCRIPTOR_BUFFER_READ_BIT_EXT
in the relevant shader
stage.
Push Descriptors With Descriptor Buffers
If the descriptorBufferPushDescriptors
feature is enabled, push descriptors
can be used with descriptor buffers in the same way as with descriptor
sets.
The VkPhysicalDeviceDescriptorBufferPropertiesEXT
::bufferlessPushDescriptors
property indicates whether the implementation requires a buffer to back push
descriptors.
If the property is VK_FALSE
then before recording any push descriptors
the application must bind exactly 1
descriptor buffer that was created
with the VK_BUFFER_USAGE_PUSH_DESCRIPTORS_DESCRIPTOR_BUFFER_BIT_EXT
bit set.
When this buffer is bound any previously recorded push descriptors that are
required for a subsequent command must be recorded again.
Capture and Replay
In a similar way to bufferDeviceAddressCaptureReplay
, the
descriptorBufferCaptureReplay
feature allows the creation of opaque
handles for objects at capture time that can be passed into object creation
calls in a future replay, causing descriptors to be created with the same
data.
The opaque memory address for any memory used by these resources must have
been captured using vkGetDeviceMemoryOpaqueCaptureAddress and be
replayed using VkMemoryOpaqueCaptureAddressAllocateInfo.