LiteFX 0.4.1.2025
Computer Graphics Engine
Loading...
Searching...
No Matches
LiteFX::Rendering::DescriptorSet< TBuffer, TImage, TSampler, TAccelerationStructure > Class Template Referenceabstract

Defines a set of descriptors. More...

#include <rendering.hpp>

Inherits LiteFX::Rendering::IDescriptorSet.

Public Types

using buffer_type = TBuffer
 
using sampler_type = TSampler
 
using image_type = TImage
 
using acceleration_structure_type = TAccelerationStructure
 

Public Member Functions

 ~DescriptorSet () noexcept override=default
 
virtual void update (UInt32 binding, const buffer_type &buffer, UInt32 bufferElement=0, UInt32 elements=0, UInt32 firstDescriptor=0) const =0
 
virtual void update (UInt32 binding, const image_type &texture, UInt32 descriptor=0, UInt32 firstLevel=0, UInt32 levels=0, UInt32 firstLayer=0, UInt32 layers=0) const =0
 
virtual void update (UInt32 binding, const sampler_type &sampler, UInt32 descriptor=0) const =0
 
virtual void update (UInt32 binding, const acceleration_structure_type &accelerationStructure, UInt32 descriptor=0) const =0
 
void update (UInt32 binding, const IBuffer &buffer, UInt32 bufferElement=0, UInt32 elements=0, UInt32 firstDescriptor=0) const
 Updates one or more buffer descriptors within the current descriptor set.
 
void update (UInt32 binding, const IImage &texture, UInt32 descriptor=0, UInt32 firstLevel=0, UInt32 levels=0, UInt32 firstLayer=0, UInt32 layers=0) const
 Updates one or more texture descriptors within the current descriptor set.
 
void update (UInt32 binding, const ISampler &sampler, UInt32 descriptor=0) const
 Updates one or more sampler descriptors within the current descriptor set.
 
void update (UInt32 binding, const IAccelerationStructure &accelerationStructure, UInt32 descriptor=0) const
 Updates an acceleration structure within the current descriptor set.
 
- Public Member Functions inherited from LiteFX::Rendering::IDescriptorSet
virtual ~IDescriptorSet () noexcept=default
 
void update (UInt32 binding, const IBuffer &buffer, UInt32 bufferElement=0, UInt32 elements=0, UInt32 firstDescriptor=0) const
 Updates one or more buffer descriptors within the current descriptor set.
 
void update (UInt32 binding, const IImage &texture, UInt32 descriptor=0, UInt32 firstLevel=0, UInt32 levels=0, UInt32 firstLayer=0, UInt32 layers=0) const
 Updates one or more texture descriptors within the current descriptor set.
 
void update (UInt32 binding, const ISampler &sampler, UInt32 descriptor=0) const
 Updates one or more sampler descriptors within the current descriptor set.
 
void update (UInt32 binding, const IAccelerationStructure &accelerationStructure, UInt32 descriptor=0) const
 Updates an acceleration structure within the current descriptor set.
 

Protected Member Functions

 DescriptorSet () noexcept=default
 
 DescriptorSet (const DescriptorSet &)=default
 
 DescriptorSet (DescriptorSet &&) noexcept=default
 
DescriptorSetoperator= (const DescriptorSet &)=default
 
DescriptorSetoperator= (DescriptorSet &&) noexcept=default
 
- Protected Member Functions inherited from LiteFX::Rendering::IDescriptorSet
 IDescriptorSet () noexcept=default
 
 IDescriptorSet (const IDescriptorSet &)=default
 
 IDescriptorSet (IDescriptorSet &&) noexcept=default
 
IDescriptorSetoperator= (const IDescriptorSet &)=default
 
IDescriptorSetoperator= (IDescriptorSet &&) noexcept=default
 

Detailed Description

template<typename TBuffer, typename TImage, typename TSampler, typename TAccelerationStructure>
requires std::derived_from<TBuffer, IBuffer> && std::derived_from<TSampler, ISampler> && std::derived_from<TImage, IImage> && std::derived_from<TAccelerationStructure, IAccelerationStructure>
class LiteFX::Rendering::DescriptorSet< TBuffer, TImage, TSampler, TAccelerationStructure >

