1183 lines
43 KiB
HLSL
1183 lines
43 KiB
HLSL
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "SSDDefinitions.ush"
|
|
|
|
|
|
//------------------------------------------------------- ENUM VALUES
|
|
|
|
/** What signal should be outputed. */
|
|
#define REJECTION_INPUT_MODE_1UNNORMALIZED 0
|
|
#define REJECTION_INPUT_MODE_2PRETRANSFORMED_MOMMENTS 1
|
|
|
|
/** How to perform history rejection. */
|
|
#define HISTORY_REJECTION_DISABLED 0
|
|
#define HISTORY_REJECTION_MINMAX_BOUNDARIES 1
|
|
#define HISTORY_REJECTION_VAR_BOUNDARIES 2
|
|
|
|
|
|
//------------------------------------------------------- CONFIGS
|
|
|
|
#define TILE_PIXEL_SIZE 8
|
|
|
|
|
|
#define CONFIG_SIGNAL_PROCESSING DIM_SIGNAL_PROCESSING
|
|
#define CONFIG_SIGNAL_BATCH_SIZE DIM_SIGNAL_BATCH_SIZE
|
|
|
|
|
|
|
|
#if CONFIG_SIGNAL_PROCESSING == SIGNAL_PROCESSING_SHADOW_VISIBILITY_MASK
|
|
#define MAX_SIGNAL_BATCH_SIZE CONFIG_SIGNAL_BATCH_SIZE
|
|
#define SIGNAL_ARRAY_SIZE CONFIG_SIGNAL_BATCH_SIZE
|
|
|
|
#define CONFIG_BILATERAL_PRESET BILATERAL_PRESET_MONOCHROMATIC_PENUMBRA
|
|
#define CONFIG_HISTORY_BILATERAL_PRESET BILATERAL_PRESET_MONOCHROMATIC_PENUMBRA
|
|
#define CONFIG_MULTIPLEXED_SIGNALS_PER_SIGNAL_DOMAIN 1
|
|
|
|
#define CONFIG_SIGNAL_INPUT_TEXTURE_TYPE SIGNAL_TEXTURE_TYPE_FLOAT4
|
|
#define CONFIG_SIGNAL_OUTPUT_TEXTURE_TYPE SIGNAL_TEXTURE_TYPE_FLOAT4
|
|
|
|
#define CONFIG_INPUT_TEXTURE_COUNT CONFIG_SIGNAL_BATCH_SIZE
|
|
#define CONFIG_HISTORY_TEXTURE_COUNT CONFIG_SIGNAL_BATCH_SIZE
|
|
|
|
#define CONFIG_SIGNAL_INPUT_LAYOUT SIGNAL_BUFFER_LAYOUT_PENUMBRA_HISTORY
|
|
#define CONFIG_SIGNAL_HISTORY_LAYOUT SIGNAL_BUFFER_LAYOUT_PENUMBRA_HISTORY
|
|
|
|
#define CONFIG_HISTORY_REJECTION HISTORY_REJECTION_VAR_BOUNDARIES
|
|
|
|
#define CONFIG_NORMALIZED_INPUT 1
|
|
|
|
#define CONFIG_REJECTION_SAMPLE_SET SAMPLE_SET_3X3_PLUS
|
|
|
|
// Uses nearest to not leak informations on geometric edges by bilateral. This is OK because just blury greyscale details.
|
|
// TODO(Denoiser): a bit hacky, need find better solution.
|
|
// TODO(Denoiser): cause a regression on spot light for some reasons.
|
|
//#define CONFIG_USE_NEAREST_HISTORY 1
|
|
|
|
#if DIM_SIGNAL_BATCH_SIZE > 1
|
|
#define CONFIG_CLAMP_UV_PER_SIGNAL 1
|
|
#endif
|
|
|
|
#elif CONFIG_SIGNAL_PROCESSING == SIGNAL_PROCESSING_POLYCHROMATIC_PENUMBRA_HARMONIC
|
|
// Denoise diffuse and specular harmonics at the same time.
|
|
#define MAX_SIGNAL_BATCH_SIZE 2
|
|
#define SIGNAL_ARRAY_SIZE 2
|
|
#undef CONFIG_SIGNAL_BATCH_SIZE
|
|
#define CONFIG_SIGNAL_BATCH_SIZE 2
|
|
|
|
#define COMPILE_SIGNAL_COLOR 1
|
|
|
|
#define CONFIG_BILATERAL_PRESET BILATERAL_PRESET_POLYCHROMATIC_PENUMBRA
|
|
#define CONFIG_HISTORY_BILATERAL_PRESET BILATERAL_PRESET_POLYCHROMATIC_PENUMBRA
|
|
#define CONFIG_MULTIPLEXED_SIGNALS_PER_SIGNAL_DOMAIN 2
|
|
|
|
// Input and output layout.
|
|
#define CONFIG_SIGNAL_INPUT_LAYOUT SIGNAL_BUFFER_LAYOUT_POLYCHROMATIC_PENUMBRA_HISTORY
|
|
#define CONFIG_SIGNAL_HISTORY_LAYOUT SIGNAL_BUFFER_LAYOUT_POLYCHROMATIC_PENUMBRA_HISTORY
|
|
#define CONFIG_INPUT_TEXTURE_COUNT 2
|
|
#define CONFIG_HISTORY_TEXTURE_COUNT 2
|
|
|
|
#define CONFIG_HISTORY_REJECTION HISTORY_REJECTION_VAR_BOUNDARIES
|
|
|
|
#elif CONFIG_SIGNAL_PROCESSING == SIGNAL_PROCESSING_REFLECTIONS
|
|
#define COMPILE_SIGNAL_COLOR 1
|
|
|
|
#define MAX_SIGNAL_BATCH_SIZE 1
|
|
#define SIGNAL_ARRAY_SIZE 2 // First and Second moment in rejection pre convolution.
|
|
|
|
// Input and output layout.
|
|
#define CONFIG_SIGNAL_INPUT_LAYOUT SIGNAL_BUFFER_LAYOUT_REFLECTIONS_HISTORY
|
|
#define CONFIG_SIGNAL_HISTORY_LAYOUT SIGNAL_BUFFER_LAYOUT_REFLECTIONS_HISTORY
|
|
|
|
#define CONFIG_INPUT_TEXTURE_COUNT 2
|
|
#define CONFIG_HISTORY_TEXTURE_COUNT 2
|
|
|
|
#define CONFIG_BILATERAL_PRESET BILATERAL_PRESET_REFLECTIONS_TAA
|
|
#define CONFIG_HISTORY_BILATERAL_PRESET BILATERAL_PRESET_REFLECTIONS_TAA
|
|
|
|
#define CONFIG_REJECTION_SAMPLE_SET SAMPLE_SET_3X3_PLUS
|
|
|
|
// Use variance based rejection.
|
|
#define CONFIG_HISTORY_REJECTION HISTORY_REJECTION_VAR_BOUNDARIES
|
|
#define CONFIG_HISTORY_REJECTION_COLOR_SPACE REFLECTIONS_REJECTION_COLOR_SPACE
|
|
|
|
#elif CONFIG_SIGNAL_PROCESSING == SIGNAL_PROCESSING_AO
|
|
#define MAX_SIGNAL_BATCH_SIZE 1
|
|
#define SIGNAL_ARRAY_SIZE 2 // First and Second moment in rejection pre convolution.
|
|
|
|
// Input and output layout.
|
|
#define CONFIG_SIGNAL_INPUT_LAYOUT SIGNAL_BUFFER_LAYOUT_AO_HISTORY
|
|
#define CONFIG_SIGNAL_HISTORY_LAYOUT SIGNAL_BUFFER_LAYOUT_AO_HISTORY
|
|
|
|
#define CONFIG_INPUT_TEXTURE_COUNT 1
|
|
#define CONFIG_HISTORY_TEXTURE_COUNT 1
|
|
|
|
#define CONFIG_NORMALIZED_INPUT 1
|
|
|
|
#define CONFIG_HISTORY_REJECTION HISTORY_REJECTION_VAR_BOUNDARIES
|
|
|
|
#define CONFIG_BILATERAL_PRESET BILATERAL_PRESET_AO_HISTORY
|
|
#define CONFIG_HISTORY_BILATERAL_PRESET BILATERAL_PRESET_AO_HISTORY
|
|
#define CONFIG_PATCH_PREV_SCENE_DEPTH 1
|
|
#define CONFIG_USE_UNLIT_HISTORY_REJECTION 1
|
|
|
|
// Use pre transformed rejection buffer that contains pre transformed momment 1 & 2.
|
|
#if 1
|
|
#define CONFIG_USE_REJECTION_BUFFER 1
|
|
#define CONFIG_SIGNAL_HISTORY_REJECTION_LAYOUT SIGNAL_BUFFER_LAYOUT_AO_REJECTION
|
|
#define CONFIG_REJECTION_TEXTURE_COUNT 1
|
|
|
|
#define CONFIG_REJECTION_INPUT_MODE REJECTION_INPUT_MODE_2PRETRANSFORMED_MOMMENTS
|
|
#define CONFIG_REJECTION_SAMPLE_SET SAMPLE_SET_3X3_SOBEK2018
|
|
#else
|
|
#define CONFIG_REJECTION_SAMPLE_SET SAMPLE_SET_3X3
|
|
#endif
|
|
|
|
#elif CONFIG_SIGNAL_PROCESSING == SIGNAL_PROCESSING_DIFFUSE_INDIRECT_AND_AO
|
|
#define MAX_SIGNAL_BATCH_SIZE 1
|
|
#define SIGNAL_ARRAY_SIZE 1
|
|
|
|
#define COMPILE_SIGNAL_COLOR 1
|
|
|
|
// Input and output layout.
|
|
#define CONFIG_SIGNAL_INPUT_LAYOUT SIGNAL_BUFFER_LAYOUT_DIFFUSE_INDIRECT_AND_AO_RECONSTRUCTION
|
|
#define CONFIG_SIGNAL_HISTORY_LAYOUT SIGNAL_BUFFER_LAYOUT_DIFFUSE_INDIRECT_AND_AO_HISTORY
|
|
|
|
#define CONFIG_INPUT_TEXTURE_COUNT 2
|
|
#define CONFIG_HISTORY_TEXTURE_COUNT 2
|
|
|
|
#define CONFIG_HISTORY_REJECTION HISTORY_REJECTION_MINMAX_BOUNDARIES
|
|
#define CONFIG_MULTIPLEXED_SIGNALS_PER_SIGNAL_DOMAIN 3
|
|
|
|
#define CONFIG_BILATERAL_PRESET BILATERAL_PRESET_DIFFUSE
|
|
#define CONFIG_HISTORY_BILATERAL_PRESET BILATERAL_PRESET_DIFFUSE
|
|
|
|
#elif CONFIG_SIGNAL_PROCESSING == SIGNAL_PROCESSING_DIFFUSE_SPHERICAL_HARMONIC && 0
|
|
#define MAX_SIGNAL_BATCH_SIZE 1
|
|
#define SIGNAL_ARRAY_SIZE 1
|
|
|
|
#define COMPILE_SIGNAL_COLOR_SH 1
|
|
|
|
// Input and output layout.
|
|
#define CONFIG_SIGNAL_INPUT_LAYOUT SIGNAL_BUFFER_LAYOUT_DIFFUSE_INDIRECT_HARMONIC
|
|
#define CONFIG_SIGNAL_INPUT_TEXTURE_TYPE SIGNAL_TEXTURE_TYPE_UINT2
|
|
#define CONFIG_SIGNAL_HISTORY_LAYOUT SIGNAL_BUFFER_LAYOUT_DIFFUSE_INDIRECT_HARMONIC
|
|
#define CONFIG_SIGNAL_OUTPUT_TEXTURE_TYPE SIGNAL_TEXTURE_TYPE_UINT2
|
|
|
|
#define CONFIG_INPUT_TEXTURE_COUNT 4
|
|
#define CONFIG_HISTORY_TEXTURE_COUNT 4
|
|
|
|
#define CONFIG_HISTORY_REJECTION HISTORY_REJECTION_MINMAX_BOUNDARIES
|
|
#define CONFIG_MULTIPLEXED_SIGNALS_PER_SIGNAL_DOMAIN 4
|
|
|
|
// Given it's a spherical harmonic that store directionality, only need position based rejection.
|
|
#define CONFIG_BILATERAL_PRESET BILATERAL_PRESET_SPHERICAL_HARMONIC
|
|
#define CONFIG_HISTORY_BILATERAL_PRESET BILATERAL_PRESET_SPHERICAL_HARMONIC
|
|
|
|
#elif CONFIG_SIGNAL_PROCESSING == SIGNAL_PROCESSING_DIFFUSE_SPHERICAL_HARMONIC && 1
|
|
#define MAX_SIGNAL_BATCH_SIZE 1
|
|
#define SIGNAL_ARRAY_SIZE 1
|
|
|
|
#define COMPILE_SIGNAL_COLOR_SH 1
|
|
|
|
// Input and output layout.
|
|
#define CONFIG_SIGNAL_INPUT_LAYOUT SIGNAL_BUFFER_LAYOUT_LUMEN_DIFFUSE_HISTORY
|
|
#define CONFIG_SIGNAL_HISTORY_LAYOUT SIGNAL_BUFFER_LAYOUT_LUMEN_DIFFUSE_HISTORY
|
|
|
|
#define CONFIG_INPUT_TEXTURE_COUNT 2
|
|
#define CONFIG_HISTORY_TEXTURE_COUNT 2
|
|
|
|
#define CONFIG_HISTORY_KERNEL SAMPLE_SET_2X2_STOCASTIC
|
|
//#define CONFIG_HISTORY_REJECTION HISTORY_REJECTION_MINMAX_BOUNDARIES
|
|
|
|
// Given it's a spherical harmonic that store directionality, only need position based rejection.
|
|
#define CONFIG_BILATERAL_PRESET BILATERAL_PRESET_SPHERICAL_HARMONIC
|
|
#define CONFIG_HISTORY_BILATERAL_PRESET BILATERAL_PRESET_SPHERICAL_HARMONIC
|
|
//#define CONFIG_BILATERAL_PRESET BILATERAL_PRESET_DISABLED
|
|
//#define CONFIG_HISTORY_BILATERAL_PRESET BILATERAL_PRESET_DISABLED
|
|
|
|
#elif CONFIG_SIGNAL_PROCESSING == SIGNAL_PROCESSING_SSGI
|
|
#define MAX_SIGNAL_BATCH_SIZE 1
|
|
#define SIGNAL_ARRAY_SIZE 1
|
|
|
|
#define COMPILE_SIGNAL_COLOR 1
|
|
#define CONFIG_MULTIPLEXED_SIGNALS_PER_SIGNAL_DOMAIN 1
|
|
|
|
// Input and output layout.
|
|
#define CONFIG_SIGNAL_INPUT_LAYOUT SIGNAL_BUFFER_LAYOUT_SSGI_HISTORY_R11G11B10
|
|
#define CONFIG_SIGNAL_HISTORY_LAYOUT SIGNAL_BUFFER_LAYOUT_SSGI_HISTORY_R11G11B10
|
|
|
|
#define CONFIG_INPUT_TEXTURE_COUNT 2
|
|
#define CONFIG_HISTORY_TEXTURE_COUNT 2
|
|
|
|
// SSGI doesn't have any bilateral distance computed from hitT, so allow to blur spatially by about the size of the kernel.
|
|
#define CONFIG_BILATERAL_DISTANCE_MULTIPLIER 3.0
|
|
|
|
// Stocastically sample history to speed up the reprojection.
|
|
#define CONFIG_HISTORY_KERNEL SAMPLE_SET_2X2_STOCASTIC
|
|
|
|
// Reject using variance to smooth highlights further on history rejections.
|
|
#define CONFIG_HISTORY_REJECTION HISTORY_REJECTION_VAR_BOUNDARIES
|
|
|
|
#define CONFIG_REJECTION_SAMPLE_SET SAMPLE_SET_3X3_PLUS
|
|
|
|
// Use position and normal based rejection ideal for diffuse.
|
|
#define CONFIG_BILATERAL_PRESET BILATERAL_PRESET_DIFFUSE
|
|
#define CONFIG_HISTORY_BILATERAL_PRESET BILATERAL_PRESET_DIFFUSE
|
|
|
|
#elif CONFIG_SIGNAL_PROCESSING == SIGNAL_PROCESSING_DIFFUSE_PROBE_HIERARCHY
|
|
#define MAX_SIGNAL_BATCH_SIZE 1
|
|
#define SIGNAL_ARRAY_SIZE 1
|
|
#define CONFIG_MULTIPLEXED_SIGNALS_PER_SIGNAL_DOMAIN 1
|
|
|
|
#define COMPILE_SIGNAL_COLOR_ARRAY 2
|
|
|
|
// Input and output layout.
|
|
#define CONFIG_SIGNAL_INPUT_LAYOUT SIGNAL_BUFFER_LAYOUT_DIFFUSE_PROBE_HIERARCHY_INPUT
|
|
#define CONFIG_SIGNAL_HISTORY_LAYOUT SIGNAL_BUFFER_LAYOUT_DIFFUSE_PROBE_HIERARCHY_HISTORY
|
|
|
|
#define CONFIG_INPUT_TEXTURE_COUNT 2
|
|
#define CONFIG_HISTORY_TEXTURE_COUNT 3
|
|
|
|
// SSGI doesn't have any bilateral distance computed from hitT, so allow to blur spatially by about the size of the kernel.
|
|
#define CONFIG_BILATERAL_DISTANCE_MULTIPLIER 3.0
|
|
|
|
// Stocastically sample history to speed up the reprojection.
|
|
//#define CONFIG_HISTORY_KERNEL SAMPLE_SET_2X2_BILINEAR
|
|
//#define CONFIG_HISTORY_KERNEL SAMPLE_SET_2X2_STOCASTIC
|
|
#define CONFIG_HISTORY_KERNEL SAMPLE_SET_2X2_ADAPTIVE
|
|
|
|
// Reject using variance to smooth highlights further on history rejections.
|
|
#define CONFIG_HISTORY_REJECTION HISTORY_REJECTION_MINMAX_BOUNDARIES
|
|
|
|
// Use position and normal based rejection ideal for diffuse.
|
|
//#define CONFIG_BILATERAL_PRESET BILATERAL_PRESET_DIFFUSE
|
|
#define CONFIG_BILATERAL_PRESET BILATERAL_PRESET_DISABLED
|
|
|
|
#define CONFIG_PATCH_PREV_SCENE_DEPTH 1
|
|
#define CONFIG_HISTORY_BILATERAL_PRESET BILATERAL_PRESET_PROBE_HIERARCHY
|
|
//#define CONFIG_HISTORY_BILATERAL_PRESET BILATERAL_PRESET_DISABLED
|
|
|
|
#else
|
|
#error Unimplemented signal processing.
|
|
#endif
|
|
|
|
|
|
//------------------------------------------------------- CONFIG DISABLED DEFAULTS
|
|
|
|
/** Whether should clamp the UV individually per texture. */
|
|
#ifndef CONFIG_CLAMP_UV_PER_SIGNAL
|
|
#define CONFIG_CLAMP_UV_PER_SIGNAL 0
|
|
#endif
|
|
|
|
/** Whether this pass make use of a tile classification. */
|
|
#ifndef CONFIG_USE_TILE_CLASSIFICATION
|
|
#define CONFIG_USE_TILE_CLASSIFICATION 0
|
|
#endif
|
|
|
|
/** Whether this pass uses custom rejection buffer. */
|
|
#ifndef CONFIG_USE_REJECTION_BUFFER
|
|
#define CONFIG_USE_REJECTION_BUFFER 0
|
|
#define CONFIG_SIGNAL_HISTORY_REJECTION_LAYOUT CONFIG_SIGNAL_INPUT_LAYOUT
|
|
#endif
|
|
|
|
/** Input mode of the rejection signals. */
|
|
#ifndef CONFIG_REJECTION_INPUT_MODE
|
|
#define CONFIG_REJECTION_INPUT_MODE REJECTION_INPUT_MODE_1UNNORMALIZED
|
|
#endif
|
|
|
|
/** Sample set to use for history rejection. */
|
|
#ifndef CONFIG_REJECTION_SAMPLE_SET
|
|
#define CONFIG_REJECTION_SAMPLE_SET SAMPLE_SET_NXN
|
|
#endif
|
|
|
|
/** The color space to use for history rejection. */
|
|
#ifndef CONFIG_REJECTION_BUFFER_COLOR_SPACE
|
|
#define CONFIG_REJECTION_BUFFER_COLOR_SPACE STANDARD_BUFFER_COLOR_SPACE
|
|
#endif
|
|
|
|
/** The number of signal that should be processed per signal domain. */
|
|
#ifndef CONFIG_MULTIPLEXED_SIGNALS_PER_SIGNAL_DOMAIN
|
|
#define CONFIG_MULTIPLEXED_SIGNALS_PER_SIGNAL_DOMAIN SIGNAL_ARRAY_SIZE
|
|
#endif
|
|
|
|
/** Whether can use a nearest sampler when sampling the history */
|
|
#ifndef CONFIG_HISTORY_KERNEL
|
|
#define CONFIG_HISTORY_KERNEL SAMPLE_SET_2X2_BILINEAR
|
|
#endif
|
|
|
|
/** Adds a multiplier on how the distance should be computed. */
|
|
#ifndef CONFIG_BILATERAL_DISTANCE_MULTIPLIER
|
|
#define CONFIG_BILATERAL_DISTANCE_MULTIPLIER 1.0
|
|
#endif
|
|
|
|
/** Whether should consider the depth velocity to compute the reference scene depth. */
|
|
#ifndef CONFIG_PATCH_PREV_SCENE_DEPTH
|
|
#define CONFIG_PATCH_PREV_REF_SCENE_DEPTH 0
|
|
#endif
|
|
|
|
#ifndef CONFIG_NORMALIZED_INPUT
|
|
#define CONFIG_NORMALIZED_INPUT 0
|
|
#endif
|
|
|
|
/** Whether should reject history on pixels with UNLIT shading model. */
|
|
#ifndef CONFIG_USE_UNLIT_HISTORY_REJECTION
|
|
#define CONFIG_USE_UNLIT_HISTORY_REJECTION 0
|
|
#endif
|
|
|
|
//------------------------------------------------------- CONFIG ENABLED DEFAULTS
|
|
|
|
/** Whether should do history rejection. */
|
|
#ifndef CONFIG_HISTORY_REJECTION
|
|
#define CONFIG_HISTORY_REJECTION HISTORY_REJECTION_DISABLED
|
|
#endif
|
|
|
|
/** The color space to use for history rejection. */
|
|
#ifndef CONFIG_HISTORY_REJECTION_COLOR_SPACE
|
|
#define CONFIG_HISTORY_REJECTION_COLOR_SPACE STANDARD_BUFFER_COLOR_SPACE
|
|
#endif
|
|
|
|
/** The color space to use for history blending. */
|
|
#ifndef CONFIG_HISTORY_BLENDING_COLOR_SPACE
|
|
#define CONFIG_HISTORY_BLENDING_COLOR_SPACE STANDARD_BUFFER_COLOR_SPACE
|
|
#endif
|
|
|
|
|
|
//------------------------------------------------------- COMPILATION CONFIGURATION
|
|
|
|
#define COMPILE_BOX_KERNEL 1
|
|
|
|
// Moment 1 needed for previous frame sampling.
|
|
#define COMPILE_MOMENT1_ACCUMULATOR 1
|
|
|
|
#if CONFIG_HISTORY_REJECTION != HISTORY_REJECTION_DISABLED
|
|
#define COMPILE_MIN_FREQUENCY_ACCUMULATOR 1
|
|
#endif
|
|
|
|
#if CONFIG_HISTORY_REJECTION == HISTORY_REJECTION_MINMAX_BOUNDARIES
|
|
#define COMPILE_MINMAX_ACCUMULATOR 1
|
|
#elif CONFIG_HISTORY_REJECTION == HISTORY_REJECTION_VAR_BOUNDARIES && CONFIG_REJECTION_INPUT_MODE == REJECTION_INPUT_MODE_1UNNORMALIZED
|
|
#define COMPILE_MOMENT2_ACCUMULATOR 1
|
|
#endif
|
|
|
|
|
|
//------------------------------------------------------- INCLUDES
|
|
|
|
#include "SSDSignalFramework.ush"
|
|
#include "SSDSignalArray.ush"
|
|
#include "SSDSpatialKernel.ush"
|
|
#include "../Random.ush"
|
|
|
|
|
|
//------------------------------------------------------- PARAMETERS
|
|
|
|
DECLARE_SCALAR_ARRAY(int, bCameraCut, MAX_SIGNAL_BATCH_SIZE);
|
|
|
|
float HistoryPreExposureCorrection;
|
|
|
|
float4 ScreenPosToHistoryBufferUV;
|
|
float4 HistoryBufferSizeAndInvSize;
|
|
float4 HistoryBufferUVMinMax;
|
|
float4 HistoryBufferScissorUVMinMax[CONFIG_SIGNAL_BATCH_SIZE];
|
|
|
|
|
|
#if !defined(CONFIG_INPUT_TEXTURE_COUNT)
|
|
#error Missing CONFIG_INPUT_TEXTURE_COUNT
|
|
#endif
|
|
|
|
FSSDTexture2D SignalInput_Textures_0;
|
|
|
|
#if CONFIG_INPUT_TEXTURE_COUNT > 1
|
|
FSSDTexture2D SignalInput_Textures_1;
|
|
#else
|
|
#define SignalInput_Textures_1 SignalInput_Textures_0
|
|
#endif
|
|
|
|
#if CONFIG_INPUT_TEXTURE_COUNT > 2
|
|
FSSDTexture2D SignalInput_Textures_2;
|
|
#else
|
|
#define SignalInput_Textures_2 SignalInput_Textures_0
|
|
#endif
|
|
|
|
#if CONFIG_INPUT_TEXTURE_COUNT > 3
|
|
FSSDTexture2D SignalInput_Textures_3;
|
|
#else
|
|
#define SignalInput_Textures_3 SignalInput_Textures_0
|
|
#endif
|
|
|
|
|
|
#if CONFIG_USE_REJECTION_BUFFER
|
|
#if !defined(CONFIG_REJECTION_TEXTURE_COUNT)
|
|
#error Missing CONFIG_REJECTION_TEXTURE_COUNT
|
|
#endif
|
|
|
|
FSSDTexture2D HistoryRejectionSignal_Textures_0;
|
|
|
|
#if CONFIG_REJECTION_TEXTURE_COUNT > 1
|
|
FSSDTexture2D HistoryRejectionSignal_Textures_1;
|
|
#else
|
|
#define HistoryRejectionSignal_Textures_1 HistoryRejectionSignal_Textures_0
|
|
#endif
|
|
|
|
#if CONFIG_REJECTION_TEXTURE_COUNT > 2
|
|
FSSDTexture2D HistoryRejectionSignal_Textures_2;
|
|
#else
|
|
#define HistoryRejectionSignal_Textures_2 HistoryRejectionSignal_Textures_0
|
|
#endif
|
|
|
|
#if CONFIG_REJECTION_TEXTURE_COUNT > 3
|
|
FSSDTexture2D HistoryRejectionSignal_Textures_3;
|
|
#else
|
|
#define HistoryRejectionSignal_Textures_3 HistoryRejectionSignal_Textures_0
|
|
#endif
|
|
#endif // CONFIG_USE_REJECTION_BUFFER
|
|
|
|
|
|
#if !defined(CONFIG_HISTORY_TEXTURE_COUNT)
|
|
#error Missing CONFIG_HISTORY_TEXTURE_COUNT
|
|
#endif
|
|
|
|
FSSDTexture2D PrevHistory_Textures_0;
|
|
FSSDRWTexture2D SignalHistoryOutput_UAVs_0;
|
|
|
|
#if CONFIG_HISTORY_TEXTURE_COUNT > 1
|
|
FSSDTexture2D PrevHistory_Textures_1;
|
|
FSSDRWTexture2D SignalHistoryOutput_UAVs_1;
|
|
#else
|
|
#define PrevHistory_Textures_1 PrevHistory_Textures_0
|
|
#define SignalHistoryOutput_UAVs_1 SignalHistoryOutput_UAVs_0
|
|
#endif
|
|
|
|
#if CONFIG_HISTORY_TEXTURE_COUNT > 2
|
|
FSSDTexture2D PrevHistory_Textures_2;
|
|
FSSDRWTexture2D SignalHistoryOutput_UAVs_2;
|
|
#else
|
|
#define PrevHistory_Textures_2 PrevHistory_Textures_0
|
|
#define SignalHistoryOutput_UAVs_2 SignalHistoryOutput_UAVs_0
|
|
#endif
|
|
|
|
#if CONFIG_HISTORY_TEXTURE_COUNT > 3
|
|
FSSDTexture2D PrevHistory_Textures_3;
|
|
FSSDRWTexture2D SignalHistoryOutput_UAVs_3;
|
|
#else
|
|
#define PrevHistory_Textures_3 PrevHistory_Textures_0
|
|
#define SignalHistoryOutput_UAVs_3 SignalHistoryOutput_UAVs_0
|
|
#endif
|
|
|
|
|
|
//------------------------------------------------------- FUNCTIONS
|
|
|
|
FSSDSignalSample TransformInputBufferForPreRejection(FSSDSignalSample Sample)
|
|
{
|
|
return TransformSignal(
|
|
Sample,
|
|
/* SrcConfig = */ STANDARD_BUFFER_COLOR_SPACE,
|
|
/* DestConfig = */ CONFIG_HISTORY_REJECTION_COLOR_SPACE);
|
|
}
|
|
|
|
FSSDSignalSample TransformSignalForPostRejection(FSSDSignalSample Sample)
|
|
{
|
|
return TransformSignal(
|
|
Sample,
|
|
/* SrcConfig = */ CONFIG_HISTORY_REJECTION_COLOR_SPACE,
|
|
/* DestConfig = */ STANDARD_BUFFER_COLOR_SPACE);
|
|
}
|
|
|
|
/** Temporally accumulate the input. */
|
|
void TemporallyAccumulate(
|
|
uint2 DispatchThreadId : SV_DispatchThreadID,
|
|
uint2 GroupId : SV_GroupID,
|
|
uint2 GroupThreadId : SV_GroupThreadID,
|
|
uint GroupThreadIndex : SV_GroupIndex)
|
|
{
|
|
// Find out scene buffer UV.
|
|
float2 SceneBufferUV = DispatchThreadId * ThreadIdToBufferUV.xy + ThreadIdToBufferUV.zw;
|
|
if (true)
|
|
{
|
|
SceneBufferUV = clamp(SceneBufferUV, DenoiserBufferBilinearUVMinMax.xy, DenoiserBufferBilinearUVMinMax.zw);
|
|
}
|
|
|
|
// Sample current frame data.
|
|
FSSDCompressedSceneInfos CompressedRefSceneMetadata = SampleCompressedSceneMetadata(
|
|
/* bPrevFrame = */ false,
|
|
SceneBufferUV, BufferUVToBufferPixelCoord(SceneBufferUV));
|
|
|
|
float DeviceZ;
|
|
uint ShadingModelID;
|
|
{
|
|
FSSDSampleSceneInfos RefInfo = UncompressSampleSceneInfo(
|
|
CONFIG_METADATA_BUFFER_LAYOUT, /* bIsPrevFrame = */ false,
|
|
DenoiserBufferUVToScreenPosition(SceneBufferUV),
|
|
CompressedRefSceneMetadata);
|
|
|
|
DeviceZ = RefInfo.DeviceZ;
|
|
ShadingModelID = RefInfo.ShadingModelID;
|
|
}
|
|
|
|
// Reproject to previous frame.
|
|
float3 HistoryScreenPosition = float3(DenoiserBufferUVToScreenPosition(SceneBufferUV), DeviceZ);
|
|
bool bIsDynamicPixel = false;
|
|
if (1)
|
|
{
|
|
|
|
float4 ThisClip = float4(HistoryScreenPosition, 1);
|
|
|
|
float4 PrevClip = mul(ThisClip, View.ClipToPrevClip);
|
|
float3 PrevScreen = PrevClip.xyz * rcp(PrevClip.w);
|
|
float3 Velocity = HistoryScreenPosition - PrevScreen;
|
|
|
|
if (1)
|
|
{
|
|
float4 EncodedVelocity = GBufferVelocityTexture.SampleLevel(GlobalPointClampedSampler, SceneBufferUV, 0);
|
|
bIsDynamicPixel = EncodedVelocity.x > 0.0;
|
|
|
|
if (bIsDynamicPixel)
|
|
{
|
|
Velocity = DecodeVelocityFromTexture(EncodedVelocity);
|
|
}
|
|
}
|
|
|
|
HistoryScreenPosition -= Velocity;
|
|
}
|
|
|
|
|
|
FSSDSignalArray CurrentFrameSamples;
|
|
FSSDSignalFrequencyArray CurrentFrameFrequencies;
|
|
SampleMultiplexedSignals(
|
|
SignalInput_Textures_0,
|
|
SignalInput_Textures_1,
|
|
SignalInput_Textures_2,
|
|
SignalInput_Textures_3,
|
|
GlobalPointClampedSampler,
|
|
CONFIG_SIGNAL_INPUT_LAYOUT,
|
|
/* MultiplexedSampleId = */ 0,
|
|
/* bNormalizeSample = */ CONFIG_NORMALIZED_INPUT != 0,
|
|
SceneBufferUV,
|
|
/* out */ CurrentFrameSamples,
|
|
/* out */ CurrentFrameFrequencies);
|
|
|
|
// Sample the history buffer.
|
|
FSSDSignalArray HistorySamples = CreateSignalArrayFromScalarValue(0.0);
|
|
{
|
|
float2 HistoryBufferUV = HistoryScreenPosition.xy * ScreenPosToHistoryBufferUV.xy + ScreenPosToHistoryBufferUV.zw;
|
|
float2 ClampedHistoryBufferUV = clamp(HistoryBufferUV, HistoryBufferUVMinMax.xy, HistoryBufferUVMinMax.zw);
|
|
bool bIsPreviousFrameOffscreen = any(HistoryBufferUV != ClampedHistoryBufferUV);
|
|
|
|
// TODO(Denoiser): global camera cut to save perf that is going to be required for panic post filtering.
|
|
BRANCH
|
|
if (!bIsPreviousFrameOffscreen)
|
|
{
|
|
FSSDKernelConfig KernelConfig = CreateKernelConfig();
|
|
|
|
#if DEBUG_OUTPUT
|
|
{
|
|
KernelConfig.DebugPixelPosition = DispatchThreadId;
|
|
KernelConfig.DebugEventCounter = 0;
|
|
}
|
|
#endif
|
|
|
|
// compile time configuration of the kernel.
|
|
KernelConfig.SampleSet = CONFIG_HISTORY_KERNEL;
|
|
//KernelConfig.SampleSet = SAMPLE_SET_1X1;
|
|
KernelConfig.bSampleKernelCenter = true;
|
|
KernelConfig.BufferLayout = CONFIG_SIGNAL_HISTORY_LAYOUT;
|
|
KernelConfig.MultiplexedSignalsPerSignalDomain = CONFIG_MULTIPLEXED_SIGNALS_PER_SIGNAL_DOMAIN;
|
|
KernelConfig.bUnroll = true;
|
|
KernelConfig.bPreviousFrameMetadata = true;
|
|
KernelConfig.BilateralDistanceComputation = SIGNAL_WORLD_FREQUENCY_MIN_METADATA;
|
|
KernelConfig.bClampUVPerMultiplexedSignal = CONFIG_CLAMP_UV_PER_SIGNAL != 0;
|
|
|
|
// Allow a little bit of error when doing bilateral rejection of the history, to forgive per frame TAA jitter.
|
|
KernelConfig.WorldBluringDistanceMultiplier = max(CONFIG_BILATERAL_DISTANCE_MULTIPLIER, 3.0);
|
|
|
|
SetBilateralPreset(CONFIG_HISTORY_BILATERAL_PRESET, /* inout */ KernelConfig);
|
|
|
|
// SGPR configuration of the kernel.
|
|
KernelConfig.BufferSizeAndInvSize = HistoryBufferSizeAndInvSize;
|
|
KernelConfig.BufferBilinearUVMinMax = HistoryBufferUVMinMax;
|
|
|
|
#if CONFIG_CLAMP_UV_PER_SIGNAL
|
|
{
|
|
UNROLL_N(CONFIG_SIGNAL_BATCH_SIZE)
|
|
for (uint BatchedSignalId = 0; BatchedSignalId < CONFIG_SIGNAL_BATCH_SIZE; BatchedSignalId++)
|
|
{
|
|
uint MultiplexId = BatchedSignalId / CONFIG_MULTIPLEXED_SIGNALS_PER_SIGNAL_DOMAIN;
|
|
KernelConfig.PerSignalUVMinMax[MultiplexId] = HistoryBufferScissorUVMinMax[MultiplexId];
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// VGPR configuration of the kernel.
|
|
KernelConfig.BufferUV = HistoryBufferUV + BufferUVBilinearCorrection;
|
|
KernelConfig.bIsDynamicPixel = bIsDynamicPixel;
|
|
|
|
#if CONFIG_PATCH_PREV_SCENE_DEPTH
|
|
{
|
|
KernelConfig.RefBufferUV = HistoryBufferUV;
|
|
KernelConfig.RefSceneMetadataLayout = CONFIG_METADATA_BUFFER_LAYOUT;
|
|
KernelConfig.bPreviousFrameRefMetadata = true;
|
|
|
|
FSSDSampleSceneInfos PrevRefInfo = UncompressSampleSceneInfo(
|
|
CONFIG_METADATA_BUFFER_LAYOUT, /* bIsPrevFrame = */ false,
|
|
BufferUVToBufferPixelCoord(SceneBufferUV),
|
|
CompressedRefSceneMetadata);
|
|
|
|
PrevRefInfo.ScreenPosition = HistoryScreenPosition.xy;
|
|
PrevRefInfo.DeviceZ = HistoryScreenPosition.z;
|
|
PrevRefInfo.WorldDepth = ConvertFromDeviceZ(HistoryScreenPosition.z);
|
|
|
|
float4 ClipPosition = float4(GetScreenPositionForProjectionType(HistoryScreenPosition.xy, PrevRefInfo.WorldDepth), PrevRefInfo.WorldDepth, 1);
|
|
|
|
float3 PreViewTranslationOffset = DFFastLocalSubtractDemote(PrimaryView.PreViewTranslation, PrimaryView.PrevPreViewTranslation);
|
|
PrevRefInfo.TranslatedWorldPosition = mul(ClipPosition, View.PrevScreenToTranslatedWorld).xyz + PreViewTranslationOffset;
|
|
|
|
KernelConfig.CompressedRefSceneMetadata = CompressSampleSceneInfo(
|
|
KernelConfig.RefSceneMetadataLayout,
|
|
PrevRefInfo);
|
|
}
|
|
#else
|
|
{
|
|
KernelConfig.CompressedRefSceneMetadata = CompressedRefSceneMetadata;
|
|
KernelConfig.RefBufferUV = SceneBufferUV;
|
|
KernelConfig.RefSceneMetadataLayout = CONFIG_METADATA_BUFFER_LAYOUT;
|
|
}
|
|
#endif
|
|
|
|
|
|
// Compute random signals.
|
|
ISOLATE
|
|
{
|
|
KernelConfig.Randoms[0] = InterleavedGradientNoise(SceneBufferUV * BufferUVToOutputPixelPosition, View.StateFrameIndexMod8);
|
|
}
|
|
|
|
FSSDSignalAccumulatorArray SignalAccumulators = CreateSignalAccumulatorArray();
|
|
FSSDCompressedSignalAccumulatorArray UnusedCompressedAccumulators = CreateUninitialisedCompressedAccumulatorArray();
|
|
|
|
AccumulateKernel(
|
|
KernelConfig,
|
|
PrevHistory_Textures_0,
|
|
PrevHistory_Textures_1,
|
|
PrevHistory_Textures_2,
|
|
PrevHistory_Textures_3,
|
|
/* inout */ SignalAccumulators,
|
|
/* inout */ UnusedCompressedAccumulators);
|
|
|
|
// Exports the history sample from accumulator.
|
|
{
|
|
UNROLL_N(CONFIG_SIGNAL_BATCH_SIZE)
|
|
for (uint BatchedSignalId = 0; BatchedSignalId < CONFIG_SIGNAL_BATCH_SIZE; BatchedSignalId++)
|
|
{
|
|
HistorySamples.Array[BatchedSignalId] = SignalAccumulators.Array[BatchedSignalId].Moment1;
|
|
BRANCH
|
|
if (GET_SCALAR_ARRAY_ELEMENT(bCameraCut, BatchedSignalId))
|
|
{
|
|
HistorySamples.Array[BatchedSignalId] = CreateSignalSampleFromScalarValue(0.0);
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
UNROLL_N(CONFIG_SIGNAL_BATCH_SIZE)
|
|
for (uint BatchedSignalId = 0; BatchedSignalId < CONFIG_SIGNAL_BATCH_SIZE; BatchedSignalId++)
|
|
{
|
|
FSSDSignalSample CurrentFrameSample = CurrentFrameSamples.Array[BatchedSignalId];
|
|
FSSDSignalSample HistorySample = HistorySamples.Array[BatchedSignalId];
|
|
|
|
// Applies correction when pre exposure change happen.
|
|
#if COMPILE_SIGNAL_COLOR
|
|
HistorySamples.Array[BatchedSignalId].SceneColor.rgb *= HistoryPreExposureCorrection;
|
|
#endif
|
|
|
|
#if COMPILE_SIGNAL_COLOR_ARRAY > 0
|
|
UNROLL_N(COMPILE_SIGNAL_COLOR_ARRAY)
|
|
for (uint ColorId = 0; ColorId < COMPILE_SIGNAL_COLOR_ARRAY; ColorId++)
|
|
{
|
|
HistorySamples.Array[BatchedSignalId].ColorArray[ColorId] *= HistoryPreExposureCorrection;
|
|
}
|
|
#endif
|
|
} // for (uint BatchedSignalId = 0; BatchedSignalId < CONFIG_SIGNAL_BATCH_SIZE; BatchedSignalId++)
|
|
}
|
|
} // if (!bIsPreviousFrameOffscreen)
|
|
}
|
|
|
|
#if CONFIG_SIGNAL_PROCESSING == SIGNAL_PROCESSING_DIFFUSE_PROBE_HIERARCHY && 0
|
|
DebugOutput[DispatchThreadId] = float4(
|
|
HistorySamples.Array[0].SceneColor.rgb,
|
|
0);
|
|
#endif
|
|
|
|
const bool bPostRejectionBlending = true;
|
|
|
|
// History rejection.
|
|
#if (CONFIG_HISTORY_REJECTION == HISTORY_REJECTION_MINMAX_BOUNDARIES || CONFIG_HISTORY_REJECTION == HISTORY_REJECTION_VAR_BOUNDARIES)
|
|
{
|
|
FSSDKernelConfig KernelConfig = CreateKernelConfig();
|
|
|
|
#if DEBUG_OUTPUT
|
|
{
|
|
KernelConfig.DebugPixelPosition = DispatchThreadId;
|
|
KernelConfig.DebugEventCounter = 0;
|
|
}
|
|
#endif
|
|
|
|
// compile time configuration of the kernel.
|
|
{
|
|
KernelConfig.bSampleKernelCenter = CONFIG_USE_REJECTION_BUFFER != 0;
|
|
|
|
// History rejection is already fudge factor by how reprojection. Want to prioritize rejection stability with more sample
|
|
// than accuracy, so only take the blur distance of the reference sample that depends on depth and pixel size of the current frame.
|
|
KernelConfig.BilateralDistanceComputation = SIGNAL_WORLD_FREQUENCY_REF_METADATA_ONLY;
|
|
KernelConfig.NeighborToRefComputation = NEIGHBOR_TO_REF_LOWEST_VGPR_PRESSURE;
|
|
|
|
// TODO(Denoiser): Should be done for all signals.
|
|
// TODO(Denoiser): Should also take into account the world bluring radius du to size of the pixel.
|
|
if (CONFIG_SIGNAL_PROCESSING == SIGNAL_PROCESSING_SHADOW_VISIBILITY_MASK)
|
|
KernelConfig.BilateralDistanceComputation = SIGNAL_WORLD_FREQUENCY_PRECOMPUTED_BLURING_RADIUS;
|
|
KernelConfig.WorldBluringDistanceMultiplier = CONFIG_BILATERAL_DISTANCE_MULTIPLIER;
|
|
|
|
#if CONFIG_REJECTION_SAMPLE_SET == REJECTION_SAMPLE_SET_SOBEK2018
|
|
{
|
|
KernelConfig.SampleSet = SAMPLE_SET_3X3_SOBEK2018;
|
|
//KernelConfig.SampleSet = SAMPLE_SET_NXN;
|
|
//KernelConfig.BoxKernelRadius = 3;
|
|
KernelConfig.bUnroll = true;
|
|
}
|
|
#elif CONFIG_SIGNAL_PROCESSING == SIGNAL_PROCESSING_SSGI || CONFIG_SIGNAL_PROCESSING == SIGNAL_PROCESSING_DIFFUSE_PROBE_HIERARCHY
|
|
{
|
|
KernelConfig.SampleSet = SAMPLE_SET_3X3_PLUS;
|
|
KernelConfig.bUnroll = true;
|
|
}
|
|
#else
|
|
{
|
|
KernelConfig.SampleSet = (CONFIG_SIGNAL_PROCESSING == SIGNAL_PROCESSING_SHADOW_VISIBILITY_MASK) ? SAMPLE_SET_3X3 : SAMPLE_SET_NXN;
|
|
KernelConfig.BoxKernelRadius = 3;
|
|
KernelConfig.bUnroll = false;
|
|
}
|
|
#endif
|
|
|
|
if (CONFIG_USE_REJECTION_BUFFER)
|
|
{
|
|
// History rejection have two moments of the signal being denoised.
|
|
KernelConfig.MultiplexedSignalsPerSignalDomain = 2;
|
|
|
|
KernelConfig.BufferLayout = CONFIG_SIGNAL_HISTORY_REJECTION_LAYOUT;
|
|
KernelConfig.bNormalizeSample = false;
|
|
|
|
for (uint MultiplexId = 0; MultiplexId < SIGNAL_ARRAY_SIZE; MultiplexId++)
|
|
{
|
|
KernelConfig.BufferColorSpace[MultiplexId] = CONFIG_REJECTION_BUFFER_COLOR_SPACE;
|
|
KernelConfig.AccumulatorColorSpace[MultiplexId] = CONFIG_HISTORY_REJECTION_COLOR_SPACE;
|
|
}
|
|
|
|
// Force to sample the kernel center because will contain two momments for matching scene meta data.
|
|
KernelConfig.bForceKernelCenterAccumulation = true;
|
|
}
|
|
else
|
|
{
|
|
KernelConfig.MultiplexedSignalsPerSignalDomain = CONFIG_MULTIPLEXED_SIGNALS_PER_SIGNAL_DOMAIN;
|
|
KernelConfig.BufferLayout = CONFIG_SIGNAL_INPUT_LAYOUT;
|
|
KernelConfig.bNormalizeSample = true;
|
|
|
|
for (uint MultiplexId = 0; MultiplexId < SIGNAL_ARRAY_SIZE; MultiplexId++)
|
|
{
|
|
KernelConfig.AccumulatorColorSpace[MultiplexId] = CONFIG_HISTORY_REJECTION_COLOR_SPACE;
|
|
}
|
|
|
|
if (MAX_SIGNAL_BATCH_SIZE == 1)
|
|
{
|
|
// TODO(Denoiser): missing && abs(PixelOffset.x) <= 1 && abs(PixelOffset.y) <= 1;
|
|
KernelConfig.bForceAllAccumulation = CurrentFrameSamples.Array[0].SampleCount == 0;
|
|
}
|
|
}
|
|
|
|
SetBilateralPreset(CONFIG_BILATERAL_PRESET, /* inout */ KernelConfig);
|
|
}
|
|
|
|
// SGPR configuration of the kernel.
|
|
{
|
|
KernelConfig.BufferSizeAndInvSize = DenoiserBufferSizeAndInvSize;
|
|
KernelConfig.BufferBilinearUVMinMax = DenoiserBufferBilinearUVMinMax;
|
|
}
|
|
|
|
// VGPR configuration of the kernel.
|
|
{
|
|
KernelConfig.BufferUV = SceneBufferUV;
|
|
{
|
|
KernelConfig.CompressedRefSceneMetadata = CompressedRefSceneMetadata;
|
|
KernelConfig.RefBufferUV = SceneBufferUV;
|
|
KernelConfig.RefSceneMetadataLayout = CONFIG_METADATA_BUFFER_LAYOUT;
|
|
}
|
|
}
|
|
|
|
// Accumulate the current frame to save perf with unecessary bilateral evaluation.
|
|
FSSDSignalAccumulatorArray SignalAccumulators = CreateSignalAccumulatorArray();
|
|
{
|
|
FSSDSampleSceneInfos RefSceneMetadata = UncompressRefSceneMetadata(KernelConfig);
|
|
|
|
FSSDCompressedSignalAccumulatorArray UnusedCompressedAccumulators = CreateUninitialisedCompressedAccumulatorArray();
|
|
|
|
FSSDSignalArray CenterSample = CurrentFrameSamples;
|
|
if (KernelConfig.bNormalizeSample)
|
|
{
|
|
CenterSample = NormalizeToOneSampleArray(CurrentFrameSamples);
|
|
}
|
|
|
|
AccumulateRefSampleAsKernelCenter(
|
|
KernelConfig,
|
|
/* inout */ SignalAccumulators,
|
|
/* inout */ UnusedCompressedAccumulators,
|
|
KernelConfig.RefBufferUV,
|
|
RefSceneMetadata,
|
|
CenterSample,
|
|
CurrentFrameFrequencies);
|
|
}
|
|
|
|
{
|
|
FSSDCompressedSignalAccumulatorArray UnusedCompressedAccumulators = CreateUninitialisedCompressedAccumulatorArray();
|
|
|
|
#if CONFIG_USE_REJECTION_BUFFER
|
|
AccumulateKernel(
|
|
KernelConfig,
|
|
HistoryRejectionSignal_Textures_0,
|
|
HistoryRejectionSignal_Textures_1,
|
|
HistoryRejectionSignal_Textures_2,
|
|
HistoryRejectionSignal_Textures_3,
|
|
/* inout */ SignalAccumulators,
|
|
/* inout */ UnusedCompressedAccumulators);
|
|
#else
|
|
AccumulateKernel(
|
|
KernelConfig,
|
|
SignalInput_Textures_0,
|
|
SignalInput_Textures_1,
|
|
SignalInput_Textures_2,
|
|
SignalInput_Textures_3,
|
|
/* inout */ SignalAccumulators,
|
|
/* inout */ UnusedCompressedAccumulators);
|
|
#endif
|
|
}
|
|
|
|
// Clamp history
|
|
UNROLL_N(CONFIG_SIGNAL_BATCH_SIZE)
|
|
for (uint BatchedSignalId = 0; BatchedSignalId < CONFIG_SIGNAL_BATCH_SIZE; BatchedSignalId++)
|
|
{
|
|
FSSDSignalSample NeighborMoment1 = CreateSignalSampleFromScalarValue(0.0);
|
|
FSSDSignalSample NeighborMoment2 = CreateSignalSampleFromScalarValue(0.0);
|
|
#if CONFIG_REJECTION_INPUT_MODE == REJECTION_INPUT_MODE_1UNNORMALIZED
|
|
{
|
|
float NormalizeFactor = SafeRcp(SignalAccumulators.Array[BatchedSignalId].Moment1.SampleCount);
|
|
NeighborMoment1 = MulSignal(SignalAccumulators.Array[BatchedSignalId].Moment1, NormalizeFactor);
|
|
|
|
#if COMPILE_MOMENT2_ACCUMULATOR
|
|
NeighborMoment2 = MulSignal(SignalAccumulators.Array[BatchedSignalId].Moment2, NormalizeFactor);
|
|
#endif
|
|
}
|
|
#elif CONFIG_REJECTION_INPUT_MODE == REJECTION_INPUT_MODE_2PRETRANSFORMED_MOMMENTS
|
|
{
|
|
#if SIGNAL_ARRAY_SIZE != 2 * MAX_SIGNAL_BATCH_SIZE
|
|
#error Invalid signal array size.
|
|
#endif
|
|
|
|
float NormalizeFactor = SafeRcp(SignalAccumulators.Array[BatchedSignalId * 2 + 0].Moment1.SampleCount);
|
|
NeighborMoment1 = MulSignal(SignalAccumulators.Array[BatchedSignalId * 2 + 0].Moment1, NormalizeFactor);
|
|
NeighborMoment2 = MulSignal(SignalAccumulators.Array[BatchedSignalId * 2 + 1].Moment1, NormalizeFactor);
|
|
}
|
|
#else
|
|
#error NOrmalized samples.
|
|
#endif
|
|
|
|
#if CONFIG_SIGNAL_PROCESSING == SIGNAL_PROCESSING_REFLECTIONS && 0
|
|
FSSDSignalSample Temp = TransformSignalForPostRejection(NeighborMoment1);
|
|
DebugOutput[DispatchThreadId] = float4(
|
|
Temp.SceneColor.rgb,
|
|
0);
|
|
#endif
|
|
|
|
FSSDSignalSample CurrentFrameSample = CurrentFrameSamples.Array[BatchedSignalId];
|
|
FSSDSignalSample HistorySample = HistorySamples.Array[BatchedSignalId];
|
|
|
|
// Clamp the history.
|
|
#if CONFIG_HISTORY_REJECTION == HISTORY_REJECTION_VAR_BOUNDARIES
|
|
{
|
|
#if CONFIG_SIGNAL_PROCESSING == SIGNAL_PROCESSING_AO
|
|
const float StdDevMultiplier = 6.00;
|
|
#else
|
|
const float StdDevMultiplier = 1.25;
|
|
#endif
|
|
|
|
// StdDev = sqrt(abs(NeighborSquareAvg - NeighborAvg * NeighborAvg));
|
|
FSSDSignalSample StdDev = SqrtSignal(AbsSignal(SubtractSignal(NeighborMoment2, PowerSignal(NeighborMoment1, 2))));
|
|
FSSDSignalSample NeighborMin = AddSignal(NeighborMoment1, MulSignal(StdDev, -StdDevMultiplier));
|
|
FSSDSignalSample NeighborMax = AddSignal(NeighborMoment1, MulSignal(StdDev, StdDevMultiplier));
|
|
|
|
if (0)
|
|
{
|
|
FSSDSignalSample QuantizationErrorMin = MulSignal(NeighborMoment1, 1 - SafeRcp(HistorySample.SampleCount));
|
|
FSSDSignalSample QuantizationErrorMax = MulSignal(NeighborMoment1, 1 + SafeRcp(HistorySample.SampleCount));
|
|
|
|
NeighborMin = MinSignal(NeighborMin, QuantizationErrorMin);
|
|
NeighborMax = MaxSignal(NeighborMax, QuantizationErrorMax);
|
|
}
|
|
|
|
// Transform the history so that it in correct component spaces, and normalized as the clamping box.
|
|
FSSDSignalSample NormalizedHistorySample = NormalizeToOneSample(HistorySample);
|
|
FSSDSignalSample TransformedHistorySample = TransformInputBufferForPreRejection(NormalizedHistorySample);
|
|
|
|
// Clamp the history.
|
|
FSSDSignalSample ClampedTransformedHistorySample = ClampSignal(TransformedHistorySample, NeighborMin, NeighborMax);
|
|
|
|
// Transform the history back to linear component spaces.
|
|
FSSDSignalSample ClampedHistorySample = TransformSignalForPostRejection(ClampedTransformedHistorySample);
|
|
|
|
// Reweight the anti ghosted history.
|
|
{
|
|
FSSDSignalSample RejectedDiff = AbsSignal(SubtractSignal(ClampedTransformedHistorySample, TransformedHistorySample));
|
|
|
|
// Compute how much this history get changed.
|
|
float RejectionFactor = 0.0;
|
|
#if CONFIG_SIGNAL_PROCESSING == SIGNAL_PROCESSING_REFLECTIONS && (CONFIG_HISTORY_REJECTION_COLOR_SPACE & COLOR_SPACE_LCOCG)
|
|
{
|
|
#if !COMPILE_SIGNAL_COLOR
|
|
#error Need to compile signal color.
|
|
#endif
|
|
RejectionFactor = abs(
|
|
Luma_To_LumaLog(ClampedTransformedHistorySample.SceneColor.x) -
|
|
Luma_To_LumaLog(TransformedHistorySample.SceneColor.x));
|
|
|
|
RejectionFactor = max(RejectionFactor, 1 * max(RejectedDiff.SceneColor.y, RejectedDiff.SceneColor.z));
|
|
RejectionFactor = max(RejectionFactor, 1 * RejectedDiff.SceneColor.a);
|
|
}
|
|
#elif CONFIG_SIGNAL_PROCESSING == SIGNAL_PROCESSING_SHADOW_VISIBILITY_MASK || CONFIG_SIGNAL_PROCESSING == SIGNAL_PROCESSING_POLYCHROMATIC_PENUMBRA_HARMONIC || CONFIG_SIGNAL_PROCESSING == SIGNAL_PROCESSING_AO || CONFIG_SIGNAL_PROCESSING == SIGNAL_PROCESSING_DIFFUSE_INDIRECT_AND_AO
|
|
{
|
|
RejectionFactor = abs(ClampedTransformedHistorySample.MissCount - TransformedHistorySample.MissCount);
|
|
}
|
|
#elif CONFIG_SIGNAL_PROCESSING == SIGNAL_PROCESSING_SSGI
|
|
{
|
|
//float4 ColorDiff = abs(ClampedTransformedHistorySample.SceneColor - TransformedHistorySample.SceneColor) / ClampedTransformedHistorySample.SceneColor;
|
|
//
|
|
//ColorDiff = -min(-ColorDiff, 0.0);
|
|
//
|
|
//RejectionFactor = saturate(max(max(ColorDiff.x, ColorDiff.y), ColorDiff.z));
|
|
RejectionFactor = abs(ClampedTransformedHistorySample.MissCount - TransformedHistorySample.MissCount);
|
|
}
|
|
#else
|
|
#error Unsupported signal rejection.
|
|
#endif
|
|
|
|
// Compute an initial history weight as if we had removed sample.
|
|
float FinalHistoryWeight = HistorySample.SampleCount * saturate(1 - RejectionFactor);
|
|
|
|
// When doing the accumulation before rejection, need to make sure the input weight get through.
|
|
if (!bPostRejectionBlending)
|
|
{
|
|
FinalHistoryWeight = max(FinalHistoryWeight, CurrentFrameSample.SampleCount);
|
|
}
|
|
|
|
// When doing upscaling, may have an invalid input sample.
|
|
FinalHistoryWeight = max(FinalHistoryWeight, NeighborMoment1.SampleCount * 0.1);
|
|
|
|
#if CONFIG_USE_UNLIT_HISTORY_REJECTION
|
|
bool bValid = DenoiseShadingModelID(ShadingModelID);
|
|
if (!bValid)
|
|
{
|
|
FinalHistoryWeight = 0.0;
|
|
}
|
|
#endif
|
|
// Apply the history weight.
|
|
HistorySample = MulSignal(ClampedHistorySample, FinalHistoryWeight);
|
|
HistorySample.SampleCount = FinalHistoryWeight;
|
|
}
|
|
}
|
|
#elif CONFIG_HISTORY_REJECTION == HISTORY_REJECTION_MINMAX_BOUNDARIES
|
|
{
|
|
FSSDSignalSample NeighborMin = SignalAccumulators.Array[BatchedSignalId].Min;
|
|
FSSDSignalSample NeighborMax = SignalAccumulators.Array[BatchedSignalId].Max;
|
|
|
|
#if CONFIG_SIGNAL_PROCESSING == SIGNAL_PROCESSING_DIFFUSE_PROBE_HIERARCHY
|
|
{
|
|
FSSDSignalSample CenterSample = CurrentFrameSamples.Array[BatchedSignalId];
|
|
|
|
FSSDSignalSample CenterMinSample = NormalizeToOneSample(CenterSample);
|
|
FSSDSignalSample CenterMaxSample = NormalizeToOneSample(CenterSample);
|
|
|
|
const float Abracadabra = 0.7;
|
|
|
|
#if COMPILE_SIGNAL_COLOR
|
|
CenterMinSample.SceneColor *= Abracadabra;
|
|
CenterMaxSample.SceneColor *= rcp(Abracadabra);
|
|
#endif
|
|
|
|
#if COMPILE_SIGNAL_COLOR_ARRAY > 0
|
|
UNROLL_N(COMPILE_SIGNAL_COLOR_ARRAY)
|
|
for (uint ColorId = 0; ColorId < COMPILE_SIGNAL_COLOR_ARRAY; ColorId++)
|
|
{
|
|
CenterMinSample.ColorArray[ColorId] *= Abracadabra;
|
|
CenterMaxSample.ColorArray[ColorId] *= rcp(Abracadabra);
|
|
}
|
|
#endif
|
|
|
|
NeighborMin = MinSignal(NeighborMin, CenterMinSample);
|
|
NeighborMax = MaxSignal(NeighborMax, CenterMaxSample);
|
|
}
|
|
#endif
|
|
|
|
// If no neighborhood had a sample the maximum sample count will remain 0.
|
|
bool bIsValid = NeighborMax.SampleCount > 0.0;
|
|
|
|
float RejectedSampleCount = 0;
|
|
HistorySample = MulSignal(TransformSignalForPostRejection(ClampSignal(TransformInputBufferForPreRejection(NormalizeToOneSample(HistorySample)), NeighborMin, NeighborMax)), HistorySample.SampleCount - RejectedSampleCount);
|
|
|
|
// All the clamping box was invalid, so invalidate the history sample too.
|
|
FLATTEN
|
|
if (!bIsValid)
|
|
{
|
|
HistorySample = CreateSignalSampleFromScalarValue(0.0);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// Dilate the smallest inv frequency.
|
|
if (1)
|
|
{
|
|
CurrentFrameFrequencies.Array[BatchedSignalId] = MinSignalFrequency(
|
|
CurrentFrameFrequencies.Array[BatchedSignalId],
|
|
SignalAccumulators.Array[BatchedSignalId].MinFrequency);
|
|
}
|
|
|
|
HistorySamples.Array[BatchedSignalId] = HistorySample;
|
|
CurrentFrameSamples.Array[BatchedSignalId] = CurrentFrameSample;
|
|
} // for (uint BatchedSignalId = 0; BatchedSignalId < CONFIG_SIGNAL_BATCH_SIZE; BatchedSignalId++)
|
|
}
|
|
#endif // CONFIG_HISTORY_REJECTION > 0
|
|
|
|
{
|
|
UNROLL
|
|
for (uint BatchedSignalId = 0; BatchedSignalId < MAX_SIGNAL_BATCH_SIZE; BatchedSignalId++)
|
|
{
|
|
FSSDSignalSample CurrentFrameSample = CurrentFrameSamples.Array[BatchedSignalId];
|
|
FSSDSignalSample HistorySample = HistorySamples.Array[BatchedSignalId];
|
|
FSSDSignalFrequency CurrentFrequency = CurrentFrameFrequencies.Array[BatchedSignalId];
|
|
|
|
float TargetedSampleCount;
|
|
{
|
|
float2 ScreenPosition = DenoiserBufferUVToScreenPosition(SceneBufferUV);
|
|
|
|
FSSDSampleSceneInfos RefSceneMetadata = UncompressSampleSceneInfo(
|
|
CONFIG_METADATA_BUFFER_LAYOUT, /* bPrevFrame = */ false,
|
|
ScreenPosition, CompressedRefSceneMetadata);
|
|
|
|
// Use the diameter, because that is the distance between two pixel.
|
|
float PixelWorldBluringRadius = ComputeWorldBluringRadiusCausedByPixelSize(RefSceneMetadata);
|
|
float WorldBluringRadius = WorldBluringRadiusToBilateralWorldDistance(PixelWorldBluringRadius);
|
|
|
|
#if CONFIG_SIGNAL_PROCESSING == SIGNAL_PROCESSING_SHADOW_VISIBILITY_MASK
|
|
{
|
|
float ResolutionFraction = 0.5;
|
|
float ToleratedNoiseRatio = 0.25 * rcp(9 * sqrt(2));
|
|
|
|
float OutputPixelRadius = CurrentFrequency.WorldBluringRadius * rcp(PixelWorldBluringRadius) * ResolutionFraction;
|
|
|
|
TargetedSampleCount = clamp(OutputPixelRadius * OutputPixelRadius * (PI * ToleratedNoiseRatio), 1, TARGETED_SAMPLE_COUNT);
|
|
}
|
|
#elif CONFIG_SIGNAL_PROCESSING == SIGNAL_PROCESSING_REFLECTIONS
|
|
{
|
|
float2 NormalizedScreenMajorAxis;
|
|
float InifinityMajorViewportRadius;
|
|
float InifinityMinorViewportRadius;
|
|
ProjectSpecularLobeToScreenSpace(
|
|
RefSceneMetadata,
|
|
/* out */ NormalizedScreenMajorAxis,
|
|
/* out */ InifinityMajorViewportRadius,
|
|
/* out */ InifinityMinorViewportRadius);
|
|
|
|
InifinityMajorViewportRadius *= View.ViewSizeAndInvSize.x;
|
|
InifinityMinorViewportRadius *= View.ViewSizeAndInvSize.x;
|
|
|
|
TargetedSampleCount = PI * InifinityMajorViewportRadius * InifinityMinorViewportRadius;
|
|
|
|
// TODO(Denoiser): try to make this better? * 0.125 to avoid banding caused by floating point precision.
|
|
TargetedSampleCount = clamp(TargetedSampleCount, 1, TARGETED_SAMPLE_COUNT);
|
|
}
|
|
#else
|
|
{
|
|
TargetedSampleCount = TARGETED_SAMPLE_COUNT;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
float PreviousFrameWeight = min(HistorySample.SampleCount, TargetedSampleCount - CurrentFrameSample.SampleCount);
|
|
float PreviousFrameMultiplier = HistorySample.SampleCount > 0 ? PreviousFrameWeight / HistorySample.SampleCount : 0;
|
|
|
|
// TODO(Denoiser): use WeightedLerp instead for VALU perf.
|
|
// Pre transformation of the signal.
|
|
HistorySample = TransformSignal(
|
|
HistorySample,
|
|
/* SrcBasis = */ STANDARD_BUFFER_COLOR_SPACE,
|
|
/* DestBasis = */ CONFIG_HISTORY_BLENDING_COLOR_SPACE);
|
|
CurrentFrameSample = TransformSignal(
|
|
CurrentFrameSample,
|
|
/* SrcBasis = */ STANDARD_BUFFER_COLOR_SPACE,
|
|
/* DestBasis = */ CONFIG_HISTORY_BLENDING_COLOR_SPACE);
|
|
|
|
// Blending.
|
|
HistorySample = AddSignal(MulSignal(HistorySample, PreviousFrameMultiplier), CurrentFrameSample);
|
|
|
|
// Post transformation of the signal.
|
|
HistorySample = TransformSignal(
|
|
HistorySample,
|
|
/* SrcBasis = */ CONFIG_HISTORY_BLENDING_COLOR_SPACE,
|
|
/* DestBasis = */ STANDARD_BUFFER_COLOR_SPACE);
|
|
|
|
//if (View.GeneralPurposeTweak > 0.5)
|
|
HistorySamples.Array[BatchedSignalId] = HistorySample;
|
|
}
|
|
}
|
|
|
|
// Romoves NaN and negative numbers
|
|
// HistorySample = Minus(Min(Minus(HistorySample), CreateSignalSampleFromScalarValue(0.0)));
|
|
|
|
// Masks what should be outputed to ensure the compiler compiles out everything that ends up unneeded.
|
|
uint MultiplexCount = 1;
|
|
FSSDSignalArray OutputSamples = CreateSignalArrayFromScalarValue(0.0);
|
|
FSSDSignalFrequencyArray OutputFrequencies = CreateInvalidSignalFrequencyArray();
|
|
{
|
|
MultiplexCount = CONFIG_SIGNAL_BATCH_SIZE;
|
|
|
|
UNROLL
|
|
for (uint BatchedSignalId = 0; BatchedSignalId < MultiplexCount; BatchedSignalId++)
|
|
{
|
|
OutputSamples.Array[BatchedSignalId] = HistorySamples.Array[BatchedSignalId];
|
|
OutputFrequencies.Array[BatchedSignalId] = CurrentFrameFrequencies.Array[BatchedSignalId];
|
|
}
|
|
}
|
|
|
|
// No need to keep DispatchThreadId, while SceneBufferUV is arround at highest VGPR peak because center of the kernel.
|
|
uint2 OutputPixelPostion = BufferUVToBufferPixelCoord(SceneBufferUV);
|
|
|
|
BRANCH
|
|
if (all(OutputPixelPostion < ViewportMax))
|
|
{
|
|
OutputMultiplexedSignal(
|
|
SignalHistoryOutput_UAVs_0,
|
|
SignalHistoryOutput_UAVs_1,
|
|
SignalHistoryOutput_UAVs_2,
|
|
SignalHistoryOutput_UAVs_3,
|
|
CONFIG_SIGNAL_HISTORY_LAYOUT,
|
|
MultiplexCount,
|
|
OutputPixelPostion,
|
|
OutputSamples,
|
|
OutputFrequencies);
|
|
}
|
|
} // TemporallyAccumulate
|
|
|
|
|
|
//------------------------------------------------------- ENTRY POINT
|
|
|
|
[numthreads(TILE_PIXEL_SIZE, TILE_PIXEL_SIZE, 1)]
|
|
void MainCS(
|
|
uint2 DispatchThreadId : SV_DispatchThreadID,
|
|
uint2 GroupId : SV_GroupID,
|
|
uint2 GroupThreadId : SV_GroupThreadID,
|
|
uint GroupThreadIndex : SV_GroupIndex)
|
|
{
|
|
TemporallyAccumulate(DispatchThreadId, GroupId, GroupThreadId, GroupThreadIndex);
|
|
}
|