Compare commits

...

24 Commits

Author SHA1 Message Date
Nico de Poel a0b519ff66 Reworked pass base class so it doesn't impose a dispatch method signature, as that proved to be too restrictive. Instead made adding a profiler sample easier using a disposable struct. 2 years ago
Nico de Poel 5944893e4b Renamed UNITY_FSR_ keywords and macros to UNITY_FFX_ to reflect that they're to be commonly used by all sorts of FidelityFX shaders. 2 years ago
Nico de Poel 8d289fdfa7 Renamed ffx_fsr_unity_common include file to ffx_unity_common, so it can be more generally used for all sorts of FidelityFX shaders. 2 years ago
Nico de Poel 80f42cae73 Struct constraint on dispatch parameters can now be enforced 2 years ago
Nico de Poel 33f410125f Minor cleanup 2 years ago
Nico de Poel 452f9e13a9 Turned all dispatch descriptions into structs with a default value, applied in-parameters wherever appropriate, renamed a few things, and made pass references use the most derived type. 2 years ago
Nico de Poel 43e0f15ab8 Made the pass classes sealed, which is a more sensible way to please the compiler about using virtual methods inside constructors. 2 years ago
Nico de Poel 371743ca70 Applied in-parameter for context and dispatch descriptions more consistently 2 years ago
Nico de Poel b565ca029f Made flags a field of the FfxPassWithFlags class, obviating the need to hold on to a context description copy, or the need to pass flags around. 2 years ago
Nico de Poel 3e4e0bb003 Moved SetupDeviceDepthToViewSpaceDepthParams to the common FfxUtils class 2 years ago
Nico de Poel 74a127a40d Further generalized SPD constants and setup 2 years ago
Nico de Poel d583c750d2 Moved SPD setup method into a separate common FfxSpd class 2 years ago
Nico de Poel 328011f7ba Added profiling samplers around the entire FSR2/3 process 2 years ago
Nico de Poel c5130f8236 Renamed frameIndex to bufferIndex 2 years ago
Nico de Poel 3e91f84cf8 Simplified handling of compute buffer data by wrapping it inside a helper class 2 years ago
Nico de Poel 19a74fee45 Created an abstract base class for context objects, with a few common helper methods 2 years ago
Nico de Poel c33ec9d4ed Further abstracted base pass class to allow for passes without shader keyword flags, and to allow custom kernel names. 2 years ago
Nico de Poel 7c923f8ce8 Renamed frameIndex to bufferIndex, which works in all contexts and makes it more clear that it'll be used as an array index 2 years ago
Nico de Poel 13b9b98318 Created additional extension methods to bind various compute shader resources, to make the dispatching code a lot more straightforward. 2 years ago
Nico de Poel 15b380eebf Abstracted some of the common pass code into a new base class for passes. 2 years ago
Nico de Poel 2d446333c1 Created additional shared helped methods for creating lookup textures and the Lanczos2 LUT 2 years ago
Nico de Poel 3bb3d78610 Refactored resource creation to make use of shared helped methods 2 years ago
Nico de Poel 6219d6159d Moved all create/destroy methods for various types of resources to a new common base class 2 years ago
Nico de Poel 9f06f24943 Moved a number of shared static helper methods to a new FfxUtils class 2 years ago
  1. 57
      Runtime/Common/FfxContextBase.cs
  2. 11
      Runtime/Common/FfxContextBase.cs.meta
  3. 79
      Runtime/Common/FfxPassBase.cs
  4. 11
      Runtime/Common/FfxPassBase.cs.meta
  5. 96
      Runtime/Common/FfxResourcesBase.cs
  6. 11
      Runtime/Common/FfxResourcesBase.cs.meta
  7. 46
      Runtime/Common/FfxSpd.cs
  8. 11
      Runtime/Common/FfxSpd.cs.meta
  9. 118
      Runtime/Common/FfxUtils.cs
  10. 11
      Runtime/Common/FfxUtils.cs.meta
  11. 90
      Runtime/FSR2/Fsr2.cs
  12. 265
      Runtime/FSR2/Fsr2Context.cs
  13. 263
      Runtime/FSR2/Fsr2Pass.cs
  14. 89
      Runtime/FSR2/Fsr2Resources.cs
  15. 90
      Runtime/FSR3/Fsr3Upscaler.cs
  16. 1
      Runtime/FSR3/Fsr3UpscalerAssets.cs
  17. 295
      Runtime/FSR3/Fsr3UpscalerContext.cs
  18. 326
      Runtime/FSR3/Fsr3UpscalerPass.cs
  19. 93
      Runtime/FSR3/Fsr3UpscalerResources.cs
  20. 4
      Shaders/ffx_fsr2_accumulate_pass.compute
  21. 4
      Shaders/ffx_fsr2_autogen_reactive_pass.compute
  22. 4
      Shaders/ffx_fsr2_compute_luminance_pyramid_pass.compute
  23. 4
      Shaders/ffx_fsr2_depth_clip_pass.compute
  24. 4
      Shaders/ffx_fsr2_lock_pass.compute
  25. 4
      Shaders/ffx_fsr2_rcas_pass.compute
  26. 4
      Shaders/ffx_fsr2_reconstruct_previous_depth_pass.compute
  27. 4
      Shaders/ffx_fsr2_tcr_autogen_pass.compute
  28. 4
      Shaders/ffx_fsr3upscaler_accumulate_pass.compute
  29. 4
      Shaders/ffx_fsr3upscaler_autogen_reactive_pass.compute
  30. 4
      Shaders/ffx_fsr3upscaler_debug_view_pass.compute
  31. 4
      Shaders/ffx_fsr3upscaler_luma_instability_pass.compute
  32. 4
      Shaders/ffx_fsr3upscaler_luma_pyramid_pass.compute
  33. 4
      Shaders/ffx_fsr3upscaler_prepare_inputs_pass.compute
  34. 4
      Shaders/ffx_fsr3upscaler_prepare_reactivity_pass.compute
  35. 4
      Shaders/ffx_fsr3upscaler_rcas_pass.compute
  36. 4
      Shaders/ffx_fsr3upscaler_shading_change_pass.compute
  37. 4
      Shaders/ffx_fsr3upscaler_shading_change_pyramid_pass.compute
  38. 4
      Shaders/ffx_fsr3upscaler_tcr_autogen_pass.compute
  39. 12
      Shaders/ffx_unity_common.cginc
  40. 0
      Shaders/ffx_unity_common.cginc.meta
  41. 48
      Shaders/shaders/fsr2/ffx_fsr2_callbacks_hlsl.h
  42. 60
      Shaders/shaders/fsr3upscaler/ffx_fsr3upscaler_callbacks_hlsl.h

57
Runtime/Common/FfxContextBase.cs

@ -0,0 +1,57 @@
using System;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.Rendering;
namespace FidelityFX
{
public abstract class FfxContextBase
{
protected static void DestroyPass<TPass>(ref TPass pass)
where TPass: class, IDisposable
{
if (pass == null)
return;
pass.Dispose();
pass = null;
}
/// <summary>
/// Convenience class for handling a constants buffer containing a single struct item.
/// This wraps the compute buffer and the value array, as well as providing easy access to both.
/// </summary>
protected class ConstantsBuffer<TConst>
where TConst: struct
{
private ComputeBuffer _computeBuffer;
private readonly TConst[] _constArray = { new TConst() };
public ref TConst Value => ref _constArray[0];
public void Create()
{
_computeBuffer = new ComputeBuffer(1, Marshal.SizeOf<TConst>(), ComputeBufferType.Constant);
}
public void UpdateBufferData(CommandBuffer commandBuffer)
{
commandBuffer.SetBufferData(_computeBuffer, _constArray);
}
public void Destroy()
{
if (_computeBuffer == null)
return;
_computeBuffer.Release();
_computeBuffer = null;
}
public static implicit operator ComputeBuffer(ConstantsBuffer<TConst> constants)
{
return constants._computeBuffer;
}
}
}
}

11
Runtime/Common/FfxContextBase.cs.meta

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f4aeccbeb6e61434eb2e50b7190fda8d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

79
Runtime/Common/FfxPassBase.cs

@ -0,0 +1,79 @@
using System;
using UnityEngine;
using UnityEngine.Profiling;
using UnityEngine.Rendering;
namespace FidelityFX
{
internal abstract class FfxPassBase: IDisposable
{
private readonly string _techName;
private string _passName;
protected ComputeShader ComputeShader;
protected int KernelIndex;
protected FfxPassBase(string techName)
{
_techName = techName;
}
protected virtual void InitComputeShader(string passName, ComputeShader shader, string kernelName = "CS")
{
if (shader == null)
{
throw new MissingReferenceException($"Shader for {_techName} pass '{passName}' could not be loaded! Please ensure it is included in the project correctly.");
}
_passName = passName;
ComputeShader = shader;
KernelIndex = ComputeShader.FindKernel(kernelName);
}
public virtual void Dispose()
{
}
protected ProfilerSampler ProfilerSample(CommandBuffer commandBuffer)
{
return new ProfilerSampler(_passName, commandBuffer);
}
protected readonly struct ProfilerSampler : IDisposable
{
private readonly string _name;
private readonly CommandBuffer _commandBuffer;
public ProfilerSampler(string name, CommandBuffer commandBuffer)
{
_name = name;
_commandBuffer = commandBuffer;
_commandBuffer.BeginSample(_name);
}
public void Dispose()
{
_commandBuffer.EndSample(_name);
}
}
}
internal abstract class FfxPassWithFlags<TFlags> : FfxPassBase
where TFlags: Enum
{
protected readonly TFlags Flags;
protected FfxPassWithFlags(string techName, TFlags flags) : base(techName)
{
Flags = flags;
}
protected override void InitComputeShader(string passName, ComputeShader shader, string kernelName = "CS")
{
base.InitComputeShader(passName, shader, kernelName);
SetupShaderKeywords();
}
protected abstract void SetupShaderKeywords();
}
}

11
Runtime/Common/FfxPassBase.cs.meta

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: deac9cc5a4c6df64db05956030e79425
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

96
Runtime/Common/FfxResourcesBase.cs

@ -0,0 +1,96 @@
using System;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.Experimental.Rendering;
namespace FidelityFX
{
internal abstract class FfxResourcesBase
{
protected static ComputeBuffer CreateBuffer<TElem>(string name, int count)
{
return new ComputeBuffer(count, Marshal.SizeOf<TElem>());
}
protected static Texture2D CreateLookup(string name, GraphicsFormat format, Color data)
{
var tex = new Texture2D(1, 1, format, TextureCreationFlags.None) { name = name };
tex.SetPixel(0, 0, data);
tex.Apply();
return tex;
}
protected static Texture2D CreateLookup<T>(string name, in Vector2Int size, GraphicsFormat format, T[] data)
{
var tex = new Texture2D(size.x, size.y, format, TextureCreationFlags.None) { name = name };
tex.SetPixelData(data, 0);
tex.Apply();
return tex;
}
protected static RenderTexture CreateResource(string name, in Vector2Int size, GraphicsFormat format)
{
var rt = new RenderTexture(size.x, size.y, 0, format) { name = name, enableRandomWrite = true };
rt.Create();
return rt;
}
protected static RenderTexture CreateResourceMips(string name, in Vector2Int size, GraphicsFormat format)
{
int mipCount = 1 + Mathf.FloorToInt(Mathf.Log(Math.Max(size.x, size.y), 2.0f));
var rt = new RenderTexture(size.x, size.y, 0, format, mipCount) { name = name, enableRandomWrite = true, useMipMap = true, autoGenerateMips = false };
rt.Create();
return rt;
}
protected static void CreateDoubleBufferedResource(RenderTexture[] resource, string name, in Vector2Int size, GraphicsFormat format, int numElements = 2)
{
numElements = Math.Min(resource.Length, numElements);
for (int i = 0; i < numElements; ++i)
{
resource[i] = new RenderTexture(size.x, size.y, 0, format) { name = name + (i + 1), enableRandomWrite = true };
resource[i].Create();
}
}
protected static void DestroyResource(ref Texture2D resource)
{
if (resource == null)
return;
#if UNITY_EDITOR
if (Application.isPlaying && !UnityEditor.EditorApplication.isPaused)
UnityEngine.Object.Destroy(resource);
else
UnityEngine.Object.DestroyImmediate(resource);
#else
UnityEngine.Object.Destroy(resource);
#endif
resource = null;
}
protected static void DestroyResource(ref RenderTexture resource)
{
if (resource == null)
return;
resource.Release();
resource = null;
}
protected static void DestroyResource(ref ComputeBuffer resource)
{
if (resource == null)
return;
resource.Release();
resource = null;
}
protected static void DestroyResource(RenderTexture[] resource)
{
for (int i = 0; i < resource.Length; ++i)
DestroyResource(ref resource[i]);
}
}
}

11
Runtime/Common/FfxResourcesBase.cs.meta

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2a46b97ac72c45545a80a896462e1112
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

46
Runtime/Common/FfxSpd.cs

@ -0,0 +1,46 @@
using System;
using System.Runtime.InteropServices;
using UnityEngine;
namespace FidelityFX
{
public static class FfxSpd
{
public static void SetupSpdConstants(Vector2Int resolution, ref SpdConstants spdConstants, out Vector2Int dispatchThreadGroupCount, int mips = -1)
{
RectInt rectInfo = new RectInt(0, 0, resolution.x, resolution.y);
SpdSetup(rectInfo, out dispatchThreadGroupCount, out Vector2Int workGroupOffset, out Vector2Int numWorkGroupsAndMips, mips);
spdConstants.numWorkGroups = (uint)numWorkGroupsAndMips.x;
spdConstants.mips = (uint)numWorkGroupsAndMips.y;
spdConstants.workGroupOffsetX = (uint)workGroupOffset.x;
spdConstants.workGroupOffsetY = (uint)workGroupOffset.y;
}
public static void SpdSetup(RectInt rectInfo, out Vector2Int dispatchThreadGroupCount, out Vector2Int workGroupOffset, out Vector2Int numWorkGroupsAndMips, int mips = -1)
{
workGroupOffset = new Vector2Int(rectInfo.x / 64, rectInfo.y / 64);
int endIndexX = (rectInfo.x + rectInfo.width - 1) / 64;
int endIndexY = (rectInfo.y + rectInfo.height - 1) / 64;
dispatchThreadGroupCount = new Vector2Int(endIndexX + 1 - workGroupOffset.x, endIndexY + 1 - workGroupOffset.y);
numWorkGroupsAndMips = new Vector2Int(dispatchThreadGroupCount.x * dispatchThreadGroupCount.y, mips);
if (mips < 0)
{
float resolution = Math.Max(rectInfo.width, rectInfo.height);
numWorkGroupsAndMips.y = Math.Min(Mathf.FloorToInt(Mathf.Log(resolution, 2.0f)), 12);
}
}
[Serializable, StructLayout(LayoutKind.Sequential)]
public struct SpdConstants
{
public uint mips;
public uint numWorkGroups;
public uint workGroupOffsetX;
public uint workGroupOffsetY;
}
}
}

11
Runtime/Common/FfxSpd.cs.meta

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: aee0f42dc1676ab4db5c01520b0b925a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

118
Runtime/Common/FfxUtils.cs

@ -0,0 +1,118 @@
using System;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.Rendering;
namespace FidelityFX
{
public static class FfxUtils
{
public static float GetMipmapBiasOffset(int renderWidth, int displayWidth)
{
return Mathf.Log((float)renderWidth / displayWidth, 2.0f) - 1.0f;
}
public static int GetJitterPhaseCount(int renderWidth, int displayWidth)
{
const float basePhaseCount = 8.0f;
int jitterPhaseCount = (int)(basePhaseCount * Mathf.Pow((float)displayWidth / renderWidth, 2.0f));
return jitterPhaseCount;
}
public static void GetJitterOffset(out float outX, out float outY, int index, int phaseCount)
{
outX = Halton((index % phaseCount) + 1, 2) - 0.5f;
outY = Halton((index % phaseCount) + 1, 3) - 0.5f;
}
// Calculate halton number for index and base.
private static float Halton(int index, int @base)
{
float f = 1.0f, result = 0.0f;
for (int currentIndex = index; currentIndex > 0;) {
f /= @base;
result += f * (currentIndex % @base);
currentIndex = (int)Mathf.Floor((float)currentIndex / @base);
}
return result;
}
public static float Lanczos2(float value)
{
return Mathf.Abs(value) < Mathf.Epsilon ? 1.0f : Mathf.Sin(Mathf.PI * value) / (Mathf.PI * value) * (Mathf.Sin(0.5f * Mathf.PI * value) / (0.5f * Mathf.PI * value));
}
public static float[] GenerateLanczos2Table(int width)
{
float[] lanczos2Weights = new float[width];
for (int currentLanczosWidthIndex = 0; currentLanczosWidthIndex < width; ++currentLanczosWidthIndex)
{
float x = 2.0f * currentLanczosWidthIndex / (width - 1);
float y = Lanczos2(x);
lanczos2Weights[currentLanczosWidthIndex] = y;
}
return lanczos2Weights;
}
public static Vector4 SetupDeviceDepthToViewSpaceDepthParams(Vector2Int renderSize, float cameraNear, float cameraFar, float cameraFovAngleVertical, bool inverted, bool infinite)
{
// make sure it has no impact if near and far plane values are swapped in dispatch params
// the flags "inverted" and "infinite" will decide what transform to use
float min = Mathf.Min(cameraNear, cameraFar);
float max = Mathf.Max(cameraNear, cameraFar);
if (inverted)
{
(min, max) = (max, min);
}
float q = max / (min - max);
float d = -1.0f;
Vector4 matrixElemC = new Vector4(q, -1.0f - Mathf.Epsilon, q, 0.0f + Mathf.Epsilon);
Vector4 matrixElemE = new Vector4(q * min, -min - Mathf.Epsilon, q * min, max);
// Revert x and y coords
float aspect = (float)renderSize.x / renderSize.y;
float cotHalfFovY = Mathf.Cos(0.5f * cameraFovAngleVertical) / Mathf.Sin(0.5f * cameraFovAngleVertical);
int matrixIndex = (inverted ? 2 : 0) + (infinite ? 1 : 0);
return new Vector4(
d * matrixElemC[matrixIndex],
matrixElemE[matrixIndex],
aspect / cotHalfFovY,
1.0f / cotHalfFovY);
}
#if !UNITY_2021_1_OR_NEWER
internal static void SetBufferData(this CommandBuffer commandBuffer, ComputeBuffer computeBuffer, Array data)
{
commandBuffer.SetComputeBufferData(computeBuffer, data);
}
#endif
/// <summary>
/// Alternative for CommandBuffer.SetComputeTextureParam that guards against attempts to bind mip levels that don't exist.
/// </summary>
internal static void SetComputeTextureMipParam(this CommandBuffer commandBuffer, ComputeShader computeShader, int kernelIndex, int nameID, Texture texture, int mipLevel)
{
mipLevel = Math.Min(mipLevel, texture.mipmapCount - 1);
commandBuffer.SetComputeTextureParam(computeShader, kernelIndex, nameID, texture, mipLevel);
}
internal static void SetComputeResourceParam(this CommandBuffer commandBuffer, ComputeShader computeShader, int kernelIndex, int nameID, in ResourceView resource)
{
commandBuffer.SetComputeTextureParam(computeShader, kernelIndex, nameID, resource.RenderTarget, resource.MipLevel, resource.SubElement);
}
internal static void SetComputeConstantBufferParam<TBuf>(this CommandBuffer commandBuffer, ComputeShader computeShader, int nameID, ComputeBuffer buffer)
where TBuf: struct
{
commandBuffer.SetComputeConstantBufferParam(computeShader, nameID, buffer, 0, Marshal.SizeOf<TBuf>());
}
}
}

11
Runtime/Common/FfxUtils.cs.meta

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9c5c0f0b987cca64c8dfd8051e09962e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

90
Runtime/FSR2/Fsr2.cs

