diff --git a/sources/Core/CoreUtils.h b/sources/Core/CoreUtils.h index 46e3da7a10..cc7befd657 100644 --- a/sources/Core/CoreUtils.h +++ b/sources/Core/CoreUtils.h @@ -10,6 +10,7 @@ #include "../Renderer/CheckedCast.h" +#include "Assertion.h" #include #include #include @@ -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::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::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. @@ -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 -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 -T Clamp(T x, T minimum, T maximum) +const T& Clamp(const T& x, const T& minimum, const T& maximum) { return std::max(minimum, std::min(x, maximum)); } diff --git a/sources/Renderer/Direct3D12/RenderState/D3D12PipelineLayout.cpp b/sources/Renderer/Direct3D12/RenderState/D3D12PipelineLayout.cpp index cab494edce..7813a3e11e 100644 --- a/sources/Renderer/Direct3D12/RenderState/D3D12PipelineLayout.cpp +++ b/sources/Renderer/Direct3D12/RenderState/D3D12PipelineLayout.cpp @@ -323,7 +323,7 @@ void D3D12PipelineLayout::BuildHeapRootParameterTableEntry( if (D3D12RootParameter* rootParam = rootSignature.FindCompatibleRootParameter(descRangeType)) { /* Append descriptor range to previous root parameter */ - rootParam->AppendDescriptorTableRange(descRangeType, bindingDesc.slot, 1u);//std::max(1u, bindingDesc.arraySize)); + rootParam->AppendDescriptorTableRange(descRangeType, bindingDesc.slot, std::max(1u, bindingDesc.arraySize)); } else { @@ -331,7 +331,7 @@ void D3D12PipelineLayout::BuildHeapRootParameterTableEntry( UINT rootParamIndex = 0; rootParam = rootSignature.AppendRootParameter(&rootParamIndex); rootParam->InitAsDescriptorTable(maxNumDescriptorRanges); - rootParam->AppendDescriptorTableRange(descRangeType, bindingDesc.slot, 1u);//std::max((1u, bindingDesc.arraySize)); + rootParam->AppendDescriptorTableRange(descRangeType, bindingDesc.slot, std::max(1u, bindingDesc.arraySize)); /* Store root parameter index */ UINT8& rootParamIndexStored = rootParameterIndices_.rootParamDescriptorHeaps[GetDescriptorTypeShift(descRangeType)]; @@ -401,7 +401,7 @@ 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 { @@ -409,7 +409,7 @@ void D3D12PipelineLayout::BuildRootParameterTableEntry( 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)]; diff --git a/sources/Renderer/Direct3D12/Shader/D3D12RootParameter.cpp b/sources/Renderer/Direct3D12/Shader/D3D12RootParameter.cpp index f2d7ee4336..1e53352ee9 100644 --- a/sources/Renderer/Direct3D12/Shader/D3D12RootParameter.cpp +++ b/sources/Renderer/Direct3D12/Shader/D3D12RootParameter.cpp @@ -8,6 +8,7 @@ #include "D3D12RootParameter.h" #include #include +#include "../../../Core/CoreUtils.h" namespace LLGL @@ -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;