Defines a set of descriptors.

Descriptors can be grouped into multiple descriptor sets. It is generally a good practice to group descriptors based on the frequency of the updates they receive. For example, it typically makes sense to store the camera buffer in a descriptor set, since it only needs to be updated once per frame for each camera, whilst the object or material data should be stored in separate descriptor sets, that are possibly updated before each draw call. However, other scenarios employing multiple descriptor sets are also possible.

From a shader perspective, a descriptor set is identified by a set (GLSL) or space (HLSL), whilst a descriptor is addressed by a binding (GLSL) or register (HLSL). Descriptor sets are read from GPU-visible memory, depending on how they are bound during the current draw call.

From a CPU perspective, think of a descriptor set as an array of pointers to different buffers (i.e. descriptors) for the shader. A descriptor can be bound to a set by calling DescriptorSet::update. Note that this does not automatically ensure, that the buffer memory is visible for the GPU. Instead, a buffer may also require a transfer into GPU visible memory, depending on the ResourceHeap. However, as long as a descriptor within a set is mapped to a buffer, modifying this buffer also reflects the change to the shader, without requiring to update the descriptor, similarly to how modifying the object behind a pointer does not require the pointer to change.

Note, that there might be multiple descriptor set instances of the same DescriptorSetLayout, pointing to different IBuffer instances, depending on the number of frames in flight. Since multiple frames can be computed concurrently, it is important to properly synchronize descriptor set updates. Generally, there are three strategies to choose from, that you can implement or mix in custom flavors, depending on your use case:

  • Naive: The naive approach most closely matches earlier graphics API concepts. Create one buffer per descriptor and synchronize frames. This basically means that each back buffer swap is synchronized to wait for the graphics pipeline. This way, writing to a buffer ensures, that it is only read within the frame of reference and modifying it does not interfere with other frames. This strategy is memory efficient, but may cause the GPU to stall. It may, however be a valid strategy, for data that is only written once or very infrequently.
  • Array of Buffers: The helper methods for creating and updating constant buffers are able to create buffer arrays. Those arrays can be used to create a buffer for each frame in flight. When binding a buffer to a descriptor, it is possible to bind only one element of the array. This way, each frame has its own buffer and does not interfere with other buffer writes.
  • Ring-Buffer: The most efficient (yet not always applicable) approach involves creating one large buffer array, that is bound to multiple descriptor sets. This ensures that the buffer memory stays contiguous and does not get fragmented. However, this requires to know upfront, how many buffers are required for each descriptor, which might not always be possible. Thus another flavor of using this technique involves a creating a large enough descriptor array and updating the descriptor set with an increasing array element for each object as a ring-buffer. As long as there are enough elements in the buffer, so that no second update interferes with a buffer write in an earlier frame, this method provides the most efficient approach. However, it may be hard or impossible to determine the ideal size of the ring-buffer upfront. </itemattach

Note that samplers, textures and input attachments currently do not support array binding, since they are typically only updated once or require pipeline synchronization anyway.

Also note, that another buffer management strategy is currently not available: the Monolithic Buffer. In this strategy, there is only one large buffer for all buffers. Differently from the ring buffer strategy, where there is one buffer per descriptor type, a monolithic buffer combines multiple constant buffers, containing different data into one giant buffer block. Calling RenderPipeline::bind for a descriptor set would then receive an additional dynamic offset for each descriptor within the descriptor set.

Template Parameters
TBufferThe type of the buffer interface. Must inherit from IBuffer.
TImageThe type of the image interface. Must inherit from IImage.
TSamplerThe type of the sampler interface. Must inherit from ISampler.
TAccelerationStructureThe type of the acceleration structure interface. Must inherit from IAccelerationStructure.
See also
DescriptorSetLayout

Member Typedef Documentation

◆ acceleration_structure_type

template<typename TBuffer , typename TImage , typename TSampler , typename TAccelerationStructure >
using LiteFX::Rendering::DescriptorSet< TBuffer, TImage, TSampler, TAccelerationStructure >::acceleration_structure_type = TAccelerationStructure

