You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

257 lines
8.1 KiB

///
/// FidelityFX Super Resolution (FSR) Common Shader Code
///
/// This file provides shader helper functions which are intended to be used with the C# helper functions in
/// FSRUtils.cs. The main purpose of this file is to simplify the usage of the external FSR shader functions within
/// the Unity shader environment.
///
/// Usage:
/// - Call SetXConstants function on a command buffer in C#
/// - Launch shader (via draw or dispatch)
/// - Call associated ApplyX function provided by this file
///
/// The following preprocessor parameters MUST be defined before including this file:
/// - FSR_INPUT_TEXTURE
/// - The texture to use as input for the FSR passes
/// - FSR_INPUT_SAMPLER
/// - The sample to use for FSR_INPUT_TEXTURE
///
/// The following preprocessor parameters are optional and MAY be defined before including this file:
/// - FSR_ENABLE_ALPHA
/// - Enables alpha pass-through functionality for the RCAS pass
///
// Ensure that the shader including this file is targeting an adequate shader level
#if SHADER_TARGET < 45
#error FidelityFX Super Resolution requires a shader target of 4.5 or greater
#endif
// Indicate that we'll be using the HLSL implementation of FSR
#define A_GPU 1
#define A_HLSL 1
// Enable either the 16-bit or the 32-bit implementation of FSR depending on platform support
// Note: There are known issues relating to the math approximation functions on some DX11 drivers when FP16 is used.
// Due to this issue, we currently prevent the 16-bit implementation from being used when DX11 is detected.
#if REAL_IS_HALF && !defined(SHADER_API_D3D11)
#define A_HALF
#define FSR_EASU_H 1
#define FSR_RCAS_H 1
#else
#define FSR_EASU_F 1
#define FSR_RCAS_F 1
#endif
// Enable the RCAS passthrough alpha feature when the alpha channel is in use
#if FSR_ENABLE_ALPHA
#define FSR_RCAS_PASSTHROUGH_ALPHA 1
#endif
// Include the external FSR HLSL files
#include "Packages/com.unity.render-pipelines.core/Runtime/PostProcessing/Shaders/ffx/ffx_a.hlsl"
#include "Packages/com.unity.render-pipelines.core/Runtime/PostProcessing/Shaders/ffx/ffx_fsr1.hlsl"
/// Bindings for FSR EASU constants provided by the CPU
///
/// Helper functions that set these constants can be found in FSRUtils
float4 _FsrEasuConstants0;
float4 _FsrEasuConstants1;
float4 _FsrEasuConstants2;
float4 _FsrEasuConstants3;
// Unity doesn't currently have a way to bind uint4 types so we reinterpret float4 as uint4 using macros below
#define FSR_EASU_CONSTANTS_0 asuint(_FsrEasuConstants0)
#define FSR_EASU_CONSTANTS_1 asuint(_FsrEasuConstants1)
#define FSR_EASU_CONSTANTS_2 asuint(_FsrEasuConstants2)
#define FSR_EASU_CONSTANTS_3 asuint(_FsrEasuConstants3)
/// EASU glue functions
///
/// These are used by the EASU implementation to access texture data
#if FSR_EASU_H
AH4 FsrEasuRH(AF2 p)
{
#ifdef FSR_CLAMP_COORD
p = FSR_CLAMP_COORD(p);
#endif
return (AH4)GATHER_RED_TEXTURE2D_X(FSR_INPUT_TEXTURE, FSR_INPUT_SAMPLER, p);
}
AH4 FsrEasuGH(AF2 p)
{
#ifdef FSR_CLAMP_COORD
p = FSR_CLAMP_COORD(p);
#endif
return (AH4)GATHER_GREEN_TEXTURE2D_X(FSR_INPUT_TEXTURE, FSR_INPUT_SAMPLER, p);
}
AH4 FsrEasuBH(AF2 p)
{
#ifdef FSR_CLAMP_COORD
p = FSR_CLAMP_COORD(p);
#endif
return (AH4)GATHER_BLUE_TEXTURE2D_X(FSR_INPUT_TEXTURE, FSR_INPUT_SAMPLER, p);
}
void FsrEasuProcessInput(inout AH4 r, inout AH4 g, inout AH4 b)
{
// HDRP only. URP use an upscaling pass before EASU pass where this operation can be done.
#ifdef HDR_INPUT
AH3 s0 = FastTonemap(AH3(r.x, g.x, b.x) * FSR_EASU_ONE_OVER_PAPER_WHITE);
AH3 s1 = FastTonemap(AH3(r.y, g.y, b.y) * FSR_EASU_ONE_OVER_PAPER_WHITE);
AH3 s2 = FastTonemap(AH3(r.z, g.z, b.z) * FSR_EASU_ONE_OVER_PAPER_WHITE);
AH3 s3 = FastTonemap(AH3(r.w, g.w, b.w) * FSR_EASU_ONE_OVER_PAPER_WHITE);
r = AH4(s0.r, s1.r, s2.r, s3.r);
g = AH4(s0.g, s1.g, s2.g, s3.g);
b = AH4(s0.b, s1.b, s2.b, s3.b);
#endif
}
#else
AF4 FsrEasuRF(AF2 p)
{
#ifdef FSR_CLAMP_COORD
p = FSR_CLAMP_COORD(p);
#endif
return GATHER_RED_TEXTURE2D_X(FSR_INPUT_TEXTURE, FSR_INPUT_SAMPLER, p);
}
AF4 FsrEasuGF(AF2 p)
{
#ifdef FSR_CLAMP_COORD
p = FSR_CLAMP_COORD(p);
#endif
return GATHER_GREEN_TEXTURE2D_X(FSR_INPUT_TEXTURE, FSR_INPUT_SAMPLER, p);
}
AF4 FsrEasuBF(AF2 p)
{
#ifdef FSR_CLAMP_COORD
p = FSR_CLAMP_COORD(p);
#endif
return GATHER_BLUE_TEXTURE2D_X(FSR_INPUT_TEXTURE, FSR_INPUT_SAMPLER, p);
}
void FsrEasuProcessInput(inout AF4 r, inout AF4 g, inout AF4 b)
{
// HDRP only. URP use an upscaling pass before EASU pass where this operation can be done.
#ifdef HDR_INPUT
#ifndef FSR_EASU_ONE_OVER_PAPER_WHITE
#error missing definition of FSR_EASU_ONE_OVER_PAPER_WHITE
#endif
float3 s0 = FastTonemap(float3(r.x, g.x, b.x) * FSR_EASU_ONE_OVER_PAPER_WHITE);
float3 s1 = FastTonemap(float3(r.y, g.y, b.y) * FSR_EASU_ONE_OVER_PAPER_WHITE);
float3 s2 = FastTonemap(float3(r.z, g.z, b.z) * FSR_EASU_ONE_OVER_PAPER_WHITE);
float3 s3 = FastTonemap(float3(r.w, g.w, b.w) * FSR_EASU_ONE_OVER_PAPER_WHITE);
r = float4(s0.r, s1.r, s2.r, s3.r);
g = float4(s0.g, s1.g, s2.g, s3.g);
b = float4(s0.b, s1.b, s2.b, s3.b);
#endif
}
#endif
/// Applies FidelityFX Super Resolution Edge Adaptive Spatial Upsampling at the provided pixel position
///
/// The source texture must be provided before this file is included via the FSR_INPUT_TEXTURE preprocessor symbol
/// Ex: #define FSR_INPUT_TEXTURE _SourceTex
///
/// A valid sampler must also be provided via the FSR_INPUT_SAMPLER preprocessor symbol
/// Ex: #define FSR_INPUT_SAMPLER sampler_LinearClamp
///
/// The color data stored in the source texture should be in gamma 2.0 color space
real3 ApplyEASU(uint2 positionSS)
{
#if FSR_EASU_H
// Execute 16-bit EASU
AH3 color;
FsrEasuH(
#else
// Execute 32-bit EASU
AF3 color;
FsrEasuF(
#endif
color, positionSS, FSR_EASU_CONSTANTS_0, FSR_EASU_CONSTANTS_1, FSR_EASU_CONSTANTS_2, FSR_EASU_CONSTANTS_3
);
return color;
}
/// Bindings for FSR RCAS constants provided by the CPU
///
/// Helper functions that set these constants can be found in FSRUtils
float4 _FsrRcasConstants;
// Unity doesn't currently have a way to bind uint4 types so we reinterpret float4 as uint4 using macros below
#define FSR_RCAS_CONSTANTS asuint(_FsrRcasConstants)
/// RCAS glue functions
///
/// These are used by the RCAS implementation to access texture data and perform color space conversion if necessary
#if FSR_RCAS_H
AH4 FsrRcasLoadH(ASW2 p)
{
return (AH4)LOAD_TEXTURE2D_X(FSR_INPUT_TEXTURE, p);
}
void FsrRcasInputH(inout AH1 r, inout AH1 g, inout AH1 b)
{
// No conversion to linear necessary since it's always performed during EASU output
}
#else
AF4 FsrRcasLoadF(ASU2 p)
{
return LOAD_TEXTURE2D_X(FSR_INPUT_TEXTURE, p);
}
void FsrRcasInputF(inout AF1 r, inout AF1 g, inout AF1 b)
{
// No conversion to linear necessary since it's always performed during EASU output
}
#endif
/// Applies FidelityFX Super Resolution Robust Contrast Adaptive Sharpening at the provided pixel position
///
/// The source texture must be provided before this file is included via the FSR_INPUT_TEXTURE preprocessor symbol
/// Ex: #define FSR_INPUT_TEXTURE _SourceTex
///
/// A valid sampler must also be provided via the FSR_INPUT_SAMPLER preprocessor symbol
/// Ex: #define FSR_INPUT_SAMPLER sampler_LinearClamp
///
/// RCAS supports an optional alpha passthrough that can be enabled via the FSR_ENABLE_ALPHA preprocessor symbol
/// When passthrough is enabled, this function will return the input texture's alpha channel unmodified
///
/// The color data stored in the source texture should be in linear color space
#if FSR_ENABLE_ALPHA
real4 ApplyRCAS(uint2 positionSS)
#else
real3 ApplyRCAS(uint2 positionSS)
#endif
{
#if FSR_RCAS_H
// Execute 16-bit RCAS
#if FSR_ENABLE_ALPHA
AH4 color;
#else
AH3 color;
#endif
FsrRcasH(
#else
// Execute 32-bit RCAS
#if FSR_ENABLE_ALPHA
AF4 color;
#else
AF3 color;
#endif
FsrRcasF(
#endif
color.r,
color.g,
color.b,
#if FSR_ENABLE_ALPHA
color.a,
#endif
positionSS,
FSR_RCAS_CONSTANTS
);
return color;
}