Path: blob/master/thirdparty/amd-fsr2/shaders/ffx_fsr2_depth_clip.h
9899 views
// This file is part of the FidelityFX SDK.1//2// Copyright (c) 2022-2023 Advanced Micro Devices, Inc. All rights reserved.3//4// Permission is hereby granted, free of charge, to any person obtaining a copy5// of this software and associated documentation files (the "Software"), to deal6// in the Software without restriction, including without limitation the rights7// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell8// copies of the Software, and to permit persons to whom the Software is9// furnished to do so, subject to the following conditions:10// The above copyright notice and this permission notice shall be included in11// all copies or substantial portions of the Software.12//13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN19// THE SOFTWARE.2021#ifndef FFX_FSR2_DEPTH_CLIP_H22#define FFX_FSR2_DEPTH_CLIP_H2324FFX_STATIC const FfxFloat32 DepthClipBaseScale = 4.0f;2526FfxFloat32 ComputeDepthClip(FfxFloat32x2 fUvSample, FfxFloat32 fCurrentDepthSample)27{28FfxFloat32 fCurrentDepthViewSpace = GetViewSpaceDepth(fCurrentDepthSample);29BilinearSamplingData bilinearInfo = GetBilinearSamplingData(fUvSample, RenderSize());3031FfxFloat32 fDilatedSum = 0.0f;32FfxFloat32 fDepth = 0.0f;33FfxFloat32 fWeightSum = 0.0f;34for (FfxInt32 iSampleIndex = 0; iSampleIndex < 4; iSampleIndex++) {3536const FfxInt32x2 iOffset = bilinearInfo.iOffsets[iSampleIndex];37const FfxInt32x2 iSamplePos = bilinearInfo.iBasePos + iOffset;3839if (IsOnScreen(iSamplePos, RenderSize())) {40const FfxFloat32 fWeight = bilinearInfo.fWeights[iSampleIndex];41if (fWeight > fReconstructedDepthBilinearWeightThreshold) {4243const FfxFloat32 fPrevDepthSample = LoadReconstructedPrevDepth(iSamplePos);44const FfxFloat32 fPrevNearestDepthViewSpace = GetViewSpaceDepth(fPrevDepthSample);4546const FfxFloat32 fDepthDiff = fCurrentDepthViewSpace - fPrevNearestDepthViewSpace;4748if (fDepthDiff > 0.0f) {4950#if FFX_FSR2_OPTION_INVERTED_DEPTH51const FfxFloat32 fPlaneDepth = ffxMin(fPrevDepthSample, fCurrentDepthSample);52#else53const FfxFloat32 fPlaneDepth = ffxMax(fPrevDepthSample, fCurrentDepthSample);54#endif5556const FfxFloat32x3 fCenter = GetViewSpacePosition(FfxInt32x2(RenderSize() * 0.5f), RenderSize(), fPlaneDepth);57const FfxFloat32x3 fCorner = GetViewSpacePosition(FfxInt32x2(0, 0), RenderSize(), fPlaneDepth);5859const FfxFloat32 fHalfViewportWidth = length(FfxFloat32x2(RenderSize()));60const FfxFloat32 fDepthThreshold = ffxMax(fCurrentDepthViewSpace, fPrevNearestDepthViewSpace);6162const FfxFloat32 Ksep = 1.37e-05f;63const FfxFloat32 Kfov = length(fCorner) / length(fCenter);64const FfxFloat32 fRequiredDepthSeparation = Ksep * Kfov * fHalfViewportWidth * fDepthThreshold;6566const FfxFloat32 fResolutionFactor = ffxSaturate(length(FfxFloat32x2(RenderSize())) / length(FfxFloat32x2(1920.0f, 1080.0f)));67const FfxFloat32 fPower = ffxLerp(1.0f, 3.0f, fResolutionFactor);68fDepth += ffxPow(ffxSaturate(FfxFloat32(fRequiredDepthSeparation / fDepthDiff)), fPower) * fWeight;69fWeightSum += fWeight;70}71}72}73}7475return (fWeightSum > 0) ? ffxSaturate(1.0f - fDepth / fWeightSum) : 0.0f;76}7778FfxFloat32 ComputeMotionDivergence(FfxInt32x2 iPxPos, FfxInt32x2 iPxInputMotionVectorSize)79{80FfxFloat32 minconvergence = 1.0f;8182FfxFloat32x2 fMotionVectorNucleus = LoadInputMotionVector(iPxPos);83FfxFloat32 fNucleusVelocityLr = length(fMotionVectorNucleus * RenderSize());84FfxFloat32 fMaxVelocityUv = length(fMotionVectorNucleus);8586const FfxFloat32 MotionVectorVelocityEpsilon = 1e-02f;8788if (fNucleusVelocityLr > MotionVectorVelocityEpsilon) {89for (FfxInt32 y = -1; y <= 1; ++y) {90for (FfxInt32 x = -1; x <= 1; ++x) {9192FfxInt32x2 sp = ClampLoad(iPxPos, FfxInt32x2(x, y), iPxInputMotionVectorSize);9394FfxFloat32x2 fMotionVector = LoadInputMotionVector(sp);95FfxFloat32 fVelocityUv = length(fMotionVector);9697fMaxVelocityUv = ffxMax(fVelocityUv, fMaxVelocityUv);98fVelocityUv = ffxMax(fVelocityUv, fMaxVelocityUv);99minconvergence = ffxMin(minconvergence, dot(fMotionVector / fVelocityUv, fMotionVectorNucleus / fVelocityUv));100}101}102}103104return ffxSaturate(1.0f - minconvergence) * ffxSaturate(fMaxVelocityUv / 0.01f);105}106107FfxFloat32 ComputeDepthDivergence(FfxInt32x2 iPxPos)108{109const FfxFloat32 fMaxDistInMeters = GetMaxDistanceInMeters();110FfxFloat32 fDepthMax = 0.0f;111FfxFloat32 fDepthMin = fMaxDistInMeters;112113FfxInt32 iMaxDistFound = 0;114115for (FfxInt32 y = -1; y < 2; y++) {116for (FfxInt32 x = -1; x < 2; x++) {117118const FfxInt32x2 iOffset = FfxInt32x2(x, y);119const FfxInt32x2 iSamplePos = iPxPos + iOffset;120121const FfxFloat32 fOnScreenFactor = IsOnScreen(iSamplePos, RenderSize()) ? 1.0f : 0.0f;122FfxFloat32 fDepth = GetViewSpaceDepthInMeters(LoadDilatedDepth(iSamplePos)) * fOnScreenFactor;123124iMaxDistFound |= FfxInt32(fMaxDistInMeters == fDepth);125126fDepthMin = ffxMin(fDepthMin, fDepth);127fDepthMax = ffxMax(fDepthMax, fDepth);128}129}130131return (1.0f - fDepthMin / fDepthMax) * (FfxBoolean(iMaxDistFound) ? 0.0f : 1.0f);132}133134FfxFloat32 ComputeTemporalMotionDivergence(FfxInt32x2 iPxPos)135{136const FfxFloat32x2 fUv = FfxFloat32x2(iPxPos + 0.5f) / RenderSize();137138FfxFloat32x2 fMotionVector = LoadDilatedMotionVector(iPxPos);139FfxFloat32x2 fReprojectedUv = fUv + fMotionVector;140fReprojectedUv = ClampUv(fReprojectedUv, RenderSize(), MaxRenderSize());141FfxFloat32x2 fPrevMotionVector = SamplePreviousDilatedMotionVector(fReprojectedUv);142143float fPxDistance = length(fMotionVector * DisplaySize());144return fPxDistance > 1.0f ? ffxLerp(0.0f, 1.0f - ffxSaturate(length(fPrevMotionVector) / length(fMotionVector)), ffxSaturate(ffxPow(fPxDistance / 20.0f, 3.0f))) : 0;145}146147void PreProcessReactiveMasks(FfxInt32x2 iPxLrPos, FfxFloat32 fMotionDivergence)148{149// Compensate for bilinear sampling in accumulation pass150151FfxFloat32x3 fReferenceColor = LoadInputColor(iPxLrPos).xyz;152FfxFloat32x2 fReactiveFactor = FfxFloat32x2(0.0f, fMotionDivergence);153154float fMasksSum = 0.0f;155156FfxFloat32x3 fColorSamples[9];157FfxFloat32 fReactiveSamples[9];158FfxFloat32 fTransparencyAndCompositionSamples[9];159160FFX_UNROLL161for (FfxInt32 y = -1; y < 2; y++) {162FFX_UNROLL163for (FfxInt32 x = -1; x < 2; x++) {164165const FfxInt32x2 sampleCoord = ClampLoad(iPxLrPos, FfxInt32x2(x, y), FfxInt32x2(RenderSize()));166167FfxInt32 sampleIdx = (y + 1) * 3 + x + 1;168169FfxFloat32x3 fColorSample = LoadInputColor(sampleCoord).xyz;170FfxFloat32 fReactiveSample = LoadReactiveMask(sampleCoord);171FfxFloat32 fTransparencyAndCompositionSample = LoadTransparencyAndCompositionMask(sampleCoord);172173fColorSamples[sampleIdx] = fColorSample;174fReactiveSamples[sampleIdx] = fReactiveSample;175fTransparencyAndCompositionSamples[sampleIdx] = fTransparencyAndCompositionSample;176177fMasksSum += (fReactiveSample + fTransparencyAndCompositionSample);178}179}180181if (fMasksSum > 0)182{183for (FfxInt32 sampleIdx = 0; sampleIdx < 9; sampleIdx++)184{185FfxFloat32x3 fColorSample = fColorSamples[sampleIdx];186FfxFloat32 fReactiveSample = fReactiveSamples[sampleIdx];187FfxFloat32 fTransparencyAndCompositionSample = fTransparencyAndCompositionSamples[sampleIdx];188189const FfxFloat32 fMaxLenSq = ffxMax(dot(fReferenceColor, fReferenceColor), dot(fColorSample, fColorSample));190const FfxFloat32 fSimilarity = dot(fReferenceColor, fColorSample) / fMaxLenSq;191192// Increase power for non-similar samples193const FfxFloat32 fPowerBiasMax = 6.0f;194const FfxFloat32 fSimilarityPower = 1.0f + (fPowerBiasMax - fSimilarity * fPowerBiasMax);195const FfxFloat32 fWeightedReactiveSample = ffxPow(fReactiveSample, fSimilarityPower);196const FfxFloat32 fWeightedTransparencyAndCompositionSample = ffxPow(fTransparencyAndCompositionSample, fSimilarityPower);197198fReactiveFactor = ffxMax(fReactiveFactor, FfxFloat32x2(fWeightedReactiveSample, fWeightedTransparencyAndCompositionSample));199}200}201202StoreDilatedReactiveMasks(iPxLrPos, fReactiveFactor);203}204205FfxFloat32x3 ComputePreparedInputColor(FfxInt32x2 iPxLrPos)206{207//We assume linear data. if non-linear input (sRGB, ...),208//then we should convert to linear first and back to sRGB on output.209FfxFloat32x3 fRgb = ffxMax(FfxFloat32x3(0, 0, 0), LoadInputColor(iPxLrPos));210211fRgb = PrepareRgb(fRgb, Exposure(), PreExposure());212213const FfxFloat32x3 fPreparedYCoCg = RGBToYCoCg(fRgb);214215return fPreparedYCoCg;216}217218FfxFloat32 EvaluateSurface(FfxInt32x2 iPxPos, FfxFloat32x2 fMotionVector)219{220FfxFloat32 d0 = GetViewSpaceDepth(LoadReconstructedPrevDepth(iPxPos + FfxInt32x2(0, -1)));221FfxFloat32 d1 = GetViewSpaceDepth(LoadReconstructedPrevDepth(iPxPos + FfxInt32x2(0, 0)));222FfxFloat32 d2 = GetViewSpaceDepth(LoadReconstructedPrevDepth(iPxPos + FfxInt32x2(0, 1)));223224return 1.0f - FfxFloat32(((d0 - d1) > (d1 * 0.01f)) && ((d1 - d2) > (d2 * 0.01f)));225}226227void DepthClip(FfxInt32x2 iPxPos)228{229FfxFloat32x2 fDepthUv = (iPxPos + 0.5f) / RenderSize();230FfxFloat32x2 fMotionVector = LoadDilatedMotionVector(iPxPos);231232// Discard tiny mvs233fMotionVector *= FfxFloat32(length(fMotionVector * DisplaySize()) > 0.01f);234235const FfxFloat32x2 fDilatedUv = fDepthUv + fMotionVector;236const FfxFloat32 fDilatedDepth = LoadDilatedDepth(iPxPos);237const FfxFloat32 fCurrentDepthViewSpace = GetViewSpaceDepth(LoadInputDepth(iPxPos));238239// Compute prepared input color and depth clip240FfxFloat32 fDepthClip = ComputeDepthClip(fDilatedUv, fDilatedDepth) * EvaluateSurface(iPxPos, fMotionVector);241FfxFloat32x3 fPreparedYCoCg = ComputePreparedInputColor(iPxPos);242StorePreparedInputColor(iPxPos, FfxFloat32x4(fPreparedYCoCg, fDepthClip));243244// Compute dilated reactive mask245#if FFX_FSR2_OPTION_LOW_RESOLUTION_MOTION_VECTORS246FfxInt32x2 iSamplePos = iPxPos;247#else248FfxInt32x2 iSamplePos = ComputeHrPosFromLrPos(iPxPos);249#endif250251FfxFloat32 fMotionDivergence = ComputeMotionDivergence(iSamplePos, RenderSize());252FfxFloat32 fTemporalMotionDifference = ffxSaturate(ComputeTemporalMotionDivergence(iPxPos) - ComputeDepthDivergence(iPxPos));253254PreProcessReactiveMasks(iPxPos, ffxMax(fTemporalMotionDifference, fMotionDivergence));255}256257#endif //!defined( FFX_FSR2_DEPTH_CLIPH )258259