Resource Descriptors

A descriptor is an opaque data structure used to access shader resources such as buffers, images, or samplers. Rather than existing as distinct objects, descriptors are handled as opaque data, which can be accessed by a shader through descriptor heaps, descriptor buffers, or descriptor sets.

Shaders access descriptors via the ResourceHeapEXT and SamplerHeapEXT built-ins, or through variables decorated with DescriptorSet and Binding values linking them to the API. Details of the shader interface mapping are described in the Shader Resource Interface section.

Shaders can also access buffers without going through descriptors by using Physical Storage Buffer Access to access them through 64-bit addresses.

Descriptor Types

There are a number of different types of descriptor supported by Vulkan, corresponding to different resources or usage. The following sections describe the API definitions of each descriptor type. The mapping of each type to SPIR-V is listed in the Shader Resource and Descriptor Type Correspondence and Shader Resource and Storage Class Correspondence tables in the Shader Interfaces chapter.

Possible descriptor types are:

// Provided by VK_VERSION_1_0
typedef enum VkDescriptorType {
    VK_DESCRIPTOR_TYPE_SAMPLER = 0,
    VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER = 1,
    VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE = 2,
    VK_DESCRIPTOR_TYPE_STORAGE_IMAGE = 3,
    VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER = 4,
    VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER = 5,
    VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER = 6,
    VK_DESCRIPTOR_TYPE_STORAGE_BUFFER = 7,
    VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC = 8,
    VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC = 9,
    VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 10,
  // Provided by VK_VERSION_1_3
    VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK = 1000138000,
  // Provided by VK_KHR_acceleration_structure
    VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR = 1000150000,
  // Provided by VK_NV_ray_tracing
    VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV = 1000165000,
  // Provided by VK_QCOM_image_processing
    VK_DESCRIPTOR_TYPE_SAMPLE_WEIGHT_IMAGE_QCOM = 1000440000,
  // Provided by VK_QCOM_image_processing
    VK_DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM = 1000440001,
  // Provided by VK_ARM_tensors
    VK_DESCRIPTOR_TYPE_TENSOR_ARM = 1000460000,
  // Provided by VK_EXT_mutable_descriptor_type
    VK_DESCRIPTOR_TYPE_MUTABLE_EXT = 1000351000,
  // Provided by VK_NV_partitioned_acceleration_structure
    VK_DESCRIPTOR_TYPE_PARTITIONED_ACCELERATION_STRUCTURE_NV = 1000570000,
  // Provided by VK_EXT_inline_uniform_block
    VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT = VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK,
  // Provided by VK_VALVE_mutable_descriptor_type
    VK_DESCRIPTOR_TYPE_MUTABLE_VALVE = VK_DESCRIPTOR_TYPE_MUTABLE_EXT,
} VkDescriptorType;

Storage Image

A storage image (VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) is a descriptor type associated with an image resource via an image view that load, store, and atomic operations can be performed on.

Storage image loads are supported in all shader stages for image views whose format features contain VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT.

Stores to storage images are supported in task, mesh and compute shaders for image views whose format features contain VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT.

Atomic operations on storage images are supported in task, mesh and compute shaders for image views whose format features contain VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT.

When the fragmentStoresAndAtomics feature is enabled, stores and atomic operations are also supported for storage images in fragment shaders with the same set of image formats as supported in compute shaders. When the vertexPipelineStoresAndAtomics feature is enabled, stores and atomic operations are also supported in vertex, tessellation, and geometry shaders with the same set of image formats as supported in compute shaders.

The image subresources for a storage image must be in the VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR or VK_IMAGE_LAYOUT_TENSOR_ALIASING_ARM or VK_IMAGE_LAYOUT_GENERAL layout in order to access its data in a shader.

When the tileShadingColorAttachments feature is enabled, loads using OpImageRead or OpImageSparseRead are supported for color tile attachments in fragment and compute shaders for image views whose format features contain VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT. Additionally, when the tileShadingColorAttachments feature is enabled, stores using OpImageWrite are supported for color attachments in compute shaders with the same set of image formats as for loads. When the tileShadingAtomicOps feature is enabled, tile atomic operations are supported for color attachments in compute shaders with the same set of image formats as for loads.

When the tileShadingInputAttachments feature is enabled, loads using OpImageRead are supported for input tile attachments in fragment and compute shaders with the same set of image formats as for color attachments. Stores to input attachments are not supported.

