Formalize forward lighting contract

This commit is contained in:
2026-04-05 15:44:37 +08:00
parent f6da4d0eb6
commit 2c96f0d164
18 changed files with 152 additions and 90 deletions

View File

@@ -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<BuiltinPassSetLayoutMetadata> 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;
}

View File

@@ -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");