795 lines
38 KiB
C++
795 lines
38 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "LumenSceneLighting.h"
|
|
#include "RendererPrivate.h"
|
|
#include "ScenePrivate.h"
|
|
#include "PipelineStateCache.h"
|
|
#include "ShaderParameterStruct.h"
|
|
#include "SceneTextureParameters.h"
|
|
#include "LumenMeshCards.h"
|
|
#include "LumenRadianceCache.h"
|
|
#include "ProfilingDebugging/CpuProfilerTrace.h"
|
|
#include "LumenTracingUtils.h"
|
|
#include "ShaderPrintParameters.h"
|
|
#include "LumenRadiosity.h"
|
|
|
|
static TAutoConsoleVariable<int32> CVarLumenSceneLightingForceFullUpdate(
|
|
TEXT("r.LumenScene.Lighting.ForceLightingUpdate"),
|
|
0,
|
|
TEXT("Force full Lumen Scene Lighting update every frame. Useful for debugging"),
|
|
ECVF_RenderThreadSafe
|
|
);
|
|
|
|
int32 GLumenSceneLightingFeedback = 1;
|
|
FAutoConsoleVariableRef CVarLumenSceneLightingFeedback(
|
|
TEXT("r.LumenScene.Lighting.Feedback"),
|
|
GLumenSceneLightingFeedback,
|
|
TEXT("Whether to prioritize surface cache lighting updates based on the feedback."),
|
|
ECVF_Scalability | ECVF_RenderThreadSafe
|
|
);
|
|
|
|
static TAutoConsoleVariable<float> CVarLumenSceneLightingMaxDistanceFromFrustumToPrioritize(
|
|
TEXT("r.LumenScene.Lighting.MaxDistanceFromFrustumToPrioritize"),
|
|
500.0f,
|
|
TEXT("Max distance from view frustum to card page extents to prioritize this card updates.\n")
|
|
TEXT("-1 to disable this feature."),
|
|
ECVF_Scalability | ECVF_RenderThreadSafe
|
|
);
|
|
|
|
int32 GLumenDirectLightingUpdateFactor = 32;
|
|
FAutoConsoleVariableRef CVarLumenSceneDirectLightingUpdateFactor(
|
|
TEXT("r.LumenScene.DirectLighting.UpdateFactor"),
|
|
GLumenDirectLightingUpdateFactor,
|
|
TEXT("Controls for how many texels direct lighting will be updated every frame. Texels = SurfaceCacheTexels / Factor."),
|
|
ECVF_Scalability | ECVF_RenderThreadSafe
|
|
);
|
|
|
|
int32 GLumenRadiosityUpdateFactor = 64;
|
|
FAutoConsoleVariableRef CVarLumenSceneRadiosityUpdateFactor(
|
|
TEXT("r.LumenScene.Radiosity.UpdateFactor"),
|
|
GLumenRadiosityUpdateFactor,
|
|
TEXT("Controls for how many texels radiosity will be updated every frame. Texels = SurfaceCacheTexels / Factor."),
|
|
ECVF_Scalability | ECVF_RenderThreadSafe
|
|
);
|
|
|
|
int32 GLumenLightingStats = 0;
|
|
FAutoConsoleVariableRef CVarLumenSceneLightingStats(
|
|
TEXT("r.LumenScene.Lighting.Stats"),
|
|
GLumenLightingStats,
|
|
TEXT("GPU print out Lumen lighting update stats."),
|
|
ECVF_Scalability | ECVF_RenderThreadSafe
|
|
);
|
|
|
|
static TAutoConsoleVariable<int32> CVarLumenSceneLightingAsyncCompute(
|
|
TEXT("r.LumenScene.Lighting.AsyncCompute"),
|
|
1,
|
|
TEXT("Whether to run LumenSceneLighting on the compute pipe if possible."),
|
|
ECVF_Scalability | ECVF_RenderThreadSafe
|
|
);
|
|
|
|
uint32 GetLumenLightingStatMode()
|
|
{
|
|
return FMath::Clamp(GLumenLightingStats, 0, 3);
|
|
}
|
|
|
|
namespace LumenSceneLighting
|
|
{
|
|
bool UseFeedback(const FSceneViewFamily& ViewFamily)
|
|
{
|
|
return Lumen::UseHardwareRayTracing(ViewFamily) && GLumenSceneLightingFeedback != 0;
|
|
}
|
|
}
|
|
|
|
bool Lumen::UseHardwareRayTracedSceneLighting(const FSceneViewFamily& ViewFamily)
|
|
{
|
|
return Lumen::UseHardwareRayTracedDirectLighting(ViewFamily) || Lumen::UseHardwareRayTracedRadiosity(ViewFamily);
|
|
}
|
|
|
|
namespace LumenCardUpdateContext
|
|
{
|
|
// Must match LumenSceneLighting.usf
|
|
constexpr uint32 CARD_UPDATE_CONTEXT_MAX = 2;
|
|
constexpr uint32 PRIORITY_HISTOGRAM_SIZE = 16;
|
|
constexpr uint32 MAX_UPDATE_BUCKET_STRIDE = 2;
|
|
constexpr uint32 CARD_PAGE_TILE_ALLOCATOR_STRIDE = 2;
|
|
};
|
|
|
|
void SetLightingUpdateAtlasSize(FIntPoint PhysicalAtlasSize, int32 UpdateFactor, FLumenCardUpdateContext& Context)
|
|
{
|
|
Context.UpdateAtlasSize = FIntPoint(0, 0);
|
|
Context.MaxUpdateTiles = 0;
|
|
Context.UpdateFactor = FMath::Clamp(UpdateFactor, 1, 1024);
|
|
|
|
if (!Lumen::IsSurfaceCacheFrozen())
|
|
{
|
|
if (CVarLumenSceneLightingForceFullUpdate.GetValueOnRenderThread() != 0)
|
|
{
|
|
Context.UpdateFactor = 1;
|
|
}
|
|
|
|
const float MultPerComponent = 1.0f / FMath::Sqrt((float)Context.UpdateFactor);
|
|
|
|
FIntPoint UpdateAtlasSize;
|
|
UpdateAtlasSize.X = FMath::DivideAndRoundUp<uint32>(PhysicalAtlasSize.X * MultPerComponent + 0.5f, Lumen::CardTileSize) * Lumen::CardTileSize;
|
|
UpdateAtlasSize.Y = FMath::DivideAndRoundUp<uint32>(PhysicalAtlasSize.Y * MultPerComponent + 0.5f, Lumen::CardTileSize) * Lumen::CardTileSize;
|
|
|
|
// Update at least one full res card page so that we don't get stuck
|
|
UpdateAtlasSize.X = FMath::Max<int32>(UpdateAtlasSize.X, Lumen::PhysicalPageSize);
|
|
UpdateAtlasSize.Y = FMath::Max<int32>(UpdateAtlasSize.Y, Lumen::PhysicalPageSize);
|
|
|
|
const FIntPoint UpdateAtlasSizeInTiles = UpdateAtlasSize / Lumen::CardTileSize;
|
|
|
|
Context.UpdateAtlasSize = UpdateAtlasSize;
|
|
Context.MaxUpdateTiles = UpdateAtlasSizeInTiles.X * UpdateAtlasSizeInTiles.Y;
|
|
}
|
|
}
|
|
|
|
IMPLEMENT_GLOBAL_SHADER(FClearLumenCardsPS, "/Engine/Private/Lumen/LumenSceneLighting.usf", "ClearLumenCardsPS", SF_Pixel);
|
|
IMPLEMENT_GLOBAL_SHADER(FCopyCardCaptureLightingToAtlasPS, "/Engine/Private/Lumen/LumenSceneLighting.usf", "CopyCardCaptureLightingToAtlasPS", SF_Pixel);
|
|
|
|
bool FRasterizeToCardsVS::ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
|
|
{
|
|
return DoesPlatformSupportLumenGI(Parameters.Platform);
|
|
}
|
|
|
|
IMPLEMENT_GLOBAL_SHADER(FRasterizeToCardsVS,"/Engine/Private/Lumen/LumenSceneLighting.usf","RasterizeToCardsVS",SF_Vertex);
|
|
|
|
class FLumenCardCombineLightingCS : public FGlobalShader
|
|
{
|
|
DECLARE_GLOBAL_SHADER(FLumenCardCombineLightingCS);
|
|
SHADER_USE_PARAMETER_STRUCT(FLumenCardCombineLightingCS, FGlobalShader);
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
|
|
RDG_BUFFER_ACCESS(IndirectArgsBuffer, ERHIAccess::IndirectArgs)
|
|
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, View)
|
|
SHADER_PARAMETER_RDG_UNIFORM_BUFFER(FLumenCardScene, LumenCardScene)
|
|
SHADER_PARAMETER(float, DiffuseColorBoost)
|
|
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, AlbedoAtlas)
|
|
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, OpacityAtlas)
|
|
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, EmissiveAtlas)
|
|
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, DirectLightingAtlas)
|
|
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, IndirectLightingAtlas)
|
|
SHADER_PARAMETER_SAMPLER(SamplerState, BilinearClampedSampler)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<uint>, CardTiles)
|
|
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<float3>, RWFinalLightingAtlas)
|
|
SHADER_PARAMETER(FVector2f, IndirectLightingAtlasHalfTexelSize)
|
|
SHADER_PARAMETER(FVector3f, TargetFormatQuantizationError)
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
|
|
using FPermutationDomain = TShaderPermutationDomain<>;
|
|
|
|
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
|
|
{
|
|
return DoesPlatformSupportLumenGI(Parameters.Platform);
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_GLOBAL_SHADER(FLumenCardCombineLightingCS, "/Engine/Private/Lumen/LumenSceneLighting.usf", "CombineLumenSceneLightingCS", SF_Compute);
|
|
|
|
void Lumen::CombineLumenSceneLighting(
|
|
FScene* Scene,
|
|
const FViewInfo& View,
|
|
FRDGBuilder& GraphBuilder,
|
|
const FLumenSceneFrameTemporaries& FrameTemporaries,
|
|
const FLumenCardUpdateContext& CardUpdateContext,
|
|
const FLumenCardTileUpdateContext& CardTileUpdateContext,
|
|
ERDGPassFlags ComputePassFlags)
|
|
{
|
|
LLM_SCOPE_BYTAG(Lumen);
|
|
FLumenSceneData& LumenSceneData = *Scene->GetLumenSceneData(View);
|
|
|
|
FLumenCardCombineLightingCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FLumenCardCombineLightingCS::FParameters>();
|
|
PassParameters->IndirectArgsBuffer = CardTileUpdateContext.DispatchCardTilesIndirectArgs;
|
|
PassParameters->View = View.ViewUniformBuffer;
|
|
PassParameters->LumenCardScene = FrameTemporaries.LumenCardSceneUniformBuffer;
|
|
PassParameters->DiffuseColorBoost = 1.0f / FMath::Max(View.FinalPostProcessSettings.LumenDiffuseColorBoost, 1.0f);
|
|
PassParameters->AlbedoAtlas = FrameTemporaries.AlbedoAtlas;
|
|
PassParameters->OpacityAtlas = FrameTemporaries.OpacityAtlas;
|
|
PassParameters->EmissiveAtlas = FrameTemporaries.EmissiveAtlas;
|
|
PassParameters->DirectLightingAtlas = FrameTemporaries.DirectLightingAtlas;
|
|
PassParameters->IndirectLightingAtlas = FrameTemporaries.IndirectLightingAtlas;
|
|
PassParameters->BilinearClampedSampler = TStaticSamplerState<SF_Bilinear, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI();
|
|
PassParameters->CardTiles = GraphBuilder.CreateSRV(CardTileUpdateContext.CardTiles);
|
|
PassParameters->RWFinalLightingAtlas = GraphBuilder.CreateUAV(FrameTemporaries.FinalLightingAtlas);
|
|
const FIntPoint IndirectLightingAtlasSize = LumenSceneData.GetRadiosityAtlasSize();
|
|
PassParameters->IndirectLightingAtlasHalfTexelSize = FVector2f(0.5f / IndirectLightingAtlasSize.X, 0.5f / IndirectLightingAtlasSize.Y);
|
|
PassParameters->TargetFormatQuantizationError = Lumen::GetLightingQuantizationError();
|
|
|
|
auto ComputeShader = View.ShaderMap->GetShader<FLumenCardCombineLightingCS>();
|
|
|
|
FComputeShaderUtils::AddPass(
|
|
GraphBuilder,
|
|
RDG_EVENT_NAME("CombineLighting CS"),
|
|
ComputePassFlags,
|
|
ComputeShader,
|
|
PassParameters,
|
|
CardTileUpdateContext.DispatchCardTilesIndirectArgs,
|
|
(uint32)ELumenDispatchCardTilesIndirectArgsOffset::OneGroupPerCardTile);
|
|
}
|
|
|
|
bool LumenSceneLighting::UseAsyncCompute(const FViewFamilyInfo& ViewFamily)
|
|
{
|
|
return Lumen::UseAsyncCompute(ViewFamily) && CVarLumenSceneLightingAsyncCompute.GetValueOnRenderThread() != 0;
|
|
}
|
|
|
|
DECLARE_GPU_STAT(LumenSceneLighting);
|
|
|
|
void FDeferredShadingSceneRenderer::RenderLumenSceneLighting(
|
|
FRDGBuilder& GraphBuilder,
|
|
const FLumenSceneFrameTemporaries& FrameTemporaries,
|
|
const FLumenDirectLightingTaskData* DirectLightingTaskData)
|
|
{
|
|
LLM_SCOPE_BYTAG(Lumen);
|
|
TRACE_CPUPROFILER_EVENT_SCOPE(FDeferredShadingSceneRenderer::RenderLumenSceneLighting);
|
|
|
|
FLumenSceneData& LumenSceneData = *Scene->GetLumenSceneData(Views[0]);
|
|
|
|
bool bAnyLumenActive = false;
|
|
|
|
for (const FViewInfo& View : Views)
|
|
{
|
|
const FPerViewPipelineState& ViewPipelineState = GetViewPipelineState(View);
|
|
bAnyLumenActive = bAnyLumenActive || ViewPipelineState.DiffuseIndirectMethod == EDiffuseIndirectMethod::Lumen;
|
|
}
|
|
|
|
if (bAnyLumenActive)
|
|
{
|
|
TRACE_CPUPROFILER_EVENT_SCOPE(RenderLumenSceneLighting);
|
|
QUICK_SCOPE_CYCLE_COUNTER(RenderLumenSceneLighting);
|
|
RDG_EVENT_SCOPE_STAT(GraphBuilder, LumenSceneLighting, "LumenSceneLighting%s", LumenCardRenderer.bPropagateGlobalLightingChange ? TEXT(" PROPAGATE GLOBAL CHANGE!") : TEXT(""));
|
|
RDG_GPU_STAT_SCOPE(GraphBuilder, LumenSceneLighting);
|
|
|
|
const ERDGPassFlags ComputePassFlags = LumenSceneLighting::UseAsyncCompute(ViewFamily) ? ERDGPassFlags::AsyncCompute : ERDGPassFlags::Compute;
|
|
|
|
LumenSceneData.IncrementSurfaceCacheUpdateFrameIndex();
|
|
|
|
if (LumenSceneData.bDebugClearAllCachedState)
|
|
{
|
|
AddClearRenderTargetPass(GraphBuilder, FrameTemporaries.DirectLightingAtlas);
|
|
AddClearRenderTargetPass(GraphBuilder, FrameTemporaries.IndirectLightingAtlas);
|
|
AddClearRenderTargetPass(GraphBuilder, FrameTemporaries.RadiosityNumFramesAccumulatedAtlas);
|
|
AddClearRenderTargetPass(GraphBuilder, FrameTemporaries.FinalLightingAtlas);
|
|
if (FrameTemporaries.DiffuseLightingAndSecondMomentHistoryAtlas)
|
|
{
|
|
AddClearRenderTargetPass(GraphBuilder, FrameTemporaries.DiffuseLightingAndSecondMomentHistoryAtlas);
|
|
}
|
|
if (FrameTemporaries.NumFramesAccumulatedHistoryAtlas)
|
|
{
|
|
AddClearRenderTargetPass(GraphBuilder, FrameTemporaries.NumFramesAccumulatedHistoryAtlas);
|
|
}
|
|
}
|
|
|
|
LumenRadiosity::FFrameTemporaries RadiosityFrameTemporaries;
|
|
LumenRadiosity::InitFrameTemporaries(GraphBuilder, LumenSceneData, ViewFamily, Views, RadiosityFrameTemporaries);
|
|
|
|
FLumenCardUpdateContext DirectLightingCardUpdateContext;
|
|
FLumenCardUpdateContext IndirectLightingCardUpdateContext;
|
|
Lumen::BuildCardUpdateContext(
|
|
GraphBuilder,
|
|
LumenSceneData,
|
|
Views,
|
|
FrameTemporaries,
|
|
RadiosityFrameTemporaries.bIndirectLightingHistoryValid,
|
|
DirectLightingCardUpdateContext,
|
|
IndirectLightingCardUpdateContext,
|
|
ComputePassFlags);
|
|
|
|
// Pointing cards debug data
|
|
if (GetLumenLightingStatMode() > 2)
|
|
{
|
|
FLumenSceneFrameTemporaries* NonCstFrameTemporaries = const_cast<FLumenSceneFrameTemporaries*>(&FrameTemporaries);
|
|
NonCstFrameTemporaries->DebugData = TraceLumenHardwareRayTracedDebug(GraphBuilder, Scene, Views[0], 0 /*ViewIndex*/, FrameTemporaries, ComputePassFlags);
|
|
}
|
|
|
|
RenderDirectLightingForLumenScene(
|
|
GraphBuilder,
|
|
FrameTemporaries,
|
|
DirectLightingTaskData,
|
|
DirectLightingCardUpdateContext,
|
|
ComputePassFlags);
|
|
|
|
RenderRadiosityForLumenScene(
|
|
GraphBuilder,
|
|
FrameTemporaries,
|
|
RadiosityFrameTemporaries,
|
|
IndirectLightingCardUpdateContext,
|
|
ComputePassFlags);
|
|
|
|
LumenSceneData.bFinalLightingAtlasContentsValid = true;
|
|
|
|
GraphBuilder.FlushSetupQueue();
|
|
}
|
|
}
|
|
|
|
class FClearCardUpdateContextCS : public FGlobalShader
|
|
{
|
|
DECLARE_GLOBAL_SHADER(FClearCardUpdateContextCS);
|
|
SHADER_USE_PARAMETER_STRUCT(FClearCardUpdateContextCS, FGlobalShader);
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
|
|
SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer<uint>, RWDirectLightingCardPageIndexAllocator)
|
|
SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer<uint>, RWIndirectLightingCardPageIndexAllocator)
|
|
SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer<uint>, RWMaxUpdateBucket)
|
|
SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer<uint>, RWCardPageTileAllocator)
|
|
SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer<uint>, RWPriorityHistogram)
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
|
|
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
|
|
{
|
|
return DoesPlatformSupportLumenGI(Parameters.Platform);
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
|
|
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE"), GetGroupSize());
|
|
}
|
|
|
|
static int32 GetGroupSize()
|
|
{
|
|
return 64;
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_GLOBAL_SHADER(FClearCardUpdateContextCS, "/Engine/Private/Lumen/LumenSceneLighting.usf", "ClearCardUpdateContextCS", SF_Compute);
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FLumenSurfaceCacheUpdateParameters, )
|
|
SHADER_PARAMETER(float, MaxDistanceFromFrustumToPrioritize)
|
|
SHADER_PARAMETER(uint32, NumCameraOrigins)
|
|
SHADER_PARAMETER_ARRAY(FVector4f, WorldCameraOrigins, [LUMEN_MAX_VIEWS])
|
|
SHADER_PARAMETER_ARRAY(FVector4f, CameraFrustumPlanes, [LUMEN_MAX_VIEWS * LUMEN_MAX_CAMERA_PLANES])
|
|
SHADER_PARAMETER_ARRAY(FVector4f, PreViewTranslationHigh, [LUMEN_MAX_VIEWS])
|
|
SHADER_PARAMETER_ARRAY(FVector4f, PreViewTranslationLow, [LUMEN_MAX_VIEWS])
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
|
|
class FBuildPageUpdatePriorityHistogramCS : public FGlobalShader
|
|
{
|
|
DECLARE_GLOBAL_SHADER(FBuildPageUpdatePriorityHistogramCS);
|
|
SHADER_USE_PARAMETER_STRUCT(FBuildPageUpdatePriorityHistogramCS, FGlobalShader);
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
|
|
SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer<uint>, RWPriorityHistogram)
|
|
SHADER_PARAMETER_RDG_UNIFORM_BUFFER(FLumenCardScene, LumenCardScene)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<uint>, CardPageLastUsedBuffer)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<uint>, CardPageHighResLastUsedBuffer)
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(FLumenSurfaceCacheUpdateParameters, SurfaceCacheUpdateParameters)
|
|
SHADER_PARAMETER(uint32, SurfaceCacheUpdateFrameIndex)
|
|
SHADER_PARAMETER(uint32, FreezeUpdateFrame)
|
|
SHADER_PARAMETER(uint32, CardPageNum)
|
|
SHADER_PARAMETER(float, FirstClipmapWorldExtentRcp)
|
|
SHADER_PARAMETER(float, DirectLightingUpdateFactor)
|
|
SHADER_PARAMETER(float, IndirectLightingUpdateFactor)
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
|
|
class FSurfaceCacheFeedback : SHADER_PERMUTATION_BOOL("SURFACE_CACHE_FEEDBACK");
|
|
using FPermutationDomain = TShaderPermutationDomain<FSurfaceCacheFeedback>;
|
|
|
|
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
|
|
{
|
|
return DoesPlatformSupportLumenGI(Parameters.Platform);
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
|
|
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE"), GetGroupSize());
|
|
}
|
|
|
|
static int32 GetGroupSize()
|
|
{
|
|
return 64;
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_GLOBAL_SHADER(FBuildPageUpdatePriorityHistogramCS, "/Engine/Private/Lumen/LumenSceneLighting.usf", "BuildPageUpdatePriorityHistogramCS", SF_Compute);
|
|
|
|
class FSelectMaxUpdateBucketCS : public FGlobalShader
|
|
{
|
|
DECLARE_GLOBAL_SHADER(FSelectMaxUpdateBucketCS);
|
|
SHADER_USE_PARAMETER_STRUCT(FSelectMaxUpdateBucketCS, FGlobalShader);
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
|
|
SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer<uint>, RWMaxUpdateBucket)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<uint>, PriorityHistogram)
|
|
SHADER_PARAMETER(uint32, MaxDirectLightingTilesToUpdate)
|
|
SHADER_PARAMETER(uint32, MaxIndirectLightingTilesToUpdate)
|
|
SHADER_PARAMETER(uint32, SurfaceCacheUpdateFrameIndex)
|
|
SHADER_PARAMETER(uint32, FreezeUpdateFrame)
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
|
|
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
|
|
{
|
|
return DoesPlatformSupportLumenGI(Parameters.Platform);
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
|
|
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE"), GetGroupSize());
|
|
}
|
|
|
|
static int32 GetGroupSize()
|
|
{
|
|
return 64;
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_GLOBAL_SHADER(FSelectMaxUpdateBucketCS, "/Engine/Private/Lumen/LumenSceneLighting.usf", "SelectMaxUpdateBucketCS", SF_Compute);
|
|
|
|
class FBuildCardsUpdateListCS : public FGlobalShader
|
|
{
|
|
DECLARE_GLOBAL_SHADER(FBuildCardsUpdateListCS);
|
|
SHADER_USE_PARAMETER_STRUCT(FBuildCardsUpdateListCS, FGlobalShader);
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
|
|
SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer<uint>, RWDirectLightingCardPageIndexAllocator)
|
|
SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer<uint>, RWDirectLightingCardPageIndexData)
|
|
SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer<uint>, RWIndirectLightingCardPageIndexAllocator)
|
|
SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer<uint>, RWIndirectLightingCardPageIndexData)
|
|
SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer<uint>, RWCardPageTileAllocator)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<uint>, MaxUpdateBucket)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<float4>, LumenCardDataBuffer)
|
|
SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer<float4>, RWLumenCardPageDataBuffer)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<uint>, CardPageLastUsedBuffer)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<uint>, CardPageHighResLastUsedBuffer)
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(FLumenSurfaceCacheUpdateParameters, SurfaceCacheUpdateParameters)
|
|
SHADER_PARAMETER(uint32, SurfaceCacheUpdateFrameIndex)
|
|
SHADER_PARAMETER(uint32, FreezeUpdateFrame)
|
|
SHADER_PARAMETER(uint32, CardPageNum)
|
|
SHADER_PARAMETER(float, FirstClipmapWorldExtentRcp)
|
|
SHADER_PARAMETER(uint32, MaxDirectLightingTilesToUpdate)
|
|
SHADER_PARAMETER(uint32, MaxIndirectLightingTilesToUpdate)
|
|
SHADER_PARAMETER(float, DirectLightingUpdateFactor)
|
|
SHADER_PARAMETER(float, IndirectLightingUpdateFactor)
|
|
SHADER_PARAMETER(int32, IndirectLightingHistoryValid)
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
|
|
class FSurfaceCacheFeedback : SHADER_PERMUTATION_BOOL("SURFACE_CACHE_FEEDBACK");
|
|
using FPermutationDomain = TShaderPermutationDomain<FSurfaceCacheFeedback>;
|
|
|
|
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
|
|
{
|
|
return DoesPlatformSupportLumenGI(Parameters.Platform);
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
|
|
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE"), GetGroupSize());
|
|
OutEnvironment.SetDefine(TEXT("USE_LUMEN_CARD_DATA_BUFFER"), 1);
|
|
OutEnvironment.SetDefine(TEXT("USE_RW_LUMEN_CARD_PAGE_DATA_BUFFER"), 1);
|
|
}
|
|
|
|
static int32 GetGroupSize()
|
|
{
|
|
return 64;
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_GLOBAL_SHADER(FBuildCardsUpdateListCS, "/Engine/Private/Lumen/LumenSceneLighting.usf", "BuildCardsUpdateListCS", SF_Compute);
|
|
|
|
class FSetCardPageIndexIndirectArgsCS : public FGlobalShader
|
|
{
|
|
DECLARE_GLOBAL_SHADER(FSetCardPageIndexIndirectArgsCS);
|
|
SHADER_USE_PARAMETER_STRUCT(FSetCardPageIndexIndirectArgsCS, FGlobalShader);
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
|
|
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<uint>, RWDirectLightingDrawCardPageIndicesIndirectArgs)
|
|
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<uint>, RWDirectLightingDispatchCardPageIndicesIndirectArgs)
|
|
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<uint>, RWIndirectLightingDrawCardPageIndicesIndirectArgs)
|
|
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<uint>, RWIndirectLightingDispatchCardPageIndicesIndirectArgs)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<uint>, DirectLightingCardPageIndexAllocator)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<uint>, IndirectLightingCardPageIndexAllocator)
|
|
SHADER_PARAMETER(uint32, VertexCountPerInstanceIndirect)
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
|
|
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
|
|
{
|
|
return DoesPlatformSupportLumenGI(Parameters.Platform);
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
|
|
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE"), GetGroupSize());
|
|
}
|
|
|
|
static int32 GetGroupSize()
|
|
{
|
|
return 64;
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_GLOBAL_SHADER(FSetCardPageIndexIndirectArgsCS, "/Engine/Private/Lumen/LumenSceneLighting.usf", "SetCardPageIndexIndirectArgsCS", SF_Compute);
|
|
|
|
class FLumenSceneLightingStatsCS : public FGlobalShader
|
|
{
|
|
DECLARE_GLOBAL_SHADER(FLumenSceneLightingStatsCS)
|
|
SHADER_USE_PARAMETER_STRUCT(FLumenSceneLightingStatsCS, FGlobalShader)
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(ShaderPrint::FShaderParameters, ShaderPrintUniformBuffer)
|
|
SHADER_PARAMETER_RDG_UNIFORM_BUFFER(FLumenCardScene, LumenCardScene)
|
|
SHADER_PARAMETER(uint32, CardPageNum)
|
|
SHADER_PARAMETER(uint32, LightingStatMode)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<uint>, DirectLightingCardPageIndexAllocator)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<uint>, IndirectLightingCardPageIndexAllocator)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<uint>, PriorityHistogram)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<uint>, MaxUpdateBucket)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<uint>, CardPageTileAllocator)
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
|
|
public:
|
|
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
|
|
{
|
|
return DoesPlatformSupportLumenGI(Parameters.Platform);
|
|
}
|
|
|
|
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
|
|
{
|
|
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
|
|
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE"), 1);
|
|
OutEnvironment.SetDefine(TEXT("SHADER_STATS"), 1);
|
|
}
|
|
};
|
|
|
|
IMPLEMENT_GLOBAL_SHADER(FLumenSceneLightingStatsCS, "/Engine/Private/Lumen/LumenSceneLightingDebug.usf", "LumenSceneLightingStatsCS", SF_Compute);
|
|
|
|
void Lumen::BuildCardUpdateContext(
|
|
FRDGBuilder& GraphBuilder,
|
|
const FLumenSceneData& LumenSceneData,
|
|
const TArray<FViewInfo>& Views,
|
|
const FLumenSceneFrameTemporaries& FrameTemporaries,
|
|
bool bIndirectLightingHistoryValid,
|
|
FLumenCardUpdateContext& DirectLightingCardUpdateContext,
|
|
FLumenCardUpdateContext& IndirectLightingCardUpdateContext,
|
|
ERDGPassFlags ComputePassFlags)
|
|
{
|
|
RDG_EVENT_SCOPE(GraphBuilder, "BuildCardUpdateContext");
|
|
|
|
float LumenSceneLightingUpdateSpeed = 0.0f;
|
|
|
|
for (const FViewInfo& View : Views)
|
|
{
|
|
LumenSceneLightingUpdateSpeed = FMath::Max(LumenSceneLightingUpdateSpeed, FMath::Clamp<float>(View.FinalPostProcessSettings.LumenSceneLightingUpdateSpeed, .5f, 16.0f));
|
|
}
|
|
|
|
FRDGBufferSRV* CardPageLastUsedBufferSRV = nullptr;
|
|
FRDGBufferSRV* CardPageHighResLastUsedBufferSRV = nullptr;
|
|
|
|
const bool bUseFeedback = FrameTemporaries.CardPageLastUsedBufferSRV && FrameTemporaries.CardPageHighResLastUsedBufferSRV && LumenSceneLighting::UseFeedback(*Views[0].Family);
|
|
if (bUseFeedback)
|
|
{
|
|
CardPageLastUsedBufferSRV = FrameTemporaries.CardPageLastUsedBufferSRV;
|
|
CardPageHighResLastUsedBufferSRV = FrameTemporaries.CardPageHighResLastUsedBufferSRV;
|
|
}
|
|
|
|
const int32 NumCardPages = LumenSceneData.GetNumCardPages();
|
|
const uint32 UpdateFrameIndex = LumenSceneData.GetSurfaceCacheUpdateFrameIndex();
|
|
const uint32 FreezeUpdateFrame = Lumen::IsSurfaceCacheUpdateFrameFrozen() ? 1 : 0;
|
|
const float FirstClipmapWorldExtentRcp = 1.0f / Lumen::GetGlobalDFClipmapExtent(0);
|
|
|
|
SetLightingUpdateAtlasSize(LumenSceneData.GetPhysicalAtlasSize(), FMath::RoundToInt(GLumenDirectLightingUpdateFactor / LumenSceneLightingUpdateSpeed), DirectLightingCardUpdateContext);
|
|
SetLightingUpdateAtlasSize(LumenSceneData.GetPhysicalAtlasSize(), FMath::RoundToInt(GLumenRadiosityUpdateFactor / LumenSceneLightingUpdateSpeed), IndirectLightingCardUpdateContext);
|
|
|
|
DirectLightingCardUpdateContext.CardPageIndexAllocator = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateStructuredDesc(sizeof(uint32), 1), TEXT("Lumen.DirectLightingCardPageIndexAllocator"));
|
|
DirectLightingCardUpdateContext.CardPageIndexData = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateStructuredDesc(sizeof(uint32), FMath::RoundUpToPowerOfTwo(NumCardPages)), TEXT("Lumen.DirectLightingCardPageIndexData"));
|
|
DirectLightingCardUpdateContext.DrawCardPageIndicesIndirectArgs = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateIndirectDesc<FRHIDrawIndirectParameters>(1), TEXT("Lumen.DirectLighting.DrawCardPageIndicesIndirectArgs"));
|
|
DirectLightingCardUpdateContext.DispatchCardPageIndicesIndirectArgs = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateIndirectDesc<FRHIDispatchIndirectParameters>(FLumenCardUpdateContext::MAX), TEXT("Lumen.DirectLighting.DispatchCardPageIndicesIndirectArgs"));
|
|
|
|
IndirectLightingCardUpdateContext.CardPageIndexAllocator = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateStructuredDesc(sizeof(uint32), 1), TEXT("Lumen.IndirectLightingCardPageIndexAllocator"));
|
|
IndirectLightingCardUpdateContext.CardPageIndexData = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateStructuredDesc(sizeof(uint32), FMath::RoundUpToPowerOfTwo(NumCardPages)), TEXT("Lumen.IndirectLightingCardPageIndexData"));
|
|
IndirectLightingCardUpdateContext.DrawCardPageIndicesIndirectArgs = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateIndirectDesc<FRHIDrawIndirectParameters>(1), TEXT("Lumen.IndirectLighting.DrawCardPageIndicesIndirectArgs"));
|
|
IndirectLightingCardUpdateContext.DispatchCardPageIndicesIndirectArgs = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateIndirectDesc<FRHIDispatchIndirectParameters>(FLumenCardUpdateContext::MAX), TEXT("Lumen.IndirectLighting.DispatchCardPageIndicesIndirectArgs"));
|
|
|
|
FRDGBufferRef PriorityHistogram = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateStructuredDesc(sizeof(uint32), LumenCardUpdateContext::CARD_UPDATE_CONTEXT_MAX * LumenCardUpdateContext::PRIORITY_HISTOGRAM_SIZE), TEXT("Lumen.PriorityHistogram"));
|
|
FRDGBufferRef MaxUpdateBucket = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateStructuredDesc(sizeof(uint32), LumenCardUpdateContext::CARD_UPDATE_CONTEXT_MAX * LumenCardUpdateContext::MAX_UPDATE_BUCKET_STRIDE), TEXT("Lumen.MaxUpdateBucket"));
|
|
FRDGBufferRef CardPageTileAllocator = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateStructuredDesc(sizeof(uint32), LumenCardUpdateContext::CARD_UPDATE_CONTEXT_MAX * LumenCardUpdateContext::CARD_PAGE_TILE_ALLOCATOR_STRIDE), TEXT("Lumen.CardPageTileAllocator"));
|
|
|
|
FRDGBufferUAV* MaxUpdateBucketUAV = GraphBuilder.CreateUAV(MaxUpdateBucket);
|
|
FRDGBufferSRV* MaxUpdateBucketSRV = GraphBuilder.CreateSRV(MaxUpdateBucket);
|
|
|
|
FRDGBufferUAV* DirectCardPageIndexAllocatorUAV = GraphBuilder.CreateUAV(DirectLightingCardUpdateContext.CardPageIndexAllocator);
|
|
FRDGBufferSRV* DirectCardPageIndexAllocatorSRV = GraphBuilder.CreateSRV(DirectLightingCardUpdateContext.CardPageIndexAllocator);
|
|
|
|
FRDGBufferUAV* CardPageTileAllocatorUAV = GraphBuilder.CreateUAV(CardPageTileAllocator);
|
|
FRDGBufferSRV* CardPageTileAllocatorSRV = GraphBuilder.CreateSRV(CardPageTileAllocator);
|
|
|
|
FRDGBufferUAV* IndirectCardPageIndexAllocatorUAV = GraphBuilder.CreateUAV(IndirectLightingCardUpdateContext.CardPageIndexAllocator);
|
|
FRDGBufferSRV* IndirectCardPageIndexAllocatorSRV = GraphBuilder.CreateSRV(IndirectLightingCardUpdateContext.CardPageIndexAllocator);
|
|
|
|
FRDGBufferUAV* PriorityHistogramUAV = GraphBuilder.CreateUAV(PriorityHistogram);
|
|
FRDGBufferSRV* PriorityHistogramSRV = GraphBuilder.CreateSRV(PriorityHistogram);
|
|
|
|
// Batch clear all resources required for the subsequent card context update pass
|
|
{
|
|
FClearCardUpdateContextCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FClearCardUpdateContextCS::FParameters>();
|
|
PassParameters->RWDirectLightingCardPageIndexAllocator = DirectCardPageIndexAllocatorUAV;
|
|
PassParameters->RWIndirectLightingCardPageIndexAllocator = IndirectCardPageIndexAllocatorUAV;
|
|
PassParameters->RWMaxUpdateBucket = MaxUpdateBucketUAV;
|
|
PassParameters->RWCardPageTileAllocator = CardPageTileAllocatorUAV;
|
|
PassParameters->RWPriorityHistogram = PriorityHistogramUAV;
|
|
|
|
auto ComputeShader = Views[0].ShaderMap->GetShader<FClearCardUpdateContextCS>();
|
|
|
|
const FIntVector GroupSize(FMath::DivideAndRoundUp<int32>(LumenCardUpdateContext::CARD_UPDATE_CONTEXT_MAX * LumenCardUpdateContext::PRIORITY_HISTOGRAM_SIZE, FClearCardUpdateContextCS::GetGroupSize()), 1, 1);
|
|
|
|
FComputeShaderUtils::AddPass(
|
|
GraphBuilder,
|
|
RDG_EVENT_NAME("ClearCardUpdateContext"),
|
|
ComputePassFlags,
|
|
ComputeShader,
|
|
PassParameters,
|
|
GroupSize);
|
|
}
|
|
|
|
FLumenSurfaceCacheUpdateParameters SurfaceCacheUpdateParameters;
|
|
{
|
|
const int32 NumViewOrigins = FrameTemporaries.ViewOrigins.Num();
|
|
check(NumViewOrigins <= SurfaceCacheUpdateParameters.WorldCameraOrigins.Num());
|
|
|
|
SurfaceCacheUpdateParameters.NumCameraOrigins = NumViewOrigins;
|
|
SurfaceCacheUpdateParameters.MaxDistanceFromFrustumToPrioritize = CVarLumenSceneLightingMaxDistanceFromFrustumToPrioritize.GetValueOnRenderThread();
|
|
|
|
for (int32 OriginIndex = 0; OriginIndex < NumViewOrigins; ++OriginIndex)
|
|
{
|
|
FLumenViewOrigin const& LumenViewOrigin = FrameTemporaries.ViewOrigins[OriginIndex];
|
|
|
|
SurfaceCacheUpdateParameters.WorldCameraOrigins[OriginIndex] = LumenViewOrigin.WorldCameraOrigin;
|
|
SurfaceCacheUpdateParameters.PreViewTranslationHigh[OriginIndex] = LumenViewOrigin.PreViewTranslationDF.High;
|
|
SurfaceCacheUpdateParameters.PreViewTranslationLow[OriginIndex] = LumenViewOrigin.PreViewTranslationDF.Low;
|
|
|
|
FPlane4f FrustumPlanes[LUMEN_MAX_CAMERA_PLANES];
|
|
LumenViewOrigin.ViewToClip.GetFrustumNearPlane(FrustumPlanes[0]);
|
|
LumenViewOrigin.ViewToClip.GetFrustumLeftPlane(FrustumPlanes[1]);
|
|
LumenViewOrigin.ViewToClip.GetFrustumRightPlane(FrustumPlanes[2]);
|
|
LumenViewOrigin.ViewToClip.GetFrustumTopPlane(FrustumPlanes[3]);
|
|
LumenViewOrigin.ViewToClip.GetFrustumBottomPlane(FrustumPlanes[4]);
|
|
static_assert(LUMEN_MAX_CAMERA_PLANES == 5, "Update code above for the new number of frustum planes");
|
|
|
|
for (uint32 PlaneIndex = 0; PlaneIndex < LUMEN_MAX_CAMERA_PLANES; ++PlaneIndex)
|
|
{
|
|
SurfaceCacheUpdateParameters.CameraFrustumPlanes[PlaneIndex] = FVector4f(FrustumPlanes[PlaneIndex]);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Prepare update priority histogram
|
|
{
|
|
FBuildPageUpdatePriorityHistogramCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FBuildPageUpdatePriorityHistogramCS::FParameters>();
|
|
PassParameters->RWPriorityHistogram = PriorityHistogramUAV;
|
|
PassParameters->LumenCardScene = FrameTemporaries.LumenCardSceneUniformBuffer;
|
|
PassParameters->CardPageLastUsedBuffer = CardPageLastUsedBufferSRV;
|
|
PassParameters->CardPageHighResLastUsedBuffer = CardPageHighResLastUsedBufferSRV;
|
|
PassParameters->CardPageNum = NumCardPages;
|
|
PassParameters->SurfaceCacheUpdateParameters = SurfaceCacheUpdateParameters;
|
|
PassParameters->SurfaceCacheUpdateFrameIndex = UpdateFrameIndex;
|
|
PassParameters->FreezeUpdateFrame = FreezeUpdateFrame;
|
|
PassParameters->FirstClipmapWorldExtentRcp = FirstClipmapWorldExtentRcp;
|
|
PassParameters->DirectLightingUpdateFactor = DirectLightingCardUpdateContext.UpdateFactor;
|
|
PassParameters->IndirectLightingUpdateFactor = IndirectLightingCardUpdateContext.UpdateFactor;
|
|
|
|
FBuildPageUpdatePriorityHistogramCS::FPermutationDomain PermutationVector;
|
|
PermutationVector.Set<FBuildPageUpdatePriorityHistogramCS::FSurfaceCacheFeedback>(bUseFeedback);
|
|
auto ComputeShader = Views[0].ShaderMap->GetShader<FBuildPageUpdatePriorityHistogramCS>(PermutationVector);
|
|
|
|
const FIntVector GroupSize(FMath::DivideAndRoundUp<int32>(LumenSceneData.GetNumCardPages(), FBuildPageUpdatePriorityHistogramCS::GetGroupSize()), 1, 1);
|
|
|
|
FComputeShaderUtils::AddPass(
|
|
GraphBuilder,
|
|
RDG_EVENT_NAME("BuildPageUpdatePriorityHistogram"),
|
|
ComputePassFlags,
|
|
ComputeShader,
|
|
PassParameters,
|
|
GroupSize);
|
|
}
|
|
|
|
// Compute prefix sum and pick max bucket
|
|
{
|
|
FSelectMaxUpdateBucketCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FSelectMaxUpdateBucketCS::FParameters>();
|
|
PassParameters->RWMaxUpdateBucket = MaxUpdateBucketUAV;
|
|
PassParameters->PriorityHistogram = PriorityHistogramSRV;
|
|
PassParameters->MaxDirectLightingTilesToUpdate = DirectLightingCardUpdateContext.MaxUpdateTiles;
|
|
PassParameters->MaxIndirectLightingTilesToUpdate = IndirectLightingCardUpdateContext.MaxUpdateTiles;
|
|
PassParameters->SurfaceCacheUpdateFrameIndex = UpdateFrameIndex;
|
|
PassParameters->FreezeUpdateFrame = FreezeUpdateFrame;
|
|
|
|
auto ComputeShader = Views[0].ShaderMap->GetShader<FSelectMaxUpdateBucketCS>();
|
|
|
|
FComputeShaderUtils::AddPass(
|
|
GraphBuilder,
|
|
RDG_EVENT_NAME("Select max update bucket"),
|
|
ComputePassFlags,
|
|
ComputeShader,
|
|
PassParameters,
|
|
FIntVector(2, 1, 1));
|
|
}
|
|
|
|
// Build list of tiles to update in this frame
|
|
{
|
|
FBuildCardsUpdateListCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FBuildCardsUpdateListCS::FParameters>();
|
|
PassParameters->RWDirectLightingCardPageIndexAllocator = DirectCardPageIndexAllocatorUAV;
|
|
PassParameters->RWDirectLightingCardPageIndexData = GraphBuilder.CreateUAV(DirectLightingCardUpdateContext.CardPageIndexData);
|
|
PassParameters->RWIndirectLightingCardPageIndexAllocator = IndirectCardPageIndexAllocatorUAV;
|
|
PassParameters->RWIndirectLightingCardPageIndexData = GraphBuilder.CreateUAV(IndirectLightingCardUpdateContext.CardPageIndexData);
|
|
PassParameters->RWCardPageTileAllocator = CardPageTileAllocatorUAV;
|
|
PassParameters->MaxUpdateBucket = MaxUpdateBucketSRV;
|
|
PassParameters->LumenCardDataBuffer = FrameTemporaries.CardBufferSRV;
|
|
PassParameters->RWLumenCardPageDataBuffer = FrameTemporaries.CardPageBufferUAV;
|
|
PassParameters->CardPageLastUsedBuffer = CardPageLastUsedBufferSRV;
|
|
PassParameters->CardPageHighResLastUsedBuffer = CardPageHighResLastUsedBufferSRV;
|
|
PassParameters->SurfaceCacheUpdateParameters = SurfaceCacheUpdateParameters;
|
|
PassParameters->CardPageNum = NumCardPages;
|
|
PassParameters->SurfaceCacheUpdateFrameIndex = UpdateFrameIndex;
|
|
PassParameters->FreezeUpdateFrame = FreezeUpdateFrame;
|
|
PassParameters->FirstClipmapWorldExtentRcp = FirstClipmapWorldExtentRcp;
|
|
PassParameters->IndirectLightingHistoryValid = bIndirectLightingHistoryValid ? 1 : 0;
|
|
PassParameters->MaxDirectLightingTilesToUpdate = DirectLightingCardUpdateContext.MaxUpdateTiles;
|
|
PassParameters->MaxIndirectLightingTilesToUpdate = IndirectLightingCardUpdateContext.MaxUpdateTiles;
|
|
PassParameters->DirectLightingUpdateFactor = DirectLightingCardUpdateContext.UpdateFactor;
|
|
PassParameters->IndirectLightingUpdateFactor = IndirectLightingCardUpdateContext.UpdateFactor;
|
|
|
|
FBuildCardsUpdateListCS::FPermutationDomain PermutationVector;
|
|
PermutationVector.Set<FBuildCardsUpdateListCS::FSurfaceCacheFeedback>(bUseFeedback);
|
|
auto ComputeShader = Views[0].ShaderMap->GetShader<FBuildCardsUpdateListCS>(PermutationVector);
|
|
|
|
const FIntVector GroupSize(FMath::DivideAndRoundUp<int32>(LumenSceneData.GetNumCardPages(), FBuildCardsUpdateListCS::GetGroupSize()), 1, 1);
|
|
|
|
FComputeShaderUtils::AddPass(
|
|
GraphBuilder,
|
|
RDG_EVENT_NAME("Build cards update list"),
|
|
ComputePassFlags,
|
|
ComputeShader,
|
|
PassParameters,
|
|
GroupSize);
|
|
}
|
|
|
|
// Setup indirect args
|
|
{
|
|
FSetCardPageIndexIndirectArgsCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FSetCardPageIndexIndirectArgsCS::FParameters>();
|
|
PassParameters->RWDirectLightingDrawCardPageIndicesIndirectArgs = GraphBuilder.CreateUAV(DirectLightingCardUpdateContext.DrawCardPageIndicesIndirectArgs);
|
|
PassParameters->RWDirectLightingDispatchCardPageIndicesIndirectArgs = GraphBuilder.CreateUAV(DirectLightingCardUpdateContext.DispatchCardPageIndicesIndirectArgs);
|
|
PassParameters->RWIndirectLightingDrawCardPageIndicesIndirectArgs = GraphBuilder.CreateUAV(IndirectLightingCardUpdateContext.DrawCardPageIndicesIndirectArgs);
|
|
PassParameters->RWIndirectLightingDispatchCardPageIndicesIndirectArgs = GraphBuilder.CreateUAV(IndirectLightingCardUpdateContext.DispatchCardPageIndicesIndirectArgs);
|
|
PassParameters->DirectLightingCardPageIndexAllocator = DirectCardPageIndexAllocatorSRV;
|
|
PassParameters->IndirectLightingCardPageIndexAllocator = IndirectCardPageIndexAllocatorSRV;
|
|
PassParameters->VertexCountPerInstanceIndirect = GRHISupportsRectTopology ? 3 : 6;
|
|
|
|
auto ComputeShader = Views[0].ShaderMap->GetShader<FSetCardPageIndexIndirectArgsCS>();
|
|
|
|
FComputeShaderUtils::AddPass(
|
|
GraphBuilder,
|
|
RDG_EVENT_NAME("SetCardPageIndexIndirectArgs"),
|
|
ComputePassFlags,
|
|
ComputeShader,
|
|
PassParameters,
|
|
FIntVector(1, 1, 1));
|
|
}
|
|
|
|
const uint32 StatMode = GetLumenLightingStatMode();
|
|
if (StatMode == 1 || StatMode == 2)
|
|
{
|
|
ShaderPrint::SetEnabled(true);
|
|
|
|
FLumenSceneLightingStatsCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FLumenSceneLightingStatsCS::FParameters>();
|
|
ShaderPrint::SetParameters(GraphBuilder, Views[0].ShaderPrintData, PassParameters->ShaderPrintUniformBuffer);
|
|
PassParameters->LumenCardScene = FrameTemporaries.LumenCardSceneUniformBuffer;
|
|
PassParameters->DirectLightingCardPageIndexAllocator = DirectCardPageIndexAllocatorSRV;
|
|
PassParameters->IndirectLightingCardPageIndexAllocator = IndirectCardPageIndexAllocatorSRV;
|
|
PassParameters->PriorityHistogram = PriorityHistogramSRV;
|
|
PassParameters->MaxUpdateBucket = MaxUpdateBucketSRV;
|
|
PassParameters->CardPageTileAllocator = GraphBuilder.CreateSRV(CardPageTileAllocator);
|
|
PassParameters->CardPageNum = LumenSceneData.GetNumCardPages();
|
|
PassParameters->LightingStatMode = StatMode;
|
|
|
|
auto ComputeShader = Views[0].ShaderMap->GetShader<FLumenSceneLightingStatsCS>();
|
|
|
|
FComputeShaderUtils::AddPass(
|
|
GraphBuilder,
|
|
RDG_EVENT_NAME("SceneLightingStats"),
|
|
ComputePassFlags,
|
|
ComputeShader,
|
|
PassParameters,
|
|
FIntVector(1, 1, 1));
|
|
}
|
|
} |