@ -21,7 +21,6 @@
using System;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.Rendering;
namespace FidelityFX.FSR2
{
@ -80,60 +79,13 @@ namespace FidelityFX.FSR2
}
}
public static void GetRenderResolutionFromQualityMode(
out int renderWidth, out int renderHeight,
int displayWidth, int displayHeight, QualityMode qualityMode)
public static void GetRenderResolutionFromQualityMode(out int renderWidth, out int renderHeight, int displayWidth, int displayHeight, QualityMode qualityMode)
{
float ratio = GetUpscaleRatioFromQualityMode(qualityMode);
renderWidth = Mathf.RoundToInt(displayWidth / ratio);
renderHeight = Mathf.RoundToInt(displayHeight / ratio);
}
public static float GetMipmapBiasOffset(int renderWidth, int displayWidth)
{
return Mathf.Log((float)renderWidth / displayWidth, 2.0f) - 1.0f;
}
public static int GetJitterPhaseCount(int renderWidth, int displayWidth)
{
const float basePhaseCount = 8.0f;
int jitterPhaseCount = (int)(basePhaseCount * Mathf.Pow((float)displayWidth / renderWidth, 2.0f));
return jitterPhaseCount;
}
public static void GetJitterOffset(out float outX, out float outY, int index, int phaseCount)
{
outX = Halton((index % phaseCount) + 1, 2) - 0.5f;
outY = Halton((index % phaseCount) + 1, 3) - 0.5f;
}
// Calculate halton number for index and base.
private static float Halton(int index, int @base)
{
float f = 1.0f, result = 0.0f;
for (int currentIndex = index; currentIndex > 0;) {
f /= @base;
result += f * (currentIndex % @base);
currentIndex = (int)Mathf.Floor((float)currentIndex / @base);
}
return result;
}
public static float Lanczos2(float value)
{
return Mathf.Abs(value) < Mathf.Epsilon ? 1.0f : Mathf.Sin(Mathf.PI * value) / (Mathf.PI * value) * (Mathf.Sin(0.5f * Mathf.PI * value) / (0.5f * Mathf.PI * value));
}
#if !UNITY_2021_1_OR_NEWER
internal static void SetBufferData(this CommandBuffer commandBuffer, ComputeBuffer computeBuffer, Array data)
{
commandBuffer.SetComputeBufferData(computeBuffer, data);
}
#endif
public enum QualityMode
{
NativeAA = 0,
@ -172,7 +124,7 @@ namespace FidelityFX.FSR2
/// <summary>
/// A structure encapsulating the parameters for dispatching the various passes of FidelityFX Super Resolution 2.
/// </summary>
public class DispatchDescription
public struct DispatchDescription
{
public ResourceView Color;
public ResourceView Depth;
@ -199,26 +151,42 @@ namespace FidelityFX.FSR2
// EXPERIMENTAL reactive mask generation parameters
public bool EnableAutoReactive;
public ResourceView ColorOpaqueOnly;
public float AutoTcThreshold = 0.05f;
public float AutoTcScale = 1.0f;
public float AutoReactiveScale = 5.0f;
public float AutoReactiveMax = 0.9f;
public float AutoTcThreshold;
public float AutoTcScale;
public float AutoReactiveScale;
public float AutoReactiveMax;
public static readonly DispatchDescription Default = new DispatchDescription
{
AutoTcThreshold = 0.05f,
AutoTcScale = 1.0f,
AutoReactiveScale = 5.0f,
AutoReactiveMax = 0.9f,
};
}
/// <summary>
/// A structure encapsulating the parameters for automatic generation of a reactive mask.
/// The default values for Scale, CutoffThreshold, BinaryValue and Flags were taken from the FSR2 demo project.
/// </summary>
public class GenerateReactiveDescription
public struct GenerateReactiveDescription
{
public ResourceView ColorOpaqueOnly;
public ResourceView ColorPreUpscale;
public ResourceView OutReactive;
public Vector2Int RenderSize;
public float Scale = 0.5f;
public float CutoffThreshold = 0.2f;
public float BinaryValue = 0.9f;
public GenerateReactiveFlags Flags = GenerateReactiveFlags.ApplyTonemap | GenerateReactiveFlags.ApplyThreshold | GenerateReactiveFlags.UseComponentsMax;
public float Scale;
public float CutoffThreshold;
public float BinaryValue;
public GenerateReactiveFlags Flags;
public static readonly GenerateReactiveDescription Default = new GenerateReactiveDescription
{
Scale = 0.5f,
CutoffThreshold = 0.2f,
BinaryValue = 0.9f,
Flags = GenerateReactiveFlags.ApplyTonemap | GenerateReactiveFlags.ApplyThreshold | GenerateReactiveFlags.UseComponentsMax,
};
}
[Flags]
@ -259,9 +227,7 @@ namespace FidelityFX.FSR2
[Serializable, StructLayout(LayoutKind.Sequential)]
internal struct SpdConstants
{
public uint mips;
public uint numWorkGroups;
public uint workGroupOffsetX, workGroupOffsetY;
public FfxSpd.SpdConstants spd;
public uint renderSizeX, renderSizeY;
}

265
Runtime/FSR2/Fsr2Context.cs

@ -19,8 +19,8 @@
// THE SOFTWARE.
using System;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.Profiling;
using UnityEngine.Rendering;
namespace FidelityFX.FSR2
@ -31,64 +31,52 @@ namespace FidelityFX.FSR2
/// Note that this class does not know anything about Unity render pipelines; all it knows is CommandBuffers and RenderTargetIdentifiers.
/// This should make it suitable for integration with any of the available Unity render pipelines.
/// </summary>
public class Fsr2Context
public class Fsr2Context: FfxContextBase
{
private const int MaxQueuedFrames = 16;
private Fsr2.ContextDescription _contextDescription;
private CommandBuffer _commandBuffer;
private Fsr2Pass _computeLuminancePyramidPass;
private Fsr2Pass _reconstructPreviousDepthPass;
private Fsr2Pass _depthClipPass;
private Fsr2Pass _lockPass;
private Fsr2Pass _accumulatePass;
private Fsr2Pass _sharpenPass;
private Fsr2Pass _generateReactivePass;
private Fsr2Pass _tcrAutogeneratePass;
private Fsr2ComputeLuminancePyramidPass _computeLuminancePyramidPass;
private Fsr2ReconstructPreviousDepthPass _reconstructPreviousDepthPass;
private Fsr2DepthClipPass _depthClipPass;
private Fsr2LockPass _lockPass;
private Fsr2AccumulatePass _accumulatePass;
private Fsr2SharpenPass _sharpenPass;
private Fsr2GenerateReactivePass _generateReactivePass;
private Fsr2TcrAutogeneratePass _tcrAutogeneratePass;
private readonly Fsr2Resources _resources = new Fsr2Resources();
private ComputeBuffer _upscalerConstantsBuffer;
private readonly Fsr2.UpscalerConstants[] _upscalerConstantsArray = { new Fsr2.UpscalerConstants() };
private ref Fsr2.UpscalerConstants UpscalerConsts => ref _upscalerConstantsArray[0];
private ComputeBuffer _spdConstantsBuffer;
private readonly Fsr2.SpdConstants[] _spdConstantsArray = { new Fsr2.SpdConstants() };
private ref Fsr2.SpdConstants SpdConsts => ref _spdConstantsArray[0];
private ComputeBuffer _rcasConstantsBuffer;
private readonly Fsr2.RcasConstants[] _rcasConstantsArray = new Fsr2.RcasConstants[1];
private ref Fsr2.RcasConstants RcasConsts => ref _rcasConstantsArray[0];
private ComputeBuffer _generateReactiveConstantsBuffer;
private readonly Fsr2.GenerateReactiveConstants[] _generateReactiveConstantsArray = { new Fsr2.GenerateReactiveConstants() };
private ref Fsr2.GenerateReactiveConstants GenReactiveConsts => ref _generateReactiveConstantsArray[0];
private ComputeBuffer _tcrAutogenerateConstantsBuffer;
private readonly Fsr2.GenerateReactiveConstants2[] _tcrAutogenerateConstantsArray = { new Fsr2.GenerateReactiveConstants2() };
private ref Fsr2.GenerateReactiveConstants2 TcrAutoGenConsts => ref _tcrAutogenerateConstantsArray[0];
private readonly ConstantsBuffer<Fsr2.UpscalerConstants> _upscalerConstants = new ConstantsBuffer<Fsr2.UpscalerConstants>();
private readonly ConstantsBuffer<Fsr2.SpdConstants> _spdConstants = new ConstantsBuffer<Fsr2.SpdConstants>();
private readonly ConstantsBuffer<Fsr2.RcasConstants> _rcasConstants = new ConstantsBuffer<Fsr2.RcasConstants>();
private readonly ConstantsBuffer<Fsr2.GenerateReactiveConstants> _generateReactiveConstants = new ConstantsBuffer<Fsr2.GenerateReactiveConstants>();
private readonly ConstantsBuffer<Fsr2.GenerateReactiveConstants2> _tcrAutogenerateConstants = new ConstantsBuffer<Fsr2.GenerateReactiveConstants2>();
private bool _firstExecution;
private Vector2 _previousJitterOffset;
private int _resourceFrameIndex;
public void Create(Fsr2.ContextDescription contextDescription)
private readonly CustomSampler _sampler = CustomSampler.Create("FSR2");
public void Create(in Fsr2.ContextDescription contextDescription)
{
_contextDescription = contextDescription;
_commandBuffer = new CommandBuffer { name = "FSR2" };
_upscalerConstantsBuffer = CreateConstantBuffer<Fsr2.UpscalerConstants>();
_spdConstantsBuffer = CreateConstantBuffer<Fsr2.SpdConstants>();
_rcasConstantsBuffer = CreateConstantBuffer<Fsr2.RcasConstants>();
_generateReactiveConstantsBuffer = CreateConstantBuffer<Fsr2.GenerateReactiveConstants>();
_tcrAutogenerateConstantsBuffer = CreateConstantBuffer<Fsr2.GenerateReactiveConstants2>();
_upscalerConstants.Create();
_spdConstants.Create();
_rcasConstants.Create();
_generateReactiveConstants.Create();
_tcrAutogenerateConstants.Create();
// Set defaults
_firstExecution = true;
_resourceFrameIndex = 0;
UpscalerConsts.displaySize = _contextDescription.DisplaySize;
_upscalerConstants.Value.displaySize = _contextDescription.DisplaySize;
_resources.Create(_contextDescription);
CreatePasses();
@ -96,14 +84,14 @@ namespace FidelityFX.FSR2
private void CreatePasses()
{
_computeLuminancePyramidPass = new Fsr2ComputeLuminancePyramidPass(_contextDescription, _resources, _upscalerConstantsBuffer, _spdConstantsBuffer);
_reconstructPreviousDepthPass = new Fsr2ReconstructPreviousDepthPass(_contextDescription, _resources, _upscalerConstantsBuffer);
_depthClipPass = new Fsr2DepthClipPass(_contextDescription, _resources, _upscalerConstantsBuffer);
_lockPass = new Fsr2LockPass(_contextDescription, _resources, _upscalerConstantsBuffer);
_accumulatePass = new Fsr2AccumulatePass(_contextDescription, _resources, _upscalerConstantsBuffer);
_sharpenPass = new Fsr2SharpenPass(_contextDescription, _resources, _upscalerConstantsBuffer, _rcasConstantsBuffer);
_generateReactivePass = new Fsr2GenerateReactivePass(_contextDescription, _resources, _generateReactiveConstantsBuffer);
_tcrAutogeneratePass = new Fsr2TcrAutogeneratePass(_contextDescription, _resources, _upscalerConstantsBuffer, _tcrAutogenerateConstantsBuffer);
_computeLuminancePyramidPass = new Fsr2ComputeLuminancePyramidPass(_contextDescription, _resources, _upscalerConstants, _spdConstants);
_reconstructPreviousDepthPass = new Fsr2ReconstructPreviousDepthPass(_contextDescription, _resources, _upscalerConstants);
_depthClipPass = new Fsr2DepthClipPass(_contextDescription, _resources, _upscalerConstants);
_lockPass = new Fsr2LockPass(_contextDescription, _resources, _upscalerConstants);
_accumulatePass = new Fsr2AccumulatePass(_contextDescription, _resources, _upscalerConstants);
_sharpenPass = new Fsr2SharpenPass(_contextDescription, _resources, _upscalerConstants, _rcasConstants);
_generateReactivePass = new Fsr2GenerateReactivePass(_contextDescription, _resources, _generateReactiveConstants);
_tcrAutogeneratePass = new Fsr2TcrAutogeneratePass(_contextDescription, _resources, _upscalerConstants, _tcrAutogenerateConstants);
}
public void Destroy()
@ -119,11 +107,11 @@ namespace FidelityFX.FSR2
_resources.Destroy();
DestroyConstantBuffer(ref _tcrAutogenerateConstantsBuffer);
DestroyConstantBuffer(ref _generateReactiveConstantsBuffer);
DestroyConstantBuffer(ref _rcasConstantsBuffer);
DestroyConstantBuffer(ref _spdConstantsBuffer);
DestroyConstantBuffer(ref _upscalerConstantsBuffer);
_tcrAutogenerateConstants.Destroy();
_generateReactiveConstants.Destroy();
_rcasConstants.Destroy();
_spdConstants.Destroy();
_upscalerConstants.Destroy();
if (_commandBuffer != null)
{
@ -132,7 +120,7 @@ namespace FidelityFX.FSR2
}
}
public void Dispatch(Fsr2.DispatchDescription dispatchParams)
public void Dispatch(in Fsr2.DispatchDescription dispatchParams)
{
_commandBuffer.Clear();
Dispatch(dispatchParams, _commandBuffer);
@ -141,13 +129,15 @@ namespace FidelityFX.FSR2
public void Dispatch(Fsr2.DispatchDescription dispatchParams, CommandBuffer commandBuffer)
{
commandBuffer.BeginSample(_sampler);
if ((_contextDescription.Flags & Fsr2.InitializationFlags.EnableDebugChecking) != 0)
{
DebugCheckDispatch(dispatchParams);
}
if (dispatchParams.UseTextureArrays)
commandBuffer.EnableShaderKeyword("UNITY_FSR_TEXTURE2D_X_ARRAY");
commandBuffer.EnableShaderKeyword("UNITY_FFX_TEXTURE2D_X_ARRAY");
if (_firstExecution)
{
@ -157,7 +147,7 @@ namespace FidelityFX.FSR2
commandBuffer.ClearRenderTarget(false, true, Color.clear);
}
int frameIndex = _resourceFrameIndex % 2;
int bufferIndex = _resourceFrameIndex % 2;
bool resetAccumulation = dispatchParams.Reset || _firstExecution;
_firstExecution = false;
@ -176,7 +166,7 @@ namespace FidelityFX.FSR2
if (resetAccumulation)
{
RenderTargetIdentifier opaqueOnly = dispatchParams.ColorOpaqueOnly.IsValid ? dispatchParams.ColorOpaqueOnly.RenderTarget : Fsr2ShaderIDs.SrvOpaqueOnly;
commandBuffer.Blit(_resources.PrevPreAlpha[frameIndex ^ 1], opaqueOnly);
commandBuffer.Blit(_resources.PrevPreAlpha[bufferIndex ^ 1], opaqueOnly);
}
}
else if (_resources.AutoReactive != null)
@ -187,24 +177,24 @@ namespace FidelityFX.FSR2
if (!dispatchParams.Reactive.IsValid) dispatchParams.Reactive = new ResourceView(_resources.DefaultReactive);
if (!dispatchParams.TransparencyAndComposition.IsValid) dispatchParams.TransparencyAndComposition = new ResourceView(_resources.DefaultReactive);
Fsr2Resources.CreateAliasableResources(commandBuffer, _contextDescription, dispatchParams);
Fsr2Resources.CreateAliasableResources(commandBuffer, _contextDescription);
SetupConstants(dispatchParams, resetAccumulation);
// Reactive mask bias
const int threadGroupWorkRegionDim = 8;
int dispatchSrcX = (UpscalerConsts.renderSize.x + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
int dispatchSrcY = (UpscalerConsts.renderSize.y + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
int dispatchSrcX = (_upscalerConstants.Value.renderSize.x + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
int dispatchSrcY = (_upscalerConstants.Value.renderSize.y + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
int dispatchDstX = (_contextDescription.DisplaySize.x + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
int dispatchDstY = (_contextDescription.DisplaySize.y + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
// Clear reconstructed depth for max depth store
if (resetAccumulation)
{
commandBuffer.SetRenderTarget(_resources.LockStatus[frameIndex ^ 1]);
commandBuffer.SetRenderTarget(_resources.LockStatus[bufferIndex ^ 1]);
commandBuffer.ClearRenderTarget(false, true, Color.clear);
commandBuffer.SetRenderTarget(_resources.InternalUpscaled[frameIndex ^ 1]);
commandBuffer.SetRenderTarget(_resources.InternalUpscaled[bufferIndex ^ 1]);
commandBuffer.ClearRenderTarget(false, true, Color.clear);
commandBuffer.SetRenderTarget(_resources.SceneLuminance);
@ -220,7 +210,7 @@ namespace FidelityFX.FSR2
}
// FSR3: need to clear here since we need the content of this surface for frame interpolation, so clearing in the lock pass is not an option
bool depthInverted = (_contextDescription.Flags & Fsr2.InitializationFlags.EnableDepthInverted) == Fsr2.InitializationFlags.EnableDepthInverted;
bool depthInverted = (_contextDescription.Flags & Fsr2.InitializationFlags.EnableDepthInverted) != 0;
commandBuffer.SetRenderTarget(Fsr2ShaderIDs.UavReconstructedPrevNearestDepth);
commandBuffer.ClearRenderTarget(false, true, depthInverted ? Color.clear : Color.white);
@ -228,92 +218,95 @@ namespace FidelityFX.FSR2
SetupSpdConstants(dispatchParams, out var dispatchThreadGroupCount);
// Initialize constant buffers data
commandBuffer.SetBufferData(_upscalerConstantsBuffer, _upscalerConstantsArray);
commandBuffer.SetBufferData(_spdConstantsBuffer, _spdConstantsArray);
_upscalerConstants.UpdateBufferData(commandBuffer);
_spdConstants.UpdateBufferData(commandBuffer);
// Auto reactive
if (dispatchParams.EnableAutoReactive)
{
GenerateTransparencyCompositionReactive(dispatchParams, commandBuffer, frameIndex);
GenerateTransparencyCompositionReactive(dispatchParams, commandBuffer, bufferIndex);
dispatchParams.Reactive = new ResourceView(_resources.AutoReactive);
dispatchParams.TransparencyAndComposition = new ResourceView(_resources.AutoComposition);
}
// Compute luminance pyramid
_computeLuminancePyramidPass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchThreadGroupCount.x, dispatchThreadGroupCount.y);
_computeLuminancePyramidPass.ScheduleDispatch(commandBuffer, dispatchParams, bufferIndex, dispatchThreadGroupCount.x, dispatchThreadGroupCount.y);
// Reconstruct previous depth
_reconstructPreviousDepthPass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchSrcX, dispatchSrcY);
_reconstructPreviousDepthPass.ScheduleDispatch(commandBuffer, dispatchParams, bufferIndex, dispatchSrcX, dispatchSrcY);
// Depth clip
_depthClipPass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchSrcX, dispatchSrcY);
_depthClipPass.ScheduleDispatch(commandBuffer, dispatchParams, bufferIndex, dispatchSrcX, dispatchSrcY);
// Create locks
_lockPass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchSrcX, dispatchSrcY);
_lockPass.ScheduleDispatch(commandBuffer, dispatchParams, bufferIndex, dispatchSrcX, dispatchSrcY);
// Accumulate
_accumulatePass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchDstX, dispatchDstY);
_accumulatePass.ScheduleDispatch(commandBuffer, dispatchParams, bufferIndex, dispatchDstX, dispatchDstY);
if (dispatchParams.EnableSharpening)
{
// Compute the constants
SetupRcasConstants(dispatchParams);
commandBuffer.SetBufferData(_rcasConstantsBuffer, _rcasConstantsArray);
_rcasConstants.UpdateBufferData(commandBuffer);
// Dispatch RCAS
const int threadGroupWorkRegionDimRcas = 16;
int threadGroupsX = (Screen.width + threadGroupWorkRegionDimRcas - 1) / threadGroupWorkRegionDimRcas;
int threadGroupsY = (Screen.height + threadGroupWorkRegionDimRcas - 1) / threadGroupWorkRegionDimRcas;
_sharpenPass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, threadGroupsX, threadGroupsY);
_sharpenPass.ScheduleDispatch(commandBuffer, dispatchParams, bufferIndex, threadGroupsX, threadGroupsY);
}
_resourceFrameIndex = (_resourceFrameIndex + 1) % MaxQueuedFrames;
Fsr2Resources.DestroyAliasableResources(commandBuffer);
commandBuffer.DisableShaderKeyword("UNITY_FSR_TEXTURE2D_X_ARRAY");
commandBuffer.DisableShaderKeyword("UNITY_FFX_TEXTURE2D_X_ARRAY");
commandBuffer.EndSample(_sampler);
}
public void GenerateReactiveMask(Fsr2.GenerateReactiveDescription dispatchParams)
public void GenerateReactiveMask(in Fsr2.GenerateReactiveDescription dispatchParams)
{
_commandBuffer.Clear();
GenerateReactiveMask(dispatchParams, _commandBuffer);
Graphics.ExecuteCommandBuffer(_commandBuffer);
}
public void GenerateReactiveMask(Fsr2.GenerateReactiveDescription dispatchParams, CommandBuffer commandBuffer)
public void GenerateReactiveMask(in Fsr2.GenerateReactiveDescription dispatchParams, CommandBuffer commandBuffer)
{
const int threadGroupWorkRegionDim = 8;
int dispatchSrcX = (dispatchParams.RenderSize.x + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
int dispatchSrcY = (dispatchParams.RenderSize.y + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
GenReactiveConsts.scale = dispatchParams.Scale;
GenReactiveConsts.threshold = dispatchParams.CutoffThreshold;
GenReactiveConsts.binaryValue = dispatchParams.BinaryValue;
GenReactiveConsts.flags = (uint)dispatchParams.Flags;
commandBuffer.SetBufferData(_generateReactiveConstantsBuffer, _generateReactiveConstantsArray);
ref var genReactiveConsts = ref _generateReactiveConstants.Value;
genReactiveConsts.scale = dispatchParams.Scale;
genReactiveConsts.threshold = dispatchParams.CutoffThreshold;
genReactiveConsts.binaryValue = dispatchParams.BinaryValue;
genReactiveConsts.flags = (uint)dispatchParams.Flags;
_generateReactiveConstants.UpdateBufferData(commandBuffer);
((Fsr2GenerateReactivePass)_generateReactivePass).ScheduleDispatch(commandBuffer, dispatchParams, dispatchSrcX, dispatchSrcY);
_generateReactivePass.ScheduleDispatch(commandBuffer, dispatchParams, dispatchSrcX, dispatchSrcY);
}
private void GenerateTransparencyCompositionReactive(Fsr2.DispatchDescription dispatchParams, CommandBuffer commandBuffer, int frameIndex)
private void GenerateTransparencyCompositionReactive(in Fsr2.DispatchDescription dispatchParams, CommandBuffer commandBuffer, int bufferIndex)
{
const int threadGroupWorkRegionDim = 8;
int dispatchSrcX = (dispatchParams.RenderSize.x + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
int dispatchSrcY = (dispatchParams.RenderSize.y + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
TcrAutoGenConsts.autoTcThreshold = dispatchParams.AutoTcThreshold;
TcrAutoGenConsts.autoTcScale = dispatchParams.AutoTcScale;
TcrAutoGenConsts.autoReactiveScale = dispatchParams.AutoReactiveScale;
TcrAutoGenConsts.autoReactiveMax = dispatchParams.AutoReactiveMax;
commandBuffer.SetBufferData(_tcrAutogenerateConstantsBuffer, _tcrAutogenerateConstantsArray);
ref var tcrAutoGenConsts = ref _tcrAutogenerateConstants.Value;
tcrAutoGenConsts.autoTcThreshold = dispatchParams.AutoTcThreshold;
tcrAutoGenConsts.autoTcScale = dispatchParams.AutoTcScale;
tcrAutoGenConsts.autoReactiveScale = dispatchParams.AutoReactiveScale;
tcrAutoGenConsts.autoReactiveMax = dispatchParams.AutoReactiveMax;
_tcrAutogenerateConstants.UpdateBufferData(commandBuffer);
_tcrAutogeneratePass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchSrcX, dispatchSrcY);
_tcrAutogeneratePass.ScheduleDispatch(commandBuffer, dispatchParams, bufferIndex, dispatchSrcX, dispatchSrcY);
}
private void SetupConstants(Fsr2.DispatchDescription dispatchParams, bool resetAccumulation)
private void SetupConstants(in Fsr2.DispatchDescription dispatchParams, bool resetAccumulation)
{
ref Fsr2.UpscalerConstants constants = ref UpscalerConsts;
ref Fsr2.UpscalerConstants constants = ref _upscalerConstants.Value;
constants.jitterOffset = dispatchParams.JitterOffset;
constants.renderSize = dispatchParams.RenderSize;
@ -327,7 +320,10 @@ namespace FidelityFX.FSR2
constants.viewSpaceToMetersFactor = (dispatchParams.ViewSpaceToMetersFactor > 0.0f) ? dispatchParams.ViewSpaceToMetersFactor : 1.0f;
// Compute params to enable device depth to view space depth computation in shader
constants.deviceToViewDepth = SetupDeviceDepthToViewSpaceDepthParams(dispatchParams);
bool inverted = (_contextDescription.Flags & Fsr2.InitializationFlags.EnableDepthInverted) != 0;
bool infinite = (_contextDescription.Flags & Fsr2.InitializationFlags.EnableDepthInfinite) != 0;
constants.deviceToViewDepth = FfxUtils.SetupDeviceDepthToViewSpaceDepthParams(
dispatchParams.RenderSize, dispatchParams.CameraNear, dispatchParams.CameraFar, dispatchParams.CameraFovAngleVertical, inverted, infinite);
// To be updated if resource is larger than the actual image size
constants.downscaleFactor = new Vector2((float)constants.renderSize.x / _contextDescription.DisplaySize.x, (float)constants.renderSize.y / _contextDescription.DisplaySize.y);
@ -345,7 +341,7 @@ namespace FidelityFX.FSR2
_previousJitterOffset = constants.jitterOffset;
}
int jitterPhaseCount = Fsr2.GetJitterPhaseCount(dispatchParams.RenderSize.x, _contextDescription.DisplaySize.x);
int jitterPhaseCount = FfxUtils.GetJitterPhaseCount(dispatchParams.RenderSize.x, _contextDescription.DisplaySize.x);
if (resetAccumulation || constants.jitterPhaseCount == 0)
{
constants.jitterPhaseCount = jitterPhaseCount;
@ -375,78 +371,22 @@ namespace FidelityFX.FSR2
constants.lumaMipDimensions.y = (int)(constants.maxRenderSize.y / mipDiv);
}
private Vector4 SetupDeviceDepthToViewSpaceDepthParams(Fsr2.DispatchDescription dispatchParams)
{
bool inverted = (_contextDescription.Flags & Fsr2.InitializationFlags.EnableDepthInverted) != 0;
bool infinite = (_contextDescription.Flags & Fsr2.InitializationFlags.EnableDepthInfinite) != 0;
// make sure it has no impact if near and far plane values are swapped in dispatch params
// the flags "inverted" and "infinite" will decide what transform to use
float min = Mathf.Min(dispatchParams.CameraNear, dispatchParams.CameraFar);
float max = Mathf.Max(dispatchParams.CameraNear, dispatchParams.CameraFar);
if (inverted)
{
(min, max) = (max, min);
}
float q = max / (min - max);
float d = -1.0f;
Vector4 matrixElemC = new Vector4(q, -1.0f - Mathf.Epsilon, q, 0.0f + Mathf.Epsilon);
Vector4 matrixElemE = new Vector4(q * min, -min - Mathf.Epsilon, q * min, max);
// Revert x and y coords
float aspect = (float)dispatchParams.RenderSize.x / dispatchParams.RenderSize.y;
float cotHalfFovY = Mathf.Cos(0.5f * dispatchParams.CameraFovAngleVertical) / Mathf.Sin(0.5f * dispatchParams.CameraFovAngleVertical);
int matrixIndex = (inverted ? 2 : 0) + (infinite ? 1 : 0);
return new Vector4(
d * matrixElemC[matrixIndex],
matrixElemE[matrixIndex],
aspect / cotHalfFovY,
1.0f / cotHalfFovY);
}
private void SetupRcasConstants(Fsr2.DispatchDescription dispatchParams)
private void SetupRcasConstants(in Fsr2.DispatchDescription dispatchParams)
{
int sharpnessIndex = Mathf.RoundToInt(Mathf.Clamp01(dispatchParams.Sharpness) * (RcasConfigs.Length - 1));
RcasConsts = RcasConfigs[sharpnessIndex];
_rcasConstants.Value = RcasConfigs[sharpnessIndex];
}
private void SetupSpdConstants(Fsr2.DispatchDescription dispatchParams, out Vector2Int dispatchThreadGroupCount)
private void SetupSpdConstants(in Fsr2.DispatchDescription dispatchParams, out Vector2Int dispatchThreadGroupCount)
{
RectInt rectInfo = new RectInt(0, 0, dispatchParams.RenderSize.x, dispatchParams.RenderSize.y);
SpdSetup(rectInfo, out dispatchThreadGroupCount, out var workGroupOffset, out var numWorkGroupsAndMips);
// Downsample
ref Fsr2.SpdConstants spdConstants = ref SpdConsts;
spdConstants.numWorkGroups = (uint)numWorkGroupsAndMips.x;
spdConstants.mips = (uint)numWorkGroupsAndMips.y;
spdConstants.workGroupOffsetX = (uint)workGroupOffset.x;
spdConstants.workGroupOffsetY = (uint)workGroupOffset.y;
ref Fsr2.SpdConstants spdConstants = ref _spdConstants.Value;
FfxSpd.SetupSpdConstants(dispatchParams.RenderSize, ref spdConstants.spd, out dispatchThreadGroupCount);
spdConstants.renderSizeX = (uint)dispatchParams.RenderSize.x;
spdConstants.renderSizeY = (uint)dispatchParams.RenderSize.y;
}
private static void SpdSetup(RectInt rectInfo, out Vector2Int dispatchThreadGroupCount, out Vector2Int workGroupOffset, out Vector2Int numWorkGroupsAndMips, int mips = -1)
{
workGroupOffset = new Vector2Int(rectInfo.x / 64, rectInfo.y / 64);
int endIndexX = (rectInfo.x + rectInfo.width - 1) / 64;
int endIndexY = (rectInfo.y + rectInfo.height - 1) / 64;
dispatchThreadGroupCount = new Vector2Int(endIndexX + 1 - workGroupOffset.x, endIndexY + 1 - workGroupOffset.y);
numWorkGroupsAndMips = new Vector2Int(dispatchThreadGroupCount.x * dispatchThreadGroupCount.y, mips);
if (mips < 0)
{
float resolution = Math.Max(rectInfo.width, rectInfo.height);
numWorkGroupsAndMips.y = Math.Min(Mathf.FloorToInt(Mathf.Log(resolution, 2.0f)), 12);
}
}
private void DebugCheckDispatch(Fsr2.DispatchDescription dispatchParams)
private void DebugCheckDispatch(in Fsr2.DispatchDescription dispatchParams)
{
if (!dispatchParams.Color.IsValid)
{
@ -591,28 +531,5 @@ namespace FidelityFX.FSR2
new Fsr2.RcasConstants(1064229695u, 997604214u),
new Fsr2.RcasConstants(1065353216u, 1006648320),
};
private static ComputeBuffer CreateConstantBuffer<TConstants>() where TConstants: struct
{
return new ComputeBuffer(1, Marshal.SizeOf<TConstants>(), ComputeBufferType.Constant);
}
private static void DestroyConstantBuffer(ref ComputeBuffer bufferRef)
{
if (bufferRef == null)
return;
bufferRef.Release();
bufferRef = null;
}
private static void DestroyPass(ref Fsr2Pass pass)
{
if (pass == null)
return;
pass.Dispose();
pass = null;
}
}
}

263
Runtime/FSR2/Fsr2Pass.cs

@ -18,10 +18,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.Profiling;
using UnityEngine.Rendering;
namespace FidelityFX.FSR2
@ -31,55 +28,32 @@ namespace FidelityFX.FSR2
/// This loosely matches the FfxPipelineState struct from the original FSR2 codebase, wrapped in an object-oriented blanket.
/// These classes are responsible for loading compute shaders, managing temporary resources, binding resources to shader kernels and dispatching said shaders.
/// </summary>
internal abstract class Fsr2Pass: IDisposable
internal abstract class Fsr2Pass: FfxPassWithFlags<Fsr2.InitializationFlags>
{
internal const int ShadingChangeMipLevel = 4; // This matches the FFX_FSR2_SHADING_CHANGE_MIP_LEVEL define
protected readonly Fsr2.ContextDescription ContextDescription;
protected readonly Fsr2Resources Resources;
protected readonly ComputeBuffer Constants;
protected ComputeShader ComputeShader;
protected int KernelIndex;
protected CustomSampler Sampler;
protected Fsr2Pass(Fsr2.ContextDescription contextDescription, Fsr2Resources resources, ComputeBuffer constants)
protected Fsr2Pass(in Fsr2.ContextDescription contextDescription, Fsr2Resources resources, ComputeBuffer constants)
: base("FSR2", contextDescription.Flags)
{
ContextDescription = contextDescription;
Resources = resources;
Constants = constants;
}
public virtual void Dispose()
{
}
public void ScheduleDispatch(CommandBuffer commandBuffer, Fsr2.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY)
{
commandBuffer.BeginSample(Sampler);
DoScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchX, dispatchY);
commandBuffer.EndSample(Sampler);
}
protected abstract void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr2.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY);
protected void InitComputeShader(string passName, ComputeShader shader)
{
InitComputeShader(passName, shader, ContextDescription.Flags);
}
private void InitComputeShader(string passName, ComputeShader shader, Fsr2.InitializationFlags flags)
public void ScheduleDispatch(CommandBuffer commandBuffer, in Fsr2.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ = 1)
{
if (shader == null)
using (ProfilerSample(commandBuffer))
{
throw new MissingReferenceException($"Shader for FSR2 pass '{passName}' could not be loaded! Please ensure it is included in the project correctly.");
Dispatch(commandBuffer, dispatchParams, bufferIndex, dispatchX, dispatchY, dispatchZ);
}
}
ComputeShader = shader;
KernelIndex = ComputeShader.FindKernel("CS");
Sampler = CustomSampler.Create(passName);
protected abstract void Dispatch(CommandBuffer commandBuffer, in Fsr2.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ);
protected override void SetupShaderKeywords()
{
bool useLut = false;
#if UNITY_2022_1_OR_NEWER // This will also work in 2020.3.43+ and 2021.3.14+
if (SystemInfo.computeSubGroupSize == 64)
@ -89,20 +63,20 @@ namespace FidelityFX.FSR2
#endif
// This matches the permutation rules from the CreatePipeline* functions
if ((flags & Fsr2.InitializationFlags.EnableHighDynamicRange) != 0) ComputeShader.EnableKeyword("FFX_FSR2_OPTION_HDR_COLOR_INPUT");
if ((flags & Fsr2.InitializationFlags.EnableDisplayResolutionMotionVectors) == 0) ComputeShader.EnableKeyword("FFX_FSR2_OPTION_LOW_RESOLUTION_MOTION_VECTORS");
if ((flags & Fsr2.InitializationFlags.EnableMotionVectorsJitterCancellation) != 0) ComputeShader.EnableKeyword("FFX_FSR2_OPTION_JITTERED_MOTION_VECTORS");
if ((flags & Fsr2.InitializationFlags.EnableDepthInverted) != 0) ComputeShader.EnableKeyword("FFX_FSR2_OPTION_INVERTED_DEPTH");
if ((Flags & Fsr2.InitializationFlags.EnableHighDynamicRange) != 0) ComputeShader.EnableKeyword("FFX_FSR2_OPTION_HDR_COLOR_INPUT");
if ((Flags & Fsr2.InitializationFlags.EnableDisplayResolutionMotionVectors) == 0) ComputeShader.EnableKeyword("FFX_FSR2_OPTION_LOW_RESOLUTION_MOTION_VECTORS");
if ((Flags & Fsr2.InitializationFlags.EnableMotionVectorsJitterCancellation) != 0) ComputeShader.EnableKeyword("FFX_FSR2_OPTION_JITTERED_MOTION_VECTORS");
if ((Flags & Fsr2.InitializationFlags.EnableDepthInverted) != 0) ComputeShader.EnableKeyword("FFX_FSR2_OPTION_INVERTED_DEPTH");
if (useLut) ComputeShader.EnableKeyword("FFX_FSR2_OPTION_REPROJECT_USE_LANCZOS_TYPE");
if ((flags & Fsr2.InitializationFlags.EnableFP16Usage) != 0) ComputeShader.EnableKeyword("FFX_HALF");
if ((Flags & Fsr2.InitializationFlags.EnableFP16Usage) != 0) ComputeShader.EnableKeyword("FFX_HALF");
}
}
internal class Fsr2ComputeLuminancePyramidPass : Fsr2Pass
internal sealed class Fsr2ComputeLuminancePyramidPass : Fsr2Pass
{
private readonly ComputeBuffer _spdConstants;
public Fsr2ComputeLuminancePyramidPass(Fsr2.ContextDescription contextDescription, Fsr2Resources resources, ComputeBuffer constants, ComputeBuffer spdConstants)
public Fsr2ComputeLuminancePyramidPass(in Fsr2.ContextDescription contextDescription, Fsr2Resources resources, ComputeBuffer constants, ComputeBuffer spdConstants)
: base(contextDescription, resources, constants)
{
_spdConstants = spdConstants;
@ -110,104 +84,91 @@ namespace FidelityFX.FSR2
InitComputeShader("Compute Luminance Pyramid", contextDescription.Shaders.computeLuminancePyramidPass);
}
protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr2.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY)
protected override void Dispatch(CommandBuffer commandBuffer, in Fsr2.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ)
{
ref var color = ref dispatchParams.Color;
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputColor, color.RenderTarget, color.MipLevel, color.SubElement);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputColor, dispatchParams.Color);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavSpdAtomicCount, Resources.SpdAtomicCounter);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavExposureMipLumaChange, Resources.SceneLuminance, ShadingChangeMipLevel);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavExposureMip5, Resources.SceneLuminance, 5);
commandBuffer.SetComputeTextureMipParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavExposureMipLumaChange, Resources.SceneLuminance, ShadingChangeMipLevel);
commandBuffer.SetComputeTextureMipParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavExposureMip5, Resources.SceneLuminance, 5);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavAutoExposure, Resources.AutoExposure);
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbFsr2, Constants, 0, Marshal.SizeOf<Fsr2.UpscalerConstants>());
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbSpd, _spdConstants, 0, Marshal.SizeOf<Fsr2.SpdConstants>());
commandBuffer.SetComputeConstantBufferParam<Fsr2.UpscalerConstants>(ComputeShader, Fsr2ShaderIDs.CbFsr2, Constants);
commandBuffer.SetComputeConstantBufferParam<Fsr2.SpdConstants>(ComputeShader, Fsr2ShaderIDs.CbSpd, _spdConstants);
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, dispatchZ);
}
}
internal class Fsr2ReconstructPreviousDepthPass : Fsr2Pass
internal sealed class Fsr2ReconstructPreviousDepthPass : Fsr2Pass
{
public Fsr2ReconstructPreviousDepthPass(Fsr2.ContextDescription contextDescription, Fsr2Resources resources, ComputeBuffer constants)
public Fsr2ReconstructPreviousDepthPass(in Fsr2.ContextDescription contextDescription, Fsr2Resources resources, ComputeBuffer constants)
: base(contextDescription, resources, constants)
{
InitComputeShader("Reconstruct & Dilate", contextDescription.Shaders.reconstructPreviousDepthPass);
}
protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr2.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY)
protected override void Dispatch(CommandBuffer commandBuffer, in Fsr2.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ)
{
ref var color = ref dispatchParams.Color;
ref var depth = ref dispatchParams.Depth;
ref var motionVectors = ref dispatchParams.MotionVectors;
ref var exposure = ref dispatchParams.Exposure;
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputColor, color.RenderTarget, color.MipLevel, color.SubElement);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputDepth, depth.RenderTarget, depth.MipLevel, depth.SubElement);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputMotionVectors, motionVectors.RenderTarget, motionVectors.MipLevel, motionVectors.SubElement);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputExposure, exposure.RenderTarget, exposure.MipLevel, exposure.SubElement);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputColor, dispatchParams.Color);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputDepth, dispatchParams.Depth);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputMotionVectors, dispatchParams.MotionVectors);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputExposure, dispatchParams.Exposure);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavDilatedMotionVectors, Resources.DilatedMotionVectors[frameIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavDilatedMotionVectors, Resources.DilatedMotionVectors[bufferIndex]);
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbFsr2, Constants, 0, Marshal.SizeOf<Fsr2.UpscalerConstants>());
commandBuffer.SetComputeConstantBufferParam<Fsr2.UpscalerConstants>(ComputeShader, Fsr2ShaderIDs.CbFsr2, Constants);
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, dispatchZ);
}
}
internal class Fsr2DepthClipPass : Fsr2Pass
internal sealed class Fsr2DepthClipPass : Fsr2Pass
{
public Fsr2DepthClipPass(Fsr2.ContextDescription contextDescription, Fsr2Resources resources, ComputeBuffer constants)
public Fsr2DepthClipPass(in Fsr2.ContextDescription contextDescription, Fsr2Resources resources, ComputeBuffer constants)
: base(contextDescription, resources, constants)
{
InitComputeShader("Depth Clip", contextDescription.Shaders.depthClipPass);
}
protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr2.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY)
protected override void Dispatch(CommandBuffer commandBuffer, in Fsr2.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ)
{
ref var color = ref dispatchParams.Color;
ref var depth = ref dispatchParams.Depth;
ref var motionVectors = ref dispatchParams.MotionVectors;
ref var exposure = ref dispatchParams.Exposure;
ref var reactive = ref dispatchParams.Reactive;
ref var tac = ref dispatchParams.TransparencyAndComposition;
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputColor, color.RenderTarget, color.MipLevel, color.SubElement);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputDepth, depth.RenderTarget, depth.MipLevel, depth.SubElement);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputMotionVectors, motionVectors.RenderTarget, motionVectors.MipLevel, motionVectors.SubElement);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputExposure, exposure.RenderTarget, exposure.MipLevel, exposure.SubElement);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvReactiveMask, reactive.RenderTarget, reactive.MipLevel, reactive.SubElement);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvTransparencyAndCompositionMask, tac.RenderTarget, tac.MipLevel, tac.SubElement);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputColor, dispatchParams.Color);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputDepth, dispatchParams.Depth);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputMotionVectors, dispatchParams.MotionVectors);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputExposure, dispatchParams.Exposure);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvReactiveMask, dispatchParams.Reactive);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvTransparencyAndCompositionMask, dispatchParams.TransparencyAndComposition);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvReconstructedPrevNearestDepth, Fsr2ShaderIDs.UavReconstructedPrevNearestDepth);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvDilatedMotionVectors, Resources.DilatedMotionVectors[frameIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvDilatedMotionVectors, Resources.DilatedMotionVectors[bufferIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvDilatedDepth, Fsr2ShaderIDs.UavDilatedDepth);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvPrevDilatedMotionVectors, Resources.DilatedMotionVectors[frameIndex ^ 1]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvPrevDilatedMotionVectors, Resources.DilatedMotionVectors[bufferIndex ^ 1]);
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbFsr2, Constants, 0, Marshal.SizeOf<Fsr2.UpscalerConstants>());
commandBuffer.SetComputeConstantBufferParam<Fsr2.UpscalerConstants>(ComputeShader, Fsr2ShaderIDs.CbFsr2, Constants);
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, dispatchZ);
}
}
internal class Fsr2LockPass : Fsr2Pass
internal sealed class Fsr2LockPass : Fsr2Pass
{
public Fsr2LockPass(Fsr2.ContextDescription contextDescription, Fsr2Resources resources, ComputeBuffer constants)
public Fsr2LockPass(in Fsr2.ContextDescription contextDescription, Fsr2Resources resources, ComputeBuffer constants)
: base(contextDescription, resources, constants)
{
InitComputeShader("Create Locks", contextDescription.Shaders.lockPass);
}
protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr2.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY)
protected override void Dispatch(CommandBuffer commandBuffer, in Fsr2.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ)
{
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvLockInputLuma, Fsr2ShaderIDs.UavLockInputLuma);
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbFsr2, Constants, 0, Marshal.SizeOf<Fsr2.UpscalerConstants>());
commandBuffer.SetComputeConstantBufferParam<Fsr2.UpscalerConstants>(ComputeShader, Fsr2ShaderIDs.CbFsr2, Constants);
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, dispatchZ);
}
}
internal class Fsr2AccumulatePass : Fsr2Pass
internal sealed class Fsr2AccumulatePass : Fsr2Pass
{
private const string SharpeningKeyword = "FFX_FSR2_OPTION_APPLY_SHARPENING";
@ -215,7 +176,7 @@ namespace FidelityFX.FSR2
private readonly LocalKeyword _sharpeningKeyword;
#endif
public Fsr2AccumulatePass(Fsr2.ContextDescription contextDescription, Fsr2Resources resources, ComputeBuffer constants)
public Fsr2AccumulatePass(in Fsr2.ContextDescription contextDescription, Fsr2Resources resources, ComputeBuffer constants)
: base(contextDescription, resources, constants)
{
InitComputeShader("Reproject & Accumulate", contextDescription.Shaders.accumulatePass);
@ -224,7 +185,7 @@ namespace FidelityFX.FSR2
#endif
}
protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr2.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY)
protected override void Dispatch(CommandBuffer commandBuffer, in Fsr2.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ)
{
#if UNITY_2021_2_OR_NEWER
if (dispatchParams.EnableSharpening)
@ -238,47 +199,44 @@ namespace FidelityFX.FSR2
commandBuffer.DisableShaderKeyword(SharpeningKeyword);
#endif
if ((ContextDescription.Flags & Fsr2.InitializationFlags.EnableDisplayResolutionMotionVectors) == 0)
if ((Flags & Fsr2.InitializationFlags.EnableDisplayResolutionMotionVectors) == 0)
{
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvDilatedMotionVectors, Resources.DilatedMotionVectors[frameIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvDilatedMotionVectors, Resources.DilatedMotionVectors[bufferIndex]);
}
else
{
ref var motionVectors = ref dispatchParams.MotionVectors;
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputMotionVectors, motionVectors.RenderTarget, motionVectors.MipLevel, motionVectors.SubElement);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputMotionVectors, dispatchParams.MotionVectors);
}
ref var exposure = ref dispatchParams.Exposure;
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputExposure, exposure.RenderTarget, exposure.MipLevel, exposure.SubElement);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputExposure, dispatchParams.Exposure);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvDilatedReactiveMasks, Fsr2ShaderIDs.UavDilatedReactiveMasks);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInternalUpscaled, Resources.InternalUpscaled[frameIndex ^ 1]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvLockStatus, Resources.LockStatus[frameIndex ^ 1]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInternalUpscaled, Resources.InternalUpscaled[bufferIndex ^ 1]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvLockStatus, Resources.LockStatus[bufferIndex ^ 1]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvPreparedInputColor, Fsr2ShaderIDs.UavPreparedInputColor);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvLanczosLut, Resources.LanczosLut);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvUpscaleMaximumBiasLut, Resources.MaximumBiasLut);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvSceneLuminanceMips, Resources.SceneLuminance);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvAutoExposure, Resources.AutoExposure);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvLumaHistory, Resources.LumaHistory[frameIndex ^ 1]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvLumaHistory, Resources.LumaHistory[bufferIndex ^ 1]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavInternalUpscaled, Resources.InternalUpscaled[frameIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavLockStatus, Resources.LockStatus[frameIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavLumaHistory, Resources.LumaHistory[frameIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavInternalUpscaled, Resources.InternalUpscaled[bufferIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavLockStatus, Resources.LockStatus[bufferIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavLumaHistory, Resources.LumaHistory[bufferIndex]);
ref var output = ref dispatchParams.Output;
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavUpscaledOutput, output.RenderTarget, output.MipLevel, output.SubElement);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavUpscaledOutput, dispatchParams.Output);
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbFsr2, Constants, 0, Marshal.SizeOf<Fsr2.UpscalerConstants>());
commandBuffer.SetComputeConstantBufferParam<Fsr2.UpscalerConstants>(ComputeShader, Fsr2ShaderIDs.CbFsr2, Constants);
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, dispatchZ);
}
}
internal class Fsr2SharpenPass : Fsr2Pass
internal sealed class Fsr2SharpenPass : Fsr2Pass
{
private readonly ComputeBuffer _rcasConstants;
public Fsr2SharpenPass(Fsr2.ContextDescription contextDescription, Fsr2Resources resources, ComputeBuffer constants, ComputeBuffer rcasConstants)
public Fsr2SharpenPass(in Fsr2.ContextDescription contextDescription, Fsr2Resources resources, ComputeBuffer constants, ComputeBuffer rcasConstants)
: base(contextDescription, resources, constants)
{
_rcasConstants = rcasConstants;
@ -286,27 +244,25 @@ namespace FidelityFX.FSR2
InitComputeShader("RCAS Sharpening", contextDescription.Shaders.sharpenPass);
}
protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr2.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY)
protected override void Dispatch(CommandBuffer commandBuffer, in Fsr2.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ)
{
ref var exposure = ref dispatchParams.Exposure;
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputExposure, exposure.RenderTarget, exposure.MipLevel, exposure.SubElement);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvRcasInput, Resources.InternalUpscaled[frameIndex]);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputExposure, dispatchParams.Exposure);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvRcasInput, Resources.InternalUpscaled[bufferIndex]);
ref var output = ref dispatchParams.Output;
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavUpscaledOutput, output.RenderTarget, output.MipLevel, output.SubElement);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavUpscaledOutput, dispatchParams.Output);
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbFsr2, Constants, 0, Marshal.SizeOf<Fsr2.UpscalerConstants>());
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbRcas, _rcasConstants, 0, Marshal.SizeOf<Fsr2.RcasConstants>());
commandBuffer.SetComputeConstantBufferParam<Fsr2.UpscalerConstants>(ComputeShader, Fsr2ShaderIDs.CbFsr2, Constants);
commandBuffer.SetComputeConstantBufferParam<Fsr2.RcasConstants>(ComputeShader, Fsr2ShaderIDs.CbRcas, _rcasConstants);
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, dispatchZ);
}
}
internal class Fsr2GenerateReactivePass : Fsr2Pass
internal sealed class Fsr2GenerateReactivePass : Fsr2Pass
{
private readonly ComputeBuffer _generateReactiveConstants;
public Fsr2GenerateReactivePass(Fsr2.ContextDescription contextDescription, Fsr2Resources resources, ComputeBuffer generateReactiveConstants)
public Fsr2GenerateReactivePass(in Fsr2.ContextDescription contextDescription, Fsr2Resources resources, ComputeBuffer generateReactiveConstants)
: base(contextDescription, resources, null)
{
_generateReactiveConstants = generateReactiveConstants;
@ -314,35 +270,30 @@ namespace FidelityFX.FSR2
InitComputeShader("Auto-Generate Reactive Mask", contextDescription.Shaders.autoGenReactivePass);
}
protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr2.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY)
protected override void Dispatch(CommandBuffer commandBuffer, in Fsr2.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ)
{
}
public void ScheduleDispatch(CommandBuffer commandBuffer, Fsr2.GenerateReactiveDescription dispatchParams, int dispatchX, int dispatchY)
public void ScheduleDispatch(CommandBuffer commandBuffer, in Fsr2.GenerateReactiveDescription dispatchParams, int dispatchX, int dispatchY)
{
commandBuffer.BeginSample(Sampler);
ref var opaqueOnly = ref dispatchParams.ColorOpaqueOnly;
ref var color = ref dispatchParams.ColorPreUpscale;
ref var reactive = ref dispatchParams.OutReactive;
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvOpaqueOnly, opaqueOnly.RenderTarget, opaqueOnly.MipLevel, opaqueOnly.SubElement);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputColor, color.RenderTarget, color.MipLevel, color.SubElement);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavAutoReactive, reactive.RenderTarget, reactive.MipLevel, reactive.SubElement);
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbGenReactive, _generateReactiveConstants, 0, Marshal.SizeOf<Fsr2.GenerateReactiveConstants>());
using (ProfilerSample(commandBuffer))
{
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvOpaqueOnly, dispatchParams.ColorOpaqueOnly);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputColor, dispatchParams.ColorPreUpscale);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavAutoReactive, dispatchParams.OutReactive);
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
commandBuffer.SetComputeConstantBufferParam<Fsr2.GenerateReactiveConstants>(ComputeShader, Fsr2ShaderIDs.CbGenReactive, _generateReactiveConstants);
commandBuffer.EndSample(Sampler);
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
}
}
}
internal class Fsr2TcrAutogeneratePass : Fsr2Pass
internal sealed class Fsr2TcrAutogeneratePass : Fsr2Pass
{
private readonly ComputeBuffer _tcrAutogenerateConstants;
public Fsr2TcrAutogeneratePass(Fsr2.ContextDescription contextDescription, Fsr2Resources resources, ComputeBuffer constants, ComputeBuffer tcrAutogenerateConstants)
public Fsr2TcrAutogeneratePass(in Fsr2.ContextDescription contextDescription, Fsr2Resources resources, ComputeBuffer constants, ComputeBuffer tcrAutogenerateConstants)
: base(contextDescription, resources, constants)
{
_tcrAutogenerateConstants = tcrAutogenerateConstants;
@ -350,31 +301,25 @@ namespace FidelityFX.FSR2
InitComputeShader("Auto-Generate Transparency & Composition Mask", contextDescription.Shaders.tcrAutoGenPass);
}
protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr2.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY)
protected override void Dispatch(CommandBuffer commandBuffer, in Fsr2.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ)
{
ref var color = ref dispatchParams.Color;
ref var motionVectors = ref dispatchParams.MotionVectors;
ref var opaqueOnly = ref dispatchParams.ColorOpaqueOnly;
ref var reactive = ref dispatchParams.Reactive;
ref var tac = ref dispatchParams.TransparencyAndComposition;
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvOpaqueOnly, opaqueOnly.RenderTarget, opaqueOnly.MipLevel, opaqueOnly.SubElement);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputColor, color.RenderTarget, color.MipLevel, color.SubElement);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputMotionVectors, motionVectors.RenderTarget, motionVectors.MipLevel, motionVectors.SubElement);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvPrevColorPreAlpha, Resources.PrevPreAlpha[frameIndex ^ 1]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvPrevColorPostAlpha, Resources.PrevPostAlpha[frameIndex ^ 1]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvReactiveMask, reactive.RenderTarget, reactive.MipLevel, reactive.SubElement);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvTransparencyAndCompositionMask, tac.RenderTarget, tac.MipLevel, tac.SubElement);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvOpaqueOnly, dispatchParams.ColorOpaqueOnly);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputColor, dispatchParams.Color);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputMotionVectors, dispatchParams.MotionVectors);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvPrevColorPreAlpha, Resources.PrevPreAlpha[bufferIndex ^ 1]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvPrevColorPostAlpha, Resources.PrevPostAlpha[bufferIndex ^ 1]);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvReactiveMask, dispatchParams.Reactive);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvTransparencyAndCompositionMask, dispatchParams.TransparencyAndComposition);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavAutoReactive, Resources.AutoReactive);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavAutoComposition, Resources.AutoComposition);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavPrevColorPreAlpha, Resources.PrevPreAlpha[frameIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavPrevColorPostAlpha, Resources.PrevPostAlpha[frameIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavPrevColorPreAlpha, Resources.PrevPreAlpha[bufferIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavPrevColorPostAlpha, Resources.PrevPostAlpha[bufferIndex]);
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbFsr2, Constants, 0, Marshal.SizeOf<Fsr2.UpscalerConstants>());
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbGenReactive, _tcrAutogenerateConstants, 0, Marshal.SizeOf<Fsr2.GenerateReactiveConstants2>());
commandBuffer.SetComputeConstantBufferParam<Fsr2.UpscalerConstants>(ComputeShader, Fsr2ShaderIDs.CbFsr2, Constants);
commandBuffer.SetComputeConstantBufferParam<Fsr2.GenerateReactiveConstants2>(ComputeShader, Fsr2ShaderIDs.CbGenReactive, _tcrAutogenerateConstants);
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, dispatchZ);
}
}
}

