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 | |
| parent | Fixed bug in DescriptorHeapAllocationManager (diff) | |
| download | DiligentCore-859eb02ccdca5c2a69935e011810490b986cb719.tar.gz DiligentCore-859eb02ccdca5c2a69935e011810490b986cb719.zip | |
Implemented committed resource validation in d3d12
Diffstat (limited to 'Graphics')
12 files changed, 428 insertions, 224 deletions
diff --git a/Graphics/GraphicsEngine/include/PipelineResourceSignatureBase.hpp b/Graphics/GraphicsEngine/include/PipelineResourceSignatureBase.hpp index 93659fa7..bf7b2bf7 100644 --- a/Graphics/GraphicsEngine/include/PipelineResourceSignatureBase.hpp +++ b/Graphics/GraphicsEngine/include/PipelineResourceSignatureBase.hpp @@ -49,14 +49,15 @@ namespace Diligent /// Validates pipeline resource signature description and throws an exception in case of an error. void ValidatePipelineResourceSignatureDesc(const PipelineResourceSignatureDesc& Desc) noexcept(false); +static constexpr Uint32 InvalidImmutableSamplerIndex = ~0u; /// Finds an immutable sampler for the resource name 'ResourceName' that is defined in shader stages 'ShaderStages'. /// If 'SamplerSuffix' is not null, it will be appended to the 'ResourceName'. -/// Returns an index of the sampler in ImtblSamplers array, or -1 if there is no suitable sampler. -Int32 FindImmutableSampler(const ImmutableSamplerDesc* ImtblSamplers, - Uint32 NumImtblSamplers, - SHADER_TYPE ShaderStages, - const char* ResourceName, - const char* SamplerSuffix); +/// Returns an index of the sampler in ImtblSamplers array, or InvalidImmutableSamplerIndex if there is no suitable sampler. +Uint32 FindImmutableSampler(const ImmutableSamplerDesc* ImtblSamplers, + Uint32 NumImtblSamplers, + SHADER_TYPE ShaderStages, + const char* ResourceName, + const char* SamplerSuffix); /// Returns true if two pipeline resource signature descriptions are compatible, and false otherwise bool PipelineResourceSignaturesCompatible(const PipelineResourceSignatureDesc& Desc0, @@ -178,6 +179,41 @@ public: return SHADER_TYPE_UNKNOWN; } + static constexpr Uint32 InvalidResourceIndex = ~0u; + /// Finds a resource with the given name in the specified shader stage and returns its + /// index in m_Desc.Resources[], or InvalidResourceIndex if the resource is not found. + Uint32 FindResource(SHADER_TYPE ShaderStage, const char* ResourceName) const + { + for (Uint32 r = 0; r < this->m_Desc.NumResources; ++r) + { + const auto& ResDesc = this->m_Desc.Resources[r]; + if ((ResDesc.ShaderStages & ShaderStage) != 0 && strcmp(ResDesc.Name, ResourceName) == 0) + return r; + } + + return InvalidResourceIndex; + } + + /// Finds an immutable with the given name in the specified shader stage and returns its + /// index in m_Desc.ImmutableSamplers[], or InvalidImmutableSamplerIndex if the sampler is not found. + Uint32 FindImmutableSampler(SHADER_TYPE ShaderStage, const char* ResourceName) const + { + return Diligent::FindImmutableSampler(this->m_Desc.ImmutableSamplers, this->m_Desc.NumImmutableSamplers, + ShaderStage, ResourceName, GetCombinedSamplerSuffix()); + } + + const PipelineResourceDesc& GetResourceDesc(Uint32 ResIndex) const + { + VERIFY_EXPR(ResIndex < this->m_Desc.NumResources); + return this->m_Desc.Resources[ResIndex]; + } + + const ImmutableSamplerDesc& GetImmutableSamplerDesc(Uint32 SampIndex) const + { + VERIFY_EXPR(SampIndex < this->m_Desc.NumImmutableSamplers); + return this->m_Desc.ImmutableSamplers[SampIndex]; + } + protected: void ReserveSpaceForDescription(FixedLinearAllocator& Allocator, const PipelineResourceSignatureDesc& Desc) const noexcept(false) { diff --git a/Graphics/GraphicsEngine/src/PipelineResourceSignatureBase.cpp b/Graphics/GraphicsEngine/src/PipelineResourceSignatureBase.cpp index 29c069de..a85e20dd 100644 --- a/Graphics/GraphicsEngine/src/PipelineResourceSignatureBase.cpp +++ b/Graphics/GraphicsEngine/src/PipelineResourceSignatureBase.cpp @@ -222,11 +222,11 @@ void ValidatePipelineResourceSignatureDesc(const PipelineResourceSignatureDesc& #undef LOG_PRS_ERROR_AND_THROW -Int32 FindImmutableSampler(const ImmutableSamplerDesc* ImtblSamplers, - Uint32 NumImtblSamplers, - SHADER_TYPE ShaderStages, - const char* ResourceName, - const char* SamplerSuffix) +Uint32 FindImmutableSampler(const ImmutableSamplerDesc* ImtblSamplers, + Uint32 NumImtblSamplers, + SHADER_TYPE ShaderStages, + const char* ResourceName, + const char* SamplerSuffix) { for (Uint32 s = 0; s < NumImtblSamplers; ++s) { @@ -242,7 +242,7 @@ Int32 FindImmutableSampler(const ImmutableSamplerDesc* ImtblSamplers, } } - return -1; + return InvalidImmutableSamplerIndex; } /// Returns true if two pipeline resources are compatible 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 diff --git a/Graphics/GraphicsEngineD3DBase/include/ShaderResources.hpp b/Graphics/GraphicsEngineD3DBase/include/ShaderResources.hpp index dcd0289b..69a61bf2 100644 --- a/Graphics/GraphicsEngineD3DBase/include/ShaderResources.hpp +++ b/Graphics/GraphicsEngineD3DBase/include/ShaderResources.hpp @@ -372,6 +372,11 @@ public: HandleAccelStruct(AS, n); } } + template <typename THandler> + void ProcessResources(THandler Handler) const + { + ProcessResources(Handler, Handler, Handler, Handler, Handler, Handler, Handler); + } bool IsCompatibleWith(const ShaderResources& Resources) const; bool IsUsingCombinedTextureSamplers() const { return m_SamplerSuffix != nullptr; } diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineResourceSignatureVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineResourceSignatureVkImpl.hpp index b873d828..cabfa010 100644 --- a/Graphics/GraphicsEngineVulkan/include/PipelineResourceSignatureVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/PipelineResourceSignatureVkImpl.hpp @@ -185,12 +185,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 { RefCntAutoPtr<ISampler> Ptr; @@ -205,12 +199,6 @@ public: return m_ImmutableSamplers[SampIndex]; } - const ImmutableSamplerDesc& GetImmutableSamplerDesc(Uint32 SampIndex) const - { - VERIFY_EXPR(SampIndex < m_Desc.NumImmutableSamplers); - return m_Desc.ImmutableSamplers[SampIndex]; - } - VkDescriptorSetLayout GetVkDescriptorSetLayout(DESCRIPTOR_SET_ID SetId) const { return m_VkDescrSetLayouts[SetId]; } bool HasDescriptorSet(DESCRIPTOR_SET_ID SetId) const { return m_VkDescrSetLayouts[SetId] != VK_NULL_HANDLE; } @@ -278,7 +266,9 @@ public: /// Verifies committed resource attribs using the SPIRV resource attributes from the PSO. bool DvpValidateCommittedResource(const SPIRVShaderResourceAttribs& SPIRVAttribs, Uint32 ResIndex, - ShaderResourceCacheVk& ResourceCache) const; + const ShaderResourceCacheVk& ResourceCache, + const char* ShaderName, + const char* PSOName) const; #endif // Returns the descriptor set index in the resource cache diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineResourceSignatureVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineResourceSignatureVkImpl.cpp index ddd59ae1..cedeaddc 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineResourceSignatureVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineResourceSignatureVkImpl.cpp @@ -189,10 +189,10 @@ inline TEXTURE_VIEW_TYPE DescriptorTypeToTextureView(DescriptorType Type) } } -Int32 FindImmutableSampler(const PipelineResourceDesc& Res, - DescriptorType DescType, - const PipelineResourceSignatureDesc& Desc, - const char* SamplerSuffix) +Uint32 FindImmutableSamplerVk(const PipelineResourceDesc& Res, + DescriptorType DescType, + const PipelineResourceSignatureDesc& Desc, + const char* SamplerSuffix) { if (DescType == DescriptorType::CombinedImageSampler) { @@ -206,10 +206,10 @@ Int32 FindImmutableSampler(const PipelineResourceDesc& Res, else { UNEXPECTED("Immutable sampler can only be assigned to a sampled image or separate sampler"); - return -1; + return InvalidImmutableSamplerIndex; } - return Diligent::FindImmutableSampler(Desc.ImmutableSamplers, Desc.NumImmutableSamplers, Res.ShaderStages, Res.Name, SamplerSuffix); + return FindImmutableSampler(Desc.ImmutableSamplers, Desc.NumImmutableSamplers, Res.ShaderStages, Res.Name, SamplerSuffix); } } // namespace @@ -443,8 +443,8 @@ void PipelineResourceSignatureVkImpl::CreateSetLayouts(const CacheOffsetsType& C // Only search for immutable sampler for combined image samplers and separate samplers. // Note that for DescriptorType::SeparateImage with immutable sampler, we will initialize // a separate immutable sampler below. It will not be assigned to the image variable. - const auto SrcImmutableSamplerInd = FindImmutableSampler(ResDesc, DescrType, m_Desc, GetCombinedSamplerSuffix()); - if (SrcImmutableSamplerInd >= 0) + const auto SrcImmutableSamplerInd = FindImmutableSamplerVk(ResDesc, DescrType, m_Desc, GetCombinedSamplerSuffix()); + if (SrcImmutableSamplerInd != InvalidImmutableSamplerIndex) { auto& ImmutableSampler = m_ImmutableSamplers[SrcImmutableSamplerInd]; const auto& ImmutableSamplerDesc = m_Desc.ImmutableSamplers[SrcImmutableSamplerInd].Desc; @@ -1592,14 +1592,17 @@ bool PipelineResourceSignatureVkImpl::IsBound(Uint32 Array #ifdef DILIGENT_DEVELOPMENT bool PipelineResourceSignatureVkImpl::DvpValidateCommittedResource(const SPIRVShaderResourceAttribs& SPIRVAttribs, Uint32 ResIndex, - ShaderResourceCacheVk& ResourceCache) const + const ShaderResourceCacheVk& ResourceCache, + const char* ShaderName, + const char* PSOName) const { VERIFY_EXPR(ResIndex < m_Desc.NumResources); - const auto& ResInfo = m_Desc.Resources[ResIndex]; + const auto& ResDesc = m_Desc.Resources[ResIndex]; const auto& ResAttribs = m_pResourceAttribs[ResIndex]; - VERIFY(strcmp(ResInfo.Name, SPIRVAttribs.Name) == 0, "Inconsistent resource names"); + VERIFY(strcmp(ResDesc.Name, SPIRVAttribs.Name) == 0, "Inconsistent resource names"); - bool BindingsOK = true; + if (ResDesc.ResourceType == SHADER_RESOURCE_TYPE_SAMPLER && ResAttribs.IsImmutableSamplerAssigned()) + return true; // Skip immutable separate samplers const auto& DescrSetResources = ResourceCache.GetDescriptorSet(ResAttribs.DescrSet); const auto CacheType = ResourceCache.GetContentType(); @@ -1607,16 +1610,43 @@ bool PipelineResourceSignatureVkImpl::DvpValidateCommittedResource(const SPIRVSh VERIFY_EXPR(SPIRVAttribs.ArraySize <= ResAttribs.ArraySize); - switch (ResAttribs.GetDescriptorType()) + bool BindingsOK = true; + for (Uint32 ArrIndex = 0; ArrIndex < SPIRVAttribs.ArraySize; ++ArrIndex) { - case DescriptorType::UniformBuffer: - case DescriptorType::UniformBufferDynamic: + if (!IsBound(ArrIndex, ResIndex, ResourceCache)) { - VERIFY_EXPR(ResInfo.ResourceType == SHADER_RESOURCE_TYPE_CONSTANT_BUFFER); - for (Uint32 i = 0; i < SPIRVAttribs.ArraySize; ++i) + LOG_ERROR_MESSAGE("No resource is bound to variable '", GetShaderResourcePrintName(SPIRVAttribs, 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()) { - const auto& Res = DescrSetResources.GetResource(CacheOffset + i); + 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 '", SPIRVAttribs.Name, "' in shader '", ShaderName, "' of PSO '", PSOName, "'."); + BindingsOK = false; + } + } + } + } + const auto& Res = DescrSetResources.GetResource(CacheOffset + ArrIndex); + switch (ResAttribs.GetDescriptorType()) + { + case DescriptorType::UniformBuffer: + case DescriptorType::UniformBufferDynamic: + VERIFY_EXPR(ResDesc.ResourceType == SHADER_RESOURCE_TYPE_CONSTANT_BUFFER); // 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* pBufferVk = Res.pObject.RawPtr<BufferVkImpl>()) @@ -1626,29 +1656,18 @@ bool PipelineResourceSignatureVkImpl::DvpValidateCommittedResource(const SPIRVSh // It is OK if robustBufferAccess feature is enabled, otherwise access outside of buffer range may lead to crash or undefined behavior. LOG_WARNING_MESSAGE("The size of uniform buffer '", pBufferVk->GetDesc().Name, "' bound to shader variable '", - GetShaderResourcePrintName(ResInfo, i), "' is ", pBufferVk->GetDesc().uiSizeInBytes, + GetShaderResourcePrintName(SPIRVAttribs, ArrIndex), "' is ", pBufferVk->GetDesc().uiSizeInBytes, " bytes, but the shader expects at least ", SPIRVAttribs.BufferStaticSize, " bytes."); } } - else - { - // Missing resource error is logged by BindResourceHelper::CacheUniformBuffer - } - } - } - break; - - case DescriptorType::StorageBuffer: - case DescriptorType::StorageBuffer_ReadOnly: - case DescriptorType::StorageBufferDynamic: - case DescriptorType::StorageBufferDynamic_ReadOnly: - { - VERIFY_EXPR(ResInfo.ResourceType == SHADER_RESOURCE_TYPE_BUFFER_UAV || ResInfo.ResourceType == SHADER_RESOURCE_TYPE_BUFFER_SRV); - for (Uint32 i = 0; i < SPIRVAttribs.ArraySize; ++i) - { - const auto& Res = DescrSetResources.GetResource(CacheOffset + i); + break; + case DescriptorType::StorageBuffer: + case DescriptorType::StorageBuffer_ReadOnly: + case DescriptorType::StorageBufferDynamic: + case DescriptorType::StorageBufferDynamic_ReadOnly: + VERIFY_EXPR(ResDesc.ResourceType == SHADER_RESOURCE_TYPE_BUFFER_UAV || ResDesc.ResourceType == SHADER_RESOURCE_TYPE_BUFFER_SRV); // 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 (auto* pBufferViewVk = Res.pObject.RawPtr<BufferViewVkImpl>()) @@ -1663,7 +1682,7 @@ bool PipelineResourceSignatureVkImpl::DvpValidateCommittedResource(const SPIRVSh { // It is OK if robustBufferAccess feature is enabled, otherwise access outside of buffer range may lead to crash or undefined behavior. LOG_WARNING_MESSAGE("The size of buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' bound to shader variable '", - GetShaderResourcePrintName(ResInfo, i), "' is ", ViewDesc.ByteWidth, " bytes, but the shader expects at least ", + GetShaderResourcePrintName(SPIRVAttribs, ArrIndex), "' is ", ViewDesc.ByteWidth, " bytes, but the shader expects at least ", SPIRVAttribs.BufferStaticSize, " bytes."); } } @@ -1675,44 +1694,33 @@ bool PipelineResourceSignatureVkImpl::DvpValidateCommittedResource(const SPIRVSh // Element stride in the shader may be differ than in the code. Here we check that the buffer size is exactly the same as the array with N elements. LOG_WARNING_MESSAGE("The size (", ViewDesc.ByteWidth, ") and stride (", BuffDesc.ElementByteStride, ") of buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' bound to shader variable '", - GetShaderResourcePrintName(ResInfo, i), "' are incompatible with what the shader expects. This may be the result of the array element size mismatch."); + GetShaderResourcePrintName(SPIRVAttribs, ArrIndex), "' are incompatible with what the shader expects. This may be the result of the array element size mismatch."); } } } - else - { - // Missing resource error is logged by BindResourceHelper::CacheStorageBuffer - } - } - } - break; + break; - case DescriptorType::StorageImage: - case DescriptorType::SeparateImage: - case DescriptorType::CombinedImageSampler: - { - VERIFY_EXPR(ResInfo.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_SRV || ResInfo.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_UAV); - for (Uint32 i = 0; i < SPIRVAttribs.ArraySize; ++i) - { - const auto& Res = DescrSetResources.GetResource(CacheOffset + i); + case DescriptorType::StorageImage: + case DescriptorType::SeparateImage: + case DescriptorType::CombinedImageSampler: + VERIFY_EXPR(ResDesc.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_SRV || ResDesc.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_UAV); // 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* pTexViewVk = Res.pObject.RawPtr<TextureViewVkImpl>()) { - if (!ValidateResourceViewDimension(ResInfo.Name, ResInfo.ArraySize, i, pTexViewVk, SPIRVAttribs.GetResourceDimension(), SPIRVAttribs.IsMultisample())) + if (!ValidateResourceViewDimension(SPIRVAttribs.Name, SPIRVAttribs.ArraySize, ArrIndex, pTexViewVk, SPIRVAttribs.GetResourceDimension(), SPIRVAttribs.IsMultisample())) BindingsOK = false; } else { // Missing resource error is logged by BindResourceHelper::CacheImage } - } - } - break; + break; - default: - break; - // Nothing to do + default: + break; + // Nothing to do + } } return BindingsOK; diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp index bab4d247..93262266 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp @@ -1109,7 +1109,8 @@ void PipelineStateVkImpl::DvpVerifySRBResources(SRBArray& SRBs) const const auto SignBindIndex = SignDesc.BindingIndex; if (auto* pSRB = SRBs[SignBindIndex]) { - res_info->Signature->DvpValidateCommittedResource(ResAttribs, res_info->ResIndex, pSRB->GetResourceCache()); + res_info->Signature->DvpValidateCommittedResource(ResAttribs, res_info->ResIndex, pSRB->GetResourceCache(), + pResources->GetShaderName(), m_Desc.Name); } else { |
