Vireo  0.0
Vireo 3D Rendering Hardware Interface
Descriptor Set

A descriptor set is a collection of shader resources bindings — think of it as a bundle that tells the GPU “here are all the buffers, images and samplers this shader will need.”

Creating a descriptor set

A descriptor set is created from a description of the resources in the form of a descriptor layout with vireo::Vireo::createDescriptorSet.

// Create a generic descriptor set
frame.descriptorSet = vireo->createDescriptorSet(descriptorLayout);
// Create a dynamic uniform descriptor set
frame.materialsDescriptorSet = vireo->createDescriptorSet(materialsDescriptorLayout);

Updating a descriptor set

Before use, fill each set’s slots with actual buffer, image or sampler via vireo::DescriptorSet::update methods. This can be done at any time except inside a render pass.

For each resource added to the corresponding descriptor layout you need to call vireo::DescriptorSet::update with the same binding numbers and the same resource type.

...
static constexpr vireo::DescriptorIndex BINDING_GLOBAL{0};
static constexpr vireo::DescriptorIndex BINDING_LIGHT{1};
static constexpr vireo::DescriptorIndex BINDING_TEXTURES{2};
...
// Update during the initialization phase
// Updating a generic descriptor set
frame.descriptorSet->update(BINDING_GLOBAL, frame.globalUniform);
frame.descriptorSet->update(BINDING_LIGHT, frame.lightUniform);
frame.descriptorSet->update(BINDING_TEXTURES, scene.getTextures());
// Updating a dynamic uniform descriptor set
frame.materialsDescriptorSet->update(frame.materialUniform);
// Update during the render phase, before beginRendering()
frame.smaaEdgeDescriptorSet->update(BINDING_INPUT, colorBuffer->getImage());

Binding descriptor sets

When recording commands during a render pass, after binding the pipeline to the command list bind the descriptor sets with vireo::CommandList::bindDescriptor or vireo::CommandList::bindDescriptors

If you use dynamic uniform buffer vireo::CommandList::bindDescriptor let you change buffer offsets at bind time without reallocating sets.

Each descriptor set will the bound to a specific set/space number.

...
static constexpr vireo::DescriptorIndex SET_GLOBAL{0};
static constexpr vireo::DescriptorIndex SET_SAMPLERS{1};
static constexpr vireo::DescriptorIndex SET_MODELS{2};
static constexpr vireo::DescriptorIndex SET_MATERIALS{3};
...
// Start a render pass
cmdList->beginRendering(renderingConfig);
...
// Bind the pipeline
cmdList->bindPipeline(pipeline);
...
// Bind the generic and samplers descriptor sets to the pipeline
cmdList->bindDescriptor(frame.descriptorSet, SET_GLOBAL);
cmdList->bindDescriptor(samplers.getDescriptorSet(), SET_SAMPLERS);
// Bind a specific buffer in a uniform dynamic descriptor set
cmdList->bindDescriptor(
frame.materialsDescriptorSet,
SET_MATERIALS,
frame.materialUniform->getInstanceSizeAligned() * Scene::MATERIAL_ROCKS);
...
scene.drawCube(cmdList);
...

If you don't need dynamic uniform descriptor set you can bind the sets using one command :

cmdList->bindDescriptors({frame.descriptorSet, samplers.getDescriptorSet()});

The sets/spaces numbers will be calculated from the vector index.

Using resources of a descriptor set

In the shaders code each resource need to be bound to the corresponding binding and set/space numbers.

If you use the Slang shader language just use the HLSL register syntax, it will works for both Vulkan and Direct X :

// Binding of resources in a shader
ConstantBuffer<Global> global : register(b0, space0); // BINDING_GLOBAL, SET_GLOBAL
ConstantBuffer<Light> light : register(b1, space0); // BINDING_LIGHT, SET_GLOBAL
Texture2D textures[5] : register(t2, space0); // BINDING_TEXTURES, SET_GLOBAL
SamplerState sampler : register(SAMPLER_LINEAR_EDGE, space1); // SET_SAMPLERS
ConstantBuffer<Material> material : register(b0, space3); // selected dynamic buffer of the SET_MATERIALS