2020-07-06 18:58:26 -04:00
// 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"
2020-10-20 11:55:33 -04:00
# include "ScenePrivate.h"
2020-10-29 13:38:15 -04:00
# include "RendererModule.h"
2020-07-06 18:58:26 -04:00
namespace
{
const int32 GTemporalAATileSizeX = 8 ;
const int32 GTemporalAATileSizeY = 8 ;
TAutoConsoleVariable < float > CVarTemporalAAFilterSize (
TEXT ( " r.TemporalAAFilterSize " ) ,
1.0f ,
TEXT ( " Size of the filter kernel. (1.0 = smoother, 0.0 = sharper but aliased). " ) ,
ECVF_Scalability | ECVF_RenderThreadSafe ) ;
TAutoConsoleVariable < int32 > CVarTemporalAACatmullRom (
TEXT ( " r.TemporalAACatmullRom " ) ,
0 ,
TEXT ( " Whether to use a Catmull-Rom filter kernel. Should be a bit sharper than Gaussian. " ) ,
ECVF_Scalability | ECVF_RenderThreadSafe ) ;
TAutoConsoleVariable < int32 > CVarTemporalAAPauseCorrect (
TEXT ( " r.TemporalAAPauseCorrect " ) ,
1 ,
TEXT ( " Correct temporal AA in pause. This holds onto render targets longer preventing reuse and consumes more memory. " ) ,
ECVF_RenderThreadSafe ) ;
TAutoConsoleVariable < float > CVarTemporalAACurrentFrameWeight (
TEXT ( " r.TemporalAACurrentFrameWeight " ) ,
.04f ,
TEXT ( " Weight of current frame's contribution to the history. Low values cause blurriness and ghosting, high values fail to hide jittering. " ) ,
ECVF_Scalability | ECVF_RenderThreadSafe ) ;
2021-07-12 07:13:12 -04:00
TAutoConsoleVariable < int32 > CVarTemporalAAQuality (
TEXT ( " r.TemporalAA.Quality " ) , 2 ,
TEXT ( " Quality of the main Temporal AA pass. \n " )
TEXT ( " 0: Disable input filtering; \n " )
TEXT ( " 1: Enable input filtering; \n " )
TEXT ( " 2: Enable input filtering, enable mobility based anti-ghosting (Default) " ) ,
2020-07-06 18:58:26 -04:00
ECVF_Scalability | ECVF_RenderThreadSafe ) ;
TAutoConsoleVariable < float > CVarTemporalAAHistorySP (
TEXT ( " r.TemporalAA.HistoryScreenPercentage " ) ,
100.0f ,
TEXT ( " Size of temporal AA's history. " ) ,
ECVF_RenderThreadSafe ) ;
TAutoConsoleVariable < int32 > CVarTemporalAAAllowDownsampling (
TEXT ( " r.TemporalAA.AllowDownsampling " ) ,
1 ,
TEXT ( " Allows half-resolution color buffer to be produced during TAA. Only possible when motion blur is off and when using compute shaders for post processing. " ) ,
ECVF_RenderThreadSafe ) ;
2020-08-23 00:00:09 -04:00
static TAutoConsoleVariable < int32 > CVarUseTemporalAAUpscaler (
TEXT ( " r.TemporalAA.Upscaler " ) ,
1 ,
TEXT ( " Choose the upscaling algorithm. \n " )
TEXT ( " 0: Forces the default temporal upscaler of the renderer; \n " )
TEXT ( " 1: GTemporalUpscaler which may be overridden by a third party plugin (default). " ) ,
ECVF_RenderThreadSafe ) ;
2020-08-23 00:10:07 -04:00
TAutoConsoleVariable < int32 > CVarTAAR11G11B10History (
2021-03-24 15:14:14 -04:00
TEXT ( " r.TemporalAA.R11G11B10History " ) , 1 ,
2020-08-23 00:10:07 -04:00
TEXT ( " Select the bitdepth of the history. " ) ,
ECVF_RenderThreadSafe ) ;
2021-11-07 23:43:01 -05:00
TAutoConsoleVariable < int32 > CVarTAAUseMobileConfig (
TEXT ( " r.TemporalAA.UseMobileConfig " ) ,
0 ,
TEXT ( " 1 to use mobile TAA config. This will disable groupshared caching of the color and depth buffers. \n " )
TEXT ( " 0: disabled (default); \n " )
TEXT ( " 1: enabled; \n " ) ,
ECVF_ReadOnly ) ;
2021-04-01 12:25:23 -04:00
2020-07-06 18:58:26 -04:00
inline bool DoesPlatformSupportTemporalHistoryUpscale ( EShaderPlatform Platform )
{
return ( IsPCPlatform ( Platform ) | | FDataDrivenShaderPlatformInfo : : GetSupportsTemporalHistoryUpscale ( Platform ) )
& & IsFeatureLevelSupported ( Platform , ERHIFeatureLevel : : SM5 ) ;
}
2021-06-10 08:42:48 -04:00
class FTemporalAACS : public FGlobalShader
2020-07-06 18:58:26 -04:00
{
2021-06-10 08:42:48 -04:00
DECLARE_GLOBAL_SHADER ( FTemporalAACS ) ;
SHADER_USE_PARAMETER_STRUCT ( FTemporalAACS , FGlobalShader ) ;
2020-07-06 18:58:26 -04:00
class FTAAPassConfigDim : SHADER_PERMUTATION_ENUM_CLASS ( " TAA_PASS_CONFIG " , ETAAPassConfig ) ;
2021-07-12 07:13:12 -04:00
class FTAAQualityDim : SHADER_PERMUTATION_ENUM_CLASS ( " TAA_QUALITY " , ETAAQuality ) ;
2020-07-06 18:58:26 -04:00
class FTAAResponsiveDim : SHADER_PERMUTATION_BOOL ( " TAA_RESPONSIVE " ) ;
class FTAAScreenPercentageDim : SHADER_PERMUTATION_INT ( " TAA_SCREEN_PERCENTAGE_RANGE " , 4 ) ;
class FTAADownsampleDim : SHADER_PERMUTATION_BOOL ( " TAA_DOWNSAMPLE " ) ;
using FPermutationDomain = TShaderPermutationDomain <
FTAAPassConfigDim ,
2021-07-12 07:13:12 -04:00
FTAAQualityDim ,
2020-07-06 18:58:26 -04:00
FTAAScreenPercentageDim ,
FTAADownsampleDim > ;
BEGIN_SHADER_PARAMETER_STRUCT ( FParameters , )
2021-09-22 10:01:48 -04:00
SHADER_PARAMETER ( FVector4f , ViewportUVToInputBufferUV )
SHADER_PARAMETER ( FVector4f , MaxViewportUVAndSvPositionToViewportUV )
2021-11-18 14:37:34 -05:00
SHADER_PARAMETER ( FVector2f , ScreenPosAbsMax )
2020-07-06 18:58:26 -04:00
SHADER_PARAMETER ( float , HistoryPreExposureCorrection )
SHADER_PARAMETER ( float , CurrentFrameWeight )
SHADER_PARAMETER ( int32 , bCameraCut )
2021-10-04 09:14:58 -04:00
SHADER_PARAMETER_SCALAR_ARRAY ( float , SampleWeights , [ 9 ] )
SHADER_PARAMETER_SCALAR_ARRAY ( float , PlusWeights , [ 5 ] )
2020-07-06 18:58:26 -04:00
2021-09-22 10:01:48 -04:00
SHADER_PARAMETER ( FVector4f , InputSceneColorSize )
2020-07-06 18:58:26 -04:00
SHADER_PARAMETER ( FIntPoint , InputMinPixelCoord )
SHADER_PARAMETER ( FIntPoint , InputMaxPixelCoord )
2021-09-22 10:01:48 -04:00
SHADER_PARAMETER ( FVector4f , OutputViewportSize )
SHADER_PARAMETER ( FVector4f , OutputViewportRect )
2021-05-05 15:07:25 -04:00
SHADER_PARAMETER ( FVector3f , OutputQuantizationError )
2020-07-06 18:58:26 -04:00
// History parameters
2021-09-22 10:01:48 -04:00
SHADER_PARAMETER ( FVector4f , HistoryBufferSize )
SHADER_PARAMETER ( FVector4f , HistoryBufferUVMinMax )
SHADER_PARAMETER ( FVector4f , ScreenPosToHistoryBufferUV )
2020-07-06 18:58:26 -04:00
2020-09-24 00:43:27 -04:00
SHADER_PARAMETER_RDG_TEXTURE ( Texture2D , EyeAdaptationTexture )
2021-02-18 21:11:17 -04:00
SHADER_PARAMETER_RDG_BUFFER_SRV ( Buffer < float4 > , EyeAdaptationBuffer )
2020-07-06 18:58:26 -04:00
// Inputs
SHADER_PARAMETER_RDG_TEXTURE ( Texture2D , InputSceneColor )
SHADER_PARAMETER_SAMPLER ( SamplerState , InputSceneColorSampler )
SHADER_PARAMETER_RDG_TEXTURE ( Texture2D , InputSceneMetadata )
SHADER_PARAMETER_SAMPLER ( SamplerState , InputSceneMetadataSampler )
// History resources
SHADER_PARAMETER_RDG_TEXTURE_ARRAY ( Texture2D , HistoryBuffer , [ FTemporalAAHistory : : kRenderTargetCount ] )
SHADER_PARAMETER_SAMPLER_ARRAY ( SamplerState , HistoryBufferSampler , [ FTemporalAAHistory : : kRenderTargetCount ] )
2020-09-24 00:43:27 -04:00
SHADER_PARAMETER_RDG_TEXTURE ( Texture2D , SceneDepthTexture )
SHADER_PARAMETER_SAMPLER ( SamplerState , SceneDepthTextureSampler )
SHADER_PARAMETER_RDG_TEXTURE ( Texture2D , GBufferVelocityTexture )
SHADER_PARAMETER_SAMPLER ( SamplerState , GBufferVelocityTextureSampler )
2020-07-06 18:58:26 -04:00
SHADER_PARAMETER_RDG_TEXTURE_SRV ( Texture2D , StencilTexture )
SHADER_PARAMETER_STRUCT_REF ( FViewUniformShaderParameters , ViewUniformBuffer )
2020-09-24 00:43:27 -04:00
2020-07-06 18:58:26 -04:00
// Temporal upsample specific parameters.
2021-09-22 10:01:48 -04:00
SHADER_PARAMETER ( FVector4f , InputViewSize )
2021-11-18 14:37:34 -05:00
SHADER_PARAMETER ( FVector2f , InputViewMin )
SHADER_PARAMETER ( FVector2f , TemporalJitterPixels )
2020-07-06 18:58:26 -04:00
SHADER_PARAMETER ( float , ScreenPercentage )
SHADER_PARAMETER ( float , UpscaleFactor )
2020-10-22 19:19:16 -04:00
SHADER_PARAMETER_RDG_TEXTURE_UAV_ARRAY ( RWTexture2D , OutComputeTex , [ FTemporalAAHistory : : kRenderTargetCount ] )
SHADER_PARAMETER_RDG_TEXTURE_UAV ( RWTexture2D , OutComputeTexDownsampled )
2020-07-06 18:58:26 -04:00
SHADER_PARAMETER_RDG_TEXTURE_UAV ( RWTexture2D , DebugOutput )
END_SHADER_PARAMETER_STRUCT ( )
2021-07-12 07:13:12 -04:00
static FPermutationDomain RemapPermutation ( FPermutationDomain PermutationVector )
{
if ( PermutationVector . Get < FTAAPassConfigDim > ( ) = = ETAAPassConfig : : Main | |
PermutationVector . Get < FTAAPassConfigDim > ( ) = = ETAAPassConfig : : MainUpsampling )
{
// No point downsampling if not using the faster quality permutation already.
if ( PermutationVector . Get < FTAAQualityDim > ( ) = = ETAAQuality : : High )
{
PermutationVector . Set < FTAADownsampleDim > ( false ) ;
}
}
else if (
PermutationVector . Get < FTAAPassConfigDim > ( ) = = ETAAPassConfig : : DiaphragmDOF | |
PermutationVector . Get < FTAAPassConfigDim > ( ) = = ETAAPassConfig : : DiaphragmDOFUpsampling )
{
// DOF pass allow only quality 1 and 2
PermutationVector . Set < FTAAQualityDim > ( ETAAQuality ( FMath : : Max ( int ( PermutationVector . Get < FTAAQualityDim > ( ) ) , int ( ETAAQuality : : Medium ) ) ) ) ;
// Only the Main and Main Upsampling can downsample the output.
PermutationVector . Set < FTAADownsampleDim > ( false ) ;
}
else
{
// Only the Main and Main Upsampling have quality options 0, 1, 2.
PermutationVector . Set < FTAAQualityDim > ( ETAAQuality : : High ) ;
// Only the Main and Main Upsampling can downsample the output.
PermutationVector . Set < FTAADownsampleDim > ( false ) ;
}
return PermutationVector ;
}
2020-07-06 18:58:26 -04:00
static bool ShouldCompilePermutation ( const FGlobalShaderPermutationParameters & Parameters )
{
FPermutationDomain PermutationVector ( Parameters . PermutationId ) ;
2021-07-12 07:13:12 -04:00
// Don't compile the shader permutation if gets remaped at runtime.
if ( PermutationVector ! = RemapPermutation ( PermutationVector ) )
{
return false ;
}
2020-07-06 18:58:26 -04:00
// Screen percentage dimension is only for upsampling permutation.
if ( ! IsTAAUpsamplingConfig ( PermutationVector . Get < FTAAPassConfigDim > ( ) ) & &
PermutationVector . Get < FTAAScreenPercentageDim > ( ) ! = 0 )
{
return false ;
}
if ( PermutationVector . Get < FTAAPassConfigDim > ( ) = = ETAAPassConfig : : MainSuperSampling )
{
// Super sampling is only available in certain configurations.
if ( ! DoesPlatformSupportTemporalHistoryUpscale ( Parameters . Platform ) )
{
return false ;
}
}
// Screen percentage range 3 is only for super sampling.
if ( PermutationVector . Get < FTAAPassConfigDim > ( ) ! = ETAAPassConfig : : MainSuperSampling & &
PermutationVector . Get < FTAAScreenPercentageDim > ( ) = = 3 )
{
return false ;
}
2021-02-18 21:11:17 -04:00
2021-03-05 19:27:14 -04:00
//Only Main and MainUpsampling config without DownSample permutations are supported on mobile platform.
2021-06-08 06:01:07 -04:00
return SupportsGen4TAA ( Parameters . Platform ) & & ( ! IsMobilePlatform ( Parameters . Platform ) | | ( ( PermutationVector . Get < FTAAPassConfigDim > ( ) = = ETAAPassConfig : : Main | | PermutationVector . Get < FTAAPassConfigDim > ( ) = = ETAAPassConfig : : MainUpsampling ) & & ! PermutationVector . Get < FTAADownsampleDim > ( ) ) ) ;
2020-07-06 18:58:26 -04:00
}
static void ModifyCompilationEnvironment ( const FGlobalShaderPermutationParameters & Parameters , FShaderCompilerEnvironment & OutEnvironment )
{
OutEnvironment . SetDefine ( TEXT ( " THREADGROUP_SIZEX " ) , GTemporalAATileSizeX ) ;
OutEnvironment . SetDefine ( TEXT ( " THREADGROUP_SIZEY " ) , GTemporalAATileSizeY ) ;
2021-02-18 21:11:17 -04:00
2021-11-23 10:17:56 -05:00
static FShaderPlatformCachedIniValue < bool > UseMobileConfig ( TEXT ( " r.TemporalAA.UseMobileConfig " ) ) ;
2021-11-07 23:43:01 -05:00
bool bUseMobileConfig = ( UseMobileConfig . Get ( ( EShaderPlatform ) Parameters . Platform ) ! = 0 ) ;
2021-02-18 21:11:17 -04:00
bool bIsMobileTiledGPU = RHIHasTiledGPU ( Parameters . Platform ) | | IsSimulatedPlatform ( Parameters . Platform ) ;
// There are some mobile specific shader optimizations need to be set in the shader, such as disable shared memory usage, disable stencil texture sampling.
2021-11-07 23:43:01 -05:00
OutEnvironment . SetDefine ( TEXT ( " AA_MOBILE_CONFIG " ) , ( bIsMobileTiledGPU | | bUseMobileConfig ) ? 1 : 0 ) ;
2020-07-06 18:58:26 -04:00
}
2021-06-10 08:42:48 -04:00
} ; // class FTemporalAACS
2020-07-06 18:58:26 -04:00
2021-06-10 08:42:48 -04:00
IMPLEMENT_GLOBAL_SHADER ( FTemporalAACS , " /Engine/Private/TemporalAA.usf " , " MainCS " , SF_Compute ) ;
2021-02-19 12:59:59 -04:00
2020-07-06 18:58:26 -04:00
float CatmullRom ( float x )
{
float ax = FMath : : Abs ( x ) ;
if ( ax > 1.0f )
return ( ( - 0.5f * ax + 2.5f ) * ax - 4.0f ) * ax + 2.0f ;
else
return ( 1.5f * ax - 2.5f ) * ax * ax + 1.0f ;
}
2021-12-07 09:55:09 -05:00
void SetupSampleWeightParameters ( FTemporalAACS : : FParameters * OutTAAParameters , const FTAAPassParameters & PassParameters , FVector2f TemporalJitterPixels )
2020-07-06 18:58:26 -04:00
{
float JitterX = TemporalJitterPixels . X ;
float JitterY = TemporalJitterPixels . Y ;
float ResDivisorInv = 1.0f / float ( PassParameters . ResolutionDivisor ) ;
static const float SampleOffsets [ 9 ] [ 2 ] =
{
{ - 1.0f , - 1.0f } ,
{ 0.0f , - 1.0f } ,
{ 1.0f , - 1.0f } ,
{ - 1.0f , 0.0f } ,
2020-08-23 00:10:07 -04:00
{ 0.0f , 0.0f } ,
2020-07-06 18:58:26 -04:00
{ 1.0f , 0.0f } ,
{ - 1.0f , 1.0f } ,
{ 0.0f , 1.0f } ,
{ 1.0f , 1.0f } ,
} ;
float FilterSize = CVarTemporalAAFilterSize . GetValueOnRenderThread ( ) ;
int32 bCatmullRom = CVarTemporalAACatmullRom . GetValueOnRenderThread ( ) ;
// Compute 3x3 weights
{
float TotalWeight = 0.0f ;
for ( int32 i = 0 ; i < 9 ; i + + )
{
float PixelOffsetX = SampleOffsets [ i ] [ 0 ] - JitterX * ResDivisorInv ;
float PixelOffsetY = SampleOffsets [ i ] [ 1 ] - JitterY * ResDivisorInv ;
PixelOffsetX / = FilterSize ;
PixelOffsetY / = FilterSize ;
if ( bCatmullRom )
{
2021-10-04 09:14:58 -04:00
const float CurrWeight = CatmullRom ( PixelOffsetX ) * CatmullRom ( PixelOffsetY ) ;
GET_SCALAR_ARRAY_ELEMENT ( OutTAAParameters - > SampleWeights , i ) = CurrWeight ;
TotalWeight + = CurrWeight ;
2020-07-06 18:58:26 -04:00
}
else
{
// Normal distribution, Sigma = 0.47
2021-10-04 09:14:58 -04:00
const float CurrWeight = FMath : : Exp ( - 2.29f * ( PixelOffsetX * PixelOffsetX + PixelOffsetY * PixelOffsetY ) ) ;
GET_SCALAR_ARRAY_ELEMENT ( OutTAAParameters - > SampleWeights , i ) = CurrWeight ;
TotalWeight + = CurrWeight ;
2020-07-06 18:58:26 -04:00
}
}
for ( int32 i = 0 ; i < 9 ; i + + )
2021-10-04 09:14:58 -04:00
{
GET_SCALAR_ARRAY_ELEMENT ( OutTAAParameters - > SampleWeights , i ) / = TotalWeight ;
}
2020-07-06 18:58:26 -04:00
}
// Compute 3x3 + weights.
{
2021-10-04 09:14:58 -04:00
GET_SCALAR_ARRAY_ELEMENT ( OutTAAParameters - > PlusWeights , 0 ) = GET_SCALAR_ARRAY_ELEMENT ( OutTAAParameters - > SampleWeights , 1 ) ;
GET_SCALAR_ARRAY_ELEMENT ( OutTAAParameters - > PlusWeights , 1 ) = GET_SCALAR_ARRAY_ELEMENT ( OutTAAParameters - > SampleWeights , 3 ) ;
GET_SCALAR_ARRAY_ELEMENT ( OutTAAParameters - > PlusWeights , 2 ) = GET_SCALAR_ARRAY_ELEMENT ( OutTAAParameters - > SampleWeights , 4 ) ;
GET_SCALAR_ARRAY_ELEMENT ( OutTAAParameters - > PlusWeights , 3 ) = GET_SCALAR_ARRAY_ELEMENT ( OutTAAParameters - > SampleWeights , 5 ) ;
GET_SCALAR_ARRAY_ELEMENT ( OutTAAParameters - > PlusWeights , 4 ) = GET_SCALAR_ARRAY_ELEMENT ( OutTAAParameters - > SampleWeights , 7 ) ;
2020-07-06 18:58:26 -04:00
float TotalWeightPlus = (
2021-10-04 09:14:58 -04:00
GET_SCALAR_ARRAY_ELEMENT ( OutTAAParameters - > SampleWeights , 1 ) +
GET_SCALAR_ARRAY_ELEMENT ( OutTAAParameters - > SampleWeights , 3 ) +
GET_SCALAR_ARRAY_ELEMENT ( OutTAAParameters - > SampleWeights , 4 ) +
GET_SCALAR_ARRAY_ELEMENT ( OutTAAParameters - > SampleWeights , 5 ) +
GET_SCALAR_ARRAY_ELEMENT ( OutTAAParameters - > SampleWeights , 7 ) ) ;
2020-07-06 18:58:26 -04:00
for ( int32 i = 0 ; i < 5 ; i + + )
2021-10-04 09:14:58 -04:00
{
GET_SCALAR_ARRAY_ELEMENT ( OutTAAParameters - > PlusWeights , i ) / = TotalWeightPlus ;
}
2020-07-06 18:58:26 -04:00
}
}
DECLARE_GPU_STAT ( TAA )
const TCHAR * const kTAAOutputNames [ ] = {
2021-01-29 06:49:13 -04:00
TEXT ( " TAA.History " ) ,
TEXT ( " TAA.History " ) ,
TEXT ( " TAA.History " ) ,
TEXT ( " SSR.TemporalAA " ) ,
TEXT ( " LightShaft.TemporalAA " ) ,
TEXT ( " DOF.TemporalAA " ) ,
TEXT ( " DOF.TemporalAA " ) ,
2020-07-06 18:58:26 -04:00
} ;
const TCHAR * const kTAAPassNames [ ] = {
2021-07-12 07:13:12 -04:00
TEXT ( " Main " ) ,
TEXT ( " MainUpsampling " ) ,
TEXT ( " MainSuperSampling " ) ,
2020-07-06 18:58:26 -04:00
TEXT ( " ScreenSpaceReflections " ) ,
TEXT ( " LightShaft " ) ,
TEXT ( " DOF " ) ,
TEXT ( " DOFUpsampling " ) ,
} ;
2021-07-12 07:13:12 -04:00
const TCHAR * const kTAAQualityNames [ ] = {
TEXT ( " Low " ) ,
TEXT ( " Medium " ) ,
TEXT ( " High " ) ,
} ;
2020-07-06 18:58:26 -04:00
static_assert ( UE_ARRAY_COUNT ( kTAAOutputNames ) = = int32 ( ETAAPassConfig : : MAX ) , " Missing TAA output name. " ) ;
static_assert ( UE_ARRAY_COUNT ( kTAAPassNames ) = = int32 ( ETAAPassConfig : : MAX ) , " Missing TAA pass name. " ) ;
2021-07-12 07:13:12 -04:00
static_assert ( UE_ARRAY_COUNT ( kTAAQualityNames ) = = int32 ( ETAAQuality : : MAX ) , " Missing TAA quality name. " ) ;
2020-07-06 18:58:26 -04:00
} //! namespace
bool IsTemporalAASceneDownsampleAllowed ( const FViewInfo & View )
{
return CVarTemporalAAAllowDownsampling . GetValueOnRenderThread ( ) ! = 0 ;
}
2021-06-10 08:42:48 -04:00
FVector ComputePixelFormatQuantizationError ( EPixelFormat PixelFormat )
{
FVector Error ;
if ( PixelFormat = = PF_FloatRGBA | | PixelFormat = = PF_FloatR11G11B10 )
{
FIntVector HistoryColorMantissaBits = PixelFormat = = PF_FloatR11G11B10 ? FIntVector ( 6 , 6 , 5 ) : FIntVector ( 10 , 10 , 10 ) ;
Error . X = FMath : : Pow ( 0.5f , HistoryColorMantissaBits . X ) ;
Error . Y = FMath : : Pow ( 0.5f , HistoryColorMantissaBits . Y ) ;
Error . Z = FMath : : Pow ( 0.5f , HistoryColorMantissaBits . Z ) ;
}
else
{
check ( 0 ) ;
}
return Error ;
}
2020-07-06 18:58:26 -04:00
float GetTemporalAAHistoryUpscaleFactor ( const FViewInfo & View )
{
float UpscaleFactor = 1.0f ;
// We only support history upscale in certain configurations.
if ( DoesPlatformSupportTemporalHistoryUpscale ( View . GetShaderPlatform ( ) ) )
{
UpscaleFactor = FMath : : Clamp ( CVarTemporalAAHistorySP . GetValueOnRenderThread ( ) / 100.0f , 1.0f , 2.0f ) ;
}
return UpscaleFactor ;
}
FIntPoint FTAAPassParameters : : GetOutputExtent ( ) const
{
check ( Validate ( ) ) ;
check ( SceneColorInput ) ;
FIntPoint InputExtent = SceneColorInput - > Desc . Extent ;
if ( ! IsTAAUpsamplingConfig ( Pass ) )
return InputExtent ;
check ( OutputViewRect . Min = = FIntPoint : : ZeroValue ) ;
FIntPoint PrimaryUpscaleViewSize = FIntPoint : : DivideAndRoundUp ( OutputViewRect . Size ( ) , ResolutionDivisor ) ;
FIntPoint QuantizedPrimaryUpscaleViewSize ;
QuantizeSceneBufferSize ( PrimaryUpscaleViewSize , QuantizedPrimaryUpscaleViewSize ) ;
return FIntPoint (
FMath : : Max ( InputExtent . X , QuantizedPrimaryUpscaleViewSize . X ) ,
FMath : : Max ( InputExtent . Y , QuantizedPrimaryUpscaleViewSize . Y ) ) ;
}
bool FTAAPassParameters : : Validate ( ) const
{
if ( IsTAAUpsamplingConfig ( Pass ) )
{
check ( OutputViewRect . Min = = FIntPoint : : ZeroValue ) ;
}
else
{
check ( InputViewRect = = OutputViewRect ) ;
}
return true ;
}
FTAAOutputs AddTemporalAAPass (
FRDGBuilder & GraphBuilder ,
const FViewInfo & View ,
const FTAAPassParameters & Inputs ,
const FTemporalAAHistory & InputHistory ,
FTemporalAAHistory * OutputHistory )
{
check ( Inputs . Validate ( ) ) ;
2020-09-24 00:43:27 -04:00
// Whether alpha channel is supported.
const bool bSupportsAlpha = IsPostProcessingWithAlphaChannelSupported ( ) ;
2020-07-06 18:58:26 -04:00
// Number of render target in TAA history.
2020-09-24 00:43:27 -04:00
const int32 IntputTextureCount = ( IsDOFTAAConfig ( Inputs . Pass ) & & bSupportsAlpha ) ? 2 : 1 ;
2020-07-06 18:58:26 -04:00
// Whether this is main TAA pass;
const bool bIsMainPass = IsMainTAAConfig ( Inputs . Pass ) ;
2020-09-24 00:43:27 -04:00
2020-07-06 18:58:26 -04:00
// Whether to use camera cut shader permutation or not.
const bool bCameraCut = ! InputHistory . IsValid ( ) | | View . bCameraCut ;
const FIntPoint OutputExtent = Inputs . GetOutputExtent ( ) ;
// Src rectangle.
const FIntRect SrcRect = Inputs . InputViewRect ;
const FIntRect DestRect = Inputs . OutputViewRect ;
const FIntRect PracticableSrcRect = FIntRect : : DivideAndRoundUp ( SrcRect , Inputs . ResolutionDivisor ) ;
const FIntRect PracticableDestRect = FIntRect : : DivideAndRoundUp ( DestRect , Inputs . ResolutionDivisor ) ;
const uint32 PassIndex = static_cast < uint32 > ( Inputs . Pass ) ;
// Name of the pass.
const TCHAR * PassName = kTAAPassNames [ PassIndex ] ;
// Create outputs
FTAAOutputs Outputs ;
TStaticArray < FRDGTextureRef , FTemporalAAHistory : : kRenderTargetCount > NewHistoryTexture ;
{
2020-09-24 00:43:27 -04:00
EPixelFormat HistoryPixelFormat = PF_FloatRGBA ;
2021-07-12 07:13:12 -04:00
if ( bIsMainPass & & Inputs . Quality ! = ETAAQuality : : High & & ! bSupportsAlpha & & CVarTAAR11G11B10History . GetValueOnRenderThread ( ) )
2020-09-24 00:43:27 -04:00
{
HistoryPixelFormat = PF_FloatR11G11B10 ;
}
FRDGTextureDesc SceneColorDesc = FRDGTextureDesc : : Create2D (
2020-07-06 18:58:26 -04:00
OutputExtent ,
2020-09-24 00:43:27 -04:00
HistoryPixelFormat ,
2020-07-06 18:58:26 -04:00
FClearValueBinding : : Black ,
2020-09-24 00:43:27 -04:00
TexCreate_ShaderResource | TexCreate_UAV ) ;
2020-07-06 18:58:26 -04:00
if ( Inputs . bOutputRenderTargetable )
{
2020-09-24 00:43:27 -04:00
SceneColorDesc . Flags | = TexCreate_RenderTargetable ;
2020-07-06 18:58:26 -04:00
}
const TCHAR * OutputName = kTAAOutputNames [ PassIndex ] ;
for ( int32 i = 0 ; i < FTemporalAAHistory : : kRenderTargetCount ; i + + )
{
NewHistoryTexture [ i ] = GraphBuilder . CreateTexture (
SceneColorDesc ,
OutputName ,
2020-09-24 00:43:27 -04:00
ERDGTextureFlags : : MultiFrame ) ;
2020-07-06 18:58:26 -04:00
}
NewHistoryTexture [ 0 ] = Outputs . SceneColor = NewHistoryTexture [ 0 ] ;
if ( IntputTextureCount = = 2 )
{
Outputs . SceneMetadata = NewHistoryTexture [ 1 ] ;
}
if ( Inputs . bDownsample )
{
2020-09-24 00:43:27 -04:00
const FRDGTextureDesc HalfResSceneColorDesc = FRDGTextureDesc : : Create2D (
2020-07-06 18:58:26 -04:00
SceneColorDesc . Extent / 2 ,
Inputs . DownsampleOverrideFormat ! = PF_Unknown ? Inputs . DownsampleOverrideFormat : Inputs . SceneColorInput - > Desc . Format ,
FClearValueBinding : : Black ,
2020-09-24 00:43:27 -04:00
TexCreate_ShaderResource | TexCreate_UAV | GFastVRamConfig . Downsample ) ;
2021-06-18 01:39:21 -04:00
const TRefCountPtr < IPooledRenderTarget > & PrevFrameHalfResTAAHistory = View . PrevViewInfo . HalfResTemporalAAHistory ;
2020-07-06 18:58:26 -04:00
2021-06-18 01:39:21 -04:00
if ( PrevFrameHalfResTAAHistory & & Translate ( PrevFrameHalfResTAAHistory - > GetDesc ( ) , ERenderTargetTexture : : ShaderResource ) = = HalfResSceneColorDesc )
{
Outputs . DownsampledSceneColor = GraphBuilder . RegisterExternalTexture ( PrevFrameHalfResTAAHistory ) ;
}
else
{
Outputs . DownsampledSceneColor = GraphBuilder . CreateTexture ( HalfResSceneColorDesc , TEXT ( " SceneColorHalfRes " ) ) ;
}
2020-07-06 18:58:26 -04:00
}
}
RDG_GPU_STAT_SCOPE ( GraphBuilder , TAA ) ;
TStaticArray < bool , FTemporalAAHistory : : kRenderTargetCount > bUseHistoryTexture ;
{
2021-06-10 08:42:48 -04:00
FTemporalAACS : : FPermutationDomain PermutationVector ;
PermutationVector . Set < FTemporalAACS : : FTAAPassConfigDim > ( Inputs . Pass ) ;
2021-07-12 07:13:12 -04:00
PermutationVector . Set < FTemporalAACS : : FTAAQualityDim > ( Inputs . Quality ) ;
2021-06-10 08:42:48 -04:00
PermutationVector . Set < FTemporalAACS : : FTAADownsampleDim > ( Inputs . bDownsample ) ;
2020-07-06 18:58:26 -04:00
if ( IsTAAUpsamplingConfig ( Inputs . Pass ) )
{
// If screen percentage > 100% on X or Y axes, then use screen percentage range = 2 shader permutation to disable LDS caching.
if ( SrcRect . Width ( ) > DestRect . Width ( ) | |
SrcRect . Height ( ) > DestRect . Height ( ) )
{
2021-06-10 08:42:48 -04:00
PermutationVector . Set < FTemporalAACS : : FTAAScreenPercentageDim > ( 2 ) ;
2020-07-06 18:58:26 -04:00
}
// If screen percentage < 50% on X and Y axes, then use screen percentage range = 3 shader permutation.
else if ( SrcRect . Width ( ) * 100 < 50 * DestRect . Width ( ) & &
SrcRect . Height ( ) * 100 < 50 * DestRect . Height ( ) & &
Inputs . Pass = = ETAAPassConfig : : MainSuperSampling )
{
2021-06-10 08:42:48 -04:00
PermutationVector . Set < FTemporalAACS : : FTAAScreenPercentageDim > ( 3 ) ;
2020-07-06 18:58:26 -04:00
}
// If screen percentage < 71% on X and Y axes, then use screen percentage range = 1 shader permutation to have smaller LDS caching.
else if ( SrcRect . Width ( ) * 100 < 71 * DestRect . Width ( ) & &
SrcRect . Height ( ) * 100 < 71 * DestRect . Height ( ) )
{
2021-06-10 08:42:48 -04:00
PermutationVector . Set < FTemporalAACS : : FTAAScreenPercentageDim > ( 1 ) ;
2020-07-06 18:58:26 -04:00
}
}
2021-07-12 07:13:12 -04:00
PermutationVector = FTemporalAACS : : RemapPermutation ( PermutationVector ) ;
2021-06-10 08:42:48 -04:00
FTemporalAACS : : FParameters * PassParameters = GraphBuilder . AllocParameters < FTemporalAACS : : FParameters > ( ) ;
2020-07-06 18:58:26 -04:00
// Setups common shader parameters
const FIntPoint InputExtent = Inputs . SceneColorInput - > Desc . Extent ;
const FIntRect InputViewRect = Inputs . InputViewRect ;
const FIntRect OutputViewRect = Inputs . OutputViewRect ;
if ( ! IsTAAUpsamplingConfig ( Inputs . Pass ) )
{
SetupSampleWeightParameters ( PassParameters , Inputs , View . TemporalJitterPixels ) ;
}
const float ResDivisor = Inputs . ResolutionDivisor ;
const float ResDivisorInv = 1.0f / ResDivisor ;
PassParameters - > ViewUniformBuffer = View . ViewUniformBuffer ;
PassParameters - > CurrentFrameWeight = CVarTemporalAACurrentFrameWeight . GetValueOnRenderThread ( ) ;
PassParameters - > bCameraCut = bCameraCut ;
2020-09-24 00:43:27 -04:00
PassParameters - > SceneDepthTexture = Inputs . SceneDepthTexture ;
PassParameters - > GBufferVelocityTexture = Inputs . SceneVelocityTexture ;
2020-08-23 00:00:09 -04:00
2020-09-24 00:43:27 -04:00
PassParameters - > SceneDepthTextureSampler = TStaticSamplerState < SF_Point > : : GetRHI ( ) ;
PassParameters - > GBufferVelocityTextureSampler = TStaticSamplerState < SF_Point > : : GetRHI ( ) ;
2020-07-06 18:58:26 -04:00
2020-08-23 00:00:09 -04:00
PassParameters - > StencilTexture = GraphBuilder . CreateSRV ( FRDGTextureSRVDesc : : CreateWithPixelFormat ( Inputs . SceneDepthTexture , PF_X24_G8 ) ) ;
2020-07-06 18:58:26 -04:00
// We need a valid velocity buffer texture. Use black (no velocity) if none exists.
2020-09-24 00:43:27 -04:00
if ( ! PassParameters - > GBufferVelocityTexture )
2020-07-06 18:58:26 -04:00
{
2020-09-24 00:43:27 -04:00
PassParameters - > GBufferVelocityTexture = GraphBuilder . RegisterExternalTexture ( GSystemTextures . BlackDummy ) ; ;
2020-07-06 18:58:26 -04:00
}
// Input buffer shader parameters
{
2021-09-22 10:01:48 -04:00
PassParameters - > InputSceneColorSize = FVector4f (
2020-07-06 18:58:26 -04:00
InputExtent . X ,
InputExtent . Y ,
1.0f / float ( InputExtent . X ) ,
1.0f / float ( InputExtent . Y ) ) ;
PassParameters - > InputMinPixelCoord = PracticableSrcRect . Min ;
PassParameters - > InputMaxPixelCoord = PracticableSrcRect . Max - FIntPoint ( 1 , 1 ) ;
PassParameters - > InputSceneColor = Inputs . SceneColorInput ;
PassParameters - > InputSceneColorSampler = TStaticSamplerState < SF_Point > : : GetRHI ( ) ;
PassParameters - > InputSceneMetadata = Inputs . SceneMetadataInput ;
PassParameters - > InputSceneMetadataSampler = TStaticSamplerState < SF_Point > : : GetRHI ( ) ;
}
2021-09-22 10:01:48 -04:00
PassParameters - > OutputViewportSize = FVector4f (
2020-07-06 18:58:26 -04:00
PracticableDestRect . Width ( ) , PracticableDestRect . Height ( ) , 1.0f / float ( PracticableDestRect . Width ( ) ) , 1.0f / float ( PracticableDestRect . Height ( ) ) ) ;
2021-09-22 10:01:48 -04:00
PassParameters - > OutputViewportRect = FVector4f ( PracticableDestRect . Min . X , PracticableDestRect . Min . Y , PracticableDestRect . Max . X , PracticableDestRect . Max . Y ) ;
2020-09-24 00:43:27 -04:00
PassParameters - > OutputQuantizationError = ComputePixelFormatQuantizationError ( NewHistoryTexture [ 0 ] - > Desc . Format ) ;
2020-07-06 18:58:26 -04:00
// Set history shader parameters.
{
FRDGTextureRef BlackDummy = GraphBuilder . RegisterExternalTexture ( GSystemTextures . BlackDummy ) ;
if ( bCameraCut )
{
2021-09-22 10:01:48 -04:00
PassParameters - > ScreenPosToHistoryBufferUV = FVector4f ( 1.0f , 1.0f , 1.0f , 1.0f ) ;
2021-12-07 09:55:09 -05:00
PassParameters - > ScreenPosAbsMax = FVector2f ( 0.0f , 0.0f ) ;
2021-09-22 10:01:48 -04:00
PassParameters - > HistoryBufferUVMinMax = FVector4f ( 0.0f , 0.0f , 0.0f , 0.0f ) ;
PassParameters - > HistoryBufferSize = FVector4f ( 1.0f , 1.0f , 1.0f , 1.0f ) ;
2020-07-06 18:58:26 -04:00
for ( int32 i = 0 ; i < FTemporalAAHistory : : kRenderTargetCount ; i + + )
{
PassParameters - > HistoryBuffer [ i ] = BlackDummy ;
}
// Remove dependency of the velocity buffer on camera cut, given it's going to be ignored by the shader.
2020-09-24 00:43:27 -04:00
PassParameters - > GBufferVelocityTexture = BlackDummy ;
2020-07-06 18:58:26 -04:00
}
else
{
FIntPoint ReferenceViewportOffset = InputHistory . ViewportRect . Min ;
FIntPoint ReferenceViewportExtent = InputHistory . ViewportRect . Size ( ) ;
FIntPoint ReferenceBufferSize = InputHistory . ReferenceBufferSize ;
float InvReferenceBufferSizeX = 1.f / float ( InputHistory . ReferenceBufferSize . X ) ;
float InvReferenceBufferSizeY = 1.f / float ( InputHistory . ReferenceBufferSize . Y ) ;
2021-09-22 10:01:48 -04:00
PassParameters - > ScreenPosToHistoryBufferUV = FVector4f (
2020-07-06 18:58:26 -04:00
ReferenceViewportExtent . X * 0.5f * InvReferenceBufferSizeX ,
- ReferenceViewportExtent . Y * 0.5f * InvReferenceBufferSizeY ,
( ReferenceViewportExtent . X * 0.5f + ReferenceViewportOffset . X ) * InvReferenceBufferSizeX ,
( ReferenceViewportExtent . Y * 0.5f + ReferenceViewportOffset . Y ) * InvReferenceBufferSizeY ) ;
FIntPoint ViewportOffset = ReferenceViewportOffset / Inputs . ResolutionDivisor ;
FIntPoint ViewportExtent = FIntPoint : : DivideAndRoundUp ( ReferenceViewportExtent , Inputs . ResolutionDivisor ) ;
FIntPoint BufferSize = ReferenceBufferSize / Inputs . ResolutionDivisor ;
2021-12-07 09:55:09 -05:00
PassParameters - > ScreenPosAbsMax = FVector2f ( 1.0f - 1.0f / float ( ViewportExtent . X ) , 1.0f - 1.0f / float ( ViewportExtent . Y ) ) ;
2020-07-06 18:58:26 -04:00
float InvBufferSizeX = 1.f / float ( BufferSize . X ) ;
float InvBufferSizeY = 1.f / float ( BufferSize . Y ) ;
2021-09-22 10:01:48 -04:00
PassParameters - > HistoryBufferUVMinMax = FVector4f (
2020-07-06 18:58:26 -04:00
( ViewportOffset . X + 0.5f ) * InvBufferSizeX ,
( ViewportOffset . Y + 0.5f ) * InvBufferSizeY ,
( ViewportOffset . X + ViewportExtent . X - 0.5f ) * InvBufferSizeX ,
( ViewportOffset . Y + ViewportExtent . Y - 0.5f ) * InvBufferSizeY ) ;
2021-09-22 10:01:48 -04:00
PassParameters - > HistoryBufferSize = FVector4f ( BufferSize . X , BufferSize . Y , InvBufferSizeX , InvBufferSizeY ) ;
2020-07-06 18:58:26 -04:00
for ( int32 i = 0 ; i < FTemporalAAHistory : : kRenderTargetCount ; i + + )
{
if ( InputHistory . RT [ i ] . IsValid ( ) )
{
PassParameters - > HistoryBuffer [ i ] = GraphBuilder . RegisterExternalTexture ( InputHistory . RT [ i ] ) ;
}
else
{
PassParameters - > HistoryBuffer [ i ] = BlackDummy ;
}
}
}
for ( int32 i = 0 ; i < FTemporalAAHistory : : kRenderTargetCount ; i + + )
{
PassParameters - > HistoryBufferSampler [ i ] = TStaticSamplerState < SF_Bilinear > : : GetRHI ( ) ;
}
}
2021-09-22 10:01:48 -04:00
PassParameters - > MaxViewportUVAndSvPositionToViewportUV = FVector4f (
2020-07-06 18:58:26 -04:00
( PracticableDestRect . Width ( ) - 0.5f * ResDivisor ) / float ( PracticableDestRect . Width ( ) ) ,
( PracticableDestRect . Height ( ) - 0.5f * ResDivisor ) / float ( PracticableDestRect . Height ( ) ) ,
ResDivisor / float ( DestRect . Width ( ) ) ,
ResDivisor / float ( DestRect . Height ( ) ) ) ;
PassParameters - > HistoryPreExposureCorrection = View . PreExposure / View . PrevViewInfo . SceneColorPreExposure ;
{
float InvSizeX = 1.0f / float ( InputExtent . X ) ;
float InvSizeY = 1.0f / float ( InputExtent . Y ) ;
2021-09-22 10:01:48 -04:00
PassParameters - > ViewportUVToInputBufferUV = FVector4f (
2020-07-06 18:58:26 -04:00
ResDivisorInv * InputViewRect . Width ( ) * InvSizeX ,
ResDivisorInv * InputViewRect . Height ( ) * InvSizeY ,
ResDivisorInv * InputViewRect . Min . X * InvSizeX ,
ResDivisorInv * InputViewRect . Min . Y * InvSizeY ) ;
}
2021-02-18 21:11:17 -04:00
if ( View . GetFeatureLevel ( ) < = ERHIFeatureLevel : : ES3_1 )
{
PassParameters - > EyeAdaptationBuffer = GraphBuilder . CreateSRV ( GetEyeAdaptationBuffer ( GraphBuilder , View ) , PF_A32B32G32R32F ) ;
}
else
{
PassParameters - > EyeAdaptationTexture = GetEyeAdaptationTexture ( GraphBuilder , View ) ;
}
2020-07-06 18:58:26 -04:00
// Temporal upsample specific shader parameters.
{
// Temporal AA upscale specific params.
float InputViewSizeInvScale = Inputs . ResolutionDivisor ;
float InputViewSizeScale = 1.0f / InputViewSizeInvScale ;
PassParameters - > TemporalJitterPixels = InputViewSizeScale * View . TemporalJitterPixels ;
PassParameters - > ScreenPercentage = float ( InputViewRect . Width ( ) ) / float ( OutputViewRect . Width ( ) ) ;
PassParameters - > UpscaleFactor = float ( OutputViewRect . Width ( ) ) / float ( InputViewRect . Width ( ) ) ;
2021-12-07 09:55:09 -05:00
PassParameters - > InputViewMin = InputViewSizeScale * FVector2f ( InputViewRect . Min . X , InputViewRect . Min . Y ) ;
2021-09-22 10:01:48 -04:00
PassParameters - > InputViewSize = FVector4f (
2020-07-06 18:58:26 -04:00
InputViewSizeScale * InputViewRect . Width ( ) , InputViewSizeScale * InputViewRect . Height ( ) ,
InputViewSizeInvScale / InputViewRect . Width ( ) , InputViewSizeInvScale / InputViewRect . Height ( ) ) ;
}
// UAVs
{
for ( int32 i = 0 ; i < FTemporalAAHistory : : kRenderTargetCount ; i + + )
{
PassParameters - > OutComputeTex [ i ] = GraphBuilder . CreateUAV ( NewHistoryTexture [ i ] ) ;
}
if ( Outputs . DownsampledSceneColor )
{
PassParameters - > OutComputeTexDownsampled = GraphBuilder . CreateUAV ( Outputs . DownsampledSceneColor ) ;
}
}
// Debug UAVs
{
2020-09-24 00:43:27 -04:00
FRDGTextureDesc DebugDesc = FRDGTextureDesc : : Create2D (
2020-07-06 18:58:26 -04:00
OutputExtent ,
PF_FloatRGBA ,
FClearValueBinding : : None ,
2020-09-24 00:43:27 -04:00
/* InFlags = */ TexCreate_ShaderResource | TexCreate_UAV ) ;
2020-07-06 18:58:26 -04:00
FRDGTextureRef DebugTexture = GraphBuilder . CreateTexture ( DebugDesc , TEXT ( " Debug.TAA " ) ) ;
PassParameters - > DebugOutput = GraphBuilder . CreateUAV ( DebugTexture ) ;
}
2021-06-10 08:42:48 -04:00
TShaderMapRef < FTemporalAACS > ComputeShader ( View . ShaderMap , PermutationVector ) ;
2020-07-06 18:58:26 -04:00
ClearUnusedGraphResources ( ComputeShader , PassParameters ) ;
for ( int32 i = 0 ; i < FTemporalAAHistory : : kRenderTargetCount ; i + + )
{
bUseHistoryTexture [ i ] = PassParameters - > HistoryBuffer [ i ] ! = nullptr ;
}
FComputeShaderUtils : : AddPass (
GraphBuilder ,
2021-07-12 07:13:12 -04:00
RDG_EVENT_NAME ( " TAA(%s Quality=%s) %dx%d -> %dx%d " ,
PassName ,
kTAAQualityNames [ int32 ( PermutationVector . Get < FTemporalAACS : : FTAAQualityDim > ( ) ) ] ,
2020-07-06 18:58:26 -04:00
PracticableSrcRect . Width ( ) , PracticableSrcRect . Height ( ) ,
PracticableDestRect . Width ( ) , PracticableDestRect . Height ( ) ) ,
ComputeShader ,
PassParameters ,
FComputeShaderUtils : : GetGroupCount ( PracticableDestRect . Size ( ) , GTemporalAATileSizeX ) ) ;
}
2020-09-24 00:43:27 -04:00
2020-07-06 18:58:26 -04:00
if ( ! View . bStatePrevViewInfoIsReadOnly )
{
OutputHistory - > SafeRelease ( ) ;
for ( int32 i = 0 ; i < FTemporalAAHistory : : kRenderTargetCount ; i + + )
{
if ( bUseHistoryTexture [ i ] )
{
GraphBuilder . QueueTextureExtraction ( NewHistoryTexture [ i ] , & OutputHistory - > RT [ i ] ) ;
}
}
OutputHistory - > ViewportRect = DestRect ;
OutputHistory - > ReferenceBufferSize = OutputExtent * Inputs . ResolutionDivisor ;
}
return Outputs ;
} // AddTemporalAAPass()
2020-08-23 00:10:07 -04:00
static void AddGen4MainTemporalAAPasses (
2020-07-06 18:58:26 -04:00
FRDGBuilder & GraphBuilder ,
const FViewInfo & View ,
2020-08-23 00:00:09 -04:00
const ITemporalUpscaler : : FPassInputs & PassInputs ,
2020-07-06 18:58:26 -04:00
FRDGTextureRef * OutSceneColorTexture ,
FIntRect * OutSceneColorViewRect ,
FRDGTextureRef * OutSceneColorHalfResTexture ,
FIntRect * OutSceneColorHalfResViewRect )
{
2021-06-23 11:54:40 -04:00
check ( View . ViewState ) ;
2020-07-06 18:58:26 -04:00
FTAAPassParameters TAAParameters ( View ) ;
TAAParameters . Pass = View . PrimaryScreenPercentageMethod = = EPrimaryScreenPercentageMethod : : TemporalUpscale
? ETAAPassConfig : : MainUpsampling
: ETAAPassConfig : : Main ;
TAAParameters . SetupViewRect ( View ) ;
2021-07-12 07:13:12 -04:00
TAAParameters . Quality = ETAAQuality ( FMath : : Clamp ( CVarTemporalAAQuality . GetValueOnRenderThread ( ) , 0 , 2 ) ) ;
2020-07-06 18:58:26 -04:00
const FIntRect SecondaryViewRect = TAAParameters . OutputViewRect ;
const float HistoryUpscaleFactor = GetTemporalAAHistoryUpscaleFactor ( View ) ;
// Configures TAA to upscale the history buffer; this is in addition to the secondary screen percentage upscale.
// We end up with a scene color that is larger than the secondary screen percentage. We immediately downscale
// afterwards using a Mitchel-Netravali filter.
if ( HistoryUpscaleFactor > 1.0f )
{
const FIntPoint HistoryViewSize (
TAAParameters . OutputViewRect . Width ( ) * HistoryUpscaleFactor ,
TAAParameters . OutputViewRect . Height ( ) * HistoryUpscaleFactor ) ;
TAAParameters . Pass = ETAAPassConfig : : MainSuperSampling ;
2021-07-12 07:13:12 -04:00
TAAParameters . Quality = ETAAQuality : : High ;
2020-07-06 18:58:26 -04:00
TAAParameters . OutputViewRect . Min . X = 0 ;
TAAParameters . OutputViewRect . Min . Y = 0 ;
TAAParameters . OutputViewRect . Max = HistoryViewSize ;
}
2020-08-23 00:00:09 -04:00
TAAParameters . DownsampleOverrideFormat = PassInputs . DownsampleOverrideFormat ;
2020-07-06 18:58:26 -04:00
2021-07-12 07:13:12 -04:00
TAAParameters . bDownsample = PassInputs . bAllowDownsampleSceneColor & & TAAParameters . Quality ! = ETAAQuality : : High ;
2020-07-06 18:58:26 -04:00
2020-08-23 00:00:09 -04:00
TAAParameters . SceneDepthTexture = PassInputs . SceneDepthTexture ;
TAAParameters . SceneVelocityTexture = PassInputs . SceneVelocityTexture ;
TAAParameters . SceneColorInput = PassInputs . SceneColorTexture ;
2020-07-06 18:58:26 -04:00
const FTemporalAAHistory & InputHistory = View . PrevViewInfo . TemporalAAHistory ;
FTemporalAAHistory & OutputHistory = View . ViewState - > PrevFrameViewInfo . TemporalAAHistory ;
2020-08-23 00:00:09 -04:00
const FTAAOutputs TAAOutputs = : : AddTemporalAAPass (
2020-07-06 18:58:26 -04:00
GraphBuilder ,
View ,
TAAParameters ,
InputHistory ,
& OutputHistory ) ;
FRDGTextureRef SceneColorTexture = TAAOutputs . SceneColor ;
// If we upscaled the history buffer, downsize back to the secondary screen percentage size.
if ( HistoryUpscaleFactor > 1.0f )
{
const FIntRect InputViewport = TAAParameters . OutputViewRect ;
FIntPoint QuantizedOutputSize ;
QuantizeSceneBufferSize ( SecondaryViewRect . Size ( ) , QuantizedOutputSize ) ;
FScreenPassTextureViewport OutputViewport ;
OutputViewport . Rect = SecondaryViewRect ;
2020-08-23 00:00:09 -04:00
OutputViewport . Extent . X = FMath : : Max ( PassInputs . SceneColorTexture - > Desc . Extent . X , QuantizedOutputSize . X ) ;
OutputViewport . Extent . Y = FMath : : Max ( PassInputs . SceneColorTexture - > Desc . Extent . Y , QuantizedOutputSize . Y ) ;
2020-07-06 18:58:26 -04:00
SceneColorTexture = ComputeMitchellNetravaliDownsample ( GraphBuilder , View , FScreenPassTexture ( SceneColorTexture , InputViewport ) , OutputViewport ) ;
}
* OutSceneColorTexture = SceneColorTexture ;
* OutSceneColorViewRect = SecondaryViewRect ;
* OutSceneColorHalfResTexture = TAAOutputs . DownsampledSceneColor ;
* OutSceneColorHalfResViewRect = FIntRect : : DivideAndRoundUp ( SecondaryViewRect , 2 ) ;
2020-08-23 00:10:07 -04:00
} // AddGen4MainTemporalAAPasses()
2020-07-06 18:58:26 -04:00
2021-06-10 08:42:48 -04:00
bool DoesPlatformSupportTSR ( EShaderPlatform Platform ) ;
2021-12-03 13:05:09 -05:00
ITemporalUpscaler : : FOutputs AddTemporalSuperResolutionPasses (
2021-06-10 08:42:48 -04:00
FRDGBuilder & GraphBuilder ,
const FViewInfo & View ,
2021-12-03 13:05:09 -05:00
const ITemporalUpscaler : : FPassInputs & PassInputs ) ;
2021-06-10 08:42:48 -04:00
2020-08-23 00:00:09 -04:00
class FDefaultTemporalUpscaler : public ITemporalUpscaler
2020-09-24 00:43:27 -04:00
{
2020-07-06 18:58:26 -04:00
public :
2020-08-23 00:00:09 -04:00
virtual const TCHAR * GetDebugName ( ) const
{
return TEXT ( " FDefaultTemporalUpscaler " ) ;
2020-07-06 18:58:26 -04:00
}
2021-12-03 13:05:09 -05:00
virtual FOutputs AddPasses (
2020-08-23 00:00:09 -04:00
FRDGBuilder & GraphBuilder ,
const FViewInfo & View ,
2021-12-03 13:05:09 -05:00
const FPassInputs & PassInputs ) const final
2020-07-06 18:58:26 -04:00
{
2021-06-23 11:54:40 -04:00
if ( ITemporalUpscaler : : GetMainTAAPassConfig ( View ) = = EMainTAAPassConfig : : TSR )
2020-08-23 00:10:07 -04:00
{
2021-04-26 14:05:52 -04:00
return AddTemporalSuperResolutionPasses (
2020-08-23 00:10:07 -04:00
GraphBuilder ,
View ,
2021-12-03 13:05:09 -05:00
PassInputs ) ;
2020-08-23 00:10:07 -04:00
}
else
{
2021-12-03 13:05:09 -05:00
FOutputs Outputs ;
AddGen4MainTemporalAAPasses (
2020-08-23 00:10:07 -04:00
GraphBuilder ,
View ,
PassInputs ,
2021-12-03 13:05:09 -05:00
& Outputs . FullRes . Texture ,
& Outputs . FullRes . ViewRect ,
& Outputs . HalfRes . Texture ,
& Outputs . HalfRes . ViewRect ) ;
return Outputs ;
2020-08-23 00:10:07 -04:00
}
2020-07-06 18:58:26 -04:00
}
2020-10-29 13:38:15 -04:00
virtual float GetMinUpsampleResolutionFraction ( ) const override
{
2021-07-14 08:25:29 -04:00
return ISceneViewFamilyScreenPercentage : : kMinTAAUpsampleResolutionFraction ;
2020-10-29 13:38:15 -04:00
}
virtual float GetMaxUpsampleResolutionFraction ( ) const override
{
2021-07-14 08:25:29 -04:00
return ISceneViewFamilyScreenPercentage : : kMaxTAAUpsampleResolutionFraction ;
2020-10-29 13:38:15 -04:00
}
2020-07-06 18:58:26 -04:00
} ;
2020-08-23 00:00:09 -04:00
// static
const ITemporalUpscaler * ITemporalUpscaler : : GetDefaultTemporalUpscaler ( )
2020-07-06 18:58:26 -04:00
{
2020-08-23 00:00:09 -04:00
static FDefaultTemporalUpscaler DefaultTemporalUpscaler ;
return & DefaultTemporalUpscaler ;
2020-07-06 18:58:26 -04:00
}
2021-02-09 06:30:16 -04:00
//static
EMainTAAPassConfig ITemporalUpscaler : : GetMainTAAPassConfig ( const FViewInfo & View )
2020-08-23 00:00:09 -04:00
{
2021-02-09 06:30:16 -04:00
if ( ! IsPostProcessingEnabled ( View ) )
{
return EMainTAAPassConfig : : Disabled ;
}
2021-06-23 11:54:40 -04:00
else if ( ! IsTemporalAccumulationBasedMethod ( View . AntiAliasingMethod ) )
2021-02-09 06:30:16 -04:00
{
return EMainTAAPassConfig : : Disabled ;
}
int32 CustomUpscalerMode = CVarUseTemporalAAUpscaler . GetValueOnRenderThread ( ) ;
if ( View . Family - > GetTemporalUpscalerInterface ( ) & & CustomUpscalerMode ! = 0 )
{
return EMainTAAPassConfig : : ThirdParty ;
}
2021-06-23 11:54:40 -04:00
else if ( View . AntiAliasingMethod = = AAM_TSR & & ! IsPostProcessingWithAlphaChannelSupported ( ) )
2021-02-09 06:30:16 -04:00
{
2021-06-23 11:54:40 -04:00
// TODO(TSR): alpha channel is not supported yet
check ( SupportsTSR ( View . GetShaderPlatform ( ) ) ) ;
2021-04-26 14:05:52 -04:00
return EMainTAAPassConfig : : TSR ;
2021-02-09 06:30:16 -04:00
}
else
{
2021-04-26 14:05:52 -04:00
return EMainTAAPassConfig : : TAA ;
2021-02-09 06:30:16 -04:00
}
2020-08-23 00:00:09 -04:00
}