312 lines
9.9 KiB
HLSL
312 lines
9.9 KiB
HLSL
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "SSDDefinitions.ush"
|
|
#include "SSDPublicHarmonics.ush"
|
|
|
|
|
|
//------------------------------------------------------- CONFIGS
|
|
|
|
#define TILE_PIXEL_SIZE 8
|
|
|
|
#define CONFIG_SIGNAL_PROCESSING SIGNAL_PROCESSING_POLYCHROMATIC_PENUMBRA_HARMONIC
|
|
|
|
#if 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
|
|
#define CONFIG_SIGNAL_BATCH_SIZE 2
|
|
|
|
// Each harmonic requires input and output RGB.
|
|
#define COMPILE_SIGNAL_COLOR_ARRAY 2
|
|
|
|
// Outputing a single composed color for each diffuse and specular.
|
|
#define COMPILE_SIGNAL_COLOR 1
|
|
|
|
//#define CONFIG_VIEW_POSITION_BASED_BILATERAL 2
|
|
#define CONFIG_MULTIPLEXED_SIGNALS_PER_SIGNAL_DOMAIN 1
|
|
|
|
// Input and output layout.
|
|
#define CONFIG_SIGNAL_INPUT_LAYOUT SIGNAL_BUFFER_LAYOUT_POLYCHROMATIC_PENUMBRA_HARMONIC_INPUT
|
|
#define CONFIG_SIGNAL_RECONSTRUCTED_LAYOUT SIGNAL_BUFFER_LAYOUT_POLYCHROMATIC_PENUMBRA_HARMONIC_RECONSTRUCTION
|
|
#define CONFIG_SIGNAL_OUTPUT_LAYOUT SIGNAL_BUFFER_LAYOUT_POLYCHROMATIC_PENUMBRA_HISTORY
|
|
#define CONFIG_INPUT_TEXTURE_COUNT 4
|
|
#define CONFIG_OUTPUT_TEXTURE_COUNT 2
|
|
|
|
#define CONFIG_HARMONIC_COUNT DENOISER_HARMONICS_COUNT
|
|
|
|
#else
|
|
#error Unknown signal processing.
|
|
#endif
|
|
|
|
|
|
//------------------------------------------------------- INCLUDES
|
|
|
|
#include "SSDSignalFramework.ush"
|
|
#include "SSDSignalArray.ush"
|
|
#include "SSDSignalBufferEncoding.ush"
|
|
|
|
|
|
//------------------------------------------------------- PARAMETERS
|
|
|
|
#if !defined(CONFIG_INPUT_TEXTURE_COUNT)
|
|
#error Missing CONFIG_INPUT_TEXTURE_COUNT
|
|
#endif
|
|
|
|
FSSDTexture2D SignalHarmonics_0_Textures_0;
|
|
FSSDTexture2D SignalHarmonics_1_Textures_0;
|
|
FSSDTexture2D SignalHarmonics_2_Textures_0;
|
|
FSSDTexture2D SignalHarmonics_3_Textures_0;
|
|
|
|
FSSDTexture2D SignalIntegrand_Textures_0;
|
|
|
|
#if CONFIG_INPUT_TEXTURE_COUNT > 1
|
|
FSSDTexture2D SignalHarmonics_0_Textures_1;
|
|
FSSDTexture2D SignalHarmonics_1_Textures_1;
|
|
FSSDTexture2D SignalHarmonics_2_Textures_1;
|
|
FSSDTexture2D SignalHarmonics_3_Textures_1;
|
|
FSSDTexture2D SignalIntegrand_Textures_1;
|
|
#else
|
|
#define SignalHarmonics_0_Textures_1 SignalHarmonics_0_Textures_0
|
|
#define SignalHarmonics_1_Textures_1 SignalHarmonics_1_Textures_0
|
|
#define SignalHarmonics_2_Textures_1 SignalHarmonics_2_Textures_0
|
|
#define SignalHarmonics_3_Textures_1 SignalHarmonics_3_Textures_0
|
|
#define SignalIntegrand_Textures_1 SignalIntegrand_Textures_0
|
|
#endif
|
|
|
|
#if CONFIG_INPUT_TEXTURE_COUNT > 2
|
|
FSSDTexture2D SignalHarmonics_0_Textures_2;
|
|
FSSDTexture2D SignalHarmonics_1_Textures_2;
|
|
FSSDTexture2D SignalHarmonics_2_Textures_2;
|
|
FSSDTexture2D SignalHarmonics_3_Textures_2;
|
|
FSSDTexture2D SignalIntegrand_Textures_2;
|
|
#else
|
|
#define SignalHarmonics_0_Textures_2 SignalHarmonics_0_Textures_0
|
|
#define SignalHarmonics_1_Textures_2 SignalHarmonics_1_Textures_0
|
|
#define SignalHarmonics_2_Textures_2 SignalHarmonics_2_Textures_0
|
|
#define SignalHarmonics_3_Textures_2 SignalHarmonics_3_Textures_0
|
|
#define SignalIntegrand_Textures_2 SignalIntegrand_Textures_0
|
|
#endif
|
|
|
|
#if CONFIG_INPUT_TEXTURE_COUNT > 3
|
|
FSSDTexture2D SignalHarmonics_0_Textures_3;
|
|
FSSDTexture2D SignalHarmonics_1_Textures_3;
|
|
FSSDTexture2D SignalHarmonics_2_Textures_3;
|
|
FSSDTexture2D SignalHarmonics_3_Textures_3;
|
|
FSSDTexture2D SignalIntegrand_Textures_3;
|
|
#else
|
|
#define SignalHarmonics_0_Textures_3 SignalHarmonics_0_Textures_0
|
|
#define SignalHarmonics_1_Textures_3 SignalHarmonics_1_Textures_0
|
|
#define SignalHarmonics_2_Textures_3 SignalHarmonics_2_Textures_0
|
|
#define SignalHarmonics_3_Textures_3 SignalHarmonics_3_Textures_0
|
|
#define SignalIntegrand_Textures_3 SignalIntegrand_Textures_0
|
|
#endif
|
|
|
|
|
|
#if !defined(CONFIG_OUTPUT_TEXTURE_COUNT)
|
|
#error Missing CONFIG_OUTPUT_TEXTURE_COUNT
|
|
#endif
|
|
|
|
FSSDRWTexture2D SignalOutput_UAVs_0;
|
|
|
|
#if CONFIG_OUTPUT_TEXTURE_COUNT > 1
|
|
FSSDRWTexture2D SignalOutput_UAVs_1;
|
|
#else
|
|
#define SignalOutput_UAVs_1 SignalOutput_UAVs_0
|
|
#endif
|
|
|
|
#if CONFIG_OUTPUT_TEXTURE_COUNT > 2
|
|
FSSDRWTexture2D SignalOutput_UAVs_2;
|
|
#else
|
|
#define SignalOutput_UAVs_2 SignalOutput_UAVs_0
|
|
#endif
|
|
|
|
#if CONFIG_OUTPUT_TEXTURE_COUNT > 3
|
|
FSSDRWTexture2D SignalOutput_UAVs_3;
|
|
#else
|
|
#define SignalOutput_UAVs_3 SignalOutput_UAVs_0
|
|
#endif
|
|
|
|
|
|
//------------------------------------------------------- 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)
|
|
{
|
|
// Find out scene buffer UV.
|
|
float2 SceneBufferUV = DispatchThreadId * ThreadIdToBufferUV.xy + ThreadIdToBufferUV.zw;
|
|
if (true)
|
|
{
|
|
SceneBufferUV = clamp(SceneBufferUV, DenoiserBufferBilinearUVMinMax.xy, DenoiserBufferBilinearUVMinMax.zw);
|
|
}
|
|
|
|
// Read reference meta data.
|
|
float2 ScreenPosition = DenoiserBufferUVToScreenPosition(SceneBufferUV);
|
|
|
|
// Sample the harmonics.
|
|
FSSDSignalArray MultiplexedHarmonics[4];
|
|
FSSDSignalFrequencyArray MultiplexedFrequencies;
|
|
{
|
|
SampleMultiplexedSignals(
|
|
SignalHarmonics_0_Textures_0,
|
|
SignalHarmonics_0_Textures_1,
|
|
SignalHarmonics_0_Textures_2,
|
|
SignalHarmonics_0_Textures_3,
|
|
GlobalPointClampedSampler,
|
|
CONFIG_SIGNAL_INPUT_LAYOUT,
|
|
/* MultiplexedSampleId = */ 0,
|
|
/* bNormalizeSample = */ false,
|
|
SceneBufferUV,
|
|
MultiplexedHarmonics[0],
|
|
MultiplexedFrequencies);
|
|
|
|
SampleMultiplexedSignals(
|
|
SignalHarmonics_1_Textures_0,
|
|
SignalHarmonics_1_Textures_1,
|
|
SignalHarmonics_1_Textures_2,
|
|
SignalHarmonics_1_Textures_3,
|
|
GlobalPointClampedSampler,
|
|
CONFIG_SIGNAL_RECONSTRUCTED_LAYOUT,
|
|
/* MultiplexedSampleId = */ 0,
|
|
/* bNormalizeSample = */ false,
|
|
SceneBufferUV,
|
|
MultiplexedHarmonics[1],
|
|
MultiplexedFrequencies);
|
|
|
|
SampleMultiplexedSignals(
|
|
SignalHarmonics_2_Textures_0,
|
|
SignalHarmonics_2_Textures_1,
|
|
SignalHarmonics_2_Textures_2,
|
|
SignalHarmonics_2_Textures_3,
|
|
GlobalPointClampedSampler,
|
|
CONFIG_SIGNAL_RECONSTRUCTED_LAYOUT,
|
|
/* MultiplexedSampleId = */ 0,
|
|
/* bNormalizeSample = */ false,
|
|
SceneBufferUV,
|
|
MultiplexedHarmonics[2],
|
|
MultiplexedFrequencies);
|
|
|
|
SampleMultiplexedSignals(
|
|
SignalHarmonics_3_Textures_0,
|
|
SignalHarmonics_3_Textures_1,
|
|
SignalHarmonics_3_Textures_2,
|
|
SignalHarmonics_3_Textures_3,
|
|
GlobalPointClampedSampler,
|
|
CONFIG_SIGNAL_RECONSTRUCTED_LAYOUT,
|
|
/* MultiplexedSampleId = */ 0,
|
|
/* bNormalizeSample = */ false,
|
|
SceneBufferUV,
|
|
MultiplexedHarmonics[3],
|
|
MultiplexedFrequencies);
|
|
}
|
|
|
|
// Sample the integrated signal.
|
|
FSSDSignalArray MultiplexedIntegrand;
|
|
SampleMultiplexedSignals(
|
|
SignalIntegrand_Textures_0,
|
|
SignalIntegrand_Textures_1,
|
|
SignalIntegrand_Textures_2,
|
|
SignalIntegrand_Textures_3,
|
|
GlobalPointClampedSampler,
|
|
CONFIG_SIGNAL_RECONSTRUCTED_LAYOUT,
|
|
/* MultiplexedSampleId = */ 0,
|
|
/* bNormalizeSample = */ true,
|
|
SceneBufferUV,
|
|
MultiplexedIntegrand,
|
|
MultiplexedFrequencies);
|
|
|
|
// Determine computation that needs to be done.
|
|
FSSDSignalArray OutputSamples = CreateSignalArrayFromScalarValue(0.0);
|
|
UNROLL_N(CONFIG_SIGNAL_BATCH_SIZE)
|
|
for (uint MultiplexId = 0; MultiplexId < CONFIG_SIGNAL_BATCH_SIZE; MultiplexId++)
|
|
{
|
|
const uint LowestFrequencyHarmonicId = DENOISER_HARMONICS_COUNT - 1;
|
|
float LowestFrequencyWeight;
|
|
{
|
|
FSSDSignalSample Sample = MultiplexedHarmonics[LowestFrequencyHarmonicId].Array[MultiplexId];
|
|
OutputSamples.Array[MultiplexId] = Sample;
|
|
LowestFrequencyWeight = Sample.SampleCount;
|
|
}
|
|
|
|
float3 Color = 0;
|
|
float3 ColorMask = 1.0;
|
|
|
|
UNROLL_N(DENOISER_HARMONICS_COUNT)
|
|
for (uint HarmonicId = 0; HarmonicId < DENOISER_HARMONICS_COUNT; HarmonicId++)
|
|
{
|
|
FSSDSignalSample Sample = MultiplexedHarmonics[HarmonicId].Array[MultiplexId];
|
|
FSSDSignalSample NormalizedSample = NormalizeToOneSample(Sample);
|
|
|
|
float3 Incoming = NormalizedSample.ColorArray[0].rgb;
|
|
float3 Outgoing = NormalizedSample.ColorArray[1].rgb;
|
|
float3 Stoped = Incoming - Outgoing;
|
|
|
|
// TODO(Denoiser).
|
|
float3 HarmonicMask;
|
|
HarmonicMask.r = Incoming.r > 0 ? saturate(Outgoing.r / Incoming.r) : 1.0;
|
|
HarmonicMask.g = Incoming.g > 0 ? saturate(Outgoing.g / Incoming.g) : 1.0;
|
|
HarmonicMask.b = Incoming.b > 0 ? saturate(Outgoing.b / Incoming.b) : 1.0;
|
|
|
|
ColorMask *= HarmonicMask;
|
|
|
|
//if (HarmonicId == View.GeneralPurposeTweak && MultiplexId == 0)
|
|
//{
|
|
// DebugOutput[DispatchThreadId] = float4(HarmonicMask, 0);
|
|
//}
|
|
}
|
|
|
|
FSSDSignalSample IntegrandSample = MultiplexedIntegrand.Array[MultiplexId];
|
|
float3 TotalLighting = IntegrandSample.ColorArray[0].rgb;
|
|
|
|
float3 FinalLighting = ColorMask * TotalLighting;
|
|
|
|
//if (MultiplexId == 0)
|
|
//{
|
|
// if (SceneBufferUV.x > 0.5)
|
|
// DebugOutput[DispatchThreadId] = float4(TotalLighting, 0);
|
|
// else
|
|
// DebugOutput[DispatchThreadId] = float4(TotalLighting, 0);
|
|
//}
|
|
|
|
OutputSamples.Array[MultiplexId].SampleCount = LowestFrequencyWeight;
|
|
OutputSamples.Array[MultiplexId].SceneColor.rgb = FinalLighting * LowestFrequencyWeight;
|
|
|
|
//OutputSamples.Array[MultiplexId].SampleCount = LowestFrequencyWeight;
|
|
//OutputSamples.Array[MultiplexId].SceneColor.rgb = MultiplexedHarmonics[2].Array[MultiplexId].ColorArray[0] * LowestFrequencyWeight;
|
|
}
|
|
|
|
// Clamp.
|
|
UNROLL_N(CONFIG_SIGNAL_BATCH_SIZE)
|
|
for (uint MultiplexId = 0; MultiplexId < CONFIG_SIGNAL_BATCH_SIZE; MultiplexId++)
|
|
{
|
|
#if COMPILE_SIGNAL_COLOR
|
|
OutputSamples.Array[MultiplexId].SceneColor = max(OutputSamples.Array[MultiplexId].SceneColor, 0);
|
|
#endif
|
|
}
|
|
|
|
#if CONFIG_VGPR_OPTIMIZATION
|
|
// No need to keep DispatchThreadId, while SceneBufferUV is arround at highest VGPR peak because center of the unique pixel to sample.
|
|
uint2 OutputPixelPostion = BufferUVToBufferPixelCoord(SceneBufferUV);
|
|
#else
|
|
uint2 OutputPixelPostion = ViewportMin + DispatchThreadId;
|
|
#endif
|
|
|
|
BRANCH
|
|
if (all(OutputPixelPostion < ViewportMax))
|
|
{
|
|
OutputMultiplexedSignal(
|
|
SignalOutput_UAVs_0,
|
|
SignalOutput_UAVs_1,
|
|
SignalOutput_UAVs_2,
|
|
SignalOutput_UAVs_3,
|
|
CONFIG_SIGNAL_OUTPUT_LAYOUT, CONFIG_SIGNAL_BATCH_SIZE,
|
|
OutputPixelPostion,
|
|
OutputSamples.Array,
|
|
MultiplexedFrequencies
|
|
);
|
|
}
|
|
} // MainCS
|