mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-22 15:09:19 +02:00
Some renaming
This commit is contained in:
51
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/dof/CMakeCompileDOFShaders.txt
vendored
Normal file
51
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/dof/CMakeCompileDOFShaders.txt
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
# 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(DOF_BASE_ARGS
|
||||
-reflection -deps=gcc -DFFX_GPU=1)
|
||||
|
||||
set(DOF_PERMUTATION_ARGS
|
||||
-DFFX_DOF_OPTION_MAX_RING_MERGE_LOG={0,1}
|
||||
-DFFX_DOF_OPTION_COMBINE_IN_PLACE={0,1}
|
||||
-DFFX_DOF_OPTION_REVERSE_DEPTH={0,1})
|
||||
|
||||
set(DOF_INCLUDE_ARGS
|
||||
"${FFX_GPU_PATH}"
|
||||
"${FFX_GPU_PATH}/dof")
|
||||
|
||||
if (NOT DOF_SHADER_EXT)
|
||||
set(DOF_SHADER_EXT *)
|
||||
endif()
|
||||
|
||||
file(GLOB DOF_SHADERS
|
||||
"shaders/dof/ffx_dof_downsample_depth_pass.${DOF_SHADER_EXT}"
|
||||
"shaders/dof/ffx_dof_downsample_color_pass.${DOF_SHADER_EXT}"
|
||||
"shaders/dof/ffx_dof_dilate_pass.${DOF_SHADER_EXT}"
|
||||
"shaders/dof/ffx_dof_blur_pass.${DOF_SHADER_EXT}"
|
||||
"shaders/dof/ffx_dof_composite_pass.${DOF_SHADER_EXT}")
|
||||
|
||||
compile_shaders_with_depfile(
|
||||
"${FFX_SC_EXECUTABLE}"
|
||||
"${DOF_BASE_ARGS}" "${DOF_API_BASE_ARGS}" "${DOF_PERMUTATION_ARGS}" "${DOF_INCLUDE_ARGS}"
|
||||
"${DOF_SHADERS}" "${FFX_PASS_SHADER_OUTPUT_PATH}" DOF_PERMUTATION_OUTPUTS)
|
||||
|
||||
add_shader_output("${DOF_PERMUTATION_OUTPUTS}")
|
||||
714
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/dof/ffx_dof_blur.h
vendored
Normal file
714
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/dof/ffx_dof_blur.h
vendored
Normal file
@@ -0,0 +1,714 @@
|
||||
// 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_core.h"
|
||||
#include "ffx_dof_common.h"
|
||||
|
||||
// Factor applied to a distance value before checking that it is in range of the blur kernel.
|
||||
FFX_STATIC const FfxFloat32 FFX_DOF_RANGE_TOLERANCE_FACTOR = 0.98;
|
||||
|
||||
// Accumulators for one ring. Used for ring occlusion.
|
||||
struct FfxDofBucket
|
||||
{
|
||||
FfxFloat32x4 color; // rgb=color sum, a=weight sum
|
||||
FfxFloat32 ringCovg; // radius of the ring coverage (average of tileCoc/coc with some clamping)
|
||||
FfxFloat32 radius; // radius of the ring center
|
||||
FfxUInt32 sampleCount; // number of samples counted
|
||||
};
|
||||
|
||||
// One sample of the input and related variables
|
||||
struct FfxDofSample
|
||||
{
|
||||
FfxFloat32 coc; // signed circle of confusion in pixels. negative values are far-field.
|
||||
FfxFloat32x3 color; // color value of the sample
|
||||
};
|
||||
|
||||
// Helper struct to contain all input variables
|
||||
struct FfxDofInputState
|
||||
{
|
||||
FfxUInt32x2 imageSize; // input pixel size (half res)
|
||||
FfxFloat32x2 pxCoord; // pixel coordinates of the kernel center
|
||||
FfxFloat32 tileCoc; // coc value bilinearly interpolated from the tile map
|
||||
FfxFloat32 centerCoc; // signed coc value at the kernel center
|
||||
FfxFloat32 ringGap; // undersampling factor. ringGap * nRings = tileCoc.
|
||||
FfxUInt32 mipLevel; // mip level to use based on coc and MAX_RINGS
|
||||
FfxBoolean nearField; // whether the center pixel is in the near field
|
||||
FfxUInt32 nSamples, // number of actual samples taken
|
||||
nRings; // number of rings to sample (<= MAX_RINGS)
|
||||
FfxFloat32 covgFactor, covgBias; // coverage parameters
|
||||
};
|
||||
|
||||
// Helper struct to contain accumulation variables
|
||||
struct FfxDofAccumulators
|
||||
{
|
||||
FfxDofBucket prevBucket, currBucket;
|
||||
FfxFloat32x4 ringColor;
|
||||
FfxFloat32 ringCovg;
|
||||
FfxFloat32x4 nearColor, fillColor;
|
||||
};
|
||||
|
||||
// Merges currBucket into prevBucket. Opacity is ratio of hit/total samples in current ring.
|
||||
void FfxDofMergeBuckets(inout FfxDofAccumulators acc, FfxFloat32 opacity)
|
||||
{
|
||||
// averaging
|
||||
FfxFloat32 prevRC = ffxSaturate(acc.prevBucket.ringCovg / acc.prevBucket.sampleCount);
|
||||
FfxFloat32 currRC = ffxSaturate(acc.currBucket.ringCovg / acc.currBucket.sampleCount);
|
||||
|
||||
// occlusion term is calculated as the ratio of the area of intersection of both buckets
|
||||
// (being viewed as rings with a radius (centered on the samples) and ring width (=avg coverage))
|
||||
// divided by the area of the previous bucket ring.
|
||||
FfxFloat32 prevOuter = ffxSaturate(acc.prevBucket.radius + prevRC);
|
||||
FfxFloat32 prevInner = (acc.prevBucket.radius - prevRC);
|
||||
FfxFloat32 currOuter = ffxSaturate(acc.currBucket.radius + currRC);
|
||||
FfxFloat32 currInner = (acc.currBucket.radius - currRC);
|
||||
// intersection is between min(outer) and max(inner)
|
||||
FfxFloat32 insOuter = min(prevOuter, currOuter);
|
||||
FfxFloat32 insInner = max(prevInner, currInner);
|
||||
// intersection area formula.
|
||||
// ffxSaturate here fixes edge case where prev area = 0 -> ffxSaturate(0/0)=ffxSaturate(nan) = 0
|
||||
// The value does not matter in that case, since the previous values will be all zero, but it must be finite.
|
||||
FfxFloat32 occlusion = insOuter < insInner ? 0 : ffxSaturate((insOuter * insOuter - sign(insInner) * insInner * insInner) / (prevOuter * prevOuter - sign(prevInner) * prevInner * prevInner));
|
||||
|
||||
FfxFloat32 factor = 1 - opacity * occlusion;
|
||||
acc.prevBucket.color = acc.prevBucket.color * factor + acc.currBucket.color;
|
||||
// select new radius so that (roughly) covers both rings, so in the middle of the combined ring
|
||||
FfxFloat32 newRadius = 0.5 * (max(prevOuter, currOuter) + min(prevInner, currInner));
|
||||
// the new coverage should then be the difference between the radius and either bound
|
||||
FfxFloat32 newCovg = 0.5 * (max(prevOuter, currOuter) - min(prevInner, currInner));
|
||||
acc.prevBucket.sampleCount = FfxUInt32(acc.prevBucket.sampleCount * factor) + acc.currBucket.sampleCount;
|
||||
acc.prevBucket.ringCovg = acc.prevBucket.sampleCount * newCovg;
|
||||
acc.prevBucket.radius = newRadius;
|
||||
}
|
||||
|
||||
FfxFloat32 FfxDofWeight(FfxDofInputState ins, FfxFloat32 coc)
|
||||
{
|
||||
// Weight is inverse coc area (1 / pi*r^2). Use pi~=4 for perf reasons.
|
||||
// Saturate to avoid explosion of weight close to zero. If coc < 0.5, the coc is contained
|
||||
// within this pixel and the weight should be 1.
|
||||
FfxFloat32 invRad = 1.0 / coc;
|
||||
return ffxSaturate(invRad * invRad / 4);
|
||||
}
|
||||
|
||||
FfxFloat32 FfxDofCoverage(FfxDofInputState ins, FfxFloat32 coc)
|
||||
{
|
||||
// Coverage is essentially the radius of the sample's projection to the lens aperture.
|
||||
// The radius is normalized to the tile CoC and kernel diameter in samples.
|
||||
// Add a small bias to account for gaps between sample rings.
|
||||
// Clamped to avoid infinity near zero.
|
||||
return ffxSaturate(ins.covgFactor / coc + ins.covgBias);
|
||||
}
|
||||
|
||||
#ifdef FFX_DOF_CUSTOM_SAMPLES
|
||||
|
||||
// declarations only
|
||||
|
||||
// *MUST DEFINE* own struct SampleStreamState ! See below #else for example.
|
||||
|
||||
/// Callback for custom blur kernels. Gets the sample offset and advances the iterator.
|
||||
/// @param state Mutable state for the sample stream.
|
||||
/// @return The sample location in normalized uv coordinates. The default implementation approximates a circle using a combination of rotation and translation in an affine transform.
|
||||
/// @ingroup FfxGPUDof
|
||||
FfxFloat32x2 FfxDofAdvanceSampleStream(inout SampleStreamState state);
|
||||
|
||||
/// Callback for custom blur kernels. Gets the number of samples in a ring and initalizes iteration state.
|
||||
/// @param state Mutable state for the sample stream.
|
||||
/// @param ins Input parameters for the blur kernel. Contains the full number of rings.
|
||||
/// @param ri Index of the current ring. If rings are being merged, this is the center of the indices.
|
||||
/// @param mergeRingsCount The number of rings being merged. 1 if the current ring is not merged with any other.
|
||||
/// @return The number of samples in the ring, assuming no merging. This is divided by the mergeRingsCount to get the actual number of samples.
|
||||
/// @ingroup FfxGPUDof
|
||||
FfxUInt32 FfxDofInitSampleStream(out SampleStreamState state, FfxDofInputState ins, FfxFloat32 ri, FfxUInt32 mergeRingsCount);
|
||||
|
||||
#else
|
||||
|
||||
struct SampleStreamState {
|
||||
// represents an affine 2d transform to go from one sample position to the next.
|
||||
FfxFloat32 cosTheta; // top-left and bottom-right element of rotation matrix
|
||||
FfxFloat32 sinThetaXAspect; // bottom-left element of rotation matrix
|
||||
FfxFloat32 mSinThetaXrAspect; // top-right element of rotation matrix
|
||||
FfxFloat32x2 translation; // additive part of affine transform
|
||||
FfxFloat32x2 position; // next sample position
|
||||
};
|
||||
|
||||
FfxFloat32x2 FfxDofAdvanceSampleStream(inout SampleStreamState state)
|
||||
{
|
||||
FfxFloat32x2 pos = state.position;
|
||||
// affine transformation.
|
||||
FfxFloat32 x = state.cosTheta * pos.x + state.mSinThetaXrAspect * pos.y;
|
||||
FfxFloat32 y = state.sinThetaXAspect * pos.x + state.cosTheta * pos.y;
|
||||
state.position = FfxFloat32x2(x, y) + state.translation;
|
||||
return pos;
|
||||
}
|
||||
|
||||
FfxUInt32 FfxDofInitSampleStream(out SampleStreamState state, FfxDofInputState ins, FfxFloat32 ri, FfxUInt32 merge)
|
||||
{
|
||||
#if FFX_DOF_MAX_RING_MERGE > 1
|
||||
FfxUInt32 n = FfxUInt32(6.25 * (ins.nRings - ri)); // approx. pi/asin(1/(2*(nR-ri)))
|
||||
#else
|
||||
// using fixed-point version of above allows scalar alu to do the same operation. Equivalent if merge == 1 (=> ri is integer).
|
||||
FfxUInt32 n = (27 * FfxUInt32(ins.nRings - ri)) >> 2;
|
||||
#endif
|
||||
FfxFloat32 r = ins.tileCoc * ffxReciprocal(ins.nRings) * FfxFloat32(ins.nRings - ri);
|
||||
state.position = InputSizeHalfRcp() * (ins.pxCoord + FfxFloat32x2(r, 0));
|
||||
FfxFloat32 theta = 6.2831853 * ffxReciprocal(n) * merge;
|
||||
FfxFloat32 s = sin(theta), c = cos(theta);
|
||||
FfxFloat32x2 aspect = InputSizeHalf() * InputSizeHalfRcp().yx;
|
||||
|
||||
state.cosTheta = c;
|
||||
state.sinThetaXAspect = s * aspect.x;
|
||||
state.mSinThetaXrAspect = -s * aspect.y;
|
||||
state.translation = InputSizeHalfRcp() * (ins.pxCoord - ins.pxCoord.x * FfxFloat32x2(c, s) - ins.pxCoord.y * FfxFloat32x2(-s, c));
|
||||
return n;
|
||||
}
|
||||
|
||||
#endif // #ifdef FFX_DOF_CUSTOM_SAMPLES
|
||||
|
||||
struct FfxDofRingParams {
|
||||
FfxFloat32 distance; // distance to center in pixels / radius of ring
|
||||
FfxFloat32 bucketBorder; // (far field) border between curr/prev bucket
|
||||
FfxFloat32 rangeThreshNear; // threshold for in-range determination in near field
|
||||
FfxFloat32 rangeThreshFar; // same for far field
|
||||
FfxFloat32 rangeThreshFill; // threshold for main or fallback fill selection
|
||||
FfxFloat32 fillQuality; // bg-fill contribution quality
|
||||
};
|
||||
|
||||
FfxDofSample FfxDofFetchSample(FfxDofInputState ins, inout SampleStreamState streamState, FfxUInt32 mipBias)
|
||||
{
|
||||
FfxFloat32x2 samplePos = FfxDofAdvanceSampleStream(streamState);
|
||||
FfxUInt32 mipLevel = ins.mipLevel + mipBias;
|
||||
FfxFloat32x4 texval = FfxDofSampleInput(samplePos, mipLevel);
|
||||
FfxDofSample result;
|
||||
result.coc = texval.a;
|
||||
result.color = texval.rgb;
|
||||
return result;
|
||||
}
|
||||
|
||||
void FfxDofProcessNearSample(FfxDofInputState ins, FfxDofSample s, inout FfxDofAccumulators acc, FfxDofRingParams ring)
|
||||
{
|
||||
// feather the range slightly (1px)
|
||||
FfxFloat32 inRangeWeight = ffxSaturate(s.coc - ring.rangeThreshNear);
|
||||
FfxFloat32 weight = FfxDofWeight(ins, abs(s.coc));
|
||||
|
||||
// fill background behind center using farther away samples.
|
||||
if (ins.nearField)
|
||||
{
|
||||
// Try to reject same-surface samples using using a slope of 1px radius per px distance.
|
||||
// But use the rejected pixels if no others are available.
|
||||
FfxFloat32 rejectionWeight = (s.coc < ring.rangeThreshFill) ? 1.0 : (1.0/2048.0);
|
||||
// prefer nearest (in image space) samples
|
||||
// Contribution decreases quadratically with sample distance.
|
||||
acc.fillColor += FfxFloat32x4(s.color, 1) * weight * ring.fillQuality * rejectionWeight;
|
||||
}
|
||||
|
||||
acc.nearColor += FfxFloat32x4(s.color, 1) * weight * inRangeWeight;
|
||||
}
|
||||
|
||||
void FfxDofProcessFarSample(FfxDofInputState ins, FfxDofSample s, inout FfxDofAccumulators acc, FfxDofRingParams ring)
|
||||
{
|
||||
FfxFloat32 clampedFarCoc = max(0, -s.coc);
|
||||
FfxFloat32 inRangeWeight = ffxSaturate(-s.coc - ring.rangeThreshFar);
|
||||
|
||||
FfxFloat32 covg = FfxDofCoverage(ins, abs(s.coc));
|
||||
FfxFloat32x4 color = FfxFloat32x4(s.color, 1) * FfxDofWeight(ins, abs(s.coc)) * inRangeWeight;
|
||||
|
||||
if (-s.coc >= ring.bucketBorder)
|
||||
{
|
||||
acc.prevBucket.ringCovg += covg;
|
||||
acc.prevBucket.color += color;
|
||||
acc.prevBucket.sampleCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
acc.currBucket.ringCovg += covg;
|
||||
acc.currBucket.color += color;
|
||||
acc.currBucket.sampleCount++;
|
||||
}
|
||||
}
|
||||
|
||||
void FfxDofProcessNearFar(FfxDofInputState ins, inout FfxDofAccumulators acc)
|
||||
{
|
||||
// base case: both near and far-field are processed.
|
||||
// scan outside-in for far-field occlusion
|
||||
for (FfxUInt32 ri = 0; ri < ins.nRings; ri++)
|
||||
{
|
||||
acc.currBucket.color = FFX_BROADCAST_FLOAT32X4(0);
|
||||
acc.currBucket.ringCovg = 0;
|
||||
acc.currBucket.radius = ffxReciprocal(ins.nRings) * FfxFloat32(ins.nRings - ri);
|
||||
acc.currBucket.sampleCount = 0;
|
||||
|
||||
SampleStreamState streamState;
|
||||
FfxUInt32 ringSamples = FfxDofInitSampleStream(streamState, ins, ri, 1);
|
||||
FfxDofRingParams ring;
|
||||
ring.distance = ins.tileCoc * ffxReciprocal(ins.nRings) * FfxFloat32(ins.nRings - ri);
|
||||
ring.bucketBorder = (ins.nRings - 1 - ri + 2.5) * ins.tileCoc * ffxReciprocal(0.5 + ins.nRings);
|
||||
ring.rangeThreshNear = max(0, ring.distance - ins.ringGap - 0.5);
|
||||
ring.rangeThreshFar = max(0, ring.distance - ins.ringGap);
|
||||
ring.rangeThreshFill = ins.centerCoc - ring.distance;
|
||||
ring.fillQuality = (1 / ring.distance) * (1 / ring.distance);
|
||||
|
||||
// partially unrolled loop
|
||||
const FfxUInt32 UNROLL_CNT = 2;
|
||||
FfxUInt32 iunr = 0;
|
||||
for (iunr = 0; iunr + UNROLL_CNT <= ringSamples; iunr += UNROLL_CNT)
|
||||
{
|
||||
FFX_DOF_UNROLL
|
||||
for (FfxUInt32 i = 0; i < UNROLL_CNT; i++)
|
||||
{
|
||||
FfxDofSample s = FfxDofFetchSample(ins, streamState, 0);
|
||||
FfxDofProcessFarSample(ins, s, acc, ring);
|
||||
FfxDofProcessNearSample(ins, s, acc, ring);
|
||||
}
|
||||
}
|
||||
for (FfxUInt32 i = iunr; i < ringSamples; i++)
|
||||
{
|
||||
FfxDofSample s = FfxDofFetchSample(ins, streamState, 0);
|
||||
FfxDofProcessFarSample(ins, s, acc, ring);
|
||||
FfxDofProcessNearSample(ins, s, acc, ring);
|
||||
}
|
||||
|
||||
FfxFloat32 opacity = FfxFloat32(acc.currBucket.sampleCount) / FfxFloat32(ringSamples);
|
||||
FfxDofMergeBuckets(acc, opacity);
|
||||
}
|
||||
}
|
||||
|
||||
void FfxDofProcessNearOnly(FfxDofInputState ins, inout FfxDofAccumulators acc)
|
||||
{
|
||||
// variant with the assumption that all samples are near field
|
||||
for (FfxUInt32 ri = 0; ri < ins.nRings; ri++)
|
||||
{
|
||||
SampleStreamState streamState;
|
||||
FfxUInt32 ringSamples = FfxDofInitSampleStream(streamState, ins, ri, 1);
|
||||
FfxDofRingParams ring;
|
||||
ring.distance = ins.tileCoc * ffxReciprocal(ins.nRings) * FfxFloat32(ins.nRings - ri);
|
||||
ring.rangeThreshNear = max(0, ring.distance - ins.ringGap - 0.5);
|
||||
ring.rangeThreshFill = ins.centerCoc - ring.distance;
|
||||
ring.fillQuality = (1 / ring.distance) * (1 / ring.distance);
|
||||
|
||||
// partially unrolled loop
|
||||
const FfxUInt32 UNROLL_CNT = 4;
|
||||
FfxUInt32 iunr = 0;
|
||||
for (iunr = 0; iunr + UNROLL_CNT <= ringSamples; iunr += UNROLL_CNT)
|
||||
{
|
||||
FFX_DOF_UNROLL
|
||||
for (FfxUInt32 i = 0; i < UNROLL_CNT; i++)
|
||||
{
|
||||
FfxDofSample s = FfxDofFetchSample(ins, streamState, 0);
|
||||
FfxDofProcessNearSample(ins, s, acc, ring);
|
||||
}
|
||||
}
|
||||
for (FfxUInt32 i = iunr; i < ringSamples; i++)
|
||||
{
|
||||
FfxDofSample s = FfxDofFetchSample(ins, streamState, 0);
|
||||
FfxDofProcessNearSample(ins, s, acc, ring);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FfxDofProcessFarOnly(FfxDofInputState ins, inout FfxDofAccumulators acc)
|
||||
{
|
||||
// variant with the assumption that all samples are far field
|
||||
// scan outside-in for far-field occlusion
|
||||
for (FfxUInt32 ri = 0; ri < ins.nRings; ri++)
|
||||
{
|
||||
acc.currBucket.color = FFX_BROADCAST_FLOAT32X4(0);
|
||||
acc.currBucket.ringCovg = 0;
|
||||
acc.currBucket.radius = ffxReciprocal(ins.nRings) * FfxFloat32(ins.nRings - ri);
|
||||
acc.currBucket.sampleCount = 0;
|
||||
|
||||
SampleStreamState streamState;
|
||||
FfxUInt32 ringSamples = FfxDofInitSampleStream(streamState, ins, ri, 1);
|
||||
FfxDofRingParams ring;
|
||||
ring.distance = ins.tileCoc * ffxReciprocal(ins.nRings) * FfxFloat32(ins.nRings - ri);
|
||||
ring.bucketBorder = (ins.nRings - 1 - ri + 2.5) * ins.tileCoc * ffxReciprocal(0.5 + ins.nRings);
|
||||
ring.rangeThreshFar = max(0, ring.distance - ins.ringGap);
|
||||
|
||||
// partially unrolled loop
|
||||
const FfxUInt32 UNROLL_CNT = 3;
|
||||
FfxUInt32 iunr = 0;
|
||||
for (iunr = 0; iunr + UNROLL_CNT <= ringSamples; iunr += UNROLL_CNT)
|
||||
{
|
||||
FFX_DOF_UNROLL
|
||||
for (FfxUInt32 i = 0; i < UNROLL_CNT; i++)
|
||||
{
|
||||
FfxDofSample s = FfxDofFetchSample(ins, streamState, 0);
|
||||
FfxDofProcessFarSample(ins, s, acc, ring);
|
||||
}
|
||||
}
|
||||
for (FfxUInt32 i = iunr; i < ringSamples; i++)
|
||||
{
|
||||
FfxDofSample s = FfxDofFetchSample(ins, streamState, 0);
|
||||
FfxDofProcessFarSample(ins, s, acc, ring);
|
||||
}
|
||||
|
||||
FfxFloat32 opacity = FfxFloat32(acc.currBucket.sampleCount) / FfxFloat32(ringSamples);
|
||||
FfxDofMergeBuckets(acc, opacity);
|
||||
}
|
||||
}
|
||||
|
||||
void FfxDofProcessNearColorOnly(FfxDofInputState ins, inout FfxDofAccumulators acc)
|
||||
{
|
||||
// variant with the assumption that all samples are near and equally weighed
|
||||
for (FfxUInt32 ri = 0; ri < ins.nRings;)
|
||||
{
|
||||
// merge inner rings if possible
|
||||
FfxUInt32 merge = min(min(1 << ri, FFX_DOF_MAX_RING_MERGE), ins.nRings - ri);
|
||||
FfxFloat32 rif = ri + 0.5 * merge - 0.5;
|
||||
FfxUInt32 weight = merge * merge;
|
||||
SampleStreamState streamState;
|
||||
FfxUInt32 ringSamples = FfxDofInitSampleStream(streamState, ins, rif, merge) / merge;
|
||||
FfxUInt32 mipBias = 2 * FfxUInt32(log2(merge));
|
||||
FfxFloat32 sampleDist = ins.tileCoc * ffxReciprocal(ins.nRings) * (FfxFloat32(ins.nRings) - rif);
|
||||
FfxHalfOpt rangeThresh = FfxHalfOpt(max(0, sampleDist - ins.ringGap - 0.5));
|
||||
|
||||
FfxHalfOpt3 nearColorAcc = FfxHalfOpt3(0, 0, 0);
|
||||
FfxHalfOpt weightSum = FfxHalfOpt(0);
|
||||
// We presume that all samples are in range
|
||||
// partially unrolled loop (x6)
|
||||
const FfxUInt32 UNROLL_CNT = 6;
|
||||
FfxUInt32 iunr = 0;
|
||||
for (iunr = 0; iunr + UNROLL_CNT <= ringSamples; iunr += UNROLL_CNT)
|
||||
{
|
||||
FFX_DOF_UNROLL
|
||||
for (FfxUInt32 i = 0; i < UNROLL_CNT; i++)
|
||||
{
|
||||
FfxDofSample s = FfxDofFetchSample(ins, streamState, mipBias);
|
||||
FfxHalfOpt rangeWeight = ffxSaturate(FfxHalfOpt(s.coc) - rangeThresh);
|
||||
nearColorAcc += FfxHalfOpt3(s.color) * rangeWeight;
|
||||
weightSum += rangeWeight;
|
||||
}
|
||||
}
|
||||
for (FfxUInt32 i = iunr; i < ringSamples; i++)
|
||||
{
|
||||
FfxDofSample s = FfxDofFetchSample(ins, streamState, mipBias);
|
||||
FfxHalfOpt rangeWeight = ffxSaturate(FfxHalfOpt(s.coc) - rangeThresh);
|
||||
nearColorAcc += FfxHalfOpt3(s.color) * rangeWeight;
|
||||
weightSum += rangeWeight;
|
||||
}
|
||||
acc.nearColor.rgb += nearColorAcc * FfxHalfOpt(weight);
|
||||
acc.nearColor.a += weightSum * FfxHalfOpt(weight);
|
||||
ri += merge;
|
||||
}
|
||||
}
|
||||
|
||||
void FfxDofProcessFarColorOnly(FfxDofInputState ins, inout FfxDofAccumulators acc)
|
||||
{
|
||||
FfxFloat32 nSamples = 0;
|
||||
FfxUInt32 ri = 0;
|
||||
// peel first iteration
|
||||
if (ri < ins.nRings)
|
||||
{
|
||||
// merge inner rings if possible
|
||||
FfxUInt32 merge = min(min(1 << ri, FFX_DOF_MAX_RING_MERGE), ins.nRings - ri);
|
||||
FfxFloat32 rif = ri + 0.5 * merge - 0.5;
|
||||
FfxUInt32 weight = merge * merge;
|
||||
SampleStreamState streamState;
|
||||
FfxUInt32 ringSamples = FfxDofInitSampleStream(streamState, ins, rif, merge) / merge;
|
||||
FfxUInt32 mipBias = 2 * FfxUInt32(log2(merge));
|
||||
FfxFloat32 sampleDist = ins.tileCoc * ffxReciprocal(ins.nRings) * (FfxFloat32(ins.nRings) - rif);
|
||||
FfxHalfOpt rangeThresh = FfxHalfOpt(max(0, sampleDist - ins.ringGap));
|
||||
|
||||
FfxHalfOpt3 colorAcc = FfxHalfOpt3(0, 0, 0);
|
||||
FfxHalfOpt weightSum = FfxHalfOpt(0);
|
||||
// partially unrolled loop (x8, then x4)
|
||||
FfxUInt32 iunr = 0;
|
||||
for (; iunr + 8 <= ringSamples; iunr += 8)
|
||||
{
|
||||
FFX_DOF_UNROLL
|
||||
for (FfxUInt32 i = 0; i < 8; i++)
|
||||
{
|
||||
FfxDofSample s = FfxDofFetchSample(ins, streamState, mipBias);
|
||||
FfxHalfOpt rangeWeight = ffxSaturate(FfxHalfOpt(-s.coc) - rangeThresh);
|
||||
colorAcc += FfxHalfOpt3(s.color) * rangeWeight;
|
||||
weightSum += rangeWeight;
|
||||
}
|
||||
}
|
||||
for (; iunr + 4 <= ringSamples; iunr += 4)
|
||||
{
|
||||
FFX_DOF_UNROLL
|
||||
for (FfxUInt32 i = 0; i < 4; i++)
|
||||
{
|
||||
FfxDofSample s = FfxDofFetchSample(ins, streamState, mipBias);
|
||||
FfxHalfOpt rangeWeight = ffxSaturate(FfxHalfOpt(-s.coc) - rangeThresh);
|
||||
colorAcc += FfxHalfOpt3(s.color) * rangeWeight;
|
||||
weightSum += rangeWeight;
|
||||
}
|
||||
}
|
||||
for (FfxUInt32 i = iunr; i < ringSamples; i++)
|
||||
{
|
||||
FfxDofSample s = FfxDofFetchSample(ins, streamState, mipBias);
|
||||
FfxHalfOpt rangeWeight = ffxSaturate(FfxHalfOpt(-s.coc) - rangeThresh);
|
||||
colorAcc += FfxHalfOpt3(s.color) * rangeWeight;
|
||||
weightSum += rangeWeight;
|
||||
}
|
||||
acc.prevBucket.color.rgb += colorAcc * FfxHalfOpt(weight);
|
||||
nSamples += weightSum * FfxHalfOpt(weight);
|
||||
ri += merge;
|
||||
}
|
||||
while (ri < ins.nRings)
|
||||
{
|
||||
// merge inner rings if possible
|
||||
FfxUInt32 merge = min(min(1 << ri, FFX_DOF_MAX_RING_MERGE), ins.nRings - ri);
|
||||
FfxFloat32 rif = ri + 0.5 * merge - 0.5;
|
||||
FfxUInt32 weight = merge * merge;
|
||||
SampleStreamState streamState;
|
||||
FfxUInt32 ringSamples = FfxDofInitSampleStream(streamState, ins, rif, merge) / merge;
|
||||
FfxUInt32 mipBias = 2 * FfxUInt32(log2(merge));
|
||||
|
||||
FfxHalfOpt3 colorAcc = FfxHalfOpt3(0, 0, 0);
|
||||
// partially unrolled loop (x12, then x4)
|
||||
FfxUInt32 iunr = 0;
|
||||
for (; iunr + 12 <= ringSamples; iunr += 12)
|
||||
{
|
||||
FFX_DOF_UNROLL
|
||||
for (FfxUInt32 i = 0; i < 12; i++)
|
||||
{
|
||||
FfxDofSample s = FfxDofFetchSample(ins, streamState, mipBias);
|
||||
// Max difference between sample coc and tile coc is 0.5px (see PrepareTile).
|
||||
// Max radius of any ring after first (ri>0) is 1 less than tile coc.
|
||||
// rangeWeight = 1
|
||||
colorAcc += FfxHalfOpt3(s.color);
|
||||
}
|
||||
}
|
||||
for (; iunr + 4 <= ringSamples; iunr += 4)
|
||||
{
|
||||
FFX_DOF_UNROLL
|
||||
for (FfxUInt32 i = 0; i < 4; i++)
|
||||
{
|
||||
FfxDofSample s = FfxDofFetchSample(ins, streamState, mipBias);
|
||||
colorAcc += FfxHalfOpt3(s.color);
|
||||
}
|
||||
}
|
||||
for (FfxUInt32 i = iunr; i < ringSamples; i++)
|
||||
{
|
||||
FfxDofSample s = FfxDofFetchSample(ins, streamState, mipBias);
|
||||
colorAcc += FfxHalfOpt3(s.color);
|
||||
}
|
||||
acc.prevBucket.color.rgb += colorAcc * FfxHalfOpt(weight);
|
||||
nSamples += ringSamples * weight;
|
||||
ri += merge;
|
||||
}
|
||||
acc.prevBucket.color.a = nSamples;
|
||||
acc.prevBucket.ringCovg = nSamples;
|
||||
acc.prevBucket.sampleCount = FfxUInt32(nSamples);
|
||||
}
|
||||
|
||||
struct FfxDofTileClass
|
||||
{
|
||||
FfxBoolean colorOnly, needsNear, needsFar;
|
||||
};
|
||||
|
||||
// prepare values for the tile. Return classification.
|
||||
FfxDofTileClass FfxDofPrepareTile(FfxUInt32x2 id, out FfxDofInputState ins)
|
||||
{
|
||||
FfxDofTileClass tileClass;
|
||||
FfxFloat32x2 dilatedCocSigned = FfxDofSampleDilatedRadius(id);
|
||||
FfxFloat32x2 dilatedCoc = abs(dilatedCocSigned);
|
||||
FfxFloat32 tileRad = max(dilatedCoc.x, dilatedCoc.y);
|
||||
|
||||
// check if copying the tile is good enough
|
||||
#if FFX_HLSL
|
||||
if (WaveActiveAllTrue(tileRad < 0.5))
|
||||
#elif FFX_GLSL
|
||||
if (subgroupAll(tileRad < 0.5))
|
||||
#endif
|
||||
{
|
||||
tileClass.needsNear = false;
|
||||
tileClass.needsFar = false;
|
||||
tileClass.colorOnly = false;
|
||||
return tileClass;
|
||||
}
|
||||
|
||||
FfxFloat32 idealRingCount = // kernel radius in pixels -> one sample per pixel
|
||||
#if FFX_HLSL
|
||||
WaveActiveMax(ceil(tileRad));
|
||||
#elif FFX_GLSL
|
||||
subgroupMax(ceil(tileRad));
|
||||
#endif
|
||||
ins.nRings = FfxUInt32(idealRingCount);
|
||||
ins.mipLevel = 0;
|
||||
if (idealRingCount > MaxRings())
|
||||
{
|
||||
ins.nRings = MaxRings();
|
||||
// use a higher mip to cover the missing rings.
|
||||
// for every factor 2 decrease of the rings, increase mips by 1.
|
||||
ins.mipLevel = FfxUInt32(log2(idealRingCount * ffxReciprocal(MaxRings())));
|
||||
}
|
||||
// Gap = number of pixels between rings that are not sampled.
|
||||
ins.ringGap = idealRingCount / ins.nRings - 1.0;
|
||||
ins.tileCoc = tileRad;
|
||||
|
||||
FfxFloat32x2 texcoord = FfxFloat32x2(id) + FfxFloat32x2(0.25, 0.25); // shift to center of top-left pixel in quad
|
||||
// Add noise to reduce banding (if too noisy, this could be disabled)
|
||||
{
|
||||
/* hash22 adapted from https://www.shadertoy.com/view/4djSRW
|
||||
Copyright (c)2014 David Hoskins.
|
||||
|
||||
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.*/
|
||||
FfxFloat32x3 p3 = ffxFract(texcoord.xyx * FfxFloat32x3(0.1031, 0.1030, 0.0973));
|
||||
p3 += dot(p3, p3.yzx + 33.33);
|
||||
texcoord += ffxFract((p3.xx+p3.yz)*p3.zy) * 0.5 - 0.25;
|
||||
}
|
||||
ins.pxCoord = texcoord;
|
||||
|
||||
FfxFloat32 centerCoc = FfxDofLoadInput(id).a;
|
||||
ins.nearField = centerCoc > 0;
|
||||
ins.centerCoc = abs(centerCoc);
|
||||
|
||||
ins.nSamples = 0;
|
||||
#ifdef FFX_DOF_CUSTOM_SAMPLES
|
||||
for (FfxUInt32 ri = 0; ri < ins.nRings; ri++)
|
||||
{
|
||||
SampleStreamState streamState;
|
||||
ins.nSamples += FfxDofInitSampleStream(streamState, ins, ri, 1);
|
||||
}
|
||||
#else
|
||||
// due to rounding this will likely over-approximate, but that should be okay.
|
||||
ins.nSamples = FfxUInt32(6.25 * 0.5 * (ins.nRings * (ins.nRings + 1)));
|
||||
#endif
|
||||
|
||||
// read first lane to force using a scalar register.
|
||||
ins.covgFactor = ffxWaveReadLaneFirst(0.5 * ffxReciprocal(ins.nRings) * ins.tileCoc);
|
||||
ins.covgBias = ffxWaveReadLaneFirst(0.5 * ffxReciprocal(ins.nRings));
|
||||
|
||||
#if FFX_HLSL
|
||||
// simple check: is there even any near/far that we would sample?
|
||||
// See ProcessNearSample: No relevant code is executed if the center is not near and no sample is near
|
||||
// (use the CoC of the dilated tile minimum depth as the proxy for any sample)
|
||||
tileClass.needsNear = WaveActiveAnyTrue(dilatedCocSigned.x > -1);
|
||||
// See ProcessFarSample: All weights will be 0 if no sample is in the far field.
|
||||
// (use the CoC of dilated tile max depth as proxy)
|
||||
tileClass.needsFar = WaveActiveAnyTrue(dilatedCocSigned.y < 1);
|
||||
|
||||
tileClass.colorOnly = WaveActiveAllTrue(dilatedCocSigned.x - dilatedCocSigned.y < 0.5);
|
||||
#elif FFX_GLSL
|
||||
// as above
|
||||
tileClass.needsNear = subgroupAny(dilatedCocSigned.x > -1);
|
||||
tileClass.needsFar = subgroupAny(dilatedCocSigned.y < 1);
|
||||
tileClass.colorOnly = subgroupAll(dilatedCocSigned.x - dilatedCocSigned.y < 0.5);
|
||||
#endif
|
||||
|
||||
return tileClass;
|
||||
}
|
||||
|
||||
/// Blur pass entry point. Runs in 8x8x1 thread groups and computes transient near and far outputs.
|
||||
///
|
||||
/// @param pixel Coordinate of the pixel (SV_DispatchThreadID)
|
||||
/// @param halfImageSize Resolution of the source image (half resolution) in pixels
|
||||
/// @ingroup FfxGPUDof
|
||||
void FfxDofBlur(FfxUInt32x2 pixel, FfxUInt32x2 halfImageSize)
|
||||
{
|
||||
FfxDofResetMaxTileRadius();
|
||||
|
||||
FfxDofInputState ins;
|
||||
FfxDofTileClass tileClass = FfxDofPrepareTile(pixel, ins);
|
||||
ins.imageSize = halfImageSize;
|
||||
|
||||
// initialize accumulators
|
||||
FfxDofAccumulators acc;
|
||||
acc.prevBucket.color = FfxFloat32x4(0, 0, 0, 0);
|
||||
acc.prevBucket.ringCovg = 0;
|
||||
acc.prevBucket.radius = 0;
|
||||
acc.prevBucket.sampleCount = 0;
|
||||
|
||||
FfxFloat32 centerWeight = FfxDofWeight(ins, ins.centerCoc);
|
||||
FfxFloat32 centerCovg = FfxDofCoverage(ins, ins.centerCoc);
|
||||
|
||||
FfxFloat32x4 centerColor = FfxFloat32x4(FfxDofLoadInput(pixel).rgb, 1);
|
||||
acc.nearColor = FfxFloat32x4(0, 0, 0, 0);
|
||||
acc.fillColor = FfxFloat32x4(0, 0, 0, 0);
|
||||
|
||||
if (ins.nearField)
|
||||
{
|
||||
// for near field: adjust center weight to cover everything beyond innermost ring
|
||||
// radius of innermost ring:
|
||||
FfxFloat32 innerRingRad = max(1, ins.tileCoc * ffxReciprocal(ins.nRings) - pow(2, ins.mipLevel));
|
||||
FfxFloat32 nearCenterWeight = innerRingRad * innerRingRad;
|
||||
|
||||
// if center radius < 1px, split the center color between near and fill
|
||||
FfxFloat32 nearPart = ffxSaturate(ins.centerCoc), fillPart = 1 - nearPart;
|
||||
acc.nearColor = centerColor * centerWeight * nearCenterWeight * nearPart;
|
||||
acc.fillColor = centerColor * fillPart;
|
||||
}
|
||||
|
||||
if (tileClass.needsNear && tileClass.needsFar)
|
||||
{
|
||||
FfxDofProcessNearFar(ins, acc);
|
||||
}
|
||||
else if (tileClass.needsNear)
|
||||
{
|
||||
if (tileClass.colorOnly)
|
||||
FfxDofProcessNearColorOnly(ins, acc);
|
||||
else
|
||||
FfxDofProcessNearOnly(ins, acc);
|
||||
}
|
||||
else if (tileClass.needsFar)
|
||||
{
|
||||
if (tileClass.colorOnly)
|
||||
FfxDofProcessFarColorOnly(ins, acc);
|
||||
else
|
||||
FfxDofProcessFarOnly(ins, acc);
|
||||
}
|
||||
else // if (!tileClass.needsFar && !tileClass.needsNear)
|
||||
{
|
||||
FfxDofStoreFar(pixel, FfxHalfOpt4(FfxDofLoadInput(pixel).rgb, 1));
|
||||
FfxDofStoreNear(pixel, FfxHalfOpt4(0, 0, 0, 0));
|
||||
return;
|
||||
}
|
||||
|
||||
// process center
|
||||
acc.currBucket.ringCovg = ins.nearField ? 0 : centerCovg;
|
||||
acc.currBucket.color = ins.nearField ? FfxFloat32x4(0, 0, 0, 0) : centerColor * centerWeight;
|
||||
acc.currBucket.radius = 0;
|
||||
acc.currBucket.sampleCount = 1;
|
||||
FfxDofMergeBuckets(acc, 1);
|
||||
|
||||
if (ins.nearField)
|
||||
{
|
||||
acc.prevBucket.color += acc.fillColor;
|
||||
}
|
||||
FfxFloat32 fgOpacity = (!tileClass.needsFar && tileClass.colorOnly) ? 1.0 :
|
||||
ffxSaturate(acc.nearColor.a / (FfxDofWeight(ins, ins.tileCoc) * ins.nSamples));
|
||||
|
||||
FfxFloat32x4 ffTarget = acc.prevBucket.color / acc.prevBucket.color.a;
|
||||
FfxFloat32x4 ffOutput = !any(isnan(ffTarget)) ? ffTarget : FfxFloat32x4(0, 0, 0, 0);
|
||||
FfxFloat32x3 nfTarget = acc.nearColor.rgb / acc.nearColor.a;
|
||||
FfxFloat32x4 nfOutput = FfxFloat32x4(!any(isnan(nfTarget)) ? nfTarget : FfxFloat32x3(0, 0, 0), fgOpacity);
|
||||
|
||||
FfxDofStoreFar(pixel, FfxHalfOpt4(ffOutput));
|
||||
FfxDofStoreNear(pixel, FfxHalfOpt4(nfOutput));
|
||||
}
|
||||
282
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/dof/ffx_dof_callbacks_glsl.h
vendored
Normal file
282
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/dof/ffx_dof_callbacks_glsl.h
vendored
Normal file
@@ -0,0 +1,282 @@
|
||||
// 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_dof_resources.h"
|
||||
#include "ffx_core.h"
|
||||
|
||||
#if defined(FFX_GPU)
|
||||
#ifndef FFX_PREFER_WAVE64
|
||||
#define FFX_PREFER_WAVE64
|
||||
#endif // #ifndef FFX_PREFER_WAVE64
|
||||
|
||||
#if defined(FFX_DOF_BIND_CB_DOF)
|
||||
layout (set = 0, binding = FFX_DOF_BIND_CB_DOF, std140) uniform cbDOF_t
|
||||
{
|
||||
FfxFloat32 cocScale;
|
||||
FfxFloat32 cocBias;
|
||||
FfxUInt32x2 inputSizeHalf;
|
||||
FfxUInt32x2 inputSize;
|
||||
FfxFloat32x2 inputSizeHalfRcp;
|
||||
FfxFloat32 cocLimit;
|
||||
FfxUInt32 maxRings;
|
||||
#define FFX_DOF_CONSTANT_BUFFER_1_SIZE 10 // Number of 32-bit values. This must be kept in sync with the cbDOF size.
|
||||
} cbDOF;
|
||||
#endif
|
||||
|
||||
FfxFloat32 CocScale()
|
||||
{
|
||||
return cbDOF.cocScale;
|
||||
}
|
||||
|
||||
FfxFloat32 CocBias()
|
||||
{
|
||||
return cbDOF.cocBias;
|
||||
}
|
||||
|
||||
FfxUInt32x2 InputSizeHalf()
|
||||
{
|
||||
return cbDOF.inputSizeHalf;
|
||||
}
|
||||
|
||||
FfxUInt32x2 InputSize()
|
||||
{
|
||||
return cbDOF.inputSize;
|
||||
}
|
||||
|
||||
FfxFloat32x2 InputSizeHalfRcp()
|
||||
{
|
||||
return cbDOF.inputSizeHalfRcp;
|
||||
}
|
||||
|
||||
FfxFloat32 CocLimit()
|
||||
{
|
||||
return cbDOF.cocLimit;
|
||||
}
|
||||
|
||||
FfxUInt32 MaxRings()
|
||||
{
|
||||
return cbDOF.maxRings;
|
||||
}
|
||||
|
||||
layout (set = 0, binding = 1000)
|
||||
uniform sampler LinearSampler;
|
||||
layout (set = 0, binding = 1001)
|
||||
uniform sampler PointSampler;
|
||||
|
||||
#if FFX_HALF
|
||||
#define FFX_DOF_HALF_OPT_LAYOUT rgba16f
|
||||
#else // #if FFX_HALF
|
||||
#define FFX_DOF_HALF_OPT_LAYOUT rgba32f
|
||||
#endif // #if FFX_HALF #else
|
||||
|
||||
// SRVs
|
||||
#if defined(FFX_DOF_BIND_SRV_INPUT_DEPTH)
|
||||
layout (set = 0, binding = FFX_DOF_BIND_SRV_INPUT_DEPTH)
|
||||
uniform texture2D r_input_depth;
|
||||
#endif
|
||||
#if defined(FFX_DOF_BIND_SRV_INPUT_COLOR)
|
||||
layout (set = 0, binding = FFX_DOF_BIND_SRV_INPUT_COLOR)
|
||||
uniform texture2D r_input_color;
|
||||
#endif
|
||||
#if defined(FFX_DOF_BIND_SRV_INTERNAL_BILAT_COLOR)
|
||||
layout (set = 0, binding = FFX_DOF_BIND_SRV_INTERNAL_BILAT_COLOR)
|
||||
uniform texture2D r_internal_bilat_color;
|
||||
#endif
|
||||
#if defined(FFX_DOF_BIND_SRV_INTERNAL_DILATED_RADIUS)
|
||||
layout (set = 0, binding = FFX_DOF_BIND_SRV_INTERNAL_DILATED_RADIUS)
|
||||
uniform texture2D r_internal_dilated_radius;
|
||||
#endif
|
||||
|
||||
// UAVs
|
||||
#if defined(FFX_DOF_BIND_UAV_INTERNAL_BILAT_COLOR)
|
||||
layout (set = 0, binding = FFX_DOF_BIND_UAV_INTERNAL_BILAT_COLOR, FFX_DOF_HALF_OPT_LAYOUT)
|
||||
uniform image2D rw_internal_bilat_color[4];
|
||||
#endif
|
||||
#if defined(FFX_DOF_BIND_UAV_INTERNAL_RADIUS)
|
||||
layout (set = 0, binding = FFX_DOF_BIND_UAV_INTERNAL_RADIUS, rg32f)
|
||||
uniform image2D rw_internal_radius;
|
||||
#endif
|
||||
#if defined(FFX_DOF_BIND_UAV_INTERNAL_DILATED_RADIUS)
|
||||
layout (set = 0, binding = FFX_DOF_BIND_UAV_INTERNAL_DILATED_RADIUS, rg32f)
|
||||
uniform image2D rw_internal_dilated_radius;
|
||||
#endif
|
||||
#if defined(FFX_DOF_BIND_UAV_INTERNAL_NEAR)
|
||||
layout (set = 0, binding = FFX_DOF_BIND_UAV_INTERNAL_NEAR, FFX_DOF_HALF_OPT_LAYOUT)
|
||||
uniform image2D rw_internal_near;
|
||||
#endif
|
||||
#if defined(FFX_DOF_BIND_UAV_INTERNAL_FAR)
|
||||
layout (set = 0, binding = FFX_DOF_BIND_UAV_INTERNAL_FAR, FFX_DOF_HALF_OPT_LAYOUT)
|
||||
uniform image2D rw_internal_far;
|
||||
#endif
|
||||
#if defined(FFX_DOF_BIND_UAV_OUTPUT_COLOR)
|
||||
layout (set = 0, binding = FFX_DOF_BIND_UAV_OUTPUT_COLOR, rgba32f)
|
||||
uniform image2D rw_output_color;
|
||||
#endif
|
||||
#if defined(FFX_DOF_BIND_UAV_INTERNAL_GLOBALS)
|
||||
layout (set = 0, binding = FFX_DOF_BIND_UAV_INTERNAL_GLOBALS, std430)
|
||||
coherent buffer DofGlobalVars_t { uint maxTileRad; } rw_internal_globals;
|
||||
#endif
|
||||
|
||||
#include "ffx_dof_common.h"
|
||||
|
||||
#if defined(FFX_DOF_BIND_SRV_INPUT_COLOR)
|
||||
FfxHalfOpt4 FfxDofLoadSource(FfxInt32x2 tex)
|
||||
{
|
||||
return FfxHalfOpt4(texelFetch(sampler2D(r_input_color, LinearSampler), tex, 0));
|
||||
}
|
||||
#endif // #if defined(FFX_DOF_BIND_SRV_INPUT_COLOR)
|
||||
|
||||
#if defined(FFX_DOF_BIND_UAV_INTERNAL_BILAT_COLOR)
|
||||
void FfxDofStoreBilatMip(FfxUInt32 mip, FfxInt32x2 tex, FfxHalfOpt4 value)
|
||||
{
|
||||
imageStore(rw_internal_bilat_color[mip], tex, value);
|
||||
}
|
||||
#endif // #if defined(FFX_DOF_BIND_UAV_INTERNAL_BILAT_COLOR)
|
||||
|
||||
#if defined(FFX_DOF_BIND_CB_DOF)
|
||||
FfxFloat32 FfxDofGetCoc(FfxFloat32 depth)
|
||||
{
|
||||
// clamped for perf reasons
|
||||
return clamp(CocScale() * depth + CocBias(), -CocLimit(), CocLimit());
|
||||
}
|
||||
#endif // #if defined(FFX_DOF_BIND_CB_DOF)
|
||||
|
||||
#if defined(FFX_DOF_BIND_UAV_INTERNAL_DILATED_RADIUS)
|
||||
void FfxDofStoreDilatedRadius(FfxUInt32x2 coord, FfxFloat32x2 dilatedMinMax)
|
||||
{
|
||||
imageStore(rw_internal_dilated_radius, ivec2(coord), vec4(dilatedMinMax, 0, 0));
|
||||
}
|
||||
#endif // #if defined(FFX_DOF_BIND_UAV_INTERNAL_DILATED_RADIUS)
|
||||
|
||||
#if defined(FFX_DOF_BIND_SRV_INTERNAL_DILATED_RADIUS)
|
||||
#if defined(FFX_DOF_BIND_CB_DOF)
|
||||
FfxFloat32x2 FfxDofSampleDilatedRadius(FfxUInt32x2 coord)
|
||||
{
|
||||
return textureLod(sampler2D(r_internal_dilated_radius, LinearSampler), vec2(coord) * InputSizeHalfRcp(), 0).rg;
|
||||
}
|
||||
#endif // #if defined(FFX_DOF_BIND_CB_DOF)
|
||||
|
||||
FfxFloat32x2 FfxDofLoadDilatedRadius(FfxUInt32x2 coord)
|
||||
{
|
||||
return texelFetch(sampler2D(r_internal_dilated_radius, LinearSampler), ivec2(coord), 0).rg;
|
||||
}
|
||||
#endif // #if defined(FFX_DOF_BIND_SRV_INTERNAL_DILATED_RADIUS)
|
||||
|
||||
#if defined(FFX_DOF_BIND_SRV_INTERNAL_BILAT_COLOR)
|
||||
FfxHalfOpt4 FfxDofLoadInput(FfxUInt32x2 coord)
|
||||
{
|
||||
return FfxHalfOpt4(texelFetch(sampler2D(r_internal_bilat_color, LinearSampler), ivec2(coord), 0));
|
||||
}
|
||||
|
||||
#if defined(FFX_DOF_BIND_CB_DOF)
|
||||
FfxHalfOpt4 FfxDofSampleInput(FfxFloat32x2 coord, FfxUInt32 mip)
|
||||
{
|
||||
return FfxHalfOpt4(textureLod(sampler2D(r_internal_bilat_color, PointSampler), coord, mip));
|
||||
}
|
||||
#endif // #if defined(FFX_DOF_BIND_CB_DOF)
|
||||
#endif // #if defined(FFX_DOF_BIND_SRV_INTERNAL_BILAT_COLOR)
|
||||
|
||||
#if defined(FFX_DOF_BIND_SRV_INPUT_DEPTH)
|
||||
FfxFloat32x4 FfxDofGatherDepth(FfxFloat32x2 coord)
|
||||
{
|
||||
return textureGather(sampler2D(r_input_depth, LinearSampler), coord);
|
||||
}
|
||||
|
||||
FfxFloat32 FfxDofLoadFullDepth(FfxUInt32x2 coord)
|
||||
{
|
||||
return texelFetch(sampler2D(r_input_depth, LinearSampler), ivec2(coord), 0).r;
|
||||
}
|
||||
#endif // #if defined(FFX_DOF_BIND_SRV_INPUT_DEPTH)
|
||||
|
||||
#if defined(FFX_DOF_BIND_UAV_INTERNAL_NEAR)
|
||||
void FfxDofStoreNear(FfxUInt32x2 coord, FfxHalfOpt4 color)
|
||||
{
|
||||
imageStore(rw_internal_near, ivec2(coord), color);
|
||||
}
|
||||
|
||||
FfxHalfOpt4 FfxDofLoadNear(FfxUInt32x2 coord)
|
||||
{
|
||||
return FfxHalfOpt4(imageLoad(rw_internal_near, ivec2(coord)));
|
||||
}
|
||||
#endif // #if defined(FFX_DOF_BIND_UAV_INTERNAL_NEAR)
|
||||
|
||||
#if defined(FFX_DOF_BIND_UAV_INTERNAL_FAR)
|
||||
void FfxDofStoreFar(FfxUInt32x2 coord, FfxHalfOpt4 color)
|
||||
{
|
||||
imageStore(rw_internal_far, ivec2(coord), color);
|
||||
}
|
||||
|
||||
FfxHalfOpt4 FfxDofLoadFar(FfxUInt32x2 coord)
|
||||
{
|
||||
return FfxHalfOpt4(imageLoad(rw_internal_far, ivec2(coord)));
|
||||
}
|
||||
#endif // #if defined(FFX_DOF_BIND_UAV_INTERNAL_FAR)
|
||||
|
||||
#if defined(FFX_DOF_BIND_UAV_INTERNAL_GLOBALS)
|
||||
void FfxDofAccumMaxTileRadius(FfxUInt32 radius)
|
||||
{
|
||||
atomicMax(rw_internal_globals.maxTileRad, radius);
|
||||
}
|
||||
|
||||
FfxUInt32 FfxDofGetMaxTileRadius()
|
||||
{
|
||||
return rw_internal_globals.maxTileRad;
|
||||
}
|
||||
|
||||
void FfxDofResetMaxTileRadius()
|
||||
{
|
||||
rw_internal_globals.maxTileRad = 0;
|
||||
}
|
||||
#endif // #if defined(FFX_DOF_BIND_UAV_INTERNAL_GLOBALS)
|
||||
|
||||
#if defined(FFX_DOF_BIND_UAV_INTERNAL_RADIUS)
|
||||
void FfxDofStoreTileRadius(FfxUInt32x2 tile, FfxFloat32x2 radius)
|
||||
{
|
||||
imageStore(rw_internal_radius, ivec2(tile), vec4(radius, 0, 0));
|
||||
}
|
||||
|
||||
FfxFloat32x2 FfxDofLoadTileRadius(FfxUInt32x2 tile)
|
||||
{
|
||||
return imageLoad(rw_internal_radius, ivec2(tile)).rg;
|
||||
}
|
||||
#endif // #if defined(FFX_DOF_BIND_UAV_INTERNAL_RADIUS)
|
||||
|
||||
#if defined(FFX_DOF_BIND_SRV_INPUT_COLOR)
|
||||
FfxFloat32x4 FfxDofLoadFullInput(FfxUInt32x2 coord)
|
||||
{
|
||||
return texelFetch(sampler2D(r_input_color, LinearSampler), ivec2(coord), 0);
|
||||
}
|
||||
#elif (defined(FFX_DOF_BIND_UAV_OUTPUT_COLOR)) && FFX_DOF_OPTION_COMBINE_IN_PLACE
|
||||
FfxFloat32x4 FfxDofLoadFullInput(FfxUInt32x2 coord)
|
||||
{
|
||||
return imageLoad(rw_output_color, ivec2(coord));
|
||||
}
|
||||
#endif // #if defined(FFX_DOF_BIND_SRV_INPUT_COLOR)
|
||||
|
||||
#if defined(FFX_DOF_BIND_UAV_OUTPUT_COLOR)
|
||||
void FfxDofStoreOutput(FfxUInt32x2 coord, FfxFloat32x4 color)
|
||||
{
|
||||
imageStore(rw_output_color, ivec2(coord), color);
|
||||
}
|
||||
#endif // #if defined(FFX_DOF_BIND_UAV_OUTPUT_COLOR)
|
||||
|
||||
#endif // #if defined(FFX_GPU)
|
||||
322
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/dof/ffx_dof_callbacks_hlsl.h
vendored
Normal file
322
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/dof/ffx_dof_callbacks_hlsl.h
vendored
Normal file
@@ -0,0 +1,322 @@
|
||||
// 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_dof_resources.h"
|
||||
#include "ffx_core.h"
|
||||
#include "ffx_dof_common.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
|
||||
|
||||
#ifndef FFX_PREFER_WAVE64
|
||||
#define FFX_PREFER_WAVE64
|
||||
#endif // #ifndef FFX_PREFER_WAVE64
|
||||
|
||||
#pragma warning(disable: 3205) // conversion from larger type to smaller
|
||||
|
||||
#define DECLARE_SRV_REGISTER(regIndex) t##regIndex
|
||||
#define DECLARE_UAV_REGISTER(regIndex) u##regIndex
|
||||
#define DECLARE_CB_REGISTER(regIndex) b##regIndex
|
||||
#define FFX_DOF_DECLARE_SRV(regIndex) register(DECLARE_SRV_REGISTER(regIndex))
|
||||
#define FFX_DOF_DECLARE_UAV(regIndex) register(DECLARE_UAV_REGISTER(regIndex))
|
||||
#define FFX_DOF_DECLARE_CB(regIndex) register(DECLARE_CB_REGISTER(regIndex))
|
||||
|
||||
#if defined(FFX_DOF_BIND_CB_DOF)
|
||||
cbuffer cbDOF : FFX_DOF_DECLARE_CB(FFX_DOF_BIND_CB_DOF)
|
||||
{
|
||||
FfxFloat32 cocScale;
|
||||
FfxFloat32 cocBias;
|
||||
FfxUInt32x2 inputSizeHalf;
|
||||
FfxUInt32x2 inputSize;
|
||||
FfxFloat32x2 inputSizeHalfRcp;
|
||||
FfxFloat32 cocLimit;
|
||||
FfxUInt32 maxRings;
|
||||
#define FFX_DOF_CONSTANT_BUFFER_1_SIZE 10 // Number of 32-bit values. This must be kept in sync with the cbDOF size.
|
||||
};
|
||||
#else
|
||||
#define cocScale 0
|
||||
#define cocBias 0
|
||||
#define inputSizeHalf 0
|
||||
#define inputSize 0
|
||||
#define inputSizeHalfRcp 0
|
||||
#define cocLimit 0
|
||||
#define maxRings 0
|
||||
#endif
|
||||
|
||||
#define FFX_DOF_ROOTSIG_STRINGIFY(p) FFX_DOF_ROOTSIG_STR(p)
|
||||
#define FFX_DOF_ROOTSIG_STR(p) #p
|
||||
#define FFX_DOF_ROOTSIG [RootSignature("DescriptorTable(UAV(u0, numDescriptors = " FFX_DOF_ROOTSIG_STRINGIFY(FFX_DOF_RESOURCE_IDENTIFIER_COUNT) ")), " \
|
||||
"DescriptorTable(SRV(t0, numDescriptors = " FFX_DOF_ROOTSIG_STRINGIFY(FFX_DOF_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), " \
|
||||
"StaticSampler(s1, filter = FILTER_MIN_MAG_MIP_POINT, " \
|
||||
"addressU = TEXTURE_ADDRESS_CLAMP, " \
|
||||
"addressV = TEXTURE_ADDRESS_CLAMP, " \
|
||||
"addressW = TEXTURE_ADDRESS_CLAMP, " \
|
||||
"comparisonFunc = COMPARISON_NEVER, " \
|
||||
"borderColor = STATIC_BORDER_COLOR_TRANSPARENT_BLACK)" )]
|
||||
|
||||
#if defined(FFX_DOF_EMBED_ROOTSIG)
|
||||
#define FFX_DOF_EMBED_ROOTSIG_CONTENT FFX_DOF_ROOTSIG
|
||||
#else
|
||||
#define FFX_DOF_EMBED_ROOTSIG_CONTENT
|
||||
#endif // #if FFX_SPD_EMBED_ROOTSIG
|
||||
|
||||
FfxFloat32 CocScale()
|
||||
{
|
||||
return cocScale;
|
||||
}
|
||||
|
||||
FfxFloat32 CocBias()
|
||||
{
|
||||
return cocBias;
|
||||
}
|
||||
|
||||
FfxUInt32x2 InputSizeHalf()
|
||||
{
|
||||
return inputSizeHalf;
|
||||
}
|
||||
|
||||
FfxUInt32x2 InputSize()
|
||||
{
|
||||
return inputSize;
|
||||
}
|
||||
|
||||
FfxFloat32x2 InputSizeHalfRcp()
|
||||
{
|
||||
return inputSizeHalfRcp;
|
||||
}
|
||||
|
||||
FfxFloat32 CocLimit()
|
||||
{
|
||||
return cocLimit;
|
||||
}
|
||||
|
||||
FfxUInt32 MaxRings()
|
||||
{
|
||||
return maxRings;
|
||||
}
|
||||
|
||||
SamplerState LinearSampler : register(s0);
|
||||
SamplerState PointSampler : register(s1);
|
||||
|
||||
// SRVs
|
||||
#if defined(FFX_DOF_BIND_SRV_INPUT_DEPTH)
|
||||
Texture2D<FfxFloat32> r_input_depth : FFX_DOF_DECLARE_SRV(FFX_DOF_BIND_SRV_INPUT_DEPTH);
|
||||
#endif
|
||||
#if defined(FFX_DOF_BIND_SRV_INPUT_COLOR)
|
||||
Texture2D<FfxFloat32x4> r_input_color : FFX_DOF_DECLARE_SRV(FFX_DOF_BIND_SRV_INPUT_COLOR);
|
||||
#endif
|
||||
#if defined(FFX_DOF_BIND_SRV_INTERNAL_BILAT_COLOR)
|
||||
Texture2D<FfxHalfOpt4> r_internal_bilat_color : FFX_DOF_DECLARE_SRV(FFX_DOF_BIND_SRV_INTERNAL_BILAT_COLOR);
|
||||
#endif
|
||||
#if defined(FFX_DOF_BIND_SRV_INTERNAL_DILATED_RADIUS)
|
||||
Texture2D<FfxFloat32x2> r_internal_dilated_radius : FFX_DOF_DECLARE_SRV(FFX_DOF_BIND_SRV_INTERNAL_DILATED_RADIUS);
|
||||
#endif
|
||||
|
||||
// UAVs
|
||||
#if defined(FFX_DOF_BIND_UAV_INTERNAL_BILAT_COLOR)
|
||||
RWTexture2D<FfxHalfOpt4> rw_internal_bilat_color[4] : FFX_DOF_DECLARE_UAV(FFX_DOF_BIND_UAV_INTERNAL_BILAT_COLOR);
|
||||
#endif
|
||||
#if defined(FFX_DOF_BIND_UAV_INTERNAL_RADIUS)
|
||||
RWTexture2D<FfxFloat32x2> rw_internal_radius : FFX_DOF_DECLARE_UAV(FFX_DOF_BIND_UAV_INTERNAL_RADIUS);
|
||||
#endif
|
||||
#if defined(FFX_DOF_BIND_UAV_INTERNAL_DILATED_RADIUS)
|
||||
RWTexture2D<FfxFloat32x2> rw_internal_dilated_radius : FFX_DOF_DECLARE_UAV(FFX_DOF_BIND_UAV_INTERNAL_DILATED_RADIUS);
|
||||
#endif
|
||||
#if defined(FFX_DOF_BIND_UAV_INTERNAL_NEAR)
|
||||
RWTexture2D<FfxHalfOpt4> rw_internal_near : FFX_DOF_DECLARE_UAV(FFX_DOF_BIND_UAV_INTERNAL_NEAR);
|
||||
#endif
|
||||
#if defined(FFX_DOF_BIND_UAV_INTERNAL_FAR)
|
||||
RWTexture2D<FfxHalfOpt4> rw_internal_far : FFX_DOF_DECLARE_UAV(FFX_DOF_BIND_UAV_INTERNAL_FAR);
|
||||
#endif
|
||||
#if defined(FFX_DOF_BIND_UAV_OUTPUT_COLOR)
|
||||
RWTexture2D<FfxFloat32x4> rw_output_color : FFX_DOF_DECLARE_UAV(FFX_DOF_BIND_UAV_OUTPUT_COLOR);
|
||||
#endif
|
||||
#if defined(FFX_DOF_BIND_UAV_INTERNAL_GLOBALS)
|
||||
struct DofGlobalVars { uint maxTileRad; };
|
||||
globallycoherent RWStructuredBuffer<DofGlobalVars> rw_internal_globals : FFX_DOF_DECLARE_UAV(FFX_DOF_BIND_UAV_INTERNAL_GLOBALS);
|
||||
#endif
|
||||
|
||||
#if defined(FFX_DOF_BIND_SRV_INPUT_COLOR)
|
||||
FfxHalfOpt4 FfxDofLoadSource(FfxInt32x2 tex)
|
||||
{
|
||||
return FfxHalfOpt4(r_input_color[tex]);
|
||||
}
|
||||
#endif // #if defined(FFX_DOF_BIND_SRV_INPUT_COLOR)
|
||||
|
||||
#if defined(FFX_DOF_BIND_UAV_INTERNAL_BILAT_COLOR)
|
||||
void FfxDofStoreBilatMip(FfxUInt32 mip, FfxInt32x2 tex, FfxHalfOpt4 value)
|
||||
{
|
||||
rw_internal_bilat_color[mip][tex] = value;
|
||||
}
|
||||
#endif // #if defined(FFX_DOF_BIND_UAV_INTERNAL_BILAT_COLOR)
|
||||
|
||||
FfxFloat32 FfxDofGetCoc(FfxFloat32 depth)
|
||||
{
|
||||
// clamped for perf reasons
|
||||
return clamp(CocScale() * depth + CocBias(), -CocLimit(), CocLimit());
|
||||
}
|
||||
|
||||
#if defined(FFX_DOF_BIND_UAV_INTERNAL_DILATED_RADIUS)
|
||||
void FfxDofStoreDilatedRadius(FfxUInt32x2 coord, FfxFloat32x2 dilatedMinMax)
|
||||
{
|
||||
rw_internal_dilated_radius[coord] = dilatedMinMax;
|
||||
}
|
||||
#endif // #if defined(FFX_DOF_BIND_UAV_INTERNAL_DILATED_RADIUS)
|
||||
|
||||
#if defined(FFX_DOF_BIND_SRV_INTERNAL_DILATED_RADIUS)
|
||||
FfxFloat32x2 FfxDofSampleDilatedRadius(FfxUInt32x2 coord)
|
||||
{
|
||||
return r_internal_dilated_radius.SampleLevel(LinearSampler, float2(coord) * InputSizeHalfRcp(), 0);
|
||||
}
|
||||
#endif // #if defined(FFX_DOF_BIND_SRV_INTERNAL_DILATED_RADIUS)
|
||||
|
||||
#if defined(FFX_DOF_BIND_SRV_INTERNAL_DILATED_RADIUS)
|
||||
FfxFloat32x2 FfxDofLoadDilatedRadius(FfxUInt32x2 coord)
|
||||
{
|
||||
return r_internal_dilated_radius[coord];
|
||||
}
|
||||
#endif // #if defined(FFX_DOF_BIND_SRV_INTERNAL_DILATED_RADIUS)
|
||||
|
||||
#if defined(FFX_DOF_BIND_SRV_INTERNAL_BILAT_COLOR)
|
||||
FfxHalfOpt4 FfxDofLoadInput(FfxUInt32x2 coord)
|
||||
{
|
||||
return r_internal_bilat_color[coord];
|
||||
}
|
||||
#endif // #if defined(FFX_DOF_BIND_SRV_INTERNAL_BILAT_COLOR)
|
||||
|
||||
#if defined(FFX_DOF_BIND_SRV_INTERNAL_BILAT_COLOR)
|
||||
FfxHalfOpt4 FfxDofSampleInput(FfxFloat32x2 coord, FfxUInt32 mip)
|
||||
{
|
||||
return r_internal_bilat_color.SampleLevel(PointSampler, coord, mip);
|
||||
}
|
||||
#endif // #if defined(FFX_DOF_BIND_SRV_INTERNAL_BILAT_COLOR)
|
||||
|
||||
#if defined(FFX_DOF_BIND_SRV_INPUT_DEPTH)
|
||||
FfxFloat32x4 FfxDofGatherDepth(FfxFloat32x2 coord)
|
||||
{
|
||||
return r_input_depth.GatherRed(LinearSampler, coord);
|
||||
}
|
||||
#endif // #if defined(FFX_DOF_BIND_SRV_INPUT_DEPTH)
|
||||
|
||||
#if defined(FFX_DOF_BIND_SRV_INPUT_DEPTH)
|
||||
FfxFloat32 FfxDofLoadFullDepth(FfxUInt32x2 coord)
|
||||
{
|
||||
return r_input_depth[coord];
|
||||
}
|
||||
#endif // #if defined(FFX_DOF_BIND_SRV_INPUT_DEPTH)
|
||||
|
||||
#if defined(FFX_DOF_BIND_UAV_INTERNAL_NEAR)
|
||||
void FfxDofStoreNear(FfxUInt32x2 coord, FfxHalfOpt4 color)
|
||||
{
|
||||
rw_internal_near[coord] = color;
|
||||
}
|
||||
#endif // #if defined(FFX_DOF_BIND_UAV_INTERNAL_NEAR)
|
||||
|
||||
#if defined(FFX_DOF_BIND_UAV_INTERNAL_NEAR)
|
||||
FfxHalfOpt4 FfxDofLoadNear(FfxUInt32x2 coord)
|
||||
{
|
||||
return rw_internal_near[coord];
|
||||
}
|
||||
#endif // #if defined(FFX_DOF_BIND_UAV_INTERNAL_NEAR)
|
||||
|
||||
#if defined(FFX_DOF_BIND_UAV_INTERNAL_FAR)
|
||||
void FfxDofStoreFar(FfxUInt32x2 coord, FfxHalfOpt4 color)
|
||||
{
|
||||
rw_internal_far[coord] = color;
|
||||
}
|
||||
#endif // #if defined(FFX_DOF_BIND_UAV_INTERNAL_FAR)
|
||||
|
||||
#if defined(FFX_DOF_BIND_UAV_INTERNAL_FAR)
|
||||
FfxHalfOpt4 FfxDofLoadFar(FfxUInt32x2 coord)
|
||||
{
|
||||
return rw_internal_far[coord];
|
||||
}
|
||||
#endif // #if defined(FFX_DOF_BIND_UAV_INTERNAL_FAR)
|
||||
|
||||
#if defined(FFX_DOF_BIND_UAV_INTERNAL_GLOBALS)
|
||||
void FfxDofAccumMaxTileRadius(FfxUInt32 radius)
|
||||
{
|
||||
uint dummy;
|
||||
InterlockedMax(rw_internal_globals[0].maxTileRad, radius, dummy);
|
||||
}
|
||||
#endif // #if defined(FFX_DOF_BIND_UAV_INTERNAL_GLOBALS)
|
||||
|
||||
#if defined(FFX_DOF_BIND_UAV_INTERNAL_GLOBALS)
|
||||
FfxUInt32 FfxDofGetMaxTileRadius()
|
||||
{
|
||||
return rw_internal_globals[0].maxTileRad;
|
||||
}
|
||||
#endif // #if defined(FFX_DOF_BIND_UAV_INTERNAL_GLOBALS)
|
||||
|
||||
#if defined(FFX_DOF_BIND_UAV_INTERNAL_GLOBALS)
|
||||
void FfxDofResetMaxTileRadius()
|
||||
{
|
||||
rw_internal_globals[0].maxTileRad = 0;
|
||||
}
|
||||
#endif // #if defined(FFX_DOF_BIND_UAV_INTERNAL_GLOBALS)
|
||||
|
||||
#if defined(FFX_DOF_BIND_UAV_INTERNAL_RADIUS)
|
||||
void FfxDofStoreTileRadius(FfxUInt32x2 tile, FfxFloat32x2 radius)
|
||||
{
|
||||
rw_internal_radius[tile] = radius;
|
||||
}
|
||||
#endif // #if defined(FFX_DOF_BIND_UAV_INTERNAL_RADIUS)
|
||||
|
||||
#if defined(FFX_DOF_BIND_UAV_INTERNAL_RADIUS)
|
||||
FfxFloat32x2 FfxDofLoadTileRadius(FfxUInt32x2 tile)
|
||||
{
|
||||
return rw_internal_radius[tile];
|
||||
}
|
||||
#endif // #if defined(FFX_DOF_BIND_UAV_INTERNAL_RADIUS)
|
||||
|
||||
FfxFloat32x4 FfxDofLoadFullInput(FfxUInt32x2 coord)
|
||||
{
|
||||
#if defined(FFX_DOF_BIND_SRV_INPUT_COLOR)
|
||||
return r_input_color[coord];
|
||||
#elif (defined(FFX_DOF_BIND_UAV_OUTPUT_COLOR)) && FFX_DOF_OPTION_COMBINE_IN_PLACE
|
||||
return rw_output_color[coord];
|
||||
#endif // #if defined(FFX_DOF_BIND_SRV_INPUT_COLOR)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(FFX_DOF_BIND_UAV_OUTPUT_COLOR)
|
||||
void FfxDofStoreOutput(FfxUInt32x2 coord, FfxFloat32x4 color)
|
||||
{
|
||||
rw_output_color[coord] = color;
|
||||
}
|
||||
#endif // #if defined(FFX_DOF_BIND_UAV_OUTPUT_COLOR)
|
||||
|
||||
#endif // #if defined(FFX_GPU)
|
||||
142
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/dof/ffx_dof_common.h
vendored
Normal file
142
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/dof/ffx_dof_common.h
vendored
Normal 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_DOF_COMMON_H
|
||||
#define FFX_DOF_COMMON_H
|
||||
|
||||
/// @defgroup FfxGPUDof FidelityFX DOF
|
||||
/// FidelityFX Depth of Field GPU documentation
|
||||
///
|
||||
/// @ingroup FfxGPUEffects
|
||||
|
||||
// Constants - these are fixed magic numbers. Changes likely require changing code.
|
||||
|
||||
/// The width/height of tiles storing per-tile min and max CoC. The blur pass needs to run
|
||||
/// at a compatible tile size, so that the assumption that min/max CoC is uniform for all threads in
|
||||
/// a thread group holds.
|
||||
///
|
||||
/// @ingroup FfxGPUDof
|
||||
FFX_STATIC const FfxUInt32 FFX_DOF_DEPTH_TILE_SIZE = 8;
|
||||
|
||||
// Default settings
|
||||
#ifndef FFX_DOF_OPTION_MAX_MIP
|
||||
/// The number of mips that should be generated in the color downsample pass
|
||||
///
|
||||
/// @ingroup FfxGPUDof
|
||||
#define FFX_DOF_OPTION_MAX_MIP 4
|
||||
#endif
|
||||
|
||||
#ifndef FFX_DOF_OPTION_MAX_RING_MERGE_LOG
|
||||
/// The base-2 logarithm of the number of blur kernel rings that may be merged, if possible.
|
||||
///
|
||||
/// Setting this to zero disables ring merging.
|
||||
///
|
||||
/// Values above 1 are technically valid, but are known to cause a visible quality drop.
|
||||
///
|
||||
/// @ingroup FfxGPUDof
|
||||
#define FFX_DOF_OPTION_MAX_RING_MERGE_LOG 1
|
||||
#endif
|
||||
|
||||
#define FFX_DOF_MAX_RING_MERGE (1 << FFX_DOF_OPTION_MAX_RING_MERGE_LOG)
|
||||
|
||||
// optional 16-bit types
|
||||
#if FFX_HLSL
|
||||
#if FFX_HALF
|
||||
typedef FfxFloat16 FfxHalfOpt;
|
||||
typedef FfxFloat16x2 FfxHalfOpt2;
|
||||
typedef FfxFloat16x3 FfxHalfOpt3;
|
||||
typedef FfxFloat16x4 FfxHalfOpt4;
|
||||
#else
|
||||
typedef FfxFloat32 FfxHalfOpt;
|
||||
typedef FfxFloat32x2 FfxHalfOpt2;
|
||||
typedef FfxFloat32x3 FfxHalfOpt3;
|
||||
typedef FfxFloat32x4 FfxHalfOpt4;
|
||||
#endif
|
||||
#elif FFX_GLSL
|
||||
#if FFX_HALF
|
||||
#define FfxHalfOpt FfxFloat16
|
||||
#define FfxHalfOpt2 FfxFloat16x2
|
||||
#define FfxHalfOpt3 FfxFloat16x3
|
||||
#define FfxHalfOpt4 FfxFloat16x4
|
||||
#else
|
||||
#define FfxHalfOpt FfxFloat32
|
||||
#define FfxHalfOpt2 FfxFloat32x2
|
||||
#define FfxHalfOpt3 FfxFloat32x3
|
||||
#define FfxHalfOpt4 FfxFloat32x4
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// unroll macros with count argument
|
||||
#if FFX_HLSL
|
||||
#define FFX_DOF_UNROLL_N(_n) [unroll(_n)]
|
||||
#define FFX_DOF_UNROLL [unroll]
|
||||
#elif FFX_GLSL // #if FFX_HLSL
|
||||
#define FFX_DOF_UNROLL_N(_n)
|
||||
// enable unrolling loops
|
||||
#extension GL_EXT_control_flow_attributes : enable
|
||||
|
||||
#if GL_EXT_control_flow_attributes
|
||||
#define FFX_DOF_UNROLL [[unroll]]
|
||||
#else
|
||||
#define FFX_DOF_UNROLL
|
||||
#endif // #if GL_EXT_control_flow_attributes
|
||||
#endif // #if FFX_HLSL #elif FFX_GLSL
|
||||
|
||||
// ReadLaneFirst
|
||||
#if FFX_HLSL
|
||||
#define ffxWaveReadLaneFirst WaveReadLaneFirst
|
||||
#elif FFX_GLSL
|
||||
#define ffxWaveReadLaneFirst subgroupBroadcastFirst
|
||||
#endif // #if FFX_GLSL
|
||||
|
||||
// Callback declarations
|
||||
FfxFloat32 FfxDofGetCoc(FfxFloat32 depth); // returns circle of confusion radius in pixels (at half-res). Sign indicates near-field (positive) or far-field (negative).
|
||||
void FfxDofStoreDilatedRadius(FfxUInt32x2 coord, FfxFloat32x2 dilatedMinMax);
|
||||
FfxFloat32x2 FfxDofSampleDilatedRadius(FfxUInt32x2 coord); // returns the dilated min and max depth for a pixel coordinate. Should be bilinearly interpolated!
|
||||
FfxFloat32x2 FfxDofLoadDilatedRadius(FfxUInt32x2 coord); // returns the dilated depth for a *tile* coordinate without interpolation
|
||||
FfxHalfOpt4 FfxDofLoadInput(FfxUInt32x2 coord); // returns input rgb and (in alpha) CoC in pixels from the most detailed mip (which is half-res)
|
||||
FfxHalfOpt4 FfxDofSampleInput(FfxFloat32x2 coord, FfxUInt32 mip); // returns input rgb and (in alpha) CoC in pixels.
|
||||
FfxFloat32x4 FfxDofGatherDepth(FfxFloat32x2 coord); // returns 4 input depth values in a quad, must use sampler with coordinate clamping
|
||||
void FfxDofStoreNear(FfxUInt32x2 coord, FfxHalfOpt4 color); // stores the near color output from the blur pass
|
||||
void FfxDofStoreFar(FfxUInt32x2 coord, FfxHalfOpt4 color); // stores the far color output from the blur pass
|
||||
FfxHalfOpt4 FfxDofLoadNear(FfxUInt32x2 coord); // loads the near color value
|
||||
FfxHalfOpt4 FfxDofLoadFar(FfxUInt32x2 coord); // loads the far color value
|
||||
void FfxDofAccumMaxTileRadius(FfxUInt32 radius); // stores the global maximum dilation radius using an atomic max operation
|
||||
FfxUInt32 FfxDofGetMaxTileRadius(); // gets the global maximum dilation radius
|
||||
void FfxDofResetMaxTileRadius(); // sets max dilation radius back to zero
|
||||
void FfxDofStoreTileRadius(FfxUInt32x2 tile, FfxFloat32x2 radius); // stores the min/max signed radius for a tile in the tile map
|
||||
FfxFloat32x2 FfxDofLoadTileRadius(FfxUInt32x2 tile); // loads the min/max depth for a tile
|
||||
FfxFloat32x4 FfxDofLoadFullInput(FfxUInt32x2 coord); // returns full resultion input rgba (alpha is ignored)
|
||||
FfxFloat32 FfxDofLoadFullDepth(FfxUInt32x2 coord); // returns full resolution depth
|
||||
void FfxDofStoreOutput(FfxUInt32x2 coord, FfxFloat32x4 color); // writes the final output
|
||||
|
||||
// Common helper functions
|
||||
FfxUInt32x2 FfxDofPxRadToTiles(FfxFloat32x2 rPx)
|
||||
{
|
||||
return FfxUInt32x2(ceil(rPx / (FFX_DOF_DEPTH_TILE_SIZE / 2))) + 1; // +1 to handle diagonals & bilinear
|
||||
}
|
||||
|
||||
FfxFloat32x2 FfxDofGetCoc2(FfxFloat32x2 depths)
|
||||
{
|
||||
return FfxFloat32x2(FfxDofGetCoc(depths.x), FfxDofGetCoc(depths.y));
|
||||
}
|
||||
#endif // #ifndef FFX_DOF_COMMON_H
|
||||
629
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/dof/ffx_dof_composite.h
vendored
Normal file
629
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/dof/ffx_dof_composite.h
vendored
Normal file
@@ -0,0 +1,629 @@
|
||||
// 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_core.h"
|
||||
#include "ffx_dof_common.h"
|
||||
|
||||
#if FFX_HALF
|
||||
FfxFloat16 FfxMed9(FfxFloat16 a, FfxFloat16 b, FfxFloat16 c,
|
||||
FfxFloat16 d, FfxFloat16 e, FfxFloat16 f,
|
||||
FfxFloat16 g, FfxFloat16 h, FfxFloat16 i)
|
||||
{
|
||||
// TODO (perf): compiler does not use med3 at all for these
|
||||
FfxFloat16 hi_lo = ffxMax3Half(ffxMin3Half(a, b, c), ffxMin3Half(d, e, f), ffxMin3Half(g, h, i));
|
||||
FfxFloat16 mi_mi = ffxMed3Half(ffxMed3Half(a, b, c), ffxMed3Half(d, e, f), ffxMed3Half(g, h, i));
|
||||
FfxFloat16 lo_hi = ffxMin3Half(ffxMax3Half(a, b, c), ffxMax3Half(d, e, f), ffxMax3Half(g, h, i));
|
||||
return ffxMed3Half(hi_lo, mi_mi, lo_hi);
|
||||
}
|
||||
#endif
|
||||
|
||||
FfxFloat32 FfxMed9(FfxFloat32 a, FfxFloat32 b, FfxFloat32 c,
|
||||
FfxFloat32 d, FfxFloat32 e, FfxFloat32 f,
|
||||
FfxFloat32 g, FfxFloat32 h, FfxFloat32 i)
|
||||
{
|
||||
// TODO (perf): compiler does not use med3 at all for these
|
||||
FfxFloat32 hi_lo = ffxMax3(ffxMin3(a, b, c), ffxMin3(d, e, f), ffxMin3(g, h, i));
|
||||
FfxFloat32 mi_mi = ffxMed3(ffxMed3(a, b, c), ffxMed3(d, e, f), ffxMed3(g, h, i));
|
||||
FfxFloat32 lo_hi = ffxMin3(ffxMax3(a, b, c), ffxMax3(d, e, f), ffxMax3(g, h, i));
|
||||
return ffxMed3(hi_lo, mi_mi, lo_hi);
|
||||
}
|
||||
|
||||
FfxFloat32 FfxCubicSpline(FfxFloat32 x)
|
||||
{
|
||||
// evaluate cubic spline -2x^3 + 3x^2
|
||||
return x * x * (3 - 2 * x);
|
||||
}
|
||||
|
||||
FFX_STATIC const FfxUInt32 FFX_DOF_COMBINE_TILE_SIZE = 8;
|
||||
FFX_STATIC const FfxUInt32 FFX_DOF_COMBINE_ROW_PITCH = FFX_DOF_COMBINE_TILE_SIZE + 3; // Add +2 for 3x3 filter margin, +1 on one side for bilinear filter.
|
||||
FFX_STATIC const FfxUInt32 FFX_DOF_COMBINE_AREA = FFX_DOF_COMBINE_ROW_PITCH * FFX_DOF_COMBINE_ROW_PITCH;
|
||||
|
||||
#if FFX_HALF
|
||||
FFX_GROUPSHARED FfxUInt32 FfxDofLDSLuma[FFX_DOF_COMBINE_AREA];
|
||||
FFX_GROUPSHARED FfxUInt32 FfxDofLDSNearRG[FFX_DOF_COMBINE_AREA];
|
||||
FFX_GROUPSHARED FfxUInt32 FfxDofLDSNearBA[FFX_DOF_COMBINE_AREA];
|
||||
FFX_GROUPSHARED FfxUInt32 FfxDofLDSFarRG[FFX_DOF_COMBINE_AREA];
|
||||
FFX_GROUPSHARED FfxUInt32 FfxDofLDSFarBA[FFX_DOF_COMBINE_AREA];
|
||||
|
||||
FFX_GROUPSHARED FfxUInt32 FfxDofLDSFullColorRG[18*18];
|
||||
FFX_GROUPSHARED FfxFloat16 FfxDofLDSFullColorB[18*18];
|
||||
#else // #if FFX_HALF
|
||||
FFX_GROUPSHARED FfxFloat32 FfxDofLDSNearLuma[FFX_DOF_COMBINE_AREA];
|
||||
FFX_GROUPSHARED FfxFloat32 FfxDofLDSFarLuma[FFX_DOF_COMBINE_AREA];
|
||||
FFX_GROUPSHARED FfxFloat32 FfxDofLDSNearR[FFX_DOF_COMBINE_AREA];
|
||||
FFX_GROUPSHARED FfxFloat32 FfxDofLDSNearG[FFX_DOF_COMBINE_AREA];
|
||||
FFX_GROUPSHARED FfxFloat32 FfxDofLDSNearB[FFX_DOF_COMBINE_AREA];
|
||||
FFX_GROUPSHARED FfxFloat32 FfxDofLDSNearA[FFX_DOF_COMBINE_AREA];
|
||||
|
||||
FFX_GROUPSHARED FfxFloat32 FfxDofLDSFarR[FFX_DOF_COMBINE_AREA];
|
||||
FFX_GROUPSHARED FfxFloat32 FfxDofLDSFarG[FFX_DOF_COMBINE_AREA];
|
||||
FFX_GROUPSHARED FfxFloat32 FfxDofLDSFarB[FFX_DOF_COMBINE_AREA];
|
||||
FFX_GROUPSHARED FfxFloat32 FfxDofLDSFarA[FFX_DOF_COMBINE_AREA];
|
||||
|
||||
FFX_GROUPSHARED FfxFloat32 FfxDofLDSFullColorR[18*18];
|
||||
FFX_GROUPSHARED FfxFloat32 FfxDofLDSFullColorG[18*18];
|
||||
FFX_GROUPSHARED FfxFloat32 FfxDofLDSFullColorB[18*18];
|
||||
#endif // #if FFX_HALF #else
|
||||
|
||||
#if FFX_HALF
|
||||
FfxFloat16x4 FfxDofGetIntermediateNearColor(FfxUInt32 idx)
|
||||
{
|
||||
FfxFloat16x2 rg = FFX_UINT32_TO_FLOAT16X2(FfxDofLDSNearRG[idx]);
|
||||
FfxFloat16x2 ba = FFX_UINT32_TO_FLOAT16X2(FfxDofLDSNearBA[idx]);
|
||||
return FfxFloat16x4(rg, ba);
|
||||
}
|
||||
FfxFloat16x4 FfxDofGetIntermediateFarColor(FfxUInt32 idx)
|
||||
{
|
||||
FfxFloat16x2 rg = FFX_UINT32_TO_FLOAT16X2(FfxDofLDSFarRG[idx]);
|
||||
FfxFloat16x2 ba = FFX_UINT32_TO_FLOAT16X2(FfxDofLDSFarBA[idx]);
|
||||
return FfxFloat16x4(rg, ba);
|
||||
}
|
||||
FfxFloat16x3 FfxDofGetIntFullColor(FfxUInt32 idx)
|
||||
{
|
||||
FfxFloat16x2 rg = FFX_UINT32_TO_FLOAT16X2(FfxDofLDSFullColorRG[idx]);
|
||||
FfxFloat16 b = FfxDofLDSFullColorB[idx];
|
||||
return FfxFloat16x3(rg, b);
|
||||
}
|
||||
void FfxDofSetIntNearLuma(FfxUInt32 idx, FfxFloat16 luma)
|
||||
{
|
||||
FfxFloat16x2 unpacked = FFX_UINT32_TO_FLOAT16X2(FfxDofLDSLuma[idx]);
|
||||
unpacked.x = luma;
|
||||
FfxDofLDSLuma[idx] = FFX_FLOAT16X2_TO_UINT32(unpacked);
|
||||
}
|
||||
void FfxDofSetIntFarLuma(FfxUInt32 idx, FfxFloat16 luma)
|
||||
{
|
||||
FfxFloat16x2 unpacked = FFX_UINT32_TO_FLOAT16X2(FfxDofLDSLuma[idx]);
|
||||
unpacked.y = luma;
|
||||
FfxDofLDSLuma[idx] = FFX_FLOAT16X2_TO_UINT32(unpacked);
|
||||
}
|
||||
|
||||
void FfxDofSetIntermediateNearColor(FfxUInt32 idx, FfxFloat16x4 col)
|
||||
{
|
||||
FfxDofLDSNearRG[idx] = FFX_FLOAT16X2_TO_UINT32(col.rg);
|
||||
FfxDofLDSNearBA[idx] = FFX_FLOAT16X2_TO_UINT32(col.ba);
|
||||
}
|
||||
void FfxDofSetIntermediateFarColor(FfxUInt32 idx, FfxFloat16x4 col)
|
||||
{
|
||||
FfxDofLDSFarRG[idx] = FFX_FLOAT16X2_TO_UINT32(col.rg);
|
||||
FfxDofLDSFarBA[idx] = FFX_FLOAT16X2_TO_UINT32(col.ba);
|
||||
}
|
||||
void FfxDofSetIntFullColor(FfxUInt32 idx, FfxFloat16x3 col)
|
||||
{
|
||||
FfxDofLDSFullColorRG[idx] = FFX_FLOAT16X2_TO_UINT32(col.rg);
|
||||
FfxDofLDSFullColorB[idx] = col.b;
|
||||
}
|
||||
FfxFloat16 FfxDofGetIntermediateNearAlpha(FfxUInt32 idx, FfxUInt32 offX, FfxUInt32 offY)
|
||||
{
|
||||
return FfxDofGetIntermediateNearColor(idx + offX + FFX_DOF_COMBINE_ROW_PITCH * offY).a;
|
||||
}
|
||||
FfxFloat16 FfxDofGetIntermediateFarAlpha(FfxUInt32 idx)
|
||||
{
|
||||
return FfxDofGetIntermediateFarColor(idx).a;
|
||||
}
|
||||
#else // #if FFX_HALF
|
||||
FfxFloat32x4 FfxDofGetIntermediateNearColor(FfxUInt32 idx)
|
||||
{
|
||||
return FfxFloat32x4(FfxDofLDSNearR[idx], FfxDofLDSNearG[idx], FfxDofLDSNearB[idx], FfxDofLDSNearA[idx]);
|
||||
}
|
||||
FfxFloat32x4 FfxDofGetIntermediateFarColor(FfxUInt32 idx)
|
||||
{
|
||||
return FfxFloat32x4(FfxDofLDSFarR[idx], FfxDofLDSFarG[idx], FfxDofLDSFarB[idx], FfxDofLDSFarA[idx]);
|
||||
}
|
||||
FfxFloat32x3 FfxDofGetIntFullColor(FfxUInt32 idx)
|
||||
{
|
||||
return FfxFloat32x3(FfxDofLDSFullColorR[idx], FfxDofLDSFullColorG[idx], FfxDofLDSFullColorB[idx]);
|
||||
}
|
||||
void FfxDofSetIntNearLuma(FfxUInt32 idx, FfxFloat32 luma)
|
||||
{
|
||||
FfxDofLDSNearLuma[idx] = luma;
|
||||
}
|
||||
void FfxDofSetIntFarLuma(FfxUInt32 idx, FfxFloat32 luma)
|
||||
{
|
||||
FfxDofLDSFarLuma[idx] = luma;
|
||||
}
|
||||
|
||||
void FfxDofSetIntermediateNearColor(FfxUInt32 idx, FfxFloat32x4 col)
|
||||
{
|
||||
FfxDofLDSNearR[idx] = col.r;
|
||||
FfxDofLDSNearG[idx] = col.g;
|
||||
FfxDofLDSNearB[idx] = col.b;
|
||||
FfxDofLDSNearA[idx] = col.a;
|
||||
}
|
||||
void FfxDofSetIntermediateFarColor(FfxUInt32 idx, FfxFloat32x4 col)
|
||||
{
|
||||
FfxDofLDSFarR[idx] = col.r;
|
||||
FfxDofLDSFarG[idx] = col.g;
|
||||
FfxDofLDSFarB[idx] = col.b;
|
||||
FfxDofLDSFarA[idx] = col.a;
|
||||
}
|
||||
void FfxDofSetIntFullColor(FfxUInt32 idx, FfxFloat32x3 col)
|
||||
{
|
||||
FfxDofLDSFullColorR[idx] = col.r;
|
||||
FfxDofLDSFullColorG[idx] = col.g;
|
||||
FfxDofLDSFullColorB[idx] = col.b;
|
||||
}
|
||||
FfxFloat32 FfxDofGetIntermediateNearAlpha(FfxUInt32 idx, FfxUInt32 offX, FfxUInt32 offY)
|
||||
{
|
||||
return FfxDofGetIntermediateNearColor(idx + offX + FFX_DOF_COMBINE_ROW_PITCH * offY).a;
|
||||
}
|
||||
FfxFloat32 FfxDofGetIntermediateFarAlpha(FfxUInt32 idx)
|
||||
{
|
||||
return FfxDofGetIntermediateFarColor(idx).a;
|
||||
}
|
||||
#endif // #if FFX_HALF #else
|
||||
|
||||
FfxHalfOpt3 FfxDofBlur3x3(FfxUInt32 baseIdx)
|
||||
{
|
||||
// kernel coefficients based on coverage of a circle in a 3x3 grid
|
||||
const FfxHalfOpt CORNER = FfxHalfOpt(0.5453);
|
||||
const FfxHalfOpt SIDE = FfxHalfOpt(0.9717);
|
||||
|
||||
// accumulate convolution
|
||||
const FfxHalfOpt weights_sum = FfxHalfOpt(1) + FfxHalfOpt(4) * CORNER + FfxHalfOpt(4) * SIDE;
|
||||
FfxHalfOpt3 sum = FfxDofGetIntFullColor(baseIdx + 19)
|
||||
+ CORNER * (FfxDofGetIntFullColor(baseIdx) + FfxDofGetIntFullColor(baseIdx + 2) + FfxDofGetIntFullColor(baseIdx + 36) + FfxDofGetIntFullColor(baseIdx + 38))
|
||||
+ SIDE * (FfxDofGetIntFullColor(baseIdx + 1) + FfxDofGetIntFullColor(baseIdx + 18) + FfxDofGetIntFullColor(baseIdx + 20) + FfxDofGetIntFullColor(baseIdx + 37));
|
||||
|
||||
return sum / weights_sum;
|
||||
}
|
||||
|
||||
FfxHalfOpt4 FfxDofFinalCombineColors(FfxUInt32x2 coord, FfxUInt32x2 relCoord, FfxHalfOpt4 bg, FfxHalfOpt4 fg, FfxHalfOpt minFgW)
|
||||
{
|
||||
FfxFloat32 d = FfxDofLoadFullDepth(coord);
|
||||
FfxUInt32 baseIdx = relCoord.x + 18 * relCoord.y;
|
||||
FfxHalfOpt3 full = FfxHalfOpt3(FfxDofGetIntFullColor(baseIdx + 19));
|
||||
FfxHalfOpt3 fixBlurred = FfxHalfOpt3(FfxDofBlur3x3(baseIdx));
|
||||
|
||||
// expand background around edges
|
||||
if (bg.a > FfxHalfOpt(0)) bg.rgb /= bg.a;
|
||||
// if any FG sample has zero weight, the interpolation is invalid.
|
||||
if (minFgW == FfxHalfOpt(0)) fg.a = FfxHalfOpt(0);
|
||||
FfxHalfOpt c = FfxHalfOpt(2) * FfxHalfOpt(abs(FfxDofGetCoc(d))); // double it for full-res pixels
|
||||
FfxHalfOpt c1 = ffxSaturate(c - FfxHalfOpt(0.5)); // lerp factor for full vs. fixed 1.5px blur
|
||||
FfxHalfOpt c2 = ffxSaturate(c - FfxHalfOpt(1.5)); // lerp factor for prev vs. quarter res
|
||||
if (bg.a == FfxHalfOpt(0)) c2 = FfxHalfOpt(0);
|
||||
FfxHalfOpt3 combinedColor = ffxLerp(full, fixBlurred, c1);
|
||||
combinedColor = ffxLerp(combinedColor, bg.rgb, c2);
|
||||
|
||||
combinedColor = ffxLerp(combinedColor, fg.rgb, FfxHalfOpt(FfxCubicSpline(fg.a)));
|
||||
return FfxHalfOpt4(combinedColor, 1);
|
||||
}
|
||||
|
||||
#if FFX_HALF
|
||||
FfxFloat16 FfxDofGetLDSNearLuma(FfxUInt32 idx, FfxUInt32 offX, FfxUInt32 offY)
|
||||
{
|
||||
return FFX_UINT32_TO_FLOAT16X2(FfxDofLDSLuma[idx + offX + FFX_DOF_COMBINE_ROW_PITCH * offY]).x;
|
||||
}
|
||||
FfxFloat16 FfxDofGetLDSFarLuma(FfxUInt32 idx, FfxUInt32 offX, FfxUInt32 offY)
|
||||
{
|
||||
return FFX_UINT32_TO_FLOAT16X2(FfxDofLDSLuma[idx + offX + FFX_DOF_COMBINE_ROW_PITCH * offY]).y;
|
||||
}
|
||||
#else // #if FFX_HALF
|
||||
FfxFloat32 FfxDofGetLDSNearLuma(FfxUInt32 idx, FfxUInt32 offX, FfxUInt32 offY)
|
||||
{
|
||||
return FfxDofLDSNearLuma[idx + offX + FFX_DOF_COMBINE_ROW_PITCH * offY];
|
||||
}
|
||||
FfxFloat32 FfxDofGetLDSFarLuma(FfxUInt32 idx, FfxUInt32 offX, FfxUInt32 offY)
|
||||
{
|
||||
return FfxDofLDSFarLuma[idx + offX + FFX_DOF_COMBINE_ROW_PITCH * offY];
|
||||
}
|
||||
#endif // #if FFX_HALF #else
|
||||
|
||||
FfxHalfOpt4 FfxDofFilterFF(FfxUInt32 baseIdx)
|
||||
{
|
||||
// get the median of the surrounding 3x3 area of luma values
|
||||
FfxHalfOpt med_luma = FfxMed9(
|
||||
FfxDofGetLDSFarLuma(baseIdx, 0, 0), FfxDofGetLDSFarLuma(baseIdx, 1, 0), FfxDofGetLDSFarLuma(baseIdx, 2, 0),
|
||||
FfxDofGetLDSFarLuma(baseIdx, 0, 1), FfxDofGetLDSFarLuma(baseIdx, 1, 1), FfxDofGetLDSFarLuma(baseIdx, 2, 1),
|
||||
FfxDofGetLDSFarLuma(baseIdx, 0, 2), FfxDofGetLDSFarLuma(baseIdx, 1, 2), FfxDofGetLDSFarLuma(baseIdx, 2, 2));
|
||||
|
||||
FfxUInt32 idx = baseIdx + FFX_DOF_COMBINE_ROW_PITCH + 1;
|
||||
FfxHalfOpt3 col = FfxDofGetIntermediateFarColor(idx).rgb;
|
||||
FfxHalfOpt lumaFactor = clamp(med_luma / FfxDofGetLDSFarLuma(idx, 0, 0), FfxHalfOpt(0), FfxHalfOpt(2));
|
||||
// corner fix: if color pixel is on a corner (has 5 black pixels as neighbor), don't reduce color.
|
||||
if (med_luma == FfxHalfOpt(0)) lumaFactor = FfxHalfOpt(1);
|
||||
return FfxHalfOpt4(col * lumaFactor, FfxDofGetIntermediateFarAlpha(idx));
|
||||
}
|
||||
|
||||
FfxHalfOpt4 FfxDofFilterNF(FfxUInt32 baseIdx)
|
||||
{
|
||||
// Get 3x3 median luma
|
||||
FfxHalfOpt med_luma = FfxMed9(
|
||||
FfxDofGetLDSNearLuma(baseIdx, 0, 0), FfxDofGetLDSNearLuma(baseIdx, 1, 0), FfxDofGetLDSNearLuma(baseIdx, 2, 0),
|
||||
FfxDofGetLDSNearLuma(baseIdx, 0, 1), FfxDofGetLDSNearLuma(baseIdx, 1, 1), FfxDofGetLDSNearLuma(baseIdx, 2, 1),
|
||||
FfxDofGetLDSNearLuma(baseIdx, 0, 2), FfxDofGetLDSNearLuma(baseIdx, 1, 2), FfxDofGetLDSNearLuma(baseIdx, 2, 2));
|
||||
FfxHalfOpt avg_alpha = FfxHalfOpt(ffxReciprocal(9.0)) * (
|
||||
FfxDofGetIntermediateNearAlpha(baseIdx, 0, 0) + FfxDofGetIntermediateNearAlpha(baseIdx, 1, 0) + FfxDofGetIntermediateNearAlpha(baseIdx, 2, 0) +
|
||||
FfxDofGetIntermediateNearAlpha(baseIdx, 0, 1) + FfxDofGetIntermediateNearAlpha(baseIdx, 1, 1) + FfxDofGetIntermediateNearAlpha(baseIdx, 2, 1) +
|
||||
FfxDofGetIntermediateNearAlpha(baseIdx, 0, 2) + FfxDofGetIntermediateNearAlpha(baseIdx, 1, 2) + FfxDofGetIntermediateNearAlpha(baseIdx, 2, 2));
|
||||
|
||||
FfxUInt32 idx = baseIdx + FFX_DOF_COMBINE_ROW_PITCH + 1;
|
||||
if (FfxDofGetIntermediateNearAlpha(idx, 0, 0) < 0.01)
|
||||
{
|
||||
// center has zero weight, grab one of the corner colors
|
||||
FfxUInt32 maxIdx = baseIdx;
|
||||
if (FfxDofGetLDSNearLuma(baseIdx, 2, 0) > FfxDofGetLDSNearLuma(maxIdx, 0, 0)) maxIdx = baseIdx + 2;
|
||||
if (FfxDofGetLDSNearLuma(baseIdx, 0, 2) > FfxDofGetLDSNearLuma(maxIdx, 0, 0)) maxIdx = baseIdx + 2 * FFX_DOF_COMBINE_ROW_PITCH;
|
||||
if (FfxDofGetLDSNearLuma(baseIdx, 2, 2) > FfxDofGetLDSNearLuma(maxIdx, 0, 0)) maxIdx = baseIdx + 2 * FFX_DOF_COMBINE_ROW_PITCH + 2;
|
||||
idx = maxIdx;
|
||||
}
|
||||
FfxHalfOpt3 col = FfxDofGetIntermediateNearColor(idx).rgb;
|
||||
FfxHalfOpt lumaFactor = med_luma > FfxHalfOpt(0) ? clamp(med_luma / FfxDofGetLDSNearLuma(idx, 0, 0), FfxHalfOpt(0), FfxHalfOpt(2)) : FfxHalfOpt(1.0);
|
||||
return FfxHalfOpt4(col.rgb * lumaFactor, avg_alpha);
|
||||
}
|
||||
|
||||
FfxFloat32x2 FfxDofGetTileRadius(FfxUInt32x2 group)
|
||||
{
|
||||
// need to read 4 values
|
||||
FfxUInt32x2 tile = group * 2;
|
||||
FfxFloat32x2 a = FfxDofLoadDilatedRadius(tile);
|
||||
FfxFloat32x2 b = FfxDofLoadDilatedRadius(tile + FfxUInt32x2(0, 1));
|
||||
FfxFloat32x2 c = FfxDofLoadDilatedRadius(tile + FfxUInt32x2(1, 0));
|
||||
FfxFloat32x2 d = FfxDofLoadDilatedRadius(tile + FfxUInt32x2(1, 1));
|
||||
FfxFloat32 near = max(a.x, ffxMax3(b.x, c.x, d.x));
|
||||
FfxFloat32 far = min(a.y, ffxMin3(b.y, c.y, d.y));
|
||||
return FfxFloat32x2(near, far);
|
||||
}
|
||||
|
||||
void FfxDofCombineSharpOnly(FfxUInt32x2 group, FfxUInt32x2 thread)
|
||||
{
|
||||
#if !defined(FFX_DOF_OPTION_COMBINE_IN_PLACE) || !FFX_DOF_OPTION_COMBINE_IN_PLACE
|
||||
FfxUInt32x2 base = 16 * group;
|
||||
FfxDofStoreOutput(base + thread + FfxUInt32x2(0, 0), FfxDofLoadFullInput(base + thread + FfxUInt32x2(0, 0)));
|
||||
FfxDofStoreOutput(base + thread + FfxUInt32x2(8, 0), FfxDofLoadFullInput(base + thread + FfxUInt32x2(8, 0)));
|
||||
FfxDofStoreOutput(base + thread + FfxUInt32x2(0, 8), FfxDofLoadFullInput(base + thread + FfxUInt32x2(0, 8)));
|
||||
FfxDofStoreOutput(base + thread + FfxUInt32x2(8, 8), FfxDofLoadFullInput(base + thread + FfxUInt32x2(8, 8)));
|
||||
#endif
|
||||
}
|
||||
|
||||
void FfxDofFetchFullColor(FfxUInt32x2 gid, FfxUInt32 gix, FfxUInt32x2 imageSize)
|
||||
{
|
||||
FFX_DOF_UNROLL
|
||||
for (FfxUInt32 iter = 0; iter < 6; iter++)
|
||||
{
|
||||
FfxUInt32 iFetch = (gix + iter * 64) % (18 * 18);
|
||||
FfxInt32x2 coord = FfxInt32x2(gid * 16) + FfxInt32x2(iFetch % 18 - 1, iFetch / 18 - 1);
|
||||
coord = clamp(coord, FfxInt32x2(0, 0), FfxInt32x2(imageSize) - FfxInt32x2(1, 1));
|
||||
FfxHalfOpt3 color = FfxHalfOpt3(FfxDofLoadFullInput(coord).rgb);
|
||||
FfxDofSetIntFullColor(iFetch, color);
|
||||
}
|
||||
}
|
||||
|
||||
void FfxDofSwizQuad(inout FfxUInt32x2 a, inout FfxUInt32x2 b, inout FfxUInt32x2 c, inout FfxUInt32x2 d)
|
||||
{
|
||||
// Input: four color values in a quad.
|
||||
// Re-orders the output to a swizzled format for better store throughput.
|
||||
// This maps from one quad per lane, stored in four separate registers to
|
||||
// four 16x2 regions (one per register).
|
||||
// This is done in two steps. First, permute the values among the lanes
|
||||
// using WaveReadLaneAt. Second, swap values between registers.
|
||||
|
||||
// This only works for lane counts >= 32, do nothing otherwise for compatibility
|
||||
#if FFX_HLSL
|
||||
if (WaveGetLaneCount() < 32) return;
|
||||
|
||||
FfxUInt32 lane = WaveGetLaneIndex();
|
||||
// index for A, switch bits around 43210 -> 10432.
|
||||
FfxUInt32 idxA = ((lane & 3) << 3) + (lane >> 2);
|
||||
// Adding 8/16/24 for B/C/D makes each variable offset from the previous by one slot.
|
||||
a = WaveReadLaneAt(a, (lane & ~31) + (idxA + 0) % 32);
|
||||
b = WaveReadLaneAt(b, (lane & ~31) + (idxA + 8) % 32);
|
||||
c = WaveReadLaneAt(c, (lane & ~31) + (idxA + 16) % 32);
|
||||
d = WaveReadLaneAt(d, (lane & ~31) + (idxA + 24) % 32);
|
||||
#elif FFX_GLSL
|
||||
if (gl_SubgroupSize < 32) return;
|
||||
|
||||
FfxUInt32 lane = gl_SubgroupInvocationID;
|
||||
FfxUInt32 idxA = ((lane & 3) << 3) + (lane >> 2);
|
||||
a = subgroupShuffle(a, (lane & ~31) + (idxA + 0) % 32);
|
||||
b = subgroupShuffle(b, (lane & ~31) + (idxA + 8) % 32);
|
||||
c = subgroupShuffle(c, (lane & ~31) + (idxA + 16) % 32);
|
||||
d = subgroupShuffle(d, (lane & ~31) + (idxA + 24) % 32);
|
||||
#endif
|
||||
|
||||
// Now, for each lane, a/b/c/d contain one value from each of the four 16x2 lines.
|
||||
// And each group of 4 lanes have values from the same quads.
|
||||
// We just need to shuffle between abcd, so that each set of 4 lanes contains one quad per variable.
|
||||
// General idea: rotate by (lane % 4) variables.
|
||||
if ((lane & 1) != 0)
|
||||
{
|
||||
// rotate A->B->C->D->A
|
||||
FfxUInt32x2 tmp = d;
|
||||
d = c;
|
||||
c = b;
|
||||
b = a;
|
||||
a = tmp;
|
||||
}
|
||||
if ((lane & 2) != 0)
|
||||
{
|
||||
// swap A<->C and B<->D
|
||||
FfxUInt32x2 tmp = a;
|
||||
a = c;
|
||||
c = tmp;
|
||||
tmp = b;
|
||||
b = d;
|
||||
d = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
#if FFX_HALF
|
||||
void FfxDofSwizQuad(inout FfxFloat16x4 a, inout FfxFloat16x4 b, inout FfxFloat16x4 c, inout FfxFloat16x4 d)
|
||||
{
|
||||
// Same as above.
|
||||
FfxUInt32x2 packed_a = FFX_FLOAT16X4_TO_UINT32X2(a);
|
||||
FfxUInt32x2 packed_b = FFX_FLOAT16X4_TO_UINT32X2(b);
|
||||
FfxUInt32x2 packed_c = FFX_FLOAT16X4_TO_UINT32X2(c);
|
||||
FfxUInt32x2 packed_d = FFX_FLOAT16X4_TO_UINT32X2(d);
|
||||
FfxDofSwizQuad(packed_a, packed_b, packed_c, packed_d);
|
||||
a = FFX_UINT32X2_TO_FLOAT16X4(packed_a);
|
||||
b = FFX_UINT32X2_TO_FLOAT16X4(packed_b);
|
||||
c = FFX_UINT32X2_TO_FLOAT16X4(packed_c);
|
||||
d = FFX_UINT32X2_TO_FLOAT16X4(packed_d);
|
||||
}
|
||||
#else // #if FFX_HALF
|
||||
void FfxDofSwizQuad(inout FfxFloat32x4 a, inout FfxFloat32x4 b, inout FfxFloat32x4 c, inout FfxFloat32x4 d)
|
||||
{
|
||||
// Same as above.
|
||||
FfxUInt32x2 a0 = ffxAsUInt32(a.xy);
|
||||
FfxUInt32x2 a1 = ffxAsUInt32(a.zw);
|
||||
FfxUInt32x2 b0 = ffxAsUInt32(b.xy);
|
||||
FfxUInt32x2 b1 = ffxAsUInt32(b.zw);
|
||||
FfxUInt32x2 c0 = ffxAsUInt32(c.xy);
|
||||
FfxUInt32x2 c1 = ffxAsUInt32(c.zw);
|
||||
FfxUInt32x2 d0 = ffxAsUInt32(d.xy);
|
||||
FfxUInt32x2 d1 = ffxAsUInt32(d.zw);
|
||||
FfxDofSwizQuad(a0, b0, c0, d0);
|
||||
FfxDofSwizQuad(a1, b1, c1, d1);
|
||||
a = FfxFloat32x4(ffxAsFloat(a0), ffxAsFloat(a1));
|
||||
b = FfxFloat32x4(ffxAsFloat(b0), ffxAsFloat(b1));
|
||||
c = FfxFloat32x4(ffxAsFloat(c0), ffxAsFloat(c1));
|
||||
d = FfxFloat32x4(ffxAsFloat(d0), ffxAsFloat(d1));
|
||||
}
|
||||
#endif // #if FFX_HALF #else
|
||||
|
||||
void FfxDofCombineFarOnly(FfxUInt32x2 id, FfxUInt32x2 gtID, FfxUInt32x2 gid, FfxUInt32 gix, FfxUInt32x2 imageSize)
|
||||
{
|
||||
// TODO: Is this the best configuration for fetching?
|
||||
FFX_DOF_UNROLL_N(2)
|
||||
for (FfxUInt32 iter = 0; iter < 2; iter++)
|
||||
{
|
||||
// HACK: with the modulo, we will re-fetch some pixels, but might be better than waiting twice (latency-wise)
|
||||
// which is what the compiler would do if it had to possibly branch
|
||||
FfxUInt32 iFetch = (gix + iter * 64) % FFX_DOF_COMBINE_AREA;
|
||||
FfxInt32x2 coord = FfxInt32x2(gid * FFX_DOF_COMBINE_TILE_SIZE) + FfxInt32x2(iFetch % FFX_DOF_COMBINE_ROW_PITCH - 1, iFetch / FFX_DOF_COMBINE_ROW_PITCH - 1);
|
||||
coord = clamp(coord, FfxInt32x2(0, 0), FfxInt32x2(imageSize - 1));
|
||||
FfxHalfOpt4 ffColor = FfxHalfOpt4(FfxDofLoadFar(coord));
|
||||
|
||||
// calculate and store luma for later median calculation
|
||||
FfxHalfOpt ffLuma = FfxHalfOpt(0.2126) * ffColor.r + FfxHalfOpt(0.7152) * ffColor.g + FfxHalfOpt(0.0722) * ffColor.b;
|
||||
FfxDofSetIntFarLuma(iFetch, ffLuma);
|
||||
FfxDofSetIntermediateFarColor(iFetch, ffColor);
|
||||
}
|
||||
|
||||
FFX_GROUP_MEMORY_BARRIER;
|
||||
|
||||
const FfxUInt32 baseIdx = gtID.x + gtID.y * FFX_DOF_COMBINE_ROW_PITCH;
|
||||
// one extra round of filtering needs to be done around the edge, this index maps to that.
|
||||
// TODO: This is ugly and possibly slow
|
||||
const FfxUInt32 baseIdx2 = (FFX_DOF_COMBINE_TILE_SIZE + FFX_DOF_COMBINE_ROW_PITCH * gix + (gix / (FFX_DOF_COMBINE_TILE_SIZE + 1)) * ((gix - FFX_DOF_COMBINE_TILE_SIZE) * (-FFX_DOF_COMBINE_ROW_PITCH + 1) - (FFX_DOF_COMBINE_TILE_SIZE + 1))) % FFX_DOF_COMBINE_AREA;
|
||||
|
||||
FfxHalfOpt4 ffColor = FfxHalfOpt4(0, 0, 0, 0), ffColor2 = FfxHalfOpt4(0, 0, 0, 0);
|
||||
// far-field post-filter
|
||||
ffColor = FfxDofFilterFF(baseIdx);
|
||||
ffColor2 = gix < (2 * FFX_DOF_COMBINE_TILE_SIZE + 1) ? FfxDofFilterFF(baseIdx2) : FfxHalfOpt4(0, 0, 0, 0);
|
||||
|
||||
FFX_GROUP_MEMORY_BARRIER;
|
||||
|
||||
// write out colors for interpolation
|
||||
FfxDofSetIntermediateFarColor(baseIdx, ffColor);
|
||||
if (gix < (2 * FFX_DOF_COMBINE_TILE_SIZE + 1))
|
||||
{
|
||||
FfxDofSetIntermediateFarColor(baseIdx2, ffColor2);
|
||||
}
|
||||
|
||||
FFX_GROUP_MEMORY_BARRIER;
|
||||
|
||||
// upscaling
|
||||
FfxHalfOpt4 ffTR = FfxHalfOpt4(0, 0, 0, 0), ffBL = FfxHalfOpt4(0, 0, 0, 0), ffBR = FfxHalfOpt4(0, 0, 0, 0);
|
||||
ffTR = FfxHalfOpt(0.5) * ffColor + FfxHalfOpt(0.5) * FfxDofGetIntermediateFarColor(baseIdx + 1);
|
||||
ffBL = FfxHalfOpt(0.5) * ffColor + FfxHalfOpt(0.5) * FfxDofGetIntermediateFarColor(baseIdx + FFX_DOF_COMBINE_ROW_PITCH);
|
||||
ffBR = FfxHalfOpt(0.5) * ffTR + FfxHalfOpt(0.25) * FfxDofGetIntermediateFarColor(baseIdx + FFX_DOF_COMBINE_ROW_PITCH) + FfxHalfOpt(0.25) * FfxDofGetIntermediateFarColor(baseIdx + FFX_DOF_COMBINE_ROW_PITCH + 1);
|
||||
|
||||
// top-left pixel
|
||||
FfxUInt32x2 coord = 2 * id;
|
||||
FfxUInt32x2 relCoord = 2 * gtID;
|
||||
FfxUInt32x2 coordA = coord;
|
||||
FfxHalfOpt4 colA = FfxDofFinalCombineColors(coord, relCoord, ffColor, FfxHalfOpt4(0, 0, 0, 0), FfxHalfOpt(0));
|
||||
// top-right
|
||||
coord.x++;
|
||||
relCoord.x++;
|
||||
FfxUInt32x2 coordB = coord;
|
||||
FfxHalfOpt4 colB = FfxDofFinalCombineColors(coord, relCoord, ffTR, FfxHalfOpt4(0, 0, 0, 0), FfxHalfOpt(0));
|
||||
// bottom-right
|
||||
coord.y++;
|
||||
relCoord.y++;
|
||||
FfxUInt32x2 coordC = coord;
|
||||
FfxHalfOpt4 colC = FfxDofFinalCombineColors(coord, relCoord, ffBR, FfxHalfOpt4(0, 0, 0, 0), FfxHalfOpt(0));
|
||||
// bottom-left
|
||||
coord.x--;
|
||||
relCoord.x--;
|
||||
FfxUInt32x2 coordD = coord;
|
||||
FfxHalfOpt4 colD = FfxDofFinalCombineColors(coord, relCoord, ffBL, FfxHalfOpt4(0, 0, 0, 0), FfxHalfOpt(0));
|
||||
|
||||
// TODO: Navi3 should make swizzling unnecessary because it supports write-combining clauses
|
||||
FfxDofSwizQuad(colA, colB, colC, colD);
|
||||
FfxDofSwizQuad(coordA, coordB, coordC, coordD);
|
||||
|
||||
FfxDofStoreOutput(coordA, colA);
|
||||
FfxDofStoreOutput(coordB, colB);
|
||||
FfxDofStoreOutput(coordC, colC);
|
||||
FfxDofStoreOutput(coordD, colD);
|
||||
}
|
||||
|
||||
void FfxDofCombineAll(FfxUInt32x2 id, FfxUInt32x2 gtID, FfxUInt32x2 gid, FfxUInt32 gix, FfxUInt32x2 imageSize)
|
||||
{
|
||||
// TODO: Is this the best configuration for fetching?
|
||||
FFX_DOF_UNROLL_N(2)
|
||||
for (FfxUInt32 iter = 0; iter < 2; iter++)
|
||||
{
|
||||
// HACK: with the modulo, we will re-fetch some pixels, but might be better than waiting twice (latency-wise)
|
||||
// which is what the compiler would do if it had to possibly branch
|
||||
FfxUInt32 iFetch = (gix + iter * 64) % FFX_DOF_COMBINE_AREA;
|
||||
FfxInt32x2 coord = FfxInt32x2(gid * FFX_DOF_COMBINE_TILE_SIZE) + FfxInt32x2(iFetch % FFX_DOF_COMBINE_ROW_PITCH - 1, iFetch / FFX_DOF_COMBINE_ROW_PITCH - 1);
|
||||
coord = clamp(coord, FfxInt32x2(0, 0), FfxInt32x2(imageSize - 1));
|
||||
FfxHalfOpt4 ffColor = FfxHalfOpt4(FfxDofLoadFar(coord));
|
||||
FfxHalfOpt4 nfColor = FfxHalfOpt4(FfxDofLoadNear(coord));
|
||||
|
||||
// calculate and store luma for later median calculation
|
||||
FfxHalfOpt ffLuma = FfxHalfOpt(0.2126) * ffColor.r + FfxHalfOpt(0.7152) * ffColor.g + FfxHalfOpt(0.0722) * ffColor.b;
|
||||
FfxHalfOpt nfLuma = FfxHalfOpt(0.2126) * nfColor.r + FfxHalfOpt(0.7152) * nfColor.g + FfxHalfOpt(0.0722) * nfColor.b;
|
||||
FfxDofSetIntFarLuma(iFetch, ffLuma);
|
||||
FfxDofSetIntNearLuma(iFetch, nfLuma);
|
||||
FfxDofSetIntermediateFarColor(iFetch, ffColor);
|
||||
FfxDofSetIntermediateNearColor(iFetch, nfColor);
|
||||
}
|
||||
|
||||
FFX_GROUP_MEMORY_BARRIER;
|
||||
|
||||
const FfxUInt32 baseIdx = gtID.x + gtID.y * FFX_DOF_COMBINE_ROW_PITCH;
|
||||
// one extra round of filtering needs to be done around the edge, this index maps to that.
|
||||
// TODO: same as above, ugly and slow.
|
||||
const FfxUInt32 baseIdx2 = (FFX_DOF_COMBINE_TILE_SIZE + FFX_DOF_COMBINE_ROW_PITCH * gix + (gix / (FFX_DOF_COMBINE_TILE_SIZE + 1)) * ((gix - FFX_DOF_COMBINE_TILE_SIZE) * (-FFX_DOF_COMBINE_ROW_PITCH + 1) - (FFX_DOF_COMBINE_TILE_SIZE + 1))) % FFX_DOF_COMBINE_AREA;
|
||||
|
||||
FfxHalfOpt4 ffColor = FfxHalfOpt4(0, 0, 0, 0), ffColor2 = FfxHalfOpt4(0, 0, 0, 0), nfColor = FfxHalfOpt4(0, 0, 0, 0), nfColor2 = FfxHalfOpt4(0, 0, 0, 0);
|
||||
// far-field post-filter
|
||||
ffColor = FfxDofFilterFF(baseIdx);
|
||||
ffColor2 = gix < (2 * FFX_DOF_COMBINE_TILE_SIZE + 1) ? FfxDofFilterFF(baseIdx2) : FfxHalfOpt4(0, 0, 0, 0);
|
||||
|
||||
// near-field post-filter
|
||||
nfColor = FfxDofFilterNF(baseIdx);
|
||||
nfColor2 = gix < (2 * FFX_DOF_COMBINE_TILE_SIZE + 1) ? FfxDofFilterNF(baseIdx2) : FfxHalfOpt4(0, 0, 0, 0);
|
||||
|
||||
FFX_GROUP_MEMORY_BARRIER;
|
||||
|
||||
// write out colors for interpolation
|
||||
FfxDofSetIntermediateNearColor(baseIdx, nfColor);
|
||||
FfxDofSetIntermediateFarColor(baseIdx, ffColor);
|
||||
if (gix < (2 * FFX_DOF_COMBINE_TILE_SIZE + 1))
|
||||
{
|
||||
FfxDofSetIntermediateNearColor(baseIdx2, nfColor2);
|
||||
FfxDofSetIntermediateFarColor(baseIdx2, ffColor2);
|
||||
}
|
||||
|
||||
FFX_GROUP_MEMORY_BARRIER;
|
||||
|
||||
// if any FG sample has zero weight, the interpolation is invalid.
|
||||
// take the min and invalidate if zero (see CombineColors)
|
||||
FfxHalfOpt fgMinW = min(nfColor.a, FfxHalfOpt(ffxMin3(FfxDofGetIntermediateNearAlpha(baseIdx, 1, 0), FfxDofGetIntermediateNearAlpha(baseIdx, 0, 1), FfxDofGetIntermediateNearAlpha(baseIdx, 1, 1))));
|
||||
|
||||
// upscaling
|
||||
FfxHalfOpt4 nfTR = FfxHalfOpt4(0, 0, 0, 0), nfBL = FfxHalfOpt4(0, 0, 0, 0), nfBR = FfxHalfOpt4(0, 0, 0, 0);
|
||||
nfTR = FfxHalfOpt(0.5) * nfColor + FfxHalfOpt(0.5) * FfxDofGetIntermediateNearColor(baseIdx + 1);
|
||||
nfBL = FfxHalfOpt(0.5) * nfColor + FfxHalfOpt(0.5) * FfxDofGetIntermediateNearColor(baseIdx + FFX_DOF_COMBINE_ROW_PITCH);
|
||||
nfBR = FfxHalfOpt(0.5) * nfTR + FfxHalfOpt(0.25) * FfxDofGetIntermediateNearColor(baseIdx + FFX_DOF_COMBINE_ROW_PITCH) + FfxHalfOpt(0.25) * FfxDofGetIntermediateNearColor(baseIdx + FFX_DOF_COMBINE_ROW_PITCH + 1);
|
||||
|
||||
FfxHalfOpt4 ffTR = FfxHalfOpt4(0, 0, 0, 0), ffBL = FfxHalfOpt4(0, 0, 0, 0), ffBR = FfxHalfOpt4(0, 0, 0, 0);
|
||||
ffTR = FfxHalfOpt(0.5) * ffColor + FfxHalfOpt(0.5) * FfxDofGetIntermediateFarColor(baseIdx + 1);
|
||||
ffBL = FfxHalfOpt(0.5) * ffColor + FfxHalfOpt(0.5) * FfxDofGetIntermediateFarColor(baseIdx + FFX_DOF_COMBINE_ROW_PITCH);
|
||||
ffBR = FfxHalfOpt(0.5) * ffTR + FfxHalfOpt(0.25) * FfxDofGetIntermediateFarColor(baseIdx + FFX_DOF_COMBINE_ROW_PITCH) + FfxHalfOpt(0.25) * FfxDofGetIntermediateFarColor(baseIdx + FFX_DOF_COMBINE_ROW_PITCH + 1);
|
||||
|
||||
// top-left pixel
|
||||
FfxUInt32x2 coord = 2 * id;
|
||||
FfxUInt32x2 relCoord = 2 * gtID;
|
||||
FfxUInt32x2 coordA = coord;
|
||||
FfxHalfOpt4 colA = FfxDofFinalCombineColors(coord, relCoord, ffColor, nfColor, fgMinW);
|
||||
// top-right
|
||||
coord.x += 1;
|
||||
relCoord.x += 1;
|
||||
FfxUInt32x2 coordB = coord;
|
||||
FfxHalfOpt4 colB = FfxDofFinalCombineColors(coord, relCoord, ffTR, nfTR, fgMinW);
|
||||
// bottom-right
|
||||
coord.y++;
|
||||
relCoord.y++;
|
||||
FfxUInt32x2 coordC = coord;
|
||||
FfxHalfOpt4 colC = FfxDofFinalCombineColors(coord, relCoord, ffBR, nfBR, fgMinW);
|
||||
// bottom-left
|
||||
coord.x--;
|
||||
relCoord.x--;
|
||||
FfxUInt32x2 coordD = coord;
|
||||
FfxHalfOpt4 colD = FfxDofFinalCombineColors(coord, relCoord, ffBL, nfBL, fgMinW);
|
||||
|
||||
FfxDofSwizQuad(colA, colB, colC, colD);
|
||||
FfxDofSwizQuad(coordA, coordB, coordC, coordD);
|
||||
|
||||
FfxDofStoreOutput(coordA, colA);
|
||||
FfxDofStoreOutput(coordB, colB);
|
||||
FfxDofStoreOutput(coordC, colC);
|
||||
FfxDofStoreOutput(coordD, colD);
|
||||
}
|
||||
|
||||
/// Entry point. Meant to run in 8x8 threads and writes 16x16 output pixels.
|
||||
///
|
||||
/// @param threadID SV_DispatchThreadID.xy
|
||||
/// @param groupThreadID SV_GroupThreadID.xy
|
||||
/// @param group SV_GroupID.xy
|
||||
/// @param index SV_GroupIndex
|
||||
/// @param halfImageSize Pixel size of the input (half resolution)
|
||||
/// @param fullImageSize Pixel size of the output (full resolution)
|
||||
/// @ingroup FfxGPUDof
|
||||
void FfxDofCombineHalfRes(FfxUInt32x2 threadID, FfxUInt32x2 groupThreadID, FfxUInt32x2 group, FfxUInt32 index, FfxUInt32x2 halfImageSize, FfxUInt32x2 fullImageSize)
|
||||
{
|
||||
// classify tile
|
||||
FfxFloat32x2 tileCoc = FfxDofGetTileRadius(group);
|
||||
FfxBoolean nearNeeded = tileCoc.x > -1.025; // halved due to resolution change, then: 2px = threshold in main pass + small inaccuracy bias
|
||||
FfxBoolean allSharp = max(abs(tileCoc.x), abs(tileCoc.y)) < 0.25;
|
||||
|
||||
if (allSharp)
|
||||
{
|
||||
FfxDofCombineSharpOnly(group, groupThreadID);
|
||||
}
|
||||
else if (!nearNeeded)
|
||||
{
|
||||
FfxDofFetchFullColor(group, index, fullImageSize);
|
||||
FfxDofCombineFarOnly(threadID, groupThreadID, group, index, halfImageSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
FfxDofFetchFullColor(group, index, fullImageSize);
|
||||
FfxDofCombineAll(threadID, groupThreadID, group, index, halfImageSize);
|
||||
}
|
||||
}
|
||||
101
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/dof/ffx_dof_dilate_depth.h
vendored
Normal file
101
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/dof/ffx_dof_dilate_depth.h
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
// 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_core.h"
|
||||
#include "ffx_dof_common.h"
|
||||
|
||||
// helper function for dilating depth values circularly
|
||||
void FfxDofDilateStep(inout FfxFloat32 cMin, inout FfxFloat32 cMax, FfxInt32 x, FfxInt32 y, FfxInt32 r, FfxUInt32x2 size, FfxUInt32x2 dtID)
|
||||
{
|
||||
if (x * x + y * y <= r * r)
|
||||
{
|
||||
// inside the circle
|
||||
FfxInt32x2 tileID = FfxInt32x2(dtID) + FfxInt32x2(x, y);
|
||||
if (tileID.x >= 0 && tileID.y >= 0 && tileID.x < size.x && tileID.y < size.y)
|
||||
{
|
||||
FfxFloat32x2 localCocRange = FfxDofLoadTileRadius(tileID);
|
||||
FfxUInt32x2 tileRad = FfxDofPxRadToTiles(abs(localCocRange));
|
||||
|
||||
// seperately for min/max: check radius in range to spread and update
|
||||
if (x * x + y * y < tileRad.x * tileRad.x)
|
||||
{
|
||||
// using max for cMin and min for cMax, since cMin actually refers to the CoC for the minimal view depth
|
||||
// NOT the minimum signed CoC value
|
||||
cMin = max(cMin, localCocRange.x);
|
||||
}
|
||||
if (x * x + y * y < tileRad.y * tileRad.y)
|
||||
{
|
||||
cMax = min(cMax, localCocRange.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Entry point for the dilate pass.
|
||||
///
|
||||
/// @param tile Coordinate of the tile to run on (SV_DispatchThreadID)
|
||||
/// @param imageSize Resolution of the depth image (full resolution)
|
||||
/// @ingroup FfxGPUDof
|
||||
void FfxDofDilate(FfxUInt32x2 tile, FfxUInt32x2 imageSize)
|
||||
{
|
||||
// dilate scatter-as-gather using global max radius
|
||||
|
||||
// reject out-of-bounds on border
|
||||
FfxUInt32x2 size = FfxUInt32x2(ceil(FfxFloat32x2(imageSize) / FfxFloat32(FFX_DOF_DEPTH_TILE_SIZE)));
|
||||
|
||||
// get CoC and depth
|
||||
FfxInt32 rMax = FfxInt32(FfxDofGetMaxTileRadius());
|
||||
FfxFloat32x2 cocMinMax = FfxDofLoadTileRadius(tile);
|
||||
FfxFloat32x2 absCocMinMax = abs(cocMinMax);
|
||||
|
||||
FfxFloat32 cMin = cocMinMax.x;
|
||||
FfxFloat32 cMax = cocMinMax.y;
|
||||
|
||||
// Very extremes of the kernel done explicity. Expanding the square (loop below) to this radius would
|
||||
// waste time with a lot of failed radius checks.
|
||||
if (rMax > 0)
|
||||
{
|
||||
FfxDofDilateStep(cMin, cMax, -rMax, 0, rMax, size, tile);
|
||||
FfxDofDilateStep(cMin, cMax, rMax, 0, rMax, size, tile);
|
||||
FfxDofDilateStep(cMin, cMax, 0, -rMax, rMax, size, tile);
|
||||
FfxDofDilateStep(cMin, cMax, 0, rMax, rMax, size, tile);
|
||||
}
|
||||
// Gather the rest as a square shape. Likely faster than trying to make a circle.
|
||||
for (FfxInt32 x = -rMax + 1; x < rMax; x++)
|
||||
{
|
||||
for (FfxInt32 y = -rMax + 1; y < rMax; y++)
|
||||
{
|
||||
// Zero offset is the starting point, don't need to handle again.
|
||||
if (x == 0 && y == 0) continue;
|
||||
FfxDofDilateStep(cMin, cMax, x, y, rMax, size, tile);
|
||||
}
|
||||
}
|
||||
|
||||
// If center tile is in-focus enough: ignore far-field dilation (it is occluded).
|
||||
if (absCocMinMax.x < 0.5 && absCocMinMax.y < 0.5)
|
||||
{
|
||||
cMax = cocMinMax.y;
|
||||
}
|
||||
|
||||
// store min and max
|
||||
FfxDofStoreDilatedRadius(tile, FfxFloat32x2(cMin, cMax));
|
||||
}
|
||||
176
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/dof/ffx_dof_downsample_color.h
vendored
Normal file
176
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/dof/ffx_dof_downsample_color.h
vendored
Normal file
@@ -0,0 +1,176 @@
|
||||
// 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_core.h"
|
||||
|
||||
#ifndef FFX_DOF_OPTION_MAX_MIP
|
||||
#define FFX_DOF_OPTION_MAX_MIP FFX_DOF_INTERNAL_BILAT_MIP_COUNT
|
||||
#endif
|
||||
|
||||
#if FFX_HALF
|
||||
#define FFX_SPD_PACKED_ONLY
|
||||
|
||||
FFX_GROUPSHARED FfxFloat16x2 spdIntermediateRG[16][16];
|
||||
FFX_GROUPSHARED FfxFloat16x2 spdIntermediateBA[16][16];
|
||||
|
||||
FfxFloat16x4 SpdLoadSourceImageH(FfxInt32x2 tex, FfxUInt32 slice)
|
||||
{
|
||||
FfxFloat16 d = FfxFloat16(FfxDofLoadFullDepth(tex));
|
||||
FfxFloat16 c = FfxFloat16(FfxDofGetCoc(d));
|
||||
return FfxFloat16x4(FfxDofLoadSource(tex).rgb, c);
|
||||
}
|
||||
|
||||
FfxFloat16x4 SpdLoadH(FfxInt32x2 tex, FfxUInt32 slice)
|
||||
{
|
||||
return FfxFloat16x4(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
void SpdStoreH(FfxInt32x2 pix, FfxFloat16x4 value, FfxUInt32 mip, FfxUInt32 slice)
|
||||
{
|
||||
FfxDofStoreBilatMip(mip, pix, value);
|
||||
}
|
||||
|
||||
FfxFloat16x4 SpdLoadIntermediateH(FfxUInt32 x, FfxUInt32 y)
|
||||
{
|
||||
return FfxFloat16x4(
|
||||
spdIntermediateRG[x][y].x,
|
||||
spdIntermediateRG[x][y].y,
|
||||
spdIntermediateBA[x][y].x,
|
||||
spdIntermediateBA[x][y].y);
|
||||
}
|
||||
void SpdStoreIntermediateH(FfxUInt32 x, FfxUInt32 y, FfxFloat16x4 value)
|
||||
{
|
||||
spdIntermediateRG[x][y] = value.xy;
|
||||
spdIntermediateBA[x][y] = value.zw;
|
||||
}
|
||||
|
||||
/// Bilateral downsampling function, half-precision version
|
||||
/// @ingroup FfxGPUDof
|
||||
FfxFloat16x4 FfxDofDownsampleQuadH(FfxFloat16x4 v0, FfxFloat16x4 v1, FfxFloat16x4 v2, FfxFloat16x4 v3)
|
||||
{
|
||||
FfxFloat16 c0 = v0.a;
|
||||
FfxFloat16 c1 = v1.a;
|
||||
FfxFloat16 c2 = v2.a;
|
||||
FfxFloat16 c3 = v3.a;
|
||||
FfxFloat16 w1 = ffxSaturate(FfxFloat16(1.0) - abs(c0 - c1));
|
||||
FfxFloat16 w2 = ffxSaturate(FfxFloat16(1.0) - abs(c0 - c2));
|
||||
FfxFloat16 w3 = ffxSaturate(FfxFloat16(1.0) - abs(c0 - c3));
|
||||
FfxFloat16x3 color = v0.rgb + w1 * v1.rgb + w2 * v2.rgb + w3 * v3.rgb;
|
||||
FfxFloat16 weights = FfxFloat16(1.0) + w1 + w2 + w3;
|
||||
return FfxFloat16x4(color / weights, c0);
|
||||
}
|
||||
|
||||
FfxFloat16x4 SpdReduce4H(FfxFloat16x4 v0, FfxFloat16x4 v1, FfxFloat16x4 v2, FfxFloat16x4 v3)
|
||||
{
|
||||
return FfxDofDownsampleQuadH(v0, v1, v2, v3);
|
||||
}
|
||||
#else // #if FFX_HALF
|
||||
#define FFX_SPD_NO_WAVE_OPERATIONS 1
|
||||
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)
|
||||
{
|
||||
FfxFloat32 d = FfxDofLoadFullDepth(tex);
|
||||
FfxFloat32 c = FfxDofGetCoc(d);
|
||||
return FfxFloat32x4(FfxDofLoadSource(tex).rgb, c);
|
||||
}
|
||||
|
||||
FfxFloat32x4 SpdLoad(FfxInt32x2 tex, FfxUInt32 slice)
|
||||
{
|
||||
return FfxFloat32x4(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
void SpdStore(FfxInt32x2 pix, FfxFloat32x4 value, FfxUInt32 mip, FfxUInt32 slice)
|
||||
{
|
||||
FfxDofStoreBilatMip(mip, pix, value);
|
||||
}
|
||||
|
||||
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.r;
|
||||
spdIntermediateG[x][y] = value.g;
|
||||
spdIntermediateB[x][y] = value.b;
|
||||
spdIntermediateA[x][y] = value.a;
|
||||
}
|
||||
|
||||
/// Bilateral downsampling function, full-precision version
|
||||
/// @ingroup FfxGPUDof
|
||||
FfxFloat32x4 FfxDofDownsampleQuad(FfxFloat32x4 v0, FfxFloat32x4 v1, FfxFloat32x4 v2, FfxFloat32x4 v3)
|
||||
{
|
||||
FfxFloat32 c0 = v0.a;
|
||||
FfxFloat32 c1 = v1.a;
|
||||
FfxFloat32 c2 = v2.a;
|
||||
FfxFloat32 c3 = v3.a;
|
||||
FfxFloat32 w1 = ffxSaturate(1.0 - abs(c0 - c1));
|
||||
FfxFloat32 w2 = ffxSaturate(1.0 - abs(c0 - c2));
|
||||
FfxFloat32 w3 = ffxSaturate(1.0 - abs(c0 - c3));
|
||||
FfxFloat32x3 color = v0.rgb + w1 * v1.rgb + w2 * v2.rgb + w3 * v3.rgb;
|
||||
FfxFloat32 weights = 1.0 + w1 + w2 + w3;
|
||||
return FfxFloat32x4(color / weights, c0);
|
||||
}
|
||||
|
||||
FfxFloat32x4 SpdReduce4(FfxFloat32x4 v0, FfxFloat32x4 v1, FfxFloat32x4 v2, FfxFloat32x4 v3)
|
||||
{
|
||||
return FfxDofDownsampleQuad(v0, v1, v2, v3);
|
||||
}
|
||||
#endif // #if FFX_HALF #else
|
||||
|
||||
// we only generate 4 mips, so these functions are not needed and never called.
|
||||
void SpdIncreaseAtomicCounter(FfxUInt32 slice)
|
||||
{
|
||||
/*nothing*/
|
||||
}
|
||||
FfxUInt32 SpdGetAtomicCounter()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
void SpdResetAtomicCounter(FfxUInt32 slice)
|
||||
{
|
||||
/*nothing*/
|
||||
}
|
||||
|
||||
#include "spd/ffx_spd.h"
|
||||
|
||||
/// Entry point for the downsample color pass. Uses SPD internally.
|
||||
///
|
||||
/// @param LocalThreadId Thread index in thread group (SV_GroupIndex)
|
||||
/// @param WorkGroupId Coordinate of the tile (SV_GroupID.xy)
|
||||
/// @ingroup FfxGPUDof
|
||||
void DownsampleColor(FfxUInt32 LocalThreadId, FfxUInt32x2 WorkGroupId)
|
||||
{
|
||||
#if FFX_HALF
|
||||
SpdDownsampleH(WorkGroupId, LocalThreadId, FfxUInt32(FFX_DOF_OPTION_MAX_MIP), FfxUInt32(0), FfxUInt32(0));
|
||||
#else
|
||||
SpdDownsample(WorkGroupId, LocalThreadId, FfxUInt32(FFX_DOF_OPTION_MAX_MIP), FfxUInt32(0), FfxUInt32(0));
|
||||
#endif
|
||||
}
|
||||
77
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/dof/ffx_dof_downsample_depth.h
vendored
Normal file
77
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/dof/ffx_dof_downsample_depth.h
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
// 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_core.h"
|
||||
#include "ffx_dof_common.h"
|
||||
|
||||
FfxUInt32x2 FfxDofCocRadInTiles(FfxFloat32x2 zMinMax)
|
||||
{
|
||||
FfxFloat32x2 rPx = abs(FfxDofGetCoc2(zMinMax));
|
||||
return FfxDofPxRadToTiles(rPx);
|
||||
}
|
||||
|
||||
FfxUInt32 FfxDofMaxCocInTiles(FfxFloat32x2 zMinMax)
|
||||
{
|
||||
FfxUInt32x2 rTiles = FfxDofCocRadInTiles(zMinMax);
|
||||
return max(rTiles.x, rTiles.y);
|
||||
}
|
||||
|
||||
/// Entry point for depth downsample function. SPD is not used for this,
|
||||
/// since we only need one specific downsampled resolution.
|
||||
///
|
||||
/// @param tile coordinate of the tile to run on (SV_DispatchThreadID)
|
||||
/// @param imageSize Size of the depth image (full resolution)
|
||||
/// @ingroup FfxGPUDof
|
||||
void DownsampleDepth(FfxUInt32x2 tile, FfxUInt32x2 imageSize)
|
||||
{
|
||||
FfxFloat32 minD = 1.0;
|
||||
FfxFloat32 maxD = 0.0;
|
||||
|
||||
const FfxUInt32x2 coordBase = tile * FFX_DOF_DEPTH_TILE_SIZE;
|
||||
const FfxFloat32x2 rcpImageSize = ffxReciprocal(FfxFloat32x2(imageSize));
|
||||
|
||||
for (FfxUInt32 yy = 0; yy < FFX_DOF_DEPTH_TILE_SIZE; yy += 2)
|
||||
{
|
||||
for (FfxUInt32 xx = 0; xx < FFX_DOF_DEPTH_TILE_SIZE; xx += 2)
|
||||
{
|
||||
FfxUInt32x2 coordInt = coordBase + FfxUInt32x2(xx, yy);
|
||||
FfxFloat32x2 coord = ffxSaturate(FfxFloat32x2(coordInt) * rcpImageSize);
|
||||
FfxFloat32x4 d = FfxDofGatherDepth(coord);
|
||||
|
||||
FfxFloat32 lo = min(min(min(d.x, d.y), d.z), d.w);
|
||||
FfxFloat32 hi = max(max(max(d.x, d.y), d.z), d.w);
|
||||
minD = min(minD, lo);
|
||||
maxD = max(maxD, hi);
|
||||
}
|
||||
}
|
||||
|
||||
#if FFX_DOF_OPTION_REVERSE_DEPTH
|
||||
// if Z-buffer is reversed, the nearest Z is the max.
|
||||
FfxFloat32x2 nearFarDepth = FfxFloat32x2(maxD, minD);
|
||||
#else
|
||||
FfxFloat32x2 nearFarDepth = FfxFloat32x2(minD, maxD);
|
||||
#endif
|
||||
FfxFloat32x2 coc = FfxDofGetCoc2(nearFarDepth);
|
||||
FfxUInt32 rTiles = FfxDofMaxCocInTiles(nearFarDepth);
|
||||
FfxDofAccumMaxTileRadius(rTiles);
|
||||
FfxDofStoreTileRadius(tile, coc);
|
||||
}
|
||||
50
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/dof/ffx_dof_resources.h
vendored
Normal file
50
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/dof/ffx_dof_resources.h
vendored
Normal 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_DOF_RESOURCES_H
|
||||
#define FFX_DOF_RESOURCES_H
|
||||
|
||||
#if defined(FFX_CPU) || defined(FFX_GPU)
|
||||
#define FFX_DOF_RESOURCE_IDENTIFIER_NULL 0
|
||||
#define FFX_DOF_RESOURCE_IDENTIFIER_INPUT_DEPTH 1
|
||||
#define FFX_DOF_RESOURCE_IDENTIFIER_INPUT_COLOR 2
|
||||
#define FFX_DOF_RESOURCE_IDENTIFIER_INTERNAL_BILAT_COLOR 3 // same as MIP0
|
||||
#define FFX_DOF_RESOURCE_IDENTIFIER_INTERNAL_BILAT_COLOR_MIP0 3
|
||||
#define FFX_DOF_RESOURCE_IDENTIFIER_INTERNAL_BILAT_COLOR_MIP1 4
|
||||
#define FFX_DOF_RESOURCE_IDENTIFIER_INTERNAL_BILAT_COLOR_MIP2 5
|
||||
#define FFX_DOF_RESOURCE_IDENTIFIER_INTERNAL_BILAT_COLOR_MIP3 6
|
||||
#define FFX_DOF_RESOURCE_IDENTIFIER_INTERNAL_RADIUS 7
|
||||
#define FFX_DOF_RESOURCE_IDENTIFIER_INTERNAL_DILATED_RADIUS 8
|
||||
#define FFX_DOF_RESOURCE_IDENTIFIER_INTERNAL_NEAR 9
|
||||
#define FFX_DOF_RESOURCE_IDENTIFIER_INTERNAL_FAR 10
|
||||
#define FFX_DOF_RESOURCE_IDENTIFIER_OUTPUT_COLOR 11
|
||||
#define FFX_DOF_RESOURCE_IDENTIFIER_INTERNAL_GLOBALS 12
|
||||
|
||||
#define FFX_DOF_RESOURCE_IDENTIFIER_COUNT 13
|
||||
|
||||
#define FFX_DOF_CONSTANTBUFFER_IDENTIFIER_DOF 0
|
||||
|
||||
#define FFX_DOF_INTERNAL_BILAT_MIP_COUNT 4
|
||||
|
||||
#endif // #if defined(FFX_CPU) || defined(FFX_GPU)
|
||||
|
||||
#endif //!defined( FFX_DOF_RESOURCES_H )
|
||||
Reference in New Issue
Block a user