89
Runtime/FSR2/Fsr2Resources.cs

@ -29,7 +29,7 @@ namespace FidelityFX.FSR2
/// Helper class for bundling and managing persistent resources required by the FSR2 process.
/// This includes lookup tables, default fallback resources and double-buffered resources that get swapped between frames.
/// </summary>
internal class Fsr2Resources
internal class Fsr2Resources: FfxResourcesBase
{
public Texture2D DefaultExposure;
public Texture2D DefaultReactive;
@ -47,17 +47,11 @@ namespace FidelityFX.FSR2
public readonly RenderTexture[] PrevPreAlpha = new RenderTexture[2];
public readonly RenderTexture[] PrevPostAlpha = new RenderTexture[2];
public void Create(Fsr2.ContextDescription contextDescription)
public void Create(in Fsr2.ContextDescription contextDescription)
{
// Generate the data for the LUT
const int lanczos2LutWidth = 128;
float[] lanczos2Weights = new float[lanczos2LutWidth];
for (int currentLanczosWidthIndex = 0; currentLanczosWidthIndex < lanczos2LutWidth; ++currentLanczosWidthIndex)
{
float x = 2.0f * currentLanczosWidthIndex / (lanczos2LutWidth - 1);
float y = Fsr2.Lanczos2(x);
lanczos2Weights[currentLanczosWidthIndex] = y;
}
float[] lanczos2Weights = FfxUtils.GenerateLanczos2Table(lanczos2LutWidth);
float[] maximumBias = new float[MaximumBiasTextureWidth * MaximumBiasTextureHeight];
for (int i = 0; i < maximumBias.Length; ++i)
@ -67,40 +61,27 @@ namespace FidelityFX.FSR2
// Resource FSR2_LanczosLutData: FFX_RESOURCE_USAGE_READ_ONLY, FFX_SURFACE_FORMAT_R16_SNORM, FFX_RESOURCE_FLAGS_NONE
// R16_SNorm textures are not supported by Unity on most platforms, strangely enough. So instead we use R32_SFloat and upload pre-normalized float data.
LanczosLut = new Texture2D(lanczos2LutWidth, 1, GraphicsFormat.R32_SFloat, TextureCreationFlags.None) { name = "FSR2_LanczosLutData" };
LanczosLut.SetPixelData(lanczos2Weights, 0);
LanczosLut.Apply();
LanczosLut = CreateLookup("FSR2_LanczosLutData", new Vector2Int(lanczos2LutWidth, 1), GraphicsFormat.R32_SFloat, lanczos2Weights);
// Resource FSR2_MaximumUpsampleBias: FFX_RESOURCE_USAGE_READ_ONLY, FFX_SURFACE_FORMAT_R16_SNORM, FFX_RESOURCE_FLAGS_NONE
MaximumBiasLut = new Texture2D(MaximumBiasTextureWidth, MaximumBiasTextureHeight, GraphicsFormat.R32_SFloat, TextureCreationFlags.None) { name = "FSR2_MaximumUpsampleBias" };
MaximumBiasLut.SetPixelData(maximumBias, 0);
MaximumBiasLut.Apply();
MaximumBiasLut = CreateLookup("FSR2_MaximumUpsampleBias", new Vector2Int(MaximumBiasTextureWidth, MaximumBiasTextureHeight), GraphicsFormat.R32_SFloat, maximumBias);
// Resource FSR2_DefaultExposure: FFX_RESOURCE_USAGE_READ_ONLY, FFX_SURFACE_FORMAT_R32G32_FLOAT, FFX_RESOURCE_FLAGS_NONE
DefaultExposure = new Texture2D(1, 1, GraphicsFormat.R32G32_SFloat, TextureCreationFlags.None) { name = "FSR2_DefaultExposure" };
DefaultExposure.SetPixel(0, 0, Color.clear);
DefaultExposure.Apply();
DefaultExposure = CreateLookup("FSR2_DefaultExposure", GraphicsFormat.R32G32_SFloat, Color.clear);
// Resource FSR2_DefaultReactivityMask: FFX_RESOURCE_USAGE_READ_ONLY, FFX_SURFACE_FORMAT_R8_UNORM, FFX_RESOURCE_FLAGS_NONE
DefaultReactive = new Texture2D(1, 1, GraphicsFormat.R8_UNorm, TextureCreationFlags.None) { name = "FSR2_DefaultReactivityMask" };
DefaultReactive.SetPixel(0, 0, Color.clear);
DefaultReactive.Apply();
DefaultReactive = CreateLookup("FSR2_DefaultReactivityMask", GraphicsFormat.R8_UNorm, Color.clear);
// Resource FSR2_SpdAtomicCounter: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R32_UINT, FFX_RESOURCE_FLAGS_ALIASABLE
// Despite what the original FSR2 codebase says, this resource really isn't aliasable. Resetting this counter to 0 every frame breaks auto-exposure on MacOS Metal.
SpdAtomicCounter = new RenderTexture(1, 1, 0, GraphicsFormat.R32_UInt) { name = "FSR2_SpdAtomicCounter", enableRandomWrite = true };
SpdAtomicCounter.Create();
SpdAtomicCounter = CreateResource("FSR2_SpdAtomicCounter", Vector2Int.one, GraphicsFormat.R32_UInt);
// Resource FSR2_AutoExposure: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R32G32_FLOAT, FFX_RESOURCE_FLAGS_NONE
AutoExposure = new RenderTexture(1, 1, 0, GraphicsFormat.R32G32_SFloat) { name = "FSR2_AutoExposure", enableRandomWrite = true };
AutoExposure.Create();
AutoExposure = CreateResource("FSR2_AutoExposure", Vector2Int.one, GraphicsFormat.R32G32_SFloat);
// Resource FSR2_ExposureMips: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R16_FLOAT, FFX_RESOURCE_FLAGS_ALIASABLE
// This is a rather special case: it's an aliasable resource, but because we require a mipmap chain and bind specific mip levels per shader, we can't easily use temporary RTs for this.
int w = contextDescription.MaxRenderSize.x / 2, h = contextDescription.MaxRenderSize.y / 2;
int mipCount = 1 + Mathf.FloorToInt(Mathf.Log(Math.Max(w, h), 2.0f));
SceneLuminance = new RenderTexture(w, h, 0, GraphicsFormat.R16_SFloat, mipCount) { name = "FSR2_ExposureMips", enableRandomWrite = true, useMipMap = true, autoGenerateMips = false };
SceneLuminance.Create();
SceneLuminance = CreateResourceMips("FSR2_ExposureMips", contextDescription.MaxRenderSize / 2, GraphicsFormat.R16_SFloat);
// Resources FSR2_InternalDilatedVelocity1/2: FFX_RESOURCE_USAGE_RENDERTARGET | FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R16G16_FLOAT, FFX_RESOURCE_FLAGS_NONE
CreateDoubleBufferedResource(DilatedMotionVectors, "FSR2_InternalDilatedVelocity", contextDescription.MaxRenderSize, GraphicsFormat.R16G16_SFloat);
@ -115,15 +96,13 @@ namespace FidelityFX.FSR2
CreateDoubleBufferedResource(LumaHistory, "FSR2_LumaHistory", contextDescription.DisplaySize, GraphicsFormat.R8G8B8A8_UNorm);
}
public void CreateTcrAutogenResources(Fsr2.ContextDescription contextDescription)
public void CreateTcrAutogenResources(in Fsr2.ContextDescription contextDescription)
{
// Resource FSR2_AutoReactive: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R8_UNORM, FFX_RESOURCE_FLAGS_NONE
AutoReactive = new RenderTexture(contextDescription.MaxRenderSize.x, contextDescription.MaxRenderSize.y, 0, GraphicsFormat.R8_UNorm) { name = "FSR2_AutoReactive", enableRandomWrite = true };
AutoReactive.Create();
AutoReactive = CreateResource("FSR2_AutoReactive", contextDescription.MaxRenderSize, GraphicsFormat.R8_UNorm);
// Resource FSR2_AutoComposition: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R8_UNORM, FFX_RESOURCE_FLAGS_NONE
AutoComposition = new RenderTexture(contextDescription.MaxRenderSize.x, contextDescription.MaxRenderSize.y, 0, GraphicsFormat.R8_UNorm) { name = "FSR2_AutoComposition", enableRandomWrite = true };
AutoComposition.Create();
AutoComposition = CreateResource("FSR2_AutoComposition", contextDescription.MaxRenderSize, GraphicsFormat.R8_UNorm);
// Resources FSR2_PrevPreAlpha0/1: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R11G11B10_FLOAT, FFX_RESOURCE_FLAGS_NONE
CreateDoubleBufferedResource(PrevPreAlpha, "FSR2_PrevPreAlpha", contextDescription.MaxRenderSize, GraphicsFormat.B10G11R11_UFloatPack32);
@ -134,7 +113,7 @@ namespace FidelityFX.FSR2
// Set up shared aliasable resources, i.e. temporary render textures
// These do not need to persist between frames, but they do need to be available between passes
public static void CreateAliasableResources(CommandBuffer commandBuffer, Fsr2.ContextDescription contextDescription, Fsr2.DispatchDescription dispatchParams)
public static void CreateAliasableResources(CommandBuffer commandBuffer, in Fsr2.ContextDescription contextDescription)
{
Vector2Int displaySize = contextDescription.DisplaySize;
Vector2Int maxRenderSize = contextDescription.MaxRenderSize;
@ -169,15 +148,6 @@ namespace FidelityFX.FSR2
commandBuffer.ReleaseTemporaryRT(Fsr2ShaderIDs.UavNewLocks);
}
private static void CreateDoubleBufferedResource(RenderTexture[] resource, string name, Vector2Int size, GraphicsFormat format)
{
for (int i = 0; i < 2; ++i)
{
resource[i] = new RenderTexture(size.x, size.y, 0, format) { name = name + (i + 1), enableRandomWrite = true };
resource[i].Create();
}
}
public void Destroy()
{
DestroyTcrAutogenResources();
@ -202,37 +172,6 @@ namespace FidelityFX.FSR2
DestroyResource(ref AutoReactive);
}
private static void DestroyResource(ref Texture2D resource)
{
if (resource == null)
return;
#if UNITY_EDITOR
if (Application.isPlaying && !UnityEditor.EditorApplication.isPaused)
UnityEngine.Object.Destroy(resource);
else
UnityEngine.Object.DestroyImmediate(resource);
#else
UnityEngine.Object.Destroy(resource);
#endif
resource = null;
}
private static void DestroyResource(ref RenderTexture resource)
{
if (resource == null)
return;
resource.Release();
resource = null;
}
private static void DestroyResource(RenderTexture[] resource)
{
for (int i = 0; i < resource.Length; ++i)
DestroyResource(ref resource[i]);
}
private const int MaximumBiasTextureWidth = 16;
private const int MaximumBiasTextureHeight = 16;
private static readonly float[] MaximumBias =

90
Runtime/FSR3/Fsr3Upscaler.cs

@ -21,7 +21,6 @@
using System;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.Rendering;
namespace FidelityFX.FSR3
{
@ -80,60 +79,13 @@ namespace FidelityFX.FSR3
}
}
public static void GetRenderResolutionFromQualityMode(
out int renderWidth, out int renderHeight,
int displayWidth, int displayHeight, QualityMode qualityMode)
public static void GetRenderResolutionFromQualityMode(out int renderWidth, out int renderHeight, int displayWidth, int displayHeight, QualityMode qualityMode)
{
float ratio = GetUpscaleRatioFromQualityMode(qualityMode);
renderWidth = Mathf.RoundToInt(displayWidth / ratio);
renderHeight = Mathf.RoundToInt(displayHeight / ratio);
}
public static float GetMipmapBiasOffset(int renderWidth, int displayWidth)
{
return Mathf.Log((float)renderWidth / displayWidth, 2.0f) - 1.0f;
}
public static int GetJitterPhaseCount(int renderWidth, int displayWidth)
{
const float basePhaseCount = 8.0f;
int jitterPhaseCount = (int)(basePhaseCount * Mathf.Pow((float)displayWidth / renderWidth, 2.0f));
return jitterPhaseCount;
}
public static void GetJitterOffset(out float outX, out float outY, int index, int phaseCount)
{
outX = Halton((index % phaseCount) + 1, 2) - 0.5f;
outY = Halton((index % phaseCount) + 1, 3) - 0.5f;
}
// Calculate halton number for index and base.
private static float Halton(int index, int @base)
{
float f = 1.0f, result = 0.0f;
for (int currentIndex = index; currentIndex > 0;) {
f /= @base;
result += f * (currentIndex % @base);
currentIndex = (int)Mathf.Floor((float)currentIndex / @base);
}
return result;
}
public static float Lanczos2(float value)
{
return Mathf.Abs(value) < Mathf.Epsilon ? 1.0f : Mathf.Sin(Mathf.PI * value) / (Mathf.PI * value) * (Mathf.Sin(0.5f * Mathf.PI * value) / (0.5f * Mathf.PI * value));
}
#if !UNITY_2021_1_OR_NEWER
internal static void SetBufferData(this CommandBuffer commandBuffer, ComputeBuffer computeBuffer, Array data)
{
commandBuffer.SetComputeBufferData(computeBuffer, data);
}
#endif
public enum QualityMode
{
NativeAA = 0,
@ -178,7 +130,7 @@ namespace FidelityFX.FSR3
/// <summary>
/// A structure encapsulating the parameters for dispatching the various passes of FidelityFX Super Resolution 3.
/// </summary>
public class DispatchDescription
public struct DispatchDescription
{
public ResourceView Color;
public ResourceView Depth;
@ -206,26 +158,42 @@ namespace FidelityFX.FSR3
// EXPERIMENTAL reactive mask generation parameters
public bool EnableAutoReactive;
public ResourceView ColorOpaqueOnly;
public float AutoTcThreshold = 0.05f;
public float AutoTcScale = 1.0f;
public float AutoReactiveScale = 5.0f;
public float AutoReactiveMax = 0.9f;
public float AutoTcThreshold;
public float AutoTcScale;
public float AutoReactiveScale;
public float AutoReactiveMax;
public static readonly DispatchDescription Default = new DispatchDescription
{
AutoTcThreshold = 0.05f,
AutoTcScale = 1.0f,
AutoReactiveScale = 5.0f,
AutoReactiveMax = 0.9f,
};
}
/// <summary>
/// A structure encapsulating the parameters for automatic generation of a reactive mask.
/// The default values for Scale, CutoffThreshold, BinaryValue and Flags were taken from the FSR3 demo project.
/// </summary>
public class GenerateReactiveDescription
public struct GenerateReactiveDescription
{
public ResourceView ColorOpaqueOnly;
public ResourceView ColorPreUpscale;
public ResourceView OutReactive;
public Vector2Int RenderSize;
public float Scale = 0.5f;
public float CutoffThreshold = 0.2f;
public float BinaryValue = 0.9f;
public GenerateReactiveFlags Flags = GenerateReactiveFlags.ApplyTonemap | GenerateReactiveFlags.ApplyThreshold | GenerateReactiveFlags.UseComponentsMax;
public float Scale;
public float CutoffThreshold;
public float BinaryValue;
public GenerateReactiveFlags Flags;
public static readonly GenerateReactiveDescription Default = new GenerateReactiveDescription
{
Scale = 0.5f,
CutoffThreshold = 0.2f,
BinaryValue = 0.9f,
Flags = GenerateReactiveFlags.ApplyTonemap | GenerateReactiveFlags.ApplyThreshold | GenerateReactiveFlags.UseComponentsMax,
};
}
[Flags]
@ -270,9 +238,7 @@ namespace FidelityFX.FSR3
[Serializable, StructLayout(LayoutKind.Sequential)]
internal struct SpdConstants
{
public uint mips;
public uint numWorkGroups;
public uint workGroupOffsetX, workGroupOffsetY;
public FfxSpd.SpdConstants spd;
public uint renderSizeX, renderSizeY;
}

1
Runtime/FSR3/Fsr3UpscalerAssets.cs

@ -19,7 +19,6 @@
// THE SOFTWARE.
using UnityEngine;
using UnityEngine.Serialization;
namespace FidelityFX.FSR3
{

295
Runtime/FSR3/Fsr3UpscalerContext.cs

@ -19,8 +19,8 @@
// THE SOFTWARE.
using System;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.Profiling;
using UnityEngine.Rendering;
namespace FidelityFX.FSR3
@ -31,48 +31,34 @@ namespace FidelityFX.FSR3
/// Note that this class does not know anything about Unity render pipelines; all it knows is CommandBuffers and RenderTargetIdentifiers.
/// This should make it suitable for integration with any of the available Unity render pipelines.
/// </summary>
public class Fsr3UpscalerContext
public class Fsr3UpscalerContext: FfxContextBase
{
private const int MaxQueuedFrames = 16;
private Fsr3Upscaler.ContextDescription _contextDescription;
private CommandBuffer _commandBuffer;
private Fsr3UpscalerPass _prepareInputsPass;
private Fsr3UpscalerPass _lumaPyramidPass;
private Fsr3UpscalerPass _shadingChangePyramidPass;
private Fsr3UpscalerPass _shadingChangePass;
private Fsr3UpscalerPass _prepareReactivityPass;
private Fsr3UpscalerPass _lumaInstabilityPass;
private Fsr3UpscalerPass _accumulatePass;
private Fsr3UpscalerPass _sharpenPass;
private Fsr3UpscalerPass _generateReactivePass;
private Fsr3UpscalerPass _tcrAutogeneratePass;
private Fsr3UpscalerPrepareInputsPass _prepareInputsPass;
private Fsr3UpscalerLumaPyramidPass _lumaPyramidPass;
private Fsr3UpscalerShadingChangePyramidPass _shadingChangePyramidPass;
private Fsr3UpscalerShadingChangePass _shadingChangePass;
private Fsr3UpscalerPrepareReactivityPass _prepareReactivityPass;
private Fsr3UpscalerLumaInstabilityPass _lumaInstabilityPass;
private Fsr3UpscalerAccumulatePass _accumulatePass;
private Fsr3UpscalerSharpenPass _sharpenPass;
private Fsr3UpscalerGenerateReactivePass _generateReactivePass;
private Fsr3UpscalerTcrAutogeneratePass _tcrAutogeneratePass;
#if UNITY_EDITOR || DEVELOPMENT_BUILD
private Fsr3UpscalerPass _debugViewPass;
private Fsr3UpscalerDebugViewPass _debugViewPass;
#endif
private readonly Fsr3UpscalerResources _resources = new Fsr3UpscalerResources();
private ComputeBuffer _upscalerConstantsBuffer;
private readonly Fsr3Upscaler.UpscalerConstants[] _upscalerConstantsArray = { new Fsr3Upscaler.UpscalerConstants() };
private ref Fsr3Upscaler.UpscalerConstants UpscalerConsts => ref _upscalerConstantsArray[0];
private ComputeBuffer _spdConstantsBuffer;
private readonly Fsr3Upscaler.SpdConstants[] _spdConstantsArray = { new Fsr3Upscaler.SpdConstants() };
private ref Fsr3Upscaler.SpdConstants SpdConsts => ref _spdConstantsArray[0];
private ComputeBuffer _rcasConstantsBuffer;
private readonly Fsr3Upscaler.RcasConstants[] _rcasConstantsArray = new Fsr3Upscaler.RcasConstants[1];
private ref Fsr3Upscaler.RcasConstants RcasConsts => ref _rcasConstantsArray[0];
private ComputeBuffer _generateReactiveConstantsBuffer;
private readonly Fsr3Upscaler.GenerateReactiveConstants[] _generateReactiveConstantsArray = { new Fsr3Upscaler.GenerateReactiveConstants() };
private ref Fsr3Upscaler.GenerateReactiveConstants GenReactiveConsts => ref _generateReactiveConstantsArray[0];
private ComputeBuffer _tcrAutogenerateConstantsBuffer;
private readonly Fsr3Upscaler.GenerateReactiveConstants2[] _tcrAutogenerateConstantsArray = { new Fsr3Upscaler.GenerateReactiveConstants2() };
private ref Fsr3Upscaler.GenerateReactiveConstants2 TcrAutoGenConsts => ref _tcrAutogenerateConstantsArray[0];
private readonly ConstantsBuffer<Fsr3Upscaler.UpscalerConstants> _upscalerConstants = new ConstantsBuffer<Fsr3Upscaler.UpscalerConstants>();
private readonly ConstantsBuffer<Fsr3Upscaler.SpdConstants> _spdConstants = new ConstantsBuffer<Fsr3Upscaler.SpdConstants>();
private readonly ConstantsBuffer<Fsr3Upscaler.RcasConstants> _rcasConstants = new ConstantsBuffer<Fsr3Upscaler.RcasConstants>();
private readonly ConstantsBuffer<Fsr3Upscaler.GenerateReactiveConstants> _generateReactiveConstants = new ConstantsBuffer<Fsr3Upscaler.GenerateReactiveConstants>();
private readonly ConstantsBuffer<Fsr3Upscaler.GenerateReactiveConstants2> _tcrAutogenerateConstants = new ConstantsBuffer<Fsr3Upscaler.GenerateReactiveConstants2>();
private bool _firstExecution;
private int _resourceFrameIndex;
@ -80,22 +66,24 @@ namespace FidelityFX.FSR3
private float _preExposure;
private float _previousFramePreExposure;
public void Create(Fsr3Upscaler.ContextDescription contextDescription)
private readonly CustomSampler _sampler = CustomSampler.Create("FSR3 Upscaler");
public void Create(in Fsr3Upscaler.ContextDescription contextDescription)
{
_contextDescription = contextDescription;
_commandBuffer = new CommandBuffer { name = "FSR3 Upscaler" };
_upscalerConstantsBuffer = CreateConstantBuffer<Fsr3Upscaler.UpscalerConstants>();
_spdConstantsBuffer = CreateConstantBuffer<Fsr3Upscaler.SpdConstants>();
_rcasConstantsBuffer = CreateConstantBuffer<Fsr3Upscaler.RcasConstants>();
_generateReactiveConstantsBuffer = CreateConstantBuffer<Fsr3Upscaler.GenerateReactiveConstants>();
_tcrAutogenerateConstantsBuffer = CreateConstantBuffer<Fsr3Upscaler.GenerateReactiveConstants2>();
_upscalerConstants.Create();
_spdConstants.Create();
_rcasConstants.Create();
_generateReactiveConstants.Create();
_tcrAutogenerateConstants.Create();
// Set defaults
_firstExecution = true;
_resourceFrameIndex = 0;
UpscalerConsts.maxUpscaleSize = _contextDescription.MaxUpscaleSize;
_upscalerConstants.Value.maxUpscaleSize = _contextDescription.MaxUpscaleSize;
_resources.Create(_contextDescription);
CreatePasses();
@ -103,18 +91,18 @@ namespace FidelityFX.FSR3
private void CreatePasses()
{
_prepareInputsPass = new Fsr3UpscalerPrepareInputsPass(_contextDescription, _resources, _upscalerConstantsBuffer);
_lumaPyramidPass = new Fsr3UpscalerLumaPyramidPass(_contextDescription, _resources, _upscalerConstantsBuffer, _spdConstantsBuffer);
_shadingChangePyramidPass = new Fsr3UpscalerShadingChangePyramidPass(_contextDescription, _resources, _upscalerConstantsBuffer, _spdConstantsBuffer);
_shadingChangePass = new Fsr3UpscalerShadingChangePass(_contextDescription, _resources, _upscalerConstantsBuffer);
_prepareReactivityPass = new Fsr3UpscalerPrepareReactivityPass(_contextDescription, _resources, _upscalerConstantsBuffer);
_lumaInstabilityPass = new Fsr3UpscalerLumaInstabilityPass(_contextDescription, _resources, _upscalerConstantsBuffer);
_accumulatePass = new Fsr3UpscalerAccumulatePass(_contextDescription, _resources, _upscalerConstantsBuffer);
_sharpenPass = new Fsr3UpscalerSharpenPass(_contextDescription, _resources, _upscalerConstantsBuffer, _rcasConstantsBuffer);
_generateReactivePass = new Fsr3UpscalerGenerateReactivePass(_contextDescription, _resources, _generateReactiveConstantsBuffer);
_tcrAutogeneratePass = new Fsr3UpscalerTcrAutogeneratePass(_contextDescription, _resources, _upscalerConstantsBuffer, _tcrAutogenerateConstantsBuffer);
_prepareInputsPass = new Fsr3UpscalerPrepareInputsPass(_contextDescription, _resources, _upscalerConstants);
_lumaPyramidPass = new Fsr3UpscalerLumaPyramidPass(_contextDescription, _resources, _upscalerConstants, _spdConstants);
_shadingChangePyramidPass = new Fsr3UpscalerShadingChangePyramidPass(_contextDescription, _resources, _upscalerConstants, _spdConstants);
_shadingChangePass = new Fsr3UpscalerShadingChangePass(_contextDescription, _resources, _upscalerConstants);
_prepareReactivityPass = new Fsr3UpscalerPrepareReactivityPass(_contextDescription, _resources, _upscalerConstants);
_lumaInstabilityPass = new Fsr3UpscalerLumaInstabilityPass(_contextDescription, _resources, _upscalerConstants);
_accumulatePass = new Fsr3UpscalerAccumulatePass(_contextDescription, _resources, _upscalerConstants);
_sharpenPass = new Fsr3UpscalerSharpenPass(_contextDescription, _resources, _upscalerConstants, _rcasConstants);
_generateReactivePass = new Fsr3UpscalerGenerateReactivePass(_contextDescription, _resources, _upscalerConstants);
_tcrAutogeneratePass = new Fsr3UpscalerTcrAutogeneratePass(_contextDescription, _resources, _upscalerConstants, _tcrAutogenerateConstants);
#if UNITY_EDITOR || DEVELOPMENT_BUILD
_debugViewPass = new Fsr3UpscalerDebugViewPass(_contextDescription, _resources, _upscalerConstantsBuffer);
_debugViewPass = new Fsr3UpscalerDebugViewPass(_contextDescription, _resources, _upscalerConstants);
#endif
}
@ -136,11 +124,11 @@ namespace FidelityFX.FSR3
_resources.Destroy();
DestroyConstantBuffer(ref _tcrAutogenerateConstantsBuffer);
DestroyConstantBuffer(ref _generateReactiveConstantsBuffer);
DestroyConstantBuffer(ref _rcasConstantsBuffer);
DestroyConstantBuffer(ref _spdConstantsBuffer);
DestroyConstantBuffer(ref _upscalerConstantsBuffer);
_tcrAutogenerateConstants.Destroy();
_generateReactiveConstants.Destroy();
_rcasConstants.Destroy();
_spdConstants.Destroy();
_upscalerConstants.Destroy();
if (_commandBuffer != null)
{
@ -149,7 +137,7 @@ namespace FidelityFX.FSR3
}
}
public void Dispatch(Fsr3Upscaler.DispatchDescription dispatchParams)
public void Dispatch(in Fsr3Upscaler.DispatchDescription dispatchParams)
{
_commandBuffer.Clear();
Dispatch(dispatchParams, _commandBuffer);
@ -158,13 +146,15 @@ namespace FidelityFX.FSR3
public void Dispatch(Fsr3Upscaler.DispatchDescription dispatchParams, CommandBuffer commandBuffer)
{
commandBuffer.BeginSample(_sampler);
if ((_contextDescription.Flags & Fsr3Upscaler.InitializationFlags.EnableDebugChecking) != 0)
{
DebugCheckDispatch(dispatchParams);
}
if (dispatchParams.UseTextureArrays)
commandBuffer.EnableShaderKeyword("UNITY_FSR_TEXTURE2D_X_ARRAY");
commandBuffer.EnableShaderKeyword("UNITY_FFX_TEXTURE2D_X_ARRAY");
if (_firstExecution)
{
@ -178,7 +168,7 @@ namespace FidelityFX.FSR3
commandBuffer.ClearRenderTarget(false, true, Color.clear);
}
int frameIndex = _resourceFrameIndex % 2;
int bufferIndex = _resourceFrameIndex % 2;
bool resetAccumulation = dispatchParams.Reset || _firstExecution;
_firstExecution = false;
@ -197,7 +187,7 @@ namespace FidelityFX.FSR3
if (resetAccumulation)
{
RenderTargetIdentifier opaqueOnly = dispatchParams.ColorOpaqueOnly.IsValid ? dispatchParams.ColorOpaqueOnly.RenderTarget : Fsr3ShaderIDs.SrvOpaqueOnly;
commandBuffer.Blit(_resources.PrevPreAlpha[frameIndex ^ 1], opaqueOnly);
commandBuffer.Blit(_resources.PrevPreAlpha[bufferIndex ^ 1], opaqueOnly);
}
}
else if (_resources.AutoReactive != null)
@ -208,23 +198,25 @@ namespace FidelityFX.FSR3
if (!dispatchParams.Reactive.IsValid) dispatchParams.Reactive = new ResourceView(_resources.DefaultReactive);
if (!dispatchParams.TransparencyAndComposition.IsValid) dispatchParams.TransparencyAndComposition = new ResourceView(_resources.DefaultReactive);
Fsr3UpscalerResources.CreateAliasableResources(commandBuffer, _contextDescription, dispatchParams);
Fsr3UpscalerResources.CreateAliasableResources(commandBuffer, _contextDescription);
SetupConstants(dispatchParams, resetAccumulation);
// Reactive mask bias
const int threadGroupWorkRegionDim = 8;
int dispatchSrcX = (UpscalerConsts.renderSize.x + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
int dispatchSrcY = (UpscalerConsts.renderSize.y + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
int dispatchDstX = (UpscalerConsts.upscaleSize.x + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
int dispatchDstY = (UpscalerConsts.upscaleSize.y + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
int dispatchShadingChangePassX = ((UpscalerConsts.renderSize.x / 2) + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
int dispatchShadingChangePassY = ((UpscalerConsts.renderSize.y / 2) + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
var renderSize = _upscalerConstants.Value.renderSize;
var upscaleSize = _upscalerConstants.Value.upscaleSize;
int dispatchSrcX = (renderSize.x + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
int dispatchSrcY = (renderSize.y + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
int dispatchDstX = (upscaleSize.x + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
int dispatchDstY = (upscaleSize.y + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
int dispatchShadingChangePassX = ((renderSize.x / 2) + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
int dispatchShadingChangePassY = ((renderSize.y / 2) + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
// Clear reconstructed depth for max depth store
if (resetAccumulation)
{
commandBuffer.SetRenderTarget(_resources.Accumulation[frameIndex ^ 1]);
commandBuffer.SetRenderTarget(_resources.Accumulation[bufferIndex ^ 1]);
commandBuffer.ClearRenderTarget(false, true, Color.clear);
commandBuffer.SetRenderTarget(_resources.SpdMips);
@ -240,7 +232,7 @@ namespace FidelityFX.FSR3
}
// FSR3: need to clear here since we need the content of this surface for frame interpolation, so clearing in the lock pass is not an option
bool depthInverted = (_contextDescription.Flags & Fsr3Upscaler.InitializationFlags.EnableDepthInverted) == Fsr3Upscaler.InitializationFlags.EnableDepthInverted;
bool depthInverted = (_contextDescription.Flags & Fsr3Upscaler.InitializationFlags.EnableDepthInverted) != 0;
commandBuffer.SetRenderTarget(_resources.ReconstructedPrevNearestDepth);
commandBuffer.ClearRenderTarget(false, true, depthInverted ? Color.clear : Color.white);
@ -248,43 +240,43 @@ namespace FidelityFX.FSR3
SetupSpdConstants(dispatchParams, out var dispatchThreadGroupCount);
// Initialize constant buffers data
commandBuffer.SetBufferData(_upscalerConstantsBuffer, _upscalerConstantsArray);
commandBuffer.SetBufferData(_spdConstantsBuffer, _spdConstantsArray);
_upscalerConstants.UpdateBufferData(commandBuffer);
_spdConstants.UpdateBufferData(commandBuffer);
// Auto reactive
if (dispatchParams.EnableAutoReactive)
{
GenerateTransparencyCompositionReactive(dispatchParams, commandBuffer, frameIndex);
GenerateTransparencyCompositionReactive(dispatchParams, commandBuffer, bufferIndex);
dispatchParams.Reactive = new ResourceView(_resources.AutoReactive);
dispatchParams.TransparencyAndComposition = new ResourceView(_resources.AutoComposition);
}
_prepareInputsPass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchSrcX, dispatchSrcY);
_lumaPyramidPass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchThreadGroupCount.x, dispatchThreadGroupCount.y);
_shadingChangePyramidPass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchThreadGroupCount.x, dispatchThreadGroupCount.y);
_shadingChangePass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchShadingChangePassX, dispatchShadingChangePassY);
_prepareReactivityPass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchSrcX, dispatchSrcY);
_lumaInstabilityPass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchSrcX, dispatchSrcY);
_prepareInputsPass.ScheduleDispatch(commandBuffer, dispatchParams, bufferIndex, dispatchSrcX, dispatchSrcY);
_lumaPyramidPass.ScheduleDispatch(commandBuffer, dispatchParams, bufferIndex, dispatchThreadGroupCount.x, dispatchThreadGroupCount.y);
_shadingChangePyramidPass.ScheduleDispatch(commandBuffer, dispatchParams, bufferIndex, dispatchThreadGroupCount.x, dispatchThreadGroupCount.y);
_shadingChangePass.ScheduleDispatch(commandBuffer, dispatchParams, bufferIndex, dispatchShadingChangePassX, dispatchShadingChangePassY);
_prepareReactivityPass.ScheduleDispatch(commandBuffer, dispatchParams, bufferIndex, dispatchSrcX, dispatchSrcY);
_lumaInstabilityPass.ScheduleDispatch(commandBuffer, dispatchParams, bufferIndex, dispatchSrcX, dispatchSrcY);
_accumulatePass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchDstX, dispatchDstY);
_accumulatePass.ScheduleDispatch(commandBuffer, dispatchParams, bufferIndex, dispatchDstX, dispatchDstY);
if (dispatchParams.EnableSharpening)
{
// Compute the constants
SetupRcasConstants(dispatchParams);
commandBuffer.SetBufferData(_rcasConstantsBuffer, _rcasConstantsArray);
_rcasConstants.UpdateBufferData(commandBuffer);
// Dispatch RCAS
const int threadGroupWorkRegionDimRcas = 16;
int threadGroupsX = (UpscalerConsts.upscaleSize.x + threadGroupWorkRegionDimRcas - 1) / threadGroupWorkRegionDimRcas;
int threadGroupsY = (UpscalerConsts.upscaleSize.y + threadGroupWorkRegionDimRcas - 1) / threadGroupWorkRegionDimRcas;
_sharpenPass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, threadGroupsX, threadGroupsY);
int threadGroupsX = (upscaleSize.x + threadGroupWorkRegionDimRcas - 1) / threadGroupWorkRegionDimRcas;
int threadGroupsY = (upscaleSize.y + threadGroupWorkRegionDimRcas - 1) / threadGroupWorkRegionDimRcas;
_sharpenPass.ScheduleDispatch(commandBuffer, dispatchParams, bufferIndex, threadGroupsX, threadGroupsY);
}
#if UNITY_EDITOR || DEVELOPMENT_BUILD
if ((dispatchParams.Flags & Fsr3Upscaler.DispatchFlags.DrawDebugView) != 0)
{
_debugViewPass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchDstX, dispatchDstY);
_debugViewPass.ScheduleDispatch(commandBuffer, dispatchParams, bufferIndex, dispatchDstX, dispatchDstY);
}
#endif
@ -292,49 +284,52 @@ namespace FidelityFX.FSR3
Fsr3UpscalerResources.DestroyAliasableResources(commandBuffer);
commandBuffer.DisableShaderKeyword("UNITY_FSR_TEXTURE2D_X_ARRAY");
commandBuffer.DisableShaderKeyword("UNITY_FFX_TEXTURE2D_X_ARRAY");
commandBuffer.EndSample(_sampler);
}
public void GenerateReactiveMask(Fsr3Upscaler.GenerateReactiveDescription dispatchParams)
public void GenerateReactiveMask(in Fsr3Upscaler.GenerateReactiveDescription dispatchParams)
{
_commandBuffer.Clear();
GenerateReactiveMask(dispatchParams, _commandBuffer);
Graphics.ExecuteCommandBuffer(_commandBuffer);
}
public void GenerateReactiveMask(Fsr3Upscaler.GenerateReactiveDescription dispatchParams, CommandBuffer commandBuffer)
public void GenerateReactiveMask(in Fsr3Upscaler.GenerateReactiveDescription dispatchParams, CommandBuffer commandBuffer)
{
const int threadGroupWorkRegionDim = 8;
int dispatchSrcX = (dispatchParams.RenderSize.x + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
int dispatchSrcY = (dispatchParams.RenderSize.y + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
GenReactiveConsts.scale = dispatchParams.Scale;
GenReactiveConsts.threshold = dispatchParams.CutoffThreshold;
GenReactiveConsts.binaryValue = dispatchParams.BinaryValue;
GenReactiveConsts.flags = (uint)dispatchParams.Flags;
commandBuffer.SetBufferData(_generateReactiveConstantsBuffer, _generateReactiveConstantsArray);
ref var genReactiveConsts = ref _generateReactiveConstants.Value;
genReactiveConsts.scale = dispatchParams.Scale;
genReactiveConsts.threshold = dispatchParams.CutoffThreshold;
genReactiveConsts.binaryValue = dispatchParams.BinaryValue;
genReactiveConsts.flags = (uint)dispatchParams.Flags;
_generateReactiveConstants.UpdateBufferData(commandBuffer);
((Fsr3UpscalerGenerateReactivePass)_generateReactivePass).ScheduleDispatch(commandBuffer, dispatchParams, dispatchSrcX, dispatchSrcY);
_generateReactivePass.ScheduleDispatch(commandBuffer, dispatchParams, dispatchSrcX, dispatchSrcY);
}
private void GenerateTransparencyCompositionReactive(Fsr3Upscaler.DispatchDescription dispatchParams, CommandBuffer commandBuffer, int frameIndex)
private void GenerateTransparencyCompositionReactive(in Fsr3Upscaler.DispatchDescription dispatchParams, CommandBuffer commandBuffer, int bufferIndex)
{
const int threadGroupWorkRegionDim = 8;
int dispatchSrcX = (dispatchParams.RenderSize.x + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
int dispatchSrcY = (dispatchParams.RenderSize.y + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
TcrAutoGenConsts.autoTcThreshold = dispatchParams.AutoTcThreshold;
TcrAutoGenConsts.autoTcScale = dispatchParams.AutoTcScale;
TcrAutoGenConsts.autoReactiveScale = dispatchParams.AutoReactiveScale;
TcrAutoGenConsts.autoReactiveMax = dispatchParams.AutoReactiveMax;
commandBuffer.SetBufferData(_tcrAutogenerateConstantsBuffer, _tcrAutogenerateConstantsArray);
ref var tcrAutoGenConsts = ref _tcrAutogenerateConstants.Value;
tcrAutoGenConsts.autoTcThreshold = dispatchParams.AutoTcThreshold;
tcrAutoGenConsts.autoTcScale = dispatchParams.AutoTcScale;
tcrAutoGenConsts.autoReactiveScale = dispatchParams.AutoReactiveScale;
tcrAutoGenConsts.autoReactiveMax = dispatchParams.AutoReactiveMax;
_tcrAutogenerateConstants.UpdateBufferData(commandBuffer);
_tcrAutogeneratePass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchSrcX, dispatchSrcY);
_tcrAutogeneratePass.ScheduleDispatch(commandBuffer, dispatchParams, bufferIndex, dispatchSrcX, dispatchSrcY);
}
private void SetupConstants(Fsr3Upscaler.DispatchDescription dispatchParams, bool resetAccumulation)
private void SetupConstants(in Fsr3Upscaler.DispatchDescription dispatchParams, bool resetAccumulation)
{
ref Fsr3Upscaler.UpscalerConstants constants = ref UpscalerConsts;
ref Fsr3Upscaler.UpscalerConstants constants = ref _upscalerConstants.Value;
constants.previousFrameJitterOffset = constants.jitterOffset;
constants.jitterOffset = dispatchParams.JitterOffset;
@ -350,7 +345,10 @@ namespace FidelityFX.FSR3
constants.viewSpaceToMetersFactor = (dispatchParams.ViewSpaceToMetersFactor > 0.0f) ? dispatchParams.ViewSpaceToMetersFactor : 1.0f;
// Compute params to enable device depth to view space depth computation in shader
constants.deviceToViewDepth = SetupDeviceDepthToViewSpaceDepthParams(dispatchParams);
bool inverted = (_contextDescription.Flags & Fsr3Upscaler.InitializationFlags.EnableDepthInverted) != 0;
bool infinite = (_contextDescription.Flags & Fsr3Upscaler.InitializationFlags.EnableDepthInfinite) != 0;
constants.deviceToViewDepth = FfxUtils.SetupDeviceDepthToViewSpaceDepthParams(
dispatchParams.RenderSize, dispatchParams.CameraNear, dispatchParams.CameraFar, dispatchParams.CameraFovAngleVertical, inverted, infinite);
constants.previousFrameUpscaleSize = constants.upscaleSize;
if (dispatchParams.UpscaleSize.x == 0 && dispatchParams.UpscaleSize.y == 0)
@ -386,7 +384,7 @@ namespace FidelityFX.FSR3
_previousJitterOffset = constants.jitterOffset;
}
int jitterPhaseCount = Fsr3Upscaler.GetJitterPhaseCount(dispatchParams.RenderSize.x, _contextDescription.MaxUpscaleSize.x);
int jitterPhaseCount = FfxUtils.GetJitterPhaseCount(dispatchParams.RenderSize.x, _contextDescription.MaxUpscaleSize.x);
if (resetAccumulation || constants.jitterPhaseCount == 0)
{
constants.jitterPhaseCount = jitterPhaseCount;
@ -409,78 +407,22 @@ namespace FidelityFX.FSR3
constants.frameIndex += 1.0f;
}
private Vector4 SetupDeviceDepthToViewSpaceDepthParams(Fsr3Upscaler.DispatchDescription dispatchParams)
{
bool inverted = (_contextDescription.Flags & Fsr3Upscaler.InitializationFlags.EnableDepthInverted) != 0;
bool infinite = (_contextDescription.Flags & Fsr3Upscaler.InitializationFlags.EnableDepthInfinite) != 0;
// make sure it has no impact if near and far plane values are swapped in dispatch params
// the flags "inverted" and "infinite" will decide what transform to use
float min = Mathf.Min(dispatchParams.CameraNear, dispatchParams.CameraFar);
float max = Mathf.Max(dispatchParams.CameraNear, dispatchParams.CameraFar);
if (inverted)
{
(min, max) = (max, min);
}
float q = max / (min - max);
float d = -1.0f;
Vector4 matrixElemC = new Vector4(q, -1.0f - Mathf.Epsilon, q, 0.0f + Mathf.Epsilon);
Vector4 matrixElemE = new Vector4(q * min, -min - Mathf.Epsilon, q * min, max);
// Revert x and y coords
float aspect = (float)dispatchParams.RenderSize.x / dispatchParams.RenderSize.y;
float cotHalfFovY = Mathf.Cos(0.5f * dispatchParams.CameraFovAngleVertical) / Mathf.Sin(0.5f * dispatchParams.CameraFovAngleVertical);
int matrixIndex = (inverted ? 2 : 0) + (infinite ? 1 : 0);
return new Vector4(
d * matrixElemC[matrixIndex],
matrixElemE[matrixIndex],
aspect / cotHalfFovY,
1.0f / cotHalfFovY);
}
private void SetupRcasConstants(Fsr3Upscaler.DispatchDescription dispatchParams)
private void SetupRcasConstants(in Fsr3Upscaler.DispatchDescription dispatchParams)
{
int sharpnessIndex = Mathf.RoundToInt(Mathf.Clamp01(dispatchParams.Sharpness) * (RcasConfigs.Length - 1));
RcasConsts = RcasConfigs[sharpnessIndex];
_rcasConstants.Value = RcasConfigs[sharpnessIndex];
}
private void SetupSpdConstants(Fsr3Upscaler.DispatchDescription dispatchParams, out Vector2Int dispatchThreadGroupCount)
private void SetupSpdConstants(in Fsr3Upscaler.DispatchDescription dispatchParams, out Vector2Int dispatchThreadGroupCount)
{
RectInt rectInfo = new RectInt(0, 0, dispatchParams.RenderSize.x, dispatchParams.RenderSize.y);
SpdSetup(rectInfo, out dispatchThreadGroupCount, out var workGroupOffset, out var numWorkGroupsAndMips);
// Downsample
ref Fsr3Upscaler.SpdConstants spdConstants = ref SpdConsts;
spdConstants.numWorkGroups = (uint)numWorkGroupsAndMips.x;
spdConstants.mips = (uint)numWorkGroupsAndMips.y;
spdConstants.workGroupOffsetX = (uint)workGroupOffset.x;
spdConstants.workGroupOffsetY = (uint)workGroupOffset.y;
ref Fsr3Upscaler.SpdConstants spdConstants = ref _spdConstants.Value;
FfxSpd.SetupSpdConstants(dispatchParams.RenderSize, ref spdConstants.spd, out dispatchThreadGroupCount);
spdConstants.renderSizeX = (uint)dispatchParams.RenderSize.x;
spdConstants.renderSizeY = (uint)dispatchParams.RenderSize.y;
}
private static void SpdSetup(RectInt rectInfo, out Vector2Int dispatchThreadGroupCount, out Vector2Int workGroupOffset, out Vector2Int numWorkGroupsAndMips, int mips = -1)
{
workGroupOffset = new Vector2Int(rectInfo.x / 64, rectInfo.y / 64);
int endIndexX = (rectInfo.x + rectInfo.width - 1) / 64;
int endIndexY = (rectInfo.y + rectInfo.height - 1) / 64;
dispatchThreadGroupCount = new Vector2Int(endIndexX + 1 - workGroupOffset.x, endIndexY + 1 - workGroupOffset.y);
numWorkGroupsAndMips = new Vector2Int(dispatchThreadGroupCount.x * dispatchThreadGroupCount.y, mips);
if (mips < 0)
{
float resolution = Math.Max(rectInfo.width, rectInfo.height);
numWorkGroupsAndMips.y = Math.Min(Mathf.FloorToInt(Mathf.Log(resolution, 2.0f)), 12);
}
}
private void DebugCheckDispatch(Fsr3Upscaler.DispatchDescription dispatchParams)
private void DebugCheckDispatch(in Fsr3Upscaler.DispatchDescription dispatchParams)
{
if (!dispatchParams.Color.IsValid)
{
@ -630,28 +572,5 @@ namespace FidelityFX.FSR3
new Fsr3Upscaler.RcasConstants(1064229695u, 997604214u),
new Fsr3Upscaler.RcasConstants(1065353216u, 1006648320),
};
private static ComputeBuffer CreateConstantBuffer<TConstants>() where TConstants: struct
{
return new ComputeBuffer(1, Marshal.SizeOf<TConstants>(), ComputeBufferType.Constant);
}
private static void DestroyConstantBuffer(ref ComputeBuffer bufferRef)
{
if (bufferRef == null)
return;
bufferRef.Release();
bufferRef = null;
}
private static void DestroyPass(ref Fsr3UpscalerPass pass)
{
if (pass == null)
return;
pass.Dispose();
pass = null;
}
}
}

326
Runtime/FSR3/Fsr3UpscalerPass.cs

@ -18,10 +18,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.Profiling;
using UnityEngine.Rendering;
namespace FidelityFX.FSR3
@ -31,53 +28,30 @@ namespace FidelityFX.FSR3
/// This loosely matches the FfxPipelineState struct from the original FSR3 codebase, wrapped in an object-oriented blanket.
/// These classes are responsible for loading compute shaders, managing temporary resources, binding resources to shader kernels and dispatching said shaders.
/// </summary>
internal abstract class Fsr3UpscalerPass: IDisposable
internal abstract class Fsr3UpscalerPass: FfxPassWithFlags<Fsr3Upscaler.InitializationFlags>
{
protected readonly Fsr3Upscaler.ContextDescription ContextDescription;
protected readonly Fsr3UpscalerResources Resources;
protected readonly ComputeBuffer Constants;
protected ComputeShader ComputeShader;
protected int KernelIndex;
protected CustomSampler Sampler;
protected Fsr3UpscalerPass(Fsr3Upscaler.ContextDescription contextDescription, Fsr3UpscalerResources resources, ComputeBuffer constants)
protected Fsr3UpscalerPass(in Fsr3Upscaler.ContextDescription contextDescription, Fsr3UpscalerResources resources, ComputeBuffer constants)
: base("FSR3 Upscaler", contextDescription.Flags)
{
ContextDescription = contextDescription;
Resources = resources;
Constants = constants;
}
public virtual void Dispose()
{
}
public void ScheduleDispatch(CommandBuffer commandBuffer, Fsr3Upscaler.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY)
{
commandBuffer.BeginSample(Sampler);
DoScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchX, dispatchY);
commandBuffer.EndSample(Sampler);
}
protected abstract void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr3Upscaler.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY);
protected void InitComputeShader(string passName, ComputeShader shader)
{
InitComputeShader(passName, shader, ContextDescription.Flags);
}
private void InitComputeShader(string passName, ComputeShader shader, Fsr3Upscaler.InitializationFlags flags)
public void ScheduleDispatch(CommandBuffer commandBuffer, in Fsr3Upscaler.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ = 1)
{
if (shader == null)
using (ProfilerSample(commandBuffer))
{
throw new MissingReferenceException($"Shader for FSR3 Upscaler pass '{passName}' could not be loaded! Please ensure it is included in the project correctly.");
Dispatch(commandBuffer, dispatchParams, bufferIndex, dispatchX, dispatchY, dispatchZ);
}
}
ComputeShader = shader;
KernelIndex = ComputeShader.FindKernel("CS");
Sampler = CustomSampler.Create(passName);
protected abstract void Dispatch(CommandBuffer commandBuffer, in Fsr3Upscaler.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ);
protected override void SetupShaderKeywords()
{
bool useLut = false;
#if UNITY_2022_1_OR_NEWER // This will also work in 2020.3.43+ and 2021.3.14+
if (SystemInfo.computeSubGroupSize == 64)
@ -87,50 +61,46 @@ namespace FidelityFX.FSR3
#endif
// This matches the permutation rules from the CreatePipeline* functions
if ((flags & Fsr3Upscaler.InitializationFlags.EnableHighDynamicRange) != 0) ComputeShader.EnableKeyword("FFX_FSR3UPSCALER_OPTION_HDR_COLOR_INPUT");
if ((flags & Fsr3Upscaler.InitializationFlags.EnableDisplayResolutionMotionVectors) == 0) ComputeShader.EnableKeyword("FFX_FSR3UPSCALER_OPTION_LOW_RESOLUTION_MOTION_VECTORS");
if ((flags & Fsr3Upscaler.InitializationFlags.EnableMotionVectorsJitterCancellation) != 0) ComputeShader.EnableKeyword("FFX_FSR3UPSCALER_OPTION_JITTERED_MOTION_VECTORS");
if ((flags & Fsr3Upscaler.InitializationFlags.EnableDepthInverted) != 0) ComputeShader.EnableKeyword("FFX_FSR3UPSCALER_OPTION_INVERTED_DEPTH");
if ((Flags & Fsr3Upscaler.InitializationFlags.EnableHighDynamicRange) != 0) ComputeShader.EnableKeyword("FFX_FSR3UPSCALER_OPTION_HDR_COLOR_INPUT");
if ((Flags & Fsr3Upscaler.InitializationFlags.EnableDisplayResolutionMotionVectors) == 0) ComputeShader.EnableKeyword("FFX_FSR3UPSCALER_OPTION_LOW_RESOLUTION_MOTION_VECTORS");
if ((Flags & Fsr3Upscaler.InitializationFlags.EnableMotionVectorsJitterCancellation) != 0) ComputeShader.EnableKeyword("FFX_FSR3UPSCALER_OPTION_JITTERED_MOTION_VECTORS");
if ((Flags & Fsr3Upscaler.InitializationFlags.EnableDepthInverted) != 0) ComputeShader.EnableKeyword("FFX_FSR3UPSCALER_OPTION_INVERTED_DEPTH");
if (useLut) ComputeShader.EnableKeyword("FFX_FSR3UPSCALER_OPTION_REPROJECT_USE_LANCZOS_TYPE");
if ((flags & Fsr3Upscaler.InitializationFlags.EnableFP16Usage) != 0) ComputeShader.EnableKeyword("FFX_HALF");
if ((Flags & Fsr3Upscaler.InitializationFlags.EnableFP16Usage) != 0) ComputeShader.EnableKeyword("FFX_HALF");
}
}
internal class Fsr3UpscalerPrepareInputsPass : Fsr3UpscalerPass
internal sealed class Fsr3UpscalerPrepareInputsPass : Fsr3UpscalerPass
{
public Fsr3UpscalerPrepareInputsPass(Fsr3Upscaler.ContextDescription contextDescription, Fsr3UpscalerResources resources, ComputeBuffer constants)
public Fsr3UpscalerPrepareInputsPass(in Fsr3Upscaler.ContextDescription contextDescription, Fsr3UpscalerResources resources, ComputeBuffer constants)
: base(contextDescription, resources, constants)
{
InitComputeShader("Prepare Inputs", contextDescription.Shaders.prepareInputsPass);
}
protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr3Upscaler.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY)
protected override void Dispatch(CommandBuffer commandBuffer, in Fsr3Upscaler.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ)
{
ref var color = ref dispatchParams.Color;
ref var depth = ref dispatchParams.Depth;
ref var motionVectors = ref dispatchParams.MotionVectors;
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputColor, color.RenderTarget, color.MipLevel, color.SubElement);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputDepth, depth.RenderTarget, depth.MipLevel, depth.SubElement);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputMotionVectors, motionVectors.RenderTarget, motionVectors.MipLevel, motionVectors.SubElement);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputColor, dispatchParams.Color);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputDepth, dispatchParams.Depth);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputMotionVectors, dispatchParams.MotionVectors);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavDilatedMotionVectors, Resources.DilatedVelocity);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavDilatedDepth, Resources.DilatedDepth);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavReconstructedPrevNearestDepth, Resources.ReconstructedPrevNearestDepth);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavFarthestDepth, Fsr3ShaderIDs.UavIntermediate);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavCurrentLuma, Resources.Luma[frameIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavCurrentLuma, Resources.Luma[bufferIndex]);
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants, 0, Marshal.SizeOf<Fsr3Upscaler.UpscalerConstants>());
commandBuffer.SetComputeConstantBufferParam<Fsr3Upscaler.UpscalerConstants>(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants);
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, dispatchZ);
}
}
internal class Fsr3UpscalerLumaPyramidPass : Fsr3UpscalerPass
internal sealed class Fsr3UpscalerLumaPyramidPass : Fsr3UpscalerPass
{
private readonly ComputeBuffer _spdConstants;
public Fsr3UpscalerLumaPyramidPass(Fsr3Upscaler.ContextDescription contextDescription, Fsr3UpscalerResources resources, ComputeBuffer constants, ComputeBuffer spdConstants)
public Fsr3UpscalerLumaPyramidPass(in Fsr3Upscaler.ContextDescription contextDescription, Fsr3UpscalerResources resources, ComputeBuffer constants, ComputeBuffer spdConstants)
: base(contextDescription, resources, constants)
{
_spdConstants = spdConstants;
@ -138,32 +108,32 @@ namespace FidelityFX.FSR3
InitComputeShader("Compute Luminance Pyramid", contextDescription.Shaders.lumaPyramidPass);
}
protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr3Upscaler.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY)
protected override void Dispatch(CommandBuffer commandBuffer, in Fsr3Upscaler.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ)
{
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvCurrentLuma, Resources.Luma[frameIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvCurrentLuma, Resources.Luma[bufferIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvFarthestDepth, Fsr3ShaderIDs.UavIntermediate);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdAtomicCount, Resources.SpdAtomicCounter);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavFrameInfo, Resources.FrameInfo);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip0, Resources.SpdMips, 0);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip1, Resources.SpdMips, 1);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip2, Resources.SpdMips, 2);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip3, Resources.SpdMips, 3);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip4, Resources.SpdMips, 4);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip5, Resources.SpdMips, 5);
commandBuffer.SetComputeTextureMipParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip0, Resources.SpdMips, 0);
commandBuffer.SetComputeTextureMipParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip1, Resources.SpdMips, 1);
commandBuffer.SetComputeTextureMipParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip2, Resources.SpdMips, 2);
commandBuffer.SetComputeTextureMipParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip3, Resources.SpdMips, 3);
commandBuffer.SetComputeTextureMipParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip4, Resources.SpdMips, 4);
commandBuffer.SetComputeTextureMipParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip5, Resources.SpdMips, 5);
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants, 0, Marshal.SizeOf<Fsr3Upscaler.UpscalerConstants>());
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbSpd, _spdConstants, 0, Marshal.SizeOf<Fsr3Upscaler.SpdConstants>());
commandBuffer.SetComputeConstantBufferParam<Fsr3Upscaler.UpscalerConstants>(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants);
commandBuffer.SetComputeConstantBufferParam<Fsr3Upscaler.SpdConstants>(ComputeShader, Fsr3ShaderIDs.CbSpd, _spdConstants);
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, dispatchZ);
}
}
internal class Fsr3UpscalerShadingChangePyramidPass : Fsr3UpscalerPass
internal sealed class Fsr3UpscalerShadingChangePyramidPass : Fsr3UpscalerPass
{
private readonly ComputeBuffer _spdConstants;
public Fsr3UpscalerShadingChangePyramidPass(Fsr3Upscaler.ContextDescription contextDescription, Fsr3UpscalerResources resources, ComputeBuffer constants, ComputeBuffer spdConstants)
public Fsr3UpscalerShadingChangePyramidPass(in Fsr3Upscaler.ContextDescription contextDescription, Fsr3UpscalerResources resources, ComputeBuffer constants, ComputeBuffer spdConstants)
: base(contextDescription, resources, constants)
{
_spdConstants = spdConstants;
@ -171,110 +141,102 @@ namespace FidelityFX.FSR3
InitComputeShader("Compute Shading Change Pyramid", contextDescription.Shaders.shadingChangePyramidPass);
}
protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr3Upscaler.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY)
protected override void Dispatch(CommandBuffer commandBuffer, in Fsr3Upscaler.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ)
{
ref var exposure = ref dispatchParams.Exposure;
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvCurrentLuma, Resources.Luma[frameIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvPreviousLuma, Resources.Luma[frameIndex ^ 1]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvCurrentLuma, Resources.Luma[bufferIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvPreviousLuma, Resources.Luma[bufferIndex ^ 1]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvDilatedMotionVectors, Resources.DilatedVelocity);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputExposure, exposure.RenderTarget, exposure.MipLevel, exposure.SubElement);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputExposure, dispatchParams.Exposure);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdAtomicCount, Resources.SpdAtomicCounter);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip0, Resources.SpdMips, 0);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip1, Resources.SpdMips, 1);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip2, Resources.SpdMips, 2);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip3, Resources.SpdMips, 3);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip4, Resources.SpdMips, 4);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip5, Resources.SpdMips, 5);
commandBuffer.SetComputeTextureMipParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip0, Resources.SpdMips, 0);
commandBuffer.SetComputeTextureMipParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip1, Resources.SpdMips, 1);
commandBuffer.SetComputeTextureMipParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip2, Resources.SpdMips, 2);
commandBuffer.SetComputeTextureMipParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip3, Resources.SpdMips, 3);
commandBuffer.SetComputeTextureMipParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip4, Resources.SpdMips, 4);
commandBuffer.SetComputeTextureMipParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip5, Resources.SpdMips, 5);
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants, 0, Marshal.SizeOf<Fsr3Upscaler.UpscalerConstants>());
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbSpd, _spdConstants, 0, Marshal.SizeOf<Fsr3Upscaler.SpdConstants>());
commandBuffer.SetComputeConstantBufferParam<Fsr3Upscaler.UpscalerConstants>(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants);
commandBuffer.SetComputeConstantBufferParam<Fsr3Upscaler.SpdConstants>(ComputeShader, Fsr3ShaderIDs.CbSpd, _spdConstants);
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, dispatchZ);
}
}
internal class Fsr3UpscalerShadingChangePass : Fsr3UpscalerPass
internal sealed class Fsr3UpscalerShadingChangePass : Fsr3UpscalerPass
{
public Fsr3UpscalerShadingChangePass(Fsr3Upscaler.ContextDescription contextDescription, Fsr3UpscalerResources resources, ComputeBuffer constants)
public Fsr3UpscalerShadingChangePass(in Fsr3Upscaler.ContextDescription contextDescription, Fsr3UpscalerResources resources, ComputeBuffer constants)
: base(contextDescription, resources, constants)
{
InitComputeShader("Compute Shading Change", contextDescription.Shaders.shadingChangePass);
}
protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr3Upscaler.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY)
protected override void Dispatch(CommandBuffer commandBuffer, in Fsr3Upscaler.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ)
{
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvSpdMips, Resources.SpdMips);
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants, 0, Marshal.SizeOf<Fsr3Upscaler.UpscalerConstants>());
commandBuffer.SetComputeConstantBufferParam<Fsr3Upscaler.UpscalerConstants>(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants);
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, dispatchZ);
}
}
internal class Fsr3UpscalerPrepareReactivityPass : Fsr3UpscalerPass
internal sealed class Fsr3UpscalerPrepareReactivityPass : Fsr3UpscalerPass
{
public Fsr3UpscalerPrepareReactivityPass(Fsr3Upscaler.ContextDescription contextDescription, Fsr3UpscalerResources resources, ComputeBuffer constants)
public Fsr3UpscalerPrepareReactivityPass(in Fsr3Upscaler.ContextDescription contextDescription, Fsr3UpscalerResources resources, ComputeBuffer constants)
: base(contextDescription, resources, constants)
{
InitComputeShader("Prepare Reactivity", contextDescription.Shaders.prepareReactivityPass);
}
protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr3Upscaler.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY)
protected override void Dispatch(CommandBuffer commandBuffer, in Fsr3Upscaler.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ)
{
ref var exposure = ref dispatchParams.Exposure;
ref var reactive = ref dispatchParams.Reactive;
ref var tac = ref dispatchParams.TransparencyAndComposition;
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvReconstructedPrevNearestDepth, Resources.ReconstructedPrevNearestDepth);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvDilatedMotionVectors, Resources.DilatedVelocity);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvDilatedDepth, Resources.DilatedDepth);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvReactiveMask, reactive.RenderTarget, reactive.MipLevel, reactive.SubElement);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvTransparencyAndCompositionMask, tac.RenderTarget, tac.MipLevel, tac.SubElement);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvAccumulation, Resources.Accumulation[frameIndex ^ 1]);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvReactiveMask, dispatchParams.Reactive);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvTransparencyAndCompositionMask, dispatchParams.TransparencyAndComposition);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvAccumulation, Resources.Accumulation[bufferIndex ^ 1]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvShadingChange, Fsr3ShaderIDs.UavShadingChange);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvCurrentLuma, Resources.Luma[frameIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputExposure, exposure.RenderTarget, exposure.MipLevel, exposure.SubElement);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvCurrentLuma, Resources.Luma[bufferIndex]);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputExposure, dispatchParams.Exposure);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavAccumulation, Resources.Accumulation[frameIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavAccumulation, Resources.Accumulation[bufferIndex]);
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants, 0, Marshal.SizeOf<Fsr3Upscaler.UpscalerConstants>());
commandBuffer.SetComputeConstantBufferParam<Fsr3Upscaler.UpscalerConstants>(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants);
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, dispatchZ);
}
}
internal class Fsr3UpscalerLumaInstabilityPass : Fsr3UpscalerPass
internal sealed class Fsr3UpscalerLumaInstabilityPass : Fsr3UpscalerPass
{
public Fsr3UpscalerLumaInstabilityPass(Fsr3Upscaler.ContextDescription contextDescription, Fsr3UpscalerResources resources, ComputeBuffer constants)
public Fsr3UpscalerLumaInstabilityPass(in Fsr3Upscaler.ContextDescription contextDescription, Fsr3UpscalerResources resources, ComputeBuffer constants)
: base(contextDescription, resources, constants)
{
InitComputeShader("Compute Luminance Instability", contextDescription.Shaders.lumaInstabilityPass);
}
protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr3Upscaler.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY)
protected override void Dispatch(CommandBuffer commandBuffer, in Fsr3Upscaler.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ)
{
ref var exposure = ref dispatchParams.Exposure;
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputExposure, exposure.RenderTarget, exposure.MipLevel, exposure.SubElement);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputExposure, dispatchParams.Exposure);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvDilatedReactiveMasks, Fsr3ShaderIDs.UavDilatedReactiveMasks);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvDilatedMotionVectors, Resources.DilatedVelocity);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvFrameInfo, Resources.FrameInfo);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvLumaHistory, Resources.LumaHistory[frameIndex ^ 1]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvLumaHistory, Resources.LumaHistory[bufferIndex ^ 1]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvFarthestDepthMip1, Fsr3ShaderIDs.UavFarthestDepthMip1);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvCurrentLuma, Resources.Luma[frameIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvCurrentLuma, Resources.Luma[bufferIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavLumaHistory, Resources.LumaHistory[frameIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavLumaHistory, Resources.LumaHistory[bufferIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavLumaInstability, Fsr3ShaderIDs.UavIntermediate);
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants, 0, Marshal.SizeOf<Fsr3Upscaler.UpscalerConstants>());
commandBuffer.SetComputeConstantBufferParam<Fsr3Upscaler.UpscalerConstants>(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants);
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, dispatchZ);
}
}
internal class Fsr3UpscalerAccumulatePass : Fsr3UpscalerPass
internal sealed class Fsr3UpscalerAccumulatePass : Fsr3UpscalerPass
{
private const string SharpeningKeyword = "FFX_FSR3UPSCALER_OPTION_APPLY_SHARPENING";
@ -282,7 +244,7 @@ namespace FidelityFX.FSR3
private readonly LocalKeyword _sharpeningKeyword;
#endif
public Fsr3UpscalerAccumulatePass(Fsr3Upscaler.ContextDescription contextDescription, Fsr3UpscalerResources resources, ComputeBuffer constants)
public Fsr3UpscalerAccumulatePass(in Fsr3Upscaler.ContextDescription contextDescription, Fsr3UpscalerResources resources, ComputeBuffer constants)
: base(contextDescription, resources, constants)
{
InitComputeShader("Accumulate", contextDescription.Shaders.accumulatePass);
@ -291,7 +253,7 @@ namespace FidelityFX.FSR3
#endif
}
protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr3Upscaler.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY)
protected override void Dispatch(CommandBuffer commandBuffer, in Fsr3Upscaler.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ)
{
#if UNITY_2021_2_OR_NEWER
if (dispatchParams.EnableSharpening)
@ -305,44 +267,39 @@ namespace FidelityFX.FSR3
commandBuffer.DisableShaderKeyword(SharpeningKeyword);
#endif
ref var color = ref dispatchParams.Color;
ref var exposure = ref dispatchParams.Exposure;
ref var output = ref dispatchParams.Output;
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputExposure, exposure.RenderTarget, exposure.MipLevel, exposure.SubElement);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputExposure, dispatchParams.Exposure);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvDilatedReactiveMasks, Fsr3ShaderIDs.UavDilatedReactiveMasks);
if ((ContextDescription.Flags & Fsr3Upscaler.InitializationFlags.EnableDisplayResolutionMotionVectors) == 0)
if ((Flags & Fsr3Upscaler.InitializationFlags.EnableDisplayResolutionMotionVectors) == 0)
{
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvDilatedMotionVectors, Resources.DilatedVelocity);
}
else
{
ref var motionVectors = ref dispatchParams.MotionVectors;
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputMotionVectors, motionVectors.RenderTarget, motionVectors.MipLevel, motionVectors.SubElement);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputMotionVectors, dispatchParams.MotionVectors);
}
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInternalUpscaled, Resources.InternalUpscaled[frameIndex ^ 1]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInternalUpscaled, Resources.InternalUpscaled[bufferIndex ^ 1]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvLanczosLut, Resources.LanczosLut);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvFarthestDepthMip1, Fsr3ShaderIDs.UavFarthestDepthMip1);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvCurrentLuma, Resources.Luma[frameIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvCurrentLuma, Resources.Luma[bufferIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvLumaInstability, Fsr3ShaderIDs.UavIntermediate);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputColor, color.RenderTarget, color.MipLevel, color.SubElement);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputColor, dispatchParams.Color);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavInternalUpscaled, Resources.InternalUpscaled[frameIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavUpscaledOutput, output.RenderTarget, output.MipLevel, output.SubElement);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavInternalUpscaled, Resources.InternalUpscaled[bufferIndex]);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavUpscaledOutput, dispatchParams.Output);
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants, 0, Marshal.SizeOf<Fsr3Upscaler.UpscalerConstants>());
commandBuffer.SetComputeConstantBufferParam<Fsr3Upscaler.UpscalerConstants>(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants);
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, dispatchZ);
}
}
internal class Fsr3UpscalerSharpenPass : Fsr3UpscalerPass
internal sealed class Fsr3UpscalerSharpenPass : Fsr3UpscalerPass
{
private readonly ComputeBuffer _rcasConstants;
public Fsr3UpscalerSharpenPass(Fsr3Upscaler.ContextDescription contextDescription, Fsr3UpscalerResources resources, ComputeBuffer constants, ComputeBuffer rcasConstants)
public Fsr3UpscalerSharpenPass(in Fsr3Upscaler.ContextDescription contextDescription, Fsr3UpscalerResources resources, ComputeBuffer constants, ComputeBuffer rcasConstants)
: base(contextDescription, resources, constants)
{
_rcasConstants = rcasConstants;
@ -350,27 +307,25 @@ namespace FidelityFX.FSR3
InitComputeShader("RCAS Sharpening", contextDescription.Shaders.sharpenPass);
}
protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr3Upscaler.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY)
protected override void Dispatch(CommandBuffer commandBuffer, in Fsr3Upscaler.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ)
{
ref var exposure = ref dispatchParams.Exposure;
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputExposure, exposure.RenderTarget, exposure.MipLevel, exposure.SubElement);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvRcasInput, Resources.InternalUpscaled[frameIndex]);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputExposure, dispatchParams.Exposure);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvRcasInput, Resources.InternalUpscaled[bufferIndex]);
ref var output = ref dispatchParams.Output;
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavUpscaledOutput, output.RenderTarget, output.MipLevel, output.SubElement);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavUpscaledOutput, dispatchParams.Output);
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants, 0, Marshal.SizeOf<Fsr3Upscaler.UpscalerConstants>());
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbRcas, _rcasConstants, 0, Marshal.SizeOf<Fsr3Upscaler.RcasConstants>());
commandBuffer.SetComputeConstantBufferParam<Fsr3Upscaler.UpscalerConstants>(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants);
commandBuffer.SetComputeConstantBufferParam<Fsr3Upscaler.RcasConstants>(ComputeShader, Fsr3ShaderIDs.CbRcas, _rcasConstants);
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, dispatchZ);
}
}
internal class Fsr3UpscalerGenerateReactivePass : Fsr3UpscalerPass
internal sealed class Fsr3UpscalerGenerateReactivePass : Fsr3UpscalerPass
{
private readonly ComputeBuffer _generateReactiveConstants;
public Fsr3UpscalerGenerateReactivePass(Fsr3Upscaler.ContextDescription contextDescription, Fsr3UpscalerResources resources, ComputeBuffer generateReactiveConstants)
public Fsr3UpscalerGenerateReactivePass(in Fsr3Upscaler.ContextDescription contextDescription, Fsr3UpscalerResources resources, ComputeBuffer generateReactiveConstants)
: base(contextDescription, resources, null)
{
_generateReactiveConstants = generateReactiveConstants;
@ -378,35 +333,30 @@ namespace FidelityFX.FSR3
InitComputeShader("Auto-Generate Reactive Mask", contextDescription.Shaders.autoGenReactivePass);
}
protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr3Upscaler.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY)
protected override void Dispatch(CommandBuffer commandBuffer, in Fsr3Upscaler.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ)
{
}
public void ScheduleDispatch(CommandBuffer commandBuffer, Fsr3Upscaler.GenerateReactiveDescription dispatchParams, int dispatchX, int dispatchY)
public void ScheduleDispatch(CommandBuffer commandBuffer, in Fsr3Upscaler.GenerateReactiveDescription dispatchParams, int dispatchX, int dispatchY)
{
commandBuffer.BeginSample(Sampler);
ref var opaqueOnly = ref dispatchParams.ColorOpaqueOnly;
ref var color = ref dispatchParams.ColorPreUpscale;
ref var reactive = ref dispatchParams.OutReactive;
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvOpaqueOnly, opaqueOnly.RenderTarget, opaqueOnly.MipLevel, opaqueOnly.SubElement);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputColor, color.RenderTarget, color.MipLevel, color.SubElement);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavAutoReactive, reactive.RenderTarget, reactive.MipLevel, reactive.SubElement);
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbGenReactive, _generateReactiveConstants, 0, Marshal.SizeOf<Fsr3Upscaler.GenerateReactiveConstants>());
using (ProfilerSample(commandBuffer))
{
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvOpaqueOnly, dispatchParams.ColorOpaqueOnly);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputColor, dispatchParams.ColorPreUpscale);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavAutoReactive, dispatchParams.OutReactive);
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
commandBuffer.SetComputeConstantBufferParam<Fsr3Upscaler.GenerateReactiveConstants>(ComputeShader, Fsr3ShaderIDs.CbGenReactive, _generateReactiveConstants);
commandBuffer.EndSample(Sampler);
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
}
}
}
internal class Fsr3UpscalerTcrAutogeneratePass : Fsr3UpscalerPass
internal sealed class Fsr3UpscalerTcrAutogeneratePass : Fsr3UpscalerPass
{
private readonly ComputeBuffer _tcrAutogenerateConstants;
public Fsr3UpscalerTcrAutogeneratePass(Fsr3Upscaler.ContextDescription contextDescription, Fsr3UpscalerResources resources, ComputeBuffer constants, ComputeBuffer tcrAutogenerateConstants)
public Fsr3UpscalerTcrAutogeneratePass(in Fsr3Upscaler.ContextDescription contextDescription, Fsr3UpscalerResources resources, ComputeBuffer constants, ComputeBuffer tcrAutogenerateConstants)
: base(contextDescription, resources, constants)
{
_tcrAutogenerateConstants = tcrAutogenerateConstants;
@ -414,58 +364,50 @@ namespace FidelityFX.FSR3
InitComputeShader("Auto-Generate Transparency & Composition Mask", contextDescription.Shaders.tcrAutoGenPass);
}
protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr3Upscaler.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY)
protected override void Dispatch(CommandBuffer commandBuffer, in Fsr3Upscaler.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ)
{
ref var color = ref dispatchParams.Color;
ref var motionVectors = ref dispatchParams.MotionVectors;
ref var opaqueOnly = ref dispatchParams.ColorOpaqueOnly;
ref var reactive = ref dispatchParams.Reactive;
ref var tac = ref dispatchParams.TransparencyAndComposition;
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvOpaqueOnly, opaqueOnly.RenderTarget, opaqueOnly.MipLevel, opaqueOnly.SubElement);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputColor, color.RenderTarget, color.MipLevel, color.SubElement);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputMotionVectors, motionVectors.RenderTarget, motionVectors.MipLevel, motionVectors.SubElement);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvPrevColorPreAlpha, Resources.PrevPreAlpha[frameIndex ^ 1]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvPrevColorPostAlpha, Resources.PrevPostAlpha[frameIndex ^ 1]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvReactiveMask, reactive.RenderTarget, reactive.MipLevel, reactive.SubElement);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvTransparencyAndCompositionMask, tac.RenderTarget, tac.MipLevel, tac.SubElement);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvOpaqueOnly, dispatchParams.ColorOpaqueOnly);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputColor, dispatchParams.Color);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputMotionVectors, dispatchParams.MotionVectors);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvPrevColorPreAlpha, Resources.PrevPreAlpha[bufferIndex ^ 1]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvPrevColorPostAlpha, Resources.PrevPostAlpha[bufferIndex ^ 1]);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvReactiveMask, dispatchParams.Reactive);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvTransparencyAndCompositionMask, dispatchParams.TransparencyAndComposition);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavAutoReactive, Resources.AutoReactive);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavAutoComposition, Resources.AutoComposition);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavPrevColorPreAlpha, Resources.PrevPreAlpha[frameIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavPrevColorPostAlpha, Resources.PrevPostAlpha[frameIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavPrevColorPreAlpha, Resources.PrevPreAlpha[bufferIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavPrevColorPostAlpha, Resources.PrevPostAlpha[bufferIndex]);
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants, 0, Marshal.SizeOf<Fsr3Upscaler.UpscalerConstants>());
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbGenReactive, _tcrAutogenerateConstants, 0, Marshal.SizeOf<Fsr3Upscaler.GenerateReactiveConstants2>());
commandBuffer.SetComputeConstantBufferParam<Fsr3Upscaler.UpscalerConstants>(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants);
commandBuffer.SetComputeConstantBufferParam<Fsr3Upscaler.GenerateReactiveConstants2>(ComputeShader, Fsr3ShaderIDs.CbGenReactive, _tcrAutogenerateConstants);
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, dispatchZ);
}
}
#if UNITY_EDITOR || DEVELOPMENT_BUILD
internal class Fsr3UpscalerDebugViewPass : Fsr3UpscalerPass
internal sealed class Fsr3UpscalerDebugViewPass : Fsr3UpscalerPass
{
public Fsr3UpscalerDebugViewPass(Fsr3Upscaler.ContextDescription contextDescription, Fsr3UpscalerResources resources, ComputeBuffer constants)
public Fsr3UpscalerDebugViewPass(in Fsr3Upscaler.ContextDescription contextDescription, Fsr3UpscalerResources resources, ComputeBuffer constants)
: base(contextDescription, resources, constants)
{
InitComputeShader("Debug View", contextDescription.Shaders.debugViewPass);
}
protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr3Upscaler.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY)
protected override void Dispatch(CommandBuffer commandBuffer, in Fsr3Upscaler.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ)
{
ref var exposure = ref dispatchParams.Exposure;
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvDilatedReactiveMasks, Fsr3ShaderIDs.UavDilatedReactiveMasks);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvDilatedMotionVectors, Resources.DilatedVelocity);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvDilatedDepth, Resources.DilatedDepth);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInternalUpscaled, Resources.InternalUpscaled[frameIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputExposure, exposure.RenderTarget, exposure.MipLevel, exposure.SubElement);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInternalUpscaled, Resources.InternalUpscaled[bufferIndex]);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputExposure, dispatchParams.Exposure);
ref var output = ref dispatchParams.Output;
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavUpscaledOutput, output.RenderTarget, output.MipLevel, output.SubElement);
commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavUpscaledOutput, dispatchParams.Output);
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants, 0, Marshal.SizeOf<Fsr3Upscaler.UpscalerConstants>());
commandBuffer.SetComputeConstantBufferParam<Fsr3Upscaler.UpscalerConstants>(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants);
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, dispatchZ);
}
}
#endif

