From 2c96f0d164c6f98f26ba57afb3b413ca9f8eb948 Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Sun, 5 Apr 2026 15:44:37 +0800 Subject: [PATCH] Formalize forward lighting contract --- .../shaders/forward-lit/forward-lit.frag.glsl | 7 +- .../forward-lit/forward-lit.frag.vk.glsl | 15 ++-- .../shaders/forward-lit/forward-lit.ps.hlsl | 7 +- .../shaders/forward-lit/forward-lit.shader | 13 +-- .../shaders/forward-lit/forward-lit.vert.glsl | 2 - .../forward-lit/forward-lit.vert.vk.glsl | 2 - .../shaders/forward-lit/forward-lit.vs.hlsl | 2 - .../builtin/shaders/unlit/unlit.frag.glsl | 2 - .../builtin/shaders/unlit/unlit.frag.vk.glsl | 2 - .../builtin/shaders/unlit/unlit.ps.hlsl | 2 - .../builtin/shaders/unlit/unlit.vert.glsl | 2 - .../builtin/shaders/unlit/unlit.vert.vk.glsl | 2 - .../builtin/shaders/unlit/unlit.vs.hlsl | 2 - .../Pipelines/BuiltinForwardPipeline.h | 5 ++ .../Rendering/RenderMaterialUtility.h | 15 ++++ .../Pipelines/BuiltinForwardPipeline.cpp | 23 +++++- .../unit/test_builtin_forward_pipeline.cpp | 81 +++++++++++-------- tests/Resources/Shader/test_shader_loader.cpp | 58 ++++++++----- 18 files changed, 152 insertions(+), 90 deletions(-) diff --git a/engine/assets/builtin/shaders/forward-lit/forward-lit.frag.glsl b/engine/assets/builtin/shaders/forward-lit/forward-lit.frag.glsl index e64f6d6c..f0527efa 100644 --- a/engine/assets/builtin/shaders/forward-lit/forward-lit.frag.glsl +++ b/engine/assets/builtin/shaders/forward-lit/forward-lit.frag.glsl @@ -8,15 +8,18 @@ layout(std140, binding = 0) uniform PerObjectConstants { mat4 gViewMatrix; mat4 gModelMatrix; mat4 gNormalMatrix; +}; + +layout(std140, binding = 1) uniform LightingConstants { vec4 gMainLightDirectionAndIntensity; vec4 gMainLightColorAndFlags; }; -layout(std140, binding = 1) uniform MaterialConstants { +layout(std140, binding = 2) uniform MaterialConstants { vec4 gBaseColorFactor; }; -layout(std140, binding = 2) uniform ShadowReceiverConstants { +layout(std140, binding = 3) uniform ShadowReceiverConstants { mat4 gWorldToShadowMatrix; vec4 gShadowBiasAndTexelSize; vec4 gShadowOptions; diff --git a/engine/assets/builtin/shaders/forward-lit/forward-lit.frag.vk.glsl b/engine/assets/builtin/shaders/forward-lit/forward-lit.frag.vk.glsl index 71a371db..927e2116 100644 --- a/engine/assets/builtin/shaders/forward-lit/forward-lit.frag.vk.glsl +++ b/engine/assets/builtin/shaders/forward-lit/forward-lit.frag.vk.glsl @@ -1,24 +1,27 @@ // XC_BUILTIN_FORWARD_LIT_VULKAN_PS #version 450 -layout(set = 2, binding = 0) uniform texture2D uBaseColorTexture; -layout(set = 3, binding = 0) uniform sampler uLinearSampler; -layout(set = 5, binding = 0) uniform texture2D uShadowMapTexture; -layout(set = 6, binding = 0) uniform sampler uShadowMapSampler; +layout(set = 4, binding = 0) uniform texture2D uBaseColorTexture; +layout(set = 5, binding = 0) uniform sampler uLinearSampler; +layout(set = 6, binding = 0) uniform texture2D uShadowMapTexture; +layout(set = 7, binding = 0) uniform sampler uShadowMapSampler; layout(set = 0, binding = 0, std140) uniform PerObjectConstants { mat4 gProjectionMatrix; mat4 gViewMatrix; mat4 gModelMatrix; mat4 gNormalMatrix; +}; + +layout(set = 1, binding = 0, std140) uniform LightingConstants { vec4 gMainLightDirectionAndIntensity; vec4 gMainLightColorAndFlags; }; -layout(set = 1, binding = 0, std140) uniform MaterialConstants { +layout(set = 2, binding = 0, std140) uniform MaterialConstants { vec4 gBaseColorFactor; }; -layout(set = 4, binding = 0, std140) uniform ShadowReceiverConstants { +layout(set = 3, binding = 0, std140) uniform ShadowReceiverConstants { mat4 gWorldToShadowMatrix; vec4 gShadowBiasAndTexelSize; vec4 gShadowOptions; diff --git a/engine/assets/builtin/shaders/forward-lit/forward-lit.ps.hlsl b/engine/assets/builtin/shaders/forward-lit/forward-lit.ps.hlsl index 0207d080..a1444118 100644 --- a/engine/assets/builtin/shaders/forward-lit/forward-lit.ps.hlsl +++ b/engine/assets/builtin/shaders/forward-lit/forward-lit.ps.hlsl @@ -9,15 +9,18 @@ cbuffer PerObjectConstants : register(b0) { float4x4 gViewMatrix; float4x4 gModelMatrix; float4x4 gNormalMatrix; +}; + +cbuffer LightingConstants : register(b1) { float4 gMainLightDirectionAndIntensity; float4 gMainLightColorAndFlags; }; -cbuffer MaterialConstants : register(b1) { +cbuffer MaterialConstants : register(b2) { float4 gBaseColorFactor; }; -cbuffer ShadowReceiverConstants : register(b2) { +cbuffer ShadowReceiverConstants : register(b3) { float4x4 gWorldToShadowMatrix; float4 gShadowBiasAndTexelSize; float4 gShadowOptions; diff --git a/engine/assets/builtin/shaders/forward-lit/forward-lit.shader b/engine/assets/builtin/shaders/forward-lit/forward-lit.shader index 19bc05f7..36fe7c96 100644 --- a/engine/assets/builtin/shaders/forward-lit/forward-lit.shader +++ b/engine/assets/builtin/shaders/forward-lit/forward-lit.shader @@ -14,12 +14,13 @@ Shader "Builtin Forward Lit" Resources { PerObjectConstants (ConstantBuffer, 0, 0) [Semantic(PerObject)] - MaterialConstants (ConstantBuffer, 1, 0) [Semantic(Material)] - BaseColorTexture (Texture2D, 2, 0) [Semantic(BaseColorTexture)] - LinearClampSampler (Sampler, 3, 0) [Semantic(LinearClampSampler)] - ShadowReceiverConstants (ConstantBuffer, 4, 0) [Semantic(ShadowReceiver)] - ShadowMapTexture (Texture2D, 5, 0) [Semantic(ShadowMapTexture)] - ShadowMapSampler (Sampler, 6, 0) [Semantic(ShadowMapSampler)] + LightingConstants (ConstantBuffer, 1, 0) [Semantic(Lighting)] + MaterialConstants (ConstantBuffer, 2, 0) [Semantic(Material)] + ShadowReceiverConstants (ConstantBuffer, 3, 0) [Semantic(ShadowReceiver)] + BaseColorTexture (Texture2D, 4, 0) [Semantic(BaseColorTexture)] + LinearClampSampler (Sampler, 5, 0) [Semantic(LinearClampSampler)] + ShadowMapTexture (Texture2D, 6, 0) [Semantic(ShadowMapTexture)] + ShadowMapSampler (Sampler, 7, 0) [Semantic(ShadowMapSampler)] } HLSLPROGRAM #pragma vertex MainVS diff --git a/engine/assets/builtin/shaders/forward-lit/forward-lit.vert.glsl b/engine/assets/builtin/shaders/forward-lit/forward-lit.vert.glsl index d225070e..eea455f9 100644 --- a/engine/assets/builtin/shaders/forward-lit/forward-lit.vert.glsl +++ b/engine/assets/builtin/shaders/forward-lit/forward-lit.vert.glsl @@ -9,8 +9,6 @@ layout(std140, binding = 0) uniform PerObjectConstants { mat4 gViewMatrix; mat4 gModelMatrix; mat4 gNormalMatrix; - vec4 gMainLightDirectionAndIntensity; - vec4 gMainLightColorAndFlags; }; out vec3 vNormalWS; diff --git a/engine/assets/builtin/shaders/forward-lit/forward-lit.vert.vk.glsl b/engine/assets/builtin/shaders/forward-lit/forward-lit.vert.vk.glsl index bc22725d..ddc84830 100644 --- a/engine/assets/builtin/shaders/forward-lit/forward-lit.vert.vk.glsl +++ b/engine/assets/builtin/shaders/forward-lit/forward-lit.vert.vk.glsl @@ -9,8 +9,6 @@ layout(set = 0, binding = 0, std140) uniform PerObjectConstants { mat4 gViewMatrix; mat4 gModelMatrix; mat4 gNormalMatrix; - vec4 gMainLightDirectionAndIntensity; - vec4 gMainLightColorAndFlags; }; layout(location = 0) out vec3 vNormalWS; diff --git a/engine/assets/builtin/shaders/forward-lit/forward-lit.vs.hlsl b/engine/assets/builtin/shaders/forward-lit/forward-lit.vs.hlsl index 1e655dd8..fcc747a6 100644 --- a/engine/assets/builtin/shaders/forward-lit/forward-lit.vs.hlsl +++ b/engine/assets/builtin/shaders/forward-lit/forward-lit.vs.hlsl @@ -4,8 +4,6 @@ cbuffer PerObjectConstants : register(b0) { float4x4 gViewMatrix; float4x4 gModelMatrix; float4x4 gNormalMatrix; - float4 gMainLightDirectionAndIntensity; - float4 gMainLightColorAndFlags; }; struct VSInput { diff --git a/engine/assets/builtin/shaders/unlit/unlit.frag.glsl b/engine/assets/builtin/shaders/unlit/unlit.frag.glsl index 5ebb93b5..ffa81606 100644 --- a/engine/assets/builtin/shaders/unlit/unlit.frag.glsl +++ b/engine/assets/builtin/shaders/unlit/unlit.frag.glsl @@ -7,8 +7,6 @@ layout(std140, binding = 0) uniform PerObjectConstants { mat4 gViewMatrix; mat4 gModelMatrix; mat4 gNormalMatrix; - vec4 gMainLightDirectionAndIntensity; - vec4 gMainLightColorAndFlags; }; layout(std140, binding = 1) uniform MaterialConstants { diff --git a/engine/assets/builtin/shaders/unlit/unlit.frag.vk.glsl b/engine/assets/builtin/shaders/unlit/unlit.frag.vk.glsl index 1c7ecb3e..a6acae3c 100644 --- a/engine/assets/builtin/shaders/unlit/unlit.frag.vk.glsl +++ b/engine/assets/builtin/shaders/unlit/unlit.frag.vk.glsl @@ -8,8 +8,6 @@ layout(set = 0, binding = 0, std140) uniform PerObjectConstants { mat4 gViewMatrix; mat4 gModelMatrix; mat4 gNormalMatrix; - vec4 gMainLightDirectionAndIntensity; - vec4 gMainLightColorAndFlags; }; layout(set = 1, binding = 0, std140) uniform MaterialConstants { diff --git a/engine/assets/builtin/shaders/unlit/unlit.ps.hlsl b/engine/assets/builtin/shaders/unlit/unlit.ps.hlsl index cd80cd29..cfb44b89 100644 --- a/engine/assets/builtin/shaders/unlit/unlit.ps.hlsl +++ b/engine/assets/builtin/shaders/unlit/unlit.ps.hlsl @@ -7,8 +7,6 @@ cbuffer PerObjectConstants : register(b0) { float4x4 gViewMatrix; float4x4 gModelMatrix; float4x4 gNormalMatrix; - float4 gMainLightDirectionAndIntensity; - float4 gMainLightColorAndFlags; }; cbuffer MaterialConstants : register(b1) { diff --git a/engine/assets/builtin/shaders/unlit/unlit.vert.glsl b/engine/assets/builtin/shaders/unlit/unlit.vert.glsl index fe7fad2d..8a73bced 100644 --- a/engine/assets/builtin/shaders/unlit/unlit.vert.glsl +++ b/engine/assets/builtin/shaders/unlit/unlit.vert.glsl @@ -9,8 +9,6 @@ layout(std140, binding = 0) uniform PerObjectConstants { mat4 gViewMatrix; mat4 gModelMatrix; mat4 gNormalMatrix; - vec4 gMainLightDirectionAndIntensity; - vec4 gMainLightColorAndFlags; }; out vec2 vTexCoord; diff --git a/engine/assets/builtin/shaders/unlit/unlit.vert.vk.glsl b/engine/assets/builtin/shaders/unlit/unlit.vert.vk.glsl index e4cd2459..0aafa5c8 100644 --- a/engine/assets/builtin/shaders/unlit/unlit.vert.vk.glsl +++ b/engine/assets/builtin/shaders/unlit/unlit.vert.vk.glsl @@ -9,8 +9,6 @@ layout(set = 0, binding = 0, std140) uniform PerObjectConstants { mat4 gViewMatrix; mat4 gModelMatrix; mat4 gNormalMatrix; - vec4 gMainLightDirectionAndIntensity; - vec4 gMainLightColorAndFlags; }; layout(location = 0) out vec2 vTexCoord; diff --git a/engine/assets/builtin/shaders/unlit/unlit.vs.hlsl b/engine/assets/builtin/shaders/unlit/unlit.vs.hlsl index 9dfaf3fb..52d6e61b 100644 --- a/engine/assets/builtin/shaders/unlit/unlit.vs.hlsl +++ b/engine/assets/builtin/shaders/unlit/unlit.vs.hlsl @@ -4,8 +4,6 @@ cbuffer PerObjectConstants : register(b0) { float4x4 gViewMatrix; float4x4 gModelMatrix; float4x4 gNormalMatrix; - float4 gMainLightDirectionAndIntensity; - float4 gMainLightColorAndFlags; }; struct VSInput { diff --git a/engine/include/XCEngine/Rendering/Pipelines/BuiltinForwardPipeline.h b/engine/include/XCEngine/Rendering/Pipelines/BuiltinForwardPipeline.h index efcc77e5..67a4839c 100644 --- a/engine/include/XCEngine/Rendering/Pipelines/BuiltinForwardPipeline.h +++ b/engine/include/XCEngine/Rendering/Pipelines/BuiltinForwardPipeline.h @@ -64,6 +64,9 @@ private: Math::Matrix4x4 view = Math::Matrix4x4::Identity(); Math::Matrix4x4 model = Math::Matrix4x4::Identity(); Math::Matrix4x4 normalMatrix = Math::Matrix4x4::Identity(); + }; + + struct LightingConstants { Math::Vector4 mainLightDirectionAndIntensity = Math::Vector4::Zero(); Math::Vector4 mainLightColorAndFlags = Math::Vector4::Zero(); }; @@ -103,6 +106,7 @@ private: std::vector staticDescriptorSets; PassResourceBindingLocation perObject = {}; PassResourceBindingLocation material = {}; + PassResourceBindingLocation lighting = {}; PassResourceBindingLocation shadowReceiver = {}; PassResourceBindingLocation baseColorTexture = {}; PassResourceBindingLocation linearClampSampler = {}; @@ -200,6 +204,7 @@ private: Core::uint64 objectId, const Resources::Material* material, const MaterialConstantPayloadView& materialConstants, + const LightingConstants& lightingConstants, const ShadowReceiverConstants& shadowReceiverConstants, RHI::RHIResourceView* baseColorTextureView, RHI::RHIResourceView* shadowMapTextureView); diff --git a/engine/include/XCEngine/Rendering/RenderMaterialUtility.h b/engine/include/XCEngine/Rendering/RenderMaterialUtility.h index f16d5c3a..eb308314 100644 --- a/engine/include/XCEngine/Rendering/RenderMaterialUtility.h +++ b/engine/include/XCEngine/Rendering/RenderMaterialUtility.h @@ -37,6 +37,7 @@ enum class BuiltinPassResourceSemantic : Core::uint8 { Unknown = 0, PerObject, Material, + Lighting, ShadowReceiver, BaseColorTexture, ShadowMapTexture, @@ -60,6 +61,7 @@ struct BuiltinPassResourceBindingPlan { bool usesSamplers = false; PassResourceBindingLocation perObject = {}; PassResourceBindingLocation material = {}; + PassResourceBindingLocation lighting = {}; PassResourceBindingLocation shadowReceiver = {}; PassResourceBindingLocation baseColorTexture = {}; PassResourceBindingLocation linearClampSampler = {}; @@ -84,6 +86,7 @@ struct BuiltinPassSetLayoutMetadata { bool shaderVisible = false; bool usesPerObject = false; bool usesMaterial = false; + bool usesLighting = false; bool usesShadowReceiver = false; bool usesTexture = false; bool usesBaseColorTexture = false; @@ -209,6 +212,11 @@ inline BuiltinPassResourceSemantic ResolveBuiltinPassResourceSemantic( return BuiltinPassResourceSemantic::Material; } + if (semantic == Containers::String("lighting") || + semantic == Containers::String("lightingconstants")) { + return BuiltinPassResourceSemantic::Lighting; + } + if (semantic == Containers::String("shadowreceiver") || semantic == Containers::String("shadowreceiverconstants")) { return BuiltinPassResourceSemantic::ShadowReceiver; @@ -242,6 +250,7 @@ inline bool IsBuiltinPassResourceTypeCompatible( switch (semantic) { case BuiltinPassResourceSemantic::PerObject: case BuiltinPassResourceSemantic::Material: + case BuiltinPassResourceSemantic::Lighting: case BuiltinPassResourceSemantic::ShadowReceiver: return type == Resources::ShaderResourceType::ConstantBuffer; case BuiltinPassResourceSemantic::BaseColorTexture: @@ -295,6 +304,9 @@ inline bool TryBuildBuiltinPassResourceBindingPlan( case BuiltinPassResourceSemantic::Material: location = &outPlan.material; break; + case BuiltinPassResourceSemantic::Lighting: + location = &outPlan.lighting; + break; case BuiltinPassResourceSemantic::ShadowReceiver: location = &outPlan.shadowReceiver; break; @@ -488,6 +500,9 @@ inline bool TryBuildBuiltinPassSetLayouts( case BuiltinPassResourceSemantic::Material: setLayout.usesMaterial = true; break; + case BuiltinPassResourceSemantic::Lighting: + setLayout.usesLighting = true; + break; case BuiltinPassResourceSemantic::ShadowReceiver: setLayout.usesShadowReceiver = true; break; diff --git a/engine/src/Rendering/Pipelines/BuiltinForwardPipeline.cpp b/engine/src/Rendering/Pipelines/BuiltinForwardPipeline.cpp index eec843b3..99f384a3 100644 --- a/engine/src/Rendering/Pipelines/BuiltinForwardPipeline.cpp +++ b/engine/src/Rendering/Pipelines/BuiltinForwardPipeline.cpp @@ -561,6 +561,7 @@ BuiltinForwardPipeline::PassResourceLayout* BuiltinForwardPipeline::GetOrCreateP passLayout.perObject = bindingPlan.perObject; passLayout.material = bindingPlan.material; + passLayout.lighting = bindingPlan.lighting; passLayout.shadowReceiver = bindingPlan.shadowReceiver; passLayout.baseColorTexture = bindingPlan.baseColorTexture; passLayout.linearClampSampler = bindingPlan.linearClampSampler; @@ -570,6 +571,10 @@ BuiltinForwardPipeline::PassResourceLayout* BuiltinForwardPipeline::GetOrCreateP if (!passLayout.perObject.IsValid()) { return failLayout("BuiltinForwardPipeline requires a PerObject resource binding"); } + if (ShaderPassMatchesBuiltinPass(*resolvedShaderPass.pass, BuiltinMaterialPass::ForwardLit) && + !passLayout.lighting.IsValid()) { + return failLayout("BuiltinForwardPipeline forward-lit pass requires a Lighting resource binding"); + } std::vector nativeSetLayouts(passLayout.setLayouts.size()); for (size_t i = 0; i < passLayout.setLayouts.size(); ++i) { @@ -718,6 +723,7 @@ BuiltinForwardPipeline::CachedDescriptorSet* BuiltinForwardPipeline::GetOrCreate Core::uint64 objectId, const Resources::Material* material, const MaterialConstantPayloadView& materialConstants, + const LightingConstants& lightingConstants, const ShadowReceiverConstants& shadowReceiverConstants, RHI::RHIResourceView* baseColorTextureView, RHI::RHIResourceView* shadowMapTextureView) { @@ -750,6 +756,16 @@ BuiltinForwardPipeline::CachedDescriptorSet* BuiltinForwardPipeline::GetOrCreate } } + if (setLayout.usesLighting) { + if (!passLayout.lighting.IsValid() || passLayout.lighting.set != setIndex) { + return nullptr; + } + cachedDescriptorSet.descriptorSet.set->WriteConstant( + passLayout.lighting.binding, + &lightingConstants, + sizeof(lightingConstants)); + } + if (setLayout.usesShadowReceiver) { if (!passLayout.shadowReceiver.IsValid() || passLayout.shadowReceiver.set != setIndex) { return nullptr; @@ -824,6 +840,7 @@ void BuiltinForwardPipeline::DestroyPassResourceLayout(PassResourceLayout& passL passLayout.descriptorSetCount = 0; passLayout.perObject = {}; passLayout.material = {}; + passLayout.lighting = {}; passLayout.shadowReceiver = {}; passLayout.baseColorTexture = {}; passLayout.linearClampSampler = {}; @@ -872,7 +889,9 @@ bool BuiltinForwardPipeline::DrawVisibleItem( sceneData.cameraData.projection, sceneData.cameraData.view, visibleItem.localToWorld.Transpose(), - visibleItem.localToWorld.Inverse(), + visibleItem.localToWorld.Inverse() + }; + const LightingConstants lightingConstants = { sceneData.lighting.HasMainDirectionalLight() ? Math::Vector4( sceneData.lighting.mainDirectionalLight.direction.x, @@ -961,6 +980,7 @@ bool BuiltinForwardPipeline::DrawVisibleItem( RHI::RHIDescriptorSet* descriptorSet = nullptr; if (setLayout.usesPerObject || + setLayout.usesLighting || setLayout.usesMaterial || setLayout.usesShadowReceiver || setLayout.usesTexture) { @@ -979,6 +999,7 @@ bool BuiltinForwardPipeline::DrawVisibleItem( objectId, materialKey, materialConstants, + lightingConstants, shadowReceiverConstants, baseColorTextureView, shadowMapTextureView); diff --git a/tests/Rendering/unit/test_builtin_forward_pipeline.cpp b/tests/Rendering/unit/test_builtin_forward_pipeline.cpp index 6e41fd2a..10061d3e 100644 --- a/tests/Rendering/unit/test_builtin_forward_pipeline.cpp +++ b/tests/Rendering/unit/test_builtin_forward_pipeline.cpp @@ -55,43 +55,48 @@ TEST(BuiltinForwardPipeline_Test, BuiltinForwardShaderDeclaresExplicitForwardRes const ShaderPass* pass = shader->FindPass("ForwardLit"); ASSERT_NE(pass, nullptr); - ASSERT_EQ(pass->resources.Size(), 7u); + ASSERT_EQ(pass->resources.Size(), 8u); EXPECT_EQ(pass->resources[0].semantic, "PerObject"); EXPECT_EQ(pass->resources[0].type, ShaderResourceType::ConstantBuffer); EXPECT_EQ(pass->resources[0].set, 0u); EXPECT_EQ(pass->resources[0].binding, 0u); - EXPECT_EQ(pass->resources[1].semantic, "Material"); + EXPECT_EQ(pass->resources[1].semantic, "Lighting"); EXPECT_EQ(pass->resources[1].type, ShaderResourceType::ConstantBuffer); EXPECT_EQ(pass->resources[1].set, 1u); EXPECT_EQ(pass->resources[1].binding, 0u); - EXPECT_EQ(pass->resources[2].semantic, "BaseColorTexture"); - EXPECT_EQ(pass->resources[2].type, ShaderResourceType::Texture2D); + EXPECT_EQ(pass->resources[2].semantic, "Material"); + EXPECT_EQ(pass->resources[2].type, ShaderResourceType::ConstantBuffer); EXPECT_EQ(pass->resources[2].set, 2u); EXPECT_EQ(pass->resources[2].binding, 0u); - EXPECT_EQ(pass->resources[3].semantic, "LinearClampSampler"); - EXPECT_EQ(pass->resources[3].type, ShaderResourceType::Sampler); + EXPECT_EQ(pass->resources[3].semantic, "ShadowReceiver"); + EXPECT_EQ(pass->resources[3].type, ShaderResourceType::ConstantBuffer); EXPECT_EQ(pass->resources[3].set, 3u); EXPECT_EQ(pass->resources[3].binding, 0u); - EXPECT_EQ(pass->resources[4].semantic, "ShadowReceiver"); - EXPECT_EQ(pass->resources[4].type, ShaderResourceType::ConstantBuffer); + EXPECT_EQ(pass->resources[4].semantic, "BaseColorTexture"); + EXPECT_EQ(pass->resources[4].type, ShaderResourceType::Texture2D); EXPECT_EQ(pass->resources[4].set, 4u); EXPECT_EQ(pass->resources[4].binding, 0u); - EXPECT_EQ(pass->resources[5].semantic, "ShadowMapTexture"); - EXPECT_EQ(pass->resources[5].type, ShaderResourceType::Texture2D); + EXPECT_EQ(pass->resources[5].semantic, "LinearClampSampler"); + EXPECT_EQ(pass->resources[5].type, ShaderResourceType::Sampler); EXPECT_EQ(pass->resources[5].set, 5u); EXPECT_EQ(pass->resources[5].binding, 0u); - EXPECT_EQ(pass->resources[6].semantic, "ShadowMapSampler"); - EXPECT_EQ(pass->resources[6].type, ShaderResourceType::Sampler); + EXPECT_EQ(pass->resources[6].semantic, "ShadowMapTexture"); + EXPECT_EQ(pass->resources[6].type, ShaderResourceType::Texture2D); EXPECT_EQ(pass->resources[6].set, 6u); EXPECT_EQ(pass->resources[6].binding, 0u); + EXPECT_EQ(pass->resources[7].semantic, "ShadowMapSampler"); + EXPECT_EQ(pass->resources[7].type, ShaderResourceType::Sampler); + EXPECT_EQ(pass->resources[7].set, 7u); + EXPECT_EQ(pass->resources[7].binding, 0u); + delete shader; } @@ -147,6 +152,7 @@ TEST(BuiltinForwardPipeline_Test, BuildsBuiltinPassResourceBindingPlanFromExplic String error; EXPECT_TRUE(TryBuildBuiltinPassResourceBindingPlan(pass->resources, plan, &error)) << error.CStr(); EXPECT_TRUE(plan.perObject.IsValid()); + EXPECT_TRUE(plan.lighting.IsValid()); EXPECT_TRUE(plan.material.IsValid()); EXPECT_TRUE(plan.shadowReceiver.IsValid()); EXPECT_TRUE(plan.baseColorTexture.IsValid()); @@ -154,7 +160,7 @@ TEST(BuiltinForwardPipeline_Test, BuildsBuiltinPassResourceBindingPlanFromExplic EXPECT_TRUE(plan.shadowMapTexture.IsValid()); EXPECT_TRUE(plan.shadowMapSampler.IsValid()); EXPECT_EQ(plan.firstDescriptorSet, 0u); - EXPECT_EQ(plan.descriptorSetCount, 7u); + EXPECT_EQ(plan.descriptorSetCount, 8u); EXPECT_TRUE(plan.usesConstantBuffers); EXPECT_TRUE(plan.usesTextures); EXPECT_TRUE(plan.usesSamplers); @@ -201,19 +207,20 @@ TEST(BuiltinForwardPipeline_Test, UsesNormalizedExplicitSetIndicesForSurfaceReso const ShaderPass* pass = shader->FindPass("ForwardLit"); ASSERT_NE(pass, nullptr); - ASSERT_EQ(pass->resources.Size(), 7u); + ASSERT_EQ(pass->resources.Size(), 8u); BuiltinPassResourceBindingPlan plan = {}; String error; EXPECT_TRUE(TryBuildBuiltinPassResourceBindingPlan(pass->resources, plan, &error)) << error.CStr(); - ASSERT_EQ(plan.bindings.Size(), 7u); + ASSERT_EQ(plan.bindings.Size(), 8u); EXPECT_EQ(plan.perObject.set, 0u); - EXPECT_EQ(plan.material.set, 1u); - EXPECT_EQ(plan.baseColorTexture.set, 2u); - EXPECT_EQ(plan.linearClampSampler.set, 3u); - EXPECT_EQ(plan.shadowReceiver.set, 4u); - EXPECT_EQ(plan.shadowMapTexture.set, 5u); - EXPECT_EQ(plan.shadowMapSampler.set, 6u); + EXPECT_EQ(plan.lighting.set, 1u); + EXPECT_EQ(plan.material.set, 2u); + EXPECT_EQ(plan.shadowReceiver.set, 3u); + EXPECT_EQ(plan.baseColorTexture.set, 4u); + EXPECT_EQ(plan.linearClampSampler.set, 5u); + EXPECT_EQ(plan.shadowMapTexture.set, 6u); + EXPECT_EQ(plan.shadowMapSampler.set, 7u); delete shader; } @@ -229,7 +236,7 @@ TEST(BuiltinPassLayout_Test, BuildsSharedSetLayoutsFromExplicitForwardResources) const ShaderPass* pass = shader->FindPass("ForwardLit"); ASSERT_NE(pass, nullptr); - ASSERT_EQ(pass->resources.Size(), 7u); + ASSERT_EQ(pass->resources.Size(), 8u); BuiltinPassResourceBindingPlan plan = {}; String error; @@ -237,7 +244,7 @@ TEST(BuiltinPassLayout_Test, BuildsSharedSetLayoutsFromExplicitForwardResources) std::vector setLayouts; ASSERT_TRUE(TryBuildBuiltinPassSetLayouts(plan, setLayouts, &error)) << error.CStr(); - ASSERT_EQ(setLayouts.size(), 7u); + ASSERT_EQ(setLayouts.size(), 8u); EXPECT_EQ(setLayouts[0].layout.bindingCount, 1u); EXPECT_FALSE(setLayouts[0].shaderVisible); @@ -245,31 +252,35 @@ TEST(BuiltinPassLayout_Test, BuildsSharedSetLayoutsFromExplicitForwardResources) EXPECT_FALSE(setLayouts[0].usesMaterial); EXPECT_EQ(setLayouts[1].layout.bindingCount, 1u); - EXPECT_TRUE(setLayouts[1].usesMaterial); + EXPECT_TRUE(setLayouts[1].usesLighting); EXPECT_FALSE(setLayouts[1].shaderVisible); EXPECT_EQ(setLayouts[2].layout.bindingCount, 1u); - EXPECT_TRUE(setLayouts[2].usesTexture); - EXPECT_TRUE(setLayouts[2].shaderVisible); - EXPECT_EQ(setLayouts[2].heapType, DescriptorHeapType::CBV_SRV_UAV); + EXPECT_TRUE(setLayouts[2].usesMaterial); + EXPECT_FALSE(setLayouts[2].shaderVisible); EXPECT_EQ(setLayouts[3].layout.bindingCount, 1u); - EXPECT_TRUE(setLayouts[3].usesSampler); - EXPECT_TRUE(setLayouts[3].shaderVisible); - EXPECT_EQ(setLayouts[3].heapType, DescriptorHeapType::Sampler); + EXPECT_TRUE(setLayouts[3].usesShadowReceiver); + EXPECT_FALSE(setLayouts[3].shaderVisible); EXPECT_EQ(setLayouts[4].layout.bindingCount, 1u); - EXPECT_TRUE(setLayouts[4].usesShadowReceiver); - EXPECT_FALSE(setLayouts[4].shaderVisible); + EXPECT_TRUE(setLayouts[4].usesTexture); + EXPECT_TRUE(setLayouts[4].shaderVisible); + EXPECT_EQ(setLayouts[4].heapType, DescriptorHeapType::CBV_SRV_UAV); EXPECT_EQ(setLayouts[5].layout.bindingCount, 1u); - EXPECT_TRUE(setLayouts[5].usesTexture); + EXPECT_TRUE(setLayouts[5].usesSampler); EXPECT_TRUE(setLayouts[5].shaderVisible); + EXPECT_EQ(setLayouts[5].heapType, DescriptorHeapType::Sampler); EXPECT_EQ(setLayouts[6].layout.bindingCount, 1u); - EXPECT_TRUE(setLayouts[6].usesSampler); + EXPECT_TRUE(setLayouts[6].usesTexture); EXPECT_TRUE(setLayouts[6].shaderVisible); - EXPECT_EQ(setLayouts[6].heapType, DescriptorHeapType::Sampler); + + EXPECT_EQ(setLayouts[7].layout.bindingCount, 1u); + EXPECT_TRUE(setLayouts[7].usesSampler); + EXPECT_TRUE(setLayouts[7].shaderVisible); + EXPECT_EQ(setLayouts[7].heapType, DescriptorHeapType::Sampler); delete shader; } diff --git a/tests/Resources/Shader/test_shader_loader.cpp b/tests/Resources/Shader/test_shader_loader.cpp index b9f93ae0..f4fb2810 100644 --- a/tests/Resources/Shader/test_shader_loader.cpp +++ b/tests/Resources/Shader/test_shader_loader.cpp @@ -135,12 +135,13 @@ TEST(ShaderLoader, LoadShaderManifestBuildsMultiPassBackendVariants) { manifest << " },\n"; manifest << " \"resources\": [\n"; manifest << " { \"name\": \"PerObjectConstants\", \"type\": \"ConstantBuffer\", \"set\": 1, \"binding\": 0, \"semantic\": \"PerObject\" },\n"; - manifest << " { \"name\": \"MaterialConstants\", \"type\": \"ConstantBuffer\", \"set\": 2, \"binding\": 0, \"semantic\": \"Material\" },\n"; - manifest << " { \"name\": \"BaseColorTexture\", \"type\": \"Texture2D\", \"set\": 3, \"binding\": 0, \"semantic\": \"BaseColorTexture\" },\n"; - manifest << " { \"name\": \"LinearClampSampler\", \"type\": \"Sampler\", \"set\": 4, \"binding\": 0, \"semantic\": \"LinearClampSampler\" },\n"; - manifest << " { \"name\": \"ShadowReceiverConstants\", \"type\": \"ConstantBuffer\", \"set\": 5, \"binding\": 0, \"semantic\": \"ShadowReceiver\" },\n"; - manifest << " { \"name\": \"ShadowMapTexture\", \"type\": \"Texture2D\", \"set\": 6, \"binding\": 0, \"semantic\": \"ShadowMapTexture\" },\n"; - manifest << " { \"name\": \"ShadowMapSampler\", \"type\": \"Sampler\", \"set\": 7, \"binding\": 0, \"semantic\": \"ShadowMapSampler\" }\n"; + manifest << " { \"name\": \"LightingConstants\", \"type\": \"ConstantBuffer\", \"set\": 2, \"binding\": 0, \"semantic\": \"Lighting\" },\n"; + manifest << " { \"name\": \"MaterialConstants\", \"type\": \"ConstantBuffer\", \"set\": 3, \"binding\": 0, \"semantic\": \"Material\" },\n"; + manifest << " { \"name\": \"ShadowReceiverConstants\", \"type\": \"ConstantBuffer\", \"set\": 4, \"binding\": 0, \"semantic\": \"ShadowReceiver\" },\n"; + manifest << " { \"name\": \"BaseColorTexture\", \"type\": \"Texture2D\", \"set\": 5, \"binding\": 0, \"semantic\": \"BaseColorTexture\" },\n"; + manifest << " { \"name\": \"LinearClampSampler\", \"type\": \"Sampler\", \"set\": 6, \"binding\": 0, \"semantic\": \"LinearClampSampler\" },\n"; + manifest << " { \"name\": \"ShadowMapTexture\", \"type\": \"Texture2D\", \"set\": 7, \"binding\": 0, \"semantic\": \"ShadowMapTexture\" },\n"; + manifest << " { \"name\": \"ShadowMapSampler\", \"type\": \"Sampler\", \"set\": 8, \"binding\": 0, \"semantic\": \"ShadowMapSampler\" }\n"; manifest << " ],\n"; manifest << " \"variants\": [\n"; manifest << " { \"stage\": \"Vertex\", \"backend\": \"D3D12\", \"language\": \"HLSL\", \"source\": \"stages/forward_lit.vs.hlsl\", \"entryPoint\": \"MainVS\", \"profile\": \"vs_5_0\" },\n"; @@ -193,7 +194,7 @@ TEST(ShaderLoader, LoadShaderManifestBuildsMultiPassBackendVariants) { const ShaderPass* forwardLitPass = shader->FindPass("ForwardLit"); ASSERT_NE(forwardLitPass, nullptr); ASSERT_EQ(forwardLitPass->tags.Size(), 2u); - ASSERT_EQ(forwardLitPass->resources.Size(), 7u); + ASSERT_EQ(forwardLitPass->resources.Size(), 8u); EXPECT_EQ(forwardLitPass->tags[0].name, "LightMode"); EXPECT_EQ(forwardLitPass->tags[0].value, "ForwardBase"); EXPECT_EQ(forwardLitPass->tags[1].name, "Queue"); @@ -203,7 +204,7 @@ TEST(ShaderLoader, LoadShaderManifestBuildsMultiPassBackendVariants) { shader->FindPassResourceBinding("ForwardLit", "BaseColorTexture"); ASSERT_NE(baseTextureBinding, nullptr); EXPECT_EQ(baseTextureBinding->type, ShaderResourceType::Texture2D); - EXPECT_EQ(baseTextureBinding->set, 3u); + EXPECT_EQ(baseTextureBinding->set, 5u); EXPECT_EQ(baseTextureBinding->binding, 0u); EXPECT_EQ(baseTextureBinding->semantic, "BaseColorTexture"); @@ -274,12 +275,13 @@ TEST(ShaderLoader, LoadUnityLikeShaderAuthoringBuildsRuntimeContract) { Resources { PerObjectConstants (ConstantBuffer, 1, 0) [Semantic(PerObject)] - MaterialConstants (ConstantBuffer, 2, 0) [Semantic(Material)] - BaseColorTexture (Texture2D, 3, 0) [Semantic(BaseColorTexture)] - LinearClampSampler (Sampler, 4, 0) [Semantic(LinearClampSampler)] - ShadowReceiverConstants (ConstantBuffer, 5, 0) [Semantic(ShadowReceiver)] - ShadowMapTexture (Texture2D, 6, 0) [Semantic(ShadowMapTexture)] - ShadowMapSampler (Sampler, 7, 0) [Semantic(ShadowMapSampler)] + LightingConstants (ConstantBuffer, 2, 0) [Semantic(Lighting)] + MaterialConstants (ConstantBuffer, 3, 0) [Semantic(Material)] + ShadowReceiverConstants (ConstantBuffer, 4, 0) [Semantic(ShadowReceiver)] + BaseColorTexture (Texture2D, 5, 0) [Semantic(BaseColorTexture)] + LinearClampSampler (Sampler, 6, 0) [Semantic(LinearClampSampler)] + ShadowMapTexture (Texture2D, 7, 0) [Semantic(ShadowMapTexture)] + ShadowMapSampler (Sampler, 8, 0) [Semantic(ShadowMapSampler)] } HLSLPROGRAM #pragma vertex MainVS @@ -331,7 +333,7 @@ TEST(ShaderLoader, LoadUnityLikeShaderAuthoringBuildsRuntimeContract) { const ShaderPass* forwardLitPass = shader->FindPass("ForwardLit"); ASSERT_NE(forwardLitPass, nullptr); ASSERT_EQ(forwardLitPass->tags.Size(), 2u); - ASSERT_EQ(forwardLitPass->resources.Size(), 7u); + ASSERT_EQ(forwardLitPass->resources.Size(), 8u); EXPECT_EQ(forwardLitPass->tags[0].name, "Queue"); EXPECT_EQ(forwardLitPass->tags[0].value, "Geometry"); EXPECT_EQ(forwardLitPass->tags[1].name, "LightMode"); @@ -341,7 +343,7 @@ TEST(ShaderLoader, LoadUnityLikeShaderAuthoringBuildsRuntimeContract) { shader->FindPassResourceBinding("ForwardLit", "BaseColorTexture"); ASSERT_NE(baseTextureBinding, nullptr); EXPECT_EQ(baseTextureBinding->type, ShaderResourceType::Texture2D); - EXPECT_EQ(baseTextureBinding->set, 3u); + EXPECT_EQ(baseTextureBinding->set, 5u); EXPECT_EQ(baseTextureBinding->binding, 0u); EXPECT_EQ(baseTextureBinding->semantic, "BaseColorTexture"); @@ -677,7 +679,7 @@ TEST(ShaderLoader, LoadBuiltinForwardLitShaderBuildsBackendVariants) { ASSERT_EQ(shader->GetProperties().Size(), 2u); ASSERT_EQ(pass->variants.Size(), 6u); ASSERT_EQ(pass->tags.Size(), 1u); - ASSERT_EQ(pass->resources.Size(), 7u); + ASSERT_EQ(pass->resources.Size(), 8u); EXPECT_EQ(pass->tags[0].name, "LightMode"); EXPECT_EQ(pass->tags[0].value, "ForwardBase"); @@ -695,18 +697,34 @@ TEST(ShaderLoader, LoadBuiltinForwardLitShaderBuildsBackendVariants) { shader->FindPassResourceBinding("ForwardLit", "PerObjectConstants"); ASSERT_NE(perObjectBinding, nullptr); EXPECT_EQ(perObjectBinding->type, ShaderResourceType::ConstantBuffer); - EXPECT_EQ(perObjectBinding->set, 1u); + EXPECT_EQ(perObjectBinding->set, 0u); EXPECT_EQ(perObjectBinding->binding, 0u); EXPECT_EQ(perObjectBinding->semantic, "PerObject"); + const ShaderResourceBindingDesc* lightingBinding = + shader->FindPassResourceBinding("ForwardLit", "LightingConstants"); + ASSERT_NE(lightingBinding, nullptr); + EXPECT_EQ(lightingBinding->type, ShaderResourceType::ConstantBuffer); + EXPECT_EQ(lightingBinding->set, 1u); + EXPECT_EQ(lightingBinding->binding, 0u); + EXPECT_EQ(lightingBinding->semantic, "Lighting"); + const ShaderResourceBindingDesc* shadowReceiverBinding = shader->FindPassResourceBinding("ForwardLit", "ShadowReceiverConstants"); ASSERT_NE(shadowReceiverBinding, nullptr); EXPECT_EQ(shadowReceiverBinding->type, ShaderResourceType::ConstantBuffer); - EXPECT_EQ(shadowReceiverBinding->set, 5u); + EXPECT_EQ(shadowReceiverBinding->set, 3u); EXPECT_EQ(shadowReceiverBinding->binding, 0u); EXPECT_EQ(shadowReceiverBinding->semantic, "ShadowReceiver"); + const ShaderResourceBindingDesc* baseColorBinding = + shader->FindPassResourceBinding("ForwardLit", "BaseColorTexture"); + ASSERT_NE(baseColorBinding, nullptr); + EXPECT_EQ(baseColorBinding->type, ShaderResourceType::Texture2D); + EXPECT_EQ(baseColorBinding->set, 4u); + EXPECT_EQ(baseColorBinding->binding, 0u); + EXPECT_EQ(baseColorBinding->semantic, "BaseColorTexture"); + const ShaderResourceBindingDesc* shadowTextureBinding = shader->FindPassResourceBinding("ForwardLit", "ShadowMapTexture"); ASSERT_NE(shadowTextureBinding, nullptr); @@ -779,7 +797,7 @@ TEST(ShaderLoader, LoadBuiltinUnlitShaderBuildsBackendVariants) { shader->FindPassResourceBinding("Unlit", "PerObjectConstants"); ASSERT_NE(perObjectBinding, nullptr); EXPECT_EQ(perObjectBinding->type, ShaderResourceType::ConstantBuffer); - EXPECT_EQ(perObjectBinding->set, 1u); + EXPECT_EQ(perObjectBinding->set, 0u); EXPECT_EQ(perObjectBinding->binding, 0u); EXPECT_EQ(perObjectBinding->semantic, "PerObject");