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

1316 lines
67 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "LumenReSTIRGather.h"
#include "LumenScreenProbeGather.h"
#include "BasePassRendering.h"
#include "Lumen/LumenRadianceCache.h"
#include "RendererPrivate.h"
#include "ScenePrivate.h"
#include "SceneUtils.h"
#include "PipelineStateCache.h"
#include "ShaderParameterStruct.h"
#include "PixelShaderUtils.h"
#include "ReflectionEnvironment.h"
#include "DistanceFieldAmbientOcclusion.h"
#include "ScreenSpaceDenoise.h"
#include "HairStrands/HairStrandsEnvironment.h"
#include "ShaderPrint.h"
#include "Substrate/Substrate.h"
#include "LumenReflections.h"
#include "DepthCopy.h"
#if RHI_RAYTRACING
#include "RayTracing/RaytracingOptions.h"
#include "RayTracing/RayTracingLighting.h"
#include "LumenHardwareRayTracingCommon.h"
#endif
static TAutoConsoleVariable<int32> CVarLumenReSTIRGather(
TEXT("r.Lumen.ReSTIRGather"),
0,
TEXT("Whether to use the prototype ReSTIR Final Gather. Disabled by default, as quality is currently much lower than LumenScreenProbeGather, and fewer features supported."),
ECVF_Scalability | ECVF_RenderThreadSafe
);
int32 GLumenReSTIRDownsampleFactor = 2;
FAutoConsoleVariableRef CVarLumenReSTIRDownsampleFactor(
TEXT("r.Lumen.ReSTIRGather.DownsampleFactor"),
GLumenReSTIRDownsampleFactor,
TEXT("Downsample factor from the main viewport to trace rays, create and resample reservoirs at. This is the main performance control for the tracing / resampling part of the algorithm."),
ECVF_Scalability | ECVF_RenderThreadSafe
);
int32 GLumenReSTIRGatherFixedJitterIndex = -1;
FAutoConsoleVariableRef CVarLumenReSTIRGatherFixedJitterIndex(
TEXT("r.Lumen.ReSTIRGather.FixedJitterIndex"),
GLumenReSTIRGatherFixedJitterIndex,
TEXT("When 0 or larger, overrides the frame index with a constant for debugging"),
ECVF_RenderThreadSafe
);
int32 GLumenReSTIRTemporalResampling = 1;
FAutoConsoleVariableRef CVarLumenReSTIRTemporalResampling(
TEXT("r.Lumen.ReSTIRGather.TemporalResampling"),
GLumenReSTIRTemporalResampling,
TEXT("Whether to do a temporal resampling pass on the reservoirs"),
ECVF_Scalability | ECVF_RenderThreadSafe
);
int32 GLumenReSTIRValidateTemporalReservoirsEveryNFrames = 0;
FAutoConsoleVariableRef CVarLumenReSTIRTemporalResamplingValidate(
TEXT("r.Lumen.ReSTIRGather.TemporalResampling.ValidateEveryNFrames"),
GLumenReSTIRValidateTemporalReservoirsEveryNFrames,
TEXT("Validate temporal reservoirs by re-tracing their rays and comparing hit positions and radiance every N frames. Used to reduce lag in lighting changes, but introduces noise."),
ECVF_Scalability | ECVF_RenderThreadSafe
);
float GLumenReSTIRTemporalResamplingHistoryDistanceThreshold = .005f;
FAutoConsoleVariableRef CVarReSTIRTemporalResamplingHistoryDistanceThreshold(
TEXT("r.Lumen.ReSTIRGather.TemporalResampling.DistanceThreshold"),
GLumenReSTIRTemporalResamplingHistoryDistanceThreshold,
TEXT(""),
ECVF_Scalability | ECVF_RenderThreadSafe
);
int32 GLumenReSTIRTemporalResamplingResetHistory = 0;
FAutoConsoleVariableRef CVarLumenReSTIRTemporalResamplingResetHistory(
TEXT("r.Lumen.ReSTIRGather.TemporalResampling.ResetHistory"),
GLumenReSTIRTemporalResamplingResetHistory,
TEXT(""),
ECVF_Scalability | ECVF_RenderThreadSafe
);
int32 GLumenReSTIRSpatialResampling = 1;
FAutoConsoleVariableRef CVarLumenReSTIRSpatialResampling(
TEXT("r.Lumen.ReSTIRGather.SpatialResampling"),
GLumenReSTIRSpatialResampling,
TEXT("Whether to use spatial resampling passes on the reservoirs"),
ECVF_Scalability | ECVF_RenderThreadSafe
);
int32 GLumenReSTIRNumSpatialResamplingPasses = 2;
FAutoConsoleVariableRef CVarLumenNumSpatialResamplingPasses(
TEXT("r.Lumen.ReSTIRGather.SpatialResampling.NumPasses"),
GLumenReSTIRNumSpatialResamplingPasses,
TEXT("The number of spatial resampling passes to do"),
ECVF_Scalability | ECVF_RenderThreadSafe
);
int32 GLumenReSTIRNumSpatialSamples = 4;
FAutoConsoleVariableRef CVarLumenReSTIRNumSpatialSamples(
TEXT("r.Lumen.ReSTIRGather.SpatialResampling.NumSamples"),
GLumenReSTIRNumSpatialSamples,
TEXT("The number of spatial samples for each resampling pass."),
ECVF_Scalability | ECVF_RenderThreadSafe
);
float GLumenReSTIRSpatialResamplingKernelRadius = .05f;
FAutoConsoleVariableRef CVarLumenReSTIRSpatialResamplingKernelRadius(
TEXT("r.Lumen.ReSTIRGather.SpatialResampling.KernelRadius"),
GLumenReSTIRSpatialResamplingKernelRadius,
TEXT("Radius of the spatial resampling kernel as a fraction of the screen."),
ECVF_Scalability | ECVF_RenderThreadSafe
);
float GLumenReSTIRResamplingAngleThreshold = 25.0f;
FAutoConsoleVariableRef CVarLumenReSTIRResamplingAngleThreshold(
TEXT("r.Lumen.ReSTIRGather.ResamplingAngleThreshold"),
GLumenReSTIRResamplingAngleThreshold,
TEXT("Largest angle between two reservoirs that will be allowed during reservoir resampling, in degrees"),
ECVF_Scalability | ECVF_RenderThreadSafe
);
float GLumenReSTIRResamplingDepthErrorThreshold = .01f;
FAutoConsoleVariableRef CVarLumenReSTIRSpatialResamplingDepthErrorThreshold(
TEXT("r.Lumen.ReSTIRGather.ResamplingDepthErrorThreshold"),
GLumenReSTIRResamplingDepthErrorThreshold,
TEXT("Largest depth error between two reservoirs that will be allowed during reservoir resampling"),
ECVF_Scalability | ECVF_RenderThreadSafe
);
float GLumenReSTIRSpatialResamplingOcclusionScreenTraceDistance = .2f;
FAutoConsoleVariableRef CVarLumenReSTIRSpatialResamplingOcclusionScreenTraceDistance(
TEXT("r.Lumen.ReSTIRGather.SpatialResampling.OcclusionScreenTraceDistance"),
GLumenReSTIRSpatialResamplingOcclusionScreenTraceDistance,
TEXT("Length of occlusion screen traces used to validate the neighbor's reservoir hit position before reuse, to reduce leaking. As a fraction of the screen size."),
ECVF_Scalability | ECVF_RenderThreadSafe
);
float GLumenReSTIRMaxRayIntensity = 100;
FAutoConsoleVariableRef CVarLumenReSTIRMaxRayIntensity(
TEXT("r.Lumen.ReSTIRGather.MaxRayIntensity"),
GLumenReSTIRMaxRayIntensity,
TEXT("Clamps the maximum ray lighting intensity (with PreExposure) to reduce fireflies."),
ECVF_Scalability | ECVF_RenderThreadSafe
);
int32 GLumenReSTIRUpsampleMethod = 1;
FAutoConsoleVariableRef CVarLumenReSTIRUpsampleMethod(
TEXT("r.Lumen.ReSTIRGather.Upsample.Method"),
GLumenReSTIRUpsampleMethod,
TEXT("Upsample method, when calculating full resolution irradiance from downsampled reservoir radiance\n")
TEXT("0 - Jittered bilinear sample, when jittered position lies in the same plane, and fallback to unjittered when all samples fail\n")
TEXT("1 - Spiral sample pattern\n")
TEXT("2 - Passthrough for debugging. Also effectively disables the bilateral filter as variance is not computed."),
ECVF_Scalability | ECVF_RenderThreadSafe
);
float GLumenReSTIRUpsampleKernelSize = 3.0f;
FAutoConsoleVariableRef CVarLumenReSTIRUpsampleKernelSize(
TEXT("r.Lumen.ReSTIRGather.Upsample.KernelSize"),
GLumenReSTIRUpsampleKernelSize,
TEXT("Upsample kernel size, in reservoir texels"),
ECVF_Scalability | ECVF_RenderThreadSafe
);
int32 GLumenReSTIRUpsampleNumSamples = 16;
FAutoConsoleVariableRef CVarLumenReSTIRNumSamples(
TEXT("r.Lumen.ReSTIRGather.Upsample.NumSamples"),
GLumenReSTIRUpsampleNumSamples,
TEXT("Number of reservoir samples to take while upsampling. Only used when r.Lumen.ReSTIRGather.Upsample.Method is set to Spiral Pattern."),
ECVF_Scalability | ECVF_RenderThreadSafe
);
int32 GLumenReSTIRGatherTemporalFilter = 1;
FAutoConsoleVariableRef CVarLumenReSTIRGatherTemporalFilter(
TEXT("r.Lumen.ReSTIRGather.Temporal"),
GLumenReSTIRGatherTemporalFilter,
TEXT("Whether to use a temporal filter"),
ECVF_Scalability | ECVF_RenderThreadSafe
);
int32 GLumenReSTIRGatherClearHistoryEveryFrame = 0;
FAutoConsoleVariableRef CVarLumenReSTIRGatherClearHistoryEveryFrame(
TEXT("r.Lumen.ReSTIRGather.Temporal.ClearHistoryEveryFrame"),
GLumenReSTIRGatherClearHistoryEveryFrame,
TEXT("Whether to clear the history every frame for debugging"),
ECVF_RenderThreadSafe
);
float GLumenReSTIRGatherHistoryDistanceThreshold = .005f;
FAutoConsoleVariableRef CVarLumenReSTIRGatherHistoryDistanceThreshold(
TEXT("r.Lumen.ReSTIRGather.Temporal.DistanceThreshold"),
GLumenReSTIRGatherHistoryDistanceThreshold,
TEXT("Relative distance threshold needed to discard last frame's lighting results. Lower values reduce ghosting from characters when near a wall but increase flickering artifacts."),
ECVF_Scalability | ECVF_RenderThreadSafe
);
float GLumenReSTIRGatherTemporalMaxFramesAccumulated = 10.0f;
FAutoConsoleVariableRef CVarLumenReSTIRGatherTemporalMaxFramesAccumulated(
TEXT("r.Lumen.ReSTIRGather.Temporal.MaxFramesAccumulated"),
GLumenReSTIRGatherTemporalMaxFramesAccumulated,
TEXT("Lower values cause the temporal filter to propagate lighting changes faster, but also increase flickering from noise."),
ECVF_Scalability | ECVF_RenderThreadSafe
);
int32 GLumenReSTIRGatherBilateralFilter = 1;
FAutoConsoleVariableRef CVarLumenReSTIRGatherBilateralFilter(
TEXT("r.Lumen.ReSTIRGather.BilateralFilter"),
GLumenReSTIRGatherBilateralFilter,
TEXT("Whether to do a bilateral filter as a last step in denoising Lumen ReSTIRGathers."),
ECVF_Scalability | ECVF_RenderThreadSafe
);
float GLumenReSTIRGatherBilateralFilterSpatialKernelRadius = .002f;
FAutoConsoleVariableRef CVarLumenReSTIRGatherBilateralFilterSpatialKernelRadius(
TEXT("r.Lumen.ReSTIRGather.BilateralFilter.SpatialKernelRadius"),
GLumenReSTIRGatherBilateralFilterSpatialKernelRadius,
TEXT("Spatial kernel radius, as a fraction of the viewport size"),
ECVF_Scalability | ECVF_RenderThreadSafe
);
int32 GLumenReSTIRGatherBilateralFilterNumSamples = 8;
FAutoConsoleVariableRef CVarLumenReSTIRGatherBilateralFilterNumSamples(
TEXT("r.Lumen.ReSTIRGather.BilateralFilter.NumSamples"),
GLumenReSTIRGatherBilateralFilterNumSamples,
TEXT("Number of bilateral filter samples."),
ECVF_Scalability | ECVF_RenderThreadSafe
);
float GLumenReSTIRGatherBilateralFilterDepthWeightScale = 10000.0f;
FAutoConsoleVariableRef CVarLumenReSTIRGatherBilateralFilterDepthWeightScale(
TEXT("r.Lumen.ReSTIRGather.BilateralFilter.DepthWeightScale"),
GLumenReSTIRGatherBilateralFilterDepthWeightScale,
TEXT("Scales the depth weight of the bilateral filter"),
ECVF_Scalability | ECVF_RenderThreadSafe
);
float GLumenReSTIRGatherBilateralFilterNormalAngleThresholdScale = .2f;
FAutoConsoleVariableRef CVarLumenReSTIRGatherBilateralFilterNormalAngleThresholdScale(
TEXT("r.Lumen.ReSTIRGather.BilateralFilter.NormalAngleThresholdScale"),
GLumenReSTIRGatherBilateralFilterNormalAngleThresholdScale,
TEXT("Scales the Normal angle threshold of the bilateral filter"),
ECVF_Scalability | ECVF_RenderThreadSafe
);
float GLumenReSTIRGatherBilateralFilterStrongBlurVarianceThreshold = .5f;
FAutoConsoleVariableRef CVarLumenReSTIRGatherBilateralFilterStrongBlurVarianceThreshold(
TEXT("r.Lumen.ReSTIRGather.BilateralFilter.StrongBlurVarianceThreshold"),
GLumenReSTIRGatherBilateralFilterStrongBlurVarianceThreshold,
TEXT("Pixels whose variance from the spatial resolve filter are higher than this value get a stronger bilateral blur."),
ECVF_Scalability | ECVF_RenderThreadSafe
);
int32 GLumenReSTIRGatherShortRangeAmbientOcclusion = 1;
FAutoConsoleVariableRef GVarLumenReSTIRGatherShortRangeAO(
TEXT("r.Lumen.ReSTIRGather.ShortRangeAO"),
GLumenReSTIRGatherShortRangeAmbientOcclusion,
TEXT("Whether to compute a short range, full resolution AO to add high frequency occlusion (contact shadows) which ReSTIR GI lacks due to spatial filtering."),
ECVF_Scalability | ECVF_RenderThreadSafe
);
float GLumenReSTIRGatherShortRangeAOMaxScreenTraceFraction = .02f;
FAutoConsoleVariableRef CVarLumenReSTIRGatherShortRangeAOMaxScreenTraceFraction(
TEXT("r.Lumen.ReSTIRGather.ShortRangeAO.MaxScreenTraceFraction"),
GLumenReSTIRGatherShortRangeAOMaxScreenTraceFraction,
TEXT("Short range AO tracing distance, as a fraction of the screen size."),
ECVF_Scalability | ECVF_RenderThreadSafe
);
namespace LumenReSTIRGather
{
int32 GetScreenDownsampleFactor(const FViewInfo& View)
{
return FMath::Clamp(GLumenReSTIRDownsampleFactor, 1, 8);
}
}
bool DoesPlatformSupportLumenReSTIRGather(EShaderPlatform Platform)
{
// Prototype feature, don't want to spend time fixing other platforms until it matters
return Platform == SP_PCD3D_SM6 && DoesPlatformSupportLumenGI(Platform);
}
namespace Lumen
{
bool UseReSTIRGather(const FSceneViewFamily& ViewFamily, EShaderPlatform ShaderPlatform)
{
#if RHI_RAYTRACING
return IsRayTracingEnabled()
&& Lumen::UseHardwareRayTracing(ViewFamily)
&& (CVarLumenReSTIRGather.GetValueOnAnyThread() != 0)
&& DoesPlatformSupportLumenReSTIRGather(ShaderPlatform);
#else
return false;
#endif
}
} // namespace Lumen
#if RHI_RAYTRACING
class FLumenValidateReservoirs : public FLumenHardwareRayTracingShaderBase
{
DECLARE_LUMEN_RAYTRACING_SHADER(FLumenValidateReservoirs)
class FHitLighting : SHADER_PERMUTATION_BOOL("HIT_LIGHTING");
using FPermutationDomain = TShaderPermutationDomain<FLumenHardwareRayTracingShaderBase::FBasePermutationDomain, FHitLighting>;
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_INCLUDE(FLumenHardwareRayTracingShaderBase::FSharedParameters, SharedParameters)
SHADER_PARAMETER_STRUCT_INCLUDE(FReSTIRParameters, ReSTIRParameters)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<float3>, RWTemporalReservoirTraceRadiance)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<float3>, RWTemporalReservoirWeights)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, TemporalReservoirRayDirection)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, TemporalReservoirTraceHitDistance)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, TemporalReservoirTraceHitNormal)
SHADER_PARAMETER(FVector4f, HistoryScreenPositionScaleBias)
SHADER_PARAMETER(FIntPoint, HistoryReservoirViewSize)
SHADER_PARAMETER(float, PrevSceneColorPreExposureCorrection)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, DownsampledDepthHistory)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, DownsampledNormalHistory)
SHADER_PARAMETER(float, PullbackBias)
SHADER_PARAMETER(int32, ApplySkyLight)
SHADER_PARAMETER(float, MaxTraceDistance)
SHADER_PARAMETER(float, MaxRayIntensity)
END_SHADER_PARAMETER_STRUCT()
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, Lumen::ERayTracingShaderDispatchType ShaderDispatchType, FShaderCompilerEnvironment& OutEnvironment)
{
FLumenHardwareRayTracingShaderBase::ModifyCompilationEnvironment(Parameters, ShaderDispatchType, Lumen::ESurfaceCacheSampling::HighResPages, OutEnvironment);
}
static ERayTracingPayloadType GetRayTracingPayloadType(const int32 PermutationId)
{
FPermutationDomain PermutationVector(PermutationId);
if (PermutationVector.Get<FHitLighting>())
{
return ERayTracingPayloadType::RayTracingMaterial;
}
else
{
return ERayTracingPayloadType::LumenMinimal;
}
}
};
IMPLEMENT_LUMEN_RAYGEN_AND_COMPUTE_RAYTRACING_SHADERS(FLumenValidateReservoirs)
IMPLEMENT_GLOBAL_SHADER(FLumenValidateReservoirsRGS, "/Engine/Private/Lumen/LumenReSTIRGather.usf", "LumenValidateReservoirsRGS", SF_RayGen);
class FLumenInitialSampling : public FLumenHardwareRayTracingShaderBase
{
DECLARE_LUMEN_RAYTRACING_SHADER(FLumenInitialSampling)
class FHitLighting : SHADER_PERMUTATION_BOOL("HIT_LIGHTING");
using FPermutationDomain = TShaderPermutationDomain<FLumenHardwareRayTracingShaderBase::FBasePermutationDomain, FHitLighting>;
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_INCLUDE(FLumenHardwareRayTracingShaderBase::FSharedParameters, SharedParameters)
SHADER_PARAMETER_STRUCT_INCLUDE(FReSTIRParameters, ReSTIRParameters)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<float>, RWDownsampledSceneDepth)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<UNORM float3>, RWDownsampledWorldNormal)
SHADER_PARAMETER(float, PullbackBias)
SHADER_PARAMETER(int32, ApplySkyLight)
SHADER_PARAMETER(float, MaxTraceDistance)
SHADER_PARAMETER(float, MaxRayIntensity)
END_SHADER_PARAMETER_STRUCT()
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, Lumen::ERayTracingShaderDispatchType ShaderDispatchType, FShaderCompilerEnvironment& OutEnvironment)
{
FLumenHardwareRayTracingShaderBase::ModifyCompilationEnvironment(Parameters, ShaderDispatchType, Lumen::ESurfaceCacheSampling::HighResPages, OutEnvironment);
}
static ERayTracingPayloadType GetRayTracingPayloadType(const int32 PermutationId)
{
FPermutationDomain PermutationVector(PermutationId);
if (PermutationVector.Get<FHitLighting>())
{
return ERayTracingPayloadType::RayTracingMaterial;
}
else
{
return ERayTracingPayloadType::LumenMinimal;
}
}
};
IMPLEMENT_LUMEN_RAYGEN_AND_COMPUTE_RAYTRACING_SHADERS(FLumenInitialSampling)
IMPLEMENT_GLOBAL_SHADER(FLumenInitialSamplingRGS, "/Engine/Private/Lumen/LumenReSTIRGather.usf", "LumenInitialSamplingRGS", SF_RayGen);
void FDeferredShadingSceneRenderer::PrepareLumenHardwareRayTracingReSTIRLumenMaterial(const FViewInfo& View, TArray<FRHIRayTracingShader*>& OutRayGenShaders)
{
if (Lumen::UseReSTIRGather(*View.Family, ShaderPlatform))
{
{
FLumenValidateReservoirsRGS::FPermutationDomain PermutationVector;
PermutationVector.Set<FLumenValidateReservoirsRGS::FHitLighting>(false);
TShaderRef<FLumenValidateReservoirsRGS> RayGenerationShader = View.ShaderMap->GetShader<FLumenValidateReservoirsRGS>(PermutationVector);
OutRayGenShaders.Add(RayGenerationShader.GetRayTracingShader());
}
{
FLumenInitialSamplingRGS::FPermutationDomain PermutationVector;
PermutationVector.Set<FLumenInitialSamplingRGS::FHitLighting>(false);
TShaderRef<FLumenInitialSamplingRGS> RayGenerationShader = View.ShaderMap->GetShader<FLumenInitialSamplingRGS>(PermutationVector);
OutRayGenShaders.Add(RayGenerationShader.GetRayTracingShader());
}
}
}
void FDeferredShadingSceneRenderer::PrepareLumenHardwareRayTracingReSTIR(const FViewInfo& View, TArray<FRHIRayTracingShader*>& OutRayGenShaders)
{
if (Lumen::UseReSTIRGather(*View.Family, ShaderPlatform))
{
const bool bUseHitLighting = LumenReflections::UseHitLighting(View, GetViewPipelineState(View).DiffuseIndirectMethod);
if (bUseHitLighting)
{
{
FLumenValidateReservoirsRGS::FPermutationDomain PermutationVector;
PermutationVector.Set<FLumenValidateReservoirsRGS::FHitLighting>(true);
TShaderRef<FLumenValidateReservoirsRGS> RayGenerationShader = View.ShaderMap->GetShader<FLumenValidateReservoirsRGS>(PermutationVector);
OutRayGenShaders.Add(RayGenerationShader.GetRayTracingShader());
}
{
FLumenInitialSamplingRGS::FPermutationDomain PermutationVector;
PermutationVector.Set<FLumenInitialSamplingRGS::FHitLighting>(true);
TShaderRef<FLumenInitialSamplingRGS> RayGenerationShader = View.ShaderMap->GetShader<FLumenInitialSamplingRGS>(PermutationVector);
OutRayGenShaders.Add(RayGenerationShader.GetRayTracingShader());
}
}
}
}
#endif
class FTemporalResamplingCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FTemporalResamplingCS)
SHADER_USE_PARAMETER_STRUCT(FTemporalResamplingCS, FGlobalShader)
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<float4>, RWTemporalReservoirRayDirection)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<float3>, RWTemporalReservoirTraceRadiance)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<float>, RWTemporalReservoirTraceHitDistance)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<UNORM float3>, RWTemporalReservoirTraceHitNormal)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<float3>, RWTemporalReservoirWeights)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, TemporalReservoirRayDirection)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, TemporalReservoirTraceRadiance)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, TemporalReservoirTraceHitDistance)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, TemporalReservoirTraceHitNormal)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, TemporalReservoirWeights)
SHADER_PARAMETER_STRUCT_INCLUDE(FReSTIRParameters, ReSTIRParameters)
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, View)
SHADER_PARAMETER_RDG_UNIFORM_BUFFER(FSceneTextureUniformParameters, SceneTexturesStruct)
SHADER_PARAMETER_STRUCT_INCLUDE(FSceneTextureParameters, SceneTextures)
SHADER_PARAMETER(FVector4f, HistoryScreenPositionScaleBias)
SHADER_PARAMETER(FVector4f, HistoryUVMinMax)
SHADER_PARAMETER(FIntPoint, HistoryReservoirViewSize)
SHADER_PARAMETER(float, PrevSceneColorPreExposureCorrection)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, DownsampledDepthHistory)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, DownsampledNormalHistory)
SHADER_PARAMETER(float, HistoryDistanceThreshold)
SHADER_PARAMETER_RDG_UNIFORM_BUFFER(FSubstrateGlobalUniformParameters, Substrate)
END_SHADER_PARAMETER_STRUCT()
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return DoesPlatformSupportLumenReSTIRGather(Parameters.Platform);
}
static int32 GetGroupSize()
{
return 8;
}
using FPermutationDomain = TShaderPermutationDomain<>;
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE"), GetGroupSize());
}
};
IMPLEMENT_GLOBAL_SHADER(FTemporalResamplingCS, "/Engine/Private/Lumen/LumenReSTIRGather.usf", "TemporalResamplingCS", SF_Compute);
class FClearTemporalHistoryCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FClearTemporalHistoryCS)
SHADER_USE_PARAMETER_STRUCT(FClearTemporalHistoryCS, FGlobalShader)
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<float4>, RWTemporalReservoirRayDirection)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<float3>, RWTemporalReservoirTraceRadiance)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<float>, RWTemporalReservoirTraceHitDistance)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<UNORM float3>, RWTemporalReservoirTraceHitNormal)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<float3>, RWTemporalReservoirWeights)
SHADER_PARAMETER_STRUCT_INCLUDE(FReSTIRParameters, ReSTIRParameters)
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, View)
SHADER_PARAMETER_RDG_UNIFORM_BUFFER(FSceneTextureUniformParameters, SceneTexturesStruct)
SHADER_PARAMETER_RDG_UNIFORM_BUFFER(FSubstrateGlobalUniformParameters, Substrate)
END_SHADER_PARAMETER_STRUCT()
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return DoesPlatformSupportLumenReSTIRGather(Parameters.Platform);
}
static int32 GetGroupSize()
{
return 8;
}
using FPermutationDomain = TShaderPermutationDomain<>;
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE"), GetGroupSize());
}
};
IMPLEMENT_GLOBAL_SHADER(FClearTemporalHistoryCS, "/Engine/Private/Lumen/LumenReSTIRGather.usf", "ClearTemporalHistoryCS", SF_Compute);
class FSpatialResamplingCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FSpatialResamplingCS)
SHADER_USE_PARAMETER_STRUCT(FSpatialResamplingCS, FGlobalShader)
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_INCLUDE(FReSTIRParameters, ReSTIRParameters)
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, View)
SHADER_PARAMETER_RDG_UNIFORM_BUFFER(FSceneTextureUniformParameters, SceneTexturesStruct)
SHADER_PARAMETER_STRUCT_INCLUDE(FSceneTextureParameters, SceneTextures)
SHADER_PARAMETER(float, SpatialResamplingKernelRadius)
SHADER_PARAMETER(float, SpatialResamplingOcclusionScreenTraceDistance)
SHADER_PARAMETER(uint32, NumSpatialSamples)
SHADER_PARAMETER(uint32, SpatialResamplingPassIndex)
SHADER_PARAMETER_RDG_UNIFORM_BUFFER(FSubstrateGlobalUniformParameters, Substrate)
END_SHADER_PARAMETER_STRUCT()
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return DoesPlatformSupportLumenReSTIRGather(Parameters.Platform);
}
static int32 GetGroupSize()
{
return 8;
}
using FPermutationDomain = TShaderPermutationDomain<>;
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE"), GetGroupSize());
}
};
IMPLEMENT_GLOBAL_SHADER(FSpatialResamplingCS, "/Engine/Private/Lumen/LumenReSTIRGather.usf", "SpatialResamplingCS", SF_Compute);
// Must match LumenReSTIRGather.ush
enum class EReSTIRUpsampleMethod : uint8
{
JitteredBilinearWithFallback,
SpiralPattern,
Passthrough,
MAX
};
class FUpsampleAndIntegrateCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FUpsampleAndIntegrateCS)
SHADER_USE_PARAMETER_STRUCT(FUpsampleAndIntegrateCS, FGlobalShader)
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<float4>, RWDiffuseIndirect)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<float3>, RWRoughSpecularIndirect)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<float>, RWResolveVariance)
SHADER_PARAMETER_STRUCT_INCLUDE(FReSTIRParameters, ReSTIRParameters)
SHADER_PARAMETER_STRUCT_INCLUDE(LumenReflections::FCompositeParameters, ReflectionsCompositeParameters)
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, View)
SHADER_PARAMETER_RDG_UNIFORM_BUFFER(FSceneTextureUniformParameters, SceneTexturesStruct)
SHADER_PARAMETER_RDG_UNIFORM_BUFFER(FSubstrateGlobalUniformParameters, Substrate)
SHADER_PARAMETER(float, UpsampleKernelSize)
SHADER_PARAMETER(uint32, UpsampleNumSamples)
END_SHADER_PARAMETER_STRUCT()
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return DoesPlatformSupportLumenReSTIRGather(Parameters.Platform);
}
static int32 GetGroupSize()
{
return 8;
}
class FUpsampleMethod : SHADER_PERMUTATION_ENUM_CLASS("UPSAMPLE_METHOD", EReSTIRUpsampleMethod);
class FBilateralFilter : SHADER_PERMUTATION_BOOL("USE_BILATERAL_FILTER");
using FPermutationDomain = TShaderPermutationDomain<FUpsampleMethod, FBilateralFilter>;
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE"), GetGroupSize());
}
};
IMPLEMENT_GLOBAL_SHADER(FUpsampleAndIntegrateCS, "/Engine/Private/Lumen/LumenReSTIRGather.usf", "UpsampleAndIntegrateCS", SF_Compute);
class FTemporalAccumulationCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FTemporalAccumulationCS)
SHADER_USE_PARAMETER_STRUCT(FTemporalAccumulationCS, FGlobalShader)
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<float4>, RWNewHistoryDiffuseIndirect)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<float3>, RWNewHistoryRoughSpecularIndirect)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<float>, RWResolveVariance)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<float>, RWNumHistoryFramesAccumulated)
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, View)
SHADER_PARAMETER_STRUCT_INCLUDE(FSceneTextureParameters, SceneTextures)
SHADER_PARAMETER_RDG_UNIFORM_BUFFER(FSceneTextureUniformParameters, SceneTexturesStruct)
SHADER_PARAMETER_RDG_UNIFORM_BUFFER(FSubstrateGlobalUniformParameters, Substrate)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, DiffuseIndirect)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, RoughSpecularIndirect)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, ResolveVariance)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, DiffuseIndirectHistory)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, RoughSpecularIndirectHistory)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, ResolveVarianceHistory)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, DiffuseIndirectDepthHistory)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, HistoryNumFramesAccumulated)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, NormalHistory)
SHADER_PARAMETER(float,HistoryDistanceThreshold)
SHADER_PARAMETER(float,PrevSceneColorPreExposureCorrection)
SHADER_PARAMETER(float,MaxFramesAccumulated)
SHADER_PARAMETER(FVector4f,HistoryScreenPositionScaleBias)
SHADER_PARAMETER(FVector4f,HistoryUVMinMax)
SHADER_PARAMETER(FVector4f, EffectiveResolution)
SHADER_PARAMETER(int32, FixedJitterIndex)
END_SHADER_PARAMETER_STRUCT()
class FBilateralFilter : SHADER_PERMUTATION_BOOL("USE_BILATERAL_FILTER");
using FPermutationDomain = TShaderPermutationDomain<FBilateralFilter>;
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
const bool bCompile = DoesPlatformSupportLumenReSTIRGather(Parameters.Platform);
#if WITH_EDITOR
if (bCompile)
{
ensureMsgf(VelocityEncodeDepth(Parameters.Platform), TEXT("Platform did not return true from VelocityEncodeDepth(). Lumen requires velocity depth."));
}
#endif
return DoesPlatformSupportLumenReSTIRGather(Parameters.Platform);
}
static int32 GetGroupSize()
{
return 8;
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE"), GetGroupSize());
}
};
IMPLEMENT_GLOBAL_SHADER(FTemporalAccumulationCS, "/Engine/Private/Lumen/LumenReSTIRGather.usf", "TemporalAccumulationCS", SF_Compute);
class FBilateralFilterCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FBilateralFilterCS)
SHADER_USE_PARAMETER_STRUCT(FBilateralFilterCS, FGlobalShader)
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<float3>, RWDiffuseIndirect)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<float3>, RWRoughSpecularIndirect)
SHADER_PARAMETER_STRUCT_INCLUDE(FReSTIRParameters, ReSTIRParameters)
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, View)
SHADER_PARAMETER_RDG_UNIFORM_BUFFER(FSceneTextureUniformParameters, SceneTexturesStruct)
SHADER_PARAMETER_RDG_UNIFORM_BUFFER(FSubstrateGlobalUniformParameters, Substrate)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D<float3>, DiffuseIndirect)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D<float3>, RoughSpecularIndirect)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, ResolveVariance)
SHADER_PARAMETER(float, BilateralFilterSpatialKernelRadius)
SHADER_PARAMETER(uint32, BilateralFilterNumSamples)
SHADER_PARAMETER(float, BilateralFilterDepthWeightScale)
SHADER_PARAMETER(float, BilateralFilterNormalAngleThresholdScale)
SHADER_PARAMETER(float, BilateralFilterStrongBlurVarianceThreshold)
END_SHADER_PARAMETER_STRUCT()
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return DoesPlatformSupportLumenReSTIRGather(Parameters.Platform);
}
static int32 GetGroupSize()
{
return 8;
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE"), GetGroupSize());
}
};
IMPLEMENT_GLOBAL_SHADER(FBilateralFilterCS, "/Engine/Private/Lumen/LumenReSTIRGather.usf", "BilateralFilterCS", SF_Compute);
void DispatchTemporalAccumulation(
FRDGBuilder& GraphBuilder,
const FViewInfo& View,
const FSceneTextures& SceneTextures,
FLumenSceneFrameTemporaries& FrameTemporaries,
bool bPropagateGlobalLightingChange,
bool bUseBilaterialFilter,
FRDGTextureRef& DiffuseIndirect,
FRDGTextureRef& RoughSpecularIndirect,
FRDGTextureRef& ResolveVariance,
ERDGPassFlags ComputePassFlags)
{
LLM_SCOPE_BYTAG(Lumen);
if (View.ViewState)
{
FReSTIRTemporalAccumulationState& TemporalAccumulationState = View.ViewState->Lumen.ReSTIRGatherState.TemporalAccumulationState;
TRefCountPtr<IPooledRenderTarget>* DiffuseIndirectHistoryState = &TemporalAccumulationState.DiffuseIndirectHistoryRT;
FIntRect* DiffuseIndirectHistoryViewRect = &TemporalAccumulationState.DiffuseIndirectHistoryViewRect;
FVector4f* DiffuseIndirectHistoryScreenPositionScaleBias = &TemporalAccumulationState.DiffuseIndirectHistoryScreenPositionScaleBias;
TRefCountPtr<IPooledRenderTarget>* HistoryNumFramesAccumulated = &TemporalAccumulationState.NumFramesAccumulatedRT;
ensureMsgf(SceneTextures.Velocity->Desc.Format != PF_G16R16, TEXT("Lumen requires 3d velocity. Update Velocity format code."));
// If the scene render targets reallocate, toss the history so we don't read uninitialized data
const FIntPoint EffectiveResolution = Substrate::GetSubstrateTextureResolution(View, SceneTextures.Config.Extent);
const FIntPoint EffectiveViewExtent = FrameTemporaries.ViewExtent;
const uint32 ClosureCount = Substrate::GetSubstrateMaxClosureCount(View);
const FIntPoint HistoryEffectiveResolution = TemporalAccumulationState.HistoryEffectiveResolution;
const bool bSceneTextureExtentMatchHistory = TemporalAccumulationState.HistorySceneTexturesExtent == SceneTextures.Config.Extent;
const FIntRect NewHistoryViewRect = View.ViewRect;
if (*DiffuseIndirectHistoryState
&& !View.bCameraCut
&& !View.bPrevTransformsReset
&& !GLumenReSTIRGatherClearHistoryEveryFrame
&& bSceneTextureExtentMatchHistory
&& (!bUseBilaterialFilter || TemporalAccumulationState.ResolveVarianceHistoryRT)
&& !bPropagateGlobalLightingChange)
{
FRDGTextureDesc DiffuseIndirectDesc = FRDGTextureDesc::Create2DArray(EffectiveResolution, PF_FloatRGBA, FClearValueBinding::Black, TexCreate_ShaderResource | TexCreate_UAV, ClosureCount);
FRDGTextureDesc RoughSpecularIndirectDesc = FRDGTextureDesc::Create2DArray(EffectiveResolution, PF_FloatRGB, FClearValueBinding::Black, TexCreate_ShaderResource | TexCreate_UAV, ClosureCount);
FRDGTextureDesc ResolveVarianceDesc = FRDGTextureDesc::Create2DArray(EffectiveResolution, PF_R16F, FClearValueBinding::Transparent, TexCreate_ShaderResource | TexCreate_UAV, ClosureCount);
FRDGTextureRef NewDiffuseIndirect = FrameTemporaries.NewDiffuseIndirect.CreateSharedRT(GraphBuilder, DiffuseIndirectDesc, EffectiveViewExtent, TEXT("Lumen.ReSTIRGather.DiffuseIndirect"));
FRDGTextureRef NewRoughSpecularIndirect = FrameTemporaries.NewRoughSpecularIndirect.CreateSharedRT(GraphBuilder, RoughSpecularIndirectDesc, EffectiveViewExtent, TEXT("Lumen.ReSTIRGather.RoughSpecularIndirect"));
FRDGTextureRef NewResolveVariance = FrameTemporaries.NewResolveVariance.CreateSharedRT(GraphBuilder, ResolveVarianceDesc, EffectiveViewExtent, TEXT("Lumen.ReSTIRGather.ResolveVariance"));
FRDGTextureRef OldDiffuseIndirectHistory = GraphBuilder.RegisterExternalTexture(TemporalAccumulationState.DiffuseIndirectHistoryRT);
FRDGTextureRef OldRoughSpecularIndirectHistory = GraphBuilder.RegisterExternalTexture(TemporalAccumulationState.RoughSpecularIndirectHistoryRT);
FRDGTextureRef OldResolveVarianceHistory = GraphBuilder.RegisterExternalTexture(TemporalAccumulationState.ResolveVarianceHistoryRT);
FRDGTextureDesc NumHistoryFramesAccumulatedDesc(FRDGTextureDesc::Create2D(EffectiveResolution, PF_R8, FClearValueBinding::Black, TexCreate_ShaderResource | TexCreate_UAV));
FRDGTextureRef NewNumHistoryFramesAccumulated = GraphBuilder.CreateTexture(NumHistoryFramesAccumulatedDesc, TEXT("Lumen.ReSTIRGather.NumHistoryFramesAccumulated"));
{
FRDGTextureRef OldDepthHistory = View.ViewState->StochasticLighting.SceneDepthHistory ? GraphBuilder.RegisterExternalTexture(View.ViewState->StochasticLighting.SceneDepthHistory) : SceneTextures.Depth.Target;
FRDGTextureRef OldHistoryNumFramesAccumulated = GraphBuilder.RegisterExternalTexture(*HistoryNumFramesAccumulated);
{
FRDGTextureUAVRef RWNewHistoryDiffuseIndirect = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(NewDiffuseIndirect), ERDGUnorderedAccessViewFlags::SkipBarrier);
FRDGTextureUAVRef RWNewHistoryRoughSpecularIndirect = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(NewRoughSpecularIndirect), ERDGUnorderedAccessViewFlags::SkipBarrier);
FRDGTextureUAVRef RWNewResolveVariance = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(NewResolveVariance), ERDGUnorderedAccessViewFlags::SkipBarrier);
FRDGTextureUAVRef RWNumHistoryFramesAccumulated = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(NewNumHistoryFramesAccumulated), ERDGUnorderedAccessViewFlags::SkipBarrier);
auto TemporalAccumulationPass = [&]()
{
FTemporalAccumulationCS::FPermutationDomain PermutationVector;
PermutationVector.Set< FTemporalAccumulationCS::FBilateralFilter >(bUseBilaterialFilter);
auto ComputeShader = View.ShaderMap->GetShader<FTemporalAccumulationCS>(PermutationVector);
FTemporalAccumulationCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FTemporalAccumulationCS::FParameters>();
PassParameters->RWNewHistoryDiffuseIndirect = RWNewHistoryDiffuseIndirect;
PassParameters->RWNewHistoryRoughSpecularIndirect = RWNewHistoryRoughSpecularIndirect;
PassParameters->RWResolveVariance = RWNewResolveVariance;
PassParameters->RWNumHistoryFramesAccumulated = RWNumHistoryFramesAccumulated;
PassParameters->View = View.ViewUniformBuffer;
PassParameters->SceneTextures = GetSceneTextureParameters(GraphBuilder, SceneTextures.UniformBuffer);
PassParameters->SceneTexturesStruct = SceneTextures.UniformBuffer;
PassParameters->Substrate = Substrate::BindSubstrateGlobalUniformParameters(View);
PassParameters->DiffuseIndirectHistory = OldDiffuseIndirectHistory;
PassParameters->RoughSpecularIndirectHistory = OldRoughSpecularIndirectHistory;
PassParameters->ResolveVarianceHistory = OldResolveVarianceHistory;
PassParameters->DiffuseIndirectDepthHistory = OldDepthHistory;
PassParameters->HistoryNumFramesAccumulated = OldHistoryNumFramesAccumulated;
PassParameters->HistoryDistanceThreshold = GLumenReSTIRGatherHistoryDistanceThreshold;
PassParameters->PrevSceneColorPreExposureCorrection = View.PreExposure / View.PrevViewInfo.SceneColorPreExposure;
const float MaxFramesAccumulatedScale = 1.0f / FMath::Sqrt(FMath::Clamp(View.FinalPostProcessSettings.LumenFinalGatherLightingUpdateSpeed, .5f, 8.0f));
const float EditingScale = View.Family->bCurrentlyBeingEdited ? .5f : 1.0f;
PassParameters->MaxFramesAccumulated = FMath::RoundToInt(GLumenReSTIRGatherTemporalMaxFramesAccumulated * MaxFramesAccumulatedScale * EditingScale);
PassParameters->HistoryScreenPositionScaleBias = *DiffuseIndirectHistoryScreenPositionScaleBias;
// History uses HistoryDepth which has the same resolution than SceneTextures (no extented/overflow space)
const FIntPoint BufferSize = SceneTextures.Config.Extent;
const FVector2D InvBufferSize(1.0f / BufferSize.X, 1.0f / BufferSize.Y);
// Pull in the max UV to exclude the region which will read outside the viewport due to bilinear filtering
PassParameters->HistoryUVMinMax = FVector4f(
(DiffuseIndirectHistoryViewRect->Min.X + 0.5f) * InvBufferSize.X,
(DiffuseIndirectHistoryViewRect->Min.Y + 0.5f) * InvBufferSize.Y,
(DiffuseIndirectHistoryViewRect->Max.X - 1.0f) * InvBufferSize.X,
(DiffuseIndirectHistoryViewRect->Max.Y - 1.0f) * InvBufferSize.Y);
PassParameters->FixedJitterIndex = GLumenReSTIRGatherFixedJitterIndex;
PassParameters->DiffuseIndirect = DiffuseIndirect;
PassParameters->RoughSpecularIndirect = RoughSpecularIndirect;
PassParameters->ResolveVariance = ResolveVariance;
{
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("TemporalAccumulation(%ux%u)", View.ViewRect.Width(), View.ViewRect.Height()),
ComputePassFlags,
ComputeShader,
PassParameters,
FComputeShaderUtils::GetGroupCount(View.ViewRect.Size(), FTemporalAccumulationCS::GetGroupSize()));
}
};
TemporalAccumulationPass();
}
if (!View.bStatePrevViewInfoIsReadOnly)
{
// Queue updating the view state's render target reference with the new history
GraphBuilder.QueueTextureExtraction(NewDiffuseIndirect, &TemporalAccumulationState.DiffuseIndirectHistoryRT);
GraphBuilder.QueueTextureExtraction(NewRoughSpecularIndirect, &TemporalAccumulationState.RoughSpecularIndirectHistoryRT);
GraphBuilder.QueueTextureExtraction(NewNumHistoryFramesAccumulated, HistoryNumFramesAccumulated);
if (bUseBilaterialFilter)
{
GraphBuilder.QueueTextureExtraction(NewResolveVariance, &TemporalAccumulationState.ResolveVarianceHistoryRT);
}
}
}
RoughSpecularIndirect = NewRoughSpecularIndirect;
DiffuseIndirect = NewDiffuseIndirect;
ResolveVariance = NewResolveVariance;
}
else
{
if (!View.bStatePrevViewInfoIsReadOnly)
{
// Queue updating the view state's render target reference with the new values
GraphBuilder.QueueTextureExtraction(DiffuseIndirect, &TemporalAccumulationState.DiffuseIndirectHistoryRT);
GraphBuilder.QueueTextureExtraction(RoughSpecularIndirect, &TemporalAccumulationState.RoughSpecularIndirectHistoryRT);
*HistoryNumFramesAccumulated = GSystemTextures.BlackDummy;
if (bUseBilaterialFilter)
{
GraphBuilder.QueueTextureExtraction(ResolveVariance, &TemporalAccumulationState.ResolveVarianceHistoryRT);
}
}
}
if (!View.bStatePrevViewInfoIsReadOnly)
{
*DiffuseIndirectHistoryViewRect = NewHistoryViewRect;
*DiffuseIndirectHistoryScreenPositionScaleBias = View.GetScreenPositionScaleBias(SceneTextures.Config.Extent, View.ViewRect);
TemporalAccumulationState.HistoryEffectiveResolution = EffectiveResolution;
TemporalAccumulationState.HistorySceneTexturesExtent = SceneTextures.Config.Extent;
}
}
else
{
// Temporal reprojection is disabled or there is no view state - pass through
}
}
FReservoirTextures AllocateReservoirTextures(FRDGBuilder& GraphBuilder, FLumenSceneFrameTemporaries& FrameTemporaries, FIntPoint ReservoirBufferSize, FIntPoint ReservoirViewExtent)
{
FReservoirTextures Textures;
FRDGTextureDesc RayDirectionDesc(FRDGTextureDesc::Create2D(ReservoirBufferSize, PF_FloatRGBA, FClearValueBinding::Black, TexCreate_ShaderResource | TexCreate_UAV));
Textures.ReservoirRayDirection = FrameTemporaries.ReservoirRayDirection.CreateSharedRT(GraphBuilder, RayDirectionDesc, ReservoirViewExtent, TEXT("Lumen.ReSTIRGather.ReservoirRayDirection"));
FRDGTextureDesc TraceRadianceDesc(FRDGTextureDesc::Create2D(ReservoirBufferSize, PF_FloatR11G11B10, FClearValueBinding::Black, TexCreate_ShaderResource | TexCreate_UAV));
Textures.ReservoirTraceRadiance = FrameTemporaries.ReservoirTraceRadiance.CreateSharedRT(GraphBuilder, TraceRadianceDesc, ReservoirViewExtent, TEXT("Lumen.ReSTIRGather.ReservoirTraceRadiance"));
FRDGTextureDesc TraceHitDistanceDesc(FRDGTextureDesc::Create2D(ReservoirBufferSize, PF_R32_FLOAT, FClearValueBinding::Black, TexCreate_ShaderResource | TexCreate_UAV));
Textures.ReservoirTraceHitDistance = FrameTemporaries.ReservoirTraceHitDistance.CreateSharedRT(GraphBuilder, TraceHitDistanceDesc, ReservoirViewExtent, TEXT("Lumen.ReSTIRGather.ReservoirTraceHitDistance"));
FRDGTextureDesc TraceHitNormalDesc(FRDGTextureDesc::Create2D(ReservoirBufferSize, PF_A2B10G10R10, FClearValueBinding::Black, TexCreate_ShaderResource | TexCreate_UAV));
Textures.ReservoirTraceHitNormal = FrameTemporaries.ReservoirTraceHitNormal.CreateSharedRT(GraphBuilder, TraceHitNormalDesc, ReservoirViewExtent, TEXT("Lumen.ReSTIRGather.ReservoirTraceHitNormal"));
FRDGTextureDesc ReservoirWeightsDesc(FRDGTextureDesc::Create2D(ReservoirBufferSize, PF_FloatRGBA, FClearValueBinding::Black, TexCreate_ShaderResource | TexCreate_UAV));
Textures.ReservoirWeights = FrameTemporaries.ReservoirWeights.CreateSharedRT(GraphBuilder, ReservoirWeightsDesc, ReservoirViewExtent, TEXT("Lumen.ReSTIRGather.ReservoirWeights"));
return Textures;
}
FReservoirUAVs CreateReservoirUAVs(FRDGBuilder& GraphBuilder, const FReservoirTextures& Textures)
{
FReservoirUAVs UAVs;
UAVs.RWReservoirRayDirection = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(Textures.ReservoirRayDirection));
UAVs.RWReservoirTraceRadiance = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(Textures.ReservoirTraceRadiance));
UAVs.RWReservoirTraceHitDistance = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(Textures.ReservoirTraceHitDistance));
UAVs.RWReservoirTraceHitNormal = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(Textures.ReservoirTraceHitNormal));
UAVs.RWReservoirWeights = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(Textures.ReservoirWeights));
return UAVs;
}
FSSDSignalTextures FDeferredShadingSceneRenderer::RenderLumenReSTIRGather(
FRDGBuilder& GraphBuilder,
const FSceneTextures& SceneTextures,
FLumenSceneFrameTemporaries& FrameTemporaries,
FRDGTextureRef LightingChannelsTexture,
FViewInfo& View,
FPreviousViewInfo* PreviousViewInfos,
ERDGPassFlags ComputePassFlags,
FLumenScreenSpaceBentNormalParameters& ScreenSpaceBentNormalParameters)
{
const FRDGSystemTextures& SystemTextures = FRDGSystemTextures::Get(GraphBuilder);
#if RHI_RAYTRACING
RDG_EVENT_SCOPE(GraphBuilder, "LumenReSTIRGather");
const FSceneTextureParameters SceneTextureParameters = GetSceneTextureParameters(GraphBuilder, SceneTextures.UniformBuffer);
FReSTIRParameters ReSTIRParameters;
ReSTIRParameters.ReservoirDownsampleFactor = GLumenReSTIRDownsampleFactor;
const FIntPoint ViewSize = FIntPoint::DivideAndRoundUp(View.ViewRect.Size(), (int32)ReSTIRParameters.ReservoirDownsampleFactor);
FIntPoint ReservoirBufferSize = FIntPoint::DivideAndRoundUp(SceneTextures.Config.Extent, (int32)ReSTIRParameters.ReservoirDownsampleFactor);
FIntPoint ReservoirViewExtent = FIntPoint::DivideAndRoundUp(FrameTemporaries.ViewExtent, (int32)ReSTIRParameters.ReservoirDownsampleFactor);
ReSTIRParameters.ReservoirViewSize = ViewSize;
ReSTIRParameters.ReservoirBufferSize = ReservoirBufferSize;
ReSTIRParameters.FixedJitterIndex = GLumenReSTIRGatherFixedJitterIndex;
ReSTIRParameters.ResamplingNormalDotThreshold = FMath::Cos(GLumenReSTIRResamplingAngleThreshold * PI / 180.0f);
ReSTIRParameters.ResamplingDepthErrorThreshold = GLumenReSTIRResamplingDepthErrorThreshold;
ReSTIRParameters.Textures = AllocateReservoirTextures(GraphBuilder, FrameTemporaries, ReservoirBufferSize, ReservoirViewExtent);
ReSTIRParameters.UAVs = CreateReservoirUAVs(GraphBuilder, ReSTIRParameters.Textures);
FRDGTextureDesc DownsampledSceneDepthDesc(FRDGTextureDesc::Create2D(ReservoirBufferSize, PF_R32_FLOAT, FClearValueBinding::Black, TexCreate_ShaderResource | TexCreate_UAV));
ReSTIRParameters.DownsampledSceneDepth = FrameTemporaries.DownsampledSceneDepth.CreateSharedRT(GraphBuilder, DownsampledSceneDepthDesc, ReservoirViewExtent, TEXT("Lumen.ReSTIRGather.DownsampledSceneDepth"));
FRDGTextureDesc DownsampledWorldNormalDesc(FRDGTextureDesc::Create2D(ReservoirBufferSize, PF_A2B10G10R10, FClearValueBinding::Black, TexCreate_ShaderResource | TexCreate_UAV));
ReSTIRParameters.DownsampledWorldNormal = FrameTemporaries.DownsampledWorldNormal.CreateSharedRT(GraphBuilder, DownsampledWorldNormalDesc, ReservoirViewExtent, TEXT("Lumen.ReSTIRGather.DownsampledWorldNormal"));
FBlueNoise BlueNoise = GetBlueNoiseGlobalParameters();
ReSTIRParameters.BlueNoise = CreateUniformBufferImmediate(BlueNoise, EUniformBufferUsage::UniformBuffer_SingleFrame);
FLumenCardTracingParameters TracingParameters;
GetLumenCardTracingParameters(GraphBuilder, View, *Scene->GetLumenSceneData(View), FrameTemporaries, false, TracingParameters);
const bool bValidateTemporalReservoirs = View.ViewState
&& GLumenReSTIRValidateTemporalReservoirsEveryNFrames > 0
&& (View.ViewState->GetFrameIndex() % GLumenReSTIRValidateTemporalReservoirsEveryNFrames) == 0;
if (bValidateTemporalReservoirs)
{
FReSTIRTemporalResamplingState& TemporalResamplingState = View.ViewState->Lumen.ReSTIRGatherState.TemporalResamplingState;
if (TemporalResamplingState.TemporalReservoirRayDirectionRT
&& ReSTIRParameters.ReservoirBufferSize == TemporalResamplingState.HistoryReservoirBufferSize)
{
FLumenValidateReservoirs::FParameters* Parameters = GraphBuilder.AllocParameters<FLumenValidateReservoirs::FParameters>();
{
SetLumenHardwareRayTracingSharedParameters(
GraphBuilder,
SceneTextureParameters,
View,
TracingParameters,
&Parameters->SharedParameters
);
Parameters->RWTemporalReservoirTraceRadiance = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(GraphBuilder.RegisterExternalTexture(TemporalResamplingState.TemporalReservoirTraceRadianceRT)));
Parameters->RWTemporalReservoirWeights = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(GraphBuilder.RegisterExternalTexture(TemporalResamplingState.TemporalReservoirWeightsRT)));
Parameters->TemporalReservoirRayDirection = GraphBuilder.RegisterExternalTexture(TemporalResamplingState.TemporalReservoirRayDirectionRT);
Parameters->TemporalReservoirTraceHitDistance = GraphBuilder.RegisterExternalTexture(TemporalResamplingState.TemporalReservoirTraceHitDistanceRT);
Parameters->TemporalReservoirTraceHitNormal = GraphBuilder.RegisterExternalTexture(TemporalResamplingState.TemporalReservoirTraceHitNormalRT);
Parameters->ReSTIRParameters = ReSTIRParameters;
Parameters->HistoryScreenPositionScaleBias = TemporalResamplingState.HistoryScreenPositionScaleBias;
Parameters->HistoryReservoirViewSize = TemporalResamplingState.HistoryReservoirViewSize;
Parameters->PrevSceneColorPreExposureCorrection = View.PreExposure / View.PrevViewInfo.SceneColorPreExposure;
Parameters->DownsampledDepthHistory = TemporalResamplingState.DownsampledDepthHistoryRT ? GraphBuilder.RegisterExternalTexture(TemporalResamplingState.DownsampledDepthHistoryRT) : Parameters->ReSTIRParameters.DownsampledSceneDepth;
Parameters->DownsampledNormalHistory = TemporalResamplingState.DownsampledNormalHistoryRT ? GraphBuilder.RegisterExternalTexture(TemporalResamplingState.DownsampledNormalHistoryRT) : Parameters->ReSTIRParameters.DownsampledWorldNormal;
Parameters->ReSTIRParameters = ReSTIRParameters;
Parameters->PullbackBias = Lumen::GetHardwareRayTracingPullbackBias();
Parameters->ApplySkyLight = 1;
Parameters->MaxTraceDistance = Lumen::GetMaxTraceDistance(View);
Parameters->MaxRayIntensity = GLumenReSTIRMaxRayIntensity;
}
const bool bUseHitLighting = LumenReflections::UseHitLighting(View, EDiffuseIndirectMethod::Lumen);
const bool bUseMinimalPayload = !bUseHitLighting;
FLumenValidateReservoirsRGS::FPermutationDomain PermutationVector;
PermutationVector.Set<FLumenValidateReservoirsRGS::FHitLighting>(bUseHitLighting);
TShaderRef<FLumenValidateReservoirsRGS> RayGenerationShader = View.ShaderMap->GetShader<FLumenValidateReservoirsRGS>(PermutationVector);
AddStochasticLightingRayTraceDispatchPass(
GraphBuilder,
RDG_EVENT_NAME("ValidateReservoirs"),
RayGenerationShader,
Parameters,
Parameters->SharedParameters.TracingParameters.Scene,
Parameters->SharedParameters.NaniteRayTracing,
TemporalResamplingState.HistoryReservoirViewSize,
View,
bUseMinimalPayload,
ERDGPassFlags::Compute);
}
}
{
FLumenInitialSampling::FParameters* Parameters = GraphBuilder.AllocParameters<FLumenInitialSampling::FParameters>();
{
SetLumenHardwareRayTracingSharedParameters(
GraphBuilder,
SceneTextureParameters,
View,
TracingParameters,
&Parameters->SharedParameters
);
Parameters->RWDownsampledSceneDepth = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(ReSTIRParameters.DownsampledSceneDepth));
Parameters->RWDownsampledWorldNormal = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(ReSTIRParameters.DownsampledWorldNormal));
Parameters->ReSTIRParameters = ReSTIRParameters;
Parameters->PullbackBias = Lumen::GetHardwareRayTracingPullbackBias();
Parameters->ApplySkyLight = 1;
Parameters->MaxTraceDistance = Lumen::GetMaxTraceDistance(View);
Parameters->MaxRayIntensity = GLumenReSTIRMaxRayIntensity;
}
const bool bUseHitLighting = LumenReflections::UseHitLighting(View, EDiffuseIndirectMethod::Lumen);
const bool bUseMinimalPayload = !bUseHitLighting;
FLumenInitialSamplingRGS::FPermutationDomain PermutationVector;
PermutationVector.Set<FLumenInitialSamplingRGS::FHitLighting>(bUseHitLighting);
TShaderRef<FLumenInitialSamplingRGS> RayGenerationShader = View.ShaderMap->GetShader<FLumenInitialSamplingRGS>(PermutationVector);
AddStochasticLightingRayTraceDispatchPass(
GraphBuilder,
RDG_EVENT_NAME("InitialSampling %ux%u", ReSTIRParameters.ReservoirViewSize.X, ReSTIRParameters.ReservoirViewSize.Y),
RayGenerationShader,
Parameters,
Parameters->SharedParameters.TracingParameters.Scene,
Parameters->SharedParameters.NaniteRayTracing,
ReSTIRParameters.ReservoirViewSize,
View,
bUseMinimalPayload,
ERDGPassFlags::Compute);
}
const bool bUseTemporalResampling = GLumenReSTIRTemporalResampling != 0 && View.ViewState;
if (bUseTemporalResampling)
{
FReSTIRTemporalResamplingState& TemporalResamplingState = View.ViewState->Lumen.ReSTIRGatherState.TemporalResamplingState;
FReservoirTextures TemporalReservoirTextures = AllocateReservoirTextures(GraphBuilder, FrameTemporaries, ReservoirBufferSize, ReservoirViewExtent);
FReservoirUAVs TemporalReservoirUAVs = CreateReservoirUAVs(GraphBuilder, TemporalReservoirTextures);
if (TemporalResamplingState.TemporalReservoirRayDirectionRT
&& !View.bCameraCut
&& !View.bPrevTransformsReset
&& ReSTIRParameters.ReservoirBufferSize == TemporalResamplingState.HistoryReservoirBufferSize
&& GLumenReSTIRTemporalResamplingResetHistory == 0)
{
FTemporalResamplingCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FTemporalResamplingCS::FParameters>();
PassParameters->RWTemporalReservoirRayDirection = TemporalReservoirUAVs.RWReservoirRayDirection;
PassParameters->RWTemporalReservoirTraceRadiance = TemporalReservoirUAVs.RWReservoirTraceRadiance;
PassParameters->RWTemporalReservoirTraceHitDistance = TemporalReservoirUAVs.RWReservoirTraceHitDistance;
PassParameters->RWTemporalReservoirTraceHitNormal = TemporalReservoirUAVs.RWReservoirTraceHitNormal;
PassParameters->RWTemporalReservoirWeights = TemporalReservoirUAVs.RWReservoirWeights;
PassParameters->TemporalReservoirRayDirection = GraphBuilder.RegisterExternalTexture(TemporalResamplingState.TemporalReservoirRayDirectionRT);
PassParameters->TemporalReservoirTraceRadiance = GraphBuilder.RegisterExternalTexture(TemporalResamplingState.TemporalReservoirTraceRadianceRT);
PassParameters->TemporalReservoirTraceHitDistance = GraphBuilder.RegisterExternalTexture(TemporalResamplingState.TemporalReservoirTraceHitDistanceRT);
PassParameters->TemporalReservoirTraceHitNormal = GraphBuilder.RegisterExternalTexture(TemporalResamplingState.TemporalReservoirTraceHitNormalRT);
PassParameters->TemporalReservoirWeights = GraphBuilder.RegisterExternalTexture(TemporalResamplingState.TemporalReservoirWeightsRT);
PassParameters->ReSTIRParameters = ReSTIRParameters;
PassParameters->View = View.ViewUniformBuffer;
PassParameters->SceneTexturesStruct = SceneTextures.UniformBuffer;
PassParameters->Substrate = Substrate::BindSubstrateGlobalUniformParameters(View);
PassParameters->SceneTextures = GetSceneTextureParameters(GraphBuilder, SceneTextures.UniformBuffer);
PassParameters->HistoryScreenPositionScaleBias = TemporalResamplingState.HistoryScreenPositionScaleBias;
const FIntPoint BufferSize = SceneTextures.Config.Extent;
const FVector2D InvBufferSize(1.0f / BufferSize.X, 1.0f / BufferSize.Y);
PassParameters->HistoryUVMinMax = FVector4f(
(TemporalResamplingState.HistoryViewRect.Min.X) * InvBufferSize.X,
(TemporalResamplingState.HistoryViewRect.Min.Y) * InvBufferSize.Y,
(TemporalResamplingState.HistoryViewRect.Max.X) * InvBufferSize.X,
(TemporalResamplingState.HistoryViewRect.Max.Y) * InvBufferSize.Y);
PassParameters->HistoryReservoirViewSize = TemporalResamplingState.HistoryReservoirViewSize;
PassParameters->PrevSceneColorPreExposureCorrection = View.PreExposure / View.PrevViewInfo.SceneColorPreExposure;
PassParameters->DownsampledDepthHistory = TemporalResamplingState.DownsampledDepthHistoryRT ? GraphBuilder.RegisterExternalTexture(TemporalResamplingState.DownsampledDepthHistoryRT) : PassParameters->ReSTIRParameters.DownsampledSceneDepth;
PassParameters->DownsampledNormalHistory = TemporalResamplingState.DownsampledNormalHistoryRT ? GraphBuilder.RegisterExternalTexture(TemporalResamplingState.DownsampledNormalHistoryRT) : PassParameters->ReSTIRParameters.DownsampledWorldNormal;
PassParameters->HistoryDistanceThreshold = GLumenReSTIRTemporalResamplingHistoryDistanceThreshold;
FTemporalResamplingCS::FPermutationDomain PermutationVector;
auto ComputeShader = View.ShaderMap->GetShader<FTemporalResamplingCS>(PermutationVector);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("TemporalResampling"),
ERDGPassFlags::Compute,
ComputeShader,
PassParameters,
FComputeShaderUtils::GetGroupCount(ReSTIRParameters.ReservoirViewSize, FTemporalResamplingCS::GetGroupSize()));
ReSTIRParameters.Textures = TemporalReservoirTextures;
}
else
{
FClearTemporalHistoryCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FClearTemporalHistoryCS::FParameters>();
PassParameters->RWTemporalReservoirRayDirection = TemporalReservoirUAVs.RWReservoirRayDirection;
PassParameters->RWTemporalReservoirTraceRadiance = TemporalReservoirUAVs.RWReservoirTraceRadiance;
PassParameters->RWTemporalReservoirTraceHitDistance = TemporalReservoirUAVs.RWReservoirTraceHitDistance;
PassParameters->RWTemporalReservoirTraceHitNormal = TemporalReservoirUAVs.RWReservoirTraceHitNormal;
PassParameters->RWTemporalReservoirWeights = TemporalReservoirUAVs.RWReservoirWeights;
PassParameters->ReSTIRParameters = ReSTIRParameters;
PassParameters->View = View.ViewUniformBuffer;
PassParameters->SceneTexturesStruct = SceneTextures.UniformBuffer;
PassParameters->Substrate = Substrate::BindSubstrateGlobalUniformParameters(View);
FClearTemporalHistoryCS::FPermutationDomain PermutationVector;
auto ComputeShader = View.ShaderMap->GetShader<FClearTemporalHistoryCS>(PermutationVector);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("ClearTemporalHistory"),
ERDGPassFlags::Compute,
ComputeShader,
PassParameters,
FComputeShaderUtils::GetGroupCount(ReSTIRParameters.ReservoirViewSize, FTemporalResamplingCS::GetGroupSize()));
GLumenReSTIRTemporalResamplingResetHistory = 0;
}
if (!View.bStatePrevViewInfoIsReadOnly)
{
// Queue updating the view state's render target reference with the new history
TemporalResamplingState.HistoryViewRect = View.ViewRect;
TemporalResamplingState.HistoryScreenPositionScaleBias = View.GetScreenPositionScaleBias(SceneTextures.Config.Extent, View.ViewRect);
TemporalResamplingState.HistoryReservoirViewSize = ReSTIRParameters.ReservoirViewSize;
TemporalResamplingState.HistoryReservoirBufferSize = ReSTIRParameters.ReservoirBufferSize;
GraphBuilder.QueueTextureExtraction(TemporalReservoirTextures.ReservoirRayDirection, &TemporalResamplingState.TemporalReservoirRayDirectionRT);
GraphBuilder.QueueTextureExtraction(TemporalReservoirTextures.ReservoirTraceRadiance, &TemporalResamplingState.TemporalReservoirTraceRadianceRT);
GraphBuilder.QueueTextureExtraction(TemporalReservoirTextures.ReservoirTraceHitDistance, &TemporalResamplingState.TemporalReservoirTraceHitDistanceRT);
GraphBuilder.QueueTextureExtraction(TemporalReservoirTextures.ReservoirTraceHitNormal, &TemporalResamplingState.TemporalReservoirTraceHitNormalRT);
GraphBuilder.QueueTextureExtraction(TemporalReservoirTextures.ReservoirWeights, &TemporalResamplingState.TemporalReservoirWeightsRT);
GraphBuilder.QueueTextureExtraction(ReSTIRParameters.DownsampledSceneDepth, &TemporalResamplingState.DownsampledDepthHistoryRT);
GraphBuilder.QueueTextureExtraction(ReSTIRParameters.DownsampledWorldNormal, &TemporalResamplingState.DownsampledNormalHistoryRT);
}
}
const int32 NumSpatialResamplingPasses = FMath::Clamp<int32>(GLumenReSTIRSpatialResampling > 0 ? GLumenReSTIRNumSpatialResamplingPasses : 0, 0, 16);
for (int32 SpatialResamplingPassIndex = 0; SpatialResamplingPassIndex < NumSpatialResamplingPasses; SpatialResamplingPassIndex++)
{
FReservoirTextures SpatialReservoirTextures = AllocateReservoirTextures(GraphBuilder, FrameTemporaries, ReservoirBufferSize, ReservoirViewExtent);
ReSTIRParameters.UAVs = CreateReservoirUAVs(GraphBuilder, SpatialReservoirTextures);
FSpatialResamplingCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FSpatialResamplingCS::FParameters>();
PassParameters->ReSTIRParameters = ReSTIRParameters;
PassParameters->View = View.ViewUniformBuffer;
PassParameters->SceneTexturesStruct = SceneTextures.UniformBuffer;
PassParameters->Substrate = Substrate::BindSubstrateGlobalUniformParameters(View);
PassParameters->SceneTextures = GetSceneTextureParameters(GraphBuilder, SceneTextures.UniformBuffer);
PassParameters->SpatialResamplingKernelRadius = GLumenReSTIRSpatialResamplingKernelRadius;
PassParameters->SpatialResamplingOcclusionScreenTraceDistance = GLumenReSTIRSpatialResamplingOcclusionScreenTraceDistance;
PassParameters->NumSpatialSamples = GLumenReSTIRNumSpatialSamples;
PassParameters->SpatialResamplingPassIndex = SpatialResamplingPassIndex;
FSpatialResamplingCS::FPermutationDomain PermutationVector;
auto ComputeShader = View.ShaderMap->GetShader<FSpatialResamplingCS>(PermutationVector);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("SpatialResampling"),
ERDGPassFlags::Compute,
ComputeShader,
PassParameters,
FComputeShaderUtils::GetGroupCount(ReSTIRParameters.ReservoirViewSize, FSpatialResamplingCS::GetGroupSize()));
ReSTIRParameters.Textures = SpatialReservoirTextures;
}
FRDGTextureDesc DiffuseIndirectDesc = FRDGTextureDesc::Create2D(SceneTextures.Config.Extent, PF_FloatRGB, FClearValueBinding::Black, TexCreate_ShaderResource | TexCreate_UAV);
FRDGTextureRef DiffuseIndirect = FrameTemporaries.DiffuseIndirect.CreateSharedRT(GraphBuilder, DiffuseIndirectDesc, FrameTemporaries.ViewExtent, TEXT("Lumen.ReSTIRGather.DiffuseIndirect"));
FRDGTextureDesc RoughSpecularIndirectDesc = FRDGTextureDesc::Create2D(SceneTextures.Config.Extent, PF_FloatRGB, FClearValueBinding::Black, TexCreate_ShaderResource | TexCreate_UAV);
FRDGTextureRef RoughSpecularIndirect = FrameTemporaries.RoughSpecularIndirect.CreateSharedRT(GraphBuilder, RoughSpecularIndirectDesc, FrameTemporaries.ViewExtent, TEXT("Lumen.ReSTIRGather.RoughSpecularIndirect"));
FRDGTextureDesc ResolveVarianceDesc = FRDGTextureDesc::Create2D(SceneTextures.Config.Extent, PF_R16F, FClearValueBinding::Black, TexCreate_ShaderResource | TexCreate_UAV);
FRDGTextureRef ResolveVariance = FrameTemporaries.ResolveVariance.CreateSharedRT(GraphBuilder, ResolveVarianceDesc, FrameTemporaries.ViewExtent, TEXT("Lumen.ReSTIRGather.ResolveVariance"));
const bool bBilateralFilter = GLumenReSTIRGatherBilateralFilter != 0;
{
FUpsampleAndIntegrateCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FUpsampleAndIntegrateCS::FParameters>();
PassParameters->RWDiffuseIndirect = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(DiffuseIndirect));
PassParameters->RWRoughSpecularIndirect = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(RoughSpecularIndirect));
PassParameters->RWResolveVariance = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(ResolveVariance));
PassParameters->ReSTIRParameters = ReSTIRParameters;
PassParameters->View = View.ViewUniformBuffer;
PassParameters->SceneTexturesStruct = SceneTextures.UniformBuffer;
PassParameters->Substrate = Substrate::BindSubstrateGlobalUniformParameters(View);
LumenReflections::SetupCompositeParameters(View, PassParameters->ReflectionsCompositeParameters);
PassParameters->UpsampleKernelSize = GLumenReSTIRUpsampleKernelSize;
PassParameters->UpsampleNumSamples = GLumenReSTIRUpsampleNumSamples;
FUpsampleAndIntegrateCS::FPermutationDomain PermutationVector;
PermutationVector.Set< FUpsampleAndIntegrateCS::FUpsampleMethod >((EReSTIRUpsampleMethod)GLumenReSTIRUpsampleMethod);
PermutationVector.Set< FUpsampleAndIntegrateCS::FBilateralFilter >(bBilateralFilter);
auto ComputeShader = View.ShaderMap->GetShader<FUpsampleAndIntegrateCS>(PermutationVector);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("IntegrateAndUpsample Type=%u %ux%u", GLumenReSTIRUpsampleMethod, View.ViewRect.Width(), View.ViewRect.Height()),
ERDGPassFlags::Compute,
ComputeShader,
PassParameters,
FComputeShaderUtils::GetGroupCount(View.ViewRect.Size(), FUpsampleAndIntegrateCS::GetGroupSize()));
}
if (GLumenReSTIRGatherTemporalFilter)
{
DispatchTemporalAccumulation(
GraphBuilder,
View,
SceneTextures,
FrameTemporaries,
LumenCardRenderer.bPropagateGlobalLightingChange,
bBilateralFilter,
DiffuseIndirect,
RoughSpecularIndirect,
ResolveVariance,
ComputePassFlags);
}
if (bBilateralFilter)
{
FRDGTextureRef FilteredDiffuseIndirect = GraphBuilder.CreateTexture(DiffuseIndirectDesc, TEXT("Lumen.ReSTIRGather.FilteredDiffuseIndirect"));
FRDGTextureRef FilteredRoughSpecularIndirect = GraphBuilder.CreateTexture(RoughSpecularIndirectDesc, TEXT("Lumen.ReSTIRGather.FilteredRoughSpecularIndirect"));
FBilateralFilterCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FBilateralFilterCS::FParameters>();
PassParameters->RWDiffuseIndirect = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(FilteredDiffuseIndirect));
PassParameters->RWRoughSpecularIndirect = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(FilteredRoughSpecularIndirect));
PassParameters->DiffuseIndirect = DiffuseIndirect;
PassParameters->RoughSpecularIndirect = RoughSpecularIndirect;
PassParameters->ResolveVariance = ResolveVariance;
PassParameters->BilateralFilterSpatialKernelRadius = GLumenReSTIRGatherBilateralFilterSpatialKernelRadius;
PassParameters->BilateralFilterNumSamples = GLumenReSTIRGatherBilateralFilterNumSamples;
PassParameters->BilateralFilterDepthWeightScale = GLumenReSTIRGatherBilateralFilterDepthWeightScale;
PassParameters->BilateralFilterNormalAngleThresholdScale = GLumenReSTIRGatherBilateralFilterNormalAngleThresholdScale;
PassParameters->BilateralFilterStrongBlurVarianceThreshold = GLumenReSTIRGatherBilateralFilterStrongBlurVarianceThreshold;
PassParameters->View = View.ViewUniformBuffer;
PassParameters->SceneTexturesStruct = SceneTextures.UniformBuffer;
PassParameters->Substrate = Substrate::BindSubstrateGlobalUniformParameters(View);
FBilateralFilterCS::FPermutationDomain PermutationVector;
auto ComputeShader = View.ShaderMap->GetShader<FBilateralFilterCS>(PermutationVector);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("BilateralFilter"),
ComputePassFlags,
ComputeShader,
PassParameters,
FComputeShaderUtils::GetGroupCount(View.ViewRect.Size(), FBilateralFilterCS::GetGroupSize()));
DiffuseIndirect = FilteredDiffuseIndirect;
RoughSpecularIndirect = FilteredRoughSpecularIndirect;
}
FSSDSignalTextures DenoiserOutputs;
DenoiserOutputs.Textures[0] = DiffuseIndirect;
DenoiserOutputs.Textures[1] = SystemTextures.Black;
DenoiserOutputs.Textures[2] = RoughSpecularIndirect;
if (GLumenReSTIRGatherShortRangeAmbientOcclusion != 0 && ViewFamily.EngineShowFlags.LumenShortRangeAmbientOcclusion)
{
float MaxScreenTraceFraction = GLumenReSTIRGatherShortRangeAOMaxScreenTraceFraction;
ScreenSpaceBentNormalParameters = ComputeScreenSpaceShortRangeAO(GraphBuilder, Scene, View, SceneTextures, LightingChannelsTexture, BlueNoise, MaxScreenTraceFraction, 1.0f, ComputePassFlags);
}
return DenoiserOutputs;
#else
FSSDSignalTextures DenoiserOutputs;
return DenoiserOutputs;
#endif
}