rendering: remove builtin authoring register annotations

This commit is contained in:
2026-04-07 10:34:20 +08:00
parent ec06340f58
commit f31fece2ce
11 changed files with 565 additions and 80 deletions

View File

@@ -5,13 +5,13 @@ Shader "Builtin Color Scale Post Process"
_ColorScale ("Color Scale", Color) = (0.65,0.80,1.00,1.0) _ColorScale ("Color Scale", Color) = (0.65,0.80,1.00,1.0)
} }
HLSLINCLUDE HLSLINCLUDE
cbuffer PostProcessConstants : register(b0) cbuffer PostProcessConstants
{ {
float4 gColorScale; float4 gColorScale;
}; };
Texture2D gSourceColorTexture : register(t0); Texture2D gSourceColorTexture;
SamplerState gLinearClampSampler : register(s0); SamplerState gLinearClampSampler;
struct VSOutput struct VSOutput
{ {

View File

@@ -7,21 +7,21 @@ Shader "Builtin Depth Only"
_MainTex ("Base Map", 2D) = "white" [Semantic(BaseColorTexture)] _MainTex ("Base Map", 2D) = "white" [Semantic(BaseColorTexture)]
} }
HLSLINCLUDE HLSLINCLUDE
cbuffer PerObjectConstants : register(b0) cbuffer PerObjectConstants
{ {
float4x4 gProjectionMatrix; float4x4 gProjectionMatrix;
float4x4 gViewMatrix; float4x4 gViewMatrix;
float4x4 gModelMatrix; float4x4 gModelMatrix;
}; };
cbuffer MaterialConstants : register(b1) cbuffer MaterialConstants
{ {
float4 gBaseColorFactor; float4 gBaseColorFactor;
float4 gAlphaCutoffParams; float4 gAlphaCutoffParams;
}; };
Texture2D BaseColorTexture : register(t0); Texture2D BaseColorTexture;
SamplerState LinearClampSampler : register(s0); SamplerState LinearClampSampler;
struct VSInput struct VSInput
{ {

View File

@@ -8,14 +8,14 @@ Shader "Builtin Final Color"
_ToneMappingMode ("Tone Mapping Mode", Float) = 0.0 _ToneMappingMode ("Tone Mapping Mode", Float) = 0.0
} }
HLSLINCLUDE HLSLINCLUDE
cbuffer FinalColorConstants : register(b0) cbuffer FinalColorConstants
{ {
float4 gColorScale; float4 gColorScale;
float4 gFinalColorParams; float4 gFinalColorParams;
}; };
Texture2D gSourceColorTexture : register(t0); Texture2D gSourceColorTexture;
SamplerState gLinearClampSampler : register(s0); SamplerState gLinearClampSampler;
struct VSOutput struct VSOutput
{ {

View File

@@ -7,7 +7,7 @@ Shader "Builtin Forward Lit"
_MainTex ("Base Map", 2D) = "white" [Semantic(BaseColorTexture)] _MainTex ("Base Map", 2D) = "white" [Semantic(BaseColorTexture)]
} }
HLSLINCLUDE HLSLINCLUDE
cbuffer PerObjectConstants : register(b0) cbuffer PerObjectConstants
{ {
float4x4 gProjectionMatrix; float4x4 gProjectionMatrix;
float4x4 gViewMatrix; float4x4 gViewMatrix;
@@ -25,7 +25,7 @@ Shader "Builtin Forward Lit"
float4 spotAnglesAndFlags; float4 spotAnglesAndFlags;
}; };
cbuffer LightingConstants : register(b1) cbuffer LightingConstants
{ {
float4 gMainLightDirectionAndIntensity; float4 gMainLightDirectionAndIntensity;
float4 gMainLightColorAndFlags; float4 gMainLightColorAndFlags;
@@ -33,23 +33,23 @@ Shader "Builtin Forward Lit"
AdditionalLightData gAdditionalLights[XC_MAX_ADDITIONAL_LIGHTS]; AdditionalLightData gAdditionalLights[XC_MAX_ADDITIONAL_LIGHTS];
}; };
cbuffer MaterialConstants : register(b2) cbuffer MaterialConstants
{ {
float4 gBaseColorFactor; float4 gBaseColorFactor;
float4 gAlphaCutoffParams; float4 gAlphaCutoffParams;
}; };
cbuffer ShadowReceiverConstants : register(b3) cbuffer ShadowReceiverConstants
{ {
float4x4 gWorldToShadowMatrix; float4x4 gWorldToShadowMatrix;
float4 gShadowBiasAndTexelSize; float4 gShadowBiasAndTexelSize;
float4 gShadowOptions; float4 gShadowOptions;
}; };
Texture2D BaseColorTexture : register(t0); Texture2D BaseColorTexture;
SamplerState LinearClampSampler : register(s0); SamplerState LinearClampSampler;
Texture2D ShadowMapTexture : register(t1); Texture2D ShadowMapTexture;
SamplerState ShadowMapSampler : register(s1); SamplerState ShadowMapSampler;
struct VSInput struct VSInput
{ {

View File

@@ -13,7 +13,7 @@ Shader "Builtin Object Id"
#pragma target 4.5 #pragma target 4.5
#pragma vertex MainVS #pragma vertex MainVS
#pragma fragment MainPS #pragma fragment MainPS
cbuffer PerObjectConstants : register(b0) cbuffer PerObjectConstants
{ {
float4x4 gProjectionMatrix; float4x4 gProjectionMatrix;
float4x4 gViewMatrix; float4x4 gViewMatrix;

View File

@@ -7,21 +7,21 @@ Shader "Builtin Shadow Caster"
_MainTex ("Base Map", 2D) = "white" [Semantic(BaseColorTexture)] _MainTex ("Base Map", 2D) = "white" [Semantic(BaseColorTexture)]
} }
HLSLINCLUDE HLSLINCLUDE
cbuffer PerObjectConstants : register(b0) cbuffer PerObjectConstants
{ {
float4x4 gProjectionMatrix; float4x4 gProjectionMatrix;
float4x4 gViewMatrix; float4x4 gViewMatrix;
float4x4 gModelMatrix; float4x4 gModelMatrix;
}; };
cbuffer MaterialConstants : register(b1) cbuffer MaterialConstants
{ {
float4 gBaseColorFactor; float4 gBaseColorFactor;
float4 gAlphaCutoffParams; float4 gAlphaCutoffParams;
}; };
Texture2D BaseColorTexture : register(t0); Texture2D BaseColorTexture;
SamplerState LinearClampSampler : register(s0); SamplerState LinearClampSampler;
struct VSInput struct VSInput
{ {

View File

@@ -9,7 +9,7 @@ Shader "Builtin Skybox"
_Tex ("Cubemap (HDR)", Cube) = "white" [Semantic(SkyboxTexture)] _Tex ("Cubemap (HDR)", Cube) = "white" [Semantic(SkyboxTexture)]
} }
HLSLINCLUDE HLSLINCLUDE
cbuffer EnvironmentConstants : register(b0) cbuffer EnvironmentConstants
{ {
float4 gSkyboxTopColor; float4 gSkyboxTopColor;
float4 gSkyboxHorizonColor; float4 gSkyboxHorizonColor;
@@ -19,15 +19,15 @@ Shader "Builtin Skybox"
float4 gCameraForwardAndUnused; float4 gCameraForwardAndUnused;
}; };
cbuffer MaterialConstants : register(b1) cbuffer MaterialConstants
{ {
float4 gSkyboxTintAndExposure; float4 gSkyboxTintAndExposure;
float4 gSkyboxRotationAndMode; float4 gSkyboxRotationAndMode;
}; };
Texture2D SkyboxPanoramicTexture : register(t0); Texture2D SkyboxPanoramicTexture;
TextureCube SkyboxTexture : register(t1); TextureCube SkyboxTexture;
SamplerState LinearClampSampler : register(s0); SamplerState LinearClampSampler;
struct VSOutput struct VSOutput
{ {

View File

@@ -18,7 +18,7 @@ Shader "Builtin Unlit"
#pragma target 4.5 #pragma target 4.5
#pragma vertex MainVS #pragma vertex MainVS
#pragma fragment MainPS #pragma fragment MainPS
cbuffer PerObjectConstants : register(b0) cbuffer PerObjectConstants
{ {
float4x4 gProjectionMatrix; float4x4 gProjectionMatrix;
float4x4 gViewMatrix; float4x4 gViewMatrix;
@@ -26,13 +26,13 @@ Shader "Builtin Unlit"
float4x4 gNormalMatrix; float4x4 gNormalMatrix;
}; };
cbuffer MaterialConstants : register(b1) cbuffer MaterialConstants
{ {
float4 gBaseColorFactor; float4 gBaseColorFactor;
}; };
Texture2D BaseColorTexture : register(t0); Texture2D BaseColorTexture;
SamplerState LinearClampSampler : register(s0); SamplerState LinearClampSampler;
struct VSInput struct VSInput
{ {

View File

@@ -190,10 +190,10 @@ void CollectHlslTextureRegisterBindings(
std::unordered_map<std::string, GLint>& outTextureUnits, std::unordered_map<std::string, GLint>& outTextureUnits,
std::unordered_set<std::string>& outSamplerNames) { std::unordered_set<std::string>& outSamplerNames) {
static const std::regex kTexturePattern( static const std::regex kTexturePattern(
R"(((?:Texture2D|TextureCube)\s+([A-Za-z_][A-Za-z0-9_]*)\s*:\s*register\s*\(\s*t([0-9]+)))", R"(((?:Texture2D|TextureCube)\s+([A-Za-z_][A-Za-z0-9_]*)\s*:\s*register\s*\(\s*t([0-9]+)(?:\s*,\s*space[0-9]+)?\s*\)))",
std::regex::ECMAScript); std::regex::ECMAScript);
static const std::regex kSamplerPattern( static const std::regex kSamplerPattern(
R"(((?:SamplerState|SamplerComparisonState)\s+([A-Za-z_][A-Za-z0-9_]*)\s*:\s*register\s*\(\s*s([0-9]+)))", R"(((?:SamplerState|SamplerComparisonState)\s+([A-Za-z_][A-Za-z0-9_]*)\s*:\s*register\s*\(\s*s([0-9]+)(?:\s*,\s*space[0-9]+)?\s*\)))",
std::regex::ECMAScript); std::regex::ECMAScript);
for (std::sregex_iterator it(sourceText.begin(), sourceText.end(), kTexturePattern), end; it != end; ++it) { for (std::sregex_iterator it(sourceText.begin(), sourceText.end(), kTexturePattern), end; it != end; ++it) {

View File

@@ -3,8 +3,10 @@
#include <XCEngine/Core/Containers/String.h> #include <XCEngine/Core/Containers/String.h>
#include <XCEngine/RHI/RHIEnums.h> #include <XCEngine/RHI/RHIEnums.h>
#include <XCEngine/RHI/RHIPipelineState.h> #include <XCEngine/RHI/RHIPipelineState.h>
#include <XCEngine/Rendering/Builtin/BuiltinPassLayoutUtils.h>
#include <XCEngine/Resources/Shader/Shader.h> #include <XCEngine/Resources/Shader/Shader.h>
#include <regex>
#include <string> #include <string>
namespace XCEngine { namespace XCEngine {
@@ -44,6 +46,316 @@ inline std::wstring ToWideAscii(const Containers::String& value) {
return wide; return wide;
} }
inline std::string ToStdString(const Containers::String& value) {
return std::string(value.CStr(), value.Length());
}
inline std::string EscapeRegexLiteral(const Containers::String& value) {
std::string escaped;
escaped.reserve(value.Length() * 2u);
for (size_t index = 0; index < value.Length(); ++index) {
const char ch = value[index];
switch (ch) {
case '\\':
case '^':
case '$':
case '.':
case '|':
case '?':
case '*':
case '+':
case '(':
case ')':
case '[':
case ']':
case '{':
case '}':
escaped.push_back('\\');
break;
default:
break;
}
escaped.push_back(ch);
}
return escaped;
}
inline bool TryCollectShaderPassResourceBindings(
const Resources::ShaderPass& pass,
Containers::Array<Resources::ShaderResourceBindingDesc>& outBindings) {
outBindings.Clear();
if (!pass.resources.Empty()) {
outBindings.Reserve(pass.resources.Size());
for (const Resources::ShaderResourceBindingDesc& binding : pass.resources) {
outBindings.PushBack(binding);
}
return true;
}
return TryBuildImplicitBuiltinPassResourceBindings(pass, outBindings);
}
inline Containers::String ResolveLegacyHlslBindingDeclarationAlias(
const Resources::ShaderResourceBindingDesc& binding) {
switch (ResolveBuiltinPassResourceSemantic(binding)) {
case BuiltinPassResourceSemantic::BaseColorTexture:
return "gBaseColorTexture";
case BuiltinPassResourceSemantic::ShadowMapTexture:
return "gShadowMapTexture";
case BuiltinPassResourceSemantic::LinearClampSampler:
return "gLinearSampler";
case BuiltinPassResourceSemantic::ShadowMapSampler:
return "gShadowMapSampler";
case BuiltinPassResourceSemantic::Unknown:
default:
return Containers::String();
}
}
inline bool TryRewriteHlslRegisterBindingWithName(
std::string& sourceText,
const Containers::String& declarationName,
const char* registerPrefix,
Core::uint32 bindingIndex,
Core::uint32 setIndex,
bool includeRegisterSpace,
Resources::ShaderResourceType resourceType) {
if (declarationName.Empty()) {
return false;
}
const std::string registerClause =
includeRegisterSpace
? std::string("register(") + registerPrefix +
std::to_string(bindingIndex) +
", space" +
std::to_string(setIndex) +
")"
: std::string("register(") + registerPrefix +
std::to_string(bindingIndex) +
")";
const std::string escapedName = EscapeRegexLiteral(declarationName);
if (resourceType == Resources::ShaderResourceType::ConstantBuffer) {
const std::regex pattern(
"(cbuffer\\s+" + escapedName + "\\s*)(:\\s*register\\s*\\([^\\)]*\\))?(\\s*\\{)",
std::regex::ECMAScript);
const std::string rewritten =
std::regex_replace(sourceText, pattern, "$1: " + registerClause + "$3");
if (rewritten != sourceText) {
sourceText = rewritten;
return true;
}
return false;
}
const std::regex pattern(
"((?:Texture2D|TextureCube|SamplerState|SamplerComparisonState)\\s+" + escapedName +
"\\s*)(:\\s*register\\s*\\([^\\)]*\\))?(\\s*;)",
std::regex::ECMAScript);
const std::string rewritten =
std::regex_replace(sourceText, pattern, "$1: " + registerClause + "$3");
if (rewritten != sourceText) {
sourceText = rewritten;
return true;
}
return false;
}
inline const char* TryGetHlslRegisterPrefix(Resources::ShaderResourceType type) {
switch (type) {
case Resources::ShaderResourceType::ConstantBuffer:
return "b";
case Resources::ShaderResourceType::Texture2D:
case Resources::ShaderResourceType::TextureCube:
return "t";
case Resources::ShaderResourceType::Sampler:
return "s";
default:
return nullptr;
}
}
inline bool TryRewriteHlslRegisterBinding(
std::string& sourceText,
const Resources::ShaderResourceBindingDesc& binding,
bool includeRegisterSpace) {
const char* registerPrefix = TryGetHlslRegisterPrefix(binding.type);
if (registerPrefix == nullptr) {
return false;
}
if (TryRewriteHlslRegisterBindingWithName(
sourceText,
binding.name,
registerPrefix,
binding.binding,
binding.set,
includeRegisterSpace,
binding.type)) {
return true;
}
const Containers::String legacyAlias = ResolveLegacyHlslBindingDeclarationAlias(binding);
if (legacyAlias != binding.name &&
TryRewriteHlslRegisterBindingWithName(
sourceText,
legacyAlias,
registerPrefix,
binding.binding,
binding.set,
includeRegisterSpace,
binding.type)) {
return true;
}
if ((binding.type == Resources::ShaderResourceType::Texture2D ||
binding.type == Resources::ShaderResourceType::TextureCube ||
binding.type == Resources::ShaderResourceType::Sampler)) {
const Containers::String prefixedName = Containers::String("g") + binding.name;
if (prefixedName != binding.name &&
prefixedName != legacyAlias &&
TryRewriteHlslRegisterBindingWithName(
sourceText,
prefixedName,
registerPrefix,
binding.binding,
binding.set,
includeRegisterSpace,
binding.type)) {
return true;
}
}
return false;
}
inline bool TryBuildRuntimeShaderBindings(
const Resources::ShaderPass& pass,
Resources::ShaderBackend backend,
Containers::Array<Resources::ShaderResourceBindingDesc>& outBindings,
bool& outIncludeRegisterSpace) {
outBindings.Clear();
outIncludeRegisterSpace = false;
if (backend == Resources::ShaderBackend::Vulkan) {
outIncludeRegisterSpace = true;
return TryCollectShaderPassResourceBindings(pass, outBindings);
}
if (backend != Resources::ShaderBackend::D3D12 &&
backend != Resources::ShaderBackend::OpenGL) {
return false;
}
if (!pass.resources.Empty()) {
return false;
}
if (!TryBuildImplicitBuiltinPassResourceBindings(pass, outBindings)) {
return false;
}
Core::uint32 nextConstantBufferRegister = 0;
Core::uint32 nextTextureRegister = 0;
Core::uint32 nextSamplerRegister = 0;
Core::uint32 nextUnorderedAccessRegister = 0;
for (Resources::ShaderResourceBindingDesc& binding : outBindings) {
binding.set = 0;
switch (binding.type) {
case Resources::ShaderResourceType::ConstantBuffer:
binding.binding = nextConstantBufferRegister++;
break;
case Resources::ShaderResourceType::Texture2D:
case Resources::ShaderResourceType::TextureCube:
binding.binding = nextTextureRegister++;
break;
case Resources::ShaderResourceType::Sampler:
binding.binding = nextSamplerRegister++;
break;
default:
binding.binding = nextUnorderedAccessRegister++;
break;
}
}
return true;
}
inline std::string BuildRuntimeShaderSource(
const Resources::ShaderPass& pass,
Resources::ShaderBackend backend,
const Resources::ShaderStageVariant& variant) {
std::string sourceText = ToStdString(variant.sourceCode);
if (variant.language != Resources::ShaderLanguage::HLSL ||
backend == Resources::ShaderBackend::Generic) {
return sourceText;
}
Containers::Array<Resources::ShaderResourceBindingDesc> bindings;
bool includeRegisterSpace = false;
if (!TryBuildRuntimeShaderBindings(pass, backend, bindings, includeRegisterSpace)) {
return sourceText;
}
for (const Resources::ShaderResourceBindingDesc& binding : bindings) {
TryRewriteHlslRegisterBinding(sourceText, binding, includeRegisterSpace);
}
return sourceText;
}
inline void AddShaderCompileMacro(
RHI::ShaderCompileDesc& compileDesc,
const wchar_t* name,
const wchar_t* definition = L"1") {
if (name == nullptr || *name == L'\0') {
return;
}
for (const RHI::ShaderCompileMacro& existingMacro : compileDesc.macros) {
if (existingMacro.name == name) {
return;
}
}
RHI::ShaderCompileMacro macro = {};
macro.name = name;
macro.definition = definition != nullptr ? definition : L"";
compileDesc.macros.push_back(std::move(macro));
}
inline void InjectUnityStyleBackendMacros(
Resources::ShaderBackend backend,
RHI::ShaderCompileDesc& compileDesc) {
switch (backend) {
case Resources::ShaderBackend::OpenGL:
AddShaderCompileMacro(compileDesc, L"SHADER_API_GLCORE");
AddShaderCompileMacro(compileDesc, L"UNITY_UV_STARTS_AT_TOP", L"0");
AddShaderCompileMacro(compileDesc, L"UNITY_NEAR_CLIP_VALUE", L"-1");
break;
case Resources::ShaderBackend::Vulkan:
AddShaderCompileMacro(compileDesc, L"SHADER_API_VULKAN");
AddShaderCompileMacro(compileDesc, L"UNITY_UV_STARTS_AT_TOP", L"1");
AddShaderCompileMacro(compileDesc, L"UNITY_NEAR_CLIP_VALUE", L"0");
break;
case Resources::ShaderBackend::D3D12:
AddShaderCompileMacro(compileDesc, L"SHADER_API_D3D12");
AddShaderCompileMacro(compileDesc, L"UNITY_UV_STARTS_AT_TOP", L"1");
AddShaderCompileMacro(compileDesc, L"UNITY_NEAR_CLIP_VALUE", L"0");
break;
case Resources::ShaderBackend::Generic:
default:
break;
}
}
inline void ApplyShaderStageVariant( inline void ApplyShaderStageVariant(
const Resources::ShaderStageVariant& variant, const Resources::ShaderStageVariant& variant,
RHI::ShaderCompileDesc& compileDesc) { RHI::ShaderCompileDesc& compileDesc) {
@@ -55,6 +367,19 @@ inline void ApplyShaderStageVariant(
compileDesc.profile = ToWideAscii(variant.profile); compileDesc.profile = ToWideAscii(variant.profile);
} }
inline void ApplyShaderStageVariant(
const Resources::ShaderPass& pass,
Resources::ShaderBackend backend,
const Resources::ShaderStageVariant& variant,
RHI::ShaderCompileDesc& compileDesc) {
const std::string sourceText = BuildRuntimeShaderSource(pass, backend, variant);
compileDesc.source.assign(sourceText.begin(), sourceText.end());
compileDesc.sourceLanguage = ToRHIShaderLanguage(variant.language);
compileDesc.entryPoint = ToWideAscii(variant.entryPoint);
compileDesc.profile = ToWideAscii(variant.profile);
InjectUnityStyleBackendMacros(backend, compileDesc);
}
inline Containers::String BuildShaderKeywordSignature( inline Containers::String BuildShaderKeywordSignature(
const Resources::ShaderKeywordSet& keywordSet) { const Resources::ShaderKeywordSet& keywordSet) {
Resources::ShaderKeywordSet normalizedKeywords = keywordSet; Resources::ShaderKeywordSet normalizedKeywords = keywordSet;

View File

@@ -15,7 +15,7 @@
#include <XCEngine/RHI/ShaderCompiler/SpirvShaderCompiler.h> #include <XCEngine/RHI/ShaderCompiler/SpirvShaderCompiler.h>
#include <fstream> #include <fstream>
#include <iostream> #include <regex>
using namespace XCEngine::Rendering::Pipelines; using namespace XCEngine::Rendering::Pipelines;
using namespace XCEngine::Rendering::Passes; using namespace XCEngine::Rendering::Passes;
@@ -24,6 +24,58 @@ using namespace XCEngine::Containers;
using namespace XCEngine::Resources; using namespace XCEngine::Resources;
using namespace XCEngine::RHI; using namespace XCEngine::RHI;
namespace {
std::string EscapeRegexLiteralForTest(const std::string& value) {
std::string escaped;
escaped.reserve(value.size() * 2u);
for (const char ch : value) {
switch (ch) {
case '\\':
case '^':
case '$':
case '.':
case '|':
case '?':
case '*':
case '+':
case '(':
case ')':
case '[':
case ']':
case '{':
case '}':
escaped.push_back('\\');
break;
default:
break;
}
escaped.push_back(ch);
}
return escaped;
}
::testing::AssertionResult SourceContainsRegisterBinding(
const std::string& source,
const std::string& declaration,
const std::string& registerClause) {
const std::regex pattern(
EscapeRegexLiteralForTest(declaration) + "\\s*:\\s*" +
EscapeRegexLiteralForTest(registerClause),
std::regex::ECMAScript);
if (std::regex_search(source, pattern)) {
return ::testing::AssertionSuccess();
}
return ::testing::AssertionFailure()
<< "Missing binding '" << declaration << " : " << registerClause << "' in source:\n"
<< source;
}
} // namespace
TEST(BuiltinForwardPipeline_Test, UsesFloat3PositionInputLayoutForStaticMeshVertices) { TEST(BuiltinForwardPipeline_Test, UsesFloat3PositionInputLayoutForStaticMeshVertices) {
const InputLayoutDesc inputLayout = BuiltinForwardPipeline::BuildInputLayout(); const InputLayoutDesc inputLayout = BuiltinForwardPipeline::BuildInputLayout();
@@ -81,6 +133,15 @@ TEST(BuiltinForwardPipeline_Test, BuiltinForwardShaderUsesUnityStyleSingleSource
EXPECT_TRUE(pass->fixedFunctionState.depthWriteEnable); EXPECT_TRUE(pass->fixedFunctionState.depthWriteEnable);
EXPECT_EQ(pass->fixedFunctionState.depthFunc, MaterialComparisonFunc::LessEqual); EXPECT_EQ(pass->fixedFunctionState.depthFunc, MaterialComparisonFunc::LessEqual);
const ShaderStageVariant* fragmentVariant = shader->FindVariant(
"ForwardLit",
XCEngine::Resources::ShaderType::Fragment,
XCEngine::Resources::ShaderBackend::D3D12);
ASSERT_NE(fragmentVariant, nullptr);
EXPECT_EQ(
std::string(fragmentVariant->sourceCode.CStr()).find("register("),
std::string::npos);
delete shader; delete shader;
} }
@@ -101,6 +162,15 @@ TEST(BuiltinForwardPipeline_Test, BuiltinUnlitShaderUsesUnityStyleSingleSourceSu
EXPECT_TRUE(pass->fixedFunctionState.depthWriteEnable); EXPECT_TRUE(pass->fixedFunctionState.depthWriteEnable);
EXPECT_EQ(pass->fixedFunctionState.depthFunc, MaterialComparisonFunc::LessEqual); EXPECT_EQ(pass->fixedFunctionState.depthFunc, MaterialComparisonFunc::LessEqual);
const ShaderStageVariant* fragmentVariant = shader->FindVariant(
"Unlit",
XCEngine::Resources::ShaderType::Fragment,
XCEngine::Resources::ShaderBackend::D3D12);
ASSERT_NE(fragmentVariant, nullptr);
EXPECT_EQ(
std::string(fragmentVariant->sourceCode.CStr()).find("register("),
std::string::npos);
delete shader; delete shader;
} }
@@ -129,9 +199,10 @@ TEST(BuiltinForwardPipeline_Test, BuiltinUnlitShaderBuildsVulkanRuntimeSourceWit
XCEngine::Resources::ShaderBackend::Vulkan, XCEngine::Resources::ShaderBackend::Vulkan,
*fragmentVariant); *fragmentVariant);
EXPECT_NE( EXPECT_TRUE(SourceContainsRegisterBinding(
runtimeSource.find("cbuffer MaterialConstants : register(b0, space1)"), runtimeSource,
std::string::npos); "cbuffer MaterialConstants",
"register(b0, space1)"));
EXPECT_NE(runtimeSource.find("BaseColorTexture"), std::string::npos); EXPECT_NE(runtimeSource.find("BaseColorTexture"), std::string::npos);
EXPECT_NE(runtimeSource.find("space2"), std::string::npos); EXPECT_NE(runtimeSource.find("space2"), std::string::npos);
EXPECT_NE(runtimeSource.find("LinearClampSampler"), std::string::npos); EXPECT_NE(runtimeSource.find("LinearClampSampler"), std::string::npos);
@@ -167,10 +238,18 @@ TEST(BuiltinForwardPipeline_Test, VulkanRuntimeCompileDescRewritesUnityStyleUnli
const std::string d3d12Source( const std::string d3d12Source(
reinterpret_cast<const char*>(d3d12CompileDesc.source.data()), reinterpret_cast<const char*>(d3d12CompileDesc.source.data()),
d3d12CompileDesc.source.size()); d3d12CompileDesc.source.size());
EXPECT_NE(d3d12Source.find("BaseColorTexture"), std::string::npos); EXPECT_TRUE(SourceContainsRegisterBinding(
EXPECT_NE(d3d12Source.find("LinearClampSampler"), std::string::npos); d3d12Source,
EXPECT_EQ(d3d12Source.find("space2"), std::string::npos); "cbuffer MaterialConstants",
EXPECT_EQ(d3d12Source.find("space3"), std::string::npos); "register(b1)"));
EXPECT_TRUE(SourceContainsRegisterBinding(
d3d12Source,
"Texture2D BaseColorTexture",
"register(t0)"));
EXPECT_TRUE(SourceContainsRegisterBinding(
d3d12Source,
"SamplerState LinearClampSampler",
"register(s0)"));
const ShaderStageVariant* vulkanFragment = shader->FindVariant( const ShaderStageVariant* vulkanFragment = shader->FindVariant(
"Unlit", "Unlit",
@@ -187,7 +266,10 @@ TEST(BuiltinForwardPipeline_Test, VulkanRuntimeCompileDescRewritesUnityStyleUnli
const std::string vulkanSource( const std::string vulkanSource(
reinterpret_cast<const char*>(vulkanCompileDesc.source.data()), reinterpret_cast<const char*>(vulkanCompileDesc.source.data()),
vulkanCompileDesc.source.size()); vulkanCompileDesc.source.size());
EXPECT_NE(vulkanSource.find("cbuffer MaterialConstants : register(b0, space1)"), std::string::npos); EXPECT_TRUE(SourceContainsRegisterBinding(
vulkanSource,
"cbuffer MaterialConstants",
"register(b0, space1)"));
EXPECT_NE(vulkanSource.find("BaseColorTexture"), std::string::npos); EXPECT_NE(vulkanSource.find("BaseColorTexture"), std::string::npos);
EXPECT_NE(vulkanSource.find("space2"), std::string::npos); EXPECT_NE(vulkanSource.find("space2"), std::string::npos);
EXPECT_NE(vulkanSource.find("LinearClampSampler"), std::string::npos); EXPECT_NE(vulkanSource.find("LinearClampSampler"), std::string::npos);
@@ -227,10 +309,40 @@ TEST(BuiltinForwardPipeline_Test, VulkanRuntimeCompileDescRewritesUnityStyleForw
const std::string d3d12Source( const std::string d3d12Source(
reinterpret_cast<const char*>(d3d12CompileDesc.source.data()), reinterpret_cast<const char*>(d3d12CompileDesc.source.data()),
d3d12CompileDesc.source.size()); d3d12CompileDesc.source.size());
EXPECT_NE(d3d12Source.find("cbuffer LightingConstants : register(b1)"), std::string::npos); EXPECT_TRUE(SourceContainsRegisterBinding(
EXPECT_NE(d3d12Source.find("Texture2D ShadowMapTexture : register(t1)"), std::string::npos); d3d12Source,
"cbuffer PerObjectConstants",
"register(b0)"));
EXPECT_TRUE(SourceContainsRegisterBinding(
d3d12Source,
"cbuffer LightingConstants",
"register(b1)"));
EXPECT_TRUE(SourceContainsRegisterBinding(
d3d12Source,
"cbuffer MaterialConstants",
"register(b2)"));
EXPECT_TRUE(SourceContainsRegisterBinding(
d3d12Source,
"cbuffer ShadowReceiverConstants",
"register(b3)"));
EXPECT_TRUE(SourceContainsRegisterBinding(
d3d12Source,
"Texture2D BaseColorTexture",
"register(t0)"));
EXPECT_TRUE(SourceContainsRegisterBinding(
d3d12Source,
"SamplerState LinearClampSampler",
"register(s0)"));
EXPECT_TRUE(SourceContainsRegisterBinding(
d3d12Source,
"Texture2D ShadowMapTexture",
"register(t1)"));
EXPECT_TRUE(SourceContainsRegisterBinding(
d3d12Source,
"SamplerState ShadowMapSampler",
"register(s1)"));
EXPECT_EQ(d3d12Source.find("space0"), std::string::npos);
EXPECT_EQ(d3d12Source.find("space1"), std::string::npos); EXPECT_EQ(d3d12Source.find("space1"), std::string::npos);
EXPECT_EQ(d3d12Source.find("space6"), std::string::npos);
const ShaderStageVariant* vulkanFragment = shader->FindVariant( const ShaderStageVariant* vulkanFragment = shader->FindVariant(
"ForwardLit", "ForwardLit",
@@ -248,14 +360,38 @@ TEST(BuiltinForwardPipeline_Test, VulkanRuntimeCompileDescRewritesUnityStyleForw
const std::string vulkanSource( const std::string vulkanSource(
reinterpret_cast<const char*>(vulkanCompileDesc.source.data()), reinterpret_cast<const char*>(vulkanCompileDesc.source.data()),
vulkanCompileDesc.source.size()); vulkanCompileDesc.source.size());
EXPECT_NE(vulkanSource.find("cbuffer PerObjectConstants : register(b0, space0)"), std::string::npos); EXPECT_TRUE(SourceContainsRegisterBinding(
EXPECT_NE(vulkanSource.find("cbuffer LightingConstants : register(b0, space1)"), std::string::npos); vulkanSource,
EXPECT_NE(vulkanSource.find("cbuffer MaterialConstants : register(b0, space2)"), std::string::npos); "cbuffer PerObjectConstants",
EXPECT_NE(vulkanSource.find("cbuffer ShadowReceiverConstants : register(b0, space3)"), std::string::npos); "register(b0, space0)"));
EXPECT_NE(vulkanSource.find("Texture2D BaseColorTexture : register(t0, space4)"), std::string::npos); EXPECT_TRUE(SourceContainsRegisterBinding(
EXPECT_NE(vulkanSource.find("SamplerState LinearClampSampler : register(s0, space5)"), std::string::npos); vulkanSource,
EXPECT_NE(vulkanSource.find("Texture2D ShadowMapTexture : register(t0, space6)"), std::string::npos); "cbuffer LightingConstants",
EXPECT_NE(vulkanSource.find("SamplerState ShadowMapSampler : register(s0, space7)"), std::string::npos); "register(b0, space1)"));
EXPECT_TRUE(SourceContainsRegisterBinding(
vulkanSource,
"cbuffer MaterialConstants",
"register(b0, space2)"));
EXPECT_TRUE(SourceContainsRegisterBinding(
vulkanSource,
"cbuffer ShadowReceiverConstants",
"register(b0, space3)"));
EXPECT_TRUE(SourceContainsRegisterBinding(
vulkanSource,
"Texture2D BaseColorTexture",
"register(t0, space4)"));
EXPECT_TRUE(SourceContainsRegisterBinding(
vulkanSource,
"SamplerState LinearClampSampler",
"register(s0, space5)"));
EXPECT_TRUE(SourceContainsRegisterBinding(
vulkanSource,
"Texture2D ShadowMapTexture",
"register(t0, space6)"));
EXPECT_TRUE(SourceContainsRegisterBinding(
vulkanSource,
"SamplerState ShadowMapSampler",
"register(s0, space7)"));
delete shader; delete shader;
} }
@@ -664,11 +800,20 @@ TEST(BuiltinForwardPipeline_Test, VulkanRuntimeCompileDescRewritesUnityStyleFina
const std::string d3d12Source( const std::string d3d12Source(
reinterpret_cast<const char*>(d3d12CompileDesc.source.data()), reinterpret_cast<const char*>(d3d12CompileDesc.source.data()),
d3d12CompileDesc.source.size()); d3d12CompileDesc.source.size());
EXPECT_NE(d3d12Source.find("cbuffer FinalColorConstants : register(b0)"), std::string::npos); EXPECT_TRUE(SourceContainsRegisterBinding(
EXPECT_NE(d3d12Source.find("Texture2D gSourceColorTexture : register(t0)"), std::string::npos); d3d12Source,
EXPECT_NE(d3d12Source.find("SamplerState gLinearClampSampler : register(s0)"), std::string::npos); "cbuffer FinalColorConstants",
"register(b0)"));
EXPECT_TRUE(SourceContainsRegisterBinding(
d3d12Source,
"Texture2D gSourceColorTexture",
"register(t0)"));
EXPECT_TRUE(SourceContainsRegisterBinding(
d3d12Source,
"SamplerState gLinearClampSampler",
"register(s0)"));
EXPECT_EQ(d3d12Source.find("space0"), std::string::npos);
EXPECT_EQ(d3d12Source.find("space1"), std::string::npos); EXPECT_EQ(d3d12Source.find("space1"), std::string::npos);
EXPECT_EQ(d3d12Source.find("space2"), std::string::npos);
const ShaderStageVariant* vulkanFragment = shader->FindVariant( const ShaderStageVariant* vulkanFragment = shader->FindVariant(
"FinalColor", "FinalColor",
@@ -681,15 +826,18 @@ TEST(BuiltinForwardPipeline_Test, VulkanRuntimeCompileDescRewritesUnityStyleFina
*pass, *pass,
XCEngine::Resources::ShaderBackend::Vulkan, XCEngine::Resources::ShaderBackend::Vulkan,
*vulkanFragment); *vulkanFragment);
EXPECT_NE( EXPECT_TRUE(SourceContainsRegisterBinding(
runtimeSource.find("cbuffer FinalColorConstants : register(b0, space0)"), runtimeSource,
std::string::npos); "cbuffer FinalColorConstants",
EXPECT_NE( "register(b0, space0)"));
runtimeSource.find("Texture2D gSourceColorTexture : register(t0, space1)"), EXPECT_TRUE(SourceContainsRegisterBinding(
std::string::npos); runtimeSource,
EXPECT_NE( "Texture2D gSourceColorTexture",
runtimeSource.find("SamplerState gLinearClampSampler : register(s0, space2)"), "register(t0, space1)"));
std::string::npos); EXPECT_TRUE(SourceContainsRegisterBinding(
runtimeSource,
"SamplerState gLinearClampSampler",
"register(s0, space2)"));
ShaderCompileDesc vulkanCompileDesc = {}; ShaderCompileDesc vulkanCompileDesc = {};
::XCEngine::Rendering::Detail::ApplyShaderStageVariant( ::XCEngine::Rendering::Detail::ApplyShaderStageVariant(
@@ -778,11 +926,20 @@ TEST(BuiltinForwardPipeline_Test, VulkanRuntimeCompileDescRewritesUnityStyleColo
const std::string d3d12Source( const std::string d3d12Source(
reinterpret_cast<const char*>(d3d12CompileDesc.source.data()), reinterpret_cast<const char*>(d3d12CompileDesc.source.data()),
d3d12CompileDesc.source.size()); d3d12CompileDesc.source.size());
EXPECT_NE(d3d12Source.find("cbuffer PostProcessConstants : register(b0)"), std::string::npos); EXPECT_TRUE(SourceContainsRegisterBinding(
EXPECT_NE(d3d12Source.find("Texture2D gSourceColorTexture : register(t0)"), std::string::npos); d3d12Source,
EXPECT_NE(d3d12Source.find("SamplerState gLinearClampSampler : register(s0)"), std::string::npos); "cbuffer PostProcessConstants",
"register(b0)"));
EXPECT_TRUE(SourceContainsRegisterBinding(
d3d12Source,
"Texture2D gSourceColorTexture",
"register(t0)"));
EXPECT_TRUE(SourceContainsRegisterBinding(
d3d12Source,
"SamplerState gLinearClampSampler",
"register(s0)"));
EXPECT_EQ(d3d12Source.find("space0"), std::string::npos);
EXPECT_EQ(d3d12Source.find("space1"), std::string::npos); EXPECT_EQ(d3d12Source.find("space1"), std::string::npos);
EXPECT_EQ(d3d12Source.find("space2"), std::string::npos);
const ShaderStageVariant* vulkanFragment = shader->FindVariant( const ShaderStageVariant* vulkanFragment = shader->FindVariant(
"ColorScale", "ColorScale",
@@ -795,15 +952,18 @@ TEST(BuiltinForwardPipeline_Test, VulkanRuntimeCompileDescRewritesUnityStyleColo
*pass, *pass,
XCEngine::Resources::ShaderBackend::Vulkan, XCEngine::Resources::ShaderBackend::Vulkan,
*vulkanFragment); *vulkanFragment);
EXPECT_NE( EXPECT_TRUE(SourceContainsRegisterBinding(
runtimeSource.find("cbuffer PostProcessConstants : register(b0, space0)"), runtimeSource,
std::string::npos); "cbuffer PostProcessConstants",
EXPECT_NE( "register(b0, space0)"));
runtimeSource.find("Texture2D gSourceColorTexture : register(t0, space1)"), EXPECT_TRUE(SourceContainsRegisterBinding(
std::string::npos); runtimeSource,
EXPECT_NE( "Texture2D gSourceColorTexture",
runtimeSource.find("SamplerState gLinearClampSampler : register(s0, space2)"), "register(t0, space1)"));
std::string::npos); EXPECT_TRUE(SourceContainsRegisterBinding(
runtimeSource,
"SamplerState gLinearClampSampler",
"register(s0, space2)"));
ShaderCompileDesc vulkanCompileDesc = {}; ShaderCompileDesc vulkanCompileDesc = {};
::XCEngine::Rendering::Detail::ApplyShaderStageVariant( ::XCEngine::Rendering::Detail::ApplyShaderStageVariant(