summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineD3D12
diff options
context:
space:
mode:
authorassiduous <assiduous@diligentgraphics.com>2021-02-22 04:20:22 +0000
committerassiduous <assiduous@diligentgraphics.com>2021-03-19 00:38:09 +0000
commit98d5716a98acf9d12eb45d91eef1440614ef13ec (patch)
tree93cfc5a453eec6aa03fbede907e29136cdc8fc45 /Graphics/GraphicsEngineD3D12
parentPipelineResourceSignatureD3D12Impl: few minor updates (diff)
downloadDiligentCore-98d5716a98acf9d12eb45d91eef1440614ef13ec.tar.gz
DiligentCore-98d5716a98acf9d12eb45d91eef1440614ef13ec.zip
Reworked shader resource binding remapping in d3d12; updated PipelineStateD3D12Impl and RootSignatureD3D12
Diffstat (limited to 'Graphics/GraphicsEngineD3D12')
-rw-r--r--Graphics/GraphicsEngineD3D12/include/PipelineResourceSignatureD3D12Impl.hpp12
-rw-r--r--Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp33
-rw-r--r--Graphics/GraphicsEngineD3D12/include/RootSignature.hpp50
-rw-r--r--Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp10
-rw-r--r--Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp69
-rw-r--r--Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp302
-rw-r--r--Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp2
-rw-r--r--Graphics/GraphicsEngineD3D12/src/RootSignature.cpp137
8 files changed, 351 insertions, 264 deletions
diff --git a/Graphics/GraphicsEngineD3D12/include/PipelineResourceSignatureD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/PipelineResourceSignatureD3D12Impl.hpp
index d46ad3a5..094f5d20 100644
--- a/Graphics/GraphicsEngineD3D12/include/PipelineResourceSignatureD3D12Impl.hpp
+++ b/Graphics/GraphicsEngineD3D12/include/PipelineResourceSignatureD3D12Impl.hpp
@@ -36,6 +36,7 @@
#include "SRBMemoryAllocator.hpp"
#include "RootParamsManager.hpp"
#include "ShaderResourceCacheD3D12.hpp"
+#include "ResourceBindingMap.hpp"
namespace Diligent
{
@@ -48,8 +49,6 @@ class ShaderVariableManagerD3D12;
/// Implementation of the Diligent::PipelineResourceSignatureD3D12Impl class
class PipelineResourceSignatureD3D12Impl final : public PipelineResourceSignatureBase<IPipelineResourceSignature, RenderDeviceD3D12Impl>
{
- friend class RootSignatureD3D12;
-
public:
using TPipelineResourceSignatureBase = PipelineResourceSignatureBase<IPipelineResourceSignature, RenderDeviceD3D12Impl>;
@@ -282,6 +281,15 @@ public:
bool IsCompute,
bool CommitDynamicBuffers) const;
+ const RootParamsManager& GetRootParams() const { return m_RootParams; }
+
+ // Adds resources and immutable samplers from this signature to the
+ // resource binding map.
+ void UpdateShaderResourceBindingMap(ResourceBinding::TMap& ResourceMap, SHADER_TYPE ShaderStage, Uint32 BaseRegisterSpace) const;
+
+ // Returns true if there is an immutable sampler array in the given shader stage.
+ bool HasImmutableSamplerArray(SHADER_TYPE ShaderStage) const;
+
private:
using StaticResCacheTblSizesArrayType = std::array<Uint32, D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER + 1>;
void AllocateRootParameters(StaticResCacheTblSizesArrayType& StaticResCacheTblSizes);
diff --git a/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp
index d9707c22..57a97796 100644
--- a/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp
+++ b/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp
@@ -35,12 +35,12 @@
#include "PipelineStateBase.hpp"
#include "RootSignature.hpp"
#include "RenderDeviceD3D12Impl.hpp"
-#include "ShaderD3D12Impl.hpp"
namespace Diligent
{
-class FixedBlockMemoryAllocator;
+class ShaderD3D12Impl;
+class ShaderResourcesD3D12;
/// Pipeline state object implementation in Direct3D12 backend.
class PipelineStateD3D12Impl final : public PipelineStateBase<IPipelineStateD3D12, RenderDeviceD3D12Impl>
@@ -75,12 +75,12 @@ public:
const RootSignatureD3D12* GetRootSignature() const { return m_RootSig; }
- Uint32 GetSignatureCount() const { return m_SignatureCount; }
+ Uint32 GetSignatureCount() const { return m_RootSig->GetSignatureCount(); }
PipelineResourceSignatureD3D12Impl* GetSignature(Uint32 index) const
{
- VERIFY_EXPR(index < m_SignatureCount);
- return m_Signatures[index].RawPtr<PipelineResourceSignatureD3D12Impl>();
+ VERIFY_EXPR(index < GetSignatureCount());
+ return m_ResourceSignatures[index];
}
private:
@@ -107,10 +107,11 @@ private:
TShaderStages& ShaderStages,
LocalRootSignatureD3D12* pLocalRootSig);
- void CreateDefaultResourceSignature(const PipelineStateCreateInfo& CreateInfo,
- TShaderStages& ShaderStages,
- LocalRootSignatureD3D12* pLocalRootSig,
- IPipelineResourceSignature** ppImplicitSignature);
+ static RefCntAutoPtr<IPipelineResourceSignature> CreateDefaultResourceSignature(
+ RenderDeviceD3D12Impl* pDevice,
+ const PipelineStateCreateInfo& CreateInfo,
+ TShaderStages& ShaderStages,
+ LocalRootSignatureD3D12* pLocalRootSig);
void Destruct();
@@ -126,20 +127,22 @@ private:
};
ResourceInfo GetResourceInfo(const char* Name, SHADER_TYPE Stage) const;
+#ifdef DILIGENT_DEVELOPMENT
+ void DvpValidateShaderResources(const ShaderD3D12Impl* pShader, const LocalRootSignatureD3D12* pLocalRootSig) const;
+#endif
+
private:
CComPtr<ID3D12DeviceChild> m_pd3d12PSO;
RefCntAutoPtr<RootSignatureD3D12> m_RootSig;
- using SignatureArrayType = RootSignatureD3D12::SignatureArrayType;
-
- Uint8 m_SignatureCount = 0;
- SignatureArrayType m_Signatures = {};
+ // NB: Pipeline resource signatures used to create the PSO may NOT be the same as
+ // pipeline resource signatures in m_RootSig, because the latter may be used from the
+ // cache. While the two signatures may be compatible, they resource names may not be identical.
+ std::unique_ptr<RefCntAutoPtr<PipelineResourceSignatureD3D12Impl>[]> m_ResourceSignatures;
#ifdef DILIGENT_DEVELOPMENT
// Shader resources for all shaders in all shader stages
std::vector<std::shared_ptr<const ShaderResourcesD3D12>> m_ShaderResources;
- // Resource info for every resource in m_ShaderResources, in the same order
- //std::vector<PipelineLayoutVk::ResourceInfo> m_ResInfo;
#endif
};
diff --git a/Graphics/GraphicsEngineD3D12/include/RootSignature.hpp b/Graphics/GraphicsEngineD3D12/include/RootSignature.hpp
index 9bc47265..51295859 100644
--- a/Graphics/GraphicsEngineD3D12/include/RootSignature.hpp
+++ b/Graphics/GraphicsEngineD3D12/include/RootSignature.hpp
@@ -29,21 +29,23 @@
/// \file
/// Declaration of Diligent::RootSignatureD3D12 class
+
#include <array>
#include <mutex>
#include <unordered_map>
+#include <memory>
#include "D3D12TypeConversions.hpp"
#include "ShaderResourceCacheD3D12.hpp"
#include "PipelineResourceSignatureD3D12Impl.hpp"
#include "PrivateConstants.h"
#include "ShaderResources.hpp"
+#include "ResourceBindingMap.hpp"
namespace Diligent
{
class RenderDeviceD3D12Impl;
-class PipelineResourceSignatureD3D12Impl;
class RootSignatureCacheD3D12;
/// Implementation of the Diligent::RootSignature class
@@ -61,10 +63,10 @@ public:
Uint32 GetSignatureCount() const { return m_SignatureCount; }
- PipelineResourceSignatureD3D12Impl* GetSignature(Uint32 index) const
+ PipelineResourceSignatureD3D12Impl* GetResourceSignature(Uint32 index) const
{
VERIFY_EXPR(index < m_SignatureCount);
- return m_Signatures[index].RawPtr<PipelineResourceSignatureD3D12Impl>();
+ return m_ResourceSignatures[index].pSignature;
}
ID3D12RootSignature* GetD3D12RootSignature() const
@@ -73,16 +75,16 @@ public:
return m_pd3d12RootSignature;
}
- Uint32 GetFirstRootIndex(Uint32 BindingIndex) const
+ Uint32 GetBaseRootIndex(Uint32 BindingIndex) const
{
VERIFY_EXPR(BindingIndex < m_SignatureCount);
- return m_FirstRootIndex[BindingIndex];
+ return m_ResourceSignatures[BindingIndex].BaseRootIndex;
}
- Uint32 GetFirstRegisterSpace(Uint32 BindingIndex) const
+ Uint32 GetBaseRegisterSpace(Uint32 BindingIndex) const
{
VERIFY_EXPR(BindingIndex <= m_SignatureCount);
- return m_FirstRegisterSpace[BindingIndex];
+ return m_ResourceSignatures[BindingIndex].BaseRegisterSpace;
}
Uint32 GetTotalSpaces() const
@@ -90,23 +92,28 @@ public:
return m_TotalSpacesUsed;
}
- using SignatureArrayType = std::array<RefCntAutoPtr<PipelineResourceSignatureD3D12Impl>, MAX_RESOURCE_SIGNATURES>;
+ bool IsCompatibleWith(const RefCntAutoPtr<PipelineResourceSignatureD3D12Impl> ppSignatures[], Uint32 SignatureCount) const noexcept;
private:
- std::array<Uint16, MAX_RESOURCE_SIGNATURES> m_FirstRootIndex = {};
- std::array<Uint16, MAX_RESOURCE_SIGNATURES> m_FirstRegisterSpace = {};
+ // The number of pipeline resource signatures used to initialize this root signature.
+ const Uint32 m_SignatureCount;
- // The total number of register spaces used by this root signature
+ // The total number of register spaces used by this root signature.
Uint32 m_TotalSpacesUsed = 0;
- // The number of resource signatures used by this root signature
- // (Maximum is MAX_RESOURCE_SIGNATURES)
- const Uint8 m_SignatureCount;
+ // Root signature hash.
+ const size_t m_Hash;
- const size_t m_Hash;
CComPtr<ID3D12RootSignature> m_pd3d12RootSignature;
- SignatureArrayType m_Signatures = {};
+ struct ResourceSignatureInfo
+ {
+ RefCntAutoPtr<PipelineResourceSignatureD3D12Impl> pSignature;
+
+ Uint32 BaseRootIndex = 0;
+ Uint32 BaseRegisterSpace = 0;
+ };
+ std::unique_ptr<ResourceSignatureInfo[]> m_ResourceSignatures;
RootSignatureCacheD3D12& m_Cache;
};
@@ -118,13 +125,13 @@ class LocalRootSignatureD3D12
public:
LocalRootSignatureD3D12(const char* pCBName, Uint32 ShaderRecordSize);
- bool IsShaderRecord(const D3DShaderResourceAttribs& CB);
+ bool IsShaderRecord(const D3DShaderResourceAttribs& CB) const;
bool Create(ID3D12Device* pDevice, Uint32 RegisterSpace);
ID3D12RootSignature* GetD3D12RootSignature() const { return m_pd3d12RootSignature; }
- bool IsDefined() const { return m_ShaderRecordSize > 0 && m_pName != nullptr; }
- const char* GetName() const { return m_pName; }
+ bool IsDefined() const { return m_ShaderRecordSize > 0 && !m_Name.empty(); }
+ const char* GetName() const { return m_Name.c_str(); }
Uint32 GetShaderRegister() const { return 0; }
Uint32 GetRegisterSpace() const
@@ -134,7 +141,7 @@ public:
}
private:
- const char* m_pName = nullptr;
+ const std::string m_Name;
const Uint32 m_ShaderRecordSize = 0;
Uint32 m_RegisterSpace = ~0u;
CComPtr<ID3D12RootSignature> m_pd3d12RootSignature;
@@ -163,8 +170,7 @@ public:
private:
RenderDeviceD3D12Impl& m_DeviceD3D12Impl;
- std::mutex m_RootSigCacheGuard;
-
+ std::mutex m_RootSigCacheMtx;
std::unordered_multimap<size_t, RefCntWeakPtr<RootSignatureD3D12>> m_RootSigCache;
};
diff --git a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp
index d5af4ce0..2fba7309 100644
--- a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp
@@ -310,21 +310,21 @@ void DeviceContextD3D12Impl::CommitRootTables(RootTableInfo& RootInfo)
RootInfo.bRootTablesCommited = true;
for (Uint32 s = 0; s < RootSig.GetSignatureCount(); ++s)
{
- auto* pSignature = RootSig.GetSignature(s);
+ auto* pSignature = RootSig.GetResourceSignature(s);
auto* pSRB = RootInfo.SRBs[s];
if (pSignature == nullptr || pSignature->GetTotalResourceCount() == 0)
continue;
VERIFY_EXPR(pSRB != nullptr);
- pSignature->CommitRootTables(pSRB->GetResourceCache(), CmdCtx, this, GetContextId(), IsCompute, RootSig.GetFirstRootIndex(s));
+ pSignature->CommitRootTables(pSRB->GetResourceCache(), CmdCtx, this, GetContextId(), IsCompute, RootSig.GetBaseRootIndex(s));
}
}
RootInfo.bRootViewsCommitted = true;
for (Uint32 s = 0; s < RootSig.GetSignatureCount(); ++s)
{
- auto* pSignature = RootSig.GetSignature(s);
+ auto* pSignature = RootSig.GetResourceSignature(s);
auto* pSRB = RootInfo.SRBs[s];
if (pSignature == nullptr || pSignature->GetNumRootViews() == 0)
@@ -332,7 +332,7 @@ void DeviceContextD3D12Impl::CommitRootTables(RootTableInfo& RootInfo)
VERIFY_EXPR(pSRB != nullptr);
constexpr auto CommitDynamicBuffers = true;
- pSignature->CommitRootViews(pSRB->GetResourceCache(), CmdCtx, this, GetContextId(), RootSig.GetFirstRootIndex(s), IsCompute, CommitDynamicBuffers);
+ pSignature->CommitRootViews(pSRB->GetResourceCache(), CmdCtx, this, GetContextId(), RootSig.GetBaseRootIndex(s), IsCompute, CommitDynamicBuffers);
}
}
@@ -410,7 +410,7 @@ void DeviceContextD3D12Impl::DvpValidateCommittedShaderResources()
for (Uint32 i = 0; i < SignCount; ++i)
{
- auto* pSignature = RootSig.GetSignature(i);
+ auto* pSignature = RootSig.GetResourceSignature(i);
if (pSignature == nullptr)
continue;
diff --git a/Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp
index 32162668..3fc80df0 100644
--- a/Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp
@@ -754,6 +754,75 @@ void PipelineResourceSignatureD3D12Impl::CommitRootTables(ShaderResourceCacheD3D
}
+void PipelineResourceSignatureD3D12Impl::UpdateShaderResourceBindingMap(ResourceBinding::TMap& ResourceMap, SHADER_TYPE ShaderStage, Uint32 BaseRegisterSpace) const
+{
+ VERIFY(ShaderStage != SHADER_TYPE_UNKNOWN && IsPowerOfTwo(ShaderStage), "Only single shader stage must be provided.");
+
+ for (Uint32 r = 0, ResCount = GetTotalResourceCount(); r < ResCount; ++r)
+ {
+ const auto& ResDesc = GetResourceDesc(r);
+ const auto& Attribs = GetResourceAttribs(r);
+
+ if ((ResDesc.ShaderStages & ShaderStage) != 0)
+ {
+ ResourceBinding::BindInfo BindInfo //
+ {
+ Attribs.Register,
+ Attribs.Space + BaseRegisterSpace,
+ ResDesc.ArraySize //
+ };
+ auto IsUnique = ResourceMap.emplace(HashMapStringKey{ResDesc.Name}, BindInfo).second;
+ VERIFY(IsUnique, "Shader resource '", ResDesc.Name,
+ "' already present in the binding map. Every shader resource in PSO must be unambiguously defined by "
+ "only one resource signature. This error should've been caught by ValidatePipelineResourceSignatures().");
+ }
+ }
+
+ for (Uint32 samp = 0, SampCount = GetImmutableSamplerCount(); samp < SampCount; ++samp)
+ {
+ const auto& ImtblSam = GetImmutableSamplerDesc(samp);
+ const auto& SampAttr = GetImmutableSamplerAttribs(samp);
+
+ if ((ImtblSam.ShaderStages & ShaderStage) != 0)
+ {
+ String SampName{ImtblSam.SamplerOrTextureName};
+ if (IsUsingCombinedSamplers())
+ SampName += GetCombinedSamplerSuffix();
+
+ ResourceBinding::BindInfo BindInfo //
+ {
+ SampAttr.ShaderRegister,
+ SampAttr.RegisterSpace + BaseRegisterSpace,
+ SampAttr.ArraySize //
+ };
+
+ auto it_inserted = ResourceMap.emplace(HashMapStringKey{SampName}, BindInfo);
+#ifdef DILIGENT_DEBUG
+ if (!it_inserted.second)
+ {
+ const auto& ExistingBindInfo = it_inserted.first->second;
+ VERIFY(ExistingBindInfo.BindPoint == BindInfo.BindPoint,
+ "Bind point defined by the immutable sampler attribs is inconsistent with the bind point defined by the sampler resource.");
+ VERIFY(ExistingBindInfo.Space == BindInfo.Space,
+ "Register space defined by the immutable sampler attribs is inconsistent with the bind point defined by the sampler resource.");
+ }
+#endif
+ }
+ }
+}
+
+bool PipelineResourceSignatureD3D12Impl::HasImmutableSamplerArray(SHADER_TYPE ShaderStage) const
+{
+ for (Uint32 s = 0; s < GetImmutableSamplerCount(); ++s)
+ {
+ const auto& ImtblSam = GetImmutableSamplerDesc(s);
+ const auto& SampAttr = GetImmutableSamplerAttribs(s);
+ if ((ImtblSam.ShaderStages & ShaderStage) != 0 && SampAttr.ArraySize > 1)
+ return true;
+ }
+ return false;
+}
+
namespace
{
diff --git a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp
index 642a9f98..5a0ed88c 100644
--- a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp
@@ -35,11 +35,9 @@
#include "D3D12TypeConversions.hpp"
#include "RenderDeviceD3D12Impl.hpp"
#include "DXGITypeConversions.hpp"
-#include "ShaderResourceBindingD3D12Impl.hpp"
#include "CommandContext.hpp"
#include "EngineMemory.h"
#include "StringTools.hpp"
-#include "ShaderVariableD3D12.hpp"
#include "DynamicLinearAllocator.hpp"
#include "DXBCUtils.hpp"
#include "DXCompiler.hpp"
@@ -47,6 +45,7 @@
namespace Diligent
{
+
namespace
{
#ifdef _MSC_VER
@@ -119,7 +118,6 @@ void BuildRTPipelineDescription(const RayTracingPipelineStateCreateInfo& CreateI
std::array<typename TShaderStages::value_type*, MAX_SHADERS_IN_PIPELINE> StagesPtr = {};
std::array<Uint32, MAX_SHADERS_IN_PIPELINE> ShaderIndices = {};
- // prepare
for (auto& Stage : ShaderStages)
{
const auto Idx = GetShaderTypePipelineIndex(Stage.Type, PIPELINE_TYPE_RAY_TRACING);
@@ -292,7 +290,7 @@ void GetShaderResourceTypeAndFlags(const D3DShaderResourceAttribs& Attribs,
{
OutFlags = PIPELINE_RESOURCE_FLAG_UNKNOWN;
- switch (static_cast<Uint32>(Attribs.GetInputType()))
+ switch (int{Attribs.GetInputType()})
{
case D3D_SIT_CBUFFER:
OutType = SHADER_RESOURCE_TYPE_CONSTANT_BUFFER;
@@ -361,6 +359,7 @@ void VerifyResourceMerge(const D3DShaderResourceAttribs& ExistingRes,
"' exists in multiple shaders from the same shader stage, but its array size is not consistent between "
"shaders. All variables with the same name from the same shader stage must have the same array size.");
}
+
} // namespace
@@ -401,36 +400,39 @@ size_t PipelineStateD3D12Impl::ShaderStageInfo::Count() const
}
-void PipelineStateD3D12Impl::CreateDefaultResourceSignature(const PipelineStateCreateInfo& CreateInfo,
- TShaderStages& ShaderStages,
- LocalRootSignatureD3D12* pLocalRootSig,
- IPipelineResourceSignature** ppImplicitSignature)
+RefCntAutoPtr<IPipelineResourceSignature> PipelineStateD3D12Impl::CreateDefaultResourceSignature(
+ RenderDeviceD3D12Impl* pDevice,
+ const PipelineStateCreateInfo& CreateInfo,
+ TShaderStages& ShaderStages,
+ LocalRootSignatureD3D12* pLocalRootSig)
{
+ const auto& LayoutDesc = CreateInfo.PSODesc.ResourceLayout;
+
struct UniqueResource
{
- D3DShaderResourceAttribs const* Attribs = nullptr;
- Uint32 DescIndex = ~0u;
+ const D3DShaderResourceAttribs& Attribs;
+
+ // Resource index
+ const Uint32 DescIndex;
};
- using ResourceNameToIndex_t = std::unordered_map<HashMapStringKey, UniqueResource, HashMapStringKey::Hasher>;
+ std::unordered_map<HashMapStringKey, UniqueResource, HashMapStringKey::Hasher> UniqueNames;
std::vector<PipelineResourceDesc> Resources;
- ResourceNameToIndex_t UniqueNames;
const char* pCombinedSamplerSuffix = nullptr;
- const auto& LayoutDesc = CreateInfo.PSODesc.ResourceLayout;
for (auto& Stage : ShaderStages)
{
UniqueNames.clear();
for (auto* pShader : Stage.Shaders)
{
- const auto DefaultVarType = LayoutDesc.DefaultVariableType;
- auto& ShaderResources = *pShader->GetShaderResources();
- const auto HandleResource = [&](const D3DShaderResourceAttribs& Res, Uint32) //
+ const auto& ShaderResources = *pShader->GetShaderResources();
+
+ const auto HandleResource = [&](const D3DShaderResourceAttribs& Res, Uint32) //
{
if (pLocalRootSig != nullptr && pLocalRootSig->IsShaderRecord(Res))
return;
- auto IterAndAssigned = UniqueNames.emplace(HashMapStringKey{Res.Name}, UniqueResource{&Res, static_cast<Uint32>(Resources.size())});
+ auto IterAndAssigned = UniqueNames.emplace(HashMapStringKey{Res.Name}, UniqueResource{Res, static_cast<Uint32>(Resources.size())});
if (IterAndAssigned.second)
{
SHADER_RESOURCE_TYPE Type;
@@ -439,15 +441,15 @@ void PipelineStateD3D12Impl::CreateDefaultResourceSignature(const PipelineStateC
if (Res.BindCount == 0)
{
- LOG_ERROR_AND_THROW("Is shader '", pShader->GetDesc().Name, "' resource '", Res.Name, "' uses runtime sized array, ",
- "you must explicitlly set resource signature to specify array size");
+ LOG_ERROR_AND_THROW("Resource '", Res.Name, "' in shader '", pShader->GetDesc().Name, "' is a runtime-sized array. ",
+ "Use explicit resource signature to specify the array size.");
}
- Resources.emplace_back(Stage.Type, Res.Name, Res.BindCount, Type, DefaultVarType, Flags);
+ Resources.emplace_back(Stage.Type, Res.Name, Res.BindCount, Type, LayoutDesc.DefaultVariableType, Flags);
}
else
{
- VerifyResourceMerge(*IterAndAssigned.first->second.Attribs, Res);
+ VerifyResourceMerge(IterAndAssigned.first->second.Attribs, Res);
}
};
@@ -481,8 +483,8 @@ void PipelineStateD3D12Impl::CreateDefaultResourceSignature(const PipelineStateC
// apply new variable type to sampler too
if (ShaderResources.IsUsingCombinedTextureSamplers() && Res.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_SRV)
{
- String SampName = String{Var.Name} + ShaderResources.GetCombinedSamplerSuffix();
- auto SampIter = UniqueNames.find(HashMapStringKey{SampName.c_str()});
+ auto SampName = String{Var.Name} + ShaderResources.GetCombinedSamplerSuffix();
+ auto SampIter = UniqueNames.find(HashMapStringKey{SampName.c_str()});
if (SampIter != UniqueNames.end())
Resources[SampIter->second.DescIndex].VarType = Var.Type;
}
@@ -492,6 +494,7 @@ void PipelineStateD3D12Impl::CreateDefaultResourceSignature(const PipelineStateC
}
}
+ RefCntAutoPtr<IPipelineResourceSignature> pImplicitSignature;
if (Resources.size())
{
PipelineResourceSignatureDesc ResSignDesc;
@@ -504,11 +507,13 @@ void PipelineStateD3D12Impl::CreateDefaultResourceSignature(const PipelineStateC
ResSignDesc.UseCombinedTextureSamplers = pCombinedSamplerSuffix != nullptr;
ResSignDesc.CombinedSamplerSuffix = pCombinedSamplerSuffix;
- GetDevice()->CreatePipelineResourceSignature(ResSignDesc, ppImplicitSignature, true);
+ pDevice->CreatePipelineResourceSignature(ResSignDesc, &pImplicitSignature, true);
- if (*ppImplicitSignature == nullptr)
+ if (!pImplicitSignature)
LOG_ERROR_AND_THROW("Failed to create resource signature for pipeline state");
}
+
+ return pImplicitSignature;
}
PipelineStateD3D12Impl::ResourceInfo PipelineStateD3D12Impl::GetResourceInfo(const char* Name, SHADER_TYPE Stage) const
@@ -539,39 +544,43 @@ void PipelineStateD3D12Impl::InitRootSignature(const PipelineStateCreateInfo& Cr
TShaderStages& ShaderStages,
LocalRootSignatureD3D12* pLocalRootSig)
{
- const Uint32 SignatureCount = CreateInfo.ResourceSignaturesCount;
- RefCntAutoPtr<IPipelineResourceSignature> pImplicitSignature;
-
- if (SignatureCount == 0 || CreateInfo.ppResourceSignatures == nullptr)
+ Uint32 SignatureCount = 0;
+ if (CreateInfo.ResourceSignaturesCount == 0 || CreateInfo.ppResourceSignatures == nullptr)
{
- CreateDefaultResourceSignature(CreateInfo, ShaderStages, pLocalRootSig, &pImplicitSignature);
-
- if (pImplicitSignature != nullptr)
+ auto pImplicitSignature = CreateDefaultResourceSignature(GetDevice(), CreateInfo, ShaderStages, pLocalRootSig);
+ if (pImplicitSignature)
{
VERIFY_EXPR(pImplicitSignature->GetDesc().BindingIndex == 0);
- m_Signatures[0] = ValidatedCast<PipelineResourceSignatureD3D12Impl>(pImplicitSignature.RawPtr());
- m_SignatureCount = 1;
+ SignatureCount = 1;
+ m_ResourceSignatures.reset(new RefCntAutoPtr<PipelineResourceSignatureD3D12Impl>[SignatureCount]);
+ m_ResourceSignatures[0] = pImplicitSignature.RawPtr<PipelineResourceSignatureD3D12Impl>();
}
}
else
{
+ Uint32 MaxSignatureBindingIndex = 0;
+ for (Uint32 i = 0; i < CreateInfo.ResourceSignaturesCount; ++i)
+ {
+ auto* pSignature = ValidatedCast<PipelineResourceSignatureD3D12Impl>(CreateInfo.ppResourceSignatures[i]);
+ VERIFY(pSignature != nullptr, "Pipeline resource signature at index ", i, " is null. This error should've been caught by ValidatePipelineResourceSignatures.");
+ MaxSignatureBindingIndex = std::max(MaxSignatureBindingIndex, Uint32{pSignature->GetDesc().BindingIndex});
+ }
+ SignatureCount = MaxSignatureBindingIndex + 1;
+ m_ResourceSignatures.reset(new RefCntAutoPtr<PipelineResourceSignatureD3D12Impl>[SignatureCount]);
+
// TODO: move to base class
const auto PipelineType = CreateInfo.PSODesc.PipelineType;
- for (Uint32 i = 0; i < SignatureCount; ++i)
+ for (Uint32 i = 0; i < CreateInfo.ResourceSignaturesCount; ++i)
{
auto* pSignature = ValidatedCast<PipelineResourceSignatureD3D12Impl>(CreateInfo.ppResourceSignatures[i]);
VERIFY(pSignature != nullptr, "Pipeline resource signature at index ", i, " is null. This error should've been caught by ValidatePipelineResourceSignatures.");
- const Uint8 Index = pSignature->GetDesc().BindingIndex;
+ const auto Index = pSignature->GetDesc().BindingIndex;
#ifdef DILIGENT_DEBUG
- VERIFY(Index < m_Signatures.size(),
- "Pipeline resource signature specifies binding index ", Uint32{Index}, " that exceeds the limit (", m_Signatures.size() - 1,
- "). This error should've been caught by ValidatePipelineResourceSignatureDesc.");
-
- VERIFY(m_Signatures[Index] == nullptr,
+ VERIFY(m_ResourceSignatures[Index] == nullptr,
"Pipeline resource signature '", pSignature->GetDesc().Name, "' at index ", Uint32{Index},
- " conflicts with another resource signature '", m_Signatures[Index]->GetDesc().Name,
+ " conflicts with another resource signature '", m_ResourceSignatures[Index]->GetDesc().Name,
"' that uses the same index. This error should've been caught by ValidatePipelineResourceSignatures.");
for (Uint32 s = 0, StageCount = pSignature->GetNumActiveShaderStages(); s < StageCount; ++s)
@@ -584,12 +593,11 @@ void PipelineStateD3D12Impl::InitRootSignature(const PipelineStateCreateInfo& Cr
}
#endif
- m_SignatureCount = std::max<Uint8>(m_SignatureCount, Index + 1);
- m_Signatures[Index] = pSignature;
+ m_ResourceSignatures[Index] = pSignature;
}
}
- m_RootSig = GetDevice()->GetRootSignatureCache().GetRootSig(m_Signatures.data(), m_SignatureCount);
+ m_RootSig = GetDevice()->GetRootSignatureCache().GetRootSig(m_ResourceSignatures.get(), SignatureCount);
if (!m_RootSig)
LOG_ERROR_AND_THROW("Failed to create root signature");
@@ -605,79 +613,44 @@ void PipelineStateD3D12Impl::InitRootSignature(const PipelineStateCreateInfo& Cr
for (size_t s = 0; s < ShaderStages.size(); ++s)
{
- const auto& Shaders = ShaderStages[s].Shaders;
- auto& ByteCodes = ShaderStages[s].ByteCodes;
- const auto ShaderType = ShaderStages[s].Type;
- bool HasImtblSampArray = false;
+ const auto& Shaders = ShaderStages[s].Shaders;
+ auto& ByteCodes = ShaderStages[s].ByteCodes;
+ const auto ShaderType = ShaderStages[s].Type;
+ bool HasImtblSamArray = false;
ResourceBinding::TMap ResourceMap;
- for (Uint32 Sig = 0, SigCount = GetSignatureCount(); Sig < SigCount; ++Sig)
+ // Note that we must use signatures from m_ResourceSignatures for resource binding map,
+ // because signatures from m_RootSig may have resources with different names.
+ for (Uint32 sign = 0; sign < SignatureCount; ++sign)
{
- auto* pSignature = GetSignature(Sig);
- if (pSignature != nullptr)
- {
- const Uint32 FirstSpace = m_RootSig->GetFirstRegisterSpace(Sig);
+ const PipelineResourceSignatureD3D12Impl* const pSignature = m_ResourceSignatures[sign];
+ if (pSignature == nullptr)
+ continue;
- for (Uint32 r = 0, ResCount = pSignature->GetTotalResourceCount(); r < ResCount; ++r)
- {
- const auto& ResDesc = pSignature->GetResourceDesc(r);
- const auto& Attribs = pSignature->GetResourceAttribs(r);
-
- if (ResDesc.ShaderStages & ShaderType)
- {
- auto IsUnique = ResourceMap.emplace(HashMapStringKey{ResDesc.Name}, ResourceBinding::BindInfo{Attribs.Register, Attribs.Space + FirstSpace, ResDesc.ArraySize}).second;
- VERIFY(IsUnique, "resource name must be unique");
- }
- }
+ VERIFY_EXPR(pSignature->GetDesc().BindingIndex == sign);
+ pSignature->UpdateShaderResourceBindingMap(ResourceMap, ShaderType, m_RootSig->GetBaseRegisterSpace(sign));
- for (Uint32 samp = 0, SampCount = pSignature->GetImmutableSamplerCount(); samp < SampCount; ++samp)
- {
- const auto& ImtblSam = pSignature->GetImmutableSamplerDesc(samp);
- const auto& SampAttr = pSignature->GetImmutableSamplerAttribs(samp);
- ResourceBinding::BindInfo BindInfo{SampAttr.ShaderRegister, SampAttr.RegisterSpace + FirstSpace, SampAttr.ArraySize};
-
- if (ImtblSam.ShaderStages & ShaderType)
- {
- HasImtblSampArray = HasImtblSampArray || (SampAttr.ArraySize > 1);
-
- String SampName{ImtblSam.SamplerOrTextureName};
- if (pSignature->IsUsingCombinedSamplers())
- SampName += pSignature->GetCombinedSamplerSuffix();
-
- auto it_inserted = ResourceMap.emplace(HashMapStringKey{SampName}, BindInfo);
-#ifdef DILIGENT_DEBUG
- if (!it_inserted.second)
- {
- const auto& ExistingBindInfo = it_inserted.first->second;
- VERIFY(ExistingBindInfo.BindPoint == BindInfo.BindPoint,
- "Bind point defined by the immutable sampler attribs is inconsistent with the bind point defined by the sampler resource.");
- VERIFY(ExistingBindInfo.Space == BindInfo.Space,
- "Register space defined by the immutable sampler attribs is inconsistent with the bind point defined by the sampler resource.");
- }
-#endif
- }
- }
- }
+ if (pSignature->HasImmutableSamplerArray(ShaderType))
+ HasImtblSamArray = true;
}
if (pLocalRootSig != nullptr && pLocalRootSig->IsDefined())
{
bool IsUnique = ResourceMap.emplace(HashMapStringKey{pLocalRootSig->GetName()}, ResourceBinding::BindInfo{pLocalRootSig->GetShaderRegister(), pLocalRootSig->GetRegisterSpace(), 1}).second;
if (!IsUnique)
- LOG_ERROR_AND_THROW("Shader record constant buffer is already exist in resource signature");
+ LOG_ERROR_AND_THROW("Shader record constant buffer already exists in the resource signature");
}
for (size_t i = 0; i < Shaders.size(); ++i)
{
- auto* pShader = Shaders[i];
+ const auto* const pShader = Shaders[i];
auto& pBytecode = ByteCodes[i];
- CComPtr<ID3DBlob> pBlob;
- Uint32 VerMajor, VerMinor;
+ Uint32 VerMajor, VerMinor;
pShader->GetShaderResources()->GetShaderModel(VerMajor, VerMinor);
const bool IsSM51orAbove = ((VerMajor == 5 && VerMinor >= 1) || VerMajor >= 6);
- if (HasImtblSampArray && IsSM51orAbove)
+ if (HasImtblSamArray && IsSM51orAbove)
{
LOG_ERROR_AND_THROW("One of resource signatures uses immutable sampler array that is not allowed in shader model 5.1 and above.");
}
@@ -689,6 +662,7 @@ void PipelineStateD3D12Impl::InitRootSignature(const PipelineStateCreateInfo& Cr
"Compile the shader using SM5.1+ or change the resource layout to use only one space.");
}
+ CComPtr<ID3DBlob> pBlob;
if (IsDXILBytecode(pBytecode->GetBufferPointer(), pBytecode->GetBufferSize()))
{
if (!compiler)
@@ -708,76 +682,85 @@ void PipelineStateD3D12Impl::InitRootSignature(const PipelineStateCreateInfo& Cr
pBytecode = pBlob;
#ifdef DILIGENT_DEVELOPMENT
- const auto& pShaderResources = pShader->GetShaderResources();
- m_ShaderResources.emplace_back(pShaderResources);
+ m_ShaderResources.emplace_back(pShader->GetShaderResources());
+ DvpValidateShaderResources(pShader, pLocalRootSig);
+#endif
+ }
+ }
+}
- // Check compatibility between shader resources and resource signature.
- const auto HandleResource = [&](const D3DShaderResourceAttribs& Attribs, Uint32) //
- {
- if (pLocalRootSig != nullptr && pLocalRootSig->IsShaderRecord(Attribs))
- return;
+#ifdef DILIGENT_DEVELOPMENT
+void PipelineStateD3D12Impl::DvpValidateShaderResources(const ShaderD3D12Impl* pShader, const LocalRootSignatureD3D12* pLocalRootSig) const
+{
+ const auto& pShaderResources = pShader->GetShaderResources();
+ const auto ShaderType = pShader->GetDesc().ShaderType;
- if (Attribs.GetInputType() == D3D_SIT_SAMPLER)
- return;
+ // Check compatibility between shader resources and resource signature.
+ const auto HandleResource = [&](const D3DShaderResourceAttribs& Attribs, Uint32) //
+ {
+ if (pLocalRootSig != nullptr && pLocalRootSig->IsShaderRecord(Attribs))
+ return;
- auto Info = GetResourceInfo(Attribs.Name, ShaderType);
- if (!Info)
- {
- LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource with name '", Attribs.Name,
- "' that is not present in any pipeline resource signature that is used to create pipeline state '",
- m_Desc.Name, "'.");
- }
+ if (Attribs.GetInputType() == D3D_SIT_SAMPLER)
+ return;
- SHADER_RESOURCE_TYPE Type;
- PIPELINE_RESOURCE_FLAGS Flags;
- GetShaderResourceTypeAndFlags(Attribs, Type, Flags);
- if (Type != Info.ResDesc->ResourceType)
- {
- LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource with name '", Attribs.Name,
- "' and type '", GetShaderResourceTypeLiteralName(Type), "' that is not compatible with type '",
- GetShaderResourceTypeLiteralName(Info.ResDesc->ResourceType), "' in pipeline resource signature '", Info.Signature->GetDesc().Name, "'.");
- }
+ auto Info = GetResourceInfo(Attribs.Name, ShaderType);
+ if (!Info)
+ {
+ LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource with name '", Attribs.Name,
+ "' that is not present in any pipeline resource signature used to create pipeline state '",
+ m_Desc.Name, "'.");
+ }
- if ((Flags & PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER) != (Info.ResDesc->Flags & PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER))
- {
- LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource '", Attribs.Name,
- "' that is", ((Flags & PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER) ? "" : " not"),
- " labeled as formatted buffer, while the same resource specified by the pipeline resource signature '",
- Info.Signature->GetDesc().Name, "' is", ((Info.ResDesc->Flags & PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER) ? "" : " not"),
- " labeled as such.");
- }
+ SHADER_RESOURCE_TYPE Type;
+ PIPELINE_RESOURCE_FLAGS Flags;
+ GetShaderResourceTypeAndFlags(Attribs, Type, Flags);
+ if (Type != Info.ResDesc->ResourceType)
+ {
+ LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource with name '", Attribs.Name,
+ "' and type '", GetShaderResourceTypeLiteralName(Type), "' that is not compatible with type '",
+ GetShaderResourceTypeLiteralName(Info.ResDesc->ResourceType), "' in pipeline resource signature '", Info.Signature->GetDesc().Name, "'.");
+ }
- if (Attribs.BindCount == 0)
- {
- if ((Info.ResDesc->Flags & PIPELINE_RESOURCE_FLAG_RUNTIME_ARRAY) != 0)
- {
- LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource with name '", Attribs.Name,
- "' that is runtime-sized array, but in resource signature '", Info.Signature->GetDesc().Name,
- "' resource defined without PIPELINE_RESOURCE_FLAG_RUNTIME_ARRAY flag.");
- }
- }
- else
- {
- if (Info.ResDesc->ArraySize < Attribs.BindCount)
- {
- LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource '", Attribs.Name,
- "' whose array size (", Attribs.BindCount, ") is greater than the array size (",
- Info.ResDesc->ArraySize, ") specified by the pipeline resource signature '", Info.Signature->GetDesc().Name, "'.");
- }
+ if ((Flags & PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER) != (Info.ResDesc->Flags & PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER))
+ {
+ LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource '", Attribs.Name,
+ "' that is", ((Flags & PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER) ? "" : " not"),
+ " labeled as formatted buffer, while the same resource specified by the pipeline resource signature '",
+ Info.Signature->GetDesc().Name, "' is", ((Info.ResDesc->Flags & PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER) ? "" : " not"),
+ " labeled as such.");
+ }
- if (Info.ResDesc->Flags & PIPELINE_RESOURCE_FLAG_RUNTIME_ARRAY)
- {
- LOG_WARNING_MESSAGE("Shader '", pShader->GetDesc().Name, "' contains resource with name '", Attribs.Name,
- "' that defined in resource signature '", Info.Signature->GetDesc().Name,
- "' with flag PIPELINE_RESOURCE_FLAG_RUNTIME_ARRAY, but resource is not a runtime-sized array.");
- }
- }
- };
- pShaderResources->ProcessResources(HandleResource, HandleResource, HandleResource, HandleResource, HandleResource, HandleResource, HandleResource);
-#endif
+ if (Attribs.BindCount == 0)
+ {
+ if ((Info.ResDesc->Flags & PIPELINE_RESOURCE_FLAG_RUNTIME_ARRAY) != 0)
+ {
+ LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource with name '", Attribs.Name,
+ "' that is runtime-sized array, but in resource signature '", Info.Signature->GetDesc().Name,
+ "' resource defined without PIPELINE_RESOURCE_FLAG_RUNTIME_ARRAY flag.");
+ }
}
- }
+ else
+ {
+ if (Info.ResDesc->ArraySize < Attribs.BindCount)
+ {
+ LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource '", Attribs.Name,
+ "' whose array size (", Attribs.BindCount, ") is greater than the array size (",
+ Info.ResDesc->ArraySize, ") specified by the pipeline resource signature '", Info.Signature->GetDesc().Name, "'.");
+ }
+
+ if (Info.ResDesc->Flags & PIPELINE_RESOURCE_FLAG_RUNTIME_ARRAY)
+ {
+ LOG_WARNING_MESSAGE("Shader '", pShader->GetDesc().Name, "' contains resource with name '", Attribs.Name,
+ "' that defined in resource signature '", Info.Signature->GetDesc().Name,
+ "' with flag PIPELINE_RESOURCE_FLAG_RUNTIME_ARRAY, but resource is not a runtime-sized array.");
+ }
+ }
+ };
+ pShaderResources->ProcessResources(HandleResource, HandleResource, HandleResource, HandleResource, HandleResource, HandleResource, HandleResource);
}
+#endif
+
template <typename PSOCreateInfoType>
void PipelineStateD3D12Impl::InitInternalObjects(const PSOCreateInfoType& CreateInfo,
@@ -1100,7 +1083,6 @@ PipelineStateD3D12Impl::~PipelineStateD3D12Impl()
void PipelineStateD3D12Impl::Destruct()
{
- m_Signatures.fill({});
m_RootSig.Release();
if (m_pd3d12PSO)
diff --git a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp
index e5a4a2af..03786c50 100644
--- a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp
@@ -854,7 +854,7 @@ DescriptorHeapAllocation RenderDeviceD3D12Impl::AllocateGPUDescriptors(D3D12_DES
void RenderDeviceD3D12Impl::CreateRootSignature(const RefCntAutoPtr<PipelineResourceSignatureD3D12Impl>* ppSignatures, Uint32 SignatureCount, size_t Hash, RootSignatureD3D12** ppRootSig)
{
- RootSignatureD3D12* pRootSigD3D12(NEW_RC_OBJ(m_RootSignatureAllocator, "RootSignatureD3D12 instance", RootSignatureD3D12)(this, ppSignatures, SignatureCount, Hash));
+ RootSignatureD3D12* pRootSigD3D12{NEW_RC_OBJ(m_RootSignatureAllocator, "RootSignatureD3D12 instance", RootSignatureD3D12)(this, ppSignatures, SignatureCount, Hash)};
pRootSigD3D12->AddRef();
*ppRootSig = pRootSigD3D12;
}
diff --git a/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp b/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp
index 1f51f4cf..1cd3400c 100644
--- a/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp
@@ -30,8 +30,6 @@
#include "RootSignature.hpp"
#include "CommandContext.hpp"
#include "RenderDeviceD3D12Impl.hpp"
-#include "TextureD3D12Impl.hpp"
-#include "TopLevelASD3D12Impl.hpp"
#include "D3D12TypeConversions.hpp"
#include "HashUtils.hpp"
@@ -44,37 +42,41 @@ RootSignatureD3D12::RootSignatureD3D12(IReferenceCounters*
Uint32 SignatureCount,
size_t Hash) :
ObjectBase<IObject>{pRefCounters},
- m_SignatureCount{static_cast<Uint8>(SignatureCount)},
+ m_SignatureCount{SignatureCount},
m_Hash{Hash},
m_Cache{pDeviceD3D12Impl->GetRootSignatureCache()}
{
- VERIFY(m_SignatureCount == SignatureCount, "Signature count (", SignatureCount, ") exceeds maximum representable value");
+ if (m_SignatureCount > 0)
+ {
+ m_ResourceSignatures.reset(new ResourceSignatureInfo[m_SignatureCount]);
+ }
for (Uint32 i = 0; i < SignatureCount; ++i)
{
- m_Signatures[i] = ppSignatures[i];
-
+ m_ResourceSignatures[i].pSignature = ppSignatures[i];
if (ppSignatures[i] != nullptr)
{
VERIFY(ppSignatures[i]->GetDesc().BindingIndex == i, "Signature placed to another binding index");
}
}
- D3D12_ROOT_SIGNATURE_DESC rootSignatureDesc = {};
- rootSignatureDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
-
- Uint32 TotalParams = 0;
- Uint32 Totald3d12StaticSamplers = 0;
- Uint32 TotalDescriptorRanges = 0;
+ // The total number of root parameters in all resource signatures.
+ Uint32 TotalParams = 0;
+ // The total number of static samplers, accounting for array size, in all resource signatures.
+ Uint32 TotalImmutableSamplers = 0;
+ // The total number of descriptor ranges in all descriptor tables from all resource signatures.
+ Uint32 TotalDescriptorRanges = 0;
for (Uint32 s = 0; s < m_SignatureCount; ++s)
{
- auto& pSignature = m_Signatures[s];
+ auto& SignInfo = m_ResourceSignatures[s];
+
+ const PipelineResourceSignatureD3D12Impl* const pSignature = SignInfo.pSignature;
if (pSignature == nullptr)
continue;
- auto& RootParams = pSignature->m_RootParams;
+ const auto& RootParams = pSignature->GetRootParams();
- m_FirstRootIndex[s] = static_cast<Uint16>(TotalParams);
+ SignInfo.BaseRootIndex = TotalParams;
TotalParams += RootParams.GetNumRootTables() + RootParams.GetNumRootViews();
for (Uint32 rt = 0; rt < RootParams.GetNumRootTables(); ++rt)
@@ -88,41 +90,55 @@ RootSignatureD3D12::RootSignatureD3D12(IReferenceCounters*
const auto& ImtblSam = pSignature->GetImmutableSamplerAttribs(samp);
VERIFY_EXPR(ImtblSam.IsValid());
- Totald3d12StaticSamplers += ImtblSam.ArraySize;
+ TotalImmutableSamplers += ImtblSam.ArraySize;
}
}
- std::vector<D3D12_ROOT_PARAMETER, STDAllocatorRawMem<D3D12_ROOT_PARAMETER>> d3d12Parameters(TotalParams, D3D12_ROOT_PARAMETER{}, STD_ALLOCATOR_RAW_MEM(D3D12_ROOT_PARAMETER, GetRawAllocator(), "Allocator for vector<D3D12_ROOT_PARAMETER>"));
- std::vector<D3D12_DESCRIPTOR_RANGE, STDAllocatorRawMem<D3D12_DESCRIPTOR_RANGE>> d3d12DescrRanges(TotalDescriptorRanges, D3D12_DESCRIPTOR_RANGE{}, STD_ALLOCATOR_RAW_MEM(D3D12_DESCRIPTOR_RANGE, GetRawAllocator(), "Allocator for vector<D3D12_DESCRIPTOR_RANGE>"));
- std::vector<D3D12_STATIC_SAMPLER_DESC, STDAllocatorRawMem<D3D12_STATIC_SAMPLER_DESC>> d3d12StaticSamplers(STD_ALLOCATOR_RAW_MEM(D3D12_STATIC_SAMPLER_DESC, GetRawAllocator(), "Allocator for vector<D3D12_STATIC_SAMPLER_DESC>"));
- d3d12StaticSamplers.reserve(Totald3d12StaticSamplers);
+ // Reserve space for all root parameters
+ std::vector<D3D12_ROOT_PARAMETER, STDAllocatorRawMem<D3D12_ROOT_PARAMETER>> d3d12Parameters(
+ TotalParams,
+ D3D12_ROOT_PARAMETER{static_cast<D3D12_ROOT_PARAMETER_TYPE>(-1)},
+ STD_ALLOCATOR_RAW_MEM(D3D12_ROOT_PARAMETER, GetRawAllocator(), "Allocator for vector<D3D12_ROOT_PARAMETER>"));
+ // ... descriptor ranges,
+ std::vector<D3D12_DESCRIPTOR_RANGE, STDAllocatorRawMem<D3D12_DESCRIPTOR_RANGE>> d3d12DescrRanges(
+ TotalDescriptorRanges,
+ D3D12_DESCRIPTOR_RANGE{},
+ STD_ALLOCATOR_RAW_MEM(D3D12_DESCRIPTOR_RANGE, GetRawAllocator(), "Allocator for vector<D3D12_DESCRIPTOR_RANGE>"));
+ // ... and static samplers.
+ std::vector<D3D12_STATIC_SAMPLER_DESC, STDAllocatorRawMem<D3D12_STATIC_SAMPLER_DESC>> d3d12StaticSamplers(
+ STD_ALLOCATOR_RAW_MEM(D3D12_STATIC_SAMPLER_DESC, GetRawAllocator(), "Allocator for vector<D3D12_STATIC_SAMPLER_DESC>"));
+ d3d12StaticSamplers.reserve(TotalImmutableSamplers);
auto descr_range_it = d3d12DescrRanges.begin();
Uint32 BaseRegisterSpace = 0;
for (Uint32 sig = 0; sig < m_SignatureCount; ++sig)
{
- m_FirstRegisterSpace[sig] = static_cast<Uint16>(BaseRegisterSpace);
+ auto& SignInfo = m_ResourceSignatures[sig];
- const auto& pSignature = m_Signatures[sig];
+ SignInfo.BaseRegisterSpace = BaseRegisterSpace;
+
+ const PipelineResourceSignatureD3D12Impl* const pSignature = SignInfo.pSignature;
if (pSignature == nullptr)
continue;
- const auto& RootParams = pSignature->m_RootParams;
- const auto FirstRootIndex = m_FirstRootIndex[sig];
+ const auto& RootParams = pSignature->GetRootParams();
Uint32 MaxSpaceUsed = 0;
for (Uint32 rt = 0; rt < RootParams.GetNumRootTables(); ++rt)
{
- const auto& RootTable = RootParams.GetRootTable(rt);
- const auto& d3d12SrcParam = RootTable.d3d12RootParam;
- const auto& d3d12SrcTbl = d3d12SrcParam.DescriptorTable;
- const Uint32 RootIndex = FirstRootIndex + RootTable.RootIndex;
+ const auto& RootTable = RootParams.GetRootTable(rt);
+ const auto& d3d12SrcParam = RootTable.d3d12RootParam;
+ const auto& d3d12SrcTbl = d3d12SrcParam.DescriptorTable;
+ // Offset root parameter index by the base root index of the current resource signature
+ const Uint32 RootIndex = SignInfo.BaseRootIndex + RootTable.RootIndex;
VERIFY(d3d12SrcParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE && d3d12SrcParam.DescriptorTable.NumDescriptorRanges > 0, "Non-empty descriptor table is expected");
auto& d3d12DstParam = d3d12Parameters[RootIndex];
auto& d3d12DstTbl = d3d12DstParam.DescriptorTable;
d3d12DstParam = d3d12SrcParam;
+ // Copy all ranges from the source descriptor table and offset register space values by
+ // the base register space of the current resource signature.
memcpy(&*descr_range_it, d3d12SrcTbl.pDescriptorRanges, d3d12SrcTbl.NumDescriptorRanges * sizeof(D3D12_DESCRIPTOR_RANGE));
d3d12DstTbl.pDescriptorRanges = &*descr_range_it;
for (Uint32 r = 0; r < d3d12SrcTbl.NumDescriptorRanges; ++r, ++descr_range_it)
@@ -136,14 +152,16 @@ RootSignatureD3D12::RootSignatureD3D12(IReferenceCounters*
{
const auto& RootView = RootParams.GetRootView(rv);
const auto& d3d12SrcParam = RootView.d3d12RootParam;
- const Uint32 RootIndex = FirstRootIndex + RootView.RootIndex;
+ const Uint32 RootIndex = SignInfo.BaseRootIndex + RootView.RootIndex;
VERIFY((d3d12SrcParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV ||
d3d12SrcParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_SRV ||
d3d12SrcParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_UAV),
"Root CBV, SRV or UAV is expected");
+
MaxSpaceUsed = std::max(MaxSpaceUsed, d3d12SrcParam.Descriptor.RegisterSpace);
d3d12Parameters[RootIndex] = d3d12SrcParam;
+ // Offset register space value by the base register space of the current resource signature.
d3d12Parameters[RootIndex].Descriptor.RegisterSpace += BaseRegisterSpace;
}
@@ -182,17 +200,26 @@ RootSignatureD3D12::RootSignatureD3D12(IReferenceCounters*
}
m_TotalSpacesUsed = BaseRegisterSpace;
+#ifdef DILIGENT_DEBUG
+ for (size_t i = 0; i < d3d12Parameters.size(); ++i)
+ {
+ VERIFY(d3d12Parameters[i].ParameterType != -1, "Root parameter at index ", i, " has not been initialized");
+ }
+#endif
+
VERIFY_EXPR(descr_range_it == d3d12DescrRanges.end());
+ D3D12_ROOT_SIGNATURE_DESC rootSignatureDesc{};
+ rootSignatureDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
rootSignatureDesc.NumParameters = static_cast<UINT>(d3d12Parameters.size());
- rootSignatureDesc.pParameters = d3d12Parameters.size() ? d3d12Parameters.data() : nullptr;
+ rootSignatureDesc.pParameters = !d3d12Parameters.empty() ? d3d12Parameters.data() : nullptr;
- rootSignatureDesc.NumStaticSamplers = Totald3d12StaticSamplers;
+ rootSignatureDesc.NumStaticSamplers = TotalImmutableSamplers;
rootSignatureDesc.pStaticSamplers = nullptr;
if (!d3d12StaticSamplers.empty())
{
rootSignatureDesc.pStaticSamplers = d3d12StaticSamplers.data();
- VERIFY_EXPR(d3d12StaticSamplers.size() == Totald3d12StaticSamplers);
+ VERIFY_EXPR(d3d12StaticSamplers.size() == TotalImmutableSamplers);
}
CComPtr<ID3DBlob> signature;
@@ -217,21 +244,17 @@ RootSignatureD3D12::~RootSignatureD3D12()
}
LocalRootSignatureD3D12::LocalRootSignatureD3D12(const char* pCBName, Uint32 ShaderRecordSize) :
- m_pName{pCBName},
+ m_Name{pCBName != nullptr ? pCBName : ""},
m_ShaderRecordSize{ShaderRecordSize}
{
- VERIFY_EXPR((m_pName != nullptr) == (m_ShaderRecordSize > 0));
+ VERIFY_EXPR(!m_Name.empty() == (m_ShaderRecordSize > 0));
}
-bool LocalRootSignatureD3D12::IsShaderRecord(const D3DShaderResourceAttribs& CB)
+bool LocalRootSignatureD3D12::IsShaderRecord(const D3DShaderResourceAttribs& CB) const
{
- if (m_ShaderRecordSize > 0 &&
- CB.GetInputType() == D3D_SIT_CBUFFER &&
- strcmp(m_pName, CB.Name) == 0)
- {
- return true;
- }
- return false;
+ return (m_ShaderRecordSize > 0 &&
+ CB.GetInputType() == D3D_SIT_CBUFFER &&
+ m_Name == CB.Name);
}
bool LocalRootSignatureD3D12::Create(ID3D12Device* pDevice, Uint32 RegisterSpace)
@@ -267,20 +290,15 @@ bool LocalRootSignatureD3D12::Create(ID3D12Device* pDevice, Uint32 RegisterSpace
}
-namespace
+bool RootSignatureD3D12::IsCompatibleWith(const RefCntAutoPtr<PipelineResourceSignatureD3D12Impl> ppSignatures[], Uint32 SignatureCount) const noexcept
{
-bool RootSignatureCompare(const RootSignatureD3D12* lhs, const RefCntAutoPtr<PipelineResourceSignatureD3D12Impl>* ppSignatures, Uint32 SignatureCount) noexcept
-{
- const Uint32 LSigCount = lhs->GetSignatureCount();
- const Uint32 RSigCount = SignatureCount;
-
- if (LSigCount != RSigCount)
+ if (GetSignatureCount() != SignatureCount)
return false;
- for (Uint32 i = 0; i < LSigCount; ++i)
+ for (Uint32 i = 0; i < SignatureCount; ++i)
{
- auto* pLSig = lhs->GetSignature(i);
- auto* pRSig = ppSignatures[i].RawPtr();
+ const PipelineResourceSignatureD3D12Impl* const pLSig = m_ResourceSignatures[i].pSignature;
+ const PipelineResourceSignatureD3D12Impl* const pRSig = ppSignatures[i];
if (pLSig == pRSig)
continue;
@@ -288,12 +306,14 @@ bool RootSignatureCompare(const RootSignatureD3D12* lhs, const RefCntAutoPtr<Pip
if ((pLSig == nullptr) != (pRSig == nullptr))
return false;
+ if (pLSig == nullptr || pRSig == nullptr)
+ continue;
+
if (!pLSig->IsCompatibleWith(*pRSig))
return false;
}
return true;
}
-} // namespace
RootSignatureCacheD3D12::RootSignatureCacheD3D12(RenderDeviceD3D12Impl& DeviceD3D12Impl) :
m_DeviceD3D12Impl{DeviceD3D12Impl}
@@ -301,8 +321,8 @@ RootSignatureCacheD3D12::RootSignatureCacheD3D12(RenderDeviceD3D12Impl& DeviceD3
RootSignatureCacheD3D12::~RootSignatureCacheD3D12()
{
- std::lock_guard<std::mutex> Lock{m_RootSigCacheGuard};
- VERIFY(m_RootSigCache.empty(), "All pipeline layouts must be released");
+ std::lock_guard<std::mutex> Lock{m_RootSigCacheMtx};
+ VERIFY(m_RootSigCache.empty(), "All pipeline resource signatures must be released before the cache is destroyed.");
}
RefCntAutoPtr<RootSignatureD3D12> RootSignatureCacheD3D12::GetRootSig(const RefCntAutoPtr<PipelineResourceSignatureD3D12Impl>* ppSignatures, Uint32 SignatureCount)
@@ -323,14 +343,14 @@ RefCntAutoPtr<RootSignatureD3D12> RootSignatureCacheD3D12::GetRootSig(const RefC
}
}
- std::lock_guard<std::mutex> Lock{m_RootSigCacheGuard};
+ std::lock_guard<std::mutex> Lock{m_RootSigCacheMtx};
auto Range = m_RootSigCache.equal_range(Hash);
for (auto Iter = Range.first; Iter != Range.second; ++Iter)
{
if (auto Ptr = Iter->second.Lock())
{
- if (RootSignatureCompare(Ptr, ppSignatures, SignatureCount))
+ if (Ptr->IsCompatibleWith(ppSignatures, SignatureCount))
return Ptr;
}
}
@@ -344,10 +364,9 @@ RefCntAutoPtr<RootSignatureD3D12> RootSignatureCacheD3D12::GetRootSig(const RefC
void RootSignatureCacheD3D12::OnDestroyRootSig(RootSignatureD3D12* pRootSig)
{
- std::lock_guard<std::mutex> Lock{m_RootSigCacheGuard};
+ std::lock_guard<std::mutex> Lock{m_RootSigCacheMtx};
auto Range = m_RootSigCache.equal_range(pRootSig->GetHash());
-
for (auto Iter = Range.first; Iter != Range.second;)
{
if (!Iter->second.IsValid())