16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-22 16:19:19 +02:00

Some renaming

This commit is contained in:
2025-04-15 01:32:56 +02:00
parent 12d6a1578d
commit a39d972126
864 changed files with 29 additions and 34 deletions

View File

@@ -0,0 +1,55 @@
# This file is part of the FidelityFX SDK.
#
# Copyright (C) 2024 Advanced Micro Devices, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files(the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions :
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
set(FRAMEINTERPOLATION_BASE_ARGS
-DFFX_FRAMEINTERPOLATION_OPTION_UPSAMPLE_SAMPLERS_USE_DATA_HALF=0
-DFFX_FRAMEINTERPOLATION_OPTION_ACCUMULATE_SAMPLERS_USE_DATA_HALF=0
-DFFX_FRAMEINTERPOLATION_OPTION_REPROJECT_SAMPLERS_USE_DATA_HALF=1
-DFFX_FRAMEINTERPOLATION_OPTION_POSTPROCESSLOCKSTATUS_SAMPLERS_USE_DATA_HALF=0
# Upsample uses lanczos approximation
-DFFX_FRAMEINTERPOLATION_OPTION_UPSAMPLE_USE_LANCZOS_TYPE=2
-reflection -deps=gcc -DFFX_GPU=1)
set(FRAMEINTERPOLATION_PERMUTATION_ARGS
-DFFX_FRAMEINTERPOLATION_OPTION_LOW_RES_MOTION_VECTORS={0,1}
-DFFX_FRAMEINTERPOLATION_OPTION_JITTER_MOTION_VECTORS={0,1}
-DFFX_FRAMEINTERPOLATION_OPTION_INVERTED_DEPTH={0,1})
set(FRAMEINTERPOLATION_INCLUDE_ARGS
"${FFX_GPU_PATH}"
"${FFX_GPU_PATH}/frameinterpolation")
if (NOT FRAMEINTERPOLATION_SHADER_EXT)
set(FRAMEINTERPOLATION_SHADER_EXT *)
endif()
file(GLOB FRAMEINTERPOLATION_SHADERS
"shaders/frameinterpolation/*.${FRAMEINTERPOLATION_SHADER_EXT}")
# compile all the shaders
compile_shaders_with_depfile(
"${FFX_SC_EXECUTABLE}"
"${FRAMEINTERPOLATION_BASE_ARGS}" "${FRAMEINTERPOLATION_API_BASE_ARGS}" "${FRAMEINTERPOLATION_PERMUTATION_ARGS}" "${FRAMEINTERPOLATION_INCLUDE_ARGS}"
"${FRAMEINTERPOLATION_SHADERS}" "${FFX_PASS_SHADER_OUTPUT_PATH}" FRAMEINTERPOLATION_PERMUTATION_OUTPUTS)
# add the header files they generate to the main list of dependencies
add_shader_output("${FRAMEINTERPOLATION_PERMUTATION_OUTPUTS}")

View File

@@ -0,0 +1,192 @@
// This file is part of the FidelityFX SDK.
//
// Copyright (C) 2024 Advanced Micro Devices, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef FFX_FRAMEINTERPOLATION_H
#define FFX_FRAMEINTERPOLATION_H
struct InterpolationSourceColor
{
FfxFloat32x3 fRaw;
FfxFloat32x3 fLinear;
FfxFloat32 fBilinearWeightSum;
};
InterpolationSourceColor NewInterpolationSourceColor()
{
InterpolationSourceColor c;
c.fRaw = FfxFloat32x3(0.0, 0.0, 0.0);
c.fLinear = FfxFloat32x3(0.0, 0.0, 0.0);
c.fBilinearWeightSum = 0.0;
return c;
}
InterpolationSourceColor SampleTextureBilinear(FfxBoolean isCurrent, FfxFloat32x2 fUv, FfxFloat32x2 fMotionVector, FfxInt32x2 texSize)
{
InterpolationSourceColor result = NewInterpolationSourceColor();
FfxFloat32x2 fReprojectedUv = fUv + fMotionVector;
BilinearSamplingData bilinearInfo = GetBilinearSamplingData(fReprojectedUv, texSize);
FfxFloat32x3 fColor = FfxFloat32x3(0.0, 0.0, 0.0);
FfxFloat32 fWeightSum = 0.0f;
for (FfxInt32 iSampleIndex = 0; iSampleIndex < 4; iSampleIndex++) {
const FfxInt32x2 iOffset = bilinearInfo.iOffsets[iSampleIndex];
const FfxInt32x2 iSamplePos = bilinearInfo.iBasePos + iOffset;
if (IsInRect(iSamplePos, InterpolationRectBase(), InterpolationRectSize()))
{
FfxFloat32 fWeight = bilinearInfo.fWeights[iSampleIndex];
if (isCurrent)
fColor += LoadCurrentBackbuffer(iSamplePos).rgb * fWeight;
else
fColor += LoadPreviousBackbuffer(iSamplePos).rgb * fWeight;
fWeightSum += fWeight;
}
}
//normalize colors
fColor = (fWeightSum != 0.0f) ? fColor / fWeightSum : FfxFloat32x3(0.0f, 0.0f, 0.0f);
result.fRaw = fColor;
result.fLinear = RawRGBToLinear(fColor);
result.fBilinearWeightSum = fWeightSum;
return result;
}
void updateInPaintingWeight(inout FfxFloat32 fInPaintingWeight, FfxFloat32 fFactor)
{
fInPaintingWeight = ffxSaturate(ffxMax(fInPaintingWeight, fFactor));
}
void computeInterpolatedColor(FfxUInt32x2 iPxPos, out FfxFloat32x3 fInterpolatedColor, inout FfxFloat32 fInPaintingWeight)
{
const FfxFloat32x2 fUvInInterpolationRect = (FfxFloat32x2(iPxPos - InterpolationRectBase()) + 0.5f) / InterpolationRectSize();
const FfxFloat32x2 fUvInScreenSpace = (FfxFloat32x2(iPxPos) + 0.5f) / DisplaySize();
const FfxFloat32x2 fLrUvInInterpolationRect = fUvInInterpolationRect * (FfxFloat32x2(RenderSize()) / GetMaxRenderSize());
const FfxFloat32x2 fUvLetterBoxScale = FfxFloat32x2(InterpolationRectSize()) / DisplaySize();
// game MV are top left aligned, the function scales them to render res UV
VectorFieldEntry gameMv;
LoadInpaintedGameFieldMv(fUvInInterpolationRect, gameMv);
// OF is done on the back buffers which already have black bars
VectorFieldEntry ofMv;
SampleOpticalFlowMotionVectorField(fUvInScreenSpace, ofMv);
// Binarize disucclusion factor
FfxFloat32x2 fDisocclusionFactor = FfxFloat32x2(FFX_EQUAL(ffxSaturate(SampleDisocclusionMask(fLrUvInInterpolationRect).xy), FfxFloat32x2(1.0, 1.0)));
InterpolationSourceColor fPrevColorGame = SampleTextureBilinear(false, fUvInScreenSpace, +gameMv.fMotionVector * fUvLetterBoxScale, DisplaySize());
InterpolationSourceColor fCurrColorGame = SampleTextureBilinear(true, fUvInScreenSpace, -gameMv.fMotionVector * fUvLetterBoxScale, DisplaySize());
InterpolationSourceColor fPrevColorOF = SampleTextureBilinear(false, fUvInScreenSpace, +ofMv.fMotionVector * fUvLetterBoxScale, DisplaySize());
InterpolationSourceColor fCurrColorOF = SampleTextureBilinear(true, fUvInScreenSpace, -ofMv.fMotionVector * fUvLetterBoxScale, DisplaySize());
FfxFloat32 fBilinearWeightSum = 0.0f;
FfxFloat32 fDisoccludedFactor = 0.0f;
// Disocclusion logic
{
fDisocclusionFactor.x *= FfxFloat32(!gameMv.bNegOutside);
fDisocclusionFactor.y *= FfxFloat32(!gameMv.bPosOutside);
// Inpaint in bi-directional disocclusion areas
updateInPaintingWeight(fInPaintingWeight, FfxFloat32(length(fDisocclusionFactor) <= FFX_FRAMEINTERPOLATION_EPSILON));
FfxFloat32 t = 0.5f;
t += 0.5f * (1 - (fDisocclusionFactor.x));
t -= 0.5f * (1 - (fDisocclusionFactor.y));
fInterpolatedColor = ffxLerp(fPrevColorGame.fRaw, fCurrColorGame.fRaw, ffxSaturate(t));
fBilinearWeightSum = ffxLerp(fPrevColorGame.fBilinearWeightSum, fCurrColorGame.fBilinearWeightSum, ffxSaturate(t));
fDisoccludedFactor = ffxSaturate(1 - ffxMin(fDisocclusionFactor.x, fDisocclusionFactor.y));
if (fPrevColorGame.fBilinearWeightSum == 0.0f)
{
fInterpolatedColor = fCurrColorGame.fRaw;
fBilinearWeightSum = fCurrColorGame.fBilinearWeightSum;
}
else if (fCurrColorGame.fBilinearWeightSum == 0.0f)
{
fInterpolatedColor = fPrevColorGame.fRaw;
fBilinearWeightSum = fPrevColorGame.fBilinearWeightSum;
}
if (fPrevColorGame.fBilinearWeightSum == 0 && fCurrColorGame.fBilinearWeightSum == 0)
{
fInPaintingWeight = 1.0f;
}
}
{
FfxFloat32 ofT = 0.5f;
if (fPrevColorOF.fBilinearWeightSum > 0 && fCurrColorOF.fBilinearWeightSum > 0)
{
ofT = 0.5f;
}
else if (fPrevColorOF.fBilinearWeightSum > 0)
{
ofT = 0;
} else {
ofT = 1;
}
const FfxFloat32x3 ofColor = ffxLerp(fPrevColorOF.fRaw, fCurrColorOF.fRaw, ofT);
FfxFloat32 fOF_Sim = NormalizedDot3(fPrevColorOF.fRaw, fCurrColorOF.fRaw);
FfxFloat32 fGame_Sim = NormalizedDot3(fPrevColorGame.fRaw, fCurrColorGame.fRaw);
fGame_Sim = ffxLerp(ffxMax(FFX_FRAMEINTERPOLATION_EPSILON, fGame_Sim), 1.0f, ffxSaturate(fDisoccludedFactor));
FfxFloat32 fGameMvBias = ffxPow(ffxSaturate(fGame_Sim / ffxMax(FFX_FRAMEINTERPOLATION_EPSILON, fOF_Sim)), 1.0f);
const FfxFloat32 fFrameIndexFactor = FfxFloat32(FrameIndexSinceLastReset() < 10);
fGameMvBias = ffxLerp(fGameMvBias, 1.0f, fFrameIndexFactor);
fInterpolatedColor = ffxLerp(ofColor, fInterpolatedColor, ffxSaturate(fGameMvBias));
}
}
void computeFrameinterpolation(FfxInt32x2 iPxPos)
{
FfxFloat32x3 fColor = FfxFloat32x3(0, 0, 0);
FfxFloat32 fInPaintingWeight = 0.0f;
if (IsInRect(iPxPos, InterpolationRectBase(), InterpolationRectSize()) == false || FrameIndexSinceLastReset() == 0)
{
// if we just reset or we are out of the interpolation rect, copy the current back buffer and don't interpolate
fColor = LoadCurrentBackbuffer(iPxPos);
}
else
{
computeInterpolatedColor(iPxPos, fColor, fInPaintingWeight);
}
StoreFrameinterpolationOutput(FfxInt32x2(iPxPos), FfxFloat32x4(fColor, fInPaintingWeight));
}
#endif // FFX_FRAMEINTERPOLATION_H

View File

