13. 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 organised into descriptor sets, which are bound during
command recording for use in subsequent draw 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.
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.
13.1. 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.
13.1.1. 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 compute shaders for image views
whose format features contain
VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT
.
Atomic operations on storage images are supported in 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.
13.1.2. 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.
13.1.3. 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
.
The image subresources for a sampled image must be in the
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_STENCIL_READ_ONLY_OPTIMAL
,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
, or
VK_IMAGE_LAYOUT_GENERAL
layout in order to access its data in a
shader.
13.1.4. 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.
The image subresources for a combined image sampler must be in the
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_STENCIL_READ_ONLY_OPTIMAL
,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
, or
VK_IMAGE_LAYOUT_GENERAL
layout in order to access its data in a
shader.
Note
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. |
13.1.5. 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 formatted load
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 image formats which report support for the
VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT
feature bit via vkGetPhysicalDeviceFormatProperties in
VkFormatProperties::bufferFeatures
.
13.1.6. 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 formatted
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 formats which report support for the
VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT
feature bit via vkGetPhysicalDeviceFormatProperties in
VkFormatProperties::bufferFeatures
.
Stores to storage texel buffers are supported in compute shaders for texel
buffer formats which report support for the
VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT
feature via
vkGetPhysicalDeviceFormatProperties in
VkFormatProperties::bufferFeatures
.
Atomic operations on storage texel buffers are supported in compute shaders
for texel buffer formats which report support for the
VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT
feature via vkGetPhysicalDeviceFormatProperties in
VkFormatProperties::bufferFeatures
.
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.
13.1.7. 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.
Note
Atomic operations can only be performed on members of certain types as defined in the SPIR-V environment appendix. |
13.1.8. 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.
13.1.9. 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.
13.1.10. 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.
13.1.11. Inline Uniform Block
An inline uniform block
(VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT
) 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 draw and dispatch 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.
13.1.12. 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 depth/stencil attachments
(VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT
) for a given image
tiling mode are also supported for input attachments.
The image subresources for an input attachment must be in the
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_STENCIL_READ_ONLY_OPTIMAL
,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
, or
VK_IMAGE_LAYOUT_GENERAL
layout in order to access its data in a
shader.
13.2. 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.
13.2.1. 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 the type of 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.
Bits which can be set in VkDescriptorSetLayoutCreateInfo::flags
to specify 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_KHR_push_descriptor
VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR = 0x00000001,
// 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,
} VkDescriptorSetLayoutCreateFlagBits;
-
VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR
specifies that descriptor sets must not be allocated using this layout, and descriptors are instead pushed by vkCmdPushDescriptorSetKHR. -
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.
// 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_EXT
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 points 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.
Note
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 the type of 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
to
specify 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
indicates 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
indicates 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. -
VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT
indicates 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. 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
indicates that this descriptor binding has a variable size that 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_EXT
wheredescriptorCount
specifies the upper bound on the byte size of the binding, thus it counts against themaxInlineUniformBlockSize
limit instead. .
Note
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.
Note
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 the type of this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
supported
specifies whether the descriptor set layout can be created.
supported
is set to VK_TRUE
if the descriptor set can be
created, or else is set to 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 the type of 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_EXT
thenmaxVariableDescriptorCount
indicates the maximum byte size supported for the binding, if that binding is variable-sized.
If the create info includes a variable-sized descriptor, then
supported
is determined assuming the requested size of the
variable-sized descriptor, and maxVariableDescriptorCount
is set to
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 create info does not include a variable-sized descriptor or if the
VkPhysicalDeviceDescriptorIndexingFeatures::descriptorBindingVariableDescriptorCount
feature is not enabled, then maxVariableDescriptorCount
is set to
zero.
For the purposes of this command, a variable-sized descriptor binding with a
descriptorCount
of zero is treated as if the descriptorCount
is
one, 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
{
0, // binding
VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, // descriptorType
1, // descriptorCount
VK_SHADER_STAGE_FRAGMENT_BIT, // stageFlags
NULL // pImmutableSamplers
},
// binding to an array of image descriptors
{
1, // binding
VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, // descriptorType
12, // descriptorCount
VK_SHADER_STAGE_FRAGMENT_BIT, // stageFlags
NULL // pImmutableSamplers
},
// binding to a single uniform buffer descriptor
{
0, // binding
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, // descriptorType
1, // descriptorCount
VK_SHADER_STAGE_FRAGMENT_BIT, // stageFlags
NULL // pImmutableSamplers
}
};
const VkDescriptorSetLayoutCreateInfo myDescriptorSetLayoutCreateInfo[] =
{
// Create info for first descriptor set with two descriptor bindings
{
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // sType
NULL, // pNext
0, // flags
2, // bindingCount
&myDescriptorSetLayoutBinding[0] // pBindings
},
// Create info for second descriptor set with one descriptor binding
{
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // sType
NULL, // pNext
0, // flags
1, // bindingCount
&myDescriptorSetLayoutBinding[2] // pBindings
}
};
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.
13.2.2. 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 the type of this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
flags
is reserved for future use. -
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.NotePush constants represent a high speed path to modify constant data in pipelines that is expected to outperform memory-backed resource updates.
// Provided by VK_VERSION_1_0
typedef VkFlags VkPipelineLayoutCreateFlags;
VkPipelineLayoutCreateFlags
is a bitmask type for setting a mask, but
is currently reserved for future use.
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, or that are dead-code eliminated from any of the shaders.
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, or for which the variables have been
dead-code eliminated from any of the shaders.
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, and if they were created with identical push constant ranges.
When binding a descriptor set (see Descriptor Set Binding) to set number N, if the previously bound descriptor sets for sets zero through N-1 were all bound using compatible pipeline layouts, then performing this binding does not disturb any of the lower numbered sets. If, additionally, the previous bound descriptor set for set N was bound using a pipeline layout compatible for set N, then the bindings in sets numbered greater than N are also not disturbed.
Similarly, when binding a pipeline, the pipeline can correctly access any previously bound descriptor sets which were bound with compatible pipeline layouts, as long as all lower numbered sets were also bound with compatible layouts.
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.
Note
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[] =
{
{
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, // stageFlags
0, // offset
4 // size
},
{
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // stageFlags
4, // offset
4 // size
},
};
const VkPipelineLayoutCreateInfo createInfo =
{
VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType
NULL, // pNext
0, // flags
2, // setLayoutCount
layouts, // pSetLayouts
2, // pushConstantRangeCount
ranges // pPushConstantRanges
};
VkPipelineLayout myPipelineLayout;
myResult = vkCreatePipelineLayout(
myDevice,
&createInfo,
NULL,
&myPipelineLayout);
13.2.3. 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.
pAllocator
controls host memory allocation as described in the
Memory Allocation chapter.
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 the type of 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 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.
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_EXT
.
This can be done by adding a
VkDescriptorPoolInlineUniformBlockCreateInfoEXT
structure to the
pNext
chain of VkDescriptorPoolCreateInfo.
The VkDescriptorPoolInlineUniformBlockCreateInfoEXT
structure is
defined as:
// Provided by VK_EXT_inline_uniform_block
typedef struct VkDescriptorPoolInlineUniformBlockCreateInfoEXT {
VkStructureType sType;
const void* pNext;
uint32_t maxInlineUniformBlockBindings;
} VkDescriptorPoolInlineUniformBlockCreateInfoEXT;
-
sType
is the type of 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
to
enable 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_descriptor_indexing
VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT,
} 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.
// 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_EXT
thendescriptorCount
is the number of bytes to allocate for descriptors of this type.
Note
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 |
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. Descriptors also become undefined if the underlying resource 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_EXT
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
member
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
VkDescriptorPoolInlineUniformBlockCreateInfoEXT::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 the type of 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 descriptor count 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 the type of 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 descriptor count 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 count descriptor binding in the corresponding descriptor set
layout.
If the variable count descriptor binding in the corresponding descriptor set
layout has a descriptor type of
VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT
then
pDescriptorCounts
[i] specifies the binding’s capacity in bytes.
If VkDescriptorSetAllocateInfo::pSetLayouts
[i] does not include
a variable count 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.
13.2.4. 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 the type of 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_EXT
thendstArrayElement
specifies the starting byte offset within the binding. -
descriptorCount
is the number of descriptors to update (the number of elements inpImageInfo
,pBufferInfo
, orpTexelBufferView
, or a value matching thedataSize
member of a VkWriteDescriptorSetInlineUniformBlockEXT structure in thepNext
chain , or a value matching theaccelerationStructureCount
of a VkWriteDescriptorSetAccelerationStructureKHR structure in thepNext
chain ). If the descriptor binding identified bydstSet
anddstBinding
has a descriptor type ofVK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT
thendescriptorCount
specifies the number of bytes to update. -
descriptorType
is a VkDescriptorType specifying the type of each descriptor inpImageInfo
,pBufferInfo
, orpTexelBufferView
, as described below. It must be the same type as that 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_EXT
, in which case the source
data for the descriptor writes is taken from the
VkWriteDescriptorSetInlineUniformBlockEXT 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
,
as specified below.
If the nullDescriptor feature is enabled, the buffer, 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.
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.
Note
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_EXT_inline_uniform_block
VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT = 1000138000,
// Provided by VK_KHR_ray_tracing
VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR = 1000165000,
// Provided by VK_NV_ray_tracing
VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR,
} 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_EXT
specifies an inline uniform block.
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_EXT
, none of the
pImageInfo
, pBufferInfo
, or pTexelBufferView
members are
accessed, instead the source data of the descriptor update operation is
taken from the VkWriteDescriptorSetInlineUniformBlockEXT 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
.
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.
Note
When setting |
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.
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_EXT
then the data to write to
the descriptor set is specified through a
VkWriteDescriptorSetInlineUniformBlockEXT
structure included in the
pNext
chain of VkWriteDescriptorSet
.
The VkWriteDescriptorSetInlineUniformBlockEXT
structure is defined as:
// Provided by VK_EXT_inline_uniform_block
typedef struct VkWriteDescriptorSetInlineUniformBlockEXT {
VkStructureType sType;
const void* pNext;
uint32_t dataSize;
const void* pData;
} VkWriteDescriptorSetInlineUniformBlockEXT;
-
sType
is the type of 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_ray_tracing
typedef struct VkWriteDescriptorSetAccelerationStructureKHR {
VkStructureType sType;
const void* pNext;
uint32_t accelerationStructureCount;
const VkAccelerationStructureKHR* pAccelerationStructures;
} VkWriteDescriptorSetAccelerationStructureKHR;
or the equivalent
// Provided by VK_NV_ray_tracing
typedef VkWriteDescriptorSetAccelerationStructureKHR VkWriteDescriptorSetAccelerationStructureNV;
-
sType
is the type of this structure. -
pNext
isNULL
or a pointer to a structure extending this structure. -
accelerationStructureCount
is the number of elements inpAccelerationStructures
. -
pAccelerationStructures
are 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 the type of 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_EXT
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_EXT
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_EXT
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.
13.2.5. 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;
13.2.6. 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 that, in conjunction with vkUpdateDescriptorSetWithTemplate
or vkCmdPushDescriptorSetWithTemplateKHR
, can be more efficient compared to calling vkUpdateDescriptorSets
or vkCmdPushDescriptorSetKHR
.
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 vkUpdateDescriptorSetWithTemplate
or vkCmdPushDescriptorSetWithTemplateKHR
.
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 vkCmdPushDescriptorSetWithTemplateKHR 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 the type of 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_KHR
it can only be used to push descriptor sets using the providedpipelineBindPoint
,pipelineLayout
, andset
number. -
descriptorSetLayout
is the descriptor set layout the parameter update template will be used with. All descriptor sets which are going to be updated through the newly created descriptor update template must be created with this layout.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 whether the descriptors will be used by graphics pipelines or compute pipelines. This parameter is ignored iftemplateType
is notVK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR
-
pipelineLayout
is a VkPipelineLayout object used to program the bindings. This parameter is ignored iftemplateType
is notVK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR
-
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_KHR
// 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_KHR_push_descriptor with VK_VERSION_1_1, VK_KHR_push_descriptor with VK_KHR_descriptor_update_template, VK_KHR_descriptor_update_template with VK_KHR_push_descriptor
VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR = 1,
// 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_KHR
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 bysrcBinding
has a descriptor type ofVK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT
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_EXT
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 informations 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_EXT
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 sets. -
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
{
0, // binding
0, // dstArrayElement
1, // descriptorCount
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, // descriptorType
offsetof(AppDataStructure, imageInfo), // offset
0 // stride is not required if descriptorCount is 1
},
// binding to an array of buffer descriptors
{
1, // binding
0, // dstArrayElement
3, // descriptorCount
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, // descriptorType
offsetof(AppDataStructure, bufferInfoArray), // offset
sizeof(VkDescriptorBufferInfo) // stride, descriptor buffer infos are compact
},
// binding to an array of buffer views
{
2, // binding
0, // dstArrayElement
2, // descriptorCount
VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, // descriptorType
offsetof(AppDataStructure, bufferView) +
offsetof(AppBufferView, bufferView), // offset
sizeof(AppBufferView) // stride, bufferViews do not have to be compact
},
};
// create a descriptor update template for descriptor set updates
const VkDescriptorUpdateTemplateCreateInfo createInfo =
{
VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO, // sType
NULL, // pNext
0, // flags
3, // descriptorUpdateEntryCount
descriptorUpdateTemplateEntries, // pDescriptorUpdateEntries
VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET, // templateType
myLayout, // descriptorSetLayout
0, // pipelineBindPoint, ignored by given templateType
0, // pipelineLayout, ignored by given templateType
0, // set, 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);
13.2.7. 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 whether the descriptors will be used by graphics pipelines or compute pipelines. There is a separate set of bind points for each of graphics and compute, so binding one does not disturb the other. -
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 write 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
causes the sets numbered [firstSet
..
firstSet
+descriptorSetCount
-1] to use the bindings stored in
pDescriptorSets
[0..descriptorSetCount-1] for subsequent rendering
commands (either compute or graphics, according to the
pipelineBindPoint
).
Any bindings that were previously applied via these sets are no longer
valid.
Once bound, a descriptor set affects rendering of subsequent graphics or compute commands in the command buffer until a different set is bound to the same set number, or else until 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 draw or dispatch 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.
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 graphics or compute commands, 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.
13.2.8. 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_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 whether the descriptors will be used by graphics pipelines or compute pipelines. There is a separate set of push descriptor bindings for each of graphics and compute, so binding one does not disturb the other. -
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 rendering commands (either compute or
graphics, according to the 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 draw or dispatch 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.
13.2.9. 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_KHR_push_descriptor with VK_VERSION_1_1, VK_KHR_push_descriptor with VK_KHR_descriptor_update_template, VK_KHR_descriptor_update_template with VK_KHR_push_descriptor
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
{
0, // binding
0, // dstArrayElement
1, // descriptorCount
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, // descriptorType
offsetof(AppDataStructure, imageInfo), // offset
0 // stride is not required if descriptorCount is 1
}
};
// create a descriptor update template for descriptor set updates
const VkDescriptorUpdateTemplateCreateInfo createInfo =
{
VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO, // sType
NULL, // pNext
0, // flags
1, // descriptorUpdateEntryCount
descriptorUpdateTemplateEntries, // pDescriptorUpdateEntries
VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR, // templateType
0, // descriptorSetLayout, ignored by given templateType
VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint
myPipelineLayout, // pipelineLayout
0, // set
};
VkDescriptorUpdateTemplate myDescriptorUpdateTemplate;
myResult = vkCreateDescriptorUpdateTemplate(
myDevice,
&createInfo,
NULL,
&myDescriptorUpdateTemplate);
}
AppDataStructure appData;
// fill appData here or cache it in your engine
vkCmdPushDescriptorSetWithTemplateKHR(myCmdBuffer, myDescriptorUpdateTemplate, myPipelineLayout, 0,&appData);
13.2.10. 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.
Note
Push constants represent a high speed path to modify constant data in pipelines that is expected to outperform memory-backed resource updates. |
The values of push constants are undefined at the start of a command buffer.
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.
Note
As |
13.3. 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 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 the type of 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.