summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineD3D12
diff options
context:
space:
mode:
authorassiduous <assiduous@diligentgraphics.com>2021-02-12 01:28:12 +0000
committerassiduous <assiduous@diligentgraphics.com>2021-03-19 00:31:35 +0000
commit6c23895eea702eb63a67deede8d3084c2da6ab7b (patch)
tree6258f58bfb44a58d1a88913f01d7f7e9e01d11ca /Graphics/GraphicsEngineD3D12
parentDXBCUtils: fixed compiler error (diff)
downloadDiligentCore-6c23895eea702eb63a67deede8d3084c2da6ab7b.tar.gz
DiligentCore-6c23895eea702eb63a67deede8d3084c2da6ab7b.zip
Refactored RootParamsManager
Diffstat (limited to 'Graphics/GraphicsEngineD3D12')
-rw-r--r--Graphics/GraphicsEngineD3D12/CMakeLists.txt2
-rw-r--r--Graphics/GraphicsEngineD3D12/include/D3D12Utils.h9
-rw-r--r--Graphics/GraphicsEngineD3D12/include/PipelineResourceSignatureD3D12Impl.hpp189
-rw-r--r--Graphics/GraphicsEngineD3D12/include/RootParamsManager.hpp191
-rw-r--r--Graphics/GraphicsEngineD3D12/src/D3D12Utils.cpp55
-rw-r--r--Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp430
-rw-r--r--Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp2
-rw-r--r--Graphics/GraphicsEngineD3D12/src/RootParamsManager.cpp320
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