13.1. Descriptor Types

The following sections outline the various descriptor types supported by Vulkan. Each section defines a descriptor type, and each descriptor type has a manifestation in the shading language and SPIR-V as well as in descriptor sets. There is mostly a one-to-one correspondence between descriptor types and classes of opaque types in the shading language, where the opaque types in the shading language must refer to a descriptor in the pipeline layout of the corresponding descriptor type. But there is an exception to this rule as described in Combined Image Sampler.

13.1.1. Storage Image

A storage image (VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) is a descriptor type that is used for load, store, and atomic operations on image memory from within shaders bound to pipelines.

Loads from storage images do not use samplers and are unfiltered and do not support coordinate wrapping or clamping. Loads are supported in all shader stages for image formats which report support for the VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT feature bit via vkGetPhysicalDeviceFormatProperties.

Stores to storage images are supported in compute shaders for image formats which report support for the VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT feature.

Storage images also support atomic operations in compute shaders for image formats which report support for the VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT feature.

Load and store operations on storage images can only be done on images in VK_IMAGE_LAYOUT_GENERAL layout.

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.

Storage image declarations must specify the image format in the shader if the variable is used for atomic operations.

If the shaderStorageImageReadWithoutFormat feature is not enabled, storage image declarations must specify the image format in the shader if the variable is used for load operations.

If the shaderStorageImageWriteWithoutFormat feature is not enabled, storage image declarations must specify the image format in the shader if the variable is used for store operations.

Storage images are declared in GLSL shader source using uniform “image” variables of the appropriate dimensionality as well as a format layout qualifier (if necessary):

GLSL example. 

layout (set=m, binding=n, r32f) uniform image2D myStorageImage;

SPIR-V example. 

               ...
          %1 = OpExtInstImport "GLSL.std.450"
               ...
               OpName %9 "myStorageImage"
               OpDecorate %9 DescriptorSet m
               OpDecorate %9 Binding n
          %2 = OpTypeVoid
          %3 = OpTypeFunction %2
          %6 = OpTypeFloat 32
          %7 = OpTypeImage %6 2D 0 0 0 2 R32f
          %8 = OpTypePointer UniformConstant %7
          %9 = OpVariable %8 UniformConstant
               ...

13.1.2. Sampler

A sampler (VK_DESCRIPTOR_TYPE_SAMPLER) represents a set of parameters which control address calculations, filtering behavior, and other properties, that can be used to perform filtered loads from sampled images (see Sampled Image).

Samplers are declared in GLSL shader source using uniform “sampler” variables, where the sampler type has no associated texture dimensionality:

GLSL Example. 

layout (set=m, binding=n) uniform sampler mySampler;

SPIR-V Example. 

               ...
          %1 = OpExtInstImport "GLSL.std.450"
               ...
               OpName %8 "mySampler"
               OpDecorate %8 DescriptorSet m
               OpDecorate %8 Binding n
          %2 = OpTypeVoid
          %3 = OpTypeFunction %2
          %6 = OpTypeSampler
          %7 = OpTypePointer UniformConstant %6
          %8 = OpVariable %7 UniformConstant
               ...

13.1.3. Sampled Image

A sampled image (VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) can be used (usually in conjunction with a sampler) to retrieve sampled image data. Shaders use a sampled image handle and a sampler handle to sample data, where the image handle generally defines the shape and format of the memory and the sampler generally defines how coordinate addressing is performed. The same sampler can be used to sample from multiple images, and it is possible to sample from the same sampled image with multiple samplers, each containing a different set of sampling parameters.

Sampled images are declared in GLSL shader source using uniform “texture” variables of the appropriate dimensionality:

GLSL example. 

layout (set=m, binding=n) uniform texture2D mySampledImage;

SPIR-V example. 

               ...
          %1 = OpExtInstImport "GLSL.std.450"
               ...
               OpName %9 "mySampledImage"
               OpDecorate %9 DescriptorSet m
               OpDecorate %9 Binding n
          %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
               ...

13.1.4. Combined Image Sampler