93
Runtime/FSR3/Fsr3UpscalerResources.cs

@ -29,7 +29,7 @@ namespace FidelityFX.FSR3
/// Helper class for bundling and managing persistent resources required by the FSR3 Upscaler process.
/// This includes lookup tables, default fallback resources and double-buffered resources that get swapped between frames.
/// </summary>
internal class Fsr3UpscalerResources
internal class Fsr3UpscalerResources: FfxResourcesBase
{
public Texture2D LanczosLut;
public Texture2D DefaultExposure;
@ -51,63 +51,44 @@ namespace FidelityFX.FSR3
public readonly RenderTexture[] PrevPreAlpha = new RenderTexture[2];
public readonly RenderTexture[] PrevPostAlpha = new RenderTexture[2];
public void Create(Fsr3Upscaler.ContextDescription contextDescription)
public void Create(in Fsr3Upscaler.ContextDescription contextDescription)
{
// Generate the data for the LUT
const int lanczos2LutWidth = 128;
float[] lanczos2Weights = new float[lanczos2LutWidth];
for (int currentLanczosWidthIndex = 0; currentLanczosWidthIndex < lanczos2LutWidth; ++currentLanczosWidthIndex)
{
float x = 2.0f * currentLanczosWidthIndex / (lanczos2LutWidth - 1);
float y = Fsr3Upscaler.Lanczos2(x);
lanczos2Weights[currentLanczosWidthIndex] = y;
}
float[] lanczos2Weights = FfxUtils.GenerateLanczos2Table(lanczos2LutWidth);
Vector2Int maxRenderSize = contextDescription.MaxRenderSize;
Vector2Int maxRenderSizeDiv2 = maxRenderSize / 2;
// Resource FSR3UPSCALER_LanczosLutData: FFX_RESOURCE_USAGE_READ_ONLY, FFX_SURFACE_FORMAT_R16_SNORM, FFX_RESOURCE_FLAGS_NONE
// R16_SNorm textures are not supported by Unity on most platforms, strangely enough. So instead we use R32_SFloat and upload pre-normalized float data.
LanczosLut = new Texture2D(lanczos2LutWidth, 1, GraphicsFormat.R32_SFloat, TextureCreationFlags.None) { name = "FSR3UPSCALER_LanczosLutData" };
LanczosLut.SetPixelData(lanczos2Weights, 0);
LanczosLut.Apply();
LanczosLut = CreateLookup("FSR3UPSCALER_LanczosLutData", new Vector2Int(lanczos2LutWidth, 1), GraphicsFormat.R32_SFloat, lanczos2Weights);
// Resource FSR3UPSCALER_DefaultReactivityMask: FFX_RESOURCE_USAGE_READ_ONLY, FFX_SURFACE_FORMAT_R8_UNORM, FFX_RESOURCE_FLAGS_NONE
DefaultReactive = new Texture2D(1, 1, GraphicsFormat.R8_UNorm, TextureCreationFlags.None) { name = "FSR3UPSCALER_DefaultReactivityMask" };
DefaultReactive.SetPixel(0, 0, Color.clear);
DefaultReactive.Apply();
DefaultReactive = CreateLookup("FSR3UPSCALER_DefaultReactivityMask", GraphicsFormat.R8_UNorm, Color.clear);
// Resource FSR3UPSCALER_DefaultExposure: FFX_RESOURCE_USAGE_READ_ONLY, FFX_SURFACE_FORMAT_R32G32_FLOAT, FFX_RESOURCE_FLAGS_NONE
DefaultExposure = new Texture2D(1, 1, GraphicsFormat.R32G32_SFloat, TextureCreationFlags.None) { name = "FSR3UPSCALER_DefaultExposure" };
DefaultExposure.SetPixel(0, 0, Color.clear);
DefaultExposure.Apply();
DefaultExposure = CreateLookup("FSR3UPSCALER_DefaultExposure", GraphicsFormat.R32G32_SFloat, Color.clear);
// Resource FSR3UPSCALER_SpdAtomicCounter: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R32_UINT, FFX_RESOURCE_FLAGS_ALIASABLE
// Despite what the original FSR3 codebase says, this resource really isn't aliasable. Resetting this counter to 0 every frame breaks auto-exposure on MacOS Metal.
SpdAtomicCounter = new RenderTexture(1, 1, 0, GraphicsFormat.R32_UInt) { name = "FSR3UPSCALER_SpdAtomicCounter", enableRandomWrite = true };
SpdAtomicCounter.Create();
SpdAtomicCounter = CreateResource("FSR3UPSCALER_SpdAtomicCounter", Vector2Int.one, GraphicsFormat.R32_UInt);
// Resource FSR3UPSCALER_SpdMips: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R16G16_FLOAT, FFX_RESOURCE_FLAGS_ALIASABLE
// This is a rather special case: it's an aliasable resource, but because we require a mipmap chain and bind specific mip levels per shader, we can't easily use temporary RTs for this.
int mipCount = 1 + Mathf.FloorToInt(Mathf.Log(Math.Max(maxRenderSizeDiv2.x, maxRenderSizeDiv2.y), 2.0f));
SpdMips = new RenderTexture(maxRenderSizeDiv2.x, maxRenderSizeDiv2.y, 0, GraphicsFormat.R16G16_SFloat, mipCount) { name = "FSR3UPSCALER_SpdMips", enableRandomWrite = true, useMipMap = true, autoGenerateMips = false };
SpdMips.Create();
SpdMips = CreateResourceMips("FSR3UPSCALER_SpdMips", maxRenderSizeDiv2, GraphicsFormat.R16G16_SFloat);
// Resource FSR3UPSCALER_DilatedVelocity: FFX_RESOURCE_USAGE_RENDERTARGET | FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R16G16_FLOAT, FFX_RESOURCE_FLAGS_NONE
DilatedVelocity = new RenderTexture(maxRenderSize.x, maxRenderSize.y, 0, GraphicsFormat.R16G16_SFloat) { name = "FSR3UPSCALER_DilatedVelocity", enableRandomWrite = true };
DilatedVelocity.Create();
DilatedVelocity = CreateResource("FSR3UPSCALER_DilatedVelocity", maxRenderSize, GraphicsFormat.R16G16_SFloat);
// Resource FSR3UPSCALER_DilatedDepth: FFX_RESOURCE_USAGE_RENDERTARGET | FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R32_FLOAT, FFX_RESOURCE_FLAGS_NONE
DilatedDepth = new RenderTexture(maxRenderSize.x, maxRenderSize.y, 0, GraphicsFormat.R32_SFloat) { name = "FSR3UPSCALER_DilatedDepth", enableRandomWrite = true };
DilatedDepth.Create();
DilatedDepth = CreateResource("FSR3UPSCALER_DilatedDepth", maxRenderSize, GraphicsFormat.R32_SFloat);
// Resource FSR3UPSCALER_ReconstructedPrevNearestDepth: FFX_RESOURCE_USAGE_RENDERTARGET | FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R32_UINT, FFX_RESOURCE_FLAGS_NONE
ReconstructedPrevNearestDepth = new RenderTexture(maxRenderSize.x, maxRenderSize.y, 0, GraphicsFormat.R32_UInt) { name = "FSR3UPSCALER_ReconstructedPrevNearestDepth", enableRandomWrite = true };
ReconstructedPrevNearestDepth.Create();
ReconstructedPrevNearestDepth = CreateResource("FSR3UPSCALER_ReconstructedPrevNearestDepth", maxRenderSize, GraphicsFormat.R32_UInt);
// Resource FSR3UPSCALER_FrameInfo: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R32G32B32A32_FLOAT, FFX_RESOURCE_FLAGS_NONE
FrameInfo = new RenderTexture(1, 1, 0, GraphicsFormat.R32G32B32A32_SFloat) { name = "FSR3UPSCALER_FrameInfo", enableRandomWrite = true };
FrameInfo.Create();
FrameInfo = CreateResource("FSR3UPSCALER_FrameInfo", Vector2Int.one, GraphicsFormat.R32G32B32A32_SFloat);
// Resources FSR3UPSCALER_Accumulation1/2: FFX_RESOURCE_USAGE_RENDERTARGET | FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R8_UNORM, FFX_RESOURCE_FLAGS_NONE
CreateDoubleBufferedResource(Accumulation, "FSR3UPSCALER_Accumulation", maxRenderSize, GraphicsFormat.R8_UNorm);
@ -122,15 +103,13 @@ namespace FidelityFX.FSR3
CreateDoubleBufferedResource(LumaHistory, "FSR3UPSCALER_LumaHistory", maxRenderSize, GraphicsFormat.R16G16B16A16_SFloat);
}
public void CreateTcrAutogenResources(Fsr3Upscaler.ContextDescription contextDescription)
public void CreateTcrAutogenResources(in Fsr3Upscaler.ContextDescription contextDescription)
{
// Resource FSR3UPSCALER_AutoReactive: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R8_UNORM, FFX_RESOURCE_FLAGS_NONE
AutoReactive = new RenderTexture(contextDescription.MaxRenderSize.x, contextDescription.MaxRenderSize.y, 0, GraphicsFormat.R8_UNorm) { name = "FSR3UPSCALER_AutoReactive", enableRandomWrite = true };
AutoReactive.Create();
AutoReactive = CreateResource("FSR3UPSCALER_AutoReactive", contextDescription.MaxRenderSize, GraphicsFormat.R8_UNorm);
// Resource FSR3UPSCALER_AutoComposition: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R8_UNORM, FFX_RESOURCE_FLAGS_NONE
AutoComposition = new RenderTexture(contextDescription.MaxRenderSize.x, contextDescription.MaxRenderSize.y, 0, GraphicsFormat.R8_UNorm) { name = "FSR3UPSCALER_AutoComposition", enableRandomWrite = true };
AutoComposition.Create();
AutoComposition = CreateResource("FSR3UPSCALER_AutoComposition", contextDescription.MaxRenderSize, GraphicsFormat.R8_UNorm);
// Resources FSR3UPSCALER_PrevPreAlpha0/1: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R11G11B10_FLOAT, FFX_RESOURCE_FLAGS_NONE
CreateDoubleBufferedResource(PrevPreAlpha, "FSR3UPSCALER_PrevPreAlpha", contextDescription.MaxRenderSize, GraphicsFormat.B10G11R11_UFloatPack32);
@ -141,7 +120,7 @@ namespace FidelityFX.FSR3
// Set up shared aliasable resources, i.e. temporary render textures
// These do not need to persist between frames, but they do need to be available between passes
public static void CreateAliasableResources(CommandBuffer commandBuffer, Fsr3Upscaler.ContextDescription contextDescription, Fsr3Upscaler.DispatchDescription dispatchParams)
public static void CreateAliasableResources(CommandBuffer commandBuffer, in Fsr3Upscaler.ContextDescription contextDescription)
{
Vector2Int maxUpscaleSize = contextDescription.MaxUpscaleSize;
Vector2Int maxRenderSize = contextDescription.MaxRenderSize;
@ -173,15 +152,6 @@ namespace FidelityFX.FSR3
commandBuffer.ReleaseTemporaryRT(Fsr3ShaderIDs.UavIntermediate);
}
private static void CreateDoubleBufferedResource(RenderTexture[] resource, string name, Vector2Int size, GraphicsFormat format)
{
for (int i = 0; i < 2; ++i)
{
resource[i] = new RenderTexture(size.x, size.y, 0, format) { name = name + (i + 1), enableRandomWrite = true };
resource[i].Create();
}
}
public void Destroy()
{
DestroyTcrAutogenResources();
@ -210,36 +180,5 @@ namespace FidelityFX.FSR3
DestroyResource(ref AutoComposition);
DestroyResource(ref AutoReactive);
}
private static void DestroyResource(ref Texture2D resource)
{
if (resource == null)
return;
#if UNITY_EDITOR
if (Application.isPlaying && !UnityEditor.EditorApplication.isPaused)
UnityEngine.Object.Destroy(resource);
else
UnityEngine.Object.DestroyImmediate(resource);
#else
UnityEngine.Object.Destroy(resource);
#endif
resource = null;
}
private static void DestroyResource(ref RenderTexture resource)
{
if (resource == null)
return;
resource.Release();
resource = null;
}
private static void DestroyResource(RenderTexture[] resource)
{
for (int i = 0; i < resource.Length; ++i)
DestroyResource(ref resource[i]);
}
}
}

