Files
UnrealEngine/Engine/Shaders/Private/TemporalSuperResolution/TSRVisualize.usf
2025-05-18 13:04:45 +08:00

593 lines
22 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
#include "TSRColorSpace.ush"
#include "TSRReprojectionField.ush"
#if TSR_SUPPORT_LENS_DISTORTION
#include "../LensDistortion.ush"
#endif
//------------------------------------------------------- CONFIG
#define TILE_SIZE 8
//------------------------------------------------------- CONSTS
static tsr_half3 kWhite = tsr_half3(0.33, 0.33, 0.33);
static tsr_half3 kYellow = tsr_half3(1.00, 1.00, 0.10);
static tsr_half3 kRed = tsr_half3(1.00, 0.10, 0.10);
static tsr_half3 kOrange = tsr_half3(1.00, 0.75, 0.10);
static tsr_half3 kGreen = tsr_half3(0.10, 1.00, 0.10);
static tsr_half3 kBlue = tsr_half3(0.10, 0.10, 1.00);
static tsr_half3 kCyan = tsr_half3(0.10, 1.00, 1.00);
static tsr_half3 kPink = tsr_half3(1.00, 0.10, 0.50);
//------------------------------------------------------- PARAMETERS
FScreenTransform OutputPixelPosToScreenPos;
FScreenTransform ScreenPosToHistoryUV;
FScreenTransform ScreenPosToInputPixelPos;
FScreenTransform ScreenPosToInputUV;
FScreenTransform ScreenPosToMoireHistoryUV;
float2 MoireHistoryUVBilinearMin;
float2 MoireHistoryUVBilinearMax;
float4x4 ClipToResurrectionClip;
uint2 OutputViewRectMin;
uint2 OutputViewRectMax;
uint VisualizeId;
uint bCanResurrectHistory;
uint bCanSpatialAntiAlias;
uint bReprojectionField;
float MaxHistorySampleCount;
float OutputToHistoryResolutionFractionSquare;
float FlickeringFramePeriod;
Texture2D<float2> PrevDistortingDisplacementTexture;
Texture2D<float2> ResurrectedDistortingDisplacementTexture;
Texture2D<float2> UndistortingDisplacementTexture;
Texture2D<tsr_half3> InputTexture;
Texture2D<tsr_half> InputMoireLumaTexture;
Texture2D<tsr_half4> InputSceneTranslucencyTexture;
Texture2D<tsr_half3> SceneColorTexture;
Texture2D<float2> ClosestDepthTexture;
Texture2D<uint> ReprojectionBoundaryTexture;
Texture2D<uint> ReprojectionJacobianTexture;
Texture2D<uint> ReprojectionVectorTexture;
Texture2D<tsr_ushort> IsMovingMaskTexture;
Texture2D<tsr_ushort> ThinGeometryTexture;
Texture2D<tsr_half2> DecimateMaskTexture;
Texture2D<tsr_half4> HistoryRejectionTexture;
Texture2D<tsr_half4> MoireHistoryTexture;
Texture2D<tsr_ushort> AntiAliasMaskTexture;
Texture2D<tsr_half4> HistoryMetadataTexture;
Texture2D<tsr_half3> ResurrectedHistoryColorTexture;
RWTexture2D<tsr_half4> Output;
//------------------------------------------------------- DEBUG
static float4 Debug;
//------------------------------------------------------- FUNCTION
#if !TSR_SUPPORT_LENS_DISTORTION
float2 ApplyLensDistortionOnScreenPos(Texture2D<float2> DisplacementTexture, float2 DestScreenPos)
{
return DestScreenPos;
}
#endif
tsr_half3 GrayScaleColor(tsr_half3 SceneColor)
{
tsr_half3 C = SceneColor;
C.rgb = dot(tsr_half(0.3333).xxx, SceneColor.rgb);
return C;
}
struct FContext
{
tsr_short2 OutputPixelPos;
float2 ScreenPos;
float2 InputUV;
tsr_short2 InputPixelPos;
};
tsr_half3 SampleTSROutputColor(FContext Ctx)
{
return SceneColorTexture[Ctx.OutputPixelPos];
}
tsr_half3 SampleTSROutputGray(FContext Ctx)
{
return GrayScaleColor(SceneColorTexture[Ctx.OutputPixelPos]);
}
struct FReprojectionFieldSample
{
bool bIsOffScreen;
bool bIsFullDilate;
bool bAntiAliasReprojectionField;
tsr_short2 Offset;
tsr_half2 Boundary;
float2 Vector;
float2 PrevScreenPos;
tsr_half2x2 Jacobian;
};
FReprojectionFieldSample SampleReprojectionField(FContext Ctx)
{
FReprojectionFieldSample Reprojection;
uint EncodedReprojectionBoundary = ReprojectionBoundaryTexture[Ctx.InputPixelPos];
Reprojection.Offset = DecodeReprojectionOffset(EncodedReprojectionBoundary);
Reprojection.Boundary = DecodeReprojectionBoundary(EncodedReprojectionBoundary);
Reprojection.bIsFullDilate = all(Reprojection.Boundary == kFullDilateBoundary);
Reprojection.bAntiAliasReprojectionField = any(Reprojection.Offset != tsr_short(0)) && !Reprojection.bIsFullDilate;
uint EncodedReprojectionVector = ReprojectionVectorTexture[Ctx.InputPixelPos + Reprojection.Offset];
uint EncodedReprojectionJacobian = ReprojectionJacobianTexture[Ctx.InputPixelPos + Reprojection.Offset];
Reprojection.Vector = DecodeReprojectionVector(EncodedReprojectionVector);
Reprojection.Jacobian = DecodeReprojectionJacobian(EncodedReprojectionJacobian);
Reprojection.PrevScreenPos = Ctx.ScreenPos - Reprojection.Vector;
// Detect whether the history reprojection is successful
bool2 bIsOffScreenLocal;
bool2 bIsDisoccluded;
IsOffScreenOrDisoccluded(
bCameraCut,
dpv_interleave_mono_registers(Reprojection.PrevScreenPos),
/* bIsParallaxRejected = */ false,
/* out */ bIsOffScreenLocal,
/* out */ bIsDisoccluded);
Reprojection.bIsOffScreen = bIsOffScreenLocal[0];
return Reprojection;
}
struct FDecimateMaskSample
{
bool bIsOffScreen;
bool bIsParallaxDisocclusion;
bool bIsDisoccluded;
bool bHasPixelAnimation;
bool bReprojectionHollFill;
};
FDecimateMaskSample SampleDecimateMask(FContext Ctx)
{
FDecimateMaskSample Decimate;
tsr_half2 DecimateMask = DecimateMaskTexture[Ctx.InputPixelPos];
tsr_ushort BitMask = tsr_ushort(DecimateMask.r * tsr_half(255.0));
Decimate.bIsOffScreen = (BitMask & tsr_ushort(0x1)) != tsr_ushort(0);
Decimate.bIsParallaxDisocclusion = (BitMask & tsr_ushort(0x2)) != tsr_ushort(0);
Decimate.bIsDisoccluded = (BitMask & tsr_ushort(0x3)) != tsr_ushort(0);
Decimate.bHasPixelAnimation = (BitMask & tsr_ushort(0x4)) != tsr_ushort(0);
Decimate.bReprojectionHollFill = (BitMask & tsr_ushort(0x8)) != tsr_ushort(0);
return Decimate;
}
//------------------------------------------------------- ENTRY POINT
tsr_half3 DisplayHistorySampleCount(FContext Ctx)
{
float2 HistoryUV = ApplyScreenTransform(Ctx.ScreenPos, ScreenPosToHistoryUV);
HistoryUV = fastClamp(HistoryUV, HistoryInfo_UVViewportBilinearMin, HistoryInfo_UVViewportBilinearMax);
tsr_half Validity = HistoryMetadataTexture.SampleLevel(GlobalBilinearClampedSampler, HistoryUV, 0).x;
#if 0
tsr_half SampleCount = Validity * MaxHistorySampleCount;
const tsr_half Threshold = tsr_half(1.0) + OutputToHistoryResolutionFractionSquare;
if (SampleCount > Threshold)
{
return SampleTSROutputGray(Ctx) * lerp(kOrange, kGreen, saturate((SampleCount - Threshold) / (MaxHistorySampleCount - Threshold)));
}
return SampleTSROutputGray(Ctx) * lerp(kRed, kOrange, saturate((SampleCount - 1.0) / (Threshold - 1.0)));
#else
return SampleTSROutputGray(Ctx) * lerp(kRed, kGreen, saturate(Validity));
#endif
}
tsr_half3 DisplayThinGeometry(FContext Ctx)
{
tsr_ushort EncodedThinGeometryFlag = ThinGeometryTexture[Ctx.InputPixelPos];
bool bClusterHole = bool(EncodedThinGeometryFlag & 0x1u);
tsr_half HistoryRelaxation = saturate(tsr_half(EncodedThinGeometryFlag >> 0x1u)*rcp(tsr_half(127.0)));
bool bUseV2Rectifier = HistoryRelaxation > tsr_half(1.0 / 127.0);
tsr_half3 Color = select(bClusterHole, kWhite, kRed);
Color = lerp(kWhite, Color, saturate((HistoryRelaxation - 0.0) * 2.0));
Color = lerp(Color, kGreen, saturate(tsr_half(select(bClusterHole && bUseV2Rectifier, 0.5f, 0.0f))));
Color = lerp(Color, kYellow, saturate(tsr_half(select(bClusterHole && !bUseV2Rectifier, 0.5f, 0.0f))));
Color = select(bCameraCut == 0, Color, kPink);
return SampleTSROutputColor(Ctx) * Color;
}
tsr_half3 DisplayHistoryRejection(FContext Ctx)
{
tsr_half LowFrequencyRejection = HistoryRejectionTexture.SampleLevel(GlobalPointClampedSampler, Ctx.InputUV, 0).r;
tsr_half3 Color = kWhite;
Color = lerp(kOrange, Color, saturate((LowFrequencyRejection - 0.5) * 2.0));
Color = lerp(kRed, Color, saturate((LowFrequencyRejection - 0.0) * 2.0));
Color = select(bCameraCut == 0, Color, kPink);
return SampleTSROutputGray(Ctx) * Color;
}
tsr_half3 DisplayHistoryClamp(FContext Ctx)
{
tsr_half LowFrequencyClamp = HistoryRejectionTexture.SampleLevel(GlobalPointClampedSampler, Ctx.InputUV, 0).g;
tsr_half3 Color = kWhite;
Color = lerp(kOrange, Color, saturate((LowFrequencyClamp - 0.5) * 2.0));
Color = lerp(kRed, Color, saturate((LowFrequencyClamp - 0.0) * 2.0));
Color = select(bCameraCut == 0, Color, kPink);
return SampleTSROutputGray(Ctx) * Color;
}
tsr_half3 DisplayParallaxDisocclusionMask(FContext Ctx)
{
FDecimateMaskSample Decimate = SampleDecimateMask(Ctx);
tsr_half3 Color;
Color = select(Decimate.bReprojectionHollFill && Decimate.bIsParallaxDisocclusion, kOrange, kWhite);
Color = select(!Decimate.bReprojectionHollFill && Decimate.bIsParallaxDisocclusion, kRed, Color);
Color = select(Decimate.bIsOffScreen, kPink, Color);
return SampleTSROutputGray(Ctx) * Color;
}
tsr_half3 DisplayResurrectionMask(FContext Ctx)
{
if (!bCanResurrectHistory)
{
return SampleTSROutputGray(Ctx) * kPink;
}
tsr_half LowFrequencyRejection = HistoryRejectionTexture.SampleLevel(GlobalPointClampedSampler, Ctx.InputUV, 0).r;
float ClosestDeviceZ = ClosestDepthTexture.SampleLevel(GlobalPointClampedSampler, Ctx.InputUV, 0).g;
bool ResurrectionMask = (tsr_ushort(HistoryRejectionTexture.SampleLevel(GlobalPointClampedSampler, Ctx.InputUV, 0).a * tsr_half(255.0)) & tsr_ushort(0x2)) != tsr_ushort(0x0);
float4 ThisClip = float4(ApplyLensDistortionOnScreenPos(UndistortingDisplacementTexture, Ctx.ScreenPos), ClosestDeviceZ, 1);
float4 ResurrectionClip = mul(ThisClip, ClipToResurrectionClip);
float2 ResurrectionScreen = ApplyLensDistortionOnScreenPos(ResurrectedDistortingDisplacementTexture, ResurrectionClip.xy / ResurrectionClip.w);
tsr_half3 Color = kWhite;
Color = select(any(ResurrectionScreen != clamp(ResurrectionScreen, -1.0, 1.0)), kPink, Color);
Color = select(ResurrectionMask, lerp(kRed, kGreen, LowFrequencyRejection), Color);
return SampleTSROutputGray(Ctx) * Color;
}
tsr_half3 DisplayResurrectedColor(FContext Ctx)
{
if (!bCanResurrectHistory)
{
return SampleTSROutputGray(Ctx) * kPink;
}
tsr_half LowFrequencyRejection = HistoryRejectionTexture.SampleLevel(GlobalPointClampedSampler, Ctx.InputUV, 0).r;
float ClosestDeviceZ = ClosestDepthTexture.SampleLevel(GlobalPointClampedSampler, Ctx.InputUV, 0).g;
bool ResurrectionMask = (tsr_ushort(HistoryRejectionTexture.SampleLevel(GlobalPointClampedSampler, Ctx.InputUV, 0).a * tsr_half(255.0)) & tsr_ushort(0x2)) != tsr_ushort(0x0);
float4 ThisClip = float4(ApplyLensDistortionOnScreenPos(UndistortingDisplacementTexture, Ctx.ScreenPos), ClosestDeviceZ, 1);
float4 ResurrectionClip = mul(ThisClip, ClipToResurrectionClip);
float2 ResurrectionScreen = ApplyLensDistortionOnScreenPos(ResurrectedDistortingDisplacementTexture, ResurrectionClip.xy / ResurrectionClip.w);
float2 KernelHistoryBufferUV = ApplyScreenTransform(ResurrectionScreen, ScreenPosToPrevHistoryBufferUV);
KernelHistoryBufferUV = fastClamp(KernelHistoryBufferUV, PrevHistoryInfo_UVViewportBilinearMin, PrevHistoryInfo_UVViewportBilinearMax);
tsr_half3 ResurrectedColor = ResurrectedHistoryColorTexture.SampleLevel(GlobalBilinearClampedSampler, KernelHistoryBufferUV, 0) * tsr_half(ResurrectionPreExposureCorrection);
tsr_half3 Color = kWhite;
Color = select(any(ResurrectionScreen != clamp(ResurrectionScreen, -1.0, 1.0)), kPink, Color);
Color = select(ResurrectionMask, lerp(kRed, kGreen, LowFrequencyRejection), Color);
return GrayScaleColor(ResurrectedColor) * Color;
}
tsr_half3 DisplaySpatialAntiAliasingMask(FContext Ctx)
{
bool bSpatialAntiAlias = AntiAliasMaskTexture[Ctx.InputPixelPos] != tsr_ushort(0x0);
if (!bCanSpatialAntiAlias)
{
return SampleTSROutputGray(Ctx) * kPink;
}
return SampleTSROutputGray(Ctx) * select(bSpatialAntiAlias, kGreen, kWhite);
}
tsr_half3 DisplayAntiFlickering(FContext Ctx)
{
if (FlickeringFramePeriod == 0.0)
{
return SampleTSROutputGray(Ctx) * kPink;
}
const tsr_half BlendFinal = tsr_half(0.05);
const tsr_half MoireEncodingError = tsr_half(rcp(127.0));
const tsr_half MaxPrevTotalVariationCount = tsr_half(20.0);
// Compute the threshold at which the variation count should quick in
const tsr_half TotalVariationCountThreshold = tsr_half(1.0 / (1.0 - pow(1.0 - BlendFinal, tsr_half(FlickeringFramePeriod))));
// Texture coordinate
float2 MoireHistoryUV = ApplyScreenTransform(ApplyLensDistortionOnScreenPos(UndistortingDisplacementTexture, Ctx.ScreenPos), ScreenPosToMoireHistoryUV);
MoireHistoryUV = fastClamp(MoireHistoryUV, MoireHistoryUVBilinearMin, MoireHistoryUVBilinearMax);
// Texture fetches
tsr_half3 OriginalOpaqueInput = InputTexture.SampleLevel(GlobalPointClampedSampler, Ctx.InputUV, 0);
tsr_half MoireInput = InputMoireLumaTexture.SampleLevel(GlobalPointClampedSampler, Ctx.InputUV, 0);
tsr_half4 OriginalTranslucencyInput = InputSceneTranslucencyTexture.SampleLevel(GlobalPointClampedSampler, Ctx.InputUV, 0);
tsr_half4 MoireHistory = MoireHistoryTexture.SampleLevel(GlobalPointClampedSampler, MoireHistoryUV, 0);
tsr_half DisableAntiFlickering = tsr_half(1.0) - tsr_half(IsMovingMaskTexture[Ctx.InputPixelPos]) * rcp(tsr_half(255.0));
// Unpack history
tsr_half FlickeringHistory = GCSToSMCS(MoireHistory[0]);
tsr_half Gradient = MoireHistory[1] * tsr_half(255.0 / 127.0) - tsr_half(1.0);
tsr_half TotalVariation = MoireHistory[2] * (tsr_half(1.0) - BlendFinal);
tsr_half TotalVariationCount = MoireHistory[3] * MaxPrevTotalVariationCount * (tsr_half(1.0) - BlendFinal);
tsr_half InputLumaModification;
{
const tsr_half InputLumaEncodingError = tsr_half(0.5 / 255.0);
tsr_half3 OriginalInput = OriginalOpaqueInput * OriginalTranslucencyInput.a + OriginalTranslucencyInput.rgb;
OriginalInput = LinearToSMCS(OriginalInput);
OriginalOpaqueInput = LinearToSMCS(OriginalOpaqueInput);
tsr_half SceneColorLuma = dot(OriginalOpaqueInput.rgb, kMoireSMCSWeights);
tsr_half TranslucencyChange = dot(abs(OriginalOpaqueInput.rgb - OriginalInput.rgb), kMoireSMCSWeights);
tsr_half InputLuma = GCSToSMCS(MoireInput);
InputLumaModification = tsr_half(0.0);
InputLumaModification = max(InputLumaModification, abs(InputLuma - SceneColorLuma) - InputLumaEncodingError);
InputLumaModification = max(InputLumaModification, TranslucencyChange);
InputLumaModification = max(InputLumaModification, tsr_half(1.0) - OriginalTranslucencyInput[3]);
}
tsr_half InputLumaModificationPercent = saturate(InputLumaModification * tsr_half(16.0));
// Compute the final luminance
#if 1
tsr_half LocalCountFadeIn = saturate(TotalVariationCount / TotalVariationCountThreshold - tsr_half(0.5));
#else
tsr_half LocalCountFadeIn = saturate(TotalVariationCount - TotalVariationCountThreshold);
#endif
tsr_half LocalMoireError = (abs(TotalVariation * SafeRcp(TotalVariationCount)) + TotalVariationCount * MoireEncodingError);
tsr_half3 Color;
Color = lerp(kGreen, kYellow, saturate(LocalMoireError * 16.0));
Color = lerp(Color, kRed, saturate(LocalMoireError * 16.0 - 1.0));
Color = lerp(kWhite, Color, LocalCountFadeIn);
Color = lerp(kPink, Color, min(DisableAntiFlickering, tsr_half(1.0) - InputLumaModificationPercent));
Color = select(bCameraCut == 0, Color, kPink);
return SampleTSROutputGray(Ctx) * Color;
}
//------------------------------------------------------- REPROJECTION FIELD
tsr_half3 DisplayReprojectionFieldSummary(FContext Ctx)
{
FReprojectionFieldSample Reprojection = SampleReprojectionField(Ctx);
tsr_half JacobianVisibilityMultiplier = tsr_half(64.0);
//tsr_half JacobianVisibilityMultiplier = tsr_half(select(Reprojection.bAntiAliasReprojectionField, 2, 1)) * tsr_half(64.0);
tsr_half MaxJacobianX = max(abs(Reprojection.Jacobian[0][0]), abs(Reprojection.Jacobian[0][1]));
tsr_half MaxJacobianY = max(abs(Reprojection.Jacobian[1][0]), abs(Reprojection.Jacobian[1][1]));
tsr_half3 Color;
Color = kWhite;
Color.g = lerp(Color.g, tsr_half(1.0), saturate(MaxJacobianX * JacobianVisibilityMultiplier));
Color.b = lerp(Color.b, tsr_half(1.0), saturate(MaxJacobianY * JacobianVisibilityMultiplier));
Color = select(Reprojection.bIsOffScreen, kPink, Color);
//Color = select(Reprojection.bAntiAliasReprojectionField, kGreen, Color);
Color = select(!bReprojectionField, kPink, Color);
return SampleTSROutputGray(Ctx) * Color;
}
tsr_half3 DisplayReprojectionFieldOffset(FContext Ctx)
{
FReprojectionFieldSample Reprojection = SampleReprojectionField(Ctx);
tsr_half3 Color = kWhite;
Color.gb = tsr_half2((float2(Reprojection.Offset) * 0.5 + 0.5) * 0.67 + 0.33);
Color = select(all(Reprojection.Offset == tsr_short(0)), select(Reprojection.bIsOffScreen, kPink, kWhite), Color);
Color = select(!bReprojectionField, kPink, Color);
return SampleTSROutputGray(Ctx) * Color;
}
tsr_half3 DisplayReprojectionOffsetCoverage(FContext Ctx)
{
FReprojectionFieldSample Reprojection = SampleReprojectionField(Ctx);
tsr_half ReprojectionBoundaryCoverage = ComputeReprojectionBoundaryCoverage(Reprojection.Boundary);
tsr_half3 Color;
Color = lerp(kRed, kGreen, ReprojectionBoundaryCoverage);
Color = select(Reprojection.bIsFullDilate, kCyan, Color);
Color = select(all(Reprojection.Offset == tsr_short(0)), select(Reprojection.bIsOffScreen, kPink, kWhite), Color);
Color = select(!bReprojectionField, kPink, Color);
return SampleTSROutputGray(Ctx) * Color;
}
tsr_half3 DisplayReprojectionNullJacobian(FContext Ctx)
{
FReprojectionFieldSample Reprojection = SampleReprojectionField(Ctx);
tsr_half MaxJacobianX = max(abs(Reprojection.Jacobian[0][0]), abs(Reprojection.Jacobian[0][1]));
tsr_half MaxJacobianY = max(abs(Reprojection.Jacobian[1][0]), abs(Reprojection.Jacobian[1][1]));
tsr_half MaxJacobian = max(MaxJacobianX, MaxJacobianY);
bool bIsNullVector = all(abs(Reprojection.Vector) < (0.5 / 65535.0));
bool bIsNullJacobian = MaxJacobian < pow(tsr_half(1u << kVelocityJacobianBits), tsr_half(-2.0));
tsr_half3 Color = select(bIsNullJacobian && !bIsNullVector, kOrange, kWhite);
Color = select(Reprojection.bIsOffScreen || !bReprojectionField, kPink, Color);
return SampleTSROutputGray(Ctx) * Color;
}
tsr_half3 DisplayReprojectionClampedJacobian(FContext Ctx)
{
FReprojectionFieldSample Reprojection = SampleReprojectionField(Ctx);
tsr_half MaxJacobianX = max(abs(Reprojection.Jacobian[0][0]), abs(Reprojection.Jacobian[0][1]));
tsr_half MaxJacobianY = max(abs(Reprojection.Jacobian[1][0]), abs(Reprojection.Jacobian[1][1]));
tsr_half MaxJacobian = max(MaxJacobianX, MaxJacobianY);
tsr_half3 Color;
Color = select(Reprojection.bIsOffScreen, kPink, kWhite);
Color = select(MaxJacobian > kVelocityJacobianRange - rcp(tsr_half(1u << kVelocityJacobianBits)), kRed, Color);
Color = select(!bReprojectionField, kPink, Color);
return SampleTSROutputGray(Ctx) * Color;
}
tsr_half3 DisplayReprojectionFieldDilatedJacobian(FContext Ctx)
{
FReprojectionFieldSample Reprojection = SampleReprojectionField(Ctx);
tsr_half ReprojectionUpscaleFactor = ComputeReprojectionUpscaleFactorFromJacobian(Reprojection.Jacobian);
tsr_half3 Color;
Color = kWhite;
Color = lerp(Color, kRed, saturate( log2(ReprojectionUpscaleFactor)));
Color = lerp(Color, kGreen, saturate(-log2(ReprojectionUpscaleFactor)));
Color = select(Reprojection.bIsOffScreen || !bReprojectionField, kPink, Color);
return SampleTSROutputGray(Ctx) * Color;
}
tsr_half3 DisplayReprojectionFieldAA(FContext Ctx)
{
FReprojectionFieldSample Reprojection = SampleReprojectionField(Ctx);
tsr_half ReprojectionUpscaleFactor = ComputeReprojectionUpscaleFactorFromJacobian(Reprojection.Jacobian);
tsr_half3 Color;
Color = select(Reprojection.bIsOffScreen, kPink, kWhite);
Color = select(Reprojection.bAntiAliasReprojectionField, kGreen, Color);
Color = select(!bReprojectionField, kPink, Color);
return SampleTSROutputGray(Ctx) * Color;
}
//------------------------------------------------------- ENTRY POINT
[numthreads(TILE_SIZE * TILE_SIZE, 1, 1)]
void MainCS(
uint2 GroupId : SV_GroupID,
uint GroupThreadIndex : SV_GroupIndex)
{
uint GroupWaveIndex = GetGroupWaveIndex(GroupThreadIndex, /* GroupSize = */ TILE_SIZE * TILE_SIZE);
Debug = 0.0;
FContext Ctx;
Ctx.OutputPixelPos = (
tsr_short2(OutputViewRectMin) +
tsr_short2(GroupId) * tsr_short2(TILE_SIZE, TILE_SIZE) +
Map8x8Tile2x2Lane(GroupThreadIndex));
Ctx.ScreenPos = ApplyScreenTransform(float2(Ctx.OutputPixelPos), OutputPixelPosToScreenPos);
Ctx.InputUV = ApplyScreenTransform(ApplyLensDistortionOnScreenPos(UndistortingDisplacementTexture, Ctx.ScreenPos), ScreenPosToInputUV);
Ctx.InputUV = fastClamp(Ctx.InputUV, InputInfo_UVViewportBilinearMin, InputInfo_UVViewportBilinearMax);
Ctx.InputPixelPos = tsr_short2(ApplyScreenTransform(ApplyLensDistortionOnScreenPos(UndistortingDisplacementTexture, Ctx.ScreenPos), ScreenPosToInputPixelPos));
Ctx.InputPixelPos = fastClamp(Ctx.InputPixelPos, tsr_short2(InputInfo_ViewportMin), tsr_short2(InputInfo_ViewportMax - 1));
tsr_half3 OutputColor = tsr_half(0.0);
BRANCH
if (VisualizeId == 0)
{
OutputColor = DisplayHistorySampleCount(Ctx);
}
else if (VisualizeId == 1)
{
OutputColor = DisplayParallaxDisocclusionMask(Ctx);
}
else if (VisualizeId == 2)
{
OutputColor = DisplayHistoryRejection(Ctx);
}
else if (VisualizeId == 3)
{
OutputColor = DisplayHistoryClamp(Ctx);
}
else if (VisualizeId == 4)
{
OutputColor = DisplayResurrectionMask(Ctx);
}
else if (VisualizeId == 5)
{
OutputColor = DisplayResurrectedColor(Ctx);
}
else if (VisualizeId == 6)
{
OutputColor = DisplaySpatialAntiAliasingMask(Ctx);
}
else if (VisualizeId == 7)
{
OutputColor = DisplayAntiFlickering(Ctx);
}
else if (VisualizeId == 8)
{
OutputColor = DisplayReprojectionFieldSummary(Ctx);
}
else if (VisualizeId == 9)
{
OutputColor = DisplayReprojectionFieldOffset(Ctx);
}
else if (VisualizeId == 10)
{
OutputColor = DisplayReprojectionOffsetCoverage(Ctx);
}
else if (VisualizeId == 11)
{
OutputColor = DisplayReprojectionFieldAA(Ctx);
}
else if (VisualizeId == 12)
{
OutputColor = DisplayReprojectionNullJacobian(Ctx);
}
else if (VisualizeId == 13)
{
OutputColor = DisplayReprojectionClampedJacobian(Ctx);
}
else if (VisualizeId == 14)
{
OutputColor = DisplayReprojectionFieldDilatedJacobian(Ctx);
}
else if (VisualizeId == 15)
{
OutputColor = DisplayThinGeometry(Ctx);
}
{
tsr_short2 OutputPixelPos = InvalidateOutputPixelPos(Ctx.OutputPixelPos, OutputViewRectMax);
Output[OutputPixelPos] = tsr_half4(OutputColor, 0.0);
#if DEBUG_OUTPUT
{
DebugOutput[tsr_short3(OutputPixelPos, 0)] = Debug;
}
#endif
}
}