Files
UnrealEngineUWP/Engine/Source/Runtime/Renderer/Private/PostProcess/TemporalSuperResolution.cpp

1653 lines
73 KiB
C++
Raw Normal View History

// Copyright Epic Games, Inc. All Rights Reserved.
#include "PostProcess/TemporalAA.h"
#include "PostProcess/PostProcessTonemap.h"
#include "PostProcess/PostProcessMitchellNetravali.h"
#include "PostProcess/PostProcessing.h"
#include "ClearQuad.h"
#include "PostProcessing.h"
#include "SceneTextureParameters.h"
#include "PixelShaderUtils.h"
#include "ScenePrivate.h"
#include "RendererModule.h"
#define COMPILE_TSR_DEBUG_PASSES (!UE_BUILD_SHIPPING)
namespace
{
TAutoConsoleVariable<float> CVarTSRHistorySP(
TEXT("r.TSR.HistoryScreenPercentage"),
100.0f,
TEXT("Size of TSR's history."),
ECVF_RenderThreadSafe);
TAutoConsoleVariable<int32> CVarTSRR11G11B10History(
TEXT("r.TSR.R11G11B10History"), 1,
TEXT("Select the bitdepth of the history."),
ECVF_RenderThreadSafe);
TAutoConsoleVariable<int32> CVarTSRHalfResShadingRejection(
TEXT("r.TSR.ShadingRejection.HalfRes"), 0,
TEXT("Whether the shading rejection should be done at half res. Saves performance but may introduce back some flickering (default = 0)."),
ECVF_RenderThreadSafe);
TAutoConsoleVariable<int32> CVarTSRFilterShadingRejection(
TEXT("r.TSR.ShadingRejection.SpatialFilter"), 1,
TEXT("Whether the shading rejection should have spatial statistical filtering pass to reduce flickering (default = 1).\n")
TEXT(" 0: Disabled;\n")
TEXT(" 1: Spatial filter pass is run at lower resolution than CompareHistory pass (default);\n")
TEXT(" 2: Spatial filter pass is run CompareHistory pass resolution to improve stability."),
ECVF_RenderThreadSafe);
TAutoConsoleVariable<int32> CVarTSRRejectionAntiAliasingQuality(
TEXT("r.TSR.RejectionAntiAliasingQuality"), 3,
TEXT("Controls the quality of spatial anti-aliasing on history rejection (default=1)."),
ECVF_Scalability | ECVF_RenderThreadSafe);
TAutoConsoleVariable<int32> CVarTSRMoireEnable(
TEXT("r.TSR.Moire"), 0,
TEXT("Enable heuristic to detect moire pattern in the input scene color caused by geometric interference between input ")
TEXT("pixel grid alignement and structured geometry."),
ECVF_RenderThreadSafe);
TAutoConsoleVariable<float> CVarTSRMoireSeedExposure(
TEXT("r.TSR.Moire.SeedExposure"), 0.125f,
TEXT("Exposure of the interference seed. Lower value will allow to detect interference more towards the shadows."),
ECVF_RenderThreadSafe);
TAutoConsoleVariable<float> CVarTSRTranslucencyHighlightLuminance(
TEXT("r.TSR.Translucency.HighlightLuminance"), -1.0f,
TEXT("Sets the liminance at which translucency is considered an highlights (default=-1.0)."),
ECVF_RenderThreadSafe);
TAutoConsoleVariable<int32> CVarTSRTranslucencyPreviousFrameRejection(
TEXT("r.TSR.Translucency.PreviousFrameRejection"), 0,
TEXT("Enable heuristic to reject Separate translucency based on previous frame translucency."),
ECVF_RenderThreadSafe);
TAutoConsoleVariable<int32> CVarTSRTranslucencySeparateTemporalAccumulation(
TEXT("r.TSR.Translucency.SeparateTemporalAccumulation"), 1,
TEXT("Accumulates separate translucency separatly (enabled by default)."),
ECVF_RenderThreadSafe);
TAutoConsoleVariable<int32> CVarTSREnableResponiveAA(
TEXT("r.TSR.Translucency.EnableResponiveAA"), 1,
TEXT("Whether the responsive AA should keep history fully clamped."),
ECVF_RenderThreadSafe);
TAutoConsoleVariable<float> CVarTSRWeightClampingPixelSpeed(
TEXT("r.TSR.Velocity.WeightClampingPixelSpeed"), 1.0f,
TEXT("Defines the pixel velocity at which the the high frequencies of the history get's their contributing weight clamped. ")
TEXT("Smallest reduce blur in movement (Default = 1.0f)."),
ECVF_RenderThreadSafe);
TAutoConsoleVariable<int32> CVarTSRVelocityHoleFill(
TEXT("r.TSR.Velocity.HoleFill"), 1,
TEXT("Whether to holl-fill the velocity buffer on parralax disocclusion to reduce boiling of disoccluded areas."),
ECVF_Scalability | ECVF_RenderThreadSafe);
TAutoConsoleVariable<float> CVarTSRVelocityMaxHoleFillScatterVelocity(
TEXT("r.TSR.Velocity.HoleFill.MaxScatterVelocity"), 8.0f,
TEXT("Maximum output pixel velocity difference tolerated between the disoccluded and scattered disoccluding geometries."),
ECVF_RenderThreadSafe);
#if COMPILE_TSR_DEBUG_PASSES
TAutoConsoleVariable<int32> CVarTSRSetupDebugPasses(
TEXT("r.TSR.Debug.SetupExtraPasses"), 0,
TEXT("Whether to enable the debug passes"),
ECVF_RenderThreadSafe);
#endif
BEGIN_SHADER_PARAMETER_STRUCT(FTSRCommonParameters, )
SHADER_PARAMETER_STRUCT(FScreenPassTextureViewportParameters, InputInfo)
SHADER_PARAMETER_STRUCT(FScreenPassTextureViewportParameters, LowFrequencyInfo)
SHADER_PARAMETER_STRUCT(FScreenPassTextureViewportParameters, RejectionInfo)
SHADER_PARAMETER_STRUCT(FScreenPassTextureViewportParameters, HistoryInfo)
SHADER_PARAMETER(FIntPoint, InputPixelPosMin)
SHADER_PARAMETER(FIntPoint, InputPixelPosMax)
SHADER_PARAMETER(FScreenTransform, InputPixelPosToScreenPos)
SHADER_PARAMETER(FVector2f, InputJitter)
SHADER_PARAMETER(int32, bCameraCut)
SHADER_PARAMETER(float, MoireInvExposure)
SHADER_PARAMETER(FVector2f, ScreenVelocityToInputPixelVelocity)
SHADER_PARAMETER(FVector2f, InputPixelVelocityToScreenVelocity)
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, ViewUniformBuffer)
END_SHADER_PARAMETER_STRUCT()
BEGIN_SHADER_PARAMETER_STRUCT(FTSRHistoryTextures, )
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, LowFrequency)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, HighFrequency)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, Metadata)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, SubpixelDetails)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, Translucency)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, TranslucencyAlpha)
SHADER_PARAMETER_RDG_TEXTURE_ARRAY(Texture2D, LowResTextures, [1])
SHADER_PARAMETER_RDG_TEXTURE_ARRAY(Texture2D, SuperResTextures, [2])
END_SHADER_PARAMETER_STRUCT()
BEGIN_SHADER_PARAMETER_STRUCT(FTSRHistoryUAVs, )
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, LowFrequency)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, HighFrequency)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, Metadata)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, SubpixelDetails)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, Translucency)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, TranslucencyAlpha)
SHADER_PARAMETER_RDG_TEXTURE_UAV_ARRAY(RWTexture2D, LowResTextures, [1])
SHADER_PARAMETER_RDG_TEXTURE_UAV_ARRAY(RWTexture2D, SuperResTextures, [2])
END_SHADER_PARAMETER_STRUCT()
BEGIN_SHADER_PARAMETER_STRUCT(FTSRPrevHistoryParameters, )
SHADER_PARAMETER_STRUCT(FScreenPassTextureViewportParameters, PrevHistoryInfo)
SHADER_PARAMETER(FScreenTransform, ScreenPosToPrevHistoryBufferUV)
SHADER_PARAMETER(float, HistoryPreExposureCorrection)
END_SHADER_PARAMETER_STRUCT()
FTSRHistoryUAVs CreateUAVs(FRDGBuilder& GraphBuilder, const FTSRHistoryTextures& Textures)
{
FTSRHistoryUAVs UAVs;
UAVs.LowFrequency = GraphBuilder.CreateUAV(Textures.LowFrequency);
UAVs.HighFrequency = GraphBuilder.CreateUAV(Textures.HighFrequency);
UAVs.Metadata = GraphBuilder.CreateUAV(Textures.Metadata);
UAVs.SubpixelDetails = GraphBuilder.CreateUAV(Textures.SubpixelDetails);
if (Textures.Translucency)
{
UAVs.Translucency = GraphBuilder.CreateUAV(Textures.Translucency);
UAVs.TranslucencyAlpha = GraphBuilder.CreateUAV(Textures.TranslucencyAlpha);
}
if (Textures.LowResTextures[0])
{
UAVs.LowResTextures[0] = GraphBuilder.CreateUAV(Textures.LowResTextures[0]);
}
if (Textures.SuperResTextures[0])
{
UAVs.SuperResTextures[0] = GraphBuilder.CreateUAV(Textures.SuperResTextures[0]);
}
if (Textures.SuperResTextures[1])
{
UAVs.SuperResTextures[1] = GraphBuilder.CreateUAV(Textures.SuperResTextures[1]);
}
return UAVs;
}
class FTSRMoireHeuristic : SHADER_PERMUTATION_BOOL("DIM_MOIRE_HEURISTIC");
class FTSRShader : public FGlobalShader
{
public:
FTSRShader(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
: FGlobalShader(Initializer)
{ }
FTSRShader()
{ }
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return SupportsTSR(Parameters.Platform);
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
OutEnvironment.CompilerFlags.Add(CFLAG_AllowRealTypes);
}
}; // class FTemporalSuperResolutionShader
class FTSRClearPrevTexturesCS : public FTSRShader
{
DECLARE_GLOBAL_SHADER(FTSRClearPrevTexturesCS);
SHADER_USE_PARAMETER_STRUCT(FTSRClearPrevTexturesCS, FTSRShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_INCLUDE(FTSRCommonParameters, CommonParameters)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, PrevUseCountOutput)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, PrevClosestDepthOutput)
END_SHADER_PARAMETER_STRUCT()
}; // class FTSRClearPrevTexturesCS
class FTSRDilateVelocityCS : public FTSRShader
{
DECLARE_GLOBAL_SHADER(FTSRDilateVelocityCS);
SHADER_USE_PARAMETER_STRUCT(FTSRDilateVelocityCS, FTSRShader);
class FMotionBlurDirectionsDim : SHADER_PERMUTATION_INT("DIM_MOTION_BLUR_DIRECTIONS", 3);
using FPermutationDomain = TShaderPermutationDomain<FMotionBlurDirectionsDim>;
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_INCLUDE(FTSRCommonParameters, CommonParameters)
SHADER_PARAMETER_STRUCT_INCLUDE(FVelocityFlattenParameters, VelocityFlattenParameters)
SHADER_PARAMETER(FVector2f, PrevOutputBufferUVMin)
SHADER_PARAMETER(FVector2f, PrevOutputBufferUVMax)
SHADER_PARAMETER(float, WorldDepthToDepthError)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, SceneDepthTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, SceneVelocityTexture)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, DilatedVelocityOutput)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, ClosestDepthOutput)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, PrevUseCountOutput)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, PrevClosestDepthOutput)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, ParallaxFactorOutput)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, VelocityFlattenOutput)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, VelocityTileOutput0)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, VelocityTileOutput1)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, DebugOutput)
END_SHADER_PARAMETER_STRUCT()
}; // class FTSRDilateVelocityCS
class FTSRDecimateHistoryCS : public FTSRShader
{
DECLARE_GLOBAL_SHADER(FTSRDecimateHistoryCS);
SHADER_USE_PARAMETER_STRUCT(FTSRDecimateHistoryCS, FTSRShader);
class FOutputHalfRes : SHADER_PERMUTATION_BOOL("DIM_OUTPUT_HALF_RES");
using FPermutationDomain = TShaderPermutationDomain<FOutputHalfRes, FTSRMoireHeuristic>;
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_INCLUDE(FTSRCommonParameters, CommonParameters)
SHADER_PARAMETER(FMatrix44f, RotationalClipToPrevClip)
SHADER_PARAMETER(FVector3f, OutputQuantizationError)
SHADER_PARAMETER(float, WorldDepthToPixelWorldRadius)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, InputSceneColorTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, DilatedVelocityTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, ClosestDepthTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, PrevUseCountTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, PrevClosestDepthTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, ParallaxFactorTexture)
SHADER_PARAMETER_STRUCT_INCLUDE(FTSRPrevHistoryParameters, PrevHistoryParameters)
SHADER_PARAMETER_STRUCT(FTSRHistoryTextures, PrevHistory)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, HalfResSceneColorOutput)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, HalfResPredictionSceneColorOutput)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, HalfResParallaxRejectionMaskOutput)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, PredictionSceneColorOutput)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, ParallaxRejectionMaskOutput)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, InterferenceSeedOutput)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, DebugOutput)
END_SHADER_PARAMETER_STRUCT()
}; // class FTSRDecimateHistoryCS
class FTSRCompareTranslucencyCS : public FTSRShader
{
DECLARE_GLOBAL_SHADER(FTSRCompareTranslucencyCS);
SHADER_USE_PARAMETER_STRUCT(FTSRCompareTranslucencyCS, FTSRShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_INCLUDE(FTSRCommonParameters, CommonParameters)
SHADER_PARAMETER_STRUCT(FScreenPassTextureViewportParameters, TranslucencyInfo)
SHADER_PARAMETER_STRUCT(FScreenPassTextureViewportParameters, PrevTranslucencyInfo)
SHADER_PARAMETER(float, PrevTranslucencyPreExposureCorrection)
SHADER_PARAMETER(float, TranslucencyHighlightLuminance)
SHADER_PARAMETER(FScreenTransform, ScreenPosToPrevTranslucencyTextureUV)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, DilatedVelocityTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, TranslucencyTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, PrevTranslucencyTexture)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, TranslucencyRejectionOutput)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, DebugOutput)
END_SHADER_PARAMETER_STRUCT()
}; // class FTSRCompareTranslucencyCS
class FTSRDetectInterferenceCS : public FTSRShader
{
DECLARE_GLOBAL_SHADER(FTSRDetectInterferenceCS);
SHADER_USE_PARAMETER_STRUCT(FTSRDetectInterferenceCS, FTSRShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_INCLUDE(FTSRCommonParameters, CommonParameters)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, InputSceneColorTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, DilatedVelocityTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, PredictionSceneColorTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, ParallaxRejectionMaskTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, InterferenceSeedTexture)
SHADER_PARAMETER_STRUCT_INCLUDE(FTSRPrevHistoryParameters, PrevHistoryParameters)
SHADER_PARAMETER_STRUCT(FTSRHistoryTextures, PrevHistory)
SHADER_PARAMETER_STRUCT(FTSRHistoryUAVs, HistoryOutput)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, InterferenceWeightOutput)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, DebugOutput)
END_SHADER_PARAMETER_STRUCT()
}; // class FTSRDetectInterferenceCS
class FTSRHoleFillVelocityCS : public FTSRShader
{
DECLARE_GLOBAL_SHADER(FTSRHoleFillVelocityCS);
SHADER_USE_PARAMETER_STRUCT(FTSRHoleFillVelocityCS, FTSRShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_INCLUDE(FTSRCommonParameters, CommonParameters)
SHADER_PARAMETER(float, MaxHollFillPixelVelocity)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, PrevClosestDepthTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, DilatedVelocityTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, ParallaxRejectionMaskTexture)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, HoleFilledVelocityOutput)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, HoleFilledVelocityMaskOutput)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, DebugOutput)
END_SHADER_PARAMETER_STRUCT()
}; // class FTSRHoleFillVelocityCS
class FTSRFilterFrequenciesCS : public FTSRShader
{
DECLARE_GLOBAL_SHADER(FTSRFilterFrequenciesCS);
SHADER_USE_PARAMETER_STRUCT(FTSRFilterFrequenciesCS, FTSRShader);
class FOutputAALumaDim : SHADER_PERMUTATION_BOOL("DIM_OUTPUT_ANTI_ALIASING_LUMA");
using FPermutationDomain = TShaderPermutationDomain<FOutputAALumaDim, FTSRMoireHeuristic>;
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_INCLUDE(FTSRCommonParameters, CommonParameters)
SHADER_PARAMETER(FVector3f, OutputQuantizationError)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, InputTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, PredictionSceneColorTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, ParallaxRejectionMaskTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, InterferenceSeedTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, InterferenceWeightTexture)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, FilteredInputOutput)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, FilteredPredictionSceneColorOutput)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, FilteredInterferenceSeedOutput)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, InputSceneColorLdrLumaOutput)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, DebugOutput)
END_SHADER_PARAMETER_STRUCT()
}; // class FTSRFilterFrequenciesCS
class FTSRCompareHistoryCS : public FTSRShader
{
DECLARE_GLOBAL_SHADER(FTSRCompareHistoryCS);
SHADER_USE_PARAMETER_STRUCT(FTSRCompareHistoryCS, FTSRShader);
class FOutputHalfRes : SHADER_PERMUTATION_BOOL("DIM_OUTPUT_HALF_RES");
using FPermutationDomain = TShaderPermutationDomain<FOutputHalfRes, FTSRMoireHeuristic>;
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_INCLUDE(FTSRCommonParameters, CommonParameters)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, ParallaxRejectionMaskTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, FilteredInputTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, FilteredPredictionSceneColorTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, FilteredInterferenceSeedTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, InterferenceWeightTexture)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, HistoryRejectionOutput)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, DebugOutput)
END_SHADER_PARAMETER_STRUCT()
}; // class FTSRCompareHistoryCS
class FTSRPostfilterRejectionCS : public FTSRShader
{
DECLARE_GLOBAL_SHADER(FTSRPostfilterRejectionCS);
SHADER_USE_PARAMETER_STRUCT(FTSRPostfilterRejectionCS, FTSRShader);
class FOutputHalfRes : SHADER_PERMUTATION_BOOL("DIM_OUTPUT_HALF_RES");
using FPermutationDomain = TShaderPermutationDomain<FOutputHalfRes>;
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER(FIntRect, HistoryRejectionViewport)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, HistoryRejectionTexture)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, HistoryRejectionOutput)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, DebugOutput)
END_SHADER_PARAMETER_STRUCT()
}; // class FTSRPostfilterRejectionCS
class FTSRDilateRejectionCS : public FTSRShader
{
DECLARE_GLOBAL_SHADER(FTSRDilateRejectionCS);
SHADER_USE_PARAMETER_STRUCT(FTSRDilateRejectionCS, FTSRShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_INCLUDE(FTSRCommonParameters, CommonParameters)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, HistoryRejectionTexture)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, DilatedHistoryRejectionOutput)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, DebugOutput)
END_SHADER_PARAMETER_STRUCT()
}; // class FTSRDilateRejectionCS
class FTSRSpatialAntiAliasingCS : public FTSRShader
{
DECLARE_GLOBAL_SHADER(FTSRSpatialAntiAliasingCS);
SHADER_USE_PARAMETER_STRUCT(FTSRSpatialAntiAliasingCS, FTSRShader);
class FQualityDim : SHADER_PERMUTATION_INT("DIM_QUALITY_PRESET", 3);
using FPermutationDomain = TShaderPermutationDomain<FQualityDim>;
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_INCLUDE(FTSRCommonParameters, CommonParameters)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, InputSceneColorTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, InputSceneColorLdrLumaTexture)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, AntiAliasingOutput)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, NoiseFilteringOutput)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, DebugOutput)
END_SHADER_PARAMETER_STRUCT()
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
FPermutationDomain PermutationVector(Parameters.PermutationId);
// There is no Quality=0 because the pass doesn't get setup.
if (PermutationVector.Get<FQualityDim>() == 0)
{
return false;
}
return FTSRShader::ShouldCompilePermutation(Parameters);
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FTSRShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.CompilerFlags.Add(CFLAG_Wave32);
}
}; // class FTSRSpatialAntiAliasingCS
class FTSRFilterAntiAliasingCS : public FTSRShader
{
DECLARE_GLOBAL_SHADER(FTSRFilterAntiAliasingCS);
SHADER_USE_PARAMETER_STRUCT(FTSRFilterAntiAliasingCS, FTSRShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_INCLUDE(FTSRCommonParameters, CommonParameters)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, AntiAliasingTexture)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, AntiAliasingOutput)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, DebugOutput)
END_SHADER_PARAMETER_STRUCT()
}; // class FTSRFilterAntiAliasingCS
class FTSRUpdateSuperResHistoryCS : public FTSRShader
{
DECLARE_GLOBAL_SHADER(FTSRUpdateSuperResHistoryCS);
SHADER_USE_PARAMETER_STRUCT(FTSRUpdateSuperResHistoryCS, FTSRShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_INCLUDE(FTSRCommonParameters, CommonParameters)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, InputSceneColorTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, DilatedVelocityTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, ParallaxRejectionMaskTexture)
SHADER_PARAMETER_STRUCT_INCLUDE(FTSRPrevHistoryParameters, PrevHistoryParameters)
SHADER_PARAMETER_STRUCT(FTSRHistoryTextures, PrevHistory)
SHADER_PARAMETER_STRUCT(FTSRHistoryUAVs, HistoryOutput)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, DebugOutput)
END_SHADER_PARAMETER_STRUCT()
}; // class FTSRUpdateSuperResHistoryCS
class FTSRUpdateHistoryCS : public FTSRShader
{
DECLARE_GLOBAL_SHADER(FTSRUpdateHistoryCS);
SHADER_USE_PARAMETER_STRUCT(FTSRUpdateHistoryCS, FTSRShader);
class FRejectionAADim : SHADER_PERMUTATION_BOOL("DIM_REJECTION_ANTI_ALIASING");
class FSeparateTranslucencyDim : SHADER_PERMUTATION_BOOL("DIM_SEPARATE_TRANSLUCENCY");
using FPermutationDomain = TShaderPermutationDomain<FRejectionAADim, FSeparateTranslucencyDim, FTSRMoireHeuristic>;
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_INCLUDE(FTSRCommonParameters, CommonParameters)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, InputSceneColorTexture)
SHADER_PARAMETER_RDG_TEXTURE_SRV(Texture2D, InputSceneStencilTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, InputSceneTranslucencyTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, InterferenceWeightTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, HistoryRejectionTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, TranslucencyRejectionTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, DilatedVelocityTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, ParallaxFactorTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, ParallaxRejectionMaskTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, AntiAliasingTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, NoiseFilteringTexture)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, HoleFilledVelocityMaskTexture)
SHADER_PARAMETER(FScreenTransform, HistoryPixelPosToScreenPos)
SHADER_PARAMETER(FScreenTransform, HistoryPixelPosToPPCo)
SHADER_PARAMETER(FVector3f, HistoryQuantizationError)
SHADER_PARAMETER(float, MinTranslucencyRejection)
SHADER_PARAMETER(float, InvWeightClampingPixelSpeed)
SHADER_PARAMETER(float, InputToHistoryFactor)
SHADER_PARAMETER(int32, ResponsiveStencilMask)
Implements dynamic half-res motion blur 1) Motionblur have tile classification to improve VGPR pressure on fast motion blur gathering tiles 2) Motionblur tile classification can lower the gathering resolution to half res with r.MotionBlur.HalfResGather=1 on part of the screen with large motion vectors to reduce VALU costs under large movements, but still can compose with full res scene color without round trip to main memory to avoid adding memory bandwidth costs 3) TSR output a half res scene color in Mip1 so motion blur can dynamically sample half res under largement movements with r.MotionBlur.HalfResInput=1 to save memory bandwidth in the motion blur convolution 4) Number of direction samples becomes dynamic (and clamped to exisiting motion blur quality) based on length of motion vector to saves VALU with slow pixel velocities 5) Motion blur automatically avoid sampling full res center if the blur kernel completly occlude its to completly stop fetching full res to save memory bandwidth cost under large motions Drops motion blur costs from 753us to 339us of motion blur costs + 40us additional cost in TSR to output half res in sandbox under movements. And saves an average 0.3ms in the entire chase gameplay sequence. #rb josie.yang [FYI] brian.karis #preflight 616960548b364e0001807ac7, 616998724cf7190001d2e6f2 #lockdown michal.valient #ROBOMERGE-OWNER: guillaume.abadie #ROBOMERGE-AUTHOR: guillaume.abadie #ROBOMERGE-SOURCE: CL 17830244 via CL 18002937 via CL 18369356 via CL 18369373 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v895-18170469) [CL 18369376 by guillaume abadie in ue5-release-engine-test branch]
2021-12-03 12:40:10 -05:00
SHADER_PARAMETER(int32, bGenerateOutputMip1)
SHADER_PARAMETER_STRUCT_INCLUDE(FTSRPrevHistoryParameters, PrevHistoryParameters)
SHADER_PARAMETER_STRUCT(FTSRHistoryTextures, PrevHistory)
SHADER_PARAMETER_STRUCT(FTSRHistoryUAVs, HistoryOutput)
Implements dynamic half-res motion blur 1) Motionblur have tile classification to improve VGPR pressure on fast motion blur gathering tiles 2) Motionblur tile classification can lower the gathering resolution to half res with r.MotionBlur.HalfResGather=1 on part of the screen with large motion vectors to reduce VALU costs under large movements, but still can compose with full res scene color without round trip to main memory to avoid adding memory bandwidth costs 3) TSR output a half res scene color in Mip1 so motion blur can dynamically sample half res under largement movements with r.MotionBlur.HalfResInput=1 to save memory bandwidth in the motion blur convolution 4) Number of direction samples becomes dynamic (and clamped to exisiting motion blur quality) based on length of motion vector to saves VALU with slow pixel velocities 5) Motion blur automatically avoid sampling full res center if the blur kernel completly occlude its to completly stop fetching full res to save memory bandwidth cost under large motions Drops motion blur costs from 753us to 339us of motion blur costs + 40us additional cost in TSR to output half res in sandbox under movements. And saves an average 0.3ms in the entire chase gameplay sequence. #rb josie.yang [FYI] brian.karis #preflight 616960548b364e0001807ac7, 616998724cf7190001d2e6f2 #lockdown michal.valient #ROBOMERGE-OWNER: guillaume.abadie #ROBOMERGE-AUTHOR: guillaume.abadie #ROBOMERGE-SOURCE: CL 17830244 via CL 18002937 via CL 18369356 via CL 18369373 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v895-18170469) [CL 18369376 by guillaume abadie in ue5-release-engine-test branch]
2021-12-03 12:40:10 -05:00
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, SceneColorOutputMip0)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, SceneColorOutputMip1)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, DebugOutput)
END_SHADER_PARAMETER_STRUCT()
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FTSRShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
OutEnvironment.CompilerFlags.Add(CFLAG_Wave32);
}
}; // class FTSRUpdateHistoryCS
#if COMPILE_TSR_DEBUG_PASSES
class FTSRDebugHistoryCS : public FTSRShader
{
DECLARE_GLOBAL_SHADER(FTSRDebugHistoryCS);
SHADER_USE_PARAMETER_STRUCT(FTSRDebugHistoryCS, FTSRShader);
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_STRUCT_INCLUDE(FTSRCommonParameters, CommonParameters)
SHADER_PARAMETER_STRUCT(FTSRHistoryTextures, History)
SHADER_PARAMETER_STRUCT(FTSRHistoryTextures, PrevHistory)
SHADER_PARAMETER_RDG_TEXTURE_UAV(RWTexture2D, DebugOutput)
END_SHADER_PARAMETER_STRUCT()
}; // class FTSRDebugHistoryCS
#endif
IMPLEMENT_GLOBAL_SHADER(FTSRClearPrevTexturesCS, "/Engine/Private/TemporalSuperResolution/TSRClearPrevTextures.usf", "MainCS", SF_Compute);
IMPLEMENT_GLOBAL_SHADER(FTSRDilateVelocityCS, "/Engine/Private/TemporalSuperResolution/TSRDilateVelocity.usf", "MainCS", SF_Compute);
IMPLEMENT_GLOBAL_SHADER(FTSRDecimateHistoryCS, "/Engine/Private/TemporalSuperResolution/TSRDecimateHistory.usf", "MainCS", SF_Compute);
IMPLEMENT_GLOBAL_SHADER(FTSRCompareTranslucencyCS, "/Engine/Private/TemporalSuperResolution/TSRCompareTranslucency.usf", "MainCS", SF_Compute);
IMPLEMENT_GLOBAL_SHADER(FTSRHoleFillVelocityCS, "/Engine/Private/TemporalSuperResolution/TSRHoleFillVelocity.usf", "MainCS", SF_Compute);
IMPLEMENT_GLOBAL_SHADER(FTSRDetectInterferenceCS, "/Engine/Private/TemporalSuperResolution/TSRDetectInterference.usf", "MainCS", SF_Compute);
IMPLEMENT_GLOBAL_SHADER(FTSRFilterFrequenciesCS, "/Engine/Private/TemporalSuperResolution/TSRFilterFrequencies.usf", "MainCS", SF_Compute);
IMPLEMENT_GLOBAL_SHADER(FTSRCompareHistoryCS, "/Engine/Private/TemporalSuperResolution/TSRCompareHistory.usf", "MainCS", SF_Compute);
IMPLEMENT_GLOBAL_SHADER(FTSRPostfilterRejectionCS, "/Engine/Private/TemporalSuperResolution/TSRPostfilterRejection.usf", "MainCS", SF_Compute);
IMPLEMENT_GLOBAL_SHADER(FTSRDilateRejectionCS, "/Engine/Private/TemporalSuperResolution/TSRDilateRejection.usf", "MainCS", SF_Compute);
IMPLEMENT_GLOBAL_SHADER(FTSRSpatialAntiAliasingCS, "/Engine/Private/TemporalSuperResolution/TSRSpatialAntiAliasing.usf", "MainCS", SF_Compute);
IMPLEMENT_GLOBAL_SHADER(FTSRFilterAntiAliasingCS, "/Engine/Private/TemporalSuperResolution/TSRFilterAntiAliasing.usf", "MainCS", SF_Compute);
IMPLEMENT_GLOBAL_SHADER(FTSRUpdateSuperResHistoryCS, "/Engine/Private/TemporalSuperResolution/TSRUpdateSuperResHistory.usf", "MainCS", SF_Compute);
IMPLEMENT_GLOBAL_SHADER(FTSRUpdateHistoryCS, "/Engine/Private/TemporalSuperResolution/TSRUpdateHistory.usf", "MainCS", SF_Compute);
#if COMPILE_TSR_DEBUG_PASSES
IMPLEMENT_GLOBAL_SHADER(FTSRDebugHistoryCS, "/Engine/Private/TemporalSuperResolution/TSRDebugHistory.usf", "MainCS", SF_Compute);
#endif
DECLARE_GPU_STAT(TemporalSuperResolution)
} //! namespace
FVector ComputePixelFormatQuantizationError(EPixelFormat PixelFormat);
bool ComposeSeparateTranslucencyInTSR(const FViewInfo& View)
{
return CVarTSRTranslucencySeparateTemporalAccumulation.GetValueOnRenderThread() != 0;
}
ITemporalUpscaler::FOutputs AddTemporalSuperResolutionPasses(
FRDGBuilder& GraphBuilder,
const FViewInfo& View,
const ITemporalUpscaler::FPassInputs& PassInputs)
{
const FTSRHistory& InputHistory = View.PrevViewInfo.TSRHistory;
#if COMPILE_TSR_DEBUG_PASSES
const bool bSetupDebugPasses = CVarTSRSetupDebugPasses.GetValueOnRenderThread() != 0;
#endif
// Whether to use camera cut shader permutation or not.
bool bCameraCut = !InputHistory.IsValid() || View.bCameraCut;
bool bHalfResLowFrequency = CVarTSRHalfResShadingRejection.GetValueOnRenderThread() != 0;
bool bEnableMoireHeuristic = CVarTSRMoireEnable.GetValueOnRenderThread() != 0;
bool bIsSeperateTranslucyTexturesValid = PassInputs.SeparateTranslucencyTextures != nullptr && PassInputs.SeparateTranslucencyTextures->IsColorValid();
bool bRejectSeparateTranslucency = bIsSeperateTranslucyTexturesValid && CVarTSRTranslucencyPreviousFrameRejection.GetValueOnRenderThread() != 0;
bool bAccumulateSeparateTranslucency = bIsSeperateTranslucyTexturesValid && CVarTSRTranslucencySeparateTemporalAccumulation.GetValueOnRenderThread() != 0;
int32 RejectionAntiAliasingQuality = FMath::Clamp(CVarTSRRejectionAntiAliasingQuality.GetValueOnRenderThread(), 0, 2);
bool bHoleFillVelocity = CVarTSRVelocityHoleFill.GetValueOnRenderThread() != 0 && RejectionAntiAliasingQuality > 0;
enum class ERejectionPostFilter : uint8
{
Disabled,
PostRejectionDownsample,
PreRejectionDownsample,
};
ERejectionPostFilter PostFilter = ERejectionPostFilter(FMath::Clamp(CVarTSRFilterShadingRejection.GetValueOnRenderThread(), 0, 2));
FIntPoint InputExtent = PassInputs.SceneColorTexture->Desc.Extent;
FIntRect InputRect = View.ViewRect;
FIntPoint LowFrequencyExtent = InputExtent;
FIntRect LowFrequencyRect = FIntRect(FIntPoint(0, 0), InputRect.Size());
if (bHalfResLowFrequency)
{
LowFrequencyExtent = InputExtent / 2;
LowFrequencyRect = FIntRect(FIntPoint(0, 0), FIntPoint::DivideAndRoundUp(InputRect.Size(), 2));
}
FIntPoint RejectionExtent = LowFrequencyExtent / 2;
FIntRect RejectionRect = FIntRect(FIntPoint(0, 0), FIntPoint::DivideAndRoundUp(LowFrequencyRect.Size(), 2));
FIntPoint OutputExtent;
FIntRect OutputRect;
if (View.PrimaryScreenPercentageMethod == EPrimaryScreenPercentageMethod::TemporalUpscale)
{
OutputRect.Min = FIntPoint(0, 0);
OutputRect.Max = View.GetSecondaryViewRectSize();
FIntPoint QuantizedPrimaryUpscaleViewSize;
QuantizeSceneBufferSize(OutputRect.Max, QuantizedPrimaryUpscaleViewSize);
OutputExtent = FIntPoint(
FMath::Max(InputExtent.X, QuantizedPrimaryUpscaleViewSize.X),
FMath::Max(InputExtent.Y, QuantizedPrimaryUpscaleViewSize.Y));
}
else
{
OutputRect.Min = FIntPoint(0, 0);
OutputRect.Max = View.ViewRect.Size();
OutputExtent = InputExtent;
}
FIntPoint HistoryExtent;
FIntPoint HistorySize;
{
float UpscaleFactor = FMath::Clamp(CVarTSRHistorySP.GetValueOnRenderThread() / 100.0f, 1.0f, 2.0f);
HistorySize = FIntPoint(
FMath::CeilToInt(OutputRect.Width() * UpscaleFactor),
FMath::CeilToInt(OutputRect.Height() * UpscaleFactor));
FIntPoint QuantizedHistoryViewSize;
QuantizeSceneBufferSize(HistorySize, QuantizedHistoryViewSize);
HistoryExtent = FIntPoint(
FMath::Max(InputExtent.X, QuantizedHistoryViewSize.X),
FMath::Max(InputExtent.Y, QuantizedHistoryViewSize.Y));
}
float ScreenPercentage = float(InputRect.Width()) / float(OutputRect.Width());
float InvScreenPercentage = float(OutputRect.Width()) / float(InputRect.Width());
RDG_EVENT_SCOPE(GraphBuilder, "TemporalSuperResolution %dx%d -> %dx%d", InputRect.Width(), InputRect.Height(), OutputRect.Width(), OutputRect.Height());
RDG_GPU_STAT_SCOPE(GraphBuilder, TemporalSuperResolution);
FRDGTextureRef BlackUintDummy = GSystemTextures.GetZeroUIntDummy(GraphBuilder);
FRDGTextureRef BlackDummy = GSystemTextures.GetBlackDummy(GraphBuilder);
FRDGTextureRef WhiteDummy = GSystemTextures.GetWhiteDummy(GraphBuilder);
FRDGTextureRef SeparateTranslucencyTexture = (bRejectSeparateTranslucency || bAccumulateSeparateTranslucency) ?
PassInputs.SeparateTranslucencyTextures->GetColorForRead(GraphBuilder) : nullptr;
FTSRCommonParameters CommonParameters;
{
CommonParameters.InputInfo = GetScreenPassTextureViewportParameters(FScreenPassTextureViewport(
InputExtent, InputRect));
CommonParameters.InputPixelPosMin = CommonParameters.InputInfo.ViewportMin;
CommonParameters.InputPixelPosMax = CommonParameters.InputInfo.ViewportMax - 1;
CommonParameters.InputPixelPosToScreenPos = (FScreenTransform::Identity + 0.5) * CommonParameters.InputInfo.ViewportSizeInverse * FScreenTransform::ViewportUVToScreenPos;
CommonParameters.ScreenVelocityToInputPixelVelocity = (FScreenTransform::Identity / CommonParameters.InputPixelPosToScreenPos).Scale;
CommonParameters.InputPixelVelocityToScreenVelocity = CommonParameters.InputPixelPosToScreenPos.Scale;
CommonParameters.LowFrequencyInfo = GetScreenPassTextureViewportParameters(FScreenPassTextureViewport(
LowFrequencyExtent, LowFrequencyRect));
CommonParameters.RejectionInfo = GetScreenPassTextureViewportParameters(FScreenPassTextureViewport(
RejectionExtent, RejectionRect));
CommonParameters.HistoryInfo = GetScreenPassTextureViewportParameters(FScreenPassTextureViewport(
HistoryExtent, FIntRect(FIntPoint(0, 0), HistorySize)));
CommonParameters.InputJitter = View.TemporalJitterPixels;
CommonParameters.bCameraCut = bCameraCut;
CommonParameters.MoireInvExposure = 1.0f / CVarTSRMoireSeedExposure.GetValueOnRenderThread();
CommonParameters.ViewUniformBuffer = View.ViewUniformBuffer;
}
auto CreateDebugUAV = [&](const FIntPoint& Extent, const TCHAR* DebugName)
{
FRDGTextureDesc DebugDesc = FRDGTextureDesc::Create2D(
Extent,
PF_FloatRGBA,
FClearValueBinding::None,
/* InFlags = */ TexCreate_ShaderResource | TexCreate_UAV);
FRDGTextureRef DebugTexture = GraphBuilder.CreateTexture(DebugDesc, DebugName);
return GraphBuilder.CreateUAV(DebugTexture);
};
// Clear atomic scattered texture.
FRDGTextureRef PrevUseCountTexture;
FRDGTextureRef PrevClosestDepthTexture;
{
{
FRDGTextureDesc Desc = FRDGTextureDesc::Create2D(
InputExtent,
PF_R32_UINT,
FClearValueBinding::None,
/* InFlags = */ TexCreate_ShaderResource | TexCreate_UAV | TexCreate_AtomicCompatible);
PrevUseCountTexture = GraphBuilder.CreateTexture(Desc, TEXT("TSR.PrevUseCountTexture"));
PrevClosestDepthTexture = GraphBuilder.CreateTexture(Desc, TEXT("TSR.PrevClosestDepthTexture"));
}
FTSRClearPrevTexturesCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FTSRClearPrevTexturesCS::FParameters>();
PassParameters->CommonParameters = CommonParameters;
PassParameters->PrevUseCountOutput = GraphBuilder.CreateUAV(PrevUseCountTexture);
PassParameters->PrevClosestDepthOutput = GraphBuilder.CreateUAV(PrevClosestDepthTexture);
TShaderMapRef<FTSRClearPrevTexturesCS> ComputeShader(View.ShaderMap);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("TSR ClearPrevTextures %dx%d", InputRect.Width(), InputRect.Height()),
ComputeShader,
PassParameters,
FComputeShaderUtils::GetGroupCount(InputRect.Size(), 8));
}
// Dilate the velocity texture & scatter reprojection into previous frame
FRDGTextureRef DilatedVelocityTexture;
FRDGTextureRef ClosestDepthTexture;
FRDGTextureRef ParallaxFactorTexture;
FVelocityFlattenTextures VelocityFlattenTextures;
{
{
FRDGTextureDesc Desc = FRDGTextureDesc::Create2D(
InputExtent,
PF_G16R16,
FClearValueBinding::None,
/* InFlags = */ TexCreate_ShaderResource | TexCreate_UAV);
DilatedVelocityTexture = GraphBuilder.CreateTexture(Desc, TEXT("TSR.DilatedVelocity"));
Desc.Format = PF_R16F;
ClosestDepthTexture = GraphBuilder.CreateTexture(Desc, TEXT("TSR.ClosestDepthTexture"));
Desc.Format = PF_R8_UINT;
ParallaxFactorTexture = GraphBuilder.CreateTexture(Desc, TEXT("TSR.ParallaxFactor"));
}
int32 TileSize = 8;
FTSRDilateVelocityCS::FPermutationDomain PermutationVector;
FTSRDilateVelocityCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FTSRDilateVelocityCS::FParameters>();
PassParameters->CommonParameters = CommonParameters;
PassParameters->PrevOutputBufferUVMin = CommonParameters.InputInfo.UVViewportBilinearMin - CommonParameters.InputInfo.ExtentInverse;
PassParameters->PrevOutputBufferUVMax = CommonParameters.InputInfo.UVViewportBilinearMax + CommonParameters.InputInfo.ExtentInverse;
{
float TanHalfFieldOfView = View.ViewMatrices.GetInvProjectionMatrix().M[0][0];
// Should be multiplied 0.5* for the diameter to radius, and by 2.0 because GetTanHalfFieldOfView() cover only half of the pixels.
float WorldDepthToPixelWorldRadius = TanHalfFieldOfView / float(View.ViewRect.Width());
PassParameters->WorldDepthToDepthError = WorldDepthToPixelWorldRadius * 2.0f;
}
PassParameters->SceneDepthTexture = PassInputs.SceneDepthTexture;
PassParameters->SceneVelocityTexture = PassInputs.SceneVelocityTexture;
PassParameters->DilatedVelocityOutput = GraphBuilder.CreateUAV(DilatedVelocityTexture);
PassParameters->ClosestDepthOutput = GraphBuilder.CreateUAV(ClosestDepthTexture);
PassParameters->PrevUseCountOutput = GraphBuilder.CreateUAV(PrevUseCountTexture);
PassParameters->PrevClosestDepthOutput = GraphBuilder.CreateUAV(PrevClosestDepthTexture);
PassParameters->ParallaxFactorOutput = GraphBuilder.CreateUAV(ParallaxFactorTexture);
// Setup up the motion blur's velocity flatten pass.
if (PassInputs.bGenerateVelocityFlattenTextures)
{
const int32 MotionBlurDirections = GetMotionBlurDirections();
PermutationVector.Set<FTSRDilateVelocityCS::FMotionBlurDirectionsDim>(MotionBlurDirections);
TileSize = FVelocityFlattenTextures::kTileSize;
{
FRDGTextureDesc Desc = FRDGTextureDesc::Create2D(
InputExtent,
PF_FloatR11G11B10,
FClearValueBinding::None,
GFastVRamConfig.VelocityFlat | TexCreate_ShaderResource | TexCreate_UAV);
VelocityFlattenTextures.VelocityFlatten.Texture = GraphBuilder.CreateTexture(Desc, TEXT("MotionBlur.VelocityTile"));
VelocityFlattenTextures.VelocityFlatten.ViewRect = InputRect;
}
{
FRDGTextureDesc Desc = FRDGTextureDesc::Create2D(
FIntPoint::DivideAndRoundUp(InputRect.Size(), FVelocityFlattenTextures::kTileSize),
PF_FloatRGBA,
FClearValueBinding::None,
GFastVRamConfig.MotionBlur | TexCreate_ShaderResource | TexCreate_UAV);
VelocityFlattenTextures.VelocityTile[0].Texture = GraphBuilder.CreateTexture(Desc, TEXT("MotionBlur.VelocityTile"));
VelocityFlattenTextures.VelocityTile[0].ViewRect = FIntRect(FIntPoint::ZeroValue, Desc.Extent);
Desc.Format = PF_G16R16F;
VelocityFlattenTextures.VelocityTile[1].Texture = GraphBuilder.CreateTexture(Desc, TEXT("MotionBlur.VelocityTile"));
VelocityFlattenTextures.VelocityTile[1].ViewRect = FIntRect(FIntPoint::ZeroValue, Desc.Extent);
}
PassParameters->VelocityFlattenParameters = GetVelocityFlattenParameters(View);
PassParameters->VelocityFlattenOutput = GraphBuilder.CreateUAV(VelocityFlattenTextures.VelocityFlatten.Texture);
PassParameters->VelocityTileOutput0 = GraphBuilder.CreateUAV(VelocityFlattenTextures.VelocityTile[0].Texture);
PassParameters->VelocityTileOutput1 = GraphBuilder.CreateUAV(VelocityFlattenTextures.VelocityTile[1].Texture);
}
PassParameters->DebugOutput = CreateDebugUAV(InputExtent, TEXT("Debug.TSR.DilateVelocity"));
TShaderMapRef<FTSRDilateVelocityCS> ComputeShader(View.ShaderMap, PermutationVector);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("TSR DilateVelocity(MotionBlurDirections=%d) %dx%d",
int32(PermutationVector.Get<FTSRDilateVelocityCS::FMotionBlurDirectionsDim>()),
InputRect.Width(), InputRect.Height()),
ComputeShader,
PassParameters,
FComputeShaderUtils::GetGroupCount(InputRect.Size(), TileSize));
}
// Setup a dummy history
FTSRHistoryTextures DummyHistory;
{
DummyHistory.LowFrequency = BlackDummy;
DummyHistory.HighFrequency = BlackDummy;
DummyHistory.Metadata = BlackDummy;
DummyHistory.Translucency = BlackDummy;
DummyHistory.TranslucencyAlpha = WhiteDummy;
DummyHistory.SubpixelDetails = BlackUintDummy;
DummyHistory.LowResTextures[0] = BlackDummy;
DummyHistory.SuperResTextures[0] = BlackUintDummy;
DummyHistory.SuperResTextures[1] = BlackUintDummy;
}
// Setup the previous frame history
FTSRHistoryTextures PrevHistory;
if (InputHistory.IsValid())
{
// Register filterable history
PrevHistory.LowFrequency = GraphBuilder.RegisterExternalTexture(InputHistory.LowFrequency);
PrevHistory.HighFrequency = GraphBuilder.RegisterExternalTexture(InputHistory.HighFrequency);
PrevHistory.Metadata = GraphBuilder.RegisterExternalTexture(InputHistory.Metadata);
PrevHistory.Translucency = InputHistory.Translucency.IsValid() ? GraphBuilder.RegisterExternalTexture(InputHistory.Translucency) : DummyHistory.Translucency;
PrevHistory.TranslucencyAlpha = InputHistory.TranslucencyAlpha.IsValid() ? GraphBuilder.RegisterExternalTexture(InputHistory.TranslucencyAlpha) : DummyHistory.TranslucencyAlpha;
// Register non-filterable history
PrevHistory.SubpixelDetails = GraphBuilder.RegisterExternalTexture(InputHistory.SubpixelDetails);
PrevHistory.LowResTextures[0] = InputHistory.LowResTextures[0].IsValid()
? GraphBuilder.RegisterExternalTexture(InputHistory.LowResTextures[0])
: DummyHistory.LowResTextures[0];
PrevHistory.SuperResTextures[0] = InputHistory.SuperResTextures[0].IsValid()
? GraphBuilder.RegisterExternalTexture(InputHistory.SuperResTextures[0])
: DummyHistory.SuperResTextures[0];
PrevHistory.SuperResTextures[1] = InputHistory.SuperResTextures[1].IsValid()
? GraphBuilder.RegisterExternalTexture(InputHistory.SuperResTextures[1])
: DummyHistory.SuperResTextures[1];
}
else
{
PrevHistory = DummyHistory;
}
// Setup the shader parameters for previous frame history
FTSRPrevHistoryParameters PrevHistoryParameters;
{
// Setup prev history parameters.
FScreenPassTextureViewport PrevHistoryViewport(PrevHistory.LowFrequency->Desc.Extent, InputHistory.OutputViewportRect);
if (bCameraCut)
{
PrevHistoryViewport.Extent = FIntPoint(1, 1);
PrevHistoryViewport.Rect = FIntRect(FIntPoint(0, 0), FIntPoint(1, 1));
}
PrevHistoryParameters.PrevHistoryInfo = GetScreenPassTextureViewportParameters(PrevHistoryViewport);
PrevHistoryParameters.ScreenPosToPrevHistoryBufferUV = FScreenTransform::ChangeTextureBasisFromTo(
PrevHistoryViewport, FScreenTransform::ETextureBasis::ScreenPosition, FScreenTransform::ETextureBasis::TextureUV);
PrevHistoryParameters.HistoryPreExposureCorrection = View.PreExposure / View.PrevViewInfo.SceneColorPreExposure;
}
// Create new history.
FTSRHistoryTextures History;
if (bEnableMoireHeuristic)
{
FRDGTextureDesc LowResDesc = FRDGTextureDesc::Create2D(
InputExtent,
PF_R8,
FClearValueBinding::None,
TexCreate_ShaderResource | TexCreate_UAV);
History.LowResTextures[0] = GraphBuilder.CreateTexture(LowResDesc, TEXT("TSR.History.LowResMetadata[0]"));
}
{
FRDGTextureDesc Desc = FRDGTextureDesc::Create2D(
HistoryExtent,
(CVarTSRR11G11B10History.GetValueOnRenderThread() != 0) ? PF_FloatR11G11B10 : PF_FloatRGBA,
FClearValueBinding::None,
TexCreate_ShaderResource | TexCreate_UAV);
History.LowFrequency = GraphBuilder.CreateTexture(Desc, TEXT("TSR.History.LowFrequencies"));
History.HighFrequency = GraphBuilder.CreateTexture(Desc, TEXT("TSR.History.HighFrequencies"));
Desc.Format = PF_R8G8;
History.Metadata = GraphBuilder.CreateTexture(Desc, TEXT("TSR.History.Metadata"));
if (bAccumulateSeparateTranslucency)
{
Desc.Format = (CVarTSRR11G11B10History.GetValueOnRenderThread() != 0) ? PF_FloatR11G11B10 : PF_FloatRGBA;
History.Translucency = GraphBuilder.CreateTexture(Desc, TEXT("TSR.History.Translucency"));
Desc.Format = PF_R8;
History.TranslucencyAlpha = GraphBuilder.CreateTexture(Desc, TEXT("TSR.History.TranslucencyAlpha"));
}
Desc.Format = PF_R16_UINT;
History.SubpixelDetails = GraphBuilder.CreateTexture(Desc, TEXT("TSR.History.SubpixelInfo"));
}
if (bEnableMoireHeuristic)
{
FRDGTextureDesc SuperResDesc = FRDGTextureDesc::Create2D(
HistoryExtent * 2,
PF_R16_UINT,
FClearValueBinding::None,
TexCreate_ShaderResource | TexCreate_UAV);
History.SuperResTextures[0] = GraphBuilder.CreateTexture(SuperResDesc, TEXT("TSR.History.SuperResMetadata[0]"));
//
SuperResDesc.Format = PF_R8_UINT;
History.SuperResTextures[1] = GraphBuilder.CreateTexture(SuperResDesc, TEXT("TSR.History.SuperResMetadata[1]"));
}
// Decimate input to flicker at same frequency as input.
FRDGTextureRef HalfResInputSceneColorTexture = nullptr;
FRDGTextureRef HalfResPredictionSceneColorTexture = nullptr;
FRDGTextureRef HalfResParallaxRejectionMaskTexture = nullptr;
FRDGTextureRef PredictionSceneColorTexture = nullptr;
FRDGTextureRef ParallaxRejectionMaskTexture = nullptr;
FRDGTextureRef InterferenceSeedTexture = nullptr;
{
{
FRDGTextureDesc Desc = FRDGTextureDesc::Create2D(
InputExtent,
PF_R8,
FClearValueBinding::None,
/* InFlags = */ TexCreate_ShaderResource | TexCreate_UAV);
ParallaxRejectionMaskTexture = GraphBuilder.CreateTexture(Desc, TEXT("TSR.ParallaxRejectionMask"));
// TODO(TSR): can compress to the history seed's 4bit per pixel
Desc.Format = PF_R8G8B8A8;
InterferenceSeedTexture = GraphBuilder.CreateTexture(Desc, TEXT("TSR.Moire.Seed"));
}
FTSRDecimateHistoryCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FTSRDecimateHistoryCS::FParameters>();
PassParameters->CommonParameters = CommonParameters;
{
const FViewMatrices& ViewMatrices = View.ViewMatrices;
const FViewMatrices& PrevViewMatrices = View.PrevViewInfo.ViewMatrices;
FMatrix RotationalInvViewProj = ViewMatrices.ComputeInvProjectionNoAAMatrix() * (ViewMatrices.GetTranslatedViewMatrix().RemoveTranslation().GetTransposed());
FMatrix RotationalPrevViewProj = (PrevViewMatrices.GetTranslatedViewMatrix().RemoveTranslation()) * PrevViewMatrices.ComputeProjectionNoAAMatrix();
PassParameters->RotationalClipToPrevClip = RotationalInvViewProj * RotationalPrevViewProj;
}
PassParameters->OutputQuantizationError = ComputePixelFormatQuantizationError(PF_FloatR11G11B10);
{
float TanHalfFieldOfView = View.ViewMatrices.GetInvProjectionMatrix().M[0][0];
// Should be multiplied 0.5* for the diameter to radius, and by 2.0 because GetTanHalfFieldOfView() cover only half of the pixels.
PassParameters->WorldDepthToPixelWorldRadius = TanHalfFieldOfView / float(View.ViewRect.Width());
}
PassParameters->InputSceneColorTexture = PassInputs.SceneColorTexture;
PassParameters->DilatedVelocityTexture = DilatedVelocityTexture;
PassParameters->ClosestDepthTexture = ClosestDepthTexture;
PassParameters->PrevUseCountTexture = PrevUseCountTexture;
PassParameters->PrevClosestDepthTexture = PrevClosestDepthTexture;
PassParameters->ParallaxFactorTexture = ParallaxFactorTexture;
PassParameters->PrevHistoryParameters = PrevHistoryParameters;
PassParameters->PrevHistory = PrevHistory;
if (bHalfResLowFrequency)
{
FRDGTextureDesc Desc = FRDGTextureDesc::Create2D(
LowFrequencyExtent,
PF_FloatR11G11B10,
FClearValueBinding::None,
/* InFlags = */ TexCreate_ShaderResource | TexCreate_UAV);
HalfResInputSceneColorTexture = GraphBuilder.CreateTexture(Desc, TEXT("TSR.HalfResInput"));
HalfResPredictionSceneColorTexture = GraphBuilder.CreateTexture(Desc, TEXT("TSR.Prediction.SceneColor"));
Desc.Format = PF_R8;
HalfResParallaxRejectionMaskTexture = GraphBuilder.CreateTexture(Desc, TEXT("TSR.HalfResParallaxRejectionMask"));
PassParameters->HalfResSceneColorOutput = GraphBuilder.CreateUAV(HalfResInputSceneColorTexture);
PassParameters->HalfResPredictionSceneColorOutput = GraphBuilder.CreateUAV(HalfResPredictionSceneColorTexture);
PassParameters->HalfResParallaxRejectionMaskOutput = GraphBuilder.CreateUAV(HalfResParallaxRejectionMaskTexture);
}
else
{
FRDGTextureDesc Desc = FRDGTextureDesc::Create2D(
InputExtent,
PF_FloatR11G11B10,
FClearValueBinding::None,
/* InFlags = */ TexCreate_ShaderResource | TexCreate_UAV);
PredictionSceneColorTexture = GraphBuilder.CreateTexture(Desc, TEXT("TSR.Prediction.SceneColor"));
PassParameters->PredictionSceneColorOutput = GraphBuilder.CreateUAV(PredictionSceneColorTexture);
}
PassParameters->ParallaxRejectionMaskOutput = GraphBuilder.CreateUAV(ParallaxRejectionMaskTexture);
PassParameters->InterferenceSeedOutput = GraphBuilder.CreateUAV(InterferenceSeedTexture);
PassParameters->DebugOutput = CreateDebugUAV(LowFrequencyExtent, TEXT("Debug.TSR.DecimateHistory"));
FTSRDecimateHistoryCS::FPermutationDomain PermutationVector;
PermutationVector.Set<FTSRDecimateHistoryCS::FOutputHalfRes>(bHalfResLowFrequency);
PermutationVector.Set<FTSRMoireHeuristic>(bEnableMoireHeuristic);
TShaderMapRef<FTSRDecimateHistoryCS> ComputeShader(View.ShaderMap, PermutationVector);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("TSR DecimateHistory(%s) %dx%d",
bHalfResLowFrequency ? TEXT("HalfResShadingOutput") : TEXT(""),
InputRect.Width(), InputRect.Height()),
ComputeShader,
PassParameters,
FComputeShaderUtils::GetGroupCount(InputRect.Size(), 8));
}
FRDGTextureRef TranslucencyRejectionTexture = nullptr;
if (bRejectSeparateTranslucency && View.PrevViewInfo.SeparateTranslucency != nullptr)
{
FRDGTextureRef PrevTranslucencyTexture;
FScreenPassTextureViewport PrevTranslucencyViewport;
if (View.PrevViewInfo.SeparateTranslucency)
{
PrevTranslucencyTexture = GraphBuilder.RegisterExternalTexture(View.PrevViewInfo.SeparateTranslucency);
PrevTranslucencyViewport = FScreenPassTextureViewport(PrevTranslucencyTexture->Desc.Extent, View.PrevViewInfo.ViewRect);
}
else
{
PrevTranslucencyTexture = BlackDummy;
PrevTranslucencyViewport = FScreenPassTextureViewport(FIntPoint(1, 1), FIntRect(FIntPoint(0, 0), FIntPoint(1, 1)));
}
{
FRDGTextureDesc Desc = FRDGTextureDesc::Create2D(
InputExtent,
PF_R8,
FClearValueBinding::None,
/* InFlags = */ TexCreate_ShaderResource | TexCreate_UAV);
TranslucencyRejectionTexture = GraphBuilder.CreateTexture(Desc, TEXT("TSR.TranslucencyRejection"));
}
FTSRCompareTranslucencyCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FTSRCompareTranslucencyCS::FParameters>();
PassParameters->CommonParameters = CommonParameters;
PassParameters->TranslucencyInfo = GetScreenPassTextureViewportParameters(FScreenPassTextureViewport(
InputExtent, InputRect));
PassParameters->PrevTranslucencyInfo = GetScreenPassTextureViewportParameters(PrevTranslucencyViewport);
PassParameters->PrevTranslucencyPreExposureCorrection = PrevHistoryParameters.HistoryPreExposureCorrection;
PassParameters->TranslucencyHighlightLuminance = CVarTSRTranslucencyHighlightLuminance.GetValueOnRenderThread();
PassParameters->ScreenPosToPrevTranslucencyTextureUV = FScreenTransform::ChangeTextureBasisFromTo(
PrevTranslucencyViewport, FScreenTransform::ETextureBasis::ScreenPosition, FScreenTransform::ETextureBasis::TextureUV);
PassParameters->DilatedVelocityTexture = DilatedVelocityTexture;
PassParameters->TranslucencyTexture = SeparateTranslucencyTexture;
PassParameters->PrevTranslucencyTexture = PrevTranslucencyTexture;
PassParameters->TranslucencyRejectionOutput = GraphBuilder.CreateUAV(TranslucencyRejectionTexture);
PassParameters->DebugOutput = CreateDebugUAV(LowFrequencyExtent, TEXT("Debug.TSR.CompareTranslucency"));
TShaderMapRef<FTSRCompareTranslucencyCS> ComputeShader(View.ShaderMap);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("TSR CompareTranslucency %dx%d", InputRect.Width(), InputRect.Height()),
ComputeShader,
PassParameters,
FComputeShaderUtils::GetGroupCount(InputRect.Size(), 8));
}
// Detect interference between geometry and alignement of input texel centers. It is not about awnser whether an
// interference has happened in the past, because interference change based on input resolution or camera position.
// So to remain stable on camera movement and input resolution change, it is about awnsering the question on whether
// an interference is possible.
// TODO(TSR): Could sample the interference seed in the DilateVelocity and detect interference in the decimate.
FRDGTextureRef InterferenceWeightTexture;
if (bEnableMoireHeuristic)
{
{
// TODO(TSR): Compress to 1bit per pixel
FRDGTextureDesc Desc = FRDGTextureDesc::Create2D(
InputExtent,
PF_R8,
FClearValueBinding::None,
/* InFlags = */ TexCreate_ShaderResource | TexCreate_UAV);
InterferenceWeightTexture = GraphBuilder.CreateTexture(Desc, TEXT("TSR.Moire.Weight"));
}
FTSRDetectInterferenceCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FTSRDetectInterferenceCS::FParameters>();
PassParameters->CommonParameters = CommonParameters;
PassParameters->InputSceneColorTexture = PassInputs.SceneColorTexture;
PassParameters->DilatedVelocityTexture = DilatedVelocityTexture;
PassParameters->PredictionSceneColorTexture = PredictionSceneColorTexture;
PassParameters->ParallaxRejectionMaskTexture = ParallaxRejectionMaskTexture;
PassParameters->InterferenceSeedTexture = InterferenceSeedTexture;
PassParameters->PrevHistoryParameters = PrevHistoryParameters;
PassParameters->PrevHistory = PrevHistory;
PassParameters->HistoryOutput = CreateUAVs(GraphBuilder, History);
PassParameters->InterferenceWeightOutput = GraphBuilder.CreateUAV(InterferenceWeightTexture);
PassParameters->DebugOutput = CreateDebugUAV(LowFrequencyExtent, TEXT("Debug.TSR.DetectInterference"));
TShaderMapRef<FTSRDetectInterferenceCS> ComputeShader(View.ShaderMap);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("TSR DetectInterference %dx%d", InputRect.Width(), InputRect.Height()),
ComputeShader,
PassParameters,
FComputeShaderUtils::GetGroupCount(InputRect.Size(), 8));
}
else
{
InterferenceWeightTexture = WhiteDummy;
}
FRDGTextureRef HoleFilledVelocityMaskTexture = BlackDummy;
if (bHoleFillVelocity)
{
FRDGTextureRef HoleFilledVelocityTexture;
{
FRDGTextureDesc Desc = FRDGTextureDesc::Create2D(
InputExtent,
PF_G16R16,
FClearValueBinding::None,
/* InFlags = */ TexCreate_ShaderResource | TexCreate_UAV);
HoleFilledVelocityTexture = GraphBuilder.CreateTexture(Desc, TEXT("TSR.Velocity.HoleFilled"));
Desc.Format = PF_R8G8;
HoleFilledVelocityMaskTexture = GraphBuilder.CreateTexture(Desc, TEXT("TSR.velocity.HoleFillMask"));
}
FTSRHoleFillVelocityCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FTSRHoleFillVelocityCS::FParameters>();
PassParameters->CommonParameters = CommonParameters;
PassParameters->MaxHollFillPixelVelocity = CVarTSRVelocityMaxHoleFillScatterVelocity.GetValueOnRenderThread() * ScreenPercentage;
PassParameters->PrevClosestDepthTexture = PrevClosestDepthTexture;
PassParameters->DilatedVelocityTexture = DilatedVelocityTexture;
PassParameters->ParallaxRejectionMaskTexture = ParallaxRejectionMaskTexture;
PassParameters->HoleFilledVelocityOutput = GraphBuilder.CreateUAV(HoleFilledVelocityTexture);
PassParameters->HoleFilledVelocityMaskOutput = GraphBuilder.CreateUAV(HoleFilledVelocityMaskTexture);
PassParameters->DebugOutput = CreateDebugUAV(LowFrequencyExtent, TEXT("Debug.TSR.HoleFillVelocity"));
TShaderMapRef<FTSRHoleFillVelocityCS> ComputeShader(View.ShaderMap);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("TSR HoleFillVelocity %dx%d", InputRect.Width(), InputRect.Height()),
ComputeShader,
PassParameters,
FComputeShaderUtils::GetGroupCount(InputRect.Size(), 8));
DilatedVelocityTexture = HoleFilledVelocityTexture;
}
// Reject the history with frequency decomposition.
FRDGTextureRef HistoryRejectionTexture;
FRDGTextureRef InputSceneColorLdrLumaTexture = nullptr;
{
// Filter out the high frquencies
FRDGTextureRef FilteredInputTexture;
FRDGTextureRef FilteredPredictionSceneColorTexture;
FRDGTextureRef FilteredInterferenceSeedTexture = nullptr;
{
{
FRDGTextureDesc Desc = FRDGTextureDesc::Create2D(
LowFrequencyExtent,
PF_FloatR11G11B10,
FClearValueBinding::None,
/* InFlags = */ TexCreate_ShaderResource | TexCreate_UAV);
FilteredInputTexture = GraphBuilder.CreateTexture(Desc, TEXT("TSR.Filtered.SceneColor"));
FilteredPredictionSceneColorTexture = GraphBuilder.CreateTexture(Desc, TEXT("TSR.Filtered.Prediction.SceneColor"));
}
if (RejectionAntiAliasingQuality > 0)
{
FRDGTextureDesc Desc = FRDGTextureDesc::Create2D(
LowFrequencyExtent,
PF_R8,
FClearValueBinding::None,
/* InFlags = */ TexCreate_ShaderResource | TexCreate_UAV);
InputSceneColorLdrLumaTexture = GraphBuilder.CreateTexture(Desc, TEXT("TSR.SceneColorLdrLuma"));
}
{
FRDGTextureDesc Desc = FRDGTextureDesc::Create2D(
LowFrequencyExtent,
PF_R8G8B8A8,
FClearValueBinding::None,
/* InFlags = */ TexCreate_ShaderResource | TexCreate_UAV);
FilteredInterferenceSeedTexture = GraphBuilder.CreateTexture(Desc, TEXT("TSR.Moire.FilteredSeeds"));
}
FTSRFilterFrequenciesCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FTSRFilterFrequenciesCS::FParameters>();
PassParameters->CommonParameters = CommonParameters;
PassParameters->OutputQuantizationError = ComputePixelFormatQuantizationError(FilteredInputTexture->Desc.Format);
if (bHalfResLowFrequency)
{
PassParameters->InputTexture = HalfResInputSceneColorTexture;
PassParameters->PredictionSceneColorTexture = HalfResPredictionSceneColorTexture;
PassParameters->ParallaxRejectionMaskTexture = HalfResParallaxRejectionMaskTexture;
}
else
{
PassParameters->InputTexture = PassInputs.SceneColorTexture;
PassParameters->PredictionSceneColorTexture = PredictionSceneColorTexture;
PassParameters->ParallaxRejectionMaskTexture = ParallaxRejectionMaskTexture;
PassParameters->InterferenceSeedTexture = InterferenceSeedTexture;
PassParameters->InterferenceWeightTexture = InterferenceWeightTexture;
}
PassParameters->FilteredInputOutput = GraphBuilder.CreateUAV(FilteredInputTexture);
PassParameters->FilteredPredictionSceneColorOutput = GraphBuilder.CreateUAV(FilteredPredictionSceneColorTexture);
PassParameters->FilteredInterferenceSeedOutput = GraphBuilder.CreateUAV(FilteredInterferenceSeedTexture);
PassParameters->InputSceneColorLdrLumaOutput = InputSceneColorLdrLumaTexture ? GraphBuilder.CreateUAV(InputSceneColorLdrLumaTexture) : nullptr;
PassParameters->DebugOutput = CreateDebugUAV(LowFrequencyExtent, TEXT("Debug.TSR.FilterFrequencies"));
FTSRFilterFrequenciesCS::FPermutationDomain PermutationVector;
PermutationVector.Set<FTSRFilterFrequenciesCS::FOutputAALumaDim>(RejectionAntiAliasingQuality > 0);
PermutationVector.Set<FTSRMoireHeuristic>(bEnableMoireHeuristic);
TShaderMapRef<FTSRFilterFrequenciesCS> ComputeShader(View.ShaderMap, PermutationVector);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("TSR FilterFrequencies(%s) %dx%d",
PermutationVector.Get<FTSRFilterFrequenciesCS::FOutputAALumaDim>() ? TEXT("OutputAALuma") : TEXT(""),
LowFrequencyRect.Width(), LowFrequencyRect.Height()),
ComputeShader,
PassParameters,
FComputeShaderUtils::GetGroupCount(LowFrequencyRect.Size(), 16));
}
// Compare the low frequencies
{
bool bOutputHalfRes = PostFilter != ERejectionPostFilter::PreRejectionDownsample;
{
FRDGTextureDesc Desc = FRDGTextureDesc::Create2D(
bOutputHalfRes ? RejectionExtent : LowFrequencyExtent,
PF_R8,
FClearValueBinding::None,
/* InFlags = */ TexCreate_ShaderResource | TexCreate_UAV);
HistoryRejectionTexture = GraphBuilder.CreateTexture(Desc, TEXT("TSR.HistoryRejection"));
}
FTSRCompareHistoryCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FTSRCompareHistoryCS::FParameters>();
PassParameters->CommonParameters = CommonParameters;
PassParameters->ParallaxRejectionMaskTexture = ParallaxRejectionMaskTexture;
PassParameters->FilteredInputTexture = FilteredInputTexture;
PassParameters->FilteredPredictionSceneColorTexture = FilteredPredictionSceneColorTexture;
PassParameters->FilteredInterferenceSeedTexture = FilteredInterferenceSeedTexture;
PassParameters->InterferenceWeightTexture = InterferenceWeightTexture;
PassParameters->HistoryRejectionOutput = GraphBuilder.CreateUAV(HistoryRejectionTexture);
PassParameters->DebugOutput = CreateDebugUAV(LowFrequencyExtent, TEXT("Debug.TSR.CompareHistory"));
FTSRCompareHistoryCS::FPermutationDomain PermutationVector;
PermutationVector.Set<FTSRCompareHistoryCS::FOutputHalfRes>(bOutputHalfRes);
PermutationVector.Set<FTSRMoireHeuristic>(bEnableMoireHeuristic);
TShaderMapRef<FTSRCompareHistoryCS> ComputeShader(View.ShaderMap, PermutationVector);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("TSR CompareHistory %dx%d", LowFrequencyRect.Width(), LowFrequencyRect.Height()),
ComputeShader,
PassParameters,
FComputeShaderUtils::GetGroupCount(LowFrequencyRect.Size(), 16));
}
}
// Spatial anti-aliasing when doing history rejection.
FRDGTextureRef AntiAliasingTexture = nullptr;
FRDGTextureRef NoiseFilteringTexture = nullptr;
if (RejectionAntiAliasingQuality > 0)
{
FRDGTextureRef RawAntiAliasingTexture;
{
FRDGTextureDesc Desc = FRDGTextureDesc::Create2D(
InputExtent,
PF_R8_UINT,
FClearValueBinding::None,
/* InFlags = */ TexCreate_ShaderResource | TexCreate_UAV);
RawAntiAliasingTexture = GraphBuilder.CreateTexture(Desc, TEXT("TSR.AntiAliasing.Raw"));
AntiAliasingTexture = GraphBuilder.CreateTexture(Desc, TEXT("TSR.AntiAliasing.Filtered"));
Desc.Format = PF_R8;
NoiseFilteringTexture = GraphBuilder.CreateTexture(Desc, TEXT("TSR.AntiAliasing.Noise"));
}
{
FTSRSpatialAntiAliasingCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FTSRSpatialAntiAliasingCS::FParameters>();
PassParameters->CommonParameters = CommonParameters;
PassParameters->InputSceneColorTexture = PassInputs.SceneColorTexture;
PassParameters->InputSceneColorLdrLumaTexture = InputSceneColorLdrLumaTexture;
PassParameters->AntiAliasingOutput = GraphBuilder.CreateUAV(RawAntiAliasingTexture);
PassParameters->NoiseFilteringOutput = GraphBuilder.CreateUAV(NoiseFilteringTexture);
PassParameters->DebugOutput = CreateDebugUAV(InputExtent, TEXT("Debug.TSR.SpatialAntiAliasing"));
FTSRSpatialAntiAliasingCS::FPermutationDomain PermutationVector;
PermutationVector.Set<FTSRSpatialAntiAliasingCS::FQualityDim>(RejectionAntiAliasingQuality);
TShaderMapRef<FTSRSpatialAntiAliasingCS> ComputeShader(View.ShaderMap, PermutationVector);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("TSR SpatialAntiAliasing(Quality=%d) %dx%d",
RejectionAntiAliasingQuality,
InputRect.Width(), InputRect.Height()),
ComputeShader,
PassParameters,
FComputeShaderUtils::GetGroupCount(InputRect.Size(), 8));
}
{
FTSRFilterAntiAliasingCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FTSRFilterAntiAliasingCS::FParameters>();
PassParameters->CommonParameters = CommonParameters;
PassParameters->AntiAliasingTexture = RawAntiAliasingTexture;
PassParameters->AntiAliasingOutput = GraphBuilder.CreateUAV(AntiAliasingTexture);
PassParameters->DebugOutput = CreateDebugUAV(InputExtent, TEXT("Debug.TSR.FilterAntiAliasing"));
TShaderMapRef<FTSRFilterAntiAliasingCS> ComputeShader(View.ShaderMap);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("TSR FilterAntiAliasing %dx%d", InputRect.Width(), InputRect.Height()),
ComputeShader,
PassParameters,
FComputeShaderUtils::GetGroupCount(InputRect.Size(), 8));
}
}
// Post filter the rejection.
if (PostFilter != ERejectionPostFilter::Disabled)
{
bool bOutputHalfRes = PostFilter == ERejectionPostFilter::PreRejectionDownsample;
FIntRect Rect = bOutputHalfRes ? LowFrequencyRect : RejectionRect;
FRDGTextureRef FilteredHistoryRejectionTexture;
{
FRDGTextureDesc Desc = FRDGTextureDesc::Create2D(
RejectionExtent,
PF_R8,
FClearValueBinding::None,
/* InFlags = */ TexCreate_ShaderResource | TexCreate_UAV);
FilteredHistoryRejectionTexture = GraphBuilder.CreateTexture(Desc, TEXT("TSR.HistoryRejection"));
}
FTSRPostfilterRejectionCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FTSRPostfilterRejectionCS::FParameters>();
PassParameters->HistoryRejectionViewport = Rect;
PassParameters->HistoryRejectionTexture = HistoryRejectionTexture;
PassParameters->HistoryRejectionOutput = GraphBuilder.CreateUAV(FilteredHistoryRejectionTexture);
PassParameters->DebugOutput = CreateDebugUAV(bOutputHalfRes ? LowFrequencyExtent : RejectionExtent, TEXT("Debug.TSR.PostfilterRejection"));
FTSRPostfilterRejectionCS::FPermutationDomain PermutationVector;
PermutationVector.Set<FTSRPostfilterRejectionCS::FOutputHalfRes>(PostFilter == ERejectionPostFilter::PreRejectionDownsample);
TShaderMapRef<FTSRPostfilterRejectionCS> ComputeShader(View.ShaderMap, PermutationVector);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("TSR PostfilterRejection %dx%d", Rect.Width(), Rect.Height()),
ComputeShader,
PassParameters,
FComputeShaderUtils::GetGroupCount(Rect.Size(), 8));
HistoryRejectionTexture = FilteredHistoryRejectionTexture;
}
// Dilate the rejection.
FRDGTextureRef DilatedHistoryRejectionTexture;
{
DilatedHistoryRejectionTexture = GraphBuilder.CreateTexture(HistoryRejectionTexture->Desc, TEXT("TSR.DilatedHistoryRejection"));
FTSRDilateRejectionCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FTSRDilateRejectionCS::FParameters>();
PassParameters->CommonParameters = CommonParameters;
PassParameters->HistoryRejectionTexture = HistoryRejectionTexture;
PassParameters->DilatedHistoryRejectionOutput = GraphBuilder.CreateUAV(DilatedHistoryRejectionTexture);
PassParameters->DebugOutput = CreateDebugUAV(RejectionExtent, TEXT("Debug.TSR.DilateRejection"));
TShaderMapRef<FTSRDilateRejectionCS> ComputeShader(View.ShaderMap);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("TSR DilateRejection %dx%d", RejectionRect.Width(), RejectionRect.Height()),
ComputeShader,
PassParameters,
FComputeShaderUtils::GetGroupCount(RejectionRect.Size(), 8));
}
if (bEnableMoireHeuristic)
{
FTSRUpdateSuperResHistoryCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FTSRUpdateSuperResHistoryCS::FParameters>();
PassParameters->CommonParameters = CommonParameters;
PassParameters->InputSceneColorTexture = PassInputs.SceneColorTexture;
PassParameters->DilatedVelocityTexture = DilatedVelocityTexture;
PassParameters->ParallaxRejectionMaskTexture = ParallaxRejectionMaskTexture;
PassParameters->PrevHistoryParameters = PrevHistoryParameters;
PassParameters->PrevHistory = PrevHistory;
PassParameters->HistoryOutput = CreateUAVs(GraphBuilder, History);
PassParameters->DebugOutput = CreateDebugUAV(HistoryExtent * 2, TEXT("Debug.TSR.UpdateSuperResHistory"));
TShaderMapRef<FTSRUpdateSuperResHistoryCS> ComputeShader(View.ShaderMap);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("TSR UpdateSuperResHistory %dx%d", HistorySize.X * 2, HistorySize.Y * 2),
ComputeShader,
PassParameters,
FComputeShaderUtils::GetGroupCount(HistorySize * 2, 8));
}
FRDGTextureRef SceneColorOutputTexture;
{
// Allocate output
{
FRDGTextureDesc Desc = FRDGTextureDesc::Create2D(
HistoryExtent,
PF_FloatR11G11B10,
FClearValueBinding::None,
Implements dynamic half-res motion blur 1) Motionblur have tile classification to improve VGPR pressure on fast motion blur gathering tiles 2) Motionblur tile classification can lower the gathering resolution to half res with r.MotionBlur.HalfResGather=1 on part of the screen with large motion vectors to reduce VALU costs under large movements, but still can compose with full res scene color without round trip to main memory to avoid adding memory bandwidth costs 3) TSR output a half res scene color in Mip1 so motion blur can dynamically sample half res under largement movements with r.MotionBlur.HalfResInput=1 to save memory bandwidth in the motion blur convolution 4) Number of direction samples becomes dynamic (and clamped to exisiting motion blur quality) based on length of motion vector to saves VALU with slow pixel velocities 5) Motion blur automatically avoid sampling full res center if the blur kernel completly occlude its to completly stop fetching full res to save memory bandwidth cost under large motions Drops motion blur costs from 753us to 339us of motion blur costs + 40us additional cost in TSR to output half res in sandbox under movements. And saves an average 0.3ms in the entire chase gameplay sequence. #rb josie.yang [FYI] brian.karis #preflight 616960548b364e0001807ac7, 616998724cf7190001d2e6f2 #lockdown michal.valient #ROBOMERGE-OWNER: guillaume.abadie #ROBOMERGE-AUTHOR: guillaume.abadie #ROBOMERGE-SOURCE: CL 17830244 via CL 18002937 via CL 18369356 via CL 18369373 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v895-18170469) [CL 18369376 by guillaume abadie in ue5-release-engine-test branch]
2021-12-03 12:40:10 -05:00
/* InFlags = */ TexCreate_ShaderResource | TexCreate_UAV,
/* NumMips = */ PassInputs.bGenerateOutputMip1 ? 2 : 1);
SceneColorOutputTexture = GraphBuilder.CreateTexture(Desc, TEXT("TSR.Output"));
}
FTSRUpdateHistoryCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FTSRUpdateHistoryCS::FParameters>();
PassParameters->CommonParameters = CommonParameters;
PassParameters->InputSceneColorTexture = PassInputs.SceneColorTexture;
PassParameters->InputSceneStencilTexture = GraphBuilder.CreateSRV(
FRDGTextureSRVDesc::CreateWithPixelFormat(PassInputs.SceneDepthTexture, PF_X24_G8));
PassParameters->InputSceneTranslucencyTexture = SeparateTranslucencyTexture;
PassParameters->InterferenceWeightTexture = InterferenceWeightTexture;
PassParameters->HistoryRejectionTexture = DilatedHistoryRejectionTexture;
PassParameters->TranslucencyRejectionTexture = TranslucencyRejectionTexture ? TranslucencyRejectionTexture : BlackDummy;
PassParameters->DilatedVelocityTexture = DilatedVelocityTexture;
PassParameters->ParallaxFactorTexture = ParallaxFactorTexture;
PassParameters->ParallaxRejectionMaskTexture = ParallaxRejectionMaskTexture;
PassParameters->AntiAliasingTexture = AntiAliasingTexture;
PassParameters->NoiseFilteringTexture = NoiseFilteringTexture;
PassParameters->HoleFilledVelocityMaskTexture = HoleFilledVelocityMaskTexture;
FScreenTransform HistoryPixelPosToViewportUV = (FScreenTransform::Identity + 0.5f) * CommonParameters.HistoryInfo.ViewportSizeInverse;
PassParameters->HistoryPixelPosToScreenPos = HistoryPixelPosToViewportUV * FScreenTransform::ViewportUVToScreenPos;
PassParameters->HistoryPixelPosToPPCo = HistoryPixelPosToViewportUV * CommonParameters.InputInfo.ViewportSize + CommonParameters.InputJitter + CommonParameters.InputPixelPosMin;
PassParameters->HistoryQuantizationError = ComputePixelFormatQuantizationError(History.LowFrequency->Desc.Format);
PassParameters->MinTranslucencyRejection = TranslucencyRejectionTexture == nullptr ? 1.0 : 0.0;
PassParameters->InvWeightClampingPixelSpeed = 1.0f / CVarTSRWeightClampingPixelSpeed.GetValueOnRenderThread();
PassParameters->InputToHistoryFactor = float(HistorySize.X) / float(InputRect.Width());
PassParameters->ResponsiveStencilMask = CVarTSREnableResponiveAA.GetValueOnRenderThread() ? (STENCIL_TEMPORAL_RESPONSIVE_AA_MASK) : 0;
Implements dynamic half-res motion blur 1) Motionblur have tile classification to improve VGPR pressure on fast motion blur gathering tiles 2) Motionblur tile classification can lower the gathering resolution to half res with r.MotionBlur.HalfResGather=1 on part of the screen with large motion vectors to reduce VALU costs under large movements, but still can compose with full res scene color without round trip to main memory to avoid adding memory bandwidth costs 3) TSR output a half res scene color in Mip1 so motion blur can dynamically sample half res under largement movements with r.MotionBlur.HalfResInput=1 to save memory bandwidth in the motion blur convolution 4) Number of direction samples becomes dynamic (and clamped to exisiting motion blur quality) based on length of motion vector to saves VALU with slow pixel velocities 5) Motion blur automatically avoid sampling full res center if the blur kernel completly occlude its to completly stop fetching full res to save memory bandwidth cost under large motions Drops motion blur costs from 753us to 339us of motion blur costs + 40us additional cost in TSR to output half res in sandbox under movements. And saves an average 0.3ms in the entire chase gameplay sequence. #rb josie.yang [FYI] brian.karis #preflight 616960548b364e0001807ac7, 616998724cf7190001d2e6f2 #lockdown michal.valient #ROBOMERGE-OWNER: guillaume.abadie #ROBOMERGE-AUTHOR: guillaume.abadie #ROBOMERGE-SOURCE: CL 17830244 via CL 18002937 via CL 18369356 via CL 18369373 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v895-18170469) [CL 18369376 by guillaume abadie in ue5-release-engine-test branch]
2021-12-03 12:40:10 -05:00
PassParameters->bGenerateOutputMip1 = PassInputs.bGenerateOutputMip1 ? 1 : 0;
PassParameters->PrevHistoryParameters = PrevHistoryParameters;
PassParameters->PrevHistory = PrevHistory;
PassParameters->HistoryOutput = CreateUAVs(GraphBuilder, History);
Implements dynamic half-res motion blur 1) Motionblur have tile classification to improve VGPR pressure on fast motion blur gathering tiles 2) Motionblur tile classification can lower the gathering resolution to half res with r.MotionBlur.HalfResGather=1 on part of the screen with large motion vectors to reduce VALU costs under large movements, but still can compose with full res scene color without round trip to main memory to avoid adding memory bandwidth costs 3) TSR output a half res scene color in Mip1 so motion blur can dynamically sample half res under largement movements with r.MotionBlur.HalfResInput=1 to save memory bandwidth in the motion blur convolution 4) Number of direction samples becomes dynamic (and clamped to exisiting motion blur quality) based on length of motion vector to saves VALU with slow pixel velocities 5) Motion blur automatically avoid sampling full res center if the blur kernel completly occlude its to completly stop fetching full res to save memory bandwidth cost under large motions Drops motion blur costs from 753us to 339us of motion blur costs + 40us additional cost in TSR to output half res in sandbox under movements. And saves an average 0.3ms in the entire chase gameplay sequence. #rb josie.yang [FYI] brian.karis #preflight 616960548b364e0001807ac7, 616998724cf7190001d2e6f2 #lockdown michal.valient #ROBOMERGE-OWNER: guillaume.abadie #ROBOMERGE-AUTHOR: guillaume.abadie #ROBOMERGE-SOURCE: CL 17830244 via CL 18002937 via CL 18369356 via CL 18369373 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v895-18170469) [CL 18369376 by guillaume abadie in ue5-release-engine-test branch]
2021-12-03 12:40:10 -05:00
PassParameters->SceneColorOutputMip0 = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(SceneColorOutputTexture, /* InMipLevel = */ 0));
if (PassInputs.bGenerateOutputMip1)
{
PassParameters->SceneColorOutputMip1 = GraphBuilder.CreateUAV(FRDGTextureUAVDesc(SceneColorOutputTexture, /* InMipLevel = */ 1));
}
else
{
FRDGTextureDesc Desc = FRDGTextureDesc::Create2D(
FIntPoint(1, 1),
PF_FloatR11G11B10,
FClearValueBinding::None,
/* InFlags = */ TexCreate_ShaderResource | TexCreate_UAV);
FRDGTextureRef DummyTexture = GraphBuilder.CreateTexture(Desc, TEXT("TSR.DummyOutput"));
PassParameters->SceneColorOutputMip1 = GraphBuilder.CreateUAV(DummyTexture);
GraphBuilder.RemoveUnusedTextureWarning(DummyTexture);
Implements dynamic half-res motion blur 1) Motionblur have tile classification to improve VGPR pressure on fast motion blur gathering tiles 2) Motionblur tile classification can lower the gathering resolution to half res with r.MotionBlur.HalfResGather=1 on part of the screen with large motion vectors to reduce VALU costs under large movements, but still can compose with full res scene color without round trip to main memory to avoid adding memory bandwidth costs 3) TSR output a half res scene color in Mip1 so motion blur can dynamically sample half res under largement movements with r.MotionBlur.HalfResInput=1 to save memory bandwidth in the motion blur convolution 4) Number of direction samples becomes dynamic (and clamped to exisiting motion blur quality) based on length of motion vector to saves VALU with slow pixel velocities 5) Motion blur automatically avoid sampling full res center if the blur kernel completly occlude its to completly stop fetching full res to save memory bandwidth cost under large motions Drops motion blur costs from 753us to 339us of motion blur costs + 40us additional cost in TSR to output half res in sandbox under movements. And saves an average 0.3ms in the entire chase gameplay sequence. #rb josie.yang [FYI] brian.karis #preflight 616960548b364e0001807ac7, 616998724cf7190001d2e6f2 #lockdown michal.valient #ROBOMERGE-OWNER: guillaume.abadie #ROBOMERGE-AUTHOR: guillaume.abadie #ROBOMERGE-SOURCE: CL 17830244 via CL 18002937 via CL 18369356 via CL 18369373 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v895-18170469) [CL 18369376 by guillaume abadie in ue5-release-engine-test branch]
2021-12-03 12:40:10 -05:00
}
PassParameters->DebugOutput = CreateDebugUAV(HistoryExtent, TEXT("Debug.TSR.UpdateHistory"));
FTSRUpdateHistoryCS::FPermutationDomain PermutationVector;
PermutationVector.Set<FTSRUpdateHistoryCS::FRejectionAADim>(RejectionAntiAliasingQuality > 0);
PermutationVector.Set<FTSRUpdateHistoryCS::FSeparateTranslucencyDim>(bAccumulateSeparateTranslucency);
PermutationVector.Set<FTSRMoireHeuristic>(bEnableMoireHeuristic);
TShaderMapRef<FTSRUpdateHistoryCS> ComputeShader(View.ShaderMap, PermutationVector);
FComputeShaderUtils::AddPass(
GraphBuilder,
Implements dynamic half-res motion blur 1) Motionblur have tile classification to improve VGPR pressure on fast motion blur gathering tiles 2) Motionblur tile classification can lower the gathering resolution to half res with r.MotionBlur.HalfResGather=1 on part of the screen with large motion vectors to reduce VALU costs under large movements, but still can compose with full res scene color without round trip to main memory to avoid adding memory bandwidth costs 3) TSR output a half res scene color in Mip1 so motion blur can dynamically sample half res under largement movements with r.MotionBlur.HalfResInput=1 to save memory bandwidth in the motion blur convolution 4) Number of direction samples becomes dynamic (and clamped to exisiting motion blur quality) based on length of motion vector to saves VALU with slow pixel velocities 5) Motion blur automatically avoid sampling full res center if the blur kernel completly occlude its to completly stop fetching full res to save memory bandwidth cost under large motions Drops motion blur costs from 753us to 339us of motion blur costs + 40us additional cost in TSR to output half res in sandbox under movements. And saves an average 0.3ms in the entire chase gameplay sequence. #rb josie.yang [FYI] brian.karis #preflight 616960548b364e0001807ac7, 616998724cf7190001d2e6f2 #lockdown michal.valient #ROBOMERGE-OWNER: guillaume.abadie #ROBOMERGE-AUTHOR: guillaume.abadie #ROBOMERGE-SOURCE: CL 17830244 via CL 18002937 via CL 18369356 via CL 18369373 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v895-18170469) [CL 18369376 by guillaume abadie in ue5-release-engine-test branch]
2021-12-03 12:40:10 -05:00
RDG_EVENT_NAME("TSR UpdateHistory(%s%s%s%s) %dx%d",
History.LowFrequency->Desc.Format == PF_FloatR11G11B10 ? TEXT("R11G11B10") : TEXT(""),
PermutationVector.Get<FTSRUpdateHistoryCS::FRejectionAADim>() ? TEXT(" RejectionAA") : TEXT(""),
PermutationVector.Get<FTSRUpdateHistoryCS::FSeparateTranslucencyDim>() ? TEXT(" SeparateTranslucency") : TEXT(""),
Implements dynamic half-res motion blur 1) Motionblur have tile classification to improve VGPR pressure on fast motion blur gathering tiles 2) Motionblur tile classification can lower the gathering resolution to half res with r.MotionBlur.HalfResGather=1 on part of the screen with large motion vectors to reduce VALU costs under large movements, but still can compose with full res scene color without round trip to main memory to avoid adding memory bandwidth costs 3) TSR output a half res scene color in Mip1 so motion blur can dynamically sample half res under largement movements with r.MotionBlur.HalfResInput=1 to save memory bandwidth in the motion blur convolution 4) Number of direction samples becomes dynamic (and clamped to exisiting motion blur quality) based on length of motion vector to saves VALU with slow pixel velocities 5) Motion blur automatically avoid sampling full res center if the blur kernel completly occlude its to completly stop fetching full res to save memory bandwidth cost under large motions Drops motion blur costs from 753us to 339us of motion blur costs + 40us additional cost in TSR to output half res in sandbox under movements. And saves an average 0.3ms in the entire chase gameplay sequence. #rb josie.yang [FYI] brian.karis #preflight 616960548b364e0001807ac7, 616998724cf7190001d2e6f2 #lockdown michal.valient #ROBOMERGE-OWNER: guillaume.abadie #ROBOMERGE-AUTHOR: guillaume.abadie #ROBOMERGE-SOURCE: CL 17830244 via CL 18002937 via CL 18369356 via CL 18369373 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v895-18170469) [CL 18369376 by guillaume abadie in ue5-release-engine-test branch]
2021-12-03 12:40:10 -05:00
PassInputs.bGenerateOutputMip1 ? TEXT(" OutputMip1") : TEXT(""),
HistorySize.X, HistorySize.Y),
ComputeShader,
PassParameters,
FComputeShaderUtils::GetGroupCount(HistorySize, 8));
}
// Debug the history.
#if COMPILE_TSR_DEBUG_PASSES
if (bSetupDebugPasses)
{
const int32 kHistoryUpscalingFactor = 2;
FTSRDebugHistoryCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FTSRDebugHistoryCS::FParameters>();
PassParameters->CommonParameters = CommonParameters;
PassParameters->History = History;
PassParameters->PrevHistory = PrevHistory;
PassParameters->DebugOutput = CreateDebugUAV(HistoryExtent * kHistoryUpscalingFactor, TEXT("Debug.TSR.History"));
TShaderMapRef<FTSRDebugHistoryCS> ComputeShader(View.ShaderMap);
FComputeShaderUtils::AddPass(
GraphBuilder,
RDG_EVENT_NAME("TSR DebugHistory %dx%d", HistorySize.X, HistorySize.Y),
ComputeShader,
PassParameters,
FComputeShaderUtils::GetGroupCount(HistorySize * kHistoryUpscalingFactor, 8));
}
#endif
// If we upscaled the history buffer, downsize back to the secondary screen percentage size.
if (HistorySize != OutputRect.Size())
{
SceneColorOutputTexture = ComputeMitchellNetravaliDownsample(
GraphBuilder, View,
/* InputViewport = */ FScreenPassTexture(SceneColorOutputTexture, FIntRect(FIntPoint(0, 0), HistorySize)),
/* OutputViewport = */ FScreenPassTextureViewport(OutputExtent, OutputRect));
}
// Extract all resources for next frame.
if (!View.bStatePrevViewInfoIsReadOnly)
{
FTSRHistory& OutputHistory = View.ViewState->PrevFrameViewInfo.TSRHistory;
OutputHistory.OutputViewportRect = FIntRect(FIntPoint(0, 0), HistorySize);
// Extract filterable history
GraphBuilder.QueueTextureExtraction(History.LowFrequency, &OutputHistory.LowFrequency);
GraphBuilder.QueueTextureExtraction(History.HighFrequency, &OutputHistory.HighFrequency);
GraphBuilder.QueueTextureExtraction(History.Metadata, &OutputHistory.Metadata);
if (bAccumulateSeparateTranslucency)
{
GraphBuilder.QueueTextureExtraction(History.Translucency, &OutputHistory.Translucency);
GraphBuilder.QueueTextureExtraction(History.TranslucencyAlpha, &OutputHistory.TranslucencyAlpha);
}
// Extract non-filterable history
GraphBuilder.QueueTextureExtraction(History.SubpixelDetails, &OutputHistory.SubpixelDetails);
// Extract the translucency buffer to compare it with next frame
if (bRejectSeparateTranslucency)
{
GraphBuilder.QueueTextureExtraction(
SeparateTranslucencyTexture, &View.ViewState->PrevFrameViewInfo.SeparateTranslucency);
}
if (bEnableMoireHeuristic)
{
GraphBuilder.QueueTextureExtraction(History.LowResTextures[0], &OutputHistory.LowResTextures[0]);
GraphBuilder.QueueTextureExtraction(History.SuperResTextures[0], &OutputHistory.SuperResTextures[0]);
GraphBuilder.QueueTextureExtraction(History.SuperResTextures[1], &OutputHistory.SuperResTextures[1]);
}
// Extract the output for next frame SSR so that separate translucency shows up in SSR.
if (bAccumulateSeparateTranslucency || HistorySize != OutputRect.Size())
{
GraphBuilder.QueueTextureExtraction(
SceneColorOutputTexture, &View.ViewState->PrevFrameViewInfo.CustomSSRInput.RT[0]);
View.ViewState->PrevFrameViewInfo.CustomSSRInput.ViewportRect = OutputRect;
View.ViewState->PrevFrameViewInfo.CustomSSRInput.ReferenceBufferSize = OutputExtent;
}
}
ITemporalUpscaler::FOutputs Outputs;
Outputs.FullRes.Texture = SceneColorOutputTexture;
Outputs.FullRes.ViewRect = OutputRect;
Outputs.VelocityFlattenTextures = VelocityFlattenTextures;
return Outputs;
} // AddTemporalSuperResolutionPasses()