4
Shaders/ffx_fsr2_accumulate_pass.compute

@ -28,9 +28,9 @@
#pragma multi_compile_local __ FFX_FSR2_OPTION_INVERTED_DEPTH
#pragma multi_compile_local __ FFX_FSR2_OPTION_APPLY_SHARPENING
#pragma multi_compile __ UNITY_FSR_TEXTURE2D_X_ARRAY
#pragma multi_compile __ UNITY_FFX_TEXTURE2D_X_ARRAY
#include "ffx_fsr_unity_common.cginc"
#include "ffx_unity_common.cginc"
// Ensure the correct value is defined for this keyword, as it is used to select one of multiple sampler functions
#ifdef FFX_FSR2_OPTION_REPROJECT_USE_LANCZOS_TYPE

4
Shaders/ffx_fsr2_autogen_reactive_pass.compute

@ -25,8 +25,8 @@
#pragma multi_compile_local __ FFX_FSR2_OPTION_JITTERED_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR2_OPTION_INVERTED_DEPTH
#pragma multi_compile __ UNITY_FSR_TEXTURE2D_X_ARRAY
#pragma multi_compile __ UNITY_FFX_TEXTURE2D_X_ARRAY
#include "ffx_fsr_unity_common.cginc"
#include "ffx_unity_common.cginc"
#include "shaders/ffx_fsr2_autogen_reactive_pass.hlsl"

