diff options
| author | assiduous <assiduous@diligentgraphics.com> | 2021-02-13 06:45:06 +0000 |
|---|---|---|
| committer | assiduous <assiduous@diligentgraphics.com> | 2021-03-19 00:31:37 +0000 |
| commit | b3171bcbda58bf5df5e0a482f88f6f234c6657c2 (patch) | |
| tree | c8a8f497bc651e89e8ba75a3c24ca62935a341cf /Graphics/GraphicsEngineD3D12 | |
| parent | PipelineResourceSignatureD3D12Impl: reworked indexing of m_SrvCbvUavRootTable... (diff) | |
| download | DiligentCore-b3171bcbda58bf5df5e0a482f88f6f234c6657c2.tar.gz DiligentCore-b3171bcbda58bf5df5e0a482f88f6f234c6657c2.zip | |
Refactored RootParamsManager: added RootParamsBuilder
Diffstat (limited to 'Graphics/GraphicsEngineD3D12')
5 files changed, 415 insertions, 424 deletions
diff --git a/Graphics/GraphicsEngineD3D12/include/PipelineResourceSignatureD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/PipelineResourceSignatureD3D12Impl.hpp index 45c6dd36..9f0fda98 100644 --- a/Graphics/GraphicsEngineD3D12/include/PipelineResourceSignatureD3D12Impl.hpp +++ b/Graphics/GraphicsEngineD3D12/include/PipelineResourceSignatureD3D12Impl.hpp @@ -280,24 +280,8 @@ public: Uint32 FirstRootIndex); private: - static ROOT_PARAMETER_GROUP GetRootParameterGroup(SHADER_RESOURCE_VARIABLE_TYPE VarType); - void CreateLayout(); - // Allocates root signature slot for the given resource. - // For graphics and compute pipelines, Register is the same as the original bind point. - // For ray-tracing pipeline, Register will be overriden. Bind points are then - // remapped by PSO constructor. - void AllocateResourceSlot(SHADER_TYPE ShaderStages, - SHADER_RESOURCE_VARIABLE_TYPE VariableType, - D3D12_DESCRIPTOR_RANGE_TYPE RangeType, - Uint32 ArraySize, - bool IsRootView, - Uint32 Register, - Uint32 Space, - Uint32& RootIndex, - Uint32& OffsetFromTableStart); - size_t CalculateHash() const; void Destruct(); @@ -307,26 +291,11 @@ private: Uint32 FindAssignedSampler(const PipelineResourceDesc& SepImg) const; private: - static constexpr Uint8 InvalidRootTableIndex = static_cast<Uint8>(-1); - ResourceAttribs* m_pResourceAttribs = nullptr; // [m_Desc.NumResources] std::array<Int8, MAX_SHADERS_IN_PIPELINE> m_StaticVarIndex = {-1, -1, -1, -1, -1, -1}; static_assert(MAX_SHADERS_IN_PIPELINE == 6, "Please update the initializer list above"); - // The array below contains array index of a CBV/SRV/UAV root table - // in m_RootParams (NOT the Root Index!), for every root parameter - // group (static/mutable, dynamic) and every shader visbility, - // or -1, if the table is not yet assigned to the combination. - // max(D3D12_SHADER_VISIBILITY) == D3D12_SHADER_VISIBILITY_MESH == 7 - std::array<std::array<Uint8, 8>, ROOT_PARAMETER_GROUP_COUNT> m_SrvCbvUavRootTablesMap = {}; - // This array contains the same data for Sampler root table - std::array<std::array<Uint8, 8>, ROOT_PARAMETER_GROUP_COUNT> m_SamplerRootTablesMap = {}; - - std::array<Uint32, ROOT_PARAMETER_GROUP_COUNT> m_TotalSrvCbvUavSlots = {}; - std::array<Uint32, ROOT_PARAMETER_GROUP_COUNT> m_TotalSamplerSlots = {}; - std::array<Uint32, ROOT_PARAMETER_GROUP_COUNT> m_TotalRootViews = {}; - Uint32 m_NumSpaces = 0; ShaderResourceCacheD3D12* m_pStaticResCache = nullptr; diff --git a/Graphics/GraphicsEngineD3D12/include/RootParamsManager.hpp b/Graphics/GraphicsEngineD3D12/include/RootParamsManager.hpp index 3941036e..c6b24a95 100644 --- a/Graphics/GraphicsEngineD3D12/include/RootParamsManager.hpp +++ b/Graphics/GraphicsEngineD3D12/include/RootParamsManager.hpp @@ -31,6 +31,8 @@ /// Declaration of Diligent::RootParamsManager class and related data structures #include <memory> +#include <vector> +#include <array> #include "BasicTypes.h" @@ -44,65 +46,53 @@ enum ROOT_PARAMETER_GROUP : Uint8 ROOT_PARAMETER_GROUP_COUNT }; -class RootParameter +struct RootParameter { -public: + const D3D12_ROOT_PARAMETER d3d12RootParam; + const Uint32 RootIndex; + const ROOT_PARAMETER_GROUP Group; + + RootParameter(ROOT_PARAMETER_GROUP Group, Uint32 RootIndex, - const D3D12_ROOT_PARAMETER& d3d12RootParam, - Uint32 DescriptorTableSize = 0) noexcept; + const D3D12_ROOT_PARAMETER& d3d12RootParam) noexcept; // clang-format off RootParameter (const RootParameter&) = delete; RootParameter& operator=(const RootParameter&) = delete; - RootParameter (RootParameter&&) = delete; + RootParameter (RootParameter&&) = default; RootParameter& operator=(RootParameter&&) = delete; // clang-format on - // Initializes descriptor range at the specified index. - // The parameter type must be D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE. - void InitDescriptorRange(UINT RangeIndex, - const D3D12_DESCRIPTOR_RANGE& Range); - - ROOT_PARAMETER_GROUP GetGroup() const { return m_Group; } - - static constexpr D3D12_DESCRIPTOR_RANGE_TYPE InvalidDescriptorRangeType = static_cast<D3D12_DESCRIPTOR_RANGE_TYPE>(0xFFFFFFFF); - Uint32 GetDescriptorTableSize() const { - VERIFY(m_d3d12RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, "Incorrect parameter type: descriptor table is expected"); - return m_DescriptorTableSize; + VERIFY(d3d12RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, + "Incorrect parameter type: descriptor table is expected"); + + // All descriptors in the table are tightly packed, so the table size is given + // by the end of the last range + const auto& d3d12Tbl = d3d12RootParam.DescriptorTable; + VERIFY(d3d12Tbl.NumDescriptorRanges > 0, "Descriptor table must contain at least one range"); + const auto& d3d12LastRange = d3d12Tbl.pDescriptorRanges[d3d12Tbl.NumDescriptorRanges - 1]; + VERIFY(d3d12LastRange.NumDescriptors > 0, "The range must not be empty"); + return d3d12LastRange.OffsetInDescriptorsFromTableStart + d3d12LastRange.NumDescriptors; } - D3D12_SHADER_VISIBILITY GetShaderVisibility() const { return m_d3d12RootParam.ShaderVisibility; } - D3D12_ROOT_PARAMETER_TYPE GetParameterType() const { return m_d3d12RootParam.ParameterType; } - - Uint32 GetLocalRootIndex() const { return m_RootIndex; } - - operator const D3D12_ROOT_PARAMETER&() const { return m_d3d12RootParam; } + D3D12_SHADER_VISIBILITY GetShaderVisibility() const { return d3d12RootParam.ShaderVisibility; } + D3D12_ROOT_PARAMETER_TYPE GetParameterType() const { return d3d12RootParam.ParameterType; } bool operator==(const RootParameter& rhs) const; bool operator!=(const RootParameter& rhs) const { return !(*this == rhs); } size_t GetHash() const; - -#ifdef DILIGENT_DEBUG - void DbgValidateAsTable() const; - void DbgValidateAsView() const; -#endif - -private: - const D3D12_ROOT_PARAMETER m_d3d12RootParam; - const Uint16 m_RootIndex; - const ROOT_PARAMETER_GROUP m_Group; - Uint32 m_DescriptorTableSize = 0; }; class RootParamsManager { public: - RootParamsManager(IMemoryAllocator& MemAllocator); + RootParamsManager() noexcept {} + ~RootParamsManager(); // clang-format off RootParamsManager (const RootParamsManager&) = delete; @@ -126,23 +116,14 @@ public: return m_pRootViews[ViewInd]; } - // Adds a new root view parameter and returns the pointer to it. - RootParameter* AddRootView(D3D12_ROOT_PARAMETER_TYPE ParameterType, - Uint32 RootIndex, - UINT Register, - UINT RegisterSpace, - D3D12_SHADER_VISIBILITY Visibility, - ROOT_PARAMETER_GROUP RootType); - - // Adds a new root table parameter and returns the pointer to it. - RootParameter* AddRootTable(Uint32 RootIndex, - D3D12_SHADER_VISIBILITY Visibility, - ROOT_PARAMETER_GROUP RootType, - Uint32 NumRangesInNewTable = 1); - - // Adds NumExtraRanges descriptor ranges to the root table at index RootTableInd - // and returns the pointer to the table. - RootParameter* ExtendRootTable(Uint32 RootTableInd, Uint32 NumExtraRanges = 1); + Uint32 GetTotalSrvCbvUavSlots(ROOT_PARAMETER_GROUP Group) const + { + return m_TotalSrvCbvUavSlots[Group]; + } + Uint32 GetTotalSamplerSlots(ROOT_PARAMETER_GROUP Group) const + { + return m_TotalSamplerSlots[Group]; + } template <class TOperation> void ProcessRootTables(TOperation) const; @@ -150,23 +131,18 @@ public: bool operator==(const RootParamsManager& RootParams) const; private: - // Extends current parameters set by adding NumExtraRootTables root tables, - // NumExtraRootViews root views, and adding NumExtraDescriptorRanges - // descriptor ranges to the root table at index RootTableToAddRanges. - void Extend(Uint32 NumExtraRootTables, - const RootParameter* ExtraRootTables, - Uint32 NumExtraRootViews, - const RootParameter* ExtraRootViews, - Uint32 NumExtraDescriptorRanges = 0, - Uint32 RootTableToAddRanges = ~0u); - - IMemoryAllocator& m_MemAllocator; + friend class RootParamsBuilder; + std::unique_ptr<void, STDDeleter<void, IMemoryAllocator>> m_pMemory; - Uint32 m_NumRootTables = 0; - Uint32 m_NumRootViews = 0; - RootParameter* m_pRootTables = nullptr; - RootParameter* m_pRootViews = nullptr; + Uint32 m_NumRootTables = 0; + Uint32 m_NumRootViews = 0; + + const RootParameter* m_pRootTables = nullptr; + const RootParameter* m_pRootViews = nullptr; + + std::array<Uint32, ROOT_PARAMETER_GROUP_COUNT> m_TotalSrvCbvUavSlots = {}; + std::array<Uint32, ROOT_PARAMETER_GROUP_COUNT> m_TotalSamplerSlots = {}; }; template <class TOperation> @@ -174,21 +150,86 @@ __forceinline void RootParamsManager::ProcessRootTables(TOperation Operation) co { for (Uint32 rt = 0; rt < m_NumRootTables; ++rt) { - auto& RootTable = GetRootTable(rt); - auto RootInd = RootTable.GetLocalRootIndex(); - const D3D12_ROOT_PARAMETER& D3D12Param = RootTable; + const auto& RootTable = GetRootTable(rt); + const auto RootInd = RootTable.RootIndex; + const auto& d3d12Param = RootTable.d3d12RootParam; - VERIFY_EXPR(D3D12Param.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE); + VERIFY_EXPR(d3d12Param.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE); - auto& d3d12Table = D3D12Param.DescriptorTable; - VERIFY(d3d12Table.NumDescriptorRanges > 0 && RootTable.GetDescriptorTableSize() > 0, "Unexepected empty descriptor table"); + const auto& d3d12Table = d3d12Param.DescriptorTable; + VERIFY(RootTable.GetDescriptorTableSize() > 0, "Unexepected empty descriptor table"); bool IsResourceTable = d3d12Table.pDescriptorRanges[0].RangeType != D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER; D3D12_DESCRIPTOR_HEAP_TYPE dbgHeapType = D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES; #ifdef DILIGENT_DEBUG dbgHeapType = IsResourceTable ? D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV : D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER; #endif - Operation(RootInd, RootTable, D3D12Param, IsResourceTable, dbgHeapType); + Operation(RootInd, RootTable, d3d12Param, IsResourceTable, dbgHeapType); } } +class RootParamsBuilder +{ +public: + RootParamsBuilder(); + + // Allocates root parameter slot for the given resource. + void AllocateResourceSlot(SHADER_TYPE ShaderStages, + SHADER_RESOURCE_VARIABLE_TYPE VariableType, + D3D12_DESCRIPTOR_RANGE_TYPE RangeType, + Uint32 ArraySize, + bool IsRootView, + Uint32 Register, + Uint32 Space, + Uint32& RootIndex, + Uint32& OffsetFromTableStart); + + void InitializeMgr(IMemoryAllocator& MemAllocator, RootParamsManager& ParamsMgr); + +private: + // Adds a new root view parameter and returns the reference to it. + RootParameter& AddRootView(D3D12_ROOT_PARAMETER_TYPE ParameterType, + Uint32 RootIndex, + UINT Register, + UINT RegisterSpace, + D3D12_SHADER_VISIBILITY Visibility, + ROOT_PARAMETER_GROUP RootType); + + struct RootTableData; + // Adds a new root table parameter and returns the reference to it. + RootTableData& AddRootTable(Uint32 RootIndex, + D3D12_SHADER_VISIBILITY Visibility, + ROOT_PARAMETER_GROUP RootType, + Uint32 NumRangesInNewTable = 1); + + +private: + struct RootTableData + { + RootTableData(Uint32 _RootIndex, + D3D12_SHADER_VISIBILITY _Visibility, + ROOT_PARAMETER_GROUP _Group, + Uint32 _NumRanges); + void Extend(Uint32 NumExtraRanges); + + const Uint32 RootIndex; + const ROOT_PARAMETER_GROUP Group; + D3D12_ROOT_PARAMETER d3d12RootParam{}; + + std::vector<D3D12_DESCRIPTOR_RANGE> Ranges; + }; + std::vector<RootTableData> m_RootTables; + std::vector<RootParameter> m_RootViews; + + static constexpr int InvalidRootTableIndex = -1; + + // The array below contains the index of a CBV/SRV/UAV root table in m_RootTables + // (NOT the Root Index!), for every root parameter group (static/mutable, dynamic) + // and every shader visbility, or -1, if the table is not yet assigned to the combination. + // Note: max(D3D12_SHADER_VISIBILITY) == D3D12_SHADER_VISIBILITY_MESH == 7 + std::array<std::array<int, 8>, ROOT_PARAMETER_GROUP_COUNT> m_SrvCbvUavRootTablesMap = {}; + + // This array contains the same data for Sampler root table + std::array<std::array<int, 8>, ROOT_PARAMETER_GROUP_COUNT> m_SamplerRootTablesMap = {}; +}; + } // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp index 3d869feb..19848b61 100644 --- a/Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp @@ -92,26 +92,15 @@ inline bool ResourcesCompatible(const PipelineResourceDesc& lhs, const PipelineR } // namespace -inline ROOT_PARAMETER_GROUP PipelineResourceSignatureD3D12Impl::GetRootParameterGroup(SHADER_RESOURCE_VARIABLE_TYPE VarType) -{ - return VarType == SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC ? ROOT_PARAMETER_GROUP_DYNAMIC : ROOT_PARAMETER_GROUP_STATIC_MUTABLE; -} - PipelineResourceSignatureD3D12Impl::PipelineResourceSignatureD3D12Impl(IReferenceCounters* pRefCounters, RenderDeviceD3D12Impl* pDevice, const PipelineResourceSignatureDesc& Desc, bool bIsDeviceInternal) : TPipelineResourceSignatureBase{pRefCounters, pDevice, Desc, bIsDeviceInternal}, - m_RootParams{GetRawAllocator()}, m_SRBMemAllocator{GetRawAllocator()} { try { - for (auto& Map : m_SrvCbvUavRootTablesMap) - Map.fill(InvalidRootTableIndex); - for (auto& Map : m_SamplerRootTablesMap) - Map.fill(InvalidRootTableIndex); - FixedLinearAllocator MemPool{GetRawAllocator()}; // Reserve at least 1 element because m_pResourceAttribs must hold a pointer to memory @@ -224,6 +213,7 @@ void PipelineResourceSignatureD3D12Impl::CreateLayout() std::array<Uint32, D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER + 1> NumResources = {}; std::array<Uint32, D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER + 1> StaticResCacheTblSizes = {}; + RootParamsBuilder ParamsBuilder; for (Uint32 i = 0; i < m_Desc.NumResources; ++i) { const auto& ResDesc = m_Desc.Resources[i]; @@ -295,7 +285,7 @@ void PipelineResourceSignatureD3D12Impl::CreateLayout() } else { - AllocateResourceSlot(ResDesc.ShaderStages, ResDesc.VarType, DescriptorRangeType, ResDesc.ArraySize, IsRootView, Register, FirstSpace + Space, SRBRootIndex, SRBOffsetFromTableStart); + ParamsBuilder.AllocateResourceSlot(ResDesc.ShaderStages, ResDesc.VarType, DescriptorRangeType, ResDesc.ArraySize, IsRootView, Register, FirstSpace + Space, SRBRootIndex, SRBOffsetFromTableStart); } new (m_pResourceAttribs + i) ResourceAttribs // @@ -311,6 +301,7 @@ void PipelineResourceSignatureD3D12Impl::CreateLayout() IsRootView // }; } + ParamsBuilder.InitializeMgr(GetRawAllocator(), m_RootParams); // Add immutable samplers that do not exist in m_Desc.Resources for (Uint32 i = 0; i < m_Desc.NumImmutableSamplers; ++i) @@ -368,78 +359,6 @@ Uint32 PipelineResourceSignatureD3D12Impl::FindAssignedSampler(const PipelineRes return SamplerInd; } -// http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-layout#Initializing-Shader-Resource-Layouts-and-Root-Signature-in-a-Pipeline-State-Object -void PipelineResourceSignatureD3D12Impl::AllocateResourceSlot(SHADER_TYPE ShaderStages, - SHADER_RESOURCE_VARIABLE_TYPE VariableType, - D3D12_DESCRIPTOR_RANGE_TYPE RangeType, - Uint32 ArraySize, - bool IsRootView, - Uint32 Register, - Uint32 Space, - Uint32& RootIndex, // Output parameter - Uint32& OffsetFromTableStart // Output parameter -) -{ - const auto ShaderVisibility = ShaderStagesToD3D12ShaderVisibility(ShaderStages); - const auto ParameterGroup = GetRootParameterGroup(VariableType); - - // Get the next available root index past all allocated tables and root views - RootIndex = m_RootParams.GetNumRootTables() + m_RootParams.GetNumRootViews(); - - if (IsRootView) - { - // Allocate single CBV directly in the root signature - OffsetFromTableStart = 0; - - // Add new root view to existing root parameters - m_RootParams.AddRootView(D3D12_ROOT_PARAMETER_TYPE_CBV, RootIndex, Register, Space, ShaderVisibility, ParameterGroup); // AZ TODO: add SRV & UAV - } - else - { - const bool IsSampler = (RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER); - // Get the table array index (this is not the root index!) - auto& RootTableArrayInd = (IsSampler ? m_SamplerRootTablesMap : m_SrvCbvUavRootTablesMap)[ParameterGroup][ShaderVisibility]; - - RootParameter* pRootTable = nullptr; - if (RootTableArrayInd == InvalidRootTableIndex) - { - // Root table has not been assigned to this combination yet - VERIFY_EXPR(m_RootParams.GetNumRootTables() < 255); - RootTableArrayInd = static_cast<Uint8>(m_RootParams.GetNumRootTables()); - // Add root table with one single-descriptor range - pRootTable = m_RootParams.AddRootTable(RootIndex, ShaderVisibility, ParameterGroup, 1); - } - else - { - // Add a new single-descriptor range to the existing table at index RootTableArrayInd - pRootTable = m_RootParams.ExtendRootTable(RootTableArrayInd, 1); - } - - (IsSampler ? m_TotalSamplerSlots : m_TotalSrvCbvUavSlots)[ParameterGroup] += ArraySize; - - // Reference to either existing or just added table - RootIndex = pRootTable->GetLocalRootIndex(); - - const auto& d3d12RootParam = static_cast<const D3D12_ROOT_PARAMETER&>(*pRootTable); - - VERIFY(d3d12RootParam.ShaderVisibility == ShaderVisibility, "Shader visibility is not correct"); - - // Descriptors are tightly packed, so the next descriptor offset is the - // current size of the table - OffsetFromTableStart = pRootTable->GetDescriptorTableSize(); - - // New just added range is the last range in the descriptor table - Uint32 NewDescriptorRangeIndex = d3d12RootParam.DescriptorTable.NumDescriptorRanges - 1; - - D3D12_DESCRIPTOR_RANGE Range{}; - Range.RangeType = RangeType; // Range type (CBV, SRV, UAV or SAMPLER) - Range.NumDescriptors = ArraySize; // Number of registers used (1 for non-array resources) - Range.BaseShaderRegister = Register; // Shader register - Range.RegisterSpace = Space; // Shader register space - Range.OffsetInDescriptorsFromTableStart = OffsetFromTableStart; // Offset in descriptors from the table start - pRootTable->InitDescriptorRange(NewDescriptorRangeIndex, Range); - } -} PipelineResourceSignatureD3D12Impl::~PipelineResourceSignatureD3D12Impl() { @@ -624,14 +543,14 @@ std::vector<Uint32, STDAllocatorRawMem<Uint32>> PipelineResourceSignatureD3D12Im std::vector<Uint32, STDAllocatorRawMem<Uint32>> CacheTableSizes(m_RootParams.GetNumRootTables() + m_RootParams.GetNumRootViews(), 0, STD_ALLOCATOR_RAW_MEM(Uint32, GetRawAllocator(), "Allocator for vector<Uint32>")); for (Uint32 rt = 0; rt < m_RootParams.GetNumRootTables(); ++rt) { - auto& RootParam = m_RootParams.GetRootTable(rt); - CacheTableSizes[RootParam.GetLocalRootIndex()] = RootParam.GetDescriptorTableSize(); + const auto& RootParam = m_RootParams.GetRootTable(rt); + CacheTableSizes[RootParam.RootIndex] = RootParam.GetDescriptorTableSize(); } for (Uint32 rv = 0; rv < m_RootParams.GetNumRootViews(); ++rv) { - auto& RootParam = m_RootParams.GetRootView(rv); - CacheTableSizes[RootParam.GetLocalRootIndex()] = 1; + const auto& RootParam = m_RootParams.GetRootView(rv); + CacheTableSizes[RootParam.RootIndex] = 1; } return CacheTableSizes; @@ -647,8 +566,8 @@ void PipelineResourceSignatureD3D12Impl::InitSRBResourceCache(ShaderResourceCach ResourceCache.Initialize(CacheMemAllocator, static_cast<Uint32>(CacheTableSizes.size()), CacheTableSizes.data()); // Allocate space in GPU-visible descriptor heap for static and mutable variables only - Uint32 TotalSrvCbvUavDescriptors = m_TotalSrvCbvUavSlots[ROOT_PARAMETER_GROUP_STATIC_MUTABLE]; - Uint32 TotalSamplerDescriptors = m_TotalSamplerSlots[ROOT_PARAMETER_GROUP_STATIC_MUTABLE]; + Uint32 TotalSrvCbvUavDescriptors = m_RootParams.GetTotalSrvCbvUavSlots(ROOT_PARAMETER_GROUP_STATIC_MUTABLE); + Uint32 TotalSamplerDescriptors = m_RootParams.GetTotalSamplerSlots(ROOT_PARAMETER_GROUP_STATIC_MUTABLE); DescriptorHeapAllocation CbcSrvUavHeapSpace, SamplerHeapSpace; if (TotalSrvCbvUavDescriptors) @@ -680,17 +599,17 @@ void PipelineResourceSignatureD3D12Impl::InitSRBResourceCache(ShaderResourceCach Uint32 SamplerTblStartOffset = 0; for (Uint32 rt = 0; rt < m_RootParams.GetNumRootTables(); ++rt) { - auto& RootParam = m_RootParams.GetRootTable(rt); - const auto& D3D12RootParam = static_cast<const D3D12_ROOT_PARAMETER&>(RootParam); - auto& RootTableCache = ResourceCache.GetRootTable(RootParam.GetLocalRootIndex()); - const bool IsDynamic = RootParam.GetGroup() == ROOT_PARAMETER_GROUP_DYNAMIC; + const auto& RootParam = m_RootParams.GetRootTable(rt); + const auto& d3d12RootParam = RootParam.d3d12RootParam; + auto& RootTableCache = ResourceCache.GetRootTable(RootParam.RootIndex); + const bool IsDynamic = RootParam.Group == ROOT_PARAMETER_GROUP_DYNAMIC; - VERIFY_EXPR(D3D12RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE); + VERIFY_EXPR(d3d12RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE); auto TableSize = RootParam.GetDescriptorTableSize(); VERIFY(TableSize > 0, "Unexpected empty descriptor table"); - auto HeapType = D3D12DescriptorRangeTypeToD3D12HeapType(D3D12RootParam.DescriptorTable.pDescriptorRanges[0].RangeType); + auto HeapType = D3D12DescriptorRangeTypeToD3D12HeapType(d3d12RootParam.DescriptorTable.pDescriptorRanges[0].RangeType); #ifdef DILIGENT_DEBUG RootTableCache.SetDebugAttribs(TableSize, HeapType, IsDynamic); @@ -721,15 +640,15 @@ void PipelineResourceSignatureD3D12Impl::InitSRBResourceCache(ShaderResourceCach #ifdef DILIGENT_DEBUG for (Uint32 rv = 0; rv < m_RootParams.GetNumRootViews(); ++rv) { - auto& RootParam = m_RootParams.GetRootView(rv); - const auto& D3D12RootParam = static_cast<const D3D12_ROOT_PARAMETER&>(RootParam); - auto& RootTableCache = ResourceCache.GetRootTable(RootParam.GetLocalRootIndex()); - const bool IsDynamic = RootParam.GetGroup() == ROOT_PARAMETER_GROUP_DYNAMIC; + const auto& RootParam = m_RootParams.GetRootView(rv); + const auto& d3d12RootParam = RootParam.d3d12RootParam; + auto& RootTableCache = ResourceCache.GetRootTable(RootParam.RootIndex); + const bool IsDynamic = RootParam.Group == ROOT_PARAMETER_GROUP_DYNAMIC; // Root views are not assigned valid table start offset VERIFY_EXPR(RootTableCache.m_TableStartOffset == ShaderResourceCacheD3D12::InvalidDescriptorOffset); - VERIFY_EXPR(D3D12RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV); + VERIFY_EXPR(d3d12RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV); RootTableCache.SetDebugAttribs(1, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, IsDynamic); } #endif @@ -1106,8 +1025,8 @@ void PipelineResourceSignatureD3D12Impl::CommitRootTables(ShaderResourceCacheD3D { auto* pd3d12Device = GetDevice()->GetD3D12Device(); - Uint32 NumDynamicCbvSrvUavDescriptors = m_TotalSrvCbvUavSlots[ROOT_PARAMETER_GROUP_DYNAMIC]; - Uint32 NumDynamicSamplerDescriptors = m_TotalSamplerSlots[ROOT_PARAMETER_GROUP_DYNAMIC]; + Uint32 NumDynamicCbvSrvUavDescriptors = m_RootParams.GetTotalSrvCbvUavSlots(ROOT_PARAMETER_GROUP_DYNAMIC); + Uint32 NumDynamicSamplerDescriptors = m_RootParams.GetTotalSamplerSlots(ROOT_PARAMETER_GROUP_DYNAMIC); //VERIFY_EXPR(NumDynamicCbvSrvUavDescriptors > 0 || NumDynamicSamplerDescriptors > 0); DescriptorHeapAllocation DynamicCbvSrvUavDescriptors, DynamicSamplerDescriptors; @@ -1160,7 +1079,7 @@ void PipelineResourceSignatureD3D12Impl::CommitRootTables(ShaderResourceCacheD3D { D3D12_GPU_DESCRIPTOR_HANDLE RootTableGPUDescriptorHandle; - bool IsDynamicTable = RootTable.GetGroup() == ROOT_PARAMETER_GROUP_DYNAMIC; + bool IsDynamicTable = RootTable.Group == ROOT_PARAMETER_GROUP_DYNAMIC; if (IsDynamicTable) { if (IsResourceTable) @@ -1234,7 +1153,7 @@ void PipelineResourceSignatureD3D12Impl::CommitRootTables(ShaderResourceCacheD3D for (Uint32 rv = 0; rv < m_RootParams.GetNumRootViews(); ++rv) { auto& RootView = m_RootParams.GetRootView(rv); - auto RootInd = RootView.GetLocalRootIndex(); + auto RootInd = RootView.RootIndex; auto& Res = ResourceCache.GetRootTable(RootInd).GetResource(0, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); if (auto* pBuffToTransition = Res.pObject.RawPtr<BufferD3D12Impl>()) @@ -1262,7 +1181,7 @@ void PipelineResourceSignatureD3D12Impl::CommitRootViews(ShaderResourceCacheD3D1 for (Uint32 rv = 0; rv < m_RootParams.GetNumRootViews(); ++rv) { auto& RootView = m_RootParams.GetRootView(rv); - auto RootInd = RootView.GetLocalRootIndex(); + auto RootInd = RootView.RootIndex; auto& Res = ResourceCache.GetRootTable(RootInd).GetResource(0, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); if (auto* pBuffToTransition = Res.pObject.RawPtr<BufferD3D12Impl>()) diff --git a/Graphics/GraphicsEngineD3D12/src/RootParamsManager.cpp b/Graphics/GraphicsEngineD3D12/src/RootParamsManager.cpp index 756568f8..0202d906 100644 --- a/Graphics/GraphicsEngineD3D12/src/RootParamsManager.cpp +++ b/Graphics/GraphicsEngineD3D12/src/RootParamsManager.cpp @@ -29,69 +29,79 @@ #include "RootParamsManager.hpp" #include "D3D12Utils.h" +#include "D3D12TypeConversions.hpp" namespace Diligent { -RootParameter::RootParameter(ROOT_PARAMETER_GROUP Group, - Uint32 RootIndex, - const D3D12_ROOT_PARAMETER& d3d12RootParam, - Uint32 DescriptorTableSize) noexcept : - m_d3d12RootParam{d3d12RootParam}, - m_RootIndex{static_cast<decltype(m_RootIndex)>(RootIndex)}, - m_Group{Group}, - m_DescriptorTableSize{DescriptorTableSize} +namespace { - VERIFY(m_RootIndex == RootIndex, "Root index (", RootIndex, ") exceeds representable range"); - VERIFY(DescriptorTableSize == 0 || m_d3d12RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, - "Non-zer descriptor table size is only allowed for DESCRIPTOR_TABLE parameters"); -#ifdef DILIGENT_DEBUG - if (m_d3d12RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE) - DbgValidateAsTable(); -#endif -} -void RootParameter::InitDescriptorRange(UINT RangeIndex, - const D3D12_DESCRIPTOR_RANGE& Range) +constexpr D3D12_DESCRIPTOR_RANGE_TYPE InvalidDescriptorRangeType = static_cast<D3D12_DESCRIPTOR_RANGE_TYPE>(-1); + +#ifdef DILIGENT_DEBUG +void DbgValidateD3D12RootTable(const D3D12_ROOT_DESCRIPTOR_TABLE& d3d12Tbl) { - VERIFY(m_d3d12RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, - "Incorrect parameter type: descriptor table is expected"); + VERIFY(d3d12Tbl.NumDescriptorRanges > 0, "Descriptor table must contain at least one range"); + VERIFY_EXPR(d3d12Tbl.pDescriptorRanges != nullptr); - const auto& d3d12Tbl = m_d3d12RootParam.DescriptorTable; - VERIFY(RangeIndex < d3d12Tbl.NumDescriptorRanges, "Invalid descriptor range index"); + const auto IsSampler = d3d12Tbl.pDescriptorRanges[0].RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER; + Uint32 CurrOffset = 0; + for (Uint32 r = 0; r < d3d12Tbl.NumDescriptorRanges; ++r) + { + const auto& Range = d3d12Tbl.pDescriptorRanges[r]; + VERIFY(Range.RangeType != InvalidDescriptorRangeType, "Range is not initialized"); + VERIFY(Range.OffsetInDescriptorsFromTableStart == CurrOffset, "Invalid offset"); + VERIFY(Range.NumDescriptors != 0, "Range must contain at lest one descriptor"); + if (IsSampler) + { + VERIFY(Range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, "All ranges in a sampler table must be D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER"); + } + else + { + VERIFY(Range.RangeType != D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, "D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER is only valid for a sampler table"); + } - auto& DstRange = const_cast<D3D12_DESCRIPTOR_RANGE&>(d3d12Tbl.pDescriptorRanges[RangeIndex]); - VERIFY(DstRange.RangeType == InvalidDescriptorRangeType, "Descriptor range has already been initialized."); - DstRange = Range; + CurrOffset += Range.NumDescriptors; + } +} +#endif - m_DescriptorTableSize = std::max(m_DescriptorTableSize, Range.OffsetInDescriptorsFromTableStart + Range.NumDescriptors); +} // namespace +RootParameter::RootParameter(ROOT_PARAMETER_GROUP _Group, + Uint32 _RootIndex, + const D3D12_ROOT_PARAMETER& _d3d12RootParam) noexcept : + d3d12RootParam{_d3d12RootParam}, + RootIndex{_RootIndex}, + Group{_Group} +{ #ifdef DILIGENT_DEBUG - DbgValidateAsTable(); + if (d3d12RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE) + DbgValidateD3D12RootTable(d3d12RootParam.DescriptorTable); #endif } bool RootParameter::operator==(const RootParameter& rhs) const { - if (m_Group != rhs.m_Group || - m_DescriptorTableSize != rhs.m_DescriptorTableSize || - m_RootIndex != rhs.m_RootIndex) - return false; - - return m_d3d12RootParam == rhs.m_d3d12RootParam; + // clang-format off + return Group == rhs.Group && + RootIndex == rhs.RootIndex && + d3d12RootParam == rhs.d3d12RootParam; + // clang-format on } size_t RootParameter::GetHash() const { - size_t hash = ComputeHash(m_Group, m_DescriptorTableSize, m_RootIndex); - HashCombine(hash, int{m_d3d12RootParam.ParameterType}, int{m_d3d12RootParam.ShaderVisibility}); + size_t hash = ComputeHash(Group, RootIndex); + HashCombine(hash, int{d3d12RootParam.ParameterType}, int{d3d12RootParam.ShaderVisibility}); - switch (m_d3d12RootParam.ParameterType) + switch (d3d12RootParam.ParameterType) { case D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE: { - const auto& tbl = m_d3d12RootParam.DescriptorTable; + const auto& tbl = d3d12RootParam.DescriptorTable; HashCombine(hash, tbl.NumDescriptorRanges); for (UINT r = 0; r < tbl.NumDescriptorRanges; ++r) { @@ -103,7 +113,7 @@ size_t RootParameter::GetHash() const case D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS: { - const auto& cnst = m_d3d12RootParam.Constants; + const auto& cnst = d3d12RootParam.Constants; HashCombine(hash, cnst.ShaderRegister, cnst.RegisterSpace, cnst.Num32BitValues); } break; @@ -112,7 +122,7 @@ size_t RootParameter::GetHash() const case D3D12_ROOT_PARAMETER_TYPE_SRV: case D3D12_ROOT_PARAMETER_TYPE_UAV: { - const auto& dscr = m_d3d12RootParam.Descriptor; + const auto& dscr = d3d12RootParam.Descriptor; HashCombine(hash, dscr.ShaderRegister, dscr.RegisterSpace); } break; @@ -123,228 +133,280 @@ size_t RootParameter::GetHash() const return hash; } -#ifdef DILIGENT_DEBUG -void RootParameter::DbgValidateAsTable() const +RootParamsManager::~RootParamsManager() +{ + static_assert(std::is_trivially_destructible<RootParameter>::value, "Destructors for m_pRootTables and m_pRootViews are required"); +} + +bool RootParamsManager::operator==(const RootParamsManager& RootParams) const { - VERIFY(GetParameterType() == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, "Unexpected parameter type: descriptor table is expected"); - const auto& d3d12SrcTbl = m_d3d12RootParam.DescriptorTable; + if (m_NumRootTables != RootParams.m_NumRootTables || + m_NumRootViews != RootParams.m_NumRootViews) + return false; - Uint32 dbgTableSize = 0; - if (d3d12SrcTbl.pDescriptorRanges != nullptr) + for (Uint32 rv = 0; rv < m_NumRootViews; ++rv) { - for (Uint32 r = 0; r < d3d12SrcTbl.NumDescriptorRanges; ++r) - { - const auto& Range = d3d12SrcTbl.pDescriptorRanges[r]; - if (r > 0) - { - const auto& PrevRange = d3d12SrcTbl.pDescriptorRanges[r - 1]; - if (PrevRange.RangeType != InvalidDescriptorRangeType) - { - VERIFY(Range.RangeType == InvalidDescriptorRangeType || PrevRange.OffsetInDescriptorsFromTableStart + PrevRange.NumDescriptors == Range.OffsetInDescriptorsFromTableStart, - "Descriptors should be tightly packed in the table"); - } - else - { - VERIFY(Range.RangeType == InvalidDescriptorRangeType, "All uninitialized ranges must be contiguous"); - } - } - if (Range.RangeType != InvalidDescriptorRangeType) - dbgTableSize = std::max(dbgTableSize, Range.OffsetInDescriptorsFromTableStart + Range.NumDescriptors); - } + const auto& RV0 = GetRootView(rv); + const auto& RV1 = RootParams.GetRootView(rv); + if (RV0 != RV1) + return false; + } + + for (Uint32 rv = 0; rv < m_NumRootTables; ++rv) + { + const auto& RT0 = GetRootTable(rv); + const auto& RT1 = RootParams.GetRootTable(rv); + if (RT0 != RT1) + return false; } - VERIFY(dbgTableSize == GetDescriptorTableSize(), "Incorrect descriptor table size"); + + return true; } -void RootParameter::DbgValidateAsView() const + +RootParamsBuilder::RootParamsBuilder() { - const auto ParameterType = GetParameterType(); - VERIFY(ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV || ParameterType == D3D12_ROOT_PARAMETER_TYPE_SRV || ParameterType == D3D12_ROOT_PARAMETER_TYPE_UAV, - "Unexpected parameter type: SBV, SRV or UAV is expected"); + for (auto& Map : m_SrvCbvUavRootTablesMap) + Map.fill(InvalidRootTableIndex); + for (auto& Map : m_SamplerRootTablesMap) + Map.fill(InvalidRootTableIndex); } -#endif -RootParamsManager::RootParamsManager(IMemoryAllocator& MemAllocator) : - m_MemAllocator{MemAllocator}, - m_pMemory{nullptr, STDDeleter<void, IMemoryAllocator>(MemAllocator)} -{} +RootParameter& RootParamsBuilder::AddRootView(D3D12_ROOT_PARAMETER_TYPE ParameterType, + Uint32 RootIndex, + UINT Register, + UINT RegisterSpace, + D3D12_SHADER_VISIBILITY Visibility, + ROOT_PARAMETER_GROUP Group) +{ +#ifdef DILIGENT_DEBUG + VERIFY(ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV || ParameterType == D3D12_ROOT_PARAMETER_TYPE_SRV || ParameterType == D3D12_ROOT_PARAMETER_TYPE_UAV, + "Unexpected parameter type SBV, SRV or UAV is expected"); + for (const auto& RootTbl : m_RootTables) + VERIFY(RootTbl.RootIndex != RootIndex, "Index ", RootIndex, " is already used by another root table"); + for (const auto& RootView : m_RootViews) + VERIFY(RootView.RootIndex != RootIndex, "Index ", RootIndex, " is already used by another root view"); +#endif -void RootParamsManager::Extend(Uint32 NumExtraRootTables, - const RootParameter* ExtraRootTables, - Uint32 NumExtraRootViews, - const RootParameter* ExtraRootViews, - Uint32 NumExtraDescriptorRanges, - Uint32 RootTableToAddRanges) -{ - VERIFY(NumExtraRootTables > 0 || NumExtraRootViews > 0 || NumExtraDescriptorRanges > 0, - "At least one root table, root view or descriptor range must be added"); + D3D12_ROOT_PARAMETER d3d12RootParam{ParameterType, {}, Visibility}; + d3d12RootParam.Descriptor.ShaderRegister = Register; + d3d12RootParam.Descriptor.RegisterSpace = RegisterSpace; + m_RootViews.emplace_back(Group, RootIndex, d3d12RootParam); - const auto NewParamsCount = m_NumRootTables + NumExtraRootTables + m_NumRootViews + NumExtraRootViews; + return m_RootViews.back(); +} - auto NewRangesCount = NumExtraDescriptorRanges; - for (Uint32 rt = 0; rt < m_NumRootTables + NumExtraRootTables; ++rt) - { - const auto& Tbl = rt < m_NumRootTables ? GetRootTable(rt) : ExtraRootTables[rt - m_NumRootTables]; - NewRangesCount += static_cast<const D3D12_ROOT_PARAMETER&>(Tbl).DescriptorTable.NumDescriptorRanges; +RootParamsBuilder::RootTableData::RootTableData(Uint32 _RootIndex, + D3D12_SHADER_VISIBILITY _Visibility, + ROOT_PARAMETER_GROUP _Group, + Uint32 _NumRanges) : + RootIndex{_RootIndex}, + Group{_Group}, + d3d12RootParam{ + D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, + D3D12_ROOT_DESCRIPTOR_TABLE{0, nullptr}, + _Visibility // } +{ + Extend(_NumRanges); +} - const auto MemorySize = - NewParamsCount * sizeof(RootParameter) + - NewRangesCount * sizeof(D3D12_DESCRIPTOR_RANGE); +void RootParamsBuilder::RootTableData::Extend(Uint32 NumExtraRanges) +{ + auto& d3d12Tbl = d3d12RootParam.DescriptorTable; + VERIFY_EXPR(d3d12Tbl.NumDescriptorRanges == Ranges.size()); + d3d12Tbl.NumDescriptorRanges += NumExtraRanges; + Ranges.resize(d3d12Tbl.NumDescriptorRanges); + d3d12Tbl.pDescriptorRanges = Ranges.data(); - VERIFY_EXPR(MemorySize > 0); - decltype(m_pMemory) pNewMemory{ - ALLOCATE_RAW(m_MemAllocator, "Memory buffer for root tables, root views & descriptor ranges", MemorySize), - m_pMemory.get_deleter() // - }; +#ifdef DILIGENT_DEBUG + for (Uint32 i = d3d12Tbl.NumDescriptorRanges - NumExtraRanges; i < d3d12Tbl.NumDescriptorRanges; ++i) + Ranges[i].RangeType = InvalidDescriptorRangeType; +#endif +} +RootParamsBuilder::RootTableData& RootParamsBuilder::AddRootTable(Uint32 RootIndex, + D3D12_SHADER_VISIBILITY Visibility, + ROOT_PARAMETER_GROUP Group, + Uint32 NumRangesInNewTable) +{ #ifdef DILIGENT_DEBUG - memset(pNewMemory.get(), 0xFF, MemorySize); + for (const auto& RootTbl : m_RootTables) + VERIFY(RootTbl.RootIndex != RootIndex, "Index ", RootIndex, " is already used by another root table"); + for (const auto& RootView : m_RootViews) + VERIFY(RootView.RootIndex != RootIndex, "Index ", RootIndex, " is already used by another root view"); #endif - // Note: this order is more efficient than views->tables->ranges - auto* const pNewRootTables = reinterpret_cast<RootParameter*>(pNewMemory.get()); - auto* const pNewRootViews = pNewRootTables + m_NumRootTables + NumExtraRootTables; - auto* const pDescriptorRanges = reinterpret_cast<D3D12_DESCRIPTOR_RANGE*>(pNewRootViews + m_NumRootViews + NumExtraRootViews); + m_RootTables.emplace_back(RootIndex, Visibility, Group, NumRangesInNewTable); - // Copy root tables to new memory - auto* pCurrDescrRangePtr = pDescriptorRanges; - for (Uint32 rt = 0; rt < m_NumRootTables + NumExtraRootTables; ++rt) + return m_RootTables.back(); +} + +inline ROOT_PARAMETER_GROUP VariableTypeToRootParameterGroup(SHADER_RESOURCE_VARIABLE_TYPE VarType) +{ + return VarType == SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC ? ROOT_PARAMETER_GROUP_DYNAMIC : ROOT_PARAMETER_GROUP_STATIC_MUTABLE; +} + +void RootParamsBuilder::AllocateResourceSlot(SHADER_TYPE ShaderStages, + SHADER_RESOURCE_VARIABLE_TYPE VariableType, + D3D12_DESCRIPTOR_RANGE_TYPE RangeType, + Uint32 ArraySize, + bool IsRootView, + Uint32 Register, + Uint32 Space, + Uint32& RootIndex, // Output parameter + Uint32& OffsetFromTableStart // Output parameter +) +{ + const auto ShaderVisibility = ShaderStagesToD3D12ShaderVisibility(ShaderStages); + const auto ParameterGroup = VariableTypeToRootParameterGroup(VariableType); + + // Get the next available root index past all allocated tables and root views + RootIndex = static_cast<Uint32>(m_RootTables.size() + m_RootViews.size()); + + if (IsRootView) { - const auto& SrcTbl = rt < m_NumRootTables ? GetRootTable(rt) : ExtraRootTables[rt - m_NumRootTables]; -#ifdef DILIGENT_DEBUG - SrcTbl.DbgValidateAsTable(); -#endif - const auto& d3d12SrcTbl = static_cast<const D3D12_ROOT_PARAMETER&>(SrcTbl).DescriptorTable; + // Allocate single CBV directly in the root signature + OffsetFromTableStart = 0; + + // Add new root view to existing root parameters + AddRootView(D3D12_ROOT_PARAMETER_TYPE_CBV, RootIndex, Register, Space, ShaderVisibility, ParameterGroup); // AZ TODO: add SRV & UAV + } + else + { + const bool IsSampler = (RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER); + // Get the table array index (this is not the root index!) + auto& RootTableArrayInd = (IsSampler ? m_SamplerRootTablesMap : m_SrvCbvUavRootTablesMap)[ParameterGroup][ShaderVisibility]; - auto NumRanges = d3d12SrcTbl.NumDescriptorRanges; - if (rt == RootTableToAddRanges) + RootTableData* pRootTable = nullptr; + if (RootTableArrayInd == InvalidRootTableIndex) { - VERIFY(d3d12SrcTbl.pDescriptorRanges != nullptr, "Adding extra descriptors to a new table. This is likely not intended."); - NumRanges += NumExtraDescriptorRanges; + // Root table has not been assigned to this combination yet + RootTableArrayInd = static_cast<int>(m_RootTables.size()); + // Add root table with one single-descriptor range + pRootTable = &AddRootTable(RootIndex, ShaderVisibility, ParameterGroup, 1); } - - // Copy existing ranges, if any (pDescriptorRanges == null for extra descriptor tables) - if (d3d12SrcTbl.pDescriptorRanges != nullptr) + else { - memcpy(pCurrDescrRangePtr, d3d12SrcTbl.pDescriptorRanges, d3d12SrcTbl.NumDescriptorRanges * sizeof(D3D12_DESCRIPTOR_RANGE)); + // Add a new single-descriptor range to the existing table at index RootTableArrayInd + pRootTable = &m_RootTables[RootTableArrayInd]; + pRootTable->Extend(1); } - new (pNewRootTables + rt) RootParameter{ - SrcTbl.GetGroup(), SrcTbl.GetLocalRootIndex(), - D3D12_ROOT_PARAMETER // - { - D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, - D3D12_ROOT_DESCRIPTOR_TABLE{NumRanges, pCurrDescrRangePtr}, - SrcTbl.GetShaderVisibility() // - }, - SrcTbl.GetDescriptorTableSize() // - }; + // Pointer to either existing or just added table + RootIndex = pRootTable->RootIndex; - pCurrDescrRangePtr += NumRanges; - } - VERIFY_EXPR(pCurrDescrRangePtr == pDescriptorRanges + NewRangesCount); + const auto& d3d12RootParam = pRootTable->d3d12RootParam; - // Copy root views to new memory - for (Uint32 rv = 0; rv < m_NumRootViews + NumExtraRootViews; ++rv) - { - const auto& SrcView = rv < m_NumRootViews ? GetRootView(rv) : ExtraRootViews[rv - m_NumRootViews]; + VERIFY(d3d12RootParam.ShaderVisibility == ShaderVisibility, "Shader visibility is not correct"); + + // New just added range is the last range in the descriptor table + Uint32 NewDescriptorRangeIndex = d3d12RootParam.DescriptorTable.NumDescriptorRanges - 1; + if (NewDescriptorRangeIndex > 0) + { + // Descriptors are tightly packed, so the next descriptor offset starts after the previous range + const auto& PrevRange = pRootTable->Ranges[NewDescriptorRangeIndex - 1]; + OffsetFromTableStart = PrevRange.OffsetInDescriptorsFromTableStart + PrevRange.NumDescriptors; + } + else + { + OffsetFromTableStart = 0; + } + + auto& NewRange = pRootTable->Ranges[NewDescriptorRangeIndex]; + NewRange.RangeType = RangeType; // Range type (CBV, SRV, UAV or SAMPLER) + NewRange.NumDescriptors = ArraySize; // Number of registers used (1 for non-array resources) + NewRange.BaseShaderRegister = Register; // Shader register + NewRange.RegisterSpace = Space; // Shader register space + NewRange.OffsetInDescriptorsFromTableStart = OffsetFromTableStart; // Offset in descriptors from the table start #ifdef DILIGENT_DEBUG - SrcView.DbgValidateAsView(); + DbgValidateD3D12RootTable(d3d12RootParam.DescriptorTable); #endif - new (pNewRootViews + rv) RootParameter{SrcView.GetGroup(), SrcView.GetLocalRootIndex(), static_cast<const D3D12_ROOT_PARAMETER&>(SrcView)}; } - - m_pMemory.swap(pNewMemory); - m_NumRootTables += NumExtraRootTables; - m_NumRootViews += NumExtraRootViews; - m_pRootTables = m_NumRootTables != 0 ? pNewRootTables : nullptr; - m_pRootViews = m_NumRootViews != 0 ? pNewRootViews : nullptr; } -RootParameter* RootParamsManager::AddRootView(D3D12_ROOT_PARAMETER_TYPE ParameterType, - Uint32 RootIndex, - UINT Register, - UINT RegisterSpace, - D3D12_SHADER_VISIBILITY Visibility, - ROOT_PARAMETER_GROUP Group) +void RootParamsBuilder::InitializeMgr(IMemoryAllocator& MemAllocator, RootParamsManager& ParamsMgr) { -#ifdef DILIGENT_DEBUG - VERIFY(ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV || ParameterType == D3D12_ROOT_PARAMETER_TYPE_SRV || ParameterType == D3D12_ROOT_PARAMETER_TYPE_UAV, - "Unexpected parameter type SBV, SRV or UAV is expected"); + VERIFY(!ParamsMgr.m_pMemory, "Params manager has already been initialized!"); - for (Uint32 rt = 0; rt < GetNumRootTables(); ++rt) - VERIFY(GetRootTable(rt).GetLocalRootIndex() != RootIndex, "Index ", RootIndex, " is already used by another root table"); - for (Uint32 rv = 0; rv < GetNumRootViews(); ++rv) - VERIFY(GetRootView(rv).GetLocalRootIndex() != RootIndex, "Index ", RootIndex, " is already used by another root view"); -#endif + auto& NumRootTables = ParamsMgr.m_NumRootTables; + auto& NumRootViews = ParamsMgr.m_NumRootViews; - D3D12_ROOT_PARAMETER d3d12RootParam{ParameterType, {}, Visibility}; - d3d12RootParam.Descriptor.ShaderRegister = Register; - d3d12RootParam.Descriptor.RegisterSpace = RegisterSpace; - RootParameter NewRootView{Group, RootIndex, d3d12RootParam}; - Extend(0, nullptr, 1, &NewRootView); + NumRootTables = static_cast<Uint32>(m_RootTables.size()); + NumRootViews = static_cast<Uint32>(m_RootViews.size()); + if (NumRootTables == 0 && NumRootViews == 0) + return; - return &m_pRootViews[m_NumRootViews - 1]; -} + const auto TotalRootParamsCount = m_RootTables.size() + m_RootViews.size(); + + size_t TotalRangesCount = 0; + for (auto& Tbl : m_RootTables) + { + VERIFY_EXPR(Tbl.d3d12RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE && Tbl.d3d12RootParam.DescriptorTable.NumDescriptorRanges > 0); + TotalRangesCount += Tbl.d3d12RootParam.DescriptorTable.NumDescriptorRanges; + } + + const auto MemorySize = TotalRootParamsCount * sizeof(RootParameter) + TotalRangesCount * sizeof(D3D12_DESCRIPTOR_RANGE); + VERIFY_EXPR(MemorySize > 0); + ParamsMgr.m_pMemory = decltype(ParamsMgr.m_pMemory){ + ALLOCATE_RAW(MemAllocator, "Memory buffer for root tables, root views & descriptor ranges", MemorySize), + STDDeleter<void, IMemoryAllocator>(MemAllocator) // + }; -RootParameter* RootParamsManager::AddRootTable(Uint32 RootIndex, - D3D12_SHADER_VISIBILITY Visibility, - ROOT_PARAMETER_GROUP Group, - Uint32 NumRangesInNewTable) -{ #ifdef DILIGENT_DEBUG - for (Uint32 rt = 0; rt < GetNumRootTables(); ++rt) - VERIFY(GetRootTable(rt).GetLocalRootIndex() != RootIndex, "Index ", RootIndex, " is already used by another root table"); - for (Uint32 rv = 0; rv < GetNumRootViews(); ++rv) - VERIFY(GetRootView(rv).GetLocalRootIndex() != RootIndex, "Index ", RootIndex, " is already used by another root view"); + memset(ParamsMgr.m_pMemory.get(), 0xFF, MemorySize); #endif - RootParameter NewRootTable{ - Group, RootIndex, - D3D12_ROOT_PARAMETER // - { - D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, - D3D12_ROOT_DESCRIPTOR_TABLE{NumRangesInNewTable, nullptr}, - Visibility // - } // - }; - Extend(1, &NewRootTable, 0, nullptr); + // Note: this order is more efficient than views->tables->ranges + auto* const pRootTables = reinterpret_cast<RootParameter*>(ParamsMgr.m_pMemory.get()); + auto* const pRootViews = pRootTables + NumRootTables; + auto* const pDescriptorRanges = reinterpret_cast<D3D12_DESCRIPTOR_RANGE*>(pRootViews + NumRootViews); - return &m_pRootTables[m_NumRootTables - 1]; -} + // Copy descriptor tables + auto* pCurrDescrRangePtr = pDescriptorRanges; + for (Uint32 rt = 0; rt < NumRootTables; ++rt) + { + const auto& SrcTbl = m_RootTables[rt]; + const auto& d3d12SrcParam = SrcTbl.d3d12RootParam; + const auto& d3d12SrcTbl = d3d12SrcParam.DescriptorTable; +#ifdef DILIGENT_DEBUG + VERIFY(d3d12SrcParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, + "Unexpected parameter type: descriptor table is expected"); + DbgValidateD3D12RootTable(d3d12SrcTbl); +#endif + memcpy(pCurrDescrRangePtr, d3d12SrcTbl.pDescriptorRanges, d3d12SrcTbl.NumDescriptorRanges * sizeof(D3D12_DESCRIPTOR_RANGE)); -RootParameter* RootParamsManager::ExtendRootTable(Uint32 RootTableInd, Uint32 NumExtraRanges) -{ - VERIFY_EXPR(RootTableInd < m_NumRootTables); - Extend(0, nullptr, 0, nullptr, NumExtraRanges, RootTableInd); - return &m_pRootTables[RootTableInd]; -} + auto* pTbl = new (pRootTables + rt) RootParameter{ + SrcTbl.Group, SrcTbl.RootIndex, + D3D12_ROOT_PARAMETER // + { + D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, + D3D12_ROOT_DESCRIPTOR_TABLE{d3d12SrcTbl.NumDescriptorRanges, pCurrDescrRangePtr}, + d3d12SrcParam.ShaderVisibility // + } // + }; -bool RootParamsManager::operator==(const RootParamsManager& RootParams) const -{ - if (m_NumRootTables != RootParams.m_NumRootTables || - m_NumRootViews != RootParams.m_NumRootViews) - return false; + const auto IsSampler = pTbl->d3d12RootParam.DescriptorTable.pDescriptorRanges[0].RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER; + (IsSampler ? ParamsMgr.m_TotalSamplerSlots : ParamsMgr.m_TotalSrvCbvUavSlots)[pTbl->Group] += pTbl->GetDescriptorTableSize(); - for (Uint32 rv = 0; rv < m_NumRootViews; ++rv) - { - const auto& RV0 = GetRootView(rv); - const auto& RV1 = RootParams.GetRootView(rv); - if (RV0 != RV1) - return false; + pCurrDescrRangePtr += d3d12SrcTbl.NumDescriptorRanges; } + VERIFY_EXPR(pCurrDescrRangePtr == pDescriptorRanges + TotalRangesCount); - for (Uint32 rv = 0; rv < m_NumRootTables; ++rv) + // Copy root views + for (Uint32 rv = 0; rv < NumRootViews; ++rv) { - const auto& RT0 = GetRootTable(rv); - const auto& RT1 = RootParams.GetRootTable(rv); - if (RT0 != RT1) - return false; + const auto& SrcView = m_RootViews[rv]; + const auto& d3d12RootParam = SrcView.d3d12RootParam; + VERIFY(d3d12RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV || d3d12RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_SRV || d3d12RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_UAV, + "Unexpected parameter type: SBV, SRV or UAV is expected"); + new (pRootViews + rv) RootParameter{SrcView.Group, SrcView.RootIndex, d3d12RootParam}; } - return true; + ParamsMgr.m_pRootTables = NumRootTables != 0 ? pRootTables : nullptr; + ParamsMgr.m_pRootViews = NumRootViews != 0 ? pRootViews : nullptr; } } // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp b/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp index 830c7a31..32a63841 100644 --- a/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp +++ b/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp @@ -122,18 +122,18 @@ void RootSignatureD3D12::Finalize() auto& RootParams = pSignature->m_RootParams; for (Uint32 rt = 0; rt < RootParams.GetNumRootTables(); ++rt) { - const auto& RootTable = RootParams.GetRootTable(rt); - const D3D12_ROOT_PARAMETER& SrcParam = RootTable; - const Uint32 RootIndex = FirstRootIndex + RootTable.GetLocalRootIndex(); + const auto& RootTable = RootParams.GetRootTable(rt); + const auto& SrcParam = RootTable.d3d12RootParam; + const Uint32 RootIndex = FirstRootIndex + RootTable.RootIndex; VERIFY(SrcParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE && SrcParam.DescriptorTable.NumDescriptorRanges > 0, "Non-empty descriptor table is expected"); D3D12Parameters[RootIndex] = SrcParam; } for (Uint32 rv = 0; rv < RootParams.GetNumRootViews(); ++rv) { - const auto& RootView = RootParams.GetRootView(rv); - const D3D12_ROOT_PARAMETER& SrcParam = RootView; - const Uint32 RootIndex = FirstRootIndex + RootView.GetLocalRootIndex(); + const auto& RootView = RootParams.GetRootView(rv); + const auto& SrcParam = RootView.d3d12RootParam; + const Uint32 RootIndex = FirstRootIndex + RootView.RootIndex; VERIFY(SrcParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV, "Root CBV is expected"); D3D12Parameters[RootIndex] = SrcParam; } |
