## 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 hardware 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);

- `device` is the logical device that creates the descriptor set layout.
- `pCreateInfo` is a pointer to an instance of the `VkDescriptorSetLayoutCreateInfo` structure specifying the state of the descriptor set layout object.
- `pAllocator` controls host memory allocation as described in the Memory Allocation chapter.
- `pSetLayout` points 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;

- `sType` is the type of this structure.
- `pNext` is `NULL` or a pointer to an extension-specific structure.
- `flags` is reserved for future use.
- `bindingCount` is the number of elements in `pBindings`.
- `pBindings` is a pointer to an array of `VkDescriptorSetLayoutBinding` structures.

The `VkDescriptorSetLayoutBinding` structure is defined as:

    typedef struct VkDescriptorSetLayoutBinding {
        uint32_t              binding;
        VkDescriptorType      descriptorType;
        uint32_t              descriptorCount;
        VkShaderStageFlags    stageFlags;
        const VkSampler*      pImmutableSamplers;
    } VkDescriptorSetLayoutBinding;

- `binding` is the binding number of this entry and corresponds to a resource of the same binding number in the shader stages.
- `descriptorType` is a `VkDescriptorType` specifying which type of resource descriptors are used for this binding.
- `descriptorCount` is the number of descriptors contained in the binding, accessed in a shader as an array. If `descriptorCount` is 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.

- `stageFlags` member is a bitmask of `VkShaderStageFlagBits` specifying which pipeline shader stages can access a resource for this binding. `VK_SHADER_STAGE_ALL` is 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. There are no limitations on what combinations of stages can be used by a descriptor binding, and in particular a binding can be used by both graphics stages and the compute stage.

- `pImmutableSamplers` affects initialization of samplers. If `descriptorType` specifies a `VK_DESCRIPTOR_TYPE_SAMPLER` or `VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER` type descriptor, then `pImmutableSamplers` can 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. If `pImmutableSamplers` is not `NULL`, 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. If `pImmutableSamplers` is `NULL`, then the sampler slots are dynamic and sampler handles must be bound into descriptor sets using this layout. If `descriptorType` is not one of these descriptor types, then `pImmutableSamplers` is 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. 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.

The following examples show a shader snippet using two descriptor sets, and application code that creates corresponding descriptor set layouts.

GLSL example.

    //
    // 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];
    };

SPIR-V example.

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

API example.

    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);

- `device` is the logical device that destroys the descriptor set layout.
- `descriptorSetLayout` is the descriptor set layout to destroy.
- `pAllocator` controls 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);

- `device` is the logical device that creates the pipeline layout.
- `pCreateInfo` is a pointer to an instance of the `VkPipelineLayoutCreateInfo` structure specifying the state of the pipeline layout object.
- `pAllocator` controls host memory allocation as described in the Memory Allocation chapter.
- `pPipelineLayout` points 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;

- `sType` is the type of this structure.
- `pNext` is `NULL` or a pointer to an extension-specific structure.
- `flags` is reserved for future use.
- `setLayoutCount` is the number of descriptor sets included in the pipeline layout.
- `pSetLayouts` is a pointer to an array of `VkDescriptorSetLayout` objects.
- `pushConstantRangeCount` is the number of push constant ranges included in the pipeline layout.

- `pPushConstantRanges` is a pointer to an array of `VkPushConstantRange` structures 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.

  | Note
  Push constants represent a high speed path to modify constant data in pipelines that is expected to outperform memory-backed resource updates.

The `VkPushConstantRange` structure is defined as:

    typedef struct VkPushConstantRange {
        VkShaderStageFlags    stageFlags;
        uint32_t              offset;
        uint32_t              size;
    } VkPushConstantRange;

- `stageFlags` is 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 result in undefined data being read.
- `offset` and `size` are the start offset and size, respectively, consumed by the range. Both `offset` and `size` are 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 hardware resources or memory locations within a descriptor set. The assignment of hardware 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.