4
Shaders/ffx_fsr2_compute_luminance_pyramid_pass.compute

@ -25,9 +25,9 @@
#pragma multi_compile_local __ FFX_FSR2_OPTION_JITTERED_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR2_OPTION_INVERTED_DEPTH
#pragma multi_compile __ UNITY_FSR_TEXTURE2D_X_ARRAY
#pragma multi_compile __ UNITY_FFX_TEXTURE2D_X_ARRAY
#include "ffx_fsr_unity_common.cginc"
#include "ffx_unity_common.cginc"
// Wave operations require shader model 6.0; this can only be enabled when using DXC on D3D12
// These pragmas are commented out by default as Unity will sometimes ignore the #if's and try to enable these features anyway.

4
Shaders/ffx_fsr2_depth_clip_pass.compute

@ -25,8 +25,8 @@
#pragma multi_compile_local __ FFX_FSR2_OPTION_JITTERED_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR2_OPTION_INVERTED_DEPTH
#pragma multi_compile __ UNITY_FSR_TEXTURE2D_X_ARRAY
#pragma multi_compile __ UNITY_FFX_TEXTURE2D_X_ARRAY
#include "ffx_fsr_unity_common.cginc"
#include "ffx_unity_common.cginc"
#include "shaders/ffx_fsr2_depth_clip_pass.hlsl"