When the tileShadingDepthAttachments or tileShadingStencilAttachments feature is enabled, loads using OpImageRead or OpImageSparseRead are supported for depth or stencil aspects of a depth/stencil tile attachment in fragment and compute shaders with the same set of image formats as for color attachments. Stores to depth/stencil attachments are not supported.

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.

Combined Image Sampler

A combined image sampler (VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) is a single descriptor type associated with both a sampler and an image resource, combining both a sampler and sampled image descriptor into a single descriptor.

If the descriptor refers to a sampler that performs Y′CBCR conversion or samples a subsampled image, the sampler must only be used to sample the image in the same descriptor. Otherwise, the sampler and image in this type of descriptor can be used freely with any other samplers and images.

An image subresources for a combined image sampler must be in one of the following layouts:

On some implementations, it may be more efficient to sample from an image using a combination of sampler and sampled image that are stored together in the descriptor set in a combined descriptor.

Uniform Texel Buffer

A uniform texel buffer (VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) is a descriptor type associated with a buffer resource via a buffer view that image sampling operations can be performed on.

Uniform texel buffers define a tightly-packed 1-dimensional linear array of texels, with texels going through format conversion when read in a shader in the same way as they are for an image.

Load operations from uniform texel buffers are supported in all shader stages for buffer view formats which report format features support for VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT

Storage Texel Buffer

A storage texel buffer (VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER) is a descriptor type associated with a buffer resource via a buffer view that image load, store, and atomic operations can be performed on.

Storage texel buffers define a tightly-packed 1-dimensional linear array of texels, with texels going through format conversion when read in a shader in the same way as they are for an image. Unlike uniform texel buffers, these buffers can also be written to in the same way as for storage images.

Storage texel buffer loads are supported in all shader stages for texel buffer view formats which report format features support for VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT

Stores to storage texel buffers are supported in task, mesh and compute shaders for texel buffer formats which report format features support for VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT

Atomic operations on storage texel buffers are supported in task, mesh and compute shaders for texel buffer formats which report format features support for VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT

When the fragmentStoresAndAtomics feature is enabled, stores and atomic operations are also supported for storage texel buffers in fragment shaders with the same set of texel buffer formats as supported in compute shaders. When the vertexPipelineStoresAndAtomics feature is enabled, stores and atomic operations are also supported in vertex, tessellation, and geometry shaders with the same set of texel buffer formats as supported in compute shaders.

Storage Buffer

A storage buffer (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) is a descriptor type associated with a buffer resource directly, described in a shader as a structure with various members that load, store, and atomic operations can be performed on.

Atomic operations can only be performed on members of certain types as defined in the SPIR-V environment appendix.

Uniform Buffer

A uniform buffer (VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) is a descriptor type associated with a buffer resource directly, described in a shader as a structure with various members that load operations can be performed on.

Dynamic Uniform Buffer

A dynamic uniform buffer (VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) is almost identical to a uniform buffer, and differs only in how the offset into the buffer is specified. This descriptor type is only valid when using descriptor sets. The base offset calculated by VkDescriptorBufferInfo when initially updating a descriptor set is added to a dynamic offset when binding a descriptor set.

Dynamic Storage Buffer

A dynamic storage buffer (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) is almost identical to a storage buffer, and differs only in how the offset into the buffer is specified. This descriptor type is only valid when using descriptor sets. The base offset calculated by VkDescriptorBufferInfo when initially updating a descriptor set is added to a dynamic offset when binding a descriptor set.

Inline Uniform Block

An inline uniform block (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK) is almost identical to a uniform buffer in how it is accessed in the shader. Where it differs is that its storage is taken directly from a containing descriptor set or descriptor buffer, instead of being backed by a separate buffer object. This descriptor type is not valid when using descriptor heaps; applications can directly access the heap pointer in a shader or use the VK_DESCRIPTOR_MAPPING_SOURCE_PUSH_DATA_EXT mapping.

Inline uniform blocks are typically used to access a small set of constant data that does not require the additional flexibility provided by the indirection enabled when using a uniform buffer where the descriptor and the referenced buffer memory are decoupled. Compared to push constants, they allow reusing the same set of constant data across multiple disjoint sets of drawing and dispatching commands.

Inline uniform block descriptors cannot be aggregated into arrays. Instead, the array size specified for an inline uniform block descriptor binding specifies the binding’s capacity in bytes.

Sample Weight Image