@@ -0,0 +1,745 @@
// This file is part of the FidelityFX SDK.
//
// Copyright (C) 2024 Advanced Micro Devices, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "ffx_frameinterpolation_resources.h"
#include "ffx_core.h"
#define COUNTER_SPD 0
#define COUNTER_FRAME_INDEX_SINCE_LAST_RESET 1
///////////////////////////////////////////////
// declare CBs and CB accessors
///////////////////////////////////////////////
#if defined(FFX_FRAMEINTERPOLATION_BIND_CB_FRAMEINTERPOLATION)
layout (set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_CB_FRAMEINTERPOLATION, std140) uniform cbFI_t
{
FfxInt32x2 renderSize;
FfxInt32x2 displaySize;
FfxFloat32x2 displaySizeRcp;
FfxFloat32 cameraNear;
FfxFloat32 cameraFar;
FfxInt32x2 upscalerTargetSize;
FfxInt32 Mode;
FfxInt32 reset;
FfxFloat32x4 fDeviceToViewDepth;
FfxFloat32 deltaTime;
FfxInt32 HUDLessAttachedFactor;
FfxFloat32x2 UNUSED;
FfxFloat32x2 opticalFlowScale;
FfxInt32 opticalFlowBlockSize;
FfxUInt32 dispatchFlags;
FfxInt32x2 maxRenderSize;
FfxInt32 opticalFlowHalfResMode;
FfxInt32 NumInstances;
FfxInt32x2 interpolationRectBase;
FfxInt32x2 interpolationRectSize;
FfxFloat32x3 debugBarColor;
FfxUInt32 backBufferTransferFunction;
FfxFloat32x2 minMaxLuminance;
FfxFloat32 fTanHalfFOV;
FfxInt32 _pad1;
FfxFloat32x2 fJitter;
FfxFloat32x2 fMotionVectorScale;
} cbFI;
FfxFloat32x2 Jitter()
{
return cbFI.fJitter;
}
FfxInt32x2 InterpolationRectBase()
{
return cbFI.interpolationRectBase;
}
FfxInt32x2 InterpolationRectSize()
{
return cbFI.interpolationRectSize;
}
FfxFloat32x2 MotionVectorScale()
{
return cbFI.fMotionVectorScale;
}
FfxInt32x2 RenderSize()
{
return cbFI.renderSize;
}
FfxInt32x2 DisplaySize()
{
return cbFI.displaySize;
}
FfxBoolean Reset()
{
return cbFI.reset == 1;
}
FfxFloat32x4 DeviceToViewSpaceTransformFactors()
{
return cbFI.fDeviceToViewDepth;
}
FfxInt32x2 GetOpticalFlowSize()
{
FfxInt32x2 iOpticalFlowSize = FfxInt32x2((1.0 / cbFI.opticalFlowScale) / FfxFloat32x2(cbFI.opticalFlowBlockSize.xx));
return iOpticalFlowSize;
}
FfxInt32x2 GetOpticalFlowSize2()
{
return GetOpticalFlowSize() * 1;
}
FfxFloat32x2 GetOpticalFlowScale()
{
return cbFI.opticalFlowScale;
}
FfxInt32 GetOpticalFlowBlockSize()
{
return cbFI.opticalFlowBlockSize;
}
FfxInt32 GetHUDLessAttachedFactor()
{
return cbFI.HUDLessAttachedFactor;
}
FfxUInt32 GetDispatchFlags()
{
return cbFI.dispatchFlags;
}
FfxInt32x2 GetMaxRenderSize()
{
return cbFI.maxRenderSize;
}
FfxInt32 GetOpticalFlowHalfResMode()
{
return cbFI.opticalFlowHalfResMode;
}
FfxFloat32x3 GetDebugBarColor()
{
return cbFI.debugBarColor;
}
FfxFloat32 TanHalfFoV()
{
return cbFI.fTanHalfFOV;
}
FfxUInt32 BackBufferTransferFunction()
{
return cbFI.backBufferTransferFunction;
}
FfxFloat32 MinLuminance()
{
return cbFI.minMaxLuminance[0];
}
FfxFloat32 MaxLuminance()
{
return cbFI.minMaxLuminance[1];
}
#endif // defined(FFX_FRAMEINTERPOLATION_BIND_CB_FRAMEINTERPOLATION)
#if defined(FFX_FRAMEINTERPOLATION_BIND_CB_INPAINTING_PYRAMID)
layout (set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_CB_INPAINTING_PYRAMID, std140) uniform cbInpaintingPyramid_t
{
FfxUInt32 mips;
FfxUInt32 numWorkGroups;
FfxUInt32x2 workGroupOffset;
} cbInpaintingPyramid;
FfxUInt32 NumMips()
{
return cbInpaintingPyramid.mips;
}
FfxUInt32 NumWorkGroups()
{
return cbInpaintingPyramid.numWorkGroups;
}
FfxUInt32x2 WorkGroupOffset()
{
return cbInpaintingPyramid.workGroupOffset;
}
#endif // defined(FFX_FRAMEINTERPOLATION_BIND_CB_INPAINTING_PYRAMID)
///////////////////////////////////////////////
// declare samplers
///////////////////////////////////////////////
layout (set = 0, binding = 1000) uniform sampler s_LinearClamp;
///////////////////////////////////////////////
// declare SRVs and SRV accessors
///////////////////////////////////////////////
#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_PREVIOUS_INTERPOLATION_SOURCE
layout (set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_SRV_PREVIOUS_INTERPOLATION_SOURCE) uniform texture2D r_previous_interpolation_source;
FfxFloat32x3 LoadPreviousBackbuffer(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return texelFetch(r_previous_interpolation_source, iPxPos, 0).rgb;
}
FfxFloat32x3 SamplePreviousBackbuffer(FFX_PARAMETER_IN FfxFloat32x2 fUv)
{
return textureLod(sampler2D(r_previous_interpolation_source, s_LinearClamp), fUv, 0.0).xyz;
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_CURRENT_INTERPOLATION_SOURCE
layout (set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_SRV_CURRENT_INTERPOLATION_SOURCE) uniform texture2D r_current_interpolation_source;
FfxFloat32x3 LoadCurrentBackbuffer(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return texelFetch(r_current_interpolation_source, iPxPos, 0).rgb;
}
FfxFloat32x3 SampleCurrentBackbuffer(FFX_PARAMETER_IN FfxFloat32x2 fUv)
{
return textureLod(sampler2D(r_current_interpolation_source, s_LinearClamp), fUv, 0.0).xyz;
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_MOTION_VECTORS
layout (set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_MOTION_VECTORS) uniform texture2D r_dilated_motion_vectors;
FfxFloat32x2 LoadDilatedMotionVector(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return texelFetch(r_dilated_motion_vectors, iPxPos, 0).xy;
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_DEPTH
layout (set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_DEPTH) uniform texture2D r_dilated_depth;
FfxFloat32 LoadDilatedDepth(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return texelFetch(r_dilated_depth, iPxPos, 0).x;
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_RECONSTRUCTED_DEPTH_PREVIOUS_FRAME
layout (set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_SRV_RECONSTRUCTED_DEPTH_PREVIOUS_FRAME) uniform utexture2D r_reconstructed_depth_previous_frame;
FfxFloat32 LoadReconstructedDepthPreviousFrame(FFX_PARAMETER_IN FfxInt32x2 iPxInput)
{
return ffxAsFloat(texelFetch(r_reconstructed_depth_previous_frame, iPxInput, 0).x);
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_RECONSTRUCTED_DEPTH_INTERPOLATED_FRAME
layout (set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_SRV_RECONSTRUCTED_DEPTH_INTERPOLATED_FRAME) uniform utexture2D r_reconstructed_depth_interpolated_frame;
FfxFloat32 LoadEstimatedInterpolationFrameDepth(FFX_PARAMETER_IN FfxInt32x2 iPxInput)
{
return ffxAsFloat(texelFetch(r_reconstructed_depth_interpolated_frame, iPxInput, 0).x);
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_DISOCCLUSION_MASK
layout (set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_SRV_DISOCCLUSION_MASK) uniform texture2D r_disocclusion_mask;
FfxFloat32x4 LoadDisocclusionMask(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return texelFetch(r_disocclusion_mask, iPxPos, 0);
}
FfxFloat32x4 SampleDisocclusionMask(FFX_PARAMETER_IN FfxFloat32x2 fUv)
{
return textureLod(sampler2D(r_disocclusion_mask, s_LinearClamp), fUv, 0);
}
#endif
#if defined(FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_X) && \
defined(FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_Y)
layout (set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_X) uniform utexture2D r_game_motion_vector_field_x;
layout (set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_Y) uniform utexture2D r_game_motion_vector_field_y;
FfxUInt32x2 LoadGameFieldMv(FFX_PARAMETER_IN FfxInt32x2 iPxSample)
{
FfxUInt32 packedX = texelFetch(r_game_motion_vector_field_x, iPxSample, 0).x;
FfxUInt32 packedY = texelFetch(r_game_motion_vector_field_y, iPxSample, 0).x;
return FfxUInt32x2(packedX, packedY);
}
#endif
#if defined(FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_X) && \
defined(FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_Y)
layout (set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_X) uniform utexture2D r_optical_flow_motion_vector_field_x;
layout (set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_Y) uniform utexture2D r_optical_flow_motion_vector_field_y;
FfxUInt32x2 LoadOpticalFlowFieldMv(FFX_PARAMETER_IN FfxInt32x2 iPxSample)
{
FfxUInt32 packedX = texelFetch(r_optical_flow_motion_vector_field_x, iPxSample, 0).x;
FfxUInt32 packedY = texelFetch(r_optical_flow_motion_vector_field_y, iPxSample, 0).x;
return FfxUInt32x2(packedX, packedY);
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW
layout (set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW) uniform itexture2D r_optical_flow;
#if defined(FFX_FRAMEINTERPOLATION_BIND_CB_FRAMEINTERPOLATION)
FfxFloat32x2 LoadOpticalFlow(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return texelFetch(r_optical_flow, iPxPos, 0).xy * GetOpticalFlowScale();
}
#endif
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_UPSAMPLED
layout (set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_UPSAMPLED) uniform texture2D r_optical_flow_upsampled;
FfxFloat32x2 LoadOpticalFlowUpsampled(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return texelFetch(r_optical_flow_upsampled, iPxPos, 0).xy;
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_CONFIDENCE
layout (set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_CONFIDENCE) uniform utexture2D r_optical_flow_confidence;
FfxFloat32 LoadOpticalFlowConfidence(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return texelFetch(r_optical_flow_confidence, iPxPos, 0).y;
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_GLOBAL_MOTION
layout (set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_GLOBAL_MOTION) uniform utexture2D r_optical_flow_global_motion;
FfxUInt32 LoadOpticalFlowGlobalMotion(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return texelFetch(r_optical_flow_global_motion, iPxPos, 0).x;
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_SCENE_CHANGE_DETECTION
layout (set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_SCENE_CHANGE_DETECTION) uniform utexture2D r_optical_flow_scd;
FfxUInt32 LoadOpticalFlowSceneChangeDetection(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return texelFetch(r_optical_flow_scd, iPxPos, 0).x;
}
FfxBoolean HasSceneChanged()
{
#define SCD_OUTPUT_HISTORY_BITS_SLOT 1
//if (FrameIndex() <= 5) // threshold according to original OpenCL code
//{
// return 1.0;
//}
//else
{
// Report that the scene is changed if the change was detected in any of the
// 4 previous frames (0xfu - covers 4 history bits).
return ((texelFetch(r_optical_flow_scd, FfxInt32x2(SCD_OUTPUT_HISTORY_BITS_SLOT, 0), 0).x) & 0xfu) != 0;
}
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_DEBUG
layout (set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_DEBUG) uniform texture2D r_optical_flow_debug;
FfxFloat32x4 LoadOpticalFlowDebug(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return texelFetch(r_optical_flow_debug, iPxPos, 0);
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_OUTPUT
layout (set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_SRV_OUTPUT) uniform texture2D r_output;
FfxFloat32x4 LoadFrameInterpolationOutput(FFX_PARAMETER_IN FfxInt32x2 iPxInput)
{
return texelFetch(r_output, iPxInput, 0);
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_INPAINTING_PYRAMID
layout (set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_SRV_INPAINTING_PYRAMID) uniform texture2D r_inpainting_pyramid;
FfxFloat32x4 LoadInpaintingPyramid(FFX_PARAMETER_IN FfxInt32 mipLevel, FFX_PARAMETER_IN FfxUInt32x2 iPxInput)
{
return texelFetch(r_inpainting_pyramid, FfxInt32x2(iPxInput), mipLevel);
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_PRESENT_BACKBUFFER
layout (set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_SRV_PRESENT_BACKBUFFER) uniform texture2D r_present_backbuffer;
FfxFloat32x4 LoadPresentBackbuffer(FFX_PARAMETER_IN FfxInt32x2 iPxInput)
{
return texelFetch(r_present_backbuffer, iPxInput, 0);
}
FfxFloat32x4 SamplePresentBackbuffer(FFX_PARAMETER_IN FfxFloat32x2 fUv)
{
return textureLod(sampler2D(r_present_backbuffer, s_LinearClamp), fUv, 0.0);
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_COUNTERS
layout(set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_SRV_COUNTERS) readonly buffer FrameInterpolationCounters_t
{
FfxUInt32 data[];
} r_counters;
FfxUInt32 LoadCounter(FFX_PARAMETER_IN FfxInt32 iPxPos)
{
return r_counters.data[iPxPos];
}
FfxUInt32 FrameIndexSinceLastReset()
{
return LoadCounter(COUNTER_FRAME_INDEX_SINCE_LAST_RESET);
}
#endif
#if defined(FFX_FRAMEINTERPOLATION_BIND_SRV_INPUT_DEPTH)
layout (set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_SRV_INPUT_DEPTH) uniform texture2D r_input_depth;
FfxFloat32 LoadInputDepth(FfxInt32x2 iPxPos)
{
return texelFetch(r_input_depth, iPxPos, 0).x;
}
#endif
#if defined(FFX_FRAMEINTERPOLATION_BIND_SRV_INPUT_MOTION_VECTORS)
layout (set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_SRV_INPUT_MOTION_VECTORS) uniform texture2D r_input_motion_vectors;
FfxFloat32x2 LoadInputMotionVector(FfxInt32x2 iPxDilatedMotionVectorPos)
{
FfxFloat32x2 fSrcMotionVector = texelFetch(r_input_motion_vectors, iPxDilatedMotionVectorPos, 0).xy;
FfxFloat32x2 fUvMotionVector = fSrcMotionVector * MotionVectorScale();
#if FFX_FRAMEINTERPOLATION_OPTION_JITTERED_MOTION_VECTORS
fUvMotionVector -= MotionVectorJitterCancellation();
#endif
return fUvMotionVector;
}
#endif
///////////////////////////////////////////////
// declare UAVs and UAV accessors
///////////////////////////////////////////////
#ifdef FFX_FRAMEINTERPOLATION_BIND_UAV_OUTPUT
layout(set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_UAV_OUTPUT /* app controlled format */) uniform image2D rw_output;
FfxFloat32x4 RWLoadFrameinterpolationOutput(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return imageLoad(rw_output, iPxPos);
}
void StoreFrameinterpolationOutput(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxFloat32x4 val)
{
imageStore(rw_output, iPxPos, val);
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_UAV_DILATED_MOTION_VECTORS
layout(set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_UAV_DILATED_MOTION_VECTORS, rg16f) uniform image2D rw_dilated_motion_vectors;
FfxFloat32x2 RWLoadDilatedMotionVectors(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return imageLoad(rw_dilated_motion_vectors, iPxPos).xy;
}
void StoreDilatedMotionVectors(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxFloat32x2 val)
{
imageStore(rw_dilated_motion_vectors, iPxPos, FfxFloat32x4(val, 0.0, 0.0));
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_UAV_DILATED_DEPTH
layout(set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_UAV_DILATED_DEPTH, r32f) uniform image2D rw_dilated_depth;
FfxFloat32 RWLoadDilatedDepth(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return imageLoad(rw_dilated_depth, iPxPos).x;
}
void StoreDilatedDepth(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxFloat32 val)
{
imageStore(rw_dilated_depth, iPxPos, FfxFloat32x4(val, 0.0, 0.0, 0.0));
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_UAV_RECONSTRUCTED_DEPTH_PREVIOUS_FRAME
layout(set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_UAV_RECONSTRUCTED_DEPTH_PREVIOUS_FRAME, r32ui) uniform uimage2D rw_reconstructed_depth_previous_frame;
FfxFloat32 RWLoadReconstructedDepthPreviousFrame(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return ffxAsFloat(imageLoad(rw_reconstructed_depth_previous_frame, iPxPos).x);
}
void UpdateReconstructedDepthPreviousFrame(FfxInt32x2 iPxSample, FfxFloat32 fDepth)
{
FfxUInt32 uDepth = ffxAsUInt32(fDepth);
#if FFX_FRAMEINTERPOLATION_OPTION_INVERTED_DEPTH
imageAtomicMax(rw_reconstructed_depth_previous_frame, iPxSample, uDepth);
#else
imageAtomicMin(rw_reconstructed_depth_previous_frame, iPxSample, uDepth); // min for standard, max for inverted depth
#endif
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_UAV_RECONSTRUCTED_DEPTH_INTERPOLATED_FRAME
layout(set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_UAV_RECONSTRUCTED_DEPTH_INTERPOLATED_FRAME, r32ui) uniform uimage2D rw_reconstructed_depth_interpolated_frame;
FfxFloat32 RWLoadReconstructedDepthInterpolatedFrame(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return ffxAsFloat(imageLoad(rw_reconstructed_depth_interpolated_frame, iPxPos).x);
}
void StoreReconstructedDepthInterpolatedFrame(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxFloat32 value)
{
FfxUInt32 uDepth = ffxAsUInt32(value);
imageStore(rw_reconstructed_depth_interpolated_frame, iPxPos, FfxUInt32x4(uDepth, 0, 0, 0));
}
void UpdateReconstructedDepthInterpolatedFrame(FfxInt32x2 iPxSample, FfxFloat32 fDepth)
{
FfxUInt32 uDepth = ffxAsUInt32(fDepth);
#if FFX_FRAMEINTERPOLATION_OPTION_INVERTED_DEPTH
imageAtomicMax(rw_reconstructed_depth_interpolated_frame, iPxSample, uDepth);
#else
imageAtomicMin(rw_reconstructed_depth_interpolated_frame, iPxSample, uDepth); // min for standard, max for inverted depth
#endif
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_UAV_DISOCCLUSION_MASK
layout(set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_UAV_DISOCCLUSION_MASK, rg8) uniform image2D rw_disocclusion_mask;
FfxFloat32x2 RWLoadDisocclusionMask(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return imageLoad(rw_disocclusion_mask, iPxPos).xy;
}
void StoreDisocclusionMask(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxFloat32x2 val)
{
imageStore(rw_disocclusion_mask, iPxPos, FfxFloat32x4(val, 0.0, 0.0));
}
#endif
#if defined(FFX_FRAMEINTERPOLATION_BIND_UAV_GAME_MOTION_VECTOR_FIELD_X) && \
defined(FFX_FRAMEINTERPOLATION_BIND_UAV_GAME_MOTION_VECTOR_FIELD_Y)
layout(set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_UAV_GAME_MOTION_VECTOR_FIELD_X, r32ui) uniform uimage2D rw_game_motion_vector_field_x;
layout(set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_UAV_GAME_MOTION_VECTOR_FIELD_Y, r32ui) uniform uimage2D rw_game_motion_vector_field_y;
FfxUInt32 RWLoadGameMotionVectorFieldX(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return imageLoad(rw_game_motion_vector_field_x, iPxPos).x;
}
void StoreGameMotionVectorFieldX(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxUInt32 val)
{
imageStore(rw_game_motion_vector_field_x, iPxPos, FfxUInt32x4(val, 0, 0, 0));
}
FfxUInt32 RWLoadGameMotionVectorFieldY(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return imageLoad(rw_game_motion_vector_field_y, iPxPos).x;
}
void StoreGameMotionVectorFieldY(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxUInt32 val)
{
imageStore(rw_game_motion_vector_field_y, iPxPos, FfxUInt32x4(val, 0, 0, 0));
}
void UpdateGameMotionVectorField(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxUInt32x2 packedVector)
{
imageAtomicMax(rw_game_motion_vector_field_x, iPxPos, packedVector.x);
imageAtomicMax(rw_game_motion_vector_field_y, iPxPos, packedVector.y);
}
FfxUInt32 UpdateGameMotionVectorFieldEx(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxUInt32x2 packedVector)
{
FfxUInt32 uPreviousValueX = imageAtomicMax(rw_game_motion_vector_field_x, iPxPos, packedVector.x);
FfxUInt32 uPreviousValueY = imageAtomicMax(rw_game_motion_vector_field_y, iPxPos, packedVector.y);
const FfxUInt32 uExistingVectorFieldEntry = ffxMax(uPreviousValueX, uPreviousValueY);
return uExistingVectorFieldEntry;
}
#endif
#if defined(FFX_FRAMEINTERPOLATION_BIND_UAV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_X) && \
defined(FFX_FRAMEINTERPOLATION_BIND_UAV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_Y)
layout(set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_UAV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_X, r32ui) uniform uimage2D rw_optical_flow_motion_vector_field_x;
layout(set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_UAV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_Y, r32ui) uniform uimage2D rw_optical_flow_motion_vector_field_y;
FfxUInt32 RWLoadOpticalflowMotionVectorFieldX(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return imageLoad(rw_optical_flow_motion_vector_field_x, iPxPos).x;
}
void StoreOpticalflowMotionVectorFieldX(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxUInt32 val)
{
imageStore(rw_optical_flow_motion_vector_field_x, iPxPos, FfxUInt32x4(val, 0, 0, 0));
}
FfxUInt32 RWLoadOpticalflowMotionVectorFieldY(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return imageLoad(rw_optical_flow_motion_vector_field_y, iPxPos).x;
}
void StoreOpticalflowMotionVectorFieldY(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxUInt32 val)
{
imageStore(rw_optical_flow_motion_vector_field_y, iPxPos, FfxUInt32x4(val, 0, 0, 0));
}
void UpdateOpticalflowMotionVectorField(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxUInt32x2 packedVector)
{
imageAtomicMax(rw_optical_flow_motion_vector_field_x, iPxPos, packedVector.x);
imageAtomicMax(rw_optical_flow_motion_vector_field_y, iPxPos, packedVector.y);
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_UAV_COUNTERS
layout(set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_UAV_COUNTERS) coherent buffer FrameInterpolationRWCounters_t
{
FfxUInt32 data[];
} rw_counters;
FfxUInt32 RWLoadCounter(FFX_PARAMETER_IN FfxInt32 iPxPos)
{
return rw_counters.data[iPxPos];
}
void StoreCounter(FFX_PARAMETER_IN FfxInt32 iPxPos, FFX_PARAMETER_IN FfxUInt32 counter)
{
rw_counters.data[iPxPos] = counter;
}
void AtomicIncreaseCounter(FFX_PARAMETER_IN FfxInt32 iPxPos, FFX_PARAMETER_OUT FfxUInt32 oldVal)
{
oldVal = atomicAdd(rw_counters.data[iPxPos], 1);
}
#endif
#if defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_0) && \
defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_1) && \
defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_2) && \
defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_3) && \
defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_4) && \
defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_5) && \
defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_6) && \
defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_7) && \
defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_8) && \
defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_9) && \
defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_10) && \
defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_11) && \
defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_12)
layout(set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_0, rgba16f) uniform image2D rw_inpainting_pyramid0;
layout(set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_1, rgba16f) uniform image2D rw_inpainting_pyramid1;
layout(set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_2, rgba16f) uniform image2D rw_inpainting_pyramid2;
layout(set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_3, rgba16f) uniform image2D rw_inpainting_pyramid3;
layout(set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_4, rgba16f) uniform image2D rw_inpainting_pyramid4;
layout(set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_5, rgba16f) coherent uniform image2D rw_inpainting_pyramid5;
layout(set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_6, rgba16f) uniform image2D rw_inpainting_pyramid6;
layout(set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_7, rgba16f) uniform image2D rw_inpainting_pyramid7;
layout(set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_8, rgba16f) uniform image2D rw_inpainting_pyramid8;
layout(set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_9, rgba16f) uniform image2D rw_inpainting_pyramid9;
layout(set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_10, rgba16f) uniform image2D rw_inpainting_pyramid10;
layout(set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_11, rgba16f) uniform image2D rw_inpainting_pyramid11;
layout(set = 0, binding = FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_12, rgba16f) uniform image2D rw_inpainting_pyramid12;
FfxFloat32x4 RWLoadInpaintingPyramid(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxUInt32 index)
{
#define LOAD(idx) \
if (index == idx) \
{ \
return imageLoad(rw_inpainting_pyramid##idx, iPxPos); \
}
LOAD(0);
LOAD(1);
LOAD(2);
LOAD(3);
LOAD(4);
LOAD(5);
LOAD(6);
LOAD(7);
LOAD(8);
LOAD(9);
LOAD(10);
LOAD(11);
LOAD(12);
return FfxFloat32x4(0.0, 0.0, 0.0, 0.0);
#undef LOAD
}
void StoreInpaintingPyramid(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxFloat32x4 outValue, FFX_PARAMETER_IN FfxUInt32 index)
{
#define STORE(idx) \
if (index == idx) \
{ \
imageStore(rw_inpainting_pyramid##idx, iPxPos, outValue); \
}
STORE(0);
STORE(1);
STORE(2);
STORE(3);
STORE(4);
STORE(5);
STORE(6);
STORE(7);
STORE(8);
STORE(9);
STORE(10);
STORE(11);
STORE(12);
#undef STORE
}
#endif

View File

@@ -0,0 +1,778 @@
// This file is part of the FidelityFX SDK.
//
// Copyright (C) 2024 Advanced Micro Devices, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "ffx_frameinterpolation_resources.h"
#if defined(FFX_GPU)
#ifdef __hlsl_dx_compiler
#pragma dxc diagnostic push
#pragma dxc diagnostic ignored "-Wambig-lit-shift"
#endif //__hlsl_dx_compiler
#include "ffx_core.h"
#ifdef __hlsl_dx_compiler
#pragma dxc diagnostic pop
#endif //__hlsl_dx_compiler
#endif // #if defined(FFX_GPU)
#if defined(FFX_GPU)
#define COUNTER_SPD 0
#define COUNTER_FRAME_INDEX_SINCE_LAST_RESET 1
///////////////////////////////////////////////
// declare CBs and CB accessors
///////////////////////////////////////////////
#if defined(FFX_FRAMEINTERPOLATION_BIND_CB_FRAMEINTERPOLATION)
cbuffer cbFI : FFX_DECLARE_CB(FFX_FRAMEINTERPOLATION_BIND_CB_FRAMEINTERPOLATION)
{
FfxInt32x2 renderSize;
FfxInt32x2 displaySize;
FfxFloat32x2 displaySizeRcp;
FfxFloat32 cameraNear;
FfxFloat32 cameraFar;
FfxInt32x2 upscalerTargetSize;
FfxInt32 Mode;
FfxInt32 reset;
FfxFloat32x4 fDeviceToViewDepth;
FfxFloat32 deltaTime;
FfxInt32 HUDLessAttachedFactor;
FfxFloat32x2 UNUSED;
FfxFloat32x2 opticalFlowScale;
FfxInt32 opticalFlowBlockSize;
FfxUInt32 dispatchFlags;
FfxInt32x2 maxRenderSize;
FfxInt32 opticalFlowHalfResMode;
FfxInt32 NumInstances;
FfxInt32x2 interpolationRectBase;
FfxInt32x2 interpolationRectSize;
FfxFloat32x3 debugBarColor;
FfxUInt32 backBufferTransferFunction;
FfxFloat32x2 minMaxLuminance;
FfxFloat32 fTanHalfFOV;
FfxInt32 _pad1;
FfxFloat32x2 fJitter;
FfxFloat32x2 fMotionVectorScale;
}
const FfxFloat32x2 Jitter()
{
return fJitter;
}
const FfxFloat32x2 MotionVectorScale()
{
return fMotionVectorScale;
}
const FfxInt32x2 InterpolationRectBase()
{
return interpolationRectBase;
}
const FfxInt32x2 InterpolationRectSize()
{
return interpolationRectSize;
}
const FfxInt32x2 RenderSize()
{
return renderSize;
}
const FfxInt32x2 DisplaySize()
{
return displaySize;
}
const FfxBoolean Reset()
{
return reset == 1;
}
FfxFloat32x4 DeviceToViewSpaceTransformFactors()
{
return fDeviceToViewDepth;
}
FfxInt32x2 GetOpticalFlowSize()
{
FfxInt32x2 iOpticalFlowSize = (1.0f / opticalFlowScale) / FfxFloat32x2(opticalFlowBlockSize.xx);
return iOpticalFlowSize;
}
FfxInt32x2 GetOpticalFlowSize2()
{
return GetOpticalFlowSize() * 1;
}
FfxFloat32x2 GetOpticalFlowScale()
{
return opticalFlowScale;
}
FfxInt32 GetOpticalFlowBlockSize()
{
return opticalFlowBlockSize;
}
FfxInt32 GetHUDLessAttachedFactor()
{
return HUDLessAttachedFactor;
}
FfxUInt32 GetDispatchFlags()
{
return dispatchFlags;
}
FfxInt32x2 GetMaxRenderSize()
{
return maxRenderSize;
}
FfxInt32 GetOpticalFlowHalfResMode()
{
return opticalFlowHalfResMode;
}
FfxFloat32x3 GetDebugBarColor()
{
return debugBarColor;
}
FfxFloat32 TanHalfFoV()
{
return fTanHalfFOV;
}
FfxUInt32 BackBufferTransferFunction()
{
return backBufferTransferFunction;
}
FfxFloat32 MinLuminance()
{
return minMaxLuminance[0];
}
FfxFloat32 MaxLuminance()
{
return minMaxLuminance[1];
}
#endif // #if defined(FFX_FRAMEINTERPOLATION_BIND_CB_FRAMEINTERPOLATION)
#if defined(FFX_FRAMEINTERPOLATION_BIND_CB_INPAINTING_PYRAMID)
cbuffer cbInpaintingPyramid : FFX_DECLARE_CB(FFX_FRAMEINTERPOLATION_BIND_CB_INPAINTING_PYRAMID)
{
FfxUInt32 mips;
FfxUInt32 numWorkGroups;
FfxUInt32x2 workGroupOffset;
}
FfxUInt32 NumMips()
{
return mips;
}
FfxUInt32 NumWorkGroups()
{
return numWorkGroups;
}
FfxUInt32x2 WorkGroupOffset()
{
return workGroupOffset;
}
#endif // #if defined(FFX_FRAMEINTERPOLATION_BIND_CB_INPAINTING_PYRAMID)
#define FFX_FRAMEINTERPOLATION_ROOTSIG_STRINGIFY(p) FFX_FRAMEINTERPOLATION_ROOTSIG_STR(p)
#define FFX_FRAMEINTERPOLATION_ROOTSIG_STR(p) #p
#define FFX_FRAMEINTERPOLATION_ROOTSIG [RootSignature( "DescriptorTable(UAV(u0, numDescriptors = " FFX_FRAMEINTERPOLATION_ROOTSIG_STRINGIFY(FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_COUNT) ")), " \
"DescriptorTable(SRV(t0, numDescriptors = " FFX_FRAMEINTERPOLATION_ROOTSIG_STRINGIFY(FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_COUNT) ")), " \
"CBV(b0), " \
"StaticSampler(s0, filter = FILTER_MIN_MAG_MIP_LINEAR, " \
"addressU = TEXTURE_ADDRESS_CLAMP, " \
"addressV = TEXTURE_ADDRESS_CLAMP, " \
"addressW = TEXTURE_ADDRESS_CLAMP, " \
"comparisonFunc = COMPARISON_NEVER, " \
"borderColor = STATIC_BORDER_COLOR_TRANSPARENT_BLACK)" )]
#define FFX_FRAMEINTERPOLATION_INPAINTING_ROOTSIG [RootSignature( "DescriptorTable(UAV(u0, numDescriptors = " FFX_FRAMEINTERPOLATION_ROOTSIG_STRINGIFY(FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_COUNT) ")), " \
"DescriptorTable(SRV(t0, numDescriptors = " FFX_FRAMEINTERPOLATION_ROOTSIG_STRINGIFY(FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_COUNT) ")), " \
"CBV(b0), " \
"CBV(b1), " \
"StaticSampler(s0, filter = FILTER_MIN_MAG_MIP_LINEAR, " \
"addressU = TEXTURE_ADDRESS_CLAMP, " \
"addressV = TEXTURE_ADDRESS_CLAMP, " \
"addressW = TEXTURE_ADDRESS_CLAMP, " \
"comparisonFunc = COMPARISON_NEVER, " \
"borderColor = STATIC_BORDER_COLOR_TRANSPARENT_BLACK)" )]
#if defined(FFX_FRAMEINTERPOLATION_EMBED_ROOTSIG)
#define FFX_FRAMEINTERPOLATION_EMBED_ROOTSIG_CONTENT FFX_FRAMEINTERPOLATION_ROOTSIG
#define FFX_FRAMEINTERPOLATION_EMBED_INPAINTING_ROOTSIG_CONTENT FFX_FRAMEINTERPOLATION_INPAINTING_ROOTSIG
#else
#define FFX_FRAMEINTERPOLATION_EMBED_ROOTSIG_CONTENT
#define FFX_FRAMEINTERPOLATION_EMBED_INPAINTING_ROOTSIG_CONTENT
#endif // #if FFX_FRAMEINTERPOLATION_EMBED_ROOTSIG
///////////////////////////////////////////////
// declare samplers
///////////////////////////////////////////////
SamplerState s_LinearClamp : register(s0);
///////////////////////////////////////////////
// declare SRVs and SRV accessors
///////////////////////////////////////////////
#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_PREVIOUS_INTERPOLATION_SOURCE
Texture2D<FfxFloat32x4> r_previous_interpolation_source : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_PREVIOUS_INTERPOLATION_SOURCE);
FfxFloat32x3 LoadPreviousBackbuffer(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return r_previous_interpolation_source[iPxPos].rgb;
}
FfxFloat32x3 SamplePreviousBackbuffer(FFX_PARAMETER_IN FfxFloat32x2 fUv)
{
return r_previous_interpolation_source.SampleLevel(s_LinearClamp, fUv, 0).xyz;
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_CURRENT_INTERPOLATION_SOURCE
Texture2D<FfxFloat32x4> r_current_interpolation_source : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_CURRENT_INTERPOLATION_SOURCE);
FfxFloat32x3 LoadCurrentBackbuffer(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return r_current_interpolation_source[iPxPos].rgb;
}
FfxFloat32x3 SampleCurrentBackbuffer(FFX_PARAMETER_IN FfxFloat32x2 fUv)
{
return r_current_interpolation_source.SampleLevel(s_LinearClamp, fUv, 0).xyz;
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_MOTION_VECTORS
Texture2D<FfxFloat32x2> r_dilated_motion_vectors : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_MOTION_VECTORS);
FfxFloat32x2 LoadDilatedMotionVector(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return r_dilated_motion_vectors[iPxPos].xy;
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_DEPTH
Texture2D<FfxFloat32> r_dilated_depth : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_DILATED_DEPTH);
FfxFloat32 LoadDilatedDepth(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return r_dilated_depth[iPxPos].x;
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_RECONSTRUCTED_DEPTH_PREVIOUS_FRAME
Texture2D<FfxUInt32> r_reconstructed_depth_previous_frame : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_RECONSTRUCTED_DEPTH_PREVIOUS_FRAME);
FfxFloat32 LoadReconstructedDepthPreviousFrame(FFX_PARAMETER_IN FfxInt32x2 iPxInput)
{
return asfloat(r_reconstructed_depth_previous_frame[iPxInput]);
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_RECONSTRUCTED_DEPTH_INTERPOLATED_FRAME
Texture2D<FfxUInt32> r_reconstructed_depth_interpolated_frame : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_RECONSTRUCTED_DEPTH_INTERPOLATED_FRAME);
FfxFloat32 LoadEstimatedInterpolationFrameDepth(FFX_PARAMETER_IN FfxInt32x2 iPxInput)
{
return asfloat(r_reconstructed_depth_interpolated_frame[iPxInput]);
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_DISOCCLUSION_MASK
Texture2D<FfxFloat32x4> r_disocclusion_mask : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_DISOCCLUSION_MASK);
FfxFloat32x4 LoadDisocclusionMask(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return r_disocclusion_mask[iPxPos];
}
FfxFloat32x4 SampleDisocclusionMask(FFX_PARAMETER_IN FfxFloat32x2 fUv)
{
return r_disocclusion_mask.SampleLevel(s_LinearClamp, fUv, 0);
}
#endif
#if defined(FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_X) && \
defined(FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_Y)
Texture2D<FfxUInt32> r_game_motion_vector_field_x : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_X);
Texture2D<FfxUInt32> r_game_motion_vector_field_y : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_Y);
FfxUInt32x2 LoadGameFieldMv(FFX_PARAMETER_IN FfxInt32x2 iPxSample)
{
FfxUInt32 packedX = r_game_motion_vector_field_x[iPxSample];
FfxUInt32 packedY = r_game_motion_vector_field_y[iPxSample];
return FfxUInt32x2(packedX, packedY);
}
#endif
#if defined(FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_X) && \
defined(FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_Y)
Texture2D<FfxUInt32> r_optical_flow_motion_vector_field_x : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_X);
Texture2D<FfxUInt32> r_optical_flow_motion_vector_field_y : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_Y);
FfxUInt32x2 LoadOpticalFlowFieldMv(FFX_PARAMETER_IN FfxInt32x2 iPxSample)
{
FfxUInt32 packedX = r_optical_flow_motion_vector_field_x[iPxSample];
FfxUInt32 packedY = r_optical_flow_motion_vector_field_y[iPxSample];
return FfxUInt32x2(packedX, packedY);
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW
Texture2D<FfxInt32x2> r_optical_flow : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW);
#if defined(FFX_FRAMEINTERPOLATION_BIND_CB_FRAMEINTERPOLATION)
FfxFloat32x2 LoadOpticalFlow(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return r_optical_flow[iPxPos] * GetOpticalFlowScale();
}
#endif
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_UPSAMPLED
Texture2D<FfxFloat32x2> r_optical_flow_upsampled : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_UPSAMPLED);
FfxFloat32x2 LoadOpticalFlowUpsampled(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return r_optical_flow_upsampled[iPxPos];
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_CONFIDENCE
Texture2D<FfxUInt32x2> r_optical_flow_confidence : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_CONFIDENCE);
FfxFloat32 LoadOpticalFlowConfidence(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return r_optical_flow_confidence[iPxPos].y;
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_GLOBAL_MOTION
Texture2D<FfxUInt32> r_optical_flow_global_motion : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_GLOBAL_MOTION);
FfxUInt32 LoadOpticalFlowGlobalMotion(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return r_optical_flow_global_motion[iPxPos];
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_SCENE_CHANGE_DETECTION
Texture2D<FfxUInt32> r_optical_flow_scd : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_SCENE_CHANGE_DETECTION);
FfxUInt32 LoadOpticalFlowSceneChangeDetection(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return r_optical_flow_scd[iPxPos];
}
FfxBoolean HasSceneChanged()
{
#define SCD_OUTPUT_HISTORY_BITS_SLOT 1
//if (FrameIndex() <= 5) // threshold according to original OpenCL code
//{
// return 1.0;
//}
//else
{
// Report that the scene is changed if the change was detected in any of the
// 4 previous frames (0xfu - covers 4 history bits).
return (r_optical_flow_scd[FfxInt32x2(SCD_OUTPUT_HISTORY_BITS_SLOT, 0)] & 0xfu) != 0;
}
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_DEBUG
Texture2D<FfxFloat32x4> r_optical_flow_debug : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_DEBUG);
FfxFloat32x4 LoadOpticalFlowDebug(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return r_optical_flow_debug[iPxPos];
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_OUTPUT
Texture2D<FfxFloat32x4> r_output : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_OUTPUT);
FfxFloat32x4 LoadFrameInterpolationOutput(FFX_PARAMETER_IN FfxInt32x2 iPxInput)
{
return r_output[iPxInput];
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_INPAINTING_PYRAMID
Texture2D<FfxFloat32x4> r_inpainting_pyramid : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_INPAINTING_PYRAMID);
FfxFloat32x4 LoadInpaintingPyramid(FFX_PARAMETER_IN FfxInt32 mipLevel, FFX_PARAMETER_IN FfxUInt32x2 iPxInput)
{
return r_inpainting_pyramid.mips[mipLevel][iPxInput];
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_PRESENT_BACKBUFFER
Texture2D<FfxFloat32x4> r_present_backbuffer : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_PRESENT_BACKBUFFER);
FfxFloat32x4 LoadPresentBackbuffer(FFX_PARAMETER_IN FfxInt32x2 iPxInput)
{
return r_present_backbuffer[iPxInput];
}
FfxFloat32x4 SamplePresentBackbuffer(FFX_PARAMETER_IN FfxFloat32x2 fUv)
{
return r_present_backbuffer.SampleLevel(s_LinearClamp, fUv, 0);
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_SRV_COUNTERS
StructuredBuffer<FfxUInt32> r_counters : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_COUNTERS);
FfxUInt32 LoadCounter(FFX_PARAMETER_IN FfxInt32 iPxPos)
{
return r_counters[iPxPos];
}
const FfxUInt32 FrameIndexSinceLastReset()
{
return LoadCounter(COUNTER_FRAME_INDEX_SINCE_LAST_RESET);
}
#endif
#if defined(FFX_FRAMEINTERPOLATION_BIND_SRV_INPUT_DEPTH)
Texture2D<FfxFloat32> r_input_depth : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_INPUT_DEPTH);
FfxFloat32 LoadInputDepth(FfxInt32x2 iPxPos)
{
return r_input_depth[iPxPos];
}
#endif
#if defined(FFX_FRAMEINTERPOLATION_BIND_SRV_INPUT_MOTION_VECTORS)
Texture2D<FfxFloat32x4> r_input_motion_vectors : FFX_DECLARE_SRV(FFX_FRAMEINTERPOLATION_BIND_SRV_INPUT_MOTION_VECTORS);
FfxFloat32x2 LoadInputMotionVector(FfxInt32x2 iPxDilatedMotionVectorPos)
{
FfxFloat32x2 fSrcMotionVector = r_input_motion_vectors[iPxDilatedMotionVectorPos].xy;
FfxFloat32x2 fUvMotionVector = fSrcMotionVector * MotionVectorScale();
#if FFX_FRAMEINTERPOLATION_OPTION_JITTERED_MOTION_VECTORS
fUvMotionVector -= MotionVectorJitterCancellation();
#endif
return fUvMotionVector;
}
#endif
///////////////////////////////////////////////
// declare UAVs and UAV accessors
///////////////////////////////////////////////
#ifdef FFX_FRAMEINTERPOLATION_BIND_UAV_OUTPUT
RWTexture2D<FfxFloat32x4> rw_output : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_OUTPUT);
FfxFloat32x4 RWLoadFrameinterpolationOutput(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return rw_output[iPxPos];
}
void StoreFrameinterpolationOutput(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxFloat32x4 val)
{
rw_output[iPxPos] = val;
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_UAV_DILATED_MOTION_VECTORS
RWTexture2D<FfxFloat32x2> rw_dilated_motion_vectors : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_DILATED_MOTION_VECTORS);
FfxFloat32x2 RWLoadDilatedMotionVectors(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return rw_dilated_motion_vectors[iPxPos];
}
void StoreDilatedMotionVectors(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxFloat32x2 val)
{
rw_dilated_motion_vectors[iPxPos] = val;
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_UAV_DILATED_DEPTH
RWTexture2D<FfxFloat32> rw_dilated_depth : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_DILATED_DEPTH);
FfxFloat32 RWLoadDilatedDepth(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return rw_dilated_depth[iPxPos];
}
void StoreDilatedDepth(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxFloat32 val)
{
rw_dilated_depth[iPxPos] = val;
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_UAV_RECONSTRUCTED_DEPTH_PREVIOUS_FRAME
RWTexture2D<FfxUInt32> rw_reconstructed_depth_previous_frame : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_RECONSTRUCTED_DEPTH_PREVIOUS_FRAME);
FfxFloat32 RWLoadReconstructedDepthPreviousFrame(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return ffxAsFloat(rw_reconstructed_depth_previous_frame[iPxPos]);
}
void UpdateReconstructedDepthPreviousFrame(FfxInt32x2 iPxSample, FfxFloat32 fDepth)
{
FfxUInt32 uDepth = ffxAsUInt32(fDepth);
#if FFX_FRAMEINTERPOLATION_OPTION_INVERTED_DEPTH
InterlockedMax(rw_reconstructed_depth_previous_frame[iPxSample], uDepth);
#else
InterlockedMin(rw_reconstructed_depth_previous_frame[iPxSample], uDepth); // min for standard, max for inverted depth
#endif
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_UAV_RECONSTRUCTED_DEPTH_INTERPOLATED_FRAME
RWTexture2D<FfxUInt32> rw_reconstructed_depth_interpolated_frame : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_RECONSTRUCTED_DEPTH_INTERPOLATED_FRAME);
FfxFloat32 RWLoadReconstructedDepthInterpolatedFrame(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return ffxAsFloat(rw_reconstructed_depth_interpolated_frame[iPxPos]);
}
void StoreReconstructedDepthInterpolatedFrame(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxFloat32 value)
{
FfxUInt32 uDepth = ffxAsUInt32(value);
rw_reconstructed_depth_interpolated_frame[iPxPos] = uDepth;
}
void UpdateReconstructedDepthInterpolatedFrame(FfxInt32x2 iPxSample, FfxFloat32 fDepth)
{
FfxUInt32 uDepth = ffxAsUInt32(fDepth);
#if FFX_FRAMEINTERPOLATION_OPTION_INVERTED_DEPTH
InterlockedMax(rw_reconstructed_depth_interpolated_frame[iPxSample], uDepth);
#else
InterlockedMin(rw_reconstructed_depth_interpolated_frame[iPxSample], uDepth); // min for standard, max for inverted depth
#endif
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_UAV_DISOCCLUSION_MASK
RWTexture2D<FfxFloat32x2> rw_disocclusion_mask : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_DISOCCLUSION_MASK);
FfxFloat32x2 RWLoadDisocclusionMask(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return rw_disocclusion_mask[iPxPos];
}
void StoreDisocclusionMask(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxFloat32x2 val)
{
rw_disocclusion_mask[iPxPos] = val;
}
#endif
#if defined(FFX_FRAMEINTERPOLATION_BIND_UAV_GAME_MOTION_VECTOR_FIELD_X) && \
defined(FFX_FRAMEINTERPOLATION_BIND_UAV_GAME_MOTION_VECTOR_FIELD_Y)
RWTexture2D<FfxUInt32> rw_game_motion_vector_field_x : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_GAME_MOTION_VECTOR_FIELD_X);
RWTexture2D<FfxUInt32> rw_game_motion_vector_field_y : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_GAME_MOTION_VECTOR_FIELD_Y);
FfxUInt32 RWLoadGameMotionVectorFieldX(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return rw_game_motion_vector_field_x[iPxPos];
}
void StoreGameMotionVectorFieldX(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxUInt32 val)
{
rw_game_motion_vector_field_x[iPxPos] = val;
}
FfxUInt32 RWLoadGameMotionVectorFieldY(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return rw_game_motion_vector_field_y[iPxPos];
}
void StoreGameMotionVectorFieldY(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxUInt32 val)
{
rw_game_motion_vector_field_y[iPxPos] = val;
}
void UpdateGameMotionVectorField(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxUInt32x2 packedVector)
{
InterlockedMax(rw_game_motion_vector_field_x[iPxPos], packedVector.x);
InterlockedMax(rw_game_motion_vector_field_y[iPxPos], packedVector.y);
}
FfxUInt32 UpdateGameMotionVectorFieldEx(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxUInt32x2 packedVector)
{
FfxUInt32 uPreviousValueX = 0;
FfxUInt32 uPreviousValueY = 0;
InterlockedMax(rw_game_motion_vector_field_x[iPxPos], packedVector.x, uPreviousValueX);
InterlockedMax(rw_game_motion_vector_field_y[iPxPos], packedVector.y, uPreviousValueY);
const FfxUInt32 uExistingVectorFieldEntry = ffxMax(uPreviousValueX, uPreviousValueY);
return uExistingVectorFieldEntry;
}
#endif
#if defined(FFX_FRAMEINTERPOLATION_BIND_UAV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_X) && \
defined(FFX_FRAMEINTERPOLATION_BIND_UAV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_Y)
RWTexture2D<FfxUInt32> rw_optical_flow_motion_vector_field_x : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_X);
RWTexture2D<FfxUInt32> rw_optical_flow_motion_vector_field_y : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_Y);
FfxUInt32 RWLoadOpticalflowMotionVectorFieldX(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return rw_optical_flow_motion_vector_field_x[iPxPos];
}
void StoreOpticalflowMotionVectorFieldX(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxUInt32 val)
{
rw_optical_flow_motion_vector_field_x[iPxPos] = val;
}
FfxUInt32 RWLoadOpticalflowMotionVectorFieldY(FFX_PARAMETER_IN FfxInt32x2 iPxPos)
{
return rw_optical_flow_motion_vector_field_y[iPxPos];
}
void StoreOpticalflowMotionVectorFieldY(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxUInt32 val)
{
rw_optical_flow_motion_vector_field_y[iPxPos] = val;
}
void UpdateOpticalflowMotionVectorField(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxUInt32x2 packedVector)
{
InterlockedMax(rw_optical_flow_motion_vector_field_x[iPxPos], packedVector.x);
InterlockedMax(rw_optical_flow_motion_vector_field_y[iPxPos], packedVector.y);
}
#endif
#ifdef FFX_FRAMEINTERPOLATION_BIND_UAV_COUNTERS
globallycoherent RWStructuredBuffer<FfxUInt32> rw_counters : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_COUNTERS);
FfxUInt32 RWLoadCounter(FFX_PARAMETER_IN FfxInt32 iPxPos)
{
return rw_counters[iPxPos];
}
void StoreCounter(FFX_PARAMETER_IN FfxInt32 iPxPos, FFX_PARAMETER_IN FfxUInt32 counter)
{
rw_counters[iPxPos] = counter;
}
void AtomicIncreaseCounter(FFX_PARAMETER_IN FfxInt32 iPxPos, FFX_PARAMETER_OUT FfxUInt32 oldVal)
{
InterlockedAdd(rw_counters[iPxPos], 1, oldVal);
}
#endif
#if defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_0) && \
defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_1) && \
defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_2) && \
defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_3) && \
defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_4) && \
defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_5) && \
defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_6) && \
defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_7) && \
defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_8) && \
defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_9) && \
defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_10) && \
defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_11) && \
defined(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_12)
RWTexture2D<FfxFloat32x4> rw_inpainting_pyramid0 : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_0);
RWTexture2D<FfxFloat32x4> rw_inpainting_pyramid1 : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_1);
RWTexture2D<FfxFloat32x4> rw_inpainting_pyramid2 : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_2);
RWTexture2D<FfxFloat32x4> rw_inpainting_pyramid3 : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_3);
RWTexture2D<FfxFloat32x4> rw_inpainting_pyramid4 : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_4);
globallycoherent RWTexture2D<FfxFloat32x4> rw_inpainting_pyramid5 : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_5);
RWTexture2D<FfxFloat32x4> rw_inpainting_pyramid6 : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_6);
RWTexture2D<FfxFloat32x4> rw_inpainting_pyramid7 : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_7);
RWTexture2D<FfxFloat32x4> rw_inpainting_pyramid8 : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_8);
RWTexture2D<FfxFloat32x4> rw_inpainting_pyramid9 : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_9);
RWTexture2D<FfxFloat32x4> rw_inpainting_pyramid10 : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_10);
RWTexture2D<FfxFloat32x4> rw_inpainting_pyramid11 : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_11);
RWTexture2D<FfxFloat32x4> rw_inpainting_pyramid12 : FFX_DECLARE_UAV(FFX_FRAMEINTERPOLATION_BIND_UAV_INPAINTING_PYRAMID_MIPMAP_12);
FfxFloat32x4 RWLoadInpaintingPyramid(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxUInt32 index)
{
#define LOAD(idx) \
if (index == idx) \
{ \
return rw_inpainting_pyramid##idx[iPxPos]; \
}
LOAD(0);
LOAD(1);
LOAD(2);
LOAD(3);
LOAD(4);
LOAD(5);
LOAD(6);
LOAD(7);
LOAD(8);
LOAD(9);
LOAD(10);
LOAD(11);
LOAD(12);
return 0;
#undef LOAD
}
void StoreInpaintingPyramid(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxFloat32x4 outValue, FFX_PARAMETER_IN FfxUInt32 index)
{
#define STORE(idx) \
if (index == idx) \
{ \
rw_inpainting_pyramid##idx[iPxPos] = outValue; \
}
STORE(0);
STORE(1);
STORE(2);
STORE(3);
STORE(4);
STORE(5);
STORE(6);
STORE(7);
STORE(8);
STORE(9);
STORE(10);
STORE(11);
STORE(12);
#undef STORE
}
#endif
#endif // #if defined(FFX_GPU)

