Skip to content

Add VK_EXT_descriptor_indexing Support #6

Description

@mrparmesan01

Overview

In modern Vulkan, focusing more in a dynamic and bindless model for 3D rendering. This task is for keeping track of the progress regarding enabling descriptor indexing to work.

Additional Information for Using Descriptor Indexing

  • Minimize need for CPU to re-bind resources that are already available to access. (Bindless textures, etc)
  • Batching draw calls by having one single giant descriptor that can be reused across multiple draw-calls if needed without having to re-bind those same resources everytime.
  • Goal with descriptor indexing is to move from a per-object/per-material bindings to a per-frame or persistent global bindings
  • Re-binding has its own sets of cost dealing with high resources, when you have to record state when doing vkCmdBindDescriptorSets.

To enable descriptor indexing

Since the device features has been merged into vulkan-cpp, this part should be relatively easy. You would just have this physical device feature be enabled.

Here is what the struct and it's parameters look like and what the parameters would be set to.

VkPhysicalDeviceDescriptorIndexingFeatures indexingFeatures{};
indexingFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES;
indexingFeatures.runtimeDescriptorArray = true;
indexingFeatures.descriptorBindingPartiallyBound = true;
indexingFeatures.descriptorBindingVariableDescriptorCount = true;
indexingFeatures.shaderSampledImageArrayNonUniformIndexing = true;

Since setting up the struct is already provided through vulkan-cpp. This is all you would need to do to enable the descriptor indexing feature.

vk::device_features device_features{
    vk::descriptor_indexing_feature{ {
     .runtimeDescriptorArray = true,
    .descriptorBindingPartiallyBound = true,
    .descriptorBindingVariableDescriptorCount = true,
    .shaderSampledImageArrayNonUniformIndexing = true,
    } },
};

Then when you create the logical device, there is a parameter that you can enable called .features that you can pass the entire chain pointer to.

vk::device_params logical_device_params = {
    .features = device_features.data(), // Here: Pass entire feature pointer chain here!
    // ...
};

API Design

I was considering if maybe, I'd have vk::dyn::descriptor_resource to indicate the differences in API usage, then considerered for simplicity to have vk::descriptor_resource contain both API's for descriptors and descriptor indexing since the API changes are only really in the flags that you use to enable the configuring the descriptor sets with the flags to allow you to use descriptor indexing.

std::vector<vk::descriptor_entry> entries = {
    vk::descriptor_entry{
        // specifies "layout (set = 0, binding = 1) uniform MaterialTextures[];"
        .type = vk::buffer::uniform,
        .binding_point = {
            .binding = 1,
            .stage = vk::shader_stage::vertex,
        },
        .descriptor_count = 1000, // Max of Textures

        // NEW
        .flags = vk::descriptor_bind_flags::partially_bound |
                 vk::descriptor_bind_flags::descriptor_count |
                 vk::descriptor_bind_flags::descriptor_update_after_bind,
    },
};
vk::descriptor_layout set0_layout = {
    .slot = 0,               // indicate specific descriptor slot 0
    .max_sets = image_count, // max descriptors to allocate
    .entries = entries,      // descriptor layout entries description
};

// VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT
vk::descriptor_resource set0_resource(logical_device,
                                      set0_layout,
                                      // NEW
                                      vk::descriptor_layout_flags::update_after_pool_bit);

vk::write_image write_texture = {
    .image_view = /* ... */,
    .sampler = /* ... */,
};

std::array<vk::write_image_descriptor, 1> set1_images = {
    vk::write_image_descriptor{
        .dst_binding = 0,
        .sample_images = std::span<vk::write_image>(&write_texture, 1),
    },
};

set0_resource.update({}, image_descriptors);

Metadata

Metadata

Assignees

Labels

💠coreCritical tasks are reserved for maintainers during fundamental architectural changes.📐designTasks that involve the core systems. Highly involve in API design.

Fields

No fields configured for Feature.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions