rendering: split shader loader authoring modes
This commit is contained in:
@@ -237,7 +237,7 @@ TEST(ShaderLoader, LoadShaderManifestBuildsMultiPassBackendVariants) {
|
||||
fs::remove_all(shaderRoot);
|
||||
}
|
||||
|
||||
TEST(ShaderLoader, LoadUnityLikeShaderAuthoringBuildsRuntimeContract) {
|
||||
TEST(ShaderLoader, LoadLegacyBackendSplitShaderAuthoringBuildsRuntimeContract) {
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
const fs::path shaderRoot = fs::temp_directory_path() / "xc_shader_authoring_test";
|
||||
@@ -382,6 +382,196 @@ TEST(ShaderLoader, LoadUnityLikeShaderAuthoringBuildsRuntimeContract) {
|
||||
fs::remove_all(shaderRoot);
|
||||
}
|
||||
|
||||
TEST(ShaderLoader, LoadUnityStyleSingleSourceShaderAuthoringBuildsGenericHlslVariants) {
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
const fs::path shaderRoot = fs::temp_directory_path() / "xc_shader_single_source_test";
|
||||
const fs::path includeRoot = shaderRoot / "shaderlib";
|
||||
const fs::path shaderPath = shaderRoot / "single_source.shader";
|
||||
|
||||
fs::remove_all(shaderRoot);
|
||||
fs::create_directories(includeRoot);
|
||||
|
||||
WriteTextFile(
|
||||
includeRoot / "shared.hlsl",
|
||||
R"(// XC_SINGLE_SOURCE_SHARED_INCLUDE
|
||||
#define XC_SINGLE_SOURCE_SHARED_VALUE 1
|
||||
)");
|
||||
|
||||
WriteTextFile(
|
||||
shaderPath,
|
||||
R"(Shader "SingleSourceLit"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
_BaseColor ("Base Color", Color) = (1,1,1,1) [Semantic(BaseColor)]
|
||||
}
|
||||
HLSLINCLUDE
|
||||
#include "shaderlib/shared.hlsl"
|
||||
struct VSInput
|
||||
{
|
||||
float3 positionOS : POSITION;
|
||||
};
|
||||
ENDHLSL
|
||||
SubShader
|
||||
{
|
||||
Tags { "Queue" = "Geometry" }
|
||||
LOD 200
|
||||
Pass
|
||||
{
|
||||
Name "ForwardLit"
|
||||
Tags { "LightMode" = "ForwardLit" }
|
||||
HLSLPROGRAM
|
||||
#pragma target 4.5
|
||||
#pragma vertex Vert
|
||||
#pragma fragment Frag
|
||||
#pragma multi_compile _ XC_MAIN_LIGHT_SHADOWS
|
||||
#pragma shader_feature_local _ XC_ALPHA_TEST
|
||||
float4 Vert(VSInput input) : SV_POSITION
|
||||
{
|
||||
return float4(input.positionOS, 1.0);
|
||||
}
|
||||
float4 Frag() : SV_TARGET
|
||||
{
|
||||
return float4(1.0, 0.0, 0.0, 1.0); // XC_SINGLE_SOURCE_FRAG_BODY
|
||||
}
|
||||
ENDHLSL
|
||||
}
|
||||
}
|
||||
}
|
||||
)");
|
||||
|
||||
ShaderLoader loader;
|
||||
LoadResult result = loader.Load(shaderPath.string().c_str());
|
||||
ASSERT_TRUE(result);
|
||||
ASSERT_NE(result.resource, nullptr);
|
||||
|
||||
Shader* shader = static_cast<Shader*>(result.resource);
|
||||
ASSERT_NE(shader, nullptr);
|
||||
ASSERT_TRUE(shader->IsValid());
|
||||
EXPECT_EQ(shader->GetName(), "SingleSourceLit");
|
||||
ASSERT_EQ(shader->GetProperties().Size(), 1u);
|
||||
ASSERT_EQ(shader->GetPassCount(), 1u);
|
||||
|
||||
const ShaderPass* pass = shader->FindPass("ForwardLit");
|
||||
ASSERT_NE(pass, nullptr);
|
||||
ASSERT_EQ(pass->tags.Size(), 2u);
|
||||
EXPECT_EQ(pass->tags[0].name, "Queue");
|
||||
EXPECT_EQ(pass->tags[0].value, "Geometry");
|
||||
EXPECT_EQ(pass->tags[1].name, "LightMode");
|
||||
EXPECT_EQ(pass->tags[1].value, "ForwardLit");
|
||||
EXPECT_TRUE(pass->resources.Empty());
|
||||
ASSERT_EQ(pass->variants.Size(), 2u);
|
||||
|
||||
const ShaderStageVariant* vertexVariant =
|
||||
shader->FindVariant("ForwardLit", ShaderType::Vertex, ShaderBackend::D3D12);
|
||||
ASSERT_NE(vertexVariant, nullptr);
|
||||
EXPECT_EQ(vertexVariant->backend, ShaderBackend::Generic);
|
||||
EXPECT_EQ(vertexVariant->language, ShaderLanguage::HLSL);
|
||||
EXPECT_EQ(vertexVariant->entryPoint, "Vert");
|
||||
EXPECT_EQ(vertexVariant->profile, "vs_5_0");
|
||||
EXPECT_NE(std::string(vertexVariant->sourceCode.CStr()).find("#include \"shaderlib/shared.hlsl\""), std::string::npos);
|
||||
EXPECT_NE(std::string(vertexVariant->sourceCode.CStr()).find("XC_SINGLE_SOURCE_FRAG_BODY"), std::string::npos);
|
||||
|
||||
const ShaderStageVariant* fragmentVariant =
|
||||
shader->FindVariant("ForwardLit", ShaderType::Fragment, ShaderBackend::D3D12);
|
||||
ASSERT_NE(fragmentVariant, nullptr);
|
||||
EXPECT_EQ(fragmentVariant->backend, ShaderBackend::Generic);
|
||||
EXPECT_EQ(fragmentVariant->language, ShaderLanguage::HLSL);
|
||||
EXPECT_EQ(fragmentVariant->entryPoint, "Frag");
|
||||
EXPECT_EQ(fragmentVariant->profile, "ps_5_0");
|
||||
|
||||
Array<String> dependencies;
|
||||
ASSERT_TRUE(loader.CollectSourceDependencies(shaderPath.string().c_str(), dependencies));
|
||||
ASSERT_EQ(dependencies.Size(), 1u);
|
||||
EXPECT_EQ(
|
||||
fs::path(dependencies[0].CStr()).lexically_normal(),
|
||||
(includeRoot / "shared.hlsl").lexically_normal());
|
||||
|
||||
delete shader;
|
||||
fs::remove_all(shaderRoot);
|
||||
}
|
||||
|
||||
TEST(ShaderLoader, LoadUnityStyleSingleSourceShaderAuthoringRejectsBackendPragma) {
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
const fs::path shaderRoot = fs::temp_directory_path() / "xc_shader_single_source_reject_backend";
|
||||
const fs::path shaderPath = shaderRoot / "invalid_backend.shader";
|
||||
|
||||
fs::remove_all(shaderRoot);
|
||||
fs::create_directories(shaderRoot);
|
||||
|
||||
WriteTextFile(
|
||||
shaderPath,
|
||||
R"(Shader "InvalidBackend"
|
||||
{
|
||||
SubShader
|
||||
{
|
||||
Pass
|
||||
{
|
||||
Name "ForwardLit"
|
||||
HLSLPROGRAM
|
||||
#pragma target 4.5
|
||||
#pragma vertex Vert
|
||||
#pragma fragment Frag
|
||||
#pragma backend D3D12 HLSL "forward.vs.hlsl" "forward.ps.hlsl"
|
||||
float4 Vert() : SV_POSITION { return 0; }
|
||||
float4 Frag() : SV_TARGET { return 1; }
|
||||
ENDHLSL
|
||||
}
|
||||
}
|
||||
}
|
||||
)");
|
||||
|
||||
ShaderLoader loader;
|
||||
LoadResult result = loader.Load(shaderPath.string().c_str());
|
||||
EXPECT_FALSE(result);
|
||||
EXPECT_NE(std::string(result.errorMessage.CStr()).find("must not use #pragma backend"), std::string::npos);
|
||||
|
||||
fs::remove_all(shaderRoot);
|
||||
}
|
||||
|
||||
TEST(ShaderLoader, LoadUnityStyleSingleSourceShaderAuthoringRejectsResourcesBlock) {
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
const fs::path shaderRoot = fs::temp_directory_path() / "xc_shader_single_source_reject_resources";
|
||||
const fs::path shaderPath = shaderRoot / "invalid_resources.shader";
|
||||
|
||||
fs::remove_all(shaderRoot);
|
||||
fs::create_directories(shaderRoot);
|
||||
|
||||
WriteTextFile(
|
||||
shaderPath,
|
||||
R"(Shader "InvalidResources"
|
||||
{
|
||||
SubShader
|
||||
{
|
||||
Pass
|
||||
{
|
||||
Name "ForwardLit"
|
||||
Resources
|
||||
{
|
||||
MaterialConstants (ConstantBuffer, 0, 0)
|
||||
}
|
||||
HLSLPROGRAM
|
||||
#pragma vertex Vert
|
||||
#pragma fragment Frag
|
||||
float4 Vert() : SV_POSITION { return 0; }
|
||||
float4 Frag() : SV_TARGET { return 1; }
|
||||
ENDHLSL
|
||||
}
|
||||
}
|
||||
}
|
||||
)");
|
||||
|
||||
ShaderLoader loader;
|
||||
LoadResult result = loader.Load(shaderPath.string().c_str());
|
||||
EXPECT_FALSE(result);
|
||||
EXPECT_NE(std::string(result.errorMessage.CStr()).find("must not declare Resources blocks"), std::string::npos);
|
||||
|
||||
fs::remove_all(shaderRoot);
|
||||
}
|
||||
|
||||
TEST(ShaderLoader, ResourceManagerLoadsShaderManifestRelativeToResourceRoot) {
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user