850 lines
28 KiB
HLSL
850 lines
28 KiB
HLSL
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "SSDSignalCore.ush"
|
|
#include "SSDPublicBufferEncoding.ush"
|
|
#include "../Lumen/LumenBufferEncoding.ush"
|
|
|
|
/** Whether the color should be clamped when encoding signal. */
|
|
#define CONFIG_ENCODING_CLAMP_COLOR 1
|
|
|
|
/** Selects the type that should be used when sampling a buffer */
|
|
#ifndef CONFIG_SIGNAL_INPUT_TEXTURE_TYPE
|
|
#define CONFIG_SIGNAL_INPUT_TEXTURE_TYPE SIGNAL_TEXTURE_TYPE_FLOAT4
|
|
#endif
|
|
|
|
/** Selects the type that should be used when sampling a buffer */
|
|
#ifndef CONFIG_SIGNAL_OUTPUT_TEXTURE_TYPE
|
|
#define CONFIG_SIGNAL_OUTPUT_TEXTURE_TYPE SIGNAL_TEXTURE_TYPE_FLOAT4
|
|
#endif
|
|
|
|
|
|
#if CONFIG_SIGNAL_INPUT_TEXTURE_TYPE == SIGNAL_TEXTURE_TYPE_FLOAT4
|
|
#define FSSDRawSample float4
|
|
#define FSSDTexture2D Texture2D
|
|
#elif CONFIG_SIGNAL_INPUT_TEXTURE_TYPE == SIGNAL_TEXTURE_TYPE_UINT1 || CONFIG_SIGNAL_INPUT_TEXTURE_TYPE == SIGNAL_TEXTURE_TYPE_UINT2 || CONFIG_SIGNAL_INPUT_TEXTURE_TYPE == SIGNAL_TEXTURE_TYPE_UINT3 || CONFIG_SIGNAL_INPUT_TEXTURE_TYPE == SIGNAL_TEXTURE_TYPE_UINT4
|
|
#if CONFIG_SIGNAL_INPUT_TEXTURE_TYPE == SIGNAL_TEXTURE_TYPE_UINT1
|
|
#define FSSDRawSample uint
|
|
#elif CONFIG_SIGNAL_INPUT_TEXTURE_TYPE == SIGNAL_TEXTURE_TYPE_UINT2
|
|
#define FSSDRawSample uint2
|
|
#elif CONFIG_SIGNAL_INPUT_TEXTURE_TYPE == SIGNAL_TEXTURE_TYPE_UINT3
|
|
#define FSSDRawSample uint3
|
|
#elif CONFIG_SIGNAL_INPUT_TEXTURE_TYPE == SIGNAL_TEXTURE_TYPE_UINT4
|
|
#define FSSDRawSample uint4
|
|
#else
|
|
#error Unknown input type for a signal texture.
|
|
#endif
|
|
#define FSSDTexture2D Texture2D<FSSDRawSample>
|
|
#else
|
|
#error Unknown input type for a signal texture.
|
|
#endif
|
|
|
|
#if CONFIG_SIGNAL_OUTPUT_TEXTURE_TYPE == SIGNAL_TEXTURE_TYPE_FLOAT4
|
|
#define FSSDOutputRawSample float4
|
|
#elif CONFIG_SIGNAL_OUTPUT_TEXTURE_TYPE == SIGNAL_TEXTURE_TYPE_UINT1
|
|
#define FSSDOutputRawSample uint
|
|
#elif CONFIG_SIGNAL_OUTPUT_TEXTURE_TYPE == SIGNAL_TEXTURE_TYPE_UINT2
|
|
#define FSSDOutputRawSample uint2
|
|
#elif CONFIG_SIGNAL_OUTPUT_TEXTURE_TYPE == SIGNAL_TEXTURE_TYPE_UINT3
|
|
#define FSSDOutputRawSample uint3
|
|
#elif CONFIG_SIGNAL_OUTPUT_TEXTURE_TYPE == SIGNAL_TEXTURE_TYPE_UINT4
|
|
#define FSSDOutputRawSample uint4
|
|
#else
|
|
#error Unknown output type for a signal texture.
|
|
#endif
|
|
|
|
#define FSSDRWTexture2D RWTexture2D<FSSDOutputRawSample>
|
|
|
|
|
|
float3 ClampColorForEncoding(float3 Color)
|
|
{
|
|
#if CONFIG_ENCODING_CLAMP_COLOR
|
|
Color = min(Color, MaxHalfFloat);
|
|
#endif
|
|
return Color;
|
|
}
|
|
|
|
float4 ClampColorForEncoding(float4 Color)
|
|
{
|
|
return float4(ClampColorForEncoding(Color.rgb), Color.a);
|
|
}
|
|
|
|
|
|
/** Raw data layout when sampling input texture of the denoiser. */
|
|
struct FSSDCompressedMultiplexedSample
|
|
{
|
|
FSSDRawSample VGPRArray[MAX_MULTIPLEXED_TEXTURES];
|
|
};
|
|
|
|
|
|
/** Decode input signal sample from raw float. */
|
|
void DecodeMultiplexedSignalsFromFloat4(
|
|
const uint SignalBufferLayout,
|
|
const uint MultiplexedSampleId,
|
|
const bool bNormalizeSample,
|
|
float4 RawSample[MAX_MULTIPLEXED_TEXTURES],
|
|
out FSSDSignalArray OutSamples,
|
|
out FSSDSignalFrequencyArray OutSampleFrequencies)
|
|
{
|
|
OutSamples = CreateSignalArrayFromScalarValue(0.0);
|
|
OutSampleFrequencies = CreateInvalidSignalFrequencyArray();
|
|
|
|
if (0)
|
|
{
|
|
|
|
}
|
|
#if 1
|
|
else if (SignalBufferLayout == SIGNAL_BUFFER_LAYOUT_UNINITIALIZED)
|
|
{
|
|
// trash out the output sample to identify quickly a miss configured buffer layout.
|
|
OutSamples = CreateSignalArrayFromScalarValue(-INFINITE_FLOAT);
|
|
}
|
|
else if (SignalBufferLayout == SIGNAL_BUFFER_LAYOUT_PENUMBRA_INPUT_NSPP)
|
|
{
|
|
UNROLL_N(MAX_SIGNAL_BATCH_SIZE)
|
|
for (uint BatchSignalId = 0; BatchSignalId < MAX_SIGNAL_BATCH_SIZE; BatchSignalId++)
|
|
{
|
|
uint MultiplexId = BatchSignalId;
|
|
// TODO(Denoiser): feed the actual number of sample.
|
|
OutSamples.Array[MultiplexId].SampleCount = (RawSample[MultiplexId].g == DENOISER_INVALID_HIT_DISTANCE ? 0.0 : 1.0);
|
|
OutSamples.Array[MultiplexId].MissCount = OutSamples.Array[MultiplexId].SampleCount * RawSample[MultiplexId].r;
|
|
OutSamples.Array[MultiplexId].TransmissionDistance = OutSamples.Array[MultiplexId].SampleCount * RawSample[MultiplexId].a;
|
|
|
|
OutSampleFrequencies.Array[MultiplexId].ClosestHitDistance = RawSample[MultiplexId].g;
|
|
|
|
FLATTEN
|
|
if (OutSamples.Array[MultiplexId].SampleCount == 0)
|
|
{
|
|
OutSampleFrequencies.Array[MultiplexId].ClosestHitDistance = DENOISER_INVALID_HIT_DISTANCE;
|
|
}
|
|
else if (OutSamples.Array[MultiplexId].MissCount > 0.999)
|
|
{
|
|
OutSampleFrequencies.Array[MultiplexId].ClosestHitDistance = DENOISER_MISS_HIT_DISTANCE;
|
|
}
|
|
}
|
|
}
|
|
else if (SignalBufferLayout == SIGNAL_BUFFER_LAYOUT_PENUMBRA_HISTORY)
|
|
{
|
|
UNROLL_N(MAX_SIGNAL_BATCH_SIZE)
|
|
for (uint MultiplexId = 0; MultiplexId < MAX_SIGNAL_BATCH_SIZE; MultiplexId++)
|
|
{
|
|
float4 Channels = RawSample[MultiplexId].xyzw;
|
|
|
|
float SampleCount = bNormalizeSample ? (Channels.g > 0 ? 1 : 0) : (Channels.g);
|
|
|
|
OutSamples.Array[MultiplexId].MissCount = Channels.r * SampleCount;
|
|
OutSamples.Array[MultiplexId].SampleCount = SampleCount;
|
|
OutSamples.Array[MultiplexId].TransmissionDistance = Channels.a * SampleCount;
|
|
|
|
OutSampleFrequencies.Array[MultiplexId].WorldBluringRadius = Channels.b;
|
|
}
|
|
}
|
|
#endif
|
|
#if COMPILE_SIGNAL_COLOR_ARRAY >= 2 && SIGNAL_ARRAY_SIZE >= 2
|
|
else if (SignalBufferLayout == SIGNAL_BUFFER_LAYOUT_POLYCHROMATIC_PENUMBRA_HARMONIC_INPUT)
|
|
{
|
|
// The RGS output same weigth for diffuse and specular given it depends only on shading model id.
|
|
float Weight = RawSample[0].a;
|
|
|
|
if (bNormalizeSample)
|
|
{
|
|
Weight = Weight > 0.0 ? 1.0 : 0.0;
|
|
}
|
|
|
|
// Decode diffuse
|
|
{
|
|
const uint MultiplexId = 0;
|
|
|
|
OutSamples.Array[MultiplexId].SampleCount = Weight;
|
|
OutSamples.Array[MultiplexId].ColorArray[0] = RawSample[0].rgb * Weight;
|
|
OutSamples.Array[MultiplexId].ColorArray[1] = RawSample[1].rgb * Weight;
|
|
}
|
|
|
|
// Decode specular
|
|
{
|
|
const uint MultiplexId = 1;
|
|
|
|
OutSamples.Array[MultiplexId].SampleCount = Weight;
|
|
OutSamples.Array[MultiplexId].ColorArray[0] = RawSample[2].rgb * Weight;
|
|
OutSamples.Array[MultiplexId].ColorArray[1] = RawSample[3].rgb * Weight;
|
|
}
|
|
}
|
|
else if (SignalBufferLayout == SIGNAL_BUFFER_LAYOUT_POLYCHROMATIC_PENUMBRA_HARMONIC_RECONSTRUCTION)
|
|
{
|
|
// Decode diffuse
|
|
{
|
|
const uint MultiplexId = 0;
|
|
|
|
float Weight = RawSample[0].a;
|
|
if (bNormalizeSample)
|
|
{
|
|
Weight = Weight > 0.0 ? 1.0 : 0.0;
|
|
}
|
|
|
|
OutSamples.Array[MultiplexId].SampleCount = Weight;
|
|
OutSamples.Array[MultiplexId].ColorArray[0] = RawSample[0].rgb * Weight;
|
|
OutSamples.Array[MultiplexId].ColorArray[1] = RawSample[1].rgb * Weight;
|
|
}
|
|
|
|
// Decode specular
|
|
{
|
|
const uint MultiplexId = 1;
|
|
|
|
float Weight = RawSample[2].a;
|
|
if (bNormalizeSample)
|
|
{
|
|
Weight = Weight > 0.0 ? 1.0 : 0.0;
|
|
}
|
|
|
|
OutSamples.Array[MultiplexId].SampleCount = Weight;
|
|
OutSamples.Array[MultiplexId].ColorArray[0] = RawSample[2].rgb * Weight;
|
|
OutSamples.Array[MultiplexId].ColorArray[1] = RawSample[3].rgb * Weight;
|
|
}
|
|
}
|
|
#endif
|
|
#if COMPILE_SIGNAL_COLOR
|
|
else if (SignalBufferLayout == SIGNAL_BUFFER_LAYOUT_POLYCHROMATIC_PENUMBRA_HISTORY)
|
|
{
|
|
// Decode diffuse harmonic
|
|
{
|
|
const uint MultiplexId = 0;
|
|
|
|
float Weight = RawSample[0].a;
|
|
|
|
if (bNormalizeSample)
|
|
{
|
|
Weight = Weight > 0 ? 1 : 0;
|
|
}
|
|
|
|
OutSamples.Array[MultiplexId].SampleCount = Weight;
|
|
OutSamples.Array[MultiplexId].SceneColor.rgb = RawSample[0].rgb * Weight;
|
|
}
|
|
|
|
#if SIGNAL_ARRAY_SIZE >= 2
|
|
// Decode specular harmonic
|
|
{
|
|
const uint MultiplexId = 1;
|
|
|
|
float Weight = RawSample[1].a;
|
|
|
|
if (bNormalizeSample)
|
|
{
|
|
Weight = Weight > 0 ? 1 : 0;
|
|
}
|
|
|
|
OutSamples.Array[MultiplexId].SampleCount = Weight;
|
|
OutSamples.Array[MultiplexId].SceneColor.rgb = RawSample[1].rgb * Weight;
|
|
}
|
|
#endif
|
|
}
|
|
#endif
|
|
#if COMPILE_SIGNAL_COLOR
|
|
else if (SignalBufferLayout == SIGNAL_BUFFER_LAYOUT_REFLECTIONS_INPUT)
|
|
{
|
|
OutSamples.Array[0].SampleCount = RawSample[1].r == DENOISER_INVALID_CONFUSION_FACTOR ? 0 : 1;
|
|
OutSamples.Array[0].MissCount = RawSample[1].r == DENOISER_INVALID_CONFUSION_FACTOR ? 0 : (1 - RawSample[0].a);
|
|
OutSamples.Array[0].SceneColor = RawSample[0];
|
|
|
|
// max() because ray hit distance is < 0 when miss / not ray has been shot.
|
|
OutSampleFrequencies.Array[0].ConfusionFactor = RawSample[1].r;
|
|
}
|
|
else if (SignalBufferLayout == SIGNAL_BUFFER_LAYOUT_REFLECTIONS_HISTORY)
|
|
{
|
|
if (bNormalizeSample)
|
|
{
|
|
OutSamples.Array[0].SampleCount = RawSample[1].r > 0 ? 1 : 0;
|
|
}
|
|
else
|
|
{
|
|
OutSamples.Array[0].SampleCount = RawSample[1].r;
|
|
}
|
|
|
|
OutSamples.Array[0].MissCount = OutSamples.Array[0].SampleCount * (1 - RawSample[0].a);
|
|
OutSamples.Array[0].SceneColor = OutSamples.Array[0].SampleCount * RawSample[0];
|
|
|
|
OutSampleFrequencies.Array[0].ConfusionFactor = RawSample[1].g;
|
|
}
|
|
#endif
|
|
#if 1
|
|
else if (SignalBufferLayout == SIGNAL_BUFFER_LAYOUT_AO_INPUT)
|
|
{
|
|
OutSamples.Array[0].SampleCount = RawSample[1].r < 0 ? 0 : 1;
|
|
OutSamples.Array[0].MissCount = OutSamples.Array[0].SampleCount * RawSample[0].r;
|
|
|
|
OutSampleFrequencies.Array[0].WorldBluringRadius = RawSample[1].r;
|
|
}
|
|
else if (SignalBufferLayout == SIGNAL_BUFFER_LAYOUT_AO_REJECTION)
|
|
{
|
|
if (bNormalizeSample)
|
|
{
|
|
OutSamples.Array[0].SampleCount = RawSample[0].g > 0 ? 1 : 0;
|
|
OutSamples.Array[0].MissCount = RawSample[0].g > 0 ? RawSample[0].r : 0;
|
|
|
|
#if SIGNAL_ARRAY_SIZE >= 2
|
|
OutSamples.Array[1].SampleCount = RawSample[0].a > 0 ? 1 : 0;
|
|
OutSamples.Array[1].MissCount = RawSample[0].a > 0 ? RawSample[0].b : 0;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
OutSamples.Array[0].SampleCount = RawSample[0].g;
|
|
OutSamples.Array[0].MissCount = RawSample[0].g * RawSample[0].r;
|
|
|
|
#if SIGNAL_ARRAY_SIZE >= 2
|
|
OutSamples.Array[1].SampleCount = RawSample[0].a;
|
|
OutSamples.Array[1].MissCount = RawSample[0].a * RawSample[0].b;
|
|
#endif
|
|
}
|
|
}
|
|
else if (SignalBufferLayout == SIGNAL_BUFFER_LAYOUT_AO_HISTORY)
|
|
{
|
|
if (bNormalizeSample)
|
|
{
|
|
OutSamples.Array[0].SampleCount = RawSample[0].g > 0 ? 1 : 0;
|
|
OutSamples.Array[0].MissCount = RawSample[0].g > 0 ? RawSample[0].r : 0;
|
|
}
|
|
else
|
|
{
|
|
OutSamples.Array[0].SampleCount = RawSample[0].g;
|
|
OutSamples.Array[0].MissCount = RawSample[0].g * RawSample[0].r;
|
|
}
|
|
|
|
OutSampleFrequencies.Array[0].WorldBluringRadius = RawSample[0].b;
|
|
}
|
|
#endif
|
|
#if COMPILE_SIGNAL_COLOR
|
|
else if (SignalBufferLayout == SIGNAL_BUFFER_LAYOUT_DIFFUSE_INDIRECT_AND_AO_INPUT_NSPP)
|
|
{
|
|
OutSamples.Array[0].SampleCount = RawSample[1].g;
|
|
OutSamples.Array[0].MissCount = OutSamples.Array[0].SampleCount * (1 - RawSample[0].a);
|
|
OutSamples.Array[0].SceneColor = OutSamples.Array[0].SampleCount * RawSample[0];
|
|
|
|
OutSampleFrequencies.Array[0].ClosestHitDistance = ((RawSample[1].r == -1.0) ? 1.0e20 : RawSample[1].r);
|
|
}
|
|
else if (SignalBufferLayout == SIGNAL_BUFFER_LAYOUT_DIFFUSE_INDIRECT_AND_AO_RECONSTRUCTION)
|
|
{
|
|
if (bNormalizeSample)
|
|
{
|
|
OutSamples.Array[0].SampleCount = RawSample[1].r > 0 ? 1 : 0;
|
|
}
|
|
else
|
|
{
|
|
OutSamples.Array[0].SampleCount = RawSample[1].r;
|
|
}
|
|
|
|
OutSamples.Array[0].MissCount = OutSamples.Array[0].SampleCount * (1 - RawSample[0].a);
|
|
OutSamples.Array[0].SceneColor = OutSamples.Array[0].SampleCount * RawSample[0];
|
|
}
|
|
else if (SignalBufferLayout == SIGNAL_BUFFER_LAYOUT_DIFFUSE_INDIRECT_AND_AO_HISTORY)
|
|
{
|
|
if (bNormalizeSample)
|
|
{
|
|
OutSamples.Array[0].SampleCount = RawSample[1].r > 0 ? 1 : 0;
|
|
}
|
|
else
|
|
{
|
|
OutSamples.Array[0].SampleCount = RawSample[1].r;
|
|
}
|
|
|
|
OutSamples.Array[0].MissCount = OutSamples.Array[0].SampleCount * (1 - RawSample[0].a);
|
|
OutSamples.Array[0].SceneColor = OutSamples.Array[0].SampleCount * RawSample[0];
|
|
|
|
// Temporal analysis.
|
|
#if SIGNAL_ARRAY_SIZE >= 3
|
|
OutSamples.Array[1].SampleCount = OutSamples.Array[0].SampleCount;
|
|
OutSamples.Array[1].SceneColor.x = OutSamples.Array[1].SampleCount * RawSample[1].g;
|
|
OutSamples.Array[2].SampleCount = OutSamples.Array[0].SampleCount;
|
|
OutSamples.Array[2].SceneColor.x = OutSamples.Array[2].SampleCount * RawSample[1].b;
|
|
#endif
|
|
}
|
|
else if (SignalBufferLayout == SIGNAL_BUFFER_LAYOUT_SSGI_INPUT)
|
|
{
|
|
OutSamples.Array[0].SampleCount = RawSample[0].a;
|
|
OutSamples.Array[0].MissCount = OutSamples.Array[0].SampleCount * RawSample[1].r;
|
|
OutSamples.Array[0].SceneColor.rgb = OutSamples.Array[0].SampleCount * RawSample[0].rgb;
|
|
}
|
|
else if (SignalBufferLayout == SIGNAL_BUFFER_LAYOUT_SSGI_HISTORY_R11G11B10)
|
|
{
|
|
if (bNormalizeSample)
|
|
{
|
|
OutSamples.Array[0].SampleCount = RawSample[1].g > 0.0 ? 1.0 : 0.0;
|
|
}
|
|
else
|
|
{
|
|
OutSamples.Array[0].SampleCount = RawSample[1].g * 64.0;
|
|
}
|
|
OutSamples.Array[0].MissCount = OutSamples.Array[0].SampleCount * RawSample[1].r;
|
|
OutSamples.Array[0].SceneColor.rgb = OutSamples.Array[0].SampleCount * RawSample[0].rgb;
|
|
}
|
|
#endif
|
|
#if COMPILE_SIGNAL_COLOR_ARRAY >= 2
|
|
else if (SignalBufferLayout == SIGNAL_BUFFER_LAYOUT_DIFFUSE_PROBE_HIERARCHY_INPUT)
|
|
{
|
|
OutSamples.Array[0].SampleCount = 1;
|
|
OutSamples.Array[0].ColorArray[0].rgb = OutSamples.Array[0].SampleCount * RawSample[0].rgb;
|
|
OutSamples.Array[0].ColorArray[1].rgb = OutSamples.Array[0].SampleCount * RawSample[1].rgb;
|
|
}
|
|
else if (SignalBufferLayout == SIGNAL_BUFFER_LAYOUT_DIFFUSE_PROBE_HIERARCHY_HISTORY)
|
|
{
|
|
// Diffuse
|
|
if (bNormalizeSample)
|
|
{
|
|
OutSamples.Array[0].SampleCount = RawSample[2].r > 0.0 ? 1.0 : 0.0;
|
|
}
|
|
else
|
|
{
|
|
OutSamples.Array[0].SampleCount = RawSample[2].r * TARGETED_SAMPLE_COUNT;
|
|
}
|
|
OutSamples.Array[0].ColorArray[0].rgb = OutSamples.Array[0].SampleCount * RawSample[0].rgb;
|
|
OutSamples.Array[0].ColorArray[1].rgb = OutSamples.Array[0].SampleCount * RawSample[1].rgb;
|
|
}
|
|
#endif
|
|
#if COMPILE_SIGNAL_COLOR_SH
|
|
else if (SignalBufferLayout == SIGNAL_BUFFER_LAYOUT_LUMEN_DIFFUSE_INPUT)
|
|
{
|
|
DecodeLumenDiffuseLighting(RawSample[0], RawSample[1], /* out */ OutSamples.Array[0].ColorSH);
|
|
|
|
float SampleCount = 1.0; // TODO(Denoiser)
|
|
|
|
OutSamples.Array[0] = MulSignal(OutSamples.Array[0], SampleCount);
|
|
OutSamples.Array[0].SampleCount = SampleCount;
|
|
}
|
|
else if (SignalBufferLayout == SIGNAL_BUFFER_LAYOUT_LUMEN_DIFFUSE_HISTORY)
|
|
{
|
|
DecodeLumenDiffuseLighting(RawSample[0], RawSample[1], /* out */ OutSamples.Array[0].ColorSH);
|
|
|
|
float SampleCount = RawSample[0].a;
|
|
if (bNormalizeSample)
|
|
{
|
|
SampleCount = SampleCount > 0 ? 1 : 0;
|
|
}
|
|
else
|
|
{
|
|
SampleCount = RawSample[0].a;
|
|
}
|
|
|
|
OutSamples.Array[0] = MulSignal(OutSamples.Array[0], SampleCount);
|
|
OutSamples.Array[0].SampleCount = SampleCount;
|
|
}
|
|
#endif
|
|
} // DecodeMultiplexedSignalsFromFloat4()
|
|
|
|
void DecodeMultiplexedSignalsFromUint2(
|
|
const uint SignalBufferLayout,
|
|
const uint MultiplexedSampleId,
|
|
const bool bNormalizeSample,
|
|
uint2 RawSample[MAX_MULTIPLEXED_TEXTURES],
|
|
out FSSDSignalArray OutSamples,
|
|
out FSSDSignalFrequencyArray OutSampleFrequencies)
|
|
{
|
|
OutSamples = CreateSignalArrayFromScalarValue(0.0);
|
|
OutSampleFrequencies = CreateInvalidSignalFrequencyArray();
|
|
|
|
if (0)
|
|
{
|
|
|
|
}
|
|
else if (SignalBufferLayout == SIGNAL_BUFFER_LAYOUT_PENUMBRA_INJESTION_NSPP)
|
|
{
|
|
UNROLL_N(MAX_SIGNAL_BATCH_SIZE)
|
|
for (uint BatchSignalId = 0; BatchSignalId < MAX_SIGNAL_BATCH_SIZE; BatchSignalId++)
|
|
{
|
|
uint MultiplexId = BatchSignalId;
|
|
uint EncodedData = MultiplexId % 2 ? RawSample[MultiplexId / 2].g : RawSample[MultiplexId / 2].r;
|
|
|
|
float MissCountRatio = (EncodedData & 0xFF) / 255.0;
|
|
float TransmissionDistanceRatio = ((EncodedData >> 8) & 0xFF) / 255.0;
|
|
float WorldBluringRadius = f16tof32(EncodedData >> 16);
|
|
float SampleCount = (WorldBluringRadius == -2.0 ? 0.0 : 1.0);
|
|
|
|
float MissCount = SampleCount * MissCountRatio;
|
|
float TransmissionDistance = TransmissionDistanceRatio;
|
|
|
|
// TODO(Denoiser): feed the actual number of sample.
|
|
OutSamples.Array[MultiplexId].SampleCount = SampleCount;
|
|
OutSamples.Array[MultiplexId].MissCount = MissCount;
|
|
OutSamples.Array[MultiplexId].TransmissionDistance = TransmissionDistance;
|
|
|
|
OutSampleFrequencies.Array[MultiplexId].WorldBluringRadius = WorldBluringRadius;
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Decode input signal sample from raw float. */
|
|
void DecodeMultiplexedSignals(
|
|
const uint SignalBufferLayout,
|
|
const uint MultiplexedSampleId,
|
|
const bool bNormalizeSample,
|
|
FSSDCompressedMultiplexedSample CompressedSample,
|
|
out FSSDSignalArray OutSamples,
|
|
out FSSDSignalFrequencyArray OutSampleFrequencies)
|
|
#if CONFIG_SIGNAL_INPUT_TEXTURE_TYPE == SIGNAL_TEXTURE_TYPE_FLOAT4
|
|
{
|
|
DecodeMultiplexedSignalsFromFloat4(
|
|
SignalBufferLayout,
|
|
MultiplexedSampleId,
|
|
bNormalizeSample,
|
|
CompressedSample.VGPRArray,
|
|
/* out */ OutSamples,
|
|
/* out */ OutSampleFrequencies);
|
|
} // DecodeMultiplexedSignals()
|
|
#elif CONFIG_SIGNAL_INPUT_TEXTURE_TYPE == SIGNAL_TEXTURE_TYPE_UINT2
|
|
{
|
|
FSSDSignalArray MultiplexedSamples = CreateSignalArrayFromScalarValue(0.0);
|
|
DecodeMultiplexedSignalsFromUint2(
|
|
SignalBufferLayout,
|
|
MultiplexedSampleId,
|
|
bNormalizeSample,
|
|
CompressedSample.VGPRArray,
|
|
/* out */ OutSamples,
|
|
/* out */ OutSampleFrequencies);
|
|
} // DecodeMultiplexedSignals()
|
|
#endif
|
|
|
|
/** Encode output signal sample. */
|
|
void EncodeMultiplexedSignals(
|
|
const uint SignalBufferLayout, const uint MultiplexCount,
|
|
FSSDSignalSample Sample[SIGNAL_ARRAY_SIZE],
|
|
FSSDSignalFrequency SampleFrequency[SIGNAL_ARRAY_SIZE],
|
|
out FSSDOutputRawSample OutRawSample[MAX_MULTIPLEXED_TEXTURES],
|
|
out uint OutBufferCount)
|
|
#if CONFIG_SIGNAL_OUTPUT_TEXTURE_TYPE == SIGNAL_TEXTURE_TYPE_FLOAT4
|
|
{
|
|
// Init all raw samples.
|
|
UNROLL_N(MAX_MULTIPLEXED_TEXTURES)
|
|
for (uint i = 0; i < MAX_MULTIPLEXED_TEXTURES; i++)
|
|
OutRawSample[i] = 0;
|
|
|
|
// Number of buffer the signal get encoded onto <= MAX_MULTIPLEXED_TEXTURES.
|
|
OutBufferCount = 1;
|
|
|
|
if (0)
|
|
{
|
|
// NOP
|
|
}
|
|
#if 1
|
|
else if (SignalBufferLayout == SIGNAL_BUFFER_LAYOUT_PENUMBRA_HISTORY)
|
|
{
|
|
UNROLL
|
|
for (uint MultiplexId = 0; MultiplexId < MultiplexCount; MultiplexId++)
|
|
{
|
|
float NormalizationFactor = SafeRcp(Sample[MultiplexId].SampleCount);
|
|
|
|
float NormalizedTransmissionDistance = Sample[MultiplexId].TransmissionDistance * NormalizationFactor;
|
|
|
|
OutRawSample[MultiplexId] = float4(
|
|
Sample[MultiplexId].MissCount * NormalizationFactor,
|
|
Sample[MultiplexId].SampleCount,
|
|
SampleFrequency[MultiplexId].WorldBluringRadius,
|
|
NormalizedTransmissionDistance);
|
|
}
|
|
OutBufferCount = MultiplexCount;
|
|
}
|
|
#endif
|
|
#if COMPILE_SIGNAL_COLOR_ARRAY >= 2 && SIGNAL_ARRAY_SIZE >= 2
|
|
else if (SignalBufferLayout == SIGNAL_BUFFER_LAYOUT_POLYCHROMATIC_PENUMBRA_HARMONIC_RECONSTRUCTION)
|
|
{
|
|
// diffuse harmonic
|
|
{
|
|
const uint MultiplexId = 0;
|
|
|
|
float NormalizationFactor = SafeRcp(Sample[MultiplexId].SampleCount);
|
|
|
|
OutRawSample[0].rgb = Sample[MultiplexId].ColorArray[0] * NormalizationFactor;
|
|
OutRawSample[0].a = Sample[MultiplexId].SampleCount;
|
|
OutRawSample[1].rgb = Sample[MultiplexId].ColorArray[1] * NormalizationFactor;
|
|
}
|
|
|
|
// specular harmonic
|
|
{
|
|
const uint MultiplexId = 1;
|
|
|
|
float NormalizationFactor = SafeRcp(Sample[1].SampleCount);
|
|
|
|
OutRawSample[2].rgb = Sample[MultiplexId].ColorArray[0] * NormalizationFactor;
|
|
OutRawSample[2].a = Sample[MultiplexId].SampleCount;
|
|
OutRawSample[3].rgb = Sample[MultiplexId].ColorArray[1] * NormalizationFactor;
|
|
}
|
|
|
|
OutBufferCount = 4;
|
|
}
|
|
#endif
|
|
#if COMPILE_SIGNAL_COLOR
|
|
else if (SignalBufferLayout == SIGNAL_BUFFER_LAYOUT_POLYCHROMATIC_PENUMBRA_HISTORY)
|
|
{
|
|
// Encode diffuse harmonic
|
|
{
|
|
const uint MultiplexId = 0;
|
|
|
|
float NormalizationFactor = SafeRcp(Sample[MultiplexId].SampleCount);
|
|
|
|
OutRawSample[0].rgb = ClampColorForEncoding(Sample[MultiplexId].SceneColor.rgb * NormalizationFactor);
|
|
OutRawSample[0].a = Sample[MultiplexId].SampleCount;
|
|
}
|
|
|
|
// Encode specular harmonic
|
|
#if SIGNAL_ARRAY_SIZE >= 2
|
|
{
|
|
const uint MultiplexId = 1;
|
|
|
|
float NormalizationFactor = SafeRcp(Sample[MultiplexId].SampleCount);
|
|
|
|
OutRawSample[1].rgb = ClampColorForEncoding(Sample[MultiplexId].SceneColor.rgb * NormalizationFactor);
|
|
OutRawSample[1].a = Sample[MultiplexId].SampleCount;
|
|
}
|
|
#endif
|
|
|
|
OutBufferCount = 2;
|
|
}
|
|
#endif
|
|
#if COMPILE_SIGNAL_COLOR
|
|
else if (SignalBufferLayout == SIGNAL_BUFFER_LAYOUT_REFLECTIONS_HISTORY)
|
|
{
|
|
float NormalizationFactor = SafeRcp(Sample[0].SampleCount);
|
|
|
|
// Outputs scene color to be compatible with a SSR output.
|
|
OutRawSample[0] = ClampColorForEncoding(Sample[0].SceneColor * NormalizationFactor);
|
|
OutRawSample[1].r = Sample[0].SampleCount;
|
|
OutRawSample[1].g = SampleFrequency[0].ConfusionFactor;
|
|
OutBufferCount = 2;
|
|
}
|
|
#endif
|
|
#if 1
|
|
else if (SignalBufferLayout == SIGNAL_BUFFER_LAYOUT_AO_REJECTION)
|
|
{
|
|
// Outputs number of ray miss in red to be compatible as a SSAO output.
|
|
OutRawSample[0].r = Sample[0].SampleCount > 0 ? Sample[0].MissCount / Sample[0].SampleCount : 1.0;
|
|
OutRawSample[0].g = Sample[0].SampleCount;
|
|
|
|
#if SIGNAL_ARRAY_SIZE >= 2
|
|
if (MultiplexCount == 2)
|
|
{
|
|
OutRawSample[0].b = Sample[1].SampleCount > 0 ? Sample[1].MissCount / Sample[1].SampleCount : 1.0;
|
|
OutRawSample[0].a = Sample[1].SampleCount;
|
|
}
|
|
#endif
|
|
}
|
|
else if (SignalBufferLayout == SIGNAL_BUFFER_LAYOUT_AO_HISTORY)
|
|
{
|
|
// Outputs number of ray miss in red to be compatible as a SSAO output.
|
|
OutRawSample[0].r = Sample[0].SampleCount > 0 ? Sample[0].MissCount / Sample[0].SampleCount : 1.0;
|
|
OutRawSample[0].g = Sample[0].SampleCount;
|
|
OutRawSample[0].b = SampleFrequency[0].WorldBluringRadius;
|
|
}
|
|
#endif
|
|
#if COMPILE_SIGNAL_COLOR
|
|
else if (SignalBufferLayout == SIGNAL_BUFFER_LAYOUT_DIFFUSE_INDIRECT_AND_AO_RECONSTRUCTION)
|
|
{
|
|
float NormalizationFactor = SafeRcp(Sample[0].SampleCount);
|
|
|
|
OutRawSample[0] = ClampColorForEncoding(Sample[0].SceneColor * NormalizationFactor);
|
|
OutRawSample[1].r = Sample[0].SampleCount;
|
|
OutBufferCount = 2;
|
|
}
|
|
else if (SignalBufferLayout == SIGNAL_BUFFER_LAYOUT_DIFFUSE_INDIRECT_AND_AO_HISTORY)
|
|
{
|
|
float NormalizationFactor = SafeRcp(Sample[0].SampleCount);
|
|
|
|
OutRawSample[0] = ClampColorForEncoding(Sample[0].SceneColor * NormalizationFactor);
|
|
OutRawSample[1].r = Sample[0].SampleCount;
|
|
OutBufferCount = 2;
|
|
|
|
// Temporal analysis.
|
|
#if SIGNAL_ARRAY_SIZE >= 3
|
|
if (MultiplexCount == 3)
|
|
{
|
|
OutRawSample[1].g = Sample[1].SceneColor.x * NormalizationFactor;
|
|
OutRawSample[1].b = Sample[2].SceneColor.x * NormalizationFactor;
|
|
}
|
|
#endif
|
|
}
|
|
else if (SignalBufferLayout == SIGNAL_BUFFER_LAYOUT_SSGI_HISTORY_R11G11B10)
|
|
{
|
|
float NormalizationFactor = SafeRcp(Sample[0].SampleCount);
|
|
|
|
OutRawSample[0].rgb = ClampColorForEncoding(Sample[0].SceneColor * NormalizationFactor).rgb;
|
|
OutRawSample[1].g = saturate(Sample[0].SampleCount * rcp(64.0));
|
|
OutRawSample[1].r = Sample[0].MissCount * NormalizationFactor;
|
|
OutBufferCount = 2;
|
|
}
|
|
#endif
|
|
#if COMPILE_SIGNAL_COLOR_ARRAY >= 2
|
|
else if (SignalBufferLayout == SIGNAL_BUFFER_LAYOUT_DIFFUSE_PROBE_HIERARCHY_HISTORY)
|
|
{
|
|
float NormalizationFactor = SafeRcp(Sample[0].SampleCount);
|
|
OutRawSample[0].rgb = ClampColorForEncoding(Sample[0].ColorArray[0] * NormalizationFactor);
|
|
OutRawSample[1].rgb = ClampColorForEncoding(Sample[0].ColorArray[1] * NormalizationFactor);
|
|
OutRawSample[2].r = saturate(Sample[0].SampleCount * rcp(TARGETED_SAMPLE_COUNT));
|
|
|
|
OutBufferCount = 3;
|
|
}
|
|
#endif
|
|
#if COMPILE_SIGNAL_COLOR_SH
|
|
else if (SignalBufferLayout == SIGNAL_BUFFER_LAYOUT_LUMEN_DIFFUSE_HISTORY)
|
|
{
|
|
FSSDSignalSample NormalizedSample = NormalizeToOneSample(Sample[0]);
|
|
//FSSDSignalSample NormalizedSample = (Sample[0]);
|
|
|
|
EncodeLumenDiffuseLighting(NormalizedSample.ColorSH, /* out */ OutRawSample[0], /* out */ OutRawSample[1]);
|
|
OutRawSample[0].a = Sample[0].SampleCount;
|
|
OutBufferCount = 2;
|
|
}
|
|
#endif
|
|
} // EncodeMultiplexedSignals()
|
|
#elif CONFIG_SIGNAL_OUTPUT_TEXTURE_TYPE == SIGNAL_TEXTURE_TYPE_UINT2
|
|
{
|
|
// Init all raw samples.
|
|
UNROLL_N(MAX_MULTIPLEXED_TEXTURES)
|
|
for (uint i = 0; i < MAX_MULTIPLEXED_TEXTURES; i++)
|
|
OutRawSample[i] = 0;
|
|
|
|
// Number of buffer the signal get encoded onto <= MAX_MULTIPLEXED_TEXTURES.
|
|
OutBufferCount = 1;
|
|
|
|
if (0)
|
|
{
|
|
}
|
|
else if (SignalBufferLayout == SIGNAL_BUFFER_LAYOUT_PENUMBRA_INJESTION_NSPP)
|
|
{
|
|
UNROLL
|
|
for (uint MultiplexId = 0; MultiplexId < MultiplexCount; MultiplexId++)
|
|
{
|
|
float MissCount = Sample[MultiplexId].MissCount;
|
|
float WorldBluringRadius = SampleFrequency[MultiplexId].WorldBluringRadius;
|
|
float TransmissionDistance = Sample[MultiplexId].TransmissionDistance;
|
|
float SampleCount = Sample[MultiplexId].SampleCount;
|
|
if (SampleCount == 0)
|
|
{
|
|
WorldBluringRadius = -2.0;
|
|
}
|
|
|
|
float MissCountRatio = MissCount * SafeRcp(SampleCount);
|
|
float TransmissionDistanceRatio = TransmissionDistance;
|
|
|
|
uint EncodedData = MissCountRatio * 255;
|
|
EncodedData |= (uint(TransmissionDistanceRatio * 255) << 8);
|
|
EncodedData |= (f32tof16(WorldBluringRadius) << 16);
|
|
|
|
if (MultiplexId % 2)
|
|
{
|
|
OutRawSample[MultiplexId / 2].g = EncodedData;
|
|
}
|
|
else
|
|
{
|
|
OutRawSample[MultiplexId / 2].r = EncodedData;
|
|
}
|
|
}
|
|
OutBufferCount = (MultiplexCount + 1) / 2;
|
|
}
|
|
#if COMPILE_SIGNAL_COLOR_SH
|
|
else if (SignalBufferLayout == SIGNAL_BUFFER_LAYOUT_DIFFUSE_INDIRECT_HARMONIC)
|
|
{
|
|
const uint EncodeOptions = (CONFIG_ENCODING_CLAMP_COLOR ? SSD_ENCODE_CLAMP_COLOR : 0) | SSD_ENCODE_NORMALIZE;
|
|
|
|
EncodeDiffuseSphericalHarmonicTexel(
|
|
Sample[0].SampleCount,
|
|
Sample[0].MissCount,
|
|
Sample[0].ColorSH,
|
|
EncodeOptions,
|
|
/* out */ OutRawSample);
|
|
|
|
OutBufferCount = 4;
|
|
}
|
|
#endif
|
|
} // EncodeMultiplexedSignals()
|
|
#else
|
|
#error Unimplemented.
|
|
#endif
|
|
|
|
|
|
/** Sample the raw of multiple input signals that have been multiplexed. */
|
|
FSSDCompressedMultiplexedSample SampleCompressedMultiplexedSignals(
|
|
FSSDTexture2D SignalBuffer0, FSSDTexture2D SignalBuffer1, FSSDTexture2D SignalBuffer2, FSSDTexture2D SignalBuffer3,
|
|
SamplerState Sampler, float2 UV, uint2 PixelCoord)
|
|
{
|
|
FSSDCompressedMultiplexedSample CompressedSample;
|
|
|
|
// Isolate the texture fetches to force lattency hiding, to outsmart compilers that tries to
|
|
// discard some of the texture fetches for instance when SampleCount == 0 in another texture.
|
|
ISOLATE
|
|
{
|
|
#if CONFIG_SIGNAL_INPUT_TEXTURE_TYPE == SIGNAL_TEXTURE_TYPE_FLOAT4
|
|
{
|
|
CompressedSample.VGPRArray[0] = SignalBuffer0.SampleLevel(Sampler, UV, 0.0);
|
|
CompressedSample.VGPRArray[1] = SignalBuffer1.SampleLevel(Sampler, UV, 0.0);
|
|
CompressedSample.VGPRArray[2] = SignalBuffer2.SampleLevel(Sampler, UV, 0.0);
|
|
CompressedSample.VGPRArray[3] = SignalBuffer3.SampleLevel(Sampler, UV, 0.0);
|
|
}
|
|
#elif CONFIG_SIGNAL_INPUT_TEXTURE_TYPE >= SIGNAL_TEXTURE_TYPE_UINT1 && CONFIG_SIGNAL_INPUT_TEXTURE_TYPE <= SIGNAL_TEXTURE_TYPE_UINT4
|
|
{
|
|
// TODO(Denoiser): Exposed the int3 instead as function parameter.
|
|
int3 Coord = int3(PixelCoord, 0);
|
|
CompressedSample.VGPRArray[0] = SignalBuffer0.Load(Coord);
|
|
CompressedSample.VGPRArray[1] = SignalBuffer1.Load(Coord);
|
|
CompressedSample.VGPRArray[2] = SignalBuffer2.Load(Coord);
|
|
CompressedSample.VGPRArray[3] = SignalBuffer3.Load(Coord);
|
|
}
|
|
#else
|
|
#error Unimplemented.
|
|
#endif
|
|
}
|
|
|
|
return CompressedSample;
|
|
}
|
|
|
|
|
|
/** Sample multiple input signals that have been multiplexed. */
|
|
void SampleMultiplexedSignals( // TODO
|
|
FSSDTexture2D SignalBuffer0, FSSDTexture2D SignalBuffer1, FSSDTexture2D SignalBuffer2, FSSDTexture2D SignalBuffer3,
|
|
SamplerState Sampler,
|
|
const uint SignalBufferLayout, const uint MultiplexedSampleId,
|
|
const bool bNormalizeSample,
|
|
float2 UV,
|
|
out FSSDSignalArray OutMultiplexedSamples,
|
|
out FSSDSignalFrequencyArray OutMultiplexedFrequencies)
|
|
{
|
|
uint2 PixelCoord = BufferUVToBufferPixelCoord(UV);
|
|
|
|
FSSDCompressedMultiplexedSample CompressedSample = SampleCompressedMultiplexedSignals(
|
|
SignalBuffer0, SignalBuffer1, SignalBuffer2, SignalBuffer3,
|
|
Sampler, UV, PixelCoord);
|
|
|
|
DecodeMultiplexedSignals(
|
|
SignalBufferLayout, MultiplexedSampleId, bNormalizeSample, CompressedSample,
|
|
/* out */ OutMultiplexedSamples,
|
|
/* out */ OutMultiplexedFrequencies);
|
|
}
|
|
|
|
|
|
/** Outputs multiplexed signal. */
|
|
void OutputMultiplexedSignal(
|
|
FSSDRWTexture2D OutputSignalBuffer0,
|
|
FSSDRWTexture2D OutputSignalBuffer1,
|
|
FSSDRWTexture2D OutputSignalBuffer2,
|
|
FSSDRWTexture2D OutputSignalBuffer3,
|
|
const uint SignalBufferLayout, const uint MultiplexCount,
|
|
const uint2 PixelPosition,
|
|
FSSDSignalArray MultiplexedSamples,
|
|
FSSDSignalFrequencyArray MultiplexedFrequencies)
|
|
{
|
|
// Encode the output signal.
|
|
FSSDOutputRawSample RawSample[MAX_MULTIPLEXED_TEXTURES];
|
|
uint BufferCount;
|
|
EncodeMultiplexedSignals(
|
|
SignalBufferLayout, MultiplexCount,
|
|
MultiplexedSamples.Array,
|
|
MultiplexedFrequencies.Array,
|
|
/* out */ RawSample, /* out */ BufferCount);
|
|
|
|
// Output the raw encoded sample according to number of RT they requires.
|
|
if (BufferCount >= 1)
|
|
OutputSignalBuffer0[PixelPosition] = RawSample[0];
|
|
if (BufferCount >= 2)
|
|
OutputSignalBuffer1[PixelPosition] = RawSample[1];
|
|
if (BufferCount >= 3)
|
|
OutputSignalBuffer2[PixelPosition] = RawSample[2];
|
|
if (BufferCount >= 4)
|
|
OutputSignalBuffer3[PixelPosition] = RawSample[3];
|
|
}
|