mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-22 17:29:18 +02:00
Some renaming
This commit is contained in:
52
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/denoiser/CMakeCompileDenoiserShaders.txt
vendored
Normal file
52
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/denoiser/CMakeCompileDenoiserShaders.txt
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
# 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(DENOISER_BASE_ARGS
|
||||
-reflection -deps=gcc -DFFX_GPU=1)
|
||||
|
||||
set(DENOISER_PERMUTATION_ARGS
|
||||
-DFFX_DENOISER_OPTION_INVERTED_DEPTH={0,1})
|
||||
|
||||
set(DENOISER_INCLUDE_ARGS
|
||||
"${FFX_GPU_PATH}"
|
||||
"${FFX_GPU_PATH}/denoiser")
|
||||
|
||||
if (NOT DENOISER_SHADER_EXT)
|
||||
set(DENOISER_SHADER_EXT *)
|
||||
endif()
|
||||
|
||||
file(GLOB DENOISER_SHADERS
|
||||
"shaders/denoiser/ffx_denoiser_prepare_shadow_mask_pass.${DENOISER_SHADER_EXT}"
|
||||
"shaders/denoiser/ffx_denoiser_shadows_tile_classification_pass.${DENOISER_SHADER_EXT}"
|
||||
"shaders/denoiser/ffx_denoiser_filter_soft_shadows_0_pass.${DENOISER_SHADER_EXT}"
|
||||
"shaders/denoiser/ffx_denoiser_filter_soft_shadows_1_pass.${DENOISER_SHADER_EXT}"
|
||||
"shaders/denoiser/ffx_denoiser_filter_soft_shadows_2_pass.${DENOISER_SHADER_EXT}"
|
||||
"shaders/denoiser/ffx_denoiser_prefilter_reflections_pass.${DENOISER_SHADER_EXT}"
|
||||
"shaders/denoiser/ffx_denoiser_reproject_reflections_pass.${DENOISER_SHADER_EXT}"
|
||||
"shaders/denoiser/ffx_denoiser_resolve_temporal_reflections_pass.${DENOISER_SHADER_EXT}")
|
||||
|
||||
compile_shaders_with_depfile(
|
||||
"${FFX_SC_EXECUTABLE}"
|
||||
"${DENOISER_BASE_ARGS}" "${DENOISER_API_BASE_ARGS}" "${DENOISER_PERMUTATION_ARGS}" "${DENOISER_INCLUDE_ARGS}"
|
||||
"${DENOISER_SHADERS}" "${FFX_PASS_SHADER_OUTPUT_PATH}" DENOISER_PERMUTATION_OUTPUTS)
|
||||
|
||||
add_shader_output("${DENOISER_PERMUTATION_OUTPUTS}")
|
||||
@@ -0,0 +1,642 @@
|
||||
// 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_denoiser_resources.h"
|
||||
|
||||
#if defined(FFX_GPU)
|
||||
#include "ffx_core.h"
|
||||
|
||||
#ifndef FFX_PREFER_WAVE64
|
||||
#define FFX_PREFER_WAVE64
|
||||
#endif // #ifndef FFX_PREFER_WAVE64
|
||||
|
||||
#if defined(DENOISER_BIND_CB_DENOISER)
|
||||
layout (set = 0, binding = DENOISER_BIND_CB_DENOISER, std140) uniform cbDenoiserReflections_t
|
||||
{
|
||||
FfxFloat32Mat4 invProjection;
|
||||
FfxFloat32Mat4 invView;
|
||||
FfxFloat32Mat4 prevViewProjection;
|
||||
FfxUInt32x2 renderSize;
|
||||
FfxFloat32x2 inverseRenderSize;
|
||||
FfxFloat32x2 motionVectorScale;
|
||||
FfxFloat32 normalsUnpackMul;
|
||||
FfxFloat32 normalsUnpackAdd;
|
||||
FfxBoolean isRoughnessPerceptual;
|
||||
FfxFloat32 temporalStabilityFactor;
|
||||
FfxFloat32 roughnessThreshold;
|
||||
} cbDenoiserReflections;
|
||||
|
||||
FfxFloat32Mat4 InvProjection()
|
||||
{
|
||||
#if defined DENOISER_BIND_CB_DENOISER
|
||||
return cbDenoiserReflections.invProjection;
|
||||
#else
|
||||
return FfxFloat32Mat4(0.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
FfxFloat32Mat4 InvView()
|
||||
{
|
||||
#if defined DENOISER_BIND_CB_DENOISER
|
||||
return cbDenoiserReflections.invView;
|
||||
#else
|
||||
return FfxFloat32Mat4(0.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
FfxFloat32Mat4 PrevViewProjection()
|
||||
{
|
||||
#if defined DENOISER_BIND_CB_DENOISER
|
||||
return cbDenoiserReflections.prevViewProjection;
|
||||
#else
|
||||
return FfxFloat32Mat4(0.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
FfxUInt32x2 RenderSize()
|
||||
{
|
||||
#if defined DENOISER_BIND_CB_DENOISER
|
||||
return cbDenoiserReflections.renderSize;
|
||||
#else
|
||||
return FfxUInt32x2(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
FfxFloat32x2 InverseRenderSize()
|
||||
{
|
||||
#if defined DENOISER_BIND_CB_DENOISER
|
||||
return cbDenoiserReflections.inverseRenderSize;
|
||||
#else
|
||||
return FfxFloat32x2(0.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
FfxFloat32x2 MotionVectorScale()
|
||||
{
|
||||
#if defined DENOISER_BIND_CB_DENOISER
|
||||
return cbDenoiserReflections.motionVectorScale;
|
||||
#else
|
||||
return FfxFloat32x2(0.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
FfxFloat32 NormalsUnpackMul()
|
||||
{
|
||||
#if defined DENOISER_BIND_CB_DENOISER
|
||||
return cbDenoiserReflections.normalsUnpackMul;
|
||||
#else
|
||||
return 0.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
FfxFloat32 NormalsUnpackAdd()
|
||||
{
|
||||
#if defined DENOISER_BIND_CB_DENOISER
|
||||
return cbDenoiserReflections.normalsUnpackAdd;
|
||||
#else
|
||||
return 0.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
FfxBoolean IsRoughnessPerceptual()
|
||||
{
|
||||
#if defined DENOISER_BIND_CB_DENOISER
|
||||
return cbDenoiserReflections.isRoughnessPerceptual;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
FfxFloat32 TemporalStabilityFactor()
|
||||
{
|
||||
#if defined DENOISER_BIND_CB_DENOISER
|
||||
return cbDenoiserReflections.temporalStabilityFactor;
|
||||
#else
|
||||
return 0.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
FfxFloat32 RoughnessThreshold()
|
||||
{
|
||||
#if defined DENOISER_BIND_CB_DENOISER
|
||||
return cbDenoiserReflections.roughnessThreshold;
|
||||
#else
|
||||
return 0.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // #if defined(DENOISER_BIND_CB_DENOISER)
|
||||
|
||||
layout (set = 0, binding = 1000) uniform sampler s_LinearSampler;
|
||||
|
||||
#if defined DENOISER_BIND_SRV_INPUT_DEPTH_HIERARCHY
|
||||
layout (set = 0, binding = DENOISER_BIND_SRV_INPUT_DEPTH_HIERARCHY) uniform texture2D r_input_depth_hierarchy;
|
||||
#endif
|
||||
#if defined DENOISER_BIND_SRV_INPUT_MOTION_VECTORS
|
||||
layout (set = 0, binding = DENOISER_BIND_SRV_INPUT_MOTION_VECTORS) uniform texture2D r_input_motion_vectors;
|
||||
#endif
|
||||
#if defined DENOISER_BIND_SRV_INPUT_NORMAL
|
||||
layout (set = 0, binding = DENOISER_BIND_SRV_INPUT_NORMAL) uniform texture2D r_input_normal;
|
||||
#endif
|
||||
#if defined DENOISER_BIND_SRV_RADIANCE
|
||||
layout (set = 0, binding = DENOISER_BIND_SRV_RADIANCE) uniform texture2D r_radiance;
|
||||
#endif
|
||||
#if defined DENOISER_BIND_SRV_RADIANCE_HISTORY
|
||||
layout (set = 0, binding = DENOISER_BIND_SRV_RADIANCE_HISTORY) uniform texture2D r_radiance_history;
|
||||
#endif
|
||||
#if defined DENOISER_BIND_SRV_VARIANCE
|
||||
layout (set = 0, binding = DENOISER_BIND_SRV_VARIANCE) uniform texture2D r_variance;
|
||||
#endif
|
||||
#if defined DENOISER_BIND_SRV_SAMPLE_COUNT
|
||||
layout (set = 0, binding = DENOISER_BIND_SRV_SAMPLE_COUNT) uniform texture2D r_sample_count;
|
||||
#endif
|
||||
#if defined DENOISER_BIND_SRV_AVERAGE_RADIANCE
|
||||
layout (set = 0, binding = DENOISER_BIND_SRV_AVERAGE_RADIANCE) uniform texture2D r_average_radiance;
|
||||
#endif
|
||||
#if defined DENOISER_BIND_SRV_EXTRACTED_ROUGHNESS
|
||||
layout (set = 0, binding = DENOISER_BIND_SRV_EXTRACTED_ROUGHNESS) uniform texture2D r_extracted_roughness;
|
||||
#endif
|
||||
#if defined DENOISER_BIND_SRV_DEPTH_HISTORY
|
||||
layout (set = 0, binding = DENOISER_BIND_SRV_DEPTH_HISTORY) uniform texture2D r_depth_history;
|
||||
#endif
|
||||
#if defined DENOISER_BIND_SRV_NORMAL_HISTORY
|
||||
layout (set = 0, binding = DENOISER_BIND_SRV_NORMAL_HISTORY) uniform texture2D r_normal_history;
|
||||
#endif
|
||||
#if defined DENOISER_BIND_SRV_ROUGHNESS_HISTORY
|
||||
layout (set = 0, binding = DENOISER_BIND_SRV_ROUGHNESS_HISTORY) uniform texture2D r_roughness_history;
|
||||
#endif
|
||||
#if defined DENOISER_BIND_SRV_REPROJECTED_RADIANCE
|
||||
layout (set = 0, binding = DENOISER_BIND_SRV_REPROJECTED_RADIANCE) uniform texture2D r_reprojected_radiance;
|
||||
#endif
|
||||
|
||||
// UAVs
|
||||
#if defined DENOISER_BIND_UAV_RADIANCE
|
||||
layout (set = 0, binding = DENOISER_BIND_UAV_RADIANCE, rgba16f) uniform image2D rw_radiance;
|
||||
#endif
|
||||
#if defined DENOISER_BIND_UAV_VARIANCE
|
||||
layout (set = 0, binding = DENOISER_BIND_UAV_VARIANCE, r16f) uniform image2D rw_variance;
|
||||
#endif
|
||||
#if defined DENOISER_BIND_UAV_SAMPLE_COUNT
|
||||
layout (set = 0, binding = DENOISER_BIND_UAV_SAMPLE_COUNT, r16f) uniform image2D rw_sample_count;
|
||||
#endif
|
||||
#if defined DENOISER_BIND_UAV_AVERAGE_RADIANCE
|
||||
layout (set = 0, binding = DENOISER_BIND_UAV_AVERAGE_RADIANCE, r11f_g11f_b10f) uniform image2D rw_average_radiance;
|
||||
#endif
|
||||
#if defined DENOISER_BIND_UAV_DENOISER_TILE_LIST
|
||||
layout (set = 0, binding = DENOISER_BIND_UAV_DENOISER_TILE_LIST, std430) buffer rw_denoiser_tile_list_t
|
||||
{
|
||||
FfxUInt32 data[];
|
||||
} rw_denoiser_tile_list;
|
||||
#endif
|
||||
#if defined DENOISER_BIND_UAV_REPROJECTED_RADIANCE
|
||||
layout (set = 0, binding = DENOISER_BIND_UAV_REPROJECTED_RADIANCE, rgba16f) uniform image2D rw_reprojected_radiance;
|
||||
#endif
|
||||
|
||||
#if FFX_HALF
|
||||
|
||||
FfxFloat16x3 FFX_DENOISER_LoadWorldSpaceNormalH(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
#if defined(DENOISER_BIND_SRV_INPUT_NORMAL)
|
||||
return normalize(FfxFloat16x3(NormalsUnpackMul() * texelFetch(r_input_normal, pixel_coordinate, 0).xyz + NormalsUnpackAdd()));
|
||||
#else
|
||||
return FfxFloat16x3(0.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
FfxFloat16x3 LoadRadianceH(FfxInt32x3 coordinate)
|
||||
{
|
||||
#if defined (DENOISER_BIND_SRV_RADIANCE)
|
||||
return FfxFloat16x3(texelFetch(r_radiance, coordinate.xy, coordinate.z).xyz);
|
||||
#else
|
||||
return FfxFloat16x3(0.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
FfxFloat16 LoadVarianceH(FfxInt32x3 coordinate)
|
||||
{
|
||||
#if defined (DENOISER_BIND_SRV_VARIANCE)
|
||||
return FfxFloat16(texelFetch(r_variance, coordinate.xy, coordinate.z).x);
|
||||
#else
|
||||
return FfxFloat16(0.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_AVERAGE_RADIANCE)
|
||||
FfxFloat16x3 FFX_DNSR_Reflections_SampleAverageRadiance(FfxFloat32x2 uv)
|
||||
{
|
||||
return FfxFloat16x3(textureLod(sampler2D(r_average_radiance, s_LinearSampler), uv, 0.0f).xyz);
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_AVERAGE_RADIANCE)
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_EXTRACTED_ROUGHNESS)
|
||||
FfxFloat16 FFX_DNSR_Reflections_LoadRoughness(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
FfxFloat16 rawRoughness = FfxFloat16(texelFetch(r_extracted_roughness, pixel_coordinate, 0).x);
|
||||
if (IsRoughnessPerceptual())
|
||||
{
|
||||
rawRoughness *= rawRoughness;
|
||||
}
|
||||
|
||||
return rawRoughness;
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_EXTRACTED_ROUGHNESS)
|
||||
|
||||
void StoreRadianceH(FfxInt32x2 coordinate, FfxFloat16x4 radiance)
|
||||
{
|
||||
#if defined (DENOISER_BIND_UAV_RADIANCE)
|
||||
imageStore(rw_radiance, coordinate, radiance);
|
||||
#endif
|
||||
}
|
||||
|
||||
void StoreVarianceH(FfxInt32x2 coordinate, FfxFloat16 variance)
|
||||
{
|
||||
#if defined (DENOISER_BIND_UAV_VARIANCE)
|
||||
imageStore(rw_variance, coordinate, FfxFloat16x4(variance));
|
||||
#endif
|
||||
}
|
||||
|
||||
void FFX_DNSR_Reflections_StorePrefilteredReflections(FfxInt32x2 pixel_coordinate, FfxFloat16x3 radiance, FfxFloat16 variance)
|
||||
{
|
||||
StoreRadianceH(pixel_coordinate, radiance.xyzz);
|
||||
StoreVarianceH(pixel_coordinate, variance.x);
|
||||
}
|
||||
|
||||
void FFX_DNSR_Reflections_StoreTemporalAccumulation(FfxInt32x2 pixel_coordinate, FfxFloat16x3 radiance, FfxFloat16 variance)
|
||||
{
|
||||
StoreRadianceH(pixel_coordinate, radiance.xyzz);
|
||||
StoreVarianceH(pixel_coordinate, variance.x);
|
||||
}
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_RADIANCE_HISTORY)
|
||||
FfxFloat16x3 FFX_DNSR_Reflections_LoadRadianceHistory(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
return FfxFloat16x3(texelFetch(r_radiance_history, pixel_coordinate, 0).xyz);
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_RADIANCE_HISTORY)
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_RADIANCE_HISTORY)
|
||||
FfxFloat16x3 FFX_DNSR_Reflections_SampleRadianceHistory(FfxFloat32x2 uv)
|
||||
{
|
||||
return FfxFloat16x3(textureLod(sampler2D(r_radiance_history, s_LinearSampler), uv, 0.0f).xyz);
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_RADIANCE_HISTORY)
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_VARIANCE)
|
||||
FfxFloat16 FFX_DNSR_Reflections_SampleVarianceHistory(FfxFloat32x2 uv)
|
||||
{
|
||||
return FfxFloat16(textureLod(sampler2D(r_variance, s_LinearSampler), uv, 0.0f).x);
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_VARIANCE)
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_SAMPLE_COUNT)
|
||||
FfxFloat16 FFX_DNSR_Reflections_SampleNumSamplesHistory(FfxFloat32x2 uv)
|
||||
{
|
||||
return FfxFloat16(textureLod(sampler2D(r_sample_count, s_LinearSampler), uv, 0.0f).x);
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_SAMPLE_COUNT)
|
||||
|
||||
#if defined (DENOISER_BIND_UAV_REPROJECTED_RADIANCE)
|
||||
void FFX_DNSR_Reflections_StoreRadianceReprojected(FfxInt32x2 pixel_coordinate, FfxFloat16x3 value)
|
||||
{
|
||||
imageStore(rw_reprojected_radiance, pixel_coordinate, FfxFloat16x4(value, 0.0f));
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_UAV_REPROJECTED_RADIANCE)
|
||||
|
||||
#if defined (DENOISER_BIND_UAV_AVERAGE_RADIANCE)
|
||||
void FFX_DNSR_Reflections_StoreAverageRadiance(FfxInt32x2 pixel_coordinate, FfxFloat16x3 value)
|
||||
{
|
||||
imageStore(rw_average_radiance, pixel_coordinate, FfxFloat16x4(value, 0.0f));
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_UAV_AVERAGE_RADIANCE)
|
||||
|
||||
FfxFloat16x3 FFX_DNSR_Reflections_LoadWorldSpaceNormal(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
return FFX_DENOISER_LoadWorldSpaceNormalH(pixel_coordinate);
|
||||
}
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_ROUGHNESS_HISTORY)
|
||||
FfxFloat16 FFX_DNSR_Reflections_SampleRoughnessHistory(FfxFloat32x2 uv)
|
||||
{
|
||||
FfxFloat16 rawRoughness = FfxFloat16(textureLod(sampler2D(r_roughness_history, s_LinearSampler), uv, 0.0f).x);
|
||||
if (IsRoughnessPerceptual())
|
||||
{
|
||||
rawRoughness *= rawRoughness;
|
||||
}
|
||||
|
||||
return rawRoughness;
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_ROUGHNESS_HISTORY)
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_NORMAL_HISTORY)
|
||||
FfxFloat16x3 FFX_DNSR_Reflections_LoadWorldSpaceNormalHistory(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
return normalize(FfxFloat16x3(NormalsUnpackMul() * texelFetch(r_normal_history, pixel_coordinate.xy, 0).xyz + NormalsUnpackAdd()));
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_NORMAL_HISTORY)
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_NORMAL_HISTORY)
|
||||
FfxFloat16x3 FFX_DNSR_Reflections_SampleWorldSpaceNormalHistory(FfxFloat32x2 uv)
|
||||
{
|
||||
return normalize(FfxFloat16x3(NormalsUnpackMul() * textureLod(sampler2D(r_normal_history, s_LinearSampler), uv, 0.0f).xyz + NormalsUnpackAdd()));
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_NORMAL_HISTORY)
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_RADIANCE)
|
||||
FfxFloat16 FFX_DNSR_Reflections_LoadRayLength(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
return FfxFloat16(texelFetch(r_radiance, pixel_coordinate, 0).w);
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_RADIANCE)
|
||||
|
||||
void FFX_DNSR_Reflections_StoreVariance(FfxInt32x2 pixel_coordinate, FfxFloat16 value)
|
||||
{
|
||||
StoreVarianceH(pixel_coordinate, value);
|
||||
}
|
||||
|
||||
#if defined (DENOISER_BIND_UAV_SAMPLE_COUNT)
|
||||
void FFX_DNSR_Reflections_StoreNumSamples(FfxInt32x2 pixel_coordinate, FfxFloat16 value)
|
||||
{
|
||||
imageStore(rw_sample_count, pixel_coordinate, FfxFloat16x4(value));
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_UAV_SAMPLE_COUNT)
|
||||
|
||||
FfxFloat16x3 FFX_DNSR_Reflections_LoadRadiance(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
return LoadRadianceH(FfxInt32x3(pixel_coordinate, 0));
|
||||
}
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_REPROJECTED_RADIANCE)
|
||||
FfxFloat16x3 FFX_DNSR_Reflections_LoadRadianceReprojected(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
return FfxFloat16x3(texelFetch(r_reprojected_radiance, pixel_coordinate, 0).xyz);
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_REPROJECTED_RADIANCE)
|
||||
|
||||
FfxFloat16 FFX_DNSR_Reflections_LoadVariance(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
return LoadVarianceH(FfxInt32x3(pixel_coordinate, 0));
|
||||
}
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_SAMPLE_COUNT)
|
||||
FfxFloat16 FFX_DNSR_Reflections_LoadNumSamples(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
return FfxFloat16(texelFetch(r_sample_count, pixel_coordinate, 0).x);
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_SAMPLE_COUNT)
|
||||
|
||||
#else // FFX_HALF
|
||||
|
||||
FfxFloat32x3 LoadRadiance(FfxInt32x3 coordinate)
|
||||
{
|
||||
#if defined (DENOISER_BIND_SRV_RADIANCE)
|
||||
return texelFetch(r_radiance, coordinate.xy, coordinate.z).xyz;
|
||||
#else
|
||||
return FfxFloat32x3(0.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
FfxFloat32 LoadVariance(FfxInt32x3 coordinate)
|
||||
{
|
||||
#if defined (DENOISER_BIND_SRV_VARIANCE)
|
||||
return texelFetch(r_variance, coordinate.xy, coordinate.z).x;
|
||||
#else
|
||||
return 0.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
FfxFloat32x3 FFX_DENOISER_LoadWorldSpaceNormal(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
#if defined(DENOISER_BIND_SRV_INPUT_NORMAL)
|
||||
return normalize(NormalsUnpackMul() * texelFetch(r_input_normal, pixel_coordinate, 0).xyz + NormalsUnpackAdd());
|
||||
#else
|
||||
return FfxFloat32x3(0.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_EXTRACTED_ROUGHNESS)
|
||||
FfxFloat32 FFX_DNSR_Reflections_LoadRoughness(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
FfxFloat32 rawRoughness = FfxFloat32(texelFetch(r_extracted_roughness, pixel_coordinate, 0).x);
|
||||
if (IsRoughnessPerceptual())
|
||||
{
|
||||
rawRoughness *= rawRoughness;
|
||||
}
|
||||
|
||||
return rawRoughness;
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_EXTRACTED_ROUGHNESS)
|
||||
|
||||
void StoreRadiance(FfxInt32x2 coordinate, FfxFloat32x4 radiance)
|
||||
{
|
||||
#if defined (DENOISER_BIND_UAV_RADIANCE)
|
||||
imageStore(rw_radiance, coordinate, radiance);
|
||||
#endif
|
||||
}
|
||||
|
||||
void StoreVariance(FfxInt32x2 coordinate, FfxFloat32 variance)
|
||||
{
|
||||
#if defined (DENOISER_BIND_UAV_VARIANCE)
|
||||
imageStore(rw_variance, coordinate, FfxFloat32x4(variance));
|
||||
#endif
|
||||
}
|
||||
|
||||
void FFX_DNSR_Reflections_StorePrefilteredReflections(FfxInt32x2 pixel_coordinate, FfxFloat32x3 radiance, FfxFloat32 variance)
|
||||
{
|
||||
StoreRadiance(pixel_coordinate, radiance.xyzz);
|
||||
StoreVariance(pixel_coordinate, variance.x);
|
||||
}
|
||||
|
||||
void FFX_DNSR_Reflections_StoreTemporalAccumulation(FfxInt32x2 pixel_coordinate, FfxFloat32x3 radiance, FfxFloat32 variance)
|
||||
{
|
||||
StoreRadiance(pixel_coordinate, radiance.xyzz);
|
||||
StoreVariance(pixel_coordinate, variance.x);
|
||||
}
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_AVERAGE_RADIANCE)
|
||||
FfxFloat32x3 FFX_DNSR_Reflections_SampleAverageRadiance(FfxFloat32x2 uv)
|
||||
{
|
||||
return FfxFloat32x3(textureLod(sampler2D(r_average_radiance, s_LinearSampler), uv, 0.0f).xyz);
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_AVERAGE_RADIANCE)
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_RADIANCE_HISTORY)
|
||||
FfxFloat32x3 FFX_DNSR_Reflections_LoadRadianceHistory(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
return FfxFloat32x3(texelFetch(r_radiance_history, pixel_coordinate, 0).xyz);
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_RADIANCE_HISTORY)
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_RADIANCE_HISTORY)
|
||||
FfxFloat32x3 FFX_DNSR_Reflections_SampleRadianceHistory(FfxFloat32x2 uv)
|
||||
{
|
||||
return FfxFloat32x3(textureLod(sampler2D(r_radiance_history, s_LinearSampler), uv, 0.0f).xyz);
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_RADIANCE_HISTORY)
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_VARIANCE)
|
||||
FfxFloat32 FFX_DNSR_Reflections_SampleVarianceHistory(FfxFloat32x2 uv)
|
||||
{
|
||||
return FfxFloat32(textureLod(sampler2D(r_variance, s_LinearSampler), uv, 0.0f).x);
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_VARIANCE)
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_SAMPLE_COUNT)
|
||||
FfxFloat32 FFX_DNSR_Reflections_SampleNumSamplesHistory(FfxFloat32x2 uv)
|
||||
{
|
||||
return FfxFloat32(textureLod(sampler2D(r_sample_count, s_LinearSampler), uv, 0.0f).x);
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_SAMPLE_COUNT)
|
||||
|
||||
#if defined (DENOISER_BIND_UAV_REPROJECTED_RADIANCE)
|
||||
void FFX_DNSR_Reflections_StoreRadianceReprojected(FfxInt32x2 pixel_coordinate, FfxFloat32x3 value)
|
||||
{
|
||||
imageStore(rw_reprojected_radiance, pixel_coordinate, FfxFloat32x4(value, 0.0f));
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_UAV_REPROJECTED_RADIANCE)
|
||||
|
||||
#if defined (DENOISER_BIND_UAV_AVERAGE_RADIANCE)
|
||||
void FFX_DNSR_Reflections_StoreAverageRadiance(FfxInt32x2 pixel_coordinate, FfxFloat32x3 value)
|
||||
{
|
||||
imageStore(rw_average_radiance, pixel_coordinate, FfxFloat32x4(value, 0.0f));
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_UAV_AVERAGE_RADIANCE)
|
||||
|
||||
FfxFloat32x3 FFX_DNSR_Reflections_LoadWorldSpaceNormal(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
return FFX_DENOISER_LoadWorldSpaceNormal(pixel_coordinate);
|
||||
}
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_ROUGHNESS_HISTORY)
|
||||
FfxFloat32 FFX_DNSR_Reflections_SampleRoughnessHistory(FfxFloat32x2 uv)
|
||||
{
|
||||
FfxFloat32 rawRoughness = FfxFloat32(textureLod(sampler2D(r_roughness_history, s_LinearSampler), uv, 0.0f).x);
|
||||
if (IsRoughnessPerceptual())
|
||||
{
|
||||
rawRoughness *= rawRoughness;
|
||||
}
|
||||
|
||||
return rawRoughness;
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_ROUGHNESS_HISTORY)
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_NORMAL_HISTORY)
|
||||
FfxFloat32x3 FFX_DNSR_Reflections_LoadWorldSpaceNormalHistory(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
return normalize(FfxFloat32x3(NormalsUnpackMul() * texelFetch(r_normal_history, pixel_coordinate.xy, 0).xyz + NormalsUnpackAdd()));
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_NORMAL_HISTORY)
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_NORMAL_HISTORY)
|
||||
FfxFloat32x3 FFX_DNSR_Reflections_SampleWorldSpaceNormalHistory(FfxFloat32x2 uv)
|
||||
{
|
||||
return normalize(FfxFloat32x3(NormalsUnpackMul() * textureLod(sampler2D(r_normal_history, s_LinearSampler), uv, 0.0f).xyz + NormalsUnpackAdd()));
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_NORMAL_HISTORY)
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_RADIANCE)
|
||||
FfxFloat32 FFX_DNSR_Reflections_LoadRayLength(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
return FfxFloat32(texelFetch(r_radiance, pixel_coordinate, 0).w);
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_RADIANCE)
|
||||
|
||||
void FFX_DNSR_Reflections_StoreVariance(FfxInt32x2 pixel_coordinate, FfxFloat32 value)
|
||||
{
|
||||
StoreVariance(pixel_coordinate, value);
|
||||
}
|
||||
|
||||
#if defined (DENOISER_BIND_UAV_SAMPLE_COUNT)
|
||||
void FFX_DNSR_Reflections_StoreNumSamples(FfxInt32x2 pixel_coordinate, FfxFloat32 value)
|
||||
{
|
||||
imageStore(rw_sample_count, pixel_coordinate, FfxFloat32x4(value));
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_UAV_SAMPLE_COUNT)
|
||||
|
||||
FfxFloat32x3 FFX_DNSR_Reflections_LoadRadiance(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
return LoadRadiance(FfxInt32x3(pixel_coordinate, 0));
|
||||
}
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_REPROJECTED_RADIANCE)
|
||||
FfxFloat32x3 FFX_DNSR_Reflections_LoadRadianceReprojected(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
return FfxFloat32x3(texelFetch(r_reprojected_radiance, pixel_coordinate, 0).xyz);
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_REPROJECTED_RADIANCE)
|
||||
|
||||
FfxFloat32 FFX_DNSR_Reflections_LoadVariance(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
return LoadVariance(FfxInt32x3(pixel_coordinate, 0));
|
||||
}
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_SAMPLE_COUNT)
|
||||
FfxFloat32 FFX_DNSR_Reflections_LoadNumSamples(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
return FfxFloat32(texelFetch(r_sample_count, pixel_coordinate, 0).x);
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_SAMPLE_COUNT)
|
||||
|
||||
#endif // #if defined(FFX_HALF)
|
||||
|
||||
FfxFloat32 FFX_DENOISER_LoadDepth(FfxInt32x2 pixel_coordinate, FfxInt32 mip)
|
||||
{
|
||||
#if defined(DENOISER_BIND_SRV_INPUT_DEPTH_HIERARCHY)
|
||||
return texelFetch(r_input_depth_hierarchy, pixel_coordinate, mip).x;
|
||||
#else
|
||||
return 0.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined (DENOISER_BIND_UAV_DENOISER_TILE_LIST)
|
||||
FfxUInt32 GetDenoiserTile(FfxUInt32 group_id)
|
||||
{
|
||||
return rw_denoiser_tile_list.data[group_id];
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_UAV_DENOISER_TILE_LIST)
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_INPUT_MOTION_VECTORS)
|
||||
FfxFloat32x2 FFX_DNSR_Reflections_LoadMotionVector(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
return MotionVectorScale() * texelFetch(r_input_motion_vectors, pixel_coordinate, 0).xy;
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_INPUT_MOTION_VECTORS)
|
||||
|
||||
FfxFloat32 FFX_DNSR_Reflections_LoadDepth(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
return FFX_DENOISER_LoadDepth(pixel_coordinate, 0);
|
||||
}
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_DEPTH_HISTORY)
|
||||
FfxFloat32 FFX_DNSR_Reflections_LoadDepthHistory(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
return texelFetch(r_depth_history, pixel_coordinate, 0).x;
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_DEPTH_HISTORY)
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_DEPTH_HISTORY)
|
||||
FfxFloat32 FFX_DNSR_Reflections_SampleDepthHistory(FfxFloat32x2 uv)
|
||||
{
|
||||
return textureLod(sampler2D(r_depth_history, s_LinearSampler), uv, 0.0f).x;
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_DEPTH_HISTORY)
|
||||
|
||||
#endif // #if defined(FFX_GPU)
|
||||
@@ -0,0 +1,647 @@
|
||||
// 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_denoiser_resources.h"
|
||||
|
||||
#if defined(FFX_GPU)
|
||||
#ifdef __hlsl_dx_compiler
|
||||
#pragma dxc diagnostic push
|
||||
#pragma dxc diagnostic ignored "-Wambig-lit-shift"
|
||||
#endif //__hlsl_dx_compiler
|
||||
#include "ffx_core.h"
|
||||
#ifdef __hlsl_dx_compiler
|
||||
#pragma dxc diagnostic pop
|
||||
#endif //__hlsl_dx_compiler
|
||||
|
||||
#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_DENOISER_DECLARE_SRV(regIndex) register(DECLARE_SRV_REGISTER(regIndex))
|
||||
#define FFX_DENOISER_DECLARE_UAV(regIndex) register(DECLARE_UAV_REGISTER(regIndex))
|
||||
#define FFX_DENOISER_DECLARE_CB(regIndex) register(DECLARE_CB_REGISTER(regIndex))
|
||||
|
||||
#if defined(DENOISER_BIND_CB_DENOISER)
|
||||
cbuffer cbDenoiserReflections : FFX_DENOISER_DECLARE_CB(DENOISER_BIND_CB_DENOISER)
|
||||
{
|
||||
FfxFloat32Mat4 invProjection;
|
||||
FfxFloat32Mat4 invView;
|
||||
FfxFloat32Mat4 prevViewProjection;
|
||||
FfxUInt32x2 renderSize;
|
||||
FfxFloat32x2 inverseRenderSize;
|
||||
FfxFloat32x2 motionVectorScale;
|
||||
FfxFloat32 normalsUnpackMul;
|
||||
FfxFloat32 normalsUnpackAdd;
|
||||
FfxBoolean isRoughnessPerceptual;
|
||||
FfxFloat32 temporalStabilityFactor;
|
||||
FfxFloat32 roughnessThreshold;
|
||||
#define FFX_DENOISER_CONSTANT_BUFFER_1_SIZE 54 // Number of 32-bit values. This must be kept in sync with the cbDenoiser size.
|
||||
};
|
||||
#else
|
||||
#define invProjection 0
|
||||
#define invView 0
|
||||
#define prevViewProjection 0
|
||||
#define renderSize 0
|
||||
#define inverseRenderSize 0
|
||||
#define motionVectorScale 0
|
||||
#define normalsUnpackMul 0
|
||||
#define normalsUnpackAdd 0
|
||||
#define isRoughnessPerceptual 0
|
||||
#define temporalStabilityFactor 0
|
||||
#define roughnessThreshold 0
|
||||
#endif
|
||||
|
||||
#if defined(FFX_GPU)
|
||||
#define FFX_DENOISER_ROOTSIG_STRINGIFY(p) FFX_DENOISER_ROOTSIG_STR(p)
|
||||
#define FFX_DENOISER_ROOTSIG_STR(p) #p
|
||||
#define FFX_DENOISER_ROOTSIG [RootSignature("DescriptorTable(UAV(u0, numDescriptors = " FFX_DENOISER_ROOTSIG_STRINGIFY(FFX_DENOISER_RESOURCE_IDENTIFIER_COUNT) ")), " \
|
||||
"DescriptorTable(SRV(t0, numDescriptors = " FFX_DENOISER_ROOTSIG_STRINGIFY(FFX_DENOISER_RESOURCE_IDENTIFIER_COUNT) ")), " \
|
||||
"CBV(b0), " \
|
||||
"StaticSampler(s0, filter = FILTER_MIN_MAG_LINEAR_MIP_POINT, " \
|
||||
"addressU = TEXTURE_ADDRESS_CLAMP, " \
|
||||
"addressV = TEXTURE_ADDRESS_CLAMP, " \
|
||||
"addressW = TEXTURE_ADDRESS_CLAMP, " \
|
||||
"comparisonFunc = COMPARISON_ALWAYS, " \
|
||||
"borderColor = STATIC_BORDER_COLOR_TRANSPARENT_BLACK, " \
|
||||
"maxAnisotropy = 1)" )]
|
||||
|
||||
#if defined(FFX_DENOISER_EMBED_ROOTSIG)
|
||||
#define FFX_DENOISER_EMBED_ROOTSIG_CONTENT FFX_DENOISER_ROOTSIG
|
||||
#else
|
||||
#define FFX_DENOISER_EMBED_ROOTSIG_CONTENT
|
||||
#endif // #if FFX_DENOISER_EMBED_ROOTSIG
|
||||
|
||||
#endif // #if defined(FFX_GPU)
|
||||
|
||||
SamplerState s_LinearSampler : register(s0);
|
||||
|
||||
FfxFloat32Mat4 InvProjection()
|
||||
{
|
||||
return invProjection;
|
||||
}
|
||||
|
||||
FfxFloat32Mat4 InvView()
|
||||
{
|
||||
return invView;
|
||||
}
|
||||
|
||||
FfxFloat32Mat4 PrevViewProjection()
|
||||
{
|
||||
return prevViewProjection;
|
||||
}
|
||||
|
||||
FfxUInt32x2 RenderSize()
|
||||
{
|
||||
return renderSize;
|
||||
}
|
||||
|
||||
FfxFloat32x2 InverseRenderSize()
|
||||
{
|
||||
return inverseRenderSize;
|
||||
}
|
||||
|
||||
FfxFloat32x2 MotionVectorScale()
|
||||
{
|
||||
return motionVectorScale;
|
||||
}
|
||||
|
||||
FfxFloat32 NormalsUnpackMul()
|
||||
{
|
||||
return normalsUnpackMul;
|
||||
}
|
||||
|
||||
FfxFloat32 NormalsUnpackAdd()
|
||||
{
|
||||
return normalsUnpackAdd;
|
||||
}
|
||||
|
||||
FfxBoolean IsRoughnessPerceptual()
|
||||
{
|
||||
return isRoughnessPerceptual;
|
||||
}
|
||||
|
||||
FfxFloat32 TemporalStabilityFactor()
|
||||
{
|
||||
return temporalStabilityFactor;
|
||||
}
|
||||
|
||||
FfxFloat32 RoughnessThreshold()
|
||||
{
|
||||
return roughnessThreshold;
|
||||
}
|
||||
|
||||
// SRVs
|
||||
#if defined DENOISER_BIND_SRV_INPUT_DEPTH_HIERARCHY
|
||||
Texture2D<FfxFloat32> r_input_depth_hierarchy : FFX_DENOISER_DECLARE_SRV(DENOISER_BIND_SRV_INPUT_DEPTH_HIERARCHY);
|
||||
#endif
|
||||
#if defined DENOISER_BIND_SRV_INPUT_MOTION_VECTORS
|
||||
Texture2D<FfxFloat32x2> r_input_motion_vectors : FFX_DENOISER_DECLARE_SRV(DENOISER_BIND_SRV_INPUT_MOTION_VECTORS);
|
||||
#endif
|
||||
#if defined DENOISER_BIND_SRV_INPUT_NORMAL
|
||||
Texture2D<FfxFloat32x3> r_input_normal : FFX_DENOISER_DECLARE_SRV(DENOISER_BIND_SRV_INPUT_NORMAL);
|
||||
#endif
|
||||
#if defined DENOISER_BIND_SRV_RADIANCE
|
||||
Texture2D<FfxFloat32x4> r_radiance : FFX_DENOISER_DECLARE_SRV(DENOISER_BIND_SRV_RADIANCE);
|
||||
#endif
|
||||
#if defined DENOISER_BIND_SRV_RADIANCE_HISTORY
|
||||
Texture2D<FfxFloat32x4> r_radiance_history : FFX_DENOISER_DECLARE_SRV(DENOISER_BIND_SRV_RADIANCE_HISTORY);
|
||||
#endif
|
||||
#if defined DENOISER_BIND_SRV_VARIANCE
|
||||
Texture2D<FfxFloat32> r_variance : FFX_DENOISER_DECLARE_SRV(DENOISER_BIND_SRV_VARIANCE);
|
||||
#endif
|
||||
#if defined DENOISER_BIND_SRV_SAMPLE_COUNT
|
||||
Texture2D<FfxFloat32> r_sample_count : FFX_DENOISER_DECLARE_SRV(DENOISER_BIND_SRV_SAMPLE_COUNT);
|
||||
#endif
|
||||
#if defined DENOISER_BIND_SRV_AVERAGE_RADIANCE
|
||||
Texture2D<FfxFloat32x3> r_average_radiance : FFX_DENOISER_DECLARE_SRV(DENOISER_BIND_SRV_AVERAGE_RADIANCE);
|
||||
#endif
|
||||
#if defined DENOISER_BIND_SRV_EXTRACTED_ROUGHNESS
|
||||
Texture2D<FfxFloat32> r_extracted_roughness : FFX_DENOISER_DECLARE_SRV(DENOISER_BIND_SRV_EXTRACTED_ROUGHNESS);
|
||||
#endif
|
||||
#if defined DENOISER_BIND_SRV_DEPTH_HISTORY
|
||||
Texture2D<FfxFloat32> r_depth_history : FFX_DENOISER_DECLARE_SRV(DENOISER_BIND_SRV_DEPTH_HISTORY);
|
||||
#endif
|
||||
#if defined DENOISER_BIND_SRV_NORMAL_HISTORY
|
||||
Texture2D<FfxFloat32x3> r_normal_history : FFX_DENOISER_DECLARE_SRV(DENOISER_BIND_SRV_NORMAL_HISTORY);
|
||||
#endif
|
||||
#if defined DENOISER_BIND_SRV_ROUGHNESS_HISTORY
|
||||
Texture2D<FfxFloat32> r_roughness_history : FFX_DENOISER_DECLARE_SRV(DENOISER_BIND_SRV_ROUGHNESS_HISTORY);
|
||||
#endif
|
||||
#if defined DENOISER_BIND_SRV_REPROJECTED_RADIANCE
|
||||
Texture2D<FfxFloat32x4> r_reprojected_radiance : FFX_DENOISER_DECLARE_SRV(DENOISER_BIND_SRV_REPROJECTED_RADIANCE);
|
||||
#endif
|
||||
|
||||
// UAVs
|
||||
#if defined DENOISER_BIND_UAV_RADIANCE
|
||||
RWTexture2D<FfxFloat32x4> rw_radiance : FFX_DENOISER_DECLARE_UAV(DENOISER_BIND_UAV_RADIANCE);
|
||||
#endif
|
||||
#if defined DENOISER_BIND_UAV_VARIANCE
|
||||
RWTexture2D<FfxFloat32> rw_variance : FFX_DENOISER_DECLARE_UAV(DENOISER_BIND_UAV_VARIANCE);
|
||||
#endif
|
||||
#if defined DENOISER_BIND_UAV_SAMPLE_COUNT
|
||||
RWTexture2D<FfxFloat32> rw_sample_count : FFX_DENOISER_DECLARE_UAV(DENOISER_BIND_UAV_SAMPLE_COUNT);
|
||||
#endif
|
||||
#if defined DENOISER_BIND_UAV_AVERAGE_RADIANCE
|
||||
RWTexture2D<FfxFloat32x3> rw_average_radiance : FFX_DENOISER_DECLARE_UAV(DENOISER_BIND_UAV_AVERAGE_RADIANCE);
|
||||
#endif
|
||||
#if defined DENOISER_BIND_UAV_DENOISER_TILE_LIST
|
||||
RWStructuredBuffer<FfxUInt32> rw_denoiser_tile_list : FFX_DENOISER_DECLARE_UAV(DENOISER_BIND_UAV_DENOISER_TILE_LIST);
|
||||
#endif
|
||||
#if defined DENOISER_BIND_UAV_REPROJECTED_RADIANCE
|
||||
RWTexture2D<FfxFloat32x3> rw_reprojected_radiance : FFX_DENOISER_DECLARE_UAV(DENOISER_BIND_UAV_REPROJECTED_RADIANCE);
|
||||
#endif
|
||||
|
||||
#if FFX_HALF
|
||||
|
||||
|
||||
FfxFloat16x3 FFX_DENOISER_LoadWorldSpaceNormalH(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
#if defined(DENOISER_BIND_SRV_INPUT_NORMAL)
|
||||
return normalize((FfxFloat16x3)(NormalsUnpackMul() * r_input_normal.Load(FfxInt32x3(pixel_coordinate, 0)) + NormalsUnpackAdd()));
|
||||
#else
|
||||
return 0.0f;
|
||||
#endif // #if defined(DENOISER_BIND_SRV_INPUT_NORMAL)
|
||||
}
|
||||
|
||||
FfxFloat16x3 LoadRadianceH(FfxInt32x3 coordinate)
|
||||
{
|
||||
#if defined (DENOISER_BIND_SRV_RADIANCE)
|
||||
return (FfxFloat16x3)r_radiance.Load(coordinate).xyz;
|
||||
#else
|
||||
return 0.0f;
|
||||
#endif // #if defined (DENOISER_BIND_SRV_RADIANCE)
|
||||
}
|
||||
|
||||
FfxFloat16 LoadVarianceH(FfxInt32x3 coordinate)
|
||||
{
|
||||
#if defined (DENOISER_BIND_SRV_VARIANCE)
|
||||
return (FfxFloat16)r_variance.Load(coordinate).x;
|
||||
#else
|
||||
return 0.0f;
|
||||
#endif // #if defined (DENOISER_BIND_SRV_VARIANCE)
|
||||
}
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_AVERAGE_RADIANCE)
|
||||
FfxFloat16x3 FFX_DNSR_Reflections_SampleAverageRadiance(FfxFloat32x2 uv)
|
||||
{
|
||||
return (FfxFloat16x3)r_average_radiance.SampleLevel(s_LinearSampler, uv, 0.0f).xyz;
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_AVERAGE_RADIANCE)
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_EXTRACTED_ROUGHNESS)
|
||||
FfxFloat16 FFX_DNSR_Reflections_LoadRoughness(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
FfxFloat16 rawRoughness = (FfxFloat16)r_extracted_roughness.Load(FfxInt32x3(pixel_coordinate, 0));
|
||||
if (IsRoughnessPerceptual())
|
||||
{
|
||||
rawRoughness *= rawRoughness;
|
||||
}
|
||||
|
||||
return rawRoughness;
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_EXTRACTED_ROUGHNESS)
|
||||
|
||||
void StoreRadianceH(FfxInt32x2 coordinate, FfxFloat16x4 radiance)
|
||||
{
|
||||
#if defined (DENOISER_BIND_UAV_RADIANCE)
|
||||
rw_radiance[coordinate] = radiance;
|
||||
#endif // #if defined (DENOISER_BIND_UAV_RADIANCE)
|
||||
}
|
||||
|
||||
void StoreVarianceH(FfxInt32x2 coordinate, FfxFloat16 variance)
|
||||
{
|
||||
#if defined (DENOISER_BIND_UAV_VARIANCE)
|
||||
rw_variance[coordinate] = variance;
|
||||
#endif // #if defined (DENOISER_BIND_UAV_VARIANCE)
|
||||
}
|
||||
|
||||
void FFX_DNSR_Reflections_StorePrefilteredReflections(FfxInt32x2 pixel_coordinate, FfxFloat16x3 radiance, FfxFloat16 variance)
|
||||
{
|
||||
StoreRadianceH(pixel_coordinate, radiance.xyzz);
|
||||
StoreVarianceH(pixel_coordinate, variance.x);
|
||||
}
|
||||
|
||||
void FFX_DNSR_Reflections_StoreTemporalAccumulation(FfxInt32x2 pixel_coordinate, FfxFloat16x3 radiance, FfxFloat16 variance)
|
||||
{
|
||||
StoreRadianceH(pixel_coordinate, radiance.xyzz);
|
||||
StoreVarianceH(pixel_coordinate, variance.x);
|
||||
}
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_RADIANCE_HISTORY)
|
||||
FfxFloat16x3 FFX_DNSR_Reflections_LoadRadianceHistory(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
return (FfxFloat16x3)r_radiance_history.Load(FfxInt32x3(pixel_coordinate, 0)).xyz;
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_RADIANCE_HISTORY)
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_RADIANCE_HISTORY)
|
||||
FfxFloat16x3 FFX_DNSR_Reflections_SampleRadianceHistory(FfxFloat32x2 uv)
|
||||
{
|
||||
return (FfxFloat16x3)r_radiance_history.SampleLevel(s_LinearSampler, uv, 0.0f).xyz;
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_RADIANCE_HISTORY)
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_VARIANCE)
|
||||
FfxFloat16 FFX_DNSR_Reflections_SampleVarianceHistory(FfxFloat32x2 uv)
|
||||
{
|
||||
return (FfxFloat16)r_variance.SampleLevel(s_LinearSampler, uv, 0.0f).x;
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_VARIANCE)
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_SAMPLE_COUNT)
|
||||
FfxFloat16 FFX_DNSR_Reflections_SampleNumSamplesHistory(FfxFloat32x2 uv)
|
||||
{
|
||||
return (FfxFloat16)r_sample_count.SampleLevel(s_LinearSampler, uv, 0.0f).x;
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_SAMPLE_COUNT)
|
||||
|
||||
#if defined (DENOISER_BIND_UAV_REPROJECTED_RADIANCE)
|
||||
void FFX_DNSR_Reflections_StoreRadianceReprojected(FfxInt32x2 pixel_coordinate, FfxFloat16x3 value)
|
||||
{
|
||||
rw_reprojected_radiance[pixel_coordinate] = value;
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_UAV_REPROJECTED_RADIANCE)
|
||||
|
||||
#if defined (DENOISER_BIND_UAV_AVERAGE_RADIANCE)
|
||||
void FFX_DNSR_Reflections_StoreAverageRadiance(FfxInt32x2 pixel_coordinate, FfxFloat16x3 value)
|
||||
{
|
||||
rw_average_radiance[pixel_coordinate] = value;
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_UAV_AVERAGE_RADIANCE)
|
||||
|
||||
FfxFloat16x3 FFX_DNSR_Reflections_LoadWorldSpaceNormal(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
return FFX_DENOISER_LoadWorldSpaceNormalH(pixel_coordinate);
|
||||
}
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_ROUGHNESS_HISTORY)
|
||||
FfxFloat16 FFX_DNSR_Reflections_SampleRoughnessHistory(FfxFloat32x2 uv)
|
||||
{
|
||||
FfxFloat16 rawRoughness = (FfxFloat16)r_roughness_history.SampleLevel(s_LinearSampler, uv, 0.0f);
|
||||
if (IsRoughnessPerceptual())
|
||||
{
|
||||
rawRoughness *= rawRoughness;
|
||||
}
|
||||
|
||||
return rawRoughness;
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_ROUGHNESS_HISTORY)
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_NORMAL_HISTORY)
|
||||
FfxFloat16x3 FFX_DNSR_Reflections_LoadWorldSpaceNormalHistory(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
return normalize((FfxFloat16x3)(NormalsUnpackMul() * r_normal_history.Load(FfxInt32x3(pixel_coordinate, 0)) + NormalsUnpackAdd()));
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_NORMAL_HISTORY)
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_NORMAL_HISTORY)
|
||||
FfxFloat16x3 FFX_DNSR_Reflections_SampleWorldSpaceNormalHistory(FfxFloat32x2 uv)
|
||||
{
|
||||
return normalize((FfxFloat16x3)(NormalsUnpackMul() * r_normal_history.SampleLevel(s_LinearSampler, uv, 0.0f) + NormalsUnpackAdd()));
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_NORMAL_HISTORY)
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_RADIANCE)
|
||||
FfxFloat16 FFX_DNSR_Reflections_LoadRayLength(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
return (FfxFloat16)r_radiance.Load(FfxInt32x3(pixel_coordinate, 0)).w;
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_RADIANCE)
|
||||
|
||||
void FFX_DNSR_Reflections_StoreVariance(FfxInt32x2 pixel_coordinate, FfxFloat16 value)
|
||||
{
|
||||
StoreVarianceH(pixel_coordinate, value);
|
||||
}
|
||||
|
||||
#if defined (DENOISER_BIND_UAV_SAMPLE_COUNT)
|
||||
void FFX_DNSR_Reflections_StoreNumSamples(FfxInt32x2 pixel_coordinate, FfxFloat16 value)
|
||||
{
|
||||
rw_sample_count[pixel_coordinate] = value;
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_UAV_SAMPLE_COUNT)
|
||||
|
||||
FfxFloat16x3 FFX_DNSR_Reflections_LoadRadiance(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
return LoadRadianceH(FfxInt32x3(pixel_coordinate, 0));
|
||||
}
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_REPROJECTED_RADIANCE)
|
||||
FfxFloat16x3 FFX_DNSR_Reflections_LoadRadianceReprojected(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
return (FfxFloat16x3)r_reprojected_radiance.Load(FfxInt32x3(pixel_coordinate, 0)).xyz;
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_REPROJECTED_RADIANCE)
|
||||
|
||||
FfxFloat16 FFX_DNSR_Reflections_LoadVariance(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
return LoadVarianceH(FfxInt32x3(pixel_coordinate, 0));
|
||||
}
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_SAMPLE_COUNT)
|
||||
FfxFloat16 FFX_DNSR_Reflections_LoadNumSamples(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
return (FfxFloat16)r_sample_count.Load(FfxInt32x3(pixel_coordinate, 0)).x;
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_SAMPLE_COUNT)
|
||||
|
||||
#else // FFX_HALF
|
||||
|
||||
FfxFloat32x3 LoadRadiance(FfxInt32x3 coordinate)
|
||||
{
|
||||
#if defined (DENOISER_BIND_SRV_RADIANCE)
|
||||
return r_radiance.Load(coordinate).xyz;
|
||||
#else
|
||||
return 0.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
FfxFloat32 LoadVariance(FfxInt32x3 coordinate)
|
||||
{
|
||||
#if defined (DENOISER_BIND_SRV_VARIANCE)
|
||||
return r_variance.Load(coordinate).x;
|
||||
#else
|
||||
return 0.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
FfxFloat32x3 FFX_DENOISER_LoadWorldSpaceNormal(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
#if defined(DENOISER_BIND_SRV_INPUT_NORMAL)
|
||||
return normalize(NormalsUnpackMul() * r_input_normal.Load(FfxInt32x3(pixel_coordinate, 0)) + NormalsUnpackAdd());
|
||||
#else
|
||||
return 0.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_EXTRACTED_ROUGHNESS)
|
||||
FfxFloat32 FFX_DNSR_Reflections_LoadRoughness(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
FfxFloat32 rawRoughness = (FfxFloat32)r_extracted_roughness.Load(FfxInt32x3(pixel_coordinate, 0));
|
||||
if (IsRoughnessPerceptual())
|
||||
{
|
||||
rawRoughness *= rawRoughness;
|
||||
}
|
||||
|
||||
return rawRoughness;
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_EXTRACTED_ROUGHNESS)
|
||||
|
||||
void StoreRadiance(FfxInt32x2 coordinate, FfxFloat32x4 radiance)
|
||||
{
|
||||
#if defined (DENOISER_BIND_UAV_RADIANCE)
|
||||
rw_radiance[coordinate] = radiance;
|
||||
#endif
|
||||
}
|
||||
|
||||
void StoreVariance(FfxInt32x2 coordinate, FfxFloat32 variance)
|
||||
{
|
||||
#if defined (DENOISER_BIND_UAV_VARIANCE)
|
||||
rw_variance[coordinate] = variance;
|
||||
#endif
|
||||
}
|
||||
|
||||
void FFX_DNSR_Reflections_StorePrefilteredReflections(FfxInt32x2 pixel_coordinate, FfxFloat32x3 radiance, FfxFloat32 variance)
|
||||
{
|
||||
StoreRadiance(pixel_coordinate, radiance.xyzz);
|
||||
StoreVariance(pixel_coordinate, variance.x);
|
||||
}
|
||||
|
||||
void FFX_DNSR_Reflections_StoreTemporalAccumulation(FfxInt32x2 pixel_coordinate, FfxFloat32x3 radiance, FfxFloat32 variance)
|
||||
{
|
||||
StoreRadiance(pixel_coordinate, radiance.xyzz);
|
||||
StoreVariance(pixel_coordinate, variance.x);
|
||||
}
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_AVERAGE_RADIANCE)
|
||||
FfxFloat32x3 FFX_DNSR_Reflections_SampleAverageRadiance(FfxFloat32x2 uv)
|
||||
{
|
||||
return (FfxFloat32x3)r_average_radiance.SampleLevel(s_LinearSampler, uv, 0.0f).xyz;
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_AVERAGE_RADIANCE)
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_RADIANCE_HISTORY)
|
||||
FfxFloat32x3 FFX_DNSR_Reflections_LoadRadianceHistory(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
return (FfxFloat32x3)r_radiance_history.Load(FfxInt32x3(pixel_coordinate, 0)).xyz;
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_RADIANCE_HISTORY)
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_RADIANCE_HISTORY)
|
||||
FfxFloat32x3 FFX_DNSR_Reflections_SampleRadianceHistory(FfxFloat32x2 uv)
|
||||
{
|
||||
return (FfxFloat32x3)r_radiance_history.SampleLevel(s_LinearSampler, uv, 0.0f).xyz;
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_RADIANCE_HISTORY)
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_VARIANCE)
|
||||
FfxFloat32 FFX_DNSR_Reflections_SampleVarianceHistory(FfxFloat32x2 uv)
|
||||
{
|
||||
return (FfxFloat32)r_variance.SampleLevel(s_LinearSampler, uv, 0.0f).x;
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_VARIANCE)
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_SAMPLE_COUNT)
|
||||
FfxFloat32 FFX_DNSR_Reflections_SampleNumSamplesHistory(FfxFloat32x2 uv)
|
||||
{
|
||||
return (FfxFloat32)r_sample_count.SampleLevel(s_LinearSampler, uv, 0.0f).x;
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_SAMPLE_COUNT)
|
||||
|
||||
#if defined (DENOISER_BIND_UAV_REPROJECTED_RADIANCE)
|
||||
void FFX_DNSR_Reflections_StoreRadianceReprojected(FfxInt32x2 pixel_coordinate, FfxFloat32x3 value)
|
||||
{
|
||||
rw_reprojected_radiance[pixel_coordinate] = value;
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_UAV_REPROJECTED_RADIANCE)
|
||||
|
||||
#if defined (DENOISER_BIND_UAV_AVERAGE_RADIANCE)
|
||||
void FFX_DNSR_Reflections_StoreAverageRadiance(FfxInt32x2 pixel_coordinate, FfxFloat32x3 value)
|
||||
{
|
||||
rw_average_radiance[pixel_coordinate] = value;
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_UAV_AVERAGE_RADIANCE)
|
||||
|
||||
FfxFloat32x3 FFX_DNSR_Reflections_LoadWorldSpaceNormal(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
return FFX_DENOISER_LoadWorldSpaceNormal(pixel_coordinate);
|
||||
}
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_ROUGHNESS_HISTORY)
|
||||
FfxFloat32 FFX_DNSR_Reflections_SampleRoughnessHistory(FfxFloat32x2 uv)
|
||||
{
|
||||
FfxFloat32 rawRoughness = (FfxFloat32)r_roughness_history.SampleLevel(s_LinearSampler, uv, 0.0f);
|
||||
if (IsRoughnessPerceptual())
|
||||
{
|
||||
rawRoughness *= rawRoughness;
|
||||
}
|
||||
|
||||
return rawRoughness;
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_ROUGHNESS_HISTORY)
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_NORMAL_HISTORY)
|
||||
FfxFloat32x3 FFX_DNSR_Reflections_LoadWorldSpaceNormalHistory(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
return normalize((FfxFloat32x3)(NormalsUnpackMul() * r_normal_history.Load(FfxInt32x3(pixel_coordinate, 0)) + NormalsUnpackAdd()));
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_NORMAL_HISTORY)
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_NORMAL_HISTORY)
|
||||
FfxFloat32x3 FFX_DNSR_Reflections_SampleWorldSpaceNormalHistory(FfxFloat32x2 uv)
|
||||
{
|
||||
return normalize((FfxFloat32x3)(NormalsUnpackMul() * r_normal_history.SampleLevel(s_LinearSampler, uv, 0.0f) + NormalsUnpackAdd()));
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_NORMAL_HISTORY)
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_RADIANCE)
|
||||
FfxFloat32 FFX_DNSR_Reflections_LoadRayLength(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
return (FfxFloat32)r_radiance.Load(FfxInt32x3(pixel_coordinate, 0)).w;
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_RADIANCE)
|
||||
|
||||
void FFX_DNSR_Reflections_StoreVariance(FfxInt32x2 pixel_coordinate, FfxFloat32 value)
|
||||
{
|
||||
StoreVariance(pixel_coordinate, value);
|
||||
}
|
||||
|
||||
#if defined (DENOISER_BIND_UAV_SAMPLE_COUNT)
|
||||
void FFX_DNSR_Reflections_StoreNumSamples(FfxInt32x2 pixel_coordinate, FfxFloat32 value)
|
||||
{
|
||||
rw_sample_count[pixel_coordinate] = value;
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_UAV_SAMPLE_COUNT)
|
||||
|
||||
FfxFloat32x3 FFX_DNSR_Reflections_LoadRadiance(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
return LoadRadiance(FfxInt32x3(pixel_coordinate, 0));
|
||||
}
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_REPROJECTED_RADIANCE)
|
||||
FfxFloat32x3 FFX_DNSR_Reflections_LoadRadianceReprojected(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
return (FfxFloat32x3)r_reprojected_radiance.Load(FfxInt32x3(pixel_coordinate, 0)).xyz;
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_REPROJECTED_RADIANCE)
|
||||
|
||||
FfxFloat32 FFX_DNSR_Reflections_LoadVariance(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
return LoadVariance(FfxInt32x3(pixel_coordinate, 0));
|
||||
}
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_SAMPLE_COUNT)
|
||||
FfxFloat32 FFX_DNSR_Reflections_LoadNumSamples(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
return (FfxFloat32)r_sample_count.Load(FfxInt32x3(pixel_coordinate, 0)).x;
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_SAMPLE_COUNT)
|
||||
|
||||
#endif // #if defined(FFX_HALF)
|
||||
|
||||
FfxFloat32 FFX_DENOISER_LoadDepth(FfxInt32x2 pixel_coordinate, FfxInt32 mip)
|
||||
{
|
||||
#if defined(DENOISER_BIND_SRV_INPUT_DEPTH_HIERARCHY)
|
||||
return r_input_depth_hierarchy.Load(FfxInt32x3(pixel_coordinate, mip));
|
||||
#else
|
||||
return 0.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined (DENOISER_BIND_UAV_DENOISER_TILE_LIST)
|
||||
FfxUInt32 GetDenoiserTile(FfxUInt32 group_id)
|
||||
{
|
||||
return rw_denoiser_tile_list[group_id];
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_UAV_DENOISER_TILE_LIST)
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_INPUT_MOTION_VECTORS)
|
||||
FfxFloat32x2 FFX_DNSR_Reflections_LoadMotionVector(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
return MotionVectorScale() * r_input_motion_vectors.Load(FfxInt32x3(pixel_coordinate, 0));
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_INPUT_MOTION_VECTORS)
|
||||
|
||||
FfxFloat32 FFX_DNSR_Reflections_LoadDepth(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
return FFX_DENOISER_LoadDepth(pixel_coordinate, 0);
|
||||
}
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_DEPTH_HISTORY)
|
||||
FfxFloat32 FFX_DNSR_Reflections_LoadDepthHistory(FfxInt32x2 pixel_coordinate)
|
||||
{
|
||||
return r_depth_history.Load(FfxInt32x3(pixel_coordinate, 0));
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_DEPTH_HISTORY)
|
||||
|
||||
#if defined (DENOISER_BIND_SRV_DEPTH_HISTORY)
|
||||
FfxFloat32 FFX_DNSR_Reflections_SampleDepthHistory(FfxFloat32x2 uv)
|
||||
{
|
||||
return r_depth_history.SampleLevel(s_LinearSampler, uv, 0.0f);
|
||||
}
|
||||
#endif // #if defined (DENOISER_BIND_SRV_DEPTH_HISTORY)
|
||||
|
||||
#endif // #if defined(FFX_GPU)
|
||||
286
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/denoiser/ffx_denoiser_reflections_common.h
vendored
Normal file
286
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/denoiser/ffx_denoiser_reflections_common.h
vendored
Normal file
@@ -0,0 +1,286 @@
|
||||
// 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_DNSR_REFLECTIONS_COMMON
|
||||
#define FFX_DNSR_REFLECTIONS_COMMON
|
||||
|
||||
#include "ffx_denoiser_reflections_config.h"
|
||||
|
||||
FfxBoolean FFX_DNSR_Reflections_IsGlossyReflection(FfxFloat32 roughness) {
|
||||
return roughness < RoughnessThreshold();
|
||||
}
|
||||
|
||||
FfxBoolean FFX_DNSR_Reflections_IsMirrorReflection(FfxFloat32 roughness) {
|
||||
return roughness < 0.0001;
|
||||
}
|
||||
|
||||
// Transforms origin to uv space
|
||||
// Mat must be able to transform origin from its current space into clip space.
|
||||
FfxFloat32x3 ProjectPosition(FfxFloat32x3 origin, FfxFloat32Mat4 mat) {
|
||||
FfxFloat32x4 projected = FFX_MATRIX_MULTIPLY(mat, FfxFloat32x4(origin, 1));
|
||||
projected.xyz /= projected.w;
|
||||
projected.xy = 0.5 * projected.xy + 0.5;
|
||||
projected.y = (1 - projected.y);
|
||||
return projected.xyz;
|
||||
}
|
||||
|
||||
// Mat must be able to transform origin from texture space to a linear space.
|
||||
FfxFloat32x3 FFX_DNSR_InvProjectPosition(FfxFloat32x3 coord, FfxFloat32Mat4 mat) {
|
||||
coord.y = (1 - coord.y);
|
||||
coord.xy = 2 * coord.xy - 1;
|
||||
FfxFloat32x4 projected = FFX_MATRIX_MULTIPLY(mat, FfxFloat32x4(coord, 1));
|
||||
projected.xyz /= projected.w;
|
||||
return projected.xyz;
|
||||
}
|
||||
|
||||
FfxFloat32 FFX_DNSR_Reflections_GetLinearDepth(FfxFloat32x2 uv, FfxFloat32 depth) {
|
||||
const FfxFloat32x3 view_space_pos = FFX_DNSR_InvProjectPosition(FfxFloat32x3(uv, depth), InvProjection());
|
||||
return abs(view_space_pos.z);
|
||||
}
|
||||
|
||||
FfxFloat32x3 FFX_DNSR_Reflections_ScreenSpaceToViewSpace(FfxFloat32x3 screen_uv_coord) {
|
||||
return FFX_DNSR_InvProjectPosition(screen_uv_coord, InvProjection());
|
||||
}
|
||||
|
||||
FfxFloat32x3 FFX_DNSR_Reflections_WorldSpaceToScreenSpacePrevious(FfxFloat32x3 world_space_pos) {
|
||||
return ProjectPosition(world_space_pos, PrevViewProjection());
|
||||
}
|
||||
|
||||
FfxFloat32x3 FFX_DNSR_Reflections_ViewSpaceToWorldSpace(FfxFloat32x4 view_space_coord) {
|
||||
return FFX_MATRIX_MULTIPLY(InvView(), view_space_coord).xyz;
|
||||
}
|
||||
|
||||
// Rounds value to the nearest multiple of 8
|
||||
FfxUInt32x2 FFX_DNSR_Reflections_RoundUp8(FfxUInt32x2 value) {
|
||||
FfxUInt32x2 round_down = value & ~7; // 0b111;
|
||||
return FFX_SELECT((round_down == value), value, value + 8);
|
||||
}
|
||||
|
||||
#if FFX_HALF
|
||||
|
||||
FfxFloat16 FFX_DNSR_Reflections_Luminance(FfxFloat16x3 color)
|
||||
{
|
||||
return max(FfxFloat16(dot(color, FfxFloat16x3(0.299f, 0.587f, 0.114f))), FfxFloat16(0.001));
|
||||
}
|
||||
|
||||
FfxFloat16 FFX_DNSR_Reflections_ComputeTemporalVariance(FfxFloat16x3 history_radiance, FfxFloat16x3 radiance) {
|
||||
FfxFloat16 history_luminance = FFX_DNSR_Reflections_Luminance(history_radiance);
|
||||
FfxFloat16 luminance = FFX_DNSR_Reflections_Luminance(radiance);
|
||||
FfxFloat16 diff = abs(history_luminance - luminance) / max(max(history_luminance, luminance), FfxFloat16(0.5f));
|
||||
return diff * diff;
|
||||
}
|
||||
|
||||
FfxUInt32 FFX_DNSR_Reflections_PackFloat16(FfxFloat16x2 v)
|
||||
{
|
||||
#if defined(FFX_GLSL)
|
||||
return ffxPackHalf2x16(FfxFloat32x2(v));
|
||||
#elif defined(FFX_HLSL)
|
||||
FfxUInt32x2 p = ffxF32ToF16(FfxFloat32x2(v));
|
||||
return p.x | (p.y << 16);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
FfxFloat16x2 FFX_DNSR_Reflections_UnpackFloat16(FfxUInt32 a)
|
||||
{
|
||||
#if defined(FFX_GLSL)
|
||||
return FfxFloat16x2(unpackHalf2x16(a));
|
||||
#elif defined(FFX_HLSL)
|
||||
FfxFloat32x2 tmp = f16tof32(FfxUInt32x2(a & 0xFFFF, a >> 16));
|
||||
return FfxFloat16x2(tmp);
|
||||
#endif
|
||||
|
||||
return FfxFloat16x2(0.0f, 0.0f);
|
||||
}
|
||||
|
||||
FfxUInt32x2 FFX_DNSR_Reflections_PackFloat16_4(FfxFloat16x4 v) { return FfxUInt32x2(FFX_DNSR_Reflections_PackFloat16(v.xy), FFX_DNSR_Reflections_PackFloat16(v.zw)); }
|
||||
|
||||
FfxFloat16x4 FFX_DNSR_Reflections_UnpackFloat16_4(FfxUInt32x2 a) { return FfxFloat16x4(FFX_DNSR_Reflections_UnpackFloat16(a.x), FFX_DNSR_Reflections_UnpackFloat16(a.y)); }
|
||||
|
||||
// From "Temporal Reprojection Anti-Aliasing"
|
||||
// https://github.com/playdeadgames/temporal
|
||||
/**********************************************************************
|
||||
Copyright (c) [2015] [Playdead]
|
||||
|
||||
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.
|
||||
********************************************************************/
|
||||
FfxFloat16x3 FFX_DNSR_Reflections_ClipAABB(FfxFloat16x3 aabb_min, FfxFloat16x3 aabb_max, FfxFloat16x3 prev_sample) {
|
||||
// Main idea behind clipping - it prevents clustering when neighbor color space
|
||||
// is distant from history sample
|
||||
|
||||
// Here we find intersection between color vector and aabb color box
|
||||
|
||||
// Note: only clips towards aabb center
|
||||
FfxFloat32x3 aabb_center = 0.5 * (aabb_max + aabb_min);
|
||||
FfxFloat32x3 extent_clip = 0.5 * (aabb_max - aabb_min) + 0.001;
|
||||
|
||||
// Find color vector
|
||||
FfxFloat32x3 color_vector = prev_sample - aabb_center;
|
||||
// Transform into clip space
|
||||
FfxFloat32x3 color_vector_clip = color_vector / extent_clip;
|
||||
// Find max absolute component
|
||||
color_vector_clip = abs(color_vector_clip);
|
||||
FfxFloat16 max_abs_unit = FfxFloat16(max(max(color_vector_clip.x, color_vector_clip.y), color_vector_clip.z));
|
||||
|
||||
if (max_abs_unit > 1.0) {
|
||||
return FfxFloat16x3(aabb_center + color_vector / max_abs_unit); // clip towards color vector
|
||||
} else {
|
||||
return FfxFloat16x3(prev_sample); // point is inside aabb
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef FFX_DNSR_REFLECTIONS_ESTIMATES_LOCAL_NEIGHBORHOOD
|
||||
|
||||
# ifndef FFX_DNSR_REFLECTIONS_LOCAL_NEIGHBORHOOD_RADIUS
|
||||
# define FFX_DNSR_REFLECTIONS_LOCAL_NEIGHBORHOOD_RADIUS 4
|
||||
# endif
|
||||
|
||||
FfxFloat16 FFX_DNSR_Reflections_LocalNeighborhoodKernelWeight(FfxFloat16 i) {
|
||||
const FfxFloat16 radius = FfxFloat16(FFX_DNSR_REFLECTIONS_LOCAL_NEIGHBORHOOD_RADIUS + 1.0f);
|
||||
return FfxFloat16(exp(-FFX_DNSR_REFLECTIONS_GAUSSIAN_K * (i * i) / (radius * radius)));
|
||||
}
|
||||
|
||||
#endif // FFX_DNSR_REFLECTIONS_ESTIMATES_LOCAL_NEIGHBORHOOD
|
||||
|
||||
#else // FFX_HALF
|
||||
|
||||
FfxFloat32 FFX_DNSR_Reflections_Luminance(FfxFloat32x3 color)
|
||||
{
|
||||
return max(FfxFloat32(dot(color, FfxFloat32x3(0.299f, 0.587f, 0.114f))), FfxFloat32(0.001));
|
||||
}
|
||||
|
||||
FfxFloat32 FFX_DNSR_Reflections_ComputeTemporalVariance(FfxFloat32x3 history_radiance, FfxFloat32x3 radiance) {
|
||||
FfxFloat32 history_luminance = FFX_DNSR_Reflections_Luminance(history_radiance);
|
||||
FfxFloat32 luminance = FFX_DNSR_Reflections_Luminance(radiance);
|
||||
FfxFloat32 diff = abs(history_luminance - luminance) / max(max(history_luminance, luminance), FfxFloat32(0.5f));
|
||||
return diff * diff;
|
||||
}
|
||||
|
||||
FfxUInt32 FFX_DNSR_Reflections_PackFloat16(FfxFloat32x2 v)
|
||||
{
|
||||
#if defined(FFX_GLSL)
|
||||
return ffxPackHalf2x16(v);
|
||||
#elif defined(FFX_HLSL)
|
||||
FfxUInt32x2 p = ffxF32ToF16(v);
|
||||
return p.x | (p.y << 16);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
FfxFloat32x2 FFX_DNSR_Reflections_UnpackFloat16(FfxUInt32 a)
|
||||
{
|
||||
#if defined(FFX_GLSL)
|
||||
return unpackHalf2x16(a);
|
||||
#elif defined(FFX_HLSL)
|
||||
FfxFloat32x2 tmp = f16tof32(FfxUInt32x2(a & 0xFFFF, a >> 16));
|
||||
return tmp;
|
||||
#endif
|
||||
|
||||
return FfxFloat32x2(0.0f, 0.0f);
|
||||
}
|
||||
|
||||
FfxUInt32x2 FFX_DNSR_Reflections_PackFloat16_4(FfxFloat32x4 v) { return FfxUInt32x2(FFX_DNSR_Reflections_PackFloat16(v.xy), FFX_DNSR_Reflections_PackFloat16(v.zw)); }
|
||||
|
||||
FfxFloat32x4 FFX_DNSR_Reflections_UnpackFloat16_4(FfxUInt32x2 a) { return FfxFloat32x4(FFX_DNSR_Reflections_UnpackFloat16(a.x), FFX_DNSR_Reflections_UnpackFloat16(a.y)); }
|
||||
|
||||
// From "Temporal Reprojection Anti-Aliasing"
|
||||
// https://github.com/playdeadgames/temporal
|
||||
/**********************************************************************
|
||||
Copyright (c) [2015] [Playdead]
|
||||
|
||||
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 FFX_DNSR_Reflections_ClipAABB(FfxFloat32x3 aabb_min, FfxFloat32x3 aabb_max, FfxFloat32x3 prev_sample) {
|
||||
// Main idea behind clipping - it prevents clustering when neighbor color space
|
||||
// is distant from history sample
|
||||
|
||||
// Here we find intersection between color vector and aabb color box
|
||||
|
||||
// Note: only clips towards aabb center
|
||||
FfxFloat32x3 aabb_center = 0.5 * (aabb_max + aabb_min);
|
||||
FfxFloat32x3 extent_clip = 0.5 * (aabb_max - aabb_min) + 0.001;
|
||||
|
||||
// Find color vector
|
||||
FfxFloat32x3 color_vector = prev_sample - aabb_center;
|
||||
// Transform into clip space
|
||||
FfxFloat32x3 color_vector_clip = color_vector / extent_clip;
|
||||
// Find max absolute component
|
||||
color_vector_clip = abs(color_vector_clip);
|
||||
FfxFloat32 max_abs_unit = FfxFloat32(max(max(color_vector_clip.x, color_vector_clip.y), color_vector_clip.z));
|
||||
|
||||
if (max_abs_unit > 1.0) {
|
||||
return FfxFloat32x3(aabb_center + color_vector / max_abs_unit); // clip towards color vector
|
||||
} else {
|
||||
return FfxFloat32x3(prev_sample); // point is inside aabb
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef FFX_DNSR_REFLECTIONS_ESTIMATES_LOCAL_NEIGHBORHOOD
|
||||
|
||||
# ifndef FFX_DNSR_REFLECTIONS_LOCAL_NEIGHBORHOOD_RADIUS
|
||||
# define FFX_DNSR_REFLECTIONS_LOCAL_NEIGHBORHOOD_RADIUS 4
|
||||
# endif
|
||||
|
||||
FfxFloat32 FFX_DNSR_Reflections_LocalNeighborhoodKernelWeight(FfxFloat32 i) {
|
||||
const FfxFloat32 radius = FFX_DNSR_REFLECTIONS_LOCAL_NEIGHBORHOOD_RADIUS + 1.0;
|
||||
return exp(-FFX_DNSR_REFLECTIONS_GAUSSIAN_K * (i * i) / (radius * radius));
|
||||
}
|
||||
|
||||
#endif // FFX_DNSR_REFLECTIONS_ESTIMATES_LOCAL_NEIGHBORHOOD
|
||||
|
||||
#endif // FFX_HALF
|
||||
|
||||
#endif // FFX_DNSR_REFLECTIONS_COMMON
|
||||
41
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/denoiser/ffx_denoiser_reflections_config.h
vendored
Normal file
41
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/denoiser/ffx_denoiser_reflections_config.h
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
// 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_DNSR_REFLECTIONS_CONFIG
|
||||
#define FFX_DNSR_REFLECTIONS_CONFIG
|
||||
|
||||
#define FFX_DNSR_REFLECTIONS_GAUSSIAN_K 3.0
|
||||
#define FFX_DNSR_REFLECTIONS_RADIANCE_WEIGHT_BIAS 0.6
|
||||
#define FFX_DNSR_REFLECTIONS_RADIANCE_WEIGHT_VARIANCE_K 0.1
|
||||
#define FFX_DNSR_REFLECTIONS_AVG_RADIANCE_LUMINANCE_WEIGHT 0.3
|
||||
#define FFX_DNSR_REFLECTIONS_PREFILTER_VARIANCE_WEIGHT 4.4
|
||||
#define FFX_DNSR_REFLECTIONS_REPROJECT_SURFACE_DISCARD_VARIANCE_WEIGHT 1.5
|
||||
#define FFX_DNSR_REFLECTIONS_PREFILTER_VARIANCE_BIAS 0.1
|
||||
#define FFX_DNSR_REFLECTIONS_PREFILTER_NORMAL_SIGMA 512.0
|
||||
#define FFX_DNSR_REFLECTIONS_PREFILTER_DEPTH_SIGMA 4.0
|
||||
#define FFX_DNSR_REFLECTIONS_DISOCCLUSION_NORMAL_WEIGHT 1.4
|
||||
#define FFX_DNSR_REFLECTIONS_DISOCCLUSION_DEPTH_WEIGHT 1.0
|
||||
#define FFX_DNSR_REFLECTIONS_DISOCCLUSION_THRESHOLD 0.9
|
||||
#define FFX_DNSR_REFLECTIONS_REPROJECTION_NORMAL_SIMILARITY_THRESHOLD 0.9999
|
||||
#define FFX_DNSR_REFLECTIONS_SAMPLES_FOR_ROUGHNESS(r) (1.0 - exp(-r * 100.0))
|
||||
|
||||
#endif // FFX_DNSR_REFLECTIONS_CONFIG
|
||||
340
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/denoiser/ffx_denoiser_reflections_prefilter.h
vendored
Normal file
340
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/denoiser/ffx_denoiser_reflections_prefilter.h
vendored
Normal file
@@ -0,0 +1,340 @@
|
||||
// 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_DNSR_REFLECTIONS_PREFILTER
|
||||
#define FFX_DNSR_REFLECTIONS_PREFILTER
|
||||
|
||||
#include "ffx_denoiser_reflections_common.h"
|
||||
|
||||
FFX_GROUPSHARED FfxUInt32 g_ffx_dnsr_shared_0[16][16];
|
||||
FFX_GROUPSHARED FfxUInt32 g_ffx_dnsr_shared_1[16][16];
|
||||
FFX_GROUPSHARED FfxUInt32 g_ffx_dnsr_shared_2[16][16];
|
||||
FFX_GROUPSHARED FfxUInt32 g_ffx_dnsr_shared_3[16][16];
|
||||
FFX_GROUPSHARED FfxFloat32 g_ffx_dnsr_shared_depth[16][16];
|
||||
|
||||
#if FFX_HALF
|
||||
|
||||
struct FFX_DNSR_Reflections_NeighborhoodSample {
|
||||
FfxFloat16x3 radiance;
|
||||
FfxFloat16 variance;
|
||||
FfxFloat16x3 normal;
|
||||
FfxFloat32 depth;
|
||||
};
|
||||
|
||||
FFX_DNSR_Reflections_NeighborhoodSample FFX_DNSR_Reflections_LoadFromGroupSharedMemory(FfxInt32x2 idx) {
|
||||
FfxUInt32x2 packed_radiance = FfxUInt32x2(g_ffx_dnsr_shared_0[idx.y][idx.x], g_ffx_dnsr_shared_1[idx.y][idx.x]);
|
||||
FfxFloat16x4 unpacked_radiance = FFX_DNSR_Reflections_UnpackFloat16_4(packed_radiance);
|
||||
FfxUInt32x2 packed_normal_variance = FfxUInt32x2(g_ffx_dnsr_shared_2[idx.y][idx.x], g_ffx_dnsr_shared_3[idx.y][idx.x]);
|
||||
FfxFloat16x4 unpacked_normal_variance = FFX_DNSR_Reflections_UnpackFloat16_4(packed_normal_variance);
|
||||
|
||||
FFX_DNSR_Reflections_NeighborhoodSample neighborSample;
|
||||
neighborSample.radiance = unpacked_radiance.xyz;
|
||||
neighborSample.normal = unpacked_normal_variance.xyz;
|
||||
neighborSample.variance = unpacked_normal_variance.w;
|
||||
neighborSample.depth = g_ffx_dnsr_shared_depth[idx.y][idx.x];
|
||||
return neighborSample;
|
||||
}
|
||||
|
||||
void FFX_DNSR_Reflections_StoreInGroupSharedMemory(FfxInt32x2 group_thread_id, FfxFloat16x3 radiance, FfxFloat16 variance, FfxFloat16x3 normal, FfxFloat32 depth) {
|
||||
g_ffx_dnsr_shared_0[group_thread_id.y][group_thread_id.x] = FFX_DNSR_Reflections_PackFloat16(radiance.xy);
|
||||
g_ffx_dnsr_shared_1[group_thread_id.y][group_thread_id.x] = FFX_DNSR_Reflections_PackFloat16(radiance.zz);
|
||||
g_ffx_dnsr_shared_2[group_thread_id.y][group_thread_id.x] = FFX_DNSR_Reflections_PackFloat16(normal.xy);
|
||||
g_ffx_dnsr_shared_3[group_thread_id.y][group_thread_id.x] = FFX_DNSR_Reflections_PackFloat16(FfxFloat16x2(normal.z, variance));
|
||||
g_ffx_dnsr_shared_depth[group_thread_id.y][group_thread_id.x] = depth;
|
||||
}
|
||||
|
||||
void FFX_DNSR_Reflections_LoadNeighborhood(
|
||||
FfxInt32x2 pixel_coordinate,
|
||||
FFX_PARAMETER_OUT FfxFloat16x3 radiance,
|
||||
FFX_PARAMETER_OUT FfxFloat16 variance,
|
||||
FFX_PARAMETER_OUT FfxFloat16x3 normal,
|
||||
FFX_PARAMETER_OUT FfxFloat32 depth,
|
||||
FfxInt32x2 screen_size) {
|
||||
|
||||
radiance = LoadRadianceH(FfxInt32x3(pixel_coordinate, 0));
|
||||
variance = LoadVarianceH(FfxInt32x3(pixel_coordinate, 0));
|
||||
|
||||
normal = FFX_DENOISER_LoadWorldSpaceNormalH(pixel_coordinate);
|
||||
|
||||
FfxFloat32x2 uv = (pixel_coordinate.xy + (0.5f).xx) / FfxFloat32x2(screen_size.xy);
|
||||
depth = FFX_DNSR_Reflections_GetLinearDepth(uv, FFX_DENOISER_LoadDepth(pixel_coordinate, 0));
|
||||
}
|
||||
|
||||
void FFX_DNSR_Reflections_InitializeGroupSharedMemory(FfxInt32x2 dispatch_thread_id, FfxInt32x2 group_thread_id, FfxInt32x2 screen_size) {
|
||||
// Load 16x16 region into shared memory using 4 8x8 blocks.
|
||||
FfxInt32x2 offset[4] = {FfxInt32x2(0, 0), FfxInt32x2(8, 0), FfxInt32x2(0, 8), FfxInt32x2(8, 8)};
|
||||
|
||||
// Intermediate storage registers to cache the result of all loads
|
||||
FfxFloat16x3 radiance[4];
|
||||
FfxFloat16 variance[4];
|
||||
FfxFloat16x3 normal[4];
|
||||
FfxFloat32 depth[4];
|
||||
|
||||
// Start in the upper left corner of the 16x16 region.
|
||||
dispatch_thread_id -= 4;
|
||||
|
||||
// First store all loads in registers
|
||||
for (FfxInt32 i = 0; i < 4; ++i) {
|
||||
FFX_DNSR_Reflections_LoadNeighborhood(dispatch_thread_id + offset[i], radiance[i], variance[i], normal[i], depth[i], screen_size);
|
||||
}
|
||||
|
||||
// Then move all registers to groupshared memory
|
||||
for (FfxInt32 j = 0; j < 4; ++j) {
|
||||
FFX_DNSR_Reflections_StoreInGroupSharedMemory(group_thread_id + offset[j], radiance[j], variance[j], normal[j], depth[j]); // X
|
||||
}
|
||||
}
|
||||
|
||||
FfxFloat16 FFX_DNSR_Reflections_GetEdgeStoppingNormalWeight(FfxFloat16x3 normal_p, FfxFloat16x3 normal_q) {
|
||||
return FfxFloat16(pow(max(dot(normal_p, normal_q), FfxFloat16(0.0f)), FFX_DNSR_REFLECTIONS_PREFILTER_NORMAL_SIGMA));
|
||||
}
|
||||
|
||||
FfxFloat16 FFX_DNSR_Reflections_GetEdgeStoppingDepthWeight(FfxFloat32 center_depth, FfxFloat32 neighbor_depth) {
|
||||
return FfxFloat16(exp(-abs(center_depth - neighbor_depth) * center_depth * FFX_DNSR_REFLECTIONS_PREFILTER_DEPTH_SIGMA));
|
||||
}
|
||||
|
||||
FfxFloat16 FFX_DNSR_Reflections_GetRadianceWeight(FfxFloat16x3 center_radiance, FfxFloat16x3 neighbor_radiance, FfxFloat16 variance) {
|
||||
return FfxFloat16(max(exp(-(FFX_DNSR_REFLECTIONS_RADIANCE_WEIGHT_BIAS + variance * FFX_DNSR_REFLECTIONS_RADIANCE_WEIGHT_VARIANCE_K)
|
||||
* length(center_radiance - neighbor_radiance.xyz))
|
||||
, 1.0e-2));
|
||||
}
|
||||
|
||||
void FFX_DNSR_Reflections_Resolve(FfxInt32x2 group_thread_id, FfxFloat16x3 avg_radiance, FFX_DNSR_Reflections_NeighborhoodSample center,
|
||||
out FfxFloat16x3 resolved_radiance, out FfxFloat16 resolved_variance) {
|
||||
// Initial weight is important to remove fireflies.
|
||||
// That removes quite a bit of energy but makes everything much more stable.
|
||||
FfxFloat16 accumulated_weight = FFX_DNSR_Reflections_GetRadianceWeight(avg_radiance, center.radiance.xyz, center.variance);
|
||||
FfxFloat16x3 accumulated_radiance = center.radiance.xyz * accumulated_weight;
|
||||
FfxFloat16 accumulated_variance = center.variance * accumulated_weight * accumulated_weight;
|
||||
// First 15 numbers of Halton(2,3) streteched to [-3,3]. Skipping the center, as we already have that in center_radiance and center_variance.
|
||||
const FfxUInt32 sample_count = 15;
|
||||
const FfxInt32x2 sample_offsets[] = {FfxInt32x2(0, 1), FfxInt32x2(-2, 1), FfxInt32x2(2, -3), FfxInt32x2(-3, 0), FfxInt32x2(1, 2), FfxInt32x2(-1, -2), FfxInt32x2(3, 0), FfxInt32x2(-3, 3),
|
||||
FfxInt32x2(0, -3), FfxInt32x2(-1, -1), FfxInt32x2(2, 1), FfxInt32x2(-2, -2), FfxInt32x2(1, 0), FfxInt32x2(0, 2), FfxInt32x2(3, -1)};
|
||||
FfxFloat16 variance_weight = FfxFloat16(max(FFX_DNSR_REFLECTIONS_PREFILTER_VARIANCE_BIAS,
|
||||
1.0 - exp(-(center.variance * FFX_DNSR_REFLECTIONS_PREFILTER_VARIANCE_WEIGHT))
|
||||
));
|
||||
for (FfxInt32 i = 0; i < sample_count; ++i) {
|
||||
FfxInt32x2 new_idx = group_thread_id + sample_offsets[i];
|
||||
FFX_DNSR_Reflections_NeighborhoodSample neighbor = FFX_DNSR_Reflections_LoadFromGroupSharedMemory(new_idx);
|
||||
|
||||
FfxFloat16 weight = FfxFloat16(1.0f);
|
||||
weight *= FFX_DNSR_Reflections_GetEdgeStoppingNormalWeight(center.normal, neighbor.normal);
|
||||
weight *= FFX_DNSR_Reflections_GetEdgeStoppingDepthWeight(center.depth, neighbor.depth);
|
||||
weight *= FFX_DNSR_Reflections_GetRadianceWeight(avg_radiance, neighbor.radiance.xyz, center.variance);
|
||||
weight *= variance_weight;
|
||||
|
||||
// Accumulate all contributions.
|
||||
accumulated_weight += weight;
|
||||
accumulated_radiance += weight * neighbor.radiance.xyz;
|
||||
accumulated_variance += weight * weight * neighbor.variance;
|
||||
}
|
||||
|
||||
accumulated_radiance /= accumulated_weight;
|
||||
accumulated_variance /= (accumulated_weight * accumulated_weight);
|
||||
resolved_radiance = accumulated_radiance;
|
||||
resolved_variance = accumulated_variance;
|
||||
}
|
||||
|
||||
void FFX_DNSR_Reflections_Prefilter(FfxInt32x2 dispatch_thread_id, FfxInt32x2 group_thread_id, FfxUInt32x2 screen_size) {
|
||||
FfxFloat16 center_roughness = FFX_DNSR_Reflections_LoadRoughness(dispatch_thread_id);
|
||||
FFX_DNSR_Reflections_InitializeGroupSharedMemory(dispatch_thread_id, group_thread_id, FfxInt32x2(screen_size));
|
||||
FFX_GROUP_MEMORY_BARRIER;
|
||||
|
||||
group_thread_id += 4; // Center threads in groupshared memory
|
||||
|
||||
FFX_DNSR_Reflections_NeighborhoodSample center = FFX_DNSR_Reflections_LoadFromGroupSharedMemory(group_thread_id);
|
||||
|
||||
FfxFloat16x3 resolved_radiance = center.radiance;
|
||||
FfxFloat16 resolved_variance = center.variance;
|
||||
|
||||
// Check if we have to denoise or if a simple copy is enough
|
||||
bool needs_denoiser = center.variance > 0.0 && FFX_DNSR_Reflections_IsGlossyReflection(center_roughness) && !FFX_DNSR_Reflections_IsMirrorReflection(center_roughness);
|
||||
if (needs_denoiser) {
|
||||
FfxFloat32x2 uv8 = (FfxFloat32x2(dispatch_thread_id.xy) + (0.5).xx) / FFX_DNSR_Reflections_RoundUp8(screen_size);
|
||||
FfxFloat16x3 avg_radiance = FFX_DNSR_Reflections_SampleAverageRadiance(uv8);
|
||||
FFX_DNSR_Reflections_Resolve(group_thread_id, avg_radiance, center, resolved_radiance, resolved_variance);
|
||||
}
|
||||
|
||||
FFX_DNSR_Reflections_StorePrefilteredReflections(dispatch_thread_id, resolved_radiance, resolved_variance);
|
||||
}
|
||||
|
||||
#else // FFX_HALF
|
||||
|
||||
struct FFX_DNSR_Reflections_NeighborhoodSample {
|
||||
FfxFloat32x3 radiance;
|
||||
FfxFloat32 variance;
|
||||
FfxFloat32x3 normal;
|
||||
FfxFloat32 depth;
|
||||
};
|
||||
|
||||
FFX_DNSR_Reflections_NeighborhoodSample FFX_DNSR_Reflections_LoadFromGroupSharedMemory(FfxInt32x2 idx) {
|
||||
FfxUInt32x2 packed_radiance = FfxUInt32x2(g_ffx_dnsr_shared_0[idx.y][idx.x], g_ffx_dnsr_shared_1[idx.y][idx.x]);
|
||||
FfxFloat32x4 unpacked_radiance = FFX_DNSR_Reflections_UnpackFloat16_4(packed_radiance);
|
||||
FfxUInt32x2 packed_normal_variance = FfxUInt32x2(g_ffx_dnsr_shared_2[idx.y][idx.x], g_ffx_dnsr_shared_3[idx.y][idx.x]);
|
||||
FfxFloat32x4 unpacked_normal_variance = FFX_DNSR_Reflections_UnpackFloat16_4(packed_normal_variance);
|
||||
|
||||
FFX_DNSR_Reflections_NeighborhoodSample neighborSample;
|
||||
neighborSample.radiance = unpacked_radiance.xyz;
|
||||
neighborSample.normal = unpacked_normal_variance.xyz;
|
||||
neighborSample.variance = unpacked_normal_variance.w;
|
||||
neighborSample.depth = g_ffx_dnsr_shared_depth[idx.y][idx.x];
|
||||
return neighborSample;
|
||||
}
|
||||
|
||||
void FFX_DNSR_Reflections_StoreInGroupSharedMemory(FfxInt32x2 group_thread_id, FfxFloat32x3 radiance, FfxFloat32 variance, FfxFloat32x3 normal, FfxFloat32 depth) {
|
||||
g_ffx_dnsr_shared_0[group_thread_id.y][group_thread_id.x] = FFX_DNSR_Reflections_PackFloat16(radiance.xy);
|
||||
g_ffx_dnsr_shared_1[group_thread_id.y][group_thread_id.x] = FFX_DNSR_Reflections_PackFloat16(radiance.zz);
|
||||
g_ffx_dnsr_shared_2[group_thread_id.y][group_thread_id.x] = FFX_DNSR_Reflections_PackFloat16(normal.xy);
|
||||
g_ffx_dnsr_shared_3[group_thread_id.y][group_thread_id.x] = FFX_DNSR_Reflections_PackFloat16(FfxFloat32x2(normal.z, variance));
|
||||
g_ffx_dnsr_shared_depth[group_thread_id.y][group_thread_id.x] = depth;
|
||||
}
|
||||
|
||||
void FFX_DNSR_Reflections_LoadNeighborhood(
|
||||
FfxInt32x2 pixel_coordinate,
|
||||
FFX_PARAMETER_OUT FfxFloat32x3 radiance,
|
||||
FFX_PARAMETER_OUT FfxFloat32 variance,
|
||||
FFX_PARAMETER_OUT FfxFloat32x3 normal,
|
||||
FFX_PARAMETER_OUT FfxFloat32 depth,
|
||||
FfxInt32x2 screen_size) {
|
||||
|
||||
radiance = LoadRadiance(FfxInt32x3(pixel_coordinate, 0));
|
||||
variance = LoadVariance(FfxInt32x3(pixel_coordinate, 0));
|
||||
|
||||
normal = FFX_DENOISER_LoadWorldSpaceNormal(pixel_coordinate);
|
||||
|
||||
FfxFloat32x2 uv = (pixel_coordinate.xy + (0.5f).xx) / FfxFloat32x2(screen_size.xy);
|
||||
depth = FFX_DNSR_Reflections_GetLinearDepth(uv, FFX_DENOISER_LoadDepth(pixel_coordinate, 0));
|
||||
}
|
||||
|
||||
void FFX_DNSR_Reflections_InitializeGroupSharedMemory(FfxInt32x2 dispatch_thread_id, FfxInt32x2 group_thread_id, FfxInt32x2 screen_size) {
|
||||
// Load 16x16 region into shared memory using 4 8x8 blocks.
|
||||
FfxInt32x2 offset[4] = {FfxInt32x2(0, 0), FfxInt32x2(8, 0), FfxInt32x2(0, 8), FfxInt32x2(8, 8)};
|
||||
|
||||
// Intermediate storage registers to cache the result of all loads
|
||||
FfxFloat32x3 radiance[4];
|
||||
FfxFloat32 variance[4];
|
||||
FfxFloat32x3 normal[4];
|
||||
FfxFloat32 depth[4];
|
||||
|
||||
// Start in the upper left corner of the 16x16 region.
|
||||
dispatch_thread_id -= 4;
|
||||
|
||||
// First store all loads in registers
|
||||
for (FfxInt32 i = 0; i < 4; ++i) {
|
||||
FFX_DNSR_Reflections_LoadNeighborhood(dispatch_thread_id + offset[i], radiance[i], variance[i], normal[i], depth[i], screen_size);
|
||||
}
|
||||
|
||||
// Then move all registers to groupshared memory
|
||||
for (FfxInt32 j = 0; j < 4; ++j) {
|
||||
FFX_DNSR_Reflections_StoreInGroupSharedMemory(group_thread_id + offset[j], radiance[j], variance[j], normal[j], depth[j]); // X
|
||||
}
|
||||
}
|
||||
|
||||
FfxFloat32 FFX_DNSR_Reflections_GetEdgeStoppingNormalWeight(FfxFloat32x3 normal_p, FfxFloat32x3 normal_q) {
|
||||
return FfxFloat32(pow(max(dot(normal_p, normal_q), FfxFloat32(0.0f)), FFX_DNSR_REFLECTIONS_PREFILTER_NORMAL_SIGMA));
|
||||
}
|
||||
|
||||
FfxFloat32 FFX_DNSR_Reflections_GetEdgeStoppingDepthWeight(FfxFloat32 center_depth, FfxFloat32 neighbor_depth) {
|
||||
return FfxFloat32(exp(-abs(center_depth - neighbor_depth) * center_depth * FFX_DNSR_REFLECTIONS_PREFILTER_DEPTH_SIGMA));
|
||||
}
|
||||
|
||||
FfxFloat32 FFX_DNSR_Reflections_GetRadianceWeight(FfxFloat32x3 center_radiance, FfxFloat32x3 neighbor_radiance, FfxFloat32 variance) {
|
||||
return FfxFloat32(max(exp(-(FFX_DNSR_REFLECTIONS_RADIANCE_WEIGHT_BIAS + variance * FFX_DNSR_REFLECTIONS_RADIANCE_WEIGHT_VARIANCE_K)
|
||||
* length(center_radiance - neighbor_radiance.xyz))
|
||||
, 1.0e-2));
|
||||
}
|
||||
|
||||
void FFX_DNSR_Reflections_Resolve(FfxInt32x2 group_thread_id, FfxFloat32x3 avg_radiance, FFX_DNSR_Reflections_NeighborhoodSample center,
|
||||
out FfxFloat32x3 resolved_radiance, out FfxFloat32 resolved_variance) {
|
||||
// Initial weight is important to remove fireflies.
|
||||
// That removes quite a bit of energy but makes everything much more stable.
|
||||
FfxFloat32 accumulated_weight = FFX_DNSR_Reflections_GetRadianceWeight(avg_radiance, center.radiance.xyz, center.variance);
|
||||
FfxFloat32x3 accumulated_radiance = center.radiance.xyz * accumulated_weight;
|
||||
FfxFloat32 accumulated_variance = center.variance * accumulated_weight * accumulated_weight;
|
||||
// First 15 numbers of Halton(2,3) streteched to [-3,3]. Skipping the center, as we already have that in center_radiance and center_variance.
|
||||
const FfxUInt32 sample_count = 15;
|
||||
const FfxInt32x2 sample_offsets[] = {FfxInt32x2(0, 1), FfxInt32x2(-2, 1), FfxInt32x2(2, -3), FfxInt32x2(-3, 0), FfxInt32x2(1, 2), FfxInt32x2(-1, -2), FfxInt32x2(3, 0), FfxInt32x2(-3, 3),
|
||||
FfxInt32x2(0, -3), FfxInt32x2(-1, -1), FfxInt32x2(2, 1), FfxInt32x2(-2, -2), FfxInt32x2(1, 0), FfxInt32x2(0, 2), FfxInt32x2(3, -1)};
|
||||
FfxFloat32 variance_weight = FfxFloat32(max(FFX_DNSR_REFLECTIONS_PREFILTER_VARIANCE_BIAS,
|
||||
1.0 - exp(-(center.variance * FFX_DNSR_REFLECTIONS_PREFILTER_VARIANCE_WEIGHT))
|
||||
));
|
||||
for (FfxInt32 i = 0; i < sample_count; ++i) {
|
||||
FfxInt32x2 new_idx = group_thread_id + sample_offsets[i];
|
||||
FFX_DNSR_Reflections_NeighborhoodSample neighbor = FFX_DNSR_Reflections_LoadFromGroupSharedMemory(new_idx);
|
||||
|
||||
FfxFloat32 weight = FfxFloat32(1.0f);
|
||||
weight *= FFX_DNSR_Reflections_GetEdgeStoppingNormalWeight(center.normal, neighbor.normal);
|
||||
weight *= FFX_DNSR_Reflections_GetEdgeStoppingDepthWeight(center.depth, neighbor.depth);
|
||||
weight *= FFX_DNSR_Reflections_GetRadianceWeight(avg_radiance, neighbor.radiance.xyz, center.variance);
|
||||
weight *= variance_weight;
|
||||
|
||||
// Accumulate all contributions.
|
||||
accumulated_weight += weight;
|
||||
accumulated_radiance += weight * neighbor.radiance.xyz;
|
||||
accumulated_variance += weight * weight * neighbor.variance;
|
||||
}
|
||||
|
||||
accumulated_radiance /= accumulated_weight;
|
||||
accumulated_variance /= (accumulated_weight * accumulated_weight);
|
||||
resolved_radiance = accumulated_radiance;
|
||||
resolved_variance = accumulated_variance;
|
||||
}
|
||||
|
||||
void FFX_DNSR_Reflections_Prefilter(FfxInt32x2 dispatch_thread_id, FfxInt32x2 group_thread_id, FfxUInt32x2 screen_size) {
|
||||
FfxFloat32 center_roughness = FFX_DNSR_Reflections_LoadRoughness(dispatch_thread_id);
|
||||
FFX_DNSR_Reflections_InitializeGroupSharedMemory(dispatch_thread_id, group_thread_id, FfxInt32x2(screen_size));
|
||||
FFX_GROUP_MEMORY_BARRIER;
|
||||
|
||||
group_thread_id += 4; // Center threads in groupshared memory
|
||||
|
||||
FFX_DNSR_Reflections_NeighborhoodSample center = FFX_DNSR_Reflections_LoadFromGroupSharedMemory(group_thread_id);
|
||||
|
||||
FfxFloat32x3 resolved_radiance = center.radiance;
|
||||
FfxFloat32 resolved_variance = center.variance;
|
||||
|
||||
// Check if we have to denoise or if a simple copy is enough
|
||||
bool needs_denoiser = center.variance > 0.0 && FFX_DNSR_Reflections_IsGlossyReflection(center_roughness) && !FFX_DNSR_Reflections_IsMirrorReflection(center_roughness);
|
||||
if (needs_denoiser) {
|
||||
FfxFloat32x2 uv8 = (FfxFloat32x2(dispatch_thread_id.xy) + (0.5).xx) / FFX_DNSR_Reflections_RoundUp8(screen_size);
|
||||
FfxFloat32x3 avg_radiance = FFX_DNSR_Reflections_SampleAverageRadiance(uv8);
|
||||
FFX_DNSR_Reflections_Resolve(group_thread_id, avg_radiance, center, resolved_radiance, resolved_variance);
|
||||
}
|
||||
|
||||
FFX_DNSR_Reflections_StorePrefilteredReflections(dispatch_thread_id, resolved_radiance, resolved_variance);
|
||||
}
|
||||
|
||||
#endif // FFX_HALF
|
||||
|
||||
void Prefilter(FfxUInt32 group_index, FfxUInt32 group_id, FfxInt32x2 group_thread_id) {
|
||||
FfxUInt32 packed_coords = GetDenoiserTile(group_id);
|
||||
FfxInt32x2 dispatch_thread_id = FfxInt32x2(packed_coords & 0xffffu, (packed_coords >> 16) & 0xffffu) + group_thread_id;
|
||||
FfxInt32x2 dispatch_group_id = dispatch_thread_id / 8;
|
||||
FfxInt32x2 remapped_group_thread_id = FfxInt32x2(ffxRemapForWaveReduction(group_index));
|
||||
FfxInt32x2 remapped_dispatch_thread_id = FfxInt32x2(dispatch_group_id * 8 + remapped_group_thread_id);
|
||||
|
||||
FFX_DNSR_Reflections_Prefilter(remapped_dispatch_thread_id, remapped_group_thread_id, RenderSize());
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void Prefilter(FfxUInt32 group_index, FfxUInt32 group_id, FfxInt32x2 group_thread_id) {}
|
||||
|
||||
#endif // FFX_DNSR_REFLECTIONS_PREFILTER
|
||||
722
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/denoiser/ffx_denoiser_reflections_reproject.h
vendored
Normal file
722
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/denoiser/ffx_denoiser_reflections_reproject.h
vendored
Normal file
@@ -0,0 +1,722 @@
|
||||
// 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_DNSR_REFLECTIONS_REPROJECT
|
||||
#define FFX_DNSR_REFLECTIONS_REPROJECT
|
||||
|
||||
#define FFX_DNSR_REFLECTIONS_ESTIMATES_LOCAL_NEIGHBORHOOD
|
||||
#include "ffx_denoiser_reflections_common.h"
|
||||
|
||||
FFX_GROUPSHARED FfxUInt32 g_ffx_dnsr_shared_0[16][16];
|
||||
FFX_GROUPSHARED FfxUInt32 g_ffx_dnsr_shared_1[16][16];
|
||||
|
||||
#if FFX_HALF
|
||||
|
||||
struct FFX_DNSR_Reflections_NeighborhoodSample {
|
||||
FfxFloat16x3 radiance;
|
||||
};
|
||||
|
||||
FFX_DNSR_Reflections_NeighborhoodSample FFX_DNSR_Reflections_LoadFromGroupSharedMemory(FfxInt32x2 idx) {
|
||||
FfxUInt32x2 packed_radiance = FfxUInt32x2(g_ffx_dnsr_shared_0[idx.y][idx.x], g_ffx_dnsr_shared_1[idx.y][idx.x]);
|
||||
FfxFloat16x4 unpacked_radiance = FFX_DNSR_Reflections_UnpackFloat16_4(packed_radiance);
|
||||
|
||||
FFX_DNSR_Reflections_NeighborhoodSample neighborSample;
|
||||
neighborSample.radiance = unpacked_radiance.xyz;
|
||||
return neighborSample;
|
||||
}
|
||||
|
||||
void FFX_DNSR_Reflections_StoreInGroupSharedMemory(FfxInt32x2 group_thread_id, FfxFloat16x3 radiance) {
|
||||
g_ffx_dnsr_shared_0[group_thread_id.y][group_thread_id.x] = FFX_DNSR_Reflections_PackFloat16(radiance.xy);
|
||||
g_ffx_dnsr_shared_1[group_thread_id.y][group_thread_id.x] = FFX_DNSR_Reflections_PackFloat16(radiance.zz);
|
||||
}
|
||||
|
||||
void FFX_DNSR_Reflections_StoreInGroupSharedMemory(FfxInt32x2 group_thread_id, FfxFloat16x4 radiance_variance) {
|
||||
g_ffx_dnsr_shared_0[group_thread_id.y][group_thread_id.x] = FFX_DNSR_Reflections_PackFloat16(radiance_variance.xy);
|
||||
g_ffx_dnsr_shared_1[group_thread_id.y][group_thread_id.x] = FFX_DNSR_Reflections_PackFloat16(radiance_variance.zw);
|
||||
}
|
||||
|
||||
void FFX_DNSR_Reflections_InitializeGroupSharedMemory(FfxInt32x2 dispatch_thread_id, FfxInt32x2 group_thread_id, FfxInt32x2 screen_size) {
|
||||
// Load 16x16 region into shared memory using 4 8x8 blocks.
|
||||
FfxInt32x2 offset[4] = {FfxInt32x2(0, 0), FfxInt32x2(8, 0), FfxInt32x2(0, 8), FfxInt32x2(8, 8)};
|
||||
|
||||
// Intermediate storage registers to cache the result of all loads
|
||||
FfxFloat16x3 radiance[4];
|
||||
|
||||
// Start in the upper left corner of the 16x16 region.
|
||||
dispatch_thread_id -= 4;
|
||||
|
||||
// First store all loads in registers
|
||||
for (FfxInt32 i = 0; i < 4; ++i) {
|
||||
radiance[i] = FFX_DNSR_Reflections_LoadRadiance(dispatch_thread_id + offset[i]);
|
||||
}
|
||||
|
||||
// Then move all registers to FFX_GROUPSHARED memory
|
||||
for (FfxInt32 j = 0; j < 4; ++j) {
|
||||
FFX_DNSR_Reflections_StoreInGroupSharedMemory(group_thread_id + offset[j], radiance[j]); // X
|
||||
}
|
||||
}
|
||||
|
||||
FfxFloat16x4 FFX_DNSR_Reflections_LoadFromGroupSharedMemoryRaw(FfxInt32x2 idx) {
|
||||
FfxUInt32x2 packed_radiance = FfxUInt32x2(g_ffx_dnsr_shared_0[idx.y][idx.x], g_ffx_dnsr_shared_1[idx.y][idx.x]);
|
||||
return FFX_DNSR_Reflections_UnpackFloat16_4(packed_radiance);
|
||||
}
|
||||
|
||||
FfxFloat16 FFX_DNSR_Reflections_GetLuminanceWeight(FfxFloat16x3 val) {
|
||||
FfxFloat16 luma = FFX_DNSR_Reflections_Luminance(val.xyz);
|
||||
FfxFloat16 weight = FfxFloat16(max(exp(-luma * FFX_DNSR_REFLECTIONS_AVG_RADIANCE_LUMINANCE_WEIGHT), 1.0e-2));
|
||||
return weight;
|
||||
}
|
||||
|
||||
FfxFloat32x2 FFX_DNSR_Reflections_GetSurfaceReprojection(FfxInt32x2 dispatch_thread_id, FfxFloat32x2 uv, FfxFloat32x2 motion_vector) {
|
||||
// Reflector position reprojection
|
||||
FfxFloat32x2 history_uv = uv + motion_vector;
|
||||
return history_uv;
|
||||
}
|
||||
|
||||
FfxFloat32x2 FFX_DNSR_Reflections_GetHitPositionReprojection(FfxInt32x2 dispatch_thread_id, FfxFloat32x2 uv, FfxFloat32 reflected_ray_length) {
|
||||
FfxFloat32 z = FFX_DNSR_Reflections_LoadDepth(dispatch_thread_id);
|
||||
FfxFloat32x3 view_space_ray = FFX_DNSR_Reflections_ScreenSpaceToViewSpace(FfxFloat32x3(uv, z));
|
||||
|
||||
// We start out with reconstructing the ray length in view space.
|
||||
// This includes the portion from the camera to the reflecting surface as well as the portion from the surface to the hit position.
|
||||
FfxFloat32 surface_depth = length(view_space_ray);
|
||||
FfxFloat32 ray_length = surface_depth + reflected_ray_length;
|
||||
|
||||
// We then perform a parallax correction by shooting a ray
|
||||
// of the same length "straight through" the reflecting surface
|
||||
// and reprojecting the tip of that ray to the previous frame.
|
||||
view_space_ray /= surface_depth; // == normalize(view_space_ray)
|
||||
view_space_ray *= ray_length;
|
||||
FfxFloat32x3 world_hit_position =
|
||||
FFX_DNSR_Reflections_ViewSpaceToWorldSpace(FfxFloat32x4(view_space_ray, 1)); // This is the "fake" hit position if we would follow the ray straight through the surface.
|
||||
FfxFloat32x3 prev_hit_position = FFX_DNSR_Reflections_WorldSpaceToScreenSpacePrevious(world_hit_position);
|
||||
FfxFloat32x2 history_uv = prev_hit_position.xy;
|
||||
return history_uv;
|
||||
}
|
||||
|
||||
FfxFloat16 FFX_DNSR_Reflections_GetDisocclusionFactor(FfxFloat16x3 normal, FfxFloat16x3 history_normal, FfxFloat32 linear_depth, FfxFloat32 history_linear_depth) {
|
||||
FfxFloat16 factor = FfxFloat16(1.0f //
|
||||
* exp(-abs(1.0f - max(FfxFloat16(0.0f), dot(normal, history_normal))) * FFX_DNSR_REFLECTIONS_DISOCCLUSION_NORMAL_WEIGHT) //
|
||||
* exp(-abs(history_linear_depth - linear_depth) / linear_depth * FFX_DNSR_REFLECTIONS_DISOCCLUSION_DEPTH_WEIGHT));
|
||||
return factor;
|
||||
}
|
||||
|
||||
struct FFX_DNSR_Reflections_Moments {
|
||||
FfxFloat16x3 mean;
|
||||
FfxFloat16x3 variance;
|
||||
};
|
||||
|
||||
FFX_DNSR_Reflections_Moments FFX_DNSR_Reflections_EstimateLocalNeighborhoodInGroup(FfxInt32x2 group_thread_id) {
|
||||
FFX_DNSR_Reflections_Moments estimate;
|
||||
estimate.mean = FfxFloat16x3(0.0f, 0.0f, 0.0f);
|
||||
estimate.variance = FfxFloat16x3(0.0f, 0.0f, 0.0f);
|
||||
FfxFloat16 accumulated_weight = FfxFloat16(0.0f);
|
||||
for (FfxInt32 j = -FFX_DNSR_REFLECTIONS_LOCAL_NEIGHBORHOOD_RADIUS; j <= FFX_DNSR_REFLECTIONS_LOCAL_NEIGHBORHOOD_RADIUS; ++j) {
|
||||
for (FfxInt32 i = -FFX_DNSR_REFLECTIONS_LOCAL_NEIGHBORHOOD_RADIUS; i <= FFX_DNSR_REFLECTIONS_LOCAL_NEIGHBORHOOD_RADIUS; ++i) {
|
||||
FfxInt32x2 new_idx = group_thread_id + FfxInt32x2(i, j);
|
||||
FfxFloat16x3 radiance = FFX_DNSR_Reflections_LoadFromGroupSharedMemory(new_idx).radiance;
|
||||
FfxFloat16 weight = FFX_DNSR_Reflections_LocalNeighborhoodKernelWeight(FfxFloat16(i)) * FFX_DNSR_Reflections_LocalNeighborhoodKernelWeight(FfxFloat16(j));
|
||||
accumulated_weight += weight;
|
||||
estimate.mean += radiance * weight;
|
||||
estimate.variance += radiance * radiance * weight;
|
||||
}
|
||||
}
|
||||
estimate.mean /= accumulated_weight;
|
||||
estimate.variance /= accumulated_weight;
|
||||
|
||||
estimate.variance = abs(estimate.variance - estimate.mean * estimate.mean);
|
||||
return estimate;
|
||||
}
|
||||
|
||||
FfxFloat32 dot2(FfxFloat32x3 a) { return dot(a, a); }
|
||||
|
||||
void FFX_DNSR_Reflections_PickReprojection(FfxInt32x2 dispatch_thread_id, //
|
||||
FfxInt32x2 group_thread_id, //
|
||||
FfxUInt32x2 screen_size, //
|
||||
FfxFloat16 roughness, //
|
||||
FfxFloat16 ray_length, //
|
||||
out FfxFloat16 disocclusion_factor, //
|
||||
out FfxFloat32x2 reprojection_uv, //
|
||||
out FfxFloat16x3 reprojection) {
|
||||
|
||||
FFX_DNSR_Reflections_Moments local_neighborhood = FFX_DNSR_Reflections_EstimateLocalNeighborhoodInGroup(group_thread_id);
|
||||
|
||||
FfxFloat32x2 uv = FfxFloat32x2(dispatch_thread_id.x + 0.5, dispatch_thread_id.y + 0.5) / screen_size;
|
||||
FfxFloat16x3 normal = FFX_DNSR_Reflections_LoadWorldSpaceNormal(dispatch_thread_id);
|
||||
FfxFloat16x3 history_normal;
|
||||
FfxFloat32 history_linear_depth;
|
||||
|
||||
{
|
||||
const FfxFloat32x2 motion_vector = FFX_DNSR_Reflections_LoadMotionVector(dispatch_thread_id);
|
||||
const FfxFloat32x2 surface_reprojection_uv = FFX_DNSR_Reflections_GetSurfaceReprojection(dispatch_thread_id, uv, motion_vector);
|
||||
const FfxFloat32x2 hit_reprojection_uv = FFX_DNSR_Reflections_GetHitPositionReprojection(dispatch_thread_id, uv, ray_length);
|
||||
const FfxFloat16x3 surface_normal = FFX_DNSR_Reflections_SampleWorldSpaceNormalHistory(surface_reprojection_uv);
|
||||
const FfxFloat16x3 hit_normal = FFX_DNSR_Reflections_SampleWorldSpaceNormalHistory(hit_reprojection_uv);
|
||||
const FfxFloat16x3 surface_history = FFX_DNSR_Reflections_SampleRadianceHistory(surface_reprojection_uv);
|
||||
const FfxFloat16x3 hit_history = FFX_DNSR_Reflections_SampleRadianceHistory(hit_reprojection_uv);
|
||||
const FfxFloat32 hit_normal_similarity = dot(normalize(FfxFloat32x3(hit_normal)), normalize(FfxFloat32x3(normal)));
|
||||
const FfxFloat32 surface_normal_similarity = dot(normalize(FfxFloat32x3(surface_normal)), normalize(FfxFloat32x3(normal)));
|
||||
const FfxFloat16 hit_roughness = FFX_DNSR_Reflections_SampleRoughnessHistory(hit_reprojection_uv);
|
||||
const FfxFloat16 surface_roughness = FFX_DNSR_Reflections_SampleRoughnessHistory(surface_reprojection_uv);
|
||||
|
||||
// Choose reprojection uv based on similarity to the local neighborhood.
|
||||
if (hit_normal_similarity > FFX_DNSR_REFLECTIONS_REPROJECTION_NORMAL_SIMILARITY_THRESHOLD // Candidate for mirror reflection parallax
|
||||
&& hit_normal_similarity + 1.0e-3 > surface_normal_similarity //
|
||||
&& abs(hit_roughness - roughness) < abs(surface_roughness - roughness) + 1.0e-3 //
|
||||
) {
|
||||
history_normal = hit_normal;
|
||||
FfxFloat32 hit_history_depth = FFX_DNSR_Reflections_SampleDepthHistory(hit_reprojection_uv);
|
||||
FfxFloat32 hit_history_linear_depth = FFX_DNSR_Reflections_GetLinearDepth(hit_reprojection_uv, hit_history_depth);
|
||||
history_linear_depth = hit_history_linear_depth;
|
||||
reprojection_uv = hit_reprojection_uv;
|
||||
reprojection = hit_history;
|
||||
} else {
|
||||
// Reject surface reprojection based on simple distance
|
||||
if (dot2(surface_history - local_neighborhood.mean) <
|
||||
FFX_DNSR_REFLECTIONS_REPROJECT_SURFACE_DISCARD_VARIANCE_WEIGHT * length(local_neighborhood.variance)) {
|
||||
history_normal = surface_normal;
|
||||
FfxFloat32 surface_history_depth = FFX_DNSR_Reflections_SampleDepthHistory(surface_reprojection_uv);
|
||||
FfxFloat32 surface_history_linear_depth = FFX_DNSR_Reflections_GetLinearDepth(surface_reprojection_uv, surface_history_depth);
|
||||
history_linear_depth = surface_history_linear_depth;
|
||||
reprojection_uv = surface_reprojection_uv;
|
||||
reprojection = surface_history;
|
||||
} else {
|
||||
disocclusion_factor = FfxFloat16(0.0f);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
FfxFloat32 depth = FFX_DNSR_Reflections_LoadDepth(dispatch_thread_id);
|
||||
FfxFloat32 linear_depth = FFX_DNSR_Reflections_GetLinearDepth(uv, depth);
|
||||
// Determine disocclusion factor based on history
|
||||
disocclusion_factor = FFX_DNSR_Reflections_GetDisocclusionFactor(normal, history_normal, linear_depth, history_linear_depth);
|
||||
|
||||
if (disocclusion_factor > FFX_DNSR_REFLECTIONS_DISOCCLUSION_THRESHOLD) // Early out, good enough
|
||||
return;
|
||||
|
||||
// Try to find the closest sample in the vicinity if we are not convinced of a disocclusion
|
||||
if (disocclusion_factor < FFX_DNSR_REFLECTIONS_DISOCCLUSION_THRESHOLD) {
|
||||
FfxFloat32x2 closest_uv = reprojection_uv;
|
||||
FfxFloat32x2 dudv = 1.0 / FfxFloat32x2(screen_size);
|
||||
const FfxInt32 search_radius = 1;
|
||||
for (FfxInt32 y = -search_radius; y <= search_radius; y++) {
|
||||
for (FfxInt32 x = -search_radius; x <= search_radius; x++) {
|
||||
FfxFloat32x2 uv = reprojection_uv + FfxFloat32x2(x, y) * dudv;
|
||||
FfxFloat16x3 history_normal = FFX_DNSR_Reflections_SampleWorldSpaceNormalHistory(uv);
|
||||
FfxFloat32 history_depth = FFX_DNSR_Reflections_SampleDepthHistory(uv);
|
||||
FfxFloat32 history_linear_depth = FFX_DNSR_Reflections_GetLinearDepth(uv, history_depth);
|
||||
FfxFloat16 weight = FFX_DNSR_Reflections_GetDisocclusionFactor(normal, history_normal, linear_depth, history_linear_depth);
|
||||
if (weight > disocclusion_factor) {
|
||||
disocclusion_factor = weight;
|
||||
closest_uv = uv;
|
||||
reprojection_uv = closest_uv;
|
||||
}
|
||||
}
|
||||
}
|
||||
reprojection = FFX_DNSR_Reflections_SampleRadianceHistory(reprojection_uv);
|
||||
}
|
||||
|
||||
// Rare slow path - triggered only on the edges.
|
||||
// Try to get rid of potential leaks at bilinear interpolation level.
|
||||
if (disocclusion_factor < FFX_DNSR_REFLECTIONS_DISOCCLUSION_THRESHOLD) {
|
||||
// If we've got a discarded history, try to construct a better sample out of 2x2 interpolation neighborhood
|
||||
// Helps quite a bit on the edges in movement
|
||||
FfxFloat32 uvx = ffxFract(FfxFloat32(screen_size.x) * reprojection_uv.x + 0.5);
|
||||
FfxFloat32 uvy = ffxFract(FfxFloat32(screen_size.y) * reprojection_uv.y + 0.5);
|
||||
FfxInt32x2 reproject_texel_coords = FfxInt32x2(screen_size * reprojection_uv - 0.5);
|
||||
FfxFloat16x3 reprojection00 = FFX_DNSR_Reflections_LoadRadianceHistory(reproject_texel_coords + FfxInt32x2(0, 0));
|
||||
FfxFloat16x3 reprojection10 = FFX_DNSR_Reflections_LoadRadianceHistory(reproject_texel_coords + FfxInt32x2(1, 0));
|
||||
FfxFloat16x3 reprojection01 = FFX_DNSR_Reflections_LoadRadianceHistory(reproject_texel_coords + FfxInt32x2(0, 1));
|
||||
FfxFloat16x3 reprojection11 = FFX_DNSR_Reflections_LoadRadianceHistory(reproject_texel_coords + FfxInt32x2(1, 1));
|
||||
FfxFloat16x3 normal00 = FFX_DNSR_Reflections_LoadWorldSpaceNormalHistory(reproject_texel_coords + FfxInt32x2(0, 0));
|
||||
FfxFloat16x3 normal10 = FFX_DNSR_Reflections_LoadWorldSpaceNormalHistory(reproject_texel_coords + FfxInt32x2(1, 0));
|
||||
FfxFloat16x3 normal01 = FFX_DNSR_Reflections_LoadWorldSpaceNormalHistory(reproject_texel_coords + FfxInt32x2(0, 1));
|
||||
FfxFloat16x3 normal11 = FFX_DNSR_Reflections_LoadWorldSpaceNormalHistory(reproject_texel_coords + FfxInt32x2(1, 1));
|
||||
FfxFloat32 depth00 = FFX_DNSR_Reflections_GetLinearDepth(reprojection_uv, FFX_DNSR_Reflections_LoadDepthHistory(reproject_texel_coords + FfxInt32x2(0, 0)));
|
||||
FfxFloat32 depth10 = FFX_DNSR_Reflections_GetLinearDepth(reprojection_uv, FFX_DNSR_Reflections_LoadDepthHistory(reproject_texel_coords + FfxInt32x2(1, 0)));
|
||||
FfxFloat32 depth01 = FFX_DNSR_Reflections_GetLinearDepth(reprojection_uv, FFX_DNSR_Reflections_LoadDepthHistory(reproject_texel_coords + FfxInt32x2(0, 1)));
|
||||
FfxFloat32 depth11 = FFX_DNSR_Reflections_GetLinearDepth(reprojection_uv, FFX_DNSR_Reflections_LoadDepthHistory(reproject_texel_coords + FfxInt32x2(1, 1)));
|
||||
FfxFloat16x4 w = FfxFloat16x4(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
// Initialize with occlusion weights
|
||||
w.x = FFX_DNSR_Reflections_GetDisocclusionFactor(normal, normal00, linear_depth, depth00) > FFX_DNSR_REFLECTIONS_DISOCCLUSION_THRESHOLD / 2.0f ? FfxFloat16(1.0f) : FfxFloat16(0.0f);
|
||||
w.y = FFX_DNSR_Reflections_GetDisocclusionFactor(normal, normal10, linear_depth, depth10) > FFX_DNSR_REFLECTIONS_DISOCCLUSION_THRESHOLD / 2.0f ? FfxFloat16(1.0f) : FfxFloat16(0.0f);
|
||||
w.z = FFX_DNSR_Reflections_GetDisocclusionFactor(normal, normal01, linear_depth, depth01) > FFX_DNSR_REFLECTIONS_DISOCCLUSION_THRESHOLD / 2.0f ? FfxFloat16(1.0f) : FfxFloat16(0.0f);
|
||||
w.w = FFX_DNSR_Reflections_GetDisocclusionFactor(normal, normal11, linear_depth, depth11) > FFX_DNSR_REFLECTIONS_DISOCCLUSION_THRESHOLD / 2.0f ? FfxFloat16(1.0f) : FfxFloat16(0.0f);
|
||||
// And then mix in bilinear weights
|
||||
w.x = FfxFloat16(w.x * (1.0 - uvx) * (1.0 - uvy));
|
||||
w.y = FfxFloat16(w.y * (uvx) * (1.0 - uvy));
|
||||
w.z = FfxFloat16(w.z * (1.0 - uvx) * (uvy));
|
||||
w.w = FfxFloat16(w.w * (uvx) * (uvy));
|
||||
FfxFloat16 ws = max(w.x + w.y + w.z + w.w, FfxFloat16(1.0e-3));
|
||||
// normalize
|
||||
w /= ws;
|
||||
|
||||
FfxFloat16x3 history_normal;
|
||||
FfxFloat32 history_linear_depth;
|
||||
reprojection = reprojection00 * w.x + reprojection10 * w.y + reprojection01 * w.z + reprojection11 * w.w;
|
||||
history_linear_depth = depth00 * w.x + depth10 * w.y + depth01 * w.z + depth11 * w.w;
|
||||
history_normal = normal00 * w.x + normal10 * w.y + normal01 * w.z + normal11 * w.w;
|
||||
disocclusion_factor = FFX_DNSR_Reflections_GetDisocclusionFactor(normal, history_normal, linear_depth, history_linear_depth);
|
||||
}
|
||||
disocclusion_factor = disocclusion_factor < FFX_DNSR_REFLECTIONS_DISOCCLUSION_THRESHOLD ? FfxFloat16(0.0f) : disocclusion_factor;
|
||||
}
|
||||
|
||||
void FFX_DNSR_Reflections_Reproject(FfxInt32x2 dispatch_thread_id, FfxInt32x2 group_thread_id, FfxUInt32x2 screen_size, FfxFloat32 temporal_stability_factor, FfxInt32 max_samples) {
|
||||
FFX_DNSR_Reflections_InitializeGroupSharedMemory(dispatch_thread_id, group_thread_id, FfxInt32x2(screen_size));
|
||||
FFX_GROUP_MEMORY_BARRIER;
|
||||
|
||||
group_thread_id += 4; // Center threads in FFX_GROUPSHARED memory
|
||||
|
||||
FfxFloat16 variance = FfxFloat16(1.0f);
|
||||
FfxFloat16 num_samples = FfxFloat16(0.0f);
|
||||
FfxFloat16 roughness = FFX_DNSR_Reflections_LoadRoughness(dispatch_thread_id);
|
||||
FfxFloat32x3 normal = FFX_DNSR_Reflections_LoadWorldSpaceNormal(dispatch_thread_id);
|
||||
FfxFloat16x3 radiance = FFX_DNSR_Reflections_LoadRadiance(dispatch_thread_id);
|
||||
const FfxFloat16 ray_length = FFX_DNSR_Reflections_LoadRayLength(dispatch_thread_id);
|
||||
|
||||
if (FFX_DNSR_Reflections_IsGlossyReflection(roughness)) {
|
||||
FfxFloat16 disocclusion_factor;
|
||||
FfxFloat32x2 reprojection_uv;
|
||||
FfxFloat16x3 reprojection;
|
||||
FFX_DNSR_Reflections_PickReprojection(/*in*/ dispatch_thread_id,
|
||||
/* in */ group_thread_id,
|
||||
/* in */ screen_size,
|
||||
/* in */ roughness,
|
||||
/* in */ ray_length,
|
||||
/* out */ disocclusion_factor,
|
||||
/* out */ reprojection_uv,
|
||||
/* out */ reprojection);
|
||||
if ( (reprojection_uv.x > 0.0f) && (reprojection_uv.y > 0.0f) && (reprojection_uv.x < 1.0f) && (reprojection_uv.y< 1.0f)) {
|
||||
FfxFloat16 prev_variance = FFX_DNSR_Reflections_SampleVarianceHistory(reprojection_uv);
|
||||
num_samples = FFX_DNSR_Reflections_SampleNumSamplesHistory(reprojection_uv) * disocclusion_factor;
|
||||
FfxFloat16 s_max_samples = FfxFloat16(max(8.0f, FfxFloat16(max_samples) * FFX_DNSR_REFLECTIONS_SAMPLES_FOR_ROUGHNESS(roughness)));
|
||||
num_samples = min(s_max_samples, num_samples + FfxFloat16(1.0f));
|
||||
FfxFloat16 new_variance = FFX_DNSR_Reflections_ComputeTemporalVariance(radiance.xyz, reprojection.xyz);
|
||||
if (disocclusion_factor < FFX_DNSR_REFLECTIONS_DISOCCLUSION_THRESHOLD) {
|
||||
FFX_DNSR_Reflections_StoreRadianceReprojected(dispatch_thread_id, FfxFloat16x3(0.0f, 0.0f, 0.0f));
|
||||
FFX_DNSR_Reflections_StoreVariance(dispatch_thread_id, FfxFloat16(1.0f));
|
||||
FFX_DNSR_Reflections_StoreNumSamples(dispatch_thread_id, FfxFloat16(1.0f));
|
||||
} else {
|
||||
FfxFloat16 variance_mix = ffxLerp(new_variance, prev_variance, FfxFloat16(1.0f / num_samples));
|
||||
FFX_DNSR_Reflections_StoreRadianceReprojected(dispatch_thread_id, reprojection);
|
||||
FFX_DNSR_Reflections_StoreVariance(dispatch_thread_id, variance_mix);
|
||||
FFX_DNSR_Reflections_StoreNumSamples(dispatch_thread_id, num_samples);
|
||||
// Mix in reprojection for radiance mip computation
|
||||
radiance = ffxLerp(radiance, reprojection, FfxFloat16(0.3f));
|
||||
}
|
||||
} else {
|
||||
FFX_DNSR_Reflections_StoreRadianceReprojected(dispatch_thread_id, FfxFloat16x3(0.0f, 0.0f, 0.0f));
|
||||
FFX_DNSR_Reflections_StoreVariance(dispatch_thread_id, FfxFloat16(1.0f));
|
||||
FFX_DNSR_Reflections_StoreNumSamples(dispatch_thread_id, FfxFloat16(1.0f));
|
||||
}
|
||||
}
|
||||
|
||||
// Downsample 8x8 -> 1 radiance using FFX_GROUPSHARED memory
|
||||
// Initialize FFX_GROUPSHARED array for downsampling
|
||||
FfxFloat16 weight = FFX_DNSR_Reflections_GetLuminanceWeight(radiance.xyz);
|
||||
radiance.xyz *= weight;
|
||||
if ( (dispatch_thread_id.x >= screen_size.x) || (dispatch_thread_id.y >= screen_size.y) || any(isinf(radiance)) || any(isnan(radiance)) || (weight > FfxFloat16(1.0e3))) {
|
||||
radiance = FfxFloat16x3(0.0f, 0.0f, 0.0f);
|
||||
weight = FfxFloat16(0.0f);
|
||||
}
|
||||
|
||||
group_thread_id -= 4; // Center threads in FFX_GROUPSHARED memory
|
||||
|
||||
FFX_DNSR_Reflections_StoreInGroupSharedMemory(group_thread_id, FfxFloat16x4(radiance.xyz, weight));
|
||||
FFX_GROUP_MEMORY_BARRIER;
|
||||
|
||||
for (FfxInt32 i = 2; i <= 8; i = i * 2) {
|
||||
FfxInt32 ox = group_thread_id.x * i;
|
||||
FfxInt32 oy = group_thread_id.y * i;
|
||||
FfxInt32 ix = group_thread_id.x * i + i / 2;
|
||||
FfxInt32 iy = group_thread_id.y * i + i / 2;
|
||||
if (ix < 8 && iy < 8) {
|
||||
FfxFloat16x4 rad_weight00 = FFX_DNSR_Reflections_LoadFromGroupSharedMemoryRaw(FfxInt32x2(ox, oy));
|
||||
FfxFloat16x4 rad_weight10 = FFX_DNSR_Reflections_LoadFromGroupSharedMemoryRaw(FfxInt32x2(ox, iy));
|
||||
FfxFloat16x4 rad_weight01 = FFX_DNSR_Reflections_LoadFromGroupSharedMemoryRaw(FfxInt32x2(ix, oy));
|
||||
FfxFloat16x4 rad_weight11 = FFX_DNSR_Reflections_LoadFromGroupSharedMemoryRaw(FfxInt32x2(ix, iy));
|
||||
FfxFloat16x4 sum = rad_weight00 + rad_weight01 + rad_weight10 + rad_weight11;
|
||||
FFX_DNSR_Reflections_StoreInGroupSharedMemory(FfxInt32x2(ox, oy), sum);
|
||||
}
|
||||
FFX_GROUP_MEMORY_BARRIER;
|
||||
}
|
||||
|
||||
if ((group_thread_id.x == 0) && (group_thread_id.y == 0)) {
|
||||
FfxFloat16x4 sum = FFX_DNSR_Reflections_LoadFromGroupSharedMemoryRaw(FfxInt32x2(0, 0));
|
||||
FfxFloat16 weight_acc = max(sum.w, FfxFloat16(1.0e-3));
|
||||
FfxFloat32x3 radiance_avg = sum.xyz / weight_acc;
|
||||
FFX_DNSR_Reflections_StoreAverageRadiance(dispatch_thread_id.xy / 8, FfxFloat16x3(radiance_avg));
|
||||
}
|
||||
}
|
||||
|
||||
#else // #if FFX_HALF
|
||||
|
||||
struct FFX_DNSR_Reflections_NeighborhoodSample {
|
||||
FfxFloat32x3 radiance;
|
||||
};
|
||||
|
||||
FFX_DNSR_Reflections_NeighborhoodSample FFX_DNSR_Reflections_LoadFromGroupSharedMemory(FfxInt32x2 idx) {
|
||||
FfxUInt32x2 packed_radiance = FfxUInt32x2(g_ffx_dnsr_shared_0[idx.y][idx.x], g_ffx_dnsr_shared_1[idx.y][idx.x]);
|
||||
FfxFloat32x4 unpacked_radiance = FFX_DNSR_Reflections_UnpackFloat16_4(packed_radiance);
|
||||
|
||||
FFX_DNSR_Reflections_NeighborhoodSample neighborSample;
|
||||
neighborSample.radiance = unpacked_radiance.xyz;
|
||||
return neighborSample;
|
||||
}
|
||||
|
||||
void FFX_DNSR_Reflections_StoreInGroupSharedMemory(FfxInt32x2 group_thread_id, FfxFloat32x3 radiance) {
|
||||
g_ffx_dnsr_shared_0[group_thread_id.y][group_thread_id.x] = FFX_DNSR_Reflections_PackFloat16(radiance.xy);
|
||||
g_ffx_dnsr_shared_1[group_thread_id.y][group_thread_id.x] = FFX_DNSR_Reflections_PackFloat16(radiance.zz);
|
||||
}
|
||||
|
||||
void FFX_DNSR_Reflections_StoreInGroupSharedMemory(FfxInt32x2 group_thread_id, FfxFloat32x4 radiance_variance) {
|
||||
g_ffx_dnsr_shared_0[group_thread_id.y][group_thread_id.x] = FFX_DNSR_Reflections_PackFloat16(radiance_variance.xy);
|
||||
g_ffx_dnsr_shared_1[group_thread_id.y][group_thread_id.x] = FFX_DNSR_Reflections_PackFloat16(radiance_variance.zw);
|
||||
}
|
||||
|
||||
void FFX_DNSR_Reflections_InitializeGroupSharedMemory(FfxInt32x2 dispatch_thread_id, FfxInt32x2 group_thread_id, FfxInt32x2 screen_size) {
|
||||
// Load 16x16 region into shared memory using 4 8x8 blocks.
|
||||
FfxInt32x2 offset[4] = {FfxInt32x2(0, 0), FfxInt32x2(8, 0), FfxInt32x2(0, 8), FfxInt32x2(8, 8)};
|
||||
|
||||
// Intermediate storage registers to cache the result of all loads
|
||||
FfxFloat32x3 radiance[4];
|
||||
|
||||
// Start in the upper left corner of the 16x16 region.
|
||||
dispatch_thread_id -= 4;
|
||||
|
||||
// First store all loads in registers
|
||||
for (FfxInt32 i = 0; i < 4; ++i) {
|
||||
radiance[i] = FFX_DNSR_Reflections_LoadRadiance(dispatch_thread_id + offset[i]);
|
||||
}
|
||||
|
||||
// Then move all registers to FFX_GROUPSHARED memory
|
||||
for (FfxInt32 j = 0; j < 4; ++j) {
|
||||
FFX_DNSR_Reflections_StoreInGroupSharedMemory(group_thread_id + offset[j], radiance[j]); // X
|
||||
}
|
||||
}
|
||||
|
||||
FfxFloat32x4 FFX_DNSR_Reflections_LoadFromGroupSharedMemoryRaw(FfxInt32x2 idx) {
|
||||
FfxUInt32x2 packed_radiance = FfxUInt32x2(g_ffx_dnsr_shared_0[idx.y][idx.x], g_ffx_dnsr_shared_1[idx.y][idx.x]);
|
||||
return FFX_DNSR_Reflections_UnpackFloat16_4(packed_radiance);
|
||||
}
|
||||
|
||||
FfxFloat32 FFX_DNSR_Reflections_GetLuminanceWeight(FfxFloat32x3 val) {
|
||||
FfxFloat32 luma = FFX_DNSR_Reflections_Luminance(val.xyz);
|
||||
FfxFloat32 weight = FfxFloat32(max(exp(-luma * FFX_DNSR_REFLECTIONS_AVG_RADIANCE_LUMINANCE_WEIGHT), 1.0e-2));
|
||||
return weight;
|
||||
}
|
||||
|
||||
FfxFloat32x2 FFX_DNSR_Reflections_GetSurfaceReprojection(FfxInt32x2 dispatch_thread_id, FfxFloat32x2 uv, FfxFloat32x2 motion_vector) {
|
||||
// Reflector position reprojection
|
||||
FfxFloat32x2 history_uv = uv + motion_vector;
|
||||
return history_uv;
|
||||
}
|
||||
|
||||
FfxFloat32x2 FFX_DNSR_Reflections_GetHitPositionReprojection(FfxInt32x2 dispatch_thread_id, FfxFloat32x2 uv, FfxFloat32 reflected_ray_length) {
|
||||
FfxFloat32 z = FFX_DNSR_Reflections_LoadDepth(dispatch_thread_id);
|
||||
FfxFloat32x3 view_space_ray = FFX_DNSR_Reflections_ScreenSpaceToViewSpace(FfxFloat32x3(uv, z));
|
||||
|
||||
// We start out with reconstructing the ray length in view space.
|
||||
// This includes the portion from the camera to the reflecting surface as well as the portion from the surface to the hit position.
|
||||
FfxFloat32 surface_depth = length(view_space_ray);
|
||||
FfxFloat32 ray_length = surface_depth + reflected_ray_length;
|
||||
|
||||
// We then perform a parallax correction by shooting a ray
|
||||
// of the same length "straight through" the reflecting surface
|
||||
// and reprojecting the tip of that ray to the previous frame.
|
||||
view_space_ray /= surface_depth; // == normalize(view_space_ray)
|
||||
view_space_ray *= ray_length;
|
||||
FfxFloat32x3 world_hit_position =
|
||||
FFX_DNSR_Reflections_ViewSpaceToWorldSpace(FfxFloat32x4(view_space_ray, 1)); // This is the "fake" hit position if we would follow the ray straight through the surface.
|
||||
FfxFloat32x3 prev_hit_position = FFX_DNSR_Reflections_WorldSpaceToScreenSpacePrevious(world_hit_position);
|
||||
FfxFloat32x2 history_uv = prev_hit_position.xy;
|
||||
return history_uv;
|
||||
}
|
||||
|
||||
FfxFloat32 FFX_DNSR_Reflections_GetDisocclusionFactor(FfxFloat32x3 normal, FfxFloat32x3 history_normal, FfxFloat32 linear_depth, FfxFloat32 history_linear_depth) {
|
||||
FfxFloat32 factor = FfxFloat32(1.0f //
|
||||
* exp(-abs(1.0f - max(FfxFloat32(0.0f), dot(normal, history_normal))) * FFX_DNSR_REFLECTIONS_DISOCCLUSION_NORMAL_WEIGHT) //
|
||||
* exp(-abs(history_linear_depth - linear_depth) / linear_depth * FFX_DNSR_REFLECTIONS_DISOCCLUSION_DEPTH_WEIGHT));
|
||||
return factor;
|
||||
}
|
||||
|
||||
struct FFX_DNSR_Reflections_Moments {
|
||||
FfxFloat32x3 mean;
|
||||
FfxFloat32x3 variance;
|
||||
};
|
||||
|
||||
FFX_DNSR_Reflections_Moments FFX_DNSR_Reflections_EstimateLocalNeighborhoodInGroup(FfxInt32x2 group_thread_id) {
|
||||
FFX_DNSR_Reflections_Moments estimate;
|
||||
estimate.mean = FfxFloat32x3(0.0f, 0.0f, 0.0f);
|
||||
estimate.variance = FfxFloat32x3(0.0f, 0.0f, 0.0f);
|
||||
FfxFloat32 accumulated_weight = FfxFloat32(0.0f);
|
||||
for (FfxInt32 j = -FFX_DNSR_REFLECTIONS_LOCAL_NEIGHBORHOOD_RADIUS; j <= FFX_DNSR_REFLECTIONS_LOCAL_NEIGHBORHOOD_RADIUS; ++j) {
|
||||
for (FfxInt32 i = -FFX_DNSR_REFLECTIONS_LOCAL_NEIGHBORHOOD_RADIUS; i <= FFX_DNSR_REFLECTIONS_LOCAL_NEIGHBORHOOD_RADIUS; ++i) {
|
||||
FfxInt32x2 new_idx = group_thread_id + FfxInt32x2(i, j);
|
||||
FfxFloat32x3 radiance = FFX_DNSR_Reflections_LoadFromGroupSharedMemory(new_idx).radiance;
|
||||
FfxFloat32 weight = FFX_DNSR_Reflections_LocalNeighborhoodKernelWeight(FfxFloat32(i)) * FFX_DNSR_Reflections_LocalNeighborhoodKernelWeight(FfxFloat32(j));
|
||||
accumulated_weight += weight;
|
||||
estimate.mean += radiance * weight;
|
||||
estimate.variance += radiance * radiance * weight;
|
||||
}
|
||||
}
|
||||
estimate.mean /= accumulated_weight;
|
||||
estimate.variance /= accumulated_weight;
|
||||
|
||||
estimate.variance = abs(estimate.variance - estimate.mean * estimate.mean);
|
||||
return estimate;
|
||||
}
|
||||
|
||||
FfxFloat32 dot2(FfxFloat32x3 a) { return dot(a, a); }
|
||||
|
||||
void FFX_DNSR_Reflections_PickReprojection(FfxInt32x2 dispatch_thread_id, //
|
||||
FfxInt32x2 group_thread_id, //
|
||||
FfxUInt32x2 screen_size, //
|
||||
FfxFloat32 roughness, //
|
||||
FfxFloat32 ray_length, //
|
||||
out FfxFloat32 disocclusion_factor, //
|
||||
out FfxFloat32x2 reprojection_uv, //
|
||||
out FfxFloat32x3 reprojection) {
|
||||
|
||||
FFX_DNSR_Reflections_Moments local_neighborhood = FFX_DNSR_Reflections_EstimateLocalNeighborhoodInGroup(group_thread_id);
|
||||
|
||||
FfxFloat32x2 uv = FfxFloat32x2(dispatch_thread_id.x + 0.5, dispatch_thread_id.y + 0.5) / screen_size;
|
||||
FfxFloat32x3 normal = FFX_DNSR_Reflections_LoadWorldSpaceNormal(dispatch_thread_id);
|
||||
FfxFloat32x3 history_normal;
|
||||
FfxFloat32 history_linear_depth;
|
||||
|
||||
{
|
||||
const FfxFloat32x2 motion_vector = FFX_DNSR_Reflections_LoadMotionVector(dispatch_thread_id);
|
||||
const FfxFloat32x2 surface_reprojection_uv = FFX_DNSR_Reflections_GetSurfaceReprojection(dispatch_thread_id, uv, motion_vector);
|
||||
const FfxFloat32x2 hit_reprojection_uv = FFX_DNSR_Reflections_GetHitPositionReprojection(dispatch_thread_id, uv, ray_length);
|
||||
const FfxFloat32x3 surface_normal = FFX_DNSR_Reflections_SampleWorldSpaceNormalHistory(surface_reprojection_uv);
|
||||
const FfxFloat32x3 hit_normal = FFX_DNSR_Reflections_SampleWorldSpaceNormalHistory(hit_reprojection_uv);
|
||||
const FfxFloat32x3 surface_history = FFX_DNSR_Reflections_SampleRadianceHistory(surface_reprojection_uv);
|
||||
const FfxFloat32x3 hit_history = FFX_DNSR_Reflections_SampleRadianceHistory(hit_reprojection_uv);
|
||||
const FfxFloat32 hit_normal_similarity = dot(normalize(FfxFloat32x3(hit_normal)), normalize(FfxFloat32x3(normal)));
|
||||
const FfxFloat32 surface_normal_similarity = dot(normalize(FfxFloat32x3(surface_normal)), normalize(FfxFloat32x3(normal)));
|
||||
const FfxFloat32 hit_roughness = FFX_DNSR_Reflections_SampleRoughnessHistory(hit_reprojection_uv);
|
||||
const FfxFloat32 surface_roughness = FFX_DNSR_Reflections_SampleRoughnessHistory(surface_reprojection_uv);
|
||||
|
||||
// Choose reprojection uv based on similarity to the local neighborhood.
|
||||
if (hit_normal_similarity > FFX_DNSR_REFLECTIONS_REPROJECTION_NORMAL_SIMILARITY_THRESHOLD // Candidate for mirror reflection parallax
|
||||
&& hit_normal_similarity + 1.0e-3 > surface_normal_similarity //
|
||||
&& abs(hit_roughness - roughness) < abs(surface_roughness - roughness) + 1.0e-3 //
|
||||
) {
|
||||
history_normal = hit_normal;
|
||||
FfxFloat32 hit_history_depth = FFX_DNSR_Reflections_SampleDepthHistory(hit_reprojection_uv);
|
||||
FfxFloat32 hit_history_linear_depth = FFX_DNSR_Reflections_GetLinearDepth(hit_reprojection_uv, hit_history_depth);
|
||||
history_linear_depth = hit_history_linear_depth;
|
||||
reprojection_uv = hit_reprojection_uv;
|
||||
reprojection = hit_history;
|
||||
} else {
|
||||
// Reject surface reprojection based on simple distance
|
||||
if (dot2(surface_history - local_neighborhood.mean) <
|
||||
FFX_DNSR_REFLECTIONS_REPROJECT_SURFACE_DISCARD_VARIANCE_WEIGHT * length(local_neighborhood.variance)) {
|
||||
history_normal = surface_normal;
|
||||
FfxFloat32 surface_history_depth = FFX_DNSR_Reflections_SampleDepthHistory(surface_reprojection_uv);
|
||||
FfxFloat32 surface_history_linear_depth = FFX_DNSR_Reflections_GetLinearDepth(surface_reprojection_uv, surface_history_depth);
|
||||
history_linear_depth = surface_history_linear_depth;
|
||||
reprojection_uv = surface_reprojection_uv;
|
||||
reprojection = surface_history;
|
||||
} else {
|
||||
disocclusion_factor = FfxFloat32(0.0f);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
FfxFloat32 depth = FFX_DNSR_Reflections_LoadDepth(dispatch_thread_id);
|
||||
FfxFloat32 linear_depth = FFX_DNSR_Reflections_GetLinearDepth(uv, depth);
|
||||
// Determine disocclusion factor based on history
|
||||
disocclusion_factor = FFX_DNSR_Reflections_GetDisocclusionFactor(normal, history_normal, linear_depth, history_linear_depth);
|
||||
|
||||
if (disocclusion_factor > FFX_DNSR_REFLECTIONS_DISOCCLUSION_THRESHOLD) // Early out, good enough
|
||||
return;
|
||||
|
||||
// Try to find the closest sample in the vicinity if we are not convinced of a disocclusion
|
||||
if (disocclusion_factor < FFX_DNSR_REFLECTIONS_DISOCCLUSION_THRESHOLD) {
|
||||
FfxFloat32x2 closest_uv = reprojection_uv;
|
||||
FfxFloat32x2 dudv = 1.0 / FfxFloat32x2(screen_size);
|
||||
const FfxInt32 search_radius = 1;
|
||||
for (FfxInt32 y = -search_radius; y <= search_radius; y++) {
|
||||
for (FfxInt32 x = -search_radius; x <= search_radius; x++) {
|
||||
FfxFloat32x2 uv = reprojection_uv + FfxFloat32x2(x, y) * dudv;
|
||||
FfxFloat32x3 history_normal = FFX_DNSR_Reflections_SampleWorldSpaceNormalHistory(uv);
|
||||
FfxFloat32 history_depth = FFX_DNSR_Reflections_SampleDepthHistory(uv);
|
||||
FfxFloat32 history_linear_depth = FFX_DNSR_Reflections_GetLinearDepth(uv, history_depth);
|
||||
FfxFloat32 weight = FFX_DNSR_Reflections_GetDisocclusionFactor(normal, history_normal, linear_depth, history_linear_depth);
|
||||
if (weight > disocclusion_factor) {
|
||||
disocclusion_factor = weight;
|
||||
closest_uv = uv;
|
||||
reprojection_uv = closest_uv;
|
||||
}
|
||||
}
|
||||
}
|
||||
reprojection = FFX_DNSR_Reflections_SampleRadianceHistory(reprojection_uv);
|
||||
}
|
||||
|
||||
// Rare slow path - triggered only on the edges.
|
||||
// Try to get rid of potential leaks at bilinear interpolation level.
|
||||
if (disocclusion_factor < FFX_DNSR_REFLECTIONS_DISOCCLUSION_THRESHOLD) {
|
||||
// If we've got a discarded history, try to construct a better sample out of 2x2 interpolation neighborhood
|
||||
// Helps quite a bit on the edges in movement
|
||||
FfxFloat32 uvx = ffxFract(FfxFloat32(screen_size.x) * reprojection_uv.x + 0.5);
|
||||
FfxFloat32 uvy = ffxFract(FfxFloat32(screen_size.y) * reprojection_uv.y + 0.5);
|
||||
FfxInt32x2 reproject_texel_coords = FfxInt32x2(screen_size * reprojection_uv - 0.5);
|
||||
FfxFloat32x3 reprojection00 = FFX_DNSR_Reflections_LoadRadianceHistory(reproject_texel_coords + FfxInt32x2(0, 0));
|
||||
FfxFloat32x3 reprojection10 = FFX_DNSR_Reflections_LoadRadianceHistory(reproject_texel_coords + FfxInt32x2(1, 0));
|
||||
FfxFloat32x3 reprojection01 = FFX_DNSR_Reflections_LoadRadianceHistory(reproject_texel_coords + FfxInt32x2(0, 1));
|
||||
FfxFloat32x3 reprojection11 = FFX_DNSR_Reflections_LoadRadianceHistory(reproject_texel_coords + FfxInt32x2(1, 1));
|
||||
FfxFloat32x3 normal00 = FFX_DNSR_Reflections_LoadWorldSpaceNormalHistory(reproject_texel_coords + FfxInt32x2(0, 0));
|
||||
FfxFloat32x3 normal10 = FFX_DNSR_Reflections_LoadWorldSpaceNormalHistory(reproject_texel_coords + FfxInt32x2(1, 0));
|
||||
FfxFloat32x3 normal01 = FFX_DNSR_Reflections_LoadWorldSpaceNormalHistory(reproject_texel_coords + FfxInt32x2(0, 1));
|
||||
FfxFloat32x3 normal11 = FFX_DNSR_Reflections_LoadWorldSpaceNormalHistory(reproject_texel_coords + FfxInt32x2(1, 1));
|
||||
FfxFloat32 depth00 = FFX_DNSR_Reflections_GetLinearDepth(reprojection_uv, FFX_DNSR_Reflections_LoadDepthHistory(reproject_texel_coords + FfxInt32x2(0, 0)));
|
||||
FfxFloat32 depth10 = FFX_DNSR_Reflections_GetLinearDepth(reprojection_uv, FFX_DNSR_Reflections_LoadDepthHistory(reproject_texel_coords + FfxInt32x2(1, 0)));
|
||||
FfxFloat32 depth01 = FFX_DNSR_Reflections_GetLinearDepth(reprojection_uv, FFX_DNSR_Reflections_LoadDepthHistory(reproject_texel_coords + FfxInt32x2(0, 1)));
|
||||
FfxFloat32 depth11 = FFX_DNSR_Reflections_GetLinearDepth(reprojection_uv, FFX_DNSR_Reflections_LoadDepthHistory(reproject_texel_coords + FfxInt32x2(1, 1)));
|
||||
FfxFloat32x4 w = FfxFloat32x4(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
// Initialize with occlusion weights
|
||||
w.x = FFX_DNSR_Reflections_GetDisocclusionFactor(normal, normal00, linear_depth, depth00) > FFX_DNSR_REFLECTIONS_DISOCCLUSION_THRESHOLD / 2.0f ? FfxFloat32(1.0f) : FfxFloat32(0.0f);
|
||||
w.y = FFX_DNSR_Reflections_GetDisocclusionFactor(normal, normal10, linear_depth, depth10) > FFX_DNSR_REFLECTIONS_DISOCCLUSION_THRESHOLD / 2.0f ? FfxFloat32(1.0f) : FfxFloat32(0.0f);
|
||||
w.z = FFX_DNSR_Reflections_GetDisocclusionFactor(normal, normal01, linear_depth, depth01) > FFX_DNSR_REFLECTIONS_DISOCCLUSION_THRESHOLD / 2.0f ? FfxFloat32(1.0f) : FfxFloat32(0.0f);
|
||||
w.w = FFX_DNSR_Reflections_GetDisocclusionFactor(normal, normal11, linear_depth, depth11) > FFX_DNSR_REFLECTIONS_DISOCCLUSION_THRESHOLD / 2.0f ? FfxFloat32(1.0f) : FfxFloat32(0.0f);
|
||||
// And then mix in bilinear weights
|
||||
w.x = FfxFloat32(w.x * (1.0 - uvx) * (1.0 - uvy));
|
||||
w.y = FfxFloat32(w.y * (uvx) * (1.0 - uvy));
|
||||
w.z = FfxFloat32(w.z * (1.0 - uvx) * (uvy));
|
||||
w.w = FfxFloat32(w.w * (uvx) * (uvy));
|
||||
FfxFloat32 ws = max(w.x + w.y + w.z + w.w, FfxFloat32(1.0e-3));
|
||||
// normalize
|
||||
w /= ws;
|
||||
|
||||
FfxFloat32x3 history_normal;
|
||||
FfxFloat32 history_linear_depth;
|
||||
reprojection = reprojection00 * w.x + reprojection10 * w.y + reprojection01 * w.z + reprojection11 * w.w;
|
||||
history_linear_depth = depth00 * w.x + depth10 * w.y + depth01 * w.z + depth11 * w.w;
|
||||
history_normal = normal00 * w.x + normal10 * w.y + normal01 * w.z + normal11 * w.w;
|
||||
disocclusion_factor = FFX_DNSR_Reflections_GetDisocclusionFactor(normal, history_normal, linear_depth, history_linear_depth);
|
||||
}
|
||||
disocclusion_factor = disocclusion_factor < FFX_DNSR_REFLECTIONS_DISOCCLUSION_THRESHOLD ? FfxFloat32(0.0f) : disocclusion_factor;
|
||||
}
|
||||
|
||||
void FFX_DNSR_Reflections_Reproject(FfxInt32x2 dispatch_thread_id, FfxInt32x2 group_thread_id, FfxUInt32x2 screen_size, FfxFloat32 temporal_stability_factor, FfxInt32 max_samples) {
|
||||
FFX_DNSR_Reflections_InitializeGroupSharedMemory(dispatch_thread_id, group_thread_id, FfxInt32x2(screen_size));
|
||||
FFX_GROUP_MEMORY_BARRIER;
|
||||
|
||||
group_thread_id += 4; // Center threads in FFX_GROUPSHARED memory
|
||||
|
||||
FfxFloat32 variance = FfxFloat32(1.0f);
|
||||
FfxFloat32 num_samples = FfxFloat32(0.0f);
|
||||
FfxFloat32 roughness = FFX_DNSR_Reflections_LoadRoughness(dispatch_thread_id);
|
||||
FfxFloat32x3 normal = FFX_DNSR_Reflections_LoadWorldSpaceNormal(dispatch_thread_id);
|
||||
FfxFloat32x3 radiance = FFX_DNSR_Reflections_LoadRadiance(dispatch_thread_id);
|
||||
const FfxFloat32 ray_length = FFX_DNSR_Reflections_LoadRayLength(dispatch_thread_id);
|
||||
|
||||
if (FFX_DNSR_Reflections_IsGlossyReflection(roughness)) {
|
||||
FfxFloat32 disocclusion_factor;
|
||||
FfxFloat32x2 reprojection_uv;
|
||||
FfxFloat32x3 reprojection;
|
||||
FFX_DNSR_Reflections_PickReprojection(/*in*/ dispatch_thread_id,
|
||||
/* in */ group_thread_id,
|
||||
/* in */ screen_size,
|
||||
/* in */ roughness,
|
||||
/* in */ ray_length,
|
||||
/* out */ disocclusion_factor,
|
||||
/* out */ reprojection_uv,
|
||||
/* out */ reprojection);
|
||||
if ( (reprojection_uv.x > 0.0f) && (reprojection_uv.y > 0.0f) && (reprojection_uv.x < 1.0f) && (reprojection_uv.y< 1.0f)) {
|
||||
FfxFloat32 prev_variance = FFX_DNSR_Reflections_SampleVarianceHistory(reprojection_uv);
|
||||
num_samples = FFX_DNSR_Reflections_SampleNumSamplesHistory(reprojection_uv) * disocclusion_factor;
|
||||
FfxFloat32 s_max_samples = FfxFloat32(max(8.0f, max_samples * FFX_DNSR_REFLECTIONS_SAMPLES_FOR_ROUGHNESS(roughness)));
|
||||
num_samples = min(s_max_samples, num_samples + FfxFloat32(1.0f));
|
||||
FfxFloat32 new_variance = FFX_DNSR_Reflections_ComputeTemporalVariance(radiance.xyz, reprojection.xyz);
|
||||
if (disocclusion_factor < FFX_DNSR_REFLECTIONS_DISOCCLUSION_THRESHOLD) {
|
||||
FFX_DNSR_Reflections_StoreRadianceReprojected(dispatch_thread_id, FfxFloat32x3(0.0f, 0.0f, 0.0f));
|
||||
FFX_DNSR_Reflections_StoreVariance(dispatch_thread_id, FfxFloat32(1.0f));
|
||||
FFX_DNSR_Reflections_StoreNumSamples(dispatch_thread_id, FfxFloat32(1.0f));
|
||||
} else {
|
||||
FfxFloat32 variance_mix = ffxLerp(new_variance, prev_variance, FfxFloat32(1.0f / num_samples));
|
||||
FFX_DNSR_Reflections_StoreRadianceReprojected(dispatch_thread_id, reprojection);
|
||||
FFX_DNSR_Reflections_StoreVariance(dispatch_thread_id, variance_mix);
|
||||
FFX_DNSR_Reflections_StoreNumSamples(dispatch_thread_id, num_samples);
|
||||
// Mix in reprojection for radiance mip computation
|
||||
radiance = ffxLerp(radiance, reprojection, FfxFloat32(0.3f));
|
||||
}
|
||||
} else {
|
||||
FFX_DNSR_Reflections_StoreRadianceReprojected(dispatch_thread_id, FfxFloat32x3(0.0f, 0.0f, 0.0f));
|
||||
FFX_DNSR_Reflections_StoreVariance(dispatch_thread_id, FfxFloat32(1.0f));
|
||||
FFX_DNSR_Reflections_StoreNumSamples(dispatch_thread_id, FfxFloat32(1.0f));
|
||||
}
|
||||
}
|
||||
|
||||
// Downsample 8x8 -> 1 radiance using FFX_GROUPSHARED memory
|
||||
// Initialize FFX_GROUPSHARED array for downsampling
|
||||
FfxFloat32 weight = FFX_DNSR_Reflections_GetLuminanceWeight(radiance.xyz);
|
||||
radiance.xyz *= weight;
|
||||
if ( (dispatch_thread_id.x >= screen_size.x) || (dispatch_thread_id.y >= screen_size.y) || any(isinf(radiance)) || any(isnan(radiance)) || (weight > FfxFloat32(1.0e3))) {
|
||||
radiance = FfxFloat32x3(0.0f, 0.0f, 0.0f);
|
||||
weight = FfxFloat32(0.0f);
|
||||
}
|
||||
|
||||
group_thread_id -= 4; // Center threads in FFX_GROUPSHARED memory
|
||||
|
||||
FFX_DNSR_Reflections_StoreInGroupSharedMemory(group_thread_id, FfxFloat32x4(radiance.xyz, weight));
|
||||
FFX_GROUP_MEMORY_BARRIER;
|
||||
|
||||
for (FfxInt32 i = 2; i <= 8; i = i * 2) {
|
||||
FfxInt32 ox = group_thread_id.x * i;
|
||||
FfxInt32 oy = group_thread_id.y * i;
|
||||
FfxInt32 ix = group_thread_id.x * i + i / 2;
|
||||
FfxInt32 iy = group_thread_id.y * i + i / 2;
|
||||
if (ix < 8 && iy < 8) {
|
||||
FfxFloat32x4 rad_weight00 = FFX_DNSR_Reflections_LoadFromGroupSharedMemoryRaw(FfxInt32x2(ox, oy));
|
||||
FfxFloat32x4 rad_weight10 = FFX_DNSR_Reflections_LoadFromGroupSharedMemoryRaw(FfxInt32x2(ox, iy));
|
||||
FfxFloat32x4 rad_weight01 = FFX_DNSR_Reflections_LoadFromGroupSharedMemoryRaw(FfxInt32x2(ix, oy));
|
||||
FfxFloat32x4 rad_weight11 = FFX_DNSR_Reflections_LoadFromGroupSharedMemoryRaw(FfxInt32x2(ix, iy));
|
||||
FfxFloat32x4 sum = rad_weight00 + rad_weight01 + rad_weight10 + rad_weight11;
|
||||
FFX_DNSR_Reflections_StoreInGroupSharedMemory(FfxInt32x2(ox, oy), sum);
|
||||
}
|
||||
FFX_GROUP_MEMORY_BARRIER;
|
||||
}
|
||||
|
||||
if ((group_thread_id.x == 0) && (group_thread_id.y == 0)) {
|
||||
FfxFloat32x4 sum = FFX_DNSR_Reflections_LoadFromGroupSharedMemoryRaw(FfxInt32x2(0, 0));
|
||||
FfxFloat32 weight_acc = max(sum.w, FfxFloat32(1.0e-3));
|
||||
FfxFloat32x3 radiance_avg = sum.xyz / weight_acc;
|
||||
FFX_DNSR_Reflections_StoreAverageRadiance(dispatch_thread_id.xy / 8, FfxFloat32x3(radiance_avg));
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #if FFX_HALF
|
||||
|
||||
void Reproject(FfxUInt32 group_index, FfxUInt32 group_id, FfxUInt32x2 group_thread_id) {
|
||||
FfxUInt32 packed_coords = GetDenoiserTile(group_id);
|
||||
FfxInt32x2 dispatch_thread_id = FfxInt32x2(packed_coords & 0xffffu, (packed_coords >> 16) & 0xffffu) + FfxInt32x2(group_thread_id);
|
||||
FfxInt32x2 dispatch_group_id = dispatch_thread_id / 8;
|
||||
FfxInt32x2 remapped_group_thread_id = FfxInt32x2(ffxRemapForWaveReduction(group_index));
|
||||
FfxInt32x2 remapped_dispatch_thread_id = dispatch_group_id * 8 + remapped_group_thread_id;
|
||||
|
||||
FFX_DNSR_Reflections_Reproject(remapped_dispatch_thread_id, remapped_group_thread_id, RenderSize(), TemporalStabilityFactor(), 32);
|
||||
}
|
||||
|
||||
#endif // FFX_DNSR_REFLECTIONS_REPROJECT
|
||||
@@ -0,0 +1,298 @@
|
||||
// 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_DNSR_REFLECTIONS_RESOLVE_TEMPORAL
|
||||
#define FFX_DNSR_REFLECTIONS_RESOLVE_TEMPORAL
|
||||
|
||||
#define RADIANCE_THRESHOLD 0.0001
|
||||
|
||||
#define FFX_DNSR_REFLECTIONS_ESTIMATES_LOCAL_NEIGHBORHOOD
|
||||
#include "ffx_denoiser_reflections_common.h"
|
||||
|
||||
FFX_GROUPSHARED FfxUInt32 g_ffx_dnsr_shared_0[16][16];
|
||||
FFX_GROUPSHARED FfxUInt32 g_ffx_dnsr_shared_1[16][16];
|
||||
|
||||
#if FFX_HALF
|
||||
|
||||
struct FFX_DNSR_Reflections_NeighborhoodSample {
|
||||
FfxFloat16x3 radiance;
|
||||
};
|
||||
|
||||
FFX_DNSR_Reflections_NeighborhoodSample FFX_DNSR_Reflections_LoadFromGroupSharedMemory(FfxInt32x2 idx) {
|
||||
FfxUInt32x2 packed_radiance = FfxUInt32x2(g_ffx_dnsr_shared_0[idx.y][idx.x], g_ffx_dnsr_shared_1[idx.y][idx.x]);
|
||||
FfxFloat16x3 unpacked_radiance = FFX_DNSR_Reflections_UnpackFloat16_4(packed_radiance).xyz;
|
||||
|
||||
FFX_DNSR_Reflections_NeighborhoodSample neighborSample;
|
||||
neighborSample.radiance = unpacked_radiance;
|
||||
return neighborSample;
|
||||
}
|
||||
|
||||
struct FFX_DNSR_Reflections_Moments {
|
||||
FfxFloat16x3 mean;
|
||||
FfxFloat16x3 variance;
|
||||
};
|
||||
|
||||
FFX_DNSR_Reflections_Moments FFX_DNSR_Reflections_EstimateLocalNeighborhoodInGroup(FfxInt32x2 group_thread_id) {
|
||||
FFX_DNSR_Reflections_Moments estimate;
|
||||
estimate.mean = FfxFloat16x3(0.0f, 0.0f, 0.0f);
|
||||
estimate.variance = FfxFloat16x3(0.0f, 0.0f, 0.0f);
|
||||
FfxFloat16 accumulated_weight = FfxFloat16(0.0f);
|
||||
for (FfxInt32 j = -FFX_DNSR_REFLECTIONS_LOCAL_NEIGHBORHOOD_RADIUS; j <= FFX_DNSR_REFLECTIONS_LOCAL_NEIGHBORHOOD_RADIUS; ++j) {
|
||||
for (FfxInt32 i = -FFX_DNSR_REFLECTIONS_LOCAL_NEIGHBORHOOD_RADIUS; i <= FFX_DNSR_REFLECTIONS_LOCAL_NEIGHBORHOOD_RADIUS; ++i) {
|
||||
FfxInt32x2 new_idx = group_thread_id + FfxInt32x2(i, j);
|
||||
FfxFloat16x3 radiance = FFX_DNSR_Reflections_LoadFromGroupSharedMemory(new_idx).radiance;
|
||||
FfxFloat16 weight = FFX_DNSR_Reflections_LocalNeighborhoodKernelWeight(FfxFloat16(i)) * FFX_DNSR_Reflections_LocalNeighborhoodKernelWeight(FfxFloat16(j));
|
||||
accumulated_weight += weight;
|
||||
estimate.mean += radiance * weight;
|
||||
estimate.variance += radiance * radiance * weight;
|
||||
}
|
||||
}
|
||||
estimate.mean /= accumulated_weight;
|
||||
estimate.variance /= accumulated_weight;
|
||||
|
||||
estimate.variance = abs(estimate.variance - estimate.mean * estimate.mean);
|
||||
return estimate;
|
||||
}
|
||||
|
||||
void FFX_DNSR_Reflections_StoreInGroupSharedMemory(FfxInt32x2 group_thread_id, FfxFloat16x3 radiance) {
|
||||
g_ffx_dnsr_shared_0[group_thread_id.y][group_thread_id.x] = FFX_DNSR_Reflections_PackFloat16(radiance.xy);
|
||||
g_ffx_dnsr_shared_1[group_thread_id.y][group_thread_id.x] = FFX_DNSR_Reflections_PackFloat16(radiance.zz);
|
||||
}
|
||||
|
||||
void FFX_DNSR_Reflections_LoadNeighborhood(FfxInt32x2 pixel_coordinate, out FfxFloat16x3 radiance) { radiance = FFX_DNSR_Reflections_LoadRadiance(pixel_coordinate); }
|
||||
|
||||
void FFX_DNSR_Reflections_InitializeGroupSharedMemory(FfxInt32x2 dispatch_thread_id, FfxInt32x2 group_thread_id, FfxInt32x2 screen_size) {
|
||||
// Load 16x16 region into shared memory using 4 8x8 blocks.
|
||||
FfxInt32x2 offset[4] = {FfxInt32x2(0, 0), FfxInt32x2(8, 0), FfxInt32x2(0, 8), FfxInt32x2(8, 8)};
|
||||
|
||||
// Intermediate storage registers to cache the result of all loads
|
||||
FfxFloat16x3 radiance[4];
|
||||
|
||||
// Start in the upper left corner of the 16x16 region.
|
||||
dispatch_thread_id -= 4;
|
||||
|
||||
// First store all loads in registers
|
||||
for (FfxInt32 i = 0; i < 4; ++i) {
|
||||
FFX_DNSR_Reflections_LoadNeighborhood(dispatch_thread_id + offset[i], radiance[i]);
|
||||
}
|
||||
|
||||
// Then move all registers to FFX_GROUPSHARED memory
|
||||
for (FfxInt32 j = 0; j < 4; ++j) {
|
||||
FFX_DNSR_Reflections_StoreInGroupSharedMemory(group_thread_id + offset[j], radiance[j]);
|
||||
}
|
||||
}
|
||||
|
||||
void FFX_DNSR_Reflections_ResolveTemporal(FfxInt32x2 dispatch_thread_id, FfxInt32x2 group_thread_id, FfxUInt32x2 screen_size, FfxFloat32x2 inv_screen_size, FfxFloat32 history_clip_weight) {
|
||||
FFX_DNSR_Reflections_InitializeGroupSharedMemory(dispatch_thread_id, group_thread_id, FfxInt32x2(screen_size));
|
||||
FFX_GROUP_MEMORY_BARRIER;
|
||||
|
||||
group_thread_id += 4; // Center threads in FFX_GROUPSHARED memory
|
||||
|
||||
FfxFloat16x3 radiance = FFX_DNSR_Reflections_LoadFromGroupSharedMemory(group_thread_id).radiance;
|
||||
FfxFloat32 radianceSum = radiance.x + radiance.y + radiance.z;
|
||||
if (radianceSum < RADIANCE_THRESHOLD)
|
||||
{
|
||||
FFX_DNSR_Reflections_StoreTemporalAccumulation(dispatch_thread_id, FfxFloat16x3(0.0f, 0.0f, 0.0f), FfxFloat16(0.0f));
|
||||
return;
|
||||
}
|
||||
|
||||
FFX_DNSR_Reflections_NeighborhoodSample center = FFX_DNSR_Reflections_LoadFromGroupSharedMemory(group_thread_id);
|
||||
FfxFloat16x3 new_signal = center.radiance;
|
||||
FfxFloat16 roughness = FFX_DNSR_Reflections_LoadRoughness(dispatch_thread_id);
|
||||
FfxFloat16 new_variance = FFX_DNSR_Reflections_LoadVariance(dispatch_thread_id);
|
||||
|
||||
if (FFX_DNSR_Reflections_IsGlossyReflection(roughness)) {
|
||||
FfxFloat16 num_samples = FFX_DNSR_Reflections_LoadNumSamples(dispatch_thread_id);
|
||||
FfxFloat32x2 uv8 = (FfxFloat32x2(dispatch_thread_id.xy) + (0.5).xx) / FFX_DNSR_Reflections_RoundUp8(screen_size);
|
||||
FfxFloat16x3 avg_radiance = FFX_DNSR_Reflections_SampleAverageRadiance(uv8);
|
||||
|
||||
FfxFloat16x3 old_signal = FFX_DNSR_Reflections_LoadRadianceReprojected(dispatch_thread_id);
|
||||
FFX_DNSR_Reflections_Moments local_neighborhood = FFX_DNSR_Reflections_EstimateLocalNeighborhoodInGroup(group_thread_id);
|
||||
// Clip history based on the curren local statistics
|
||||
FfxFloat16x3 color_std = FfxFloat16x3((sqrt(local_neighborhood.variance.xyz) + length(local_neighborhood.mean.xyz - avg_radiance)) * history_clip_weight * 1.4f);
|
||||
local_neighborhood.mean.xyz = ffxLerp(local_neighborhood.mean.xyz, avg_radiance, FfxFloat16x3(0.2f, 0.2f, 0.2f));
|
||||
FfxFloat16x3 radiance_min = local_neighborhood.mean.xyz - color_std;
|
||||
FfxFloat16x3 radiance_max = local_neighborhood.mean.xyz + color_std;
|
||||
FfxFloat16x3 clipped_old_signal = FFX_DNSR_Reflections_ClipAABB(radiance_min, radiance_max, old_signal.xyz);
|
||||
FfxFloat16 accumulation_speed = FfxFloat16(1.0f) / max(num_samples, FfxFloat16(1.0f));
|
||||
FfxFloat16 weight = (FfxFloat16(1.0f) - accumulation_speed);
|
||||
// Blend with average for small sample count
|
||||
new_signal.xyz = ffxLerp(new_signal.xyz, avg_radiance, FfxFloat16(1.0f) / max(num_samples + FfxFloat16(1.0f), FfxFloat16(1.0f)));
|
||||
// Clip outliers
|
||||
{
|
||||
FfxFloat16x3 radiance_min = avg_radiance.xyz - color_std * FfxFloat16x3(1.0f, 1.0f, 1.0f);
|
||||
FfxFloat16x3 radiance_max = avg_radiance.xyz + color_std * FfxFloat16x3(1.0f, 1.0f, 1.0f);
|
||||
new_signal.xyz = FFX_DNSR_Reflections_ClipAABB(radiance_min, radiance_max, new_signal.xyz);
|
||||
}
|
||||
// Blend with history
|
||||
#ifdef FFX_GLSL
|
||||
new_signal = (FfxFloat16(1.0) - weight) * new_signal + weight * clipped_old_signal;
|
||||
#else
|
||||
new_signal = ffxLerp(new_signal, clipped_old_signal, weight);
|
||||
#endif
|
||||
new_variance = ffxLerp(FFX_DNSR_Reflections_ComputeTemporalVariance(new_signal.xyz, clipped_old_signal.xyz), new_variance, weight);
|
||||
if (any(isinf(new_signal)) || any(isnan(new_signal)) || isinf(new_variance) || isnan(new_variance)) {
|
||||
new_signal = FfxFloat16x3(0.0f, 0.0f, 0.0f);
|
||||
new_variance = FfxFloat16(0.0f);
|
||||
}
|
||||
|
||||
}
|
||||
FFX_DNSR_Reflections_StoreTemporalAccumulation(dispatch_thread_id, new_signal, new_variance);
|
||||
}
|
||||
|
||||
#else // #if FFX_HALF
|
||||
|
||||
struct FFX_DNSR_Reflections_NeighborhoodSample {
|
||||
FfxFloat32x3 radiance;
|
||||
};
|
||||
|
||||
FFX_DNSR_Reflections_NeighborhoodSample FFX_DNSR_Reflections_LoadFromGroupSharedMemory(FfxInt32x2 idx) {
|
||||
FfxUInt32x2 packed_radiance = FfxUInt32x2(g_ffx_dnsr_shared_0[idx.y][idx.x], g_ffx_dnsr_shared_1[idx.y][idx.x]);
|
||||
FfxFloat32x3 unpacked_radiance = FFX_DNSR_Reflections_UnpackFloat16_4(packed_radiance).xyz;
|
||||
|
||||
FFX_DNSR_Reflections_NeighborhoodSample neighborSample;
|
||||
neighborSample.radiance = unpacked_radiance;
|
||||
return neighborSample;
|
||||
}
|
||||
|
||||
struct FFX_DNSR_Reflections_Moments {
|
||||
FfxFloat32x3 mean;
|
||||
FfxFloat32x3 variance;
|
||||
};
|
||||
|
||||
FFX_DNSR_Reflections_Moments FFX_DNSR_Reflections_EstimateLocalNeighborhoodInGroup(FfxInt32x2 group_thread_id) {
|
||||
FFX_DNSR_Reflections_Moments estimate;
|
||||
estimate.mean = FfxFloat32x3(0.0f, 0.0f, 0.0f);
|
||||
estimate.variance = FfxFloat32x3(0.0f, 0.0f, 0.0f);
|
||||
FfxFloat32 accumulated_weight = FfxFloat32(0.0f);
|
||||
for (FfxInt32 j = -FFX_DNSR_REFLECTIONS_LOCAL_NEIGHBORHOOD_RADIUS; j <= FFX_DNSR_REFLECTIONS_LOCAL_NEIGHBORHOOD_RADIUS; ++j) {
|
||||
for (FfxInt32 i = -FFX_DNSR_REFLECTIONS_LOCAL_NEIGHBORHOOD_RADIUS; i <= FFX_DNSR_REFLECTIONS_LOCAL_NEIGHBORHOOD_RADIUS; ++i) {
|
||||
FfxInt32x2 new_idx = group_thread_id + FfxInt32x2(i, j);
|
||||
FfxFloat32x3 radiance = FFX_DNSR_Reflections_LoadFromGroupSharedMemory(new_idx).radiance;
|
||||
FfxFloat32 weight = FFX_DNSR_Reflections_LocalNeighborhoodKernelWeight(FfxFloat32(i)) * FFX_DNSR_Reflections_LocalNeighborhoodKernelWeight(FfxFloat32(j));
|
||||
accumulated_weight += weight;
|
||||
estimate.mean += radiance * weight;
|
||||
estimate.variance += radiance * radiance * weight;
|
||||
}
|
||||
}
|
||||
estimate.mean /= accumulated_weight;
|
||||
estimate.variance /= accumulated_weight;
|
||||
|
||||
estimate.variance = abs(estimate.variance - estimate.mean * estimate.mean);
|
||||
return estimate;
|
||||
}
|
||||
|
||||
void FFX_DNSR_Reflections_StoreInGroupSharedMemory(FfxInt32x2 group_thread_id, FfxFloat32x3 radiance) {
|
||||
g_ffx_dnsr_shared_0[group_thread_id.y][group_thread_id.x] = FFX_DNSR_Reflections_PackFloat16(radiance.xy);
|
||||
g_ffx_dnsr_shared_1[group_thread_id.y][group_thread_id.x] = FFX_DNSR_Reflections_PackFloat16(radiance.zz);
|
||||
}
|
||||
|
||||
void FFX_DNSR_Reflections_LoadNeighborhood(FfxInt32x2 pixel_coordinate, out FfxFloat32x3 radiance) { radiance = FFX_DNSR_Reflections_LoadRadiance(pixel_coordinate); }
|
||||
|
||||
void FFX_DNSR_Reflections_InitializeGroupSharedMemory(FfxInt32x2 dispatch_thread_id, FfxInt32x2 group_thread_id, FfxInt32x2 screen_size) {
|
||||
// Load 16x16 region into shared memory using 4 8x8 blocks.
|
||||
FfxInt32x2 offset[4] = {FfxInt32x2(0, 0), FfxInt32x2(8, 0), FfxInt32x2(0, 8), FfxInt32x2(8, 8)};
|
||||
|
||||
// Intermediate storage registers to cache the result of all loads
|
||||
FfxFloat32x3 radiance[4];
|
||||
|
||||
// Start in the upper left corner of the 16x16 region.
|
||||
dispatch_thread_id -= 4;
|
||||
|
||||
// First store all loads in registers
|
||||
for (FfxInt32 i = 0; i < 4; ++i) {
|
||||
FFX_DNSR_Reflections_LoadNeighborhood(dispatch_thread_id + offset[i], radiance[i]);
|
||||
}
|
||||
|
||||
// Then move all registers to FFX_GROUPSHARED memory
|
||||
for (FfxInt32 j = 0; j < 4; ++j) {
|
||||
FFX_DNSR_Reflections_StoreInGroupSharedMemory(group_thread_id + offset[j], radiance[j]);
|
||||
}
|
||||
}
|
||||
|
||||
void FFX_DNSR_Reflections_ResolveTemporal(FfxInt32x2 dispatch_thread_id, FfxInt32x2 group_thread_id, FfxUInt32x2 screen_size, FfxFloat32x2 inv_screen_size, FfxFloat32 history_clip_weight) {
|
||||
FFX_DNSR_Reflections_InitializeGroupSharedMemory(dispatch_thread_id, group_thread_id, FfxInt32x2(screen_size));
|
||||
FFX_GROUP_MEMORY_BARRIER;
|
||||
|
||||
group_thread_id += 4; // Center threads in FFX_GROUPSHARED memory
|
||||
|
||||
FfxFloat32x3 radiance = FFX_DNSR_Reflections_LoadFromGroupSharedMemory(group_thread_id).radiance;
|
||||
FfxFloat32 radianceSum = radiance.x + radiance.y + radiance.z;
|
||||
if (radianceSum < RADIANCE_THRESHOLD)
|
||||
{
|
||||
FFX_DNSR_Reflections_StoreTemporalAccumulation(dispatch_thread_id, FfxFloat32x3(0.0f, 0.0f, 0.0f), FfxFloat32(0.0f));
|
||||
return;
|
||||
}
|
||||
|
||||
FFX_DNSR_Reflections_NeighborhoodSample center = FFX_DNSR_Reflections_LoadFromGroupSharedMemory(group_thread_id);
|
||||
FfxFloat32x3 new_signal = center.radiance;
|
||||
FfxFloat32 roughness = FFX_DNSR_Reflections_LoadRoughness(dispatch_thread_id);
|
||||
FfxFloat32 new_variance = FFX_DNSR_Reflections_LoadVariance(dispatch_thread_id);
|
||||
|
||||
if (FFX_DNSR_Reflections_IsGlossyReflection(roughness)) {
|
||||
FfxFloat32 num_samples = FFX_DNSR_Reflections_LoadNumSamples(dispatch_thread_id);
|
||||
FfxFloat32x2 uv8 = (FfxFloat32x2(dispatch_thread_id.xy) + (0.5).xx) / FFX_DNSR_Reflections_RoundUp8(screen_size);
|
||||
FfxFloat32x3 avg_radiance = FFX_DNSR_Reflections_SampleAverageRadiance(uv8);
|
||||
|
||||
FfxFloat32x3 old_signal = FFX_DNSR_Reflections_LoadRadianceReprojected(dispatch_thread_id);
|
||||
FFX_DNSR_Reflections_Moments local_neighborhood = FFX_DNSR_Reflections_EstimateLocalNeighborhoodInGroup(group_thread_id);
|
||||
// Clip history based on the curren local statistics
|
||||
FfxFloat32x3 color_std = FfxFloat32x3((sqrt(local_neighborhood.variance.xyz) + length(local_neighborhood.mean.xyz - avg_radiance)) * history_clip_weight * 1.4f);
|
||||
local_neighborhood.mean.xyz = ffxLerp(local_neighborhood.mean.xyz, avg_radiance, FfxFloat32x3(0.2f, 0.2f, 0.2f));
|
||||
FfxFloat32x3 radiance_min = local_neighborhood.mean.xyz - color_std;
|
||||
FfxFloat32x3 radiance_max = local_neighborhood.mean.xyz + color_std;
|
||||
FfxFloat32x3 clipped_old_signal = FFX_DNSR_Reflections_ClipAABB(radiance_min, radiance_max, old_signal.xyz);
|
||||
FfxFloat32 accumulation_speed = FfxFloat32(1.0f) / max(num_samples, FfxFloat32(1.0f));
|
||||
FfxFloat32 weight = (FfxFloat32(1.0f) - accumulation_speed);
|
||||
// Blend with average for small sample count
|
||||
new_signal.xyz = ffxLerp(new_signal.xyz, avg_radiance, FfxFloat32(1.0f) / max(num_samples + FfxFloat32(1.0f), FfxFloat32(1.0f)));
|
||||
// Clip outliers
|
||||
{
|
||||
FfxFloat32x3 radiance_min = avg_radiance.xyz - color_std * FfxFloat32x3(1.0f, 1.0f, 1.0f);
|
||||
FfxFloat32x3 radiance_max = avg_radiance.xyz + color_std * FfxFloat32x3(1.0f, 1.0f, 1.0f);
|
||||
new_signal.xyz = FFX_DNSR_Reflections_ClipAABB(radiance_min, radiance_max, new_signal.xyz);
|
||||
}
|
||||
// Blend with history
|
||||
new_signal = ffxLerp(new_signal, clipped_old_signal, weight);
|
||||
new_variance = ffxLerp(FFX_DNSR_Reflections_ComputeTemporalVariance(new_signal.xyz, clipped_old_signal.xyz), new_variance, weight);
|
||||
if (any(isinf(new_signal)) || any(isnan(new_signal)) || isinf(new_variance) || isnan(new_variance)) {
|
||||
new_signal = FfxFloat32x3(0.0f, 0.0f, 0.0f);
|
||||
new_variance = FfxFloat32(0.0f);
|
||||
}
|
||||
|
||||
}
|
||||
FFX_DNSR_Reflections_StoreTemporalAccumulation(dispatch_thread_id, new_signal, new_variance);
|
||||
}
|
||||
|
||||
#endif // #if FFX_HALF
|
||||
|
||||
void ResolveTemporal(FfxUInt32 group_index, FfxUInt32 group_id, FfxUInt32x2 group_thread_id) {
|
||||
FfxUInt32 packed_coords = GetDenoiserTile(group_id);
|
||||
FfxInt32x2 dispatch_thread_id = FfxInt32x2(packed_coords & 0xffffu, (packed_coords >> 16) & 0xffffu) + FfxInt32x2(group_thread_id);
|
||||
FfxInt32x2 dispatch_group_id = dispatch_thread_id / 8;
|
||||
FfxInt32x2 remapped_group_thread_id = FfxInt32x2(ffxRemapForWaveReduction(group_index));
|
||||
FfxInt32x2 remapped_dispatch_thread_id = dispatch_group_id * 8 + remapped_group_thread_id;
|
||||
|
||||
FFX_DNSR_Reflections_ResolveTemporal(remapped_dispatch_thread_id, remapped_group_thread_id, RenderSize(), InverseRenderSize(), TemporalStabilityFactor());
|
||||
}
|
||||
|
||||
#endif // FFX_DNSR_REFLECTIONS_RESOLVE_TEMPORAL
|
||||
94
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/denoiser/ffx_denoiser_resources.h
vendored
Normal file
94
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/denoiser/ffx_denoiser_resources.h
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
// 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_SHADOWS_DENOISER_RESOURCES_H
|
||||
#define FFX_SHADOWS_DENOISER_RESOURCES_H
|
||||
|
||||
#if defined(FFX_CPU) || defined(FFX_GPU)
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_NULL 0
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_HIT_MASK_RESULTS 1
|
||||
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_TILE_BUFFER 2
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_SHADOW_MASK 3
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_RAYTRACER_RESULT 4
|
||||
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_DEPTH 5
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_VELOCITY 6
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_NORMAL 7
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_NORMAL_FP16 8 //same resource as NORMAL
|
||||
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_PREVIOUS_DEPTH 9
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_TILE_META_DATA 10
|
||||
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_MOMENTS0 11
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_MOMENTS1 12
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_PREVIOUS_MOMENTS 13 //same resource as MOMENT0 & MOMENT1
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_CURRENT_MOMENTS 14 //same resource as MOMENT0 & MOMENT1
|
||||
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_SCRATCH0 15
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_SCRATCH1 16
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_HISTORY 17 //same resource as SCRATCH1
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_REPROJECTION_RESULTS 18 //same resource as SCRATCH0
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_FILTER_INPUT 19 //same resource as SCRATCH0 & SCRATCH1
|
||||
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_FILTER_OUTPUT 20
|
||||
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_INPUT_DEPTH_HIERARCHY 21
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_INPUT_MOTION_VECTORS 22
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_INPUT_NORMAL 23
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_OUTPUT 24
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_RADIANCE 25
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_RADIANCE_HISTORY 26
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_VARIANCE 27
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_SAMPLE_COUNT 28
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_AVERAGE_RADIANCE 29
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_DENOISER_TILE_LIST 10
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_EXTRACTED_ROUGHNESS 31
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_DEPTH_HISTORY 32
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_NORMAL_HISTORY 33
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_ROUGHNESS_HISTORY 34
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_RADIANCE_0 35
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_RADIANCE_1 36
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_VARIANCE_0 37
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_VARIANCE_1 38
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_SAMPLE_COUNT_0 39
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_SAMPLE_COUNT_1 40
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_AVERAGE_RADIANCE_0 41
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_AVERAGE_RADIANCE_1 42
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_REPROJECTED_RADIANCE 43
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_INDIRECT_ARGS 44
|
||||
|
||||
#define FFX_DENOISER_RESOURCE_IDENTIFIER_COUNT 45
|
||||
|
||||
// CBV resource definitions
|
||||
#define FFX_DENOISER_SHADOWS_CONSTANTBUFFER_IDENTIFIER_DENOISER_SHADOWS0 0
|
||||
#define FFX_DENOISER_SHADOWS_CONSTANTBUFFER_IDENTIFIER_DENOISER_SHADOWS1 1
|
||||
#define FFX_DENOISER_SHADOWS_CONSTANTBUFFER_IDENTIFIER_DENOISER_SHADOWS2 2
|
||||
#define FFX_DENOISER_SHADOWS_CONSTANTBUFFER_IDENTIFIER_DENOISER_SHADOWS_COUNT 3
|
||||
|
||||
// CBV resource definitions
|
||||
#define FFX_DENOISER_REFLECTIONS_CONSTANTBUFFER_IDENTIFIER 0
|
||||
#define FFX_DENOISER_REFLECTIONS_CONSTANTBUFFER_IDENTIFIER_COUNT 1
|
||||
|
||||
#endif // #if defined(FFX_CPU) || defined(FFX_GPU)
|
||||
|
||||
#endif // FFX_SHADOWS_DENOISER_RESOURCES_H
|
||||
378
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/denoiser/ffx_denoiser_shadows_callbacks_glsl.h
vendored
Normal file
378
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/denoiser/ffx_denoiser_shadows_callbacks_glsl.h
vendored
Normal file
@@ -0,0 +1,378 @@
|
||||
// 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_denoiser_resources.h"
|
||||
|
||||
#if defined(FFX_GPU)
|
||||
#include "ffx_core.h"
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_CB0_DENOISER_SHADOWS)
|
||||
layout (set = 0, binding = DENOISER_SHADOWS_BIND_CB0_DENOISER_SHADOWS, std140) uniform cb0DenoiserShadows_t
|
||||
{
|
||||
FfxInt32x2 iBufferDimensions;
|
||||
} cb0DenoiserShadows;
|
||||
#endif
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_CB1_DENOISER_SHADOWS)
|
||||
layout (set = 0, binding = DENOISER_SHADOWS_BIND_CB1_DENOISER_SHADOWS, std140) uniform cb1DenoiserShadows_t
|
||||
{
|
||||
FfxFloat32x3 fEye;
|
||||
FfxInt32 iFirstFrame;
|
||||
FfxInt32x2 iBufferDimensions;
|
||||
FfxFloat32x2 fInvBufferDimensions;
|
||||
FfxFloat32x2 fMotionVectorScale;
|
||||
FfxFloat32x2 normalsUnpackMul_unpackAdd;
|
||||
FfxFloat32Mat4 fProjectionInverse;
|
||||
FfxFloat32Mat4 fReprojectionMatrix;
|
||||
FfxFloat32Mat4 fViewProjectionInverse;
|
||||
} cb1DenoiserShadows;
|
||||
#endif
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_CB2_DENOISER_SHADOWS)
|
||||
layout (set = 0, binding = DENOISER_SHADOWS_BIND_CB2_DENOISER_SHADOWS, std140) uniform cb2DenoiserShadows_t
|
||||
{
|
||||
FfxFloat32Mat4 fProjectionInverse;
|
||||
FfxFloat32x2 fInvBufferDimensions;
|
||||
FfxFloat32x2 normalsUnpackMul_unpackAdd;
|
||||
FfxInt32x2 iBufferDimensions;
|
||||
FfxFloat32 fDepthSimilaritySigma;
|
||||
} cb2DenoiserShadows;
|
||||
#endif
|
||||
|
||||
FfxInt32x2 BufferDimensions()
|
||||
{
|
||||
#if defined(DENOISER_SHADOWS_BIND_CB0_DENOISER_SHADOWS)
|
||||
return cb0DenoiserShadows.iBufferDimensions;
|
||||
#elif defined(DENOISER_SHADOWS_BIND_CB1_DENOISER_SHADOWS)
|
||||
return cb1DenoiserShadows.iBufferDimensions;
|
||||
#elif defined(DENOISER_SHADOWS_BIND_CB2_DENOISER_SHADOWS)
|
||||
return cb2DenoiserShadows.iBufferDimensions;
|
||||
#endif
|
||||
|
||||
return FfxInt32x2(0, 0);
|
||||
}
|
||||
|
||||
FfxFloat32x2 MotionVectorScale()
|
||||
{
|
||||
#if defined(DENOISER_SHADOWS_BIND_CB1_DENOISER_SHADOWS)
|
||||
return cb1DenoiserShadows.fMotionVectorScale;
|
||||
#endif
|
||||
return FfxFloat32x2(0, 0);
|
||||
}
|
||||
|
||||
// SRVs
|
||||
#if defined DENOISER_SHADOWS_BIND_SRV_INPUT_HIT_MASK_RESULTS
|
||||
layout (set = 0, binding = DENOISER_SHADOWS_BIND_SRV_INPUT_HIT_MASK_RESULTS)
|
||||
uniform utexture2D r_hit_mask_results;
|
||||
#endif
|
||||
#if defined DENOISER_SHADOWS_BIND_SRV_DEPTH
|
||||
layout (set = 0, binding = DENOISER_SHADOWS_BIND_SRV_DEPTH)
|
||||
uniform texture2D r_depth;
|
||||
#endif
|
||||
#if defined DENOISER_SHADOWS_BIND_SRV_VELOCITY
|
||||
layout (set = 0, binding = DENOISER_SHADOWS_BIND_SRV_VELOCITY)
|
||||
uniform texture2D r_velocity;
|
||||
#endif
|
||||
#if defined DENOISER_SHADOWS_BIND_SRV_NORMAL
|
||||
layout (set = 0, binding = DENOISER_SHADOWS_BIND_SRV_NORMAL)
|
||||
uniform texture2D r_normal;
|
||||
#endif
|
||||
#if defined DENOISER_SHADOWS_BIND_SRV_HISTORY
|
||||
layout (set = 0, binding = DENOISER_SHADOWS_BIND_SRV_HISTORY)
|
||||
uniform texture2D r_history;
|
||||
#endif
|
||||
#if defined DENOISER_SHADOWS_BIND_SRV_PREVIOUS_DEPTH
|
||||
layout (set = 0, binding = DENOISER_SHADOWS_BIND_SRV_PREVIOUS_DEPTH)
|
||||
uniform texture2D r_previous_depth;
|
||||
#endif
|
||||
#if defined DENOISER_SHADOWS_BIND_SRV_PREVIOUS_MOMENTS
|
||||
layout (set = 0, binding = DENOISER_SHADOWS_BIND_SRV_PREVIOUS_MOMENTS)
|
||||
uniform texture2D r_previous_moments;
|
||||
#endif
|
||||
#if FFX_HALF
|
||||
#if defined DENOISER_SHADOWS_BIND_SRV_FILTER_INPUT
|
||||
layout (set = 0, binding = DENOISER_SHADOWS_BIND_SRV_FILTER_INPUT)
|
||||
uniform texture2D r_filter_input;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// UAV declarations
|
||||
#if defined DENOISER_SHADOWS_BIND_UAV_SHADOW_MASK
|
||||
layout (set = 0, binding = DENOISER_SHADOWS_BIND_UAV_SHADOW_MASK, std430) buffer rw_shadow_mask_t
|
||||
{
|
||||
FfxUInt32 data[];
|
||||
} rw_shadow_mask;
|
||||
#endif
|
||||
#if defined DENOISER_SHADOWS_BIND_UAV_RAYTRACER_RESULT
|
||||
layout (set = 0, binding = DENOISER_SHADOWS_BIND_UAV_RAYTRACER_RESULT, std430) buffer rw_raytracer_result_t
|
||||
{
|
||||
FfxUInt32 data[];
|
||||
} rw_raytracer_result;
|
||||
#endif
|
||||
#if defined DENOISER_SHADOWS_BIND_UAV_TILE_METADATA
|
||||
layout (set = 0, binding = DENOISER_SHADOWS_BIND_UAV_TILE_METADATA, std430) buffer rw_tile_metadata_t
|
||||
{
|
||||
FfxUInt32 data[];
|
||||
} rw_tile_metadata;
|
||||
#endif
|
||||
#if defined DENOISER_SHADOWS_BIND_UAV_REPROJECTION_RESULTS
|
||||
layout (set = 0, binding = DENOISER_SHADOWS_BIND_UAV_REPROJECTION_RESULTS, rg32f)
|
||||
uniform image2D rw_reprojection_results;
|
||||
#endif
|
||||
#if defined DENOISER_SHADOWS_BIND_UAV_CURRENT_MOMENTS
|
||||
layout (set = 0, binding = DENOISER_SHADOWS_BIND_UAV_CURRENT_MOMENTS, rgba32f)
|
||||
uniform image2D rw_current_moments;
|
||||
#endif
|
||||
#if defined DENOISER_SHADOWS_BIND_UAV_HISTORY
|
||||
layout (set = 0, binding = DENOISER_SHADOWS_BIND_UAV_HISTORY, rg32f)
|
||||
uniform image2D rw_history;
|
||||
#endif
|
||||
#if defined DENOISER_SHADOWS_BIND_UAV_FILTER_OUTPUT
|
||||
layout (set = 0, binding = DENOISER_SHADOWS_BIND_UAV_FILTER_OUTPUT) writeonly
|
||||
uniform image2D rw_filter_output;
|
||||
#endif
|
||||
|
||||
#define TILE_SIZE_X 8
|
||||
#define TILE_SIZE_Y 4
|
||||
|
||||
FfxUInt32 LaneIdToBitShift(FfxUInt32x2 localID)
|
||||
{
|
||||
return localID.y * TILE_SIZE_X + localID.x;
|
||||
}
|
||||
|
||||
FfxBoolean WaveMaskToBool(FfxUInt32 mask, FfxUInt32x2 localID)
|
||||
{
|
||||
return FfxBoolean((FfxUInt32(1) << LaneIdToBitShift(localID.xy)) & mask);
|
||||
}
|
||||
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_SRV_INPUT_HIT_MASK_RESULTS)
|
||||
FfxBoolean HitsLight(FfxUInt32x2 did, FfxUInt32x2 gtid, FfxUInt32x2 gid)
|
||||
{
|
||||
FfxUInt32 mask = texelFetch(r_hit_mask_results, ivec2(gid), 0).r;
|
||||
return !WaveMaskToBool(mask, gtid);
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_SRV_INPUT_HIT_MASK_RESULTS)
|
||||
|
||||
FfxFloat32 NormalsUnpackMul()
|
||||
{
|
||||
#if defined(DENOISER_SHADOWS_BIND_CB1_DENOISER_SHADOWS)
|
||||
return cb1DenoiserShadows.normalsUnpackMul_unpackAdd[0];
|
||||
#endif
|
||||
#if defined(DENOISER_SHADOWS_BIND_CB2_DENOISER_SHADOWS)
|
||||
return cb2DenoiserShadows.normalsUnpackMul_unpackAdd[0];
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
FfxFloat32 NormalsUnpackAdd()
|
||||
{
|
||||
#if defined(DENOISER_SHADOWS_BIND_CB1_DENOISER_SHADOWS)
|
||||
return cb1DenoiserShadows.normalsUnpackMul_unpackAdd[1];
|
||||
#endif
|
||||
#if defined(DENOISER_SHADOWS_BIND_CB2_DENOISER_SHADOWS)
|
||||
return cb2DenoiserShadows.normalsUnpackMul_unpackAdd[1];
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_UAV_SHADOW_MASK)
|
||||
void StoreShadowMask(FfxUInt32 offset, FfxUInt32 value)
|
||||
{
|
||||
rw_shadow_mask.data[offset] = value;
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_UAV_SHADOW_MASK)
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_CB1_DENOISER_SHADOWS)
|
||||
FfxFloat32Mat4 ViewProjectionInverse()
|
||||
{
|
||||
return cb1DenoiserShadows.fViewProjectionInverse;
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_CB1_DENOISER_SHADOWS)
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_CB1_DENOISER_SHADOWS)
|
||||
FfxFloat32Mat4 ReprojectionMatrix()
|
||||
{
|
||||
return cb1DenoiserShadows.fReprojectionMatrix;
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_CB1_DENOISER_SHADOWS)
|
||||
|
||||
FfxFloat32Mat4 ProjectionInverse()
|
||||
{
|
||||
#if defined(DENOISER_SHADOWS_BIND_CB1_DENOISER_SHADOWS)
|
||||
return cb1DenoiserShadows.fProjectionInverse;
|
||||
#endif
|
||||
#if defined(DENOISER_SHADOWS_BIND_CB2_DENOISER_SHADOWS)
|
||||
return cb2DenoiserShadows.fProjectionInverse;
|
||||
#else
|
||||
return FfxFloat32Mat4(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
FfxFloat32x2 InvBufferDimensions()
|
||||
{
|
||||
#if defined(DENOISER_SHADOWS_BIND_CB1_DENOISER_SHADOWS)
|
||||
return cb1DenoiserShadows.fInvBufferDimensions;
|
||||
#elif defined(DENOISER_SHADOWS_BIND_CB2_DENOISER_SHADOWS)
|
||||
return cb2DenoiserShadows.fInvBufferDimensions;
|
||||
#else
|
||||
return FfxFloat32x2(0, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_CB1_DENOISER_SHADOWS)
|
||||
FfxInt32 IsFirstFrame()
|
||||
{
|
||||
return cb1DenoiserShadows.iFirstFrame;
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_CB1_DENOISER_SHADOWS)
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_CB1_DENOISER_SHADOWS)
|
||||
FfxFloat32x3 Eye()
|
||||
{
|
||||
return cb1DenoiserShadows.fEye;
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_CB1_DENOISER_SHADOWS)
|
||||
|
||||
FfxFloat32 LoadDepth(FfxInt32x2 p)
|
||||
{
|
||||
#if defined(DENOISER_SHADOWS_BIND_SRV_DEPTH)
|
||||
return texelFetch(r_depth, ivec2(p), 0).x;
|
||||
#else
|
||||
return 0.f;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_SRV_PREVIOUS_DEPTH)
|
||||
FfxFloat32 LoadPreviousDepth(FfxInt32x2 p)
|
||||
{
|
||||
return texelFetch(r_previous_depth, ivec2(p), 0).x;
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_SRV_PREVIOUS_DEPTH)
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_SRV_NORMAL)
|
||||
FfxFloat32x3 LoadNormals(FfxUInt32x2 p)
|
||||
{
|
||||
FfxFloat32x3 normal = texelFetch(r_normal, ivec2(p), 0).xyz;
|
||||
normal = normal * NormalsUnpackMul().xxx + NormalsUnpackAdd().xxx;
|
||||
return normalize(normal);
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_SRV_NORMAL)
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_SRV_VELOCITY)
|
||||
FfxFloat32x2 LoadVelocity(FfxInt32x2 p)
|
||||
{
|
||||
FfxFloat32x2 velocity = texelFetch(r_velocity, ivec2(p), 0).rg;
|
||||
return velocity * MotionVectorScale();
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_SRV_VELOCITY)
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_SRV_HISTORY)
|
||||
layout (set = 0, binding = 1000) uniform sampler s_trilinerClamp;
|
||||
FfxFloat32 LoadHistory(FfxFloat32x2 p)
|
||||
{
|
||||
return FfxFloat32(textureLod(sampler2D(r_history, s_trilinerClamp), p, 0.0f).x);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_SRV_PREVIOUS_MOMENTS)
|
||||
FfxFloat32x3 LoadPreviousMomentsBuffer(FfxInt32x2 p)
|
||||
{
|
||||
return texelFetch(r_previous_moments, ivec2(p), 0).xyz;
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_SRV_PREVIOUS_MOMENTS)
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_UAV_RAYTRACER_RESULT)
|
||||
FfxUInt32 LoadRaytracedShadowMask(FfxUInt32 p)
|
||||
{
|
||||
return rw_raytracer_result.data[p];
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_UAV_RAYTRACER_RESULT)
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_UAV_TILE_METADATA)
|
||||
void StoreMetadata(FfxUInt32 p, FfxUInt32 val)
|
||||
{
|
||||
rw_tile_metadata.data[p] = val;
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_UAV_TILE_METADATA)
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_UAV_CURRENT_MOMENTS)
|
||||
void StoreMoments(FfxUInt32x2 p, FfxFloat32x3 val)
|
||||
{
|
||||
imageStore(rw_current_moments, ivec2(p), FfxFloat32x4(val, 0));
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_UAV_CURRENT_MOMENTS)
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_UAV_REPROJECTION_RESULTS)
|
||||
void StoreReprojectionResults(FfxUInt32x2 p, FfxFloat32x2 val)
|
||||
{
|
||||
imageStore(rw_reprojection_results, ivec2(p), FfxFloat32x4(val, 0, 0));
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_UAV_REPROJECTION_RESULTS)
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_CB2_DENOISER_SHADOWS)
|
||||
FfxFloat32 DepthSimilaritySigma()
|
||||
{
|
||||
return cb2DenoiserShadows.fDepthSimilaritySigma;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if FFX_HALF
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_SRV_FILTER_INPUT)
|
||||
FfxFloat16x2 LoadFilterInput(FfxUInt32x2 p)
|
||||
{
|
||||
return FfxFloat16x2(texelFetch(r_filter_input, ivec2(p), 0).xy);
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_SRV_FILTER_INPUT)
|
||||
|
||||
#endif // #if FFX_HALF
|
||||
|
||||
FfxBoolean IsShadowReciever(FfxUInt32x2 p)
|
||||
{
|
||||
FfxFloat32 depth = LoadDepth(FfxInt32x2(p));
|
||||
return (depth > 0.0f) && (depth < 1.0f);
|
||||
}
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_UAV_TILE_METADATA)
|
||||
FfxUInt32 LoadTileMetaData(FfxUInt32 p)
|
||||
{
|
||||
return rw_tile_metadata.data[p];
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_UAV_TILE_METADATA)
|
||||
|
||||
void StoreHistory(FfxUInt32x2 p, FfxFloat32x2 val)
|
||||
{
|
||||
#if defined(DENOISER_SHADOWS_BIND_UAV_HISTORY)
|
||||
imageStore(rw_history, ivec2(p), FfxFloat32x4(val, 0, 0));
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_UAV_HISTORY)
|
||||
}
|
||||
|
||||
void StoreFilterOutput(FfxUInt32x2 p, FfxFloat32 val)
|
||||
{
|
||||
#if defined(DENOISER_SHADOWS_BIND_UAV_FILTER_OUTPUT)
|
||||
imageStore(rw_filter_output, ivec2(p), FfxFloat32x4(val, 0, 0, 0));
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_UAV_FILTER_OUTPUT)
|
||||
}
|
||||
|
||||
#endif // #if defined(FFX_GPU)
|
||||
392
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/denoiser/ffx_denoiser_shadows_callbacks_hlsl.h
vendored
Normal file
392
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/denoiser/ffx_denoiser_shadows_callbacks_hlsl.h
vendored
Normal file
@@ -0,0 +1,392 @@
|
||||
// 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_denoiser_resources.h"
|
||||
|
||||
#if defined(FFX_GPU)
|
||||
#ifdef __hlsl_dx_compiler
|
||||
#pragma dxc diagnostic push
|
||||
#pragma dxc diagnostic ignored "-Wambig-lit-shift"
|
||||
#endif //__hlsl_dx_compiler
|
||||
#include "ffx_core.h"
|
||||
#ifdef __hlsl_dx_compiler
|
||||
#pragma dxc diagnostic pop
|
||||
#endif //__hlsl_dx_compiler
|
||||
|
||||
#ifndef FFX_PREFER_WAVE64
|
||||
#define FFX_PREFER_WAVE64
|
||||
#endif // #ifndef FFX_PREFER_WAVE64
|
||||
|
||||
#pragma warning(disable: 3205) // conversion from larger type to smaller
|
||||
|
||||
#define FFX_DECLARE_SRV_REGISTER(regIndex) t##regIndex
|
||||
#define FFX_DECLARE_UAV_REGISTER(regIndex) u##regIndex
|
||||
#define FFX_DECLARE_CB_REGISTER(regIndex) b##regIndex
|
||||
#define FFX_DENOISER_SHADOWS_DECLARE_SRV(regIndex) register(FFX_DECLARE_SRV_REGISTER(regIndex))
|
||||
#define FFX_DENOISER_SHADOWS_DECLARE_UAV(regIndex) register(FFX_DECLARE_UAV_REGISTER(regIndex))
|
||||
#define FFX_DENOISER_SHADOWS_DECLARE_CB(regIndex) register(FFX_DECLARE_CB_REGISTER(regIndex))
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_CB0_DENOISER_SHADOWS)
|
||||
cbuffer cb0DenoiserShadows : FFX_DENOISER_SHADOWS_DECLARE_CB(DENOISER_SHADOWS_BIND_CB0_DENOISER_SHADOWS)
|
||||
{
|
||||
FfxInt32x2 iBufferDimensions;
|
||||
#define FFX_DENOISER_SHADOWS_CONSTANT_BUFFER_0_SIZE 2
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_CB1_DENOISER_SHADOWS)
|
||||
cbuffer cb1DenoiserShadows : FFX_DENOISER_SHADOWS_DECLARE_CB(DENOISER_SHADOWS_BIND_CB1_DENOISER_SHADOWS)
|
||||
{
|
||||
FfxFloat32x3 fEye;
|
||||
FfxInt32 iFirstFrame;
|
||||
FfxInt32x2 iBufferDimensions;
|
||||
FfxFloat32x2 fInvBufferDimensions;
|
||||
FfxFloat32x2 fMotionVectorScale;
|
||||
FfxFloat32x2 normalsUnpackMul_unpackAdd;
|
||||
FfxFloat32Mat4 fProjectionInverse;
|
||||
FfxFloat32Mat4 fReprojectionMatrix;
|
||||
FfxFloat32Mat4 fViewProjectionInverse;
|
||||
#define FFX_DENOISER_SHADOWS_CONSTANT_BUFFER_1_SIZE 56
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_CB2_DENOISER_SHADOWS)
|
||||
cbuffer cb2DenoiserShadows : FFX_DENOISER_SHADOWS_DECLARE_CB(DENOISER_SHADOWS_BIND_CB2_DENOISER_SHADOWS)
|
||||
{
|
||||
FfxFloat32Mat4 fProjectionInverse;
|
||||
FfxFloat32x2 fInvBufferDimensions;
|
||||
FfxFloat32x2 normalsUnpackMul_unpackAdd;
|
||||
FfxInt32x2 iBufferDimensions;
|
||||
FfxFloat32 fDepthSimilaritySigma;
|
||||
#define FFX_DENOISER_SHADOWS_CONSTANT_BUFFER_2_SIZE 24
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(FFX_GPU)
|
||||
#define FFX_DENOISER_SHADOWS_ROOTSIG_STRINGIFY(p) FFX_DENOISER_SHADOWS_ROOTSIG_STR(p)
|
||||
#define FFX_DENOISER_SHADOWS_ROOTSIG_STR(p) #p
|
||||
#define FFX_DENOISER_SHADOWS_PREPARE_SHADOW_MASK_ROOTSIG [RootSignature( "DescriptorTable(UAV(u0, numDescriptors = " FFX_DENOISER_SHADOWS_ROOTSIG_STRINGIFY(FFX_DENOISER_RESOURCE_IDENTIFIER_COUNT) ")), " \
|
||||
"DescriptorTable(SRV(t0, numDescriptors = " FFX_DENOISER_SHADOWS_ROOTSIG_STRINGIFY(FFX_DENOISER_RESOURCE_IDENTIFIER_COUNT) ")), " \
|
||||
"CBV(b0)")]
|
||||
|
||||
#define FFX_DENOISER_SHADOWS_TILE_CLASSIFICATION_ROOTSIG [RootSignature( "DescriptorTable(UAV(u0, numDescriptors = " FFX_DENOISER_SHADOWS_ROOTSIG_STRINGIFY(FFX_DENOISER_RESOURCE_IDENTIFIER_COUNT) ")), " \
|
||||
"DescriptorTable(SRV(t0, numDescriptors = " FFX_DENOISER_SHADOWS_ROOTSIG_STRINGIFY(FFX_DENOISER_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, " \
|
||||
"MinLOD = 0, " \
|
||||
"MaxLOD = 3.402823466e+38f, " \
|
||||
"mipLODBias = 0, " \
|
||||
"comparisonFunc = COMPARISON_LESS_EQUAL, " \
|
||||
"maxAnisotropy = 16, " \
|
||||
"borderColor = STATIC_BORDER_COLOR_OPAQUE_WHITE)")]
|
||||
|
||||
#define FFX_DENOISER_SHADOWS_FILTER_SOFT_SHADOWS_ROOTSIG [RootSignature( "DescriptorTable(UAV(u0, numDescriptors = " FFX_DENOISER_SHADOWS_ROOTSIG_STRINGIFY(FFX_DENOISER_RESOURCE_IDENTIFIER_COUNT) ")), " \
|
||||
"DescriptorTable(SRV(t0, numDescriptors = " FFX_DENOISER_SHADOWS_ROOTSIG_STRINGIFY(FFX_DENOISER_RESOURCE_IDENTIFIER_COUNT) ")), " \
|
||||
"CBV(b0)")]
|
||||
|
||||
#if defined(FFX_DENOISER_SHADOWS_EMBED_ROOTSIG)
|
||||
#define FFX_DENOISER_SHADOWS_EMBED_PREPARE_SHADOW_MASK_ROOTSIG_CONTENT FFX_DENOISER_SHADOWS_PREPARE_SHADOW_MASK_ROOTSIG
|
||||
#define FFX_DENOISER_SHADOWS_EMBED_TILE_CLASSIFICATION_ROOTSIG_CONTENT FFX_DENOISER_SHADOWS_TILE_CLASSIFICATION_ROOTSIG
|
||||
#define FFX_DENOISER_SHADOWS_EMBED_FILTER_SOFT_SHADOWS_ROOTSIG_CONTENT FFX_DENOISER_SHADOWS_FILTER_SOFT_SHADOWS_ROOTSIG
|
||||
#else
|
||||
#define FFX_DENOISER_SHADOWS_EMBED_PREPARE_SHADOW_MASK_ROOTSIG_CONTENT
|
||||
#define FFX_DENOISER_SHADOWS_EMBED_TILE_CLASSIFICATION_ROOTSIG_CONTENT
|
||||
#define FFX_DENOISER_SHADOWS_EMBED_FILTER_SOFT_SHADOWS_ROOTSIG_CONTENT
|
||||
#endif // #if FFX_DENOISER_SHADOWS_EMBED_ROOTSIG
|
||||
#endif // #if defined(FFX_GPU)
|
||||
|
||||
// Sampler
|
||||
#if defined(DENOISER_SHADOWS_BIND_SRV_HISTORY)
|
||||
SamplerState s_trilinerClamp : register(s0);
|
||||
#endif
|
||||
|
||||
// SRVs
|
||||
#if defined DENOISER_SHADOWS_BIND_SRV_INPUT_HIT_MASK_RESULTS
|
||||
Texture2D<FfxUInt32> r_hit_mask_results : FFX_DENOISER_SHADOWS_DECLARE_SRV(DENOISER_SHADOWS_BIND_SRV_INPUT_HIT_MASK_RESULTS);
|
||||
#endif
|
||||
#if defined DENOISER_SHADOWS_BIND_SRV_DEPTH
|
||||
Texture2D<FfxFloat32> r_depth : FFX_DENOISER_SHADOWS_DECLARE_SRV(DENOISER_SHADOWS_BIND_SRV_DEPTH);
|
||||
#endif
|
||||
#if defined DENOISER_SHADOWS_BIND_SRV_VELOCITY
|
||||
Texture2D<FfxFloat32x2> r_velocity : FFX_DENOISER_SHADOWS_DECLARE_SRV(DENOISER_SHADOWS_BIND_SRV_VELOCITY);
|
||||
#endif
|
||||
#if defined DENOISER_SHADOWS_BIND_SRV_NORMAL
|
||||
Texture2D<FfxFloat32x3> r_normal : FFX_DENOISER_SHADOWS_DECLARE_SRV(DENOISER_SHADOWS_BIND_SRV_NORMAL);
|
||||
#endif
|
||||
#if defined DENOISER_SHADOWS_BIND_SRV_HISTORY
|
||||
Texture2D<FfxFloat32x2> r_history : FFX_DENOISER_SHADOWS_DECLARE_SRV(DENOISER_SHADOWS_BIND_SRV_HISTORY);
|
||||
#endif
|
||||
#if defined DENOISER_SHADOWS_BIND_SRV_PREVIOUS_DEPTH
|
||||
Texture2D<FfxFloat32> r_previous_depth : FFX_DENOISER_SHADOWS_DECLARE_SRV(DENOISER_SHADOWS_BIND_SRV_PREVIOUS_DEPTH);
|
||||
#endif
|
||||
#if defined DENOISER_SHADOWS_BIND_SRV_PREVIOUS_MOMENTS
|
||||
Texture2D<FfxFloat32x3> r_previous_moments : FFX_DENOISER_SHADOWS_DECLARE_SRV(DENOISER_SHADOWS_BIND_SRV_PREVIOUS_MOMENTS);
|
||||
#endif
|
||||
|
||||
#if FFX_HALF
|
||||
#if defined DENOISER_SHADOWS_BIND_SRV_FILTER_INPUT
|
||||
Texture2D<FfxFloat16x2> r_filter_input : FFX_DENOISER_SHADOWS_DECLARE_SRV(DENOISER_SHADOWS_BIND_SRV_FILTER_INPUT);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// UAV declarations
|
||||
#if defined DENOISER_SHADOWS_BIND_UAV_SHADOW_MASK
|
||||
RWStructuredBuffer<FfxUInt32> rw_shadow_mask : FFX_DENOISER_SHADOWS_DECLARE_UAV(DENOISER_SHADOWS_BIND_UAV_SHADOW_MASK);
|
||||
#endif
|
||||
#if defined DENOISER_SHADOWS_BIND_UAV_RAYTRACER_RESULT
|
||||
RWStructuredBuffer<FfxUInt32> rw_raytracer_result : FFX_DENOISER_SHADOWS_DECLARE_UAV(DENOISER_SHADOWS_BIND_UAV_RAYTRACER_RESULT);
|
||||
#endif
|
||||
#if defined DENOISER_SHADOWS_BIND_UAV_TILE_METADATA
|
||||
RWStructuredBuffer<FfxUInt32> rw_tile_metadata : FFX_DENOISER_SHADOWS_DECLARE_UAV(DENOISER_SHADOWS_BIND_UAV_TILE_METADATA);
|
||||
#endif
|
||||
#if defined DENOISER_SHADOWS_BIND_UAV_REPROJECTION_RESULTS
|
||||
RWTexture2D<FfxFloat32x2> rw_reprojection_results : FFX_DENOISER_SHADOWS_DECLARE_UAV(DENOISER_SHADOWS_BIND_UAV_REPROJECTION_RESULTS);
|
||||
#endif
|
||||
#if defined DENOISER_SHADOWS_BIND_UAV_CURRENT_MOMENTS
|
||||
RWTexture2D<FfxFloat32x3> rw_current_moments : FFX_DENOISER_SHADOWS_DECLARE_UAV(DENOISER_SHADOWS_BIND_UAV_CURRENT_MOMENTS);
|
||||
#endif
|
||||
#if defined DENOISER_SHADOWS_BIND_UAV_HISTORY
|
||||
RWTexture2D<FfxFloat32x2> rw_history : FFX_DENOISER_SHADOWS_DECLARE_UAV(DENOISER_SHADOWS_BIND_UAV_HISTORY);
|
||||
#endif
|
||||
#if defined DENOISER_SHADOWS_BIND_UAV_FILTER_OUTPUT
|
||||
RWTexture2D<unorm FfxFloat32x4> rw_filter_output : FFX_DENOISER_SHADOWS_DECLARE_UAV(DENOISER_SHADOWS_BIND_UAV_FILTER_OUTPUT);
|
||||
#endif
|
||||
|
||||
#define TILE_SIZE_X 8
|
||||
#define TILE_SIZE_Y 4
|
||||
|
||||
FfxUInt32 LaneIdToBitShift(FfxUInt32x2 localID)
|
||||
{
|
||||
return localID.y * TILE_SIZE_X + localID.x;
|
||||
}
|
||||
|
||||
FfxBoolean WaveMaskToBool(FfxUInt32 mask, FfxUInt32x2 localID)
|
||||
{
|
||||
return (1 << LaneIdToBitShift(localID.xy)) & mask;
|
||||
}
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_CB0_DENOISER_SHADOWS) || defined(DENOISER_SHADOWS_BIND_CB1_DENOISER_SHADOWS) || defined(DENOISER_SHADOWS_BIND_CB2_DENOISER_SHADOWS)
|
||||
FfxInt32x2 BufferDimensions()
|
||||
{
|
||||
return iBufferDimensions;
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_CB0_DENOISER_SHADOWS) || defined(DENOISER_SHADOWS_BIND_CB1_DENOISER_SHADOWS) || defined(DENOISER_SHADOWS_BIND_CB2_DENOISER_SHADOWS)
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_SRV_INPUT_HIT_MASK_RESULTS)
|
||||
FfxBoolean HitsLight(FfxUInt32x2 did, FfxUInt32x2 gtid, FfxUInt32x2 gid)
|
||||
{
|
||||
return !WaveMaskToBool(r_hit_mask_results[gid], gtid);
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_SRV_INPUT_HIT_MASK_RESULTS)
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_CB1_DENOISER_SHADOWS) || defined(DENOISER_SHADOWS_BIND_CB2_DENOISER_SHADOWS)
|
||||
FfxFloat32 NormalsUnpackMul()
|
||||
{
|
||||
return normalsUnpackMul_unpackAdd[0];
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_CB1_DENOISER_SHADOWS) || defined(DENOISER_SHADOWS_BIND_CB2_DENOISER_SHADOWS)
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_CB1_DENOISER_SHADOWS) || defined(DENOISER_SHADOWS_BIND_CB2_DENOISER_SHADOWS)
|
||||
FfxFloat32 NormalsUnpackAdd()
|
||||
{
|
||||
return normalsUnpackMul_unpackAdd[1];
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_CB1_DENOISER_SHADOWS) || defined(DENOISER_SHADOWS_BIND_CB2_DENOISER_SHADOWS)
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_UAV_SHADOW_MASK)
|
||||
void StoreShadowMask(FfxUInt32 offset, FfxUInt32 value)
|
||||
{
|
||||
rw_shadow_mask[offset] = value;
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_UAV_SHADOW_MASK)
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_CB1_DENOISER_SHADOWS)
|
||||
FfxFloat32Mat4 ViewProjectionInverse()
|
||||
{
|
||||
return fViewProjectionInverse;
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_CB1_DENOISER_SHADOWS)
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_CB1_DENOISER_SHADOWS)
|
||||
FfxFloat32Mat4 ReprojectionMatrix()
|
||||
{
|
||||
return fReprojectionMatrix;
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_CB1_DENOISER_SHADOWS)
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_CB1_DENOISER_SHADOWS) || defined(DENOISER_SHADOWS_BIND_CB2_DENOISER_SHADOWS)
|
||||
FfxFloat32Mat4 ProjectionInverse()
|
||||
{
|
||||
return fProjectionInverse;
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_CB1_DENOISER_SHADOWS) || defined(DENOISER_SHADOWS_BIND_CB2_DENOISER_SHADOWS)
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_CB1_DENOISER_SHADOWS) || defined(DENOISER_SHADOWS_BIND_CB2_DENOISER_SHADOWS)
|
||||
FfxFloat32x2 InvBufferDimensions()
|
||||
{
|
||||
return fInvBufferDimensions;
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_CB1_DENOISER_SHADOWS) || defined(DENOISER_SHADOWS_BIND_CB2_DENOISER_SHADOWS)
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_CB1_DENOISER_SHADOWS)
|
||||
FfxFloat32x2 MotionVectorScale()
|
||||
{
|
||||
return fMotionVectorScale;
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_CB1_DENOISER_SHADOWS)
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_CB1_DENOISER_SHADOWS)
|
||||
FfxInt32 IsFirstFrame()
|
||||
{
|
||||
return iFirstFrame;
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_CB1_DENOISER_SHADOWS)
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_CB1_DENOISER_SHADOWS)
|
||||
FfxFloat32x3 Eye()
|
||||
{
|
||||
return fEye;
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_CB1_DENOISER_SHADOWS)
|
||||
|
||||
FfxFloat32 LoadDepth(FfxInt32x2 p)
|
||||
{
|
||||
#if defined(DENOISER_SHADOWS_BIND_SRV_DEPTH)
|
||||
return r_depth.Load(FfxInt32x3(p, 0)).x;
|
||||
#else
|
||||
return 0.f;
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_SRV_DEPTH)
|
||||
}
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_SRV_PREVIOUS_DEPTH)
|
||||
FfxFloat32 LoadPreviousDepth(FfxInt32x2 p)
|
||||
{
|
||||
return r_previous_depth.Load(FfxInt32x3(p, 0)).x;
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_SRV_PREVIOUS_DEPTH)
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_SRV_NORMAL)
|
||||
FfxFloat32x3 LoadNormals(FfxInt32x2 p)
|
||||
{
|
||||
FfxFloat32x3 normal = r_normal.Load(FfxInt32x3(p, 0)).xyz;
|
||||
normal = normal * NormalsUnpackMul().xxx + NormalsUnpackAdd().xxx;
|
||||
return normalize(normal);
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_SRV_NORMAL)
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_SRV_VELOCITY)
|
||||
FfxFloat32x2 LoadVelocity(FfxInt32x2 p)
|
||||
{
|
||||
FfxFloat32x2 velocity = r_velocity.Load(FfxInt32x3(p, 0)).rg;
|
||||
return velocity * MotionVectorScale();
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_SRV_VELOCITY)
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_SRV_HISTORY)
|
||||
FfxFloat32 LoadHistory(FfxFloat32x2 p)
|
||||
{
|
||||
return r_history.SampleLevel(s_trilinerClamp, p, 0).x;
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_SRV_HISTORY)
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_SRV_PREVIOUS_MOMENTS)
|
||||
FfxFloat32x3 LoadPreviousMomentsBuffer(FfxInt32x2 p)
|
||||
{
|
||||
return r_previous_moments.Load(FfxInt32x3(p, 0)).xyz;
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_SRV_PREVIOUS_MOMENTS)
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_UAV_RAYTRACER_RESULT)
|
||||
FfxUInt32 LoadRaytracedShadowMask(FfxUInt32 p)
|
||||
{
|
||||
return rw_raytracer_result[p];
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_UAV_RAYTRACER_RESULT)
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_UAV_TILE_METADATA)
|
||||
void StoreMetadata(FfxUInt32 p, FfxUInt32 val)
|
||||
{
|
||||
rw_tile_metadata[p] = val;
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_UAV_TILE_METADATA)
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_UAV_CURRENT_MOMENTS)
|
||||
void StoreMoments(FfxUInt32x2 p, FfxFloat32x3 val)
|
||||
{
|
||||
rw_current_moments[p] = val;
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_UAV_CURRENT_MOMENTS)
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_UAV_REPROJECTION_RESULTS)
|
||||
void StoreReprojectionResults(FfxUInt32x2 p, FfxFloat32x2 val)
|
||||
{
|
||||
rw_reprojection_results[p] = val;
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_UAV_REPROJECTION_RESULTS)
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_CB2_DENOISER_SHADOWS)
|
||||
FfxFloat32 DepthSimilaritySigma()
|
||||
{
|
||||
return fDepthSimilaritySigma;
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_CB2_DENOISER_SHADOWS)
|
||||
|
||||
#if FFX_HALF
|
||||
#if defined(DENOISER_SHADOWS_BIND_SRV_FILTER_INPUT)
|
||||
FfxFloat16x2 LoadFilterInput(FfxUInt32x2 p)
|
||||
{
|
||||
return (FfxFloat16x2)r_filter_input.Load(FfxInt32x3(p, 0)).xy;
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_SRV_FILTER_INPUT)
|
||||
#endif
|
||||
|
||||
FfxBoolean IsShadowReciever(FfxUInt32x2 p)
|
||||
{
|
||||
FfxFloat32 depth = LoadDepth(p);
|
||||
return (depth > 0.0f) && (depth < 1.0f);
|
||||
}
|
||||
|
||||
#if defined(DENOISER_SHADOWS_BIND_UAV_TILE_METADATA)
|
||||
FfxUInt32 LoadTileMetaData(FfxUInt32 p)
|
||||
{
|
||||
return rw_tile_metadata[p];
|
||||
}
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_UAV_TILE_METADATA)
|
||||
|
||||
void StoreHistory(FfxUInt32x2 p, FfxFloat32x2 val)
|
||||
{
|
||||
#if defined(DENOISER_SHADOWS_BIND_UAV_HISTORY)
|
||||
rw_history[p] = val;
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_UAV_HISTORY)
|
||||
}
|
||||
|
||||
void StoreFilterOutput(FfxUInt32x2 p, FfxFloat32 val)
|
||||
{
|
||||
#if defined(DENOISER_SHADOWS_BIND_UAV_FILTER_OUTPUT)
|
||||
rw_filter_output[p].x = val;
|
||||
#endif // #if defined(DENOISER_SHADOWS_BIND_UAV_FILTER_OUTPUT)
|
||||
}
|
||||
|
||||
#endif // #if defined(FFX_GPU)
|
||||
331
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/denoiser/ffx_denoiser_shadows_filter.h
vendored
Normal file
331
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/denoiser/ffx_denoiser_shadows_filter.h
vendored
Normal file
@@ -0,0 +1,331 @@
|
||||
// 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_DNSR_SHADOWS_FILTER_HLSL
|
||||
#define FFX_DNSR_SHADOWS_FILTER_HLSL
|
||||
|
||||
#include "ffx_denoiser_shadows_util.h"
|
||||
|
||||
FFX_GROUPSHARED FfxUInt32 g_FFX_DNSR_Shadows_shared_input[16][16];
|
||||
FFX_GROUPSHARED FfxFloat32 g_FFX_DNSR_Shadows_shared_depth[16][16];
|
||||
FFX_GROUPSHARED FfxUInt32 g_FFX_DNSR_Shadows_shared_normals_xy[16][16];
|
||||
FFX_GROUPSHARED FfxUInt32 g_FFX_DNSR_Shadows_shared_normals_zw[16][16];
|
||||
|
||||
#if FFX_HALF
|
||||
FfxUInt32 FFX_DNSR_Shadows_PackFloat16(FfxFloat16x2 v)
|
||||
{
|
||||
return ffxPackHalf2x16(FfxFloat32x2(v));
|
||||
}
|
||||
|
||||
FfxFloat16x2 FFX_DNSR_Shadows_UnpackFloat16(FfxUInt32 a)
|
||||
{
|
||||
return ffxUnpackF16(a);
|
||||
}
|
||||
|
||||
FfxFloat16x2 FFX_DNSR_Shadows_LoadInputFromGroupSharedMemory(FfxInt32x2 idx)
|
||||
{
|
||||
return FFX_DNSR_Shadows_UnpackFloat16(g_FFX_DNSR_Shadows_shared_input[idx.y][idx.x]);
|
||||
}
|
||||
#endif
|
||||
|
||||
FfxFloat32 FFX_DNSR_Shadows_LoadDepthFromGroupSharedMemory(FfxInt32x2 idx)
|
||||
{
|
||||
return g_FFX_DNSR_Shadows_shared_depth[idx.y][idx.x];
|
||||
}
|
||||
|
||||
#if FFX_HALF
|
||||
FfxFloat16x3 FFX_DNSR_Shadows_LoadNormalsFromGroupSharedMemory(FfxInt32x2 idx)
|
||||
{
|
||||
FfxFloat16x3 normals;
|
||||
normals.xy = FFX_DNSR_Shadows_UnpackFloat16(g_FFX_DNSR_Shadows_shared_normals_xy[idx.y][idx.x]);
|
||||
normals.z = FFX_DNSR_Shadows_UnpackFloat16(g_FFX_DNSR_Shadows_shared_normals_zw[idx.y][idx.x]).x;
|
||||
return normals;
|
||||
}
|
||||
|
||||
void FFX_DNSR_Shadows_StoreInGroupSharedMemory(FfxInt32x2 idx, FfxFloat16x3 normals, FfxFloat16x2 inp, FfxFloat32 depth)
|
||||
{
|
||||
g_FFX_DNSR_Shadows_shared_input[idx.y][idx.x] = FFX_DNSR_Shadows_PackFloat16(inp);
|
||||
g_FFX_DNSR_Shadows_shared_depth[idx.y][idx.x] = depth;
|
||||
g_FFX_DNSR_Shadows_shared_normals_xy[idx.y][idx.x] = FFX_DNSR_Shadows_PackFloat16(normals.xy);
|
||||
g_FFX_DNSR_Shadows_shared_normals_zw[idx.y][idx.x] = FFX_DNSR_Shadows_PackFloat16(FfxFloat16x2(normals.z, 0));
|
||||
}
|
||||
|
||||
void FFX_DNSR_Shadows_LoadWithOffset(FfxInt32x2 did, FfxInt32x2 offset, out FfxFloat16x3 normals, out FfxFloat16x2 inp, out FfxFloat32 depth)
|
||||
{
|
||||
did += offset;
|
||||
|
||||
const FfxInt32x2 p = clamp(did, FfxInt32x2(0, 0), BufferDimensions() - 1);
|
||||
normals = FfxFloat16x3(LoadNormals(p));
|
||||
inp = LoadFilterInput(p);
|
||||
depth = LoadDepth(p);
|
||||
}
|
||||
|
||||
void FFX_DNSR_Shadows_StoreWithOffset(FfxInt32x2 gtid, FfxInt32x2 offset, FfxFloat16x3 normals, FfxFloat16x2 inp, FfxFloat32 depth)
|
||||
{
|
||||
gtid += offset;
|
||||
FFX_DNSR_Shadows_StoreInGroupSharedMemory(gtid, normals, inp, depth);
|
||||
}
|
||||
|
||||
void FFX_DNSR_Shadows_InitializeGroupSharedMemory(FfxInt32x2 did, FfxInt32x2 gtid)
|
||||
{
|
||||
FfxInt32x2 offset_0 = FfxInt32x2(0, 0);
|
||||
FfxInt32x2 offset_1 = FfxInt32x2(8, 0);
|
||||
FfxInt32x2 offset_2 = FfxInt32x2(0, 8);
|
||||
FfxInt32x2 offset_3 = FfxInt32x2(8, 8);
|
||||
|
||||
FfxFloat16x3 normals_0;
|
||||
FfxFloat16x2 input_0;
|
||||
FfxFloat32 depth_0;
|
||||
|
||||
FfxFloat16x3 normals_1;
|
||||
FfxFloat16x2 input_1;
|
||||
FfxFloat32 depth_1;
|
||||
|
||||
FfxFloat16x3 normals_2;
|
||||
FfxFloat16x2 input_2;
|
||||
FfxFloat32 depth_2;
|
||||
|
||||
FfxFloat16x3 normals_3;
|
||||
FfxFloat16x2 input_3;
|
||||
FfxFloat32 depth_3;
|
||||
|
||||
/// XA
|
||||
/// BC
|
||||
|
||||
did -= 4;
|
||||
FFX_DNSR_Shadows_LoadWithOffset(did, offset_0, normals_0, input_0, depth_0); // X
|
||||
FFX_DNSR_Shadows_LoadWithOffset(did, offset_1, normals_1, input_1, depth_1); // A
|
||||
FFX_DNSR_Shadows_LoadWithOffset(did, offset_2, normals_2, input_2, depth_2); // B
|
||||
FFX_DNSR_Shadows_LoadWithOffset(did, offset_3, normals_3, input_3, depth_3); // C
|
||||
|
||||
FFX_DNSR_Shadows_StoreWithOffset(gtid, offset_0, normals_0, input_0, depth_0); // X
|
||||
FFX_DNSR_Shadows_StoreWithOffset(gtid, offset_1, normals_1, input_1, depth_1); // A
|
||||
FFX_DNSR_Shadows_StoreWithOffset(gtid, offset_2, normals_2, input_2, depth_2); // B
|
||||
FFX_DNSR_Shadows_StoreWithOffset(gtid, offset_3, normals_3, input_3, depth_3); // C
|
||||
}
|
||||
#else
|
||||
// Not used, defined to make sure f32 path compiles
|
||||
FfxUInt32 FFX_DNSR_Shadows_PackFloat16(FfxFloat32x2 v){return 0;}
|
||||
FfxFloat32x2 FFX_DNSR_Shadows_UnpackFloat16(FfxUInt32 a){return FfxFloat32x2(0,0);}
|
||||
FfxFloat32x2 FFX_DNSR_Shadows_LoadInputFromGroupSharedMemory(FfxInt32x2 idx){return FfxFloat32x2(0,0);}
|
||||
FfxFloat32x3 FFX_DNSR_Shadows_LoadNormalsFromGroupSharedMemory(FfxInt32x2 idx){return FfxFloat32x3(0,0,0);}
|
||||
void FFX_DNSR_Shadows_StoreInGroupSharedMemory(FfxInt32x2 idx, FfxFloat32x3 normals, FfxFloat32x2 inp, FfxFloat32 depth){}
|
||||
void FFX_DNSR_Shadows_LoadWithOffset(FfxInt32x2 did, FfxInt32x2 offset, out FfxFloat32x3 normals, out FfxFloat32x2 inp, out FfxFloat32 depth){depth = 0;}
|
||||
void FFX_DNSR_Shadows_StoreWithOffset(FfxInt32x2 gtid, FfxInt32x2 offset, FfxFloat32x3 normals, FfxFloat32x2 inp, FfxFloat32 depth){}
|
||||
void FFX_DNSR_Shadows_InitializeGroupSharedMemory(FfxInt32x2 did, FfxInt32x2 gtid){}
|
||||
#endif
|
||||
|
||||
FfxFloat32 FFX_DNSR_Shadows_GetShadowSimilarity(FfxFloat32 x1, FfxFloat32 x2, FfxFloat32 sigma)
|
||||
{
|
||||
return exp(-abs(x1 - x2) / sigma);
|
||||
}
|
||||
|
||||
FfxFloat32 FFX_DNSR_Shadows_GetDepthSimilarity(FfxFloat32 x1, FfxFloat32 x2, FfxFloat32 sigma)
|
||||
{
|
||||
return exp(-abs(x1 - x2) / sigma);
|
||||
}
|
||||
|
||||
FfxFloat32 FFX_DNSR_Shadows_GetNormalSimilarity(FfxFloat32x3 x1, FfxFloat32x3 x2)
|
||||
{
|
||||
return ffxPow(ffxSaturate(dot(x1, x2)), 32.0f);
|
||||
}
|
||||
|
||||
FfxFloat32 FFX_DNSR_Shadows_GetLinearDepth(FfxUInt32x2 did, FfxFloat32 depth)
|
||||
{
|
||||
const FfxFloat32x2 uv = (did + 0.5f) * InvBufferDimensions();
|
||||
const FfxFloat32x2 ndc = 2.0f * FfxFloat32x2(uv.x, 1.0f - uv.y) - 1.0f;
|
||||
|
||||
FfxFloat32x4 projected = FFX_MATRIX_MULTIPLY(ProjectionInverse(), FfxFloat32x4(ndc, depth, 1));
|
||||
|
||||
return abs(projected.z / projected.w);
|
||||
}
|
||||
|
||||
FfxFloat32 FFX_DNSR_Shadows_FetchFilteredVarianceFromGroupSharedMemory(FfxInt32x2 pos)
|
||||
{
|
||||
const FfxInt32 k = 1;
|
||||
FfxFloat32 variance = 0.0f;
|
||||
const FfxFloat32 kernel[2][2] =
|
||||
{
|
||||
{ 1.0f / 4.0f, 1.0f / 8.0f },
|
||||
{ 1.0f / 8.0f, 1.0f / 16.0f }
|
||||
};
|
||||
for (FfxInt32 y = -k; y <= k; ++y)
|
||||
{
|
||||
for (FfxInt32 x = -k; x <= k; ++x)
|
||||
{
|
||||
const FfxFloat32 w = kernel[abs(x)][abs(y)];
|
||||
variance += w * FFX_DNSR_Shadows_LoadInputFromGroupSharedMemory(pos + FfxInt32x2(x, y)).y;
|
||||
}
|
||||
}
|
||||
return variance;
|
||||
}
|
||||
|
||||
void FFX_DNSR_Shadows_DenoiseFromGroupSharedMemory(FfxUInt32x2 did, FfxUInt32x2 gtid, inout FfxFloat32 weight_sum, inout FfxFloat32x2 shadow_sum, FfxFloat32 depth, FfxUInt32 stepsize)
|
||||
{
|
||||
// Load our center sample
|
||||
const FfxFloat32x2 shadow_center = FFX_DNSR_Shadows_LoadInputFromGroupSharedMemory(FfxInt32x2(gtid));
|
||||
const FfxFloat32x3 normal_center = FFX_DNSR_Shadows_LoadNormalsFromGroupSharedMemory(FfxInt32x2(gtid));
|
||||
|
||||
weight_sum = 1.0f;
|
||||
shadow_sum = shadow_center;
|
||||
|
||||
const FfxFloat32 variance = FFX_DNSR_Shadows_FetchFilteredVarianceFromGroupSharedMemory(FfxInt32x2(gtid));
|
||||
const FfxFloat32 std_deviation = sqrt(max(variance + 1e-9f, 0.0f));
|
||||
const FfxFloat32 depth_center = FFX_DNSR_Shadows_GetLinearDepth(did, depth); // linearize the depth value
|
||||
|
||||
// Iterate filter kernel
|
||||
const FfxInt32 k = 1;
|
||||
const FfxFloat32 kernel[3] = { 1.0f, 2.0f / 3.0f, 1.0f / 6.0f };
|
||||
|
||||
for (FfxInt32 y = -k; y <= k; ++y)
|
||||
{
|
||||
for (FfxInt32 x = -k; x <= k; ++x)
|
||||
{
|
||||
// Should we process this sample?
|
||||
const FfxInt32x2 step = FfxInt32x2(x, y) * FfxInt32x2(stepsize, stepsize);
|
||||
const FfxInt32x2 gtid_idx = FfxInt32x2(gtid) + step;
|
||||
const FfxInt32x2 did_idx = FfxInt32x2(did) + step;
|
||||
|
||||
FfxFloat32 depth_neigh = FFX_DNSR_Shadows_LoadDepthFromGroupSharedMemory(gtid_idx);
|
||||
FfxFloat32x3 normal_neigh = FFX_DNSR_Shadows_LoadNormalsFromGroupSharedMemory(gtid_idx);
|
||||
FfxFloat32x2 shadow_neigh = FFX_DNSR_Shadows_LoadInputFromGroupSharedMemory(gtid_idx);
|
||||
|
||||
FfxFloat32 sky_pixel_multiplier = ((x == 0 && y == 0) || depth_neigh >= 1.0f || depth_neigh <= 0.0f) ? 0 : 1; // Zero weight for sky pixels
|
||||
|
||||
// Fetch our filtering values
|
||||
depth_neigh = FFX_DNSR_Shadows_GetLinearDepth(did_idx, depth_neigh);
|
||||
|
||||
// Evaluate the edge-stopping function
|
||||
FfxFloat32 w = kernel[abs(x)] * kernel[abs(y)]; // kernel weight
|
||||
w *= FFX_DNSR_Shadows_GetShadowSimilarity(shadow_center.x, shadow_neigh.x, std_deviation);
|
||||
w *= FFX_DNSR_Shadows_GetDepthSimilarity(depth_center, depth_neigh, DepthSimilaritySigma());
|
||||
w *= FFX_DNSR_Shadows_GetNormalSimilarity(normal_center, normal_neigh);
|
||||
w *= sky_pixel_multiplier;
|
||||
|
||||
// Accumulate the filtered sample
|
||||
shadow_sum += FfxFloat32x2(w, w * w) * shadow_neigh;
|
||||
weight_sum += w;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FfxFloat32x2 FFX_DNSR_Shadows_ApplyFilterWithPrecache(FfxUInt32x2 did, FfxUInt32x2 gtid, FfxUInt32 stepsize)
|
||||
{
|
||||
FfxFloat32 weight_sum = 1.0;
|
||||
FfxFloat32x2 shadow_sum = FfxFloat32x2(0, 0);
|
||||
|
||||
FFX_DNSR_Shadows_InitializeGroupSharedMemory(FfxInt32x2(did), FfxInt32x2(gtid));
|
||||
FfxBoolean needs_denoiser = IsShadowReciever(did);
|
||||
FFX_GROUP_MEMORY_BARRIER;
|
||||
if (needs_denoiser)
|
||||
{
|
||||
FfxFloat32 depth = LoadDepth(FfxInt32x2(did));
|
||||
gtid += 4; // Center threads in groupshared memory
|
||||
FFX_DNSR_Shadows_DenoiseFromGroupSharedMemory(did, gtid, weight_sum, shadow_sum, depth, stepsize);
|
||||
}
|
||||
|
||||
FfxFloat32 mean = shadow_sum.x / weight_sum;
|
||||
FfxFloat32 variance = shadow_sum.y / (weight_sum * weight_sum);
|
||||
return FfxFloat32x2(mean, variance);
|
||||
}
|
||||
|
||||
void FFX_DNSR_Shadows_ReadTileMetaData(FfxUInt32x2 gid, out FfxBoolean is_cleared, out FfxBoolean all_in_light)
|
||||
{
|
||||
FfxUInt32 meta_data = LoadTileMetaData(gid.y * FFX_DNSR_Shadows_RoundedDivide(BufferDimensions().x, 8) + gid.x);
|
||||
is_cleared = FfxBoolean(meta_data & FfxUInt32(TILE_META_DATA_CLEAR_MASK));
|
||||
all_in_light = FfxBoolean(meta_data & FfxUInt32(TILE_META_DATA_LIGHT_MASK));
|
||||
}
|
||||
|
||||
|
||||
FfxFloat32x2 FFX_DNSR_Shadows_FilterSoftShadowsPass(FfxUInt32x2 gid, FfxUInt32x2 gtid, FfxUInt32x2 did, out FfxBoolean bWriteResults, const FfxUInt32 pass, const FfxUInt32 stepsize)
|
||||
{
|
||||
FfxBoolean is_cleared;
|
||||
FfxBoolean all_in_light;
|
||||
FFX_DNSR_Shadows_ReadTileMetaData(gid, is_cleared, all_in_light);
|
||||
|
||||
bWriteResults = FFX_FALSE;
|
||||
FfxFloat32x2 results = FfxFloat32x2(0, 0);
|
||||
|
||||
if (is_cleared)
|
||||
{
|
||||
if (pass != 1)
|
||||
{
|
||||
results.x = all_in_light ? 1.0 : 0.0;
|
||||
bWriteResults = FFX_TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
results = FFX_DNSR_Shadows_ApplyFilterWithPrecache(did, gtid, stepsize);
|
||||
bWriteResults = FFX_TRUE;
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
void DenoiserShadowsFilterPass0(FfxUInt32x2 gid, FfxUInt32x2 gtid, FfxUInt32x2 did)
|
||||
{
|
||||
const uint PASS_INDEX = 0;
|
||||
const uint STEP_SIZE = 1;
|
||||
|
||||
FfxBoolean bWriteOutput = FFX_FALSE;
|
||||
const FfxFloat32x2 results = FFX_DNSR_Shadows_FilterSoftShadowsPass(gid, gtid, did, bWriteOutput, PASS_INDEX, STEP_SIZE);
|
||||
|
||||
if (bWriteOutput)
|
||||
{
|
||||
StoreHistory(did, results);
|
||||
}
|
||||
}
|
||||
|
||||
void DenoiserShadowsFilterPass1(FfxUInt32x2 gid, FfxUInt32x2 gtid, FfxUInt32x2 did)
|
||||
{
|
||||
const uint PASS_INDEX = 1;
|
||||
const uint STEP_SIZE = 2;
|
||||
|
||||
FfxBoolean bWriteOutput = FFX_FALSE;
|
||||
const FfxFloat32x2 results = FFX_DNSR_Shadows_FilterSoftShadowsPass(gid, gtid, did, bWriteOutput, PASS_INDEX, STEP_SIZE);
|
||||
|
||||
if (bWriteOutput)
|
||||
{
|
||||
StoreHistory(did, results);
|
||||
}
|
||||
}
|
||||
|
||||
void DenoiserShadowsFilterPass2(FfxUInt32x2 gid, FfxUInt32x2 gtid, FfxUInt32x2 did)
|
||||
{
|
||||
const uint PASS_INDEX = 2;
|
||||
const uint STEP_SIZE = 4;
|
||||
|
||||
FfxBoolean bWriteOutput = FFX_FALSE;
|
||||
const FfxFloat32x2 results = FFX_DNSR_Shadows_FilterSoftShadowsPass(gid, gtid, did, bWriteOutput, PASS_INDEX, STEP_SIZE);
|
||||
|
||||
// Recover some of the contrast lost during denoising
|
||||
const FfxFloat32 shadow_remap = max(1.2f - results.y, 1.0f);
|
||||
const FfxFloat32 mean = pow(abs(results.x), shadow_remap);
|
||||
|
||||
if (bWriteOutput)
|
||||
{
|
||||
StoreFilterOutput(did, mean);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
53
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/denoiser/ffx_denoiser_shadows_prepare.h
vendored
Normal file
53
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/denoiser/ffx_denoiser_shadows_prepare.h
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
// 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_DNSR_SHADOWS_PREPARESHADOWMASK_HLSL
|
||||
#define FFX_DNSR_SHADOWS_PREPARESHADOWMASK_HLSL
|
||||
|
||||
#include "ffx_denoiser_shadows_util.h"
|
||||
|
||||
void FFX_DNSR_Shadows_CopyResult(FfxUInt32x2 gtid, FfxUInt32x2 gid)
|
||||
{
|
||||
const FfxUInt32x2 did = gid * FfxUInt32x2(8, 4) + gtid;
|
||||
const FfxUInt32 linear_tile_index = FFX_DNSR_Shadows_LinearTileIndex(gid, BufferDimensions().x);
|
||||
const FfxBoolean hit_light = HitsLight(did, gtid, gid);
|
||||
const FfxUInt32 lane_mask = hit_light ? FFX_DNSR_Shadows_GetBitMaskFromPixelPosition(did) : 0;
|
||||
StoreShadowMask(linear_tile_index, ffxWaveOr(lane_mask));
|
||||
}
|
||||
|
||||
void FFX_DNSR_Shadows_PrepareShadowMask(FfxUInt32x2 gtid, FfxUInt32x2 gid)
|
||||
{
|
||||
gid *= 4;
|
||||
FfxUInt32x2 tile_dimensions = (BufferDimensions() + FfxUInt32x2(7, 3)) / FfxUInt32x2(8, 4);
|
||||
|
||||
for (FfxInt32 i = 0; i < 4; ++i)
|
||||
{
|
||||
for (FfxInt32 j = 0; j < 4; ++j)
|
||||
{
|
||||
FfxUInt32x2 tile_id = FfxUInt32x2(gid.x + i, gid.y + j);
|
||||
tile_id = clamp(tile_id, FfxUInt32x2(0, 0), tile_dimensions - FfxUInt32x2(1,1));
|
||||
FFX_DNSR_Shadows_CopyResult(gtid, tile_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,430 @@
|
||||
// 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_DNSR_SHADOWS_TILECLASSIFICATION_HLSL
|
||||
#define FFX_DNSR_SHADOWS_TILECLASSIFICATION_HLSL
|
||||
|
||||
#include "ffx_denoiser_shadows_util.h"
|
||||
|
||||
FFX_GROUPSHARED FfxInt32 g_FFX_DNSR_Shadows_false_count;
|
||||
FfxBoolean FFX_DNSR_Shadows_ThreadGroupAllTrue(FfxBoolean val)
|
||||
{
|
||||
const FfxUInt32 lane_count_in_thread_group = 64;
|
||||
if (ffxWaveLaneCount() == lane_count_in_thread_group)
|
||||
{
|
||||
return ffxWaveAllTrue(val);
|
||||
}
|
||||
else
|
||||
{
|
||||
FFX_GROUP_MEMORY_BARRIER;
|
||||
g_FFX_DNSR_Shadows_false_count = 0;
|
||||
FFX_GROUP_MEMORY_BARRIER;
|
||||
if (!val) g_FFX_DNSR_Shadows_false_count = 1;
|
||||
FFX_GROUP_MEMORY_BARRIER;
|
||||
return g_FFX_DNSR_Shadows_false_count == 0;
|
||||
}
|
||||
}
|
||||
|
||||
void FFX_DNSR_Shadows_SearchSpatialRegion(FfxUInt32x2 gid, out FfxBoolean all_in_light, out FfxBoolean all_in_shadow)
|
||||
{
|
||||
// The spatial passes can reach a total region of 1+2+4 = 7x7 around each block.
|
||||
// The masks are 8x4, so we need a larger vertical stride
|
||||
|
||||
// Visualization - each x represents a 4x4 block, xx is one entire 8x4 mask as read from the raytracer result
|
||||
// Same for yy, these are the ones we are working on right now
|
||||
|
||||
// xx xx xx
|
||||
// xx xx xx
|
||||
// xx yy xx <-- yy here is the base_tile below
|
||||
// xx yy xx
|
||||
// xx xx xx
|
||||
// xx xx xx
|
||||
|
||||
// All of this should result in scalar ops
|
||||
FfxUInt32x2 base_tile = FFX_DNSR_Shadows_GetTileIndexFromPixelPosition(gid * FfxInt32x2(8, 8));
|
||||
|
||||
// Load the entire region of masks in a scalar fashion
|
||||
FfxUInt32 combined_or_mask = 0;
|
||||
FfxUInt32 combined_and_mask = 0xFFFFFFFF;
|
||||
for (FfxInt32 j = -2; j <= 3; ++j)
|
||||
{
|
||||
for (FfxInt32 i = -1; i <= 1; ++i)
|
||||
{
|
||||
FfxInt32x2 tile_index = FfxInt32x2(base_tile) + FfxInt32x2(i, j);
|
||||
tile_index = clamp(tile_index, FfxInt32x2(0,0), FfxInt32x2(FFX_DNSR_Shadows_RoundedDivide(BufferDimensions().x, 8), FFX_DNSR_Shadows_RoundedDivide(BufferDimensions().y, 4)) - 1);
|
||||
const FfxUInt32 linear_tile_index = FFX_DNSR_Shadows_LinearTileIndex(tile_index, BufferDimensions().x);
|
||||
const FfxUInt32 shadow_mask = LoadRaytracedShadowMask(linear_tile_index);
|
||||
|
||||
combined_or_mask = combined_or_mask | shadow_mask;
|
||||
combined_and_mask = combined_and_mask & shadow_mask;
|
||||
}
|
||||
}
|
||||
|
||||
all_in_light = combined_and_mask == 0xFFFFFFFFu;
|
||||
all_in_shadow = combined_or_mask == 0u;
|
||||
}
|
||||
|
||||
FfxFloat32 FFX_DNSR_Shadows_GetLinearDepth(FfxUInt32x2 did, FfxFloat32 depth)
|
||||
{
|
||||
const FfxFloat32x2 uv = (did + 0.5f) * InvBufferDimensions();
|
||||
const FfxFloat32x2 ndc = 2.0f * FfxFloat32x2(uv.x, 1.0f - uv.y) - 1.0f;
|
||||
|
||||
FfxFloat32x4 projected = FFX_MATRIX_MULTIPLY(ProjectionInverse(), FfxFloat32x4(ndc, depth, 1));
|
||||
|
||||
return abs(projected.z / projected.w);
|
||||
}
|
||||
|
||||
FfxBoolean FFX_DNSR_Shadows_IsDisoccluded(FfxUInt32x2 did, FfxFloat32 depth, FfxFloat32x2 velocity)
|
||||
{
|
||||
const FfxInt32x2 dims = BufferDimensions();
|
||||
const FfxFloat32x2 texel_size = InvBufferDimensions();
|
||||
const FfxFloat32x2 uv = (did + 0.5f) * texel_size;
|
||||
const FfxFloat32x2 ndc = (2.0f * uv - 1.0f) * FfxFloat32x2(1.0f, -1.0f);
|
||||
const FfxFloat32x2 previous_uv = uv + velocity;
|
||||
|
||||
FfxBoolean is_disoccluded = FFX_TRUE;
|
||||
|
||||
if (all(FFX_GREATER_THAN(previous_uv, FfxFloat32x2(0,0))) && all(FFX_LESS_THAN(previous_uv, FfxFloat32x2(1,1))))
|
||||
{
|
||||
// Read the center values
|
||||
FfxFloat32x3 normal = LoadNormals(did);
|
||||
|
||||
FfxFloat32x4 clip_space = FFX_MATRIX_MULTIPLY(ReprojectionMatrix(), FfxFloat32x4(ndc, depth, 1.0f));
|
||||
|
||||
clip_space.z /= clip_space.w; // perspective divide
|
||||
|
||||
// How aligned with the view vector? (the more Z aligned, the higher the depth errors)
|
||||
const FfxFloat32x4 homogeneous = FFX_MATRIX_MULTIPLY(ViewProjectionInverse(), FfxFloat32x4(ndc, depth, 1.0f));
|
||||
const FfxFloat32x3 world_position = FfxFloat32x3(homogeneous.xyz / homogeneous.w); // perspective divide
|
||||
const FfxFloat32x3 view_direction = normalize(Eye().xyz - world_position);
|
||||
FfxFloat32 z_alignment = 1.0f - dot(view_direction, normal);
|
||||
z_alignment = pow(z_alignment, 8);
|
||||
|
||||
// Calculate the depth difference
|
||||
FfxFloat32 linear_depth = FFX_DNSR_Shadows_GetLinearDepth(did, clip_space.z); // get linear depth
|
||||
|
||||
FfxInt32x2 idx = FfxInt32x2(previous_uv * FfxFloat32x2(dims));
|
||||
const FfxFloat32 previous_depth = FFX_DNSR_Shadows_GetLinearDepth(idx, LoadPreviousDepth(idx));
|
||||
const FfxFloat32 depth_difference = abs(previous_depth - linear_depth) / linear_depth;
|
||||
|
||||
// Resolve into the disocclusion mask
|
||||
const FfxFloat32 depth_tolerance = ffxLerp(1e-2f, 1e-1f, z_alignment);
|
||||
is_disoccluded = depth_difference >= depth_tolerance;
|
||||
}
|
||||
|
||||
return is_disoccluded;
|
||||
}
|
||||
|
||||
FfxFloat32x2 FFX_DNSR_Shadows_GetClosestVelocity(FfxInt32x2 did, FfxFloat32 depth)
|
||||
{
|
||||
FfxFloat32x2 closest_velocity = LoadVelocity(did);
|
||||
FfxFloat32 closest_depth = depth;
|
||||
|
||||
FfxFloat32 new_depth = ffxQuadReadX(closest_depth);
|
||||
FfxFloat32x2 new_velocity = ffxQuadReadX(closest_velocity);
|
||||
|
||||
#if FFX_DENOISER_OPTION_INVERTED_DEPTH
|
||||
if (new_depth > closest_depth)
|
||||
#else
|
||||
if (new_depth < closest_depth)
|
||||
#endif
|
||||
{
|
||||
closest_depth = new_depth;
|
||||
closest_velocity = new_velocity;
|
||||
}
|
||||
|
||||
new_depth = ffxQuadReadY(closest_depth);
|
||||
new_velocity = ffxQuadReadY(closest_velocity);
|
||||
|
||||
#if FFX_DENOISER_OPTION_INVERTED_DEPTH
|
||||
if (new_depth > closest_depth)
|
||||
#else
|
||||
if (new_depth < closest_depth)
|
||||
#endif
|
||||
{
|
||||
closest_depth = new_depth;
|
||||
closest_velocity = new_velocity;
|
||||
}
|
||||
|
||||
return closest_velocity;
|
||||
}
|
||||
|
||||
#define KERNEL_RADIUS 8
|
||||
FfxFloat32 FFX_DNSR_Shadows_KernelWeight(FfxFloat32 i)
|
||||
{
|
||||
#define KERNEL_WEIGHT(i) (exp(-3.0 * FfxFloat32(i * i) / ((KERNEL_RADIUS + 1.0) * (KERNEL_RADIUS + 1.0))))
|
||||
|
||||
// Statically initialize kernel_weights_sum
|
||||
FfxFloat32 kernel_weights_sum = 0;
|
||||
kernel_weights_sum += KERNEL_WEIGHT(0);
|
||||
for (FfxInt32 c = 1; c <= KERNEL_RADIUS; ++c)
|
||||
{
|
||||
kernel_weights_sum += 2 * KERNEL_WEIGHT(c); // Add other half of the kernel to the sum
|
||||
}
|
||||
FfxFloat32 inv_kernel_weights_sum = ffxReciprocal(kernel_weights_sum);
|
||||
|
||||
// The only runtime code in this function
|
||||
return KERNEL_WEIGHT(i) * inv_kernel_weights_sum;
|
||||
}
|
||||
|
||||
void FFX_DNSR_Shadows_AccumulateMoments(FfxFloat32 value, FfxFloat32 weight, inout FfxFloat32 moments)
|
||||
{
|
||||
// We get value from the horizontal neighborhood calculations. Thus, it's both mean and variance due to using one sample per pixel
|
||||
moments += value * weight;
|
||||
}
|
||||
|
||||
// The horizontal part of a 17x17 local neighborhood kernel
|
||||
FfxFloat32 FFX_DNSR_Shadows_HorizontalNeighborhood(FfxInt32x2 did)
|
||||
{
|
||||
const FfxInt32x2 base_did = did;
|
||||
|
||||
// Prevent vertical out of bounds access
|
||||
if ((base_did.y < 0) || (base_did.y >= BufferDimensions().y)) return 0;
|
||||
|
||||
const FfxUInt32x2 tile_index = FFX_DNSR_Shadows_GetTileIndexFromPixelPosition(base_did);
|
||||
const FfxUInt32 linear_tile_index = FFX_DNSR_Shadows_LinearTileIndex(tile_index, BufferDimensions().x);
|
||||
|
||||
const FfxUInt32 left_tile_index = linear_tile_index - 1;
|
||||
const FfxUInt32 center_tile_index = linear_tile_index;
|
||||
const FfxUInt32 right_tile_index = linear_tile_index + 1;
|
||||
|
||||
FfxBoolean is_first_tile_in_row = tile_index.x == 0;
|
||||
FfxBoolean is_last_tile_in_row = tile_index.x == (FFX_DNSR_Shadows_RoundedDivide(BufferDimensions().x, 8) - 1);
|
||||
|
||||
FfxUInt32 left_tile = 0;
|
||||
if (!is_first_tile_in_row) left_tile = LoadRaytracedShadowMask(left_tile_index);
|
||||
FfxUInt32 center_tile = LoadRaytracedShadowMask(center_tile_index);
|
||||
FfxUInt32 right_tile = 0;
|
||||
if (!is_last_tile_in_row) right_tile = LoadRaytracedShadowMask(right_tile_index);
|
||||
|
||||
// Construct a single FfxUInt32 with the lowest 17bits containing the horizontal part of the local neighborhood.
|
||||
|
||||
// First extract the 8 bits of our row in each of the neighboring tiles
|
||||
const FfxUInt32 row_base_index = (did.y % 4) * 8;
|
||||
const FfxUInt32 left = (left_tile >> row_base_index) & 0xFF;
|
||||
const FfxUInt32 center = (center_tile >> row_base_index) & 0xFF;
|
||||
const FfxUInt32 right = (right_tile >> row_base_index) & 0xFF;
|
||||
|
||||
// Combine them into a single mask containting [left, center, right] from least significant to most significant bit
|
||||
FfxUInt32 neighborhood = left | (center << 8) | (right << 16);
|
||||
|
||||
// Make sure our pixel is at bit position 9 to get the highest contribution from the filter kernel
|
||||
const FfxUInt32 bit_index_in_row = (did.x % 8);
|
||||
neighborhood = neighborhood >> bit_index_in_row; // Shift out bits to the right, so the center bit ends up at bit 9.
|
||||
|
||||
FfxFloat32 moment = 0.0; // For one sample per pixel this is both, mean and variance
|
||||
|
||||
// First 8 bits up to the center pixel
|
||||
FfxUInt32 mask;
|
||||
FfxInt32 i;
|
||||
for (i = 0; i < 8; ++i)
|
||||
{
|
||||
mask = 1u << i;
|
||||
moment += FfxBoolean(mask & neighborhood) ? FFX_DNSR_Shadows_KernelWeight(8 - i) : 0;
|
||||
}
|
||||
|
||||
// Center pixel
|
||||
mask = 1u << 8;
|
||||
moment += FfxBoolean(mask & neighborhood) ? FFX_DNSR_Shadows_KernelWeight(0) : 0;
|
||||
|
||||
// Last 8 bits
|
||||
for (i = 1; i <= 8; ++i)
|
||||
{
|
||||
mask = 1u << (8 + i);
|
||||
moment += FfxBoolean(mask & neighborhood) ? FFX_DNSR_Shadows_KernelWeight(i) : 0;
|
||||
}
|
||||
|
||||
return moment;
|
||||
}
|
||||
|
||||
FFX_GROUPSHARED FfxFloat32 g_FFX_DNSR_Shadows_neighborhood[8][24];
|
||||
|
||||
FfxFloat32 FFX_DNSR_Shadows_ComputeLocalNeighborhood(FfxInt32x2 did, FfxInt32x2 gtid)
|
||||
{
|
||||
FfxFloat32 local_neighborhood = 0;
|
||||
|
||||
FfxFloat32 upper = FFX_DNSR_Shadows_HorizontalNeighborhood(FfxInt32x2(did.x, did.y - 8));
|
||||
FfxFloat32 center = FFX_DNSR_Shadows_HorizontalNeighborhood(FfxInt32x2(did.x, did.y));
|
||||
FfxFloat32 lower = FFX_DNSR_Shadows_HorizontalNeighborhood(FfxInt32x2(did.x, did.y + 8));
|
||||
|
||||
g_FFX_DNSR_Shadows_neighborhood[gtid.x][gtid.y] = upper;
|
||||
g_FFX_DNSR_Shadows_neighborhood[gtid.x][gtid.y + 8] = center;
|
||||
g_FFX_DNSR_Shadows_neighborhood[gtid.x][gtid.y + 16] = lower;
|
||||
|
||||
FFX_GROUP_MEMORY_BARRIER;
|
||||
|
||||
// First combine the own values.
|
||||
// KERNEL_RADIUS pixels up is own upper and KERNEL_RADIUS pixels down is own lower value
|
||||
FFX_DNSR_Shadows_AccumulateMoments(center, FFX_DNSR_Shadows_KernelWeight(0), local_neighborhood);
|
||||
FFX_DNSR_Shadows_AccumulateMoments(upper, FFX_DNSR_Shadows_KernelWeight(KERNEL_RADIUS), local_neighborhood);
|
||||
FFX_DNSR_Shadows_AccumulateMoments(lower, FFX_DNSR_Shadows_KernelWeight(KERNEL_RADIUS), local_neighborhood);
|
||||
|
||||
// Then read the neighboring values.
|
||||
for (FfxInt32 i = 1; i < KERNEL_RADIUS; ++i)
|
||||
{
|
||||
FfxFloat32 upper_value = g_FFX_DNSR_Shadows_neighborhood[gtid.x][8 + gtid.y - i];
|
||||
FfxFloat32 lower_value = g_FFX_DNSR_Shadows_neighborhood[gtid.x][8 + gtid.y + i];
|
||||
FfxFloat32 weight = FFX_DNSR_Shadows_KernelWeight(i);
|
||||
FFX_DNSR_Shadows_AccumulateMoments(upper_value, weight, local_neighborhood);
|
||||
FFX_DNSR_Shadows_AccumulateMoments(lower_value, weight, local_neighborhood);
|
||||
}
|
||||
|
||||
return local_neighborhood;
|
||||
}
|
||||
|
||||
void FFX_DNSR_Shadows_WriteTileMetaData(FfxUInt32x2 gid, FfxUInt32x2 gtid, FfxBoolean is_cleared, FfxBoolean all_in_light)
|
||||
{
|
||||
if (all(FFX_EQUAL(gtid, FfxUInt32x2(0,0))))
|
||||
{
|
||||
FfxUInt32 light_mask = all_in_light ? TILE_META_DATA_LIGHT_MASK : 0;
|
||||
FfxUInt32 clear_mask = is_cleared ? TILE_META_DATA_CLEAR_MASK : 0;
|
||||
FfxUInt32 mask = FfxUInt32(light_mask | clear_mask);
|
||||
StoreMetadata(gid.y * FFX_DNSR_Shadows_RoundedDivide(BufferDimensions().x, 8) + gid.x, mask);
|
||||
}
|
||||
}
|
||||
|
||||
void FFX_DNSR_Shadows_ClearTargets(FfxUInt32x2 did, FfxUInt32x2 gtid, FfxUInt32x2 gid, FfxFloat32 shadow_value, FfxBoolean is_shadow_receiver, FfxBoolean all_in_light)
|
||||
{
|
||||
FFX_DNSR_Shadows_WriteTileMetaData(gid, gtid, FFX_TRUE, all_in_light);
|
||||
StoreReprojectionResults(did, FfxFloat32x2(shadow_value, 0)); // mean, variance
|
||||
|
||||
FfxFloat32 temporal_sample_count = is_shadow_receiver ? 1 : 0;
|
||||
StoreMoments(did, FfxFloat32x3(shadow_value, 0, temporal_sample_count));// mean, variance, temporal sample count
|
||||
}
|
||||
|
||||
void FFX_DNSR_Shadows_TileClassification(FfxUInt32 group_index, FfxUInt32x2 gid)
|
||||
{
|
||||
FfxUInt32x2 gtid = ffxRemapForWaveReduction(group_index); // Make sure we can use the QuadReadAcross intrinsics to access a 2x2 region.
|
||||
FfxUInt32x2 did = gid * 8 + gtid;
|
||||
|
||||
FfxBoolean is_shadow_receiver = IsShadowReciever(did);
|
||||
|
||||
FfxBoolean skip_sky = FFX_DNSR_Shadows_ThreadGroupAllTrue(!is_shadow_receiver);
|
||||
if (skip_sky)
|
||||
{
|
||||
// We have to set all resources of the tile we skipped to sensible values as neighboring active denoiser tiles might want to read them.
|
||||
FFX_DNSR_Shadows_ClearTargets(did, gtid, gid, 0, is_shadow_receiver, FFX_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
FfxBoolean all_in_light = FFX_FALSE;
|
||||
FfxBoolean all_in_shadow = FFX_FALSE;
|
||||
FFX_DNSR_Shadows_SearchSpatialRegion(gid, all_in_light, all_in_shadow);
|
||||
FfxFloat32 shadow_value = all_in_light ? 1 : 0; // Either all_in_light or all_in_shadow must be true, otherwise we would not skip the tile.
|
||||
|
||||
FfxBoolean can_skip = all_in_light || all_in_shadow;
|
||||
// We have to append the entire tile if there is a single lane that we can't skip
|
||||
FfxBoolean skip_tile = FFX_DNSR_Shadows_ThreadGroupAllTrue(can_skip);
|
||||
if (skip_tile)
|
||||
{
|
||||
// We have to set all resources of the tile we skipped to sensible values as neighboring active denoiser tiles might want to read them.
|
||||
FFX_DNSR_Shadows_ClearTargets(did, gtid, gid, shadow_value, is_shadow_receiver, all_in_light);
|
||||
return;
|
||||
}
|
||||
|
||||
FFX_DNSR_Shadows_WriteTileMetaData(gid, gtid, FFX_FALSE, FFX_FALSE);
|
||||
|
||||
FfxFloat32 depth = LoadDepth(FfxInt32x2(did));
|
||||
const FfxFloat32x2 velocity = FFX_DNSR_Shadows_GetClosestVelocity(FfxInt32x2(did), depth); // Must happen before we deactivate lanes
|
||||
const FfxFloat32 local_neighborhood = FFX_DNSR_Shadows_ComputeLocalNeighborhood(FfxInt32x2(did), FfxInt32x2(gtid));
|
||||
|
||||
const FfxFloat32x2 texel_size = InvBufferDimensions();
|
||||
const FfxFloat32x2 uv = (did.xy + 0.5f) * texel_size;
|
||||
const FfxFloat32x2 history_uv = uv + velocity;
|
||||
const FfxInt32x2 history_pos = FfxInt32x2(history_uv * BufferDimensions());
|
||||
|
||||
const FfxUInt32x2 tile_index = FFX_DNSR_Shadows_GetTileIndexFromPixelPosition(FfxInt32x2(did));
|
||||
const FfxUInt32 linear_tile_index = FFX_DNSR_Shadows_LinearTileIndex(tile_index, BufferDimensions().x);
|
||||
|
||||
const FfxUInt32 shadow_tile = LoadRaytracedShadowMask(linear_tile_index);
|
||||
|
||||
FfxFloat32x3 moments_current = FfxFloat32x3(0,0,0);
|
||||
FfxFloat32 variance = 0;
|
||||
FfxFloat32 shadow_clamped = 0;
|
||||
if (is_shadow_receiver) // do not process sky pixels
|
||||
{
|
||||
FfxBoolean hit_light = FfxBoolean(shadow_tile & FFX_DNSR_Shadows_GetBitMaskFromPixelPosition(did));
|
||||
const FfxFloat32 shadow_current = hit_light ? 1.0 : 0.0;
|
||||
|
||||
// Perform moments and variance calculations
|
||||
{
|
||||
FfxBoolean is_disoccluded = FFX_DNSR_Shadows_IsDisoccluded(did, depth, velocity);
|
||||
const FfxFloat32x3 previous_moments = is_disoccluded ? FfxFloat32x3(0.0f, 0.0f, 0.0f) // Can't trust previous moments on disocclusion
|
||||
: LoadPreviousMomentsBuffer(history_pos);
|
||||
|
||||
const FfxFloat32 old_m = previous_moments.x;
|
||||
const FfxFloat32 old_s = previous_moments.y;
|
||||
const FfxFloat32 sample_count = previous_moments.z + 1.0f;
|
||||
const FfxFloat32 new_m = old_m + (shadow_current - old_m) / sample_count;
|
||||
const FfxFloat32 new_s = old_s + (shadow_current - old_m) * (shadow_current - new_m);
|
||||
|
||||
variance = (sample_count > 1.0f ? new_s / (sample_count - 1.0f) : 1.0f);
|
||||
moments_current = FfxFloat32x3(new_m, new_s, sample_count);
|
||||
}
|
||||
|
||||
// Retrieve local neighborhood and reproject
|
||||
{
|
||||
FfxFloat32 mean = local_neighborhood;
|
||||
FfxFloat32 spatial_variance = local_neighborhood;
|
||||
|
||||
spatial_variance = max(spatial_variance - mean * mean, 0.0f);
|
||||
|
||||
// Compute the clamping bounding box
|
||||
const FfxFloat32 std_deviation = sqrt(spatial_variance);
|
||||
const FfxFloat32 nmin = mean - 0.5f * std_deviation;
|
||||
const FfxFloat32 nmax = mean + 0.5f * std_deviation;
|
||||
|
||||
// Clamp reprojected sample to local neighborhood
|
||||
FfxFloat32 shadow_previous = shadow_current;
|
||||
if (IsFirstFrame() == 0)
|
||||
{
|
||||
shadow_previous = LoadHistory(history_uv);
|
||||
}
|
||||
|
||||
shadow_clamped = clamp(shadow_previous, nmin, nmax);
|
||||
|
||||
// Reduce history weighting
|
||||
const FfxFloat32 sigma = 20.0f;
|
||||
const FfxFloat32 temporal_discontinuity = (shadow_previous - mean) / max(0.5f * std_deviation, 0.001f);
|
||||
const FfxFloat32 sample_counter_damper = exp(-temporal_discontinuity * temporal_discontinuity / sigma);
|
||||
moments_current.z *= sample_counter_damper;
|
||||
|
||||
// Boost variance on first frames
|
||||
if (moments_current.z < 16.0f)
|
||||
{
|
||||
const FfxFloat32 variance_boost = max(16.0f - moments_current.z, 1.0f);
|
||||
variance = max(variance, spatial_variance);
|
||||
variance *= variance_boost;
|
||||
}
|
||||
}
|
||||
|
||||
// Perform the temporal blend
|
||||
const FfxFloat32 history_weight = sqrt(max(8.0f - moments_current.z, 0.0f) / 8.0f);
|
||||
shadow_clamped = ffxLerp(shadow_clamped, shadow_current, ffxLerp(0.05f, 1.0f, history_weight));
|
||||
}
|
||||
|
||||
// Output the results of the temporal pass
|
||||
StoreReprojectionResults(did.xy, FfxFloat32x2(shadow_clamped, variance));
|
||||
StoreMoments(did.xy, moments_current);
|
||||
}
|
||||
|
||||
#endif
|
||||
50
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/denoiser/ffx_denoiser_shadows_util.h
vendored
Normal file
50
betterRenderer/thirdparty/fsr2/include/FidelityFX/gpu/denoiser/ffx_denoiser_shadows_util.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_DNSR_SHADOWS_UTILS_HLSL
|
||||
#define FFX_DNSR_SHADOWS_UTILS_HLSL
|
||||
|
||||
FfxUInt32 FFX_DNSR_Shadows_RoundedDivide(FfxUInt32 value, FfxUInt32 divisor)
|
||||
{
|
||||
return (value + divisor - 1) / divisor;
|
||||
}
|
||||
|
||||
FfxUInt32x2 FFX_DNSR_Shadows_GetTileIndexFromPixelPosition(FfxUInt32x2 pixel_pos)
|
||||
{
|
||||
return FfxUInt32x2(pixel_pos.x / 8, pixel_pos.y / 4);
|
||||
}
|
||||
|
||||
FfxUInt32 FFX_DNSR_Shadows_LinearTileIndex(FfxUInt32x2 tile_index, FfxUInt32 screen_width)
|
||||
{
|
||||
return tile_index.y * FFX_DNSR_Shadows_RoundedDivide(screen_width, 8) + tile_index.x;
|
||||
}
|
||||
|
||||
FfxUInt32 FFX_DNSR_Shadows_GetBitMaskFromPixelPosition(FfxUInt32x2 pixel_pos)
|
||||
{
|
||||
FfxUInt32 lane_index = (pixel_pos.y % 4) * 8 + (pixel_pos.x % 8);
|
||||
return (1u << lane_index);
|
||||
}
|
||||
|
||||
#define TILE_META_DATA_CLEAR_MASK 1
|
||||
#define TILE_META_DATA_LIGHT_MASK 2
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user