diff options
| author | assiduous <assiduous@diligentgraphics.com> | 2021-02-12 01:28:12 +0000 |
|---|---|---|
| committer | assiduous <assiduous@diligentgraphics.com> | 2021-03-19 00:31:35 +0000 |
| commit | 6c23895eea702eb63a67deede8d3084c2da6ab7b (patch) | |
| tree | 6258f58bfb44a58d1a88913f01d7f7e9e01d11ca /Graphics/GraphicsEngineD3D12 | |
| parent | DXBCUtils: fixed compiler error (diff) | |
| download | DiligentCore-6c23895eea702eb63a67deede8d3084c2da6ab7b.tar.gz DiligentCore-6c23895eea702eb63a67deede8d3084c2da6ab7b.zip | |
Refactored RootParamsManager
Diffstat (limited to 'Graphics/GraphicsEngineD3D12')
8 files changed, 630 insertions, 568 deletions
diff --git a/Graphics/GraphicsEngineD3D12/CMakeLists.txt b/Graphics/GraphicsEngineD3D12/CMakeLists.txt index 84c1d47c..a5c643c1 100644 --- a/Graphics/GraphicsEngineD3D12/CMakeLists.txt +++ b/Graphics/GraphicsEngineD3D12/CMakeLists.txt @@ -26,6 +26,7 @@ set(INCLUDE include/QueryManagerD3D12.hpp include/RenderDeviceD3D12Impl.hpp include/RenderPassD3D12Impl.hpp + include/RootParamsManager.hpp include/RootSignature.hpp include/SamplerD3D12Impl.hpp include/ShaderD3D12Impl.hpp @@ -84,6 +85,7 @@ set(SRC src/QueryManagerD3D12.cpp src/RenderDeviceD3D12Impl.cpp src/RenderPassD3D12Impl.cpp + src/RootParamsManager.cpp src/RootSignature.cpp src/SamplerD3D12Impl.cpp src/ShaderD3D12Impl.cpp diff --git a/Graphics/GraphicsEngineD3D12/include/D3D12Utils.h b/Graphics/GraphicsEngineD3D12/include/D3D12Utils.h index ac3e98e5..e162c969 100644 --- a/Graphics/GraphicsEngineD3D12/include/D3D12Utils.h +++ b/Graphics/GraphicsEngineD3D12/include/D3D12Utils.h @@ -30,5 +30,12 @@ #include "BasicTypes.h" namespace Diligent { + const Char* GetD3D12DescriptorHeapTypeLiteralName(D3D12_DESCRIPTOR_HEAP_TYPE Type); -} + +bool operator==(const D3D12_ROOT_DESCRIPTOR_TABLE& Tbl0, const D3D12_ROOT_DESCRIPTOR_TABLE& Tbl1); +bool operator==(const D3D12_ROOT_CONSTANTS& Const0, const D3D12_ROOT_CONSTANTS& Const1); +bool operator==(const D3D12_ROOT_DESCRIPTOR& Descr0, const D3D12_ROOT_DESCRIPTOR& Descr1); +bool operator==(const D3D12_ROOT_PARAMETER& Param0, const D3D12_ROOT_PARAMETER& Param1); + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/PipelineResourceSignatureD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/PipelineResourceSignatureD3D12Impl.hpp index db5b4030..ec47d421 100644 --- a/Graphics/GraphicsEngineD3D12/include/PipelineResourceSignatureD3D12Impl.hpp +++ b/Graphics/GraphicsEngineD3D12/include/PipelineResourceSignatureD3D12Impl.hpp @@ -34,6 +34,7 @@ #include "PipelineResourceSignatureBase.hpp" #include "SRBMemoryAllocator.hpp" +#include "RootParamsManager.hpp" namespace Diligent { @@ -68,38 +69,37 @@ public: struct ResourceAttribs { private: - static constexpr Uint32 _BindPointBits = 16; + static constexpr Uint32 _RegisterBits = 16; static constexpr Uint32 _SpaceBits = 8; static constexpr Uint32 _SRBRootIndexBits = 16; static constexpr Uint32 _SigRootIndexBits = 3; static constexpr Uint32 _SamplerIndBits = 16; static constexpr Uint32 _SamplerAssignedBits = 1; - static constexpr Uint32 _SigOffsetBits = 16; static constexpr Uint32 _RootViewBits = 1; - static_assert((1u << _BindPointBits) >= MAX_RESOURCES_IN_SIGNATURE, "Not enough bits to store bind point"); + static_assert((1u << _RegisterBits) >= MAX_RESOURCES_IN_SIGNATURE, "Not enough bits to store sahder register"); static_assert((1u << _SamplerIndBits) >= MAX_RESOURCES_IN_SIGNATURE, "Not enough bits to store sampler resource index"); public: static constexpr Uint32 InvalidSamplerInd = (1u << _SamplerIndBits) - 1; static constexpr Uint32 InvalidSRBRootIndex = (1u << _SRBRootIndexBits) - 1; static constexpr Uint32 InvalidSigRootIndex = (1u << _SigRootIndexBits) - 1; - static constexpr Uint32 InvalidBindPoint = (1u << _BindPointBits) - 1; + static constexpr Uint32 InvalidRegister = (1u << _RegisterBits) - 1; static constexpr Uint32 InvalidOffset = ~0u; // clang-format off - const Uint32 BindPoint : _BindPointBits; // shader register - const Uint32 SRBRootIndex : _SRBRootIndexBits; // Root view/table index for SRB + const Uint32 Register : _RegisterBits; // Shader register + const Uint32 SRBRootIndex : _SRBRootIndexBits; // Root view/table index in the SRB const Uint32 SamplerInd : _SamplerIndBits; // Index in m_Desc.Resources and m_pResourceAttribs const Uint32 SigRootIndex : _SigRootIndexBits; // Root table index for signature (static only) - const Uint32 Space : _SpaceBits; // shader register space + const Uint32 Space : _SpaceBits; // Shader register space const Uint32 ImtblSamplerAssigned : _SamplerAssignedBits; // Immutable sampler flag const Uint32 RootView : _RootViewBits; // Is root view (for debugging) const Uint32 SigOffsetFromTableStart; // Offset in the root table for signature (static only) const Uint32 SRBOffsetFromTableStart; // Offset in the root table for SRB // clang-format on - ResourceAttribs(Uint32 _BindPoint, + ResourceAttribs(Uint32 _Register, Uint32 _Space, Uint32 _SamplerInd, Uint32 _SRBRootIndex, @@ -109,7 +109,7 @@ public: bool _ImtblSamplerAssigned, bool _IsRootView) noexcept : // clang-format off - BindPoint {_BindPoint }, + Register {_Register }, SRBRootIndex {_SRBRootIndex }, SamplerInd {_SamplerInd }, SigRootIndex {_SigRootIndex }, @@ -120,7 +120,7 @@ public: SRBOffsetFromTableStart{_SRBOffsetFromTableStart } // clang-format on { - VERIFY(BindPoint == _BindPoint, "Bind point (", _BindPoint, ") exceeds maximum representable value"); + VERIFY(Register == _Register, "Bind point (", _Register, ") exceeds maximum representable value"); VERIFY(SRBRootIndex == _SRBRootIndex, "SRB Root index (", _SRBRootIndex, ") exceeds maximum representable value"); VERIFY(SigRootIndex == _SigRootIndex, "Signature Root index (", SigRootIndex, ") exceeds maximum representable value"); VERIFY(SamplerInd == _SamplerInd, "Sampler index (", _SamplerInd, ") exceeds maximum representable value"); @@ -268,171 +268,20 @@ public: Uint32 FirstRootIndex); private: - enum ROOT_TYPE : Uint8 - { - ROOT_TYPE_STATIC = 0, - ROOT_TYPE_DYNAMIC = 1, - ROOT_TYPE_COUNT - }; - static ROOT_TYPE GetRootType(SHADER_RESOURCE_VARIABLE_TYPE VarType); - - - class RootParameter - { - public: - RootParameter(D3D12_ROOT_PARAMETER_TYPE ParameterType, - Uint32 RootIndex, - UINT Register, - UINT RegisterSpace, - D3D12_SHADER_VISIBILITY Visibility, - ROOT_TYPE RootType) noexcept; - - RootParameter(D3D12_ROOT_PARAMETER_TYPE ParameterType, - Uint32 RootIndex, - UINT Register, - UINT RegisterSpace, - UINT NumDwords, - D3D12_SHADER_VISIBILITY Visibility, - ROOT_TYPE RootType) noexcept; - - RootParameter(D3D12_ROOT_PARAMETER_TYPE ParameterType, - Uint32 RootIndex, - UINT NumRanges, - D3D12_DESCRIPTOR_RANGE* pRanges, - D3D12_SHADER_VISIBILITY Visibility, - ROOT_TYPE RootType) noexcept; - - RootParameter(const RootParameter& RP) noexcept; - - RootParameter(const RootParameter& RP, - UINT NumRanges, - D3D12_DESCRIPTOR_RANGE* pRanges) noexcept; - - RootParameter& operator=(const RootParameter&) = delete; - RootParameter& operator=(RootParameter&&) = delete; - - void SetDescriptorRange(UINT RangeIndex, - D3D12_DESCRIPTOR_RANGE_TYPE Type, - UINT Register, - UINT RegisterSpace, - UINT Count, - UINT OffsetFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND); - - ROOT_TYPE GetRootType() const { return m_RootType; } - - Uint32 GetDescriptorTableSize() const; - - D3D12_SHADER_VISIBILITY GetShaderVisibility() const { return m_RootParam.ShaderVisibility; } - D3D12_ROOT_PARAMETER_TYPE GetParameterType() const { return m_RootParam.ParameterType; } - - Uint32 GetLocalRootIndex() const { return m_RootIndex; } - - operator const D3D12_ROOT_PARAMETER&() const { return m_RootParam; } - - bool operator==(const RootParameter& rhs) const; - bool operator!=(const RootParameter& rhs) const { return !(*this == rhs); } - - size_t GetHash() const; - - private: - ROOT_TYPE m_RootType = static_cast<ROOT_TYPE>(-1); - D3D12_ROOT_PARAMETER m_RootParam = {}; - Uint32 m_DescriptorTableSize = 0; - Uint32 m_RootIndex = static_cast<Uint32>(-1); - }; - - - class RootParamsManager - { - public: - RootParamsManager(IMemoryAllocator& MemAllocator); - - // clang-format off - RootParamsManager (const RootParamsManager&) = delete; - RootParamsManager& operator=(const RootParamsManager&) = delete; - RootParamsManager (RootParamsManager&&) = delete; - RootParamsManager& operator=(RootParamsManager&&) = delete; - // clang-format on - - Uint32 GetNumRootTables() const { return m_NumRootTables; } - Uint32 GetNumRootViews() const { return m_NumRootViews; } - - const RootParameter& GetRootTable(Uint32 TableInd) const - { - VERIFY_EXPR(TableInd < m_NumRootTables); - return m_pRootTables[TableInd]; - } - - RootParameter& GetRootTable(Uint32 TableInd) - { - VERIFY_EXPR(TableInd < m_NumRootTables); - return m_pRootTables[TableInd]; - } - - const RootParameter& GetRootView(Uint32 ViewInd) const - { - VERIFY_EXPR(ViewInd < m_NumRootViews); - return m_pRootViews[ViewInd]; - } - - RootParameter& GetRootView(Uint32 ViewInd) - { - VERIFY_EXPR(ViewInd < m_NumRootViews); - return m_pRootViews[ViewInd]; - } - - void AddRootView(D3D12_ROOT_PARAMETER_TYPE ParameterType, - Uint32 RootIndex, - UINT Register, - UINT RegisterSpace, - D3D12_SHADER_VISIBILITY Visibility, - ROOT_TYPE RootType); - - void AddRootTable(Uint32 RootIndex, - D3D12_SHADER_VISIBILITY Visibility, - ROOT_TYPE RootType, - Uint32 NumRangesInNewTable = 1); - - void AddDescriptorRanges(Uint32 RootTableInd, Uint32 NumExtraRanges = 1); - - template <class TOperation> - void ProcessRootTables(TOperation) const; - - bool operator==(const RootParamsManager& RootParams) const; - - private: - size_t GetRequiredMemorySize(Uint32 NumExtraRootTables, - Uint32 NumExtraRootViews, - Uint32 NumExtraDescriptorRanges) const; - - D3D12_DESCRIPTOR_RANGE* Extend(Uint32 NumExtraRootTables, - Uint32 NumExtraRootViews, - Uint32 NumExtraDescriptorRanges, - Uint32 RootTableToAddRanges = static_cast<Uint32>(-1)); - - IMemoryAllocator& m_MemAllocator; - std::unique_ptr<void, STDDeleter<void, IMemoryAllocator>> m_pMemory; - Uint32 m_NumRootTables = 0; - Uint32 m_NumRootViews = 0; - Uint32 m_TotalDescriptorRanges = 0; - RootParameter* m_pRootTables = nullptr; - RootParameter* m_pRootViews = nullptr; - }; - - using CacheOffsetsType = std::array<Uint32, 2>; + 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, BindPoint is the same as the original bind point. - // For ray-tracing pipeline, BindPoint will be overriden. Bind points are then + // 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 BindPoint, + Uint32 Register, Uint32 Space, Uint32& RootIndex, Uint32& OffsetFromTableStart); @@ -458,13 +307,13 @@ private: // in m_RootParams (NOT the Root Index!), for every variable type // (static, mutable, dynamic) and every shader type, // or -1, if the table is not yet assigned to the combination - std::array<Uint8, ROOT_TYPE_COUNT* MAX_SHADERS_IN_PIPELINE> m_SrvCbvUavRootTablesMap = {}; + std::array<Uint8, ROOT_PARAMETER_GROUP_COUNT* MAX_SHADERS_IN_PIPELINE> m_SrvCbvUavRootTablesMap = {}; // This array contains the same data for Sampler root table - std::array<Uint8, ROOT_TYPE_COUNT* MAX_SHADERS_IN_PIPELINE> m_SamplerRootTablesMap = {}; + std::array<Uint8, ROOT_PARAMETER_GROUP_COUNT* MAX_SHADERS_IN_PIPELINE> m_SamplerRootTablesMap = {}; - std::array<Uint32, ROOT_TYPE_COUNT> m_TotalSrvCbvUavSlots = {}; - std::array<Uint32, ROOT_TYPE_COUNT> m_TotalSamplerSlots = {}; - std::array<Uint32, ROOT_TYPE_COUNT> m_TotalRootViews = {}; + 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; diff --git a/Graphics/GraphicsEngineD3D12/include/RootParamsManager.hpp b/Graphics/GraphicsEngineD3D12/include/RootParamsManager.hpp new file mode 100644 index 00000000..7127ffcf --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/include/RootParamsManager.hpp @@ -0,0 +1,191 @@ +/* + * Copyright 2019-2021 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#pragma once + +/// \file +/// Declaration of Diligent::RootParamsManager class and related data structures + +#include <memory> + +#include "BasicTypes.h" + +namespace Diligent +{ + +enum ROOT_PARAMETER_GROUP : Uint8 +{ + ROOT_PARAMETER_GROUP_STATIC_MUTABLE = 0, + ROOT_PARAMETER_GROUP_DYNAMIC = 1, + ROOT_PARAMETER_GROUP_COUNT +}; + +class RootParameter +{ +public: + RootParameter(ROOT_PARAMETER_GROUP Group, + Uint32 RootIndex, + const D3D12_ROOT_PARAMETER& d3d12RootParam) noexcept; + + // clang-format off + RootParameter (const RootParameter&) = delete; + RootParameter& operator=(const RootParameter&) = delete; + RootParameter (RootParameter&&) = delete; + RootParameter& operator=(RootParameter&&) = delete; + // clang-format on + + // Initializes a 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; } + + Uint32 GetDescriptorTableSize() const + { + VERIFY(m_d3d12RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, "Incorrect parameter type: descriptor table is expected"); + return m_DescriptorTableSize; + } + + 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; } + + 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); + + // clang-format off + RootParamsManager (const RootParamsManager&) = delete; + RootParamsManager& operator=(const RootParamsManager&) = delete; + RootParamsManager (RootParamsManager&&) = delete; + RootParamsManager& operator=(RootParamsManager&&) = delete; + // clang-format on + + Uint32 GetNumRootTables() const { return m_NumRootTables; } + Uint32 GetNumRootViews() const { return m_NumRootViews; } + + const RootParameter& GetRootTable(Uint32 TableInd) const + { + VERIFY_EXPR(TableInd < m_NumRootTables); + return m_pRootTables[TableInd]; + } + + const RootParameter& GetRootView(Uint32 ViewInd) const + { + VERIFY_EXPR(ViewInd < m_NumRootViews); + return m_pRootViews[ViewInd]; + } + + // Adds a new root view 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 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); + + template <class TOperation> + void ProcessRootTables(TOperation) const; + + 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; + 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; +}; + +template <class TOperation> +__forceinline void RootParamsManager::ProcessRootTables(TOperation Operation) const +{ + for (Uint32 rt = 0; rt < m_NumRootTables; ++rt) + { + auto& RootTable = GetRootTable(rt); + auto RootInd = RootTable.GetLocalRootIndex(); + const D3D12_ROOT_PARAMETER& D3D12Param = RootTable; + + 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"); + 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); + } +} + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/src/D3D12Utils.cpp b/Graphics/GraphicsEngineD3D12/src/D3D12Utils.cpp index ba422ccc..a4c1e99b 100644 --- a/Graphics/GraphicsEngineD3D12/src/D3D12Utils.cpp +++ b/Graphics/GraphicsEngineD3D12/src/D3D12Utils.cpp @@ -28,8 +28,11 @@ #include "pch.h" #include "D3D12Utils.h" +#include <cstring> + namespace Diligent { + const Char* GetD3D12DescriptorHeapTypeLiteralName(D3D12_DESCRIPTOR_HEAP_TYPE Type) { static bool bIsInitialized = false; @@ -48,4 +51,56 @@ const Char* GetD3D12DescriptorHeapTypeLiteralName(D3D12_DESCRIPTOR_HEAP_TYPE Typ VERIFY_EXPR(Type >= 0 && Type < D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES); return HeapTypeNames[Type]; } + + +bool operator==(const D3D12_ROOT_DESCRIPTOR_TABLE& Tbl0, const D3D12_ROOT_DESCRIPTOR_TABLE& Tbl1) +{ + if (Tbl0.NumDescriptorRanges != Tbl1.NumDescriptorRanges) + return false; + + return memcmp(Tbl0.pDescriptorRanges, Tbl1.pDescriptorRanges, Tbl0.NumDescriptorRanges * sizeof(D3D12_DESCRIPTOR_RANGE)) == 0; +} + +bool operator==(const D3D12_ROOT_CONSTANTS& Const0, const D3D12_ROOT_CONSTANTS& Const1) +{ + // clang-format off + return Const0.ShaderRegister == Const1.ShaderRegister && + Const0.RegisterSpace == Const1.RegisterSpace && + Const0.Num32BitValues == Const1.Num32BitValues; + // clang-format on +} + +bool operator==(const D3D12_ROOT_DESCRIPTOR& Descr0, const D3D12_ROOT_DESCRIPTOR& Descr1) +{ + // clang-format off + return Descr0.ShaderRegister == Descr1.ShaderRegister && + Descr0.RegisterSpace == Descr1.RegisterSpace; + // clang-format on +} + +bool operator==(const D3D12_ROOT_PARAMETER& Param0, const D3D12_ROOT_PARAMETER& Param1) +{ + if (Param0.ParameterType != Param1.ParameterType || + Param0.ShaderVisibility != Param1.ShaderVisibility) + return false; + + switch (Param0.ParameterType) + { + case D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE: + return Param0.DescriptorTable == Param1.DescriptorTable; + + case D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS: + return Param0.Constants == Param1.Constants; + + case D3D12_ROOT_PARAMETER_TYPE_CBV: + case D3D12_ROOT_PARAMETER_TYPE_SRV: + case D3D12_ROOT_PARAMETER_TYPE_UAV: + return Param0.Descriptor == Param1.Descriptor; + + default: + UNEXPECTED("Unexpected root parameter type"); + return false; + } +} + } // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp index 81c80f81..eaaf7c37 100644 --- a/Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp @@ -41,369 +41,6 @@ namespace Diligent { -PipelineResourceSignatureD3D12Impl::RootParameter::RootParameter(D3D12_ROOT_PARAMETER_TYPE ParameterType, - Uint32 RootIndex, - UINT Register, - UINT RegisterSpace, - D3D12_SHADER_VISIBILITY Visibility, - ROOT_TYPE RootType) noexcept : - // clang-format off - m_RootIndex{RootIndex}, - m_RootType {RootType } -// clang-format on -{ - VERIFY(ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV || ParameterType == D3D12_ROOT_PARAMETER_TYPE_SRV || ParameterType == D3D12_ROOT_PARAMETER_TYPE_UAV, "Unexpected parameter type - verify argument list"); - m_RootParam.ParameterType = ParameterType; - m_RootParam.ShaderVisibility = Visibility; - m_RootParam.Descriptor.ShaderRegister = Register; - m_RootParam.Descriptor.RegisterSpace = RegisterSpace; -} - -PipelineResourceSignatureD3D12Impl::RootParameter::RootParameter(D3D12_ROOT_PARAMETER_TYPE ParameterType, - Uint32 RootIndex, - UINT Register, - UINT RegisterSpace, - UINT NumDwords, - D3D12_SHADER_VISIBILITY Visibility, - ROOT_TYPE RootType) noexcept : - // clang-format off - m_RootIndex{RootIndex}, - m_RootType {RootType } -// clang-format on -{ - VERIFY(ParameterType == D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS, "Unexpected parameter type - verify argument list"); - m_RootParam.ParameterType = ParameterType; - m_RootParam.ShaderVisibility = Visibility; - m_RootParam.Constants.Num32BitValues = NumDwords; - m_RootParam.Constants.ShaderRegister = Register; - m_RootParam.Constants.RegisterSpace = RegisterSpace; -} - -PipelineResourceSignatureD3D12Impl::RootParameter::RootParameter(D3D12_ROOT_PARAMETER_TYPE ParameterType, - Uint32 RootIndex, - UINT NumRanges, - D3D12_DESCRIPTOR_RANGE* pRanges, - D3D12_SHADER_VISIBILITY Visibility, - ROOT_TYPE RootType) noexcept : - // clang-format off - m_RootIndex{RootIndex}, - m_RootType {RootType } -// clang-format on -{ - VERIFY(ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, "Unexpected parameter type - verify argument list"); - VERIFY_EXPR(pRanges != nullptr); - m_RootParam.ParameterType = ParameterType; - m_RootParam.ShaderVisibility = Visibility; - m_RootParam.DescriptorTable.NumDescriptorRanges = NumRanges; - m_RootParam.DescriptorTable.pDescriptorRanges = pRanges; -#ifdef DILIGENT_DEBUG - for (Uint32 r = 0; r < NumRanges; ++r) - pRanges[r].RangeType = static_cast<D3D12_DESCRIPTOR_RANGE_TYPE>(-1); -#endif -} - -PipelineResourceSignatureD3D12Impl::RootParameter::RootParameter(const RootParameter& RP) noexcept : - // clang-format off - m_RootParam {RP.m_RootParam }, - m_DescriptorTableSize{RP.m_DescriptorTableSize}, - m_RootType {RP.m_RootType }, - m_RootIndex {RP.m_RootIndex } -// clang-format on -{ - VERIFY(m_RootParam.ParameterType != D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, "Use another constructor to copy descriptor table"); -} - -PipelineResourceSignatureD3D12Impl::RootParameter::RootParameter(const RootParameter& RP, - UINT NumRanges, - D3D12_DESCRIPTOR_RANGE* pRanges) noexcept : - // clang-format off - m_RootParam {RP.m_RootParam }, - m_DescriptorTableSize{RP.m_DescriptorTableSize}, - m_RootType {RP.m_RootType }, - m_RootIndex {RP.m_RootIndex } -// clang-format on -{ - VERIFY(m_RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, "Root parameter is expected to be a descriptor table"); - VERIFY(NumRanges >= m_RootParam.DescriptorTable.NumDescriptorRanges, "New table must be larger than source one"); - auto& DstTbl = m_RootParam.DescriptorTable; - DstTbl.NumDescriptorRanges = NumRanges; - DstTbl.pDescriptorRanges = pRanges; - const auto& SrcTbl = RP.m_RootParam.DescriptorTable; - memcpy(pRanges, SrcTbl.pDescriptorRanges, SrcTbl.NumDescriptorRanges * sizeof(D3D12_DESCRIPTOR_RANGE)); -#ifdef DILIGENT_DEBUG - { - Uint32 dbgTableSize = 0; - for (Uint32 r = 0; r < SrcTbl.NumDescriptorRanges; ++r) - { - const auto& Range = SrcTbl.pDescriptorRanges[r]; - dbgTableSize = std::max(dbgTableSize, Range.OffsetInDescriptorsFromTableStart + Range.NumDescriptors); - } - VERIFY(dbgTableSize == m_DescriptorTableSize, "Incorrect descriptor table size"); - - for (Uint32 r = SrcTbl.NumDescriptorRanges; r < DstTbl.NumDescriptorRanges; ++r) - pRanges[r].RangeType = static_cast<D3D12_DESCRIPTOR_RANGE_TYPE>(-1); - } -#endif -} - -void PipelineResourceSignatureD3D12Impl::RootParameter::SetDescriptorRange(UINT RangeIndex, - D3D12_DESCRIPTOR_RANGE_TYPE Type, - UINT Register, - UINT RegisterSpace, - UINT Count, - UINT OffsetFromTableStart) -{ - VERIFY(m_RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, "Incorrect parameter table: descriptor table is expected"); - auto& Tbl = m_RootParam.DescriptorTable; - VERIFY(RangeIndex < Tbl.NumDescriptorRanges, "Invalid descriptor range index"); - D3D12_DESCRIPTOR_RANGE& range = const_cast<D3D12_DESCRIPTOR_RANGE&>(Tbl.pDescriptorRanges[RangeIndex]); - VERIFY(range.RangeType == static_cast<D3D12_DESCRIPTOR_RANGE_TYPE>(-1), "Descriptor range has already been initialized. m_DescriptorTableSize may be updated incorrectly"); - range.RangeType = Type; - range.NumDescriptors = Count; - range.BaseShaderRegister = Register; - range.RegisterSpace = RegisterSpace; - range.OffsetInDescriptorsFromTableStart = OffsetFromTableStart; - m_DescriptorTableSize = std::max(m_DescriptorTableSize, OffsetFromTableStart + Count); -} - -Uint32 PipelineResourceSignatureD3D12Impl::RootParameter::GetDescriptorTableSize() const -{ - VERIFY(m_RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, "Incorrect parameter table: descriptor table is expected"); - return m_DescriptorTableSize; -} - -bool PipelineResourceSignatureD3D12Impl::RootParameter::operator==(const RootParameter& rhs) const -{ - if (m_RootType != rhs.m_RootType || - m_DescriptorTableSize != rhs.m_DescriptorTableSize || - m_RootIndex != rhs.m_RootIndex) - return false; - - if (m_RootParam.ParameterType != rhs.m_RootParam.ParameterType || - m_RootParam.ShaderVisibility != rhs.m_RootParam.ShaderVisibility) - return false; - - switch (m_RootParam.ParameterType) - { - case D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE: - { - const auto& tbl0 = m_RootParam.DescriptorTable; - const auto& tbl1 = rhs.m_RootParam.DescriptorTable; - if (tbl0.NumDescriptorRanges != tbl1.NumDescriptorRanges) - return false; - for (UINT r = 0; r < tbl0.NumDescriptorRanges; ++r) - { - const auto& rng0 = tbl0.pDescriptorRanges[r]; - const auto& rng1 = tbl1.pDescriptorRanges[r]; - if (memcmp(&rng0, &rng1, sizeof(rng0)) != 0) - return false; - } - } - break; - - case D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS: - { - const auto& cnst0 = m_RootParam.Constants; - const auto& cnst1 = rhs.m_RootParam.Constants; - if (memcmp(&cnst0, &cnst1, sizeof(cnst0)) != 0) - return false; - } - break; - - case D3D12_ROOT_PARAMETER_TYPE_CBV: - case D3D12_ROOT_PARAMETER_TYPE_SRV: - case D3D12_ROOT_PARAMETER_TYPE_UAV: - { - const auto& dscr0 = m_RootParam.Descriptor; - const auto& dscr1 = rhs.m_RootParam.Descriptor; - if (memcmp(&dscr0, &dscr1, sizeof(dscr0)) != 0) - return false; - } - break; - - default: UNEXPECTED("Unexpected root parameter type"); - } - - return true; -} - -size_t PipelineResourceSignatureD3D12Impl::RootParameter::GetHash() const -{ - size_t hash = ComputeHash(m_RootType, m_DescriptorTableSize, m_RootIndex); - HashCombine(hash, m_RootParam.ParameterType, m_RootParam.ShaderVisibility); - - switch (m_RootParam.ParameterType) - { - case D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE: - { - const auto& tbl = m_RootParam.DescriptorTable; - HashCombine(hash, tbl.NumDescriptorRanges); - for (UINT r = 0; r < tbl.NumDescriptorRanges; ++r) - { - const auto& rng = tbl.pDescriptorRanges[r]; - HashCombine(hash, rng.BaseShaderRegister, rng.NumDescriptors, rng.OffsetInDescriptorsFromTableStart, rng.RangeType, rng.RegisterSpace); - } - } - break; - - case D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS: - { - const auto& cnst = m_RootParam.Constants; - HashCombine(hash, cnst.Num32BitValues, cnst.RegisterSpace, cnst.ShaderRegister); - } - break; - - case D3D12_ROOT_PARAMETER_TYPE_CBV: - case D3D12_ROOT_PARAMETER_TYPE_SRV: - case D3D12_ROOT_PARAMETER_TYPE_UAV: - { - const auto& dscr = m_RootParam.Descriptor; - HashCombine(hash, dscr.RegisterSpace, dscr.ShaderRegister); - } - break; - - default: UNEXPECTED("Unexpected root parameter type"); - } - - return hash; -} - - -PipelineResourceSignatureD3D12Impl::RootParamsManager::RootParamsManager(IMemoryAllocator& MemAllocator) : - m_MemAllocator{MemAllocator}, - m_pMemory{nullptr, STDDeleter<void, IMemoryAllocator>(MemAllocator)} -{} - -size_t PipelineResourceSignatureD3D12Impl::RootParamsManager::GetRequiredMemorySize(Uint32 NumExtraRootTables, - Uint32 NumExtraRootViews, - Uint32 NumExtraDescriptorRanges) const -{ - return sizeof(RootParameter) * (m_NumRootTables + NumExtraRootTables + m_NumRootViews + NumExtraRootViews) + sizeof(D3D12_DESCRIPTOR_RANGE) * (m_TotalDescriptorRanges + NumExtraDescriptorRanges); -} - -D3D12_DESCRIPTOR_RANGE* PipelineResourceSignatureD3D12Impl::RootParamsManager::Extend(Uint32 NumExtraRootTables, - Uint32 NumExtraRootViews, - Uint32 NumExtraDescriptorRanges, - Uint32 RootTableToAddRanges) -{ - VERIFY(NumExtraRootTables > 0 || NumExtraRootViews > 0 || NumExtraDescriptorRanges > 0, "At least one root table, root view or descriptor range must be added"); - auto MemorySize = GetRequiredMemorySize(NumExtraRootTables, NumExtraRootViews, NumExtraDescriptorRanges); - VERIFY_EXPR(MemorySize > 0); - auto* pNewMemory = ALLOCATE_RAW(m_MemAllocator, "Memory buffer for root tables, root views & descriptor ranges", MemorySize); - memset(pNewMemory, 0, MemorySize); - - // Note: this order is more efficient than views->tables->ranges - auto* pNewRootTables = reinterpret_cast<RootParameter*>(pNewMemory); - auto* pNewRootViews = pNewRootTables + (m_NumRootTables + NumExtraRootTables); - auto* pCurrDescriptorRangePtr = reinterpret_cast<D3D12_DESCRIPTOR_RANGE*>(pNewRootViews + m_NumRootViews + NumExtraRootViews); - - // Copy existing root tables to new memory - for (Uint32 rt = 0; rt < m_NumRootTables; ++rt) - { - const auto& SrcTbl = GetRootTable(rt); - auto& D3D12SrcTbl = static_cast<const D3D12_ROOT_PARAMETER&>(SrcTbl).DescriptorTable; - auto NumRanges = D3D12SrcTbl.NumDescriptorRanges; - if (rt == RootTableToAddRanges) - { - VERIFY(NumExtraRootTables == 0 || NumExtraRootTables == 1, "Up to one descriptor table can be extended at a time"); - NumRanges += NumExtraDescriptorRanges; - } - new (pNewRootTables + rt) RootParameter(SrcTbl, NumRanges, pCurrDescriptorRangePtr); - pCurrDescriptorRangePtr += NumRanges; - } - - // Copy existing root views to new memory - for (Uint32 rv = 0; rv < m_NumRootViews; ++rv) - { - const auto& SrcView = GetRootView(rv); - new (pNewRootViews + rv) RootParameter(SrcView); - } - - m_pMemory.reset(pNewMemory); - m_NumRootTables += NumExtraRootTables; - m_NumRootViews += NumExtraRootViews; - m_TotalDescriptorRanges += NumExtraDescriptorRanges; - m_pRootTables = m_NumRootTables != 0 ? pNewRootTables : nullptr; - m_pRootViews = m_NumRootViews != 0 ? pNewRootViews : nullptr; - - return pCurrDescriptorRangePtr; -} - -void PipelineResourceSignatureD3D12Impl::RootParamsManager::AddRootView(D3D12_ROOT_PARAMETER_TYPE ParameterType, - Uint32 RootIndex, - UINT Register, - UINT RegisterSpace, - D3D12_SHADER_VISIBILITY Visibility, - ROOT_TYPE RootType) -{ - auto* pRangePtr = Extend(0, 1, 0); - VERIFY_EXPR((char*)pRangePtr == (char*)m_pMemory.get() + GetRequiredMemorySize(0, 0, 0)); - new (m_pRootViews + m_NumRootViews - 1) RootParameter(ParameterType, RootIndex, Register, RegisterSpace, Visibility, RootType); -} - -void PipelineResourceSignatureD3D12Impl::RootParamsManager::AddRootTable(Uint32 RootIndex, - D3D12_SHADER_VISIBILITY Visibility, - ROOT_TYPE RootType, - Uint32 NumRangesInNewTable) -{ - auto* pRangePtr = Extend(1, 0, NumRangesInNewTable); - VERIFY_EXPR((char*)(pRangePtr + NumRangesInNewTable) == (char*)m_pMemory.get() + GetRequiredMemorySize(0, 0, 0)); - new (m_pRootTables + m_NumRootTables - 1) RootParameter(D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, RootIndex, NumRangesInNewTable, pRangePtr, Visibility, RootType); -} - -void PipelineResourceSignatureD3D12Impl::RootParamsManager::AddDescriptorRanges(Uint32 RootTableInd, Uint32 NumExtraRanges) -{ - auto* pRangePtr = Extend(0, 0, NumExtraRanges, RootTableInd); - VERIFY_EXPR((char*)pRangePtr == (char*)m_pMemory.get() + GetRequiredMemorySize(0, 0, 0)); -} - -bool PipelineResourceSignatureD3D12Impl::RootParamsManager::operator==(const RootParamsManager& RootParams) const -{ - if (m_NumRootTables != RootParams.m_NumRootTables || - m_NumRootViews != RootParams.m_NumRootViews) - return false; - - for (Uint32 rv = 0; rv < m_NumRootViews; ++rv) - { - 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; - } - - return true; -} - -template <class TOperation> -__forceinline void PipelineResourceSignatureD3D12Impl::RootParamsManager::ProcessRootTables(TOperation Operation) const -{ - for (Uint32 rt = 0; rt < m_NumRootTables; ++rt) - { - auto& RootTable = GetRootTable(rt); - auto RootInd = RootTable.GetLocalRootIndex(); - const D3D12_ROOT_PARAMETER& D3D12Param = RootTable; - - 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"); - 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); - } -} - namespace { @@ -775,7 +412,7 @@ inline bool ResourcesCompatible(const PipelineResourceSignatureD3D12Impl::Resour { // Ignore sampler index, signature root index & offset. // clang-format off - return lhs.BindPoint == rhs.BindPoint && + return lhs.Register == rhs.Register && lhs.Space == rhs.Space && lhs.SRBRootIndex == rhs.SRBRootIndex && lhs.SRBOffsetFromTableStart == rhs.SRBOffsetFromTableStart && @@ -797,10 +434,9 @@ inline bool ResourcesCompatible(const PipelineResourceDesc& lhs, const PipelineR } // namespace -inline PipelineResourceSignatureD3D12Impl::ROOT_TYPE -PipelineResourceSignatureD3D12Impl::GetRootType(SHADER_RESOURCE_VARIABLE_TYPE VarType) +inline ROOT_PARAMETER_GROUP PipelineResourceSignatureD3D12Impl::GetRootParameterGroup(SHADER_RESOURCE_VARIABLE_TYPE VarType) { - return VarType == SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC ? ROOT_TYPE_DYNAMIC : ROOT_TYPE_STATIC; + return VarType == SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC ? ROOT_PARAMETER_GROUP_DYNAMIC : ROOT_PARAMETER_GROUP_STATIC_MUTABLE; } PipelineResourceSignatureD3D12Impl::PipelineResourceSignatureD3D12Impl(IReferenceCounters* pRefCounters, @@ -936,7 +572,7 @@ void PipelineResourceSignatureD3D12Impl::CreateLayout() const bool IsRuntimeSizedArray = (ResDesc.Flags & PIPELINE_RESOURCE_FLAG_RUNTIME_ARRAY) != 0; const auto DescriptorRangeType = GetDescriptorRangeType(ResDesc.ResourceType); - const Uint32 BindPoint = IsRuntimeSizedArray ? 0 : NumResources[DescriptorRangeType]; + const Uint32 Register = IsRuntimeSizedArray ? 0 : NumResources[DescriptorRangeType]; const Uint32 Space = (IsRuntimeSizedArray ? m_NumSpaces++ : 0); Uint32 SRBRootIndex = ResourceAttribs::InvalidSRBRootIndex; Uint32 SRBOffsetFromTableStart = ResourceAttribs::InvalidOffset; @@ -985,7 +621,7 @@ void PipelineResourceSignatureD3D12Impl::CreateLayout() if (!ImmutableSampler.IsAssigned()) { - ImmutableSampler.ShaderRegister = BindPoint; + ImmutableSampler.ShaderRegister = Register; ImmutableSampler.RegisterSpace = Space; ImmutableSampler.ArraySize = ResDesc.ArraySize; } @@ -998,12 +634,12 @@ void PipelineResourceSignatureD3D12Impl::CreateLayout() } else { - AllocateResourceSlot(ResDesc.ShaderStages, ResDesc.VarType, DescriptorRangeType, ResDesc.ArraySize, IsRootView, BindPoint, FirstSpace + Space, SRBRootIndex, SRBOffsetFromTableStart); + AllocateResourceSlot(ResDesc.ShaderStages, ResDesc.VarType, DescriptorRangeType, ResDesc.ArraySize, IsRootView, Register, FirstSpace + Space, SRBRootIndex, SRBOffsetFromTableStart); } new (m_pResourceAttribs + i) ResourceAttribs // { - BindPoint, + Register, Space, AssignedSamplerInd, SRBRootIndex, @@ -1077,7 +713,7 @@ void PipelineResourceSignatureD3D12Impl::AllocateResourceSlot(SHADER_TYPE D3D12_DESCRIPTOR_RANGE_TYPE RangeType, Uint32 ArraySize, bool IsRootView, - Uint32 BindPoint, + Uint32 Register, Uint32 Space, Uint32& RootIndex, // Output parameter Uint32& OffsetFromTableStart // Output parameter @@ -1087,7 +723,7 @@ void PipelineResourceSignatureD3D12Impl::AllocateResourceSlot(SHADER_TYPE Uint32 RootTableIndex; GetRootTableIndex(ShaderStages, ShaderVisibility, RootTableIndex); - const auto RootType = GetRootType(VariableType); + const auto RootType = GetRootParameterGroup(VariableType); // Get the next available root index past all allocated tables and root views RootIndex = m_RootParams.GetNumRootTables() + m_RootParams.GetNumRootViews(); @@ -1098,51 +734,53 @@ void PipelineResourceSignatureD3D12Impl::AllocateResourceSlot(SHADER_TYPE OffsetFromTableStart = 0; // Add new root view to existing root parameters - m_RootParams.AddRootView(D3D12_ROOT_PARAMETER_TYPE_CBV, RootIndex, BindPoint, Space, ShaderVisibility, RootType); // AZ TODO: add SRV & UAV + m_RootParams.AddRootView(D3D12_ROOT_PARAMETER_TYPE_CBV, RootIndex, Register, Space, ShaderVisibility, RootType); // AZ TODO: add SRV & UAV } else { const bool IsSampler = (RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER); - const auto TableIndKey = RootTableIndex * ROOT_TYPE_COUNT + Uint32{RootType}; + const auto TableIndKey = RootTableIndex * ROOT_PARAMETER_GROUP_COUNT + Uint32{RootType}; // Get the table array index (this is not the root index!) auto& RootTableArrayInd = (IsSampler ? m_SamplerRootTablesMap : m_SrvCbvUavRootTablesMap)[TableIndKey]; + + 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 - m_RootParams.AddRootTable(RootIndex, ShaderVisibility, RootType, 1); + pRootTable = m_RootParams.AddRootTable(RootIndex, ShaderVisibility, RootType, 1); } else { // Add a new single-descriptor range to the existing table at index RootTableArrayInd - m_RootParams.AddDescriptorRanges(RootTableArrayInd, 1); + pRootTable = m_RootParams.ExtendRootTable(RootTableArrayInd, 1); } (IsSampler ? m_TotalSamplerSlots : m_TotalSrvCbvUavSlots)[RootType] += ArraySize; // Reference to either existing or just added table - auto& CurrParam = m_RootParams.GetRootTable(RootTableArrayInd); - RootIndex = CurrParam.GetLocalRootIndex(); + RootIndex = pRootTable->GetLocalRootIndex(); - const auto& d3d12RootParam = static_cast<const D3D12_ROOT_PARAMETER&>(CurrParam); + 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 = CurrParam.GetDescriptorTableSize(); + OffsetFromTableStart = pRootTable->GetDescriptorTableSize(); // New just added range is the last range in the descriptor table Uint32 NewDescriptorRangeIndex = d3d12RootParam.DescriptorTable.NumDescriptorRanges - 1; - CurrParam.SetDescriptorRange(NewDescriptorRangeIndex, - RangeType, // Range type (CBV, SRV, UAV or SAMPLER) - BindPoint, // Shader register - Space, // Shader register space - ArraySize, // Number of registers used (1 for non-array resources) - OffsetFromTableStart // Offset in descriptors from the table start - ); + + 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); } } @@ -1310,7 +948,7 @@ size_t PipelineResourceSignatureD3D12Impl::CalculateHash() const const auto& Attr = m_pResourceAttribs[i]; HashCombine(Hash, Res.ArraySize, Uint32{Res.ShaderStages}, Uint32{Res.VarType}, Uint32{Res.Flags}, - Attr.BindPoint, Attr.Space, Attr.SRBRootIndex, Attr.SRBOffsetFromTableStart, Attr.IsImmutableSamplerAssigned()); + Attr.Register, Attr.Space, Attr.SRBRootIndex, Attr.SRBOffsetFromTableStart, Attr.IsImmutableSamplerAssigned()); } for (Uint32 i = 0; i < m_Desc.NumImmutableSamplers; ++i) @@ -1352,8 +990,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_TYPE_STATIC]; - Uint32 TotalSamplerDescriptors = m_TotalSamplerSlots[ROOT_TYPE_STATIC]; + Uint32 TotalSrvCbvUavDescriptors = m_TotalSrvCbvUavSlots[ROOT_PARAMETER_GROUP_STATIC_MUTABLE]; + Uint32 TotalSamplerDescriptors = m_TotalSamplerSlots[ROOT_PARAMETER_GROUP_STATIC_MUTABLE]; DescriptorHeapAllocation CbcSrvUavHeapSpace, SamplerHeapSpace; if (TotalSrvCbvUavDescriptors) @@ -1388,7 +1026,7 @@ void PipelineResourceSignatureD3D12Impl::InitSRBResourceCache(ShaderResourceCach 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.GetRootType() == ROOT_TYPE_DYNAMIC; + const bool IsDynamic = RootParam.GetGroup() == ROOT_PARAMETER_GROUP_DYNAMIC; VERIFY_EXPR(D3D12RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE); @@ -1429,7 +1067,7 @@ void PipelineResourceSignatureD3D12Impl::InitSRBResourceCache(ShaderResourceCach 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.GetRootType() == ROOT_TYPE_DYNAMIC; + const bool IsDynamic = RootParam.GetGroup() == ROOT_PARAMETER_GROUP_DYNAMIC; // Root views are not assigned valid table start offset VERIFY_EXPR(RootTableCache.m_TableStartOffset == ShaderResourceCacheD3D12::InvalidDescriptorOffset); @@ -1580,8 +1218,8 @@ void PipelineResourceSignatureD3D12Impl::CommitRootTables(ShaderResourceCacheD3D { auto* pd3d12Device = GetDevice()->GetD3D12Device(); - Uint32 NumDynamicCbvSrvUavDescriptors = m_TotalSrvCbvUavSlots[ROOT_TYPE_DYNAMIC]; - Uint32 NumDynamicSamplerDescriptors = m_TotalSamplerSlots[ROOT_TYPE_DYNAMIC]; + Uint32 NumDynamicCbvSrvUavDescriptors = m_TotalSrvCbvUavSlots[ROOT_PARAMETER_GROUP_DYNAMIC]; + Uint32 NumDynamicSamplerDescriptors = m_TotalSamplerSlots[ROOT_PARAMETER_GROUP_DYNAMIC]; //VERIFY_EXPR(NumDynamicCbvSrvUavDescriptors > 0 || NumDynamicSamplerDescriptors > 0); DescriptorHeapAllocation DynamicCbvSrvUavDescriptors, DynamicSamplerDescriptors; @@ -1634,7 +1272,7 @@ void PipelineResourceSignatureD3D12Impl::CommitRootTables(ShaderResourceCacheD3D { D3D12_GPU_DESCRIPTOR_HANDLE RootTableGPUDescriptorHandle; - bool IsDynamicTable = RootTable.GetRootType() == ROOT_TYPE_DYNAMIC; + bool IsDynamicTable = RootTable.GetGroup() == ROOT_PARAMETER_GROUP_DYNAMIC; if (IsDynamicTable) { if (IsResourceTable) diff --git a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp index 9cfc7c7d..f83c89d2 100644 --- a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp @@ -568,7 +568,7 @@ void PipelineStateD3D12Impl::InitRootSignature(const PipelineStateCreateInfo& Cr if (ResDesc.ShaderStages & ShaderType) { - auto IsUnique = ResourceMap.emplace(HashMapStringKey{ResDesc.Name}, ResourceBinding::BindInfo{Attribs.BindPoint, Attribs.Space + FirstSpace}).second; + auto IsUnique = ResourceMap.emplace(HashMapStringKey{ResDesc.Name}, ResourceBinding::BindInfo{Attribs.Register, Attribs.Space + FirstSpace}).second; VERIFY(IsUnique, "resource name must be unique"); } } diff --git a/Graphics/GraphicsEngineD3D12/src/RootParamsManager.cpp b/Graphics/GraphicsEngineD3D12/src/RootParamsManager.cpp new file mode 100644 index 00000000..4021a7c9 --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/src/RootParamsManager.cpp @@ -0,0 +1,320 @@ +/* + * Copyright 2019-2021 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" + +#include "RootParamsManager.hpp" +#include "D3D12Utils.h" + +namespace Diligent +{ + +RootParameter::RootParameter(ROOT_PARAMETER_GROUP Group, + Uint32 RootIndex, + const D3D12_ROOT_PARAMETER& d3d12RootParam) noexcept : + m_d3d12RootParam{d3d12RootParam}, + m_RootIndex{static_cast<decltype(m_RootIndex)>(RootIndex)}, + m_Group{Group} +{ + VERIFY(m_RootIndex == RootIndex, "Root index (", RootIndex, ") exceeds representable range"); +} + +void RootParameter::InitDescriptorRange(UINT RangeIndex, + const D3D12_DESCRIPTOR_RANGE& Range) +{ + VERIFY(m_d3d12RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, + "Incorrect parameter type: descriptor table is expected"); + + const auto& d3d12Tbl = m_d3d12RootParam.DescriptorTable; + VERIFY(RangeIndex < d3d12Tbl.NumDescriptorRanges, "Invalid descriptor range index"); + + auto& DstRange = const_cast<D3D12_DESCRIPTOR_RANGE&>(d3d12Tbl.pDescriptorRanges[RangeIndex]); + VERIFY(DstRange.RangeType == static_cast<D3D12_DESCRIPTOR_RANGE_TYPE>(0xFFFFFFFF), "Descriptor range has already been initialized."); + DstRange = Range; + + m_DescriptorTableSize = std::max(m_DescriptorTableSize, Range.OffsetInDescriptorsFromTableStart + Range.NumDescriptors); +} + +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; +} + + +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}); + + switch (m_d3d12RootParam.ParameterType) + { + case D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE: + { + const auto& tbl = m_d3d12RootParam.DescriptorTable; + HashCombine(hash, tbl.NumDescriptorRanges); + for (UINT r = 0; r < tbl.NumDescriptorRanges; ++r) + { + const auto& rng = tbl.pDescriptorRanges[r]; + HashCombine(hash, int{rng.RangeType}, rng.NumDescriptors, rng.BaseShaderRegister, rng.RegisterSpace, rng.OffsetInDescriptorsFromTableStart); + } + } + break; + + case D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS: + { + const auto& cnst = m_d3d12RootParam.Constants; + HashCombine(hash, cnst.ShaderRegister, cnst.RegisterSpace, cnst.Num32BitValues); + } + break; + + case D3D12_ROOT_PARAMETER_TYPE_CBV: + case D3D12_ROOT_PARAMETER_TYPE_SRV: + case D3D12_ROOT_PARAMETER_TYPE_UAV: + { + const auto& dscr = m_d3d12RootParam.Descriptor; + HashCombine(hash, dscr.ShaderRegister, dscr.RegisterSpace); + } + break; + + default: UNEXPECTED("Unexpected root parameter type"); + } + + return hash; +} + +#ifdef DILIGENT_DEBUG +void RootParameter::DbgValidateAsTable() const +{ + VERIFY(GetParameterType() == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, "Unexpected parameter type: descriptor table is expected"); + const auto& d3d12SrcTbl = m_d3d12RootParam.DescriptorTable; + + Uint32 dbgTableSize = 0; + if (d3d12SrcTbl.pDescriptorRanges != nullptr) + { + for (Uint32 r = 0; r < d3d12SrcTbl.NumDescriptorRanges; ++r) + { + const auto& Range = d3d12SrcTbl.pDescriptorRanges[r]; + dbgTableSize = std::max(dbgTableSize, Range.OffsetInDescriptorsFromTableStart + Range.NumDescriptors); + } + } + VERIFY(dbgTableSize == GetDescriptorTableSize(), "Incorrect descriptor table size"); +} + +void RootParameter::DbgValidateAsView() const +{ + 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"); +} +#endif + +RootParamsManager::RootParamsManager(IMemoryAllocator& MemAllocator) : + m_MemAllocator{MemAllocator}, + m_pMemory{nullptr, STDDeleter<void, IMemoryAllocator>(MemAllocator)} +{} + + +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"); + + const auto NewParamsCount = m_NumRootTables + NumExtraRootTables + m_NumRootViews + NumExtraRootViews; + + 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; + } + + const auto MemorySize = + NewParamsCount * sizeof(RootParameter) + + NewRangesCount * sizeof(D3D12_DESCRIPTOR_RANGE); + + 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 + memset(pNewMemory.get(), 0xFF, MemorySize); +#endif + + // Note: this order is more efficient than views->tables->ranges + auto* pNewRootTables = reinterpret_cast<RootParameter*>(pNewMemory.get()); + auto* pNewRootViews = pNewRootTables + (m_NumRootTables + NumExtraRootTables); + auto* pDescriptorRangePtr = reinterpret_cast<D3D12_DESCRIPTOR_RANGE*>(pNewRootViews + m_NumRootViews + NumExtraRootViews); + + // Copy root tables to new memory + for (Uint32 rt = 0; rt < m_NumRootTables + NumExtraRootTables; ++rt) + { + const auto& SrcTbl = rt < m_NumRootTables ? GetRootTable(rt) : ExtraRootTables[rt - m_NumRootTables]; +#ifdef DILIGENT_DEBUG + SrcTbl.DbgValidateAsTable(); +#endif + auto& d3d12SrcTbl = static_cast<const D3D12_ROOT_PARAMETER&>(SrcTbl).DescriptorTable; + auto NumRanges = d3d12SrcTbl.NumDescriptorRanges; + if (rt == RootTableToAddRanges) + { + VERIFY(d3d12SrcTbl.pDescriptorRanges == nullptr, "Adding extra descriptors to a new table. This is likely not intended."); + NumRanges += NumExtraDescriptorRanges; + } + + // Copy existing ranges, if any (pDescriptorRanges == null for extra descriptor tables) + if (d3d12SrcTbl.pDescriptorRanges != nullptr) + { + memcpy(pDescriptorRangePtr, d3d12SrcTbl.pDescriptorRanges, d3d12SrcTbl.NumDescriptorRanges * sizeof(D3D12_DESCRIPTOR_RANGE)); + } + + new (pNewRootTables + rt) RootParameter{ + SrcTbl.GetGroup(), SrcTbl.GetLocalRootIndex(), + D3D12_ROOT_PARAMETER // + { + D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, + D3D12_ROOT_DESCRIPTOR_TABLE{NumRanges, pDescriptorRangePtr}, + SrcTbl.GetShaderVisibility() // + } // + }; + + pDescriptorRangePtr += NumRanges; + } + + // 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]; +#ifdef DILIGENT_DEBUG + SrcView.DbgValidateAsView(); +#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) +{ +#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 (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 + + D3D12_ROOT_PARAMETER d3d12RootParam{ParameterType, {}, Visibility}; + d3d12RootParam.Descriptor.ShaderRegister = Register; + d3d12RootParam.Descriptor.RegisterSpace = RegisterSpace; + RootParameter NewRootView{Group, RootIndex, d3d12RootParam}; + Extend(0, nullptr, 1, &NewRootView); + + return &m_pRootViews[m_NumRootViews - 1]; +} + +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"); +#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); + + return &m_pRootTables[m_NumRootTables - 1]; +} + +RootParameter* RootParamsManager::ExtendRootTable(Uint32 RootTableInd, Uint32 NumExtraRanges) +{ + VERIFY_EXPR(RootTableInd < m_NumRootTables); + Extend(0, nullptr, 0, nullptr, NumExtraRanges, RootTableInd); + return &m_pRootTables[RootTableInd - 1]; +} + +bool RootParamsManager::operator==(const RootParamsManager& RootParams) const +{ + if (m_NumRootTables != RootParams.m_NumRootTables || + m_NumRootViews != RootParams.m_NumRootViews) + return false; + + for (Uint32 rv = 0; rv < m_NumRootViews; ++rv) + { + 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; + } + + return true; +} + +} // namespace Diligent |