View File

@@ -0,0 +1,445 @@
// This file is part of the FidelityFX SDK.
//
// Copyright (C) 2024 Advanced Micro Devices, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if !defined(FFX_FRAMEINTERPOLATION_COMMON_H)
#define FFX_FRAMEINTERPOLATION_COMMON_H
#define FFX_FRAMEINTERPOLATION_DISPATCH_DRAW_DEBUG_TEAR_LINES (1 << 0)
#define FFX_FRAMEINTERPOLATION_DISPATCH_DRAW_DEBUG_RESET_INDICATORS (1 << 1)
#define FFX_FRAMEINTERPOLATION_DISPATCH_DRAW_DEBUG_VIEW (1 << 2)
FFX_STATIC const FfxFloat32 FFX_FRAMEINTERPOLATION_EPSILON = 1e-03f;
FFX_STATIC const FfxFloat32 FFX_FRAMEINTERPOLATION_FLT_MAX = 3.402823466e+38f;
FFX_STATIC const FfxFloat32 FFX_FRAMEINTERPOLATION_FLT_MIN = 1.175494351e-38f;
FFX_STATIC const FfxFloat32 fReconstructedDepthBilinearWeightThreshold = FFX_FRAMEINTERPOLATION_EPSILON;
FfxFloat32 RGBToLuma(FfxFloat32x3 fLinearRgb)
{
return dot(fLinearRgb, FfxFloat32x3(0.2126f, 0.7152f, 0.0722f));
}
FfxFloat32 LinearRec2020ToLuminance(FfxFloat32x3 linearRec2020RGB)
{
FfxFloat32 fY = 0.2627 * linearRec2020RGB.x + 0.678 * linearRec2020RGB.y + 0.0593 * linearRec2020RGB.z;
return fY;
}
FfxFloat32x3 ffxscRGBToLinear(FfxFloat32x3 value, FfxFloat32 minLuminance, FfxFloat32 maxLuminance)
{
FfxFloat32x3 p = value - ffxBroadcast3(minLuminance / 80.0f);
return p / ffxBroadcast3((maxLuminance - minLuminance) / 80.0f);
}
FfxFloat32x3 RawRGBToLinear(FfxFloat32x3 fRawRgb)
{
FfxFloat32x3 fLinearRgb;
switch (BackBufferTransferFunction())
{
case 0:
fLinearRgb = ffxLinearFromSrgb(fRawRgb);
break;
case 1:
fLinearRgb = ffxLinearFromPQ(fRawRgb) * (10000.0f / MaxLuminance());
break;
case 2:
fLinearRgb = ffxscRGBToLinear(fRawRgb, MinLuminance(), MaxLuminance());
break;
}
return fLinearRgb;
}
FfxFloat32 RawRGBToLuminance(FfxFloat32x3 fRawRgb)
{
FfxFloat32 fLuminance = 0.0f;
switch (BackBufferTransferFunction())
{
case 0:
fLuminance = RGBToLuma(RawRGBToLinear(fRawRgb));
break;
case 1:
fLuminance = LinearRec2020ToLuminance(RawRGBToLinear(fRawRgb));
break;
case 2:
fLuminance = RGBToLuma(RawRGBToLinear(fRawRgb));
break;
}
return fLuminance;
}
FfxFloat32 RawRGBToPerceivedLuma(FfxFloat32x3 fRawRgb)
{
FfxFloat32 fLuminance = RawRGBToLuminance(fRawRgb);
FfxFloat32 fPercievedLuminance = 0;
if (fLuminance <= 216.0f / 24389.0f)
{
fPercievedLuminance = fLuminance * (24389.0f / 27.0f);
}
else
{
fPercievedLuminance = ffxPow(fLuminance, 1.0f / 3.0f) * 116.0f - 16.0f;
}
return fPercievedLuminance * 0.01f;
}
struct BilinearSamplingData
{
FfxInt32x2 iOffsets[4];
FfxFloat32 fWeights[4];
FfxInt32x2 iBasePos;
};
BilinearSamplingData GetBilinearSamplingData(FfxFloat32x2 fUv, FfxInt32x2 iSize)
{
BilinearSamplingData data;
FfxFloat32x2 fPxSample = (fUv * iSize) - FfxFloat32x2(0.5f, 0.5f);
data.iBasePos = FfxInt32x2(floor(fPxSample));
FfxFloat32x2 fPxFrac = ffxFract(fPxSample);
data.iOffsets[0] = FfxInt32x2(0, 0);
data.iOffsets[1] = FfxInt32x2(1, 0);
data.iOffsets[2] = FfxInt32x2(0, 1);
data.iOffsets[3] = FfxInt32x2(1, 1);
data.fWeights[0] = (1 - fPxFrac.x) * (1 - fPxFrac.y);
data.fWeights[1] = (fPxFrac.x) * (1 - fPxFrac.y);
data.fWeights[2] = (1 - fPxFrac.x) * (fPxFrac.y);
data.fWeights[3] = (fPxFrac.x) * (fPxFrac.y);
return data;
}
#if defined(FFX_FRAMEINTERPOLATION_BIND_CB_FRAMEINTERPOLATION)
FfxFloat32 ConvertFromDeviceDepthToViewSpace(FfxFloat32 fDeviceDepth)
{
const FfxFloat32x4 deviceToViewDepth = DeviceToViewSpaceTransformFactors();
return deviceToViewDepth[1] / (fDeviceDepth - deviceToViewDepth[0]);
}
FfxFloat32x2 ComputeNdc(FfxFloat32x2 fPxPos, FfxInt32x2 iSize)
{
return fPxPos / FfxFloat32x2(iSize) * FfxFloat32x2(2.0f, -2.0f) + FfxFloat32x2(-1.0f, 1.0f);
}
FfxFloat32x3 GetViewSpacePosition(FfxInt32x2 iViewportPos, FfxInt32x2 iViewportSize, FfxFloat32 fDeviceDepth)
{
const FfxFloat32x4 fDeviceToViewDepth = DeviceToViewSpaceTransformFactors();
const FfxFloat32 Z = ConvertFromDeviceDepthToViewSpace(fDeviceDepth);
const FfxFloat32x2 fNdcPos = ComputeNdc(iViewportPos, iViewportSize);
const FfxFloat32 X = fDeviceToViewDepth[2] * fNdcPos.x * Z;
const FfxFloat32 Y = fDeviceToViewDepth[3] * fNdcPos.y * Z;
return FfxFloat32x3(X, Y, Z);
}
#endif
FfxBoolean IsOnScreen(FfxInt32x2 pos, FfxInt32x2 size)
{
return all(FFX_LESS_THAN(FfxUInt32x2(pos), FfxUInt32x2(size)));
}
FfxBoolean IsUvInside(FfxFloat32x2 fUv)
{
return (fUv.x > 0.0f && fUv.x < 1.0f) && (fUv.y > 0.0f && fUv.y < 1.0f);
}
FfxBoolean IsInRect(FfxInt32x2 pos, FfxInt32x2 iRectCorner, FfxInt32x2 iRectSize)
{
return (pos.x >= iRectCorner.x && pos.x < (iRectSize.x + iRectCorner.x) && pos.y >= iRectCorner.y && pos.y < (iRectSize.y + iRectCorner.y));
}
FfxFloat32 MinDividedByMax(const FfxFloat32 v0, const FfxFloat32 v1)
{
const FfxFloat32 m = ffxMax(v0, v1);
return m != 0 ? ffxMin(v0, v1) / m : 0;
}
FfxFloat32 NormalizedDot3(const FfxFloat32x3 v0, const FfxFloat32x3 v1)
{
FfxFloat32 fMaxLength = ffxMax(length(v0), length(v1));
return fMaxLength > 0.0f ? dot(v0 / fMaxLength, v1 / fMaxLength) : 1.0f;
}
FfxFloat32 NormalizedDot2(const FfxFloat32x2 v0, const FfxFloat32x2 v1)
{
FfxFloat32 fMaxLength = ffxMax(length(v0), length(v1));
return fMaxLength > 0.0f ? dot(v0 / fMaxLength, v1 / fMaxLength) : 1.0f;
}
FfxFloat32 CalculateStaticContentFactor(FfxFloat32x3 fCurrentInterpolationSource, FfxFloat32x3 fPresentColor)
{
const FfxFloat32x3 fFactor = ffxSaturate(FfxFloat32x3(
ffxSaturate((1.0f - MinDividedByMax(fCurrentInterpolationSource.r, fPresentColor.r)) / 0.1f),
ffxSaturate((1.0f - MinDividedByMax(fCurrentInterpolationSource.g, fPresentColor.g)) / 0.1f),
ffxSaturate((1.0f - MinDividedByMax(fCurrentInterpolationSource.b, fPresentColor.b)) / 0.1f)
));
return max(fFactor.x, max(fFactor.y, fFactor.z));
}
//
// MOTION VECTOR FIELD
//
FFX_STATIC const FfxUInt32 MOTION_VECTOR_FIELD_ENTRY_BIT_COUNT = 32;
// Make sure all bit counts add up to MOTION_VECTOR_FIELD_ENTRY_BIT_COUNT
FFX_STATIC const FfxUInt32 MOTION_VECTOR_FIELD_VECTOR_COEFFICIENT_BIT_COUNT = 16;
FFX_STATIC const FfxUInt32 MOTION_VECTOR_FIELD_PRIORITY_LOW_BIT_COUNT = 5;
FFX_STATIC const FfxUInt32 MOTION_VECTOR_FIELD_PRIORITY_HIGH_BIT_COUNT = 10;
FFX_STATIC const FfxUInt32 MOTION_VECTOR_PRIMARY_VECTOR_INDICATION_BIT_COUNT = 1;
FFX_STATIC const FfxUInt32 MOTION_VECTOR_FIELD_PRIMARY_VECTOR_INDICATION_BIT = (1U << (MOTION_VECTOR_FIELD_ENTRY_BIT_COUNT - 1));
FFX_STATIC const FfxUInt32 PRIORITY_LOW_MAX = (1U << MOTION_VECTOR_FIELD_PRIORITY_LOW_BIT_COUNT) - 1;
FFX_STATIC const FfxUInt32 PRIORITY_HIGH_MAX = (1U << MOTION_VECTOR_FIELD_PRIORITY_HIGH_BIT_COUNT) - 1;
FFX_STATIC const FfxUInt32 PRIORITY_LOW_OFFSET = MOTION_VECTOR_FIELD_VECTOR_COEFFICIENT_BIT_COUNT;
FFX_STATIC const FfxUInt32 PRIORITY_HIGH_OFFSET = PRIORITY_LOW_OFFSET + MOTION_VECTOR_FIELD_PRIORITY_LOW_BIT_COUNT;
FFX_STATIC const FfxUInt32 PRIMARY_VECTOR_INDICATION_OFFSET = PRIORITY_HIGH_OFFSET + MOTION_VECTOR_FIELD_PRIORITY_HIGH_BIT_COUNT;
struct VectorFieldEntry
{
FfxFloat32x2 fMotionVector;
FfxFloat32 uHighPriorityFactor;
FfxFloat32 uLowPriorityFactor;
FfxBoolean bValid;
FfxBoolean bPrimary;
FfxBoolean bSecondary;
FfxBoolean bInPainted;
FfxFloat32 fVelocity;
FfxBoolean bNegOutside;
FfxBoolean bPosOutside;
};
VectorFieldEntry NewVectorFieldEntry()
{
VectorFieldEntry vfe;
vfe.fMotionVector = FfxFloat32x2(0.0, 0.0);
vfe.uHighPriorityFactor = 0.0;
vfe.uLowPriorityFactor = 0.0;
vfe.bValid = false;
vfe.bPrimary = false;
vfe.bSecondary = false;
vfe.bInPainted = false;
vfe.fVelocity = 0.0;
vfe.bNegOutside = false;
vfe.bPosOutside = false;
return vfe;
}
FfxBoolean PackedVectorFieldEntryIsPrimary(FfxUInt32 packedEntry)
{
return ((packedEntry & MOTION_VECTOR_FIELD_PRIMARY_VECTOR_INDICATION_BIT) != 0);
}
FfxUInt32x2 PackVectorFieldEntries(FfxBoolean bIsPrimary, FfxUInt32 uHighPriorityFactor, FfxUInt32 uLowPriorityFactor, FfxFloat32x2 fMotionVector)
{
const FfxUInt32 uPriority =
(FfxUInt32(bIsPrimary) * MOTION_VECTOR_FIELD_PRIMARY_VECTOR_INDICATION_BIT)
| ((uHighPriorityFactor & PRIORITY_HIGH_MAX) << PRIORITY_HIGH_OFFSET)
| ((uLowPriorityFactor & PRIORITY_LOW_MAX) << PRIORITY_LOW_OFFSET);
FfxUInt32 packedX = uPriority | ffxF32ToF16(fMotionVector.x);
FfxUInt32 packedY = uPriority | ffxF32ToF16(fMotionVector.y);
return FfxUInt32x2(packedX, packedY);
}
void UnpackVectorFieldEntries(FfxUInt32x2 packed, out VectorFieldEntry vfElement)
{
vfElement.uHighPriorityFactor = FfxFloat32((packed.x >> PRIORITY_HIGH_OFFSET) & PRIORITY_HIGH_MAX) / PRIORITY_HIGH_MAX;
vfElement.uLowPriorityFactor = FfxFloat32((packed.x >> PRIORITY_LOW_OFFSET) & PRIORITY_LOW_MAX) / PRIORITY_LOW_MAX;
vfElement.bPrimary = PackedVectorFieldEntryIsPrimary(packed.x);
vfElement.bValid = (vfElement.uHighPriorityFactor > 0.0f);
vfElement.bSecondary = vfElement.bValid && !vfElement.bPrimary;
// Reverse priority factor for secondary vectors
if (vfElement.bSecondary)
{
vfElement.uHighPriorityFactor = 1.0f - vfElement.uHighPriorityFactor;
}
vfElement.fMotionVector.x = ffxUnpackF32(packed.x).x;
vfElement.fMotionVector.y = ffxUnpackF32(packed.y).x;
vfElement.bInPainted = false;
}
//
// MOTION VECTOR FIELD
//
#if defined(FFX_FRAMEINTERPOLATION_BIND_SRV_INPAINTING_PYRAMID)
FfxFloat32x4 ComputeMvInpaintingLevel(FfxFloat32x2 fUv, const FfxInt32 iMipLevel, const FfxInt32x2 iTexSize)
{
BilinearSamplingData bilinearInfo = GetBilinearSamplingData(fUv, iTexSize);
FfxFloat32 fSum = 0.0f;
FfxFloat32x4 fColor = FfxFloat32x4(0.0, 0.0, 0.0, 0.0);
fColor.z = 0;
const FfxFloat32 fMaxPriorityFactor = 1.0f;
for (FfxInt32 iSampleIndex = 0; iSampleIndex < 4; iSampleIndex++)
{
const FfxInt32x2 iOffset = bilinearInfo.iOffsets[iSampleIndex];
const FfxInt32x2 iSamplePos = bilinearInfo.iBasePos + iOffset;
if (IsOnScreen(iSamplePos, iTexSize))
{
FfxFloat32x4 fSample = LoadInpaintingPyramid(iMipLevel, iSamplePos);
const FfxFloat32 fPriorityFactor = fSample.z;
const FfxFloat32 fValidMvFactor = FfxFloat32(fSample.z > 0);
const FfxFloat32 fSampleWeight = bilinearInfo.fWeights[iSampleIndex] * fValidMvFactor * fPriorityFactor;
fSum += fSampleWeight;
fColor += fSample * fSampleWeight;
}
}
fColor /= (fSum > 0.0f) ? fSum : 1.0f;
return fColor;
}
#if defined(FFX_FRAMEINTERPOLATION_BIND_CB_FRAMEINTERPOLATION) && \
defined(FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_X) && \
defined(FFX_FRAMEINTERPOLATION_BIND_SRV_GAME_MOTION_VECTOR_FIELD_Y)
void LoadInpaintedGameFieldMv(FfxFloat32x2 fUv, out VectorFieldEntry vfElement)
{
FfxInt32x2 iPxSample = FfxInt32x2(fUv * RenderSize());
FfxUInt32x2 packedGameFieldMv = LoadGameFieldMv(iPxSample);
UnpackVectorFieldEntries(packedGameFieldMv, vfElement);
if (!vfElement.bValid)
{
//FfxFloat32x2 fUv = (FfxFloat32x2(iPxSample) + 0.5f) / RenderSize();
FfxInt32x2 iTexSize = RenderSize();
FfxFloat32x4 fInPaintedVector = FfxFloat32x4(0.0, 0.0, 0.0, 0.0);
for (FfxInt32 iMipLevel = 0; iMipLevel < 11 && (fInPaintedVector.w == 0.0f); iMipLevel++)
{
iTexSize /= 2;
fInPaintedVector = ComputeMvInpaintingLevel(fUv, iMipLevel, iTexSize);
}
vfElement.fMotionVector = fInPaintedVector.xy;
vfElement.uHighPriorityFactor = fInPaintedVector.z;
vfElement.uLowPriorityFactor = fInPaintedVector.w;
vfElement.bInPainted = true;
}
vfElement.bNegOutside = !IsUvInside(fUv - vfElement.fMotionVector);
vfElement.bPosOutside = !IsUvInside(fUv + vfElement.fMotionVector);
vfElement.fVelocity = length(vfElement.fMotionVector);
}
#endif
#endif
#if defined(FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_X) && \
defined(FFX_FRAMEINTERPOLATION_BIND_SRV_OPTICAL_FLOW_MOTION_VECTOR_FIELD_Y) && \
defined(FFX_FRAMEINTERPOLATION_BIND_CB_FRAMEINTERPOLATION)
void SampleOpticalFlowMotionVectorField(FfxFloat32x2 fUv, out VectorFieldEntry vfElement)
{
const FfxFloat32 scaleFactor = 1.0f;
BilinearSamplingData bilinearInfo = GetBilinearSamplingData(fUv, FfxInt32x2(GetOpticalFlowSize2() * scaleFactor));
vfElement = NewVectorFieldEntry();
FfxFloat32 fWeightSum = 0.0f;
for (FfxInt32 iSampleIndex = 0; iSampleIndex < 4; iSampleIndex++)
{
const FfxInt32x2 iOffset = bilinearInfo.iOffsets[iSampleIndex];
const FfxInt32x2 iSamplePos = bilinearInfo.iBasePos + iOffset;
if (IsOnScreen(iSamplePos, FfxInt32x2(GetOpticalFlowSize2() * scaleFactor)))
{
const FfxFloat32 fWeight = bilinearInfo.fWeights[iSampleIndex];
VectorFieldEntry fOfVectorSample = NewVectorFieldEntry();
FfxInt32x2 packedOpticalFlowMv = FfxInt32x2(LoadOpticalFlowFieldMv(iSamplePos));
UnpackVectorFieldEntries(packedOpticalFlowMv, fOfVectorSample);
vfElement.fMotionVector += fOfVectorSample.fMotionVector * fWeight;
vfElement.uHighPriorityFactor += fOfVectorSample.uHighPriorityFactor * fWeight;
vfElement.uLowPriorityFactor += fOfVectorSample.uLowPriorityFactor * fWeight;
fWeightSum += fWeight;
}
}
if (fWeightSum > 0.0f)
{
vfElement.fMotionVector /= fWeightSum;
vfElement.uHighPriorityFactor /= fWeightSum;
vfElement.uLowPriorityFactor /= fWeightSum;
}
vfElement.bNegOutside = !IsUvInside(fUv - vfElement.fMotionVector);
vfElement.bPosOutside = !IsUvInside(fUv + vfElement.fMotionVector);
vfElement.fVelocity = length(vfElement.fMotionVector);
}
#endif
FfxFloat32x3 Tonemap(FfxFloat32x3 fRgb)
{
return fRgb / (ffxMax(ffxMax(0.f, fRgb.r), ffxMax(fRgb.g, fRgb.b)) + 1.f).xxx;
}
FfxFloat32x3 InverseTonemap(FfxFloat32x3 fRgb)
{
return fRgb / ffxMax(FFX_TONEMAP_EPSILON, 1.f - ffxMax(fRgb.r, ffxMax(fRgb.g, fRgb.b))).xxx;
}
FfxInt32x2 ComputeHrPosFromLrPos(FfxInt32x2 iPxLrPos)
{
FfxFloat32x2 fSrcJitteredPos = FfxFloat32x2(iPxLrPos) + 0.5f - Jitter();
FfxFloat32x2 fLrPosInHr = (fSrcJitteredPos / RenderSize()) * DisplaySize();
FfxInt32x2 iPxHrPos = FfxInt32x2(floor(fLrPosInHr));
return iPxHrPos;
}
#if FFX_HALF
FFX_MIN16_I2 ComputeHrPosFromLrPos(FFX_MIN16_I2 iPxLrPos)
{
FFX_MIN16_F2 fSrcJitteredPos = FFX_MIN16_F2(iPxLrPos) + FFX_MIN16_F(0.5f) - FFX_MIN16_F2(Jitter());
FFX_MIN16_F2 fLrPosInHr = (fSrcJitteredPos / FFX_MIN16_F2(RenderSize())) * FFX_MIN16_F2(DisplaySize());
FFX_MIN16_I2 iPxHrPos = FFX_MIN16_I2(floor(fLrPosInHr));
return iPxHrPos;
}
#endif
#endif //!defined(FFX_FRAMEINTERPOLATION_COMMON_H)

