diff --git a/engine/include/XCEngine/Rendering/RenderMaterialUtility.h b/engine/include/XCEngine/Rendering/RenderMaterialUtility.h index eb308314..59dfddd2 100644 --- a/engine/include/XCEngine/Rendering/RenderMaterialUtility.h +++ b/engine/include/XCEngine/Rendering/RenderMaterialUtility.h @@ -10,6 +10,7 @@ #include #include #include +#include #include namespace XCEngine { @@ -244,6 +245,71 @@ inline BuiltinPassResourceSemantic ResolveBuiltinPassResourceSemantic( return BuiltinPassResourceSemantic::Unknown; } +inline const char* BuiltinPassResourceSemanticToString(BuiltinPassResourceSemantic semantic) { + switch (semantic) { + case BuiltinPassResourceSemantic::PerObject: + return "PerObject"; + case BuiltinPassResourceSemantic::Material: + return "Material"; + case BuiltinPassResourceSemantic::Lighting: + return "Lighting"; + case BuiltinPassResourceSemantic::ShadowReceiver: + return "ShadowReceiver"; + case BuiltinPassResourceSemantic::BaseColorTexture: + return "BaseColorTexture"; + case BuiltinPassResourceSemantic::ShadowMapTexture: + return "ShadowMapTexture"; + case BuiltinPassResourceSemantic::LinearClampSampler: + return "LinearClampSampler"; + case BuiltinPassResourceSemantic::ShadowMapSampler: + return "ShadowMapSampler"; + case BuiltinPassResourceSemantic::Unknown: + default: + return "Unknown"; + } +} + +inline const char* ShaderResourceTypeToString(Resources::ShaderResourceType type) { + switch (type) { + case Resources::ShaderResourceType::ConstantBuffer: + return "ConstantBuffer"; + case Resources::ShaderResourceType::Texture2D: + return "Texture2D"; + case Resources::ShaderResourceType::TextureCube: + return "TextureCube"; + case Resources::ShaderResourceType::Sampler: + return "Sampler"; + default: + return "Unknown"; + } +} + +inline Containers::String DescribeShaderResourceBinding( + const Resources::ShaderResourceBindingDesc& binding) { + const BuiltinPassResourceSemantic resolvedSemantic = ResolveBuiltinPassResourceSemantic(binding); + return Containers::String("name=") + binding.name + + ", semantic=" + binding.semantic + + ", resolvedSemantic=" + Containers::String(BuiltinPassResourceSemanticToString(resolvedSemantic)) + + ", type=" + Containers::String(ShaderResourceTypeToString(binding.type)) + + ", set=" + Containers::String(std::to_string(binding.set).c_str()) + + ", binding=" + Containers::String(std::to_string(binding.binding).c_str()); +} + +inline Containers::String DescribeShaderResourceBindings( + const Containers::Array& bindings) { + Containers::String description; + for (size_t bindingIndex = 0; bindingIndex < bindings.Size(); ++bindingIndex) { + if (!description.Empty()) { + description += " | "; + } + + description += "[" + Containers::String(std::to_string(bindingIndex).c_str()) + "] "; + description += DescribeShaderResourceBinding(bindings[bindingIndex]); + } + + return description; +} + inline bool IsBuiltinPassResourceTypeCompatible( BuiltinPassResourceSemantic semantic, Resources::ShaderResourceType type) { diff --git a/engine/src/Rendering/Passes/BuiltinDepthStylePassBase.cpp b/engine/src/Rendering/Passes/BuiltinDepthStylePassBase.cpp index 08aa4fdd..38cd3879 100644 --- a/engine/src/Rendering/Passes/BuiltinDepthStylePassBase.cpp +++ b/engine/src/Rendering/Passes/BuiltinDepthStylePassBase.cpp @@ -422,7 +422,13 @@ BuiltinDepthStylePassBase::PassResourceLayout* BuiltinDepthStylePassBase::GetOrC BuiltinPassResourceBindingPlan bindingPlan = {}; Containers::String bindingPlanError; if (!TryBuildSupportedBindingPlan(*resolvedShaderPass.pass, bindingPlan, &bindingPlanError)) { - return failLayout(bindingPlanError.CStr()); + const Containers::String contextualError = + Containers::String("BuiltinDepthStylePassBase failed to resolve pass resource bindings for shader='") + + resolvedShaderPass.shader->GetPath() + + "', pass='" + resolvedShaderPass.passName + + "': " + bindingPlanError + + ". Bindings: " + DescribeShaderResourceBindings(resolvedShaderPass.pass->resources); + return failLayout(contextualError.CStr()); } std::vector setLayouts; diff --git a/engine/src/Rendering/Pipelines/BuiltinForwardPipeline.cpp b/engine/src/Rendering/Pipelines/BuiltinForwardPipeline.cpp index 6022500e..caeb961e 100644 --- a/engine/src/Rendering/Pipelines/BuiltinForwardPipeline.cpp +++ b/engine/src/Rendering/Pipelines/BuiltinForwardPipeline.cpp @@ -549,7 +549,13 @@ BuiltinForwardPipeline::PassResourceLayout* BuiltinForwardPipeline::GetOrCreateP BuiltinPassResourceBindingPlan bindingPlan = {}; Containers::String bindingPlanError; if (!TryBuildBuiltinPassResourceBindingPlan(resourceBindings, bindingPlan, &bindingPlanError)) { - return failLayout(bindingPlanError.CStr()); + const Containers::String contextualError = + Containers::String("BuiltinForwardPipeline failed to resolve pass resource bindings for shader='") + + resolvedShaderPass.shader->GetPath() + + "', pass='" + resolvedShaderPass.passName + + "': " + bindingPlanError + + ". Bindings: " + DescribeShaderResourceBindings(resourceBindings); + return failLayout(contextualError.CStr()); } const bool hasAnyResource = !bindingPlan.bindings.Empty();