A game about forced loneliness, made by TACStudios
1using System;
2using Unity.Collections;
3using UnityEngine.Experimental.Rendering;
4
5namespace UnityEngine.Rendering
6{
7 /// <summary>
8 /// Utility functions relating to FidelityFX Super Resolution (FSR)
9 ///
10 /// These functions are expected to be used in conjuction with the helper functions provided by FSRCommon.hlsl.
11 /// </summary>
12 public static class FSRUtils
13 {
14 /// Shader constant ids used to communicate with the FSR shader implementation
15 static class ShaderConstants
16 {
17 // EASU
18 public static readonly int _FsrEasuConstants0 = Shader.PropertyToID("_FsrEasuConstants0");
19 public static readonly int _FsrEasuConstants1 = Shader.PropertyToID("_FsrEasuConstants1");
20 public static readonly int _FsrEasuConstants2 = Shader.PropertyToID("_FsrEasuConstants2");
21 public static readonly int _FsrEasuConstants3 = Shader.PropertyToID("_FsrEasuConstants3");
22
23 // RCAS
24 public static readonly int _FsrRcasConstants = Shader.PropertyToID("_FsrRcasConstants");
25 }
26
27 /// <summary>
28 /// Sets the constant values required by the FSR EASU shader on the provided command buffer
29 ///
30 /// Logic ported from "FsrEasuCon()" in Runtime/PostProcessing/Shaders/ffx/ffx_fsr1.hlsl
31 /// </summary>
32 /// <param name="cmd">Command buffer to modify</param>
33 /// <param name="inputViewportSizeInPixels">This the rendered image resolution being upscaled</param>
34 /// <param name="inputImageSizeInPixels">This is the resolution of the resource containing the input image (useful for dynamic resolution)</param>
35 /// <param name="outputImageSizeInPixels">This is the display resolution which the input image gets upscaled to</param>
36 public static void SetEasuConstants(CommandBuffer cmd, Vector2 inputViewportSizeInPixels, Vector2 inputImageSizeInPixels, Vector2 outputImageSizeInPixels)
37 {
38 Vector4 constants0;
39 Vector4 constants1;
40 Vector4 constants2;
41 Vector4 constants3;
42
43 // Output integer position to a pixel position in viewport.
44 constants0.x = (inputViewportSizeInPixels.x / outputImageSizeInPixels.x);
45 constants0.y = (inputViewportSizeInPixels.y / outputImageSizeInPixels.y);
46 constants0.z = (0.5f * inputViewportSizeInPixels.x / outputImageSizeInPixels.x - 0.5f);
47 constants0.w = (0.5f * inputViewportSizeInPixels.y / outputImageSizeInPixels.y - 0.5f);
48
49 // Viewport pixel position to normalized image space.
50 // This is used to get upper-left of 'F' tap.
51 constants1.x = (1.0f / inputImageSizeInPixels.x);
52 constants1.y = (1.0f / inputImageSizeInPixels.y);
53
54 // Centers of gather4, first offset from upper-left of 'F'.
55 // +---+---+
56 // | | |
57 // +--(0)--+
58 // | b | c |
59 // +---F---+---+---+
60 // | e | f | g | h |
61 // +--(1)--+--(2)--+
62 // | i | j | k | l |
63 // +---+---+---+---+
64 // | n | o |
65 // +--(3)--+
66 // | | |
67 // +---+---+
68 constants1.z = (1.0f / inputImageSizeInPixels.x);
69 constants1.w = (-1.0f / inputImageSizeInPixels.y);
70
71 // These are from (0) instead of 'F'.
72 constants2.x = (-1.0f / inputImageSizeInPixels.x);
73 constants2.y = (2.0f / inputImageSizeInPixels.y);
74 constants2.z = (1.0f / inputImageSizeInPixels.x);
75 constants2.w = (2.0f / inputImageSizeInPixels.y);
76
77 constants3.x = (0.0f / inputImageSizeInPixels.x);
78 constants3.y = (4.0f / inputImageSizeInPixels.y);
79
80 // Fill the last constant with zeros to avoid using uninitialized memory
81 constants3.z = 0.0f;
82 constants3.w = 0.0f;
83
84 cmd.SetGlobalVector(ShaderConstants._FsrEasuConstants0, constants0);
85 cmd.SetGlobalVector(ShaderConstants._FsrEasuConstants1, constants1);
86 cmd.SetGlobalVector(ShaderConstants._FsrEasuConstants2, constants2);
87 cmd.SetGlobalVector(ShaderConstants._FsrEasuConstants3, constants3);
88 }
89
90 /// <summary>
91 /// Sets the constant values required by the FSR EASU shader on the provided command buffer
92 ///
93 /// Logic ported from "FsrEasuCon()" in Runtime/PostProcessing/Shaders/ffx/ffx_fsr1.hlsl
94 /// </summary>
95 /// <param name="cmd">RasterCommandBuffer/ComputeCommandBuffer/UnsafeCommandBuffer to modify</param>
96 /// <param name="inputViewportSizeInPixels">This the rendered image resolution being upscaled</param>
97 /// <param name="inputImageSizeInPixels">This is the resolution of the resource containing the input image (useful for dynamic resolution)</param>
98 /// <param name="outputImageSizeInPixels">This is the display resolution which the input image gets upscaled to</param>
99 public static void SetEasuConstants(BaseCommandBuffer cmd, Vector2 inputViewportSizeInPixels,
100 Vector2 inputImageSizeInPixels, Vector2 outputImageSizeInPixels)
101 {
102 SetEasuConstants(cmd.m_WrappedCommandBuffer, inputViewportSizeInPixels, inputImageSizeInPixels, outputImageSizeInPixels);
103 }
104
105 /// <summary>
106 /// The maximum sharpness value in stops before the effect of RCAS is no longer visible.
107 /// This value is used to map between linear and stops.
108 /// </summary>
109 internal const float kMaxSharpnessStops = 2.5f;
110
111 /// <summary>
112 /// AMD's FidelityFX Super Resolution integration guide recommends a value of 0.2 for the RCAS sharpness parameter when specified in stops
113 /// </summary>
114 public const float kDefaultSharpnessStops = 0.2f;
115
116 /// <summary>
117 /// The default RCAS sharpness parameter as a linear value
118 /// </summary>
119 public const float kDefaultSharpnessLinear = (1.0f - (kDefaultSharpnessStops / kMaxSharpnessStops));
120
121 /// <summary>
122 /// Sets the constant values required by the FSR RCAS shader on the provided command buffer
123 ///
124 /// Logic ported from "FsrRcasCon()" in Runtime/PostProcessing/Shaders/ffx/ffx_fsr1.hlsl
125 /// For a more user-friendly version of this function, see SetRcasConstantsLinear().
126 /// </summary>
127 /// <param name="cmd">Command buffer to modify</param>
128 /// <param name="sharpnessStops">The scale is {0.0 := maximum, to N>0, where N is the number of stops(halving) of the reduction of sharpness</param>
129 public static void SetRcasConstants(CommandBuffer cmd, float sharpnessStops = kDefaultSharpnessStops)
130 {
131 // Transform from stops to linear value.
132 float sharpnessLinear = Mathf.Pow(2.0f, -sharpnessStops);
133
134 Vector4 constants;
135
136 uint sharpnessAsHalf = Mathf.FloatToHalf(sharpnessLinear);
137 int packedSharpness = (int)(sharpnessAsHalf | (sharpnessAsHalf << 16));
138 float packedSharpnessAsFloat = BitConverter.Int32BitsToSingle(packedSharpness);
139
140 constants.x = sharpnessLinear;
141 constants.y = packedSharpnessAsFloat;
142
143 // Fill the last constant with zeros to avoid using uninitialized memory
144 constants.z = 0.0f;
145 constants.w = 0.0f;
146
147 cmd.SetGlobalVector(ShaderConstants._FsrRcasConstants, constants);
148 }
149
150 /// <summary>
151 /// Sets the constant values required by the FSR RCAS shader on the provided command buffer
152 ///
153 /// Equivalent to SetRcasConstants(), but handles the sharpness parameter as a linear value instead of one specified in stops.
154 /// This is intended to simplify code that allows users to configure the sharpening behavior from a GUI.
155 /// </summary>
156 /// <param name="cmd">Command buffer to modify</param>
157 /// <param name="sharpnessLinear">The level of intensity of the sharpening filter where 0.0 is the least sharp and 1.0 is the most sharp</param>
158 public static void SetRcasConstantsLinear(CommandBuffer cmd, float sharpnessLinear = kDefaultSharpnessLinear)
159 {
160 // Ensure that the input value is between 0.0 and 1.0 prevent incorrect results
161 Assertions.Assert.IsTrue((sharpnessLinear >= 0.0f) && (sharpnessLinear <= 1.0f));
162
163 float sharpnessStops = (1.0f - sharpnessLinear) * kMaxSharpnessStops;
164
165 SetRcasConstants(cmd, sharpnessStops);
166 }
167
168 /// <summary>
169 /// Sets the constant values required by the FSR RCAS shader on the provided command buffer
170 ///
171 /// Equivalent to SetRcasConstants(), but handles the sharpness parameter as a linear value instead of one specified in stops.
172 /// This is intended to simplify code that allows users to configure the sharpening behavior from a GUI.
173 /// </summary>
174 /// <param name="cmd">RasterCommandBuffer to modify</param>
175 /// <param name="sharpnessLinear">The level of intensity of the sharpening filter where 0.0 is the least sharp and 1.0 is the most sharp</param>
176 public static void SetRcasConstantsLinear(RasterCommandBuffer cmd, float sharpnessLinear = kDefaultSharpnessLinear)
177 {
178 SetRcasConstantsLinear(cmd.m_WrappedCommandBuffer, sharpnessLinear);
179 }
180
181 /// <summary>
182 /// Returns true if FidelityFX Super Resolution (FSR) is supported on the current system
183 /// FSR requires the textureGather shader instruction which wasn't supported by OpenGL ES until version 3.1
184 /// </summary>
185 /// <returns>True if supported</returns>
186 public static bool IsSupported()
187 {
188 return SystemInfo.graphicsShaderLevel >= 45;
189 }
190 }
191}