From a764fd27e4d6abfe6a8f62e3463bd88b132adc82 Mon Sep 17 00:00:00 2001 From: Egor Yusov Date: Wed, 9 Oct 2019 20:39:02 -0700 Subject: Unified resource binding verification in all backends --- .../include/ShaderResourceVariableBase.h | 179 +++++++++++++++++++++ 1 file changed, 179 insertions(+) (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/include/ShaderResourceVariableBase.h b/Graphics/GraphicsEngine/include/ShaderResourceVariableBase.h index 22d2d661..d49ea328 100644 --- a/Graphics/GraphicsEngine/include/ShaderResourceVariableBase.h +++ b/Graphics/GraphicsEngine/include/ShaderResourceVariableBase.h @@ -127,6 +127,185 @@ inline Int32 FindStaticSampler(const StaticSamplerDesc* StaticSamplers, return -1; } + + + +template +bool VerifyConstantBufferBinding(const ResourceAttribsType& Attribs, + SHADER_RESOURCE_VARIABLE_TYPE VarType, + Uint32 ArrayIndex, + const IDeviceObject* pBuffer, + const BufferImplType* pBufferImpl, + const IDeviceObject* pCachedBuffer, + const char* ShaderName = nullptr) +{ + if (pBuffer != nullptr && pBufferImpl == nullptr) + { + std::stringstream ss; + ss << "Failed to bind resource '" << pBuffer->GetDesc().Name << "' to variable '" << Attribs.GetPrintName(ArrayIndex) << '\''; + if (ShaderName != nullptr) + { + ss << " in shader '" << ShaderName << '\''; + } + ss << ". Invalid resource type: buffer is expected."; + LOG_ERROR_MESSAGE(ss.str()); + return false; + } + + bool BindingOK = true; + if (pBufferImpl != nullptr && (pBufferImpl->GetDesc().BindFlags & BIND_UNIFORM_BUFFER) == 0) + { + std::stringstream ss; + ss << "Error binding buffer '" << pBufferImpl->GetDesc().Name << "' to variable '" << Attribs.GetPrintName(ArrayIndex) << '\''; + if (ShaderName != nullptr) + { + ss << " in shader '" << ShaderName << '\''; + } + ss << ". The buffer was not created with BIND_UNIFORM_BUFFER flag."; + LOG_ERROR_MESSAGE(ss.str()); + BindingOK = false; + } + + if (VarType != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC && pCachedBuffer != nullptr && pCachedBuffer != pBufferImpl) + { + auto VarTypeStr = GetShaderVariableTypeLiteralName(VarType); + + std::stringstream ss; + ss << "Non-null constant (uniform) buffer '" << pCachedBuffer->GetDesc().Name << "' is already bound to " << VarTypeStr + << " shader variable '" << Attribs.GetPrintName(ArrayIndex) << '\''; + if (ShaderName != nullptr) + { + ss << " in shader '" << ShaderName << '\''; + } + ss << ". Attempting to bind "; + if (pBufferImpl) + { + ss << "another resource ('" << pBufferImpl->GetDesc().Name << "')"; + } + else + { + ss << "null"; + } + ss << " is an error and may cause unpredicted behavior. Use another shader resource binding instance or label the variable as dynamic."; + LOG_ERROR_MESSAGE(ss.str()); + + BindingOK = false; + } + + return BindingOK; +} + +template +const char* GetResourceTypeName(); + +template<> +inline const char* GetResourceTypeName() +{ + return "texture view"; +} + +template<> +inline const char* GetResourceTypeName() +{ + return "buffer view"; +} + +template +bool VerifyResourceViewBinding(const ResourceAttribsType& Attribs, + SHADER_RESOURCE_VARIABLE_TYPE VarType, + Uint32 ArrayIndex, + const IDeviceObject* pView, + const ResourceViewImplType* pViewImpl, + std::initializer_list ExpectedViewTypes, + const IDeviceObject* pCachedView, + const char* ShaderName = nullptr) +{ + const char* ExpectedResourceType = GetResourceTypeName(); + + if (pView && !pViewImpl) + { + std::stringstream ss; + ss << "Failed to bind resource '" << pView->GetDesc().Name << "' to variable '" << Attribs.GetPrintName(ArrayIndex) << '\''; + if (ShaderName != nullptr) + { + ss << " in shader '" << ShaderName << '\''; + } + ss << ". Invalid resource type: " << ExpectedResourceType << " is expected."; + LOG_ERROR_MESSAGE(ss.str()); + return false; + } + + bool BindingOK = true; + if (pViewImpl) + { + auto ViewType = pViewImpl->GetDesc().ViewType; + bool IsExpectedViewType = false; + for(auto ExpectedViewType : ExpectedViewTypes) + { + if (ExpectedViewType == ViewType) + IsExpectedViewType = true; + } + + if (!IsExpectedViewType) + { + std::string ExpectedViewTypeName; + + std::stringstream ss; + ss << "Error binding " << ExpectedResourceType << " '" << pViewImpl->GetDesc().Name << "' to variable '" + << Attribs.GetPrintName(ArrayIndex) << '\''; + if (ShaderName != nullptr) + { + ss << " in shader '" << ShaderName << '\''; + } + ss << ". Incorrect view type: "; + bool IsFirstViewType = true; + for(auto ExpectedViewType : ExpectedViewTypes) + { + if (!IsFirstViewType) + { + ss << " or "; + } + ss << GetViewTypeLiteralName(ExpectedViewType); + IsFirstViewType = false; + } + ss << " is expected, " << GetViewTypeLiteralName(ViewType) << " is provided."; + LOG_ERROR_MESSAGE(ss.str()); + + BindingOK = false; + } + } + + if (VarType != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC && pCachedView != nullptr && pCachedView != pViewImpl) + { + auto VarTypeStr = GetShaderVariableTypeLiteralName(VarType); + std::stringstream ss; + ss << "Non-null resource '" << pCachedView->GetDesc().Name << "' is already bound to " << VarTypeStr + << " shader variable '" << Attribs.GetPrintName(ArrayIndex) << '\''; + if (ShaderName != nullptr) + { + ss << " in shader '" << ShaderName << '\''; + } + ss << ". Attempting to bind "; + if (pViewImpl) + { + ss << "another resource ('" << pViewImpl->GetDesc().Name << "')"; + } + else + { + ss << "null"; + } + ss << " is an error and may cause unpredicted behavior. Use another shader resource binding instance or label the variable as dynamic."; + LOG_ERROR_MESSAGE(ss.str()); + + BindingOK = false; + } + return BindingOK; +} + + struct DefaultShaderVariableIDComparator { bool operator() (const INTERFACE_ID& IID)const -- cgit v1.2.3