4
Shaders/ffx_fsr2_lock_pass.compute

@ -25,8 +25,8 @@
#pragma multi_compile_local __ FFX_FSR2_OPTION_JITTERED_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR2_OPTION_INVERTED_DEPTH
#pragma multi_compile __ UNITY_FSR_TEXTURE2D_X_ARRAY
#pragma multi_compile __ UNITY_FFX_TEXTURE2D_X_ARRAY
#include "ffx_fsr_unity_common.cginc"
#include "ffx_unity_common.cginc"
#include "shaders/ffx_fsr2_lock_pass.hlsl"

4
Shaders/ffx_fsr2_rcas_pass.compute

@ -24,8 +24,8 @@
#pragma multi_compile_local __ FFX_FSR2_OPTION_JITTERED_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR2_OPTION_INVERTED_DEPTH
#pragma multi_compile __ UNITY_FSR_TEXTURE2D_X_ARRAY
#pragma multi_compile __ UNITY_FFX_TEXTURE2D_X_ARRAY
#include "ffx_fsr_unity_common.cginc"
#include "ffx_unity_common.cginc"
#include "shaders/ffx_fsr2_rcas_pass.hlsl"

4
Shaders/ffx_fsr2_reconstruct_previous_depth_pass.compute

@ -26,8 +26,8 @@
#pragma multi_compile_local __ FFX_FSR2_OPTION_JITTERED_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR2_OPTION_INVERTED_DEPTH
#pragma multi_compile __ UNITY_FSR_TEXTURE2D_X_ARRAY
#pragma multi_compile __ UNITY_FFX_TEXTURE2D_X_ARRAY
#include "ffx_fsr_unity_common.cginc"
#include "ffx_unity_common.cginc"
#include "shaders/ffx_fsr2_reconstruct_previous_depth_pass.hlsl"

4
Shaders/ffx_fsr2_tcr_autogen_pass.compute

@ -25,8 +25,8 @@
#pragma multi_compile_local __ FFX_FSR2_OPTION_JITTERED_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR2_OPTION_INVERTED_DEPTH
#pragma multi_compile __ UNITY_FSR_TEXTURE2D_X_ARRAY
#pragma multi_compile __ UNITY_FFX_TEXTURE2D_X_ARRAY
#include "ffx_fsr_unity_common.cginc"
#include "ffx_unity_common.cginc"
#include "shaders/ffx_fsr2_tcr_autogen_pass.hlsl"

4
Shaders/ffx_fsr3upscaler_accumulate_pass.compute

@ -26,9 +26,9 @@
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_LOW_RESOLUTION_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_APPLY_SHARPENING
#pragma multi_compile __ UNITY_FSR_TEXTURE2D_X_ARRAY
#pragma multi_compile __ UNITY_FFX_TEXTURE2D_X_ARRAY
#include "ffx_fsr_unity_common.cginc"
#include "ffx_unity_common.cginc"
// Ensure the correct value is defined for this keyword, as it is used to select one of multiple sampler functions
#ifdef FFX_FSR3UPSCALER_OPTION_REPROJECT_USE_LANCZOS_TYPE

4
Shaders/ffx_fsr3upscaler_autogen_reactive_pass.compute

@ -22,8 +22,8 @@
#pragma multi_compile_local __ FFX_HALF
#pragma multi_compile __ UNITY_FSR_TEXTURE2D_X_ARRAY
#pragma multi_compile __ UNITY_FFX_TEXTURE2D_X_ARRAY
#include "ffx_fsr_unity_common.cginc"
#include "ffx_unity_common.cginc"
#include "shaders/ffx_fsr3upscaler_autogen_reactive_pass.hlsl"

4
Shaders/ffx_fsr3upscaler_debug_view_pass.compute

@ -22,8 +22,8 @@
#pragma multi_compile_local __ FFX_HALF
#pragma multi_compile __ UNITY_FSR_TEXTURE2D_X_ARRAY
#pragma multi_compile __ UNITY_FFX_TEXTURE2D_X_ARRAY
#include "ffx_fsr_unity_common.cginc"
#include "ffx_unity_common.cginc"
#include "shaders/ffx_fsr3upscaler_debug_view_pass.hlsl"

4
Shaders/ffx_fsr3upscaler_luma_instability_pass.compute

@ -22,8 +22,8 @@
#pragma multi_compile_local __ FFX_HALF
#pragma multi_compile __ UNITY_FSR_TEXTURE2D_X_ARRAY
#pragma multi_compile __ UNITY_FFX_TEXTURE2D_X_ARRAY
#include "ffx_fsr_unity_common.cginc"
#include "ffx_unity_common.cginc"
#include "shaders/ffx_fsr3upscaler_luma_instability_pass.hlsl"

4
Shaders/ffx_fsr3upscaler_luma_pyramid_pass.compute

@ -22,9 +22,9 @@
#pragma multi_compile_local __ FFX_HALF
#pragma multi_compile __ UNITY_FSR_TEXTURE2D_X_ARRAY
#pragma multi_compile __ UNITY_FFX_TEXTURE2D_X_ARRAY
#include "ffx_fsr_unity_common.cginc"
#include "ffx_unity_common.cginc"
// Wave operations require shader model 6.0; this can only be enabled when using DXC on D3D12
// These pragmas are commented out by default as Unity will sometimes ignore the #if's and try to enable these features anyway.

4
Shaders/ffx_fsr3upscaler_prepare_inputs_pass.compute

@ -24,8 +24,8 @@
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_LOW_RESOLUTION_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_INVERTED_DEPTH
#pragma multi_compile __ UNITY_FSR_TEXTURE2D_X_ARRAY
#pragma multi_compile __ UNITY_FFX_TEXTURE2D_X_ARRAY
#include "ffx_fsr_unity_common.cginc"
#include "ffx_unity_common.cginc"
#include "shaders/ffx_fsr3upscaler_prepare_inputs_pass.hlsl"

4
Shaders/ffx_fsr3upscaler_prepare_reactivity_pass.compute

@ -22,8 +22,8 @@
#pragma multi_compile_local __ FFX_HALF
#pragma multi_compile __ UNITY_FSR_TEXTURE2D_X_ARRAY
#pragma multi_compile __ UNITY_FFX_TEXTURE2D_X_ARRAY
#include "ffx_fsr_unity_common.cginc"
#include "ffx_unity_common.cginc"
#include "shaders/ffx_fsr3upscaler_prepare_reactivity_pass.hlsl"

