summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineD3D12
diff options
context:
space:
mode:
authorassiduous <assiduous@diligentgraphics.com>2021-02-23 02:01:50 +0000
committerassiduous <assiduous@diligentgraphics.com>2021-03-19 00:38:10 +0000
commit859eb02ccdca5c2a69935e011810490b986cb719 (patch)
treef7594cd1dcaae6edc6a0cb9e8d292e79ccb6fb13 /Graphics/GraphicsEngineD3D12
parentFixed bug in DescriptorHeapAllocationManager (diff)
downloadDiligentCore-859eb02ccdca5c2a69935e011810490b986cb719.tar.gz
DiligentCore-859eb02ccdca5c2a69935e011810490b986cb719.zip
Implemented committed resource validation in d3d12
Diffstat (limited to 'Graphics/GraphicsEngineD3D12')
-rw-r--r--Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp16
-rw-r--r--Graphics/GraphicsEngineD3D12/include/PipelineResourceSignatureD3D12Impl.hpp28
-rw-r--r--Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp51
-rw-r--r--Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp2
-rw-r--r--Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp83
-rw-r--r--Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp260
6 files changed, 302 insertions, 138 deletions
diff --git a/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp
index 333dc912..c8fabce5 100644
--- a/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp
+++ b/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp
@@ -391,13 +391,13 @@ private:
using Bitfield = Uint8;
static_assert(sizeof(Bitfield) * 8 >= MAX_RESOURCE_SIGNATURES, "not enought space to store MAX_RESOURCE_SIGNATURES bits");
- Bitfield ActiveSRBMask = 0; // Indicates which SRBs are active in current PSO
- Bitfield DynamicBuffersMask = 0; // Indicates which SRBs have dynamic buffers
- bool bRootViewsCommitted; // Indicates if root views have been committed since the time SRB has been committed.
- bool bRootTablesCommited;
- ID3D12RootSignature* pRootSig;
+ Bitfield ActiveSRBMask = 0; // Indicates which SRBs are active in current PSO
+ Bitfield DynamicBuffersMask = 0; // Indicates which SRBs have dynamic buffers
+ bool bRootViewsCommitted = false; // Indicates if root views have been committed since the time SRB has been committed.
+ bool bRootTablesCommited = false;
+ ID3D12RootSignature* pRootSig = nullptr;
- std::array<class ShaderResourceBindingD3D12Impl*, MAX_RESOURCE_SIGNATURES> SRBs;
+ std::array<class ShaderResourceBindingD3D12Impl*, MAX_RESOURCE_SIGNATURES> SRBs{};
RootTableInfo()
{
@@ -455,10 +455,10 @@ private:
// Indicates if currently committed D3D12 vertex buffers are up to date
bool bCommittedD3D12VBsUpToDate = false;
- // Indicates if currently committed D3D11 index buffer is up to date
+ // Indicates if currently committed D3D12 index buffer is up to date
bool bCommittedD3D12IBUpToDate = false;
- // AZ TODO
+ // Indicates if currently committed resources have been validated
bool CommittedResourcesValidated = false;
} m_State;
diff --git a/Graphics/GraphicsEngineD3D12/include/PipelineResourceSignatureD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/PipelineResourceSignatureD3D12Impl.hpp
index 094f5d20..2020df72 100644
--- a/Graphics/GraphicsEngineD3D12/include/PipelineResourceSignatureD3D12Impl.hpp
+++ b/Graphics/GraphicsEngineD3D12/include/PipelineResourceSignatureD3D12Impl.hpp
@@ -45,6 +45,7 @@ class CommandContext;
class RenderDeviceD3D12Impl;
class DeviceContextD3D12Impl;
class ShaderVariableManagerD3D12;
+struct D3DShaderResourceAttribs;
/// Implementation of the Diligent::PipelineResourceSignatureD3D12Impl class
class PipelineResourceSignatureD3D12Impl final : public PipelineResourceSignatureBase<IPipelineResourceSignature, RenderDeviceD3D12Impl>
@@ -147,12 +148,6 @@ public:
return m_pResourceAttribs[ResIndex];
}
- const PipelineResourceDesc& GetResourceDesc(Uint32 ResIndex) const
- {
- VERIFY_EXPR(ResIndex < m_Desc.NumResources);
- return m_Desc.Resources[ResIndex];
- }
-
struct ImmutableSamplerAttribs
{
private:
@@ -197,12 +192,6 @@ public:
return m_ImmutableSamplers[SampIndex];
}
- const ImmutableSamplerDesc& GetImmutableSamplerDesc(Uint32 SampIndex) const
- {
- VERIFY_EXPR(SampIndex < m_Desc.NumImmutableSamplers);
- return m_Desc.ImmutableSamplers[SampIndex];
- }
-
Uint32 GetTotalRootParamsCount() const
{
return m_RootParams.GetNumRootTables() + m_RootParams.GetNumRootViews();
@@ -262,9 +251,9 @@ public:
Uint32 ResIndex,
ShaderResourceCacheD3D12& ResourceCache) const;
- bool IsBound(Uint32 ArrayIndex,
- Uint32 ResIndex,
- ShaderResourceCacheD3D12& ResourceCache) const;
+ bool IsBound(Uint32 ArrayIndex,
+ Uint32 ResIndex,
+ const ShaderResourceCacheD3D12& ResourceCache) const;
void CommitRootTables(ShaderResourceCacheD3D12& ResourceCache,
CommandContext& Ctx,
@@ -290,6 +279,15 @@ public:
// Returns true if there is an immutable sampler array in the given shader stage.
bool HasImmutableSamplerArray(SHADER_TYPE ShaderStage) const;
+#ifdef DILIGENT_DEVELOPMENT
+ /// Verifies committed resource using the resource attributes from the PSO.
+ bool DvpValidateCommittedResource(const D3DShaderResourceAttribs& D3DAttribs,
+ Uint32 ResIndex,
+ const ShaderResourceCacheD3D12& ResourceCache,
+ const char* ShaderName,
+ const char* PSOName) const;
+#endif
+
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 57a97796..50fab6c5 100644
--- a/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp
+++ b/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp
@@ -30,8 +30,11 @@
/// \file
/// Declaration of Diligent::PipelineStateD3D12Impl class
+#include <vector>
+
#include "RenderDeviceD3D12.h"
#include "PipelineStateD3D12.h"
+#include "PipelineResourceSignatureD3D12Impl.hpp"
#include "PipelineStateBase.hpp"
#include "RootSignature.hpp"
#include "RenderDeviceD3D12Impl.hpp"
@@ -41,6 +44,7 @@ namespace Diligent
class ShaderD3D12Impl;
class ShaderResourcesD3D12;
+class ShaderResourceBindingD3D12Impl;
/// Pipeline state object implementation in Direct3D12 backend.
class PipelineStateD3D12Impl final : public PipelineStateBase<IPipelineStateD3D12, RenderDeviceD3D12Impl>
@@ -83,6 +87,10 @@ public:
return m_ResourceSignatures[index];
}
+#ifdef DILIGENT_DEVELOPMENT
+ void DvpVerifySRBResources(ShaderResourceBindingD3D12Impl* pSRBs[], Uint32 NumSRBs) const;
+#endif
+
private:
struct ShaderStageInfo
{
@@ -115,20 +123,46 @@ private:
void Destruct();
- struct ResourceInfo
+ struct ResourceAttribution
{
- PipelineResourceSignatureD3D12Impl* Signature = nullptr;
- PipelineResourceDesc const* ResDesc = nullptr;
+ static constexpr Uint32 InvalidSignatureIndex = ~0u;
+ static constexpr Uint32 InvalidResourceIndex = PipelineResourceSignatureD3D12Impl::InvalidResourceIndex;
+ static constexpr Uint32 InvalidSamplerIndex = InvalidImmutableSamplerIndex;
+
+ const PipelineResourceSignatureD3D12Impl* pSignature = nullptr;
+
+ Uint32 SignatureIndex = InvalidSignatureIndex;
+ Uint32 ResourceIndex = InvalidResourceIndex;
+ Uint32 ImmutableSamplerIndex = InvalidSamplerIndex;
+
+ ResourceAttribution() noexcept {}
+ ResourceAttribution(const PipelineResourceSignatureD3D12Impl* _pSignature,
+ Uint32 _SignatureIndex,
+ Uint32 _ResourceIndex,
+ Uint32 _ImmutableSamplerIndex = InvalidResourceIndex) noexcept :
+ pSignature{_pSignature},
+ SignatureIndex{_SignatureIndex},
+ ResourceIndex{_ResourceIndex},
+ ImmutableSamplerIndex{_ImmutableSamplerIndex}
+ {
+ VERIFY_EXPR(pSignature == nullptr || pSignature->GetDesc().BindingIndex == SignatureIndex);
+ VERIFY_EXPR((ResourceIndex == InvalidResourceIndex) || (ImmutableSamplerIndex == InvalidSamplerIndex));
+ }
explicit operator bool() const
{
- return Signature != nullptr && ResDesc != nullptr;
+ return SignatureIndex != InvalidSignatureIndex && (ResourceIndex != InvalidResourceIndex || ImmutableSamplerIndex != InvalidSamplerIndex);
+ }
+
+ bool IsImmutableSampler() const
+ {
+ return *this && ImmutableSamplerIndex != InvalidSamplerIndex;
}
};
- ResourceInfo GetResourceInfo(const char* Name, SHADER_TYPE Stage) const;
+ ResourceAttribution GetResourceAttribution(const char* Name, SHADER_TYPE Stage) const;
#ifdef DILIGENT_DEVELOPMENT
- void DvpValidateShaderResources(const ShaderD3D12Impl* pShader, const LocalRootSignatureD3D12* pLocalRootSig) const;
+ void DvpValidateShaderResources(const ShaderD3D12Impl* pShader, const LocalRootSignatureD3D12* pLocalRootSig);
#endif
private:
@@ -141,8 +175,11 @@ private:
std::unique_ptr<RefCntAutoPtr<PipelineResourceSignatureD3D12Impl>[]> m_ResourceSignatures;
#ifdef DILIGENT_DEVELOPMENT
- // Shader resources for all shaders in all shader stages
+ // Shader resources for all shaders in all shader stages in the pipeline.
std::vector<std::shared_ptr<const ShaderResourcesD3D12>> m_ShaderResources;
+
+ // Shader resource attributions for every resource in m_ShaderResources, in the same order.
+ std::vector<ResourceAttribution> m_ResourceAttibutions;
#endif
};
diff --git a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp
index 2fba7309..495a13d2 100644
--- a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp
@@ -437,7 +437,7 @@ void DeviceContextD3D12Impl::DvpValidateCommittedShaderResources()
}
}
- //m_pPipelineState->DvpVerifySRBResources(RootInfo.SRBs);
+ m_pPipelineState->DvpVerifySRBResources(RootInfo.SRBs.data(), static_cast<Uint32>(RootInfo.SRBs.size()));
m_State.CommittedResourcesValidated = true;
}
diff --git a/Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp
index 3fc80df0..a1ee657b 100644
--- a/Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp
@@ -176,9 +176,8 @@ void PipelineResourceSignatureD3D12Impl::AllocateRootParameters(StaticResCacheTb
// and we will be looking for the 'Texture_sampler' name.
// - When combined texture samplers are not used, sampler suffix will be null,
// and we will be looking for the sampler name itself.
- const auto SrcImmutableSamplerInd = FindImmutableSampler(m_Desc.ImmutableSamplers, m_Desc.NumImmutableSamplers, ResDesc.ShaderStages,
- ResDesc.Name, GetCombinedSamplerSuffix());
- if (SrcImmutableSamplerInd >= 0)
+ const auto SrcImmutableSamplerInd = FindImmutableSampler(ResDesc.ShaderStages, ResDesc.Name);
+ if (SrcImmutableSamplerInd != InvalidImmutableSamplerIndex)
{
ResourceToImmutableSamplerInd[i] = SrcImmutableSamplerInd;
// Set the immutable sampler array size to match the resource array size
@@ -1250,9 +1249,9 @@ void PipelineResourceSignatureD3D12Impl::BindResource(IDeviceObject*
Helper.BindResource(pObj);
}
-bool PipelineResourceSignatureD3D12Impl::IsBound(Uint32 ArrayIndex,
- Uint32 ResIndex,
- ShaderResourceCacheD3D12& ResourceCache) const
+bool PipelineResourceSignatureD3D12Impl::IsBound(Uint32 ArrayIndex,
+ Uint32 ResIndex,
+ const ShaderResourceCacheD3D12& ResourceCache) const
{
const auto& ResDesc = GetResourceDesc(ResIndex);
const auto& Attribs = GetResourceAttribs(ResIndex);
@@ -1265,9 +1264,9 @@ bool PipelineResourceSignatureD3D12Impl::IsBound(Uint32 Array
if (RootIndex < ResourceCache.GetNumRootTables())
{
const auto& RootTable = ResourceCache.GetRootTable(RootIndex);
- if (OffsetFromTableStart + ArrayIndex < RootTable.GetSize())
+ if (OffsetFromTableStart < RootTable.GetSize())
{
- const auto& CachedRes = RootTable.GetResource(OffsetFromTableStart + ArrayIndex);
+ const auto& CachedRes = RootTable.GetResource(OffsetFromTableStart);
return !CachedRes.IsNull();
}
}
@@ -1275,4 +1274,72 @@ bool PipelineResourceSignatureD3D12Impl::IsBound(Uint32 Array
return false;
}
+#ifdef DILIGENT_DEVELOPMENT
+bool PipelineResourceSignatureD3D12Impl::DvpValidateCommittedResource(const D3DShaderResourceAttribs& D3DAttribs,
+ Uint32 ResIndex,
+ const ShaderResourceCacheD3D12& ResourceCache,
+ const char* ShaderName,
+ const char* PSOName) const
+{
+ const auto& ResDesc = GetResourceDesc(ResIndex);
+ const auto& ResAttribs = GetResourceAttribs(ResIndex);
+ VERIFY_EXPR(strcmp(ResDesc.Name, D3DAttribs.Name) == 0);
+ VERIFY_EXPR(D3DAttribs.BindCount <= ResDesc.ArraySize);
+
+ if ((ResDesc.ResourceType == SHADER_RESOURCE_TYPE_SAMPLER) && ResAttribs.IsImmutableSamplerAssigned())
+ return true;
+
+ const auto CacheType = ResourceCache.GetContentType();
+ const auto RootIndex = ResAttribs.RootIndex(CacheType);
+ const auto OffsetFromTableStart = ResAttribs.OffsetFromTableStart(CacheType);
+ const auto& RootTable = ResourceCache.GetRootTable(RootIndex);
+
+ bool BindingsOK = true;
+ for (Uint32 ArrIndex = 0; ArrIndex < D3DAttribs.BindCount; ++ArrIndex)
+ {
+ if (!IsBound(ArrIndex, ResIndex, ResourceCache))
+ {
+ LOG_ERROR_MESSAGE("No resource is bound to variable '", GetShaderResourcePrintName(D3DAttribs.Name, D3DAttribs.BindCount, ArrIndex),
+ "' in shader '", ShaderName, "' of PSO '", PSOName, "'.");
+ BindingsOK = false;
+ continue;
+ }
+
+ if (ResAttribs.IsCombinedWithSampler())
+ {
+ auto& SamplerResDesc = GetResourceDesc(ResAttribs.SamplerInd);
+ auto& SamplerAttribs = GetResourceAttribs(ResAttribs.SamplerInd);
+ VERIFY_EXPR(SamplerResDesc.ResourceType == SHADER_RESOURCE_TYPE_SAMPLER);
+ VERIFY_EXPR(SamplerResDesc.ArraySize == 1 || SamplerResDesc.ArraySize == ResDesc.ArraySize);
+ if (!SamplerAttribs.IsImmutableSamplerAssigned())
+ {
+ if (ArrIndex < SamplerResDesc.ArraySize)
+ {
+ if (!IsBound(ArrIndex, ResAttribs.SamplerInd, ResourceCache))
+ {
+ LOG_ERROR_MESSAGE("No sampler is bound to sampler variable '", GetShaderResourcePrintName(SamplerResDesc, ArrIndex),
+ "' combined with texture '", D3DAttribs.Name, "' in shader '", ShaderName, "' of PSO '", PSOName, "'.");
+ BindingsOK = false;
+ }
+ }
+ }
+ }
+
+ if (ResDesc.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_SRV || ResDesc.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_UAV)
+ {
+ const auto& CachedRes = RootTable.GetResource(OffsetFromTableStart);
+ // When can use raw cast here because the dynamic type is verified when the resource
+ // is bound. It will be null if the type is incorrect.
+ if (const auto* pTexViewD3D12 = CachedRes.pObject.RawPtr<TextureViewD3D12Impl>())
+ {
+ if (!ValidateResourceViewDimension(D3DAttribs.Name, D3DAttribs.BindCount, ArrIndex, pTexViewD3D12, D3DAttribs.GetResourceDimension(), D3DAttribs.IsMultisample()))
+ BindingsOK = false;
+ }
+ }
+ }
+ return BindingsOK;
+}
+#endif
+
+
} // namespace Diligent
diff --git a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp
index 5a0ed88c..d649046c 100644
--- a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp
@@ -30,6 +30,10 @@
#include <sstream>
#include <d3dcompiler.h>
+#ifdef FindResource
+# undef FindResource
+#endif
+
#include "PipelineStateD3D12Impl.hpp"
#include "ShaderD3D12Impl.hpp"
#include "D3D12TypeConversions.hpp"
@@ -39,6 +43,7 @@
#include "EngineMemory.h"
#include "StringTools.hpp"
#include "DynamicLinearAllocator.hpp"
+#include "ShaderResourceBindingD3D12Impl.hpp"
#include "DXBCUtils.hpp"
#include "DXCompiler.hpp"
#include "dxc/dxcapi.h"
@@ -427,33 +432,33 @@ RefCntAutoPtr<IPipelineResourceSignature> PipelineStateD3D12Impl::CreateDefaultR
{
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())});
- if (IterAndAssigned.second)
+ ShaderResources.ProcessResources(
+ [&](const D3DShaderResourceAttribs& Res, Uint32) //
{
- SHADER_RESOURCE_TYPE Type;
- PIPELINE_RESOURCE_FLAGS Flags;
- GetShaderResourceTypeAndFlags(Res, Type, Flags);
+ if (pLocalRootSig != nullptr && pLocalRootSig->IsShaderRecord(Res))
+ return;
- if (Res.BindCount == 0)
+ auto IterAndAssigned = UniqueNames.emplace(HashMapStringKey{Res.Name}, UniqueResource{Res, static_cast<Uint32>(Resources.size())});
+ if (IterAndAssigned.second)
{
- 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.");
- }
+ SHADER_RESOURCE_TYPE Type;
+ PIPELINE_RESOURCE_FLAGS Flags;
+ GetShaderResourceTypeAndFlags(Res, Type, Flags);
- Resources.emplace_back(Stage.Type, Res.Name, Res.BindCount, Type, LayoutDesc.DefaultVariableType, Flags);
- }
- else
- {
- VerifyResourceMerge(IterAndAssigned.first->second.Attribs, Res);
- }
- };
+ if (Res.BindCount == 0)
+ {
+ 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.");
+ }
- ShaderResources.ProcessResources(HandleResource, HandleResource, HandleResource, HandleResource, HandleResource, HandleResource, HandleResource);
+ Resources.emplace_back(Stage.Type, Res.Name, Res.BindCount, Type, LayoutDesc.DefaultVariableType, Flags);
+ }
+ else
+ {
+ VerifyResourceMerge(IterAndAssigned.first->second.Attribs, Res);
+ }
+ } //
+ );
// merge combined sampler suffixes
if (ShaderResources.IsUsingCombinedTextureSamplers() && ShaderResources.GetNumSamplers() > 0)
@@ -516,30 +521,6 @@ RefCntAutoPtr<IPipelineResourceSignature> PipelineStateD3D12Impl::CreateDefaultR
return pImplicitSignature;
}
-PipelineStateD3D12Impl::ResourceInfo PipelineStateD3D12Impl::GetResourceInfo(const char* Name, SHADER_TYPE Stage) const
-{
- ResourceInfo Info;
- for (Uint32 sign = 0, SignCount = GetSignatureCount(); sign < SignCount && !Info; ++sign)
- {
- auto* const pSignature = GetSignature(sign);
- if (pSignature == nullptr)
- continue;
-
- for (Uint32 r = 0, ResCount = pSignature->GetTotalResourceCount(); r < ResCount; ++r)
- {
- const auto& ResDesc = pSignature->GetResourceDesc(r);
-
- if ((ResDesc.ShaderStages & Stage) != 0 && strcmp(ResDesc.Name, Name) == 0)
- {
- Info.Signature = pSignature;
- Info.ResDesc = &ResDesc;
- break;
- }
- }
- }
- return Info;
-}
-
void PipelineStateD3D12Impl::InitRootSignature(const PipelineStateCreateInfo& CreateInfo,
TShaderStages& ShaderStages,
LocalRootSignatureD3D12* pLocalRootSig)
@@ -682,83 +663,164 @@ void PipelineStateD3D12Impl::InitRootSignature(const PipelineStateCreateInfo& Cr
pBytecode = pBlob;
#ifdef DILIGENT_DEVELOPMENT
- m_ShaderResources.emplace_back(pShader->GetShaderResources());
DvpValidateShaderResources(pShader, pLocalRootSig);
#endif
}
}
}
+
+PipelineStateD3D12Impl::ResourceAttribution PipelineStateD3D12Impl::GetResourceAttribution(const char* Name, SHADER_TYPE Stage) const
+{
+ const auto SignCount = GetSignatureCount();
+ for (Uint32 sign = 0; sign < SignCount; ++sign)
+ {
+ const auto* const pSignature = GetSignature(sign);
+ if (pSignature == nullptr)
+ continue;
+
+ const auto ResIndex = pSignature->FindResource(Stage, Name);
+ if (ResIndex != ResourceAttribution::InvalidResourceIndex)
+ return ResourceAttribution{pSignature, sign, ResIndex};
+ else
+ {
+ const auto ImtblSamIndex = pSignature->FindImmutableSampler(Stage, Name);
+ if (ImtblSamIndex != ResourceAttribution::InvalidSamplerIndex)
+ return ResourceAttribution{pSignature, sign, ResourceAttribution::InvalidResourceIndex, ImtblSamIndex};
+ }
+ }
+ return ResourceAttribution{};
+}
+
#ifdef DILIGENT_DEVELOPMENT
-void PipelineStateD3D12Impl::DvpValidateShaderResources(const ShaderD3D12Impl* pShader, const LocalRootSignatureD3D12* pLocalRootSig) const
+void PipelineStateD3D12Impl::DvpValidateShaderResources(const ShaderD3D12Impl* pShader, const LocalRootSignatureD3D12* pLocalRootSig)
{
const auto& pShaderResources = pShader->GetShaderResources();
const auto ShaderType = pShader->GetDesc().ShaderType;
+ m_ShaderResources.emplace_back(pShaderResources);
+
// Check compatibility between shader resources and resource signature.
- const auto HandleResource = [&](const D3DShaderResourceAttribs& Attribs, Uint32) //
- {
- if (pLocalRootSig != nullptr && pLocalRootSig->IsShaderRecord(Attribs))
- return;
+ pShaderResources->ProcessResources(
+ [&](const D3DShaderResourceAttribs& Attribs, Uint32) //
+ {
+ m_ResourceAttibutions.emplace_back();
- if (Attribs.GetInputType() == D3D_SIT_SAMPLER)
- return;
+ 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 used to create pipeline state '",
- m_Desc.Name, "'.");
- }
+ const auto IsSampler = Attribs.GetInputType() == D3D_SIT_SAMPLER;
+ if (IsSampler && pShaderResources->IsUsingCombinedTextureSamplers())
+ 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& ResAttribution = m_ResourceAttibutions.back();
- 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.");
- }
+ ResAttribution = GetResourceAttribution(Attribs.Name, ShaderType);
+ if (!ResAttribution)
+ {
+ LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource '", Attribs.Name,
+ "' that is not present in any pipeline resource signature used to create pipeline state '",
+ m_Desc.Name, "'.");
+ }
- if (Attribs.BindCount == 0)
- {
- if ((Info.ResDesc->Flags & PIPELINE_RESOURCE_FLAG_RUNTIME_ARRAY) != 0)
+ SHADER_RESOURCE_TYPE Type = SHADER_RESOURCE_TYPE_UNKNOWN;
+ PIPELINE_RESOURCE_FLAGS Flags = PIPELINE_RESOURCE_FLAG_UNKNOWN;
+ GetShaderResourceTypeAndFlags(Attribs, Type, Flags);
+
+ const auto* const pSignature = ResAttribution.pSignature;
+ VERIFY_EXPR(pSignature != nullptr);
+
+ if (ResAttribution.ResourceIndex != ResourceAttribution::InvalidResourceIndex)
+ {
+ const auto& ResDesc = pSignature->GetResourceDesc(ResAttribution.ResourceIndex);
+
+ if (Type != 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(ResDesc.ResourceType), "' in pipeline resource signature '", pSignature->GetDesc().Name, "'.");
+ }
+
+ if ((Flags & PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER) != (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 '",
+ pSignature->GetDesc().Name, "' is", ((ResDesc.Flags & PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER) ? "" : " not"),
+ " labeled as such.");
+ }
+
+ if (Attribs.BindCount == 0)
+ {
+ if ((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 '", pSignature->GetDesc().Name,
+ "' resource defined without PIPELINE_RESOURCE_FLAG_RUNTIME_ARRAY flag.");
+ }
+ }
+ else
+ {
+ if (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 (",
+ ResDesc.ArraySize, ") specified by the pipeline resource signature '", pSignature->GetDesc().Name, "'.");
+ }
+
+ if (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 '", pSignature->GetDesc().Name,
+ "' with flag PIPELINE_RESOURCE_FLAG_RUNTIME_ARRAY, but resource is not a runtime-sized array.");
+ }
+ }
+ }
+ else if (ResAttribution.ImmutableSamplerIndex != ResourceAttribution::InvalidResourceIndex)
{
- 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.");
+ if (Type != SHADER_RESOURCE_TYPE_SAMPLER)
+ {
+ LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource with name '", Attribs.Name,
+ "' and type '", GetShaderResourceTypeLiteralName(Type),
+ "' that is not compatible with immutable sampler defined in pipeline resource signature '",
+ pSignature->GetDesc().Name, "'.");
+ }
}
- }
- else
- {
- if (Info.ResDesc->ArraySize < Attribs.BindCount)
+ else
{
- 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, "'.");
+ UNEXPECTED("Either immutable sampler or resource index should be valid");
}
+ } //
+ );
+}
- if (Info.ResDesc->Flags & PIPELINE_RESOURCE_FLAG_RUNTIME_ARRAY)
+void PipelineStateD3D12Impl::DvpVerifySRBResources(ShaderResourceBindingD3D12Impl* pSRBs[], Uint32 NumSRBs) const
+{
+ auto attrib_it = m_ResourceAttibutions.begin();
+ for (const auto& pResources : m_ShaderResources)
+ {
+ pResources->ProcessResources(
+ [&](const D3DShaderResourceAttribs& Attribs, Uint32) //
{
- 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);
+ if (*attrib_it && !attrib_it->IsImmutableSampler())
+ {
+ if (attrib_it->SignatureIndex >= NumSRBs || pSRBs[attrib_it->SignatureIndex] == nullptr)
+ {
+ LOG_ERROR_MESSAGE("No resource is bound to variable '", Attribs.Name, "' in shader '", pResources->GetShaderName(),
+ "' of PSO '", m_Desc.Name, "': SRB at index ", attrib_it->SignatureIndex, " is not bound in the context.");
+ return;
+ }
+
+ const auto& SRBCache = pSRBs[attrib_it->SignatureIndex]->GetResourceCache();
+ attrib_it->pSignature->DvpValidateCommittedResource(Attribs, attrib_it->ResourceIndex, SRBCache, pResources->GetShaderName(), m_Desc.Name);
+ }
+ ++attrib_it;
+ } //
+ );
+ }
+ VERIFY_EXPR(attrib_it == m_ResourceAttibutions.end());
}
+
#endif