rendering: unify builtin forward and depth-style shaders
This commit is contained in:
@@ -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());
|
||||
|
||||
Reference in New Issue
Block a user