Table 13.1. Pipeline Layout Resource Limits

Total Resources Available | Resource Types
--- | ---
`maxDescriptorSetSamplers` | sampler
combined image sampler
`maxDescriptorSetSampledImages` | sampled image
combined image sampler
uniform texel buffer
`maxDescriptorSetStorageImages` | storage image
storage texel buffer
`maxDescriptorSetUniformBuffers` | uniform buffer
uniform buffer dynamic
`maxDescriptorSetUniformBuffersDynamic` | uniform buffer dynamic
`maxDescriptorSetStorageBuffers` | storage buffer
storage buffer dynamic
`maxDescriptorSetStorageBuffersDynamic` | storage buffer dynamic
`maxDescriptorSetInputAttachments` | input attachment

To destroy a pipeline layout, call:

    void vkDestroyPipelineLayout(
        VkDevice                                    device,
        VkPipelineLayout                            pipelineLayout,
        const VkAllocationCallbacks*                pAllocator);

- `device` is the logical device that destroys the pipeline layout.
- `pipelineLayout` is the pipeline layout to destroy.
- `pAllocator` controls 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 matching (the same, or 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).

API example.

    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);

- `device` is the logical device that creates the descriptor pool.
- `pCreateInfo` is a pointer to an instance of the `VkDescriptorPoolCreateInfo` structure specifying the state of the descriptor pool object.
- `pAllocator` controls host memory allocation as described in the Memory Allocation chapter.
- `pDescriptorPool` points 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;

- `sType` is the type of this structure.
- `pNext` is `NULL` or a pointer to an extension-specific structure.

- `flags` specifies certain supported operations on the pool. Bits which can be set include:

      typedef enum VkDescriptorPoolCreateFlagBits {
          VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT = 0x00000001,
      } VkDescriptorPoolCreateFlagBits;

  If `flags` includes `VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT`, then 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.

- `maxSets` is the maximum number of descriptor sets that can be allocated from the pool.
- `poolSizeCount` is the number of elements in `pPoolSizes`.
- `pPoolSizes` is 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.

The `VkDescriptorPoolSize` structure is defined as:

    typedef struct VkDescriptorPoolSize {
        VkDescriptorType    type;
        uint32_t            descriptorCount;
    } VkDescriptorPoolSize;

- `type` is the type of descriptor.
- `descriptorCount` is the number of descriptors of that type to allocate.

To destroy a descriptor pool, call:

    void vkDestroyDescriptorPool(
        VkDevice                                    device,
        VkDescriptorPool                            descriptorPool,
        const VkAllocationCallbacks*                pAllocator);

- `device` is the logical device that destroys the descriptor pool.
- `descriptorPool` is the descriptor pool to destroy.
- `pAllocator` controls 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);

- `device` is the logical device that owns the descriptor pool.
- `pAllocateInfo` is a pointer to an instance of the `VkDescriptorSetAllocateInfo` structure describing parameters of the allocation.
- `pDescriptorSets` is a pointer to an array of `VkDescriptorSet` handles in which the resulting descriptor set objects are returned. The array must be at least the length specified by the `descriptorSetCount` member of `pAllocateInfo`.

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. However, the descriptor set can be bound in a command buffer without causing errors or exceptions. All entries that are statically used by a pipeline in a drawing or dispatching command must have been populated before the descriptor set is bound for use by that command. Entries that are not statically used by a pipeline can have uninitialized descriptors or descriptors of resources that have been destroyed, and executing a draw or dispatch with such a descriptor set bound does not cause undefined behavior. This means applications need not populate unused entries with dummy descriptors.

If an allocation fails due to fragmentation, an indeterminate error is returned with an unspecified error code. Any returned error other than `VK_ERROR_FRAGMENTED_POOL` does not imply its usual meaning: applications should assume that the allocation failed due to fragmentation, and create a new descriptor pool.

