Files
UnrealEngineUWP/Engine/Source/Runtime/Renderer/Private/ScreenSpaceRayTracing.cpp
guillaume abadie 0e8d8a4792 Uses a Texture2DArray for TSR history to saves on number of UAVs
#rb none
#preflight 62711d64e16e280be60a0286

#ROBOMERGE-AUTHOR: guillaume.abadie
#ROBOMERGE-SOURCE: CL 20024040 via CL 20024043 via CL 20024050
#ROBOMERGE-BOT: UE5 (Release-Engine-Staging -> Main) (v943-19904690)

[CL 20024826 by guillaume abadie in ue5-main branch]
2022-05-03 09:58:40 -04:00

1495 lines
59 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "ScreenSpaceRayTracing.h"
#include "RenderGraph.h"
#include "PixelShaderUtils.h"
#include "ScreenPass.h"
#include "ScenePrivate.h"
#include "SceneTextureParameters.h"
#include "Strata/Strata.h"
static TAutoConsoleVariable<int32> CVarSSRQuality(
TEXT("r.SSR.Quality"),
3,
TEXT("Whether to use screen space reflections and at what quality setting.\n")
TEXT("(limits the setting in the post process settings which has a different scale)\n")
TEXT("(costs performance, adds more visual realism but the technique has limits)\n")
TEXT(" 0: off (default)\n")
TEXT(" 1: low (no glossy)\n")
TEXT(" 2: medium (no glossy)\n")
TEXT(" 3: high (glossy/using roughness, few samples)\n")
TEXT(" 4: very high (likely too slow for real-time)"),
ECVF_Scalability | ECVF_RenderThreadSafe);
int32 GSSRHalfResSceneColor = 0;
FAutoConsoleVariableRef CVarSSRHalfResSceneColor(
TEXT("r.SSR.HalfResSceneColor"),
GSSRHalfResSceneColor,
TEXT("Use half res scene color as input for SSR. Improves performance without much of a visual quality loss."),
ECVF_Scalability | ECVF_RenderThreadSafe
);
static TAutoConsoleVariable<int32> CVarSSRTemporal(
TEXT("r.SSR.Temporal"),
0,
TEXT("Defines if we use the temporal smoothing for the screen space reflection\n")
TEXT(" 0 is off (for debugging), 1 is on (default)"),
ECVF_RenderThreadSafe);
static TAutoConsoleVariable<int32> CVarSSRStencil(
TEXT("r.SSR.Stencil"),
0,
TEXT("Defines if we use the stencil prepass for the screen space reflection\n")
TEXT(" 0 is off (default), 1 is on"),
ECVF_RenderThreadSafe);
static TAutoConsoleVariable<int32> CVarSSGILeakFreeReprojection(
TEXT("r.SSGI.LeakFreeReprojection"), 1,
TEXT("Whether use a more expensive but leak free reprojection of previous frame's scene color.\n"),
ECVF_RenderThreadSafe);
static TAutoConsoleVariable<int32> CVarSSGIQuality(
TEXT("r.SSGI.Quality"), 4,
TEXT("Quality setting to control number of ray shot with SSGI, between 1 and 4 (defaults to 4).\n"),
ECVF_Scalability | ECVF_RenderThreadSafe);
static TAutoConsoleVariable<float> CVarSSGIMinimumLuminance(
TEXT("r.SSGI.MinimumLuminance"), 0.5f,
TEXT(""),
ECVF_Scalability | ECVF_RenderThreadSafe);
static TAutoConsoleVariable<int32> CVarSSGIRejectUncertainRays(
TEXT("r.SSGI.RejectUncertainRays"), 1,
TEXT("Rejects the screen space ray if it was uncertain due to going behind screen geometry."),
ECVF_Scalability | ECVF_RenderThreadSafe);
static TAutoConsoleVariable<int32> CVarSSGITerminateCertainRay(
TEXT("r.SSGI.TerminateCertainRay"), 1,
TEXT("Optimisations that if the screen space ray is certain and didn't find any geometry, don't fallback on otehr tracing technic."),
ECVF_Scalability | ECVF_RenderThreadSafe);
static TAutoConsoleVariable<float> CVarSSGISkyDistance(
TEXT("r.SSGI.SkyDistance"), 10000000,
TEXT("Distance of the sky in KM."),
ECVF_Scalability | ECVF_RenderThreadSafe);
DECLARE_GPU_STAT_NAMED(ScreenSpaceReflections, TEXT("ScreenSpace Reflections"));
DECLARE_GPU_STAT_NAMED(ScreenSpaceDiffuseIndirect, TEXT("Screen Space Diffuse Indirect"));
static bool IsScreenSpaceDiffuseIndirectSupported(EShaderPlatform ShaderPlatform)
{
if (IsAnyForwardShadingEnabled(ShaderPlatform))
{
return false;
}
return IsFeatureLevelSupported(ShaderPlatform, ERHIFeatureLevel::SM5);
}
static bool SupportScreenSpaceDiffuseIndirect(const FViewInfo& View)
{
if (View.FinalPostProcessSettings.DynamicGlobalIlluminationMethod != EDynamicGlobalIlluminationMethod::ScreenSpace)
{
return false;
}
int Quality = CVarSSGIQuality.GetValueOnRenderThread();
if (Quality <= 0)
{
return false;
}
if (!IsScreenSpaceDiffuseIndirectSupported(View.GetShaderPlatform()))
{
return false;
}
return View.ViewState != nullptr;
}
namespace ScreenSpaceRayTracing
{
bool ShouldKeepBleedFreeSceneColor(const FViewInfo& View)
{
// TODO(Guillaume): SSR as well.
return CVarSSGILeakFreeReprojection.GetValueOnRenderThread() != 0;
}
bool ShouldRenderScreenSpaceReflections(const FViewInfo& View)
{
if(!View.Family->EngineShowFlags.ScreenSpaceReflections
|| View.FinalPostProcessSettings.ReflectionMethod != EReflectionMethod::ScreenSpace
|| HasRayTracedOverlay(*View.Family)
|| View.bIsReflectionCapture)
{
return false;
}
if(!View.State)
{
// not view state (e.g. thumbnail rendering?), no HZB (no screen space reflections or occlusion culling)
return false;
}
int SSRQuality = CVarSSRQuality.GetValueOnRenderThread();
if(SSRQuality <= 0)
{
return false;
}
if(View.FinalPostProcessSettings.ScreenSpaceReflectionIntensity < 1.0f)
{
return false;
}
if (IsAnyForwardShadingEnabled(View.GetShaderPlatform()))
{
return false;
}
return true;
}
bool IsScreenSpaceDiffuseIndirectSupported(const FViewInfo& View)
{
if (!SupportScreenSpaceDiffuseIndirect(View))
{
return false;
}
return View.PrevViewInfo.ScreenSpaceRayTracingInput.IsValid();
}
bool IsSSRTemporalPassRequired(const FViewInfo& View)
{
check(ShouldRenderScreenSpaceReflections(View));
if (!View.State)
{
return false;
}
return !IsTemporalAccumulationBasedMethod(View.AntiAliasingMethod) || CVarSSRTemporal.GetValueOnRenderThread() != 0;
}
FRDGTextureUAV* CreateScreenSpaceRayTracingDebugUAV(FRDGBuilder& GraphBuilder, const FRDGTextureDesc& Desc, const TCHAR* Name, bool bClear = false)
#if (!UE_BUILD_SHIPPING && !UE_BUILD_TEST)
{
FRDGTextureDesc DebugDesc = FRDGTextureDesc::Create2D(
Desc.Extent,
PF_FloatRGBA,
FClearValueBinding::None,
TexCreate_ShaderResource | TexCreate_UAV);
FRDGTexture* DebugTexture = GraphBuilder.CreateTexture(DebugDesc, Name);
FRDGTextureUAVRef DebugOutput = GraphBuilder.CreateUAV(DebugTexture);
if (bClear)
AddClearUAVPass(GraphBuilder, DebugOutput, FLinearColor::Transparent);
return DebugOutput;
}
#else
{
return nullptr;
}
#endif
void SetupCommonScreenSpaceRayParameters(
FRDGBuilder& GraphBuilder,
const FSceneTextureParameters& SceneTextures,
const ScreenSpaceRayTracing::FPrevSceneColorMip& PrevSceneColor,
const FViewInfo& View,
FCommonScreenSpaceRayParameters* OutParameters)
{
{
// float2 SceneBufferUV;
// float2 PixelPos = SceneBufferUV * View.BufferSizeAndInvSize.xy - View.ViewRect.Min;
// PixelPos *= 0.5 // ReducedSceneColor is half resolution.
// float2 ReducedSceneColorUV = PixelPos / ReducedSceneColor->Extent;
OutParameters->ColorBufferScaleBias = FVector4f(
0.5f * SceneTextures.SceneDepthTexture->Desc.Extent.X / float(PrevSceneColor.SceneColor->Desc.Extent.X),
0.5f * SceneTextures.SceneDepthTexture->Desc.Extent.Y / float(PrevSceneColor.SceneColor->Desc.Extent.Y),
-0.5f * View.ViewRect.Min.X / float(PrevSceneColor.SceneColor->Desc.Extent.X),
-0.5f * View.ViewRect.Min.Y / float(PrevSceneColor.SceneColor->Desc.Extent.Y));
OutParameters->ReducedColorUVMax = FVector2f(
(0.5f * View.ViewRect.Width() - 0.5f) / float(PrevSceneColor.SceneColor->Desc.Extent.X),
(0.5f * View.ViewRect.Height() - 0.5f) / float(PrevSceneColor.SceneColor->Desc.Extent.Y));
}
OutParameters->FurthestHZBTexture = View.HZB;
OutParameters->FurthestHZBTextureSampler = TStaticSamplerState<SF_Point>::GetRHI();
OutParameters->ColorTexture = PrevSceneColor.SceneColor;
OutParameters->ColorTextureSampler = TStaticSamplerState<SF_Point>::GetRHI();
OutParameters->AlphaTexture = PrevSceneColor.SceneAlpha;
OutParameters->AlphaTextureSampler = TStaticSamplerState<SF_Point>::GetRHI();
const FVector2D ViewportUVToHZBBufferUV(
float(View.ViewRect.Width()) / float(2 * View.HZBMipmap0Size.X),
float(View.ViewRect.Height()) / float(2 * View.HZBMipmap0Size.Y)
);
OutParameters->HZBUvFactorAndInvFactor = FVector4f(
ViewportUVToHZBBufferUV.X,
ViewportUVToHZBBufferUV.Y,
1.0f / ViewportUVToHZBBufferUV.X,
1.0f / ViewportUVToHZBBufferUV.Y);
OutParameters->ViewUniformBuffer = View.ViewUniformBuffer;
OutParameters->DebugOutput = CreateScreenSpaceRayTracingDebugUAV(GraphBuilder, SceneTextures.SceneDepthTexture->Desc, TEXT("DebugSSRT"));
OutParameters->bRejectUncertainRays = CVarSSGIRejectUncertainRays.GetValueOnRenderThread() ? 1 : 0;
OutParameters->bTerminateCertainRay = CVarSSGITerminateCertainRay.GetValueOnRenderThread() ? 1 : 0;
} // SetupCommonScreenSpaceRayParameters()
void SetupCommonScreenSpaceRayParameters(
FRDGBuilder& GraphBuilder,
const HybridIndirectLighting::FCommonParameters& CommonDiffuseParameters,
const ScreenSpaceRayTracing::FPrevSceneColorMip& PrevSceneColor,
const FViewInfo& View,
FCommonScreenSpaceRayParameters* OutParameters)
{
OutParameters->CommonDiffuseParameters = CommonDiffuseParameters;
if (CommonDiffuseParameters.DownscaleFactor == 2.0f)
{
OutParameters->PixelPositionToFullResPixel = 2.0f;
OutParameters->FullResPixelOffset = FVector2f(0.5f, 0.5f); // TODO.
}
else if (CommonDiffuseParameters.DownscaleFactor == 1.0f)
{
OutParameters->PixelPositionToFullResPixel = 1.0f;
OutParameters->FullResPixelOffset = FVector2f(0.5f, 0.5f);
}
else
{
unimplemented();
}
SetupCommonScreenSpaceRayParameters(
GraphBuilder, CommonDiffuseParameters.SceneTextures,
PrevSceneColor, View,
/* inout */ OutParameters);
} // SetupCommonScreenSpaceRayParameters()
} // namespace ScreenSpaceRayTracing
bool UseSingleLayerWaterIndirectDraw(EShaderPlatform ShaderPlatform);
namespace
{
float ComputeRoughnessMaskScale(const FViewInfo& View, ESSRQuality SSRQuality)
{
float MaxRoughness = FMath::Clamp(View.FinalPostProcessSettings.ScreenSpaceReflectionMaxRoughness, 0.01f, 1.0f);
// f(x) = x * Scale + Bias
// f(MaxRoughness) = 0
// f(MaxRoughness/2) = 1
float RoughnessMaskScale = -2.0f / MaxRoughness;
return RoughnessMaskScale * (int32(SSRQuality) < 3 ? 2.0f : 1.0f);
}
FLinearColor ComputeSSRParams(const FViewInfo& View, ESSRQuality SSRQuality, bool bEnableDiscard)
{
float RoughnessMaskScale = ComputeRoughnessMaskScale(View, SSRQuality);
float FrameRandom = 0;
if(View.ViewState)
{
bool bTemporalAAIsOn = IsTemporalAccumulationBasedMethod(View.AntiAliasingMethod);
if(bTemporalAAIsOn)
{
// usually this number is in the 0..7 range but it depends on the TemporalAA quality
FrameRandom = View.ViewState->GetCurrentTemporalAASampleIndex() * 1551;
}
else
{
// 8 aligns with the temporal smoothing, larger number will do more flickering (power of two for best performance)
FrameRandom = View.ViewState->GetFrameIndex(8) * 1551;
}
}
return FLinearColor(
FMath::Clamp(View.FinalPostProcessSettings.ScreenSpaceReflectionIntensity * 0.01f, 0.0f, 1.0f),
RoughnessMaskScale,
(float)bEnableDiscard, // TODO
FrameRandom);
}
BEGIN_SHADER_PARAMETER_STRUCT(FSSRTTileClassificationParameters, )
SHADER_PARAMETER(FIntPoint, TileBufferExtent)
SHADER_PARAMETER(int32, ViewTileCount)
SHADER_PARAMETER(int32, MaxTileCount)
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<float>, TileClassificationBuffer)
END_SHADER_PARAMETER_STRUCT()
BEGIN_SHADER_PARAMETER_STRUCT(FSSRCommonParameters, )
SHADER_PARAMETER(FLinearColor, SSRParams)
SHADER_PARAMETER_STRUCT_INCLUDE(FSceneTextureParameters, SceneTextures)
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, ViewUniformBuffer)
END_SHADER_PARAMETER_STRUCT()
BEGIN_SHADER_PARAMETER_STRUCT(FSSRPassCommonParameters, )
SHADER_PARAMETER(FVector4f, HZBUvFactorAndInvFactor)
SHADER_PARAMETER(FVector4f, PrevScreenPositionScaleBias)
SHADER_PARAMETER(float, PrevSceneColorPreExposureCorrection)
SHADER_PARAMETER(uint32, ShouldReflectOnlyWater)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, SceneColor)
SHADER_PARAMETER_SAMPLER(SamplerState, SceneColorSampler)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, HZB)
SHADER_PARAMETER_SAMPLER(SamplerState, HZBSampler)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<float4>, ScreenSpaceRayTracingDebugOutput)
END_SHADER_PARAMETER_STRUCT()
enum class ELightingTerm
{
Diffuse,
Specular,
MAX
};
class FSSRQualityDim : SHADER_PERMUTATION_ENUM_CLASS("SSR_QUALITY", ESSRQuality);
class FSSROutputForDenoiser : SHADER_PERMUTATION_BOOL("SSR_OUTPUT_FOR_DENOISER");
class FLightingTermDim : SHADER_PERMUTATION_ENUM_CLASS("DIM_LIGHTING_TERM", ELightingTerm);
class FSSRTPrevFrameReductionCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FSSRTPrevFrameReductionCS);
SHADER_USE_PARAMETER_STRUCT(FSSRTPrevFrameReductionCS, FGlobalShader);
class FLowerMips : SHADER_PERMUTATION_BOOL("DIM_LOWER_MIPS");
class FLeakFree : SHADER_PERMUTATION_BOOL("DIM_LEAK_FREE");
using FPermutationDomain = TShaderPermutationDomain<FLowerMips, FLeakFree>;
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return IsFeatureLevelSupported(Parameters.Platform, ERHIFeatureLevel::SM5);
}
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER(FVector4f, PrevBufferBilinearUVMinMax)
SHADER_PARAMETER(FVector4f, PrevScreenPositionScaleBias)
SHADER_PARAMETER(FVector2f, ViewportUVToHZBBufferUV)
SHADER_PARAMETER(FVector2f, ReducedSceneColorSize)
SHADER_PARAMETER(FVector2f, ReducedSceneColorTexelSize)
SHADER_PARAMETER(FVector2f, HigherMipBufferBilinearMax)
SHADER_PARAMETER(float, PrevSceneColorPreExposureCorrection)
SHADER_PARAMETER(float, MinimumLuminance)
SHADER_PARAMETER(float, HigherMipDownScaleFactor)
SHADER_PARAMETER(float, SkyDistance)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, PrevSceneColor)
SHADER_PARAMETER_SAMPLER(SamplerState, PrevSceneColorSampler)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, PrevSceneDepth)
SHADER_PARAMETER_SAMPLER(SamplerState, PrevSceneDepthSampler)
SHADER_PARAMETER_RDG_TEXTURE_SRV(Texture2D, HigherMipTexture)
SHADER_PARAMETER_RDG_TEXTURE_SRV(Texture2D, HigherAlphaMipTexture)
SHADER_PARAMETER_SAMPLER(SamplerState, HigherMipTextureSampler)
SHADER_PARAMETER_SAMPLER(SamplerState, HigherAlphaMipTextureSampler)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, FurthestHZBTexture)
SHADER_PARAMETER_SAMPLER(SamplerState, FurthestHZBTextureSampler)
SHADER_PARAMETER_STRUCT_INCLUDE(FSceneTextureParameters, SceneTextures)
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, View)
SHADER_PARAMETER_RDG_TEXTURE_UAV_ARRAY(RWTexture2D<float4>, ReducedSceneColorOutput, [3])
SHADER_PARAMETER_RDG_TEXTURE_UAV_ARRAY(RWTexture2D<float>, ReducedSceneAlphaOutput, [3])
END_SHADER_PARAMETER_STRUCT()
};
class FSSRTDiffuseTileClassificationCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FSSRTDiffuseTileClassificationCS);
SHADER_USE_PARAMETER_STRUCT(FSSRTDiffuseTileClassificationCS, FGlobalShader);
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return IsFeatureLevelSupported(Parameters.Platform, ERHIFeatureLevel::SM5);
}
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER(FVector2f, SamplePixelToHZBUV)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, ClosestHZBTexture)
SHADER_PARAMETER_SAMPLER(SamplerState, ClosestHZBTextureSampler)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, FurthestHZBTexture)
SHADER_PARAMETER_SAMPLER(SamplerState, FurthestHZBTextureSampler)
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, View)
SHADER_PARAMETER_STRUCT_INCLUDE(FSSRTTileClassificationParameters, TileClassificationParameters)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWStructuredBuffer<float>, TileClassificationBufferOutput)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<float4>, DebugOutput)
END_SHADER_PARAMETER_STRUCT()
};
class FScreenSpaceReflectionsStencilPS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FScreenSpaceReflectionsStencilPS);
SHADER_USE_PARAMETER_STRUCT(FScreenSpaceReflectionsStencilPS, FGlobalShader);
using FPermutationDomain = TShaderPermutationDomain<FSSROutputForDenoiser>;
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return IsFeatureLevelSupported(Parameters.Platform, ERHIFeatureLevel::SM5);
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("SSR_QUALITY"), uint32(0));
}
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_INCLUDE(FSSRCommonParameters, CommonParameters)
SHADER_PARAMETER_RDG_UNIFORM_BUFFER(FStrataGlobalUniformParameters, Strata)
RENDER_TARGET_BINDING_SLOTS()
END_SHADER_PARAMETER_STRUCT()
};
class FScreenSpaceReflectionsPS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FScreenSpaceReflectionsPS);
SHADER_USE_PARAMETER_STRUCT(FScreenSpaceReflectionsPS, FGlobalShader);
using FPermutationDomain = TShaderPermutationDomain<FSSRQualityDim, FSSROutputForDenoiser>;
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
FPermutationDomain PermutationVector(Parameters.PermutationId);
return IsFeatureLevelSupported(Parameters.Platform, ERHIFeatureLevel::SM5);
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.SetDefine(TEXT("SUPPORTS_ANISOTROPIC_MATERIALS"), FDataDrivenShaderPlatformInfo::GetSupportsAnisotropicMaterials(Parameters.Platform));
}
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_INCLUDE(FSSRCommonParameters, CommonParameters)
SHADER_PARAMETER_STRUCT_INCLUDE(FSSRPassCommonParameters, SSRPassCommonParameter)
RDG_BUFFER_ACCESS(IndirectDrawParameter, ERHIAccess::IndirectArgs)
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<uint>, TileListData) // FScreenSpaceReflectionsTileVS
SHADER_PARAMETER_RDG_UNIFORM_BUFFER(FStrataGlobalUniformParameters, Strata)
RENDER_TARGET_BINDING_SLOTS()
END_SHADER_PARAMETER_STRUCT()
};
// This is duplicated from FWaterTileVS because vertex shader should share Parameters structure for everything to be registered correctly in a RDG pass.
class FScreenSpaceReflectionsTileVS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FScreenSpaceReflectionsTileVS);
SHADER_USE_PARAMETER_STRUCT(FScreenSpaceReflectionsTileVS, FGlobalShader);
using FPermutationDomain = TShaderPermutationDomain<>;
using FParameters = FScreenSpaceReflectionsPS::FParameters; // Sharing parameters for proper registration with RDG
static FPermutationDomain RemapPermutation(FPermutationDomain PermutationVector)
{
return PermutationVector;
}
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return ::UseSingleLayerWaterIndirectDraw(Parameters.Platform);
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
OutEnvironment.SetDefine(TEXT("TILE_VERTEX_SHADER"), 1.0f);
OutEnvironment.SetDefine(TEXT("WORK_TILE_SIZE"), 8);
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
}
};
class FScreenSpaceCastStandaloneRayCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FScreenSpaceCastStandaloneRayCS);
SHADER_USE_PARAMETER_STRUCT(FScreenSpaceCastStandaloneRayCS, FGlobalShader)
class FQualityDim : SHADER_PERMUTATION_RANGE_INT("QUALITY", 1, 4);
using FPermutationDomain = TShaderPermutationDomain<FQualityDim>;
BEGIN_SHADER_PARAMETER_STRUCT(FParameters,)
SHADER_PARAMETER_STRUCT_INCLUDE(FCommonScreenSpaceRayParameters, CommonParameters)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<float4>, IndirectDiffuseOutput)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<float>, AmbientOcclusionOutput)
END_SHADER_PARAMETER_STRUCT()
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return IsScreenSpaceDiffuseIndirectSupported(Parameters.Platform);
}
};
class FSetupScreenSpaceTraceProbeCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FSetupScreenSpaceTraceProbeCS)
SHADER_USE_PARAMETER_STRUCT(FSetupScreenSpaceTraceProbeCS, FGlobalShader)
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_INCLUDE(LumenProbeHierarchy::FHierarchyParameters, HierarchyParameters)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<uint>, DispatchParametersOutput)
END_SHADER_PARAMETER_STRUCT()
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return IsScreenSpaceDiffuseIndirectSupported(Parameters.Platform);
}
};
class FScreenSpaceTraceProbeCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FScreenSpaceTraceProbeCS);
SHADER_USE_PARAMETER_STRUCT(FScreenSpaceTraceProbeCS, FGlobalShader)
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_INCLUDE(FCommonScreenSpaceRayParameters, CommonParameters)
SHADER_PARAMETER_STRUCT_INCLUDE(LumenProbeHierarchy::FHierarchyParameters, HierarchyParameters)
SHADER_PARAMETER_STRUCT_INCLUDE(LumenProbeHierarchy::FHierarchyLevelParameters, LevelParameters)
SHADER_PARAMETER(float, FurthestHZBStartMipLevel)
RDG_BUFFER_ACCESS(DispatchParameters, ERHIAccess::IndirectArgs)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, ProbeAtlasColorOutput)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<uint>, ProbeAtlasSampleMaskOutput)
END_SHADER_PARAMETER_STRUCT()
using FPermutationDomain = TShaderPermutationDomain<LumenProbeHierarchy::FProbeTracingPermutationDim>;
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return IsScreenSpaceDiffuseIndirectSupported(Parameters.Platform);
}
};
class FSetupScreenSpaceProbeOcclusionCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FSetupScreenSpaceProbeOcclusionCS);
SHADER_USE_PARAMETER_STRUCT(FSetupScreenSpaceProbeOcclusionCS, FGlobalShader)
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER(int32, MaxTilePerDispatch)
SHADER_PARAMETER_RDG_BUFFER_SRV(Buffer<uint>, GlobalClassificationCountersBuffer)
SHADER_PARAMETER_RDG_BUFFER_UAV(RWBuffer<uint>, DispatchParametersOutput)
END_SHADER_PARAMETER_STRUCT()
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return IsScreenSpaceDiffuseIndirectSupported(Parameters.Platform);
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.CompilerFlags.Add(CFLAG_Wave32);
}
};
class FScreenSpaceCastProbeOcclusionCS : public FGlobalShader
{
DECLARE_GLOBAL_SHADER(FScreenSpaceCastProbeOcclusionCS);
SHADER_USE_PARAMETER_STRUCT(FScreenSpaceCastProbeOcclusionCS, FGlobalShader)
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_INCLUDE(FCommonScreenSpaceRayParameters, CommonParameters)
SHADER_PARAMETER_STRUCT_INCLUDE(FSSRTTileClassificationParameters, TileClassificationParameters)
SHADER_PARAMETER_STRUCT_INCLUDE(LumenProbeHierarchy::FIndirectLightingProbeOcclusionParameters, ProbeOcclusionParameters)
SHADER_PARAMETER_STRUCT_INCLUDE(LumenProbeHierarchy::FIndirectLightingProbeOcclusionOutputParameters, ProbeOcclusionOutputParameters)
SHADER_PARAMETER(int32, DispatchOffset)
RDG_BUFFER_ACCESS(DispatchParameters, ERHIAccess::IndirectArgs)
END_SHADER_PARAMETER_STRUCT()
class FTileClassificationDim : SHADER_PERMUTATION_ENUM_CLASS("DIM_PROBE_OCCLUSION_CLASSIFICATION", LumenProbeHierarchy::EProbeOcclusionClassification);
using FPermutationDomain = TShaderPermutationDomain<FTileClassificationDim>;
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return IsScreenSpaceDiffuseIndirectSupported(Parameters.Platform);
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.CompilerFlags.Add(CFLAG_Wave32);
}
};
IMPLEMENT_GLOBAL_SHADER(FSSRTPrevFrameReductionCS, "/Engine/Private/SSRT/SSRTPrevFrameReduction.usf", "MainCS", SF_Compute);
IMPLEMENT_GLOBAL_SHADER(FSSRTDiffuseTileClassificationCS, "/Engine/Private/SSRT/SSRTTileClassification.usf", "MainCS", SF_Compute);
IMPLEMENT_GLOBAL_SHADER(FScreenSpaceReflectionsPS, "/Engine/Private/SSRT/SSRTReflections.usf", "ScreenSpaceReflectionsPS", SF_Pixel);
IMPLEMENT_GLOBAL_SHADER(FScreenSpaceReflectionsTileVS, "/Engine/Private/SingleLayerWaterComposite.usf", "WaterTileVS", SF_Vertex);
IMPLEMENT_GLOBAL_SHADER(FScreenSpaceReflectionsStencilPS, "/Engine/Private/SSRT/SSRTReflections.usf", "ScreenSpaceReflectionsStencilPS", SF_Pixel);
IMPLEMENT_GLOBAL_SHADER(FScreenSpaceCastStandaloneRayCS, "/Engine/Private/SSRT/SSRTDiffuseIndirect.usf", "MainCS", SF_Compute);
IMPLEMENT_GLOBAL_SHADER(FSetupScreenSpaceTraceProbeCS, "/Engine/Private/SSRT/SSRTTraceProbe.usf", "SetupIndirectParametersCS", SF_Compute);
IMPLEMENT_GLOBAL_SHADER(FScreenSpaceTraceProbeCS, "/Engine/Private/SSRT/SSRTTraceProbe.usf", "MainCS", SF_Compute);
IMPLEMENT_GLOBAL_SHADER(FSetupScreenSpaceProbeOcclusionCS, "/Engine/Private/SSRT/SSRTTraceProbeOcclusion.usf", "MainCS", SF_Compute);
IMPLEMENT_GLOBAL_SHADER(FScreenSpaceCastProbeOcclusionCS, "/Engine/Private/SSRT/SSRTTraceProbeOcclusion.usf", "MainCS", SF_Compute);
void GetSSRShaderOptionsForQuality(ESSRQuality Quality, IScreenSpaceDenoiser::FReflectionsRayTracingConfig* OutRayTracingConfigs)
{
if (Quality == ESSRQuality::VisualizeSSR)
{
OutRayTracingConfigs->RayCountPerPixel = 12;
}
else if (Quality == ESSRQuality::Epic)
{
OutRayTracingConfigs->RayCountPerPixel = 12;
}
else if (Quality == ESSRQuality::High)
{
OutRayTracingConfigs->RayCountPerPixel = 4;
}
else if (Quality == ESSRQuality::Medium)
{
OutRayTracingConfigs->RayCountPerPixel = 1;
}
else if (Quality == ESSRQuality::Low)
{
OutRayTracingConfigs->RayCountPerPixel = 1;
}
else
{
check(0);
}
}
FIntPoint GetSSRTGroupSizeForSampleCount(int32 RayCountPerPixel)
{
FIntPoint GroupCount(1, 1);
if (RayCountPerPixel == 4)
{
GroupCount = FIntPoint(8, 8);
}
else if (RayCountPerPixel == 8)
{
GroupCount = FIntPoint(8, 4);
}
else if (RayCountPerPixel == 16)
{
GroupCount = FIntPoint(4, 4);
}
else if (RayCountPerPixel == 32)
{
GroupCount = FIntPoint(4, 2);
}
else
{
check(0);
}
check(GroupCount.X * GroupCount.Y * RayCountPerPixel == 256);
return GroupCount;
}
void GetSSRTGIShaderOptionsForQuality(int32 Quality, int32* OutRayCountPerPixel)
{
if (Quality == 1)
{
*OutRayCountPerPixel = 4;
}
else if (Quality == 2)
{
*OutRayCountPerPixel = 8;
}
else if (Quality == 3)
{
*OutRayCountPerPixel = 16;
}
else if (Quality == 4)
{
*OutRayCountPerPixel = 32;
}
else
{
check(0);
}
}
} // namespace
namespace ScreenSpaceRayTracing
{
void GetSSRQualityForView(const FViewInfo& View, ESSRQuality* OutQuality, IScreenSpaceDenoiser::FReflectionsRayTracingConfig* OutRayTracingConfigs)
{
check(ShouldRenderScreenSpaceReflections(View));
int32 SSRQualityCVar = FMath::Clamp(CVarSSRQuality.GetValueOnRenderThread(), 0, int32(ESSRQuality::MAX) - 1);
if (View.Family->EngineShowFlags.VisualizeSSR)
{
*OutQuality = ESSRQuality::VisualizeSSR;
return;
}
else if (View.FinalPostProcessSettings.ScreenSpaceReflectionQuality >= 80.0f && SSRQualityCVar >= 4)
{
*OutQuality = ESSRQuality::Epic;
}
else if (View.FinalPostProcessSettings.ScreenSpaceReflectionQuality >= 60.0f && SSRQualityCVar >= 3)
{
*OutQuality = ESSRQuality::High;
}
else if (View.FinalPostProcessSettings.ScreenSpaceReflectionQuality >= 40.0f && SSRQualityCVar >= 2)
{
*OutQuality = ESSRQuality::Medium;
}
else
{
*OutQuality = ESSRQuality::Low;
}
GetSSRShaderOptionsForQuality(*OutQuality, OutRayTracingConfigs);
}
FPrevSceneColorMip ReducePrevSceneColorMip(
FRDGBuilder& GraphBuilder,
const FSceneTextureParameters& SceneTextures,
const FViewInfo& View)
{
RDG_EVENT_SCOPE(GraphBuilder, "SSGI SceneColorReduction");
FRDGTexture* FurthestHZBTexture = View.HZB;
FRDGTexture* ClosestHZBTexture = View.ClosestHZB;
// Number of mip skipped at the begining of the mip chain.
const int32 DownSamplingMip = 1;
// Number of mip in the mip chain
const int32 kNumMips = 5;
bool bUseLeakFree = View.PrevViewInfo.ScreenSpaceRayTracingInput != nullptr && View.PrevViewInfo.DepthBuffer != nullptr;
check(bUseLeakFree == true);
// Allocate FPrevSceneColorMip.
FPrevSceneColorMip PrevSceneColorMip;
{
FIntPoint RequiredSize = SceneTextures.SceneDepthTexture->Desc.Extent / (1 << DownSamplingMip);
int32 QuantizeMultiple = 1 << (kNumMips - 1);
FIntPoint QuantizedSize = FIntPoint::DivideAndRoundUp(RequiredSize, QuantizeMultiple);
FRDGTextureDesc Desc = FRDGTextureDesc::Create2D(
FIntPoint(QuantizeMultiple * QuantizedSize.X, QuantizeMultiple * QuantizedSize.Y),
PF_FloatR11G11B10,
FClearValueBinding::None,
TexCreate_ShaderResource | TexCreate_UAV);
Desc.NumMips = kNumMips;
PrevSceneColorMip.SceneColor = GraphBuilder.CreateTexture(Desc, TEXT("SSRTReducedSceneColor"));
if (bUseLeakFree)
{
Desc.Format = PF_R8;
PrevSceneColorMip.SceneAlpha = GraphBuilder.CreateTexture(Desc, TEXT("SSRTReducedSceneAlpha"));
}
}
FSSRTPrevFrameReductionCS::FParameters DefaultPassParameters;
{
DefaultPassParameters.SceneTextures = SceneTextures;
DefaultPassParameters.View = View.ViewUniformBuffer;
DefaultPassParameters.ReducedSceneColorSize = FVector2f(
PrevSceneColorMip.SceneColor->Desc.Extent.X, PrevSceneColorMip.SceneColor->Desc.Extent.Y);
DefaultPassParameters.ReducedSceneColorTexelSize = FVector2f(
1.0f / float(PrevSceneColorMip.SceneColor->Desc.Extent.X), 1.0f / float(PrevSceneColorMip.SceneColor->Desc.Extent.Y));
}
{
FSSRTPrevFrameReductionCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FSSRTPrevFrameReductionCS::FParameters>();
*PassParameters = DefaultPassParameters;
FIntPoint ViewportOffset;
FIntPoint ViewportExtent;
FIntPoint BufferSize;
if (bUseLeakFree)
{
BufferSize = View.PrevViewInfo.ScreenSpaceRayTracingInput->GetDesc().Extent;
ViewportOffset = View.PrevViewInfo.ViewRect.Min;
ViewportExtent = View.PrevViewInfo.ViewRect.Size();
PassParameters->PrevSceneColor = GraphBuilder.RegisterExternalTexture(View.PrevViewInfo.ScreenSpaceRayTracingInput);
PassParameters->PrevSceneColorSampler = TStaticSamplerState<SF_Point>::GetRHI();
PassParameters->PrevSceneDepth = GraphBuilder.RegisterExternalTexture(View.PrevViewInfo.DepthBuffer);
PassParameters->PrevSceneDepthSampler = TStaticSamplerState<SF_Bilinear>::GetRHI();
}
else
{
BufferSize = View.PrevViewInfo.TemporalAAHistory.ReferenceBufferSize;
ViewportOffset = View.PrevViewInfo.TemporalAAHistory.ViewportRect.Min;
ViewportExtent = View.PrevViewInfo.TemporalAAHistory.ViewportRect.Size();
PassParameters->PrevSceneColor = GraphBuilder.RegisterExternalTexture(View.PrevViewInfo.TemporalAAHistory.RT[0]);
PassParameters->PrevSceneColorSampler = TStaticSamplerState<SF_Bilinear>::GetRHI();
}
float InvBufferSizeX = 1.f / float(BufferSize.X);
float InvBufferSizeY = 1.f / float(BufferSize.Y);
PassParameters->PrevBufferBilinearUVMinMax = FVector4f(
(ViewportOffset.X + 0.5f) * InvBufferSizeX,
(ViewportOffset.Y + 0.5f) * InvBufferSizeY,
(ViewportOffset.X + ViewportExtent.X - 0.5f) * InvBufferSizeX,
(ViewportOffset.Y + ViewportExtent.Y - 0.5f) * InvBufferSizeY);
PassParameters->PrevSceneColorPreExposureCorrection = View.PreExposure / View.PrevViewInfo.SceneColorPreExposure;
PassParameters->MinimumLuminance = CVarSSGIMinimumLuminance.GetValueOnRenderThread();
PassParameters->SkyDistance = CVarSSGISkyDistance.GetValueOnRenderThread();
PassParameters->PrevScreenPositionScaleBias = FVector4f(
ViewportExtent.X * 0.5f / BufferSize.X,
-ViewportExtent.Y * 0.5f / BufferSize.Y,
(ViewportExtent.X * 0.5f + ViewportOffset.X) / BufferSize.X,
(ViewportExtent.Y * 0.5f + ViewportOffset.Y) / BufferSize.Y);
for (int32 MipLevel = 0; MipLevel < (PassParameters->ReducedSceneColorOutput.Num() - DownSamplingMip); MipLevel++)
{
PassParameters->ReducedSceneColorOutput[DownSamplingMip + MipLevel] = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(PrevSceneColorMip.SceneColor, MipLevel));
if (PrevSceneColorMip.SceneAlpha)
PassParameters->ReducedSceneAlphaOutput[DownSamplingMip + MipLevel] = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(PrevSceneColorMip.SceneAlpha, MipLevel));
}
FSSRTPrevFrameReductionCS::FPermutationDomain PermutationVector;
PermutationVector.Set<FSSRTPrevFrameReductionCS::FLowerMips>(false);
PermutationVector.Set<FSSRTPrevFrameReductionCS::FLeakFree>(bUseLeakFree);
TShaderMapRef<FSSRTPrevFrameReductionCS> ComputeShader(View.ShaderMap, PermutationVector);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("PrevFrameReduction(LeakFree=%i) %dx%d",
bUseLeakFree ? 1 : 0,
View.ViewRect.Width(), View.ViewRect.Height()),
ComputeShader,
PassParameters,
FComputeShaderUtils::GetGroupCount(View.ViewRect.Size(), 8));
}
for (int32 i = 0; i < 1; i++)
{
int32 SrcMip = i * 3 + 2 - DownSamplingMip;
int32 StartDestMip = SrcMip + 1;
int32 Divisor = 1 << (StartDestMip + DownSamplingMip);
FSSRTPrevFrameReductionCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FSSRTPrevFrameReductionCS::FParameters>();
*PassParameters = DefaultPassParameters;
PassParameters->HigherMipTexture = GraphBuilder.CreateSRV(FRDGTextureSRVDesc::CreateForMipLevel(PrevSceneColorMip.SceneColor, SrcMip));
if (bUseLeakFree)
{
PassParameters->HigherMipTextureSampler = TStaticSamplerState<SF_Point>::GetRHI();
PassParameters->HigherAlphaMipTexture = GraphBuilder.CreateSRV(FRDGTextureSRVDesc::CreateForMipLevel(PrevSceneColorMip.SceneAlpha, SrcMip));
PassParameters->HigherAlphaMipTextureSampler = TStaticSamplerState<SF_Point>::GetRHI();
}
else
{
PassParameters->HigherMipTextureSampler = TStaticSamplerState<SF_Bilinear>::GetRHI();
}
PassParameters->HigherMipDownScaleFactor = 1 << (DownSamplingMip + SrcMip);
PassParameters->HigherMipBufferBilinearMax = FVector2f(
(0.5f * View.ViewRect.Width() - 0.5f) / float(PrevSceneColorMip.SceneColor->Desc.Extent.X),
(0.5f * View.ViewRect.Height() - 0.5f) / float(PrevSceneColorMip.SceneColor->Desc.Extent.Y));
PassParameters->ViewportUVToHZBBufferUV = FVector2f(
float(View.ViewRect.Width()) / float(2 * View.HZBMipmap0Size.X),
float(View.ViewRect.Height()) / float(2 * View.HZBMipmap0Size.Y));
PassParameters->FurthestHZBTexture = FurthestHZBTexture;
PassParameters->FurthestHZBTextureSampler = TStaticSamplerState<SF_Point>::GetRHI();
for (int32 MipLevel = 0; MipLevel < PassParameters->ReducedSceneColorOutput.Num(); MipLevel++)
{
PassParameters->ReducedSceneColorOutput[MipLevel] = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(PrevSceneColorMip.SceneColor, StartDestMip + MipLevel));
if (PrevSceneColorMip.SceneAlpha)
PassParameters->ReducedSceneAlphaOutput[MipLevel] = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(PrevSceneColorMip.SceneAlpha, StartDestMip + MipLevel));
}
FSSRTPrevFrameReductionCS::FPermutationDomain PermutationVector;
PermutationVector.Set<FSSRTPrevFrameReductionCS::FLowerMips>(true);
PermutationVector.Set<FSSRTPrevFrameReductionCS::FLeakFree>(bUseLeakFree);
TShaderMapRef<FSSRTPrevFrameReductionCS> ComputeShader(View.ShaderMap, PermutationVector);
ClearUnusedGraphResources(ComputeShader, PassParameters);
GraphBuilder.AddPass(
RDG_EVENT_NAME("PrevFrameReduction(LeakFree=%i) %dx%d",
bUseLeakFree ? 1 : 0,
View.ViewRect.Width() / Divisor, View.ViewRect.Height() / Divisor),
PassParameters,
ERDGPassFlags::Compute,
[PassParameters, ComputeShader, &View, Divisor](FRHICommandList& RHICmdList)
{
FComputeShaderUtils::Dispatch(RHICmdList, ComputeShader, *PassParameters, FComputeShaderUtils::GetGroupCount(View.ViewRect.Size(), 8 * Divisor));
});
}
return PrevSceneColorMip;
}
FSSRTTileClassificationParameters RenderHorizonTileClassification(
FRDGBuilder& GraphBuilder,
const FSceneTextureParameters& SceneTextures,
const FViewInfo& View)
{
FIntPoint SceneTexturesExtent = SceneTextures.SceneDepthTexture->Desc.Extent;
FRDGTextureRef FurthestHZBTexture = View.HZB;
FRDGTextureRef ClosestHZBTexture = View.ClosestHZB;
FSSRTTileClassificationParameters ClassificationParameters;
{
FRDGBufferRef TileClassificationBuffer;
{
FIntPoint MaxTileBufferExtent = FIntPoint::DivideAndRoundUp(SceneTexturesExtent, 8);
int32 MaxTileCount = MaxTileBufferExtent.X * MaxTileBufferExtent.Y;
ClassificationParameters.TileBufferExtent = FIntPoint::DivideAndRoundUp(View.ViewRect.Size(), 8);
ClassificationParameters.ViewTileCount = ClassificationParameters.TileBufferExtent.X * ClassificationParameters.TileBufferExtent.Y;
TileClassificationBuffer = GraphBuilder.CreateBuffer(
FRDGBufferDesc::CreateStructuredDesc(sizeof(float) * 16, MaxTileCount), TEXT("SSRTTileClassification"));
ClassificationParameters.TileClassificationBuffer = GraphBuilder.CreateSRV(TileClassificationBuffer);
}
FIntPoint ThreadCount = ClassificationParameters.TileBufferExtent;
FSSRTDiffuseTileClassificationCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FSSRTDiffuseTileClassificationCS::FParameters>();
PassParameters->SamplePixelToHZBUV = FVector2f(
0.5f / float(FurthestHZBTexture->Desc.Extent.X),
0.5f / float(FurthestHZBTexture->Desc.Extent.Y));
PassParameters->FurthestHZBTexture = FurthestHZBTexture;
PassParameters->FurthestHZBTextureSampler = TStaticSamplerState<SF_Point>::GetRHI();
PassParameters->ClosestHZBTexture = ClosestHZBTexture;
PassParameters->ClosestHZBTextureSampler = TStaticSamplerState<SF_Point>::GetRHI();
PassParameters->View = View.ViewUniformBuffer;
PassParameters->TileClassificationParameters = ClassificationParameters;
PassParameters->TileClassificationBufferOutput = GraphBuilder.CreateUAV(TileClassificationBuffer);
{
FRDGTextureDesc DebugDesc = FRDGTextureDesc::Create2D(
FIntPoint::DivideAndRoundUp(SceneTexturesExtent, 8),
PF_FloatRGBA,
FClearValueBinding::Transparent,
TexCreate_ShaderResource | TexCreate_UAV);
PassParameters->DebugOutput = GraphBuilder.CreateUAV(GraphBuilder.CreateTexture(DebugDesc, TEXT("DebugSSRTTiles")));
}
TShaderMapRef<FSSRTDiffuseTileClassificationCS> ComputeShader(View.ShaderMap);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("ScreenSpaceDiffuseClassification %dx%d", ClassificationParameters.TileBufferExtent.X, ClassificationParameters.TileBufferExtent.Y),
ComputeShader,
PassParameters,
FComputeShaderUtils::GetGroupCount(ClassificationParameters.TileBufferExtent, 8));
}
return ClassificationParameters;
}
void RenderScreenSpaceReflections(
FRDGBuilder& GraphBuilder,
const FSceneTextureParameters& SceneTextures,
const FRDGTextureRef CurrentSceneColor,
const FViewInfo& View,
ESSRQuality SSRQuality,
bool bDenoiser,
IScreenSpaceDenoiser::FReflectionsInputs* DenoiserInputs,
bool bSingleLayerWater,
FTiledReflection* TiledScreenSpaceReflection)
{
FRDGTextureRef InputColor = CurrentSceneColor;
if (SSRQuality != ESSRQuality::VisualizeSSR)
{
if (View.PrevViewInfo.CustomSSRInput.IsValid())
{
InputColor = GraphBuilder.RegisterExternalTexture(View.PrevViewInfo.CustomSSRInput.RT[0]);
}
else if (GSSRHalfResSceneColor && View.PrevViewInfo.HalfResTemporalAAHistory.IsValid())
{
InputColor = GraphBuilder.RegisterExternalTexture(View.PrevViewInfo.HalfResTemporalAAHistory);
}
else if (View.PrevViewInfo.TemporalAAHistory.IsValid())
{
InputColor = GraphBuilder.RegisterExternalTexture(View.PrevViewInfo.TemporalAAHistory.RT[0]);
}
}
const bool SSRStencilPrePass = CVarSSRStencil.GetValueOnRenderThread() != 0 && SSRQuality != ESSRQuality::VisualizeSSR && TiledScreenSpaceReflection == nullptr;
// Alloc inputs for denoising.
{
FRDGTextureDesc Desc = FRDGTextureDesc::Create2D(
View.GetSceneTexturesConfig().Extent,
PF_FloatRGBA, FClearValueBinding(FLinearColor(0, 0, 0, 0)),
TexCreate_RenderTargetable | TexCreate_ShaderResource | TexCreate_UAV);
Desc.Flags |= GFastVRamConfig.SSR;
DenoiserInputs->Color = GraphBuilder.CreateTexture(Desc, TEXT("ScreenSpaceReflections"));
if (bDenoiser)
{
Desc.Format = PF_R16F;
DenoiserInputs->RayHitDistance = GraphBuilder.CreateTexture(Desc, TEXT("ScreenSpaceReflectionsHitDistance"));
}
}
IScreenSpaceDenoiser::FReflectionsRayTracingConfig RayTracingConfigs;
GetSSRShaderOptionsForQuality(SSRQuality, &RayTracingConfigs);
FSSRCommonParameters CommonParameters;
CommonParameters.SSRParams = ComputeSSRParams(View, SSRQuality, false);
CommonParameters.ViewUniformBuffer = View.ViewUniformBuffer;
CommonParameters.SceneTextures = SceneTextures;
// Pipe down a mid grey texture when not using TAA's history to avoid wrongly reprojecting current scene color as if previous frame's TAA history.
if (InputColor == CurrentSceneColor || !CommonParameters.SceneTextures.GBufferVelocityTexture)
{
// Technically should be 32767.0f / 65535.0f to perfectly null out DecodeVelocityFromTexture(), but 0.5f is good enough.
CommonParameters.SceneTextures.GBufferVelocityTexture = GraphBuilder.RegisterExternalTexture(GSystemTextures.MidGreyDummy);
}
FRenderTargetBindingSlots RenderTargets;
RenderTargets[0] = FRenderTargetBinding(DenoiserInputs->Color, ERenderTargetLoadAction::ENoAction);
if (bDenoiser)
{
RenderTargets[1] = FRenderTargetBinding(DenoiserInputs->RayHitDistance, ERenderTargetLoadAction::ENoAction);
}
// Do a pre pass that output 0, or set a stencil mask to run the more expensive pixel shader.
if (SSRStencilPrePass)
{
// Also bind the depth buffer
RenderTargets.DepthStencil = FDepthStencilBinding(
SceneTextures.SceneDepthTexture,
ERenderTargetLoadAction::ENoAction,
ERenderTargetLoadAction::ELoad,
FExclusiveDepthStencil::DepthNop_StencilWrite);
FScreenSpaceReflectionsStencilPS::FPermutationDomain PermutationVector;
PermutationVector.Set<FSSROutputForDenoiser>(bDenoiser);
FScreenSpaceReflectionsStencilPS::FParameters* PassParameters = GraphBuilder.AllocParameters<FScreenSpaceReflectionsStencilPS::FParameters>();
PassParameters->CommonParameters = CommonParameters;
PassParameters->Strata = Strata::BindStrataGlobalUniformParameters(View);
PassParameters->RenderTargets = RenderTargets;
TShaderMapRef<FScreenSpaceReflectionsStencilPS> PixelShader(View.ShaderMap, PermutationVector);
ClearUnusedGraphResources(PixelShader, PassParameters);
RDG_GPU_STAT_SCOPE(GraphBuilder, ScreenSpaceReflections);
GraphBuilder.AddPass(
RDG_EVENT_NAME("SSR StencilSetup %dx%d", View.ViewRect.Width(), View.ViewRect.Height()),
PassParameters,
ERDGPassFlags::Raster,
[PassParameters, &View, PixelShader](FRHICommandList& RHICmdList)
{
RHICmdList.SetViewport(View.ViewRect.Min.X, View.ViewRect.Min.Y, 0.0f, View.ViewRect.Max.X, View.ViewRect.Max.Y, 1.0f);
FGraphicsPipelineStateInitializer GraphicsPSOInit;
FPixelShaderUtils::InitFullscreenPipelineState(RHICmdList, View.ShaderMap, PixelShader, /* out */ GraphicsPSOInit);
// Clobers the stencil to pixel that should not compute SSR
GraphicsPSOInit.DepthStencilState = TStaticDepthStencilState<false, CF_Always, true, CF_Always, SO_Replace, SO_Replace, SO_Replace>::GetRHI();
SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit, 0x80);
SetShaderParameters(RHICmdList, PixelShader, PixelShader.GetPixelShader(), *PassParameters);
FPixelShaderUtils::DrawFullscreenTriangle(RHICmdList);
});
}
// Adds SSR pass.
auto SetSSRParameters = [&](auto* PassParameters)
{
{
const FVector2D HZBUvFactor(
float(View.ViewRect.Width()) / float(2 * View.HZBMipmap0Size.X),
float(View.ViewRect.Height()) / float(2 * View.HZBMipmap0Size.Y));
PassParameters->HZBUvFactorAndInvFactor = FVector4f(
HZBUvFactor.X,
HZBUvFactor.Y,
1.0f / HZBUvFactor.X,
1.0f / HZBUvFactor.Y);
}
{
FIntPoint ViewportOffset = View.ViewRect.Min;
FIntPoint ViewportExtent = View.ViewRect.Size();
FIntPoint BufferSize = SceneTextures.SceneDepthTexture->Desc.Extent;
if (View.PrevViewInfo.CustomSSRInput.IsValid())
{
ViewportOffset = View.PrevViewInfo.CustomSSRInput.ViewportRect.Min;
ViewportExtent = View.PrevViewInfo.CustomSSRInput.ViewportRect.Size();
BufferSize = View.PrevViewInfo.CustomSSRInput.ReferenceBufferSize;
ensure(ViewportExtent.X > 0 && ViewportExtent.Y > 0);
ensure(BufferSize.X > 0 && BufferSize.Y > 0);
}
else if (View.PrevViewInfo.TemporalAAHistory.IsValid())
{
ViewportOffset = View.PrevViewInfo.TemporalAAHistory.ViewportRect.Min;
ViewportExtent = View.PrevViewInfo.TemporalAAHistory.ViewportRect.Size();
BufferSize = View.PrevViewInfo.TemporalAAHistory.ReferenceBufferSize;
ensure(ViewportExtent.X > 0 && ViewportExtent.Y > 0);
ensure(BufferSize.X > 0 && BufferSize.Y > 0);
}
FVector2D InvBufferSize(1.0f / float(BufferSize.X), 1.0f / float(BufferSize.Y));
PassParameters->PrevScreenPositionScaleBias = FVector4f(
ViewportExtent.X * 0.5f * InvBufferSize.X,
-ViewportExtent.Y * 0.5f * InvBufferSize.Y,
(ViewportExtent.X * 0.5f + ViewportOffset.X) * InvBufferSize.X,
(ViewportExtent.Y * 0.5f + ViewportOffset.Y) * InvBufferSize.Y);
PassParameters->ScreenSpaceRayTracingDebugOutput = CreateScreenSpaceRayTracingDebugUAV(GraphBuilder, DenoiserInputs->Color->Desc, TEXT("DebugSSR"), true);
}
PassParameters->PrevSceneColorPreExposureCorrection = InputColor != CurrentSceneColor ? View.PreExposure / View.PrevViewInfo.SceneColorPreExposure : 1.0f;
PassParameters->ShouldReflectOnlyWater = bSingleLayerWater ? 1u : 0u;
PassParameters->SceneColor = InputColor;
PassParameters->SceneColorSampler = GSSRHalfResSceneColor ? TStaticSamplerState<SF_Bilinear>::GetRHI() : TStaticSamplerState<SF_Point>::GetRHI();
PassParameters->HZB = View.HZB;
PassParameters->HZBSampler = TStaticSamplerState<SF_Point>::GetRHI();
};
FScreenSpaceReflectionsPS::FPermutationDomain PermutationVector;
PermutationVector.Set<FSSRQualityDim>(SSRQuality);
PermutationVector.Set<FSSROutputForDenoiser>(bDenoiser);
FScreenSpaceReflectionsPS::FParameters* PassParameters = GraphBuilder.AllocParameters<FScreenSpaceReflectionsPS::FParameters>();
PassParameters->CommonParameters = CommonParameters;
SetSSRParameters(&PassParameters->SSRPassCommonParameter);
PassParameters->Strata = Strata::BindStrataGlobalUniformParameters(View);
PassParameters->RenderTargets = RenderTargets;
TShaderMapRef<FScreenSpaceReflectionsPS> PixelShader(View.ShaderMap, PermutationVector);
RDG_GPU_STAT_SCOPE(GraphBuilder, ScreenSpaceReflections);
if (TiledScreenSpaceReflection == nullptr)
{
ClearUnusedGraphResources(PixelShader, PassParameters);
GraphBuilder.AddPass(
RDG_EVENT_NAME("SSR RayMarch(Quality=%d RayPerPixel=%d%s) %dx%d",
SSRQuality, RayTracingConfigs.RayCountPerPixel, bDenoiser ? TEXT(" DenoiserOutput") : TEXT(""),
View.ViewRect.Width(), View.ViewRect.Height()),
PassParameters,
ERDGPassFlags::Raster,
[PassParameters, &View, PixelShader, SSRStencilPrePass](FRHICommandList& RHICmdList)
{
RHICmdList.SetViewport(View.ViewRect.Min.X, View.ViewRect.Min.Y, 0.0f, View.ViewRect.Max.X, View.ViewRect.Max.Y, 1.0f);
FGraphicsPipelineStateInitializer GraphicsPSOInit;
FPixelShaderUtils::InitFullscreenPipelineState(RHICmdList, View.ShaderMap, PixelShader, /* out */ GraphicsPSOInit);
if (SSRStencilPrePass)
{
// Clobers the stencil to pixel that should not compute SSR
GraphicsPSOInit.DepthStencilState = TStaticDepthStencilState<false, CF_Always, true, CF_Equal, SO_Keep, SO_Keep, SO_Keep>::GetRHI();
}
SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit, 0x80);
SetShaderParameters(RHICmdList, PixelShader, PixelShader.GetPixelShader(), *PassParameters);
FPixelShaderUtils::DrawFullscreenTriangle(RHICmdList);
});
}
else
{
check(TiledScreenSpaceReflection->TileSize == 8); // WORK_TILE_SIZE
FScreenSpaceReflectionsTileVS::FPermutationDomain VsPermutationVector;
TShaderMapRef<FScreenSpaceReflectionsTileVS> VertexShader(View.ShaderMap, VsPermutationVector);
PassParameters->TileListData = TiledScreenSpaceReflection->TileListDataBufferSRV;
PassParameters->IndirectDrawParameter = TiledScreenSpaceReflection->DrawIndirectParametersBuffer;
ClearUnusedGraphResources(VertexShader, PixelShader, PassParameters);
GraphBuilder.AddPass(
RDG_EVENT_NAME("SSR RayMarch(Quality=%d RayPerPixel=%d%s) %dx%d",
SSRQuality, RayTracingConfigs.RayCountPerPixel, bDenoiser ? TEXT(" DenoiserOutput") : TEXT(""),
View.ViewRect.Width(), View.ViewRect.Height()),
PassParameters,
ERDGPassFlags::Raster,
[PassParameters, &View, VertexShader, PixelShader, SSRStencilPrePass](FRHICommandList& RHICmdList)
{
RHICmdList.SetViewport(View.ViewRect.Min.X, View.ViewRect.Min.Y, 0.0f, View.ViewRect.Max.X, View.ViewRect.Max.Y, 1.0f);
FGraphicsPipelineStateInitializer GraphicsPSOInit;
FPixelShaderUtils::InitFullscreenPipelineState(RHICmdList, View.ShaderMap, PixelShader, /* out */ GraphicsPSOInit);
if (SSRStencilPrePass)
{
// Clobers the stencil to pixel that should not compute SSR
GraphicsPSOInit.DepthStencilState = TStaticDepthStencilState<false, CF_Always, true, CF_Equal, SO_Keep, SO_Keep, SO_Keep>::GetRHI();
}
GraphicsPSOInit.PrimitiveType = GRHISupportsRectTopology ? PT_RectList : PT_TriangleList;
GraphicsPSOInit.BoundShaderState.VertexDeclarationRHI = GEmptyVertexDeclaration.VertexDeclarationRHI;
GraphicsPSOInit.BoundShaderState.VertexShaderRHI = VertexShader.GetVertexShader();
GraphicsPSOInit.BoundShaderState.PixelShaderRHI = PixelShader.GetPixelShader();
SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit, 0x80);
SetShaderParameters(RHICmdList, VertexShader, VertexShader.GetVertexShader(), *PassParameters);
SetShaderParameters(RHICmdList, PixelShader, PixelShader.GetPixelShader(), *PassParameters);
PassParameters->IndirectDrawParameter->MarkResourceAsUsed();
RHICmdList.DrawPrimitiveIndirect(PassParameters->IndirectDrawParameter->GetIndirectRHICallBuffer(), 0);
});
}
} // RenderScreenSpaceReflections()
int32 GetSSGIRayCountPerTracingPixel()
{
const int32 Quality = FMath::Clamp(CVarSSGIQuality.GetValueOnRenderThread(), 1, 4);
int32 RayCountPerPixel;
GetSSRTGIShaderOptionsForQuality(Quality, /* out */ &RayCountPerPixel);
return RayCountPerPixel;
}
IScreenSpaceDenoiser::FDiffuseIndirectInputs CastStandaloneDiffuseIndirectRays(
FRDGBuilder& GraphBuilder,
const HybridIndirectLighting::FCommonParameters& CommonParameters,
const FPrevSceneColorMip& PrevSceneColor,
const FViewInfo& View)
{
const int32 Quality = FMath::Clamp(CVarSSGIQuality.GetValueOnRenderThread(), 1, 4);
int32 RayCountPerPixel;
GetSSRTGIShaderOptionsForQuality(Quality, &RayCountPerPixel);
check(RayCountPerPixel == CommonParameters.RayCountPerPixel);
FIntPoint GroupSize = GetSSRTGroupSizeForSampleCount(CommonParameters.RayCountPerPixel);
// Alloc output for the denoiser.
IScreenSpaceDenoiser::FDiffuseIndirectInputs DenoiserInputs;
{
FRDGTextureDesc Desc = FRDGTextureDesc::Create2D(
CommonParameters.SceneTextures.SceneDepthTexture->Desc.Extent / CommonParameters.DownscaleFactor,
PF_FloatRGBA,
FClearValueBinding::Transparent,
TexCreate_ShaderResource | TexCreate_UAV);
DenoiserInputs.Color = GraphBuilder.CreateTexture(Desc, TEXT("SSRTDiffuseIndirect"));
Desc.Format = PF_R16F;
Desc.Flags |= TexCreate_RenderTargetable;
DenoiserInputs.AmbientOcclusionMask = GraphBuilder.CreateTexture(Desc, TEXT("SSRTAmbientOcclusion"));
}
FScreenSpaceCastStandaloneRayCS::FParameters* PassParameters =
GraphBuilder.AllocParameters<FScreenSpaceCastStandaloneRayCS::FParameters>();
ScreenSpaceRayTracing::SetupCommonScreenSpaceRayParameters(GraphBuilder, CommonParameters, PrevSceneColor, View, /* out */ &PassParameters->CommonParameters);
PassParameters->IndirectDiffuseOutput = GraphBuilder.CreateUAV(DenoiserInputs.Color);
PassParameters->AmbientOcclusionOutput = GraphBuilder.CreateUAV(DenoiserInputs.AmbientOcclusionMask);
FScreenSpaceCastStandaloneRayCS::FPermutationDomain PermutationVector;
PermutationVector.Set<FScreenSpaceCastStandaloneRayCS::FQualityDim>(Quality);
TShaderMapRef<FScreenSpaceCastStandaloneRayCS> ComputeShader(View.ShaderMap, PermutationVector);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("SSGI Standalone(Quality=%d RayPerPixel=%d) %dx%d",
Quality, CommonParameters.RayCountPerPixel, CommonParameters.TracingViewportSize.X, CommonParameters.TracingViewportSize.Y),
ComputeShader,
PassParameters,
FComputeShaderUtils::GetGroupCount(CommonParameters.TracingViewportSize, GroupSize));
return DenoiserInputs;
}
void TraceProbe(
FRDGBuilder& GraphBuilder,
const FViewInfo& View,
const FSceneTextureParameters& SceneTextures,
const FPrevSceneColorMip& PrevSceneColor,
const LumenProbeHierarchy::FHierarchyParameters& HierarchyParameters,
const LumenProbeHierarchy::FIndirectLightingAtlasParameters& IndirectLightingAtlasParameters)
{
RDG_EVENT_SCOPE(GraphBuilder, "SSGI ProbeTracing");
FRDGBufferRef DispatchParameters = GraphBuilder.CreateBuffer(
FRDGBufferDesc::CreateIndirectDesc<FRHIDispatchIndirectParameters>(LumenProbeHierarchy::kProbeMaxHierarchyDepth),
TEXT("LumenVoxelTraceProbeDispatch"));
{
FSetupScreenSpaceTraceProbeCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FSetupScreenSpaceTraceProbeCS::FParameters>();
PassParameters->HierarchyParameters = HierarchyParameters;
PassParameters->DispatchParametersOutput = GraphBuilder.CreateUAV(DispatchParameters);
TShaderMapRef<FSetupScreenSpaceTraceProbeCS> ComputeShader(View.ShaderMap);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("SSGI SetupTraceProbe"),
ComputeShader,
PassParameters,
FIntVector(1, 1, 1));
}
FRDGTextureUAVRef ProbeAtlasColorOutput = GraphBuilder.CreateUAV(IndirectLightingAtlasParameters.ProbeAtlasColor, ERDGUnorderedAccessViewFlags::SkipBarrier);
FRDGTextureUAVRef ProbeAtlasSampleMaskOutput = GraphBuilder.CreateUAV(IndirectLightingAtlasParameters.ProbeAtlasSampleMask, ERDGUnorderedAccessViewFlags::SkipBarrier);
for (int32 HierarchyLevelId = 0; HierarchyLevelId < HierarchyParameters.HierarchyDepth; HierarchyLevelId++)
{
FScreenSpaceTraceProbeCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FScreenSpaceTraceProbeCS::FParameters>();
ScreenSpaceRayTracing::SetupCommonScreenSpaceRayParameters(GraphBuilder, SceneTextures, PrevSceneColor, View, /* out */ &PassParameters->CommonParameters);
PassParameters->HierarchyParameters = HierarchyParameters;
PassParameters->LevelParameters = LumenProbeHierarchy::GetLevelParameters(HierarchyParameters, HierarchyLevelId);
PassParameters->DispatchParameters = DispatchParameters;
// Compute the mip level at wich the trace should start from.
{
float ProbePixelRadius = LumenProbeHierarchy::kProbeHierarchyMinPixelRadius * float(1 << PassParameters->LevelParameters.LevelId);
float TexelCount = PassParameters->LevelParameters.LevelResolution * 4;
// Amount of noise tolerated by sampling slightly more detailed mip level.
float kTolerableMipNoise = 1.0;
PassParameters->FurthestHZBStartMipLevel = float(FMath::FloorToInt(FMath::Log2(ProbePixelRadius * (2.0f * PI / TexelCount)))) - kTolerableMipNoise;
}
PassParameters->ProbeAtlasColorOutput = ProbeAtlasColorOutput;
PassParameters->ProbeAtlasSampleMaskOutput = ProbeAtlasSampleMaskOutput;
FScreenSpaceTraceProbeCS::FPermutationDomain PermutationVector;
PermutationVector.Set<LumenProbeHierarchy::FProbeTracingPermutationDim>(
LumenProbeHierarchy::GetProbeTracingPermutation(PassParameters->LevelParameters));
TShaderMapRef<FScreenSpaceTraceProbeCS> ComputeShader(View.ShaderMap, PermutationVector);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("SSGI TraceProbe(Level=%d Res=%d SuperSample=%d)",
PassParameters->LevelParameters.LevelId,
PassParameters->LevelParameters.LevelResolution,
PassParameters->LevelParameters.LevelSuperSampling),
ComputeShader,
PassParameters,
DispatchParameters,
/* IndirectArgOffset = */ sizeof(FRHIDispatchIndirectParameters) * HierarchyLevelId);
}
}
void TraceIndirectProbeOcclusion(
FRDGBuilder& GraphBuilder,
const HybridIndirectLighting::FCommonParameters& CommonParameters,
const FPrevSceneColorMip& PrevSceneColor,
const FViewInfo& View,
const LumenProbeHierarchy::FIndirectLightingProbeOcclusionParameters& ProbeOcclusionParameters)
{
using namespace LumenProbeHierarchy;
RDG_EVENT_SCOPE(GraphBuilder, "SSGI ProbeOcclusion %dx%d",
CommonParameters.TracingViewportSize.X,
CommonParameters.TracingViewportSize.Y);
FRDGBufferRef DispatchParameters;
{
DispatchParameters = GraphBuilder.CreateBuffer(
FRDGBufferDesc::CreateIndirectDesc<FRHIDispatchIndirectParameters>(int32(EProbeOcclusionClassification::MAX) * ProbeOcclusionParameters.DispatchCount),
TEXT("SSGI.ProbeOcclusionDispatchParameters"));
FSetupScreenSpaceProbeOcclusionCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FSetupScreenSpaceProbeOcclusionCS::FParameters>();
PassParameters->MaxTilePerDispatch = ProbeOcclusionParameters.MaxTilePerDispatch;
PassParameters->GlobalClassificationCountersBuffer = ProbeOcclusionParameters.GlobalClassificationCountersBuffer;
PassParameters->DispatchParametersOutput = GraphBuilder.CreateUAV(DispatchParameters);
TShaderMapRef<FSetupScreenSpaceProbeOcclusionCS> ComputeShader(View.ShaderMap);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("SetupScreenSpaceProbeOcclusion"),
ComputeShader,
PassParameters,
FIntVector(ProbeOcclusionParameters.DispatchCount, 1, 1));
}
FScreenSpaceCastProbeOcclusionCS::FParameters ReferencePassParameters;
{
ScreenSpaceRayTracing::SetupCommonScreenSpaceRayParameters(GraphBuilder, CommonParameters, PrevSceneColor, View, /* out */ &ReferencePassParameters.CommonParameters);
ReferencePassParameters.ProbeOcclusionParameters = ProbeOcclusionParameters;
ReferencePassParameters.ProbeOcclusionOutputParameters = CreateProbeOcclusionOutputParameters(
GraphBuilder, ProbeOcclusionParameters, ERDGUnorderedAccessViewFlags::SkipBarrier);
ReferencePassParameters.DispatchParameters = DispatchParameters;
}
for (int32 i = 0; i < int32(EProbeOcclusionClassification::MAX); i++)
{
EProbeOcclusionClassification TileClassification = EProbeOcclusionClassification(i);
FScreenSpaceCastProbeOcclusionCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FScreenSpaceCastProbeOcclusionCS::FParameters>();
*PassParameters = ReferencePassParameters;
FScreenSpaceCastProbeOcclusionCS::FPermutationDomain PermutationVector;
PermutationVector.Set<FScreenSpaceCastProbeOcclusionCS::FTileClassificationDim>(TileClassification);
TShaderMapRef<FScreenSpaceCastProbeOcclusionCS> ComputeShader(View.ShaderMap, PermutationVector);
ClearUnusedGraphResources(ComputeShader, PassParameters);
GraphBuilder.AddPass(
RDG_EVENT_NAME("SSGI ProbeOcclusion(%s)", GetEventName(TileClassification)),
PassParameters,
ERDGPassFlags::Compute,
[PassParameters, ComputeShader, i](FRHICommandList& RHICmdList)
{
FScreenSpaceCastProbeOcclusionCS::FParameters ShaderParameters = *PassParameters;
ShaderParameters.DispatchParameters->MarkResourceAsUsed();
for (int32 DispatchId = 0; DispatchId < ShaderParameters.ProbeOcclusionParameters.DispatchCount; DispatchId++)
{
ShaderParameters.DispatchOffset = DispatchId * ShaderParameters.ProbeOcclusionParameters.MaxTilePerDispatch;
int32 IndirectArgsOffset = sizeof(FRHIDispatchIndirectParameters) * (i + DispatchId * int32(EProbeOcclusionClassification::MAX));
FComputeShaderUtils::DispatchIndirect(
RHICmdList,
ComputeShader,
ShaderParameters,
ShaderParameters.DispatchParameters->GetIndirectRHICallBuffer(),
IndirectArgsOffset);
}
});
}
}
} // namespace ScreenSpaceRayTracing