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