Create descriptor set

In Vulkan, binding is done through descriptors. For using descriptors, 3 classes are key:

  • Descriptor pool
  • Descriptor set
  • Descriptor layout

The descriptor pool is used in order to create a large chunk of memory to be subdivided into descriptor sets.

The descriptor sets are the objects responsible for binding resources. These descriptor sets are bound to the command list for usage by a pipeline state during the rendering process, and contains a list of all resources to be used.

The descriptor layout is used both in the creation of both the descriptor set and the pipeline state. The descriptor set will gather information on which descriptors to allocate from a descriptor pool, and the pipeline state will know the exact layout of descriptor sets to be allowed to be bound at runtime.

For this example, we will only need a single descriptor set with a number of combined image sampler objects. We will index the list of textures in the fragment shader using a dynamic index passed by the application when drawing new meshes, allowing us to keep the bindings static.

VkDescriptorPool descriptorPool;
result = vkCreateDescriptorPool (
    renderer->device,
    &(VkDescriptorPoolCreateInfo){
        .sType         = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
        .pNext         = NULL,
        .flags         = 0,
        .maxSets       = 1,
        .poolSizeCount = 1,
        .pPoolSizes    = (VkDescriptorPoolSize[1]){ { .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, .descriptorCount = 64 } },
    },
    NULL,
    &descriptorPool
);
if ( result != VK_SUCCESS )
    RETURN_ERROR(-1, "vkCreateDescriptorPool failed (0x%08X)", (uint32_t)result);

VkDescriptorSetLayout dsLayout;
result = vkCreateDescriptorSetLayout (
    renderer->device,
    &(VkDescriptorSetLayoutCreateInfo){
        .sType        = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
        .pNext        = NULL,
        .flags        = 0,
        .bindingCount = 1,
        .pBindings    = (VkDescriptorSetLayoutBinding[1]){
            [0] = {
                .binding         = 0,
                .descriptorType  = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
                .descriptorCount = 64,
                .stageFlags      = VK_SHADER_STAGE_FRAGMENT_BIT,
            },
        },
    },
    NULL,
    &dsLayout
);
if ( result != VK_SUCCESS )
    RETURN_ERROR(-1, "vkCreateDescriptorSetLayout failed (0x%08X)", (uint32_t)result);

result = vkAllocateDescriptorSets (
    renderer->device,
    &(VkDescriptorSetAllocateInfo){
        .sType              = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
        .pNext              = NULL,
        .descriptorPool     = descriptorPool,
        .descriptorSetCount = 1,
        .pSetLayouts        = (VkDescriptorSetLayout[1]) { dsLayout },
    },
    &renderer->descriptorSet
);
if ( result != VK_SUCCESS )
    RETURN_ERROR(-1, "vkAllocateDescriptorSets failed (0x%08X)", (uint32_t)result);