| Note
Applications should check for a negative return value when allocating new descriptor sets, assume that any error effectively means `VK_ERROR_FRAGMENTED_POOL`, and try to create a new descriptor pool. If `VK_ERROR_FRAGMENTED_POOL` is the actual return value, it adds certainty to that decision. The reason for this is that `VK_ERROR_FRAGMENTED_POOL` was only added in a later revision of the 1.0 specification, and so drivers may return other errors if they were written against earlier revisions. To ensure full compatibility with earlier patch revisions, these other errors are allowed.

The `VkDescriptorSetAllocateInfo` structure is defined as:

    typedef struct VkDescriptorSetAllocateInfo {
        VkStructureType                 sType;
        const void*                     pNext;
        VkDescriptorPool                descriptorPool;
        uint32_t                        descriptorSetCount;
        const VkDescriptorSetLayout*    pSetLayouts;
    } VkDescriptorSetAllocateInfo;

- `sType` is the type of this structure.
- `pNext` is `NULL` or a pointer to an extension-specific structure.
- `descriptorPool` is the pool which the sets will be allocated from.
- `descriptorSetCount` determines the number of descriptor sets to be allocated from the pool.
- `pSetLayouts` is an array of descriptor set layouts, with each member specifying how the corresponding descriptor set is allocated.

To free allocated descriptor sets, call:

    VkResult vkFreeDescriptorSets(
        VkDevice                                    device,
        VkDescriptorPool                            descriptorPool,
        uint32_t                                    descriptorSetCount,
        const VkDescriptorSet*                      pDescriptorSets);

- `device` is the logical device that owns the descriptor pool.
- `descriptorPool` is the descriptor pool from which the descriptor sets were allocated.
- `descriptorSetCount` is the number of elements in the `pDescriptorSets` array.
- `pDescriptorSets` is 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);

- `device` is the logical device that owns the descriptor pool.
- `descriptorPool` is the descriptor pool to be reset.
- `flags` is 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.

### 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);

- `device` is the logical device that updates the descriptor sets.
- `descriptorWriteCount` is the number of elements in the `pDescriptorWrites` array.
- `pDescriptorWrites` is a pointer to an array of `VkWriteDescriptorSet` structures describing the descriptor sets to write to.
- `descriptorCopyCount` is the number of elements in the `pDescriptorCopies` array.
- `pDescriptorCopies` is 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.

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;

- `sType` is the type of this structure.
- `pNext` is `NULL` or a pointer to an extension-specific structure.
- `dstSet` is the destination descriptor set to update.
- `dstBinding` is the descriptor binding within that set.
- `dstArrayElement` is the starting element in that array.
- `descriptorCount` is the number of descriptors to update (the number of elements in `pImageInfo`, `pBufferInfo`, or `pTexelBufferView`).
- `descriptorType` is a `VkDescriptorType` specifying the type of each descriptor in `pImageInfo`, `pBufferInfo`, or `pTexelBufferView`, as described below. It must be the same type as that specified in `VkDescriptorSetLayoutBinding` for `dstSet` at `dstBinding`. The type of the descriptor also controls which array the descriptors are taken from.
- `pImageInfo` points to an array of `VkDescriptorImageInfo` structures or is ignored, as described below.
- `pBufferInfo` points to an array of `VkDescriptorBufferInfo` structures or is ignored, as described below.
- `pTexelBufferView` points 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, 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. This behavior applies recursively, with the update affecting consecutive bindings as needed to update all `descriptorCount` descriptors. All consecutive bindings updated via a single `VkWriteDescriptorSet` structure must have identical `descriptorType` and `stageFlags`, and must all either use immutable samplers or must all not use immutable samplers.

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,
    } VkDescriptorType;

If `descriptorType` is `VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER`, `VK_DESCRIPTOR_TYPE_STORAGE_BUFFER`, `VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC`, or `VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC`, the elements of the `VkWriteDescriptorSet`::`pBufferInfo` array of `VkDescriptorBufferInfo` structures will be used to update the descriptors, and other arrays will be ignored.