A combined image sampler (VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) represents a sampled image along with a set of sampling parameters. It is logically considered a sampled image and a sampler bound together.

[Note]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.

Combined image samplers are declared in GLSL shader source using uniform “sampler” variables of the appropriate dimensionality:

GLSL example. 

layout (set=m, binding=n) uniform sampler2D myCombinedImageSampler;

SPIR-V example. 

               ...
          %1 = OpExtInstImport "GLSL.std.450"
               ...
               OpName %10 "myCombinedImageSampler"
               OpDecorate %10 DescriptorSet m
               OpDecorate %10 Binding n
          %2 = OpTypeVoid
          %3 = OpTypeFunction %2
          %6 = OpTypeFloat 32
          %7 = OpTypeImage %6 2D 0 0 0 1 Unknown
          %8 = OpTypeSampledImage %7
          %9 = OpTypePointer UniformConstant %8
         %10 = OpVariable %9 UniformConstant
               ...

VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER descriptor set entries can also be accessed via separate sampler and sampled image shader variables. Such variables refer exclusively to the corresponding half of the descriptor, and can be combined in the shader with samplers or sampled images that can come from the same descriptor or from other combined or separate descriptor types. There are no additional restrictions on how a separate sampler or sampled image variable is used due to it originating from a combined descriptor.

13.1.5. Uniform Texel Buffer

A uniform texel buffer (VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) represents a tightly packed array of homogeneous formatted data that is stored in a buffer and is made accessible to shaders. Uniform texel buffers are read-only.

Uniform texel buffers are declared in GLSL shader source using uniform “samplerBuffer” variables:

GLSL example. 

layout (set=m, binding=n) uniform samplerBuffer myUniformTexelBuffer;

SPIR-V example. 

               ...
          %1 = OpExtInstImport "GLSL.std.450"
               ...
               OpName %10 "myUniformTexelBuffer"
               OpDecorate %10 DescriptorSet m
               OpDecorate %10 Binding n
          %2 = OpTypeVoid
          %3 = OpTypeFunction %2
          %6 = OpTypeFloat 32
          %7 = OpTypeImage %6 Buffer 0 0 0 1 Unknown
          %8 = OpTypeSampledImage %7
          %9 = OpTypePointer UniformConstant %8
         %10 = OpVariable %9 UniformConstant
               ...

13.1.6. Storage Texel Buffer

A storage texel buffer (VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER) represents a tightly packed array of homogeneous formatted data that is stored in a buffer and is made accessible to shaders. Storage texel buffers differ from uniform texel buffers in that they support stores and atomic operations in shaders, may support a different maximum length, and may have different performance characteristics.

Storage texel buffers are declared in GLSL shader source using uniform “imageBuffer” variables:

GLSL example. 

layout (set=m, binding=n, r32f) uniform imageBuffer myStorageTexelBuffer;

SPIR-V example. 

               ...
          %1 = OpExtInstImport "GLSL.std.450"
               ...
               OpName %9 "myStorageTexelBuffer"
               OpDecorate %9 DescriptorSet m
               OpDecorate %9 Binding n
          %2 = OpTypeVoid
          %3 = OpTypeFunction %2
          %6 = OpTypeFloat 32
          %7 = OpTypeImage %6 Buffer 0 0 0 2 R32f
          %8 = OpTypePointer UniformConstant %7
          %9 = OpVariable %8 UniformConstant
               ...

13.1.7. Uniform Buffer

A uniform buffer (VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) is a region of structured storage that is made accessible for read-only access to shaders. It is typically used to store medium sized arrays of constants such as shader parameters, matrices and other related data.

Uniform buffers are declared in GLSL shader source using the uniform storage qualifier and block syntax:

GLSL example. 

layout (set=m, binding=n) uniform myUniformBuffer
{
    vec4 myElement[32];
};