4
Shaders/ffx_fsr3upscaler_rcas_pass.compute

@ -20,8 +20,8 @@
#pragma kernel CS
#pragma multi_compile __ UNITY_FSR_TEXTURE2D_X_ARRAY
#pragma multi_compile __ UNITY_FFX_TEXTURE2D_X_ARRAY
#include "ffx_fsr_unity_common.cginc"
#include "ffx_unity_common.cginc"
#include "shaders/ffx_fsr3upscaler_rcas_pass.hlsl"

4
Shaders/ffx_fsr3upscaler_shading_change_pass.compute

@ -22,8 +22,8 @@
#pragma multi_compile_local __ FFX_HALF
#pragma multi_compile __ UNITY_FSR_TEXTURE2D_X_ARRAY
#pragma multi_compile __ UNITY_FFX_TEXTURE2D_X_ARRAY
#include "ffx_fsr_unity_common.cginc"
#include "ffx_unity_common.cginc"
#include "shaders/ffx_fsr3upscaler_shading_change_pass.hlsl"

4
Shaders/ffx_fsr3upscaler_shading_change_pyramid_pass.compute

@ -22,9 +22,9 @@
#pragma multi_compile_local __ FFX_HALF
#pragma multi_compile __ UNITY_FSR_TEXTURE2D_X_ARRAY
#pragma multi_compile __ UNITY_FFX_TEXTURE2D_X_ARRAY
#include "ffx_fsr_unity_common.cginc"
#include "ffx_unity_common.cginc"
// Wave operations require shader model 6.0; this can only be enabled when using DXC on D3D12
#define FFX_SPD_NO_WAVE_OPERATIONS

4
Shaders/ffx_fsr3upscaler_tcr_autogen_pass.compute

@ -23,8 +23,8 @@
#pragma multi_compile_local __ FFX_HALF
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_JITTERED_MOTION_VECTORS
#pragma multi_compile __ UNITY_FSR_TEXTURE2D_X_ARRAY
#pragma multi_compile __ UNITY_FFX_TEXTURE2D_X_ARRAY
#include "ffx_fsr_unity_common.cginc"
#include "ffx_unity_common.cginc"
#include "shaders/ffx_fsr3upscaler_tcr_autogen_pass.hlsl"

12
Shaders/ffx_fsr_unity_common.cginc → Shaders/ffx_unity_common.cginc

@ -52,7 +52,7 @@
#endif
// Control if TEXTURE2D_X macros will expand to texture arrays
#if defined(UNITY_TEXTURE2D_X_ARRAY_SUPPORTED) && defined(UNITY_FSR_TEXTURE2D_X_ARRAY)
#if defined(UNITY_TEXTURE2D_X_ARRAY_SUPPORTED) && defined(UNITY_FFX_TEXTURE2D_X_ARRAY)
#define USE_TEXTURE2D_X_AS_ARRAY
#endif
@ -73,10 +73,10 @@
#endif
// Declare and sample camera buffers as texture arrays
#define UNITY_FSR_TEX2D(type) Texture2DArray<type>
#define UNITY_FSR_RWTEX2D(type) RWTexture2DArray<type>
#define UNITY_FSR_POS(pxPos) FfxUInt32x3(pxPos, SLICE_ARRAY_INDEX)
#define UNITY_FSR_UV(uv) FfxFloat32x3(uv, SLICE_ARRAY_INDEX)
#define UNITY_FSR_GETDIMS(tex, w, h) { FfxUInt32 uElements; (tex).GetDimensions((w), (h), uElements); }
#define UNITY_FFX_TEX2D(type) Texture2DArray<type>
#define UNITY_FFX_RWTEX2D(type) RWTexture2DArray<type>
#define UNITY_FFX_POS(pxPos) FfxUInt32x3(pxPos, SLICE_ARRAY_INDEX)
#define UNITY_FFX_UV(uv) FfxFloat32x3(uv, SLICE_ARRAY_INDEX)
#define UNITY_FFX_GETDIMS(tex, w, h) { FfxUInt32 uElements; (tex).GetDimensions((w), (h), uElements); }
#endif

0
Shaders/ffx_fsr_unity_common.cginc.meta → Shaders/ffx_unity_common.cginc.meta

48
Shaders/shaders/fsr2/ffx_fsr2_callbacks_hlsl.h

@ -340,17 +340,17 @@ FfxUInt32x2 SPD_RenderSize()
#endif // #if defined(FSR2_BIND_CB_SPD)
// Declare and sample camera buffers as regular textures, unless overridden
#if !defined(UNITY_FSR_TEX2D)
#define UNITY_FSR_TEX2D(type) Texture2D<type>
#if !defined(UNITY_FFX_TEX2D)
#define UNITY_FFX_TEX2D(type) Texture2D<type>
#endif
#if !defined(UNITY_FSR_RWTEX2D)
#define UNITY_FSR_RWTEX2D(type) RWTexture2D<type>
#if !defined(UNITY_FFX_RWTEX2D)
#define UNITY_FFX_RWTEX2D(type) RWTexture2D<type>
#endif
#if !defined(UNITY_FSR_POS)
#define UNITY_FSR_POS(pxPos) (pxPos)
#if !defined(UNITY_FFX_POS)
#define UNITY_FFX_POS(pxPos) (pxPos)
#endif
#if !defined(UNITY_FSR_UV)
#define UNITY_FSR_UV(uv) (uv)
#if !defined(UNITY_FFX_UV)
#define UNITY_FFX_UV(uv) (uv)
#endif
SamplerState s_PointClamp : register(s0);
@ -358,16 +358,16 @@ SamplerState s_LinearClamp : register(s1);
// SRVs
#if defined FSR2_BIND_SRV_INPUT_COLOR
UNITY_FSR_TEX2D(FfxFloat32x4) r_input_color_jittered : FFX_FSR2_DECLARE_SRV(FSR2_BIND_SRV_INPUT_COLOR);
UNITY_FFX_TEX2D(FfxFloat32x4) r_input_color_jittered : FFX_FSR2_DECLARE_SRV(FSR2_BIND_SRV_INPUT_COLOR);
#endif
#if defined FSR2_BIND_SRV_INPUT_OPAQUE_ONLY
UNITY_FSR_TEX2D(FfxFloat32x4) r_input_opaque_only : FFX_FSR2_DECLARE_SRV(FSR2_BIND_SRV_INPUT_OPAQUE_ONLY);
UNITY_FFX_TEX2D(FfxFloat32x4) r_input_opaque_only : FFX_FSR2_DECLARE_SRV(FSR2_BIND_SRV_INPUT_OPAQUE_ONLY);
#endif
#if defined FSR2_BIND_SRV_INPUT_MOTION_VECTORS
UNITY_FSR_TEX2D(FfxFloat32x4) r_input_motion_vectors : FFX_FSR2_DECLARE_SRV(FSR2_BIND_SRV_INPUT_MOTION_VECTORS);
UNITY_FFX_TEX2D(FfxFloat32x4) r_input_motion_vectors : FFX_FSR2_DECLARE_SRV(FSR2_BIND_SRV_INPUT_MOTION_VECTORS);
#endif
#if defined FSR2_BIND_SRV_INPUT_DEPTH
UNITY_FSR_TEX2D(FfxFloat32) r_input_depth : FFX_FSR2_DECLARE_SRV(FSR2_BIND_SRV_INPUT_DEPTH);
UNITY_FFX_TEX2D(FfxFloat32) r_input_depth : FFX_FSR2_DECLARE_SRV(FSR2_BIND_SRV_INPUT_DEPTH);
#endif
#if defined FSR2_BIND_SRV_INPUT_EXPOSURE
Texture2D<FfxFloat32x2> r_input_exposure : FFX_FSR2_DECLARE_SRV(FSR2_BIND_SRV_INPUT_EXPOSURE);
@ -376,10 +376,10 @@ SamplerState s_LinearClamp : register(s1);
Texture2D<FfxFloat32x2> r_auto_exposure : FFX_FSR2_DECLARE_SRV(FSR2_BIND_SRV_AUTO_EXPOSURE);
#endif
#if defined FSR2_BIND_SRV_REACTIVE_MASK
UNITY_FSR_TEX2D(FfxFloat32) r_reactive_mask : FFX_FSR2_DECLARE_SRV(FSR2_BIND_SRV_REACTIVE_MASK);
UNITY_FFX_TEX2D(FfxFloat32) r_reactive_mask : FFX_FSR2_DECLARE_SRV(FSR2_BIND_SRV_REACTIVE_MASK);
#endif
#if defined FSR2_BIND_SRV_TRANSPARENCY_AND_COMPOSITION_MASK
UNITY_FSR_TEX2D(FfxFloat32) r_transparency_and_composition_mask : FFX_FSR2_DECLARE_SRV(FSR2_BIND_SRV_TRANSPARENCY_AND_COMPOSITION_MASK);
UNITY_FFX_TEX2D(FfxFloat32) r_transparency_and_composition_mask : FFX_FSR2_DECLARE_SRV(FSR2_BIND_SRV_TRANSPARENCY_AND_COMPOSITION_MASK);
#endif
#if defined FSR2_BIND_SRV_RECONSTRUCTED_PREV_NEAREST_DEPTH
Texture2D<FfxUInt32> r_reconstructed_previous_nearest_depth : FFX_FSR2_DECLARE_SRV(FSR2_BIND_SRV_RECONSTRUCTED_PREV_NEAREST_DEPTH);
@ -463,7 +463,7 @@ SamplerState s_LinearClamp : register(s1);
RWTexture2D<FfxFloat32x4> rw_luma_history : FFX_FSR2_DECLARE_UAV(FSR2_BIND_UAV_LUMA_HISTORY);
#endif
#if defined FSR2_BIND_UAV_UPSCALED_OUTPUT
UNITY_FSR_RWTEX2D(FfxFloat32x4) rw_upscaled_output : FFX_FSR2_DECLARE_UAV(FSR2_BIND_UAV_UPSCALED_OUTPUT);
UNITY_FFX_RWTEX2D(FfxFloat32x4) rw_upscaled_output : FFX_FSR2_DECLARE_UAV(FSR2_BIND_UAV_UPSCALED_OUTPUT);
#endif
#if defined FSR2_BIND_UAV_EXPOSURE_MIP_LUMA_CHANGE
globallycoherent RWTexture2D<FfxFloat32> rw_img_mip_shading_change : FFX_FSR2_DECLARE_UAV(FSR2_BIND_UAV_EXPOSURE_MIP_LUMA_CHANGE);
@ -514,42 +514,42 @@ FfxFloat32 SampleMipLuma(FfxFloat32x2 fUV, FfxUInt32 mipLevel)
#if defined(FSR2_BIND_SRV_INPUT_DEPTH)
FfxFloat32 LoadInputDepth(FfxUInt32x2 iPxPos)
{
return r_input_depth[UNITY_FSR_POS(iPxPos)];
return r_input_depth[UNITY_FFX_POS(iPxPos)];
}
#endif
#if defined(FSR2_BIND_SRV_INPUT_DEPTH)
FfxFloat32 SampleInputDepth(FfxFloat32x2 fUV)
{
return r_input_depth.SampleLevel(s_LinearClamp, UNITY_FSR_UV(fUV), 0).x;
return r_input_depth.SampleLevel(s_LinearClamp, UNITY_FFX_UV(fUV), 0).x;
}
#endif
#if defined(FSR2_BIND_SRV_REACTIVE_MASK)
FfxFloat32 LoadReactiveMask(FfxUInt32x2 iPxPos)
{
return r_reactive_mask[UNITY_FSR_POS(iPxPos)];
return r_reactive_mask[UNITY_FFX_POS(iPxPos)];
}
#endif
#if defined(FSR2_BIND_SRV_TRANSPARENCY_AND_COMPOSITION_MASK)
FfxFloat32 LoadTransparencyAndCompositionMask(FfxUInt32x2 iPxPos)
{
return r_transparency_and_composition_mask[UNITY_FSR_POS(iPxPos)];
return r_transparency_and_composition_mask[UNITY_FFX_POS(iPxPos)];
}
#endif
#if defined(FSR2_BIND_SRV_INPUT_COLOR)
FfxFloat32x3 LoadInputColor(FfxUInt32x2 iPxPos)
{
return r_input_color_jittered[UNITY_FSR_POS(iPxPos)].rgb;
return r_input_color_jittered[UNITY_FFX_POS(iPxPos)].rgb;
}
#endif
#if defined(FSR2_BIND_SRV_INPUT_COLOR)
FfxFloat32x3 SampleInputColor(FfxFloat32x2 fUV)
{
return r_input_color_jittered.SampleLevel(s_LinearClamp, UNITY_FSR_UV(fUV), 0).rgb;
return r_input_color_jittered.SampleLevel(s_LinearClamp, UNITY_FFX_UV(fUV), 0).rgb;
}
#endif
@ -563,7 +563,7 @@ FfxFloat32x3 LoadPreparedInputColor(FfxUInt32x2 iPxPos)
#if defined(FSR2_BIND_SRV_INPUT_MOTION_VECTORS)
FfxFloat32x2 LoadInputMotionVector(FfxUInt32x2 iPxDilatedMotionVectorPos)
{
FfxFloat32x2 fSrcMotionVector = r_input_motion_vectors[UNITY_FSR_POS(iPxDilatedMotionVectorPos)].xy;
FfxFloat32x2 fSrcMotionVector = r_input_motion_vectors[UNITY_FFX_POS(iPxDilatedMotionVectorPos)].xy;
FfxFloat32x2 fUvMotionVector = fSrcMotionVector * MotionVectorScale();
@ -622,7 +622,7 @@ void StoreInternalColorAndWeight(FfxUInt32x2 iPxPos, FfxFloat32x4 fColorAndWeigh
#if defined(FSR2_BIND_UAV_UPSCALED_OUTPUT)
void StoreUpscaledOutput(FfxUInt32x2 iPxPos, FfxFloat32x3 fColor)
{
rw_upscaled_output[UNITY_FSR_POS(iPxPos)] = FfxFloat32x4(fColor, 1.f);
rw_upscaled_output[UNITY_FFX_POS(iPxPos)] = FfxFloat32x4(fColor, 1.f);
}
#endif
@ -833,7 +833,7 @@ void StoreDilatedReactiveMasks(FFX_PARAMETER_IN FfxUInt32x2 iPxPos, FFX_PARAMETE
#if defined(FSR2_BIND_SRV_INPUT_OPAQUE_ONLY)
FfxFloat32x3 LoadOpaqueOnly(FFX_PARAMETER_IN FFX_MIN16_I2 iPxPos)
{
return r_input_opaque_only[UNITY_FSR_POS(iPxPos)].xyz;
return r_input_opaque_only[UNITY_FFX_POS(iPxPos)].xyz;
}
#endif

60
Shaders/shaders/fsr3upscaler/ffx_fsr3upscaler_callbacks_hlsl.h

@ -320,20 +320,20 @@ FfxUInt32x2 SPD_RenderSize()
#endif // #if defined(FSR3UPSCALER_BIND_CB_SPD)
// Declare and sample camera buffers as regular textures, unless overridden
#if !defined(UNITY_FSR_TEX2D)
#define UNITY_FSR_TEX2D(type) Texture2D<type>
#if !defined(UNITY_FFX_TEX2D)
#define UNITY_FFX_TEX2D(type) Texture2D<type>
#endif
#if !defined(UNITY_FSR_RWTEX2D)
#define UNITY_FSR_RWTEX2D(type) RWTexture2D<type>
#if !defined(UNITY_FFX_RWTEX2D)
#define UNITY_FFX_RWTEX2D(type) RWTexture2D<type>
#endif
#if !defined(UNITY_FSR_POS)
#define UNITY_FSR_POS(pxPos) (pxPos)
#if !defined(UNITY_FFX_POS)
#define UNITY_FFX_POS(pxPos) (pxPos)
#endif
#if !defined(UNITY_FSR_UV)
#define UNITY_FSR_UV(uv) (uv)
#if !defined(UNITY_FFX_UV)
#define UNITY_FFX_UV(uv) (uv)
#endif
#if !defined(UNITY_FSR_GETDIMS)
#define UNITY_FSR_GETDIMS(tex, w, h) (tex).GetDimensions((w), (h))
#if !defined(UNITY_FFX_GETDIMS)
#define UNITY_FFX_GETDIMS(tex, w, h) (tex).GetDimensions((w), (h))
#endif
SamplerState s_PointClamp : register(s0);
@ -359,85 +359,85 @@ FfxFloat32x2 SampleSPDMipLevel(FfxFloat32x2 fUV, FfxUInt32 mipLevel)
#endif
#if defined(FSR3UPSCALER_BIND_SRV_INPUT_DEPTH)
UNITY_FSR_TEX2D(FfxFloat32) r_input_depth : FFX_FSR3UPSCALER_DECLARE_SRV(FSR3UPSCALER_BIND_SRV_INPUT_DEPTH);
UNITY_FFX_TEX2D(FfxFloat32) r_input_depth : FFX_FSR3UPSCALER_DECLARE_SRV(FSR3UPSCALER_BIND_SRV_INPUT_DEPTH);
FfxFloat32 LoadInputDepth(FfxUInt32x2 iPxPos)
{
return r_input_depth[UNITY_FSR_POS(iPxPos)];
return r_input_depth[UNITY_FFX_POS(iPxPos)];
}
FfxFloat32 SampleInputDepth(FfxFloat32x2 fUV)
{
return r_input_depth.SampleLevel(s_LinearClamp, UNITY_FSR_UV(fUV), 0).x;
return r_input_depth.SampleLevel(s_LinearClamp, UNITY_FFX_UV(fUV), 0).x;
}
#endif
#if defined(FSR3UPSCALER_BIND_SRV_REACTIVE_MASK)
UNITY_FSR_TEX2D(FfxFloat32) r_reactive_mask : FFX_FSR3UPSCALER_DECLARE_SRV(FSR3UPSCALER_BIND_SRV_REACTIVE_MASK);
UNITY_FFX_TEX2D(FfxFloat32) r_reactive_mask : FFX_FSR3UPSCALER_DECLARE_SRV(FSR3UPSCALER_BIND_SRV_REACTIVE_MASK);
FfxFloat32 LoadReactiveMask(FfxUInt32x2 iPxPos)
{
return r_reactive_mask[UNITY_FSR_POS(iPxPos)];
return r_reactive_mask[UNITY_FFX_POS(iPxPos)];
}
FfxInt32x2 GetReactiveMaskResourceDimensions()
{
FfxUInt32 uWidth;
FfxUInt32 uHeight;
UNITY_FSR_GETDIMS(r_reactive_mask, uWidth, uHeight);
UNITY_FFX_GETDIMS(r_reactive_mask, uWidth, uHeight);
return FfxInt32x2(uWidth, uHeight);
}
FfxFloat32 SampleReactiveMask(FfxFloat32x2 fUV)
{
return r_reactive_mask.SampleLevel(s_LinearClamp, UNITY_FSR_UV(fUV), 0).x;
return r_reactive_mask.SampleLevel(s_LinearClamp, UNITY_FFX_UV(fUV), 0).x;
}
#endif
#if defined(FSR3UPSCALER_BIND_SRV_TRANSPARENCY_AND_COMPOSITION_MASK)
UNITY_FSR_TEX2D(FfxFloat32) r_transparency_and_composition_mask : FFX_FSR3UPSCALER_DECLARE_SRV(FSR3UPSCALER_BIND_SRV_TRANSPARENCY_AND_COMPOSITION_MASK);
UNITY_FFX_TEX2D(FfxFloat32) r_transparency_and_composition_mask : FFX_FSR3UPSCALER_DECLARE_SRV(FSR3UPSCALER_BIND_SRV_TRANSPARENCY_AND_COMPOSITION_MASK);
FfxFloat32 LoadTransparencyAndCompositionMask(FfxUInt32x2 iPxPos)
{
return r_transparency_and_composition_mask[UNITY_FSR_POS(iPxPos)];
return r_transparency_and_composition_mask[UNITY_FFX_POS(iPxPos)];
}
FfxInt32x2 GetTransparencyAndCompositionMaskResourceDimensions()
{
FfxUInt32 uWidth;
FfxUInt32 uHeight;
UNITY_FSR_GETDIMS(r_transparency_and_composition_mask, uWidth, uHeight);
UNITY_FFX_GETDIMS(r_transparency_and_composition_mask, uWidth, uHeight);
return FfxInt32x2(uWidth, uHeight);
}
FfxFloat32 SampleTransparencyAndCompositionMask(FfxFloat32x2 fUV)
{
return r_transparency_and_composition_mask.SampleLevel(s_LinearClamp, UNITY_FSR_UV(fUV), 0).x;
return r_transparency_and_composition_mask.SampleLevel(s_LinearClamp, UNITY_FFX_UV(fUV), 0).x;
}
#endif
#if defined(FSR3UPSCALER_BIND_SRV_INPUT_COLOR)
UNITY_FSR_TEX2D(FfxFloat32x4) r_input_color_jittered : FFX_FSR3UPSCALER_DECLARE_SRV(FSR3UPSCALER_BIND_SRV_INPUT_COLOR);
UNITY_FFX_TEX2D(FfxFloat32x4) r_input_color_jittered : FFX_FSR3UPSCALER_DECLARE_SRV(FSR3UPSCALER_BIND_SRV_INPUT_COLOR);
FfxFloat32x3 LoadInputColor(FfxUInt32x2 iPxPos)
{
return r_input_color_jittered[UNITY_FSR_POS(iPxPos)].rgb;
return r_input_color_jittered[UNITY_FFX_POS(iPxPos)].rgb;
}
FfxFloat32x3 SampleInputColor(FfxFloat32x2 fUV)
{
return r_input_color_jittered.SampleLevel(s_LinearClamp, UNITY_FSR_UV(fUV), 0).rgb;
return r_input_color_jittered.SampleLevel(s_LinearClamp, UNITY_FFX_UV(fUV), 0).rgb;
}
#endif
#if defined(FSR3UPSCALER_BIND_SRV_INPUT_MOTION_VECTORS)
UNITY_FSR_TEX2D(FfxFloat32x4) r_input_motion_vectors : FFX_FSR3UPSCALER_DECLARE_SRV(FSR3UPSCALER_BIND_SRV_INPUT_MOTION_VECTORS);
UNITY_FFX_TEX2D(FfxFloat32x4) r_input_motion_vectors : FFX_FSR3UPSCALER_DECLARE_SRV(FSR3UPSCALER_BIND_SRV_INPUT_MOTION_VECTORS);
FfxFloat32x2 LoadInputMotionVector(FfxUInt32x2 iPxDilatedMotionVectorPos)
{
FfxFloat32x2 fSrcMotionVector = r_input_motion_vectors[UNITY_FSR_POS(iPxDilatedMotionVectorPos)].xy;
FfxFloat32x2 fSrcMotionVector = r_input_motion_vectors[UNITY_FFX_POS(iPxDilatedMotionVectorPos)].xy;
FfxFloat32x2 fUvMotionVector = fSrcMotionVector * MotionVectorScale();
@ -515,11 +515,11 @@ void StoreInternalColorAndWeight(FfxUInt32x2 iPxPos, FfxFloat32x4 fColorAndWeigh
#endif
#if defined(FSR3UPSCALER_BIND_UAV_UPSCALED_OUTPUT)
UNITY_FSR_RWTEX2D(FfxFloat32x4) rw_upscaled_output : FFX_FSR3UPSCALER_DECLARE_UAV(FSR3UPSCALER_BIND_UAV_UPSCALED_OUTPUT);
UNITY_FFX_RWTEX2D(FfxFloat32x4) rw_upscaled_output : FFX_FSR3UPSCALER_DECLARE_UAV(FSR3UPSCALER_BIND_UAV_UPSCALED_OUTPUT);
void StoreUpscaledOutput(FfxUInt32x2 iPxPos, FfxFloat32x3 fColor)
{
rw_upscaled_output[UNITY_FSR_POS(iPxPos)] = FfxFloat32x4(fColor, 1.f);
rw_upscaled_output[UNITY_FFX_POS(iPxPos)] = FfxFloat32x4(fColor, 1.f);
}
#endif
@ -830,11 +830,11 @@ void StoreDilatedReactiveMasks(FFX_PARAMETER_IN FfxUInt32x2 iPxPos, FFX_PARAMETE
#endif
#if defined(FSR3UPSCALER_BIND_SRV_INPUT_OPAQUE_ONLY)
UNITY_FSR_TEX2D(FfxFloat32x4) r_input_opaque_only : FFX_FSR3UPSCALER_DECLARE_SRV(FSR3UPSCALER_BIND_SRV_INPUT_OPAQUE_ONLY);
UNITY_FFX_TEX2D(FfxFloat32x4) r_input_opaque_only : FFX_FSR3UPSCALER_DECLARE_SRV(FSR3UPSCALER_BIND_SRV_INPUT_OPAQUE_ONLY);
FfxFloat32x3 LoadOpaqueOnly(FFX_PARAMETER_IN FFX_MIN16_I2 iPxPos)
{
return r_input_opaque_only[UNITY_FSR_POS(iPxPos)].xyz;
return r_input_opaque_only[UNITY_FFX_POS(iPxPos)].xyz;
}
#endif

Loading…
Cancel
Save