◆ buffer_type

template<typename TBuffer , typename TImage , typename TSampler , typename TAccelerationStructure >
using LiteFX::Rendering::DescriptorSet< TBuffer, TImage, TSampler, TAccelerationStructure >::buffer_type = TBuffer

◆ image_type

template<typename TBuffer , typename TImage , typename TSampler , typename TAccelerationStructure >
using LiteFX::Rendering::DescriptorSet< TBuffer, TImage, TSampler, TAccelerationStructure >::image_type = TImage

◆ sampler_type

template<typename TBuffer , typename TImage , typename TSampler , typename TAccelerationStructure >
using LiteFX::Rendering::DescriptorSet< TBuffer, TImage, TSampler, TAccelerationStructure >::sampler_type = TSampler

Constructor & Destructor Documentation

◆ DescriptorSet() [1/3]

template<typename TBuffer , typename TImage , typename TSampler , typename TAccelerationStructure >
LiteFX::Rendering::DescriptorSet< TBuffer, TImage, TSampler, TAccelerationStructure >::DescriptorSet ( )
protecteddefaultnoexcept

◆ DescriptorSet() [2/3]

template<typename TBuffer , typename TImage , typename TSampler , typename TAccelerationStructure >
LiteFX::Rendering::DescriptorSet< TBuffer, TImage, TSampler, TAccelerationStructure >::DescriptorSet ( const DescriptorSet< TBuffer, TImage, TSampler, TAccelerationStructure > & )
protecteddefault

◆ DescriptorSet() [3/3]

template<typename TBuffer , typename TImage , typename TSampler , typename TAccelerationStructure >
LiteFX::Rendering::DescriptorSet< TBuffer, TImage, TSampler, TAccelerationStructure >::DescriptorSet ( DescriptorSet< TBuffer, TImage, TSampler, TAccelerationStructure > && )
protecteddefaultnoexcept

◆ ~DescriptorSet()

template<typename TBuffer , typename TImage , typename TSampler , typename TAccelerationStructure >
LiteFX::Rendering::DescriptorSet< TBuffer, TImage, TSampler, TAccelerationStructure >::~DescriptorSet ( )
overridedefaultnoexcept

Member Function Documentation

◆ operator=() [1/2]

template<typename TBuffer , typename TImage , typename TSampler , typename TAccelerationStructure >
DescriptorSet & LiteFX::Rendering::DescriptorSet< TBuffer, TImage, TSampler, TAccelerationStructure >::operator= ( const DescriptorSet< TBuffer, TImage, TSampler, TAccelerationStructure > & )
protecteddefault

◆ operator=() [2/2]

template<typename TBuffer , typename TImage , typename TSampler , typename TAccelerationStructure >
DescriptorSet & LiteFX::Rendering::DescriptorSet< TBuffer, TImage, TSampler, TAccelerationStructure >::operator= ( DescriptorSet< TBuffer, TImage, TSampler, TAccelerationStructure > && )
protecteddefaultnoexcept

◆ update() [1/8]

template<typename TBuffer , typename TImage , typename TSampler , typename TAccelerationStructure >
virtual void LiteFX::Rendering::DescriptorSet< TBuffer, TImage, TSampler, TAccelerationStructure >::update ( UInt32 binding,
const acceleration_structure_type & accelerationStructure,
UInt32 descriptor = 0 ) const
pure virtual

◆ update() [2/8]

template<typename TBuffer , typename TImage , typename TSampler , typename TAccelerationStructure >
virtual void LiteFX::Rendering::DescriptorSet< TBuffer, TImage, TSampler, TAccelerationStructure >::update ( UInt32 binding,
const buffer_type & buffer,
UInt32 bufferElement = 0,
UInt32 elements = 0,
UInt32 firstDescriptor = 0 ) const
pure virtual

◆ update() [3/8]

template<typename TBuffer , typename TImage , typename TSampler , typename TAccelerationStructure >
void LiteFX::Rendering::IDescriptorSet::update ( UInt32 binding,
const IAccelerationStructure & accelerationStructure,
UInt32 descriptor = 0 ) const
inline

