rendering: unify builtin forward and depth-style shaders

This commit is contained in:
2026-04-07 03:35:06 +08:00
parent 503ffbc4ff
commit 5f9f3386ab
27 changed files with 1135 additions and 1151 deletions

View File

@@ -1,5 +1,7 @@
#include <gtest/gtest.h>
#include "Rendering/Detail/ShaderVariantUtils.h"
#include <XCEngine/Rendering/Builtin/BuiltinPassLayoutUtils.h>
#include <XCEngine/Rendering/Passes/BuiltinDepthOnlyPass.h>
#include <XCEngine/Rendering/Passes/BuiltinObjectIdPass.h>
@@ -10,6 +12,10 @@
#include <XCEngine/Resources/Shader/Shader.h>
#include <XCEngine/Resources/Shader/ShaderLoader.h>
#include <XCEngine/RHI/RHIEnums.h>
#include <XCEngine/RHI/ShaderCompiler/SpirvShaderCompiler.h>
#include <fstream>
#include <iostream>
using namespace XCEngine::Rendering::Pipelines;
using namespace XCEngine::Rendering::Passes;
@@ -53,7 +59,7 @@ TEST(BuiltinForwardPipeline_Test, SplitsSceneItemsIntoOpaqueAndTransparentQueueR
EXPECT_TRUE(IsTransparentRenderQueue(static_cast<int>(MaterialRenderQueue::Overlay)));
}
TEST(BuiltinForwardPipeline_Test, BuiltinForwardShaderDeclaresExplicitForwardResourceContract) {
TEST(BuiltinForwardPipeline_Test, BuiltinForwardShaderUsesUnityStyleSingleSourceSurfaceContract) {
ShaderLoader loader;
LoadResult result = loader.Load(GetBuiltinForwardLitShaderPath());
ASSERT_TRUE(result);
@@ -69,52 +75,16 @@ TEST(BuiltinForwardPipeline_Test, BuiltinForwardShaderDeclaresExplicitForwardRes
const ShaderPass* pass = shader->FindPass("ForwardLit");
ASSERT_NE(pass, nullptr);
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, "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, "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, "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, "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, "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, "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);
EXPECT_TRUE(pass->resources.Empty());
EXPECT_TRUE(pass->hasFixedFunctionState);
EXPECT_EQ(pass->fixedFunctionState.cullMode, MaterialCullMode::Back);
EXPECT_TRUE(pass->fixedFunctionState.depthWriteEnable);
EXPECT_EQ(pass->fixedFunctionState.depthFunc, MaterialComparisonFunc::LessEqual);
delete shader;
}
TEST(BuiltinForwardPipeline_Test, BuiltinUnlitShaderDeclaresExplicitSurfaceResourceContract) {
TEST(BuiltinForwardPipeline_Test, BuiltinUnlitShaderUsesUnityStyleSingleSourceSurfaceContract) {
ShaderLoader loader;
LoadResult result = loader.Load(GetBuiltinUnlitShaderPath());
ASSERT_TRUE(result);
@@ -125,27 +95,362 @@ TEST(BuiltinForwardPipeline_Test, BuiltinUnlitShaderDeclaresExplicitSurfaceResou
const ShaderPass* pass = shader->FindPass("Unlit");
ASSERT_NE(pass, nullptr);
ASSERT_EQ(pass->resources.Size(), 4u);
EXPECT_TRUE(pass->resources.Empty());
EXPECT_TRUE(pass->hasFixedFunctionState);
EXPECT_EQ(pass->fixedFunctionState.cullMode, MaterialCullMode::Back);
EXPECT_TRUE(pass->fixedFunctionState.depthWriteEnable);
EXPECT_EQ(pass->fixedFunctionState.depthFunc, MaterialComparisonFunc::LessEqual);
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);
delete shader;
}
EXPECT_EQ(pass->resources[1].semantic, "Material");
EXPECT_EQ(pass->resources[1].type, ShaderResourceType::ConstantBuffer);
EXPECT_EQ(pass->resources[1].set, 1u);
EXPECT_EQ(pass->resources[1].binding, 0u);
TEST(BuiltinForwardPipeline_Test, BuiltinUnlitShaderBuildsVulkanRuntimeSourceWithResolvedBindings) {
ShaderLoader loader;
LoadResult result = loader.Load(GetBuiltinUnlitShaderPath());
ASSERT_TRUE(result);
ASSERT_NE(result.resource, nullptr);
EXPECT_EQ(pass->resources[2].semantic, "BaseColorTexture");
EXPECT_EQ(pass->resources[2].type, ShaderResourceType::Texture2D);
EXPECT_EQ(pass->resources[2].set, 2u);
EXPECT_EQ(pass->resources[2].binding, 0u);
Shader* shader = static_cast<Shader*>(result.resource);
ASSERT_NE(shader, nullptr);
EXPECT_EQ(pass->resources[3].semantic, "LinearClampSampler");
EXPECT_EQ(pass->resources[3].type, ShaderResourceType::Sampler);
EXPECT_EQ(pass->resources[3].set, 3u);
EXPECT_EQ(pass->resources[3].binding, 0u);
const ShaderPass* pass = shader->FindPass("Unlit");
ASSERT_NE(pass, nullptr);
const ShaderStageVariant* fragmentVariant =
shader->FindVariant(
"Unlit",
XCEngine::Resources::ShaderType::Fragment,
XCEngine::Resources::ShaderBackend::Vulkan);
ASSERT_NE(fragmentVariant, nullptr);
const std::string runtimeSource =
::XCEngine::Rendering::Detail::BuildRuntimeShaderSource(
*pass,
XCEngine::Resources::ShaderBackend::Vulkan,
*fragmentVariant);
EXPECT_NE(
runtimeSource.find("cbuffer MaterialConstants : register(b0, space1)"),
std::string::npos);
EXPECT_NE(runtimeSource.find("BaseColorTexture"), std::string::npos);
EXPECT_NE(runtimeSource.find("space2"), std::string::npos);
EXPECT_NE(runtimeSource.find("LinearClampSampler"), std::string::npos);
EXPECT_NE(runtimeSource.find("space3"), std::string::npos);
delete shader;
}
TEST(BuiltinForwardPipeline_Test, VulkanRuntimeCompileDescRewritesUnityStyleUnlitBindingsToDescriptorSpaces) {
ShaderLoader loader;
LoadResult result = loader.Load(GetBuiltinUnlitShaderPath());
ASSERT_TRUE(result);
ASSERT_NE(result.resource, nullptr);
Shader* shader = static_cast<Shader*>(result.resource);
ASSERT_NE(shader, nullptr);
const ShaderPass* pass = shader->FindPass("Unlit");
ASSERT_NE(pass, nullptr);
const ShaderStageVariant* d3d12Fragment = shader->FindVariant(
"Unlit",
XCEngine::Resources::ShaderType::Fragment,
XCEngine::Resources::ShaderBackend::D3D12);
ASSERT_NE(d3d12Fragment, nullptr);
ShaderCompileDesc d3d12CompileDesc = {};
::XCEngine::Rendering::Detail::ApplyShaderStageVariant(
*pass,
XCEngine::Resources::ShaderBackend::D3D12,
*d3d12Fragment,
d3d12CompileDesc);
const std::string d3d12Source(
reinterpret_cast<const char*>(d3d12CompileDesc.source.data()),
d3d12CompileDesc.source.size());
EXPECT_NE(d3d12Source.find("BaseColorTexture"), std::string::npos);
EXPECT_NE(d3d12Source.find("LinearClampSampler"), std::string::npos);
EXPECT_EQ(d3d12Source.find("space2"), std::string::npos);
EXPECT_EQ(d3d12Source.find("space3"), std::string::npos);
const ShaderStageVariant* vulkanFragment = shader->FindVariant(
"Unlit",
XCEngine::Resources::ShaderType::Fragment,
XCEngine::Resources::ShaderBackend::Vulkan);
ASSERT_NE(vulkanFragment, nullptr);
ShaderCompileDesc vulkanCompileDesc = {};
::XCEngine::Rendering::Detail::ApplyShaderStageVariant(
*pass,
XCEngine::Resources::ShaderBackend::Vulkan,
*vulkanFragment,
vulkanCompileDesc);
const std::string vulkanSource(
reinterpret_cast<const char*>(vulkanCompileDesc.source.data()),
vulkanCompileDesc.source.size());
EXPECT_NE(vulkanSource.find("cbuffer MaterialConstants : register(b0, space1)"), std::string::npos);
EXPECT_NE(vulkanSource.find("BaseColorTexture"), std::string::npos);
EXPECT_NE(vulkanSource.find("space2"), std::string::npos);
EXPECT_NE(vulkanSource.find("LinearClampSampler"), std::string::npos);
EXPECT_NE(vulkanSource.find("space3"), std::string::npos);
delete shader;
}
TEST(BuiltinForwardPipeline_Test, VulkanRuntimeCompileDescRewritesUnityStyleForwardBindingsToDescriptorSpaces) {
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);
ShaderKeywordSet shadowKeywords = {};
shadowKeywords.enabledKeywords.PushBack("XC_MAIN_LIGHT_SHADOWS");
const ShaderStageVariant* d3d12Fragment = shader->FindVariant(
"ForwardLit",
XCEngine::Resources::ShaderType::Fragment,
XCEngine::Resources::ShaderBackend::D3D12,
shadowKeywords);
ASSERT_NE(d3d12Fragment, nullptr);
ShaderCompileDesc d3d12CompileDesc = {};
::XCEngine::Rendering::Detail::ApplyShaderStageVariant(
*pass,
XCEngine::Resources::ShaderBackend::D3D12,
*d3d12Fragment,
d3d12CompileDesc);
const std::string d3d12Source(
reinterpret_cast<const char*>(d3d12CompileDesc.source.data()),
d3d12CompileDesc.source.size());
EXPECT_NE(d3d12Source.find("cbuffer LightingConstants : register(b1)"), std::string::npos);
EXPECT_NE(d3d12Source.find("Texture2D ShadowMapTexture : register(t1)"), std::string::npos);
EXPECT_EQ(d3d12Source.find("space1"), std::string::npos);
EXPECT_EQ(d3d12Source.find("space6"), std::string::npos);
const ShaderStageVariant* vulkanFragment = shader->FindVariant(
"ForwardLit",
XCEngine::Resources::ShaderType::Fragment,
XCEngine::Resources::ShaderBackend::Vulkan,
shadowKeywords);
ASSERT_NE(vulkanFragment, nullptr);
ShaderCompileDesc vulkanCompileDesc = {};
::XCEngine::Rendering::Detail::ApplyShaderStageVariant(
*pass,
XCEngine::Resources::ShaderBackend::Vulkan,
*vulkanFragment,
vulkanCompileDesc);
const std::string vulkanSource(
reinterpret_cast<const char*>(vulkanCompileDesc.source.data()),
vulkanCompileDesc.source.size());
EXPECT_NE(vulkanSource.find("cbuffer PerObjectConstants : register(b0, space0)"), std::string::npos);
EXPECT_NE(vulkanSource.find("cbuffer LightingConstants : register(b0, space1)"), std::string::npos);
EXPECT_NE(vulkanSource.find("cbuffer MaterialConstants : register(b0, space2)"), std::string::npos);
EXPECT_NE(vulkanSource.find("cbuffer ShadowReceiverConstants : register(b0, space3)"), std::string::npos);
EXPECT_NE(vulkanSource.find("Texture2D BaseColorTexture : register(t0, space4)"), std::string::npos);
EXPECT_NE(vulkanSource.find("SamplerState LinearClampSampler : register(s0, space5)"), std::string::npos);
EXPECT_NE(vulkanSource.find("Texture2D ShadowMapTexture : register(t0, space6)"), std::string::npos);
EXPECT_NE(vulkanSource.find("SamplerState ShadowMapSampler : register(s0, space7)"), std::string::npos);
delete shader;
}
TEST(BuiltinForwardPipeline_Test, OpenGLRuntimeTranspilesForwardShadowVariantToLegacyClipConventions) {
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);
ShaderKeywordSet shadowKeywords = {};
shadowKeywords.enabledKeywords.PushBack("XC_MAIN_LIGHT_SHADOWS");
const ShaderStageVariant* openGLFragment = shader->FindVariant(
"ForwardLit",
XCEngine::Resources::ShaderType::Fragment,
XCEngine::Resources::ShaderBackend::OpenGL,
shadowKeywords);
ASSERT_NE(openGLFragment, nullptr);
ShaderCompileDesc compileDesc = {};
::XCEngine::Rendering::Detail::ApplyShaderStageVariant(
*pass,
XCEngine::Resources::ShaderBackend::OpenGL,
*openGLFragment,
compileDesc);
const std::string runtimeSource(
reinterpret_cast<const char*>(compileDesc.source.data()),
compileDesc.source.size());
EXPECT_NE(runtimeSource.find("const float shadowUvY = shadowNdc.y * 0.5f + 0.5f;"), std::string::npos);
EXPECT_NE(
runtimeSource.find("shadowNdc.z < -1.0f || shadowNdc.z > 1.0f"),
std::string::npos);
EXPECT_NE(
runtimeSource.find(
"const float receiverDepth = shadowNdc.z * 0.5f + 0.5f - gShadowBiasAndTexelSize.x;"),
std::string::npos);
XCEngine::RHI::CompiledSpirvShader spirvShader = {};
std::string errorMessage;
ASSERT_TRUE(
XCEngine::RHI::CompileSpirvShader(
compileDesc,
XCEngine::RHI::SpirvTargetEnvironment::Vulkan,
spirvShader,
&errorMessage))
<< errorMessage;
std::string glslSource;
ASSERT_TRUE(XCEngine::RHI::TranspileSpirvToOpenGLGLSL(spirvShader, glslSource, &errorMessage))
<< errorMessage;
EXPECT_NE(
glslSource.find("uniform sampler2D SPIRV_Cross_CombinedBaseColorTextureLinearClampSampler;"),
std::string::npos);
EXPECT_NE(
glslSource.find("uniform sampler2D SPIRV_Cross_CombinedShadowMapTextureShadowMapSampler;"),
std::string::npos);
EXPECT_NE(
glslSource.find("spvWorkaroundRowMajor(ShadowReceiverConstants.gWorldToShadowMatrix)"),
std::string::npos);
EXPECT_NE(glslSource.find("texture(SPIRV_Cross_CombinedShadowMapTextureShadowMapSampler"), std::string::npos);
delete shader;
}
TEST(BuiltinDepthStylePass_Test, OpenGLRuntimeTranspilesDepthOnlyAlphaVariantWithTexcoordAtLocation2) {
ShaderLoader loader;
LoadResult result = loader.Load(GetBuiltinDepthOnlyShaderPath());
ASSERT_TRUE(result);
ASSERT_NE(result.resource, nullptr);
Shader* shader = static_cast<Shader*>(result.resource);
ASSERT_NE(shader, nullptr);
const ShaderPass* pass = shader->FindPass("DepthOnly");
ASSERT_NE(pass, nullptr);
ShaderKeywordSet alphaKeywords = {};
alphaKeywords.enabledKeywords.PushBack("XC_ALPHA_TEST");
const ShaderStageVariant* openGLVertex = shader->FindVariant(
"DepthOnly",
XCEngine::Resources::ShaderType::Vertex,
ShaderBackend::OpenGL,
alphaKeywords);
ASSERT_NE(openGLVertex, nullptr);
const ShaderStageVariant* openGLFragment = shader->FindVariant(
"DepthOnly",
XCEngine::Resources::ShaderType::Fragment,
ShaderBackend::OpenGL,
alphaKeywords);
ASSERT_NE(openGLFragment, nullptr);
auto transpileStage = [](const ShaderPass& targetPass,
const ShaderStageVariant& variant,
std::string& glslSource) {
ShaderCompileDesc compileDesc = {};
::XCEngine::Rendering::Detail::ApplyShaderStageVariant(
targetPass,
XCEngine::Resources::ShaderBackend::OpenGL,
variant,
compileDesc);
XCEngine::RHI::CompiledSpirvShader spirvShader = {};
std::string errorMessage;
EXPECT_TRUE(
XCEngine::RHI::CompileSpirvShader(
compileDesc,
XCEngine::RHI::SpirvTargetEnvironment::Vulkan,
spirvShader,
&errorMessage))
<< errorMessage;
EXPECT_TRUE(XCEngine::RHI::TranspileSpirvToOpenGLGLSL(spirvShader, glslSource, &errorMessage))
<< errorMessage;
};
std::string vertexGlsl;
transpileStage(*pass, *openGLVertex, vertexGlsl);
EXPECT_NE(vertexGlsl.find("layout(location = 2) in vec2"), std::string::npos);
std::string fragmentGlsl;
transpileStage(*pass, *openGLFragment, fragmentGlsl);
EXPECT_NE(fragmentGlsl.find("discard;"), std::string::npos);
EXPECT_NE(fragmentGlsl.find("gl_FragDepth"), std::string::npos);
delete shader;
}
TEST(BuiltinDepthStylePass_Test, OpenGLRuntimeTranspilesShadowCasterAlphaVariantWithTexcoordAtLocation2) {
ShaderLoader loader;
LoadResult result = loader.Load(GetBuiltinShadowCasterShaderPath());
ASSERT_TRUE(result);
ASSERT_NE(result.resource, nullptr);
Shader* shader = static_cast<Shader*>(result.resource);
ASSERT_NE(shader, nullptr);
const ShaderPass* pass = shader->FindPass("ShadowCaster");
ASSERT_NE(pass, nullptr);
ShaderKeywordSet alphaKeywords = {};
alphaKeywords.enabledKeywords.PushBack("XC_ALPHA_TEST");
const ShaderStageVariant* openGLVertex = shader->FindVariant(
"ShadowCaster",
XCEngine::Resources::ShaderType::Vertex,
ShaderBackend::OpenGL,
alphaKeywords);
ASSERT_NE(openGLVertex, nullptr);
const ShaderStageVariant* openGLFragment = shader->FindVariant(
"ShadowCaster",
XCEngine::Resources::ShaderType::Fragment,
ShaderBackend::OpenGL,
alphaKeywords);
ASSERT_NE(openGLFragment, nullptr);
auto transpileStage = [](const ShaderPass& targetPass,
const ShaderStageVariant& variant,
std::string& glslSource) {
ShaderCompileDesc compileDesc = {};
::XCEngine::Rendering::Detail::ApplyShaderStageVariant(
targetPass,
XCEngine::Resources::ShaderBackend::OpenGL,
variant,
compileDesc);
XCEngine::RHI::CompiledSpirvShader spirvShader = {};
std::string errorMessage;
EXPECT_TRUE(
XCEngine::RHI::CompileSpirvShader(
compileDesc,
XCEngine::RHI::SpirvTargetEnvironment::Vulkan,
spirvShader,
&errorMessage))
<< errorMessage;
EXPECT_TRUE(XCEngine::RHI::TranspileSpirvToOpenGLGLSL(spirvShader, glslSource, &errorMessage))
<< errorMessage;
};
std::string vertexGlsl;
transpileStage(*pass, *openGLVertex, vertexGlsl);
EXPECT_NE(vertexGlsl.find("layout(location = 2) in vec2"), std::string::npos);
std::string fragmentGlsl;
transpileStage(*pass, *openGLFragment, fragmentGlsl);
EXPECT_NE(fragmentGlsl.find("discard;"), std::string::npos);
EXPECT_NE(fragmentGlsl.find("gl_FragDepth"), std::string::npos);
delete shader;
}
@@ -263,7 +568,7 @@ TEST(BuiltinForwardPipeline_Test, BuiltinFinalColorShaderDeclaresExplicitFullscr
delete shader;
}
TEST(BuiltinForwardPipeline_Test, BuildsBuiltinPassResourceBindingPlanFromExplicitForwardResources) {
TEST(BuiltinForwardPipeline_Test, BuildsBuiltinPassResourceBindingPlanFromLoadedImplicitForwardShader) {
ShaderLoader loader;
LoadResult result = loader.Load(GetBuiltinForwardLitShaderPath());
ASSERT_TRUE(result);
@@ -277,7 +582,7 @@ TEST(BuiltinForwardPipeline_Test, BuildsBuiltinPassResourceBindingPlanFromExplic
BuiltinPassResourceBindingPlan plan = {};
String error;
EXPECT_TRUE(TryBuildBuiltinPassResourceBindingPlan(pass->resources, plan, &error)) << error.CStr();
EXPECT_TRUE(TryBuildBuiltinPassResourceBindingPlan(*pass, plan, &error)) << error.CStr();
EXPECT_TRUE(plan.perObject.IsValid());
EXPECT_TRUE(plan.lighting.IsValid());
EXPECT_TRUE(plan.material.IsValid());
@@ -295,7 +600,7 @@ TEST(BuiltinForwardPipeline_Test, BuildsBuiltinPassResourceBindingPlanFromExplic
delete shader;
}
TEST(BuiltinForwardPipeline_Test, BuildsBuiltinPassResourceBindingPlanFromImplicitForwardContract) {
TEST(BuiltinForwardPipeline_Test, BuildsBuiltinPassResourceBindingPlanFromBuiltinForwardShaderContract) {
ShaderPass pass = {};
pass.name = "ForwardLit";
@@ -319,7 +624,7 @@ TEST(BuiltinForwardPipeline_Test, BuildsBuiltinPassResourceBindingPlanFromImplic
EXPECT_EQ(plan.descriptorSetCount, 8u);
}
TEST(BuiltinForwardPipeline_Test, BuildsBuiltinPassResourceBindingPlanFromExplicitUnlitResources) {
TEST(BuiltinForwardPipeline_Test, BuildsBuiltinPassResourceBindingPlanFromImplicitUnlitContract) {
ShaderLoader loader;
LoadResult result = loader.Load(GetBuiltinUnlitShaderPath());
ASSERT_TRUE(result);
@@ -333,7 +638,7 @@ TEST(BuiltinForwardPipeline_Test, BuildsBuiltinPassResourceBindingPlanFromExplic
BuiltinPassResourceBindingPlan plan = {};
String error;
EXPECT_TRUE(TryBuildBuiltinPassResourceBindingPlan(pass->resources, plan, &error)) << error.CStr();
EXPECT_TRUE(TryBuildBuiltinPassResourceBindingPlan(*pass, plan, &error)) << error.CStr();
EXPECT_TRUE(plan.perObject.IsValid());
EXPECT_TRUE(plan.material.IsValid());
EXPECT_TRUE(plan.baseColorTexture.IsValid());
@@ -347,7 +652,7 @@ TEST(BuiltinForwardPipeline_Test, BuildsBuiltinPassResourceBindingPlanFromExplic
delete shader;
}
TEST(BuiltinForwardPipeline_Test, UsesNormalizedExplicitSetIndicesForSurfaceResources) {
TEST(BuiltinForwardPipeline_Test, UsesNormalizedImplicitSetIndicesForForwardSurfaceResources) {
ShaderLoader loader;
LoadResult result = loader.Load(GetBuiltinForwardLitShaderPath());
ASSERT_TRUE(result);
@@ -358,11 +663,11 @@ TEST(BuiltinForwardPipeline_Test, UsesNormalizedExplicitSetIndicesForSurfaceReso
const ShaderPass* pass = shader->FindPass("ForwardLit");
ASSERT_NE(pass, nullptr);
ASSERT_EQ(pass->resources.Size(), 8u);
EXPECT_TRUE(pass->resources.Empty());
BuiltinPassResourceBindingPlan plan = {};
String error;
EXPECT_TRUE(TryBuildBuiltinPassResourceBindingPlan(pass->resources, plan, &error)) << error.CStr();
EXPECT_TRUE(TryBuildBuiltinPassResourceBindingPlan(*pass, plan, &error)) << error.CStr();
ASSERT_EQ(plan.bindings.Size(), 8u);
EXPECT_EQ(plan.perObject.set, 0u);
EXPECT_EQ(plan.lighting.set, 1u);
@@ -376,7 +681,7 @@ TEST(BuiltinForwardPipeline_Test, UsesNormalizedExplicitSetIndicesForSurfaceReso
delete shader;
}
TEST(BuiltinPassLayout_Test, BuildsSharedSetLayoutsFromExplicitForwardResources) {
TEST(BuiltinPassLayout_Test, BuildsSharedSetLayoutsFromImplicitForwardResources) {
ShaderLoader loader;
LoadResult result = loader.Load(GetBuiltinForwardLitShaderPath());
ASSERT_TRUE(result);
@@ -387,11 +692,11 @@ TEST(BuiltinPassLayout_Test, BuildsSharedSetLayoutsFromExplicitForwardResources)
const ShaderPass* pass = shader->FindPass("ForwardLit");
ASSERT_NE(pass, nullptr);
ASSERT_EQ(pass->resources.Size(), 8u);
EXPECT_TRUE(pass->resources.Empty());
BuiltinPassResourceBindingPlan plan = {};
String error;
ASSERT_TRUE(TryBuildBuiltinPassResourceBindingPlan(pass->resources, plan, &error)) << error.CStr();
ASSERT_TRUE(TryBuildBuiltinPassResourceBindingPlan(*pass, plan, &error)) << error.CStr();
std::vector<BuiltinPassSetLayoutMetadata> setLayouts;
ASSERT_TRUE(TryBuildBuiltinPassSetLayouts(plan, setLayouts, &error)) << error.CStr();
@@ -436,7 +741,7 @@ TEST(BuiltinPassLayout_Test, BuildsSharedSetLayoutsFromExplicitForwardResources)
delete shader;
}
TEST(BuiltinDepthStylePass_Test, BuiltinDepthOnlyShaderDeclaresExplicitPerObjectResourceContract) {
TEST(BuiltinDepthStylePass_Test, BuiltinDepthOnlyShaderUsesUnityStyleSingleSourceContract) {
ShaderLoader loader;
LoadResult result = loader.Load(GetBuiltinDepthOnlyShaderPath());
ASSERT_TRUE(result);
@@ -447,29 +752,16 @@ TEST(BuiltinDepthStylePass_Test, BuiltinDepthOnlyShaderDeclaresExplicitPerObject
const ShaderPass* pass = shader->FindPass("DepthOnly");
ASSERT_NE(pass, nullptr);
ASSERT_EQ(pass->resources.Size(), 4u);
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].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].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].set, 3u);
EXPECT_EQ(pass->resources[3].binding, 0u);
EXPECT_TRUE(pass->resources.Empty());
EXPECT_TRUE(pass->hasFixedFunctionState);
EXPECT_EQ(pass->fixedFunctionState.cullMode, MaterialCullMode::Back);
EXPECT_TRUE(pass->fixedFunctionState.depthWriteEnable);
EXPECT_EQ(pass->fixedFunctionState.depthFunc, MaterialComparisonFunc::LessEqual);
delete shader;
}
TEST(BuiltinDepthStylePass_Test, BuiltinShadowCasterShaderDeclaresExplicitPerObjectResourceContract) {
TEST(BuiltinDepthStylePass_Test, BuiltinShadowCasterShaderUsesUnityStyleSingleSourceContract) {
ShaderLoader loader;
LoadResult result = loader.Load(GetBuiltinShadowCasterShaderPath());
ASSERT_TRUE(result);
@@ -480,24 +772,11 @@ TEST(BuiltinDepthStylePass_Test, BuiltinShadowCasterShaderDeclaresExplicitPerObj
const ShaderPass* pass = shader->FindPass("ShadowCaster");
ASSERT_NE(pass, nullptr);
ASSERT_EQ(pass->resources.Size(), 4u);
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].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].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].set, 3u);
EXPECT_EQ(pass->resources[3].binding, 0u);
EXPECT_TRUE(pass->resources.Empty());
EXPECT_TRUE(pass->hasFixedFunctionState);
EXPECT_EQ(pass->fixedFunctionState.cullMode, MaterialCullMode::Back);
EXPECT_TRUE(pass->fixedFunctionState.depthWriteEnable);
EXPECT_EQ(pass->fixedFunctionState.depthFunc, MaterialComparisonFunc::LessEqual);
delete shader;
}
@@ -647,7 +926,7 @@ TEST(BuiltinPassLayout_Test, BuildsSharedSetLayoutsFromExplicitObjectIdResources
delete shader;
}
TEST(BuiltinPassLayout_Test, BuildsSharedSetLayoutsFromExplicitDepthOnlyResources) {
TEST(BuiltinPassLayout_Test, BuildsSharedSetLayoutsFromBuiltinDepthOnlyShaderContract) {
ShaderLoader loader;
LoadResult result = loader.Load(GetBuiltinDepthOnlyShaderPath());
ASSERT_TRUE(result);
@@ -658,11 +937,10 @@ TEST(BuiltinPassLayout_Test, BuildsSharedSetLayoutsFromExplicitDepthOnlyResource
const ShaderPass* pass = shader->FindPass("DepthOnly");
ASSERT_NE(pass, nullptr);
ASSERT_EQ(pass->resources.Size(), 4u);
BuiltinPassResourceBindingPlan plan = {};
String error;
ASSERT_TRUE(TryBuildBuiltinPassResourceBindingPlan(pass->resources, plan, &error)) << error.CStr();
ASSERT_TRUE(TryBuildBuiltinPassResourceBindingPlan(*pass, plan, &error)) << error.CStr();
EXPECT_TRUE(plan.perObject.IsValid());
EXPECT_TRUE(plan.material.IsValid());
EXPECT_TRUE(plan.baseColorTexture.IsValid());
@@ -703,7 +981,7 @@ TEST(BuiltinPassLayout_Test, BuildsSharedSetLayoutsFromExplicitDepthOnlyResource
delete shader;
}
TEST(BuiltinPassLayout_Test, BuildsSharedSetLayoutsFromExplicitShadowCasterResources) {
TEST(BuiltinPassLayout_Test, BuildsSharedSetLayoutsFromBuiltinShadowCasterShaderContract) {
ShaderLoader loader;
LoadResult result = loader.Load(GetBuiltinShadowCasterShaderPath());
ASSERT_TRUE(result);
@@ -714,11 +992,10 @@ TEST(BuiltinPassLayout_Test, BuildsSharedSetLayoutsFromExplicitShadowCasterResou
const ShaderPass* pass = shader->FindPass("ShadowCaster");
ASSERT_NE(pass, nullptr);
ASSERT_EQ(pass->resources.Size(), 4u);
BuiltinPassResourceBindingPlan plan = {};
String error;
ASSERT_TRUE(TryBuildBuiltinPassResourceBindingPlan(pass->resources, plan, &error)) << error.CStr();
ASSERT_TRUE(TryBuildBuiltinPassResourceBindingPlan(*pass, plan, &error)) << error.CStr();
EXPECT_TRUE(plan.perObject.IsValid());
EXPECT_TRUE(plan.material.IsValid());
EXPECT_TRUE(plan.baseColorTexture.IsValid());