SPIR-V example. 

               ...
          %1 = OpExtInstImport "GLSL.std.450"
               ...
               OpName %11 "myUniformBuffer"
               OpMemberName %11 0 "myElement"
               OpName %13 ""
               OpDecorate %10 ArrayStride 16
               OpMemberDecorate %11 0 Offset 0
               OpDecorate %11 Block
               OpDecorate %13 DescriptorSet m
               OpDecorate %13 Binding n
          %2 = OpTypeVoid
          %3 = OpTypeFunction %2
          %6 = OpTypeFloat 32
          %7 = OpTypeVector %6 4
          %8 = OpTypeInt 32 0
          %9 = OpConstant %8 32
         %10 = OpTypeArray %7 %9
         %11 = OpTypeStruct %10
         %12 = OpTypePointer Uniform %11
         %13 = OpVariable %12 Uniform
               ...

13.1.8. Storage Buffer

A storage buffer (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) is a region of structured storage that supports both read and write access for shaders. In addition to general read and write operations, some members of storage buffers can be used as the target of atomic operations. In general, atomic operations are only supported on members that have unsigned integer formats.

Storage buffers are declared in GLSL shader source using buffer storage qualifier and block syntax:

GLSL example. 

layout (set=m, binding=n) buffer myStorageBuffer
{
    vec4 myElement[];
};

SPIR-V example. 

               ...
          %1 = OpExtInstImport "GLSL.std.450"
               ...
               OpName %9 "myStorageBuffer"
               OpMemberName %9 0 "myElement"
               OpName %11 ""
               OpDecorate %8 ArrayStride 16
               OpMemberDecorate %9 0 Offset 0
               OpDecorate %9 BufferBlock
               OpDecorate %11 DescriptorSet m
               OpDecorate %11 Binding n
          %2 = OpTypeVoid
          %3 = OpTypeFunction %2
          %6 = OpTypeFloat 32
          %7 = OpTypeVector %6 4
          %8 = OpTypeRuntimeArray %7
          %9 = OpTypeStruct %8
         %10 = OpTypePointer Uniform %9
         %11 = OpVariable %10 Uniform
               ...

13.1.9. Dynamic Uniform Buffer

A dynamic uniform buffer (VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) differs from a uniform buffer only in how its address and length are specified. Uniform buffers bind a buffer address and length that is specified in the descriptor set update by a buffer handle, offset and range (see Descriptor Set Updates). With dynamic uniform buffers the buffer handle, offset and range specified in the descriptor set define the base address and length. The dynamic offset which is relative to this base address is taken from the pDynamicOffsets parameter to vkCmdBindDescriptorSets (see Descriptor Set Binding). The address used for a dynamic uniform buffer is the sum of the buffer base address and the relative offset. The length is unmodified and remains the range as specified in the descriptor update. The shader syntax is identical for uniform buffers and dynamic uniform buffers.

13.1.10. Dynamic Storage Buffer

A dynamic storage buffer (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) differs from a storage buffer only in how its address and length are specified. The difference is identical to the difference between uniform buffers and dynamic uniform buffers (see Dynamic Uniform Buffer). The shader syntax is identical for storage buffers and dynamic storage buffers.

13.1.11. Input Attachment

An input attachment (VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT) is an image view that can be used for pixel local load operations from within fragment shaders bound to pipelines. Loads from input attachments are unfiltered. 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.

In the shader, input attachments must be decorated with their input attachment index in addition to descriptor set and binding numbers.

GLSL example. 

layout (input_attachment_index=i, set=m, binding=n) uniform subpassInput myInputAttachment;

SPIR-V example. 

               ...
          %1 = OpExtInstImport "GLSL.std.450"
               ...
               OpName %9 "myInputAttachment"
               OpDecorate %9 DescriptorSet m
               OpDecorate %9 Binding n
               OpDecorate %9 InputAttachmentIndex i
          %2 = OpTypeVoid
          %3 = OpTypeFunction %2
          %6 = OpTypeFloat 32
          %7 = OpTypeImage %6 SubpassData 0 0 0 2 Unknown
          %8 = OpTypePointer UniformConstant %7
          %9 = OpVariable %8 UniformConstant
               ...