View File

@@ -0,0 +1,121 @@
// This file is part of the FidelityFX SDK.
//
// Copyright (C) 2024 Advanced Micro Devices, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef FFX_FRAMEINTERPOLATION_COMPUTE_GAME_VECTOR_FIELD_INPAINTING_PYRAMID_H
#define FFX_FRAMEINTERPOLATION_COMPUTE_GAME_VECTOR_FIELD_INPAINTING_PYRAMID_H
#include "ffx_frameinterpolation_common.h"
//--------------------------------------------------------------------------------------
// Buffer definitions - global atomic counter
//--------------------------------------------------------------------------------------
FFX_GROUPSHARED FfxUInt32 spdCounter;
FFX_GROUPSHARED FfxFloat32 spdIntermediateR[16][16];
FFX_GROUPSHARED FfxFloat32 spdIntermediateG[16][16];
FFX_GROUPSHARED FfxFloat32 spdIntermediateB[16][16];
FFX_GROUPSHARED FfxFloat32 spdIntermediateA[16][16];
FfxFloat32x4 SpdLoadSourceImage(FfxInt32x2 tex, FfxUInt32 slice)
{
VectorFieldEntry gameMv;
FfxUInt32x2 packedGameFieldMv = LoadGameFieldMv(tex);
UnpackVectorFieldEntries(packedGameFieldMv, gameMv);
return FfxFloat32x4(gameMv.fMotionVector, gameMv.uHighPriorityFactor, gameMv.uLowPriorityFactor) * FfxFloat32(DisplaySize().x > 0);
}
FfxFloat32x4 SpdLoad(FfxInt32x2 tex, FfxUInt32 slice)
{
return RWLoadInpaintingPyramid(tex, 5);
}
void SpdStore(FfxInt32x2 pix, FfxFloat32x4 outValue, FfxUInt32 index, FfxUInt32 slice)
{
StoreInpaintingPyramid(pix, outValue, index);
}
void SpdIncreaseAtomicCounter(FfxUInt32 slice)
{
AtomicIncreaseCounter(COUNTER_SPD, spdCounter);
}
FfxUInt32 SpdGetAtomicCounter()
{
return spdCounter;
}
void SpdResetAtomicCounter(FfxUInt32 slice)
{
StoreCounter(COUNTER_SPD, 0);
}
FfxFloat32x4 SpdLoadIntermediate(FfxUInt32 x, FfxUInt32 y)
{
return FfxFloat32x4(
spdIntermediateR[x][y],
spdIntermediateG[x][y],
spdIntermediateB[x][y],
spdIntermediateA[x][y]);
}
void SpdStoreIntermediate(FfxUInt32 x, FfxUInt32 y, FfxFloat32x4 value)
{
spdIntermediateR[x][y] = value.x;
spdIntermediateG[x][y] = value.y;
spdIntermediateB[x][y] = value.z;
spdIntermediateA[x][y] = value.w;
}
FfxFloat32x4 SpdReduce4(FfxFloat32x4 v0, FfxFloat32x4 v1, FfxFloat32x4 v2, FfxFloat32x4 v3)
{
FfxFloat32x4 vec = FfxFloat32x4(0,0,0,0);
FfxFloat32 fWeightSum = 0.0f;
#define ADD(SAMPLE) { \
FfxFloat32 fWeight = FfxFloat32(SAMPLE.z > 0.0f); \
vec += SAMPLE * fWeight; \
fWeightSum += fWeight; \
}
ADD(v0);
ADD(v1);
ADD(v2);
ADD(v3);
vec /= (fWeightSum > FFX_FRAMEINTERPOLATION_EPSILON) ? fWeightSum : 1.0f;
return vec;
}
#include "spd/ffx_spd.h"
void computeFrameinterpolationGameVectorFieldInpaintingPyramid(FfxInt32x3 iGroupId, FfxInt32 iLocalIndex)
{
SpdDownsample(
FfxUInt32x2(iGroupId.xy),
FfxUInt32(iLocalIndex),
FfxUInt32(NumMips()),
FfxUInt32(NumWorkGroups()),
FfxUInt32(iGroupId.z),
FfxUInt32x2(WorkGroupOffset()));
}
#endif // FFX_FRAMEINTERPOLATION_COMPUTE_GAME_VECTOR_FIELD_INPAINTING_PYRAMID_H

