Files
UnrealEngine/Engine/Source/Runtime/Renderer/Private/Lumen/LumenRadianceCache.cpp
2025-05-18 13:04:45 +08:00

2468 lines
121 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "LumenRadianceCache.h"
#include "LumenRadianceCacheInternal.h"
#include "RendererPrivate.h"
#include "ScenePrivate.h"
#include "SceneUtils.h"
#include "PipelineStateCache.h"
#include "ShaderParameterStruct.h"
#include "DistanceFieldAmbientOcclusion.h"
#include "LumenScreenProbeGather.h"
#include "LumenSceneLighting.h"
#include "ShaderPrintParameters.h"
int32 GRadianceCacheUpdate = 1;
FAutoConsoleVariableRef CVarRadianceCacheUpdate(
TEXT("r.Lumen.RadianceCache.Update"),
GRadianceCacheUpdate,
TEXT("Whether to update radiance cache every frame. Useful for debugging."),
ECVF_RenderThreadSafe
);
int32 GRadianceCacheForceFullUpdate = 0;
FAutoConsoleVariableRef CVarRadianceForceFullUpdate(
TEXT("r.Lumen.RadianceCache.ForceFullUpdate"),
GRadianceCacheForceFullUpdate,
TEXT("Whether to update entuire radiance cache once. Useful for debugging."),
ECVF_RenderThreadSafe
);
static TAutoConsoleVariable<int32> CVarRadianceCacheNumFramesToKeepCachedProbes(
TEXT("r.Lumen.RadianceCache.NumFramesToKeepCachedProbes"),
8,
TEXT("Number of frames to keep unused probes in cache. Higher values enable more reuse between frames, but too high values will cause filtering from stale probes."),
ECVF_Scalability | ECVF_RenderThreadSafe
);
int32 GRadianceCacheOverrideCacheOcclusionLighting = 0;
FAutoConsoleVariableRef CVarRadianceCacheShowOnlyRadianceCacheLighting(
TEXT("r.Lumen.RadianceCache.OverrideCacheOcclusionLighting"),
GRadianceCacheOverrideCacheOcclusionLighting,
TEXT(""),
ECVF_RenderThreadSafe
);
int32 GRadianceCacheShowBlackRadianceCacheLighting = 0;
FAutoConsoleVariableRef CVarRadianceCacheShowBlackRadianceCacheLighting(
TEXT("r.Lumen.RadianceCache.ShowBlackRadianceCacheLighting"),
GRadianceCacheShowBlackRadianceCacheLighting,
TEXT(""),
ECVF_RenderThreadSafe
);
int32 GRadianceCacheFilterProbes = 1;
FAutoConsoleVariableRef CVarRadianceCacheFilterProbes(
TEXT("r.Lumen.RadianceCache.SpatialFilterProbes"),
GRadianceCacheFilterProbes,
TEXT("Whether to filter probe radiance between neighbors"),
ECVF_RenderThreadSafe
);
int32 GRadianceCacheSortTraceTiles = 0;
FAutoConsoleVariableRef CVarRadianceCacheSortTraceTiles(
TEXT("r.Lumen.RadianceCache.SortTraceTiles"),
GRadianceCacheSortTraceTiles,
TEXT("Whether to sort Trace Tiles by direction before tracing to extract coherency"),
ECVF_RenderThreadSafe
);
float GLumenRadianceCacheFilterMaxRadianceHitAngle = .2f;
FAutoConsoleVariableRef GVarLumenRadianceCacheFilterMaxRadianceHitAngle(
TEXT("r.Lumen.RadianceCache.SpatialFilterMaxRadianceHitAngle"),
GLumenRadianceCacheFilterMaxRadianceHitAngle,
TEXT("In Degrees. Larger angles allow filtering of nearby features but more leaking."),
ECVF_Scalability | ECVF_RenderThreadSafe
);
int32 GLumenRadianceCacheForceUniformTraceTileLevel = -1;
FAutoConsoleVariableRef CVarLumenRadianceCacheForceUniformTraceTileLevel(
TEXT("r.Lumen.RadianceCache.ForceUniformTraceTileLevel"),
GLumenRadianceCacheForceUniformTraceTileLevel,
TEXT("When set to >= 0, forces a uniform trace tile level for debugging, and overrides trace tile BRDF importance sampling. Valid range is [0, 2]. 0 = half res, 1 = full res, 2 = supersampled"),
ECVF_Scalability | ECVF_RenderThreadSafe
);
float GLumenRadianceCacheSupersampleTileBRDFThreshold = .1f;
FAutoConsoleVariableRef CVarLumenRadianceCacheSupersampleTileBRDFThreshold(
TEXT("r.Lumen.RadianceCache.SupersampleTileBRDFThreshold"),
GLumenRadianceCacheSupersampleTileBRDFThreshold,
TEXT("Value of the BRDF [0-1] above which to trace more rays to supersample the probe radiance."),
ECVF_Scalability | ECVF_RenderThreadSafe
);
static TAutoConsoleVariable<float> CVarLumenRadianceCacheSupersampleDistanceFromCamera(
TEXT("r.Lumen.RadianceCache.SupersampleDistanceFromCamera"),
-1.0f,
TEXT("Only probes closer to the camera than this distance can be supersampled."),
ECVF_Scalability | ECVF_RenderThreadSafe
);
float GLumenRadianceCacheDownsampleDistanceFromCamera = 4000.0f;
FAutoConsoleVariableRef CVarLumenRadianceCacheDownsampleDistanceFromCamera(
TEXT("r.Lumen.RadianceCache.DownsampleDistanceFromCamera"),
GLumenRadianceCacheDownsampleDistanceFromCamera,
TEXT("Probes further than this distance from the camera are always downsampled."),
ECVF_Scalability | ECVF_RenderThreadSafe
);
namespace LumenRadianceCache
{
// Must match LumenRadianceCacheCommon.ush
constexpr uint32 PRIORITY_HISTOGRAM_SIZE = 16;
constexpr uint32 PROBES_TO_UPDATE_TRACE_COST_STRIDE = 2;
FRadianceCacheInputs GetDefaultRadianceCacheInputs()
{
FRadianceCacheInputs RadianceCacheInputs;
RadianceCacheInputs.CalculateIrradiance = 0;
RadianceCacheInputs.UseSkyVisibility = 0;
RadianceCacheInputs.ProbeTMinScale = 1.0f;
RadianceCacheInputs.IrradianceProbeResolution = 0;
RadianceCacheInputs.InvClipmapFadeSize = 1.0f;
return RadianceCacheInputs;
}
void GetInterpolationParametersNoResources(
FRDGBuilder& GraphBuilder,
const FRadianceCacheState& RadianceCacheState,
const LumenRadianceCache::FRadianceCacheInputs& RadianceCacheInputs,
FRadianceCacheInterpolationParameters& OutParameters)
{
OutParameters.RadianceCacheInputs = RadianceCacheInputs;
OutParameters.RadianceCacheInputs.NumProbesToTraceBudget = GRadianceCacheForceFullUpdate ? UINT32_MAX : OutParameters.RadianceCacheInputs.NumProbesToTraceBudget;
OutParameters.RadianceProbeIndirectionTexture = nullptr;
OutParameters.RadianceCacheFinalRadianceAtlas = nullptr;
OutParameters.RadianceCacheFinalSkyVisibilityAtlas = nullptr;
OutParameters.RadianceCacheFinalIrradianceAtlas = nullptr;
OutParameters.RadianceCacheProbeOcclusionAtlas = nullptr;
OutParameters.RadianceCacheDepthAtlas = nullptr;
OutParameters.ProbeWorldOffset = nullptr;
OutParameters.RadianceCacheOneOverCachedLightingPreExposure = 1.0f / Lumen::GetCachedLightingPreExposure();
OutParameters.OverrideCacheOcclusionLighting = GRadianceCacheOverrideCacheOcclusionLighting;
OutParameters.ShowBlackRadianceCacheLighting = GRadianceCacheShowBlackRadianceCacheLighting;
OutParameters.ProbeAtlasResolutionModuloMask = (1u << FMath::FloorLog2(RadianceCacheInputs.ProbeAtlasResolutionInProbes.X)) - 1;
OutParameters.ProbeAtlasResolutionDivideShift = FMath::FloorLog2(RadianceCacheInputs.ProbeAtlasResolutionInProbes.X);
for (int32 ClipmapIndex = 0; ClipmapIndex < RadianceCacheState.Clipmaps.Num(); ++ClipmapIndex)
{
const FRadianceCacheClipmap& Clipmap = RadianceCacheState.Clipmaps[ClipmapIndex];
SetRadianceProbeClipmapTMin(OutParameters, ClipmapIndex, Clipmap.ProbeTMin);
SetClipmapCornerTWS(OutParameters, ClipmapIndex, Clipmap.CornerTranslatedWorldSpace);
SetClipmapCellSize(OutParameters, ClipmapIndex, Clipmap.CellSize);
}
const FVector2f ProbeAtlasResolutionInProbesAsFloat = FVector2f(RadianceCacheInputs.ProbeAtlasResolutionInProbes);
OutParameters.InvProbeFinalRadianceAtlasResolution = FVector2f::UnitVector / (RadianceCacheInputs.FinalProbeResolution * ProbeAtlasResolutionInProbesAsFloat); // LWC_TODO: Fix! Used to be FVector2D(RadianceCacheInputs.FinalProbeResolution * RadianceCacheInputs.ProbeAtlasResolutionInProbes). No auto conversion of ProbeAtlastResolutionInProbes to FVector2D. ADL thing?
const int32 FinalIrradianceProbeResolution = RadianceCacheInputs.IrradianceProbeResolution + 2 * (1 << RadianceCacheInputs.FinalRadianceAtlasMaxMip);
OutParameters.InvProbeFinalIrradianceAtlasResolution = FVector2f::UnitVector / (FinalIrradianceProbeResolution * ProbeAtlasResolutionInProbesAsFloat);
OutParameters.InvProbeDepthAtlasResolution = FVector2f::UnitVector / (RadianceCacheInputs.RadianceProbeResolution * ProbeAtlasResolutionInProbesAsFloat);
}
void GetInterpolationParameters(
const FViewInfo& View,
FRDGBuilder& GraphBuilder,
const FRadianceCacheState& RadianceCacheState,
const LumenRadianceCache::FRadianceCacheInputs& RadianceCacheInputs,
FRadianceCacheInterpolationParameters& OutParameters)
{
GetInterpolationParametersNoResources(GraphBuilder, RadianceCacheState, RadianceCacheInputs, OutParameters);
OutParameters.RadianceProbeIndirectionTexture = RadianceCacheState.RadianceProbeIndirectionTexture ? GraphBuilder.RegisterExternalTexture(RadianceCacheState.RadianceProbeIndirectionTexture, TEXT("Lumen.RadianceCacheIndirectionTexture")) : nullptr;
OutParameters.RadianceCacheFinalRadianceAtlas = RadianceCacheState.FinalRadianceAtlas ? GraphBuilder.RegisterExternalTexture(RadianceCacheState.FinalRadianceAtlas, TEXT("Lumen.RadianceCacheFinalRadianceAtlas")) : nullptr;
OutParameters.RadianceCacheFinalSkyVisibilityAtlas = RadianceCacheState.FinalSkyVisibilityAtlas ? GraphBuilder.RegisterExternalTexture(RadianceCacheState.FinalSkyVisibilityAtlas, TEXT("Lumen.RadianceCacheFinalSkyVisiblityAtlas")) : nullptr;
OutParameters.RadianceCacheFinalIrradianceAtlas = RadianceCacheState.FinalIrradianceAtlas ? GraphBuilder.RegisterExternalTexture(RadianceCacheState.FinalIrradianceAtlas, TEXT("Lumen.RadianceCacheFinalIrradianceAtlas")) : nullptr;
OutParameters.RadianceCacheProbeOcclusionAtlas = RadianceCacheState.ProbeOcclusionAtlas ? GraphBuilder.RegisterExternalTexture(RadianceCacheState.ProbeOcclusionAtlas, TEXT("Lumen.RadianceCacheProbeOcclusionAtlas")) : nullptr;
OutParameters.RadianceCacheDepthAtlas = RadianceCacheState.DepthProbeAtlasTexture ? GraphBuilder.RegisterExternalTexture(RadianceCacheState.DepthProbeAtlasTexture, TEXT("Lumen.RadianceCacheDepthAtlas")) : nullptr;
FRDGBufferRef ProbeWorldOffset = RadianceCacheState.ProbeWorldOffset ? GraphBuilder.RegisterExternalBuffer(RadianceCacheState.ProbeWorldOffset) : nullptr;
OutParameters.ProbeWorldOffset = ProbeWorldOffset ? GraphBuilder.CreateSRV(FRDGBufferSRVDesc(ProbeWorldOffset, PF_A32B32G32R32F)) : nullptr;
}
FRadianceCacheMarkParameters GetMarkParameters(
FRDGTextureUAVRef RadianceProbeIndirectionTextureUAV,
const FRadianceCacheState& RadianceCacheState,
const LumenRadianceCache::FRadianceCacheInputs& RadianceCacheInputs)
{
FRadianceCacheMarkParameters MarkParameters;
MarkParameters.RWRadianceProbeIndirectionTexture = RadianceProbeIndirectionTextureUAV;
for (int32 ClipmapIndex = 0; ClipmapIndex < RadianceCacheState.Clipmaps.Num(); ++ClipmapIndex)
{
const FRadianceCacheClipmap& Clipmap = RadianceCacheState.Clipmaps[ClipmapIndex];
MarkParameters.ClipmapCornerTWSAndCellSizeForMark[ClipmapIndex] = FVector4f(Clipmap.CornerTranslatedWorldSpace, Clipmap.CellSize);
}
MarkParameters.RadianceProbeClipmapResolutionForMark = RadianceCacheInputs.RadianceProbeClipmapResolution;
MarkParameters.NumRadianceProbeClipmapsForMark = RadianceCacheInputs.NumRadianceProbeClipmaps;
MarkParameters.InvClipmapFadeSizeForMark = RadianceCacheInputs.InvClipmapFadeSize;
return MarkParameters;
}
};
class FMarkRadianceProbesUsedByVisualizeCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FMarkRadianceProbesUsedByVisualizeCS)
SHADER_USE_PARAMETER_STRUCT(FMarkRadianceProbesUsedByVisualizeCS, FGlobalShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, View)
SHADER_PARAMETER_STRUCT_INCLUDE(LumenRadianceCache::FRadianceCacheMarkParameters, RadianceCacheMarkParameters)
END_SHADER_PARAMETER_STRUCT()
public:
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return DoesPlatformSupportLumenGI(Parameters.Platform);
}
static uint32 GetGroupSize()
{
return 8;
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE"), GetGroupSize());
}
};
IMPLEMENT_GLOBAL_SHADER(FMarkRadianceProbesUsedByVisualizeCS, "/Engine/Private/Lumen/LumenRadianceCache.usf", "MarkRadianceProbesUsedByVisualizeCS", SF_Compute);
void MarkUsedProbesForVisualize(
FRDGBuilder& GraphBuilder,
const FViewInfo& View,
const LumenRadianceCache::FRadianceCacheMarkParameters& RadianceCacheMarkParameters,
ERDGPassFlags ComputePassFlags)
{
extern int32 GVisualizeLumenSceneTraceRadianceCache;
if (View.Family->EngineShowFlags.VisualizeLumen && GVisualizeLumenSceneTraceRadianceCache != 0)
{
FMarkRadianceProbesUsedByVisualizeCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FMarkRadianceProbesUsedByVisualizeCS::FParameters>();
PassParameters->View = View.ViewUniformBuffer;
PassParameters->RadianceCacheMarkParameters = RadianceCacheMarkParameters;
auto ComputeShader = View.ShaderMap->GetShader<FMarkRadianceProbesUsedByVisualizeCS>(0);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("MarkRadianceProbes(Visualize)"),
ComputePassFlags,
ComputeShader,
PassParameters,
FIntVector(1, 1, 1));
}
}
class FClearProbeFreeList : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FClearProbeFreeList)
SHADER_USE_PARAMETER_STRUCT(FClearProbeFreeList, FGlobalShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<int>, RWProbeFreeListAllocator)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<uint>, RWProbeFreeList)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<uint>, RWProbeLastUsedFrame)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer<float4>, RWProbeWorldOffset)
SHADER_PARAMETER(uint32, MaxNumProbes)
END_SHADER_PARAMETER_STRUCT()
public:
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return DoesPlatformSupportLumenGI(Parameters.Platform);
}
static uint32 GetGroupSize()
{
return 64;
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE"), GetGroupSize());
}
};
IMPLEMENT_GLOBAL_SHADER(FClearProbeFreeList, "/Engine/Private/Lumen/LumenRadianceCacheUpdate.usf", "ClearProbeFreeListCS", SF_Compute);
class FClearProbeIndirectionCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FClearProbeIndirectionCS)
SHADER_USE_PARAMETER_STRUCT(FClearProbeIndirectionCS, FGlobalShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture3D<uint>, RWRadianceProbeIndirectionTexture)
END_SHADER_PARAMETER_STRUCT()
public:
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return DoesPlatformSupportLumenGI(Parameters.Platform);
}
static uint32 GetGroupSize()
{
return 4;
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE"), GetGroupSize());
}
};
IMPLEMENT_GLOBAL_SHADER(FClearProbeIndirectionCS, "/Engine/Private/Lumen/LumenRadianceCache.usf", "ClearProbeIndirectionCS", SF_Compute);
class FUpdateCacheForUsedProbesCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FUpdateCacheForUsedProbesCS)
SHADER_USE_PARAMETER_STRUCT(FUpdateCacheForUsedProbesCS, FGlobalShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, View)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture3D<uint>, RWRadianceProbeIndirectionTexture)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer<uint>, ProbeAllocator)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<int>, RWProbeFreeListAllocator)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<uint>, RWProbeFreeList)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<uint>, RWProbeLastUsedFrame)
SHADER_PARAMETER_RDG_TEXTURE(Texture3D<uint>, LastFrameRadianceProbeIndirectionTexture)
SHADER_PARAMETER_STRUCT_INCLUDE(LumenRadianceCache::FRadianceCacheInterpolationParameters, RadianceCacheParameters)
SHADER_PARAMETER_ARRAY(FVector4f, LastFrameClipmapCornerTWSAndCellSize, [LumenRadianceCache::MaxClipmaps])
SHADER_PARAMETER(uint32, FrameNumber)
SHADER_PARAMETER(uint32, NumFramesToKeepCachedProbes)
SHADER_PARAMETER(uint32, MaxNumProbes)
END_SHADER_PARAMETER_STRUCT()
public:
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return DoesPlatformSupportLumenGI(Parameters.Platform);
}
static uint32 GetGroupSize()
{
return 4;
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE"), GetGroupSize());
}
};
IMPLEMENT_GLOBAL_SHADER(FUpdateCacheForUsedProbesCS, "/Engine/Private/Lumen/LumenRadianceCacheUpdate.usf", "UpdateCacheForUsedProbesCS", SF_Compute);
class FClearRadianceCacheUpdateResourcesCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FClearRadianceCacheUpdateResourcesCS);
SHADER_USE_PARAMETER_STRUCT(FClearRadianceCacheUpdateResourcesCS, FGlobalShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<uint>, RWProbeTraceAllocator)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer<uint>, RWPriorityHistogram)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer<uint>, RWMaxUpdateBucket)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer<uint>, RWMaxTracesFromMaxUpdateBucket)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer<uint>, RWProbesToUpdateTraceCost)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer<uint>, RWMinNewProbeTraceCost)
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());
}
public:
static int32 GetGroupSize()
{
return 64;
}
};
IMPLEMENT_GLOBAL_SHADER(FClearRadianceCacheUpdateResourcesCS, "/Engine/Private/Lumen/LumenRadianceCacheUpdate.usf", "ClearRadianceCacheUpdateResourcesCS", SF_Compute);
class FAllocateUsedProbesCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FAllocateUsedProbesCS)
SHADER_USE_PARAMETER_STRUCT(FAllocateUsedProbesCS, FGlobalShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture3D<uint>, RWRadianceProbeIndirectionTexture)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer<uint>, RWProbeLastTracedFrame)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer<uint>, RWPriorityHistogram)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer<uint>, RWMinNewProbeTraceCost)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<uint>, RWProbeLastUsedFrame)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<uint>, RWProbeAllocator)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<int>, RWProbeFreeListAllocator)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer<uint>, ProbeFreeList)
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, View)
SHADER_PARAMETER(float, DownsampleDistanceFromCameraSq)
SHADER_PARAMETER(float, SupersampleDistanceFromCameraSq)
SHADER_PARAMETER(float, FirstClipmapWorldExtentRcp)
SHADER_PARAMETER(uint32, FrameNumber)
SHADER_PARAMETER(uint32, MaxNumProbes)
SHADER_PARAMETER_STRUCT_INCLUDE(LumenRadianceCache::FRadianceCacheInterpolationParameters, RadianceCacheParameters)
END_SHADER_PARAMETER_STRUCT()
class FPersistentCache : SHADER_PERMUTATION_BOOL("PERSISTENT_CACHE");
using FPermutationDomain = TShaderPermutationDomain<FPersistentCache>;
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());
}
public:
static uint32 GetGroupSize()
{
return 4;
}
};
IMPLEMENT_GLOBAL_SHADER(FAllocateUsedProbesCS, "/Engine/Private/Lumen/LumenRadianceCacheUpdate.usf", "AllocateUsedProbesCS", SF_Compute);
class FAllocateProbeTracesCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FAllocateProbeTracesCS)
SHADER_USE_PARAMETER_STRUCT(FAllocateProbeTracesCS, FGlobalShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture3D<uint>, RWRadianceProbeIndirectionTexture)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer<uint>, RWProbeLastTracedFrame)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer<uint>, RWProbesToUpdateTraceCost)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer<uint>, RWMinNewProbeTraceCost)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<uint>, RWProbeTraceAllocator)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<float4>, RWProbeTraceData)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<int>, RWProbeFreeListAllocator)
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<uint>, MaxUpdateBucket)
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<uint>, MaxTracesFromMaxUpdateBucket)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer<uint>, ProbeLastUsedFrame)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer<uint>, ProbeFreeList)
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, View)
SHADER_PARAMETER(float, FirstClipmapWorldExtentRcp)
SHADER_PARAMETER(float, DownsampleDistanceFromCameraSq)
SHADER_PARAMETER(float, SupersampleDistanceFromCameraSq)
SHADER_PARAMETER(uint32, FrameNumber)
SHADER_PARAMETER(uint32, MaxNumProbes)
SHADER_PARAMETER_STRUCT_INCLUDE(LumenRadianceCache::FRadianceCacheInterpolationParameters, RadianceCacheParameters)
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());
}
public:
static uint32 GetGroupSize()
{
return 4;
}
};
IMPLEMENT_GLOBAL_SHADER(FAllocateProbeTracesCS, "/Engine/Private/Lumen/LumenRadianceCacheUpdate.usf", "AllocateProbeTracesCS", SF_Compute);
class FSelectMaxPriorityBucketCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FSelectMaxPriorityBucketCS)
SHADER_USE_PARAMETER_STRUCT(FSelectMaxPriorityBucketCS, FGlobalShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, View)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer<uint>, RWMaxUpdateBucket)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer<uint>, RWMaxTracesFromMaxUpdateBucket)
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<uint>, PriorityHistogram)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer<uint>, ProbeTraceAllocator)
SHADER_PARAMETER(uint32, NumProbesToTraceBudget)
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());
}
public:
static uint32 GetGroupSize()
{
return 1;
}
};
IMPLEMENT_GLOBAL_SHADER(FSelectMaxPriorityBucketCS, "/Engine/Private/Lumen/LumenRadianceCacheUpdate.usf", "SelectMaxPriorityBucketCS", SF_Compute);
class FRadianceCacheUpdateStatsCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FRadianceCacheUpdateStatsCS)
SHADER_USE_PARAMETER_STRUCT(FRadianceCacheUpdateStatsCS, FGlobalShader)
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, View)
SHADER_PARAMETER_STRUCT_INCLUDE(ShaderPrint::FShaderParameters, ShaderPrintUniformBuffer)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer<uint>, ProbeTraceTileAllocator)
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<uint>, PriorityHistogram)
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<uint>, MaxUpdateBucket)
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<uint>, MaxTracesFromMaxUpdateBucket)
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<uint>, ProbesToUpdateTraceCost)
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<uint>, MinNewProbeTraceCost)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer<uint>, ProbeTraceAllocator)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer<uint>, ProbeAllocator)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer<uint>, ProbeFreeListAllocator)
SHADER_PARAMETER(uint32, NumProbesToTraceBudget)
SHADER_PARAMETER(uint32, MaxNumProbes)
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());
}
public:
static uint32 GetGroupSize()
{
return 64;
}
};
IMPLEMENT_GLOBAL_SHADER(FRadianceCacheUpdateStatsCS, "/Engine/Private/Lumen/LumenRadianceCacheDebug.usf", "RadianceCacheUpdateStatsCS", SF_Compute);
class FSetupProbeIndirectArgsCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FSetupProbeIndirectArgsCS)
SHADER_USE_PARAMETER_STRUCT(FSetupProbeIndirectArgsCS, FGlobalShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<uint>, RWProbeAllocator)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<int>, RWProbeFreeListAllocator)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<uint>, RWClearProbePDFsIndirectArgs)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<uint>, RWGenerateProbeTraceTilesIndirectArgs)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<uint>, RWProbeTraceTileAllocator)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<uint>, RWFilterProbesIndirectArgs)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<uint>, RWPrepareProbeOcclusionIndirectArgs)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<uint>, RWFixupProbeBordersIndirectArgs)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer<uint>, ProbeTraceAllocator)
SHADER_PARAMETER_STRUCT_INCLUDE(LumenRadianceCache::FRadianceCacheInterpolationParameters, RadianceCacheParameters)
SHADER_PARAMETER(uint32, TraceFromProbesGroupSizeXY)
SHADER_PARAMETER(uint32, FilterProbesGroupSizeXY)
SHADER_PARAMETER(uint32, ClearProbePDFGroupSize)
SHADER_PARAMETER(uint32, MaxNumProbes)
END_SHADER_PARAMETER_STRUCT()
public:
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return DoesPlatformSupportLumenGI(Parameters.Platform);
}
static uint32 GetGroupSize()
{
return 8;
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE"), GetGroupSize());
}
};
IMPLEMENT_GLOBAL_SHADER(FSetupProbeIndirectArgsCS, "/Engine/Private/Lumen/LumenRadianceCache.usf", "SetupProbeIndirectArgsCS", SF_Compute);
class FComputeProbeWorldOffsetsCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FComputeProbeWorldOffsetsCS)
SHADER_USE_PARAMETER_STRUCT(FComputeProbeWorldOffsetsCS, FGlobalShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer<uint>, RWProbeWorldOffset)
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, View)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer<float4>, ProbeTraceData)
SHADER_PARAMETER_STRUCT_INCLUDE(LumenRadianceCache::FRadianceCacheInterpolationParameters, RadianceCacheParameters)
RDG_BUFFER_ACCESS(IndirectArgs, ERHIAccess::IndirectArgs)
END_SHADER_PARAMETER_STRUCT()
public:
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return DoesPlatformSupportLumenGI(Parameters.Platform);
}
static uint32 GetGroupSize()
{
return 64;
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE"), GetGroupSize());
}
};
IMPLEMENT_GLOBAL_SHADER(FComputeProbeWorldOffsetsCS, "/Engine/Private/Lumen/LumenRadianceCache.usf", "ComputeProbeWorldOffsetsCS", SF_Compute);
class FClearProbePDFs : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FClearProbePDFs)
SHADER_USE_PARAMETER_STRUCT(FClearProbePDFs, FGlobalShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<uint>, RWRadianceProbeSH_PDF)
RDG_BUFFER_ACCESS(ClearProbePDFsIndirectArgs, ERHIAccess::IndirectArgs)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer<float4>, ProbeTraceData)
END_SHADER_PARAMETER_STRUCT()
public:
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return DoesPlatformSupportLumenGI(Parameters.Platform);
}
static uint32 GetGroupSize()
{
return 64;
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE"), GetGroupSize());
}
};
IMPLEMENT_GLOBAL_SHADER(FClearProbePDFs, "/Engine/Private/Lumen/LumenRadianceCache.usf", "ClearProbePDFs", SF_Compute);
class FScatterScreenProbeBRDFToRadianceProbesCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FScatterScreenProbeBRDFToRadianceProbesCS)
SHADER_USE_PARAMETER_STRUCT(FScatterScreenProbeBRDFToRadianceProbesCS, FGlobalShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<uint>, RWRadianceProbeSH_PDF)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer<float>, BRDFProbabilityDensityFunctionSH)
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, View)
SHADER_PARAMETER_STRUCT_INCLUDE(FScreenProbeParameters, ScreenProbeParameters)
SHADER_PARAMETER_STRUCT_INCLUDE(LumenRadianceCache::FRadianceCacheInterpolationParameters, RadianceCacheParameters)
END_SHADER_PARAMETER_STRUCT()
public:
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return DoesPlatformSupportLumenGI(Parameters.Platform);
}
static uint32 GetGroupSize()
{
return 8;
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE"), GetGroupSize());
}
};
IMPLEMENT_GLOBAL_SHADER(FScatterScreenProbeBRDFToRadianceProbesCS, "/Engine/Private/Lumen/LumenRadianceCache.usf", "ScatterScreenProbeBRDFToRadianceProbesCS", SF_Compute);
class FGenerateProbeTraceTilesCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FGenerateProbeTraceTilesCS)
SHADER_USE_PARAMETER_STRUCT(FGenerateProbeTraceTilesCS, FGlobalShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<uint>, RWProbeTraceTileAllocator)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<uint2>, RWProbeTraceTileData)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer<float4>, ProbeTraceData)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer<int>, RadianceProbeSH_PDF)
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<uint>, ProbesToUpdateTraceCost)
SHADER_PARAMETER(float, SupersampleTileBRDFThreshold)
SHADER_PARAMETER(float, SupersampleDistanceFromCameraSq)
SHADER_PARAMETER(float, DownsampleDistanceFromCameraSq)
SHADER_PARAMETER(int32, ForcedUniformLevel)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<float>, RWDebugBRDFProbabilityDensityFunction)
SHADER_PARAMETER(uint32, DebugProbeBRDFOctahedronResolution)
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, View)
SHADER_PARAMETER_STRUCT_INCLUDE(LumenRadianceCache::FRadianceCacheInterpolationParameters, RadianceCacheParameters)
RDG_BUFFER_ACCESS(GenerateProbeTraceTilesIndirectArgs, ERHIAccess::IndirectArgs)
END_SHADER_PARAMETER_STRUCT()
public:
class FUniformTraces : SHADER_PERMUTATION_BOOL("FORCE_UNIFORM_TRACES");
using FPermutationDomain = TShaderPermutationDomain<FUniformTraces>;
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return DoesPlatformSupportLumenGI(Parameters.Platform);
}
static uint32 GetGroupSize()
{
return 8;
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE"), GetGroupSize());
// Workaround for an internal PC FXC compiler crash when compiling with disabled optimizations
if (Parameters.Platform == SP_PCD3D_SM5)
{
OutEnvironment.CompilerFlags.Add(CFLAG_ForceOptimization);
}
}
};
IMPLEMENT_GLOBAL_SHADER(FGenerateProbeTraceTilesCS, "/Engine/Private/Lumen/LumenRadianceCache.usf", "GenerateProbeTraceTilesCS", SF_Compute);
class FSetupTraceFromProbesCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FSetupTraceFromProbesCS)
SHADER_USE_PARAMETER_STRUCT(FSetupTraceFromProbesCS, FGlobalShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<uint>, RWTraceProbesIndirectArgs)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<uint>, RWSortProbeTraceTilesIndirectArgs)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<uint>, RWRadianceCacheHardwareRayTracingIndirectArgs)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<uint>, RWHardwareRayTracingRayAllocatorBuffer)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer<uint>, ProbeTraceTileAllocator)
SHADER_PARAMETER(uint32, SortTraceTilesGroupSize)
END_SHADER_PARAMETER_STRUCT()
public:
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return DoesPlatformSupportLumenGI(Parameters.Platform);
}
static uint32 GetGroupSize()
{
return 8;
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE"), GetGroupSize());
}
};
IMPLEMENT_GLOBAL_SHADER(FSetupTraceFromProbesCS, "/Engine/Private/Lumen/LumenRadianceCache.usf", "SetupTraceFromProbesCS", SF_Compute);
class FSortProbeTraceTilesCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FSortProbeTraceTilesCS)
SHADER_USE_PARAMETER_STRUCT(FSortProbeTraceTilesCS, FGlobalShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<uint>, RWProbeTraceTileData)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer<float4>, ProbeTraceData)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer<uint2>, ProbeTraceTileData)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer<uint>, ProbeTraceTileAllocator)
SHADER_PARAMETER_STRUCT_INCLUDE(LumenRadianceCache::FRadianceCacheInputs, RadianceCacheInputs)
RDG_BUFFER_ACCESS(SortProbeTraceTilesIndirectArgs, ERHIAccess::IndirectArgs)
END_SHADER_PARAMETER_STRUCT()
public:
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return DoesPlatformSupportLumenGI(Parameters.Platform);
}
static uint32 GetGroupSize()
{
// Group size affects sorting window, the larger the group the more coherency can be extracted
return 1024;
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("SORT_TILES_THREADGROUP_SIZE"), GetGroupSize());
}
};
IMPLEMENT_GLOBAL_SHADER(FSortProbeTraceTilesCS, "/Engine/Private/Lumen/LumenRadianceCache.usf", "SortProbeTraceTilesCS", SF_Compute);
class FRadianceCacheTraceFromProbesCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FRadianceCacheTraceFromProbesCS)
SHADER_USE_PARAMETER_STRUCT(FRadianceCacheTraceFromProbesCS, FGlobalShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, RWRadianceProbeAtlasTexture)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, RWSkyVisibilityProbeAtlasTexture)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, RWDepthProbeAtlasTexture)
SHADER_PARAMETER_STRUCT_INCLUDE(FLumenCardTracingParameters, TracingParameters)
SHADER_PARAMETER_STRUCT_INCLUDE(FLumenIndirectTracingParameters, IndirectTracingParameters)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer<float4>, ProbeTraceData)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer<uint2>, ProbeTraceTileData)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer<uint>, ProbeTraceTileAllocator)
SHADER_PARAMETER_STRUCT_INCLUDE(LumenRadianceCache::FRadianceCacheInterpolationParameters, RadianceCacheParameters)
RDG_BUFFER_ACCESS(TraceProbesIndirectArgs, ERHIAccess::IndirectArgs)
END_SHADER_PARAMETER_STRUCT()
class FTraceGlobalSDF : SHADER_PERMUTATION_BOOL("TRACE_GLOBAL_SDF");
class FSimpleCoverageBasedExpand : SHADER_PERMUTATION_BOOL("GLOBALSDF_SIMPLE_COVERAGE_BASED_EXPAND");
class FDynamicSkyLight : SHADER_PERMUTATION_BOOL("ENABLE_DYNAMIC_SKY_LIGHT");
class FRadianceCacheSkyVisibility : SHADER_PERMUTATION_BOOL("RADIANCE_CACHE_SKY_VISIBILITY");
using FPermutationDomain = TShaderPermutationDomain<FTraceGlobalSDF, FSimpleCoverageBasedExpand, FRadianceCacheSkyVisibility, FDynamicSkyLight>;
public:
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
const FPermutationDomain PermutationVector(Parameters.PermutationId);
if (!PermutationVector.Get<FTraceGlobalSDF>() && PermutationVector.Get<FSimpleCoverageBasedExpand>())
{
return false;
}
return DoesPlatformSupportLumenGI(Parameters.Platform);
}
static uint32 GetGroupSize()
{
// Must match RADIANCE_CACHE_TRACE_TILE_SIZE_2D
return 8;
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
// Workaround for an internal PC FXC compiler crash when compiling with disabled optimizations
if (Parameters.Platform == SP_PCD3D_SM5)
{
OutEnvironment.CompilerFlags.Add(CFLAG_ForceOptimization);
}
}
};
IMPLEMENT_GLOBAL_SHADER(FRadianceCacheTraceFromProbesCS, "/Engine/Private/Lumen/LumenRadianceCache.usf", "TraceFromProbesCS", SF_Compute);
class FFilterProbeRadianceWithGatherCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FFilterProbeRadianceWithGatherCS)
SHADER_USE_PARAMETER_STRUCT(FFilterProbeRadianceWithGatherCS, FGlobalShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, RWRadianceProbeAtlasTexture)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, RWSkyVisibilityProbeAtlasTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, RadianceProbeAtlasTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, SkyVisibilityProbeAtlasTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, DepthProbeAtlasTexture)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer<float4>, ProbeTraceData)
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, View)
SHADER_PARAMETER_STRUCT_INCLUDE(LumenRadianceCache::FRadianceCacheInterpolationParameters, RadianceCacheParameters)
RDG_BUFFER_ACCESS(FilterProbesIndirectArgs, ERHIAccess::IndirectArgs)
SHADER_PARAMETER(float, SpatialFilterMaxRadianceHitAngle)
END_SHADER_PARAMETER_STRUCT()
public:
class FRadianceCacheSkyVisibility : SHADER_PERMUTATION_BOOL("RADIANCE_CACHE_SKY_VISIBILITY");
using FPermutationDomain = TShaderPermutationDomain<FRadianceCacheSkyVisibility>;
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return DoesPlatformSupportLumenGI(Parameters.Platform);
}
static uint32 GetGroupSize()
{
return 8;
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE"), GetGroupSize());
// Workaround for an internal PC FXC compiler crash when compiling with disabled optimizations
if (Parameters.Platform == SP_PCD3D_SM5)
{
OutEnvironment.CompilerFlags.Add(CFLAG_ForceOptimization);
}
}
};
IMPLEMENT_GLOBAL_SHADER(FFilterProbeRadianceWithGatherCS, "/Engine/Private/Lumen/LumenRadianceCache.usf", "FilterProbeRadianceWithGatherCS", SF_Compute);
class FCalculateProbeIrradianceCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FCalculateProbeIrradianceCS)
SHADER_USE_PARAMETER_STRUCT(FCalculateProbeIrradianceCS, FGlobalShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, RWFinalIrradianceAtlas)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, RadianceProbeAtlasTexture)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer<float4>, ProbeTraceData)
SHADER_PARAMETER_STRUCT_INCLUDE(LumenRadianceCache::FRadianceCacheInterpolationParameters, RadianceCacheParameters)
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, View)
RDG_BUFFER_ACCESS(CalculateProbeIrradianceIndirectArgs, ERHIAccess::IndirectArgs)
END_SHADER_PARAMETER_STRUCT()
public:
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return DoesPlatformSupportLumenGI(Parameters.Platform);
}
static uint32 GetGroupSize()
{
return 8;
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE"), GetGroupSize());
}
};
IMPLEMENT_GLOBAL_SHADER(FCalculateProbeIrradianceCS, "/Engine/Private/Lumen/LumenRadianceCache.usf", "CalculateProbeIrradianceCS", SF_Compute);
class FPrepareProbeOcclusionCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FPrepareProbeOcclusionCS)
SHADER_USE_PARAMETER_STRUCT(FPrepareProbeOcclusionCS, FGlobalShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, RWRadianceCacheProbeOcclusionAtlas)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, DepthProbeAtlasTexture)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer<float4>, ProbeTraceData)
SHADER_PARAMETER_STRUCT_INCLUDE(LumenRadianceCache::FRadianceCacheInterpolationParameters, RadianceCacheParameters)
RDG_BUFFER_ACCESS(PrepareProbeOcclusionIndirectArgs, ERHIAccess::IndirectArgs)
END_SHADER_PARAMETER_STRUCT()
public:
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return DoesPlatformSupportLumenGI(Parameters.Platform);
}
static uint32 GetGroupSize()
{
return 8;
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE"), GetGroupSize());
}
};
IMPLEMENT_GLOBAL_SHADER(FPrepareProbeOcclusionCS, "/Engine/Private/Lumen/LumenRadianceCache.usf", "PrepareProbeOcclusionCS", SF_Compute);
class FFixupBordersAndGenerateMipsCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FFixupBordersAndGenerateMipsCS)
SHADER_USE_PARAMETER_STRUCT(FFixupBordersAndGenerateMipsCS, FGlobalShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, RWFinalRadianceAtlasMip0)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, RWFinalRadianceAtlasMip1)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, RWFinalRadianceAtlasMip2)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, RWFinalSkyVisibilityAtlasMip0)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, RadianceProbeAtlasTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, SkyVisibilityProbeAtlasTexture)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer<float4>, ProbeTraceData)
SHADER_PARAMETER_STRUCT_INCLUDE(LumenRadianceCache::FRadianceCacheInterpolationParameters, RadianceCacheParameters)
RDG_BUFFER_ACCESS(FixupProbeBordersIndirectArgs, ERHIAccess::IndirectArgs)
END_SHADER_PARAMETER_STRUCT()
public:
class FGenerateMips : SHADER_PERMUTATION_BOOL("GENERATE_MIPS");
class FRadianceCacheSkyVisibility : SHADER_PERMUTATION_BOOL("RADIANCE_CACHE_SKY_VISIBILITY");
using FPermutationDomain = TShaderPermutationDomain<FGenerateMips, FRadianceCacheSkyVisibility>;
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return DoesPlatformSupportLumenGI(Parameters.Platform);
}
static uint32 GetGroupSize()
{
return 8;
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE"), GetGroupSize());
}
};
IMPLEMENT_GLOBAL_SHADER(FFixupBordersAndGenerateMipsCS, "/Engine/Private/Lumen/LumenRadianceCache.usf", "FixupBordersAndGenerateMipsCS", SF_Compute);
struct FClipmapLevelGeometry
{
/** Origin point, snapped to the cell grid of this level with floor(). */
FVector SnappedOrigin;
/** Worldspace length of this level on each axis. */
FVector Size;
/** Worldspace length of each cell on this level. */
FVector CellSize;
/**
* Shift the cell grid such that the center of a cell on this level
* lines up with the center of a cell on every level below this one.
*/
FVector GetCenterAlignedOrigin() const
{
return SnappedOrigin - (0.5 * CellSize);
}
};
struct FClipmapGeometry
{
/** Origin of this clipmap before snapping, so this point may not lie on the cell grid */
FVector Origin;
/** Worldspace length of each cell on the level. */
FVector Level0CellSize;
/** Resolution of the grid on each level */
FIntVector CellsPerLevel;
/** The maximum level present in this clipmap. Levels may also go below 0. */
int MaxLevel;
static FVector SnapToGrid(const FVector& Position, const FVector& GridCellSize)
{
FVector SnapUnits(
FMath::FloorToDouble(Position.X / GridCellSize.X),
FMath::FloorToDouble(Position.Y / GridCellSize.Y),
FMath::FloorToDouble(Position.Z / GridCellSize.Z));
FVector SnappedPosition(
SnapUnits.X * GridCellSize.X,
SnapUnits.Y * GridCellSize.Y,
SnapUnits.Z * GridCellSize.Z);
return SnappedPosition;
}
FVector GetCellSize(int Level) const
{
return Level0CellSize * FMath::Pow(2.0f, static_cast<float>(Level));
}
FClipmapGeometry(
/** Clipmap origin, in absolute world space */
FVector InOrigin,
int InMaxLevel,
FVector InLevel0CellSize,
FIntVector InCellsPerLevel)
: Origin(InOrigin)
, Level0CellSize(InLevel0CellSize)
, CellsPerLevel(InCellsPerLevel)
, MaxLevel(InMaxLevel)
{ }
FClipmapGeometry(
/** Clipmap origin, in absolute world space */
FVector InOrigin,
int InMaxLevel,
double InLevel0CellSize,
int InCellsPerLevel)
: FClipmapGeometry(InOrigin, InMaxLevel, FVector(InLevel0CellSize), FIntVector(InCellsPerLevel))
{ }
FClipmapLevelGeometry GetLevel(int Level) const
{
FClipmapLevelGeometry LevelGeometry;
LevelGeometry.CellSize = GetCellSize(Level);
LevelGeometry.SnappedOrigin = SnapToGrid(Origin, LevelGeometry.CellSize);
LevelGeometry.Size = LevelGeometry.CellSize * (FVector)CellsPerLevel;
return LevelGeometry;
}
/**
* Return the root origin of this clipmap, which is the origin of the last level.
* This point is guaranteed to line up with the cell grid on every level.
*/
FVector GetRootOrigin() const
{
FClipmapLevelGeometry LastLevel = GetLevel(MaxLevel);
return LastLevel.SnappedOrigin;
}
};
bool UpdateRadianceCacheState(FRDGBuilder& GraphBuilder, const FViewInfo& View, const LumenRadianceCache::FRadianceCacheInputs& RadianceCacheInputs, FRadianceCacheState& CacheState)
{
bool bResetState = CacheState.ClipmapWorldExtent != RadianceCacheInputs.ClipmapWorldExtent
|| CacheState.ClipmapDistributionBase != RadianceCacheInputs.ClipmapDistributionBase
|| CacheState.CachedLightingPreExposure != Lumen::GetCachedLightingPreExposure();
CacheState.ClipmapWorldExtent = RadianceCacheInputs.ClipmapWorldExtent;
CacheState.ClipmapDistributionBase = RadianceCacheInputs.ClipmapDistributionBase;
CacheState.CachedLightingPreExposure = Lumen::GetCachedLightingPreExposure();
const float ClipmapWorldExtent = RadianceCacheInputs.ClipmapWorldExtent;
const int32 ClipmapResolution = RadianceCacheInputs.RadianceProbeClipmapResolution;
const int32 NumClipmaps = RadianceCacheInputs.NumRadianceProbeClipmaps;
const FVector NewViewOrigin = View.ViewMatrices.GetViewOrigin();
CacheState.Clipmaps.SetNum(NumClipmaps);
double Level0CellSize = (ClipmapWorldExtent * 2.0f) / ClipmapResolution;
FClipmapGeometry ClipmapGeometry(NewViewOrigin, NumClipmaps - 1, Level0CellSize, ClipmapResolution);
for (int32 LevelIndex = 0; LevelIndex < NumClipmaps; ++LevelIndex)
{
FClipmapLevelGeometry LevelGeometry = ClipmapGeometry.GetLevel(LevelIndex);
const FVector WorldspaceCorner = LevelGeometry.GetCenterAlignedOrigin() - (LevelGeometry.Size / 2.0);
const FVector3f Corner = (FVector3f)(WorldspaceCorner + View.ViewMatrices.GetPreViewTranslation());
const float ClipmapExtent = LevelGeometry.Size.X / 2.0;
const float CellSize = LevelGeometry.CellSize.X;
FRadianceCacheClipmap& Clipmap = CacheState.Clipmaps[LevelIndex];
Clipmap.Center = LevelGeometry.SnappedOrigin;
Clipmap.Extent = ClipmapExtent;
Clipmap.VolumeUVOffset = FVector(0.0f, 0.0f, 0.0f);
Clipmap.CornerWorldSpace = WorldspaceCorner;
Clipmap.CornerTranslatedWorldSpace = Corner;
Clipmap.CellSize = CellSize;
Clipmap.ProbeTMin = RadianceCacheInputs.CalculateIrradiance ? 0.0f : FVector(CellSize, CellSize, CellSize).Size() * RadianceCacheInputs.ProbeTMinScale;
}
return bResetState;
}
namespace LumenRadianceCache
{
bool ShouldImportanceSampleBRDF(const FUpdateInputs& Inputs)
{
return Inputs.ScreenProbeParameters && Inputs.BRDFProbabilityDensityFunctionSH && GLumenRadianceCacheForceUniformTraceTileLevel < 0;
}
float GetSupersampleDistanceFromCameraSq()
{
const float Distance = FMath::Max(CVarLumenRadianceCacheSupersampleDistanceFromCamera.GetValueOnRenderThread(), 0.0f);
return Distance * Distance;
}
void UpdateRadianceCaches(
FRDGBuilder& GraphBuilder,
const FLumenSceneFrameTemporaries& FrameTemporaries,
const TInlineArray<FUpdateInputs>& InputArray,
TInlineArray<FUpdateOutputs>& OutputArray,
const FScene* Scene,
const FViewFamilyInfo& ViewFamily,
bool bPropagateGlobalLightingChange,
ERDGPassFlags ComputePassFlags)
{
if (GRadianceCacheUpdate != 0)
{
RDG_EVENT_SCOPE(GraphBuilder, "UpdateRadianceCaches");
check(InputArray.Num() == OutputArray.Num());
TInlineArray<FRadianceCacheSetup> SetupOutputArray(InputArray.Num());
for (int32 RadianceCacheIndex = 0; RadianceCacheIndex < InputArray.Num(); RadianceCacheIndex++)
{
const FUpdateInputs& Inputs = InputArray[RadianceCacheIndex];
const FRadianceCacheInputs& RadianceCacheInputs = Inputs.RadianceCacheInputs;
const FViewInfo& View = Inputs.View;
FUpdateOutputs& Outputs = OutputArray[RadianceCacheIndex];
FRadianceCacheState& RadianceCacheState = Outputs.RadianceCacheState;
FRadianceCacheInterpolationParameters& RadianceCacheParameters = Outputs.RadianceCacheParameters;
FRadianceCacheSetup& SetupOutputs = SetupOutputArray[RadianceCacheIndex];
SetupOutputs.LastFrameClipmaps = RadianceCacheState.Clipmaps;
bool bResizedHistoryState = UpdateRadianceCacheState(GraphBuilder, View, RadianceCacheInputs, RadianceCacheState);
const FIntPoint RadianceProbeAtlasTextureSize(RadianceCacheInputs.ProbeAtlasResolutionInProbes * RadianceCacheInputs.RadianceProbeResolution);
if (RadianceCacheState.DepthProbeAtlasTexture.IsValid()
&& RadianceCacheState.DepthProbeAtlasTexture->GetDesc().Extent == RadianceProbeAtlasTextureSize)
{
SetupOutputs.DepthProbeAtlasTexture = GraphBuilder.RegisterExternalTexture(RadianceCacheState.DepthProbeAtlasTexture);
}
else
{
FRDGTextureDesc ProbeAtlasDesc = FRDGTextureDesc::Create2D(
RadianceProbeAtlasTextureSize,
PF_R16F,
FClearValueBinding::None,
TexCreate_ShaderResource | TexCreate_UAV);
SetupOutputs.DepthProbeAtlasTexture = GraphBuilder.CreateTexture(ProbeAtlasDesc, TEXT("Lumen.RadianceCache.DepthProbeAtlasTexture"));
bResizedHistoryState = true;
}
SetupOutputs.FinalIrradianceAtlas = nullptr;
SetupOutputs.ProbeOcclusionAtlas = nullptr;
SetupOutputs.FinalRadianceAtlas = nullptr;
SetupOutputs.FinalSkyVisibilityAtlas = nullptr;
const EPixelFormat LightingDataFormat = Lumen::GetLightingDataFormat();
if (RadianceCacheInputs.CalculateIrradiance)
{
const FIntPoint FinalIrradianceAtlasSize(RadianceCacheInputs.ProbeAtlasResolutionInProbes * (RadianceCacheInputs.IrradianceProbeResolution + 2 * (1 << RadianceCacheInputs.FinalRadianceAtlasMaxMip)));
if (RadianceCacheState.FinalIrradianceAtlas.IsValid()
&& RadianceCacheState.FinalIrradianceAtlas->GetDesc().Extent == FinalIrradianceAtlasSize
&& RadianceCacheState.FinalIrradianceAtlas->GetDesc().NumMips == RadianceCacheInputs.FinalRadianceAtlasMaxMip + 1
&& RadianceCacheState.FinalIrradianceAtlas->GetDesc().Format == LightingDataFormat)
{
SetupOutputs.FinalIrradianceAtlas = GraphBuilder.RegisterExternalTexture(RadianceCacheState.FinalIrradianceAtlas);
}
else
{
FRDGTextureDesc FinalRadianceAtlasDesc = FRDGTextureDesc::Create2D(
FinalIrradianceAtlasSize,
LightingDataFormat,
FClearValueBinding::None,
TexCreate_ShaderResource | TexCreate_UAV,
RadianceCacheInputs.FinalRadianceAtlasMaxMip + 1);
SetupOutputs.FinalIrradianceAtlas = GraphBuilder.CreateTexture(FinalRadianceAtlasDesc, TEXT("Lumen.RadianceCache.FinalIrradianceAtlas"));
bResizedHistoryState = true;
}
if (GRadianceCacheForceFullUpdate)
{
AddClearUAVPass(GraphBuilder, GraphBuilder.CreateUAV(FRDGTextureUAVDesc(SetupOutputs.FinalIrradianceAtlas)), FLinearColor::Black, ComputePassFlags);
}
const FIntPoint ProbeOcclusionAtlasSize(RadianceCacheInputs.ProbeAtlasResolutionInProbes * (RadianceCacheInputs.OcclusionProbeResolution + 2 * (1 << RadianceCacheInputs.FinalRadianceAtlasMaxMip)));
if (RadianceCacheState.ProbeOcclusionAtlas.IsValid()
&& RadianceCacheState.ProbeOcclusionAtlas->GetDesc().Extent == ProbeOcclusionAtlasSize
&& RadianceCacheState.ProbeOcclusionAtlas->GetDesc().NumMips == RadianceCacheInputs.FinalRadianceAtlasMaxMip + 1)
{
SetupOutputs.ProbeOcclusionAtlas = GraphBuilder.RegisterExternalTexture(RadianceCacheState.ProbeOcclusionAtlas);
}
else
{
FRDGTextureDesc ProbeOcclusionAtlasDesc = FRDGTextureDesc::Create2D(
ProbeOcclusionAtlasSize,
PF_G16R16F,
FClearValueBinding::None,
TexCreate_ShaderResource | TexCreate_UAV,
RadianceCacheInputs.FinalRadianceAtlasMaxMip + 1);
SetupOutputs.ProbeOcclusionAtlas = GraphBuilder.CreateTexture(ProbeOcclusionAtlasDesc, TEXT("Lumen.RadianceCache.ProbeOcclusionAtlas"));
bResizedHistoryState = true;
}
}
else
{
const FIntPoint FinalRadianceAtlasSize(RadianceCacheInputs.ProbeAtlasResolutionInProbes * RadianceCacheInputs.FinalProbeResolution);
if (RadianceCacheState.FinalRadianceAtlas.IsValid()
&& RadianceCacheState.FinalRadianceAtlas->GetDesc().Extent == FinalRadianceAtlasSize
&& RadianceCacheState.FinalRadianceAtlas->GetDesc().NumMips == RadianceCacheInputs.FinalRadianceAtlasMaxMip + 1
&& RadianceCacheState.FinalRadianceAtlas->GetDesc().Format == LightingDataFormat)
{
SetupOutputs.FinalRadianceAtlas = GraphBuilder.RegisterExternalTexture(RadianceCacheState.FinalRadianceAtlas);
}
else
{
FRDGTextureDesc FinalRadianceAtlasDesc = FRDGTextureDesc::Create2D(
FinalRadianceAtlasSize,
LightingDataFormat,
FClearValueBinding::None,
TexCreate_ShaderResource | TexCreate_UAV,
RadianceCacheInputs.FinalRadianceAtlasMaxMip + 1);
SetupOutputs.FinalRadianceAtlas = GraphBuilder.CreateTexture(FinalRadianceAtlasDesc, TEXT("Lumen.RadianceCache.FinalRadianceAtlas"));
bResizedHistoryState = true;
}
SetupOutputs.FinalSkyVisibilityAtlas = nullptr;
if (Inputs.Configuration.bSkyVisibility)
{
if (RadianceCacheState.FinalSkyVisibilityAtlas.IsValid()
&& RadianceCacheState.FinalSkyVisibilityAtlas->GetDesc().Extent == FinalRadianceAtlasSize)
{
SetupOutputs.FinalSkyVisibilityAtlas = GraphBuilder.RegisterExternalTexture(RadianceCacheState.FinalSkyVisibilityAtlas);
}
else
{
SetupOutputs.FinalSkyVisibilityAtlas = GraphBuilder.CreateTexture(
FRDGTextureDesc::Create2D(
FinalRadianceAtlasSize,
PF_R8,
FClearValueBinding::None,
TexCreate_ShaderResource | TexCreate_UAV)
,TEXT("Lumen.RadianceCache.FinalSkyVisibilityAtlas"));
bResizedHistoryState = true;
}
}
if (GRadianceCacheForceFullUpdate)
{
AddClearUAVPass(GraphBuilder, GraphBuilder.CreateUAV(SetupOutputs.FinalRadianceAtlas), FLinearColor::Black, ComputePassFlags);
if (SetupOutputs.FinalSkyVisibilityAtlas)
{
AddClearUAVPass(GraphBuilder, GraphBuilder.CreateUAV(SetupOutputs.FinalSkyVisibilityAtlas), FLinearColor::Black, ComputePassFlags);
}
}
}
SetupOutputs.RadianceProbeAtlasTextureSource = nullptr;
if (RadianceCacheState.RadianceProbeAtlasTexture.IsValid()
&& RadianceCacheState.RadianceProbeAtlasTexture->GetDesc().Extent == RadianceProbeAtlasTextureSize
&& RadianceCacheState.RadianceProbeAtlasTexture->GetDesc().Format == LightingDataFormat)
{
SetupOutputs.RadianceProbeAtlasTextureSource = GraphBuilder.RegisterExternalTexture(RadianceCacheState.RadianceProbeAtlasTexture);
}
else
{
FRDGTextureDesc ProbeAtlasDesc = FRDGTextureDesc::Create2D(
RadianceProbeAtlasTextureSize,
LightingDataFormat,
FClearValueBinding::None,
TexCreate_ShaderResource | TexCreate_UAV);
SetupOutputs.RadianceProbeAtlasTextureSource = GraphBuilder.CreateTexture(ProbeAtlasDesc, TEXT("Lumen.RadianceCache.RadianceProbeAtlasTextureSource"));
}
SetupOutputs.SkyVisibilityProbeAtlasTextureSource = nullptr;
if (Inputs.Configuration.bSkyVisibility)
{
if (RadianceCacheState.SkyVisibilityProbeAtlasTexture.IsValid()
&& RadianceCacheState.SkyVisibilityProbeAtlasTexture->GetDesc().Extent == RadianceProbeAtlasTextureSize)
{
SetupOutputs.SkyVisibilityProbeAtlasTextureSource = GraphBuilder.RegisterExternalTexture(RadianceCacheState.SkyVisibilityProbeAtlasTexture);
}
else
{
SetupOutputs.SkyVisibilityProbeAtlasTextureSource = GraphBuilder.CreateTexture(
FRDGTextureDesc::Create2D(
RadianceProbeAtlasTextureSize,
PF_G8,
FClearValueBinding::None,
TexCreate_ShaderResource | TexCreate_UAV),
TEXT("Lumen.RadianceCache.SkyVisibilityProbeAtlasTextureSource"));
}
}
else
{
RadianceCacheState.SkyVisibilityProbeAtlasTexture = nullptr;
}
GetInterpolationParametersNoResources(GraphBuilder, RadianceCacheState, RadianceCacheInputs, RadianceCacheParameters);
const FIntVector RadianceProbeIndirectionTextureSize = FIntVector(
RadianceCacheInputs.RadianceProbeClipmapResolution * RadianceCacheInputs.NumRadianceProbeClipmaps,
RadianceCacheInputs.RadianceProbeClipmapResolution,
RadianceCacheInputs.RadianceProbeClipmapResolution);
FRDGTextureDesc ProbeIndirectionDesc = FRDGTextureDesc::Create3D(
RadianceProbeIndirectionTextureSize,
PF_R32_UINT,
FClearValueBinding::None,
TexCreate_ShaderResource | TexCreate_UAV | TexCreate_3DTiling);
RadianceCacheParameters.RadianceProbeIndirectionTexture = GraphBuilder.CreateTexture(FRDGTextureDesc(ProbeIndirectionDesc), TEXT("Lumen.RadianceCache.RadianceProbeIndirectionTexture"));
SetupOutputs.bPersistentCache = !GRadianceCacheForceFullUpdate
&& View.ViewState
&& IsValidRef(RadianceCacheState.RadianceProbeIndirectionTexture)
&& RadianceCacheState.RadianceProbeIndirectionTexture->GetDesc().GetSize() == RadianceProbeIndirectionTextureSize
&& !bResizedHistoryState
&& !bPropagateGlobalLightingChange;
}
const bool bLumenSceneLightingAsync = LumenSceneLighting::UseAsyncCompute(ViewFamily);
// Clear each clipmap indirection entry to invalid probe index
for (int32 RadianceCacheIndex = 0; RadianceCacheIndex < InputArray.Num(); RadianceCacheIndex++)
{
const FUpdateInputs& Inputs = InputArray[RadianceCacheIndex];
FUpdateOutputs& Outputs = OutputArray[RadianceCacheIndex];
FClearProbeIndirectionCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FClearProbeIndirectionCS::FParameters>();
PassParameters->RWRadianceProbeIndirectionTexture = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(Outputs.RadianceCacheParameters.RadianceProbeIndirectionTexture));
auto ComputeShader = Inputs.View.ShaderMap->GetShader<FClearProbeIndirectionCS>(0);
const FIntVector GroupSize = FComputeShaderUtils::GetGroupCount(Outputs.RadianceCacheParameters.RadianceProbeIndirectionTexture->Desc.GetSize(), FClearProbeIndirectionCS::GetGroupSize());
// Do clear on graphics if there is any graphics mark pass and LumenSeneLighting is async so the mark pass is not blocked.
// If LumenSceneLighting isn't async, it will block graphics mark passes anyway. May as well finish the clear early on the compute pipe.
// TODO: Is it possible to move graphics mark passes and their clears before LumenSceneLighting without heavy code change?
const ERDGPassFlags ClearPassFlags = Inputs.GraphicsMarkUsedRadianceCacheProbes.IsBound() && bLumenSceneLightingAsync ? ERDGPassFlags::Compute : ComputePassFlags;
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("ClearProbeIndirectionCS"),
ClearPassFlags,
ComputeShader,
PassParameters,
GroupSize);
}
for (int32 RadianceCacheIndex = 0; RadianceCacheIndex < InputArray.Num(); RadianceCacheIndex++)
{
const FUpdateInputs& Inputs = InputArray[RadianceCacheIndex];
FUpdateOutputs& Outputs = OutputArray[RadianceCacheIndex];
FRDGTextureUAVRef RadianceProbeIndirectionTextureMarkUAV = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(Outputs.RadianceCacheParameters.RadianceProbeIndirectionTexture), ERDGUnorderedAccessViewFlags::SkipBarrier);
FRadianceCacheMarkParameters RadianceCacheMarkParameters = GetMarkParameters(RadianceProbeIndirectionTextureMarkUAV, Outputs.RadianceCacheState, Inputs.RadianceCacheInputs);
// Mark indirection entries around positions that will be sampled by dependent features as used
Inputs.GraphicsMarkUsedRadianceCacheProbes.Broadcast(GraphBuilder, Inputs.View, RadianceCacheMarkParameters);
Inputs.ComputeMarkUsedRadianceCacheProbes.Broadcast(GraphBuilder, Inputs.View, RadianceCacheMarkParameters);
}
TInlineArray<FRDGBufferRef> ProbeFreeListAllocator(InputArray.Num());
TInlineArray<FRDGBufferRef> ProbeFreeList(InputArray.Num());
TInlineArray<FRDGBufferRef> ProbeLastUsedFrame(InputArray.Num());
TInlineArray<FRDGBufferRef> ProbeLastTracedFrame(InputArray.Num());
TInlineArray<FRDGBufferRef> ProbeWorldOffset(InputArray.Num());
for (int32 RadianceCacheIndex = 0; RadianceCacheIndex < InputArray.Num(); RadianceCacheIndex++)
{
const FUpdateInputs& Inputs = InputArray[RadianceCacheIndex];
const FRadianceCacheInputs& RadianceCacheInputs = Inputs.RadianceCacheInputs;
const FViewInfo& View = Inputs.View;
const FRadianceCacheSetup& Setup = SetupOutputArray[RadianceCacheIndex];
FUpdateOutputs& Outputs = OutputArray[RadianceCacheIndex];
FRadianceCacheState& RadianceCacheState = Outputs.RadianceCacheState;
FRadianceCacheInterpolationParameters& RadianceCacheParameters = Outputs.RadianceCacheParameters;
const int32 MaxNumProbes = RadianceCacheInputs.ProbeAtlasResolutionInProbes.X * RadianceCacheInputs.ProbeAtlasResolutionInProbes.Y;
if (IsValidRef(RadianceCacheState.ProbeFreeList) && RadianceCacheState.ProbeFreeList->Desc.NumElements == MaxNumProbes)
{
ProbeFreeListAllocator[RadianceCacheIndex] = GraphBuilder.RegisterExternalBuffer(RadianceCacheState.ProbeFreeListAllocator);
ProbeFreeList[RadianceCacheIndex] = GraphBuilder.RegisterExternalBuffer(RadianceCacheState.ProbeFreeList);
ProbeLastUsedFrame[RadianceCacheIndex] = GraphBuilder.RegisterExternalBuffer(RadianceCacheState.ProbeLastUsedFrame);
ProbeLastTracedFrame[RadianceCacheIndex] = GraphBuilder.RegisterExternalBuffer(RadianceCacheState.ProbeLastTracedFrame);
ProbeWorldOffset[RadianceCacheIndex] = GraphBuilder.RegisterExternalBuffer(RadianceCacheState.ProbeWorldOffset);
}
else
{
ProbeFreeListAllocator[RadianceCacheIndex] = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateBufferDesc(sizeof(int32), 1), TEXT("Lumen.RadianceCache.ProbeFreeListAllocator"));
ProbeFreeList[RadianceCacheIndex] = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateBufferDesc(sizeof(uint32), MaxNumProbes), TEXT("Lumen.RadianceCache.ProbeFreeList"));
ProbeLastUsedFrame[RadianceCacheIndex] = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateBufferDesc(sizeof(uint32), MaxNumProbes), TEXT("Lumen.RadianceCache.ProbeLastUsedFrame"));
ProbeLastTracedFrame[RadianceCacheIndex] = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateStructuredDesc(sizeof(uint32), MaxNumProbes), TEXT("Lumen.RadianceCache.ProbeLastTracedFrame"));
ProbeWorldOffset[RadianceCacheIndex] = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateStructuredDesc(sizeof(FVector4f), MaxNumProbes), TEXT("Lumen.RadianceCache.ProbeWorldOffset"));
}
FRDGBufferUAVRef ProbeFreeListAllocatorUAV = GraphBuilder.CreateUAV(FRDGBufferUAVDesc(ProbeFreeListAllocator[RadianceCacheIndex], PF_R32_SINT));
FRDGBufferUAVRef ProbeFreeListUAV = GraphBuilder.CreateUAV(FRDGBufferUAVDesc(ProbeFreeList[RadianceCacheIndex], PF_R32_UINT));
FRDGBufferUAVRef ProbeLastUsedFrameUAV = GraphBuilder.CreateUAV(FRDGBufferUAVDesc(ProbeLastUsedFrame[RadianceCacheIndex], PF_R32_UINT));
FRDGBufferUAVRef ProbeWorldOffsetUAV = GraphBuilder.CreateUAV(FRDGBufferUAVDesc(ProbeWorldOffset[RadianceCacheIndex], PF_A32B32G32R32F));
if (!Setup.bPersistentCache || !IsValidRef(RadianceCacheState.ProbeFreeListAllocator))
{
FClearProbeFreeList::FParameters* PassParameters = GraphBuilder.AllocParameters<FClearProbeFreeList::FParameters>();
PassParameters->RWProbeFreeListAllocator = ProbeFreeListAllocatorUAV;
PassParameters->RWProbeFreeList = ProbeFreeListUAV;
PassParameters->RWProbeLastUsedFrame = ProbeLastUsedFrameUAV;
PassParameters->RWProbeWorldOffset = ProbeWorldOffsetUAV;
PassParameters->MaxNumProbes = MaxNumProbes;
auto ComputeShader = View.ShaderMap->GetShader<FClearProbeFreeList>();
const FIntVector GroupSize = FComputeShaderUtils::GetGroupCount(MaxNumProbes, FClearProbeFreeList::GetGroupSize());
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("ClearProbeFreeList"),
ComputePassFlags,
ComputeShader,
PassParameters,
GroupSize);
}
}
TInlineArray<FRDGBufferRef> ProbeAllocator(InputArray.Num());
for (int32 RadianceCacheIndex = 0; RadianceCacheIndex < InputArray.Num(); RadianceCacheIndex++)
{
const FUpdateInputs& Inputs = InputArray[RadianceCacheIndex];
const FRadianceCacheInputs& RadianceCacheInputs = Inputs.RadianceCacheInputs;
const FViewInfo& View = Inputs.View;
const FRadianceCacheSetup& Setup = SetupOutputArray[RadianceCacheIndex];
FUpdateOutputs& Outputs = OutputArray[RadianceCacheIndex];
FRadianceCacheState& RadianceCacheState = Outputs.RadianceCacheState;
FRadianceCacheInterpolationParameters& RadianceCacheParameters = Outputs.RadianceCacheParameters;
if (IsValidRef(RadianceCacheState.ProbeAllocator))
{
ProbeAllocator[RadianceCacheIndex] = GraphBuilder.RegisterExternalBuffer(RadianceCacheState.ProbeAllocator, TEXT("Lumen.RadianceCache.ProbeAllocator"));
}
else
{
ProbeAllocator[RadianceCacheIndex] = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateBufferDesc(sizeof(uint32), 1), TEXT("Lumen.RadianceCache.ProbeAllocator"));
}
FRDGBufferUAVRef ProbeAllocatorUAV = GraphBuilder.CreateUAV(FRDGBufferUAVDesc(ProbeAllocator[RadianceCacheIndex], PF_R32_UINT));
if (!Setup.bPersistentCache || !IsValidRef(RadianceCacheState.ProbeAllocator))
{
AddClearUAVPass(GraphBuilder, ProbeAllocatorUAV, 0);
}
}
for (int32 RadianceCacheIndex = 0; RadianceCacheIndex < InputArray.Num(); RadianceCacheIndex++)
{
const FUpdateInputs& Inputs = InputArray[RadianceCacheIndex];
const FRadianceCacheInputs& RadianceCacheInputs = Inputs.RadianceCacheInputs;
const FViewInfo& View = Inputs.View;
const FRadianceCacheSetup& Setup = SetupOutputArray[RadianceCacheIndex];
FUpdateOutputs& Outputs = OutputArray[RadianceCacheIndex];
FRadianceCacheState& RadianceCacheState = Outputs.RadianceCacheState;
FRadianceCacheInterpolationParameters& RadianceCacheParameters = Outputs.RadianceCacheParameters;
const int32 MaxNumProbes = RadianceCacheInputs.ProbeAtlasResolutionInProbes.X * RadianceCacheInputs.ProbeAtlasResolutionInProbes.Y;
// Propagate probes from last frame to the new frame's indirection
if (Setup.bPersistentCache)
{
FRDGTextureUAVRef RadianceProbeIndirectionTextureUAV = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(RadianceCacheParameters.RadianceProbeIndirectionTexture));
FRDGTextureRef LastFrameRadianceProbeIndirectionTexture = GraphBuilder.RegisterExternalTexture(RadianceCacheState.RadianceProbeIndirectionTexture);
{
FRDGBufferUAVRef ProbeFreeListAllocatorUAV = GraphBuilder.CreateUAV(FRDGBufferUAVDesc(ProbeFreeListAllocator[RadianceCacheIndex], PF_R32_SINT));
FRDGBufferUAVRef ProbeFreeListUAV = GraphBuilder.CreateUAV(FRDGBufferUAVDesc(ProbeFreeList[RadianceCacheIndex], PF_R32_UINT));
FRDGBufferUAVRef ProbeLastUsedFrameUAV = GraphBuilder.CreateUAV(FRDGBufferUAVDesc(ProbeLastUsedFrame[RadianceCacheIndex], PF_R32_UINT));
FUpdateCacheForUsedProbesCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FUpdateCacheForUsedProbesCS::FParameters>();
PassParameters->View = View.ViewUniformBuffer;
PassParameters->RWRadianceProbeIndirectionTexture = RadianceProbeIndirectionTextureUAV;
PassParameters->ProbeAllocator = GraphBuilder.CreateSRV(ProbeAllocator[RadianceCacheIndex], PF_R32_UINT);
PassParameters->RWProbeFreeListAllocator = ProbeFreeListAllocatorUAV;
PassParameters->RWProbeFreeList = ProbeFreeListUAV;
PassParameters->RWProbeLastUsedFrame = ProbeLastUsedFrameUAV;
PassParameters->LastFrameRadianceProbeIndirectionTexture = LastFrameRadianceProbeIndirectionTexture;
PassParameters->RadianceCacheParameters = RadianceCacheParameters;
PassParameters->FrameNumber = View.ViewState->GetFrameIndex();
PassParameters->NumFramesToKeepCachedProbes = FMath::Max(CVarRadianceCacheNumFramesToKeepCachedProbes.GetValueOnRenderThread(), 0);
PassParameters->MaxNumProbes = MaxNumProbes;
for (int32 ClipmapIndex = 0; ClipmapIndex < Setup.LastFrameClipmaps.Num(); ++ClipmapIndex)
{
const FRadianceCacheClipmap& Clipmap = Setup.LastFrameClipmaps[ClipmapIndex];
PassParameters->LastFrameClipmapCornerTWSAndCellSize[ClipmapIndex] = FVector4f(Clipmap.CornerTranslatedWorldSpace, Clipmap.CellSize);
}
auto ComputeShader = View.ShaderMap->GetShader<FUpdateCacheForUsedProbesCS>(0);
const FIntVector GroupSize = FComputeShaderUtils::GetGroupCount(RadianceCacheParameters.RadianceProbeIndirectionTexture->Desc.GetSize(), FUpdateCacheForUsedProbesCS::GetGroupSize());
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("UpdateCacheForUsedProbes"),
ComputePassFlags,
ComputeShader,
PassParameters,
GroupSize);
}
}
}
TInlineArray<FRDGBufferRef> ProbeTraceData(InputArray.Num());
TInlineArray<FRDGBufferRef> ProbeTraceAllocator(InputArray.Num());
TInlineArray<FRDGBufferRef> PriorityHistogram(InputArray.Num());
TInlineArray<FRDGBufferRef> MaxUpdateBucket(InputArray.Num());
TInlineArray<FRDGBufferRef> MaxTracesFromMaxUpdateBucket(InputArray.Num());
TInlineArray<FRDGBufferRef> ProbesToUpdateTraceCost(InputArray.Num());
TInlineArray<FRDGBufferRef> MinNewProbeTraceCost(InputArray.Num());
for (int32 RadianceCacheIndex = 0; RadianceCacheIndex < InputArray.Num(); RadianceCacheIndex++)
{
const FUpdateInputs& Inputs = InputArray[RadianceCacheIndex];
const FRadianceCacheInputs& RadianceCacheInputs = Inputs.RadianceCacheInputs;
const FViewInfo& View = Inputs.View;
const FRadianceCacheSetup& Setup = SetupOutputArray[RadianceCacheIndex];
FUpdateOutputs& Outputs = OutputArray[RadianceCacheIndex];
FRadianceCacheState& RadianceCacheState = Outputs.RadianceCacheState;
FRadianceCacheInterpolationParameters& RadianceCacheParameters = Outputs.RadianceCacheParameters;
const int32 MaxNumProbes = RadianceCacheInputs.ProbeAtlasResolutionInProbes.X * RadianceCacheInputs.ProbeAtlasResolutionInProbes.Y;
ProbeTraceData[RadianceCacheIndex] = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateBufferDesc(sizeof(FVector4f), MaxNumProbes), TEXT("Lumen.RadianceCache.ProbeTraceData"));
ProbeTraceAllocator[RadianceCacheIndex] = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateBufferDesc(sizeof(uint32), 1), TEXT("Lumen.RadianceCache.ProbeTraceAllocator"));
FRDGBufferUAVRef ProbeTraceAllocatorUAV = GraphBuilder.CreateUAV(FRDGBufferUAVDesc(ProbeTraceAllocator[RadianceCacheIndex], PF_R32_UINT));
PriorityHistogram[RadianceCacheIndex] = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateStructuredDesc(sizeof(uint32), PRIORITY_HISTOGRAM_SIZE), TEXT("Lumen.RadianceCache.PriorityHistogram"));
MinNewProbeTraceCost[RadianceCacheIndex] = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateStructuredDesc(sizeof(uint32), 1), TEXT("Lumen.RadianceCache.MinNewProbeTraceCost"));
MaxUpdateBucket[RadianceCacheIndex] = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateStructuredDesc(sizeof(uint32), 1), TEXT("Lumen.RadianceCache.MaxUpdateBucket"));
MaxTracesFromMaxUpdateBucket[RadianceCacheIndex] = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateStructuredDesc(sizeof(uint32), 1), TEXT("Lumen.RadianceCache.MaxTracesFromMaxUpdateBucket"));
ProbesToUpdateTraceCost[RadianceCacheIndex] = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateStructuredDesc(sizeof(uint32), PROBES_TO_UPDATE_TRACE_COST_STRIDE), TEXT("Lumen.RadianceCache.ProbesToUpdateTraceCost"));
// Batch clear all resources required for the subsequent radiance cache probe update pass
{
FClearRadianceCacheUpdateResourcesCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FClearRadianceCacheUpdateResourcesCS::FParameters>();
PassParameters->RWProbeTraceAllocator = ProbeTraceAllocatorUAV;
PassParameters->RWPriorityHistogram = GraphBuilder.CreateUAV(PriorityHistogram[RadianceCacheIndex]);
PassParameters->RWMaxUpdateBucket = GraphBuilder.CreateUAV(MaxUpdateBucket[RadianceCacheIndex]);
PassParameters->RWMaxTracesFromMaxUpdateBucket = GraphBuilder.CreateUAV(MaxTracesFromMaxUpdateBucket[RadianceCacheIndex]);
PassParameters->RWProbesToUpdateTraceCost = GraphBuilder.CreateUAV(ProbesToUpdateTraceCost[RadianceCacheIndex]);
PassParameters->RWMinNewProbeTraceCost = GraphBuilder.CreateUAV(MinNewProbeTraceCost[RadianceCacheIndex]);
auto ComputeShader = View.ShaderMap->GetShader<FClearRadianceCacheUpdateResourcesCS>();
const FIntVector GroupSize(FMath::DivideAndRoundUp<int32>(PRIORITY_HISTOGRAM_SIZE, FClearRadianceCacheUpdateResourcesCS::GetGroupSize()), 1, 1);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("ClearRadianceCacheUpdateResources"),
ComputePassFlags,
ComputeShader,
PassParameters,
GroupSize);
}
}
for (int32 RadianceCacheIndex = 0; RadianceCacheIndex < InputArray.Num(); RadianceCacheIndex++)
{
const FUpdateInputs& Inputs = InputArray[RadianceCacheIndex];
const FRadianceCacheInputs& RadianceCacheInputs = Inputs.RadianceCacheInputs;
const FViewInfo& View = Inputs.View;
const FRadianceCacheSetup& Setup = SetupOutputArray[RadianceCacheIndex];
FUpdateOutputs& Outputs = OutputArray[RadianceCacheIndex];
FRadianceCacheState& RadianceCacheState = Outputs.RadianceCacheState;
FRadianceCacheInterpolationParameters& RadianceCacheParameters = Outputs.RadianceCacheParameters;
// Allocated used probes
{
FRDGBufferUAVRef ProbeFreeListAllocatorUAV = GraphBuilder.CreateUAV(FRDGBufferUAVDesc(ProbeFreeListAllocator[RadianceCacheIndex], PF_R32_SINT));
FRDGBufferUAVRef ProbeLastUsedFrameUAV = GraphBuilder.CreateUAV(FRDGBufferUAVDesc(ProbeLastUsedFrame[RadianceCacheIndex], PF_R32_UINT));
FRDGTextureUAVRef RadianceProbeIndirectionTextureUAV = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(RadianceCacheParameters.RadianceProbeIndirectionTexture));
FRDGBufferUAVRef ProbeAllocatorUAV = GraphBuilder.CreateUAV(FRDGBufferUAVDesc(ProbeAllocator[RadianceCacheIndex], PF_R32_UINT));
const int32 MaxNumProbes = RadianceCacheInputs.ProbeAtlasResolutionInProbes.X * RadianceCacheInputs.ProbeAtlasResolutionInProbes.Y;
FAllocateUsedProbesCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FAllocateUsedProbesCS::FParameters>();
PassParameters->RWRadianceProbeIndirectionTexture = RadianceProbeIndirectionTextureUAV;
PassParameters->RWPriorityHistogram = GraphBuilder.CreateUAV(PriorityHistogram[RadianceCacheIndex]);
PassParameters->RWMinNewProbeTraceCost = GraphBuilder.CreateUAV(MinNewProbeTraceCost[RadianceCacheIndex]);
PassParameters->RWProbeLastTracedFrame = GraphBuilder.CreateUAV(ProbeLastTracedFrame[RadianceCacheIndex]);
PassParameters->RWProbeLastUsedFrame = ProbeLastUsedFrameUAV;
PassParameters->RWProbeAllocator = ProbeAllocatorUAV;
PassParameters->RWProbeFreeListAllocator = Setup.bPersistentCache ? ProbeFreeListAllocatorUAV : nullptr;
PassParameters->View = View.ViewUniformBuffer;
PassParameters->ProbeFreeList = Setup.bPersistentCache ? GraphBuilder.CreateSRV(FRDGBufferSRVDesc(ProbeFreeList[RadianceCacheIndex], PF_R32_UINT)) : nullptr;
PassParameters->FirstClipmapWorldExtentRcp = 1.0f / FMath::Max(RadianceCacheInputs.ClipmapWorldExtent, 1.0f);
PassParameters->SupersampleDistanceFromCameraSq = GetSupersampleDistanceFromCameraSq();
PassParameters->DownsampleDistanceFromCameraSq = GLumenRadianceCacheDownsampleDistanceFromCamera * GLumenRadianceCacheDownsampleDistanceFromCamera;
PassParameters->FrameNumber = View.ViewState ? View.ViewState->GetFrameIndex() : View.Family->FrameNumber;
PassParameters->MaxNumProbes = MaxNumProbes;
PassParameters->RadianceCacheParameters = RadianceCacheParameters;
FAllocateUsedProbesCS::FPermutationDomain PermutationVector;
PermutationVector.Set<FAllocateUsedProbesCS::FPersistentCache>(Setup.bPersistentCache);
auto ComputeShader = View.ShaderMap->GetShader<FAllocateUsedProbesCS>(PermutationVector);
const FIntVector GroupSize = FComputeShaderUtils::GetGroupCount(RadianceCacheParameters.RadianceProbeIndirectionTexture->Desc.GetSize(), FAllocateUsedProbesCS::GetGroupSize());
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("AllocateUsedProbes"),
ComputePassFlags,
ComputeShader,
PassParameters,
GroupSize);
}
}
for (int32 RadianceCacheIndex = 0; RadianceCacheIndex < InputArray.Num(); RadianceCacheIndex++)
{
const FUpdateInputs& Inputs = InputArray[RadianceCacheIndex];
const FRadianceCacheInputs& RadianceCacheInputs = Inputs.RadianceCacheInputs;
const FViewInfo& View = Inputs.View;
const FRadianceCacheSetup& Setup = SetupOutputArray[RadianceCacheIndex];
FUpdateOutputs& Outputs = OutputArray[RadianceCacheIndex];
FRadianceCacheState& RadianceCacheState = Outputs.RadianceCacheState;
FRadianceCacheInterpolationParameters& RadianceCacheParameters = Outputs.RadianceCacheParameters;
// Selected max priority bucket
{
FSelectMaxPriorityBucketCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FSelectMaxPriorityBucketCS::FParameters>();
PassParameters->RWMaxUpdateBucket = GraphBuilder.CreateUAV(MaxUpdateBucket[RadianceCacheIndex]);
PassParameters->RWMaxTracesFromMaxUpdateBucket = GraphBuilder.CreateUAV(MaxTracesFromMaxUpdateBucket[RadianceCacheIndex]);
PassParameters->PriorityHistogram = GraphBuilder.CreateSRV(PriorityHistogram[RadianceCacheIndex]);
PassParameters->ProbeTraceAllocator = GraphBuilder.CreateSRV(ProbeTraceAllocator[RadianceCacheIndex], PF_R32_UINT);
const float TraceBudgetScale = bPropagateGlobalLightingChange ? 4.0f : 1.0f;
PassParameters->NumProbesToTraceBudget = GRadianceCacheForceFullUpdate ? UINT32_MAX : RadianceCacheInputs.NumProbesToTraceBudget * TraceBudgetScale;
auto ComputeShader = View.ShaderMap->GetShader<FSelectMaxPriorityBucketCS>();
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("SelectMaxPriorityBucket"),
ComputePassFlags,
ComputeShader,
PassParameters,
FIntVector(1, 1, 1));
}
}
for (int32 RadianceCacheIndex = 0; RadianceCacheIndex < InputArray.Num(); RadianceCacheIndex++)
{
const FUpdateInputs& Inputs = InputArray[RadianceCacheIndex];
const FRadianceCacheInputs& RadianceCacheInputs = Inputs.RadianceCacheInputs;
const FViewInfo& View = Inputs.View;
const FRadianceCacheSetup& Setup = SetupOutputArray[RadianceCacheIndex];
FUpdateOutputs& Outputs = OutputArray[RadianceCacheIndex];
FRadianceCacheState& RadianceCacheState = Outputs.RadianceCacheState;
FRadianceCacheInterpolationParameters& RadianceCacheParameters = Outputs.RadianceCacheParameters;
// Trace probes up to selected priority bucket
{
FRDGBufferUAVRef ProbeFreeListAllocatorUAV = GraphBuilder.CreateUAV(FRDGBufferUAVDesc(ProbeFreeListAllocator[RadianceCacheIndex], PF_R32_SINT));
FRDGTextureUAVRef RadianceProbeIndirectionTextureUAV = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(RadianceCacheParameters.RadianceProbeIndirectionTexture));
FRDGBufferUAVRef ProbeTraceAllocatorUAV = GraphBuilder.CreateUAV(FRDGBufferUAVDesc(ProbeTraceAllocator[RadianceCacheIndex], PF_R32_UINT));
const int32 MaxNumProbes = RadianceCacheInputs.ProbeAtlasResolutionInProbes.X * RadianceCacheInputs.ProbeAtlasResolutionInProbes.Y;
FAllocateProbeTracesCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FAllocateProbeTracesCS::FParameters>();
PassParameters->RWRadianceProbeIndirectionTexture = RadianceProbeIndirectionTextureUAV;
PassParameters->RWProbesToUpdateTraceCost = GraphBuilder.CreateUAV(ProbesToUpdateTraceCost[RadianceCacheIndex]);
PassParameters->RWMinNewProbeTraceCost = GraphBuilder.CreateUAV(MinNewProbeTraceCost[RadianceCacheIndex]);
PassParameters->RWProbeLastTracedFrame = GraphBuilder.CreateUAV(ProbeLastTracedFrame[RadianceCacheIndex]);
PassParameters->RWProbeTraceAllocator = ProbeTraceAllocatorUAV;
PassParameters->RWProbeTraceData = GraphBuilder.CreateUAV(FRDGBufferUAVDesc(ProbeTraceData[RadianceCacheIndex], PF_A32B32G32R32F));
PassParameters->RWProbeFreeListAllocator = Setup.bPersistentCache ? ProbeFreeListAllocatorUAV : nullptr;
PassParameters->MaxUpdateBucket = GraphBuilder.CreateSRV(MaxUpdateBucket[RadianceCacheIndex], PF_R32_UINT);
PassParameters->MaxTracesFromMaxUpdateBucket = GraphBuilder.CreateSRV(MaxTracesFromMaxUpdateBucket[RadianceCacheIndex]);
PassParameters->ProbeLastUsedFrame = GraphBuilder.CreateSRV(ProbeLastUsedFrame[RadianceCacheIndex], PF_R32_UINT);
PassParameters->View = View.ViewUniformBuffer;
PassParameters->ProbeFreeList = Setup.bPersistentCache ? GraphBuilder.CreateSRV(FRDGBufferSRVDesc(ProbeFreeList[RadianceCacheIndex], PF_R32_UINT)) : nullptr;
PassParameters->SupersampleDistanceFromCameraSq = GetSupersampleDistanceFromCameraSq();
PassParameters->DownsampleDistanceFromCameraSq = GLumenRadianceCacheDownsampleDistanceFromCamera * GLumenRadianceCacheDownsampleDistanceFromCamera;
PassParameters->FirstClipmapWorldExtentRcp = 1.0f / FMath::Max(RadianceCacheInputs.ClipmapWorldExtent, 1.0f);
PassParameters->FrameNumber = View.ViewState ? View.ViewState->GetFrameIndex() : View.Family->FrameNumber;
PassParameters->MaxNumProbes = MaxNumProbes;
PassParameters->RadianceCacheParameters = RadianceCacheParameters;
auto ComputeShader = View.ShaderMap->GetShader<FAllocateProbeTracesCS>();
const FIntVector GroupSize = FComputeShaderUtils::GetGroupCount(RadianceCacheParameters.RadianceProbeIndirectionTexture->Desc.GetSize(), FAllocateProbeTracesCS::GetGroupSize());
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("AllocateProbeTraces"),
ComputePassFlags,
ComputeShader,
PassParameters,
GroupSize);
}
}
TInlineArray<FRDGBufferRef> ClearProbePDFsIndirectArgs(InputArray.Num());
TInlineArray<FRDGBufferRef> GenerateProbeTraceTilesIndirectArgs(InputArray.Num());
TInlineArray<FRDGBufferRef> ProbeTraceTileAllocator(InputArray.Num());
TInlineArray<FRDGBufferRef> FilterProbesIndirectArgs(InputArray.Num());
TInlineArray<FRDGBufferRef> PrepareProbeOcclusionIndirectArgs(InputArray.Num());
TInlineArray<FRDGBufferRef> FixupProbeBordersIndirectArgs(InputArray.Num());
for (int32 RadianceCacheIndex = 0; RadianceCacheIndex < InputArray.Num(); RadianceCacheIndex++)
{
const FUpdateInputs& Inputs = InputArray[RadianceCacheIndex];
const FRadianceCacheInputs& RadianceCacheInputs = Inputs.RadianceCacheInputs;
const FViewInfo& View = Inputs.View;
const FRadianceCacheSetup& Setup = SetupOutputArray[RadianceCacheIndex];
FUpdateOutputs& Outputs = OutputArray[RadianceCacheIndex];
FRadianceCacheState& RadianceCacheState = Outputs.RadianceCacheState;
FRadianceCacheInterpolationParameters& RadianceCacheParameters = Outputs.RadianceCacheParameters;
ClearProbePDFsIndirectArgs[RadianceCacheIndex] = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateIndirectDesc<FRHIDispatchIndirectParameters>(2), TEXT("Lumen.RadianceCache.ClearProbePDFsIndirectArgs"));
GenerateProbeTraceTilesIndirectArgs[RadianceCacheIndex] = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateIndirectDesc<FRHIDispatchIndirectParameters>(3), TEXT("Lumen.RadianceCache.GenerateProbeTraceTilesIndirectArgs"));
ProbeTraceTileAllocator[RadianceCacheIndex] = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateBufferDesc(sizeof(uint32), 1), TEXT("Lumen.RadianceCache.ProbeTraceTileAllocator"));
FilterProbesIndirectArgs[RadianceCacheIndex] = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateIndirectDesc<FRHIDispatchIndirectParameters>(5), TEXT("Lumen.RadianceCache.FilterProbesIndirectArgs"));
PrepareProbeOcclusionIndirectArgs[RadianceCacheIndex] = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateIndirectDesc<FRHIDispatchIndirectParameters>(7), TEXT("Lumen.RadianceCache.PrepareProbeOcclusionIndirectArgs"));
FixupProbeBordersIndirectArgs[RadianceCacheIndex] = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateIndirectDesc<FRHIDispatchIndirectParameters>(8), TEXT("Lumen.RadianceCache.FixupProbeBordersIndirectArgs"));
{
FRDGBufferUAVRef ProbeFreeListAllocatorUAV = GraphBuilder.CreateUAV(FRDGBufferUAVDesc(ProbeFreeListAllocator[RadianceCacheIndex], PF_R32_SINT));
FRDGBufferUAVRef ProbeAllocatorUAV = GraphBuilder.CreateUAV(FRDGBufferUAVDesc(ProbeAllocator[RadianceCacheIndex], PF_R32_UINT));
const int32 MaxNumProbes = RadianceCacheInputs.ProbeAtlasResolutionInProbes.X * RadianceCacheInputs.ProbeAtlasResolutionInProbes.Y;
FSetupProbeIndirectArgsCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FSetupProbeIndirectArgsCS::FParameters>();
PassParameters->RWProbeAllocator = ProbeAllocatorUAV;
PassParameters->RWProbeFreeListAllocator = ProbeFreeListAllocatorUAV;
PassParameters->RWClearProbePDFsIndirectArgs = GraphBuilder.CreateUAV(FRDGBufferUAVDesc(ClearProbePDFsIndirectArgs[RadianceCacheIndex], PF_R32_UINT));
PassParameters->RWGenerateProbeTraceTilesIndirectArgs = GraphBuilder.CreateUAV(FRDGBufferUAVDesc(GenerateProbeTraceTilesIndirectArgs[RadianceCacheIndex], PF_R32_UINT));
PassParameters->RWProbeTraceTileAllocator = GraphBuilder.CreateUAV(FRDGBufferUAVDesc(ProbeTraceTileAllocator[RadianceCacheIndex], PF_R32_UINT));
PassParameters->RWFilterProbesIndirectArgs = GraphBuilder.CreateUAV(FRDGBufferUAVDesc(FilterProbesIndirectArgs[RadianceCacheIndex], PF_R32_UINT));
PassParameters->RWPrepareProbeOcclusionIndirectArgs = GraphBuilder.CreateUAV(FRDGBufferUAVDesc(PrepareProbeOcclusionIndirectArgs[RadianceCacheIndex], PF_R32_UINT));
PassParameters->RWFixupProbeBordersIndirectArgs = GraphBuilder.CreateUAV(FRDGBufferUAVDesc(FixupProbeBordersIndirectArgs[RadianceCacheIndex], PF_R32_UINT));
PassParameters->ProbeTraceAllocator = GraphBuilder.CreateSRV(FRDGBufferSRVDesc(ProbeTraceAllocator[RadianceCacheIndex], PF_R32_UINT));
PassParameters->TraceFromProbesGroupSizeXY = FRadianceCacheTraceFromProbesCS::GetGroupSize();
PassParameters->FilterProbesGroupSizeXY = FFilterProbeRadianceWithGatherCS::GetGroupSize();
PassParameters->ClearProbePDFGroupSize = FClearProbePDFs::GetGroupSize();
PassParameters->MaxNumProbes = MaxNumProbes;
PassParameters->RadianceCacheParameters = RadianceCacheParameters;
auto ComputeShader = View.ShaderMap->GetShader<FSetupProbeIndirectArgsCS>(0);
const FIntVector GroupSize = FIntVector(1);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("SetupProbeIndirectArgsCS"),
ComputePassFlags,
ComputeShader,
PassParameters,
GroupSize);
}
}
for (int32 RadianceCacheIndex = 0; RadianceCacheIndex < InputArray.Num(); RadianceCacheIndex++)
{
const FUpdateInputs& Inputs = InputArray[RadianceCacheIndex];
const FRadianceCacheInputs& RadianceCacheInputs = Inputs.RadianceCacheInputs;
const FViewInfo& View = Inputs.View;
const FRadianceCacheSetup& Setup = SetupOutputArray[RadianceCacheIndex];
FUpdateOutputs& Outputs = OutputArray[RadianceCacheIndex];
FRadianceCacheState& RadianceCacheState = Outputs.RadianceCacheState;
FRadianceCacheInterpolationParameters& RadianceCacheParameters = Outputs.RadianceCacheParameters;
if (RadianceCacheInputs.CalculateIrradiance)
{
FRDGBufferUAVRef ProbeWorldOffsetUAV = GraphBuilder.CreateUAV(FRDGBufferUAVDesc(ProbeWorldOffset[RadianceCacheIndex], PF_A32B32G32R32F));
FComputeProbeWorldOffsetsCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FComputeProbeWorldOffsetsCS::FParameters>();
PassParameters->RWProbeWorldOffset = ProbeWorldOffsetUAV;
PassParameters->View = View.ViewUniformBuffer;
PassParameters->ProbeTraceData = GraphBuilder.CreateSRV(FRDGBufferSRVDesc(ProbeTraceData[RadianceCacheIndex], PF_A32B32G32R32F));
PassParameters->RadianceCacheParameters = RadianceCacheParameters;
PassParameters->IndirectArgs = GenerateProbeTraceTilesIndirectArgs[RadianceCacheIndex];
auto ComputeShader = View.ShaderMap->GetShader<FComputeProbeWorldOffsetsCS>();
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("ComputeProbeWorldOffsets"),
ComputePassFlags,
ComputeShader,
PassParameters,
PassParameters->IndirectArgs,
0);
}
RadianceCacheParameters.ProbeWorldOffset = GraphBuilder.CreateSRV(FRDGBufferSRVDesc(ProbeWorldOffset[RadianceCacheIndex], PF_A32B32G32R32F));
}
TInlineArray<FRDGBufferRef> RadianceProbeSH_PDF(InputArray.Num());
for (int32 RadianceCacheIndex = 0; RadianceCacheIndex < InputArray.Num(); RadianceCacheIndex++)
{
const FUpdateInputs& Inputs = InputArray[RadianceCacheIndex];
const FRadianceCacheInputs& RadianceCacheInputs = Inputs.RadianceCacheInputs;
const FViewInfo& View = Inputs.View;
const FRadianceCacheSetup& Setup = SetupOutputArray[RadianceCacheIndex];
FUpdateOutputs& Outputs = OutputArray[RadianceCacheIndex];
FRadianceCacheState& RadianceCacheState = Outputs.RadianceCacheState;
FRadianceCacheInterpolationParameters& RadianceCacheParameters = Outputs.RadianceCacheParameters;
const bool bGenerateBRDF_PDF = ShouldImportanceSampleBRDF(Inputs);
if (bGenerateBRDF_PDF)
{
const int32 MaxNumProbes = RadianceCacheInputs.ProbeAtlasResolutionInProbes.X * RadianceCacheInputs.ProbeAtlasResolutionInProbes.Y;
RadianceProbeSH_PDF[RadianceCacheIndex] = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateBufferDesc(sizeof(int32), MaxNumProbes * (9 + 1)), TEXT("Lumen.RadianceCache.RadianceProbeSH_PDF"));
{
FClearProbePDFs::FParameters* PassParameters = GraphBuilder.AllocParameters<FClearProbePDFs::FParameters>();
PassParameters->RWRadianceProbeSH_PDF = GraphBuilder.CreateUAV(FRDGBufferUAVDesc(RadianceProbeSH_PDF[RadianceCacheIndex], PF_R32_SINT));
PassParameters->ClearProbePDFsIndirectArgs = ClearProbePDFsIndirectArgs[RadianceCacheIndex];
PassParameters->ProbeTraceData = GraphBuilder.CreateSRV(FRDGBufferSRVDesc(ProbeTraceData[RadianceCacheIndex], PF_A32B32G32R32F));
auto ComputeShader = View.ShaderMap->GetShader<FClearProbePDFs>(0);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("ClearProbePDFs"),
ComputePassFlags,
ComputeShader,
PassParameters,
PassParameters->ClearProbePDFsIndirectArgs,
0);
}
}
}
for (int32 RadianceCacheIndex = 0; RadianceCacheIndex < InputArray.Num(); RadianceCacheIndex++)
{
const FUpdateInputs& Inputs = InputArray[RadianceCacheIndex];
const FRadianceCacheInputs& RadianceCacheInputs = Inputs.RadianceCacheInputs;
const FViewInfo& View = Inputs.View;
const FRadianceCacheSetup& Setup = SetupOutputArray[RadianceCacheIndex];
FUpdateOutputs& Outputs = OutputArray[RadianceCacheIndex];
FRadianceCacheState& RadianceCacheState = Outputs.RadianceCacheState;
FRadianceCacheInterpolationParameters& RadianceCacheParameters = Outputs.RadianceCacheParameters;
if (RadianceProbeSH_PDF[RadianceCacheIndex])
{
FScatterScreenProbeBRDFToRadianceProbesCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FScatterScreenProbeBRDFToRadianceProbesCS::FParameters>();
PassParameters->RWRadianceProbeSH_PDF = GraphBuilder.CreateUAV(FRDGBufferUAVDesc(RadianceProbeSH_PDF[RadianceCacheIndex], PF_R32_SINT));
PassParameters->BRDFProbabilityDensityFunctionSH = Inputs.BRDFProbabilityDensityFunctionSH;
PassParameters->View = View.ViewUniformBuffer;
PassParameters->ScreenProbeParameters = *Inputs.ScreenProbeParameters;
PassParameters->RadianceCacheParameters = RadianceCacheParameters;
auto ComputeShader = View.ShaderMap->GetShader<FScatterScreenProbeBRDFToRadianceProbesCS>(0);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("ScatterScreenProbeBRDFToRadianceProbes"),
ComputePassFlags,
ComputeShader,
PassParameters,
Inputs.ScreenProbeParameters->ProbeIndirectArgs,
(uint32)EScreenProbeIndirectArgs::GroupPerProbe * sizeof(FRHIDispatchIndirectParameters));
}
}
TInlineArray<FRDGBufferRef> ProbeTraceTileData(InputArray.Num());
for (int32 RadianceCacheIndex = 0; RadianceCacheIndex < InputArray.Num(); RadianceCacheIndex++)
{
const FUpdateInputs& Inputs = InputArray[RadianceCacheIndex];
const FRadianceCacheInputs& RadianceCacheInputs = Inputs.RadianceCacheInputs;
const FViewInfo& View = Inputs.View;
const FRadianceCacheSetup& Setup = SetupOutputArray[RadianceCacheIndex];
FUpdateOutputs& Outputs = OutputArray[RadianceCacheIndex];
FRadianceCacheState& RadianceCacheState = Outputs.RadianceCacheState;
FRadianceCacheInterpolationParameters& RadianceCacheParameters = Outputs.RadianceCacheParameters;
const int32 MaxNumProbes = RadianceCacheInputs.ProbeAtlasResolutionInProbes.X * RadianceCacheInputs.ProbeAtlasResolutionInProbes.Y;
const int32 MaxProbeTraceTileResolution = RadianceCacheInputs.RadianceProbeResolution / FRadianceCacheTraceFromProbesCS::GetGroupSize() * 2;
ProbeTraceTileData[RadianceCacheIndex] = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateBufferDesc(sizeof(FIntPoint), MaxNumProbes * MaxProbeTraceTileResolution * MaxProbeTraceTileResolution), TEXT("Lumen.RadianceCache.ProbeTraceTileData"));
const int32 DebugProbeBRDFOctahedronResolution = 8;
FRDGTextureDesc DebugBRDFProbabilityDensityFunctionDesc = FRDGTextureDesc::Create2D(
FIntPoint(RadianceCacheInputs.ProbeAtlasResolutionInProbes * DebugProbeBRDFOctahedronResolution),
PF_R16F,
FClearValueBinding::None,
TexCreate_ShaderResource | TexCreate_UAV);
FRDGTextureRef DebugBRDFProbabilityDensityFunction = GraphBuilder.CreateTexture(DebugBRDFProbabilityDensityFunctionDesc, TEXT("Lumen.RadianceCache.DebugBRDFProbabilityDensityFunction"));
{
FGenerateProbeTraceTilesCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FGenerateProbeTraceTilesCS::FParameters>();
PassParameters->RWProbeTraceTileAllocator = GraphBuilder.CreateUAV(FRDGBufferUAVDesc(ProbeTraceTileAllocator[RadianceCacheIndex], PF_R32_UINT));
PassParameters->RWProbeTraceTileData = GraphBuilder.CreateUAV(FRDGBufferUAVDesc(ProbeTraceTileData[RadianceCacheIndex], PF_R32G32_UINT));
PassParameters->ProbeTraceData = GraphBuilder.CreateSRV(FRDGBufferSRVDesc(ProbeTraceData[RadianceCacheIndex], PF_A32B32G32R32F));
PassParameters->RadianceProbeSH_PDF = RadianceProbeSH_PDF[RadianceCacheIndex] ? GraphBuilder.CreateSRV(FRDGBufferSRVDesc(RadianceProbeSH_PDF[RadianceCacheIndex], PF_R32_SINT)) : nullptr;
PassParameters->ProbesToUpdateTraceCost = GraphBuilder.CreateSRV(ProbesToUpdateTraceCost[RadianceCacheIndex]);
PassParameters->SupersampleTileBRDFThreshold = GLumenRadianceCacheSupersampleTileBRDFThreshold;
PassParameters->SupersampleDistanceFromCameraSq = LumenRadianceCache::GetSupersampleDistanceFromCameraSq();
PassParameters->DownsampleDistanceFromCameraSq = GLumenRadianceCacheDownsampleDistanceFromCamera * GLumenRadianceCacheDownsampleDistanceFromCamera;
PassParameters->ForcedUniformLevel = GLumenRadianceCacheForceUniformTraceTileLevel >= 0 ? FMath::Clamp<int32>(GLumenRadianceCacheForceUniformTraceTileLevel, 0, 2) : 1;
PassParameters->RWDebugBRDFProbabilityDensityFunction = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(DebugBRDFProbabilityDensityFunction));
PassParameters->DebugProbeBRDFOctahedronResolution = DebugProbeBRDFOctahedronResolution;
PassParameters->View = View.ViewUniformBuffer;
PassParameters->RadianceCacheParameters = RadianceCacheParameters;
PassParameters->GenerateProbeTraceTilesIndirectArgs = GenerateProbeTraceTilesIndirectArgs[RadianceCacheIndex];
FGenerateProbeTraceTilesCS::FPermutationDomain PermutationVector;
PermutationVector.Set<FGenerateProbeTraceTilesCS::FUniformTraces>(RadianceProbeSH_PDF[RadianceCacheIndex] == nullptr);
auto ComputeShader = View.ShaderMap->GetShader<FGenerateProbeTraceTilesCS>(PermutationVector);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("GenerateProbeTraceTiles"),
ComputePassFlags,
ComputeShader,
PassParameters,
PassParameters->GenerateProbeTraceTilesIndirectArgs,
0);
}
}
TInlineArray<FRDGBufferRef> TraceProbesIndirectArgs(InputArray.Num());
TInlineArray<FRDGBufferRef> SortProbeTraceTilesIndirectArgs(InputArray.Num());
TInlineArray<FRDGBufferRef> RadianceCacheHardwareRayTracingIndirectArgs(InputArray.Num());
TInlineArray<FRDGBufferRef> HardwareRayTracingRayAllocatorBuffer(InputArray.Num());
for (int32 RadianceCacheIndex = 0; RadianceCacheIndex < InputArray.Num(); RadianceCacheIndex++)
{
const FUpdateInputs& Inputs = InputArray[RadianceCacheIndex];
const FRadianceCacheInputs& RadianceCacheInputs = Inputs.RadianceCacheInputs;
const FViewInfo& View = Inputs.View;
const FRadianceCacheSetup& Setup = SetupOutputArray[RadianceCacheIndex];
FUpdateOutputs& Outputs = OutputArray[RadianceCacheIndex];
FRadianceCacheState& RadianceCacheState = Outputs.RadianceCacheState;
FRadianceCacheInterpolationParameters& RadianceCacheParameters = Outputs.RadianceCacheParameters;
TraceProbesIndirectArgs[RadianceCacheIndex] = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateIndirectDesc<FRHIDispatchIndirectParameters>(4), TEXT("Lumen.RadianceCache.TraceProbesIndirectArgs"));
SortProbeTraceTilesIndirectArgs[RadianceCacheIndex] = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateIndirectDesc<FRHIDispatchIndirectParameters>(5), TEXT("Lumen.RadianceCache.SortProbeTraceTilesIndirectArgs"));
RadianceCacheHardwareRayTracingIndirectArgs[RadianceCacheIndex] = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateIndirectDesc<FRHIDispatchIndirectParameters>(6), TEXT("Lumen.RadianceCache.RadianceCacheHardwareRayTracingIndirectArgs"));
HardwareRayTracingRayAllocatorBuffer[RadianceCacheIndex] = GraphBuilder.CreateBuffer(FRDGBufferDesc::CreateBufferDesc(sizeof(uint32), 1), TEXT("Lumen.RadianceCache.HardwareRayTracing.RayAllocatorBuffer"));
{
FSetupTraceFromProbesCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FSetupTraceFromProbesCS::FParameters>();
PassParameters->RWTraceProbesIndirectArgs = GraphBuilder.CreateUAV(FRDGBufferUAVDesc(TraceProbesIndirectArgs[RadianceCacheIndex], PF_R32_UINT));
PassParameters->RWSortProbeTraceTilesIndirectArgs = GraphBuilder.CreateUAV(FRDGBufferUAVDesc(SortProbeTraceTilesIndirectArgs[RadianceCacheIndex], PF_R32_UINT));
PassParameters->RWRadianceCacheHardwareRayTracingIndirectArgs = GraphBuilder.CreateUAV(FRDGBufferUAVDesc(RadianceCacheHardwareRayTracingIndirectArgs[RadianceCacheIndex], PF_R32_UINT));
PassParameters->RWHardwareRayTracingRayAllocatorBuffer = GraphBuilder.CreateUAV(FRDGBufferUAVDesc(HardwareRayTracingRayAllocatorBuffer[RadianceCacheIndex], PF_R32_UINT));
PassParameters->ProbeTraceTileAllocator = GraphBuilder.CreateSRV(FRDGBufferSRVDesc(ProbeTraceTileAllocator[RadianceCacheIndex], PF_R32_UINT));
PassParameters->SortTraceTilesGroupSize = FSortProbeTraceTilesCS::GetGroupSize();
auto ComputeShader = View.ShaderMap->GetShader<FSetupTraceFromProbesCS>(0);
const FIntVector GroupSize = FIntVector(1);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("SetupTraceFromProbesCS"),
ComputePassFlags,
ComputeShader,
PassParameters,
GroupSize);
}
}
for (int32 RadianceCacheIndex = 0; RadianceCacheIndex < InputArray.Num(); RadianceCacheIndex++)
{
const FUpdateInputs& Inputs = InputArray[RadianceCacheIndex];
const FRadianceCacheInputs& RadianceCacheInputs = Inputs.RadianceCacheInputs;
const FViewInfo& View = Inputs.View;
const FRadianceCacheSetup& Setup = SetupOutputArray[RadianceCacheIndex];
FUpdateOutputs& Outputs = OutputArray[RadianceCacheIndex];
FRadianceCacheState& RadianceCacheState = Outputs.RadianceCacheState;
FRadianceCacheInterpolationParameters& RadianceCacheParameters = Outputs.RadianceCacheParameters;
if (GRadianceCacheSortTraceTiles)
{
FRDGBufferRef SortedProbeTraceTileData = GraphBuilder.CreateBuffer(ProbeTraceTileData[RadianceCacheIndex]->Desc, TEXT("Lumen.RadianceCache.SortedProbeTraceTileData"));
FSortProbeTraceTilesCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FSortProbeTraceTilesCS::FParameters>();
PassParameters->RWProbeTraceTileData = GraphBuilder.CreateUAV(FRDGBufferUAVDesc(SortedProbeTraceTileData, PF_R32G32_UINT));
PassParameters->ProbeTraceData = GraphBuilder.CreateSRV(FRDGBufferSRVDesc(ProbeTraceData[RadianceCacheIndex], PF_A32B32G32R32F));
PassParameters->ProbeTraceTileData = GraphBuilder.CreateSRV(FRDGBufferSRVDesc(ProbeTraceTileData[RadianceCacheIndex], PF_R32G32_UINT));
PassParameters->ProbeTraceTileAllocator = GraphBuilder.CreateSRV(FRDGBufferSRVDesc(ProbeTraceTileAllocator[RadianceCacheIndex], PF_R32_UINT));
PassParameters->SortProbeTraceTilesIndirectArgs = SortProbeTraceTilesIndirectArgs[RadianceCacheIndex];
PassParameters->RadianceCacheInputs = RadianceCacheInputs;
auto ComputeShader = View.ShaderMap->GetShader<FSortProbeTraceTilesCS>();
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("SortTraceTiles"),
ComputePassFlags,
ComputeShader,
PassParameters,
PassParameters->SortProbeTraceTilesIndirectArgs,
0);
ProbeTraceTileData[RadianceCacheIndex] = SortedProbeTraceTileData;
}
}
if (Lumen::UseHardwareRayTracedRadianceCache(ViewFamily))
{
RenderLumenHardwareRayTracingRadianceCache(
GraphBuilder,
Scene,
FrameTemporaries,
InputArray,
OutputArray,
SetupOutputArray,
ProbeTraceTileAllocator,
ProbeTraceTileData,
ProbeTraceData,
HardwareRayTracingRayAllocatorBuffer,
TraceProbesIndirectArgs,
ComputePassFlags);
}
else
{
for (int32 RadianceCacheIndex = 0; RadianceCacheIndex < InputArray.Num(); RadianceCacheIndex++)
{
const FUpdateInputs& Inputs = InputArray[RadianceCacheIndex];
const FRadianceCacheInputs& RadianceCacheInputs = Inputs.RadianceCacheInputs;
const FViewInfo& View = Inputs.View;
const FRadianceCacheSetup& Setup = SetupOutputArray[RadianceCacheIndex];
FLumenCardTracingParameters TracingParameters;
GetLumenCardTracingParameters(GraphBuilder, View, *Scene->GetLumenSceneData(View), FrameTemporaries, /*bSurfaceCacheFeedback*/ false, TracingParameters);
FUpdateOutputs& Outputs = OutputArray[RadianceCacheIndex];
FRadianceCacheInterpolationParameters& RadianceCacheParameters = Outputs.RadianceCacheParameters;
FRDGTextureUAVRef RadianceProbeAtlasTextureUAV = GraphBuilder.CreateUAV(Setup.RadianceProbeAtlasTextureSource);
FRDGTextureUAVRef SkyVisibilityProbeAtlasTextureUAV = Setup.SkyVisibilityProbeAtlasTextureSource ? GraphBuilder.CreateUAV(Setup.SkyVisibilityProbeAtlasTextureSource) : nullptr;
FRDGTextureUAVRef DepthProbeTextureUAV = GraphBuilder.CreateUAV(Setup.DepthProbeAtlasTexture);
FRadianceCacheTraceFromProbesCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FRadianceCacheTraceFromProbesCS::FParameters>();
PassParameters->TracingParameters = TracingParameters;
SetupLumenDiffuseTracingParametersForProbe(View, PassParameters->IndirectTracingParameters, -1.0f);
PassParameters->RWRadianceProbeAtlasTexture = RadianceProbeAtlasTextureUAV;
PassParameters->RWSkyVisibilityProbeAtlasTexture = SkyVisibilityProbeAtlasTextureUAV;
PassParameters->RWDepthProbeAtlasTexture = DepthProbeTextureUAV;
PassParameters->ProbeTraceData = GraphBuilder.CreateSRV(FRDGBufferSRVDesc(ProbeTraceData[RadianceCacheIndex], PF_A32B32G32R32F));
PassParameters->ProbeTraceTileData = GraphBuilder.CreateSRV(FRDGBufferSRVDesc(ProbeTraceTileData[RadianceCacheIndex], PF_R32G32_UINT));
PassParameters->ProbeTraceTileAllocator = GraphBuilder.CreateSRV(FRDGBufferSRVDesc(ProbeTraceTileAllocator[RadianceCacheIndex], PF_R32_UINT));
PassParameters->RadianceCacheParameters = RadianceCacheParameters;
PassParameters->TraceProbesIndirectArgs = TraceProbesIndirectArgs[RadianceCacheIndex];
FRadianceCacheTraceFromProbesCS::FPermutationDomain PermutationVector;
PermutationVector.Set<FRadianceCacheTraceFromProbesCS::FTraceGlobalSDF>(Lumen::UseGlobalSDFTracing(View.Family->EngineShowFlags));
PermutationVector.Set<FRadianceCacheTraceFromProbesCS::FSimpleCoverageBasedExpand>(Lumen::UseGlobalSDFTracing(View.Family->EngineShowFlags) && Lumen::UseGlobalSDFSimpleCoverageBasedExpand());
PermutationVector.Set<FRadianceCacheTraceFromProbesCS::FDynamicSkyLight>(Lumen::ShouldHandleSkyLight(Scene, *View.Family));
PermutationVector.Set<FRadianceCacheTraceFromProbesCS::FRadianceCacheSkyVisibility>(Inputs.Configuration.bSkyVisibility);
auto ComputeShader = View.ShaderMap->GetShader<FRadianceCacheTraceFromProbesCS>(PermutationVector);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("TraceFromProbes Res=%ux%u SkyVisibility:%d", RadianceCacheInputs.RadianceProbeResolution, RadianceCacheInputs.RadianceProbeResolution, Inputs.Configuration.bSkyVisibility),
ComputePassFlags,
ComputeShader,
PassParameters,
PassParameters->TraceProbesIndirectArgs,
0);
}
}
TInlineArray<FRDGTextureRef> RadianceProbeAtlasTexture(InputArray.Num());
TInlineArray<FRDGTextureRef> SkyVisibilityProbeAtlasTexture(InputArray.Num());
for (int32 RadianceCacheIndex = 0; RadianceCacheIndex < InputArray.Num(); RadianceCacheIndex++)
{
const FUpdateInputs& Inputs = InputArray[RadianceCacheIndex];
const FRadianceCacheInputs& RadianceCacheInputs = Inputs.RadianceCacheInputs;
const FViewInfo& View = Inputs.View;
const FRadianceCacheSetup& Setup = SetupOutputArray[RadianceCacheIndex];
FUpdateOutputs& Outputs = OutputArray[RadianceCacheIndex];
FRadianceCacheState& RadianceCacheState = Outputs.RadianceCacheState;
FRadianceCacheInterpolationParameters& RadianceCacheParameters = Outputs.RadianceCacheParameters;
RadianceProbeAtlasTexture[RadianceCacheIndex] = Setup.RadianceProbeAtlasTextureSource;
SkyVisibilityProbeAtlasTexture[RadianceCacheIndex] = Setup.SkyVisibilityProbeAtlasTextureSource;
if (GRadianceCacheFilterProbes)
{
FRDGTextureRef FilteredRadianceProbeAtlasTexture = GraphBuilder.CreateTexture(RadianceProbeAtlasTexture[RadianceCacheIndex]->Desc, TEXT("Lumen.RadianceCache.FilteredRadianceProbeAtlasTexture"));
FRDGTextureRef FilteredSkyVisibilityProbeAtlasTexture = Inputs.Configuration.bSkyVisibility ? GraphBuilder.CreateTexture(RadianceProbeAtlasTexture[RadianceCacheIndex]->Desc, TEXT("Lumen.RadianceCache.FilteredSkyVisibilityProbeAtlasTexture")) : nullptr;
{
FFilterProbeRadianceWithGatherCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FFilterProbeRadianceWithGatherCS::FParameters>();
PassParameters->RWRadianceProbeAtlasTexture = GraphBuilder.CreateUAV(FilteredRadianceProbeAtlasTexture);
PassParameters->RWSkyVisibilityProbeAtlasTexture = FilteredSkyVisibilityProbeAtlasTexture ? GraphBuilder.CreateUAV(FilteredSkyVisibilityProbeAtlasTexture) : nullptr;
PassParameters->RadianceProbeAtlasTexture = RadianceProbeAtlasTexture[RadianceCacheIndex];
PassParameters->SkyVisibilityProbeAtlasTexture = SkyVisibilityProbeAtlasTexture[RadianceCacheIndex];
PassParameters->DepthProbeAtlasTexture = Setup.DepthProbeAtlasTexture;
PassParameters->ProbeTraceData = GraphBuilder.CreateSRV(FRDGBufferSRVDesc(ProbeTraceData[RadianceCacheIndex], PF_A32B32G32R32F));
PassParameters->View = View.ViewUniformBuffer;
PassParameters->RadianceCacheParameters = RadianceCacheParameters;
PassParameters->FilterProbesIndirectArgs = FilterProbesIndirectArgs[RadianceCacheIndex];
PassParameters->SpatialFilterMaxRadianceHitAngle = GLumenRadianceCacheFilterMaxRadianceHitAngle;
FFilterProbeRadianceWithGatherCS::FPermutationDomain PermutationVector;
PermutationVector.Set<FFilterProbeRadianceWithGatherCS::FRadianceCacheSkyVisibility>(Inputs.Configuration.bSkyVisibility);
auto ComputeShader = View.ShaderMap->GetShader<FFilterProbeRadianceWithGatherCS>(PermutationVector);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("FilterProbeRadiance Res=%ux%u", RadianceCacheInputs.RadianceProbeResolution, RadianceCacheInputs.RadianceProbeResolution),
ComputePassFlags,
ComputeShader,
PassParameters,
PassParameters->FilterProbesIndirectArgs,
0);
}
RadianceProbeAtlasTexture[RadianceCacheIndex] = FilteredRadianceProbeAtlasTexture;
SkyVisibilityProbeAtlasTexture[RadianceCacheIndex] = FilteredSkyVisibilityProbeAtlasTexture;
}
}
for (int32 RadianceCacheIndex = 0; RadianceCacheIndex < InputArray.Num(); RadianceCacheIndex++)
{
const FUpdateInputs& Inputs = InputArray[RadianceCacheIndex];
const FRadianceCacheInputs& RadianceCacheInputs = Inputs.RadianceCacheInputs;
const FViewInfo& View = Inputs.View;
const FRadianceCacheSetup& Setup = SetupOutputArray[RadianceCacheIndex];
FUpdateOutputs& Outputs = OutputArray[RadianceCacheIndex];
FRadianceCacheState& RadianceCacheState = Outputs.RadianceCacheState;
FRadianceCacheInterpolationParameters& RadianceCacheParameters = Outputs.RadianceCacheParameters;
if (RadianceCacheInputs.CalculateIrradiance)
{
{
FCalculateProbeIrradianceCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FCalculateProbeIrradianceCS::FParameters>();
PassParameters->RWFinalIrradianceAtlas = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(Setup.FinalIrradianceAtlas));
PassParameters->RadianceProbeAtlasTexture = RadianceProbeAtlasTexture[RadianceCacheIndex];
PassParameters->ProbeTraceData = GraphBuilder.CreateSRV(FRDGBufferSRVDesc(ProbeTraceData[RadianceCacheIndex], PF_A32B32G32R32F));
PassParameters->RadianceCacheParameters = RadianceCacheParameters;
PassParameters->View = View.ViewUniformBuffer;
// GenerateProbeTraceTilesIndirectArgs is the same so we can reuse it
PassParameters->CalculateProbeIrradianceIndirectArgs = GenerateProbeTraceTilesIndirectArgs[RadianceCacheIndex];
auto ComputeShader = View.ShaderMap->GetShader<FCalculateProbeIrradianceCS>();
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("CalculateProbeIrradiance Res=%ux%u", RadianceCacheInputs.IrradianceProbeResolution, RadianceCacheInputs.IrradianceProbeResolution),
ComputePassFlags,
ComputeShader,
PassParameters,
GenerateProbeTraceTilesIndirectArgs[RadianceCacheIndex],
0);
}
RadianceCacheParameters.RadianceCacheFinalIrradianceAtlas = Setup.FinalIrradianceAtlas;
{
FPrepareProbeOcclusionCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FPrepareProbeOcclusionCS::FParameters>();
PassParameters->RWRadianceCacheProbeOcclusionAtlas = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(Setup.ProbeOcclusionAtlas));
PassParameters->DepthProbeAtlasTexture = Setup.DepthProbeAtlasTexture;
PassParameters->ProbeTraceData = GraphBuilder.CreateSRV(FRDGBufferSRVDesc(ProbeTraceData[RadianceCacheIndex], PF_A32B32G32R32F));
PassParameters->RadianceCacheParameters = RadianceCacheParameters;
PassParameters->PrepareProbeOcclusionIndirectArgs = PrepareProbeOcclusionIndirectArgs[RadianceCacheIndex];
auto ComputeShader = View.ShaderMap->GetShader<FPrepareProbeOcclusionCS>();
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("PrepareProbeOcclusion Res=%ux%u", RadianceCacheInputs.OcclusionProbeResolution, RadianceCacheInputs.OcclusionProbeResolution),
ComputePassFlags,
ComputeShader,
PassParameters,
PrepareProbeOcclusionIndirectArgs[RadianceCacheIndex],
0);
}
RadianceCacheParameters.RadianceCacheProbeOcclusionAtlas = Setup.ProbeOcclusionAtlas;
}
else
{
const bool bGenerateMips = RadianceCacheInputs.FinalRadianceAtlasMaxMip > 0;
ensureMsgf(RadianceCacheInputs.FinalRadianceAtlasMaxMip <= 2, TEXT("Requested mip is more than supported by shader"));
{
FFixupBordersAndGenerateMipsCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FFixupBordersAndGenerateMipsCS::FParameters>();
PassParameters->RWFinalRadianceAtlasMip0 = GraphBuilder.CreateUAV(Setup.FinalRadianceAtlas);
PassParameters->RWFinalSkyVisibilityAtlasMip0 = Setup.FinalSkyVisibilityAtlas ? GraphBuilder.CreateUAV(Setup.FinalSkyVisibilityAtlas) : nullptr;
if (bGenerateMips)
{
PassParameters->RWFinalRadianceAtlasMip1 = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(Setup.FinalRadianceAtlas, 1));
PassParameters->RWFinalRadianceAtlasMip2 = PassParameters->RWFinalRadianceAtlasMip1;
if (RadianceCacheInputs.FinalRadianceAtlasMaxMip > 1)
{
PassParameters->RWFinalRadianceAtlasMip2 = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(Setup.FinalRadianceAtlas, 2));
}
}
PassParameters->RadianceProbeAtlasTexture = RadianceProbeAtlasTexture[RadianceCacheIndex];
PassParameters->SkyVisibilityProbeAtlasTexture = SkyVisibilityProbeAtlasTexture[RadianceCacheIndex];
PassParameters->ProbeTraceData = GraphBuilder.CreateSRV(FRDGBufferSRVDesc(ProbeTraceData[RadianceCacheIndex], PF_A32B32G32R32F));
PassParameters->RadianceCacheParameters = RadianceCacheParameters;
PassParameters->FixupProbeBordersIndirectArgs = FixupProbeBordersIndirectArgs[RadianceCacheIndex];
FFixupBordersAndGenerateMipsCS::FPermutationDomain PermutationVector;
PermutationVector.Set<FFixupBordersAndGenerateMipsCS::FGenerateMips>(bGenerateMips);
PermutationVector.Set<FFixupBordersAndGenerateMipsCS::FRadianceCacheSkyVisibility>(Inputs.Configuration.bSkyVisibility);
auto ComputeShader = View.ShaderMap->GetShader<FFixupBordersAndGenerateMipsCS>(PermutationVector);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("FixupBordersAndGenerateMips"),
ComputePassFlags,
ComputeShader,
PassParameters,
FixupProbeBordersIndirectArgs[RadianceCacheIndex],
0);
}
RadianceCacheParameters.RadianceCacheFinalRadianceAtlas = Setup.FinalRadianceAtlas;
RadianceCacheParameters.RadianceCacheFinalSkyVisibilityAtlas = Setup.FinalSkyVisibilityAtlas ? Setup.FinalSkyVisibilityAtlas : nullptr;
}
if (RadianceCacheInputs.RadianceCacheStats != 0)
{
ShaderPrint::SetEnabled(true);
const int32 MaxNumProbes = RadianceCacheInputs.ProbeAtlasResolutionInProbes.X * RadianceCacheInputs.ProbeAtlasResolutionInProbes.Y;
FRadianceCacheUpdateStatsCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FRadianceCacheUpdateStatsCS::FParameters>();
ShaderPrint::SetParameters(GraphBuilder, View.ShaderPrintData, PassParameters->ShaderPrintUniformBuffer);
PassParameters->View = View.ViewUniformBuffer;
PassParameters->PriorityHistogram = GraphBuilder.CreateSRV(PriorityHistogram[RadianceCacheIndex]);
PassParameters->MaxUpdateBucket = GraphBuilder.CreateSRV(MaxUpdateBucket[RadianceCacheIndex]);
PassParameters->MaxTracesFromMaxUpdateBucket = GraphBuilder.CreateSRV(MaxTracesFromMaxUpdateBucket[RadianceCacheIndex]);
PassParameters->ProbesToUpdateTraceCost = GraphBuilder.CreateSRV(ProbesToUpdateTraceCost[RadianceCacheIndex]);
PassParameters->MinNewProbeTraceCost = GraphBuilder.CreateSRV(MinNewProbeTraceCost[RadianceCacheIndex]);
PassParameters->ProbeTraceAllocator = GraphBuilder.CreateSRV(ProbeTraceAllocator[RadianceCacheIndex], PF_R32_UINT);
PassParameters->ProbeTraceTileAllocator = GraphBuilder.CreateSRV(ProbeTraceTileAllocator[RadianceCacheIndex], PF_R32_UINT);
PassParameters->ProbeAllocator = GraphBuilder.CreateSRV(ProbeAllocator[RadianceCacheIndex], PF_R32_UINT);
PassParameters->ProbeFreeListAllocator = GraphBuilder.CreateSRV(ProbeFreeListAllocator[RadianceCacheIndex], PF_R32_UINT);
PassParameters->NumProbesToTraceBudget = RadianceCacheInputs.NumProbesToTraceBudget;
PassParameters->MaxNumProbes = MaxNumProbes;
auto ComputeShader = View.ShaderMap->GetShader<FRadianceCacheUpdateStatsCS>();
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("RadianceCacheUpdateStats"),
ComputeShader,
PassParameters,
FIntVector(1, 1, 1));
}
RadianceCacheState.ProbeFreeListAllocator = GraphBuilder.ConvertToExternalBuffer(ProbeFreeListAllocator[RadianceCacheIndex]);
RadianceCacheState.ProbeFreeList = GraphBuilder.ConvertToExternalBuffer(ProbeFreeList[RadianceCacheIndex]);
RadianceCacheState.ProbeAllocator = GraphBuilder.ConvertToExternalBuffer(ProbeAllocator[RadianceCacheIndex]);
RadianceCacheState.ProbeLastUsedFrame = GraphBuilder.ConvertToExternalBuffer(ProbeLastUsedFrame[RadianceCacheIndex]);
RadianceCacheState.ProbeLastTracedFrame = GraphBuilder.ConvertToExternalBuffer(ProbeLastTracedFrame[RadianceCacheIndex]);
RadianceCacheState.ProbeWorldOffset = GraphBuilder.ConvertToExternalBuffer(ProbeWorldOffset[RadianceCacheIndex]);
RadianceCacheState.RadianceProbeIndirectionTexture = GraphBuilder.ConvertToExternalTexture(RadianceCacheParameters.RadianceProbeIndirectionTexture);
RadianceCacheState.DepthProbeAtlasTexture = GraphBuilder.ConvertToExternalTexture(Setup.DepthProbeAtlasTexture);
RadianceCacheState.RadianceProbeAtlasTexture = GraphBuilder.ConvertToExternalTexture(Setup.RadianceProbeAtlasTextureSource);
if (Setup.SkyVisibilityProbeAtlasTextureSource)
{
RadianceCacheState.SkyVisibilityProbeAtlasTexture = GraphBuilder.ConvertToExternalTexture(Setup.SkyVisibilityProbeAtlasTextureSource);
}
else
{
RadianceCacheState.SkyVisibilityProbeAtlasTexture = nullptr;
}
if (Setup.FinalRadianceAtlas)
{
RadianceCacheState.FinalRadianceAtlas = GraphBuilder.ConvertToExternalTexture(Setup.FinalRadianceAtlas);
}
else
{
RadianceCacheState.FinalRadianceAtlas = nullptr;
}
if (Setup.FinalSkyVisibilityAtlas)
{
RadianceCacheState.FinalSkyVisibilityAtlas = GraphBuilder.ConvertToExternalTexture(Setup.FinalSkyVisibilityAtlas);
}
else
{
RadianceCacheState.FinalSkyVisibilityAtlas = nullptr;
}
if (Setup.FinalIrradianceAtlas)
{
RadianceCacheState.FinalIrradianceAtlas = GraphBuilder.ConvertToExternalTexture(Setup.FinalIrradianceAtlas);
RadianceCacheState.ProbeOcclusionAtlas = GraphBuilder.ConvertToExternalTexture(Setup.ProbeOcclusionAtlas);
}
else
{
RadianceCacheState.FinalIrradianceAtlas = nullptr;
RadianceCacheState.ProbeOcclusionAtlas = nullptr;
}
RadianceCacheParameters.RadianceCacheDepthAtlas = Setup.DepthProbeAtlasTexture;
}
}
else // GRadianceCacheUpdate != 0
{
for (int32 RadianceCacheIndex = 0; RadianceCacheIndex < InputArray.Num(); RadianceCacheIndex++)
{
const FUpdateInputs& Inputs = InputArray[RadianceCacheIndex];
FUpdateOutputs& Outputs = OutputArray[RadianceCacheIndex];
// Only update CornerTranslatedWorldSpace based on the current camera position, so that freezing updates works correctly
FRadianceCacheState& RadianceCacheState = Outputs.RadianceCacheState;
for (uint32 LevelIndex = 0; LevelIndex < Inputs.RadianceCacheInputs.NumRadianceProbeClipmaps; ++LevelIndex)
{
FRadianceCacheClipmap& Clipmap = RadianceCacheState.Clipmaps[LevelIndex];
Clipmap.CornerTranslatedWorldSpace = (FVector3f)(Clipmap.CornerWorldSpace + Inputs.View.ViewMatrices.GetPreViewTranslation());
}
GetInterpolationParameters(Inputs.View, GraphBuilder, Outputs.RadianceCacheState, Inputs.RadianceCacheInputs, Outputs.RadianceCacheParameters);
}
}
}
}