rendering: thread global shader keywords into builtin variants
This commit is contained in:
@@ -43,6 +43,9 @@ in vec3 vPositionWS;
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
|
||||
float ComputeShadowAttenuation(vec3 positionWS) {
|
||||
#ifndef XC_MAIN_LIGHT_SHADOWS
|
||||
return 1.0;
|
||||
#else
|
||||
if (gShadowOptions.x < 0.5) {
|
||||
return 1.0;
|
||||
}
|
||||
@@ -66,6 +69,7 @@ float ComputeShadowAttenuation(vec3 positionWS) {
|
||||
float receiverDepth = shadowNdc.z * 0.5 + 0.5 - gShadowBiasAndTexelSize.x;
|
||||
float shadowStrength = clamp(gShadowBiasAndTexelSize.w, 0.0, 1.0);
|
||||
return receiverDepth <= shadowDepth ? 1.0 : (1.0 - shadowStrength);
|
||||
#endif
|
||||
}
|
||||
|
||||
float ComputeRangeAttenuation(float distanceSq, float range) {
|
||||
|
||||
@@ -45,6 +45,9 @@ layout(location = 2) in vec3 vPositionWS;
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
|
||||
float ComputeShadowAttenuation(vec3 positionWS) {
|
||||
#ifndef XC_MAIN_LIGHT_SHADOWS
|
||||
return 1.0;
|
||||
#else
|
||||
if (gShadowOptions.x < 0.5) {
|
||||
return 1.0;
|
||||
}
|
||||
@@ -68,6 +71,7 @@ float ComputeShadowAttenuation(vec3 positionWS) {
|
||||
float receiverDepth = shadowNdc.z - gShadowBiasAndTexelSize.x;
|
||||
float shadowStrength = clamp(gShadowBiasAndTexelSize.w, 0.0, 1.0);
|
||||
return receiverDepth <= shadowDepth ? 1.0 : (1.0 - shadowStrength);
|
||||
#endif
|
||||
}
|
||||
|
||||
float ComputeRangeAttenuation(float distanceSq, float range) {
|
||||
|
||||
@@ -45,6 +45,9 @@ struct PSInput {
|
||||
};
|
||||
|
||||
float ComputeShadowAttenuation(float3 positionWS) {
|
||||
#ifndef XC_MAIN_LIGHT_SHADOWS
|
||||
return 1.0f;
|
||||
#else
|
||||
if (gShadowOptions.x < 0.5f) {
|
||||
return 1.0f;
|
||||
}
|
||||
@@ -68,6 +71,7 @@ float ComputeShadowAttenuation(float3 positionWS) {
|
||||
const float receiverDepth = shadowNdc.z - gShadowBiasAndTexelSize.x;
|
||||
const float shadowStrength = saturate(gShadowBiasAndTexelSize.w);
|
||||
return receiverDepth <= shadowDepth ? 1.0f : (1.0f - shadowStrength);
|
||||
#endif
|
||||
}
|
||||
|
||||
float ComputeRangeAttenuation(float distanceSq, float range) {
|
||||
|
||||
@@ -25,6 +25,7 @@ Shader "Builtin Forward Lit"
|
||||
HLSLPROGRAM
|
||||
#pragma vertex MainVS
|
||||
#pragma fragment MainPS
|
||||
#pragma multi_compile _ XC_MAIN_LIGHT_SHADOWS
|
||||
#pragma backend D3D12 HLSL "forward-lit.vs.hlsl" "forward-lit.ps.hlsl" vs_5_0 ps_5_0
|
||||
#pragma backend OpenGL GLSL "forward-lit.vert.glsl" "forward-lit.frag.glsl"
|
||||
#pragma backend Vulkan GLSL "forward-lit.vert.vk.glsl" "forward-lit.frag.vk.glsl"
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <XCEngine/Rendering/FrameData/RenderCameraData.h>
|
||||
#include <XCEngine/Rendering/FrameData/RenderEnvironmentData.h>
|
||||
#include <XCEngine/Rendering/FrameData/VisibleRenderItem.h>
|
||||
#include <XCEngine/Resources/Shader/ShaderKeywordTypes.h>
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
@@ -84,6 +85,7 @@ struct RenderSceneData {
|
||||
RenderCameraData cameraData;
|
||||
RenderEnvironmentData environment;
|
||||
RenderLightingData lighting;
|
||||
Resources::ShaderKeywordSet globalShaderKeywords;
|
||||
std::vector<VisibleRenderItem> visibleItems;
|
||||
|
||||
bool HasCamera() const {
|
||||
|
||||
@@ -139,7 +139,9 @@ private:
|
||||
bool CreateResources(const RenderContext& context);
|
||||
void DestroyResources();
|
||||
|
||||
ResolvedShaderPass ResolveSurfaceShaderPass(const Resources::Material* material) const;
|
||||
ResolvedShaderPass ResolveSurfaceShaderPass(
|
||||
const RenderSceneData& sceneData,
|
||||
const Resources::Material* material) const;
|
||||
bool TryBuildSupportedBindingPlan(
|
||||
const Resources::ShaderPass& shaderPass,
|
||||
BuiltinPassResourceBindingPlan& outPlan,
|
||||
@@ -150,6 +152,7 @@ private:
|
||||
RHI::RHIPipelineState* GetOrCreatePipelineState(
|
||||
const RenderContext& context,
|
||||
const RenderSurface& surface,
|
||||
const RenderSceneData& sceneData,
|
||||
const Resources::Material* material);
|
||||
bool CreateOwnedDescriptorSet(
|
||||
const BuiltinPassSetLayoutMetadata& setLayout,
|
||||
|
||||
@@ -222,12 +222,15 @@ private:
|
||||
static bool TryResolveSurfacePassType(
|
||||
const Resources::Material* material,
|
||||
BuiltinMaterialPass& outPass);
|
||||
ResolvedShaderPass ResolveSurfaceShaderPass(const Resources::Material* material) const;
|
||||
ResolvedShaderPass ResolveSurfaceShaderPass(
|
||||
const RenderSceneData& sceneData,
|
||||
const Resources::Material* material) const;
|
||||
PassResourceLayout* GetOrCreatePassResourceLayout(
|
||||
const RenderContext& context,
|
||||
const ResolvedShaderPass& resolvedShaderPass);
|
||||
RHI::RHIPipelineState* GetOrCreatePipelineState(
|
||||
const RenderContext& context,
|
||||
const RenderSceneData& sceneData,
|
||||
const Resources::Material* material);
|
||||
bool CreateOwnedDescriptorSet(
|
||||
const BuiltinPassSetLayoutMetadata& setLayout,
|
||||
|
||||
@@ -112,5 +112,17 @@ inline bool IsShaderKeywordSubset(
|
||||
return true;
|
||||
}
|
||||
|
||||
inline ShaderKeywordSet CombineShaderKeywordSets(
|
||||
const ShaderKeywordSet& first,
|
||||
const ShaderKeywordSet& second) {
|
||||
ShaderKeywordSet combined = first;
|
||||
for (const Containers::String& keyword : second.enabledKeywords) {
|
||||
combined.enabledKeywords.PushBack(keyword);
|
||||
}
|
||||
|
||||
NormalizeShaderKeywordSetInPlace(combined);
|
||||
return combined;
|
||||
}
|
||||
|
||||
} // namespace Resources
|
||||
} // namespace XCEngine
|
||||
|
||||
@@ -45,6 +45,17 @@ std::unique_ptr<RenderPipeline> CreatePipelineFromAsset(
|
||||
return std::make_unique<Pipelines::BuiltinForwardPipeline>();
|
||||
}
|
||||
|
||||
Resources::ShaderKeywordSet BuildSceneGlobalShaderKeywords(
|
||||
const RenderSceneData& sceneData) {
|
||||
Resources::ShaderKeywordSet keywords = {};
|
||||
if (sceneData.lighting.HasMainDirectionalShadow()) {
|
||||
keywords.enabledKeywords.PushBack("XC_MAIN_LIGHT_SHADOWS");
|
||||
}
|
||||
|
||||
Resources::NormalizeShaderKeywordSetInPlace(keywords);
|
||||
return keywords;
|
||||
}
|
||||
|
||||
bool InitializeStandalonePass(
|
||||
RenderPass* pass,
|
||||
const RenderContext& context) {
|
||||
@@ -563,6 +574,7 @@ bool CameraRenderer::BuildSceneDataForRequest(
|
||||
outSceneData.lighting.mainDirectionalShadow =
|
||||
BuildDirectionalShadowData(request.directionalShadow, shadowMapView);
|
||||
}
|
||||
outSceneData.globalShaderKeywords = BuildSceneGlobalShaderKeywords(outSceneData);
|
||||
|
||||
outSceneData.cameraData.clearFlags = request.clearFlags;
|
||||
outSceneData.environment = BuildEnvironmentData(request);
|
||||
|
||||
@@ -20,6 +20,14 @@ namespace Passes {
|
||||
|
||||
namespace {
|
||||
|
||||
Resources::ShaderKeywordSet ResolvePassKeywordSet(
|
||||
const RenderSceneData& sceneData,
|
||||
const Resources::Material* material) {
|
||||
return Resources::CombineShaderKeywordSets(
|
||||
sceneData.globalShaderKeywords,
|
||||
material != nullptr ? material->GetKeywordSet() : Resources::ShaderKeywordSet());
|
||||
}
|
||||
|
||||
bool IsSupportedPerObjectOnlyBindingPlan(const BuiltinPassResourceBindingPlan& bindingPlan) {
|
||||
return bindingPlan.perObject.IsValid() &&
|
||||
bindingPlan.bindings.Size() == 1u &&
|
||||
@@ -57,6 +65,7 @@ RHI::GraphicsPipelineDesc CreatePipelineDesc(
|
||||
RHI::RHIPipelineLayout* pipelineLayout,
|
||||
const Resources::Shader& shader,
|
||||
const Containers::String& passName,
|
||||
const Resources::ShaderKeywordSet& keywordSet,
|
||||
const Resources::Material* material,
|
||||
const RenderSurface& surface,
|
||||
const RHI::InputLayoutDesc& inputLayout) {
|
||||
@@ -81,8 +90,6 @@ RHI::GraphicsPipelineDesc CreatePipelineDesc(
|
||||
pipelineDesc.depthStencilState.depthFunc = static_cast<uint32_t>(RHI::ComparisonFunc::LessEqual);
|
||||
|
||||
const Resources::ShaderBackend backend = ::XCEngine::Rendering::Detail::ToShaderBackend(backendType);
|
||||
const Resources::ShaderKeywordSet keywordSet =
|
||||
material != nullptr ? material->GetKeywordSet() : Resources::ShaderKeywordSet();
|
||||
if (const Resources::ShaderStageVariant* vertexVariant =
|
||||
shader.FindVariant(passName, Resources::ShaderType::Vertex, backend, keywordSet)) {
|
||||
::XCEngine::Rendering::Detail::ApplyShaderStageVariant(*vertexVariant, pipelineDesc.vertexShader);
|
||||
@@ -154,12 +161,13 @@ void BuiltinDepthStylePassBase::DestroyResources() {
|
||||
}
|
||||
|
||||
BuiltinDepthStylePassBase::ResolvedShaderPass BuiltinDepthStylePassBase::ResolveSurfaceShaderPass(
|
||||
const RenderSceneData& sceneData,
|
||||
const Resources::Material* material) const {
|
||||
ResolvedShaderPass resolved = {};
|
||||
const Resources::ShaderBackend backend = ::XCEngine::Rendering::Detail::ToShaderBackend(m_backendType);
|
||||
|
||||
auto tryResolveFromShader =
|
||||
[this, backend, &resolved](
|
||||
[this, backend, &resolved, &sceneData](
|
||||
const Resources::Shader* shader,
|
||||
const Resources::Material* ownerMaterial) -> bool {
|
||||
if (shader == nullptr) {
|
||||
@@ -167,8 +175,7 @@ BuiltinDepthStylePassBase::ResolvedShaderPass BuiltinDepthStylePassBase::Resolve
|
||||
}
|
||||
|
||||
const bool shaderHasExplicitBuiltinMetadata = ShaderHasExplicitBuiltinMetadata(*shader);
|
||||
const Resources::ShaderKeywordSet keywordSet =
|
||||
ownerMaterial != nullptr ? ownerMaterial->GetKeywordSet() : Resources::ShaderKeywordSet();
|
||||
const Resources::ShaderKeywordSet keywordSet = ResolvePassKeywordSet(sceneData, ownerMaterial);
|
||||
|
||||
auto tryAcceptPass =
|
||||
[this, shader, &resolved](const Resources::ShaderPass& shaderPass) -> bool {
|
||||
@@ -333,8 +340,10 @@ BuiltinDepthStylePassBase::PassResourceLayout* BuiltinDepthStylePassBase::GetOrC
|
||||
RHI::RHIPipelineState* BuiltinDepthStylePassBase::GetOrCreatePipelineState(
|
||||
const RenderContext& context,
|
||||
const RenderSurface& surface,
|
||||
const RenderSceneData& sceneData,
|
||||
const Resources::Material* material) {
|
||||
const ResolvedShaderPass resolvedShaderPass = ResolveSurfaceShaderPass(material);
|
||||
const Resources::ShaderKeywordSet keywordSet = ResolvePassKeywordSet(sceneData, material);
|
||||
const ResolvedShaderPass resolvedShaderPass = ResolveSurfaceShaderPass(sceneData, material);
|
||||
if (resolvedShaderPass.shader == nullptr || resolvedShaderPass.pass == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -349,9 +358,7 @@ RHI::RHIPipelineState* BuiltinDepthStylePassBase::GetOrCreatePipelineState(
|
||||
material != nullptr ? material->GetRenderState() : Resources::MaterialRenderState();
|
||||
pipelineKey.shader = resolvedShaderPass.shader;
|
||||
pipelineKey.passName = resolvedShaderPass.passName;
|
||||
pipelineKey.keywordSignature =
|
||||
::XCEngine::Rendering::Detail::BuildShaderKeywordSignature(
|
||||
material != nullptr ? material->GetKeywordSet() : Resources::ShaderKeywordSet());
|
||||
pipelineKey.keywordSignature = ::XCEngine::Rendering::Detail::BuildShaderKeywordSignature(keywordSet);
|
||||
pipelineKey.renderTargetCount = ResolveSurfaceColorAttachmentCount(surface);
|
||||
pipelineKey.renderTargetFormat = static_cast<uint32_t>(ResolveSurfaceColorFormat(surface));
|
||||
pipelineKey.depthStencilFormat = static_cast<uint32_t>(ResolveSurfaceDepthFormat(surface));
|
||||
@@ -366,6 +373,7 @@ RHI::RHIPipelineState* BuiltinDepthStylePassBase::GetOrCreatePipelineState(
|
||||
passLayout->pipelineLayout,
|
||||
*resolvedShaderPass.shader,
|
||||
resolvedShaderPass.passName,
|
||||
keywordSet,
|
||||
material,
|
||||
surface,
|
||||
BuildCommonInputLayout());
|
||||
@@ -480,7 +488,7 @@ bool BuiltinDepthStylePassBase::DrawVisibleItem(
|
||||
}
|
||||
|
||||
const Resources::Material* material = ResolveMaterial(visibleItem);
|
||||
const ResolvedShaderPass resolvedShaderPass = ResolveSurfaceShaderPass(material);
|
||||
const ResolvedShaderPass resolvedShaderPass = ResolveSurfaceShaderPass(sceneData, material);
|
||||
if (resolvedShaderPass.shader == nullptr || resolvedShaderPass.pass == nullptr) {
|
||||
Debug::Logger::Get().Error(
|
||||
Debug::LogCategory::Rendering,
|
||||
@@ -502,7 +510,7 @@ bool BuiltinDepthStylePassBase::DrawVisibleItem(
|
||||
return false;
|
||||
}
|
||||
|
||||
RHI::RHIPipelineState* pipelineState = GetOrCreatePipelineState(context, surface, material);
|
||||
RHI::RHIPipelineState* pipelineState = GetOrCreatePipelineState(context, surface, sceneData, material);
|
||||
if (pipelineState == nullptr) {
|
||||
Debug::Logger::Get().Error(
|
||||
Debug::LogCategory::Rendering,
|
||||
|
||||
@@ -506,7 +506,7 @@ bool BuiltinForwardPipeline::DrawVisibleItems(
|
||||
continue;
|
||||
}
|
||||
|
||||
RHI::RHIPipelineState* pipelineState = GetOrCreatePipelineState(context, material);
|
||||
RHI::RHIPipelineState* pipelineState = GetOrCreatePipelineState(context, sceneData, material);
|
||||
if (pipelineState == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -23,14 +23,22 @@ namespace {
|
||||
constexpr float kForwardAmbientIntensity = 0.28f;
|
||||
constexpr float kSpotInnerAngleRatio = 0.8f;
|
||||
|
||||
Resources::ShaderKeywordSet ResolvePassKeywordSet(
|
||||
const RenderSceneData& sceneData,
|
||||
const Resources::Material* material) {
|
||||
return Resources::CombineShaderKeywordSets(
|
||||
sceneData.globalShaderKeywords,
|
||||
material != nullptr ? material->GetKeywordSet() : Resources::ShaderKeywordSet());
|
||||
}
|
||||
|
||||
const Resources::ShaderPass* FindCompatibleSurfacePass(
|
||||
const Resources::Shader& shader,
|
||||
const RenderSceneData& sceneData,
|
||||
const Resources::Material* material,
|
||||
BuiltinMaterialPass pass,
|
||||
Resources::ShaderBackend backend) {
|
||||
const bool shaderHasExplicitBuiltinMetadata = ShaderHasExplicitBuiltinMetadata(shader);
|
||||
const Resources::ShaderKeywordSet keywordSet =
|
||||
material != nullptr ? material->GetKeywordSet() : Resources::ShaderKeywordSet();
|
||||
const Resources::ShaderKeywordSet keywordSet = ResolvePassKeywordSet(sceneData, material);
|
||||
|
||||
for (const Resources::ShaderPass& shaderPass : shader.GetPasses()) {
|
||||
if (ShaderPassMatchesBuiltinPass(shaderPass, pass) &&
|
||||
@@ -102,6 +110,7 @@ RHI::GraphicsPipelineDesc CreatePipelineDesc(
|
||||
RHI::RHIPipelineLayout* pipelineLayout,
|
||||
const Resources::Shader& shader,
|
||||
const Containers::String& passName,
|
||||
const Resources::ShaderKeywordSet& keywordSet,
|
||||
const Resources::Material* material) {
|
||||
RHI::GraphicsPipelineDesc pipelineDesc = {};
|
||||
pipelineDesc.pipelineLayout = pipelineLayout;
|
||||
@@ -115,8 +124,6 @@ RHI::GraphicsPipelineDesc CreatePipelineDesc(
|
||||
pipelineDesc.inputLayout = BuiltinForwardPipeline::BuildInputLayout();
|
||||
|
||||
const Resources::ShaderBackend backend = ::XCEngine::Rendering::Detail::ToShaderBackend(backendType);
|
||||
const Resources::ShaderKeywordSet keywordSet =
|
||||
material != nullptr ? material->GetKeywordSet() : Resources::ShaderKeywordSet();
|
||||
const Resources::ShaderStageVariant* vertexVariant =
|
||||
shader.FindVariant(passName, Resources::ShaderType::Vertex, backend, keywordSet);
|
||||
const Resources::ShaderStageVariant* fragmentVariant =
|
||||
@@ -150,6 +157,7 @@ bool BuiltinForwardPipeline::TryResolveSurfacePassType(
|
||||
}
|
||||
|
||||
BuiltinForwardPipeline::ResolvedShaderPass BuiltinForwardPipeline::ResolveSurfaceShaderPass(
|
||||
const RenderSceneData& sceneData,
|
||||
const Resources::Material* material) const {
|
||||
ResolvedShaderPass resolved = {};
|
||||
BuiltinMaterialPass pass = BuiltinMaterialPass::ForwardLit;
|
||||
@@ -162,7 +170,7 @@ BuiltinForwardPipeline::ResolvedShaderPass BuiltinForwardPipeline::ResolveSurfac
|
||||
if (material != nullptr && material->GetShader() != nullptr) {
|
||||
const Resources::Shader* materialShader = material->GetShader();
|
||||
if (const Resources::ShaderPass* shaderPass =
|
||||
FindCompatibleSurfacePass(*materialShader, material, pass, backend)) {
|
||||
FindCompatibleSurfacePass(*materialShader, sceneData, material, pass, backend)) {
|
||||
resolved.shader = materialShader;
|
||||
resolved.pass = shaderPass;
|
||||
resolved.passName = shaderPass->name;
|
||||
@@ -175,7 +183,7 @@ BuiltinForwardPipeline::ResolvedShaderPass BuiltinForwardPipeline::ResolveSurfac
|
||||
if (builtinShaderHandle->IsValid()) {
|
||||
const Resources::Shader* builtinShader = builtinShaderHandle->Get();
|
||||
if (const Resources::ShaderPass* shaderPass =
|
||||
FindCompatibleSurfacePass(*builtinShader, nullptr, pass, backend)) {
|
||||
FindCompatibleSurfacePass(*builtinShader, sceneData, nullptr, pass, backend)) {
|
||||
resolved.shader = builtinShader;
|
||||
resolved.pass = shaderPass;
|
||||
resolved.passName = shaderPass->name;
|
||||
@@ -274,8 +282,10 @@ BuiltinForwardPipeline::PassResourceLayout* BuiltinForwardPipeline::GetOrCreateP
|
||||
|
||||
RHI::RHIPipelineState* BuiltinForwardPipeline::GetOrCreatePipelineState(
|
||||
const RenderContext& context,
|
||||
const RenderSceneData& sceneData,
|
||||
const Resources::Material* material) {
|
||||
const ResolvedShaderPass resolvedShaderPass = ResolveSurfaceShaderPass(material);
|
||||
const Resources::ShaderKeywordSet keywordSet = ResolvePassKeywordSet(sceneData, material);
|
||||
const ResolvedShaderPass resolvedShaderPass = ResolveSurfaceShaderPass(sceneData, material);
|
||||
if (resolvedShaderPass.shader == nullptr || resolvedShaderPass.pass == nullptr) {
|
||||
Debug::Logger::Get().Error(
|
||||
Debug::LogCategory::Rendering,
|
||||
@@ -293,9 +303,7 @@ RHI::RHIPipelineState* BuiltinForwardPipeline::GetOrCreatePipelineState(
|
||||
material != nullptr ? material->GetRenderState() : Resources::MaterialRenderState();
|
||||
pipelineKey.shader = resolvedShaderPass.shader;
|
||||
pipelineKey.passName = resolvedShaderPass.passName;
|
||||
pipelineKey.keywordSignature =
|
||||
::XCEngine::Rendering::Detail::BuildShaderKeywordSignature(
|
||||
material != nullptr ? material->GetKeywordSet() : Resources::ShaderKeywordSet());
|
||||
pipelineKey.keywordSignature = ::XCEngine::Rendering::Detail::BuildShaderKeywordSignature(keywordSet);
|
||||
|
||||
const auto existing = m_pipelineStates.find(pipelineKey);
|
||||
if (existing != m_pipelineStates.end()) {
|
||||
@@ -308,6 +316,7 @@ RHI::RHIPipelineState* BuiltinForwardPipeline::GetOrCreatePipelineState(
|
||||
passLayout->pipelineLayout,
|
||||
*resolvedShaderPass.shader,
|
||||
resolvedShaderPass.passName,
|
||||
keywordSet,
|
||||
material);
|
||||
RHI::RHIPipelineState* pipelineState = context.device->CreatePipelineState(pipelineDesc);
|
||||
if (pipelineState == nullptr || !pipelineState->IsValid()) {
|
||||
@@ -665,7 +674,7 @@ bool BuiltinForwardPipeline::DrawVisibleItem(
|
||||
};
|
||||
|
||||
const Resources::Material* material = ResolveMaterial(visibleItem);
|
||||
const ResolvedShaderPass resolvedShaderPass = ResolveSurfaceShaderPass(material);
|
||||
const ResolvedShaderPass resolvedShaderPass = ResolveSurfaceShaderPass(sceneData, material);
|
||||
if (resolvedShaderPass.shader == nullptr || resolvedShaderPass.pass == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <XCEngine/Rendering/RenderSurface.h>
|
||||
#include <XCEngine/Rendering/Execution/SceneRenderer.h>
|
||||
#include <XCEngine/Resources/Material/Material.h>
|
||||
#include <XCEngine/Resources/Shader/ShaderKeywordTypes.h>
|
||||
#include <XCEngine/Scene/Scene.h>
|
||||
|
||||
#include <memory>
|
||||
@@ -44,6 +45,7 @@ struct MockPipelineState {
|
||||
XCEngine::RHI::RHIResourceView* lastShadowMap = nullptr;
|
||||
XCEngine::Math::Matrix4x4 lastShadowViewProjection = XCEngine::Math::Matrix4x4::Identity();
|
||||
XCEngine::Math::Vector4 lastShadowParams = XCEngine::Math::Vector4::Zero();
|
||||
bool lastHasMainDirectionalShadowKeyword = false;
|
||||
RenderEnvironmentMode lastEnvironmentMode = RenderEnvironmentMode::None;
|
||||
bool lastHasSkybox = false;
|
||||
const XCEngine::Resources::Material* lastSkyboxMaterial = nullptr;
|
||||
@@ -320,6 +322,10 @@ public:
|
||||
m_state->lastShadowMap = sceneData.lighting.mainDirectionalShadow.shadowMap;
|
||||
m_state->lastShadowViewProjection = sceneData.lighting.mainDirectionalShadow.viewProjection;
|
||||
m_state->lastShadowParams = sceneData.lighting.mainDirectionalShadow.shadowParams;
|
||||
m_state->lastHasMainDirectionalShadowKeyword =
|
||||
XCEngine::Resources::ShaderKeywordSetContains(
|
||||
sceneData.globalShaderKeywords,
|
||||
"XC_MAIN_LIGHT_SHADOWS");
|
||||
m_state->lastEnvironmentMode = sceneData.environment.mode;
|
||||
m_state->lastHasSkybox = sceneData.environment.HasSkybox();
|
||||
m_state->lastSkyboxMaterial = sceneData.environment.materialSkybox.material;
|
||||
@@ -1281,6 +1287,7 @@ TEST(CameraRenderer_Test, AutoAllocatesDirectionalShadowSurfaceFromShadowPlan) {
|
||||
EXPECT_FLOAT_EQ(pipelineState->lastShadowParams.y, 1.0f / 256.0f);
|
||||
EXPECT_FLOAT_EQ(pipelineState->lastShadowParams.z, 1.0f / 128.0f);
|
||||
EXPECT_FLOAT_EQ(pipelineState->lastShadowParams.w, 0.85f);
|
||||
EXPECT_TRUE(pipelineState->lastHasMainDirectionalShadowKeyword);
|
||||
}
|
||||
|
||||
EXPECT_EQ(allocationState->shutdownDepthViewCalls, 1);
|
||||
|
||||
@@ -1269,7 +1269,7 @@ TEST(ShaderLoader, LoadBuiltinForwardLitShaderBuildsBackendVariants) {
|
||||
const ShaderPass* pass = shader->FindPass("ForwardLit");
|
||||
ASSERT_NE(pass, nullptr);
|
||||
ASSERT_EQ(shader->GetProperties().Size(), 2u);
|
||||
ASSERT_EQ(pass->variants.Size(), 6u);
|
||||
ASSERT_EQ(pass->variants.Size(), 12u);
|
||||
ASSERT_EQ(pass->tags.Size(), 1u);
|
||||
ASSERT_EQ(pass->resources.Size(), 8u);
|
||||
EXPECT_EQ(pass->tags[0].name, "LightMode");
|
||||
@@ -1324,6 +1324,13 @@ TEST(ShaderLoader, LoadBuiltinForwardLitShaderBuildsBackendVariants) {
|
||||
EXPECT_EQ(shadowTextureBinding->set, 6u);
|
||||
EXPECT_EQ(shadowTextureBinding->binding, 0u);
|
||||
EXPECT_EQ(shadowTextureBinding->semantic, "ShadowMapTexture");
|
||||
ASSERT_EQ(pass->keywordDeclarations.Size(), 1u);
|
||||
EXPECT_EQ(pass->keywordDeclarations[0].type, ShaderKeywordDeclarationType::MultiCompile);
|
||||
ASSERT_EQ(pass->keywordDeclarations[0].options.Size(), 2u);
|
||||
EXPECT_EQ(pass->keywordDeclarations[0].options[0], "_");
|
||||
EXPECT_EQ(pass->keywordDeclarations[0].options[1], "XC_MAIN_LIGHT_SHADOWS");
|
||||
EXPECT_TRUE(shader->PassDeclaresKeyword("ForwardLit", "XC_MAIN_LIGHT_SHADOWS"));
|
||||
ASSERT_EQ(pass->variants.Size(), 12u);
|
||||
|
||||
EXPECT_NE(shader->FindVariant("ForwardLit", ShaderType::Vertex, ShaderBackend::D3D12), nullptr);
|
||||
EXPECT_NE(shader->FindVariant("ForwardLit", ShaderType::Fragment, ShaderBackend::D3D12), nullptr);
|
||||
@@ -1346,6 +1353,23 @@ TEST(ShaderLoader, LoadBuiltinForwardLitShaderBuildsBackendVariants) {
|
||||
ASSERT_NE(d3d12Fragment, nullptr);
|
||||
EXPECT_NE(std::string(d3d12Fragment->sourceCode.CStr()).find("gAdditionalLights"), std::string::npos);
|
||||
EXPECT_NE(std::string(d3d12Fragment->sourceCode.CStr()).find("gLightingParams"), std::string::npos);
|
||||
EXPECT_EQ(std::string(d3d12Fragment->sourceCode.CStr()).find("#define XC_MAIN_LIGHT_SHADOWS 1"), std::string::npos);
|
||||
|
||||
ShaderKeywordSet shadowKeywords = {};
|
||||
shadowKeywords.enabledKeywords.PushBack("XC_MAIN_LIGHT_SHADOWS");
|
||||
|
||||
const ShaderStageVariant* shadowD3D12Fragment = shader->FindVariant(
|
||||
"ForwardLit",
|
||||
ShaderType::Fragment,
|
||||
ShaderBackend::D3D12,
|
||||
shadowKeywords);
|
||||
ASSERT_NE(shadowD3D12Fragment, nullptr);
|
||||
EXPECT_NE(
|
||||
std::string(shadowD3D12Fragment->sourceCode.CStr()).find("#define XC_MAIN_LIGHT_SHADOWS 1"),
|
||||
std::string::npos);
|
||||
EXPECT_NE(
|
||||
std::string(shadowD3D12Fragment->sourceCode.CStr()).find("gShadowMapTexture.Sample"),
|
||||
std::string::npos);
|
||||
|
||||
const ShaderStageVariant* openglFragment = shader->FindVariant(
|
||||
"ForwardLit",
|
||||
|
||||
Reference in New Issue
Block a user