View File

@@ -0,0 +1,120 @@
// This file is part of the FidelityFX SDK.
//
// Copyright (C) 2024 Advanced Micro Devices, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef FFX_FRAMEINTERPOLATION_COMPUTE_INPAINTING_PYRAMID_H
#define FFX_FRAMEINTERPOLATION_COMPUTE_INPAINTING_PYRAMID_H
//--------------------------------------------------------------------------------------
// Buffer definitions - global atomic counter
//--------------------------------------------------------------------------------------
FFX_GROUPSHARED FfxUInt32 spdCounter;
FFX_GROUPSHARED FfxFloat32 spdIntermediateR[16][16];
FFX_GROUPSHARED FfxFloat32 spdIntermediateG[16][16];
FFX_GROUPSHARED FfxFloat32 spdIntermediateB[16][16];
FFX_GROUPSHARED FfxFloat32 spdIntermediateA[16][16];
FfxFloat32x4 SpdLoadSourceImage(FfxInt32x2 tex, FfxUInt32 slice)
{
FfxFloat32x4 fColor = LoadFrameInterpolationOutput(tex) * FfxFloat32(DisplaySize().x > 0);
// reverse sample weights
fColor.w = ffxSaturate(1.0f - fColor.w);
if (tex.x < InterpolationRectBase().x || tex.x >= (InterpolationRectSize().x + InterpolationRectBase().x) || tex.y < InterpolationRectBase().y ||
tex.y >= (InterpolationRectSize().y + InterpolationRectBase().y))
{
fColor.w = 0.0f; // don't take contributions from outside of the interpolation rect
}
return fColor;
}
FfxFloat32x4 SpdLoad(FfxInt32x2 tex, FfxUInt32 slice)
{
return RWLoadInpaintingPyramid(tex, 5);
}
void SpdStore(FfxInt32x2 pix, FfxFloat32x4 outValue, FfxUInt32 index, FfxUInt32 slice)
{
StoreInpaintingPyramid(pix, outValue, index);
}
void SpdIncreaseAtomicCounter(FfxUInt32 slice)
{
AtomicIncreaseCounter(COUNTER_SPD, spdCounter);
}
FfxUInt32 SpdGetAtomicCounter()
{
return spdCounter;
}
void SpdResetAtomicCounter(FfxUInt32 slice)
{
StoreCounter(COUNTER_SPD, 0);
}
FfxFloat32x4 SpdLoadIntermediate(FfxUInt32 x, FfxUInt32 y)
{
return FfxFloat32x4(
spdIntermediateR[x][y],
spdIntermediateG[x][y],
spdIntermediateB[x][y],
spdIntermediateA[x][y]);
}
void SpdStoreIntermediate(FfxUInt32 x, FfxUInt32 y, FfxFloat32x4 value)
{
spdIntermediateR[x][y] = value.x;
spdIntermediateG[x][y] = value.y;
spdIntermediateB[x][y] = value.z;
spdIntermediateA[x][y] = value.w;
}
FfxFloat32x4 SpdReduce4(FfxFloat32x4 v0, FfxFloat32x4 v1, FfxFloat32x4 v2, FfxFloat32x4 v3)
{
FfxFloat32x4 w = FfxFloat32x4(v0.w, v1.w, v2.w, v3.w);
FfxFloat32 sum = (w[0] + w[1] + w[2] + w[3]);
if (sum == 0.0f) {
return FfxFloat32x4(0.0, 0.0, 0.0, 0.0);
}
return (v0 * w[0] + v1 * w[1] + v2 * w[2] + v3 * w[3]) / sum;
}
#include "spd/ffx_spd.h"
void computeFrameinterpolationInpaintingPyramid(FfxInt32x3 iGroupId, FfxInt32 iLocalIndex)
{
SpdDownsample(
FfxUInt32x2(iGroupId.xy),
FfxUInt32(iLocalIndex),
FfxUInt32(NumMips()),
FfxUInt32(NumWorkGroups()),
FfxUInt32(iGroupId.z),
FfxUInt32x2(WorkGroupOffset()));
}
#endif // FFX_FRAMEINTERPOLATION_COMPUTE_INPAINTING_PYRAMID_H

