2468 lines
121 KiB
C++
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
} |