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 operations
can 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
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
|
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
A descriptor set layout object is defined by an array of zero or more descriptor bindings. Each individual descriptor binding is specified by a descriptor type, a count (array size) of the number of descriptors in the binding, a set of shader stages that can access the binding, and (if using immutable samplers) an array of sampler descriptors.
Descriptor set layout objects are represented by VkDescriptorSetLayout
handles:
// Provided by VK_VERSION_1_0
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorSetLayout)
To create descriptor set layout objects, call:
// Provided by VK_VERSION_1_0
VkResult vkCreateDescriptorSetLayout(
VkDevice device,
const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkDescriptorSetLayout* pSetLayout);
-
device
is the logical device that creates the descriptor set layout. -
pCreateInfo
is a pointer to a VkDescriptorSetLayoutCreateInfo structure specifying the state of the descriptor set layout object. -
pAllocator
controls host memory allocation as described in the Memory Allocation chapter. -
pSetLayout
is a pointer to a VkDescriptorSetLayout handle in which the resulting descriptor set layout object is returned.
Information about the descriptor set layout is passed in a
VkDescriptorSetLayoutCreateInfo
structure:
// Provided by VK_VERSION_1_0
typedef struct VkDescriptorSetLayoutCreateInfo {
VkStructureType sType;
const void* pNext;
VkDescriptorSetLayoutCreateFlags flags;
uint32_t bindingCount;
const VkDescriptorSetLayoutBinding* pBindings;
} VkDescriptorSetLayoutCreateInfo;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
flags
is a bitmask of VkDescriptorSetLayoutCreateFlagBits specifying options for descriptor set layout creation. -
bindingCount
is the number of elements inpBindings
. -
pBindings
is a pointer to an array of VkDescriptorSetLayoutBinding structures.
If the pNext
chain of a VkDescriptorSetLayoutCreateInfo or
VkDescriptorPoolCreateInfo structure includes a
VkMutableDescriptorTypeCreateInfoEXT structure, then that structure
specifies Information about the possible descriptor types for mutable
descriptor types.
The VkMutableDescriptorTypeCreateInfoEXT
structure is defined as:
// Provided by VK_EXT_mutable_descriptor_type
typedef struct VkMutableDescriptorTypeCreateInfoEXT {
VkStructureType sType;
const void* pNext;
uint32_t mutableDescriptorTypeListCount;
const VkMutableDescriptorTypeListEXT* pMutableDescriptorTypeLists;
} VkMutableDescriptorTypeCreateInfoEXT;
or the equivalent
// Provided by VK_VALVE_mutable_descriptor_type
typedef VkMutableDescriptorTypeCreateInfoEXT VkMutableDescriptorTypeCreateInfoVALVE;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
mutableDescriptorTypeListCount
is the number of elements inpMutableDescriptorTypeLists
. -
pMutableDescriptorTypeLists
is a pointer to an array ofVkMutableDescriptorTypeListEXT
structures.
If mutableDescriptorTypeListCount
is zero or if this structure is not
included in the pNext
chain, the VkMutableDescriptorTypeListEXT
for each element is considered to be zero or NULL
for each member.
Otherwise, the descriptor set layout binding at
VkDescriptorSetLayoutCreateInfo::pBindings
[i] uses the
descriptor type lists in
VkMutableDescriptorTypeCreateInfoEXT::pMutableDescriptorTypeLists
[i].
The list of potential descriptor types a given mutable descriptor can
mutate to is passed in a VkMutableDescriptorTypeListEXT
structure.
The VkMutableDescriptorTypeListEXT
structure is defined as:
// Provided by VK_EXT_mutable_descriptor_type
typedef struct VkMutableDescriptorTypeListEXT {
uint32_t descriptorTypeCount;
const VkDescriptorType* pDescriptorTypes;
} VkMutableDescriptorTypeListEXT;
or the equivalent
// Provided by VK_VALVE_mutable_descriptor_type
typedef VkMutableDescriptorTypeListEXT VkMutableDescriptorTypeListVALVE;
-
descriptorTypeCount
is the number of elements inpDescriptorTypes
. -
pDescriptorTypes
isNULL
or a pointer to an array ofdescriptorTypeCount
VkDescriptorType values defining which descriptor types a given binding may mutate to.
Bits which can be set in
VkDescriptorSetLayoutCreateInfo::flags
, specifying options for
descriptor set layout, are:
// Provided by VK_VERSION_1_0
typedef enum VkDescriptorSetLayoutCreateFlagBits {
// Provided by VK_VERSION_1_2
VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT = 0x00000002,
// Provided by VK_VERSION_1_4
VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT = 0x00000001,
// Provided by VK_EXT_descriptor_buffer
VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT = 0x00000010,
// Provided by VK_EXT_descriptor_buffer
VK_DESCRIPTOR_SET_LAYOUT_CREATE_EMBEDDED_IMMUTABLE_SAMPLERS_BIT_EXT = 0x00000020,
// Provided by VK_NV_device_generated_commands_compute
VK_DESCRIPTOR_SET_LAYOUT_CREATE_INDIRECT_BINDABLE_BIT_NV = 0x00000080,
// Provided by VK_EXT_mutable_descriptor_type
VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_EXT = 0x00000004,
// Provided by VK_NV_per_stage_descriptor_set
VK_DESCRIPTOR_SET_LAYOUT_CREATE_PER_STAGE_BIT_NV = 0x00000040,
// Provided by VK_KHR_push_descriptor
VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT,
// Provided by VK_EXT_descriptor_indexing
VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT,
// Provided by VK_VALVE_mutable_descriptor_type
VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_VALVE = VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_EXT,
} VkDescriptorSetLayoutCreateFlagBits;
-
VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT
specifies that descriptor sets must not be allocated using this layout, and descriptors are instead pushed by vkCmdPushDescriptorSet. -
VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT
specifies that descriptor sets using this layout must be allocated from a descriptor pool created with theVK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT
bit set. Descriptor set layouts created with this bit set have alternate limits for the maximum number of descriptors per-stage and per-pipeline layout. The non-UpdateAfterBind limits only count descriptors in sets created without this flag. The UpdateAfterBind limits count all descriptors, but the limits may be higher than the non-UpdateAfterBind limits. -
VK_DESCRIPTOR_SET_LAYOUT_CREATE_INDIRECT_BINDABLE_BIT_NV
specifies that descriptor sets using this layout allows them to be bound with compute pipelines that are created withVK_PIPELINE_CREATE_INDIRECT_BINDABLE_BIT_NV
flag set to be used in Device-Generated Commands. -
VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT
specifies that this layout must only be used with descriptor buffers. -
VK_DESCRIPTOR_SET_LAYOUT_CREATE_EMBEDDED_IMMUTABLE_SAMPLERS_BIT_EXT
specifies that this is a layout only containing immutable samplers that can be bound by vkCmdBindDescriptorBufferEmbeddedSamplersEXT. Unlike normal immutable samplers, embedded immutable samplers do not require the application to provide them in a descriptor buffer. -
VK_DESCRIPTOR_SET_LAYOUT_CREATE_HOST_ONLY_POOL_BIT_EXT
specifies that descriptor sets using this layout must be allocated from a descriptor pool created with theVK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_EXT
bit set. Descriptor set layouts created with this bit have no expressible limit for maximum number of descriptors per-stage. Host descriptor sets are limited only by available host memory, but may be limited for implementation specific reasons. Implementations may limit the number of supported descriptors to UpdateAfterBind limits or non-UpdateAfterBind limits, whichever is larger. -
VK_DESCRIPTOR_SET_LAYOUT_CREATE_PER_STAGE_BIT_NV
specifies that binding numbers in descriptor sets using this layout may represent different resources and/or types of resources in each stage.
// Provided by VK_VERSION_1_0
typedef VkFlags VkDescriptorSetLayoutCreateFlags;
VkDescriptorSetLayoutCreateFlags
is a bitmask type for setting a mask
of zero or more VkDescriptorSetLayoutCreateFlagBits.
The VkDescriptorSetLayoutBinding
structure is defined as:
// Provided by VK_VERSION_1_0
typedef struct VkDescriptorSetLayoutBinding {
uint32_t binding;
VkDescriptorType descriptorType;
uint32_t descriptorCount;
VkShaderStageFlags stageFlags;
const VkSampler* pImmutableSamplers;
} VkDescriptorSetLayoutBinding;
-
binding
is the binding number of this entry and corresponds to a resource of the same binding number in the shader stages. -
descriptorType
is a VkDescriptorType specifying which type of resource descriptors are used for this binding. -
descriptorCount
is the number of descriptors contained in the binding, accessed in a shader as an array, except ifdescriptorType
isVK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK
in which casedescriptorCount
is the size in bytes of the inline uniform block. IfdescriptorCount
is zero this binding entry is reserved and the resource must not be accessed from any stage via this binding within any pipeline using the set layout. -
stageFlags
member is a bitmask of VkShaderStageFlagBits specifying which pipeline shader stages can access a resource for this binding.VK_SHADER_STAGE_ALL
is a shorthand specifying that all defined shader stages, including any additional stages defined by extensions, can access the resource.If a shader stage is not included in
stageFlags
, then a resource must not be accessed from that stage via this binding within any pipeline using the set layout. Other than input attachments which are limited to the fragment shader, there are no limitations on what combinations of stages can use a descriptor binding, and in particular a binding can be used by both graphics stages and the compute stage. -
pImmutableSamplers
affects initialization of samplers. IfdescriptorType
specifies aVK_DESCRIPTOR_TYPE_SAMPLER
orVK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
type descriptor, thenpImmutableSamplers
can be used to initialize a set of immutable samplers. Immutable samplers are permanently bound into the set layout and must not be changed; updating aVK_DESCRIPTOR_TYPE_SAMPLER
descriptor with immutable samplers is not allowed and updates to aVK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
descriptor with immutable samplers does not modify the samplers (the image views are updated, but the sampler updates are ignored). IfpImmutableSamplers
is notNULL
, then it is a pointer to an array of sampler handles that will be copied into the set layout and used for the corresponding binding. Only the sampler handles are copied; the sampler objects must not be destroyed before the final use of the set layout and any descriptor pools and sets created using it. IfpImmutableSamplers
isNULL
, then the sampler slots are dynamic and sampler handles must be bound into descriptor sets using this layout. IfdescriptorType
is not one of these descriptor types, thenpImmutableSamplers
is ignored.
The above layout definition allows the descriptor bindings to be specified
sparsely such that not all binding numbers between 0 and the maximum binding
number need to be specified in the pBindings
array.
Bindings that are not specified have a descriptorCount
and
stageFlags
of zero, and the value of descriptorType
is
undefined.
However, all binding numbers between 0 and the maximum binding number in the
VkDescriptorSetLayoutCreateInfo::pBindings
array may consume
memory in the descriptor set layout even if not all descriptor bindings are
used, though it should not consume additional memory from the descriptor
pool.
The maximum binding number specified should be as compact as possible to avoid wasted memory. |
If the pNext
chain of a VkDescriptorSetLayoutCreateInfo
structure includes a VkDescriptorSetLayoutBindingFlagsCreateInfo
structure, then that structure includes an array of flags, one for each
descriptor set layout binding.
The VkDescriptorSetLayoutBindingFlagsCreateInfo structure is defined as:
// Provided by VK_VERSION_1_2
typedef struct VkDescriptorSetLayoutBindingFlagsCreateInfo {
VkStructureType sType;
const void* pNext;
uint32_t bindingCount;
const VkDescriptorBindingFlags* pBindingFlags;
} VkDescriptorSetLayoutBindingFlagsCreateInfo;
or the equivalent
// Provided by VK_EXT_descriptor_indexing
typedef VkDescriptorSetLayoutBindingFlagsCreateInfo VkDescriptorSetLayoutBindingFlagsCreateInfoEXT;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
bindingCount
is zero or the number of elements inpBindingFlags
. -
pBindingFlags
is a pointer to an array of VkDescriptorBindingFlags bitfields, one for each descriptor set layout binding.
If bindingCount
is zero or if this structure is not included in the
pNext
chain, the VkDescriptorBindingFlags for each descriptor
set layout binding is considered to be zero.
Otherwise, the descriptor set layout binding at
VkDescriptorSetLayoutCreateInfo::pBindings
[i] uses the flags in
pBindingFlags
[i].
Bits which can be set in each element of
VkDescriptorSetLayoutBindingFlagsCreateInfo::pBindingFlags
,
specifying options for the corresponding descriptor set layout binding, are:
// Provided by VK_VERSION_1_2
typedef enum VkDescriptorBindingFlagBits {
VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT = 0x00000001,
VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT = 0x00000002,
VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT = 0x00000004,
VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT = 0x00000008,
// Provided by VK_EXT_descriptor_indexing
VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT = VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT,
// Provided by VK_EXT_descriptor_indexing
VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT = VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT,
// Provided by VK_EXT_descriptor_indexing
VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT = VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT,
// Provided by VK_EXT_descriptor_indexing
VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT = VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT,
} VkDescriptorBindingFlagBits;
or the equivalent
// Provided by VK_EXT_descriptor_indexing
typedef VkDescriptorBindingFlagBits VkDescriptorBindingFlagBitsEXT;
-
VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT
specifies that if descriptors in this binding are updated between when the descriptor set is bound in a command buffer and when that command buffer is submitted to a queue, then the submission will use the most recently set descriptors for this binding and the updates do not invalidate the command buffer. Descriptor bindings created with this flag are also partially exempt from the external synchronization requirement in vkUpdateDescriptorSetWithTemplateKHR and vkUpdateDescriptorSets. Multiple descriptors with this flag set can be updated concurrently in different threads, though the same descriptor must not be updated concurrently by two threads. Descriptors with this flag set can be updated concurrently with the set being bound to a command buffer in another thread, but not concurrently with the set being reset or freed. -
VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT
specifies that descriptors in this binding that are not dynamically used need not contain valid descriptors at the time the descriptors are consumed. A descriptor is dynamically used if any shader invocation executes an instruction that performs any memory access using the descriptor. If a descriptor is not dynamically used, any resource referenced by the descriptor is not considered to be referenced during command execution. -
VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT
specifies that descriptors in this binding can be updated after a command buffer has bound this descriptor set, or while a command buffer that uses this descriptor set is pending execution, as long as the descriptors that are updated are not used by those command buffers. Descriptor bindings created with this flag are also partially exempt from the external synchronization requirement in vkUpdateDescriptorSetWithTemplateKHR and vkUpdateDescriptorSets in the same way as forVK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT
. IfVK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT
is also set, then descriptors can be updated as long as they are not dynamically used by any shader invocations. IfVK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT
is not set, then descriptors can be updated as long as they are not statically used by any shader invocations. -
VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT
specifies that this is a variable-sized descriptor binding whose size will be specified when a descriptor set is allocated using this layout. The value ofdescriptorCount
is treated as an upper bound on the size of the binding. This must only be used for the last binding in the descriptor set layout (i.e. the binding with the largest value ofbinding
). For the purposes of counting against limits such asmaxDescriptorSet
* andmaxPerStageDescriptor
*, the full value ofdescriptorCount
is counted, except for descriptor bindings with a descriptor type ofVK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK
, when VkDescriptorSetLayoutCreateInfo::flags
does not containVK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT
. In this case,descriptorCount
specifies the upper bound on the byte size of the binding; thus it counts against themaxInlineUniformBlockSize
andmaxInlineUniformTotalSize
limits instead.
Note that while |
// Provided by VK_VERSION_1_2
typedef VkFlags VkDescriptorBindingFlags;
or the equivalent
// Provided by VK_EXT_descriptor_indexing
typedef VkDescriptorBindingFlags VkDescriptorBindingFlagsEXT;
VkDescriptorBindingFlags
is a bitmask type for setting a mask of zero
or more VkDescriptorBindingFlagBits.
To query information about whether a descriptor set layout can be created, call:
// Provided by VK_VERSION_1_1
void vkGetDescriptorSetLayoutSupport(
VkDevice device,
const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
VkDescriptorSetLayoutSupport* pSupport);
or the equivalent command
// Provided by VK_KHR_maintenance3
void vkGetDescriptorSetLayoutSupportKHR(
VkDevice device,
const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
VkDescriptorSetLayoutSupport* pSupport);
-
device
is the logical device that would create the descriptor set layout. -
pCreateInfo
is a pointer to a VkDescriptorSetLayoutCreateInfo structure specifying the state of the descriptor set layout object. -
pSupport
is a pointer to a VkDescriptorSetLayoutSupport structure, in which information about support for the descriptor set layout object is returned.
Some implementations have limitations on what fits in a descriptor set which
are not easily expressible in terms of existing limits like
maxDescriptorSet
*, for example if all descriptor types share a limited
space in memory but each descriptor is a different size or alignment.
This command returns information about whether a descriptor set satisfies
this limit.
If the descriptor set layout satisfies the
VkPhysicalDeviceMaintenance3Properties::maxPerSetDescriptors
limit, this command is guaranteed to return VK_TRUE
in
VkDescriptorSetLayoutSupport::supported
.
If the descriptor set layout exceeds the
VkPhysicalDeviceMaintenance3Properties::maxPerSetDescriptors
limit, whether the descriptor set layout is supported is
implementation-dependent and may depend on whether the descriptor sizes and
alignments cause the layout to exceed an internal limit.
This command does not consider other limits such as
maxPerStageDescriptor
*, and so a descriptor set layout that is
supported according to this command must still satisfy the pipeline layout
limits such as maxPerStageDescriptor
* in order to be used in a
pipeline layout.
This is a |
Information about support for the descriptor set layout is returned in a
VkDescriptorSetLayoutSupport
structure:
// Provided by VK_VERSION_1_1
typedef struct VkDescriptorSetLayoutSupport {
VkStructureType sType;
void* pNext;
VkBool32 supported;
} VkDescriptorSetLayoutSupport;
or the equivalent
// Provided by VK_KHR_maintenance3
typedef VkDescriptorSetLayoutSupport VkDescriptorSetLayoutSupportKHR;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
supported
specifies whether the descriptor set layout can be created.
supported
will be VK_TRUE
if the descriptor set can be created,
or else VK_FALSE
.
If the pNext
chain of a VkDescriptorSetLayoutSupport structure
includes a VkDescriptorSetVariableDescriptorCountLayoutSupport
structure, then that structure returns additional information about whether
the descriptor set layout is supported.
// Provided by VK_VERSION_1_2
typedef struct VkDescriptorSetVariableDescriptorCountLayoutSupport {
VkStructureType sType;
void* pNext;
uint32_t maxVariableDescriptorCount;
} VkDescriptorSetVariableDescriptorCountLayoutSupport;
or the equivalent
// Provided by VK_EXT_descriptor_indexing
typedef VkDescriptorSetVariableDescriptorCountLayoutSupport VkDescriptorSetVariableDescriptorCountLayoutSupportEXT;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
maxVariableDescriptorCount
indicates the maximum number of descriptors supported in the highest numbered binding of the layout, if that binding is variable-sized. If the highest numbered binding of the layout has a descriptor type ofVK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK
thenmaxVariableDescriptorCount
indicates the maximum byte size supported for the binding, if that binding is variable-sized.
If the VkDescriptorSetLayoutCreateInfo structure specified in
vkGetDescriptorSetLayoutSupport::pCreateInfo
includes a
variable-sized descriptor, then supported
is determined assuming the
requested size of the variable-sized descriptor, and
maxVariableDescriptorCount
is the maximum size of that descriptor that
can be successfully created (which is greater than or equal to the
requested size passed in).
If the VkDescriptorSetLayoutCreateInfo structure does not include a
variable-sized descriptor, or if the
VkPhysicalDeviceDescriptorIndexingFeatures::descriptorBindingVariableDescriptorCount
feature is not enabled, then maxVariableDescriptorCount
is zero.
For the purposes of this command, a variable-sized descriptor binding with a
descriptorCount
of zero is treated as having a descriptorCount
of
four if descriptorType
is
VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK
, or one otherwise,
and thus the binding is not ignored and the maximum descriptor count will be
returned.
If the layout is not supported, then the value written to
maxVariableDescriptorCount
is undefined.
The following examples show a shader snippet using two descriptor sets, and application code that creates corresponding descriptor set layouts.
//
// 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];
};
...
%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
...
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]);
To destroy a descriptor set layout, call:
// Provided by VK_VERSION_1_0
void vkDestroyDescriptorSetLayout(
VkDevice device,
VkDescriptorSetLayout descriptorSetLayout,
const VkAllocationCallbacks* pAllocator);
-
device
is the logical device that destroys the descriptor set layout. -
descriptorSetLayout
is the descriptor set layout to destroy. -
pAllocator
controls host memory allocation as described in the Memory Allocation chapter.
Pipeline Layouts
Access to descriptor sets from a pipeline is accomplished through a pipeline layout. Zero or more descriptor set layouts and zero or more push constant ranges are combined to form a pipeline layout object describing the complete set of resources that can be accessed by a pipeline. The pipeline layout represents a sequence of descriptor sets with each having a specific layout. This sequence of layouts is used to determine the interface between shader stages and shader resources. Each pipeline is created using a pipeline layout.
Pipeline layout objects are represented by VkPipelineLayout
handles:
// Provided by VK_VERSION_1_0
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipelineLayout)
To create a pipeline layout, call:
// Provided by VK_VERSION_1_0
VkResult vkCreatePipelineLayout(
VkDevice device,
const VkPipelineLayoutCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkPipelineLayout* pPipelineLayout);
-
device
is the logical device that creates the pipeline layout. -
pCreateInfo
is a pointer to a VkPipelineLayoutCreateInfo structure specifying the state of the pipeline layout object. -
pAllocator
controls host memory allocation as described in the Memory Allocation chapter. -
pPipelineLayout
is a pointer to a VkPipelineLayout handle in which the resulting pipeline layout object is returned.
The VkPipelineLayoutCreateInfo structure is defined as:
// Provided by VK_VERSION_1_0
typedef struct VkPipelineLayoutCreateInfo {
VkStructureType sType;
const void* pNext;
VkPipelineLayoutCreateFlags flags;
uint32_t setLayoutCount;
const VkDescriptorSetLayout* pSetLayouts;
uint32_t pushConstantRangeCount;
const VkPushConstantRange* pPushConstantRanges;
} VkPipelineLayoutCreateInfo;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
flags
is a bitmask of VkPipelineLayoutCreateFlagBits specifying options for pipeline layout creation. -
setLayoutCount
is the number of descriptor sets included in the pipeline layout. -
pSetLayouts
is a pointer to an array ofVkDescriptorSetLayout
objects. -
pushConstantRangeCount
is the number of push constant ranges included in the pipeline layout. -
pPushConstantRanges
is a pointer to an array ofVkPushConstantRange
structures defining a set of push constant ranges for use in a single pipeline layout. In addition to descriptor set layouts, a pipeline layout also describes how many push constants can be accessed by each stage of the pipeline.Push constants represent a high speed path to modify constant data in pipelines that is expected to outperform memory-backed resource updates.
// Provided by VK_EXT_graphics_pipeline_library
typedef enum VkPipelineLayoutCreateFlagBits {
// Provided by VK_EXT_graphics_pipeline_library
VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT = 0x00000002,
} VkPipelineLayoutCreateFlagBits;
-
VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT
specifies that implementations must ensure that the properties and/or absence of a particular descriptor set do not influence any other properties of the pipeline layout. This allows pipelines libraries linked withoutVK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT
to be created with a subset of the total descriptor sets.
// Provided by VK_VERSION_1_0
typedef VkFlags VkPipelineLayoutCreateFlags;
VkPipelineLayoutCreateFlags
is a bitmask type for setting a mask of
VkPipelineLayoutCreateFlagBits.
The VkPushConstantRange
structure is defined as:
// Provided by VK_VERSION_1_0
typedef struct VkPushConstantRange {
VkShaderStageFlags stageFlags;
uint32_t offset;
uint32_t size;
} VkPushConstantRange;
-
stageFlags
is a set of stage flags describing the shader stages that will access a range of push constants. If a particular stage is not included in the range, then accessing members of that range of push constants from the corresponding shader stage will return undefined values. -
offset
andsize
are the start offset and size, respectively, consumed by the range. Bothoffset
andsize
are in units of bytes and must be a multiple of 4. The layout of the push constant variables is specified in the shader.
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 |
To destroy a pipeline layout, call:
// Provided by VK_VERSION_1_0
void vkDestroyPipelineLayout(
VkDevice device,
VkPipelineLayout pipelineLayout,
const VkAllocationCallbacks* pAllocator);
-
device
is the logical device that destroys the pipeline layout. -
pipelineLayout
is the pipeline layout to destroy. -
pAllocator
controls host memory allocation as described in the Memory Allocation chapter.
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).
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
A descriptor pool maintains a pool of descriptors, from which descriptor sets are allocated. Descriptor pools are externally synchronized, meaning that the application must not allocate and/or free descriptor sets from the same pool in multiple threads simultaneously.
Descriptor pools are represented by VkDescriptorPool
handles:
// Provided by VK_VERSION_1_0
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorPool)
To create a descriptor pool object, call:
// Provided by VK_VERSION_1_0
VkResult vkCreateDescriptorPool(
VkDevice device,
const VkDescriptorPoolCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkDescriptorPool* pDescriptorPool);
-
device
is the logical device that creates the descriptor pool. -
pCreateInfo
is a pointer to a VkDescriptorPoolCreateInfo structure specifying the state of the descriptor pool object. -
pAllocator
controls host memory allocation as described in the Memory Allocation chapter. -
pDescriptorPool
is a pointer to a VkDescriptorPool handle in which the resulting descriptor pool object is returned.
The created descriptor pool is returned in pDescriptorPool
.
Additional information about the pool is passed in a
VkDescriptorPoolCreateInfo
structure:
// Provided by VK_VERSION_1_0
typedef struct VkDescriptorPoolCreateInfo {
VkStructureType sType;
const void* pNext;
VkDescriptorPoolCreateFlags flags;
uint32_t maxSets;
uint32_t poolSizeCount;
const VkDescriptorPoolSize* pPoolSizes;
} VkDescriptorPoolCreateInfo;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
flags
is a bitmask of VkDescriptorPoolCreateFlagBits specifying certain supported operations on the pool. -
maxSets
is the maximum number of descriptor sets that can be allocated from the pool. -
poolSizeCount
is the number of elements inpPoolSizes
. -
pPoolSizes
is a pointer to an array of VkDescriptorPoolSize structures, each containing a descriptor type and number of descriptors of that type to be allocated in the pool.
If multiple VkDescriptorPoolSize
structures containing the same
descriptor type appear in the pPoolSizes
array then the pool will be
created with enough storage for the total number of descriptors of each
type.
Fragmentation of a descriptor pool is possible and may lead to descriptor set allocation failures. A failure due to fragmentation is defined as failing a descriptor set allocation despite the sum of all outstanding descriptor set allocations from the pool plus the requested allocation requiring no more than the total number of descriptors requested at pool creation. Implementations provide certain guarantees of when fragmentation must not cause allocation failure, as described below.
If a descriptor pool has not had any descriptor sets freed since it was
created or most recently reset then fragmentation must not cause an
allocation failure (note that this is always the case for a pool created
without the VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT
bit
set).
Additionally, if all sets allocated from the pool since it was created or
most recently reset use the same number of descriptors (of each type) and
the requested allocation also uses that same number of descriptors (of each
type), then fragmentation must not cause an allocation failure.
If an allocation failure occurs due to fragmentation, an application can create an additional descriptor pool to perform further descriptor set allocations.
If flags
has the VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT
bit set, descriptor pool creation may fail with the error
VK_ERROR_FRAGMENTATION
if the total number of descriptors across all
pools (including this one) created with this bit set exceeds
maxUpdateAfterBindDescriptorsInAllPools
, or if fragmentation of the
underlying hardware resources occurs.
If a pPoolSizes
[i]::type
is
VK_DESCRIPTOR_TYPE_MUTABLE_EXT
, a
VkMutableDescriptorTypeCreateInfoEXT struct in the pNext
chain
can be used to specify which mutable descriptor types can be allocated
from the pool.
If included in the pNext
chain,
VkMutableDescriptorTypeCreateInfoEXT::pMutableDescriptorTypeLists
[i]
specifies which kind of VK_DESCRIPTOR_TYPE_MUTABLE_EXT
descriptors
can be allocated from this pool entry.
If VkMutableDescriptorTypeCreateInfoEXT does not exist in the
pNext
chain, or
VkMutableDescriptorTypeCreateInfoEXT::pMutableDescriptorTypeLists
[i]
is out of range, the descriptor pool allocates enough memory to be able to
allocate a VK_DESCRIPTOR_TYPE_MUTABLE_EXT
descriptor with any
supported VkDescriptorType as a mutable descriptor.
A mutable descriptor can be allocated from a pool entry if the type list in
VkDescriptorSetLayoutCreateInfo is a subset of the type list declared
in the descriptor pool, or if the pool entry is created without a descriptor
type list.
Multiple pPoolSizes
entries with VK_DESCRIPTOR_TYPE_MUTABLE_EXT
can be declared.
When multiple such pool entries are present in pPoolSizes
, they
specify sets of supported descriptor types which either fully overlap,
partially overlap, or are disjoint.
Two sets fully overlap if the sets of supported descriptor types are equal.
If the sets are not disjoint they partially overlap.
A pool entry without a VkMutableDescriptorTypeListEXT
assigned to it
is considered to partially overlap any other pool entry which has a
VkMutableDescriptorTypeListEXT
assigned to it.
The application must ensure that partial overlap does not exist in
pPoolSizes
.
The requirement of no partial overlap is intended to resolve ambiguity for
validation as there is no confusion which |
In order to be able to allocate descriptor sets having
inline uniform block bindings the
descriptor pool must be created with specifying the inline uniform block
binding capacity of the descriptor pool, in addition to the total inline
uniform data capacity in bytes which is specified through a
VkDescriptorPoolSize structure with a descriptorType
value of
VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK
.
This can be done by adding a
VkDescriptorPoolInlineUniformBlockCreateInfo
structure to the
pNext
chain of VkDescriptorPoolCreateInfo.
The VkDescriptorPoolInlineUniformBlockCreateInfo
structure is defined
as:
// Provided by VK_VERSION_1_3
typedef struct VkDescriptorPoolInlineUniformBlockCreateInfo {
VkStructureType sType;
const void* pNext;
uint32_t maxInlineUniformBlockBindings;
} VkDescriptorPoolInlineUniformBlockCreateInfo;
or the equivalent
// Provided by VK_EXT_inline_uniform_block
typedef VkDescriptorPoolInlineUniformBlockCreateInfo VkDescriptorPoolInlineUniformBlockCreateInfoEXT;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
maxInlineUniformBlockBindings
is the number of inline uniform block bindings to allocate.
Bits which can be set in VkDescriptorPoolCreateInfo::flags
,
enabling operations on a descriptor pool, are:
// Provided by VK_VERSION_1_0
typedef enum VkDescriptorPoolCreateFlagBits {
VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT = 0x00000001,
// Provided by VK_VERSION_1_2
VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT = 0x00000002,
// Provided by VK_EXT_mutable_descriptor_type
VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_EXT = 0x00000004,
// Provided by VK_NV_descriptor_pool_overallocation
VK_DESCRIPTOR_POOL_CREATE_ALLOW_OVERALLOCATION_SETS_BIT_NV = 0x00000008,
// Provided by VK_NV_descriptor_pool_overallocation
VK_DESCRIPTOR_POOL_CREATE_ALLOW_OVERALLOCATION_POOLS_BIT_NV = 0x00000010,
// Provided by VK_EXT_descriptor_indexing
VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT,
// Provided by VK_VALVE_mutable_descriptor_type
VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_VALVE = VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_EXT,
} VkDescriptorPoolCreateFlagBits;
-
VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT
specifies that descriptor sets can return their individual allocations to the pool, i.e. all of vkAllocateDescriptorSets, vkFreeDescriptorSets, and vkResetDescriptorPool are allowed. Otherwise, descriptor sets allocated from the pool must not be individually freed back to the pool, i.e. only vkAllocateDescriptorSets and vkResetDescriptorPool are allowed. -
VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT
specifies that descriptor sets allocated from this pool can include bindings with theVK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT
bit set. It is valid to allocate descriptor sets that have bindings that do not set theVK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT
bit from a pool that hasVK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT
set. -
VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_EXT
specifies that this descriptor pool and the descriptor sets allocated from it reside entirely in host memory and cannot be bound. Similar to descriptor sets allocated without this flag, applications can copy-from and copy-to descriptors sets allocated from this descriptor pool. Descriptor sets allocated from this pool are partially exempt from the external synchronization requirement in vkUpdateDescriptorSetWithTemplateKHR and vkUpdateDescriptorSets. Descriptor sets and their descriptors can be updated concurrently in different threads, though the same descriptor must not be updated concurrently by two threads. -
VK_DESCRIPTOR_POOL_CREATE_ALLOW_OVERALLOCATION_SETS_BIT_NV
specifies that the implementation should allow the application to allocate more than VkDescriptorPoolCreateInfo::maxSets
descriptor set objects from the descriptor pool as available resources allow. The implementation may use themaxSets
value to allocate the initial available sets, but using zero is permitted. -
VK_DESCRIPTOR_POOL_CREATE_ALLOW_OVERALLOCATION_POOLS_BIT_NV
specifies that the implementation should allow the application to allocate more descriptors from the pool than was specified by the VkDescriptorPoolSize::descriptorCount
for any descriptor type as specified by VkDescriptorPoolCreateInfo::poolSizeCount
and VkDescriptorPoolCreateInfo::pPoolSizes
, as available resources allow. The implementation may use thedescriptorCount
for each descriptor type to allocate the initial pool, but the application is allowed to set thepoolSizeCount
to zero, or any of thedescriptorCount
values in thepPoolSizes
array to zero.
// Provided by VK_VERSION_1_0
typedef VkFlags VkDescriptorPoolCreateFlags;
VkDescriptorPoolCreateFlags
is a bitmask type for setting a mask of
zero or more VkDescriptorPoolCreateFlagBits.
The VkDescriptorPoolSize
structure is defined as:
// Provided by VK_VERSION_1_0
typedef struct VkDescriptorPoolSize {
VkDescriptorType type;
uint32_t descriptorCount;
} VkDescriptorPoolSize;
-
type
is the type of descriptor. -
descriptorCount
is the number of descriptors of that type to allocate. Iftype
isVK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK
thendescriptorCount
is the number of bytes to allocate for descriptors of this type.
When creating a descriptor pool that will contain descriptors for combined
image samplers of multi-planar formats, an application needs to account for
non-trivial descriptor consumption when choosing the For simplicity the application can use the
VkPhysicalDeviceMaintenance6Properties:: |
To destroy a descriptor pool, call:
// Provided by VK_VERSION_1_0
void vkDestroyDescriptorPool(
VkDevice device,
VkDescriptorPool descriptorPool,
const VkAllocationCallbacks* pAllocator);
-
device
is the logical device that destroys the descriptor pool. -
descriptorPool
is the descriptor pool to destroy. -
pAllocator
controls host memory allocation as described in the Memory Allocation chapter.
When a pool is destroyed, all descriptor sets allocated from the pool are implicitly freed and become invalid. Descriptor sets allocated from a given pool do not need to be freed before destroying that descriptor pool.
Descriptor sets are allocated from descriptor pool objects, and are
represented by VkDescriptorSet
handles:
// Provided by VK_VERSION_1_0
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorSet)
To allocate descriptor sets from a descriptor pool, call:
// Provided by VK_VERSION_1_0
VkResult vkAllocateDescriptorSets(
VkDevice device,
const VkDescriptorSetAllocateInfo* pAllocateInfo,
VkDescriptorSet* pDescriptorSets);
-
device
is the logical device that owns the descriptor pool. -
pAllocateInfo
is a pointer to a VkDescriptorSetAllocateInfo structure describing parameters of the allocation. -
pDescriptorSets
is a pointer to an array of VkDescriptorSet handles in which the resulting descriptor set objects are returned.
The allocated descriptor sets are returned in pDescriptorSets
.
When a descriptor set is allocated, the initial state is largely
uninitialized and all descriptors are undefined, with the exception that
samplers with a non-null pImmutableSamplers
are initialized on
allocation.
Descriptors also become undefined if the underlying resource or view object
is destroyed.
Descriptor sets containing undefined descriptors can still be bound and
used, subject to the following conditions:
-
For descriptor set bindings created with the
VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT
bit set, all descriptors in that binding that are dynamically used must have been populated before the descriptor set is consumed. -
For descriptor set bindings created without the
VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT
bit set, all descriptors in that binding that are statically used must have been populated before the descriptor set is consumed. -
Descriptor bindings with descriptor type of
VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK
can be undefined when the descriptor set is consumed; though values in that block will be undefined. -
Entries that are not used by a pipeline can have undefined descriptors.
If a call to vkAllocateDescriptorSets
would cause the total number of
descriptor sets allocated from the pool to exceed the value of
VkDescriptorPoolCreateInfo::maxSets
used to create
pAllocateInfo->descriptorPool
, then the allocation may fail due to
lack of space in the descriptor pool.
Similarly, the allocation may fail due to lack of space if the call to
vkAllocateDescriptorSets
would cause the number of any given
descriptor type to exceed the sum of all the descriptorCount
members
of each element of VkDescriptorPoolCreateInfo::pPoolSizes
with a
type
equal to that type.
Additionally, the allocation may also fail if a call to
vkAllocateDescriptorSets
would cause the total number of inline
uniform block bindings allocated from the pool to exceed the value of
VkDescriptorPoolInlineUniformBlockCreateInfo::maxInlineUniformBlockBindings
used to create the descriptor pool.
If the allocation fails due to no more space in the descriptor pool, and not
because of system or device memory exhaustion, then
VK_ERROR_OUT_OF_POOL_MEMORY
must be returned.
vkAllocateDescriptorSets
can be used to create multiple descriptor
sets.
If the creation of any of those descriptor sets fails, then the
implementation must destroy all successfully created descriptor set objects
from this command, set all entries of the pDescriptorSets
array to
VK_NULL_HANDLE and return the error.
The VkDescriptorSetAllocateInfo
structure is defined as:
// Provided by VK_VERSION_1_0
typedef struct VkDescriptorSetAllocateInfo {
VkStructureType sType;
const void* pNext;
VkDescriptorPool descriptorPool;
uint32_t descriptorSetCount;
const VkDescriptorSetLayout* pSetLayouts;
} VkDescriptorSetAllocateInfo;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
descriptorPool
is the pool which the sets will be allocated from. -
descriptorSetCount
determines the number of descriptor sets to be allocated from the pool. -
pSetLayouts
is a pointer to an array of descriptor set layouts, with each member specifying how the corresponding descriptor set is allocated.
If the pNext
chain of a VkDescriptorSetAllocateInfo structure
includes a VkDescriptorSetVariableDescriptorCountAllocateInfo
structure, then that structure includes an array of descriptor counts for
variable-sized descriptor bindings, one for each descriptor set being
allocated.
The VkDescriptorSetVariableDescriptorCountAllocateInfo
structure is
defined as:
// Provided by VK_VERSION_1_2
typedef struct VkDescriptorSetVariableDescriptorCountAllocateInfo {
VkStructureType sType;
const void* pNext;
uint32_t descriptorSetCount;
const uint32_t* pDescriptorCounts;
} VkDescriptorSetVariableDescriptorCountAllocateInfo;
or the equivalent
// Provided by VK_EXT_descriptor_indexing
typedef VkDescriptorSetVariableDescriptorCountAllocateInfo VkDescriptorSetVariableDescriptorCountAllocateInfoEXT;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
descriptorSetCount
is zero or the number of elements inpDescriptorCounts
. -
pDescriptorCounts
is a pointer to an array of descriptor counts, with each member specifying the number of descriptors in a variable-sized descriptor binding in the corresponding descriptor set being allocated.
If descriptorSetCount
is zero or this structure is not included in the
pNext
chain, then the variable lengths are considered to be zero.
Otherwise, pDescriptorCounts
[i] is the number of descriptors in the
variable-sized descriptor binding in the corresponding descriptor set
layout.
If the variable-sized descriptor binding in the corresponding descriptor set
layout has a descriptor type of
VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK
then
pDescriptorCounts
[i] specifies the binding’s capacity in bytes.
If VkDescriptorSetAllocateInfo::pSetLayouts
[i] does not include
a variable-sized descriptor binding, then pDescriptorCounts
[i] is
ignored.
To free allocated descriptor sets, call:
// Provided by VK_VERSION_1_0
VkResult vkFreeDescriptorSets(
VkDevice device,
VkDescriptorPool descriptorPool,
uint32_t descriptorSetCount,
const VkDescriptorSet* pDescriptorSets);
-
device
is the logical device that owns the descriptor pool. -
descriptorPool
is the descriptor pool from which the descriptor sets were allocated. -
descriptorSetCount
is the number of elements in thepDescriptorSets
array. -
pDescriptorSets
is a pointer to an array of handles to VkDescriptorSet objects.
After calling vkFreeDescriptorSets
, all descriptor sets in
pDescriptorSets
are invalid.
To return all descriptor sets allocated from a given pool to the pool, rather than freeing individual descriptor sets, call:
// Provided by VK_VERSION_1_0
VkResult vkResetDescriptorPool(
VkDevice device,
VkDescriptorPool descriptorPool,
VkDescriptorPoolResetFlags flags);
-
device
is the logical device that owns the descriptor pool. -
descriptorPool
is the descriptor pool to be reset. -
flags
is reserved for future use.
Resetting a descriptor pool recycles all of the resources from all of the descriptor sets allocated from the descriptor pool back to the descriptor pool, and the descriptor sets are implicitly freed.
// Provided by VK_VERSION_1_0
typedef VkFlags VkDescriptorPoolResetFlags;
VkDescriptorPoolResetFlags
is a bitmask type for setting a mask, but
is currently reserved for future use.
Descriptor Set Updates
Once allocated, descriptor sets can be updated with a combination of write and copy operations. To update descriptor sets, call:
// Provided by VK_VERSION_1_0
void vkUpdateDescriptorSets(
VkDevice device,
uint32_t descriptorWriteCount,
const VkWriteDescriptorSet* pDescriptorWrites,
uint32_t descriptorCopyCount,
const VkCopyDescriptorSet* pDescriptorCopies);
-
device
is the logical device that updates the descriptor sets. -
descriptorWriteCount
is the number of elements in thepDescriptorWrites
array. -
pDescriptorWrites
is a pointer to an array of VkWriteDescriptorSet structures describing the descriptor sets to write to. -
descriptorCopyCount
is the number of elements in thepDescriptorCopies
array. -
pDescriptorCopies
is a pointer to an array of VkCopyDescriptorSet structures describing the descriptor sets to copy between.
The operations described by pDescriptorWrites
are performed first,
followed by the operations described by pDescriptorCopies
.
Within each array, the operations are performed in the order they appear in
the array.
Each element in the pDescriptorWrites
array describes an operation
updating the descriptor set using descriptors for resources specified in the
structure.
Each element in the pDescriptorCopies
array is a
VkCopyDescriptorSet structure describing an operation copying
descriptors between sets.
If the dstSet
member of any element of pDescriptorWrites
or
pDescriptorCopies
is bound, accessed, or modified by any command that
was recorded to a command buffer which is currently in the
recording or executable state,
and any of the descriptor bindings that are updated were not created with
the VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT
or
VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT
bits set,
that command buffer becomes invalid.
The VkWriteDescriptorSet
structure is defined as:
// Provided by VK_VERSION_1_0
typedef struct VkWriteDescriptorSet {
VkStructureType sType;
const void* pNext;
VkDescriptorSet dstSet;
uint32_t dstBinding;
uint32_t dstArrayElement;
uint32_t descriptorCount;
VkDescriptorType descriptorType;
const VkDescriptorImageInfo* pImageInfo;
const VkDescriptorBufferInfo* pBufferInfo;
const VkBufferView* pTexelBufferView;
} VkWriteDescriptorSet;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
dstSet
is the destination descriptor set to update. -
dstBinding
is the descriptor binding within that set. -
dstArrayElement
is the starting element in that array. If the descriptor binding identified bydstSet
anddstBinding
has a descriptor type ofVK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK
thendstArrayElement
specifies the starting byte offset within the binding. -
descriptorCount
is the number of descriptors to update. If the descriptor binding identified bydstSet
anddstBinding
has a descriptor type ofVK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK
, thendescriptorCount
specifies the number of bytes to update. Otherwise,descriptorCount
is one of-
the number of elements in
pImageInfo
-
the number of elements in
pBufferInfo
-
the number of elements in
pTexelBufferView
-
a value matching the
dataSize
member of a VkWriteDescriptorSetInlineUniformBlock structure in thepNext
chain -
a value matching the
accelerationStructureCount
of a VkWriteDescriptorSetAccelerationStructureKHR or VkWriteDescriptorSetAccelerationStructureNV structure in thepNext
chain
-
-
descriptorType
is a VkDescriptorType specifying the type of each descriptor inpImageInfo
,pBufferInfo
, orpTexelBufferView
, as described below. IfVkDescriptorSetLayoutBinding
fordstSet
atdstBinding
is not equal toVK_DESCRIPTOR_TYPE_MUTABLE_EXT
,descriptorType
must be the same type as thedescriptorType
specified inVkDescriptorSetLayoutBinding
fordstSet
atdstBinding
. The type of the descriptor also controls which array the descriptors are taken from. -
pImageInfo
is a pointer to an array of VkDescriptorImageInfo structures or is ignored, as described below. -
pBufferInfo
is a pointer to an array of VkDescriptorBufferInfo structures or is ignored, as described below. -
pTexelBufferView
is a pointer to an array of VkBufferView handles as described in the Buffer Views section or is ignored, as described below.
Only one of pImageInfo
, pBufferInfo
, or pTexelBufferView
members is used according to the descriptor type specified in the
descriptorType
member of the containing VkWriteDescriptorSet
structure,
or none of them in case descriptorType
is
VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK
, in which case the source data
for the descriptor writes is taken from the
VkWriteDescriptorSetInlineUniformBlock structure included in the
pNext
chain of VkWriteDescriptorSet
,
or if descriptorType
is
VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR
, in which case the
source data for the descriptor writes is taken from the
VkWriteDescriptorSetAccelerationStructureKHR structure in the
pNext
chain of VkWriteDescriptorSet
,
or if descriptorType
is
VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV
, in which case the source
data for the descriptor writes is taken from the
VkWriteDescriptorSetAccelerationStructureNV structure in the
pNext
chain of VkWriteDescriptorSet
,
as specified below.
If the nullDescriptor
feature is enabled,
the buffer,
acceleration structure,
imageView, or bufferView can be VK_NULL_HANDLE.
Loads from a null descriptor return zero values and stores and atomics to a
null descriptor are discarded.
A null acceleration structure descriptor results in the miss shader being
invoked.
If the destination descriptor is a mutable descriptor, the active descriptor
type for the destination descriptor becomes descriptorType
.
If the dstBinding
has fewer than descriptorCount
array elements
remaining starting from dstArrayElement
, then the remainder will be
used to update the subsequent binding - dstBinding
+1 starting at
array element zero.
If a binding has a descriptorCount
of zero, it is skipped.
This behavior applies recursively, with the update affecting consecutive
bindings as needed to update all descriptorCount
descriptors.
Consecutive bindings must have identical VkDescriptorType,
VkShaderStageFlags,
VkDescriptorBindingFlagBits,
and immutable samplers references.
In addition, if the VkDescriptorType is
VK_DESCRIPTOR_TYPE_MUTABLE_EXT
, the supported descriptor types in
VkMutableDescriptorTypeCreateInfoEXT must be equally defined.
The same behavior applies to bindings with a descriptor type of
|
The type of descriptors in a descriptor set is specified by
VkWriteDescriptorSet::descriptorType
, which must be one of the
values:
// Provided by VK_VERSION_1_0
typedef enum VkDescriptorType {
VK_DESCRIPTOR_TYPE_SAMPLER = 0,
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER = 1,
VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE = 2,
VK_DESCRIPTOR_TYPE_STORAGE_IMAGE = 3,
VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER = 4,
VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER = 5,
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER = 6,
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER = 7,
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC = 8,
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC = 9,
VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 10,
// Provided by VK_VERSION_1_3
VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK = 1000138000,
// Provided by VK_KHR_acceleration_structure
VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR = 1000150000,
// Provided by VK_NV_ray_tracing
VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV = 1000165000,
// Provided by VK_QCOM_image_processing
VK_DESCRIPTOR_TYPE_SAMPLE_WEIGHT_IMAGE_QCOM = 1000440000,
// Provided by VK_QCOM_image_processing
VK_DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM = 1000440001,
// Provided by VK_EXT_mutable_descriptor_type
VK_DESCRIPTOR_TYPE_MUTABLE_EXT = 1000351000,
// Provided by VK_EXT_inline_uniform_block
VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT = VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK,
// Provided by VK_VALVE_mutable_descriptor_type
VK_DESCRIPTOR_TYPE_MUTABLE_VALVE = VK_DESCRIPTOR_TYPE_MUTABLE_EXT,
} VkDescriptorType;
-
VK_DESCRIPTOR_TYPE_SAMPLER
specifies a sampler descriptor. -
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
specifies a combined image sampler descriptor. -
VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE
specifies a sampled image descriptor. -
VK_DESCRIPTOR_TYPE_STORAGE_IMAGE
specifies a storage image descriptor. -
VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER
specifies a uniform texel buffer descriptor. -
VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER
specifies a storage texel buffer descriptor. -
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER
specifies a uniform buffer descriptor. -
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER
specifies a storage buffer descriptor. -
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC
specifies a dynamic uniform buffer descriptor. -
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC
specifies a dynamic storage buffer descriptor. -
VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT
specifies an input attachment descriptor. -
VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK
specifies an inline uniform block. -
VK_DESCRIPTOR_TYPE_MUTABLE_EXT
specifies a descriptor of mutable type. -
VK_DESCRIPTOR_TYPE_SAMPLE_WEIGHT_IMAGE_QCOM
specifies a sampled weight image descriptor. -
VK_DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM
specifies a block matching image descriptor.
When a descriptor set is updated via elements of VkWriteDescriptorSet,
members of pImageInfo
, pBufferInfo
and pTexelBufferView
are only accessed by the implementation when they correspond to descriptor
type being defined - otherwise they are ignored.
The members accessed are as follows for each descriptor type:
-
For
VK_DESCRIPTOR_TYPE_SAMPLER
, only thesampler
member of each element of VkWriteDescriptorSet::pImageInfo
is accessed. -
For
VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE
,VK_DESCRIPTOR_TYPE_STORAGE_IMAGE
, orVK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT
, only theimageView
andimageLayout
members of each element of VkWriteDescriptorSet::pImageInfo
are accessed. -
For
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
, all members of each element of VkWriteDescriptorSet::pImageInfo
are accessed. -
For
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER
,VK_DESCRIPTOR_TYPE_STORAGE_BUFFER
,VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC
, orVK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC
, all members of each element of VkWriteDescriptorSet::pBufferInfo
are accessed. -
For
VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER
orVK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER
, each element of VkWriteDescriptorSet::pTexelBufferView
is accessed.
When updating descriptors with a descriptorType
of
VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK
, none of the pImageInfo
,
pBufferInfo
, or pTexelBufferView
members are accessed, instead
the source data of the descriptor update operation is taken from the
VkWriteDescriptorSetInlineUniformBlock structure in the pNext
chain of VkWriteDescriptorSet
.
When updating descriptors with a descriptorType
of
VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR
, none of the
pImageInfo
, pBufferInfo
, or pTexelBufferView
members are
accessed, instead the source data of the descriptor update operation is
taken from the VkWriteDescriptorSetAccelerationStructureKHR structure
in the pNext
chain of VkWriteDescriptorSet
.
When updating descriptors with a descriptorType
of
VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV
, none of the
pImageInfo
, pBufferInfo
, or pTexelBufferView
members are
accessed, instead the source data of the descriptor update operation is
taken from the VkWriteDescriptorSetAccelerationStructureNV structure
in the pNext
chain of VkWriteDescriptorSet
.
The VkDescriptorBufferInfo
structure is defined as:
// Provided by VK_VERSION_1_0
typedef struct VkDescriptorBufferInfo {
VkBuffer buffer;
VkDeviceSize offset;
VkDeviceSize range;
} VkDescriptorBufferInfo;
-
buffer
is VK_NULL_HANDLE or the buffer resource. -
offset
is the offset in bytes from the start ofbuffer
. Access to buffer memory via this descriptor uses addressing that is relative to this starting offset. -
range
is the size in bytes that is used for this descriptor update, orVK_WHOLE_SIZE
to use the range fromoffset
to the end of the buffer.When setting
range
toVK_WHOLE_SIZE
, the effective range must not be larger than the maximum range for the descriptor type (maxUniformBufferRange
ormaxStorageBufferRange
). This means thatVK_WHOLE_SIZE
is not typically useful in the common case where uniform buffer descriptors are suballocated from a buffer that is much larger thanmaxUniformBufferRange
.
For VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC
and
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC
descriptor types,
offset
is the base offset from which the dynamic offset is applied and
range
is the static size used for all dynamic offsets.
When range
is VK_WHOLE_SIZE
the effective range is calculated at
vkUpdateDescriptorSets is by taking the size of buffer
minus the
offset
.
The VkDescriptorImageInfo
structure is defined as:
// Provided by VK_VERSION_1_0
typedef struct VkDescriptorImageInfo {
VkSampler sampler;
VkImageView imageView;
VkImageLayout imageLayout;
} VkDescriptorImageInfo;
-
sampler
is a sampler handle, and is used in descriptor updates for typesVK_DESCRIPTOR_TYPE_SAMPLER
andVK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
if the binding being updated does not use immutable samplers. -
imageView
is VK_NULL_HANDLE or an image view handle, and is used in descriptor updates for typesVK_DESCRIPTOR_TYPE_SAMPLED_IMAGE
,VK_DESCRIPTOR_TYPE_STORAGE_IMAGE
,VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
, andVK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT
. -
imageLayout
is the layout that the image subresources accessible fromimageView
will be in at the time this descriptor is accessed.imageLayout
is used in descriptor updates for typesVK_DESCRIPTOR_TYPE_SAMPLED_IMAGE
,VK_DESCRIPTOR_TYPE_STORAGE_IMAGE
,VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
, andVK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT
.
Members of VkDescriptorImageInfo
that are not used in an update (as
described above) are ignored.
If the descriptorType
member of VkWriteDescriptorSet is
VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK
then the data to write to the
descriptor set is specified through a
VkWriteDescriptorSetInlineUniformBlock
structure included in the
pNext
chain of VkWriteDescriptorSet
.
The VkWriteDescriptorSetInlineUniformBlock
structure is defined as:
// Provided by VK_VERSION_1_3
typedef struct VkWriteDescriptorSetInlineUniformBlock {
VkStructureType sType;
const void* pNext;
uint32_t dataSize;
const void* pData;
} VkWriteDescriptorSetInlineUniformBlock;
or the equivalent
// Provided by VK_EXT_inline_uniform_block
typedef VkWriteDescriptorSetInlineUniformBlock VkWriteDescriptorSetInlineUniformBlockEXT;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
dataSize
is the number of bytes of inline uniform block data pointed to bypData
. -
pData
is a pointer todataSize
number of bytes of data to write to the inline uniform block.
The VkWriteDescriptorSetAccelerationStructureKHR
structure is defined
as:
// Provided by VK_KHR_acceleration_structure
typedef struct VkWriteDescriptorSetAccelerationStructureKHR {
VkStructureType sType;
const void* pNext;
uint32_t accelerationStructureCount;
const VkAccelerationStructureKHR* pAccelerationStructures;
} VkWriteDescriptorSetAccelerationStructureKHR;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
accelerationStructureCount
is the number of elements inpAccelerationStructures
. -
pAccelerationStructures
is a pointer to an array of VkAccelerationStructureKHR structures specifying the acceleration structures to update.
The VkWriteDescriptorSetAccelerationStructureNV
structure is defined
as:
// Provided by VK_NV_ray_tracing
typedef struct VkWriteDescriptorSetAccelerationStructureNV {
VkStructureType sType;
const void* pNext;
uint32_t accelerationStructureCount;
const VkAccelerationStructureNV* pAccelerationStructures;
} VkWriteDescriptorSetAccelerationStructureNV;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
accelerationStructureCount
is the number of elements inpAccelerationStructures
. -
pAccelerationStructures
is a pointer to an array of VkAccelerationStructureNV structures specifying the acceleration structures to update.
The VkCopyDescriptorSet
structure is defined as:
// Provided by VK_VERSION_1_0
typedef struct VkCopyDescriptorSet {
VkStructureType sType;
const void* pNext;
VkDescriptorSet srcSet;
uint32_t srcBinding;
uint32_t srcArrayElement;
VkDescriptorSet dstSet;
uint32_t dstBinding;
uint32_t dstArrayElement;
uint32_t descriptorCount;
} VkCopyDescriptorSet;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
srcSet
,srcBinding
, andsrcArrayElement
are the source set, binding, and array element, respectively. If the descriptor binding identified bysrcSet
andsrcBinding
has a descriptor type ofVK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK
thensrcArrayElement
specifies the starting byte offset within the binding to copy from. -
dstSet
,dstBinding
, anddstArrayElement
are the destination set, binding, and array element, respectively. If the descriptor binding identified bydstSet
anddstBinding
has a descriptor type ofVK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK
thendstArrayElement
specifies the starting byte offset within the binding to copy to. -
descriptorCount
is the number of descriptors to copy from the source to destination. IfdescriptorCount
is greater than the number of remaining array elements in the source or destination binding, those affect consecutive bindings in a manner similar to VkWriteDescriptorSet above. If the descriptor binding identified bysrcSet
andsrcBinding
has a descriptor type ofVK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK
thendescriptorCount
specifies the number of bytes to copy and the remaining array elements in the source or destination binding refer to the remaining number of bytes in those.
If the VkDescriptorSetLayoutBinding
for dstBinding
is
VK_DESCRIPTOR_TYPE_MUTABLE_EXT
and srcBinding
is not
VK_DESCRIPTOR_TYPE_MUTABLE_EXT
, the new active descriptor type becomes
the descriptor type of srcBinding
.
If both VkDescriptorSetLayoutBinding
for srcBinding
and
dstBinding
are VK_DESCRIPTOR_TYPE_MUTABLE_EXT
, the active
descriptor type in each source descriptor is copied into the corresponding
destination descriptor.
The active descriptor type can be different for each source descriptor.
The intention is that copies to and from mutable descriptors is a simple
memcpy.
Copies between non-mutable and mutable descriptors are expected to require
one memcpy per descriptor to handle the difference in size, but this use
case with more than one |
Descriptor Update Templates
A descriptor update template specifies a mapping from descriptor update information in host memory to descriptors in a descriptor set. It is designed to avoid passing redundant information to the driver when frequently updating the same set of descriptors in descriptor sets.
Descriptor update template objects are represented by
VkDescriptorUpdateTemplate
handles:
// Provided by VK_VERSION_1_1
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorUpdateTemplate)
or the equivalent
// Provided by VK_KHR_descriptor_update_template
typedef VkDescriptorUpdateTemplate VkDescriptorUpdateTemplateKHR;
Descriptor Set Updates With Templates
Updating a large VkDescriptorSet
array can be an expensive operation
since an application must specify one VkWriteDescriptorSet structure
for each descriptor or descriptor array to update, each of which
re-specifies the same state when updating the same descriptor in multiple
descriptor sets.
For cases when an application wishes to update the same set of descriptors
in multiple descriptor sets allocated using the same
VkDescriptorSetLayout
, vkUpdateDescriptorSetWithTemplate can be
used as a replacement for vkUpdateDescriptorSets.
VkDescriptorUpdateTemplate
allows implementations to convert a set of
descriptor update operations on a single descriptor set to an internal
format.
In conjunction with
vkCmdPushDescriptorSetWithTemplate or
vkUpdateDescriptorSetWithTemplate, this can be more efficient
compared to calling
vkCmdPushDescriptorSet or
vkUpdateDescriptorSets.
The descriptors themselves are not specified in the
VkDescriptorUpdateTemplate
, rather, offsets into an application
provided pointer to host memory are specified, which are combined with a
pointer passed to
vkCmdPushDescriptorSetWithTemplate or
vkUpdateDescriptorSetWithTemplate.
This allows large batches of updates to be executed without having to
convert application data structures into a strictly-defined Vulkan data
structure.
To create a descriptor update template, call:
// Provided by VK_VERSION_1_1
VkResult vkCreateDescriptorUpdateTemplate(
VkDevice device,
const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate);
or the equivalent command
// Provided by VK_KHR_descriptor_update_template
VkResult vkCreateDescriptorUpdateTemplateKHR(
VkDevice device,
const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate);
-
device
is the logical device that creates the descriptor update template. -
pCreateInfo
is a pointer to a VkDescriptorUpdateTemplateCreateInfo structure specifying the set of descriptors to update with a single call to vkCmdPushDescriptorSetWithTemplate or vkUpdateDescriptorSetWithTemplate. -
pAllocator
controls host memory allocation as described in the Memory Allocation chapter. -
pDescriptorUpdateTemplate
is a pointer to aVkDescriptorUpdateTemplate
handle in which the resulting descriptor update template object is returned.
The VkDescriptorUpdateTemplateCreateInfo structure is defined as:
// Provided by VK_VERSION_1_1
typedef struct VkDescriptorUpdateTemplateCreateInfo {
VkStructureType sType;
const void* pNext;
VkDescriptorUpdateTemplateCreateFlags flags;
uint32_t descriptorUpdateEntryCount;
const VkDescriptorUpdateTemplateEntry* pDescriptorUpdateEntries;
VkDescriptorUpdateTemplateType templateType;
VkDescriptorSetLayout descriptorSetLayout;
VkPipelineBindPoint pipelineBindPoint;
VkPipelineLayout pipelineLayout;
uint32_t set;
} VkDescriptorUpdateTemplateCreateInfo;
or the equivalent
// Provided by VK_KHR_descriptor_update_template
typedef VkDescriptorUpdateTemplateCreateInfo VkDescriptorUpdateTemplateCreateInfoKHR;
-
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. -
descriptorUpdateEntryCount
is the number of elements in thepDescriptorUpdateEntries
array. -
pDescriptorUpdateEntries
is a pointer to an array of VkDescriptorUpdateTemplateEntry structures describing the descriptors to be updated by the descriptor update template. -
templateType
Specifies the type of the descriptor update template. If set toVK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET
it can only be used to update descriptor sets with a fixeddescriptorSetLayout
. If set toVK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS
it can only be used to push descriptor sets using the providedpipelineBindPoint
,pipelineLayout
, andset
number. -
descriptorSetLayout
is the descriptor set layout used to build the descriptor update template. All descriptor sets which are going to be updated through the newly created descriptor update template must be created with a layout that matches (is the same as, or defined identically to) this layout. This parameter is ignored iftemplateType
is notVK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET
. -
pipelineBindPoint
is a VkPipelineBindPoint indicating the type of the pipeline that will use the descriptors. This parameter is ignored iftemplateType
is notVK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS
-
pipelineLayout
is a VkPipelineLayout object used to program the bindings. This parameter is ignored iftemplateType
is notVK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS
-
set
is the set number of the descriptor set in the pipeline layout that will be updated. This parameter is ignored iftemplateType
is notVK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS
// Provided by VK_VERSION_1_1
typedef VkFlags VkDescriptorUpdateTemplateCreateFlags;
or the equivalent
// Provided by VK_KHR_descriptor_update_template
typedef VkDescriptorUpdateTemplateCreateFlags VkDescriptorUpdateTemplateCreateFlagsKHR;
VkDescriptorUpdateTemplateCreateFlags
is a bitmask type for setting a
mask, but is currently reserved for future use.
The descriptor update template type is determined by the
VkDescriptorUpdateTemplateCreateInfo::templateType
property,
which takes the following values:
// Provided by VK_VERSION_1_1
typedef enum VkDescriptorUpdateTemplateType {
VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET = 0,
// Provided by VK_VERSION_1_4
VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS = 1,
// Provided by VK_KHR_descriptor_update_template with VK_KHR_push_descriptor, VK_KHR_push_descriptor with VK_VERSION_1_1 or VK_KHR_descriptor_update_template
VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS,
// Provided by VK_KHR_descriptor_update_template
VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
} VkDescriptorUpdateTemplateType;
or the equivalent
// Provided by VK_KHR_descriptor_update_template
typedef VkDescriptorUpdateTemplateType VkDescriptorUpdateTemplateTypeKHR;
-
VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET
specifies that the descriptor update template will be used for descriptor set updates only. -
VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS
specifies that the descriptor update template will be used for push descriptor updates only.
The VkDescriptorUpdateTemplateEntry
structure is defined as:
// Provided by VK_VERSION_1_1
typedef struct VkDescriptorUpdateTemplateEntry {
uint32_t dstBinding;
uint32_t dstArrayElement;
uint32_t descriptorCount;
VkDescriptorType descriptorType;
size_t offset;
size_t stride;
} VkDescriptorUpdateTemplateEntry;
or the equivalent
// Provided by VK_KHR_descriptor_update_template
typedef VkDescriptorUpdateTemplateEntry VkDescriptorUpdateTemplateEntryKHR;
-
dstBinding
is the descriptor binding to update when using this descriptor update template. -
dstArrayElement
is the starting element in the array belonging todstBinding
. If the descriptor binding identified bydstBinding
has a descriptor type ofVK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK
thendstArrayElement
specifies the starting byte offset to update. -
descriptorCount
is the number of descriptors to update. IfdescriptorCount
is greater than the number of remaining array elements in the destination binding, those affect consecutive bindings in a manner similar to VkWriteDescriptorSet above. If the descriptor binding identified bydstBinding
has a descriptor type ofVK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK
thendescriptorCount
specifies the number of bytes to update and the remaining array elements in the destination binding refer to the remaining number of bytes in it. -
descriptorType
is a VkDescriptorType specifying the type of the descriptor. -
offset
is the offset in bytes of the first binding in the raw data structure. -
stride
is the stride in bytes between two consecutive array elements of the descriptor update information in the raw data structure. The actual pointer ptr for each array element j of update entry i is computed using the following formula:const char *ptr = (const char *)pData + pDescriptorUpdateEntries[i].offset + j * pDescriptorUpdateEntries[i].stride
The stride is useful in case the bindings are stored in structs along with other data. If
descriptorType
isVK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK
then the value ofstride
is ignored and the stride is assumed to be1
, i.e. the descriptor update information for them is always specified as a contiguous range.
To destroy a descriptor update template, call:
// Provided by VK_VERSION_1_1
void vkDestroyDescriptorUpdateTemplate(
VkDevice device,
VkDescriptorUpdateTemplate descriptorUpdateTemplate,
const VkAllocationCallbacks* pAllocator);
or the equivalent command
// Provided by VK_KHR_descriptor_update_template
void vkDestroyDescriptorUpdateTemplateKHR(
VkDevice device,
VkDescriptorUpdateTemplate descriptorUpdateTemplate,
const VkAllocationCallbacks* pAllocator);
-
device
is the logical device that has been used to create the descriptor update template -
descriptorUpdateTemplate
is the descriptor update template to destroy. -
pAllocator
controls host memory allocation as described in the Memory Allocation chapter.
Once a VkDescriptorUpdateTemplate
has been created, descriptor sets
can be updated by calling:
// Provided by VK_VERSION_1_1
void vkUpdateDescriptorSetWithTemplate(
VkDevice device,
VkDescriptorSet descriptorSet,
VkDescriptorUpdateTemplate descriptorUpdateTemplate,
const void* pData);
or the equivalent command
// Provided by VK_KHR_descriptor_update_template
void vkUpdateDescriptorSetWithTemplateKHR(
VkDevice device,
VkDescriptorSet descriptorSet,
VkDescriptorUpdateTemplate descriptorUpdateTemplate,
const void* pData);
-
device
is the logical device that updates the descriptor set. -
descriptorSet
is the descriptor set to update -
descriptorUpdateTemplate
is a VkDescriptorUpdateTemplate object specifying the update mapping betweenpData
and the descriptor set to update. -
pData
is a pointer to memory containing one or more VkDescriptorImageInfo, VkDescriptorBufferInfo, or VkBufferView structures or VkAccelerationStructureKHR or VkAccelerationStructureNV handles used to write the descriptors.
struct AppBufferView {
VkBufferView bufferView;
uint32_t applicationRelatedInformation;
};
struct AppDataStructure
{
VkDescriptorImageInfo imageInfo; // a single image info
VkDescriptorBufferInfo bufferInfoArray[3]; // 3 buffer infos in an array
AppBufferView bufferView[2]; // An application-defined structure containing a bufferView
// ... some more application-related data
};
const VkDescriptorUpdateTemplateEntry descriptorUpdateTemplateEntries[] =
{
// binding to a single image descriptor
{
.binding = 0,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
.offset = offsetof(AppDataStructure, imageInfo),
.stride = 0 // stride not required if descriptorCount is 1
},
// binding to an array of buffer descriptors
{
.binding = 1,
.dstArrayElement = 0,
.descriptorCount = 3,
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.offset = offsetof(AppDataStructure, bufferInfoArray),
.stride = sizeof(VkDescriptorBufferInfo) // descriptor buffer infos are compact
},
// binding to an array of buffer views
{
.binding = 2,
.dstArrayElement = 0,
.descriptorCount = 2,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
.offset = offsetof(AppDataStructure, bufferView) +
offsetof(AppBufferView, bufferView),
.stride = sizeof(AppBufferView) // bufferViews do not have to be compact
},
};
// create a descriptor update template for descriptor set updates
const VkDescriptorUpdateTemplateCreateInfo createInfo =
{
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO,
.pNext = NULL,
.flags = 0,
.descriptorUpdateEntryCount = 3,
.pDescriptorUpdateEntries = descriptorUpdateTemplateEntries,
.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
.descriptorSetLayout = myLayout,
.pipelineBindPoint = 0, // ignored by given templateType
.pipelineLayout = 0, // ignored by given templateType
.set = 0, // ignored by given templateType
};
VkDescriptorUpdateTemplate myDescriptorUpdateTemplate;
myResult = vkCreateDescriptorUpdateTemplate(
myDevice,
&createInfo,
NULL,
&myDescriptorUpdateTemplate);
AppDataStructure appData;
// fill appData here or cache it in your engine
vkUpdateDescriptorSetWithTemplate(myDevice, myDescriptorSet, myDescriptorUpdateTemplate, &appData);
Descriptor Set Binding
To bind one or more descriptor sets to a command buffer, call:
// Provided by VK_VERSION_1_0
void vkCmdBindDescriptorSets(
VkCommandBuffer commandBuffer,
VkPipelineBindPoint pipelineBindPoint,
VkPipelineLayout layout,
uint32_t firstSet,
uint32_t descriptorSetCount,
const VkDescriptorSet* pDescriptorSets,
uint32_t dynamicOffsetCount,
const uint32_t* pDynamicOffsets);
-
commandBuffer
is the command buffer that the descriptor sets will be bound to. -
pipelineBindPoint
is a VkPipelineBindPoint indicating the type of the pipeline that will use the descriptors. There is a separate set of bind points for each pipeline type, so binding one does not disturb the others. -
layout
is a VkPipelineLayout object used to program the bindings. -
firstSet
is the set number of the first descriptor set to be bound. -
descriptorSetCount
is the number of elements in thepDescriptorSets
array. -
pDescriptorSets
is a pointer to an array of handles to VkDescriptorSet objects describing the descriptor sets to bind to. -
dynamicOffsetCount
is the number of dynamic offsets in thepDynamicOffsets
array. -
pDynamicOffsets
is a pointer to an array ofuint32_t
values specifying dynamic offsets.
vkCmdBindDescriptorSets
binds descriptor sets
pDescriptorSets
[0..descriptorSetCount
-1] to set numbers
[firstSet
..firstSet
+descriptorSetCount
-1] for subsequent
bound pipeline commands set by
pipelineBindPoint
.
Any bindings that were previously applied via these sets
, or calls to vkCmdSetDescriptorBufferOffsetsEXT or
vkCmdBindDescriptorBufferEmbeddedSamplersEXT,
are no longer valid.
Once bound, a descriptor set affects rendering of subsequent commands that interact with the given pipeline type in the command buffer until either a different set is bound to the same set number, or the set is disturbed as described in Pipeline Layout Compatibility.
A compatible descriptor set must be bound for all set numbers that any shaders in a pipeline access, at the time that a drawing or dispatching command is recorded to execute using that pipeline. However, if none of the shaders in a pipeline statically use any bindings with a particular set number, then no descriptor set need be bound for that set number, even if the pipeline layout includes a non-trivial descriptor set layout for that set number.
When consuming a descriptor, a descriptor is considered valid if the
descriptor is not undefined as described by
descriptor set allocation.
If the nullDescriptor
feature is enabled,
a null descriptor is also considered valid.
A descriptor that was disturbed by Pipeline Layout Compatibility, or was never bound by vkCmdBindDescriptorSets
is not considered valid.
If a pipeline accesses a descriptor either statically or dynamically
depending on the VkDescriptorBindingFlagBits, the consuming descriptor
type in the pipeline must match the VkDescriptorType in
VkDescriptorSetLayoutCreateInfo for the descriptor to be considered
valid.
If a descriptor is a mutable descriptor, the consuming descriptor type in
the pipeline must match the active descriptor type for the descriptor to be
considered valid.
Further validation may be carried out beyond validation for descriptor types, e.g. Texel Input Validation. |
If any of the sets being bound include dynamic uniform or storage buffers,
then pDynamicOffsets
includes one element for each array element in
each dynamic descriptor type binding in each set.
Values are taken from pDynamicOffsets
in an order such that all
entries for set N come before set N+1; within a set, entries are ordered by
the binding numbers in the descriptor set layouts; and within a binding
array, elements are in order.
dynamicOffsetCount
must equal the total number of dynamic descriptors
in the sets being bound.
The effective offset used for dynamic uniform and storage buffer bindings is
the sum of the relative offset taken from pDynamicOffsets
, and the
base address of the buffer plus base offset in the descriptor set.
The range of the dynamic uniform and storage buffer bindings is the buffer
range as specified in the descriptor set.
Each of the pDescriptorSets
must be compatible with the pipeline
layout specified by layout
.
The layout used to program the bindings must also be compatible with the
pipeline used in subsequent bound pipeline commands with that pipeline type, as defined in the
Pipeline Layout Compatibility section.
The descriptor set contents bound by a call to vkCmdBindDescriptorSets
may be consumed at the following times:
-
For descriptor bindings created with the
VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT
bit set, the contents may be consumed when the command buffer is submitted to a queue, or during shader execution of the resulting draws and dispatches, or any time in between. Otherwise, -
during host execution of the command, or during shader execution of the resulting draws and dispatches, or any time in between.
Thus, the contents of a descriptor set binding must not be altered (overwritten by an update command, or freed) between the first point in time that it may be consumed, and when the command completes executing on the queue.
The contents of pDynamicOffsets
are consumed immediately during
execution of vkCmdBindDescriptorSets
.
Once all pending uses have completed, it is legal to update and reuse a
descriptor set.
Alternatively, to bind one or more descriptor sets to a command buffer, call:
// Provided by VK_VERSION_1_4
void vkCmdBindDescriptorSets2(
VkCommandBuffer commandBuffer,
const VkBindDescriptorSetsInfo* pBindDescriptorSetsInfo);
or the equivalent command
// Provided by VK_KHR_maintenance6
void vkCmdBindDescriptorSets2KHR(
VkCommandBuffer commandBuffer,
const VkBindDescriptorSetsInfo* pBindDescriptorSetsInfo);
-
commandBuffer
is the command buffer that the descriptor sets will be bound to. -
pBindDescriptorSetsInfo
is a pointer to aVkBindDescriptorSetsInfo
structure.
The VkBindDescriptorSetsInfo
structure is defined as:
// Provided by VK_VERSION_1_4
typedef struct VkBindDescriptorSetsInfo {
VkStructureType sType;
const void* pNext;
VkShaderStageFlags stageFlags;
VkPipelineLayout layout;
uint32_t firstSet;
uint32_t descriptorSetCount;
const VkDescriptorSet* pDescriptorSets;
uint32_t dynamicOffsetCount;
const uint32_t* pDynamicOffsets;
} VkBindDescriptorSetsInfo;
or the equivalent
// Provided by VK_KHR_maintenance6
typedef VkBindDescriptorSetsInfo VkBindDescriptorSetsInfoKHR;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
stageFlags
is a bitmask of VkShaderStageFlagBits specifying the shader stages the descriptor sets will be bound to. -
layout
is a VkPipelineLayout object used to program the bindings. If thedynamicPipelineLayout
feature is enabled,layout
can be VK_NULL_HANDLE and the layout must be specified by chaining the VkPipelineLayoutCreateInfo structure off thepNext
-
firstSet
is the set number of the first descriptor set to be bound. -
descriptorSetCount
is the number of elements in thepDescriptorSets
array. -
pDescriptorSets
is a pointer to an array of handles to VkDescriptorSet objects describing the descriptor sets to bind to. -
dynamicOffsetCount
is the number of dynamic offsets in thepDynamicOffsets
array. -
pDynamicOffsets
is a pointer to an array ofuint32_t
values specifying dynamic offsets.
If stageFlags
specifies a subset of all stages corresponding to one or
more pipeline bind points, the binding operation still affects all stages
corresponding to the given pipeline bind point(s) as if the equivalent
original version of this command had been called with the same parameters.
For example, specifying a stageFlags
value of
VK_SHADER_STAGE_VERTEX_BIT
| VK_SHADER_STAGE_FRAGMENT_BIT
|
VK_SHADER_STAGE_COMPUTE_BIT
is equivalent to calling the original
version of this command once with VK_PIPELINE_BIND_POINT_GRAPHICS
and
once with VK_PIPELINE_BIND_POINT_COMPUTE
.
Push Descriptor Updates
In addition to allocating descriptor sets and binding them to a command buffer, an application can record descriptor updates into the command buffer.
To push descriptor updates into a command buffer, call:
// Provided by VK_VERSION_1_4
void vkCmdPushDescriptorSet(
VkCommandBuffer commandBuffer,
VkPipelineBindPoint pipelineBindPoint,
VkPipelineLayout layout,
uint32_t set,
uint32_t descriptorWriteCount,
const VkWriteDescriptorSet* pDescriptorWrites);
or the equivalent command
// Provided by VK_KHR_push_descriptor
void vkCmdPushDescriptorSetKHR(
VkCommandBuffer commandBuffer,
VkPipelineBindPoint pipelineBindPoint,
VkPipelineLayout layout,
uint32_t set,
uint32_t descriptorWriteCount,
const VkWriteDescriptorSet* pDescriptorWrites);
-
commandBuffer
is the command buffer that the descriptors will be recorded in. -
pipelineBindPoint
is a VkPipelineBindPoint indicating the type of the pipeline that will use the descriptors. There is a separate set of push descriptor bindings for each pipeline type, so binding one does not disturb the others. -
layout
is a VkPipelineLayout object used to program the bindings. -
set
is the set number of the descriptor set in the pipeline layout that will be updated. -
descriptorWriteCount
is the number of elements in thepDescriptorWrites
array. -
pDescriptorWrites
is a pointer to an array of VkWriteDescriptorSet structures describing the descriptors to be updated.
Push descriptors are a small bank of descriptors whose storage is internally managed by the command buffer rather than being written into a descriptor set and later bound to a command buffer. Push descriptors allow for incremental updates of descriptors without managing the lifetime of descriptor sets.
When a command buffer begins recording, all push descriptors are undefined.
Push descriptors can be updated incrementally and cause shaders to use the
updated descriptors for subsequent bound pipeline commands with the pipeline type set by pipelineBindPoint
until the descriptor is overwritten, or else until the set is disturbed as
described in Pipeline Layout Compatibility.
When the set is disturbed or push descriptors with a different descriptor
set layout are set, all push descriptors are undefined.
Push descriptors that are statically used by a
pipeline must not be undefined at the time that a drawing or dispatching
command is recorded to execute using that pipeline.
This includes immutable sampler descriptors, which must be pushed before
they are accessed by a pipeline (the immutable samplers are pushed, rather
than the samplers in pDescriptorWrites
).
Push descriptors that are not statically used can remain undefined.
Push descriptors do not use dynamic offsets.
Instead, the corresponding non-dynamic descriptor types can be used and the
offset
member of VkDescriptorBufferInfo can be changed each
time the descriptor is written.
Each element of pDescriptorWrites
is interpreted as in
VkWriteDescriptorSet, except the dstSet
member is ignored.
To push an immutable sampler, use a VkWriteDescriptorSet with
dstBinding
and dstArrayElement
selecting the immutable sampler’s
binding.
If the descriptor type is VK_DESCRIPTOR_TYPE_SAMPLER
, the
pImageInfo
parameter is ignored and the immutable sampler is taken
from the push descriptor set layout in the pipeline layout.
If the descriptor type is VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
,
the sampler
member of the pImageInfo
parameter is ignored and
the immutable sampler is taken from the push descriptor set layout in the
pipeline layout.
Alternatively, to push descriptor updates into a command buffer, call:
// Provided by VK_VERSION_1_4
void vkCmdPushDescriptorSet2(
VkCommandBuffer commandBuffer,
const VkPushDescriptorSetInfo* pPushDescriptorSetInfo);
or the equivalent command
// Provided by VK_KHR_maintenance6 with VK_KHR_push_descriptor
void vkCmdPushDescriptorSet2KHR(
VkCommandBuffer commandBuffer,
const VkPushDescriptorSetInfo* pPushDescriptorSetInfo);
-
commandBuffer
is the command buffer that the descriptors will be recorded in. -
pPushDescriptorSetInfo
is a pointer to aVkPushDescriptorSetInfo
structure.
The VkPushDescriptorSetInfo
structure is defined as:
// Provided by VK_VERSION_1_4
typedef struct VkPushDescriptorSetInfo {
VkStructureType sType;
const void* pNext;
VkShaderStageFlags stageFlags;
VkPipelineLayout layout;
uint32_t set;
uint32_t descriptorWriteCount;
const VkWriteDescriptorSet* pDescriptorWrites;
} VkPushDescriptorSetInfo;
or the equivalent
// Provided by VK_KHR_maintenance6 with VK_KHR_push_descriptor
typedef VkPushDescriptorSetInfo VkPushDescriptorSetInfoKHR;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
stageFlags
is a bitmask of VkShaderStageFlagBits specifying the shader stages that will use the descriptors. -
layout
is a VkPipelineLayout object used to program the bindings. If thedynamicPipelineLayout
feature is enabled,layout
can be VK_NULL_HANDLE and the layout must be specified by chaining VkPipelineLayoutCreateInfo structure off thepNext
-
set
is the set number of the descriptor set in the pipeline layout that will be updated. -
descriptorWriteCount
is the number of elements in thepDescriptorWrites
array. -
pDescriptorWrites
is a pointer to an array of VkWriteDescriptorSet structures describing the descriptors to be updated.
If stageFlags
specifies a subset of all stages corresponding to one or
more pipeline bind points, the binding operation still affects all stages
corresponding to the given pipeline bind point(s) as if the equivalent
original version of this command had been called with the same parameters.
For example, specifying a stageFlags
value of
VK_SHADER_STAGE_VERTEX_BIT
| VK_SHADER_STAGE_FRAGMENT_BIT
|
VK_SHADER_STAGE_COMPUTE_BIT
is equivalent to calling the original
version of this command once with VK_PIPELINE_BIND_POINT_GRAPHICS
and
once with VK_PIPELINE_BIND_POINT_COMPUTE
.
Push Descriptor Updates With Descriptor Update Templates
It is also possible to use a descriptor update template to specify the push descriptors to update. To do so, call:
// Provided by VK_VERSION_1_4
void vkCmdPushDescriptorSetWithTemplate(
VkCommandBuffer commandBuffer,
VkDescriptorUpdateTemplate descriptorUpdateTemplate,
VkPipelineLayout layout,
uint32_t set,
const void* pData);
or the equivalent command
// Provided by VK_KHR_descriptor_update_template with VK_KHR_push_descriptor, VK_KHR_push_descriptor with VK_VERSION_1_1 or VK_KHR_descriptor_update_template
void vkCmdPushDescriptorSetWithTemplateKHR(
VkCommandBuffer commandBuffer,
VkDescriptorUpdateTemplate descriptorUpdateTemplate,
VkPipelineLayout layout,
uint32_t set,
const void* pData);
-
commandBuffer
is the command buffer that the descriptors will be recorded in. -
descriptorUpdateTemplate
is a descriptor update template defining how to interpret the descriptor information inpData
. -
layout
is a VkPipelineLayout object used to program the bindings. It must be compatible with the layout used to create thedescriptorUpdateTemplate
handle. -
set
is the set number of the descriptor set in the pipeline layout that will be updated. This must be the same number used to create thedescriptorUpdateTemplate
handle. -
pData
is a pointer to memory containing descriptors for the templated update.
struct AppDataStructure
{
VkDescriptorImageInfo imageInfo; // a single image info
// ... some more application-related data
};
const VkDescriptorUpdateTemplateEntry descriptorUpdateTemplateEntries[] =
{
// binding to a single image descriptor
{
.binding = 0,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
.offset = offsetof(AppDataStructure, imageInfo),
.stride = 0 // not required if descriptorCount is 1
}
};
// create a descriptor update template for push descriptor set updates
const VkDescriptorUpdateTemplateCreateInfo createInfo =
{
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO,
.pNext = NULL,
.flags = 0,
.descriptorUpdateEntryCount = 1,
.pDescriptorUpdateEntries = descriptorUpdateTemplateEntries,
.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS,
.descriptorSetLayout = 0, // ignored by given templateType
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
.pipelineLayout = myPipelineLayout,
.set = 0,
};
VkDescriptorUpdateTemplate myDescriptorUpdateTemplate;
myResult = vkCreateDescriptorUpdateTemplate(
myDevice,
&createInfo,
NULL,
&myDescriptorUpdateTemplate);
AppDataStructure appData;
// fill appData here or cache it in your engine
vkCmdPushDescriptorSetWithTemplate(myCmdBuffer, myDescriptorUpdateTemplate, myPipelineLayout, 0,&appData);
Alternatively, to use a descriptor update template to specify the push descriptors to update, call:
// Provided by VK_VERSION_1_4
void vkCmdPushDescriptorSetWithTemplate2(
VkCommandBuffer commandBuffer,
const VkPushDescriptorSetWithTemplateInfo* pPushDescriptorSetWithTemplateInfo);
or the equivalent command
// Provided by VK_KHR_maintenance6 with VK_KHR_push_descriptor
void vkCmdPushDescriptorSetWithTemplate2KHR(
VkCommandBuffer commandBuffer,
const VkPushDescriptorSetWithTemplateInfo* pPushDescriptorSetWithTemplateInfo);
-
commandBuffer
is the command buffer that the descriptors will be recorded in. -
pPushDescriptorSetWithTemplateInfo
is a pointer to aVkPushDescriptorSetWithTemplateInfo
structure.
The VkPushDescriptorSetWithTemplateInfo
structure is defined as:
// Provided by VK_VERSION_1_4
typedef struct VkPushDescriptorSetWithTemplateInfo {
VkStructureType sType;
const void* pNext;
VkDescriptorUpdateTemplate descriptorUpdateTemplate;
VkPipelineLayout layout;
uint32_t set;
const void* pData;
} VkPushDescriptorSetWithTemplateInfo;
or the equivalent
// Provided by VK_KHR_maintenance6 with VK_KHR_push_descriptor
typedef VkPushDescriptorSetWithTemplateInfo VkPushDescriptorSetWithTemplateInfoKHR;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
descriptorUpdateTemplate
is a descriptor update template defining how to interpret the descriptor information inpData
. -
layout
is a VkPipelineLayout object used to program the bindings. It must be compatible with the layout used to create thedescriptorUpdateTemplate
handle. If thedynamicPipelineLayout
feature is enabled,layout
can be VK_NULL_HANDLE and the layout must be specified by chaining VkPipelineLayoutCreateInfo structure off thepNext
-
set
is the set number of the descriptor set in the pipeline layout that will be updated. This must be the same number used to create thedescriptorUpdateTemplate
handle. -
pData
is a pointer to memory containing descriptors for the templated update.
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. |
To update push constants, call:
// Provided by VK_VERSION_1_0
void vkCmdPushConstants(
VkCommandBuffer commandBuffer,
VkPipelineLayout layout,
VkShaderStageFlags stageFlags,
uint32_t offset,
uint32_t size,
const void* pValues);
-
commandBuffer
is the command buffer in which the push constant update will be recorded. -
layout
is the pipeline layout used to program the push constant updates. -
stageFlags
is a bitmask of VkShaderStageFlagBits specifying the shader stages that will use the push constants in the updated range. -
offset
is the start offset of the push constant range to update, in units of bytes. -
size
is the size of the push constant range to update, in units of bytes. -
pValues
is a pointer to an array ofsize
bytes containing the new push constant values.
When a command buffer begins recording, all push constant values are undefined. Reads of undefined push constant values by the executing shader return undefined values.
Push constant values can be updated incrementally, causing shader stages in
stageFlags
to read the new data from pValues
for push constants
modified by this command, while still reading the previous data for push
constants not modified by this command.
When a bound pipeline command is issued,
the bound pipeline’s layout must be compatible with the layouts used to set
the values of all push constants in the pipeline layout’s push constant
ranges, as described in Pipeline Layout Compatibility.
Binding a pipeline with a layout that is not compatible with the push
constant layout does not disturb the push constant values.
As |
Alternatively, to update push constants, call:
// Provided by VK_VERSION_1_4
void vkCmdPushConstants2(
VkCommandBuffer commandBuffer,
const VkPushConstantsInfo* pPushConstantsInfo);
or the equivalent command
// Provided by VK_KHR_maintenance6
void vkCmdPushConstants2KHR(
VkCommandBuffer commandBuffer,
const VkPushConstantsInfo* pPushConstantsInfo);
-
commandBuffer
is the command buffer in which the push constant update will be recorded. -
pPushConstantsInfo
is a pointer to aVkPushConstantsInfo
structure.
The VkPushConstantsInfo
structure is defined as:
// Provided by VK_VERSION_1_4
typedef struct VkPushConstantsInfo {
VkStructureType sType;
const void* pNext;
VkPipelineLayout layout;
VkShaderStageFlags stageFlags;
uint32_t offset;
uint32_t size;
const void* pValues;
} VkPushConstantsInfo;
or the equivalent
// Provided by VK_KHR_maintenance6
typedef VkPushConstantsInfo VkPushConstantsInfoKHR;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
layout
is the pipeline layout used to program the push constant updates. If thedynamicPipelineLayout
feature is enabled,layout
can be VK_NULL_HANDLE and the layout must be specified by chaining VkPipelineLayoutCreateInfo structure off thepNext
-
stageFlags
is a bitmask of VkShaderStageFlagBits specifying the shader stages that will use the push constants in the updated range. -
offset
is the start offset of the push constant range to update, in units of bytes. -
size
is the size of the push constant range to update, in units of bytes. -
pValues
is a pointer to an array ofsize
bytes containing the new push constant values.
Physical Storage Buffer Access
To query a 64-bit buffer device address value through which buffer memory can be accessed in a shader, call:
// Provided by VK_VERSION_1_2
VkDeviceAddress vkGetBufferDeviceAddress(
VkDevice device,
const VkBufferDeviceAddressInfo* pInfo);
or the equivalent command
// Provided by VK_KHR_buffer_device_address
VkDeviceAddress vkGetBufferDeviceAddressKHR(
VkDevice device,
const VkBufferDeviceAddressInfo* pInfo);
or the equivalent command
// Provided by VK_EXT_buffer_device_address
VkDeviceAddress vkGetBufferDeviceAddressEXT(
VkDevice device,
const VkBufferDeviceAddressInfo* pInfo);
-
device
is the logical device that the buffer was created on. -
pInfo
is a pointer to a VkBufferDeviceAddressInfo structure specifying the buffer to retrieve an address for.
The 64-bit return value is an address of the start of pInfo->buffer
.
The address range starting at this value and whose size is the size of the
buffer can be used in a shader to access the memory bound to that buffer,
using the
SPV_KHR_physical_storage_buffer
extension
or the equivalent
SPV_EXT_physical_storage_buffer
extension
and the PhysicalStorageBuffer
storage class.
For example, this value can be stored in a uniform buffer, and the shader
can read the value from the uniform buffer and use it to do a dependent
read/write to this buffer.
A value of zero is reserved as a “null” pointer and must not be returned
as a valid buffer device address.
All loads, stores, and atomics in a shader through
PhysicalStorageBuffer
pointers must access addresses in the address
range of some buffer.
If the buffer was created with a non-zero value of
VkBufferOpaqueCaptureAddressCreateInfo::opaqueCaptureAddress
or
VkBufferDeviceAddressCreateInfoEXT::deviceAddress
,
the return value will be the same address that was returned at capture time.
The returned address must satisfy the alignment requirement specified by
VkMemoryRequirements::alignment
for the buffer in
VkBufferDeviceAddressInfo::buffer
.
If multiple VkBuffer objects are bound to overlapping ranges of VkDeviceMemory, implementations may return address ranges which overlap. In this case, it is ambiguous which VkBuffer is associated with any given device address. For purposes of valid usage, if multiple VkBuffer objects can be attributed to a device address, a VkBuffer is selected such that valid usage passes, if it exists.
The VkBufferDeviceAddressInfo
structure is defined as:
// Provided by VK_VERSION_1_2
typedef struct VkBufferDeviceAddressInfo {
VkStructureType sType;
const void* pNext;
VkBuffer buffer;
} VkBufferDeviceAddressInfo;
or the equivalent
// Provided by VK_KHR_buffer_device_address
typedef VkBufferDeviceAddressInfo VkBufferDeviceAddressInfoKHR;
or the equivalent
// Provided by VK_EXT_buffer_device_address
typedef VkBufferDeviceAddressInfo VkBufferDeviceAddressInfoEXT;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
buffer
specifies the buffer whose address is being queried.
To query a 64-bit buffer opaque capture address, call:
// Provided by VK_VERSION_1_2
uint64_t vkGetBufferOpaqueCaptureAddress(
VkDevice device,
const VkBufferDeviceAddressInfo* pInfo);
or the equivalent command
// Provided by VK_KHR_buffer_device_address
uint64_t vkGetBufferOpaqueCaptureAddressKHR(
VkDevice device,
const VkBufferDeviceAddressInfo* pInfo);
-
device
is the logical device that the buffer was created on. -
pInfo
is a pointer to a VkBufferDeviceAddressInfo structure specifying the buffer to retrieve an address for.
The 64-bit return value is an opaque capture address of the start of
pInfo->buffer
.
If the buffer was created with a non-zero value of
VkBufferOpaqueCaptureAddressCreateInfo::opaqueCaptureAddress
the
return value must be the same address.
The VkStridedDeviceAddressRegionKHR
structure is defined as:
// Provided by VK_KHR_ray_tracing_pipeline
typedef struct VkStridedDeviceAddressRegionKHR {
VkDeviceAddress deviceAddress;
VkDeviceSize stride;
VkDeviceSize size;
} VkStridedDeviceAddressRegionKHR;
-
deviceAddress
is the device address (as returned by the vkGetBufferDeviceAddress command) at which the region starts, or zero if the region is unused. -
stride
is the byte stride between consecutive elements. -
size
is the size in bytes of the region starting atdeviceAddress
.
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.
To determine the amount of memory needed to store all descriptors with a given layout, call:
// Provided by VK_EXT_descriptor_buffer
void vkGetDescriptorSetLayoutSizeEXT(
VkDevice device,
VkDescriptorSetLayout layout,
VkDeviceSize* pLayoutSizeInBytes);
-
device
is the logical device that gets the size. -
layout
is the descriptor set layout being queried. -
pLayoutSizeInBytes
is a pointer toVkDeviceSize
where the size in bytes will be written.
The size of a descriptor set layout will be at least as large as the sum total of the size of all descriptors in the layout, and may be larger. This size represents the amount of memory that will be required to store all of the descriptors for this layout in memory, when placed according to the layout’s offsets as obtained by vkGetDescriptorSetLayoutBindingOffsetEXT.
If any binding
in layout
is
VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT
, the returned size
includes space for the maximum descriptorCount
descriptors as declared
for that binding
.
To compute the required size of a descriptor set with a
VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT
:
-
size = offset + descriptorSize × variableDescriptorCount
where offset is obtained by
vkGetDescriptorSetLayoutBindingOffsetEXT and descriptorSize is
the size of the relevant descriptor as obtained from
VkPhysicalDeviceDescriptorBufferPropertiesEXT, and
variableDescriptorCount is the equivalent of
VkDescriptorSetVariableDescriptorCountAllocateInfo::pDescriptorCounts
.
For VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK
,
variableDescriptorCount is the size in bytes for the inline uniform
block, and descriptorSize is 1.
If
VkPhysicalDeviceDescriptorBufferPropertiesEXT::combinedImageSamplerDescriptorSingleArray
is VK_FALSE
and the variable descriptor type is
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
,
variableDescriptorCount is always considered to be the upper bound.
To get the offset of a binding within a descriptor set layout in memory, call:
// Provided by VK_EXT_descriptor_buffer
void vkGetDescriptorSetLayoutBindingOffsetEXT(
VkDevice device,
VkDescriptorSetLayout layout,
uint32_t binding,
VkDeviceSize* pOffset);
-
device
is the logical device that gets the offset. -
layout
is the descriptor set layout being queried. -
binding
is the binding number being queried. -
pOffset
is a pointer toVkDeviceSize
where the byte offset of the binding will be written.
Each binding in a descriptor set layout is assigned an offset in memory by the implementation. When a shader accesses a resource with that binding, it will access the bound descriptor buffer from that offset to look for its descriptor. This command provides an application with that offset, so that descriptors can be placed in the correct locations. The precise location accessed by a shader for a given descriptor is as follows:
-
location = bufferAddress + setOffset + descriptorOffset + (arrayElement × descriptorSize)
where bufferAddress and setOffset are the base address and
offset for the identified descriptor set as specified by
vkCmdBindDescriptorBuffersEXT and
vkCmdSetDescriptorBufferOffsetsEXT, descriptorOffset is the
offset for the binding returned by this command, arrayElement is the
index into the array specified in the shader, and descriptorSize is
the size of the relevant descriptor as obtained from
VkPhysicalDeviceDescriptorBufferPropertiesEXT.
Applications are responsible for placing valid descriptors at the expected
location in order for a shader to access it.
The overall offset added to bufferAddress to calculate location
must be less than
VkPhysicalDeviceDescriptorBufferPropertiesEXT::maxSamplerDescriptorBufferRange
for samplers and
VkPhysicalDeviceDescriptorBufferPropertiesEXT::maxResourceDescriptorBufferRange
for resources.
If any binding
in layout
is
VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT
, that
binding
must have the largest offset of any binding
.
A descriptor binding
with type VK_DESCRIPTOR_TYPE_MUTABLE_VALVE
can be used.
Any potential types in
VkMutableDescriptorTypeCreateInfoVALVE::pDescriptorTypes
for
binding
share the same offset.
If the size of the mutable descriptor is larger
than the size of a concrete descriptor type being accessed, the padding area
is ignored by the implementation.
To get descriptor data to place in a buffer, call:
// Provided by VK_EXT_descriptor_buffer
void vkGetDescriptorEXT(
VkDevice device,
const VkDescriptorGetInfoEXT* pDescriptorInfo,
size_t dataSize,
void* pDescriptor);
-
device
is the logical device that gets the descriptor. -
pDescriptorInfo
is a pointer to a VkDescriptorGetInfoEXT structure specifying the parameters of the descriptor to get. -
dataSize
is the amount of the descriptor data to get in bytes. -
pDescriptor
is a pointer to an application-allocated buffer where the descriptor will be written.
The size of the data for each descriptor type is determined by the value in VkPhysicalDeviceDescriptorBufferPropertiesEXT. This value also defines the stride in bytes for arrays of that descriptor type.
If the
VkPhysicalDeviceDescriptorBufferPropertiesEXT::combinedImageSamplerDescriptorSingleArray
property is VK_FALSE
the implementation requires an array of
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
descriptors to be written
into a descriptor buffer as an array of image descriptors, immediately
followed by an array of sampler descriptors.
Applications must write the first
VkPhysicalDeviceDescriptorBufferPropertiesEXT::sampledImageDescriptorSize
bytes of the data returned through pDescriptor
to the first array, and
the remaining
VkPhysicalDeviceDescriptorBufferPropertiesEXT::samplerDescriptorSize
bytes of the data to the second array.
For variable-sized descriptor bindings of
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
descriptors, the two arrays
each have a size equal to the upper bound descriptorCount
of that
binding.
A descriptor obtained by this command references the underlying VkImageView or VkSampler, and these objects must not be destroyed before the last time a descriptor is dynamically accessed. For descriptor types which consume an address instead of an object, the underlying VkBuffer is referenced instead.
Information about the descriptor to get is passed in a
VkDescriptorGetInfoEXT
structure:
// Provided by VK_EXT_descriptor_buffer
typedef struct VkDescriptorGetInfoEXT {
VkStructureType sType;
const void* pNext;
VkDescriptorType type;
VkDescriptorDataEXT data;
} VkDescriptorGetInfoEXT;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
type
is the type of descriptor to get. -
data
is a structure containing the information needed to get the descriptor.
Data describing the descriptor is passed in a VkDescriptorDataEXT
structure:
// Provided by VK_EXT_descriptor_buffer
typedef union VkDescriptorDataEXT {
const VkSampler* pSampler;
const VkDescriptorImageInfo* pCombinedImageSampler;
const VkDescriptorImageInfo* pInputAttachmentImage;
const VkDescriptorImageInfo* pSampledImage;
const VkDescriptorImageInfo* pStorageImage;
const VkDescriptorAddressInfoEXT* pUniformTexelBuffer;
const VkDescriptorAddressInfoEXT* pStorageTexelBuffer;
const VkDescriptorAddressInfoEXT* pUniformBuffer;
const VkDescriptorAddressInfoEXT* pStorageBuffer;
VkDeviceAddress accelerationStructure;
} VkDescriptorDataEXT;
-
pSampler
is a pointer to a VkSampler handle specifying the parameters of aVK_DESCRIPTOR_TYPE_SAMPLER
descriptor. -
pCombinedImageSampler
is a pointer to a VkDescriptorImageInfo structure specifying the parameters of aVK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
descriptor. -
pInputAttachmentImage
is a pointer to a VkDescriptorImageInfo structure specifying the parameters of aVK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT
descriptor. -
pSampledImage
is a pointer to a VkDescriptorImageInfo structure specifying the parameters of aVK_DESCRIPTOR_TYPE_SAMPLED_IMAGE
descriptor. -
pStorageImage
is a pointer to a VkDescriptorImageInfo structure specifying the parameters of aVK_DESCRIPTOR_TYPE_STORAGE_IMAGE
descriptor. -
pUniformTexelBuffer
is a pointer to a VkDescriptorAddressInfoEXT structure specifying the parameters of aVK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER
descriptor. -
pStorageTexelBuffer
is a pointer to a VkDescriptorAddressInfoEXT structure specifying the parameters of aVK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER
descriptor. -
pUniformBuffer
is a pointer to a VkDescriptorAddressInfoEXT structure specifying the parameters of aVK_DESCRIPTOR_TYPE_UNIFORM_BUFFER
descriptor. -
pStorageBuffer
is a pointer to a VkDescriptorAddressInfoEXT structure specifying the parameters of aVK_DESCRIPTOR_TYPE_STORAGE_BUFFER
descriptor. -
accelerationStructure
is the address of a VkAccelerationStructureKHR specifying the parameters of aVK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR
descriptor , or a VkAccelerationStructureNV handle specifying the parameters of aVK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV
descriptor.
If the nullDescriptor
feature is enabled,
pSampledImage
, pStorageImage
, pUniformTexelBuffer
,
pStorageTexelBuffer
, pUniformBuffer
, and pStorageBuffer
can each be NULL
.
Loads from a null descriptor return zero values and stores and atomics to a
null descriptor are discarded.
If the nullDescriptor
feature is enabled,
accelerationStructure
can be 0
.
A null acceleration structure descriptor results in the miss shader being
invoked.
Data describing a VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER
,
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER
,
VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER
, or
VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER
descriptor is passed in a
VkDescriptorAddressInfoEXT
structure:
// Provided by VK_EXT_descriptor_buffer
typedef struct VkDescriptorAddressInfoEXT {
VkStructureType sType;
void* pNext;
VkDeviceAddress address;
VkDeviceSize range;
VkFormat format;
} VkDescriptorAddressInfoEXT;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
address
is either0
or a device address at an offset in a buffer, where the base address can be queried from vkGetBufferDeviceAddress. -
range
is the size in bytes of the buffer or buffer view used by the descriptor. -
format
is the format of the data elements in the buffer view and is ignored for buffers.
If the nullDescriptor
feature is enabled,
address
can be zero.
Loads from a null descriptor return zero values and stores and atomics to a
null descriptor are discarded.
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
|
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.
To bind descriptor buffers to a command buffer, call:
// Provided by VK_EXT_descriptor_buffer
void vkCmdBindDescriptorBuffersEXT(
VkCommandBuffer commandBuffer,
uint32_t bufferCount,
const VkDescriptorBufferBindingInfoEXT* pBindingInfos);
-
commandBuffer
is the command buffer that the descriptor buffers will be bound to. -
bufferCount
is the number of elements in thepBindingInfos
array. -
pBindingInfos
is a pointer to an array of VkDescriptorBufferBindingInfoEXT structures.
vkCmdBindDescriptorBuffersEXT
causes any offsets previously set by
vkCmdSetDescriptorBufferOffsetsEXT that use the bindings numbered
[0
..
bufferCount
-1] to be no longer valid for subsequent bound pipeline
commands.
Any previously bound buffers at binding points greater than or equal to
bufferCount
are unbound.
Data describing a descriptor buffer binding is passed in a
VkDescriptorBufferBindingInfoEXT
structure:
// Provided by VK_EXT_descriptor_buffer
typedef struct VkDescriptorBufferBindingInfoEXT {
VkStructureType sType;
const void* pNext;
VkDeviceAddress address;
VkBufferUsageFlags usage;
} VkDescriptorBufferBindingInfoEXT;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
address
is aVkDeviceAddress
specifying the device address defining the descriptor buffer to be bound. -
usage
is a bitmask of VkBufferUsageFlagBits specifying the VkBufferCreateInfo::usage
for the buffer from whichaddress
was queried.
If the pNext
chain includes a VkBufferUsageFlags2CreateInfo
structure, VkBufferUsageFlags2CreateInfo::usage
from that
structure is used instead of usage
from this structure.
When the VkPhysicalDeviceDescriptorBufferPropertiesEXT
::bufferlessPushDescriptors
property is VK_FALSE
, the VkBuffer
handle of the buffer for push
descriptors is passed in a
VkDescriptorBufferBindingPushDescriptorBufferHandleEXT
structure:
// Provided by VK_EXT_descriptor_buffer
typedef struct VkDescriptorBufferBindingPushDescriptorBufferHandleEXT {
VkStructureType sType;
const void* pNext;
VkBuffer buffer;
} VkDescriptorBufferBindingPushDescriptorBufferHandleEXT;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
buffer
is theVkBuffer
handle of the buffer for push descriptors.
To set descriptor buffer offsets in a command buffer, call:
// Provided by VK_EXT_descriptor_buffer
void vkCmdSetDescriptorBufferOffsetsEXT(
VkCommandBuffer commandBuffer,
VkPipelineBindPoint pipelineBindPoint,
VkPipelineLayout layout,
uint32_t firstSet,
uint32_t setCount,
const uint32_t* pBufferIndices,
const VkDeviceSize* pOffsets);
-
commandBuffer
is the command buffer in which the descriptor buffer offsets will be set. -
pipelineBindPoint
is a VkPipelineBindPoint indicating the type of the pipeline that will use the descriptors. -
layout
is a VkPipelineLayout object used to program the bindings. -
firstSet
is the number of the first set to be bound. -
setCount
is the number of elements in thepBufferIndices
andpOffsets
arrays. -
pBufferIndices
is a pointer to an array of indices into the descriptor buffer binding points set by vkCmdBindDescriptorBuffersEXT. -
pOffsets
is a pointer to an array ofVkDeviceSize
offsets to apply to the bound descriptor buffers.
vkCmdSetDescriptorBufferOffsetsEXT
binds setCount
pairs of
descriptor buffers, specified by indices into the binding points bound using
vkCmdBindDescriptorBuffersEXT, and buffer offsets to set numbers
[firstSet
..firstSet
+descriptorSetCount
-1] for subsequent
bound pipeline commands set by
pipelineBindPoint
.
Set [firstSet
+ i] is bound to the descriptor buffer at binding
pBufferIndices
[i] at an offset of pOffsets
[i].
Any bindings that were previously applied via these sets, or calls to
vkCmdBindDescriptorSets, are no longer valid.
Other sets will also be invalidated upon calling this command if
layout
differs from the pipeline layout used to bind those other sets,
as described in Pipeline Layout Compatibility.
After binding descriptors, applications can modify descriptor memory either
by performing writes on the host or with device commands.
When descriptor memory is updated with device commands, visibility for the
shader stage accessing a descriptor is ensured with the
VK_ACCESS_2_DESCRIPTOR_BUFFER_READ_BIT_EXT
access flag.
Implementations must not access resources referenced by these descriptors
unless they are dynamically accessed by shaders.
Descriptors bound with this call can be undefined if they are not
dynamically accessed by shaders.
Implementations may read descriptor data for any statically accessed
descriptor if the binding
in layout
is not declared with the
VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT
flag.
If the binding
in layout
is declared with
VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT
, implementations
must not read descriptor data that is not dynamically accessed.
Applications must ensure that any descriptor which the implementation may read must be in-bounds of the underlying descriptor buffer binding.
Applications can freely decide how large a variable descriptor buffer binding is, so it may not be safe to read such descriptor payloads statically. The intention of these rules is to allow implementations to speculatively prefetch descriptor payloads where feasible. |
Dynamically accessing a resource through descriptor data from an unbound region of a sparse partially-resident buffer will result in invalid descriptor data being read, and therefore undefined behavior.
For descriptors written by the host, visibility is implied through the
automatic visibility operation on queue submit, and there is no need to
consider |
The requirements above imply that all descriptor bindings have been defined
with the equivalent of |
Alternatively, to set descriptor buffer offsets in a command buffer, call:
// Provided by VK_KHR_maintenance6 with VK_EXT_descriptor_buffer
void vkCmdSetDescriptorBufferOffsets2EXT(
VkCommandBuffer commandBuffer,
const VkSetDescriptorBufferOffsetsInfoEXT* pSetDescriptorBufferOffsetsInfo);
-
commandBuffer
is the command buffer in which the descriptor buffer offsets will be set. -
pSetDescriptorBufferOffsetsInfo
is a pointer to aVkSetDescriptorBufferOffsetsInfoEXT
structure.
The VkSetDescriptorBufferOffsetsInfoEXT
structure is defined as:
// Provided by VK_KHR_maintenance6 with VK_EXT_descriptor_buffer
typedef struct VkSetDescriptorBufferOffsetsInfoEXT {
VkStructureType sType;
const void* pNext;
VkShaderStageFlags stageFlags;
VkPipelineLayout layout;
uint32_t firstSet;
uint32_t setCount;
const uint32_t* pBufferIndices;
const VkDeviceSize* pOffsets;
} VkSetDescriptorBufferOffsetsInfoEXT;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
stageFlags
is a bitmask of VkShaderStageFlagBits specifying the shader stages the descriptor sets will be bound to -
layout
is a VkPipelineLayout object used to program the bindings. If thedynamicPipelineLayout
feature is enabled,layout
can be VK_NULL_HANDLE and the layout must be specified by chaining VkPipelineLayoutCreateInfo structure off thepNext
-
firstSet
is the number of the first set to be bound. -
setCount
is the number of elements in thepBufferIndices
andpOffsets
arrays. -
pBufferIndices
is a pointer to an array of indices into the descriptor buffer binding points set by vkCmdBindDescriptorBuffersEXT. -
pOffsets
is a pointer to an array ofVkDeviceSize
offsets to apply to the bound descriptor buffers.
If stageFlags
specifies a subset of all stages corresponding to one or
more pipeline bind points, the binding operation still affects all stages
corresponding to the given pipeline bind point(s) as if the equivalent
original version of this command had been called with the same parameters.
For example, specifying a stageFlags
value of
VK_SHADER_STAGE_VERTEX_BIT
| VK_SHADER_STAGE_FRAGMENT_BIT
|
VK_SHADER_STAGE_COMPUTE_BIT
is equivalent to calling the original
version of this command once with VK_PIPELINE_BIND_POINT_GRAPHICS
and
once with VK_PIPELINE_BIND_POINT_COMPUTE
.
To bind an embedded immutable sampler set to a command buffer, call:
// Provided by VK_EXT_descriptor_buffer
void vkCmdBindDescriptorBufferEmbeddedSamplersEXT(
VkCommandBuffer commandBuffer,
VkPipelineBindPoint pipelineBindPoint,
VkPipelineLayout layout,
uint32_t set);
-
commandBuffer
is the command buffer that the embedded immutable samplers will be bound to. -
pipelineBindPoint
is a VkPipelineBindPoint indicating the type of the pipeline that will use the embedded immutable samplers. -
layout
is a VkPipelineLayout object used to program the bindings. -
set
is the number of the set to be bound.
vkCmdBindDescriptorBufferEmbeddedSamplersEXT
binds the embedded immutable
samplers in set
of layout
to set
for the command buffer
for subsequent bound pipeline commands set
by pipelineBindPoint
.
Any previous binding to this set by vkCmdSetDescriptorBufferOffsetsEXT
or this command is overwritten.
Any sets that were last bound by a call to vkCmdBindDescriptorSets are
invalidated upon calling this command.
Other sets will also be invalidated upon calling this command if
layout
differs from the pipeline layout used to bind those other sets,
as described in Pipeline Layout Compatibility.
Alternatively, to bind an embedded immutable sampler set to a command buffer, call:
// Provided by VK_KHR_maintenance6 with VK_EXT_descriptor_buffer
void vkCmdBindDescriptorBufferEmbeddedSamplers2EXT(
VkCommandBuffer commandBuffer,
const VkBindDescriptorBufferEmbeddedSamplersInfoEXT* pBindDescriptorBufferEmbeddedSamplersInfo);
-
commandBuffer
is the command buffer that the embedded immutable samplers will be bound to. -
pBindDescriptorBufferEmbeddedSamplersInfo
is a pointer to aVkBindDescriptorBufferEmbeddedSamplersInfoEXT
structure.
The VkBindDescriptorBufferEmbeddedSamplersInfoEXT
structure is defined
as:
// Provided by VK_KHR_maintenance6 with VK_EXT_descriptor_buffer
typedef struct VkBindDescriptorBufferEmbeddedSamplersInfoEXT {
VkStructureType sType;
const void* pNext;
VkShaderStageFlags stageFlags;
VkPipelineLayout layout;
uint32_t set;
} VkBindDescriptorBufferEmbeddedSamplersInfoEXT;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
stageFlags
is a bitmask of VkShaderStageFlagBits specifying the shader stages that will use the embedded immutable samplers. -
layout
is a VkPipelineLayout object used to program the bindings. If thedynamicPipelineLayout
feature is enabled,layout
can be VK_NULL_HANDLE and the layout must be specified by chaining VkPipelineLayoutCreateInfo structure off thepNext
-
set
is the number of the set to be bound.
If stageFlags
specifies a subset of all stages corresponding to one or
more pipeline bind points, the binding operation still affects all stages
corresponding to the given pipeline bind point(s) as if the equivalent
original version of this command had been called with the same parameters.
For example, specifying a stageFlags
value of
VK_SHADER_STAGE_VERTEX_BIT
| VK_SHADER_STAGE_FRAGMENT_BIT
|
VK_SHADER_STAGE_COMPUTE_BIT
is equivalent to calling the original
version of this command once with VK_PIPELINE_BIND_POINT_GRAPHICS
and
once with VK_PIPELINE_BIND_POINT_COMPUTE
.
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.
To get the opaque descriptor data for a buffer, call:
// Provided by VK_EXT_descriptor_buffer
VkResult vkGetBufferOpaqueCaptureDescriptorDataEXT(
VkDevice device,
const VkBufferCaptureDescriptorDataInfoEXT* pInfo,
void* pData);
-
device
is the logical device that gets the data. -
pInfo
is a pointer to a VkBufferCaptureDescriptorDataInfoEXT structure specifying the buffer. -
pData
is a pointer to an application-allocated buffer where the data will be written.
Information about the buffer to get descriptor buffer capture data for is
passed in a VkBufferCaptureDescriptorDataInfoEXT
structure:
// Provided by VK_EXT_descriptor_buffer
typedef struct VkBufferCaptureDescriptorDataInfoEXT {
VkStructureType sType;
const void* pNext;
VkBuffer buffer;
} VkBufferCaptureDescriptorDataInfoEXT;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
buffer
is theVkBuffer
handle of the buffer to get opaque capture data for.
To get the opaque capture descriptor data for an image, call:
// Provided by VK_EXT_descriptor_buffer
VkResult vkGetImageOpaqueCaptureDescriptorDataEXT(
VkDevice device,
const VkImageCaptureDescriptorDataInfoEXT* pInfo,
void* pData);
-
device
is the logical device that gets the data. -
pInfo
is a pointer to a VkImageCaptureDescriptorDataInfoEXT structure specifying the image. -
pData
is a pointer to an application-allocated buffer where the data will be written.
Information about the image to get descriptor buffer capture data for is
passed in a VkImageCaptureDescriptorDataInfoEXT
structure:
// Provided by VK_EXT_descriptor_buffer
typedef struct VkImageCaptureDescriptorDataInfoEXT {
VkStructureType sType;
const void* pNext;
VkImage image;
} VkImageCaptureDescriptorDataInfoEXT;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
image
is theVkImage
handle of the image to get opaque capture data for.
To get the opaque capture descriptor data for an image view, call:
// Provided by VK_EXT_descriptor_buffer
VkResult vkGetImageViewOpaqueCaptureDescriptorDataEXT(
VkDevice device,
const VkImageViewCaptureDescriptorDataInfoEXT* pInfo,
void* pData);
-
device
is the logical device that gets the data. -
pInfo
is a pointer to a VkImageViewCaptureDescriptorDataInfoEXT structure specifying the image view. -
pData
is a pointer to an application-allocated buffer where the data will be written.
Information about the image view to get descriptor buffer capture data for
is passed in a VkImageViewCaptureDescriptorDataInfoEXT
structure:
// Provided by VK_EXT_descriptor_buffer
typedef struct VkImageViewCaptureDescriptorDataInfoEXT {
VkStructureType sType;
const void* pNext;
VkImageView imageView;
} VkImageViewCaptureDescriptorDataInfoEXT;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
imageView
is theVkImageView
handle of the image view to get opaque capture data for.
To get the opaque capture descriptor data for a sampler, call:
// Provided by VK_EXT_descriptor_buffer
VkResult vkGetSamplerOpaqueCaptureDescriptorDataEXT(
VkDevice device,
const VkSamplerCaptureDescriptorDataInfoEXT* pInfo,
void* pData);
-
device
is the logical device that gets the data. -
pInfo
is a pointer to a VkSamplerCaptureDescriptorDataInfoEXT structure specifying the sampler. -
pData
is a pointer to an application-allocated buffer where the data will be written.
Information about the sampler to get descriptor buffer capture data for is
passed in a VkSamplerCaptureDescriptorDataInfoEXT
structure:
// Provided by VK_EXT_descriptor_buffer
typedef struct VkSamplerCaptureDescriptorDataInfoEXT {
VkStructureType sType;
const void* pNext;
VkSampler sampler;
} VkSamplerCaptureDescriptorDataInfoEXT;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
sampler
is theVkSampler
handle of the sampler to get opaque capture data for.
To get the opaque capture descriptor data for an acceleration structure, call:
// Provided by VK_EXT_descriptor_buffer with VK_KHR_acceleration_structure or VK_NV_ray_tracing
VkResult vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT(
VkDevice device,
const VkAccelerationStructureCaptureDescriptorDataInfoEXT* pInfo,
void* pData);
-
device
is the logical device that gets the data. -
pInfo
is a pointer to a VkAccelerationStructureCaptureDescriptorDataInfoEXT structure specifying the acceleration structure. -
pData
is a pointer to an application-allocated buffer where the data will be written.
Information about the acceleration structure to get descriptor buffer
capture data for is passed in a
VkAccelerationStructureCaptureDescriptorDataInfoEXT
structure:
// Provided by VK_EXT_descriptor_buffer with VK_KHR_acceleration_structure or VK_NV_ray_tracing
typedef struct VkAccelerationStructureCaptureDescriptorDataInfoEXT {
VkStructureType sType;
const void* pNext;
VkAccelerationStructureKHR accelerationStructure;
VkAccelerationStructureNV accelerationStructureNV;
} VkAccelerationStructureCaptureDescriptorDataInfoEXT;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
accelerationStructure
is theVkAccelerationStructureKHR
handle of the acceleration structure to get opaque capture data for. -
accelerationStructureNV
is theVkAccelerationStructureNV
handle of the acceleration structure to get opaque capture data for.
The VkOpaqueCaptureDescriptorDataCreateInfoEXT
structure is defined
as:
// Provided by VK_EXT_descriptor_buffer
typedef struct VkOpaqueCaptureDescriptorDataCreateInfoEXT {
VkStructureType sType;
const void* pNext;
const void* opaqueCaptureDescriptorData;
} VkOpaqueCaptureDescriptorDataCreateInfoEXT;
-
sType
is a VkStructureType value identifying this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
opaqueCaptureDescriptorData
is a pointer to an application-allocated buffer containing opaque capture data retrieved using vkGetBufferOpaqueCaptureDescriptorDataEXT, vkGetImageOpaqueCaptureDescriptorDataEXT, vkGetImageViewOpaqueCaptureDescriptorDataEXT, vkGetSamplerOpaqueCaptureDescriptorDataEXT, or vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT.
During replay, opaque descriptor capture data can be specified by adding a
VkOpaqueCaptureDescriptorDataCreateInfoEXT
structure to the relevant
pNext
chain of a VkBufferCreateInfo, VkImageCreateInfo,
VkImageViewCreateInfo, VkSamplerCreateInfo,
VkAccelerationStructureCreateInfoNV or
VkAccelerationStructureCreateInfoKHR structure.