View File

@@ -0,0 +1,163 @@
// This file is part of the FidelityFX SDK.
//
// Copyright (C) 2024 Advanced Micro Devices, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef FFX_FRAMEINTERPOLATION_DEBUG_VIEW_H
#define FFX_FRAMEINTERPOLATION_DEBUG_VIEW_H
struct FfxFrameInterpolationDebugViewport
{
FfxInt32x2 offset;
FfxInt32x2 size;
};
// Macro to cull and draw debug viewport
#define DRAW_VIEWPORT(function, pos, vp) \
{ \
if (pointIsInsideViewport(pos, vp)) \
{ \
function(pos, vp); \
} \
}
FfxFloat32x2 getTransformedUv(FfxInt32x2 iPxPos, FfxFrameInterpolationDebugViewport vp)
{
FfxFloat32x2 fUv = (FfxFloat32x2(iPxPos - vp.offset) + 0.5f) / vp.size;
return fUv;
}
FfxFloat32x4 getMotionVectorColor(FfxFloat32x2 fMotionVector)
{
return FfxFloat32x4(0.5f + fMotionVector * DisplaySize() * 0.1f, 0.5f, 1.0f);
}
FfxFloat32x4 getUnusedIndicationColor(FfxInt32x2 iPxPos, FfxFrameInterpolationDebugViewport vp)
{
FfxInt32x2 basePos = iPxPos - vp.offset;
FfxFloat32 ar = FfxFloat32(vp.size.x) / FfxFloat32(vp.size.y);
return FfxFloat32x4(basePos.x == FfxInt32(basePos.y * ar), 0, 0, 1);
}
void drawGameMotionVectorFieldVectors(FfxInt32x2 iPxPos, FfxFrameInterpolationDebugViewport vp)
{
FfxFloat32x2 fUv = getTransformedUv(iPxPos, vp);
VectorFieldEntry gameMv;
LoadInpaintedGameFieldMv(fUv, gameMv);
StoreFrameinterpolationOutput(iPxPos, getMotionVectorColor(gameMv.fMotionVector));
}
void drawGameMotionVectorFieldDepthPriority(FfxInt32x2 iPxPos, FfxFrameInterpolationDebugViewport vp)
{
FfxFloat32x2 fUv = getTransformedUv(iPxPos, vp);
VectorFieldEntry gameMv;
LoadInpaintedGameFieldMv(fUv, gameMv);
StoreFrameinterpolationOutput(iPxPos, FfxFloat32x4(0, gameMv.uHighPriorityFactor, 0, 1));
}
void drawOpticalFlowMotionVectorField(FfxInt32x2 iPxPos, FfxFrameInterpolationDebugViewport vp)
{
FfxFloat32x2 fUv = getTransformedUv(iPxPos, vp);
VectorFieldEntry ofMv;
SampleOpticalFlowMotionVectorField(fUv, ofMv);
StoreFrameinterpolationOutput(iPxPos, getMotionVectorColor(ofMv.fMotionVector));
}
void drawDisocclusionMask(FfxInt32x2 iPxPos, FfxFrameInterpolationDebugViewport vp)
{
FfxFloat32x2 fUv = getTransformedUv(iPxPos, vp);
FfxFloat32x2 fLrUv = fUv * (FfxFloat32x2(RenderSize()) / GetMaxRenderSize());
FfxFloat32x2 fDisocclusionFactor = ffxSaturate(SampleDisocclusionMask(fLrUv).xy);
StoreFrameinterpolationOutput(iPxPos, FfxFloat32x4(fDisocclusionFactor, 0, 1));
}
void drawPresentBackbuffer(FfxInt32x2 iPxPos, FfxFrameInterpolationDebugViewport vp)
{
FfxFloat32x2 fUv = getTransformedUv(iPxPos, vp);
FfxFloat32x4 fPresentColor = getUnusedIndicationColor(iPxPos, vp);
if (GetHUDLessAttachedFactor() == 1)
{
fPresentColor = SamplePresentBackbuffer(fUv);
}
StoreFrameinterpolationOutput(iPxPos, fPresentColor);
}
void drawCurrentInterpolationSource(FfxInt32x2 iPxPos, FfxFrameInterpolationDebugViewport vp)
{
FfxFloat32x2 fUv = getTransformedUv(iPxPos, vp);
FfxFloat32x4 fCurrentBackBuffer = FfxFloat32x4(SampleCurrentBackbuffer(fUv), 1.0f);
StoreFrameinterpolationOutput(iPxPos, fCurrentBackBuffer);
}
FfxBoolean pointIsInsideViewport(FfxInt32x2 iPxPos, FfxFrameInterpolationDebugViewport vp)
{
FfxInt32x2 extent = vp.offset + vp.size;
return (iPxPos.x >= vp.offset.x && iPxPos.x < extent.x) && (iPxPos.y >= vp.offset.y && iPxPos.y < extent.y);
}
void computeDebugView(FfxInt32x2 iPxPos)
{
#define VIEWPORT_GRID_SIZE_X 3
#define VIEWPORT_GRID_SIZE_Y 3
FfxFloat32x2 fViewportScale = FfxFloat32x2(1.0f / VIEWPORT_GRID_SIZE_X, 1.0f / VIEWPORT_GRID_SIZE_Y);
FfxInt32x2 iViewportSize = FfxInt32x2(DisplaySize() * fViewportScale);
// compute grid [y][x] for easier placement of viewports
FfxFrameInterpolationDebugViewport vp[VIEWPORT_GRID_SIZE_Y][VIEWPORT_GRID_SIZE_X];
for (FfxInt32 y = 0; y < VIEWPORT_GRID_SIZE_Y; y++)
{
for (FfxInt32 x = 0; x < VIEWPORT_GRID_SIZE_X; x++)
{
vp[y][x].offset = iViewportSize * FfxInt32x2(x, y);
vp[y][x].size = iViewportSize;
}
}
// top row
DRAW_VIEWPORT(drawGameMotionVectorFieldVectors, iPxPos, vp[0][0]);
DRAW_VIEWPORT(drawGameMotionVectorFieldDepthPriority, iPxPos, vp[0][1]);
DRAW_VIEWPORT(drawOpticalFlowMotionVectorField, iPxPos, vp[0][2]);
// bottom row
DRAW_VIEWPORT(drawDisocclusionMask, iPxPos, vp[2][0]);
DRAW_VIEWPORT(drawCurrentInterpolationSource, iPxPos, vp[2][1]);
DRAW_VIEWPORT(drawPresentBackbuffer, iPxPos, vp[2][2]);
}
#endif // FFX_FRAMEINTERPOLATION_DEBUG_VIEW_H

View File

