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.1.13. Acceleration Structure
An acceleration structure
(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV) is a descriptor type
that is used to retrieve scene geometry from within shaders bound to ray
tracing pipelines.
Shaders have read-only access to the memory.
13.2. Descriptor Sets
Descriptors are grouped together into descriptor set objects. A descriptor set object is an opaque object that contains 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:
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorSetLayout)
To create descriptor set layout objects, call:
VkResult vkCreateDescriptorSetLayout(
VkDevice device,
const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkDescriptorSetLayout* pSetLayout);
-
deviceis the logical device that creates the descriptor set layout. -
pCreateInfois a pointer to an instance of the VkDescriptorSetLayoutCreateInfo structure specifying the state of the descriptor set layout object. -
pAllocatorcontrols host memory allocation as described in the Memory Allocation chapter. -
pSetLayoutpoints to a VkDescriptorSetLayout handle in which the resulting descriptor set layout object is returned.
Information about the descriptor set layout is passed in an instance of the
VkDescriptorSetLayoutCreateInfo structure:
typedef struct VkDescriptorSetLayoutCreateInfo {
VkStructureType sType;
const void* pNext;
VkDescriptorSetLayoutCreateFlags flags;
uint32_t bindingCount;
const VkDescriptorSetLayoutBinding* pBindings;
} VkDescriptorSetLayoutCreateInfo;
-
sTypeis the type of this structure. -
pNextisNULLor a pointer to an extension-specific structure. -
flagsis a bitmask of VkDescriptorSetLayoutCreateFlagBits specifying options for descriptor set layout creation. -
bindingCountis the number of elements inpBindings. -
pBindingsis a pointer to an array of VkDescriptorSetLayoutBinding structures.
Bits which can be set in VkDescriptorSetLayoutCreateInfo::flags
to specify options for descriptor set layout are:
typedef enum VkDescriptorSetLayoutCreateFlagBits {
VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR = 0x00000001,
VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT = 0x00000002,
VK_DESCRIPTOR_SET_LAYOUT_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkDescriptorSetLayoutCreateFlagBits;
-
VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHRspecifies 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_EXTspecifies that descriptor sets using this layout must be allocated from a descriptor pool created with theVK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXTbit 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.
typedef VkFlags VkDescriptorSetLayoutCreateFlags;
VkDescriptorSetLayoutCreateFlags is a bitmask type for setting a mask
of zero or more VkDescriptorSetLayoutCreateFlagBits.
The VkDescriptorSetLayoutBinding structure is defined as:
typedef struct VkDescriptorSetLayoutBinding {
uint32_t binding;
VkDescriptorType descriptorType;
uint32_t descriptorCount;
VkShaderStageFlags stageFlags;
const VkSampler* pImmutableSamplers;
} VkDescriptorSetLayoutBinding;
-
bindingis the binding number of this entry and corresponds to a resource of the same binding number in the shader stages. -
descriptorTypeis a VkDescriptorType specifying which type of resource descriptors are used for this binding. -
descriptorCountis the number of descriptors contained in the binding, accessed in a shader as an array , except ifdescriptorTypeisVK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXTin which casedescriptorCountis the size in bytes of the inline uniform block . IfdescriptorCountis 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. -
stageFlagsmember is a bitmask of VkShaderStageFlagBits specifying which pipeline shader stages can access a resource for this binding.VK_SHADER_STAGE_ALLis 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. -
pImmutableSamplersaffects initialization of samplers. IfdescriptorTypespecifies aVK_DESCRIPTOR_TYPE_SAMPLERorVK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLERtype descriptor, thenpImmutableSamplerscan be used to initialize a set of immutable samplers. Immutable samplers are permanently bound into the set layout; later binding a sampler into an immutable sampler slot in a descriptor set is not allowed. IfpImmutableSamplersis notNULL, then it is considered to be a pointer to an array of sampler handles that will be consumed by the set layout and used for the corresponding binding. IfpImmutableSamplersisNULL, then the sampler slots are dynamic and sampler handles must be bound into descriptor sets using this layout. IfdescriptorTypeis not one of these descriptor types, thenpImmutableSamplersis 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 VkDescriptorSetLayoutBindingFlagsCreateInfoEXT
structure, then that structure includes an array of flags, one for each
descriptor set layout binding.
The VkDescriptorSetLayoutBindingFlagsCreateInfoEXT structure is defined as:
typedef struct VkDescriptorSetLayoutBindingFlagsCreateInfoEXT {
VkStructureType sType;
const void* pNext;
uint32_t bindingCount;
const VkDescriptorBindingFlagsEXT* pBindingFlags;
} VkDescriptorSetLayoutBindingFlagsCreateInfoEXT;
-
sTypeis the type of this structure. -
pNextisNULLor a pointer to an extension-specific structure. -
bindingCountis zero or the number of elements inpBindingFlags. -
pBindingFlagsis a pointer to an array of VkDescriptorBindingFlagsEXT bitfields, one for each descriptor set layout binding.
If bindingCount is zero or if this structure is not in the pNext
chain, the VkDescriptorBindingFlagsEXT 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
VkDescriptorSetLayoutBindingFlagsCreateInfoEXT::pBindingFlags to
specify options for the corresponding descriptor set layout binding are:
typedef enum VkDescriptorBindingFlagBitsEXT {
VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT = 0x00000001,
VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT = 0x00000002,
VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT = 0x00000004,
VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT = 0x00000008,
VK_DESCRIPTOR_BINDING_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF
} VkDescriptorBindingFlagBitsEXT;
-
VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXTindicates 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. They 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_EXTindicates 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_EXTindicates 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_EXTis 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_EXTis 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_EXTindicates that this descriptor binding has a variable size that will be specified when a descriptor set is allocated using this layout. The value ofdescriptorCountis 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 ofdescriptorCountis counted , except for descriptor bindings with a descriptor type ofVK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXTwheredescriptorCountspecifies the upper bound on the byte size of the binding, thus it counts against themaxInlineUniformBlockSizelimit instead. .
|
Note
Note that while |
typedef VkFlags VkDescriptorBindingFlagsEXT;
VkDescriptorBindingFlagsEXT is a bitmask type for setting a mask of
zero or more VkDescriptorBindingFlagBitsEXT.
To query information about whether a descriptor set layout can be created, call:
void vkGetDescriptorSetLayoutSupport(
VkDevice device,
const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
VkDescriptorSetLayoutSupport* pSupport);
or the equivalent command
void vkGetDescriptorSetLayoutSupportKHR(
VkDevice device,
const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
VkDescriptorSetLayoutSupport* pSupport);
-
deviceis the logical device that would create the descriptor set layout. -
pCreateInfois a pointer to an instance of the VkDescriptorSetLayoutCreateInfo structure specifying the state of the descriptor set layout object. -
pSupportpoints 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 an
instance of the VkDescriptorSetLayoutSupport structure:
typedef struct VkDescriptorSetLayoutSupport {
VkStructureType sType;
void* pNext;
VkBool32 supported;
} VkDescriptorSetLayoutSupport;
or the equivalent
typedef VkDescriptorSetLayoutSupport VkDescriptorSetLayoutSupportKHR;
-
sTypeis the type of this structure. -
pNextisNULLor a pointer to an extension-specific structure. -
supportedspecifies 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 VkDescriptorSetVariableDescriptorCountLayoutSupportEXT
structure, then that structure returns additional information about whether
the descriptor set layout is supported.
typedef struct VkDescriptorSetVariableDescriptorCountLayoutSupportEXT {
VkStructureType sType;
void* pNext;
uint32_t maxVariableDescriptorCount;
} VkDescriptorSetVariableDescriptorCountLayoutSupportEXT;
-
sTypeis the type of this structure. -
pNextisNULLor a pointer to an extension-specific structure. -
maxVariableDescriptorCountindicates 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_EXTthenmaxVariableDescriptorCountindicates 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
VkPhysicalDeviceDescriptorIndexingFeaturesEXT::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:
void vkDestroyDescriptorSetLayout(
VkDevice device,
VkDescriptorSetLayout descriptorSetLayout,
const VkAllocationCallbacks* pAllocator);
-
deviceis the logical device that destroys the descriptor set layout. -
descriptorSetLayoutis the descriptor set layout to destroy. -
pAllocatorcontrols 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 which describes 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:
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipelineLayout)
To create a pipeline layout, call:
VkResult vkCreatePipelineLayout(
VkDevice device,
const VkPipelineLayoutCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkPipelineLayout* pPipelineLayout);
-
deviceis the logical device that creates the pipeline layout. -
pCreateInfois a pointer to an instance of the VkPipelineLayoutCreateInfo structure specifying the state of the pipeline layout object. -
pAllocatorcontrols host memory allocation as described in the Memory Allocation chapter. -
pPipelineLayoutpoints to a VkPipelineLayout handle in which the resulting pipeline layout object is returned.
The VkPipelineLayoutCreateInfo structure is defined as:
typedef struct VkPipelineLayoutCreateInfo {
VkStructureType sType;
const void* pNext;
VkPipelineLayoutCreateFlags flags;
uint32_t setLayoutCount;
const VkDescriptorSetLayout* pSetLayouts;
uint32_t pushConstantRangeCount;
const VkPushConstantRange* pPushConstantRanges;
} VkPipelineLayoutCreateInfo;
-
sTypeis the type of this structure. -
pNextisNULLor a pointer to an extension-specific structure. -
flagsis reserved for future use. -
setLayoutCountis the number of descriptor sets included in the pipeline layout. -
pSetLayoutsis a pointer to an array ofVkDescriptorSetLayoutobjects. -
pushConstantRangeCountis the number of push constant ranges included in the pipeline layout. -
pPushConstantRangesis a pointer to an array ofVkPushConstantRangestructures 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.
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:
typedef struct VkPushConstantRange {
VkShaderStageFlags stageFlags;
uint32_t offset;
uint32_t size;
} VkPushConstantRange;
-
stageFlagsis 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. -
offsetandsizeare the start offset and size, respectively, consumed by the range. Bothoffsetandsizeare 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:
void vkDestroyPipelineLayout(
VkDevice device,
VkPipelineLayout pipelineLayout,
const VkAllocationCallbacks* pAllocator);
-
deviceis the logical device that destroys the pipeline layout. -
pipelineLayoutis the pipeline layout to destroy. -
pAllocatorcontrols 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:
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorPool)
To create a descriptor pool object, call:
VkResult vkCreateDescriptorPool(
VkDevice device,
const VkDescriptorPoolCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkDescriptorPool* pDescriptorPool);
-
deviceis the logical device that creates the descriptor pool. -
pCreateInfois a pointer to an instance of the VkDescriptorPoolCreateInfo structure specifying the state of the descriptor pool object. -
pAllocatorcontrols host memory allocation as described in the Memory Allocation chapter. -
pDescriptorPoolpoints 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 an instance of the
VkDescriptorPoolCreateInfo structure:
typedef struct VkDescriptorPoolCreateInfo {
VkStructureType sType;
const void* pNext;
VkDescriptorPoolCreateFlags flags;
uint32_t maxSets;
uint32_t poolSizeCount;
const VkDescriptorPoolSize* pPoolSizes;
} VkDescriptorPoolCreateInfo;
-
sTypeis the type of this structure. -
pNextisNULLor a pointer to an extension-specific structure. -
flagsis a bitmask of VkDescriptorPoolCreateFlagBits specifying certain supported operations on the pool. -
maxSetsis the maximum number of descriptor sets that can be allocated from the pool. -
poolSizeCountis the number of elements inpPoolSizes. -
pPoolSizesis 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_EXT bit set,
descriptor pool creation may fail with the error
VK_ERROR_FRAGMENTATION_EXT 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 an instance of the
VkDescriptorPoolSize structure with a descriptorType value of
VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT.
This can be done by chaining an instance of the
VkDescriptorPoolInlineUniformBlockCreateInfoEXT structure to the
pNext chain of VkDescriptorPoolCreateInfo.
The VkDescriptorPoolInlineUniformBlockCreateInfoEXT structure is
defined as:
typedef struct VkDescriptorPoolInlineUniformBlockCreateInfoEXT {
VkStructureType sType;
const void* pNext;
uint32_t maxInlineUniformBlockBindings;
} VkDescriptorPoolInlineUniformBlockCreateInfoEXT;
-
sTypeis the type of this structure. -
pNextisNULLor a pointer to an extension-specific structure. -
maxInlineUniformBlockBindingsis 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:
typedef enum VkDescriptorPoolCreateFlagBits {
VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT = 0x00000001,
VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT = 0x00000002,
VK_DESCRIPTOR_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VkDescriptorPoolCreateFlagBits;
-
VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BITspecifies 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_EXTspecifies that descriptor sets allocated from this pool can include bindings with theVK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXTbit set. It is valid to allocate descriptor sets that have bindings that do not set theVK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXTbit from a pool that hasVK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXTset.
typedef VkFlags VkDescriptorPoolCreateFlags;
VkDescriptorPoolCreateFlags is a bitmask type for setting a mask of
zero or more VkDescriptorPoolCreateFlagBits.
The VkDescriptorPoolSize structure is defined as:
typedef struct VkDescriptorPoolSize {
VkDescriptorType type;
uint32_t descriptorCount;
} VkDescriptorPoolSize;
-
typeis the type of descriptor. -
descriptorCountis the number of descriptors of that type to allocate. IftypeisVK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXTthendescriptorCountis the number of bytes to allocate for descriptors of this type.
Each combined image sampler descriptor for a multi-planar format may
consume multiple descriptors from the pool, as indicated by
VkSamplerYcbcrConversionImageFormatProperties::maxCombinedImageSamplerDescriptorCount.
The descriptorCount for pools that will contain such descriptors must
be expanded to allow for this.
|
Note
For example, consider a descriptor set layout binding with two descriptors
and immutable samplers for multi-planar formats that have
|
To destroy a descriptor pool, call:
void vkDestroyDescriptorPool(
VkDevice device,
VkDescriptorPool descriptorPool,
const VkAllocationCallbacks* pAllocator);
-
deviceis the logical device that destroys the descriptor pool. -
descriptorPoolis the descriptor pool to destroy. -
pAllocatorcontrols 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:
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorSet)
To allocate descriptor sets from a descriptor pool, call:
VkResult vkAllocateDescriptorSets(
VkDevice device,
const VkDescriptorSetAllocateInfo* pAllocateInfo,
VkDescriptorSet* pDescriptorSets);
-
deviceis the logical device that owns the descriptor pool. -
pAllocateInfois a pointer to an instance of the VkDescriptorSetAllocateInfo structure describing parameters of the allocation. -
pDescriptorSetsis 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_EXTbit 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_EXTbit 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_EXTcan 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:
typedef struct VkDescriptorSetAllocateInfo {
VkStructureType sType;
const void* pNext;
VkDescriptorPool descriptorPool;
uint32_t descriptorSetCount;
const VkDescriptorSetLayout* pSetLayouts;
} VkDescriptorSetAllocateInfo;
-
sTypeis the type of this structure. -
pNextisNULLor a pointer to an extension-specific structure. -
descriptorPoolis the pool which the sets will be allocated from. -
descriptorSetCountdetermines the number of descriptor sets to be allocated from the pool. -
pSetLayoutsis 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 VkDescriptorSetVariableDescriptorCountAllocateInfoEXT
structure, then that structure includes an array of descriptor counts for
variable descriptor count bindings, one for each descriptor set being
allocated.
The VkDescriptorSetVariableDescriptorCountAllocateInfoEXT structure is
defined as:
typedef struct VkDescriptorSetVariableDescriptorCountAllocateInfoEXT {
VkStructureType sType;
const void* pNext;
uint32_t descriptorSetCount;
const uint32_t* pDescriptorCounts;
} VkDescriptorSetVariableDescriptorCountAllocateInfoEXT;
-
sTypeis the type of this structure. -
pNextisNULLor a pointer to an extension-specific structure. -
descriptorSetCountis zero or the number of elements inpDescriptorCounts. -
pDescriptorCountsis 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:
VkResult vkFreeDescriptorSets(
VkDevice device,
VkDescriptorPool descriptorPool,
uint32_t descriptorSetCount,
const VkDescriptorSet* pDescriptorSets);
-
deviceis the logical device that owns the descriptor pool. -
descriptorPoolis the descriptor pool from which the descriptor sets were allocated. -
descriptorSetCountis the number of elements in thepDescriptorSetsarray. -
pDescriptorSetsis an array of handles to VkDescriptorSet objects.
After a successful call to 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:
VkResult vkResetDescriptorPool(
VkDevice device,
VkDescriptorPool descriptorPool,
VkDescriptorPoolResetFlags flags);
-
deviceis the logical device that owns the descriptor pool. -
descriptorPoolis the descriptor pool to be reset. -
flagsis 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.
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:
void vkUpdateDescriptorSets(
VkDevice device,
uint32_t descriptorWriteCount,
const VkWriteDescriptorSet* pDescriptorWrites,
uint32_t descriptorCopyCount,
const VkCopyDescriptorSet* pDescriptorCopies);
-
deviceis the logical device that updates the descriptor sets. -
descriptorWriteCountis the number of elements in thepDescriptorWritesarray. -
pDescriptorWritesis a pointer to an array of VkWriteDescriptorSet structures describing the descriptor sets to write to. -
descriptorCopyCountis the number of elements in thepDescriptorCopiesarray. -
pDescriptorCopiesis 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_EXT or
VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT bits set,
that command buffer becomes invalid.
The VkWriteDescriptorSet structure is defined as:
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;
-
sTypeis the type of this structure. -
pNextisNULLor a pointer to an extension-specific structure. -
dstSetis the destination descriptor set to update. -
dstBindingis the descriptor binding within that set. -
dstArrayElementis the starting element in that array. If the descriptor binding identified bydstSetanddstBindinghas a descriptor type ofVK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXTthendstArrayElementspecifies the starting byte offset within the binding. -
descriptorCountis the number of descriptors to update (the number of elements inpImageInfo,pBufferInfo, orpTexelBufferView, or a value matching thedataSizemember of an instance of VkWriteDescriptorSetInlineUniformBlockEXT in thepNextchain , or a value matching theaccelerationStructureCountof an instance of VkWriteDescriptorSetAccelerationStructureNV in thepNextchain ). If the descriptor binding identified bydstSetanddstBindinghas a descriptor type ofVK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXTthendescriptorCountspecifies the number of bytes to update. -
descriptorTypeis a VkDescriptorType specifying the type of each descriptor inpImageInfo,pBufferInfo, orpTexelBufferView, as described below. It must be the same type as that specified inVkDescriptorSetLayoutBindingfordstSetatdstBinding. The type of the descriptor also controls which array the descriptors are taken from. -
pImageInfopoints to an array of VkDescriptorImageInfo structures or is ignored, as described below. -
pBufferInfopoints to an array of VkDescriptorBufferInfo structures or is ignored, as described below. -
pTexelBufferViewpoints 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 instance of
VkWriteDescriptorSetInlineUniformBlockEXT in the pNext chain of
VkWriteDescriptorSet,
or if descriptorType is
VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV, in which case the source
data for the descriptor writes is taken from the instance of
VkWriteDescriptorSetAccelerationStructureNV in the pNext chain
of VkWriteDescriptorSet,
as specified below.
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:
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,
VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT = 1000138000,
VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV = 1000165000,
VK_DESCRIPTOR_TYPE_MAX_ENUM = 0x7FFFFFFF
} VkDescriptorType;
-
VK_DESCRIPTOR_TYPE_SAMPLERspecifies a sampler descriptor. -
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLERspecifies a combined image sampler descriptor. -
VK_DESCRIPTOR_TYPE_SAMPLED_IMAGEspecifies a sampled image descriptor. -
VK_DESCRIPTOR_TYPE_STORAGE_IMAGEspecifies a storage image descriptor. -
VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFERspecifies a uniform texel buffer descriptor. -
VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFERspecifies a storage texel buffer descriptor. -
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFERspecifies a uniform buffer descriptor. -
VK_DESCRIPTOR_TYPE_STORAGE_BUFFERspecifies a storage buffer descriptor. -
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMICspecifies a dynamic uniform buffer descriptor. -
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMICspecifies a dynamic storage buffer descriptor. -
VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENTspecifies an input attachment descriptor. -
VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXTspecifies 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 thesamplermember of each element of VkWriteDescriptorSet::pImageInfois accessed. -
For
VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, orVK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, only theimageViewandimageLayoutmembers of each element of VkWriteDescriptorSet::pImageInfoare accessed. -
For
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, all members of each element of VkWriteDescriptorSet::pImageInfoare 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::pBufferInfoare accessed. -
For
VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFERorVK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, each element of VkWriteDescriptorSet::pTexelBufferViewis 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 instance of VkWriteDescriptorSetInlineUniformBlockEXT
in the pNext chain of VkWriteDescriptorSet.
When updating descriptors with a descriptorType of
VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV, none of the
pImageInfo, pBufferInfo, or pTexelBufferView members are
accessed, instead the source data of the descriptor update operation is
taken from the instance of VkWriteDescriptorSetAccelerationStructureNV
in the pNext chain of VkWriteDescriptorSet.
The VkDescriptorBufferInfo structure is defined as:
typedef struct VkDescriptorBufferInfo {
VkBuffer buffer;
VkDeviceSize offset;
VkDeviceSize range;
} VkDescriptorBufferInfo;
-
bufferis the buffer resource. -
offsetis the offset in bytes from the start ofbuffer. Access to buffer memory via this descriptor uses addressing that is relative to this starting offset. -
rangeis the size in bytes that is used for this descriptor update, orVK_WHOLE_SIZEto use the range fromoffsetto 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:
typedef struct VkDescriptorImageInfo {
VkSampler sampler;
VkImageView imageView;
VkImageLayout imageLayout;
} VkDescriptorImageInfo;
-
sampleris a sampler handle, and is used in descriptor updates for typesVK_DESCRIPTOR_TYPE_SAMPLERandVK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLERif the binding being updated does not use immutable samplers. -
imageViewis 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. -
imageLayoutis the layout that the image subresources accessible fromimageViewwill be in at the time this descriptor is accessed.imageLayoutis 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 an instance of
VkWriteDescriptorSetInlineUniformBlockEXT chained to the pNext
chain of VkWriteDescriptorSet.
The VkWriteDescriptorSetInlineUniformBlockEXT structure is defined as:
typedef struct VkWriteDescriptorSetInlineUniformBlockEXT {
VkStructureType sType;
const void* pNext;
uint32_t dataSize;
const void* pData;
} VkWriteDescriptorSetInlineUniformBlockEXT;
-
sTypeis the type of this structure. -
pNextisNULLor a pointer to an extension-specific structure. -
dataSizeis the number of bytes of inline uniform block data pointed to bypData. -
pDatais a pointer todataSizenumber of bytes of data to write to the inline uniform block.
The VkWriteDescriptorSetAccelerationStructureNV structure is defined
as:
typedef struct VkWriteDescriptorSetAccelerationStructureNV {
VkStructureType sType;
const void* pNext;
uint32_t accelerationStructureCount;
const VkAccelerationStructureNV* pAccelerationStructures;
} VkWriteDescriptorSetAccelerationStructureNV;
-
sTypeis the type of this structure. -
pNextisNULLor a pointer to an extension-specific structure. -
accelerationStructureCountis the number of elements inpAccelerationStructures. -
pAccelerationStructuresare the acceleration structures to update.
The VkCopyDescriptorSet structure is defined as:
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;
-
sTypeis the type of this structure. -
pNextisNULLor a pointer to an extension-specific structure. -
srcSet,srcBinding, andsrcArrayElementare the source set, binding, and array element, respectively. If the descriptor binding identified bysrcSetandsrcBindinghas a descriptor type ofVK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXTthensrcArrayElementspecifies the starting byte offset within the binding to copy from. -
dstSet,dstBinding, anddstArrayElementare the destination set, binding, and array element, respectively. If the descriptor binding identified bydstSetanddstBindinghas a descriptor type ofVK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXTthendstArrayElementspecifies the starting byte offset within the binding to copy to. -
descriptorCountis the number of descriptors to copy from the source to destination. IfdescriptorCountis 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 bysrcSetandsrcBindinghas a descriptor type ofVK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXTthendescriptorCountspecifies 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:
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorUpdateTemplate)
or the equivalent
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:
VkResult vkCreateDescriptorUpdateTemplate(
VkDevice device,
const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate);
or the equivalent command
VkResult vkCreateDescriptorUpdateTemplateKHR(
VkDevice device,
const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate);
-
deviceis the logical device that creates the descriptor update template. -
pCreateInfois a pointer to an instance of the VkDescriptorUpdateTemplateCreateInfo structure specifying the set of descriptors to update with a single call to vkCmdPushDescriptorSetWithTemplateKHR or vkUpdateDescriptorSetWithTemplate. -
pAllocatorcontrols host memory allocation as described in the Memory Allocation chapter. -
pDescriptorUpdateTemplatepoints to aVkDescriptorUpdateTemplatehandle in which the resulting descriptor update template object is returned.
The VkDescriptorUpdateTemplateCreateInfo structure is defined as:
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
typedef VkDescriptorUpdateTemplateCreateInfo VkDescriptorUpdateTemplateCreateInfoKHR;
-
sTypeis the type of this structure. -
pNextisNULLor a pointer to an extension-specific structure. -
flagsis reserved for future use. -
descriptorUpdateEntryCountis the number of elements in thepDescriptorUpdateEntriesarray. -
pDescriptorUpdateEntriesis a pointer to an array of VkDescriptorUpdateTemplateEntry structures describing the descriptors to be updated by the descriptor update template. -
templateTypeSpecifies the type of the descriptor update template. If set toVK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SETit can only be used to update descriptor sets with a fixeddescriptorSetLayout. If set toVK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHRit can only be used to push descriptor sets using the providedpipelineBindPoint,pipelineLayout, andsetnumber. -
descriptorSetLayoutis 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.descriptorSetLayoutis 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 iftemplateTypeis notVK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET. -
pipelineBindPointis a VkPipelineBindPoint indicating whether the descriptors will be used by graphics pipelines or compute pipelines. This parameter is ignored iftemplateTypeis notVK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR -
pipelineLayoutis a VkPipelineLayout object used to program the bindings. This parameter is ignored iftemplateTypeis notVK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR -
setis the set number of the descriptor set in the pipeline layout that will be updated. This parameter is ignored iftemplateTypeis notVK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR
typedef VkFlags VkDescriptorUpdateTemplateCreateFlags;
or the equivalent
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:
typedef enum VkDescriptorUpdateTemplateType {
VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET = 0,
VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR = 1,
VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET,
VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_MAX_ENUM = 0x7FFFFFFF
} VkDescriptorUpdateTemplateType;
or the equivalent
typedef VkDescriptorUpdateTemplateType VkDescriptorUpdateTemplateTypeKHR;
-
VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SETspecifies that the descriptor update template will be used for descriptor set updates only. -
VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHRspecifies that the descriptor update template will be used for push descriptor updates only.
The VkDescriptorUpdateTemplateEntry structure is defined as:
typedef struct VkDescriptorUpdateTemplateEntry {
uint32_t dstBinding;
uint32_t dstArrayElement;
uint32_t descriptorCount;
VkDescriptorType descriptorType;
size_t offset;
size_t stride;
} VkDescriptorUpdateTemplateEntry;
or the equivalent
typedef VkDescriptorUpdateTemplateEntry VkDescriptorUpdateTemplateEntryKHR;
-
dstBindingis the descriptor binding to update when using this descriptor update template. -
dstArrayElementis the starting element in the array belonging todstBinding. If the descriptor binding identified bysrcBindinghas a descriptor type ofVK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXTthendstArrayElementspecifies the starting byte offset to update. -
descriptorCountis the number of descriptors to update. IfdescriptorCountis 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 bydstBindinghas a descriptor type ofVK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXTthendescriptorCountspecifies the number of bytes to update and the remaining array elements in the destination binding refer to the remaining number of bytes in it. -
descriptorTypeis a VkDescriptorType specifying the type of the descriptor. -
offsetis the offset in bytes of the first binding in the raw data structure. -
strideis 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].strideThe stride is useful in case the bindings are stored in structs along with other data. If
descriptorTypeisVK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXTthen the value ofstrideis 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:
void vkDestroyDescriptorUpdateTemplate(
VkDevice device,
VkDescriptorUpdateTemplate descriptorUpdateTemplate,
const VkAllocationCallbacks* pAllocator);
or the equivalent command
void vkDestroyDescriptorUpdateTemplateKHR(
VkDevice device,
VkDescriptorUpdateTemplate descriptorUpdateTemplate,
const VkAllocationCallbacks* pAllocator);
-
deviceis the logical device that has been used to create the descriptor update template -
descriptorUpdateTemplateis the descriptor update template to destroy. -
pAllocatorcontrols host memory allocation as described in the Memory Allocation chapter.
Once a VkDescriptorUpdateTemplate has been created, descriptor sets
can be updated by calling:
void vkUpdateDescriptorSetWithTemplate(
VkDevice device,
VkDescriptorSet descriptorSet,
VkDescriptorUpdateTemplate descriptorUpdateTemplate,
const void* pData);
or the equivalent command
void vkUpdateDescriptorSetWithTemplateKHR(
VkDevice device,
VkDescriptorSet descriptorSet,
VkDescriptorUpdateTemplate descriptorUpdateTemplate,
const void* pData);
-
deviceis the logical device that updates the descriptor sets. -
descriptorSetis the descriptor set to update -
descriptorUpdateTemplateis the VkDescriptorUpdateTemplate which specifies the update mapping betweenpDataand the descriptor set to update. -
pDatais a pointer to memory which contains one or more structures of VkDescriptorImageInfo, VkDescriptorBufferInfo, or VkBufferView 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:
void vkCmdBindDescriptorSets(
VkCommandBuffer commandBuffer,
VkPipelineBindPoint pipelineBindPoint,
VkPipelineLayout layout,
uint32_t firstSet,
uint32_t descriptorSetCount,
const VkDescriptorSet* pDescriptorSets,
uint32_t dynamicOffsetCount,
const uint32_t* pDynamicOffsets);
-
commandBufferis the command buffer that the descriptor sets will be bound to. -
pipelineBindPointis 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. -
layoutis a VkPipelineLayout object used to program the bindings. -
firstSetis the set number of the first descriptor set to be bound. -
descriptorSetCountis the number of elements in thepDescriptorSetsarray. -
pDescriptorSetsis an array of handles to VkDescriptorSet objects describing the descriptor sets to write to. -
dynamicOffsetCountis the number of dynamic offsets in thepDynamicOffsetsarray. -
pDynamicOffsetsis a pointer to an array ofuint32_tvalues 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_EXTbit 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:
void vkCmdPushDescriptorSetKHR(
VkCommandBuffer commandBuffer,
VkPipelineBindPoint pipelineBindPoint,
VkPipelineLayout layout,
uint32_t set,
uint32_t descriptorWriteCount,
const VkWriteDescriptorSet* pDescriptorWrites);
-
commandBufferis the command buffer that the descriptors will be recorded in. -
pipelineBindPointis 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. -
layoutis a VkPipelineLayout object used to program the bindings. -
setis the set number of the descriptor set in the pipeline layout that will be updated. -
descriptorWriteCountis the number of elements in thepDescriptorWritesarray. -
pDescriptorWritesis 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. 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:
void vkCmdPushDescriptorSetWithTemplateKHR(
VkCommandBuffer commandBuffer,
VkDescriptorUpdateTemplate descriptorUpdateTemplate,
VkPipelineLayout layout,
uint32_t set,
const void* pData);
-
commandBufferis the command buffer that the descriptors will be recorded in. -
descriptorUpdateTemplateis a descriptor update template that defines how to interpret the descriptor information inpData. -
layoutis a VkPipelineLayout object used to program the bindings. It must be compatible with the layout used to create thedescriptorUpdateTemplatehandle. -
setis the set number of the descriptor set in the pipeline layout that will be updated. This must be the same number used to create thedescriptorUpdateTemplatehandle. -
pDatapoints to memory which contains the 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:
void vkCmdPushConstants(
VkCommandBuffer commandBuffer,
VkPipelineLayout layout,
VkShaderStageFlags stageFlags,
uint32_t offset,
uint32_t size,
const void* pValues);
-
commandBufferis the command buffer in which the push constant update will be recorded. -
layoutis the pipeline layout used to program the push constant updates. -
stageFlagsis a bitmask of VkShaderStageFlagBits specifying the shader stages that will use the push constants in the updated range. -
offsetis the start offset of the push constant range to update, in units of bytes. -
sizeis the size of the push constant range to update, in units of bytes. -
pValuesis an array ofsizebytes 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:
VkDeviceAddress vkGetBufferDeviceAddressEXT(
VkDevice device,
const VkBufferDeviceAddressInfoEXT* pInfo);
-
deviceis the logical device that the buffer was created on. -
pInfois a pointer to an instance of the VkBufferDeviceAddressInfoEXT 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_EXT_physical_storage_buffer extension and the
PhysicalStorageBufferEXT 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
PhysicalStorageBufferEXT pointers must access addresses in the address
range of some buffer.
If the buffer was created with a non-zero value of
VkBufferDeviceAddressCreateInfoEXT::deviceAddress, the return
value will be the same address.
The VkBufferDeviceAddressInfoEXT structure is defined as:
typedef struct VkBufferDeviceAddressInfoEXT {
VkStructureType sType;
const void* pNext;
VkBuffer buffer;
} VkBufferDeviceAddressInfoEXT;
-
sTypeis the type of this structure. -
pNextisNULLor a pointer to an extension-specific structure. -
bufferspecifies the buffer whose address is being queried.