If `descriptorType` is `VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER` or `VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER`, the `VkWriteDescriptorSet`::`pTexelBufferView` array will be used to update the descriptors, and other arrays will be ignored.

If `descriptorType` is `VK_DESCRIPTOR_TYPE_SAMPLER`, `VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER`, `VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE`, `VK_DESCRIPTOR_TYPE_STORAGE_IMAGE`, or `VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT`, the elements of the `VkWriteDescriptorSet`::`pImageInfo` array of `VkDescriptorImageInfo` structures will be used to update the descriptors, and other arrays will be ignored.

The `VkDescriptorBufferInfo` structure is defined as:

    typedef struct VkDescriptorBufferInfo {
        VkBuffer        buffer;
        VkDeviceSize    offset;
        VkDeviceSize    range;
    } VkDescriptorBufferInfo;

- `buffer` is the buffer resource.
- `offset` is the offset in bytes from the start of `buffer`. Access to buffer memory via this descriptor uses addressing that is relative to this starting offset.

- `range` is the size in bytes that is used for this descriptor update, or `VK_WHOLE_SIZE` to use the range from `offset` to the end of the buffer.

  | Note
  When using `VK_WHOLE_SIZE`, the effective range must not be larger than the maximum range for the descriptor type (maxUniformBufferRange or maxStorageBufferRange). This means that `VK_WHOLE_SIZE` is not typically useful in the common case where uniform buffer descriptors are suballocated from a buffer that is much larger than `maxUniformBufferRange`.

  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;

- `sampler` is a sampler handle, and is used in descriptor updates for types `VK_DESCRIPTOR_TYPE_SAMPLER` and `VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER` if the binding being updated does not use immutable samplers.
- `imageView` is an image view handle, and is used in descriptor updates for types `VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE`, `VK_DESCRIPTOR_TYPE_STORAGE_IMAGE`, `VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER`, and `VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT`.
- `imageLayout` is the layout that the image will be in at the time this descriptor is accessed. `imageLayout` is used in descriptor updates for types `VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE`, `VK_DESCRIPTOR_TYPE_STORAGE_IMAGE`, `VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER`, and `VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT`.

Members of `VkDescriptorImageInfo` that are not used in an update (as described above) are ignored.

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;

- `sType` is the type of this structure.
- `pNext` is `NULL` or a pointer to an extension-specific structure.
- `srcSet`, `srcBinding`, and `srcArrayElement` are the source set, binding, and array element, respectively.
- `dstSet`, `dstBinding`, and `dstArrayElement` are the destination set, binding, and array element, respectively.
- `descriptorCount` is the number of descriptors to copy from the source to destination. If `descriptorCount` is 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.

### 13.2.5. 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);

- `commandBuffer` is the command buffer that the descriptor sets will be bound to.
- `pipelineBindPoint` is 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.
- `layout` is a `VkPipelineLayout` object used to program the bindings.
- `firstSet` is the set number of the first descriptor set to be bound.
- `descriptorSetCount` is the number of elements in the `pDescriptorSets` array.
- `pDescriptorSets` is an array of handles to `VkDescriptorSet` objects describing the descriptor sets to write to.
- `dynamicOffsetCount` is the number of dynamic offsets in the `pDynamicOffsets` array.
- `pDynamicOffsets` is a pointer to an array of `uint32_t` values 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 length 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 during host execution of the command, or during shader execution of the resulting draws, or any time in between. Thus, the contents must not be altered (overwritten by an update command, or freed) between when the command is recorded 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.6. 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);

- `commandBuffer` is the command buffer in which the push constant update will be recorded.
- `layout` is the pipeline layout used to program the push constant updates.
- `stageFlags` is a bitmask of `VkShaderStageFlagBits` specifying the shader stages that will use the push constants in the updated range.
- `offset` is the start offset of the push constant range to update, in units of bytes.
- `size` is the size of the push constant range to update, in units of bytes.
- `pValues` is an array of `size` bytes containing the new push constant values.