@@ -0,0 +1,142 @@
// This file is part of the FidelityFX SDK.
//
// Copyright (C) 2024 Advanced Micro Devices, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef FFX_FRAMEINTERPOLATION_DISOCCLUSION_MASK_H
#define FFX_FRAMEINTERPOLATION_DISOCCLUSION_MASK_H
FFX_STATIC const FfxFloat32 DepthClipBaseScale = 1.0f;
FfxFloat32 ComputeSampleDepthClip(FfxInt32x2 iPxSamplePos, FfxFloat32 fPreviousDepth, FfxFloat32 fPreviousDepthBilinearWeight, FfxFloat32 fCurrentDepthViewSpace)
{
FfxFloat32 fPrevNearestDepthViewSpace = ConvertFromDeviceDepthToViewSpace(fPreviousDepth);
// Depth separation logic ref: See "Minimum Triangle Separation for Correct Z-Buffer Occlusion"
// Intention: worst case of formula in Figure4 combined with Ksep factor in Section 4
const FfxFloat32 fHalfViewportWidth = RenderSize().x * 0.5f;
FfxFloat32 fDepthThreshold = ffxMax(fCurrentDepthViewSpace, fPrevNearestDepthViewSpace);
// WARNING: Ksep only works with reversed-z with infinite projection.
const FfxFloat32 Ksep = 1.37e-05f;
FfxFloat32 fRequiredDepthSeparation = Ksep * fDepthThreshold * TanHalfFoV() * fHalfViewportWidth;
FfxFloat32 fDepthDiff = fCurrentDepthViewSpace - fPrevNearestDepthViewSpace;
FfxFloat32 fDepthClipFactor = (fDepthDiff > 0) ? ffxSaturate(fRequiredDepthSeparation / fDepthDiff) : 1.0f;
return fPreviousDepthBilinearWeight * fDepthClipFactor * ffxLerp(1.0f, DepthClipBaseScale, ffxSaturate(fDepthDiff * fDepthDiff));
}
FfxFloat32 LoadEstimatedDepth(FfxUInt32 estimatedIndex, FfxInt32x2 iSamplePos)
{
if (estimatedIndex == 0)
{
return LoadReconstructedDepthPreviousFrame(iSamplePos);
}
else if (estimatedIndex == 1)
{
return LoadDilatedDepth(iSamplePos);
}
return 0;
}
FfxFloat32 ComputeDepthClip(FfxUInt32 estimatedIndex, FfxFloat32x2 fUvSample, FfxFloat32 fCurrentDepthSample)
{
FfxFloat32 fCurrentDepthViewSpace = ConvertFromDeviceDepthToViewSpace(fCurrentDepthSample);
BilinearSamplingData bilinearInfo = GetBilinearSamplingData(fUvSample, RenderSize());
FfxFloat32 fDilatedSum = 0.0f;
FfxFloat32 fDepth = 0.0f;
FfxFloat32 fWeightSum = 0.0f;
for (FfxInt32 iSampleIndex = 0; iSampleIndex < 4; iSampleIndex++) {
const FfxInt32x2 iOffset = bilinearInfo.iOffsets[iSampleIndex];
const FfxInt32x2 iSamplePos = bilinearInfo.iBasePos + iOffset;
if (IsOnScreen(iSamplePos, RenderSize())) {
const FfxFloat32 fWeight = bilinearInfo.fWeights[iSampleIndex];
if (fWeight > fReconstructedDepthBilinearWeightThreshold) {
const FfxFloat32 fPrevDepthSample = LoadEstimatedDepth(estimatedIndex, iSamplePos);
const FfxFloat32 fPrevNearestDepthViewSpace = ConvertFromDeviceDepthToViewSpace(fPrevDepthSample);
const FfxFloat32 fDepthDiff = fCurrentDepthViewSpace - fPrevNearestDepthViewSpace;
if (fDepthDiff > 0.0f) {
#if FFX_FRAMEINTERPOLATION_OPTION_INVERTED_DEPTH
const FfxFloat32 fPlaneDepth = ffxMin(fPrevDepthSample, fCurrentDepthSample);
#else
const FfxFloat32 fPlaneDepth = ffxMax(fPrevDepthSample, fCurrentDepthSample);
#endif
const FfxFloat32x3 fCenter = GetViewSpacePosition(FfxInt32x2(RenderSize() * 0.5f), RenderSize(), fPlaneDepth);
const FfxFloat32x3 fCorner = GetViewSpacePosition(FfxInt32x2(0, 0), RenderSize(), fPlaneDepth);
const FfxFloat32 fHalfViewportWidth = length(FfxFloat32x2(RenderSize()));
const FfxFloat32 fDepthThreshold = ffxMin(fCurrentDepthViewSpace, fPrevNearestDepthViewSpace);
const FfxFloat32 Ksep = 1.37e-05f;
const FfxFloat32 Kfov = length(fCorner) / length(fCenter);
const FfxFloat32 fRequiredDepthSeparation = Ksep * Kfov * fHalfViewportWidth * fDepthThreshold;
const FfxFloat32 fResolutionFactor = ffxSaturate(length(FfxFloat32x2(RenderSize())) / length(FfxFloat32x2(1920.0f, 1080.0f)));
const FfxFloat32 fPower = ffxLerp(1.0f, 3.0f, fResolutionFactor);
fDepth += FfxFloat32((fRequiredDepthSeparation / fDepthDiff) >= 1.0f) * fWeight;
fWeightSum += fWeight;
}
}
}
}
return (fWeightSum > 0.0f) ? ffxSaturate(1.0f - fDepth / fWeightSum) : 0.0f;
}
void computeDisocclusionMask(FfxInt32x2 iPxPos)
{
FfxFloat32 fDilatedDepth = LoadEstimatedInterpolationFrameDepth(iPxPos);
FfxFloat32x2 fDepthUv = (iPxPos + 0.5f) / RenderSize();
FfxFloat32 fCurrentDepthViewSpace = ConvertFromDeviceDepthToViewSpace(fDilatedDepth);
VectorFieldEntry gameMv;
LoadInpaintedGameFieldMv(fDepthUv, gameMv);
const FfxFloat32 fDepthClipInterpolatedToPrevious = 1.0f - ComputeDepthClip(0, fDepthUv + gameMv.fMotionVector, fDilatedDepth);
const FfxFloat32 fDepthClipInterpolatedToCurrent = 1.0f - ComputeDepthClip(1, fDepthUv - gameMv.fMotionVector, fDilatedDepth);
FfxFloat32x2 fDisocclusionMask = FfxFloat32x2(fDepthClipInterpolatedToPrevious, fDepthClipInterpolatedToCurrent);
fDisocclusionMask = FfxFloat32x2(FFX_GREATER_THAN_EQUAL(fDisocclusionMask, ffxBroadcast2(FFX_FRAMEINTERPOLATION_EPSILON)));
// Avoid false disocclusion if primary game vector pointer outside screen area
const FfxFloat32x2 fSrcMotionVector = gameMv.fMotionVector * 2.0f;
const FfxInt32x2 iSamplePosPrevious = FfxInt32x2((fDepthUv + fSrcMotionVector) * RenderSize());
fDisocclusionMask.x = ffxSaturate(fDisocclusionMask.x + FfxFloat32(!IsOnScreen(iSamplePosPrevious, RenderSize())));
const FfxInt32x2 iSamplePosCurrent = FfxInt32x2((fDepthUv - fSrcMotionVector) * RenderSize());
fDisocclusionMask.y = ffxSaturate(fDisocclusionMask.y + FfxFloat32(!IsOnScreen(iSamplePosCurrent, RenderSize())));
StoreDisocclusionMask(iPxPos, fDisocclusionMask);
}
#endif // FFX_FRAMEINTERPOLATION_DISOCCLUSION_MASK_H

View File

@@ -0,0 +1,118 @@
// This file is part of the FidelityFX SDK.
//
// Copyright (C) 2024 Advanced Micro Devices, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef FFX_FRAMEINTERPOLATION_GAME_MOTION_VECTOR_FIELD_H
#define FFX_FRAMEINTERPOLATION_GAME_MOTION_VECTOR_FIELD_H
FfxUInt32 getPriorityFactorFromViewSpaceDepth(FfxFloat32 fViewSpaceDepthInMeters)
{
fViewSpaceDepthInMeters = ffxPow(fViewSpaceDepthInMeters, 0.33f);
FfxUInt32 uPriorityFactor = FfxUInt32(FfxFloat32(1 - (fViewSpaceDepthInMeters * (1.0f / (1.0f + fViewSpaceDepthInMeters)))) * PRIORITY_HIGH_MAX);
return ffxMax(1, uPriorityFactor);
}
void computeGameFieldMvs(FfxInt32x2 iPxPos)
{
const FfxFloat32x2 fUvInScreenSpace = (FfxFloat32x2(iPxPos) + 0.5f) / RenderSize();
const FfxFloat32x2 fUvInInterpolationRectStart = FfxFloat32x2(InterpolationRectBase()) / DisplaySize();
const FfxFloat32x2 fUvLetterBoxScale = FfxFloat32x2(InterpolationRectSize()) / DisplaySize();
const FfxFloat32x2 fUvInInterpolationRect = fUvInInterpolationRectStart + fUvInScreenSpace * fUvLetterBoxScale;
const FfxFloat32 fDepthSample = LoadDilatedDepth(iPxPos);
const FfxFloat32x2 fGameMotionVector = LoadDilatedMotionVector(iPxPos);
const FfxFloat32x2 fMotionVectorHalf = fGameMotionVector * 0.5f;
const FfxFloat32x2 fInterpolatedLocationUv = fUvInScreenSpace + fMotionVectorHalf;
const FfxFloat32 fViewSpaceDepth = ConvertFromDeviceDepthToViewSpace(fDepthSample);
const FfxUInt32 uHighPriorityFactorPrimary = getPriorityFactorFromViewSpaceDepth(fViewSpaceDepth);
FfxFloat32x3 prevBackbufferCol = SamplePreviousBackbuffer(fUvInInterpolationRect).xyz;
FfxFloat32x3 curBackbufferCol = SamplePreviousBackbuffer(fUvInInterpolationRect + fGameMotionVector * fUvLetterBoxScale).xyz;
FfxFloat32 prevLuma = 0.001f + RawRGBToLuminance(prevBackbufferCol);
FfxFloat32 currLuma = 0.001f + RawRGBToLuminance(curBackbufferCol);
FfxUInt32 uLowPriorityFactor = FfxUInt32(ffxRound(ffxPow(MinDividedByMax(prevLuma, currLuma), 1.0f / 1.0f) * PRIORITY_LOW_MAX))
* FfxUInt32(IsUvInside(fUvInInterpolationRect + fGameMotionVector * fUvLetterBoxScale));
// Update primary motion vectors
{
const FfxUInt32x2 packedVectorPrimary = PackVectorFieldEntries(true, uHighPriorityFactorPrimary, uLowPriorityFactor, fMotionVectorHalf);
BilinearSamplingData bilinearInfo = GetBilinearSamplingData(fInterpolatedLocationUv, RenderSize());
for (FfxInt32 iSampleIndex = 0; iSampleIndex < 4; iSampleIndex++)
{
const FfxInt32x2 iOffset = bilinearInfo.iOffsets[iSampleIndex];
const FfxInt32x2 iSamplePos = bilinearInfo.iBasePos + iOffset;
if (IsOnScreen(iSamplePos, RenderSize()))
{
UpdateGameMotionVectorField(iSamplePos, packedVectorPrimary);
}
}
}
// Update secondary vectors
// Main purpose of secondary vectors is to improve quality of inpainted vectors
const FfxBoolean bWriteSecondaryVectors = length(fMotionVectorHalf * RenderSize()) > FFX_FRAMEINTERPOLATION_EPSILON;
if (bWriteSecondaryVectors)
{
FfxBoolean bWriteSecondary = true;
FfxUInt32 uNumPrimaryHits = 0;
const FfxFloat32 fSecondaryStepScale = length(1.0f / RenderSize());
const FfxFloat32x2 fStepMv = normalize(fGameMotionVector);
const FfxFloat32 fBreakDist = ffxMin(length(fMotionVectorHalf), length(FfxFloat32x2(0.5f, 0.5f)));
for (FfxFloat32 fMvScale = fSecondaryStepScale; fMvScale <= fBreakDist && bWriteSecondary; fMvScale += fSecondaryStepScale)
{
const FfxFloat32x2 fSecondaryLocationUv = fInterpolatedLocationUv - fStepMv * fMvScale;
BilinearSamplingData bilinearInfo = GetBilinearSamplingData(fSecondaryLocationUv, RenderSize());
// Reverse depth prio for secondary vectors
FfxUInt32 uHighPriorityFactorSecondary = ffxMax(1, PRIORITY_HIGH_MAX - uHighPriorityFactorPrimary);
const FfxFloat32x2 fToCenter = normalize(FfxFloat32x2(0.5f, 0.5f) - fSecondaryLocationUv);
uLowPriorityFactor = FfxUInt32(ffxMax(0.0f, dot(fToCenter, fStepMv)) * PRIORITY_LOW_MAX);
const FfxUInt32x2 packedVectorSecondary = PackVectorFieldEntries(false, uHighPriorityFactorSecondary, uLowPriorityFactor, fMotionVectorHalf);
// Only write secondary mvs to single bilinear location
for (FfxInt32 iSampleIndex = 0; iSampleIndex < 1; iSampleIndex++)
{
const FfxInt32x2 iOffset = bilinearInfo.iOffsets[iSampleIndex];
const FfxInt32x2 iSamplePos = bilinearInfo.iBasePos + iOffset;
bWriteSecondary = bWriteSecondary && IsOnScreen(iSamplePos, RenderSize());
if (bWriteSecondary)
{
const FfxUInt32 uExistingVectorFieldEntry = UpdateGameMotionVectorFieldEx(iSamplePos, packedVectorSecondary);
uNumPrimaryHits += FfxUInt32(PackedVectorFieldEntryIsPrimary(uExistingVectorFieldEntry));
bWriteSecondary = bWriteSecondary && (uNumPrimaryHits <= 3);
}
}
}
}
}
#endif // FFX_FRAMEINTERPOLATION_GAME_MOTION_VECTOR_FIELD_H

View File

@@ -0,0 +1,150 @@
// This file is part of the FidelityFX SDK.
//
// Copyright (C) 2024 Advanced Micro Devices, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef FFX_FRAMEINTERPOLATION_INPAINTING_H
#define FFX_FRAMEINTERPOLATION_INPAINTING_H
FfxFloat32x4 ComputeInpaintingLevel(FfxFloat32x2 fUv, const FfxInt32 iMipLevel, const FfxInt32x2 iTexSize)
{
BilinearSamplingData bilinearInfo = GetBilinearSamplingData(fUv, iTexSize);
FfxFloat32x4 fColor = FfxFloat32x4(0.0, 0.0, 0.0, 0.0);
for (FfxInt32 iSampleIndex = 0; iSampleIndex < 4; iSampleIndex++) {
const FfxInt32x2 iOffset = bilinearInfo.iOffsets[iSampleIndex];
const FfxInt32x2 iSamplePos = bilinearInfo.iBasePos + iOffset;
if (IsOnScreen(iSamplePos, iTexSize)) {
FfxFloat32x4 fSample = LoadInpaintingPyramid(iMipLevel, iSamplePos);
const FfxFloat32 fWeight = bilinearInfo.fWeights[iSampleIndex] * FfxFloat32(fSample.w > 0.0f);
fColor += FfxFloat32x4(fSample.rgb * fWeight, fWeight);
}
}
return fColor;
}
FfxFloat32x3 ComputeInpainting(FfxInt32x2 iPxPos)
{
FfxFloat32x2 fUv = (iPxPos + 0.5f) / (DisplaySize());
FfxFloat32x4 fColor = FfxFloat32x4(0.0, 0.0, 0.0, 0.0);
FfxFloat32 fWeightSum = 0.0f;
FfxInt32x2 iTexSize = DisplaySize();
for (FfxInt32 iMipLevel = 0; iMipLevel < 10; iMipLevel++) {
iTexSize /= 2;
FfxFloat32x4 fMipColor = ComputeInpaintingLevel(fUv, iMipLevel, iTexSize);
if (fMipColor.w > 0.0f) {
const FfxFloat32x3 fNormalizedMipColor = fMipColor.rgb / fMipColor.w;
const FfxFloat32 fMipWeight = ffxPow(1.0f - iMipLevel / 10.0f, 3.0f) * fMipColor.w;
fColor += FfxFloat32x4(fNormalizedMipColor, 1.0f) * fMipWeight;
}
}
return fColor.rgb / fColor.w;
}
void drawDebugTearLines(FfxInt32x2 iPxPos, inout FfxFloat32x3 fColor, inout FfxBoolean bWriteColor)
{
if (iPxPos.x < 16)
{
fColor.g = 1.f;
bWriteColor = true;
}
else if (iPxPos.x > DisplaySize().x - 16)
{
fColor += GetDebugBarColor();
bWriteColor = true;
}
}
void drawDebugResetIndicators(FfxInt32x2 iPxPos, inout FfxFloat32x3 fColor, inout FfxBoolean bWriteColor)
{
if (iPxPos.y < 32 && Reset())
{
fColor.r = 1.f;
bWriteColor = true;
}
else if (iPxPos.y > 32 && iPxPos.y < 64 && HasSceneChanged())
{
fColor.b = 1.f;
bWriteColor = true;
}
}
void computeInpainting(FfxInt32x2 iPxPos)
{
FfxBoolean bWriteColor = false;
FfxFloat32x4 fInterpolatedColor = RWLoadFrameinterpolationOutput(iPxPos);
const FfxFloat32 fInPaintingWeight = fInterpolatedColor.w;
if (fInPaintingWeight > FFX_FRAMEINTERPOLATION_EPSILON)
{
fInterpolatedColor.rgb = ffxLerp(fInterpolatedColor.rgb, ComputeInpainting(iPxPos) * FfxFloat32(DisplaySize().x > 0), fInPaintingWeight);
bWriteColor = true;
}
if (GetHUDLessAttachedFactor() == 1)
{
const FfxFloat32x3 fCurrentInterpolationSource = LoadCurrentBackbuffer(iPxPos).rgb;
const FfxFloat32x3 fPresentColor = LoadPresentBackbuffer(iPxPos).rgb;
if (any(FFX_GREATER_THAN(abs(fCurrentInterpolationSource - fPresentColor), FfxFloat32x3(0.0, 0.0, 0.0))))
{
const FfxFloat32 fStaticFactor = CalculateStaticContentFactor(RawRGBToLinear(fCurrentInterpolationSource), RawRGBToLinear(fPresentColor));
if (fStaticFactor > FFX_FRAMEINTERPOLATION_EPSILON)
{
fInterpolatedColor.rgb = ffxLerp(fInterpolatedColor.rgb, fPresentColor, fStaticFactor);
bWriteColor = true;
}
}
}
if ((GetDispatchFlags() & FFX_FRAMEINTERPOLATION_DISPATCH_DRAW_DEBUG_TEAR_LINES) != 0)
{
drawDebugTearLines(iPxPos, fInterpolatedColor.rgb, bWriteColor);
}
if ((GetDispatchFlags() & FFX_FRAMEINTERPOLATION_DISPATCH_DRAW_DEBUG_RESET_INDICATORS) != 0)
{
drawDebugResetIndicators(iPxPos, fInterpolatedColor.rgb, bWriteColor);
}
if (bWriteColor)
{
StoreFrameinterpolationOutput(iPxPos, FfxFloat32x4(fInterpolatedColor.rgb, 1.0f));
}
}
#endif // FFX_FRAMEINTERPOLATION_INPAINTING_H