A sample weight image (VK_DESCRIPTOR_TYPE_SAMPLE_WEIGHT_IMAGE_QCOM) is a descriptor type associated with an image resource via an image view that can be used in weight image sampling. The image view must have been created with VkImageViewSampleWeightCreateInfoQCOM.

Shaders can combine a weight image variable, a sampled image variable, and a sampler variable to perform weight image sampling.

Weight image sampling is supported in all shader stages if the weight image view specifies a format that supports format feature VK_FORMAT_FEATURE_2_WEIGHT_IMAGE_BIT_QCOM and the sampled image view specifies a format that supports format feature VK_FORMAT_FEATURE_2_WEIGHT_SAMPLED_IMAGE_BIT_QCOM

The image subresources for the weight image must be in the VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, or VK_IMAGE_LAYOUT_GENERAL layout in order to access its data in a shader.

Block Matching Image

A block matching image (VK_DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM) is a descriptor type associated with an image resource via an image view that can be used in block matching.

Shaders can combine a target image variable, a reference image variable, and a sampler variable to perform block matching.

Block matching is supported in all shader stages for if both the target view and reference view specifies a format that supports format feature VK_FORMAT_FEATURE_2_BLOCK_MATCHING_BIT_QCOM

The image subresources for block matching must be in the VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, or VK_IMAGE_LAYOUT_GENERAL layout in order to access its data in a shader.

Acceleration Structure

An acceleration structure ( VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR or VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV ) is a descriptor type that is used to retrieve scene geometry from within shaders that are used for ray traversal. Shaders have read-only access to the memory.

Mutable

A descriptor of mutable (VK_DESCRIPTOR_TYPE_MUTABLE_EXT) type indicates that this descriptor can mutate to a number of different types. This descriptor type is not valid when using descriptor heaps, as the elements of a descriptor heap can be manually adjusted to hold different descriptor types already. When specified in a descriptor set layout, any of the descriptor types given in the VkMutableDescriptorTypeListEXT::pDescriptorTypes list of descriptor types in the pNext chain of VkDescriptorSetLayoutCreateInfo for this binding. At any point, each individual descriptor of mutable type has an active descriptor type. The active descriptor type can be any one of the declared types in pDescriptorTypes. Additionally, a mutable descriptor’s active descriptor type can be of the VK_DESCRIPTOR_TYPE_MUTABLE_EXT type, which is the initial active descriptor type. The active descriptor type can change when the descriptor is updated. When a descriptor is consumed by binding a descriptor buffer or set, the active descriptor type is considered, not VK_DESCRIPTOR_TYPE_MUTABLE_EXT.

An active descriptor type of VK_DESCRIPTOR_TYPE_MUTABLE_EXT is considered an undefined descriptor. If a descriptor is consumed where the active descriptor type does not match what the shader expects, the descriptor is considered an undefined descriptor.

To find which descriptor types are supported as VK_DESCRIPTOR_TYPE_MUTABLE_EXT, the application can use vkGetDescriptorSetLayoutSupport with a VK_DESCRIPTOR_TYPE_MUTABLE_EXT binding, with the list of descriptor types to query in the VkMutableDescriptorTypeCreateInfoEXT::pMutableDescriptorTypeLists array for that binding.

The intention of a mutable descriptor type is that implementations allocate N bytes per descriptor, where N is determined by the maximum descriptor size for a given descriptor binding. Implementations are not expected to keep track of the active descriptor type, and it should be considered a C-like union type.

A mutable descriptor type is not considered as efficient in terms of runtime performance as using a non-mutable descriptor type, and applications are not encouraged to use them outside API layering efforts. Mutable descriptor types can be more efficient if the alternative is using many different descriptors to emulate mutable descriptor types.

Storage Tensor

A storage tensor (VK_DESCRIPTOR_TYPE_TENSOR_ARM) is a descriptor type associated with a tensor resource via a tensor view that read and write operations can be performed on.

Storage tensor reads and writes are supported in shaders for tensor views whose format features contain VK_FORMAT_FEATURE_2_TENSOR_SHADER_BIT_ARM.

Storage tensor reads and writes are supported in graph pipelines for tensor views whose format features contain VK_FORMAT_FEATURE_2_TENSOR_DATA_GRAPH_BIT_ARM.

Physical Storage Buffer Access

Buffer device addresses can also be used to access buffer memory in a shader, 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. All loads, stores, and atomics in a shader through PhysicalStorageBuffer pointers must access addresses in the address range of some buffer.