1408 lines
57 KiB
C++
1408 lines
57 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "ScreenSpaceRayTracing.h"
|
|
#include "DataDrivenShaderPlatformInfo.h"
|
|
#include "RenderGraph.h"
|
|
#include "PixelShaderUtils.h"
|
|
#include "ScreenPass.h"
|
|
#include "ScenePrivate.h"
|
|
#include "SceneTextureParameters.h"
|
|
#include "Substrate/Substrate.h"
|
|
#include "SystemTextures.h"
|
|
#include "VariableRateShadingImageManager.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> CVarSSRCompute(
|
|
TEXT("r.SSR.Compute"), 0,
|
|
TEXT("Use compute for SSR if possible. Only available for non tiled SSR with no stencil prepass currently\n")
|
|
TEXT(" 0 is PS (default), 1 is sync compute, 2 is async compute"),
|
|
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_DRAWCALL_STAT_NAMED(ScreenSpaceReflections, TEXT("ScreenSpace Reflections"));
|
|
DECLARE_GPU_STAT_NAMED(ScreenSpaceDiffuseIndirect, TEXT("Screen Space Diffuse Indirect"));
|
|
|
|
|
|
static bool IsScreenSpaceDiffuseIndirectSupported(EShaderPlatform ShaderPlatform)
|
|
{
|
|
if (IsForwardShadingEnabled(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
|
|
// Note: intentionally allow falling back to SSR from other reflection methods, which may be disabled by scalability
|
|
|| View.FinalPostProcessSettings.ReflectionMethod == EReflectionMethod::None
|
|
|| 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;
|
|
}
|
|
|
|
const EShaderPlatform ShaderPlatform = View.GetShaderPlatform();
|
|
if (IsForwardShadingEnabled(ShaderPlatform) && !IsMobilePlatform(ShaderPlatform))
|
|
{
|
|
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) || ShouldRenderScreenSpaceReflectionsWater(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->HZBParameters = GetHZBParameters(GraphBuilder, View, EHZBType::FurthestHZB);
|
|
OutParameters->ColorTexture = PrevSceneColor.SceneColor;
|
|
OutParameters->ColorTextureSampler = TStaticSamplerState<SF_Point>::GetRHI();
|
|
|
|
OutParameters->AlphaTexture = PrevSceneColor.SceneAlpha;
|
|
OutParameters->AlphaTextureSampler = TStaticSamplerState<SF_Point>::GetRHI();
|
|
|
|
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()
|
|
|
|
static 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);
|
|
}
|
|
|
|
} // namespace ScreenSpaceRayTracing
|
|
|
|
bool UseSingleLayerWaterIndirectDraw(EShaderPlatform ShaderPlatform);
|
|
|
|
namespace
|
|
{
|
|
|
|
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, PrevScreenPositionScaleBias)
|
|
SHADER_PARAMETER(float, PrevSceneColorPreExposureCorrection)
|
|
SHADER_PARAMETER(uint32, ShouldReflectOnlyWater)
|
|
SHADER_PARAMETER_RDG_TEXTURE_SRV(Texture2D, SceneColor)
|
|
SHADER_PARAMETER_SAMPLER(SamplerState, SceneColorSampler)
|
|
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<float4>, ScreenSpaceRayTracingDebugOutput)
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(FHZBParameters, HZBParameters)
|
|
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, 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_SRV(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_STRUCT_INCLUDE(FSceneTextureParameters, SceneTextures)
|
|
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, View)
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(FHZBParameters, HZBParameters)
|
|
|
|
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_STRUCT_REF(FViewUniformShaderParameters, View)
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(FHZBParameters, HZBParameters)
|
|
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(FSubstrateGlobalUniformParameters, Substrate)
|
|
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(FSubstrateGlobalUniformParameters, Substrate)
|
|
RENDER_TARGET_BINDING_SLOTS()
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
};
|
|
|
|
class FScreenSpaceReflectionsCS : public FGlobalShader
|
|
{
|
|
DECLARE_GLOBAL_SHADER(FScreenSpaceReflectionsCS);
|
|
SHADER_USE_PARAMETER_STRUCT(FScreenSpaceReflectionsCS, 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));
|
|
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE_X"), GetThreadGroupSize().X);
|
|
OutEnvironment.SetDefine(TEXT("THREADGROUP_SIZE_Y"), GetThreadGroupSize().Y);
|
|
OutEnvironment.SetDefine(TEXT("COMPUTE_SHADER"), 1);
|
|
}
|
|
|
|
static FIntPoint GetThreadGroupSize()
|
|
{
|
|
return 8;
|
|
}
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(FSSRCommonParameters, CommonParameters)
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(FSSRPassCommonParameters, SSRPassCommonParameter)
|
|
SHADER_PARAMETER_RDG_UNIFORM_BUFFER(FSubstrateGlobalUniformParameters, Substrate)
|
|
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<float4>, SSRColorOutput)
|
|
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D<float>, SSRHitDistanceOutput)
|
|
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 FVisualizeTiledScreenSpaceReflectionsPS : public FGlobalShader
|
|
{
|
|
DECLARE_GLOBAL_SHADER(FVisualizeTiledScreenSpaceReflectionsPS);
|
|
SHADER_USE_PARAMETER_STRUCT(FVisualizeTiledScreenSpaceReflectionsPS, 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);
|
|
}
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(FScreenSpaceReflectionsPS::FParameters, CommonParameters)
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
};
|
|
|
|
class FVisualizeTiledScreenSpaceReflectionsVS : public FGlobalShader
|
|
{
|
|
DECLARE_GLOBAL_SHADER(FVisualizeTiledScreenSpaceReflectionsVS);
|
|
SHADER_USE_PARAMETER_STRUCT(FVisualizeTiledScreenSpaceReflectionsVS, FGlobalShader);
|
|
|
|
using FPermutationDomain = TShaderPermutationDomain<>;
|
|
|
|
using FParameters = FVisualizeTiledScreenSpaceReflectionsPS::FParameters; // Sharing parameters for proper registration with RDG
|
|
|
|
static FPermutationDomain RemapPermutation(FPermutationDomain PermutationVector)
|
|
{
|
|
return PermutationVector;
|
|
}
|
|
|
|
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
|
|
{
|
|
return IsFeatureLevelSupported(Parameters.Platform, ERHIFeatureLevel::SM5);
|
|
}
|
|
|
|
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);
|
|
}
|
|
};
|
|
|
|
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(FScreenSpaceReflectionsCS, "/Engine/Private/SSRT/SSRTReflections.usf", "ScreenSpaceReflectionsCS", SF_Compute);
|
|
IMPLEMENT_GLOBAL_SHADER(FScreenSpaceReflectionsTileVS, "/Engine/Private/SingleLayerWaterComposite.usf", "WaterTileVS", SF_Vertex);
|
|
IMPLEMENT_GLOBAL_SHADER(FVisualizeTiledScreenSpaceReflectionsPS, "/Engine/Private/SSRT/SSRTReflections.usf", "VisualizeTiledScreenSpaceReflectionsPS", SF_Pixel)
|
|
IMPLEMENT_GLOBAL_SHADER(FVisualizeTiledScreenSpaceReflectionsVS, "/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);
|
|
|
|
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) || ShouldRenderScreenSpaceReflectionsWater(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");
|
|
|
|
// 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.CreateSRV(FRDGTextureSRVDesc(
|
|
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();
|
|
|
|
FRDGTextureRef TemporalAAHistoryTexture = GraphBuilder.RegisterExternalTexture(View.PrevViewInfo.TemporalAAHistory.RT[0]);
|
|
PassParameters->PrevSceneColorSampler = TStaticSamplerState<SF_Bilinear>::GetRHI();
|
|
PassParameters->PrevSceneColor = GraphBuilder.CreateSRV(TemporalAAHistoryTexture->Desc.IsTextureArray()
|
|
? FRDGTextureSRVDesc::CreateForSlice(TemporalAAHistoryTexture, View.PrevViewInfo.TemporalAAHistory.OutputSliceIndex)
|
|
: FRDGTextureSRVDesc(TemporalAAHistoryTexture));
|
|
}
|
|
|
|
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->HZBParameters = GetHZBParameters(GraphBuilder, View, EHZBType::FurthestHZB);
|
|
|
|
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](FRDGAsyncTask, 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;
|
|
|
|
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->HZBParameters = GetHZBParameters(GraphBuilder, View, EHZBType::All);
|
|
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)
|
|
{
|
|
FRDGTextureSRVRef InputColor = GraphBuilder.CreateSRV(FRDGTextureSRVDesc(CurrentSceneColor));
|
|
if (SSRQuality != ESSRQuality::VisualizeSSR)
|
|
{
|
|
if (View.PrevViewInfo.CustomSSRInput.IsValid())
|
|
{
|
|
InputColor = GraphBuilder.CreateSRV(FRDGTextureSRVDesc(
|
|
GraphBuilder.RegisterExternalTexture(View.PrevViewInfo.CustomSSRInput.RT[0])));
|
|
}
|
|
else if (GSSRHalfResSceneColor && View.PrevViewInfo.HalfResTemporalAAHistory.IsValid())
|
|
{
|
|
FRDGTextureRef HalfResTemporalAAHistory = GraphBuilder.RegisterExternalTexture(View.PrevViewInfo.HalfResTemporalAAHistory);
|
|
|
|
if (HalfResTemporalAAHistory->Desc.Dimension == ETextureDimension::Texture2DArray)
|
|
{
|
|
InputColor = GraphBuilder.CreateSRV(FRDGTextureSRVDesc::CreateForSlice(HalfResTemporalAAHistory, /* SliceIndex = */ 0));
|
|
}
|
|
else
|
|
{
|
|
InputColor = GraphBuilder.CreateSRV(FRDGTextureSRVDesc(HalfResTemporalAAHistory));
|
|
}
|
|
}
|
|
else if (View.PrevViewInfo.TemporalAAHistory.IsValid())
|
|
{
|
|
FRDGTextureRef TemporalAAHistoryTexture = GraphBuilder.RegisterExternalTexture(View.PrevViewInfo.TemporalAAHistory.RT[0]);
|
|
InputColor = GraphBuilder.CreateSRV(TemporalAAHistoryTexture->Desc.IsTextureArray()
|
|
? FRDGTextureSRVDesc::CreateForSlice(TemporalAAHistoryTexture, View.PrevViewInfo.TemporalAAHistory.OutputSliceIndex)
|
|
: FRDGTextureSRVDesc(TemporalAAHistoryTexture));
|
|
}
|
|
}
|
|
|
|
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 | TexCreate_NoFastClear);
|
|
|
|
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->Desc.Texture == 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->Substrate = Substrate::BindSubstrateGlobalUniformParameters(View);
|
|
PassParameters->RenderTargets = RenderTargets;
|
|
|
|
TShaderMapRef<FScreenSpaceReflectionsStencilPS> PixelShader(View.ShaderMap, PermutationVector);
|
|
ClearUnusedGraphResources(PixelShader, PassParameters);
|
|
|
|
RDG_EVENT_SCOPE_STAT(GraphBuilder, ScreenSpaceReflections, "ScreenSpaceReflections");
|
|
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](FRDGAsyncTask, 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)
|
|
{
|
|
{
|
|
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->Desc.Texture != 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->HZBParameters = GetHZBParameters(GraphBuilder, View, EHZBType::FurthestHZB);
|
|
};
|
|
|
|
const int32 CVarSSRComputeValue = CVarSSRCompute.GetValueOnRenderThread();
|
|
// Compute path is only implemented for non-tiled SSR currently
|
|
const bool bCompute = CVarSSRComputeValue > 0 && !TiledScreenSpaceReflection && !SSRStencilPrePass && !bSingleLayerWater;
|
|
const bool bAsyncCompute = bCompute && CVarSSRComputeValue == 2;
|
|
|
|
FScreenSpaceReflectionsPS::FPermutationDomain PermutationVectorPS;
|
|
FScreenSpaceReflectionsCS::FPermutationDomain PermutationVectorCS;
|
|
FScreenSpaceReflectionsPS::FParameters* PassParametersPS = nullptr;
|
|
FScreenSpaceReflectionsCS::FParameters* PassParametersCS = nullptr;
|
|
|
|
if (bCompute)
|
|
{
|
|
PermutationVectorCS.Set<FSSRQualityDim>(SSRQuality);
|
|
PermutationVectorCS.Set<FSSROutputForDenoiser>(bDenoiser);
|
|
|
|
PassParametersCS = GraphBuilder.AllocParameters<FScreenSpaceReflectionsCS::FParameters>();
|
|
PassParametersCS->CommonParameters = CommonParameters;
|
|
SetSSRParameters(&PassParametersCS->SSRPassCommonParameter);
|
|
PassParametersCS->Substrate = Substrate::BindSubstrateGlobalUniformParameters(View);
|
|
PassParametersCS->SSRColorOutput = GraphBuilder.CreateUAV(DenoiserInputs->Color);
|
|
if (bDenoiser)
|
|
{
|
|
PassParametersCS->SSRHitDistanceOutput = GraphBuilder.CreateUAV(DenoiserInputs->RayHitDistance);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PermutationVectorPS.Set<FSSRQualityDim>(SSRQuality);
|
|
PermutationVectorPS.Set<FSSROutputForDenoiser>(bDenoiser);
|
|
|
|
PassParametersPS = GraphBuilder.AllocParameters<FScreenSpaceReflectionsPS::FParameters>();
|
|
PassParametersPS->CommonParameters = CommonParameters;
|
|
SetSSRParameters(&PassParametersPS->SSRPassCommonParameter);
|
|
PassParametersPS->Substrate = Substrate::BindSubstrateGlobalUniformParameters(View);
|
|
PassParametersPS->RenderTargets = RenderTargets;
|
|
PassParametersPS->RenderTargets.ShadingRateTexture = GVRSImageManager.GetVariableRateShadingImage(GraphBuilder, View, FVariableRateShadingImageManager::EVRSPassType::SSR);
|
|
}
|
|
|
|
RDG_EVENT_SCOPE_STAT(GraphBuilder, ScreenSpaceReflections, "ScreenSpaceReflections");
|
|
RDG_GPU_STAT_SCOPE(GraphBuilder, ScreenSpaceReflections);
|
|
|
|
static const auto CVarSSRTiledCompositeVisualize = IConsoleManager::Get().FindTConsoleVariableDataBool(TEXT("r.SSR.TiledComposite.Visualize"));
|
|
const bool bVisualizeTiledScreenSpaceReflection = CVarSSRTiledCompositeVisualize ? CVarSSRTiledCompositeVisualize->GetValueOnRenderThread() : false;
|
|
|
|
if (TiledScreenSpaceReflection == nullptr)
|
|
{
|
|
if (bCompute)
|
|
{
|
|
TShaderMapRef<FScreenSpaceReflectionsCS> ComputeShader(View.ShaderMap, PermutationVectorCS);
|
|
|
|
FComputeShaderUtils::AddPass(
|
|
GraphBuilder,
|
|
RDG_EVENT_NAME("SSR RayMarchCS(Quality=%d RayPerPixel=%d%s) %dx%d",
|
|
SSRQuality, RayTracingConfigs.RayCountPerPixel, bDenoiser ? TEXT(" DenoiserOutput") : TEXT(""),
|
|
View.ViewRect.Width(), View.ViewRect.Height()),
|
|
bAsyncCompute ? ERDGPassFlags::AsyncCompute : ERDGPassFlags::Compute,
|
|
ComputeShader,
|
|
PassParametersCS,
|
|
FComputeShaderUtils::GetGroupCount(View.ViewRect.Size(), FScreenSpaceReflectionsCS::GetThreadGroupSize()));
|
|
}
|
|
else
|
|
{
|
|
TShaderMapRef<FScreenSpaceReflectionsPS> PixelShader(View.ShaderMap, PermutationVectorPS);
|
|
|
|
ClearUnusedGraphResources(PixelShader, PassParametersPS);
|
|
|
|
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()),
|
|
PassParametersPS,
|
|
ERDGPassFlags::Raster,
|
|
[PassParametersPS, &View, PixelShader, SSRStencilPrePass](FRDGAsyncTask, 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(), *PassParametersPS);
|
|
|
|
FPixelShaderUtils::DrawFullscreenTriangle(RHICmdList);
|
|
});
|
|
}
|
|
}
|
|
else if (!bVisualizeTiledScreenSpaceReflection)
|
|
{
|
|
check(TiledScreenSpaceReflection->TileSize == 8); // WORK_TILE_SIZE
|
|
|
|
FScreenSpaceReflectionsTileVS::FPermutationDomain VsPermutationVector;
|
|
TShaderMapRef<FScreenSpaceReflectionsTileVS> VertexShader(View.ShaderMap, VsPermutationVector);
|
|
|
|
PassParametersPS->TileListData = TiledScreenSpaceReflection->TileListDataBufferSRV;
|
|
PassParametersPS->IndirectDrawParameter = TiledScreenSpaceReflection->DrawIndirectParametersBuffer;
|
|
|
|
TShaderMapRef<FScreenSpaceReflectionsPS> PixelShader(View.ShaderMap, PermutationVectorPS);
|
|
|
|
ClearUnusedGraphResources(VertexShader, PixelShader, PassParametersPS);
|
|
|
|
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()),
|
|
PassParametersPS,
|
|
ERDGPassFlags::Raster,
|
|
[PassParametersPS, &View, VertexShader, PixelShader, SSRStencilPrePass](FRDGAsyncTask, 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(), *PassParametersPS);
|
|
SetShaderParameters(RHICmdList, PixelShader, PixelShader.GetPixelShader(), *PassParametersPS);
|
|
|
|
PassParametersPS->IndirectDrawParameter->MarkResourceAsUsed();
|
|
|
|
RHICmdList.DrawPrimitiveIndirect(PassParametersPS->IndirectDrawParameter->GetIndirectRHICallBuffer(), 0);
|
|
});
|
|
}
|
|
else
|
|
{
|
|
// Visualize tiled screen space reflection
|
|
check(TiledScreenSpaceReflection->TileSize == 8); // WORK_TILE_SIZE
|
|
|
|
FVisualizeTiledScreenSpaceReflectionsVS::FPermutationDomain VsPermutationVector;
|
|
TShaderMapRef<FVisualizeTiledScreenSpaceReflectionsVS> VertexShader(View.ShaderMap, VsPermutationVector);
|
|
|
|
FVisualizeTiledScreenSpaceReflectionsPS::FPermutationDomain VisualizePermutationVector;
|
|
VisualizePermutationVector.Set<FSSRQualityDim>(SSRQuality);
|
|
VisualizePermutationVector.Set<FSSROutputForDenoiser>(bDenoiser);
|
|
|
|
TShaderMapRef<FVisualizeTiledScreenSpaceReflectionsPS> VisualizePixelShader(View.ShaderMap, VisualizePermutationVector);
|
|
|
|
FVisualizeTiledScreenSpaceReflectionsPS::FParameters* VisualizePassParameters = GraphBuilder.AllocParameters<FVisualizeTiledScreenSpaceReflectionsPS::FParameters>();
|
|
|
|
VisualizePassParameters->CommonParameters = *PassParametersPS;
|
|
VisualizePassParameters->CommonParameters.TileListData = TiledScreenSpaceReflection->TileListDataBufferSRV;
|
|
VisualizePassParameters->CommonParameters.IndirectDrawParameter = TiledScreenSpaceReflection->DrawIndirectParametersBuffer;
|
|
|
|
ClearUnusedGraphResources(VertexShader, VisualizePixelShader, VisualizePassParameters);
|
|
|
|
GraphBuilder.AddPass(
|
|
RDG_EVENT_NAME("SSR RayMarch(Visualize Tiles%s) %dx%d",
|
|
bDenoiser ? TEXT(" DenoiserOutput") : TEXT(""), View.ViewRect.Width(), View.ViewRect.Height()),
|
|
VisualizePassParameters,
|
|
ERDGPassFlags::Raster,
|
|
[VisualizePassParameters, &View, VertexShader, VisualizePixelShader, SSRStencilPrePass](FRDGAsyncTask, 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, VisualizePixelShader, /* 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 = VisualizePixelShader.GetPixelShader();
|
|
|
|
SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit, 0x80);
|
|
SetShaderParameters(RHICmdList, VertexShader, VertexShader.GetVertexShader(), *VisualizePassParameters);
|
|
SetShaderParameters(RHICmdList, VisualizePixelShader, VisualizePixelShader.GetPixelShader(), *VisualizePassParameters);
|
|
|
|
VisualizePassParameters->CommonParameters.IndirectDrawParameter->MarkResourceAsUsed();
|
|
|
|
RHICmdList.DrawPrimitiveIndirect(VisualizePassParameters->CommonParameters.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;
|
|
}
|
|
|
|
} // namespace ScreenSpaceRayTracing
|