Normalize builtin forward shader bindings

This commit is contained in:
2026-04-05 13:50:52 +08:00
parent f407e2d15c
commit ec96d2c7e5
17 changed files with 131 additions and 150 deletions

View File

@@ -1,9 +1,9 @@
// XC_BUILTIN_FORWARD_LIT_OPENGL_PS // XC_BUILTIN_FORWARD_LIT_OPENGL_PS
#version 430 #version 430
layout(binding = 1) uniform sampler2D uBaseColorTexture; layout(binding = 0) uniform sampler2D uBaseColorTexture;
layout(binding = 2) uniform sampler2D uShadowMapTexture; layout(binding = 1) uniform sampler2D uShadowMapTexture;
layout(std140, binding = 1) uniform PerObjectConstants { layout(std140, binding = 0) uniform PerObjectConstants {
mat4 gProjectionMatrix; mat4 gProjectionMatrix;
mat4 gViewMatrix; mat4 gViewMatrix;
mat4 gModelMatrix; mat4 gModelMatrix;
@@ -12,11 +12,11 @@ layout(std140, binding = 1) uniform PerObjectConstants {
vec4 gMainLightColorAndFlags; vec4 gMainLightColorAndFlags;
}; };
layout(std140, binding = 2) uniform MaterialConstants { layout(std140, binding = 1) uniform MaterialConstants {
vec4 gBaseColorFactor; vec4 gBaseColorFactor;
}; };
layout(std140, binding = 3) uniform ShadowReceiverConstants { layout(std140, binding = 2) uniform ShadowReceiverConstants {
mat4 gWorldToShadowMatrix; mat4 gWorldToShadowMatrix;
vec4 gShadowBiasAndTexelSize; vec4 gShadowBiasAndTexelSize;
vec4 gShadowOptions; vec4 gShadowOptions;

View File

@@ -1,11 +1,11 @@
// XC_BUILTIN_FORWARD_LIT_VULKAN_PS // XC_BUILTIN_FORWARD_LIT_VULKAN_PS
#version 450 #version 450
layout(set = 3, binding = 0) uniform texture2D uBaseColorTexture; layout(set = 2, binding = 0) uniform texture2D uBaseColorTexture;
layout(set = 4, binding = 0) uniform sampler uLinearSampler; layout(set = 3, binding = 0) uniform sampler uLinearSampler;
layout(set = 6, binding = 0) uniform texture2D uShadowMapTexture; layout(set = 5, binding = 0) uniform texture2D uShadowMapTexture;
layout(set = 7, binding = 0) uniform sampler uShadowMapSampler; layout(set = 6, binding = 0) uniform sampler uShadowMapSampler;
layout(set = 1, binding = 0, std140) uniform PerObjectConstants { layout(set = 0, binding = 0, std140) uniform PerObjectConstants {
mat4 gProjectionMatrix; mat4 gProjectionMatrix;
mat4 gViewMatrix; mat4 gViewMatrix;
mat4 gModelMatrix; mat4 gModelMatrix;
@@ -14,11 +14,11 @@ layout(set = 1, binding = 0, std140) uniform PerObjectConstants {
vec4 gMainLightColorAndFlags; vec4 gMainLightColorAndFlags;
}; };
layout(set = 2, binding = 0, std140) uniform MaterialConstants { layout(set = 1, binding = 0, std140) uniform MaterialConstants {
vec4 gBaseColorFactor; vec4 gBaseColorFactor;
}; };
layout(set = 5, binding = 0, std140) uniform ShadowReceiverConstants { layout(set = 4, binding = 0, std140) uniform ShadowReceiverConstants {
mat4 gWorldToShadowMatrix; mat4 gWorldToShadowMatrix;
vec4 gShadowBiasAndTexelSize; vec4 gShadowBiasAndTexelSize;
vec4 gShadowOptions; vec4 gShadowOptions;

View File

@@ -1,10 +1,10 @@
// XC_BUILTIN_FORWARD_LIT_D3D12_PS // XC_BUILTIN_FORWARD_LIT_D3D12_PS
Texture2D gBaseColorTexture : register(t1); Texture2D gBaseColorTexture : register(t0);
SamplerState gLinearSampler : register(s1); SamplerState gLinearSampler : register(s0);
Texture2D gShadowMapTexture : register(t2); Texture2D gShadowMapTexture : register(t1);
SamplerState gShadowMapSampler : register(s2); SamplerState gShadowMapSampler : register(s1);
cbuffer PerObjectConstants : register(b1) { cbuffer PerObjectConstants : register(b0) {
float4x4 gProjectionMatrix; float4x4 gProjectionMatrix;
float4x4 gViewMatrix; float4x4 gViewMatrix;
float4x4 gModelMatrix; float4x4 gModelMatrix;
@@ -13,11 +13,11 @@ cbuffer PerObjectConstants : register(b1) {
float4 gMainLightColorAndFlags; float4 gMainLightColorAndFlags;
}; };
cbuffer MaterialConstants : register(b2) { cbuffer MaterialConstants : register(b1) {
float4 gBaseColorFactor; float4 gBaseColorFactor;
}; };
cbuffer ShadowReceiverConstants : register(b3) { cbuffer ShadowReceiverConstants : register(b2) {
float4x4 gWorldToShadowMatrix; float4x4 gWorldToShadowMatrix;
float4 gShadowBiasAndTexelSize; float4 gShadowBiasAndTexelSize;
float4 gShadowOptions; float4 gShadowOptions;

View File

@@ -13,13 +13,13 @@ Shader "Builtin Forward Lit"
Tags { "LightMode" = "ForwardBase" } Tags { "LightMode" = "ForwardBase" }
Resources Resources
{ {
PerObjectConstants (ConstantBuffer, 1, 0) [Semantic(PerObject)] PerObjectConstants (ConstantBuffer, 0, 0) [Semantic(PerObject)]
MaterialConstants (ConstantBuffer, 2, 0) [Semantic(Material)] MaterialConstants (ConstantBuffer, 1, 0) [Semantic(Material)]
BaseColorTexture (Texture2D, 3, 0) [Semantic(BaseColorTexture)] BaseColorTexture (Texture2D, 2, 0) [Semantic(BaseColorTexture)]
LinearClampSampler (Sampler, 4, 0) [Semantic(LinearClampSampler)] LinearClampSampler (Sampler, 3, 0) [Semantic(LinearClampSampler)]
ShadowReceiverConstants (ConstantBuffer, 5, 0) [Semantic(ShadowReceiver)] ShadowReceiverConstants (ConstantBuffer, 4, 0) [Semantic(ShadowReceiver)]
ShadowMapTexture (Texture2D, 6, 0) [Semantic(ShadowMapTexture)] ShadowMapTexture (Texture2D, 5, 0) [Semantic(ShadowMapTexture)]
ShadowMapSampler (Sampler, 7, 0) [Semantic(ShadowMapSampler)] ShadowMapSampler (Sampler, 6, 0) [Semantic(ShadowMapSampler)]
} }
HLSLPROGRAM HLSLPROGRAM
#pragma vertex MainVS #pragma vertex MainVS

View File

@@ -4,7 +4,7 @@ layout(location = 0) in vec3 aPosition;
layout(location = 1) in vec3 aNormal; layout(location = 1) in vec3 aNormal;
layout(location = 2) in vec2 aTexCoord; layout(location = 2) in vec2 aTexCoord;
layout(std140, binding = 1) uniform PerObjectConstants { layout(std140, binding = 0) uniform PerObjectConstants {
mat4 gProjectionMatrix; mat4 gProjectionMatrix;
mat4 gViewMatrix; mat4 gViewMatrix;
mat4 gModelMatrix; mat4 gModelMatrix;

View File

@@ -4,7 +4,7 @@ layout(location = 0) in vec3 aPosition;
layout(location = 1) in vec3 aNormal; layout(location = 1) in vec3 aNormal;
layout(location = 2) in vec2 aTexCoord; layout(location = 2) in vec2 aTexCoord;
layout(set = 1, binding = 0, std140) uniform PerObjectConstants { layout(set = 0, binding = 0, std140) uniform PerObjectConstants {
mat4 gProjectionMatrix; mat4 gProjectionMatrix;
mat4 gViewMatrix; mat4 gViewMatrix;
mat4 gModelMatrix; mat4 gModelMatrix;

View File

@@ -1,5 +1,5 @@
// XC_BUILTIN_FORWARD_LIT_D3D12_VS // XC_BUILTIN_FORWARD_LIT_D3D12_VS
cbuffer PerObjectConstants : register(b1) { cbuffer PerObjectConstants : register(b0) {
float4x4 gProjectionMatrix; float4x4 gProjectionMatrix;
float4x4 gViewMatrix; float4x4 gViewMatrix;
float4x4 gModelMatrix; float4x4 gModelMatrix;

View File

@@ -1,8 +1,8 @@
// XC_BUILTIN_UNLIT_OPENGL_PS // XC_BUILTIN_UNLIT_OPENGL_PS
#version 430 #version 430
layout(binding = 1) uniform sampler2D uBaseColorTexture; layout(binding = 0) uniform sampler2D uBaseColorTexture;
layout(std140, binding = 1) uniform PerObjectConstants { layout(std140, binding = 0) uniform PerObjectConstants {
mat4 gProjectionMatrix; mat4 gProjectionMatrix;
mat4 gViewMatrix; mat4 gViewMatrix;
mat4 gModelMatrix; mat4 gModelMatrix;
@@ -11,7 +11,7 @@ layout(std140, binding = 1) uniform PerObjectConstants {
vec4 gMainLightColorAndFlags; vec4 gMainLightColorAndFlags;
}; };
layout(std140, binding = 2) uniform MaterialConstants { layout(std140, binding = 1) uniform MaterialConstants {
vec4 gBaseColorFactor; vec4 gBaseColorFactor;
}; };

View File

@@ -1,9 +1,9 @@
// XC_BUILTIN_UNLIT_VULKAN_PS // XC_BUILTIN_UNLIT_VULKAN_PS
#version 450 #version 450
layout(set = 3, binding = 0) uniform texture2D uBaseColorTexture; layout(set = 2, binding = 0) uniform texture2D uBaseColorTexture;
layout(set = 4, binding = 0) uniform sampler uLinearSampler; layout(set = 3, binding = 0) uniform sampler uLinearSampler;
layout(set = 1, binding = 0, std140) uniform PerObjectConstants { layout(set = 0, binding = 0, std140) uniform PerObjectConstants {
mat4 gProjectionMatrix; mat4 gProjectionMatrix;
mat4 gViewMatrix; mat4 gViewMatrix;
mat4 gModelMatrix; mat4 gModelMatrix;
@@ -12,7 +12,7 @@ layout(set = 1, binding = 0, std140) uniform PerObjectConstants {
vec4 gMainLightColorAndFlags; vec4 gMainLightColorAndFlags;
}; };
layout(set = 2, binding = 0, std140) uniform MaterialConstants { layout(set = 1, binding = 0, std140) uniform MaterialConstants {
vec4 gBaseColorFactor; vec4 gBaseColorFactor;
}; };

View File

@@ -1,8 +1,8 @@
// XC_BUILTIN_UNLIT_D3D12_PS // XC_BUILTIN_UNLIT_D3D12_PS
Texture2D gBaseColorTexture : register(t1); Texture2D gBaseColorTexture : register(t0);
SamplerState gLinearSampler : register(s1); SamplerState gLinearSampler : register(s0);
cbuffer PerObjectConstants : register(b1) { cbuffer PerObjectConstants : register(b0) {
float4x4 gProjectionMatrix; float4x4 gProjectionMatrix;
float4x4 gViewMatrix; float4x4 gViewMatrix;
float4x4 gModelMatrix; float4x4 gModelMatrix;
@@ -11,7 +11,7 @@ cbuffer PerObjectConstants : register(b1) {
float4 gMainLightColorAndFlags; float4 gMainLightColorAndFlags;
}; };
cbuffer MaterialConstants : register(b2) { cbuffer MaterialConstants : register(b1) {
float4 gBaseColorFactor; float4 gBaseColorFactor;
}; };

View File

@@ -13,10 +13,10 @@ Shader "Builtin Unlit"
Tags { "LightMode" = "Unlit" } Tags { "LightMode" = "Unlit" }
Resources Resources
{ {
PerObjectConstants (ConstantBuffer, 1, 0) [Semantic(PerObject)] PerObjectConstants (ConstantBuffer, 0, 0) [Semantic(PerObject)]
MaterialConstants (ConstantBuffer, 2, 0) [Semantic(Material)] MaterialConstants (ConstantBuffer, 1, 0) [Semantic(Material)]
BaseColorTexture (Texture2D, 3, 0) [Semantic(BaseColorTexture)] BaseColorTexture (Texture2D, 2, 0) [Semantic(BaseColorTexture)]
LinearClampSampler (Sampler, 4, 0) [Semantic(LinearClampSampler)] LinearClampSampler (Sampler, 3, 0) [Semantic(LinearClampSampler)]
} }
HLSLPROGRAM HLSLPROGRAM
#pragma vertex MainVS #pragma vertex MainVS

View File

@@ -4,7 +4,7 @@ layout(location = 0) in vec3 aPosition;
layout(location = 1) in vec3 aNormal; layout(location = 1) in vec3 aNormal;
layout(location = 2) in vec2 aTexCoord; layout(location = 2) in vec2 aTexCoord;
layout(std140, binding = 1) uniform PerObjectConstants { layout(std140, binding = 0) uniform PerObjectConstants {
mat4 gProjectionMatrix; mat4 gProjectionMatrix;
mat4 gViewMatrix; mat4 gViewMatrix;
mat4 gModelMatrix; mat4 gModelMatrix;

View File

@@ -4,7 +4,7 @@ layout(location = 0) in vec3 aPosition;
layout(location = 1) in vec3 aNormal; layout(location = 1) in vec3 aNormal;
layout(location = 2) in vec2 aTexCoord; layout(location = 2) in vec2 aTexCoord;
layout(set = 1, binding = 0, std140) uniform PerObjectConstants { layout(set = 0, binding = 0, std140) uniform PerObjectConstants {
mat4 gProjectionMatrix; mat4 gProjectionMatrix;
mat4 gViewMatrix; mat4 gViewMatrix;
mat4 gModelMatrix; mat4 gModelMatrix;

View File

@@ -1,5 +1,5 @@
// XC_BUILTIN_UNLIT_D3D12_VS // XC_BUILTIN_UNLIT_D3D12_VS
cbuffer PerObjectConstants : register(b1) { cbuffer PerObjectConstants : register(b0) {
float4x4 gProjectionMatrix; float4x4 gProjectionMatrix;
float4x4 gViewMatrix; float4x4 gViewMatrix;
float4x4 gModelMatrix; float4x4 gModelMatrix;

View File

@@ -236,37 +236,6 @@ inline BuiltinPassResourceSemantic ResolveBuiltinPassResourceSemantic(
return BuiltinPassResourceSemantic::Unknown; return BuiltinPassResourceSemantic::Unknown;
} }
inline Containers::Array<Resources::ShaderResourceBindingDesc> BuildLegacyBuiltinForwardPassResourceBindings() {
Containers::Array<Resources::ShaderResourceBindingDesc> bindings;
bindings.Resize(4);
bindings[0].name = "PerObjectConstants";
bindings[0].type = Resources::ShaderResourceType::ConstantBuffer;
bindings[0].set = 1;
bindings[0].binding = 0;
bindings[0].semantic = "PerObject";
bindings[1].name = "MaterialConstants";
bindings[1].type = Resources::ShaderResourceType::ConstantBuffer;
bindings[1].set = 2;
bindings[1].binding = 0;
bindings[1].semantic = "Material";
bindings[2].name = "BaseColorTexture";
bindings[2].type = Resources::ShaderResourceType::Texture2D;
bindings[2].set = 3;
bindings[2].binding = 0;
bindings[2].semantic = "BaseColorTexture";
bindings[3].name = "LinearClampSampler";
bindings[3].type = Resources::ShaderResourceType::Sampler;
bindings[3].set = 4;
bindings[3].binding = 0;
bindings[3].semantic = "LinearClampSampler";
return bindings;
}
inline bool IsBuiltinPassResourceTypeCompatible( inline bool IsBuiltinPassResourceTypeCompatible(
BuiltinPassResourceSemantic semantic, BuiltinPassResourceSemantic semantic,
Resources::ShaderResourceType type) { Resources::ShaderResourceType type) {

View File

@@ -52,6 +52,11 @@ private:
namespace { namespace {
bool IsDepthFormat(RHI::Format format) {
return format == RHI::Format::D24_UNorm_S8_UInt ||
format == RHI::Format::D32_Float;
}
bool TryResolveSurfacePassType( bool TryResolveSurfacePassType(
const Resources::Material* material, const Resources::Material* material,
BuiltinMaterialPass& outPass) { BuiltinMaterialPass& outPass) {
@@ -283,7 +288,8 @@ bool BuiltinForwardPipeline::ExecuteForwardOpaquePass(const RenderPassContext& p
commandList->SetPrimitiveTopology(RHI::PrimitiveTopology::TriangleList); commandList->SetPrimitiveTopology(RHI::PrimitiveTopology::TriangleList);
if (sceneData.lighting.HasMainDirectionalShadow()) { if (sceneData.lighting.HasMainDirectionalShadow() &&
IsDepthFormat(sceneData.lighting.mainDirectionalShadow.shadowMap->GetFormat())) {
commandList->TransitionBarrier( commandList->TransitionBarrier(
sceneData.lighting.mainDirectionalShadow.shadowMap, sceneData.lighting.mainDirectionalShadow.shadowMap,
RHI::ResourceStates::DepthWrite, RHI::ResourceStates::DepthWrite,
@@ -310,7 +316,8 @@ bool BuiltinForwardPipeline::ExecuteForwardOpaquePass(const RenderPassContext& p
DrawVisibleItem(context, sceneData, visibleItem); DrawVisibleItem(context, sceneData, visibleItem);
} }
if (sceneData.lighting.HasMainDirectionalShadow()) { if (sceneData.lighting.HasMainDirectionalShadow() &&
IsDepthFormat(sceneData.lighting.mainDirectionalShadow.shadowMap->GetFormat())) {
commandList->TransitionBarrier( commandList->TransitionBarrier(
sceneData.lighting.mainDirectionalShadow.shadowMap, sceneData.lighting.mainDirectionalShadow.shadowMap,
RHI::ResourceStates::PixelShaderResource, RHI::ResourceStates::PixelShaderResource,
@@ -530,9 +537,9 @@ BuiltinForwardPipeline::PassResourceLayout* BuiltinForwardPipeline::GetOrCreateP
return nullptr; return nullptr;
}; };
Containers::Array<Resources::ShaderResourceBindingDesc> resourceBindings = resolvedShaderPass.pass->resources; const Containers::Array<Resources::ShaderResourceBindingDesc>& resourceBindings = resolvedShaderPass.pass->resources;
if (resourceBindings.Empty()) { if (resourceBindings.Empty()) {
resourceBindings = BuildLegacyBuiltinForwardPassResourceBindings(); return failLayout("BuiltinForwardPipeline requires explicit resource bindings on the resolved shader pass");
} }
BuiltinPassResourceBindingPlan bindingPlan = {}; BuiltinPassResourceBindingPlan bindingPlan = {};
@@ -564,38 +571,6 @@ BuiltinForwardPipeline::PassResourceLayout* BuiltinForwardPipeline::GetOrCreateP
return failLayout("BuiltinForwardPipeline requires a PerObject resource binding"); return failLayout("BuiltinForwardPipeline requires a PerObject resource binding");
} }
if (hasAnyResource &&
passLayout.firstDescriptorSet > 0 &&
!passLayout.setLayouts.empty() &&
passLayout.setLayouts[0].bindings.empty()) {
BuiltinPassSetLayoutMetadata& compatibilitySet = passLayout.setLayouts[0];
if (bindingPlan.usesConstantBuffers) {
compatibilitySet.bindings.push_back({
0,
static_cast<uint32_t>(RHI::DescriptorType::CBV),
1,
0
});
}
if (bindingPlan.usesTextures) {
compatibilitySet.bindings.push_back({
0,
static_cast<uint32_t>(RHI::DescriptorType::SRV),
1,
0
});
}
if (bindingPlan.usesSamplers) {
compatibilitySet.bindings.push_back({
0,
static_cast<uint32_t>(RHI::DescriptorType::Sampler),
1,
0
});
}
RefreshBuiltinPassSetLayoutMetadata(compatibilitySet);
}
std::vector<RHI::DescriptorSetLayoutDesc> nativeSetLayouts(passLayout.setLayouts.size()); std::vector<RHI::DescriptorSetLayoutDesc> nativeSetLayouts(passLayout.setLayouts.size());
for (size_t i = 0; i < passLayout.setLayouts.size(); ++i) { for (size_t i = 0; i < passLayout.setLayouts.size(); ++i) {
nativeSetLayouts[i] = passLayout.setLayouts[i].layout; nativeSetLayouts[i] = passLayout.setLayouts[i].layout;

View File

@@ -59,37 +59,37 @@ TEST(BuiltinForwardPipeline_Test, BuiltinForwardShaderDeclaresExplicitForwardRes
EXPECT_EQ(pass->resources[0].semantic, "PerObject"); EXPECT_EQ(pass->resources[0].semantic, "PerObject");
EXPECT_EQ(pass->resources[0].type, ShaderResourceType::ConstantBuffer); EXPECT_EQ(pass->resources[0].type, ShaderResourceType::ConstantBuffer);
EXPECT_EQ(pass->resources[0].set, 1u); EXPECT_EQ(pass->resources[0].set, 0u);
EXPECT_EQ(pass->resources[0].binding, 0u); EXPECT_EQ(pass->resources[0].binding, 0u);
EXPECT_EQ(pass->resources[1].semantic, "Material"); EXPECT_EQ(pass->resources[1].semantic, "Material");
EXPECT_EQ(pass->resources[1].type, ShaderResourceType::ConstantBuffer); EXPECT_EQ(pass->resources[1].type, ShaderResourceType::ConstantBuffer);
EXPECT_EQ(pass->resources[1].set, 2u); EXPECT_EQ(pass->resources[1].set, 1u);
EXPECT_EQ(pass->resources[1].binding, 0u); EXPECT_EQ(pass->resources[1].binding, 0u);
EXPECT_EQ(pass->resources[2].semantic, "BaseColorTexture"); EXPECT_EQ(pass->resources[2].semantic, "BaseColorTexture");
EXPECT_EQ(pass->resources[2].type, ShaderResourceType::Texture2D); EXPECT_EQ(pass->resources[2].type, ShaderResourceType::Texture2D);
EXPECT_EQ(pass->resources[2].set, 3u); EXPECT_EQ(pass->resources[2].set, 2u);
EXPECT_EQ(pass->resources[2].binding, 0u); EXPECT_EQ(pass->resources[2].binding, 0u);
EXPECT_EQ(pass->resources[3].semantic, "LinearClampSampler"); EXPECT_EQ(pass->resources[3].semantic, "LinearClampSampler");
EXPECT_EQ(pass->resources[3].type, ShaderResourceType::Sampler); EXPECT_EQ(pass->resources[3].type, ShaderResourceType::Sampler);
EXPECT_EQ(pass->resources[3].set, 4u); EXPECT_EQ(pass->resources[3].set, 3u);
EXPECT_EQ(pass->resources[3].binding, 0u); EXPECT_EQ(pass->resources[3].binding, 0u);
EXPECT_EQ(pass->resources[4].semantic, "ShadowReceiver"); EXPECT_EQ(pass->resources[4].semantic, "ShadowReceiver");
EXPECT_EQ(pass->resources[4].type, ShaderResourceType::ConstantBuffer); EXPECT_EQ(pass->resources[4].type, ShaderResourceType::ConstantBuffer);
EXPECT_EQ(pass->resources[4].set, 5u); EXPECT_EQ(pass->resources[4].set, 4u);
EXPECT_EQ(pass->resources[4].binding, 0u); EXPECT_EQ(pass->resources[4].binding, 0u);
EXPECT_EQ(pass->resources[5].semantic, "ShadowMapTexture"); EXPECT_EQ(pass->resources[5].semantic, "ShadowMapTexture");
EXPECT_EQ(pass->resources[5].type, ShaderResourceType::Texture2D); EXPECT_EQ(pass->resources[5].type, ShaderResourceType::Texture2D);
EXPECT_EQ(pass->resources[5].set, 6u); EXPECT_EQ(pass->resources[5].set, 5u);
EXPECT_EQ(pass->resources[5].binding, 0u); EXPECT_EQ(pass->resources[5].binding, 0u);
EXPECT_EQ(pass->resources[6].semantic, "ShadowMapSampler"); EXPECT_EQ(pass->resources[6].semantic, "ShadowMapSampler");
EXPECT_EQ(pass->resources[6].type, ShaderResourceType::Sampler); EXPECT_EQ(pass->resources[6].type, ShaderResourceType::Sampler);
EXPECT_EQ(pass->resources[6].set, 7u); EXPECT_EQ(pass->resources[6].set, 6u);
EXPECT_EQ(pass->resources[6].binding, 0u); EXPECT_EQ(pass->resources[6].binding, 0u);
delete shader; delete shader;
@@ -110,22 +110,22 @@ TEST(BuiltinForwardPipeline_Test, BuiltinUnlitShaderDeclaresExplicitSurfaceResou
EXPECT_EQ(pass->resources[0].semantic, "PerObject"); EXPECT_EQ(pass->resources[0].semantic, "PerObject");
EXPECT_EQ(pass->resources[0].type, ShaderResourceType::ConstantBuffer); EXPECT_EQ(pass->resources[0].type, ShaderResourceType::ConstantBuffer);
EXPECT_EQ(pass->resources[0].set, 1u); EXPECT_EQ(pass->resources[0].set, 0u);
EXPECT_EQ(pass->resources[0].binding, 0u); EXPECT_EQ(pass->resources[0].binding, 0u);
EXPECT_EQ(pass->resources[1].semantic, "Material"); EXPECT_EQ(pass->resources[1].semantic, "Material");
EXPECT_EQ(pass->resources[1].type, ShaderResourceType::ConstantBuffer); EXPECT_EQ(pass->resources[1].type, ShaderResourceType::ConstantBuffer);
EXPECT_EQ(pass->resources[1].set, 2u); EXPECT_EQ(pass->resources[1].set, 1u);
EXPECT_EQ(pass->resources[1].binding, 0u); EXPECT_EQ(pass->resources[1].binding, 0u);
EXPECT_EQ(pass->resources[2].semantic, "BaseColorTexture"); EXPECT_EQ(pass->resources[2].semantic, "BaseColorTexture");
EXPECT_EQ(pass->resources[2].type, ShaderResourceType::Texture2D); EXPECT_EQ(pass->resources[2].type, ShaderResourceType::Texture2D);
EXPECT_EQ(pass->resources[2].set, 3u); EXPECT_EQ(pass->resources[2].set, 2u);
EXPECT_EQ(pass->resources[2].binding, 0u); EXPECT_EQ(pass->resources[2].binding, 0u);
EXPECT_EQ(pass->resources[3].semantic, "LinearClampSampler"); EXPECT_EQ(pass->resources[3].semantic, "LinearClampSampler");
EXPECT_EQ(pass->resources[3].type, ShaderResourceType::Sampler); EXPECT_EQ(pass->resources[3].type, ShaderResourceType::Sampler);
EXPECT_EQ(pass->resources[3].set, 4u); EXPECT_EQ(pass->resources[3].set, 3u);
EXPECT_EQ(pass->resources[3].binding, 0u); EXPECT_EQ(pass->resources[3].binding, 0u);
delete shader; delete shader;
@@ -153,7 +153,7 @@ TEST(BuiltinForwardPipeline_Test, BuildsBuiltinPassResourceBindingPlanFromExplic
EXPECT_TRUE(plan.linearClampSampler.IsValid()); EXPECT_TRUE(plan.linearClampSampler.IsValid());
EXPECT_TRUE(plan.shadowMapTexture.IsValid()); EXPECT_TRUE(plan.shadowMapTexture.IsValid());
EXPECT_TRUE(plan.shadowMapSampler.IsValid()); EXPECT_TRUE(plan.shadowMapSampler.IsValid());
EXPECT_EQ(plan.firstDescriptorSet, 1u); EXPECT_EQ(plan.firstDescriptorSet, 0u);
EXPECT_EQ(plan.descriptorSetCount, 7u); EXPECT_EQ(plan.descriptorSetCount, 7u);
EXPECT_TRUE(plan.usesConstantBuffers); EXPECT_TRUE(plan.usesConstantBuffers);
EXPECT_TRUE(plan.usesTextures); EXPECT_TRUE(plan.usesTextures);
@@ -181,7 +181,7 @@ TEST(BuiltinForwardPipeline_Test, BuildsBuiltinPassResourceBindingPlanFromExplic
EXPECT_TRUE(plan.material.IsValid()); EXPECT_TRUE(plan.material.IsValid());
EXPECT_TRUE(plan.baseColorTexture.IsValid()); EXPECT_TRUE(plan.baseColorTexture.IsValid());
EXPECT_TRUE(plan.linearClampSampler.IsValid()); EXPECT_TRUE(plan.linearClampSampler.IsValid());
EXPECT_EQ(plan.firstDescriptorSet, 1u); EXPECT_EQ(plan.firstDescriptorSet, 0u);
EXPECT_EQ(plan.descriptorSetCount, 4u); EXPECT_EQ(plan.descriptorSetCount, 4u);
EXPECT_TRUE(plan.usesConstantBuffers); EXPECT_TRUE(plan.usesConstantBuffers);
EXPECT_TRUE(plan.usesTextures); EXPECT_TRUE(plan.usesTextures);
@@ -190,51 +190,88 @@ TEST(BuiltinForwardPipeline_Test, BuildsBuiltinPassResourceBindingPlanFromExplic
delete shader; delete shader;
} }
TEST(BuiltinForwardPipeline_Test, BuildsBuiltinPassResourceBindingPlanFromLegacyFallbackResources) { TEST(BuiltinForwardPipeline_Test, UsesNormalizedExplicitSetIndicesForSurfaceResources) {
const Array<ShaderResourceBindingDesc> bindings = BuildLegacyBuiltinForwardPassResourceBindings(); ShaderLoader loader;
ASSERT_EQ(bindings.Size(), 4u); LoadResult result = loader.Load(GetBuiltinForwardLitShaderPath());
ASSERT_TRUE(result);
ASSERT_NE(result.resource, nullptr);
Shader* shader = static_cast<Shader*>(result.resource);
ASSERT_NE(shader, nullptr);
const ShaderPass* pass = shader->FindPass("ForwardLit");
ASSERT_NE(pass, nullptr);
ASSERT_EQ(pass->resources.Size(), 7u);
BuiltinPassResourceBindingPlan plan = {}; BuiltinPassResourceBindingPlan plan = {};
String error; String error;
EXPECT_TRUE(TryBuildBuiltinPassResourceBindingPlan(bindings, plan, &error)) << error.CStr(); EXPECT_TRUE(TryBuildBuiltinPassResourceBindingPlan(pass->resources, plan, &error)) << error.CStr();
ASSERT_EQ(plan.bindings.Size(), 4u); ASSERT_EQ(plan.bindings.Size(), 7u);
EXPECT_EQ(plan.perObject.set, 1u); EXPECT_EQ(plan.perObject.set, 0u);
EXPECT_EQ(plan.material.set, 2u); EXPECT_EQ(plan.material.set, 1u);
EXPECT_EQ(plan.baseColorTexture.set, 3u); EXPECT_EQ(plan.baseColorTexture.set, 2u);
EXPECT_EQ(plan.linearClampSampler.set, 4u); EXPECT_EQ(plan.linearClampSampler.set, 3u);
EXPECT_EQ(plan.shadowReceiver.set, 4u);
EXPECT_EQ(plan.shadowMapTexture.set, 5u);
EXPECT_EQ(plan.shadowMapSampler.set, 6u);
delete shader;
} }
TEST(BuiltinPassLayout_Test, BuildsSharedSetLayoutsFromLegacyForwardResources) { TEST(BuiltinPassLayout_Test, BuildsSharedSetLayoutsFromExplicitForwardResources) {
const Array<ShaderResourceBindingDesc> bindings = BuildLegacyBuiltinForwardPassResourceBindings(); ShaderLoader loader;
LoadResult result = loader.Load(GetBuiltinForwardLitShaderPath());
ASSERT_TRUE(result);
ASSERT_NE(result.resource, nullptr);
Shader* shader = static_cast<Shader*>(result.resource);
ASSERT_NE(shader, nullptr);
const ShaderPass* pass = shader->FindPass("ForwardLit");
ASSERT_NE(pass, nullptr);
ASSERT_EQ(pass->resources.Size(), 7u);
BuiltinPassResourceBindingPlan plan = {}; BuiltinPassResourceBindingPlan plan = {};
String error; String error;
ASSERT_TRUE(TryBuildBuiltinPassResourceBindingPlan(bindings, plan, &error)) << error.CStr(); ASSERT_TRUE(TryBuildBuiltinPassResourceBindingPlan(pass->resources, plan, &error)) << error.CStr();
std::vector<BuiltinPassSetLayoutMetadata> setLayouts; std::vector<BuiltinPassSetLayoutMetadata> setLayouts;
ASSERT_TRUE(TryBuildBuiltinPassSetLayouts(plan, setLayouts, &error)) << error.CStr(); ASSERT_TRUE(TryBuildBuiltinPassSetLayouts(plan, setLayouts, &error)) << error.CStr();
ASSERT_EQ(setLayouts.size(), 5u); ASSERT_EQ(setLayouts.size(), 7u);
EXPECT_EQ(setLayouts[0].layout.bindingCount, 0u); EXPECT_EQ(setLayouts[0].layout.bindingCount, 1u);
EXPECT_FALSE(setLayouts[0].shaderVisible);
EXPECT_TRUE(setLayouts[0].usesPerObject);
EXPECT_FALSE(setLayouts[0].usesMaterial);
EXPECT_EQ(setLayouts[1].layout.bindingCount, 1u); EXPECT_EQ(setLayouts[1].layout.bindingCount, 1u);
EXPECT_TRUE(setLayouts[1].usesMaterial);
EXPECT_FALSE(setLayouts[1].shaderVisible); EXPECT_FALSE(setLayouts[1].shaderVisible);
EXPECT_TRUE(setLayouts[1].usesPerObject);
EXPECT_FALSE(setLayouts[1].usesMaterial);
EXPECT_EQ(setLayouts[2].layout.bindingCount, 1u); EXPECT_EQ(setLayouts[2].layout.bindingCount, 1u);
EXPECT_TRUE(setLayouts[2].usesMaterial); EXPECT_TRUE(setLayouts[2].usesTexture);
EXPECT_FALSE(setLayouts[2].shaderVisible); EXPECT_TRUE(setLayouts[2].shaderVisible);
EXPECT_EQ(setLayouts[2].heapType, DescriptorHeapType::CBV_SRV_UAV);
EXPECT_EQ(setLayouts[3].layout.bindingCount, 1u); EXPECT_EQ(setLayouts[3].layout.bindingCount, 1u);
EXPECT_TRUE(setLayouts[3].usesTexture); EXPECT_TRUE(setLayouts[3].usesSampler);
EXPECT_TRUE(setLayouts[3].shaderVisible); EXPECT_TRUE(setLayouts[3].shaderVisible);
EXPECT_EQ(setLayouts[3].heapType, DescriptorHeapType::CBV_SRV_UAV); EXPECT_EQ(setLayouts[3].heapType, DescriptorHeapType::Sampler);
EXPECT_EQ(setLayouts[4].layout.bindingCount, 1u); EXPECT_EQ(setLayouts[4].layout.bindingCount, 1u);
EXPECT_TRUE(setLayouts[4].usesSampler); EXPECT_TRUE(setLayouts[4].usesShadowReceiver);
EXPECT_TRUE(setLayouts[4].shaderVisible); EXPECT_FALSE(setLayouts[4].shaderVisible);
EXPECT_EQ(setLayouts[4].heapType, DescriptorHeapType::Sampler);
EXPECT_EQ(setLayouts[5].layout.bindingCount, 1u);
EXPECT_TRUE(setLayouts[5].usesTexture);
EXPECT_TRUE(setLayouts[5].shaderVisible);
EXPECT_EQ(setLayouts[6].layout.bindingCount, 1u);
EXPECT_TRUE(setLayouts[6].usesSampler);
EXPECT_TRUE(setLayouts[6].shaderVisible);
EXPECT_EQ(setLayouts[6].heapType, DescriptorHeapType::Sampler);
delete shader;
} }
TEST(BuiltinDepthStylePass_Test, BuiltinDepthOnlyShaderDeclaresExplicitPerObjectResourceContract) { TEST(BuiltinDepthStylePass_Test, BuiltinDepthOnlyShaderDeclaresExplicitPerObjectResourceContract) {