View File

@@ -0,0 +1,124 @@
// This file is part of the FidelityFX SDK.
//
// Copyright (C) 2024 Advanced Micro Devices, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef FFX_FRAMEINTERPOLATION_OPTICAL_FLOW_VECTOR_FIELD_H
#define FFX_FRAMEINTERPOLATION_OPTICAL_FLOW_VECTOR_FIELD_H
void computeOpticalFlowFieldMvs(FfxUInt32x2 dtID, FfxFloat32x2 fOpticalFlowVector)
{
FfxFloat32x2 fUv = FfxFloat32x2(FfxFloat32x2(dtID)+0.5f) / GetOpticalFlowSize2();
const FfxFloat32 scaleFactor = 1.0f;
FfxFloat32x2 fMotionVectorHalf = fOpticalFlowVector * 0.5f;
FfxFloat32 fDilatedDepth = ConvertFromDeviceDepthToViewSpace(LoadDilatedDepth(FfxInt32x2(dtID)));
FfxFloat32x3 prevBackbufferCol = SamplePreviousBackbuffer(fUv).xyz;
FfxFloat32x3 curBackbufferCol = SampleCurrentBackbuffer(fUv + fOpticalFlowVector).xyz;
FfxFloat32 prevLuma = 0.001f + RawRGBToLuminance(prevBackbufferCol);
FfxFloat32 currLuma = 0.001f + RawRGBToLuminance(curBackbufferCol);
FfxFloat32 fVelocity = length(fOpticalFlowVector * InterpolationRectSize());
FfxUInt32 uHighPriorityFactor = FfxUInt32(fVelocity > 1.0f) * FfxUInt32(ffxSaturate(fVelocity / length(InterpolationRectSize() * 0.05f)) * PRIORITY_HIGH_MAX);
if(uHighPriorityFactor > 0) {
FfxUInt32 uLowPriorityFactor = FfxUInt32(ffxRound(ffxPow(MinDividedByMax(prevLuma, currLuma), 1.0f / 1.0f) * PRIORITY_LOW_MAX))
* FfxUInt32(IsUvInside(fUv + fOpticalFlowVector));
// Project current depth into previous frame locations.
// Push to all pixels having some contribution if reprojection is using bilinear logic.
const FfxUInt32x2 packedVectorPrimary = PackVectorFieldEntries(true, uHighPriorityFactor, uLowPriorityFactor, fMotionVectorHalf);
BilinearSamplingData bilinearInfo = GetBilinearSamplingData(fUv + fMotionVectorHalf, GetOpticalFlowSize2());
for (FfxInt32 iSampleIndex = 0; iSampleIndex < 4; iSampleIndex++)
{
const FfxInt32x2 iOffset = bilinearInfo.iOffsets[iSampleIndex];
const FfxInt32x2 iSamplePos = bilinearInfo.iBasePos + iOffset;
if (IsOnScreen(iSamplePos, GetOpticalFlowSize2()))
{
UpdateOpticalflowMotionVectorField(iSamplePos, packedVectorPrimary);
}
}
}
}
void computeOpticalFlowVectorField(FfxInt32x2 iPxPos)
{
FfxFloat32x2 fOpticalFlowVector = FfxFloat32x2(0.0, 0.0);
FfxFloat32x2 fOpticalFlowVector3x3Avg = FfxFloat32x2(0.0, 0.0);
FfxInt32 size = 1;
FfxFloat32 sw = 0.0f;
for(FfxInt32 y = -size; y <= size; y++) {
for(FfxInt32 x = -size; x <= size; x++) {
FfxInt32x2 samplePos = iPxPos + FfxInt32x2(x, y);
FfxFloat32x2 vs = LoadOpticalFlow(samplePos);
FfxFloat32 fConfidenceFactor = ffxMax(FFX_FRAMEINTERPOLATION_EPSILON, LoadOpticalFlowConfidence(samplePos));
FfxFloat32 len = length(vs * InterpolationRectSize());
FfxFloat32 len_factor = ffxMax(0.0f, 512.0f - len) * FfxFloat32(len > 1.0f);
FfxFloat32 w = len_factor;
fOpticalFlowVector3x3Avg += vs * w;
sw += w;
}
}
fOpticalFlowVector3x3Avg /= sw;
sw = 0.0f;
for(FfxInt32 y = -size; y <= size; y++) {
for(FfxInt32 x = -size; x <= size; x++) {
FfxInt32x2 samplePos = iPxPos + FfxInt32x2(x, y);
FfxFloat32x2 vs = LoadOpticalFlow(samplePos);
FfxFloat32 fConfidenceFactor = ffxMax(FFX_FRAMEINTERPOLATION_EPSILON, LoadOpticalFlowConfidence(samplePos));
FfxFloat32 len = length(vs * InterpolationRectSize());
FfxFloat32 len_factor = ffxMax(0.0f, 512.0f - len) * FfxFloat32(len > 1.0f);
FfxFloat32 w = ffxMax(0.0f, ffxPow(dot(fOpticalFlowVector3x3Avg, vs), 1.25f)) * len_factor;
fOpticalFlowVector += vs * w;
sw += w;
}
}
if (sw > FFX_FRAMEINTERPOLATION_EPSILON)
{
fOpticalFlowVector /= sw;
}
computeOpticalFlowFieldMvs(iPxPos, fOpticalFlowVector);
}
#endif // FFX_FRAMEINTERPOLATION_OPTICAL_FLOW_VECTOR_FIELD_H

View File

@@ -0,0 +1,123 @@
// This file is part of the FidelityFX SDK.
//
// Copyright (C) 2024 Advanced Micro Devices, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef FFX_FRAMEINTERPOLATION_RECONSTRUCT_DILATED_VELOCITY_AND_PREVIOUS_DEPTH_H
#define FFX_FRAMEINTERPOLATION_RECONSTRUCT_DILATED_VELOCITY_AND_PREVIOUS_DEPTH_H
void ReconstructPrevDepth(FfxInt32x2 iPxPos, FfxFloat32 fDepth, FfxFloat32x2 fMotionVector, FfxInt32x2 iPxDepthSize)
{
fMotionVector *= FfxFloat32(length(fMotionVector * DisplaySize()) > 0.1f);
FfxFloat32x2 fUv = (iPxPos + FfxFloat32(0.5)) / iPxDepthSize;
FfxFloat32x2 fReprojectedUv = fUv + fMotionVector;
BilinearSamplingData bilinearInfo = GetBilinearSamplingData(fReprojectedUv, RenderSize());
// Project current depth into previous frame locations.
// Push to all pixels having some contribution if reprojection is using bilinear logic.
for (FfxInt32 iSampleIndex = 0; iSampleIndex < 4; iSampleIndex++) {
const FfxInt32x2 iOffset = bilinearInfo.iOffsets[iSampleIndex];
FfxFloat32 fWeight = bilinearInfo.fWeights[iSampleIndex];
if (fWeight > fReconstructedDepthBilinearWeightThreshold) {
FfxInt32x2 iStorePos = bilinearInfo.iBasePos + iOffset;
if (IsOnScreen(iStorePos, iPxDepthSize)) {
UpdateReconstructedDepthPreviousFrame(iStorePos, fDepth);
}
}
}
}
void FindNearestDepth(FFX_PARAMETER_IN FfxInt32x2 iPxPos, FFX_PARAMETER_IN FfxInt32x2 iPxSize, FFX_PARAMETER_OUT FfxFloat32 fNearestDepth, FFX_PARAMETER_OUT FfxInt32x2 fNearestDepthCoord)
{
const FfxInt32 iSampleCount = 9;
const FfxInt32x2 iSampleOffsets[iSampleCount] = {
FfxInt32x2(+0, +0),
FfxInt32x2(+1, +0),
FfxInt32x2(+0, +1),
FfxInt32x2(+0, -1),
FfxInt32x2(-1, +0),
FfxInt32x2(-1, +1),
FfxInt32x2(+1, +1),
FfxInt32x2(-1, -1),
FfxInt32x2(+1, -1),
};
// pull out the depth loads to allow SC to batch them
FfxFloat32 depth[9];
FfxInt32 iSampleIndex = 0;
FFX_UNROLL
for (iSampleIndex = 0; iSampleIndex < iSampleCount; ++iSampleIndex) {
FfxInt32x2 iPos = iPxPos + iSampleOffsets[iSampleIndex];
depth[iSampleIndex] = LoadInputDepth(iPos);
}
// find closest depth
fNearestDepthCoord = iPxPos;
fNearestDepth = depth[0];
FFX_UNROLL
for (iSampleIndex = 1; iSampleIndex < iSampleCount; ++iSampleIndex) {
FfxInt32x2 iPos = iPxPos + iSampleOffsets[iSampleIndex];
if (IsOnScreen(iPos, iPxSize)) {
FfxFloat32 fNdDepth = depth[iSampleIndex];
#if FFX_FRAMEINTERPOLATION_OPTION_INVERTED_DEPTH
if (fNdDepth > fNearestDepth) {
#else
if (fNdDepth < fNearestDepth) {
#endif
fNearestDepthCoord = iPos;
fNearestDepth = fNdDepth;
}
}
}
}
void ReconstructAndDilate(FfxInt32x2 iPxLrPos)
{
FfxFloat32 fDilatedDepth;
FfxInt32x2 iNearestDepthCoord;
FindNearestDepth(iPxLrPos, RenderSize(), fDilatedDepth, iNearestDepthCoord);
#if FFX_FRAMEINTERPOLATION_OPTION_LOW_RES_MOTION_VECTORS
FfxInt32x2 iSamplePos = iPxLrPos;
FfxInt32x2 iMotionVectorPos = iNearestDepthCoord;
#else
FfxInt32x2 iSamplePos = ComputeHrPosFromLrPos(iPxLrPos);
FfxInt32x2 iMotionVectorPos = ComputeHrPosFromLrPos(iNearestDepthCoord);
#endif
FfxFloat32x2 fDilatedMotionVector = LoadInputMotionVector(iMotionVectorPos);
StoreDilatedDepth(iPxLrPos, fDilatedDepth);
StoreDilatedMotionVectors(iPxLrPos, fDilatedMotionVector);
ReconstructPrevDepth(iPxLrPos, fDilatedDepth, fDilatedMotionVector, RenderSize());
}
#endif //!defined( FFX_FRAMEINTERPOLATION_RECONSTRUCT_DILATED_VELOCITY_AND_PREVIOUS_DEPTH_H )

View File

@@ -0,0 +1,59 @@
// This file is part of the FidelityFX SDK.
//
// Copyright (C) 2024 Advanced Micro Devices, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef FFX_FRAMEINTERPOLATION_RECONSTRUCT_PREVIOUS_DEPTH_H
#define FFX_FRAMEINTERPOLATION_RECONSTRUCT_PREVIOUS_DEPTH_H
void ReconstructPrevDepth(FfxInt32x2 iPxPos, FfxUInt32 depthTarget, FfxFloat32 fDepth, FfxFloat32x2 fMotionVector, FfxInt32x2 iPxDepthSize)
{
const FfxFloat32x2 fUv = (iPxPos + FfxFloat32(0.5)) / iPxDepthSize;
// Project current depth into previous frame locations.
// Push to all pixels having some contribution if reprojection is using bilinear logic.
BilinearSamplingData bilinearInfo = GetBilinearSamplingData(fUv + fMotionVector, RenderSize());
for (FfxInt32 iSampleIndex = 0; iSampleIndex < 4; iSampleIndex++)
{
const FfxInt32x2 iOffset = bilinearInfo.iOffsets[iSampleIndex];
const FfxInt32x2 iSamplePos = bilinearInfo.iBasePos + iOffset;
const FfxFloat32 fSampleWeight = bilinearInfo.fWeights[iSampleIndex];
if (fSampleWeight > fReconstructedDepthBilinearWeightThreshold)
{
if (IsOnScreen(iSamplePos, RenderSize()))
{
if (depthTarget != 0) {
UpdateReconstructedDepthInterpolatedFrame(iSamplePos, fDepth);
}
}
}
}
}
void reconstructPreviousDepth(FfxInt32x2 iPxPos)
{
FfxFloat32x2 fMotionVector = LoadDilatedMotionVector(iPxPos);
FfxFloat32 fDilatedDepth = LoadDilatedDepth(iPxPos);
ReconstructPrevDepth(iPxPos, 1, fDilatedDepth, fMotionVector * 0.5f, RenderSize());
}
#endif // FFX_FRAMEINTERPOLATION_RECONSTRUCT_PREVIOUS_DEPTH_H

View File

@@ -0,0 +1,99 @@
// This file is part of the FidelityFX SDK.
//
// Copyright (C) 2024 Advanced Micro Devices, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef FFX_FRAMEINTERPOLATION_RESOURCES_H
#define FFX_FRAMEINTERPOLATION_RESOURCES_H
#if defined(FFX_CPU) || defined(FFX_GPU)
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_NULL 0
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OUTPUT 1
//#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_BACKBUFFER 2
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_PREVIOUS_INTERPOLATION_SOURCE 3
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_CURRENT_INTERPOLATION_SOURCE 4
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_DEPTH 5
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_MOTION_VECTORS 6
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_RESERVED_2 7
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_RESERVED_3 8
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_RESERVED_4 9
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_DILATED_DEPTH 10
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_DILATED_MOTION_VECTORS 11
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_RECONSTRUCTED_DEPTH_PREVIOUS_FRAME 12
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_RECONSTRUCTED_DEPTH_INTERPOLATED_FRAME 13
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_DISOCCLUSION_MASK 14
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_GAME_MOTION_VECTOR_FIELD_X 15
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_GAME_MOTION_VECTOR_FIELD_Y 16
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OPTICAL_FLOW_MOTION_VECTOR_FIELD_X 17
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OPTICAL_FLOW_MOTION_VECTOR_FIELD_Y 18
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OPTICAL_FLOW_VECTOR 19
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_RESERVED_5 20
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OPTICAL_FLOW_CONFIDENCE 21
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OPTICAL_FLOW_GLOBAL_MOTION 22
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_OPTICAL_FLOW_SCENE_CHANGE_DETECTION 23
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_RESERVED_6 25
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_RESERVED_7 26
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_DEBUG_OUTPUT_0 27
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_DEBUG_OUTPUT_1 28
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_DEBUG_OUTPUT 29
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_RESERVED_8 30
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_PRESENT_BACKBUFFER 31
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_COUNTERS 32
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID 33 // same as FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_0
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_0 33
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_1 34
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_2 35
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_3 36
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_4 37
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_5 38
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_6 39
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_7 40
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_8 41
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_9 42
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_10 43
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_11 44
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_INPAINTING_PYRAMID_MIPMAP_12 45
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_DILATED_DEPTH_0 46 // resources for ping ponging if async is enabled.
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_DILATED_DEPTH_1 47 // code relies on them being interleaved
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_DILATED_MOTION_VECTORS_0 48
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_DILATED_MOTION_VECTORS_1 49 // code relies on them being interleaved
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_RECONSTRUCTED_DEPTH_PREVIOUS_FRAME_0 50
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_RECONSTRUCTED_DEPTH_PREVIOUS_FRAME_1 51 // code relies on them being interleaved
#define FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_COUNT 52
#define FFX_FRAMEINTERPOLATION_CONSTANTBUFFER_IDENTIFIER 0
#define FFX_FRAMEINTERPOLATION_INPAINTING_PYRAMID_CONSTANTBUFFER_IDENTIFIER 1
#define FFX_FRAMEINTERPOLATION_CONSTANTBUFFER_COUNT 2
#endif // #if defined(FFX_CPU) || defined(FFX_GPU)
#endif //!defined( FFX_FRAMEINTERPOLATION_RESOURCES_H )

View File

@@ -0,0 +1,50 @@
// This file is part of the FidelityFX SDK.
//
// Copyright (C) 2024 Advanced Micro Devices, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef FFX_FRAMEINTERPOLATION_SETUP_H
#define FFX_FRAMEINTERPOLATION_SETUP_H
void setupFrameinterpolationResources(FfxInt32x2 iPxPos)
{
// Update reset counters
StoreCounter(COUNTER_SPD, 0);
if (all(FFX_EQUAL(iPxPos, FfxInt32x2(0, 0))))
{
if(Reset() || HasSceneChanged()) {
StoreCounter(COUNTER_FRAME_INDEX_SINCE_LAST_RESET, 0);
} else {
FfxUInt32 counter = RWLoadCounter(COUNTER_FRAME_INDEX_SINCE_LAST_RESET);
StoreCounter(COUNTER_FRAME_INDEX_SINCE_LAST_RESET, counter + 1);
}
}
// Reset resources
StoreGameMotionVectorFieldX(iPxPos, 0);
StoreGameMotionVectorFieldY(iPxPos, 0);
StoreOpticalflowMotionVectorFieldX(iPxPos, 0);
StoreOpticalflowMotionVectorFieldY(iPxPos, 0);
StoreDisocclusionMask(iPxPos, FfxFloat32x2(0.0, 0.0));
}
#endif // FFX_FRAMEINTERPOLATION_SETUP_H