Updates an acceleration structure within the current descriptor set.

Parameters
bindingThe acceleration structure binding point.
accelerationStructureThe acceleration structure to write to the descriptor set.
descriptorThe index of the descriptor in the descriptor array to bind the acceleration structure to.

◆ update() [4/8]

template<typename TBuffer , typename TImage , typename TSampler , typename TAccelerationStructure >
void LiteFX::Rendering::IDescriptorSet::update ( UInt32 binding,
const IBuffer & buffer,
UInt32 bufferElement = 0,
UInt32 elements = 0,
UInt32 firstDescriptor = 0 ) const
inline

Updates one or more buffer descriptors within the current descriptor set.

Parameters
bindingThe buffer binding point.
bufferThe buffer to write to the descriptor set.
bufferElementThe index of the first element in the buffer to bind to the descriptor set.
elementsThe number of elements from the buffer to bind to the descriptor set. A value of 0 binds all available elements, starting at bufferElement .
firstDescriptorThe index of the first descriptor in the descriptor array to update.

◆ update() [5/8]

template<typename TBuffer , typename TImage , typename TSampler , typename TAccelerationStructure >
void LiteFX::Rendering::IDescriptorSet::update ( UInt32 binding,
const IImage & texture,
UInt32 descriptor = 0,
UInt32 firstLevel = 0,
UInt32 levels = 0,
UInt32 firstLayer = 0,
UInt32 layers = 0 ) const
inline

Updates one or more texture descriptors within the current descriptor set.

The exact representation of the level and layer parameters depends on the dimension of the provided texture, as well as the type of the descriptor identified by the binding parameter.

If the texture itself is not an array (i.e. the number of layers equals 1), the parameters firstLayer and layers are ignored.

The descriptor type dictates, how mip-maps can be provided. If the descriptor type identifies a writable texture, the firstLevel parameter specifies the mip-map level to write to (or read from). Multiple levels are not allowed in this case, so the levels parameter is ignored. Instead, you have to bind them to separate descriptors. Furthermore, the firstLayer and layers parameter can be used to specify the number of depth or W-slices of a writable 3D texture or the side(s) of a cube map.

Parameters
bindingThe texture binding point.
textureThe texture to write to the descriptor set.
descriptorThe index of the descriptor in the descriptor array to bind the texture to.
firstLevelThe index of the first mip-map level to bind.
levelsThe number of mip-map levels to bind. A value of 0 binds all available levels, starting at firstLevel .
firstLayerThe index of the first layer to bind.
layersThe number of layers to bind. A value of 0 binds all available layers, starting at firstLayer .

◆ update() [6/8]

template<typename TBuffer , typename TImage , typename TSampler , typename TAccelerationStructure >
virtual void LiteFX::Rendering::DescriptorSet< TBuffer, TImage, TSampler, TAccelerationStructure >::update ( UInt32 binding,
const image_type & texture,
UInt32 descriptor = 0,
UInt32 firstLevel = 0,
UInt32 levels = 0,
UInt32 firstLayer = 0,
UInt32 layers = 0 ) const
pure virtual

◆ update() [7/8]

template<typename TBuffer , typename TImage , typename TSampler , typename TAccelerationStructure >
void LiteFX::Rendering::IDescriptorSet::update ( UInt32 binding,
const ISampler & sampler,
UInt32 descriptor = 0 ) const
inline

Updates one or more sampler descriptors within the current descriptor set.

Parameters
bindingThe sampler binding point.
samplerThe sampler to write to the descriptor set.
descriptorThe index of the descriptor in the descriptor array to bind the sampler to.

◆ update() [8/8]

template<typename TBuffer , typename TImage , typename TSampler , typename TAccelerationStructure >
virtual void LiteFX::Rendering::DescriptorSet< TBuffer, TImage, TSampler, TAccelerationStructure >::update ( UInt32 binding,
const sampler_type & sampler,
UInt32 descriptor = 0 ) const
pure virtual