diff options
| author | assiduous <assiduous@diligentgraphics.com> | 2021-02-23 02:01:50 +0000 |
|---|---|---|
| committer | assiduous <assiduous@diligentgraphics.com> | 2021-03-19 00:38:10 +0000 |
| commit | 859eb02ccdca5c2a69935e011810490b986cb719 (patch) | |
| tree | f7594cd1dcaae6edc6a0cb9e8d292e79ccb6fb13 /Graphics/GraphicsEngineD3D12 | |
| parent | Fixed bug in DescriptorHeapAllocationManager (diff) | |
| download | DiligentCore-859eb02ccdca5c2a69935e011810490b986cb719.tar.gz DiligentCore-859eb02ccdca5c2a69935e011810490b986cb719.zip | |
Implemented committed resource validation in d3d12
Diffstat (limited to 'Graphics/GraphicsEngineD3D12')
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 |
