Skip to content

Commit

Permalink
[D3D12] Enable resource arrays in D3D12RootParameter.
Browse files Browse the repository at this point in the history
- Use 'BindingDescriptor::arraySize' member when building heap-descriptor layout in D3D12PipelineLayout.
- Ignore call to D3D12RootParameter::AppendDescriptorTableRange() if new descriptor slot overlaps with previous descriptor range (to avoid duplicate binding of expanded heap-descriptors).
- Added two new container utility template functions: ResizeNoRealloc() and AppendElementNoRealloc().
  • Loading branch information
LukasBanana committed Jun 23, 2024
1 parent 46445a7 commit 493bdea
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 8 deletions.
24 changes: 22 additions & 2 deletions sources/Core/CoreUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@


#include "../Renderer/CheckedCast.h"
#include "Assertion.h"
#include <LLGL/Export.h>
#include <LLGL/Types.h>
#include <algorithm>
Expand Down Expand Up @@ -111,6 +112,25 @@ void RemoveFromSharedList(Container& cont, const T* entry)
}
}

// Resizes the specified container and throws an exception if the container would have to be re-allocated.
// Returns the pointer to the first new element.
template <typename Container>
typename Container::pointer ResizeNoRealloc(Container& cont, typename Container::size_type count)
{
LLGL_ASSERT(cont.size() + count <= cont.capacity(), "exceeded capacity to append element without re-allocating container");
typename Container::size_type offset = cont.size();
cont.resize(cont.size() + count);
return &(cont[offset]);
}

// Appends one new element to the specified container and throws an exception if the container would have to be re-allocated.
template <typename Container>
typename Container::reference AppendElementNoRealloc(Container& cont)
{
return *ResizeNoRealloc(cont, 1);
}


/*
\brief Returns the next resource from the specified resource array.
\param[in,out] numResources Specifies the remaining number of resources in the array.
Expand Down Expand Up @@ -198,14 +218,14 @@ Returns the image buffer size (in bytes) with aligned row stride for a given 3D
The last row of the last layer will have length 'rowSize', all other rows will have length 'alignedRowStride'.
*/
template <typename T>
T GetAlignedImageSize(const Extent3D& extent, T rowSize, T alignedRowStride)
constexpr T GetAlignedImageSize(const Extent3D& extent, T rowSize, T alignedRowStride)
{
return (alignedRowStride * extent.height) * (extent.depth - 1) + (alignedRowStride * (extent.height - 1) + rowSize);
}

// Clamps value x into the range [minimum, maximum].
template <typename T>
T Clamp(T x, T minimum, T maximum)
const T& Clamp(const T& x, const T& minimum, const T& maximum)
{
return std::max<T>(minimum, std::min<T>(x, maximum));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -323,15 +323,15 @@ void D3D12PipelineLayout::BuildHeapRootParameterTableEntry(
if (D3D12RootParameter* rootParam = rootSignature.FindCompatibleRootParameter(descRangeType))
{
/* Append descriptor range to previous root parameter */
rootParam->AppendDescriptorTableRange(descRangeType, bindingDesc.slot, 1u);//std::max<UINT>(1u, bindingDesc.arraySize));
rootParam->AppendDescriptorTableRange(descRangeType, bindingDesc.slot, std::max<UINT>(1u, bindingDesc.arraySize));
}
else
{
/* Create new root parameter and append descriptor range */
UINT rootParamIndex = 0;
rootParam = rootSignature.AppendRootParameter(&rootParamIndex);
rootParam->InitAsDescriptorTable(maxNumDescriptorRanges);
rootParam->AppendDescriptorTableRange(descRangeType, bindingDesc.slot, 1u);//std::max<UINT>((1u, bindingDesc.arraySize));
rootParam->AppendDescriptorTableRange(descRangeType, bindingDesc.slot, std::max<UINT>(1u, bindingDesc.arraySize));

/* Store root parameter index */
UINT8& rootParamIndexStored = rootParameterIndices_.rootParamDescriptorHeaps[GetDescriptorTypeShift(descRangeType)];
Expand Down Expand Up @@ -401,15 +401,15 @@ void D3D12PipelineLayout::BuildRootParameterTableEntry(
if (D3D12RootParameter* rootParam = rootSignature.FindCompatibleRootParameter(descRangeType, rootParamOffset))
{
/* Append descriptor range to previous root parameter */
rootParam->AppendDescriptorTableRange(descRangeType, bindingDesc.slot, std::max(1u, bindingDesc.arraySize));
rootParam->AppendDescriptorTableRange(descRangeType, bindingDesc.slot);
}
else
{
/* Create new root parameter and append descriptor range */
UINT rootParamIndex = 0;
rootParam = rootSignature.AppendRootParameter(&rootParamIndex);
rootParam->InitAsDescriptorTable(maxNumDescriptorRanges);
rootParam->AppendDescriptorTableRange(descRangeType, bindingDesc.slot, std::max(1u, bindingDesc.arraySize));
rootParam->AppendDescriptorTableRange(descRangeType, bindingDesc.slot);

/* Store root parameter index */
UINT8& rootParamIndexStored = rootParameterIndices_.rootParamDescriptors[GetDescriptorTypeShift(descRangeType)];
Expand Down
19 changes: 17 additions & 2 deletions sources/Renderer/Direct3D12/Shader/D3D12RootParameter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "D3D12RootParameter.h"
#include <LLGL/ShaderFlags.h>
#include <LLGL/PipelineLayoutFlags.h>
#include "../../../Core/CoreUtils.h"


namespace LLGL
Expand Down Expand Up @@ -78,11 +79,25 @@ void D3D12RootParameter::InitAsDescriptorTable(UINT maxNumDescriptorRanges, D3D1
managedRootParam_->ShaderVisibility = visibility;
}

static bool IsIncludedInDescriptorRange(const D3D12_DESCRIPTOR_RANGE& descRange, D3D12_DESCRIPTOR_RANGE_TYPE rangeType, UINT baseShaderRegister, UINT registerSpace)
{
return
(
rangeType == descRange.RangeType &&
registerSpace == descRange.RegisterSpace &&
baseShaderRegister >= descRange.BaseShaderRegister &&
baseShaderRegister < descRange.BaseShaderRegister + descRange.NumDescriptors
);
}

void D3D12RootParameter::AppendDescriptorTableRange(D3D12_DESCRIPTOR_RANGE_TYPE rangeType, UINT baseShaderRegister, UINT numDescriptors, UINT registerSpace)
{
/* Ignore this call if the input is already included in the current range */
if (!descRanges_.empty() && IsIncludedInDescriptorRange(descRanges_.back(), rangeType, baseShaderRegister, registerSpace))
return;

/* Add new descriptor range to array */
descRanges_.resize(descRanges_.size() + 1);
auto& descRange = descRanges_.back();
D3D12_DESCRIPTOR_RANGE& descRange = AppendElementNoRealloc(descRanges_);

/* Initialize descriptor range */
descRange.RangeType = rangeType;
Expand Down

0 comments on commit 493bdea

Please sign in to comment.