diff options
| author | assiduous <assiduous@diligentgraphics.com> | 2021-01-28 21:22:04 +0000 |
|---|---|---|
| committer | assiduous <assiduous@diligentgraphics.com> | 2021-01-28 21:22:04 +0000 |
| commit | d4f3ca9fc42dfd8ba8a220a8c4355bde48359c00 (patch) | |
| tree | 4aea65cac0529c4f332330b9b87b3c5e71452733 /Graphics/GraphicsEngineVulkan | |
| parent | Device context Vk: added CommittedResourcesValidated to avoid calling DvpVali... (diff) | |
| download | DiligentCore-d4f3ca9fc42dfd8ba8a220a8c4355bde48359c00.tar.gz DiligentCore-d4f3ca9fc42dfd8ba8a220a8c4355bde48359c00.zip | |
Vk backend: added validation of parameters that can't be validated when resources are bound
Diffstat (limited to 'Graphics/GraphicsEngineVulkan')
8 files changed, 257 insertions, 54 deletions
diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineLayoutVk.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineLayoutVk.hpp index 87cf1da0..131a9006 100644 --- a/Graphics/GraphicsEngineVulkan/include/PipelineLayoutVk.hpp +++ b/Graphics/GraphicsEngineVulkan/include/PipelineLayoutVk.hpp @@ -69,10 +69,12 @@ public: struct ResourceInfo { - IPipelineResourceSignature* Signature = nullptr; - SHADER_RESOURCE_TYPE Type = SHADER_RESOURCE_TYPE_UNKNOWN; - Uint32 DescrSetIndex = 0; - Uint32 BindingIndex = 0; + PipelineResourceSignatureVkImpl* Signature = nullptr; + SHADER_RESOURCE_TYPE Type = SHADER_RESOURCE_TYPE_UNKNOWN; + // Index in m_Desc.Resources for a resource, or ~0U for an immutable sampler. + Uint32 ResIndex = 0; + Uint32 DescrSetIndex = 0; + Uint32 BindingIndex = 0; }; bool GetResourceInfo(const char* Name, SHADER_TYPE Stage, ResourceInfo& Info) const; diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineResourceSignatureVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineResourceSignatureVkImpl.hpp index 2fdb2ba8..8e8829f2 100644 --- a/Graphics/GraphicsEngineVulkan/include/PipelineResourceSignatureVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/PipelineResourceSignatureVkImpl.hpp @@ -42,6 +42,7 @@ namespace Diligent class RenderDeviceVkImpl; class ShaderResourceCacheVk; class ShaderVariableManagerVk; +struct SPIRVShaderResourceAttribs; enum class DescriptorType : Uint8 { @@ -53,9 +54,9 @@ enum class DescriptorType : Uint8 StorageTexelBuffer, StorageTexelBuffer_ReadOnly, UniformBuffer, + UniformBufferDynamic, StorageBuffer, StorageBuffer_ReadOnly, - UniformBufferDynamic, StorageBufferDynamic, StorageBufferDynamic_ReadOnly, InputAttachment, @@ -274,6 +275,10 @@ public: return GetHash() != Other.GetHash(); } +#ifdef DILIGENT_DEVELOPMENT + bool DvpValidateCommittedResource(const SPIRVShaderResourceAttribs& SPIRVAttribs, Uint32 ResIndex, ShaderResourceCacheVk& ResourceCache) const; +#endif + private: // Resource cache group identifier enum CACHE_GROUP : size_t diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp index 438b09e9..d65c85ac 100644 --- a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp @@ -31,6 +31,7 @@ /// Declaration of Diligent::PipelineStateVkImpl class #include <array> +#include <memory> #include "RenderDeviceVk.h" #include "PipelineStateVk.h" @@ -50,6 +51,7 @@ namespace Diligent class FixedBlockMemoryAllocator; class ShaderVariableManagerVk; class ShaderVkImpl; +class ShaderResourceBindingVkImpl; /// Pipeline state object implementation in Vulkan backend. class PipelineStateVkImpl final : public PipelineStateBase<IPipelineStateVk, RenderDeviceVkImpl> @@ -108,6 +110,13 @@ public: }; using TShaderStages = std::vector<ShaderStageInfo>; +#ifdef DILIGENT_DEVELOPMENT + // Performs validation of SRB resource parameters that are not possible to validate + // when resource is bound. + using SRBArray = std::array<ShaderResourceBindingVkImpl*, MAX_RESOURCE_SIGNATURES>; + void DvpVerifySRBResources(SRBArray& SRBs) const; +#endif + private: template <typename PSOCreateInfoType> TShaderStages InitInternalObjects(const PSOCreateInfoType& CreateInfo, @@ -126,6 +135,13 @@ private: VulkanUtilities::PipelineWrapper m_Pipeline; PipelineLayoutVk m_PipelineLayout; + +#ifdef DILIGENT_DEVELOPMENT + // Shader resources for all shaders in all shader stages + std::vector<std::shared_ptr<const SPIRVShaderResources>> m_ShaderResources; + // Resource info for every resource in m_ShaderResources, in the same order + std::vector<PipelineLayoutVk::ResourceInfo> m_ResInfo; +#endif }; } // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderVkImpl.hpp index e3bb52f6..804a1c84 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderVkImpl.hpp @@ -68,14 +68,13 @@ public: return m_SPIRV; } - const SPIRVShaderResources& GetShaderResources() const { return *m_pShaderResources; } + const std::shared_ptr<const SPIRVShaderResources>& GetShaderResources() const { return m_pShaderResources; } const char* GetEntryPoint() const { return m_EntryPoint.c_str(); } private: void MapHLSLVertexShaderInputs(); - // AZ TODO: remove shared pointer std::shared_ptr<const SPIRVShaderResources> m_pShaderResources; std::string m_EntryPoint; diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp index 4aba7d94..f03e6e07 100644 --- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp @@ -473,6 +473,8 @@ void DeviceContextVkImpl::DvpValidateCommittedShaderResources() } } + m_pPipelineState->DvpVerifySRBResources(BindInfo.Resources); + m_State.CommittedResourcesValidated = true; } #endif diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineLayoutVk.cpp index 3c0d642c..c10bffcd 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineLayoutVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineLayoutVk.cpp @@ -171,9 +171,9 @@ size_t PipelineLayoutVk::GetHash() const bool PipelineLayoutVk::GetResourceInfo(const char* Name, SHADER_TYPE Stage, ResourceInfo& Info) const { - for (Uint32 i = 0, DSCount = GetSignatureCount(); i < DSCount; ++i) + for (Uint32 sign = 0, SignCount = GetSignatureCount(); sign < SignCount; ++sign) { - auto* pSignature = GetSignature(i); + auto* const pSignature = GetSignature(sign); if (pSignature == nullptr) continue; @@ -185,8 +185,9 @@ bool PipelineLayoutVk::GetResourceInfo(const char* Name, SHADER_TYPE Stage, Reso if ((ResDesc.ShaderStages & Stage) && strcmp(ResDesc.Name, Name) == 0) { Info.Type = ResDesc.ResourceType; + Info.ResIndex = r; Info.BindingIndex = Attr.BindingIndex; - Info.DescrSetIndex = m_FirstDescrSetIndex[i] + Attr.DescrSet; + Info.DescrSetIndex = m_FirstDescrSetIndex[sign] + Attr.DescrSet; Info.Signature = pSignature; return true; } @@ -200,8 +201,9 @@ bool PipelineLayoutVk::GetResourceInfo(const char* Name, SHADER_TYPE Stage, Reso if (Attr.Ptr && (Desc.ShaderStages & Stage) && StreqSuff(Name, Desc.SamplerOrTextureName, pSignature->GetCombinedSamplerSuffix())) { Info.Type = SHADER_RESOURCE_TYPE_SAMPLER; + Info.ResIndex = ~0U; Info.BindingIndex = Attr.BindingIndex; - Info.DescrSetIndex = m_FirstDescrSetIndex[i] + Attr.DescrSet; + Info.DescrSetIndex = m_FirstDescrSetIndex[sign] + Attr.DescrSet; Info.Signature = pSignature; return true; } diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineResourceSignatureVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineResourceSignatureVkImpl.cpp index 28a11445..408a784a 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineResourceSignatureVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineResourceSignatureVkImpl.cpp @@ -35,6 +35,7 @@ #include "TopLevelASVkImpl.hpp" #include "BasicMath.hpp" #include "DynamicLinearAllocator.hpp" +#include "SPIRVShaderResources.hpp" namespace Diligent { @@ -1131,20 +1132,12 @@ void PipelineResourceSignatureVkImpl::CommitDynamicResources(const ShaderResourc String PipelineResourceSignatureVkImpl::GetPrintName(const PipelineResourceDesc& ResDesc, Uint32 ArrayInd) { - VERIFY_EXPR(ArrayInd < ResDesc.ArraySize); - - if (ResDesc.ArraySize > 1) - { - std::stringstream ss; - ss << ResDesc.Name << '[' << ArrayInd << ']'; - return ss.str(); - } - else - return ResDesc.Name; + return GetShaderResourcePrintName(ResDesc, ArrayInd); } namespace { + struct BindResourceHelper { ShaderResourceCacheVk::Resource& DstRes; @@ -1316,15 +1309,6 @@ void BindResourceHelper::CacheUniformBuffer(IDeviceObject* pBuffer, RefCntAutoPtr<BufferVkImpl> pBufferVk{pBuffer, IID_BufferVk}; #ifdef DILIGENT_DEVELOPMENT VerifyConstantBufferBinding(*this, ResDesc.VarType, ArrayIndex, pBuffer, pBufferVk.RawPtr(), DstRes.pObject.RawPtr()); - - // AZ TODO - /*if (pBufferVk->GetDesc().uiSizeInBytes < BufferStaticSize) - { - // It is OK if robustBufferAccess feature is enabled, otherwise access outside of buffer range may lead to crash or undefined behavior. - LOG_WARNING_MESSAGE("Error binding uniform buffer '", pBufferVk->GetDesc().Name, "' to shader variable '", - GetDesc().Name, "': buffer size in the shader (", - BufferStaticSize, ") is incompatible with the actual buffer size (", pBufferVk->GetDesc().uiSizeInBytes, ")."); - }*/ #endif auto UpdateDynamicBuffersCounter = [&DynamicBuffersCounter](const BufferVkImpl* pOldBuffer, const BufferVkImpl* pNewBuffer) { @@ -1377,25 +1361,6 @@ void BindResourceHelper::CacheStorageBuffer(IDeviceObject* pBufferView, LOG_ERROR_MESSAGE("Error binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' to shader variable '", ResDesc.Name, "': structured buffer view is expected."); } - - // AZ TODO - /*if (BufferStride == 0 && ViewDesc.ByteWidth < BufferStaticSize) - { - // It is OK if robustBufferAccess feature is enabled, otherwise access outside of buffer range may lead to crash or undefined behavior. - LOG_WARNING_MESSAGE("Error binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' to shader variable '", - Name, "': buffer size in the shader (", - BufferStaticSize, ") is incompatible with the actual buffer view size (", ViewDesc.ByteWidth, ")."); - } - - if (BufferStride > 0 && (ViewDesc.ByteWidth < BufferStaticSize || (ViewDesc.ByteWidth - BufferStaticSize) % BufferStride != 0)) - { - // For buffers with dynamic arrays we know only static part size and array element stride. - // 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("Error binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' to shader variable '", - Name, "': static buffer size in the shader (", - BufferStaticSize, ") and array element stride (", BufferStride, ") are incompatible with the actual buffer view size (", ViewDesc.ByteWidth, "),", - " this may be the result of the array element size mismatch."); - }*/ } } #endif @@ -1671,12 +1636,16 @@ String BindResourceHelper::GetPrintName(Uint32 ArrayInd) const RESOURCE_DIMENSION BindResourceHelper::GetResourceDimension() const { - return RESOURCE_DIM_UNDEFINED; // AZ TODO + // Required resource dimension is not known to the root signature as + // shader resources are only known to PSO. + return RESOURCE_DIM_UNDEFINED; } bool BindResourceHelper::IsMultisample() const { - return false; // AZ TODO + // Required multisample state is not known to the root signature as + // shader resources are only known to PSO. + return false; } } // namespace @@ -1707,4 +1676,171 @@ void PipelineResourceSignatureVkImpl::BindResource(IDeviceObject* pObj, Helper.BindResource(pObj); } +template <typename TextureViewImplType> +bool ValidateTextureDimension(const PipelineResourceDesc& ResDesc, + Uint32 ArrayInd, + const TextureViewImplType* pTexView, + RESOURCE_DIMENSION ExpectedResourceDim, + bool IsMultisample) +{ + VERIFY_EXPR(ExpectedResourceDim != RESOURCE_DIM_UNDEFINED); + + bool BindingsOK = true; + + const auto ResourceDim = pTexView->GetDesc().TextureDim; + if (ResourceDim != ExpectedResourceDim) + { + LOG_ERROR_MESSAGE("The resource dimension of texture view '", pTexView->GetDesc().Name, + "' bound to variable '", GetShaderResourcePrintName(ResDesc, ArrayInd), "' is ", GetResourceDimString(ResourceDim), + ", but resource dimension expected by the shader is ", GetResourceDimString(ExpectedResourceDim), "."); + } + + if (ResourceDim == RESOURCE_DIM_TEX_2D || ResourceDim == RESOURCE_DIM_TEX_2D_ARRAY) + { + auto SampleCount = pTexView->GetTexture()->GetDesc().SampleCount; + if (IsMultisample && SampleCount == 1) + { + LOG_ERROR_MESSAGE("Texture view '", pTexView->GetDesc().Name, "' bound to variable '", + GetShaderResourcePrintName(ResDesc, ArrayInd), "' is invalid: multisample texture is expected."); + BindingsOK = false; + } + else if (!IsMultisample && SampleCount > 1) + { + LOG_ERROR_MESSAGE("Texture view '", pTexView->GetDesc().Name, "' bound to variable '", + GetShaderResourcePrintName(ResDesc, ArrayInd), "' is invalid: single-sample texture is expected."); + BindingsOK = false; + } + } + + return BindingsOK; +} + +#ifdef DILIGENT_DEVELOPMENT +bool PipelineResourceSignatureVkImpl::DvpValidateCommittedResource(const SPIRVShaderResourceAttribs& SPIRVAttribs, + Uint32 ResIndex, + ShaderResourceCacheVk& ResourceCache) const +{ + VERIFY_EXPR(ResIndex < m_Desc.NumResources); + const auto& ResInfo = m_Desc.Resources[ResIndex]; + const auto& ResAttribs = m_pResourceAttribs[ResIndex]; + VERIFY(strcmp(ResInfo.Name, SPIRVAttribs.Name) == 0, "Inconsistent resource names"); + + bool BindingsOK = true; + + const auto& DescrSetResources = ResourceCache.GetDescriptorSet(ResAttribs.DescrSet); + const auto CacheType = ResourceCache.GetContentType(); + const auto CacheOffset = ResAttribs.CacheOffset(CacheType); + + switch (ResAttribs.GetDescriptorType()) + { + case DescriptorType::UniformBuffer: + case DescriptorType::UniformBufferDynamic: + { + VERIFY_EXPR(ResInfo.ResourceType == SHADER_RESOURCE_TYPE_CONSTANT_BUFFER); + for (Uint32 i = 0; i < ResAttribs.ArraySize; ++i) + { + const auto& Res = DescrSetResources.GetResource(CacheOffset + i); + + // 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>()) + { + if (pBufferVk->GetDesc().uiSizeInBytes < SPIRVAttribs.BufferStaticSize) + { + // 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 '", + GetPrintName(ResInfo, i), "' 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 < ResAttribs.ArraySize; ++i) + { + const auto& Res = DescrSetResources.GetResource(CacheOffset + i); + + // 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>()) + { + const auto* pBufferVk = ValidatedCast<BufferVkImpl>(pBufferViewVk->GetBuffer()); + const auto& ViewDesc = pBufferViewVk->GetDesc(); + const auto& BuffDesc = pBufferVk->GetDesc(); + + if (BuffDesc.ElementByteStride == 0) + { + if (ViewDesc.ByteWidth < SPIRVAttribs.BufferStaticSize) + { + // 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 '", + GetPrintName(ResInfo, i), "' is ", ViewDesc.ByteWidth, " bytes, but the shader expects at least ", + SPIRVAttribs.BufferStaticSize, " bytes."); + } + } + else + { + if (ViewDesc.ByteWidth < SPIRVAttribs.BufferStaticSize || (ViewDesc.ByteWidth - SPIRVAttribs.BufferStaticSize) % BuffDesc.ElementByteStride != 0) + { + // For buffers with dynamic arrays we know only static part size and array element stride. + // 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 '", + GetPrintName(ResInfo, i), "' 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; + + 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 < ResAttribs.ArraySize; ++i) + { + const auto& Res = DescrSetResources.GetResource(CacheOffset + i); + // 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 (!ValidateTextureDimension(ResInfo, i, pTexViewVk, SPIRVAttribs.GetResourceDimension(), SPIRVAttribs.IsMultisample())) + BindingsOK = false; + } + else + { + // Missing resource error is logged by BindResourceHelper::CacheImage + } + } + } + break; + + default: + break; + // Nothing to do + } + + return BindingsOK; +} +#endif + } // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp index ce53ed59..ac260c8d 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp @@ -36,6 +36,7 @@ #include "ShaderResourceBindingVkImpl.hpp" #include "EngineMemory.h" #include "StringTools.hpp" +#include "ShaderResourceBindingVkImpl.hpp" #if !DILIGENT_NO_HLSL @@ -750,8 +751,8 @@ void PipelineStateVkImpl::InitPipelineLayout(const PipelineStateCreateInfo& Crea UniqueNames.clear(); for (auto* pShader : Stage.Shaders) { - const auto DefaultVarType = LayoutDesc.DefaultVariableType; - auto& ShaderResources = pShader->GetShaderResources(); + const auto DefaultVarType = LayoutDesc.DefaultVariableType; + const auto& ShaderResources = *pShader->GetShaderResources(); ShaderResources.ProcessResources( [&](const SPIRVShaderResourceAttribs& Res, Uint32) // @@ -849,7 +850,12 @@ void PipelineStateVkImpl::InitPipelineLayout(const PipelineStateCreateInfo& Crea auto* pShader = Shaders[i]; auto& SPIRV = SPIRVs[i]; - pShader->GetShaderResources().ProcessResources( + const auto& pShaderResources = pShader->GetShaderResources(); +#ifdef DILIGENT_DEVELOPMENT + m_ShaderResources.emplace_back(pShaderResources); +#endif + + pShaderResources->ProcessResources( [&](const SPIRVShaderResourceAttribs& Res, Uint32) // { PipelineLayoutVk::ResourceInfo Info; @@ -872,6 +878,10 @@ void PipelineStateVkImpl::InitPipelineLayout(const PipelineStateCreateInfo& Crea SPIRV[Res.BindingDecorationOffset] = Info.BindingIndex; SPIRV[Res.DescriptorSetDecorationOffset] = Info.DescrSetIndex; + +#ifdef DILIGENT_DEVELOPMENT + m_ResInfo.emplace_back(Info); +#endif }); } } @@ -1016,4 +1026,35 @@ bool PipelineStateVkImpl::IsCompatibleWith(const IPipelineState* pPSO) const return false; } +#ifdef DILIGENT_DEVELOPMENT +void PipelineStateVkImpl::DvpVerifySRBResources(SRBArray& SRBs) const +{ + auto res_info = m_ResInfo.begin(); + for (const auto& pResources : m_ShaderResources) + { + pResources->ProcessResources( + [&](const SPIRVShaderResourceAttribs& ResAttribs, Uint32) // + { + if (res_info->ResIndex != ~0u) // There are also immutable samplers in the list + { + VERIFY_EXPR(res_info->Signature != nullptr); + const auto& SignDesc = res_info->Signature->GetDesc(); + const auto SignBindIndex = SignDesc.BindingIndex; + if (auto* pSRB = SRBs[SignBindIndex]) + { + res_info->Signature->DvpValidateCommittedResource(ResAttribs, res_info->ResIndex, pSRB->GetResourceCache()); + } + else + { + LOG_ERROR_MESSAGE("No SRB is bound to binding index ", SignBindIndex, " for signature '", SignDesc.Name, '\''); + } + } + ++res_info; + } // + ); + } + VERIFY_EXPR(res_info == m_ResInfo.end()); +} +#endif + } // namespace Diligent |
