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.
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 ...
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 ...
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 ...
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 |
---|---|
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.
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 ...
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 ...
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 ...
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 ...
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.
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.
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 ...