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