Browse Source

First import of combined FSR2/3 core assets package

master
Nico de Poel 2 years ago
commit
f2cb2c5116
  1. 49
      .gitignore
  2. 8
      Runtime.meta
  3. 8
      Runtime/Common.meta
  4. 55
      Runtime/Common/ResourceView.cs
  5. 11
      Runtime/Common/ResourceView.cs.meta
  6. 14
      Runtime/Common/fidelityfx.fsr.common.asmdef
  7. 7
      Runtime/Common/fidelityfx.fsr.common.asmdef.meta
  8. 8
      Runtime/FSR2.meta
  9. 301
      Runtime/FSR2/Fsr2.cs
  10. 3
      Runtime/FSR2/Fsr2.cs.meta
  11. 152
      Runtime/FSR2/Fsr2Assets.cs
  12. 11
      Runtime/FSR2/Fsr2Assets.cs.meta
  13. 81
      Runtime/FSR2/Fsr2Callbacks.cs
  14. 11
      Runtime/FSR2/Fsr2Callbacks.cs.meta
  15. 613
      Runtime/FSR2/Fsr2Context.cs
  16. 3
      Runtime/FSR2/Fsr2Context.cs.meta
  17. 387
      Runtime/FSR2/Fsr2Pass.cs
  18. 3
      Runtime/FSR2/Fsr2Pass.cs.meta
  19. 258
      Runtime/FSR2/Fsr2Resources.cs
  20. 3
      Runtime/FSR2/Fsr2Resources.cs.meta
  21. 80
      Runtime/FSR2/Fsr2ShaderIDs.cs
  22. 3
      Runtime/FSR2/Fsr2ShaderIDs.cs.meta
  23. 16
      Runtime/FSR2/fidelityfx.fsr.fsr2.asmdef
  24. 7
      Runtime/FSR2/fidelityfx.fsr.fsr2.asmdef.meta
  25. 8
      Runtime/FSR3.meta
  26. 90
      Runtime/FSR3/Fsr3ShaderIDs.cs
  27. 3
      Runtime/FSR3/Fsr3ShaderIDs.cs.meta
  28. 312
      Runtime/FSR3/Fsr3Upscaler.cs
  29. 3
      Runtime/FSR3/Fsr3Upscaler.cs.meta
  30. 177
      Runtime/FSR3/Fsr3UpscalerAssets.cs
  31. 11
      Runtime/FSR3/Fsr3UpscalerAssets.cs.meta
  32. 81
      Runtime/FSR3/Fsr3UpscalerCallbacks.cs
  33. 11
      Runtime/FSR3/Fsr3UpscalerCallbacks.cs.meta
  34. 652
      Runtime/FSR3/Fsr3UpscalerContext.cs
  35. 3
      Runtime/FSR3/Fsr3UpscalerContext.cs.meta
  36. 478
      Runtime/FSR3/Fsr3UpscalerPass.cs
  37. 3
      Runtime/FSR3/Fsr3UpscalerPass.cs.meta
  38. 248
      Runtime/FSR3/Fsr3UpscalerResources.cs
  39. 3
      Runtime/FSR3/Fsr3UpscalerResources.cs.meta
  40. 16
      Runtime/FSR3/fidelityfx.fsr.fsr3upscaler.asmdef
  41. 7
      Runtime/FSR3/fidelityfx.fsr.fsr3upscaler.asmdef.meta
  42. 8
      Shaders.meta
  43. 41
      Shaders/ffx_fsr2_accumulate_pass.compute
  44. 8
      Shaders/ffx_fsr2_accumulate_pass.compute.meta
  45. 32
      Shaders/ffx_fsr2_autogen_reactive_pass.compute
  46. 8
      Shaders/ffx_fsr2_autogen_reactive_pass.compute.meta
  47. 42
      Shaders/ffx_fsr2_compute_luminance_pyramid_pass.compute
  48. 8
      Shaders/ffx_fsr2_compute_luminance_pyramid_pass.compute.meta
  49. 32
      Shaders/ffx_fsr2_depth_clip_pass.compute
  50. 8
      Shaders/ffx_fsr2_depth_clip_pass.compute.meta
  51. 30
      Shaders/ffx_fsr2_lock_pass.compute
  52. 8
      Shaders/ffx_fsr2_lock_pass.compute.meta
  53. 31
      Shaders/ffx_fsr2_rcas_pass.compute
  54. 8
      Shaders/ffx_fsr2_rcas_pass.compute.meta
  55. 33
      Shaders/ffx_fsr2_reconstruct_previous_depth_pass.compute
  56. 8
      Shaders/ffx_fsr2_reconstruct_previous_depth_pass.compute.meta
  57. 32
      Shaders/ffx_fsr2_tcr_autogen_pass.compute
  58. 8
      Shaders/ffx_fsr2_tcr_autogen_pass.compute.meta
  59. 41
      Shaders/ffx_fsr3upscaler_accumulate_pass.compute
  60. 8
      Shaders/ffx_fsr3upscaler_accumulate_pass.compute.meta
  61. 32
      Shaders/ffx_fsr3upscaler_autogen_reactive_pass.compute
  62. 8
      Shaders/ffx_fsr3upscaler_autogen_reactive_pass.compute.meta
  63. 35
      Shaders/ffx_fsr3upscaler_debug_view_pass.compute
  64. 8
      Shaders/ffx_fsr3upscaler_debug_view_pass.compute.meta
  65. 35
      Shaders/ffx_fsr3upscaler_luma_instability_pass.compute
  66. 8
      Shaders/ffx_fsr3upscaler_luma_instability_pass.compute.meta
  67. 45
      Shaders/ffx_fsr3upscaler_luma_pyramid_pass.compute
  68. 8
      Shaders/ffx_fsr3upscaler_luma_pyramid_pass.compute.meta
  69. 36
      Shaders/ffx_fsr3upscaler_prepare_inputs_pass.compute
  70. 8
      Shaders/ffx_fsr3upscaler_prepare_inputs_pass.compute.meta
  71. 35
      Shaders/ffx_fsr3upscaler_prepare_reactivity_pass.compute
  72. 8
      Shaders/ffx_fsr3upscaler_prepare_reactivity_pass.compute.meta
  73. 31
      Shaders/ffx_fsr3upscaler_rcas_pass.compute
  74. 8
      Shaders/ffx_fsr3upscaler_rcas_pass.compute.meta
  75. 35
      Shaders/ffx_fsr3upscaler_shading_change_pass.compute
  76. 8
      Shaders/ffx_fsr3upscaler_shading_change_pass.compute.meta
  77. 38
      Shaders/ffx_fsr3upscaler_shading_change_pyramid_pass.compute
  78. 8
      Shaders/ffx_fsr3upscaler_shading_change_pyramid_pass.compute.meta
  79. 32
      Shaders/ffx_fsr3upscaler_tcr_autogen_pass.compute
  80. 8
      Shaders/ffx_fsr3upscaler_tcr_autogen_pass.compute.meta
  81. 85
      Shaders/ffx_fsr_unity_common.cginc
  82. 7
      Shaders/ffx_fsr_unity_common.cginc.meta
  83. 8
      Shaders/shaders.meta
  84. 654
      Shaders/shaders/ffx_common_types.h
  85. 60
      Shaders/shaders/ffx_common_types.h.meta
  86. 80
      Shaders/shaders/ffx_core.h
  87. 60
      Shaders/shaders/ffx_core.h.meta
  88. 2736
      Shaders/shaders/ffx_core_gpu_common.h
  89. 60
      Shaders/shaders/ffx_core_gpu_common.h.meta
  90. 2981
      Shaders/shaders/ffx_core_gpu_common_half.h
  91. 60
      Shaders/shaders/ffx_core_gpu_common_half.h.meta
  92. 1898
      Shaders/shaders/ffx_core_hlsl.h
  93. 60
      Shaders/shaders/ffx_core_hlsl.h.meta
  94. 46
      Shaders/shaders/ffx_core_portability.h
  95. 60
      Shaders/shaders/ffx_core_portability.h.meta
  96. 79
      Shaders/shaders/ffx_fsr2_accumulate_pass.hlsl
  97. 7
      Shaders/shaders/ffx_fsr2_accumulate_pass.hlsl.meta
  98. 78
      Shaders/shaders/ffx_fsr2_autogen_reactive_pass.hlsl
  99. 7
      Shaders/shaders/ffx_fsr2_autogen_reactive_pass.hlsl.meta
  100. 56
      Shaders/shaders/ffx_fsr2_compute_luminance_pyramid_pass.hlsl

49
.gitignore

@ -0,0 +1,49 @@
[Ll]ibrary/
[Tt]emp/
[Oo]bj/
[Bb]uild/
[Bb]uilds/
Assets/AssetStoreTools*
# Visual Studio cache directory
.vs/
# Autogenerated VS/MD/Consulo solution and project files
ExportedObj/
.consulo/
*.csproj
*.unityproj
*.sln
*.suo
*.tmp
*.user
*.userprefs
*.pidb
*.booproj
*.svd
*.pdb
*.opendb
# Unity3D generated meta files
*.pidb.meta
*.pdb.meta
# Unity3D Generated File On Crash Reports
sysinfo.txt
# Builds
*.apk
*.unitypackage
*.DS_Store
Logs
UserSettings
.vscode
.multitool
.vsconfig
Assets/ActualImages/
*ActualImages.meta
*InitTestScene*.unity*
Assets/GITT/
Assets/GITT.meta
Recordings

8
Runtime.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b64c5aa2a705139438e2bcc551a02b97
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Runtime/Common.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e87a0efd0d1d4644abdef16b5a28bd0f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

55
Runtime/Common/ResourceView.cs

@ -0,0 +1,55 @@
// Copyright (c) 2024 Nico de Poel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using UnityEngine.Rendering;
namespace FidelityFX
{
/// <summary>
/// An immutable structure wrapping all of the necessary information to bind a specific buffer or attachment of a render target to a compute shader.
/// </summary>
public readonly struct ResourceView
{
/// <summary>
/// This value is the equivalent of not setting any value at all; all struct fields will have their default values.
/// It does not refer to a valid texture, therefore any variable set to this value should be checked for IsValid and reassigned before being bound to a shader.
/// </summary>
public static readonly ResourceView Unassigned = new ResourceView(default);
/// <summary>
/// This value contains a valid texture reference that can be bound to a shader, however it is just an empty placeholder texture.
/// Binding this to a shader can be seen as setting the texture variable inside the shader to null.
/// </summary>
public static readonly ResourceView None = new ResourceView(BuiltinRenderTextureType.None);
public ResourceView(in RenderTargetIdentifier renderTarget, RenderTextureSubElement subElement = RenderTextureSubElement.Default, int mipLevel = 0)
{
RenderTarget = renderTarget;
SubElement = subElement;
MipLevel = mipLevel;
}
public bool IsValid => !RenderTarget.Equals(default);
public readonly RenderTargetIdentifier RenderTarget;
public readonly RenderTextureSubElement SubElement;
public readonly int MipLevel;
}
}

11
Runtime/Common/ResourceView.cs.meta

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

14
Runtime/Common/fidelityfx.fsr.common.asmdef

@ -0,0 +1,14 @@
{
"name": "fidelityfx.fsr.common",
"rootNamespace": "FidelityFX",
"references": [],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

7
Runtime/Common/fidelityfx.fsr.common.asmdef.meta

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: f355c2e9d97d4d8438e24fa268b0f6a5
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Runtime/FSR2.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: cce3e495c6ece2145b041d0a6e43bb26
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

301
Runtime/FSR2/Fsr2.cs

@ -0,0 +1,301 @@
// Copyright (c) 2024 Nico de Poel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.Rendering;
namespace FidelityFX
{
/// <summary>
/// A collection of helper functions and data structures required by the FSR2 process.
/// </summary>
public static class Fsr2
{
/// <summary>
/// Creates a new FSR2 context with standard parameters that are appropriate for the current platform.
/// </summary>
public static Fsr2Context CreateContext(Vector2Int displaySize, Vector2Int maxRenderSize, Fsr2Shaders shaders, InitializationFlags flags = 0)
{
if (SystemInfo.usesReversedZBuffer)
flags |= InitializationFlags.EnableDepthInverted;
else
flags &= ~InitializationFlags.EnableDepthInverted;
#if UNITY_EDITOR || DEVELOPMENT_BUILD
flags |= InitializationFlags.EnableDebugChecking;
#endif
Debug.Log($"Setting up FSR2 with render size: {maxRenderSize.x}x{maxRenderSize.y}, display size: {displaySize.x}x{displaySize.y}, flags: {flags}");
var contextDescription = new ContextDescription
{
Flags = flags,
DisplaySize = displaySize,
MaxRenderSize = maxRenderSize,
Shaders = shaders,
};
var context = new Fsr2Context();
context.Create(contextDescription);
return context;
}
public static float GetUpscaleRatioFromQualityMode(QualityMode qualityMode)
{
switch (qualityMode)
{
case QualityMode.NativeAA:
return 1.0f;
case QualityMode.UltraQuality:
return 1.2f;
case QualityMode.Quality:
return 1.5f;
case QualityMode.Balanced:
return 1.7f;
case QualityMode.Performance:
return 2.0f;
case QualityMode.UltraPerformance:
return 3.0f;
default:
return 1.0f;
}
}
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,
UltraQuality = 1,
Quality = 2,
Balanced = 3,
Performance = 4,
UltraPerformance = 5,
}
[Flags]
public enum InitializationFlags
{
EnableHighDynamicRange = 1 << 0,
EnableDisplayResolutionMotionVectors = 1 << 1,
EnableMotionVectorsJitterCancellation = 1 << 2,
EnableDepthInverted = 1 << 3,
EnableDepthInfinite = 1 << 4,
EnableAutoExposure = 1 << 5,
EnableDynamicResolution = 1 << 6,
EnableFP16Usage = 1 << 7,
EnableDebugChecking = 1 << 8,
}
/// <summary>
/// A structure encapsulating the parameters required to initialize FidelityFX Super Resolution 2 upscaling.
/// </summary>
public struct ContextDescription
{
public InitializationFlags Flags;
public Vector2Int MaxRenderSize;
public Vector2Int DisplaySize;
public Fsr2Shaders Shaders;
}
/// <summary>
/// A structure encapsulating the parameters for dispatching the various passes of FidelityFX Super Resolution 2.
/// </summary>
public class DispatchDescription
{
public ResourceView Color;
public ResourceView Depth;
public ResourceView MotionVectors;
public ResourceView Exposure; // optional
public ResourceView Reactive; // optional
public ResourceView TransparencyAndComposition; // optional
public ResourceView Output;
public Vector2 JitterOffset;
public Vector2 MotionVectorScale;
public Vector2Int RenderSize;
public Vector2Int InputResourceSize;
public bool EnableSharpening;
public float Sharpness;
public float FrameTimeDelta; // in seconds
public float PreExposure;
public bool Reset;
public float CameraNear;
public float CameraFar;
public float CameraFovAngleVertical;
public float ViewSpaceToMetersFactor;
// 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;
}
/// <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 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;
}
[Flags]
public enum GenerateReactiveFlags
{
ApplyTonemap = 1 << 0,
ApplyInverseTonemap = 1 << 1,
ApplyThreshold = 1 << 2,
UseComponentsMax = 1 << 3,
}
[Serializable, StructLayout(LayoutKind.Sequential)]
internal struct UpscalerConstants
{
public Vector2Int renderSize;
public Vector2Int maxRenderSize;
public Vector2Int displaySize;
public Vector2Int inputColorResourceDimensions;
public Vector2Int lumaMipDimensions;
public int lumaMipLevelToUse;
public int frameIndex;
public Vector4 deviceToViewDepth;
public Vector2 jitterOffset;
public Vector2 motionVectorScale;
public Vector2 downscaleFactor;
public Vector2 motionVectorJitterCancellation;
public float preExposure;
public float previousFramePreExposure;
public float tanHalfFOV;
public float jitterPhaseCount;
public float deltaTime;
public float dynamicResChangeFactor;
public float viewSpaceToMetersFactor;
public float padding;
}
[Serializable, StructLayout(LayoutKind.Sequential)]
internal struct SpdConstants
{
public uint mips;
public uint numWorkGroups;
public uint workGroupOffsetX, workGroupOffsetY;
public uint renderSizeX, renderSizeY;
}
[Serializable, StructLayout(LayoutKind.Sequential)]
internal struct GenerateReactiveConstants
{
public float scale;
public float threshold;
public float binaryValue;
public uint flags;
}
[Serializable, StructLayout(LayoutKind.Sequential)]
internal struct GenerateReactiveConstants2
{
public float autoTcThreshold;
public float autoTcScale;
public float autoReactiveScale;
public float autoReactiveMax;
}
[Serializable, StructLayout(LayoutKind.Sequential)]
internal struct RcasConstants
{
public RcasConstants(uint sharpness, uint halfSharp)
{
this.sharpness = sharpness;
this.halfSharp = halfSharp;
dummy0 = dummy1 = 0;
}
public readonly uint sharpness;
public readonly uint halfSharp;
public readonly uint dummy0;
public readonly uint dummy1;
}
}
}

3
Runtime/FSR2/Fsr2.cs.meta

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 742d52dc87714f0d93f3b59719859dff
timeCreated: 1673441954

152
Runtime/FSR2/Fsr2Assets.cs

@ -0,0 +1,152 @@
// Copyright (c) 2024 Nico de Poel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using UnityEngine;
namespace FidelityFX
{
/// <summary>
/// Scriptable object containing all shader resources required by FidelityFX Super Resolution 2 (FSR2).
/// These can be stored in an asset file and referenced from a scene or prefab, avoiding the need to load the shaders from a Resources folder.
/// </summary>
[CreateAssetMenu(fileName = "FSR2 Assets", menuName = "FidelityFX/FSR2 Assets", order = 1102)]
public class Fsr2Assets : ScriptableObject
{
public Fsr2Shaders shaders;
#if UNITY_EDITOR
private void Reset()
{
shaders = new Fsr2Shaders
{
computeLuminancePyramidPass = FindComputeShader("ffx_fsr2_compute_luminance_pyramid_pass"),
reconstructPreviousDepthPass = FindComputeShader("ffx_fsr2_reconstruct_previous_depth_pass"),
depthClipPass = FindComputeShader("ffx_fsr2_depth_clip_pass"),
lockPass = FindComputeShader("ffx_fsr2_lock_pass"),
accumulatePass = FindComputeShader("ffx_fsr2_accumulate_pass"),
sharpenPass = FindComputeShader("ffx_fsr2_rcas_pass"),
autoGenReactivePass = FindComputeShader("ffx_fsr2_autogen_reactive_pass"),
tcrAutoGenPass = FindComputeShader("ffx_fsr2_tcr_autogen_pass"),
};
}
private static ComputeShader FindComputeShader(string name)
{
string[] assetGuids = UnityEditor.AssetDatabase.FindAssets($"t:ComputeShader {name}");
if (assetGuids == null || assetGuids.Length == 0)
return null;
string assetPath = UnityEditor.AssetDatabase.GUIDToAssetPath(assetGuids[0]);
return UnityEditor.AssetDatabase.LoadAssetAtPath<ComputeShader>(assetPath);
}
#endif
}
/// <summary>
/// All the compute shaders used by FSR2.
/// </summary>
[System.Serializable]
public class Fsr2Shaders
{
/// <summary>
/// The compute shader used by the luminance pyramid computation pass.
/// </summary>
public ComputeShader computeLuminancePyramidPass;
/// <summary>
/// The compute shader used by the previous depth reconstruction pass.
/// </summary>
public ComputeShader reconstructPreviousDepthPass;
/// <summary>
/// The compute shader used by the depth clip pass.
/// </summary>
public ComputeShader depthClipPass;
/// <summary>
/// The compute shader used by the lock pass.
/// </summary>
public ComputeShader lockPass;
/// <summary>
/// The compute shader used by the accumulation pass.
/// </summary>
public ComputeShader accumulatePass;
/// <summary>
/// The compute shader used by the RCAS sharpening pass.
/// </summary>
public ComputeShader sharpenPass;
/// <summary>
/// The compute shader used to auto-generate a reactive mask.
/// </summary>
public ComputeShader autoGenReactivePass;
/// <summary>
/// The compute shader used to auto-generate a transparency & composition mask.
/// </summary>
public ComputeShader tcrAutoGenPass;
/// <summary>
/// Returns a copy of this class and its contents.
/// </summary>
public Fsr2Shaders Clone()
{
return (Fsr2Shaders)MemberwiseClone();
}
/// <summary>
/// Returns a copy of this class with clones of all its shaders.
/// This can be useful if you're running multiple FSR2 instances with different shader configurations.
/// Be sure to clean up these clones through Dispose once you're done with them.
/// </summary>
public Fsr2Shaders DeepCopy()
{
return new Fsr2Shaders
{
computeLuminancePyramidPass = Object.Instantiate(computeLuminancePyramidPass),
reconstructPreviousDepthPass = Object.Instantiate(reconstructPreviousDepthPass),
depthClipPass = Object.Instantiate(depthClipPass),
lockPass = Object.Instantiate(lockPass),
accumulatePass = Object.Instantiate(accumulatePass),
sharpenPass = Object.Instantiate(sharpenPass),
autoGenReactivePass = Object.Instantiate(autoGenReactivePass),
tcrAutoGenPass = Object.Instantiate(tcrAutoGenPass),
};
}
/// <summary>
/// Destroy all the shaders within this instance.
/// Use this only on clones created through DeepCopy.
/// </summary>
public void Dispose()
{
Object.Destroy(computeLuminancePyramidPass);
Object.Destroy(reconstructPreviousDepthPass);
Object.Destroy(depthClipPass);
Object.Destroy(lockPass);
Object.Destroy(accumulatePass);
Object.Destroy(sharpenPass);
Object.Destroy(autoGenReactivePass);
Object.Destroy(tcrAutoGenPass);
}
}
}

11
Runtime/FSR2/Fsr2Assets.cs.meta

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

81
Runtime/FSR2/Fsr2Callbacks.cs

@ -0,0 +1,81 @@
// Copyright (c) 2024 Nico de Poel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using UnityEngine;
namespace FidelityFX
{
/// <summary>
/// A collection of callbacks required by the FSR2 process.
/// This allows some customization by the game dev on how to integrate FSR2 upscaling into their own game setup.
/// </summary>
public interface IFsr2Callbacks
{
/// <summary>
/// Apply a mipmap bias to in-game textures to prevent them from becoming blurry as the internal rendering resolution lowers.
/// This will need to be customized on a per-game basis, as there is no clear universal way to determine what are "in-game" textures.
/// The default implementation will simply apply a mipmap bias to all 2D textures, which will include things like UI textures and which might miss things like terrain texture arrays.
///
/// Depending on how your game organizes its assets, you will want to create a filter that more specifically selects the textures that need to have this mipmap bias applied.
/// You may also want to store the bias offset value and apply it to any assets that are loaded in on demand.
/// </summary>
void ApplyMipmapBias(float biasOffset);
void UndoMipmapBias();
}
/// <summary>
/// Default implementation of IFsr2Callbacks.
/// These are fine for testing but a proper game will want to extend and override these methods.
/// </summary>
public class Fsr2CallbacksBase: IFsr2Callbacks
{
protected float CurrentBiasOffset = 0;
public virtual void ApplyMipmapBias(float biasOffset)
{
if (float.IsNaN(biasOffset) || float.IsInfinity(biasOffset))
return;
CurrentBiasOffset += biasOffset;
if (Mathf.Approximately(CurrentBiasOffset, 0f))
{
CurrentBiasOffset = 0f;
}
foreach (var texture in Resources.FindObjectsOfTypeAll<Texture2D>())
{
if (texture.mipmapCount <= 1)
continue;
texture.mipMapBias += biasOffset;
}
}
public virtual void UndoMipmapBias()
{
if (CurrentBiasOffset == 0f)
return;
ApplyMipmapBias(-CurrentBiasOffset);
}
}
}

11
Runtime/FSR2/Fsr2Callbacks.cs.meta

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

613
Runtime/FSR2/Fsr2Context.cs

@ -0,0 +1,613 @@
// Copyright (c) 2024 Nico de Poel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.Rendering;
namespace FidelityFX
{
/// <summary>
/// This class loosely matches the FfxFsr2Context struct from the original FSR2 codebase.
/// It manages the various resources and compute passes required by the FSR2 process.
/// 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
{
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 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 bool _firstExecution;
private Vector2 _previousJitterOffset;
private int _resourceFrameIndex;
public void Create(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>();
// Set defaults
_firstExecution = true;
_resourceFrameIndex = 0;
UpscalerConsts.displaySize = _contextDescription.DisplaySize;
_resources.Create(_contextDescription);
CreatePasses();
}
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);
}
public void Destroy()
{
DestroyPass(ref _tcrAutogeneratePass);
DestroyPass(ref _generateReactivePass);
DestroyPass(ref _sharpenPass);
DestroyPass(ref _accumulatePass);
DestroyPass(ref _lockPass);
DestroyPass(ref _depthClipPass);
DestroyPass(ref _reconstructPreviousDepthPass);
DestroyPass(ref _computeLuminancePyramidPass);
_resources.Destroy();
DestroyConstantBuffer(ref _tcrAutogenerateConstantsBuffer);
DestroyConstantBuffer(ref _generateReactiveConstantsBuffer);
DestroyConstantBuffer(ref _rcasConstantsBuffer);
DestroyConstantBuffer(ref _spdConstantsBuffer);
DestroyConstantBuffer(ref _upscalerConstantsBuffer);
if (_commandBuffer != null)
{
_commandBuffer.Dispose();
_commandBuffer = null;
}
}
public void Dispatch(Fsr2.DispatchDescription dispatchParams)
{
_commandBuffer.Clear();
Dispatch(dispatchParams, _commandBuffer);
Graphics.ExecuteCommandBuffer(_commandBuffer);
}
public void Dispatch(Fsr2.DispatchDescription dispatchParams, CommandBuffer commandBuffer)
{
if ((_contextDescription.Flags & Fsr2.InitializationFlags.EnableDebugChecking) != 0)
{
DebugCheckDispatch(dispatchParams);
}
if (_firstExecution)
{
commandBuffer.SetRenderTarget(_resources.LockStatus[0]);
commandBuffer.ClearRenderTarget(false, true, Color.clear);
commandBuffer.SetRenderTarget(_resources.LockStatus[1]);
commandBuffer.ClearRenderTarget(false, true, Color.clear);
}
int frameIndex = _resourceFrameIndex % 2;
bool resetAccumulation = dispatchParams.Reset || _firstExecution;
_firstExecution = false;
// If auto exposure is enabled use the auto exposure SRV, otherwise what the app sends
if ((_contextDescription.Flags & Fsr2.InitializationFlags.EnableAutoExposure) != 0)
dispatchParams.Exposure = new ResourceView(_resources.AutoExposure);
else if (!dispatchParams.Exposure.IsValid)
dispatchParams.Exposure = new ResourceView(_resources.DefaultExposure);
if (dispatchParams.EnableAutoReactive)
{
// Create the auto-TCR resources only when we need them
if (_resources.AutoReactive == null)
_resources.CreateTcrAutogenResources(_contextDescription);
if (resetAccumulation)
{
RenderTargetIdentifier opaqueOnly = dispatchParams.ColorOpaqueOnly.IsValid ? dispatchParams.ColorOpaqueOnly.RenderTarget : Fsr2ShaderIDs.SrvOpaqueOnly;
commandBuffer.Blit(_resources.PrevPreAlpha[frameIndex ^ 1], opaqueOnly);
}
}
else if (_resources.AutoReactive != null)
{
// Destroy the auto-TCR resources if we don't use the feature
_resources.DestroyTcrAutogenResources();
}
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);
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 = (_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.ClearRenderTarget(false, true, Color.clear);
commandBuffer.SetRenderTarget(_resources.InternalUpscaled[frameIndex ^ 1]);
commandBuffer.ClearRenderTarget(false, true, Color.clear);
commandBuffer.SetRenderTarget(_resources.SceneLuminance);
commandBuffer.ClearRenderTarget(false, true, Color.clear);
// Auto exposure always used to track luma changes in locking logic
commandBuffer.SetRenderTarget(_resources.AutoExposure);
commandBuffer.ClearRenderTarget(false, true, new Color(0f, 1e8f, 0f, 0f));
// Reset atomic counter to 0
commandBuffer.SetRenderTarget(_resources.SpdAtomicCounter);
commandBuffer.ClearRenderTarget(false, true, Color.clear);
}
// 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;
commandBuffer.SetRenderTarget(Fsr2ShaderIDs.UavReconstructedPrevNearestDepth);
commandBuffer.ClearRenderTarget(false, true, depthInverted ? Color.clear : Color.white);
// Auto exposure
SetupSpdConstants(dispatchParams, out var dispatchThreadGroupCount);
// Initialize constant buffers data
commandBuffer.SetBufferData(_upscalerConstantsBuffer, _upscalerConstantsArray);
commandBuffer.SetBufferData(_spdConstantsBuffer, _spdConstantsArray);
// Auto reactive
if (dispatchParams.EnableAutoReactive)
{
GenerateTransparencyCompositionReactive(dispatchParams, commandBuffer, frameIndex);
dispatchParams.Reactive = new ResourceView(_resources.AutoReactive);
dispatchParams.TransparencyAndComposition = new ResourceView(_resources.AutoComposition);
}
// Compute luminance pyramid
_computeLuminancePyramidPass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchThreadGroupCount.x, dispatchThreadGroupCount.y);
// Reconstruct previous depth
_reconstructPreviousDepthPass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchSrcX, dispatchSrcY);
// Depth clip
_depthClipPass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchSrcX, dispatchSrcY);
// Create locks
_lockPass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchSrcX, dispatchSrcY);
// Accumulate
_accumulatePass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchDstX, dispatchDstY);
if (dispatchParams.EnableSharpening)
{
// Compute the constants
SetupRcasConstants(dispatchParams);
commandBuffer.SetBufferData(_rcasConstantsBuffer, _rcasConstantsArray);
// 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);
}
_resourceFrameIndex = (_resourceFrameIndex + 1) % MaxQueuedFrames;
Fsr2Resources.DestroyAliasableResources(commandBuffer);
}
public void GenerateReactiveMask(Fsr2.GenerateReactiveDescription dispatchParams)
{
_commandBuffer.Clear();
GenerateReactiveMask(dispatchParams, _commandBuffer);
Graphics.ExecuteCommandBuffer(_commandBuffer);
}
public void GenerateReactiveMask(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);
((Fsr2GenerateReactivePass)_generateReactivePass).ScheduleDispatch(commandBuffer, dispatchParams, dispatchSrcX, dispatchSrcY);
}
private void GenerateTransparencyCompositionReactive(Fsr2.DispatchDescription dispatchParams, CommandBuffer commandBuffer, int frameIndex)
{
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);
_tcrAutogeneratePass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchSrcX, dispatchSrcY);
}
private void SetupConstants(Fsr2.DispatchDescription dispatchParams, bool resetAccumulation)
{
ref Fsr2.UpscalerConstants constants = ref UpscalerConsts;
constants.jitterOffset = dispatchParams.JitterOffset;
constants.renderSize = dispatchParams.RenderSize;
constants.maxRenderSize = _contextDescription.MaxRenderSize;
constants.inputColorResourceDimensions = dispatchParams.InputResourceSize;
// Compute the horizontal FOV for the shader from the vertical one
float aspectRatio = (float)dispatchParams.RenderSize.x / dispatchParams.RenderSize.y;
float cameraAngleHorizontal = Mathf.Atan(Mathf.Tan(dispatchParams.CameraFovAngleVertical / 2.0f) * aspectRatio) * 2.0f;
constants.tanHalfFOV = Mathf.Tan(cameraAngleHorizontal * 0.5f);
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);
// 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);
constants.previousFramePreExposure = constants.preExposure;
constants.preExposure = (dispatchParams.PreExposure != 0) ? dispatchParams.PreExposure : 1.0f;
// Motion vector data
Vector2Int motionVectorsTargetSize = (_contextDescription.Flags & Fsr2.InitializationFlags.EnableDisplayResolutionMotionVectors) != 0 ? constants.displaySize : constants.renderSize;
constants.motionVectorScale = dispatchParams.MotionVectorScale / motionVectorsTargetSize;
// Compute jitter cancellation
if ((_contextDescription.Flags & Fsr2.InitializationFlags.EnableMotionVectorsJitterCancellation) != 0)
{
constants.motionVectorJitterCancellation = (_previousJitterOffset - constants.jitterOffset) / motionVectorsTargetSize;
_previousJitterOffset = constants.jitterOffset;
}
int jitterPhaseCount = Fsr2.GetJitterPhaseCount(dispatchParams.RenderSize.x, _contextDescription.DisplaySize.x);
if (resetAccumulation || constants.jitterPhaseCount == 0)
{
constants.jitterPhaseCount = jitterPhaseCount;
}
else
{
int jitterPhaseCountDelta = (int)(jitterPhaseCount - constants.jitterPhaseCount);
if (jitterPhaseCountDelta > 0)
constants.jitterPhaseCount++;
else if (jitterPhaseCountDelta < 0)
constants.jitterPhaseCount--;
}
// Convert delta time to seconds and clamp to [0, 1]
constants.deltaTime = Mathf.Clamp01(dispatchParams.FrameTimeDelta);
if (resetAccumulation)
constants.frameIndex = 0;
else
constants.frameIndex++;
// Shading change usage of the SPD mip levels
constants.lumaMipLevelToUse = Fsr2Pass.ShadingChangeMipLevel;
float mipDiv = 2 << constants.lumaMipLevelToUse;
constants.lumaMipDimensions.x = (int)(constants.maxRenderSize.x / mipDiv);
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)
{
int sharpnessIndex = Mathf.RoundToInt(Mathf.Clamp01(dispatchParams.Sharpness) * (RcasConfigs.Length - 1));
RcasConsts = RcasConfigs[sharpnessIndex];
}
private void SetupSpdConstants(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;
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)
{
if (!dispatchParams.Color.IsValid)
{
Debug.LogError("Color resource is null");
}
if (!dispatchParams.Depth.IsValid)
{
Debug.LogError("Depth resource is null");
}
if (!dispatchParams.MotionVectors.IsValid)
{
Debug.LogError("MotionVectors resource is null");
}
if (!dispatchParams.Output.IsValid)
{
Debug.LogError("Output resource is null");
}
if (dispatchParams.Exposure.IsValid && (_contextDescription.Flags & Fsr2.InitializationFlags.EnableAutoExposure) != 0)
{
Debug.LogWarning("Exposure resource provided, however auto exposure flag is present");
}
if (Mathf.Abs(dispatchParams.JitterOffset.x) > 1.0f || Mathf.Abs(dispatchParams.JitterOffset.y) > 1.0f)
{
Debug.LogWarning("JitterOffset contains value outside of expected range [-1.0, 1.0]");
}
if (dispatchParams.MotionVectorScale.x > _contextDescription.MaxRenderSize.x || dispatchParams.MotionVectorScale.y > _contextDescription.MaxRenderSize.y)
{
Debug.LogWarning("MotionVectorScale contains scale value greater than MaxRenderSize");
}
if (dispatchParams.MotionVectorScale.x == 0.0f || dispatchParams.MotionVectorScale.y == 0.0f)
{
Debug.LogWarning("MotionVectorScale contains zero scale value");
}
if (dispatchParams.RenderSize.x > _contextDescription.MaxRenderSize.x || dispatchParams.RenderSize.y > _contextDescription.MaxRenderSize.y)
{
Debug.LogWarning("RenderSize is greater than context MaxRenderSize");
}
if (dispatchParams.RenderSize.x == 0 || dispatchParams.RenderSize.y == 0)
{
Debug.LogWarning("RenderSize contains zero dimension");
}
if (dispatchParams.FrameTimeDelta > 1.0f)
{
Debug.LogWarning("FrameTimeDelta is greater than 1.0f - this value should be seconds (~0.0166 for 60fps)");
}
if (dispatchParams.PreExposure == 0.0f)
{
Debug.LogError("PreExposure provided as 0.0f which is invalid");
}
bool infiniteDepth = (_contextDescription.Flags & Fsr2.InitializationFlags.EnableDepthInfinite) != 0;
bool inverseDepth = (_contextDescription.Flags & Fsr2.InitializationFlags.EnableDepthInverted) != 0;
if (inverseDepth)
{
if (dispatchParams.CameraNear < dispatchParams.CameraFar)
{
Debug.LogWarning("EnableDepthInverted flag is present yet CameraNear is less than CameraFar");
}
if (infiniteDepth)
{
if (dispatchParams.CameraNear < float.MaxValue)
{
Debug.LogWarning("EnableDepthInfinite and EnableDepthInverted present, yet CameraNear != float.MaxValue");
}
}
if (dispatchParams.CameraFar < 0.075f)
{
Debug.LogWarning("EnableDepthInverted present, CameraFar value is very low which may result in depth separation artefacting");
}
}
else
{
if (dispatchParams.CameraNear > dispatchParams.CameraFar)
{
Debug.LogWarning("CameraNear is greater than CameraFar in non-inverted-depth context");
}
if (infiniteDepth)
{
if (dispatchParams.CameraFar < float.MaxValue)
{
Debug.LogWarning("EnableDepthInfinite present, yet CameraFar != float.MaxValue");
}
}
if (dispatchParams.CameraNear < 0.075f)
{
Debug.LogWarning("CameraNear value is very low which may result in depth separation artefacting");
}
}
if (dispatchParams.CameraFovAngleVertical <= 0.0f)
{
Debug.LogError("CameraFovAngleVertical is 0.0f - this value should be > 0.0f");
}
if (dispatchParams.CameraFovAngleVertical > Mathf.PI)
{
Debug.LogError("CameraFovAngleVertical is greater than 180 degrees/PI");
}
}
/// <summary>
/// The FSR2 C++ codebase uses floats bitwise converted to ints to pass sharpness parameters to the RCAS shader.
/// This is not possible in C# without enabling unsafe code compilation, so to avoid that we instead use a table of precomputed values.
/// </summary>
private static readonly Fsr2.RcasConstants[] RcasConfigs = new []
{
new Fsr2.RcasConstants(1048576000u, 872428544u),
new Fsr2.RcasConstants(1049178080u, 877212745u),
new Fsr2.RcasConstants(1049823372u, 882390168u),
new Fsr2.RcasConstants(1050514979u, 887895276u),
new Fsr2.RcasConstants(1051256227u, 893859143u),
new Fsr2.RcasConstants(1052050675u, 900216232u),
new Fsr2.RcasConstants(1052902144u, 907032080u),
new Fsr2.RcasConstants(1053814727u, 914306687u),
new Fsr2.RcasConstants(1054792807u, 922105590u),
new Fsr2.RcasConstants(1055841087u, 930494326u),
new Fsr2.RcasConstants(1056964608u, 939538432u),
new Fsr2.RcasConstants(1057566688u, 944322633u),
new Fsr2.RcasConstants(1058211980u, 949500056u),
new Fsr2.RcasConstants(1058903587u, 955005164u),
new Fsr2.RcasConstants(1059644835u, 960969031u),
new Fsr2.RcasConstants(1060439283u, 967326120u),
new Fsr2.RcasConstants(1061290752u, 974141968u),
new Fsr2.RcasConstants(1062203335u, 981416575u),
new Fsr2.RcasConstants(1063181415u, 989215478u),
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;
}
}
}

3
Runtime/FSR2/Fsr2Context.cs.meta

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2f00ea267c3443d88bbd0e9dd7c08b4a
timeCreated: 1673442225

387
Runtime/FSR2/Fsr2Pass.cs

@ -0,0 +1,387 @@
// Copyright (c) 2024 Nico de Poel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.Profiling;
using UnityEngine.Rendering;
namespace FidelityFX
{
/// <summary>
/// Base class for all of the compute passes that make up the FSR2 process.
/// 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 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)
{
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)
{
if (shader == null)
{
throw new MissingReferenceException($"Shader for FSR2 pass '{passName}' could not be loaded! Please ensure it is included in the project correctly.");
}
ComputeShader = shader;
KernelIndex = ComputeShader.FindKernel("CS");
Sampler = CustomSampler.Create(passName);
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)
{
useLut = true;
}
#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 (useLut) ComputeShader.EnableKeyword("FFX_FSR2_OPTION_REPROJECT_USE_LANCZOS_TYPE");
if ((flags & Fsr2.InitializationFlags.EnableFP16Usage) != 0) ComputeShader.EnableKeyword("FFX_HALF");
// Inform the shader which render pipeline we're currently using
var pipeline = GraphicsSettings.currentRenderPipeline;
if (pipeline != null && pipeline.GetType().Name.Contains("HDRenderPipeline"))
{
ComputeShader.EnableKeyword("UNITY_FSR_HDRP");
}
}
}
internal class Fsr2ComputeLuminancePyramidPass : Fsr2Pass
{
private readonly ComputeBuffer _spdConstants;
public Fsr2ComputeLuminancePyramidPass(Fsr2.ContextDescription contextDescription, Fsr2Resources resources, ComputeBuffer constants, ComputeBuffer spdConstants)
: base(contextDescription, resources, constants)
{
_spdConstants = spdConstants;
InitComputeShader("Compute Luminance Pyramid", contextDescription.Shaders.computeLuminancePyramidPass);
}
protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr2.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY)
{
ref var color = ref dispatchParams.Color;
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputColor, color.RenderTarget, color.MipLevel, color.SubElement);
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.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.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
}
}
internal class Fsr2ReconstructPreviousDepthPass : Fsr2Pass
{
public Fsr2ReconstructPreviousDepthPass(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)
{
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.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavDilatedMotionVectors, Resources.DilatedMotionVectors[frameIndex]);
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbFsr2, Constants, 0, Marshal.SizeOf<Fsr2.UpscalerConstants>());
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
}
}
internal class Fsr2DepthClipPass : Fsr2Pass
{
public Fsr2DepthClipPass(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)
{
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.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvReconstructedPrevNearestDepth, Fsr2ShaderIDs.UavReconstructedPrevNearestDepth);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvDilatedMotionVectors, Resources.DilatedMotionVectors[frameIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvDilatedDepth, Fsr2ShaderIDs.UavDilatedDepth);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvPrevDilatedMotionVectors, Resources.DilatedMotionVectors[frameIndex ^ 1]);
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbFsr2, Constants, 0, Marshal.SizeOf<Fsr2.UpscalerConstants>());
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
}
}
internal class Fsr2LockPass : Fsr2Pass
{
public Fsr2LockPass(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)
{
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvLockInputLuma, Fsr2ShaderIDs.UavLockInputLuma);
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbFsr2, Constants, 0, Marshal.SizeOf<Fsr2.UpscalerConstants>());
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
}
}
internal class Fsr2AccumulatePass : Fsr2Pass
{
private const string SharpeningKeyword = "FFX_FSR2_OPTION_APPLY_SHARPENING";
#if UNITY_2021_2_OR_NEWER
private readonly LocalKeyword _sharpeningKeyword;
#endif
public Fsr2AccumulatePass(Fsr2.ContextDescription contextDescription, Fsr2Resources resources, ComputeBuffer constants)
: base(contextDescription, resources, constants)
{
InitComputeShader("Reproject & Accumulate", contextDescription.Shaders.accumulatePass);
#if UNITY_2021_2_OR_NEWER
_sharpeningKeyword = new LocalKeyword(ComputeShader, SharpeningKeyword);
#endif
}
protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr2.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY)
{
#if UNITY_2021_2_OR_NEWER
if (dispatchParams.EnableSharpening)
commandBuffer.EnableKeyword(ComputeShader, _sharpeningKeyword);
else
commandBuffer.DisableKeyword(ComputeShader, _sharpeningKeyword);
#else
if (dispatchParams.EnableSharpening)
commandBuffer.EnableShaderKeyword(SharpeningKeyword);
else
commandBuffer.DisableShaderKeyword(SharpeningKeyword);
#endif
if ((ContextDescription.Flags & Fsr2.InitializationFlags.EnableDisplayResolutionMotionVectors) == 0)
{
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvDilatedMotionVectors, Resources.DilatedMotionVectors[frameIndex]);
}
else
{
ref var motionVectors = ref dispatchParams.MotionVectors;
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputMotionVectors, motionVectors.RenderTarget, motionVectors.MipLevel, motionVectors.SubElement);
}
ref var exposure = ref dispatchParams.Exposure;
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputExposure, exposure.RenderTarget, exposure.MipLevel, exposure.SubElement);
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.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.UavInternalUpscaled, Resources.InternalUpscaled[frameIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavLockStatus, Resources.LockStatus[frameIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavLumaHistory, Resources.LumaHistory[frameIndex]);
ref var output = ref dispatchParams.Output;
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavUpscaledOutput, output.RenderTarget, output.MipLevel, output.SubElement);
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbFsr2, Constants, 0, Marshal.SizeOf<Fsr2.UpscalerConstants>());
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
}
}
internal class Fsr2SharpenPass : Fsr2Pass
{
private readonly ComputeBuffer _rcasConstants;
public Fsr2SharpenPass(Fsr2.ContextDescription contextDescription, Fsr2Resources resources, ComputeBuffer constants, ComputeBuffer rcasConstants)
: base(contextDescription, resources, constants)
{
_rcasConstants = rcasConstants;
InitComputeShader("RCAS Sharpening", contextDescription.Shaders.sharpenPass);
}
protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr2.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY)
{
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]);
ref var output = ref dispatchParams.Output;
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavUpscaledOutput, output.RenderTarget, output.MipLevel, output.SubElement);
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbFsr2, Constants, 0, Marshal.SizeOf<Fsr2.UpscalerConstants>());
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbRcas, _rcasConstants, 0, Marshal.SizeOf<Fsr2.RcasConstants>());
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
}
}
internal class Fsr2GenerateReactivePass : Fsr2Pass
{
private readonly ComputeBuffer _generateReactiveConstants;
public Fsr2GenerateReactivePass(Fsr2.ContextDescription contextDescription, Fsr2Resources resources, ComputeBuffer generateReactiveConstants)
: base(contextDescription, resources, null)
{
_generateReactiveConstants = generateReactiveConstants;
InitComputeShader("Auto-Generate Reactive Mask", contextDescription.Shaders.autoGenReactivePass);
}
protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr2.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY)
{
}
public void ScheduleDispatch(CommandBuffer commandBuffer, 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>());
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
commandBuffer.EndSample(Sampler);
}
}
internal class Fsr2TcrAutogeneratePass : Fsr2Pass
{
private readonly ComputeBuffer _tcrAutogenerateConstants;
public Fsr2TcrAutogeneratePass(Fsr2.ContextDescription contextDescription, Fsr2Resources resources, ComputeBuffer constants, ComputeBuffer tcrAutogenerateConstants)
: base(contextDescription, resources, constants)
{
_tcrAutogenerateConstants = tcrAutogenerateConstants;
InitComputeShader("Auto-Generate Transparency & Composition Mask", contextDescription.Shaders.tcrAutoGenPass);
}
protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr2.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY)
{
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.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.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbFsr2, Constants, 0, Marshal.SizeOf<Fsr2.UpscalerConstants>());
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbGenReactive, _tcrAutogenerateConstants, 0, Marshal.SizeOf<Fsr2.GenerateReactiveConstants2>());
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
}
}
}

3
Runtime/FSR2/Fsr2Pass.cs.meta

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 14234aed75ce454183019d2e20a44d24
timeCreated: 1676885169

258
Runtime/FSR2/Fsr2Resources.cs

@ -0,0 +1,258 @@
// Copyright (c) 2024 Nico de Poel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering;
namespace FidelityFX
{
/// <summary>
/// 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
{
public Texture2D DefaultExposure;
public Texture2D DefaultReactive;
public Texture2D LanczosLut;
public Texture2D MaximumBiasLut;
public RenderTexture SpdAtomicCounter;
public RenderTexture AutoExposure;
public RenderTexture SceneLuminance;
public RenderTexture AutoReactive;
public RenderTexture AutoComposition;
public readonly RenderTexture[] DilatedMotionVectors = new RenderTexture[2];
public readonly RenderTexture[] LockStatus = new RenderTexture[2];
public readonly RenderTexture[] InternalUpscaled = new RenderTexture[2];
public readonly RenderTexture[] LumaHistory = new RenderTexture[2];
public readonly RenderTexture[] PrevPreAlpha = new RenderTexture[2];
public readonly RenderTexture[] PrevPostAlpha = new RenderTexture[2];
public void Create(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[] maximumBias = new float[MaximumBiasTextureWidth * MaximumBiasTextureHeight];
for (int i = 0; i < maximumBias.Length; ++i)
{
maximumBias[i] = MaximumBias[i] / 2.0f;
}
// 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();
// Resource FSR3UPSCALER_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 = "FSR3UPSCALER_MaximumUpsampleBias" };
MaximumBiasLut.SetPixelData(maximumBias, 0);
MaximumBiasLut.Apply();
// 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();
// 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();
// 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();
// Resource FSR3UPSCALER_AutoExposure: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R32G32_FLOAT, FFX_RESOURCE_FLAGS_NONE
AutoExposure = new RenderTexture(1, 1, 0, GraphicsFormat.R32G32_SFloat) { name = "FSR3UPSCALER_AutoExposure", enableRandomWrite = true };
AutoExposure.Create();
// Resource FSR3UPSCALER_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 = "FSR3UPSCALER_ExposureMips", enableRandomWrite = true, useMipMap = true, autoGenerateMips = false };
SceneLuminance.Create();
// Resources FSR3UPSCALER_InternalDilatedVelocity1/2: FFX_RESOURCE_USAGE_RENDERTARGET | FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R16G16_FLOAT, FFX_RESOURCE_FLAGS_NONE
CreateDoubleBufferedResource(DilatedMotionVectors, "FSR3UPSCALER_InternalDilatedVelocity", contextDescription.MaxRenderSize, GraphicsFormat.R16G16_SFloat);
// Resources FSR3UPSCALER_LockStatus1/2: FFX_RESOURCE_USAGE_RENDERTARGET | FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R16G16_FLOAT, FFX_RESOURCE_FLAGS_NONE
CreateDoubleBufferedResource(LockStatus, "FSR3UPSCALER_LockStatus", contextDescription.DisplaySize, GraphicsFormat.R16G16_SFloat);
// Resources FSR3UPSCALER_InternalUpscaled1/2: FFX_RESOURCE_USAGE_RENDERTARGET | FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R16G16B16A16_FLOAT, FFX_RESOURCE_FLAGS_NONE
CreateDoubleBufferedResource(InternalUpscaled, "FSR3UPSCALER_InternalUpscaled", contextDescription.DisplaySize, GraphicsFormat.R16G16B16A16_SFloat);
// Resources FSR3UPSCALER_LumaHistory1/2: FFX_RESOURCE_USAGE_RENDERTARGET | FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R8G8B8A8_UNORM, FFX_RESOURCE_FLAGS_NONE
CreateDoubleBufferedResource(LumaHistory, "FSR3UPSCALER_LumaHistory", contextDescription.DisplaySize, GraphicsFormat.R8G8B8A8_UNorm);
}
public void CreateTcrAutogenResources(Fsr2.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();
// 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();
// 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);
// Resources FSR3UPSCALER_PrevPostAlpha0/1: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R11G11B10_FLOAT, FFX_RESOURCE_FLAGS_NONE
CreateDoubleBufferedResource(PrevPostAlpha, "FSR3UPSCALER_PrevPostAlpha", contextDescription.MaxRenderSize, GraphicsFormat.B10G11R11_UFloatPack32);
}
// 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)
{
Vector2Int displaySize = contextDescription.DisplaySize;
Vector2Int maxRenderSize = contextDescription.MaxRenderSize;
// FSR3UPSCALER_ReconstructedPrevNearestDepth: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R32_UINT, FFX_RESOURCE_FLAGS_ALIASABLE
commandBuffer.GetTemporaryRT(Fsr2ShaderIDs.UavReconstructedPrevNearestDepth, maxRenderSize.x, maxRenderSize.y, 0, default, GraphicsFormat.R32_UInt, 1, true);
// FSR3UPSCALER_DilatedDepth: FFX_RESOURCE_USAGE_RENDERTARGET | FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R32_FLOAT, FFX_RESOURCE_FLAGS_ALIASABLE
commandBuffer.GetTemporaryRT(Fsr2ShaderIDs.UavDilatedDepth, maxRenderSize.x, maxRenderSize.y, 0, default, GraphicsFormat.R32_SFloat, 1, true);
// FSR3UPSCALER_LockInputLuma: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R16_FLOAT, FFX_RESOURCE_FLAGS_ALIASABLE
commandBuffer.GetTemporaryRT(Fsr2ShaderIDs.UavLockInputLuma, maxRenderSize.x, maxRenderSize.y, 0, default, GraphicsFormat.R16_SFloat, 1, true);
// FSR3UPSCALER_DilatedReactiveMasks: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R8G8_UNORM, FFX_RESOURCE_FLAGS_ALIASABLE
commandBuffer.GetTemporaryRT(Fsr2ShaderIDs.UavDilatedReactiveMasks, maxRenderSize.x, maxRenderSize.y, 0, default, GraphicsFormat.R8G8_UNorm, 1, true);
// FSR3UPSCALER_PreparedInputColor: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R16G16B16A16_FLOAT, FFX_RESOURCE_FLAGS_ALIASABLE
commandBuffer.GetTemporaryRT(Fsr2ShaderIDs.UavPreparedInputColor, maxRenderSize.x, maxRenderSize.y, 0, default, GraphicsFormat.R16G16B16A16_SFloat, 1, true);
// FSR3UPSCALER_NewLocks: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R8_UNORM, FFX_RESOURCE_FLAGS_ALIASABLE
commandBuffer.GetTemporaryRT(Fsr2ShaderIDs.UavNewLocks, displaySize.x, displaySize.y, 0, default, GraphicsFormat.R8_UNorm, 1, true);
}
public static void DestroyAliasableResources(CommandBuffer commandBuffer)
{
// Release all of the aliasable resources used this frame
commandBuffer.ReleaseTemporaryRT(Fsr2ShaderIDs.UavReconstructedPrevNearestDepth);
commandBuffer.ReleaseTemporaryRT(Fsr2ShaderIDs.UavDilatedDepth);
commandBuffer.ReleaseTemporaryRT(Fsr2ShaderIDs.UavLockInputLuma);
commandBuffer.ReleaseTemporaryRT(Fsr2ShaderIDs.UavDilatedReactiveMasks);
commandBuffer.ReleaseTemporaryRT(Fsr2ShaderIDs.UavPreparedInputColor);
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();
DestroyResource(LumaHistory);
DestroyResource(InternalUpscaled);
DestroyResource(LockStatus);
DestroyResource(DilatedMotionVectors);
DestroyResource(ref SceneLuminance);
DestroyResource(ref AutoExposure);
DestroyResource(ref DefaultReactive);
DestroyResource(ref DefaultExposure);
DestroyResource(ref MaximumBiasLut);
DestroyResource(ref LanczosLut);
}
public void DestroyTcrAutogenResources()
{
DestroyResource(PrevPostAlpha);
DestroyResource(PrevPreAlpha);
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]);
}
private const int MaximumBiasTextureWidth = 16;
private const int MaximumBiasTextureHeight = 16;
private static readonly float[] MaximumBias =
{
2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 1.876f, 1.809f, 1.772f, 1.753f, 1.748f,
2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 1.869f, 1.801f, 1.764f, 1.745f, 1.739f,
2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 1.976f, 1.841f, 1.774f, 1.737f, 1.716f, 1.71f,
2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 1.914f, 1.784f, 1.716f, 1.673f, 1.649f, 1.641f,
2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 1.793f, 1.676f, 1.604f, 1.562f, 1.54f, 1.533f,
2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 1.802f, 1.619f, 1.536f, 1.492f, 1.467f, 1.454f, 1.449f,
2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 1.812f, 1.575f, 1.496f, 1.456f, 1.432f, 1.416f, 1.408f, 1.405f,
2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 1.555f, 1.479f, 1.438f, 1.413f, 1.398f, 1.387f, 1.381f, 1.379f,
2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 1.812f, 1.555f, 1.474f, 1.43f, 1.404f, 1.387f, 1.376f, 1.368f, 1.363f, 1.362f,
2.0f, 2.0f, 2.0f, 2.0f, 2.0f, 1.802f, 1.575f, 1.479f, 1.43f, 1.401f, 1.382f, 1.369f, 1.36f, 1.354f, 1.351f, 1.35f,
2.0f, 2.0f, 1.976f, 1.914f, 1.793f, 1.619f, 1.496f, 1.438f, 1.404f, 1.382f, 1.367f, 1.357f, 1.349f, 1.344f, 1.341f, 1.34f,
1.876f, 1.869f, 1.841f, 1.784f, 1.676f, 1.536f, 1.456f, 1.413f, 1.387f, 1.369f, 1.357f, 1.347f, 1.341f, 1.336f, 1.333f, 1.332f,
1.809f, 1.801f, 1.774f, 1.716f, 1.604f, 1.492f, 1.432f, 1.398f, 1.376f, 1.36f, 1.349f, 1.341f, 1.335f, 1.33f, 1.328f, 1.327f,
1.772f, 1.764f, 1.737f, 1.673f, 1.562f, 1.467f, 1.416f, 1.387f, 1.368f, 1.354f, 1.344f, 1.336f, 1.33f, 1.326f, 1.323f, 1.323f,
1.753f, 1.745f, 1.716f, 1.649f, 1.54f, 1.454f, 1.408f, 1.381f, 1.363f, 1.351f, 1.341f, 1.333f, 1.328f, 1.323f, 1.321f, 1.32f,
1.748f, 1.739f, 1.71f, 1.641f, 1.533f, 1.449f, 1.405f, 1.379f, 1.362f, 1.35f, 1.34f, 1.332f, 1.327f, 1.323f, 1.32f, 1.319f,
};
}
}

3
Runtime/FSR2/Fsr2Resources.cs.meta

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 22ad49193f244ab4a36d0a1512f3015f
timeCreated: 1677236102

80
Runtime/FSR2/Fsr2ShaderIDs.cs

@ -0,0 +1,80 @@
// Copyright (c) 2024 Nico de Poel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using UnityEngine;
namespace FidelityFX
{
public static class Fsr2ShaderIDs
{
// Shader resource views, i.e. read-only bindings
public static readonly int SrvInputColor = Shader.PropertyToID("r_input_color_jittered");
public static readonly int SrvOpaqueOnly = Shader.PropertyToID("r_input_opaque_only");
public static readonly int SrvInputMotionVectors = Shader.PropertyToID("r_input_motion_vectors");
public static readonly int SrvInputDepth = Shader.PropertyToID("r_input_depth");
public static readonly int SrvInputExposure = Shader.PropertyToID("r_input_exposure");
public static readonly int SrvAutoExposure = Shader.PropertyToID("r_auto_exposure");
public static readonly int SrvReactiveMask = Shader.PropertyToID("r_reactive_mask");
public static readonly int SrvTransparencyAndCompositionMask = Shader.PropertyToID("r_transparency_and_composition_mask");
public static readonly int SrvReconstructedPrevNearestDepth = Shader.PropertyToID("r_reconstructed_previous_nearest_depth");
public static readonly int SrvDilatedMotionVectors = Shader.PropertyToID("r_dilated_motion_vectors");
public static readonly int SrvPrevDilatedMotionVectors = Shader.PropertyToID("r_previous_dilated_motion_vectors");
public static readonly int SrvDilatedDepth = Shader.PropertyToID("r_dilatedDepth");
public static readonly int SrvInternalUpscaled = Shader.PropertyToID("r_internal_upscaled_color");
public static readonly int SrvLockStatus = Shader.PropertyToID("r_lock_status");
public static readonly int SrvLockInputLuma = Shader.PropertyToID("r_lock_input_luma");
public static readonly int SrvPreparedInputColor = Shader.PropertyToID("r_prepared_input_color");
public static readonly int SrvLumaHistory = Shader.PropertyToID("r_luma_history");
public static readonly int SrvRcasInput = Shader.PropertyToID("r_rcas_input");
public static readonly int SrvLanczosLut = Shader.PropertyToID("r_lanczos_lut");
public static readonly int SrvSceneLuminanceMips = Shader.PropertyToID("r_imgMips");
public static readonly int SrvUpscaleMaximumBiasLut = Shader.PropertyToID("r_upsample_maximum_bias_lut");
public static readonly int SrvDilatedReactiveMasks = Shader.PropertyToID("r_dilated_reactive_masks");
public static readonly int SrvPrevColorPreAlpha = Shader.PropertyToID("r_input_prev_color_pre_alpha");
public static readonly int SrvPrevColorPostAlpha = Shader.PropertyToID("r_input_prev_color_post_alpha");
// Unordered access views, i.e. random read/write bindings
public static readonly int UavReconstructedPrevNearestDepth = Shader.PropertyToID("rw_reconstructed_previous_nearest_depth");
public static readonly int UavDilatedMotionVectors = Shader.PropertyToID("rw_dilated_motion_vectors");
public static readonly int UavDilatedDepth = Shader.PropertyToID("rw_dilatedDepth");
public static readonly int UavInternalUpscaled = Shader.PropertyToID("rw_internal_upscaled_color");
public static readonly int UavLockStatus = Shader.PropertyToID("rw_lock_status");
public static readonly int UavLockInputLuma = Shader.PropertyToID("rw_lock_input_luma");
public static readonly int UavNewLocks = Shader.PropertyToID("rw_new_locks");
public static readonly int UavPreparedInputColor = Shader.PropertyToID("rw_prepared_input_color");
public static readonly int UavLumaHistory = Shader.PropertyToID("rw_luma_history");
public static readonly int UavUpscaledOutput = Shader.PropertyToID("rw_upscaled_output");
public static readonly int UavExposureMipLumaChange = Shader.PropertyToID("rw_img_mip_shading_change");
public static readonly int UavExposureMip5 = Shader.PropertyToID("rw_img_mip_5");
public static readonly int UavDilatedReactiveMasks = Shader.PropertyToID("rw_dilated_reactive_masks");
public static readonly int UavAutoExposure = Shader.PropertyToID("rw_auto_exposure");
public static readonly int UavSpdAtomicCount = Shader.PropertyToID("rw_spd_global_atomic");
public static readonly int UavAutoReactive = Shader.PropertyToID("rw_output_autoreactive");
public static readonly int UavAutoComposition = Shader.PropertyToID("rw_output_autocomposition");
public static readonly int UavPrevColorPreAlpha = Shader.PropertyToID("rw_output_prev_color_pre_alpha");
public static readonly int UavPrevColorPostAlpha = Shader.PropertyToID("rw_output_prev_color_post_alpha");
// Constant buffer bindings
public static readonly int CbFsr2 = Shader.PropertyToID("cbFSR2");
public static readonly int CbSpd = Shader.PropertyToID("cbSPD");
public static readonly int CbRcas = Shader.PropertyToID("cbRCAS");
public static readonly int CbGenReactive = Shader.PropertyToID("cbGenerateReactive");
}
}

3
Runtime/FSR2/Fsr2ShaderIDs.cs.meta

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ad1eca9398174f6c85d8bc01d10993df
timeCreated: 1679060863

16
Runtime/FSR2/fidelityfx.fsr.fsr2.asmdef

@ -0,0 +1,16 @@
{
"name": "fidelityfx.fsr.fsr2",
"rootNamespace": "FidelityFX",
"references": [
"GUID:f355c2e9d97d4d8438e24fa268b0f6a5"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

7
Runtime/FSR2/fidelityfx.fsr.fsr2.asmdef.meta

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 8d3d81074ae24444fab654e0a84c9f8d
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Runtime/FSR3.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 16d16ad51c3bc2a429d3da6788f65e07
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

90
Runtime/FSR3/Fsr3ShaderIDs.cs

@ -0,0 +1,90 @@
// Copyright (c) 2024 Nico de Poel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using UnityEngine;
namespace FidelityFX
{
public static class Fsr3ShaderIDs
{
// Shader resource views, i.e. read-only bindings
public static readonly int SrvInputColor = Shader.PropertyToID("r_input_color_jittered");
public static readonly int SrvOpaqueOnly = Shader.PropertyToID("r_input_opaque_only");
public static readonly int SrvInputMotionVectors = Shader.PropertyToID("r_input_motion_vectors");
public static readonly int SrvInputDepth = Shader.PropertyToID("r_input_depth");
public static readonly int SrvInputExposure = Shader.PropertyToID("r_input_exposure");
public static readonly int SrvFrameInfo = Shader.PropertyToID("r_frame_info");
public static readonly int SrvReactiveMask = Shader.PropertyToID("r_reactive_mask");
public static readonly int SrvTransparencyAndCompositionMask = Shader.PropertyToID("r_transparency_and_composition_mask");
public static readonly int SrvReconstructedPrevNearestDepth = Shader.PropertyToID("r_reconstructed_previous_nearest_depth");
public static readonly int SrvDilatedMotionVectors = Shader.PropertyToID("r_dilated_motion_vectors");
public static readonly int SrvDilatedDepth = Shader.PropertyToID("r_dilated_depth");
public static readonly int SrvInternalUpscaled = Shader.PropertyToID("r_internal_upscaled_color");
public static readonly int SrvAccumulation = Shader.PropertyToID("r_accumulation");
public static readonly int SrvLumaHistory = Shader.PropertyToID("r_luma_history");
public static readonly int SrvRcasInput = Shader.PropertyToID("r_rcas_input");
public static readonly int SrvLanczosLut = Shader.PropertyToID("r_lanczos_lut");
public static readonly int SrvSpdMips = Shader.PropertyToID("r_spd_mips");
public static readonly int SrvDilatedReactiveMasks = Shader.PropertyToID("r_dilated_reactive_masks");
public static readonly int SrvNewLocks = Shader.PropertyToID("r_new_locks");
public static readonly int SrvFarthestDepth = Shader.PropertyToID("r_farthest_depth");
public static readonly int SrvFarthestDepthMip1 = Shader.PropertyToID("r_farthest_depth_mip1");
public static readonly int SrvShadingChange = Shader.PropertyToID("r_shading_change");
public static readonly int SrvCurrentLuma = Shader.PropertyToID("r_current_luma");
public static readonly int SrvPreviousLuma = Shader.PropertyToID("r_previous_luma");
public static readonly int SrvLumaInstability = Shader.PropertyToID("r_luma_instability");
public static readonly int SrvPrevColorPreAlpha = Shader.PropertyToID("r_input_prev_color_pre_alpha");
public static readonly int SrvPrevColorPostAlpha = Shader.PropertyToID("r_input_prev_color_post_alpha");
// Unordered access views, i.e. random read/write bindings
public static readonly int UavReconstructedPrevNearestDepth = Shader.PropertyToID("rw_reconstructed_previous_nearest_depth");
public static readonly int UavDilatedMotionVectors = Shader.PropertyToID("rw_dilated_motion_vectors");
public static readonly int UavDilatedDepth = Shader.PropertyToID("rw_dilated_depth");
public static readonly int UavInternalUpscaled = Shader.PropertyToID("rw_internal_upscaled_color");
public static readonly int UavAccumulation = Shader.PropertyToID("rw_accumulation");
public static readonly int UavLumaHistory = Shader.PropertyToID("rw_luma_history");
public static readonly int UavUpscaledOutput = Shader.PropertyToID("rw_upscaled_output");
public static readonly int UavDilatedReactiveMasks = Shader.PropertyToID("rw_dilated_reactive_masks");
public static readonly int UavFrameInfo = Shader.PropertyToID("rw_frame_info");
public static readonly int UavSpdAtomicCount = Shader.PropertyToID("rw_spd_global_atomic");
public static readonly int UavNewLocks = Shader.PropertyToID("rw_new_locks");
public static readonly int UavAutoReactive = Shader.PropertyToID("rw_output_autoreactive");
public static readonly int UavShadingChange = Shader.PropertyToID("rw_shading_change");
public static readonly int UavFarthestDepth = Shader.PropertyToID("rw_farthest_depth");
public static readonly int UavFarthestDepthMip1 = Shader.PropertyToID("rw_farthest_depth_mip1");
public static readonly int UavCurrentLuma = Shader.PropertyToID("rw_current_luma");
public static readonly int UavLumaInstability = Shader.PropertyToID("rw_luma_instability");
public static readonly int UavSpdMip0 = Shader.PropertyToID("rw_spd_mip0");
public static readonly int UavSpdMip1 = Shader.PropertyToID("rw_spd_mip1");
public static readonly int UavSpdMip2 = Shader.PropertyToID("rw_spd_mip2");
public static readonly int UavSpdMip3 = Shader.PropertyToID("rw_spd_mip3");
public static readonly int UavSpdMip4 = Shader.PropertyToID("rw_spd_mip4");
public static readonly int UavSpdMip5 = Shader.PropertyToID("rw_spd_mip5");
public static readonly int UavAutoComposition = Shader.PropertyToID("rw_output_autocomposition");
public static readonly int UavPrevColorPreAlpha = Shader.PropertyToID("rw_output_prev_color_pre_alpha");
public static readonly int UavPrevColorPostAlpha = Shader.PropertyToID("rw_output_prev_color_post_alpha");
// Constant buffer bindings
public static readonly int CbFsr3Upscaler = Shader.PropertyToID("cbFSR3Upscaler");
public static readonly int CbSpd = Shader.PropertyToID("cbSPD");
public static readonly int CbRcas = Shader.PropertyToID("cbRCAS");
public static readonly int CbGenReactive = Shader.PropertyToID("cbGenerateReactive");
}
}

3
Runtime/FSR3/Fsr3ShaderIDs.cs.meta

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a1e3e7c189594b94897510b4a20b8a00
timeCreated: 1679060863

312
Runtime/FSR3/Fsr3Upscaler.cs

@ -0,0 +1,312 @@
// Copyright (c) 2024 Nico de Poel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.Rendering;
namespace FidelityFX
{
/// <summary>
/// A collection of helper functions and data structures required by the FSR3 Upscaler process.
/// </summary>
public static class Fsr3Upscaler
{
/// <summary>
/// Creates a new FSR3 Upscaler context with standard parameters that are appropriate for the current platform.
/// </summary>
public static Fsr3UpscalerContext CreateContext(Vector2Int displaySize, Vector2Int maxRenderSize, Fsr3UpscalerShaders shaders, InitializationFlags flags = 0)
{
if (SystemInfo.usesReversedZBuffer)
flags |= InitializationFlags.EnableDepthInverted;
else
flags &= ~InitializationFlags.EnableDepthInverted;
#if UNITY_EDITOR || DEVELOPMENT_BUILD
flags |= InitializationFlags.EnableDebugChecking;
#endif
Debug.Log($"Setting up FSR3 Upscaler with render size: {maxRenderSize.x}x{maxRenderSize.y}, display size: {displaySize.x}x{displaySize.y}, flags: {flags}");
var contextDescription = new ContextDescription
{
Flags = flags,
MaxUpscaleSize = displaySize,
MaxRenderSize = maxRenderSize,
Shaders = shaders,
};
var context = new Fsr3UpscalerContext();
context.Create(contextDescription);
return context;
}
public static float GetUpscaleRatioFromQualityMode(QualityMode qualityMode)
{
switch (qualityMode)
{
case QualityMode.NativeAA:
return 1.0f;
case QualityMode.UltraQuality:
return 1.2f;
case QualityMode.Quality:
return 1.5f;
case QualityMode.Balanced:
return 1.7f;
case QualityMode.Performance:
return 2.0f;
case QualityMode.UltraPerformance:
return 3.0f;
default:
return 1.0f;
}
}
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,
UltraQuality = 1,
Quality = 2,
Balanced = 3,
Performance = 4,
UltraPerformance = 5,
}
[Flags]
public enum InitializationFlags
{
EnableHighDynamicRange = 1 << 0,
EnableDisplayResolutionMotionVectors = 1 << 1,
EnableMotionVectorsJitterCancellation = 1 << 2,
EnableDepthInverted = 1 << 3,
EnableDepthInfinite = 1 << 4,
EnableAutoExposure = 1 << 5,
EnableDynamicResolution = 1 << 6,
EnableFP16Usage = 1 << 7,
EnableDebugChecking = 1 << 8,
}
[Flags]
public enum DispatchFlags
{
DrawDebugView = 1 << 0,
}
/// <summary>
/// A structure encapsulating the parameters required to initialize FidelityFX Super Resolution 3 upscaling.
/// </summary>
public struct ContextDescription
{
public InitializationFlags Flags;
public Vector2Int MaxRenderSize;
public Vector2Int MaxUpscaleSize;
public Fsr3UpscalerShaders Shaders;
}
/// <summary>
/// A structure encapsulating the parameters for dispatching the various passes of FidelityFX Super Resolution 3.
/// </summary>
public class DispatchDescription
{
public ResourceView Color;
public ResourceView Depth;
public ResourceView MotionVectors;
public ResourceView Exposure; // optional
public ResourceView Reactive; // optional
public ResourceView TransparencyAndComposition; // optional
public ResourceView Output;
public Vector2 JitterOffset;
public Vector2 MotionVectorScale;
public Vector2Int RenderSize;
public Vector2Int UpscaleSize;
public bool EnableSharpening;
public float Sharpness;
public float FrameTimeDelta; // in seconds
public float PreExposure;
public bool Reset;
public float CameraNear;
public float CameraFar;
public float CameraFovAngleVertical;
public float ViewSpaceToMetersFactor;
public DispatchFlags Flags;
// 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;
}
/// <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 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;
}
[Flags]
public enum GenerateReactiveFlags
{
ApplyTonemap = 1 << 0,
ApplyInverseTonemap = 1 << 1,
ApplyThreshold = 1 << 2,
UseComponentsMax = 1 << 3,
}
[Serializable, StructLayout(LayoutKind.Sequential)]
internal struct UpscalerConstants
{
public Vector2Int renderSize;
public Vector2Int previousFrameRenderSize;
public Vector2Int upscaleSize;
public Vector2Int previousFrameUpscaleSize;
public Vector2Int maxRenderSize;
public Vector2Int maxUpscaleSize;
public Vector4 deviceToViewDepth;
public Vector2 jitterOffset;
public Vector2 previousFrameJitterOffset;
public Vector2 motionVectorScale;
public Vector2 downscaleFactor;
public Vector2 motionVectorJitterCancellation;
public float tanHalfFOV;
public float jitterPhaseCount;
public float deltaTime;
public float deltaPreExposure;
public float viewSpaceToMetersFactor;
public float frameIndex;
}
[Serializable, StructLayout(LayoutKind.Sequential)]
internal struct SpdConstants
{
public uint mips;
public uint numWorkGroups;
public uint workGroupOffsetX, workGroupOffsetY;
public uint renderSizeX, renderSizeY;
}
[Serializable, StructLayout(LayoutKind.Sequential)]
internal struct GenerateReactiveConstants
{
public float scale;
public float threshold;
public float binaryValue;
public uint flags;
}
[Serializable, StructLayout(LayoutKind.Sequential)]
internal struct GenerateReactiveConstants2
{
public float autoTcThreshold;
public float autoTcScale;
public float autoReactiveScale;
public float autoReactiveMax;
}
[Serializable, StructLayout(LayoutKind.Sequential)]
internal struct RcasConstants
{
public RcasConstants(uint sharpness, uint halfSharp)
{
this.sharpness = sharpness;
this.halfSharp = halfSharp;
dummy0 = dummy1 = 0;
}
public readonly uint sharpness;
public readonly uint halfSharp;
public readonly uint dummy0;
public readonly uint dummy1;
}
}
}

3
Runtime/FSR3/Fsr3Upscaler.cs.meta

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7ee72b891c35d614eac306ca6154b66d
timeCreated: 1673441954

177
Runtime/FSR3/Fsr3UpscalerAssets.cs

@ -0,0 +1,177 @@
// Copyright (c) 2024 Nico de Poel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using UnityEngine;
using UnityEngine.Serialization;
namespace FidelityFX
{
/// <summary>
/// Scriptable object containing all shader resources required by FidelityFX Super Resolution 3 (FSR3) Upscaler.
/// These can be stored in an asset file and referenced from a scene or prefab, avoiding the need to load the shaders from a Resources folder.
/// </summary>
[CreateAssetMenu(fileName = "FSR3 Upscaler Assets", menuName = "FidelityFX/FSR3 Upscaler Assets", order = 1103)]
public class Fsr3UpscalerAssets : ScriptableObject
{
public Fsr3UpscalerShaders shaders;
#if UNITY_EDITOR
private void Reset()
{
shaders = new Fsr3UpscalerShaders
{
prepareInputsPass = FindComputeShader("ffx_fsr3upscaler_prepare_inputs_pass"),
lumaPyramidPass = FindComputeShader("ffx_fsr3upscaler_luma_pyramid_pass"),
shadingChangePyramidPass = FindComputeShader("ffx_fsr3upscaler_shading_change_pyramid_pass"),
shadingChangePass = FindComputeShader("ffx_fsr3upscaler_shading_change_pass"),
prepareReactivityPass = FindComputeShader("ffx_fsr3upscaler_prepare_reactivity_pass"),
lumaInstabilityPass = FindComputeShader("ffx_fsr3upscaler_luma_instability_pass"),
accumulatePass = FindComputeShader("ffx_fsr3upscaler_accumulate_pass"),
sharpenPass = FindComputeShader("ffx_fsr3upscaler_rcas_pass"),
autoGenReactivePass = FindComputeShader("ffx_fsr3upscaler_autogen_reactive_pass"),
tcrAutoGenPass = FindComputeShader("ffx_fsr3upscaler_tcr_autogen_pass"),
debugViewPass = FindComputeShader("ffx_fsr3upscaler_debug_view_pass"),
};
}
private static ComputeShader FindComputeShader(string name)
{
string[] assetGuids = UnityEditor.AssetDatabase.FindAssets($"t:ComputeShader {name}");
if (assetGuids == null || assetGuids.Length == 0)
return null;
string assetPath = UnityEditor.AssetDatabase.GUIDToAssetPath(assetGuids[0]);
return UnityEditor.AssetDatabase.LoadAssetAtPath<ComputeShader>(assetPath);
}
#endif
}
/// <summary>
/// All the compute shaders used by the FSR3 Upscaler.
/// </summary>
[System.Serializable]
public class Fsr3UpscalerShaders
{
/// <summary>
/// The compute shader used by the prepare inputs pass.
/// </summary>
public ComputeShader prepareInputsPass;
/// <summary>
/// The compute shader used by the luminance pyramid computation pass.
/// </summary>
public ComputeShader lumaPyramidPass;
/// <summary>
/// The compute shader used by the shading change pyramid pass.
/// </summary>
public ComputeShader shadingChangePyramidPass;
/// <summary>
/// The compute shader used by the shading change pass.
/// </summary>
public ComputeShader shadingChangePass;
/// <summary>
/// The compute shader used by the prepare reactivity pass.
/// </summary>
public ComputeShader prepareReactivityPass;
/// <summary>
/// The compute shader used by the luma instability pass.
/// </summary>
public ComputeShader lumaInstabilityPass;
/// <summary>
/// The compute shader used by the accumulation pass.
/// </summary>
public ComputeShader accumulatePass;
/// <summary>
/// The compute shader used by the RCAS sharpening pass.
/// </summary>
public ComputeShader sharpenPass;
/// <summary>
/// The compute shader used to auto-generate a reactive mask.
/// </summary>
public ComputeShader autoGenReactivePass;
/// <summary>
/// The compute shader used to auto-generate a transparency & composition mask.
/// </summary>
public ComputeShader tcrAutoGenPass;
/// <summary>
/// The compute shader used to display a debug view.
/// </summary>
public ComputeShader debugViewPass;
/// <summary>
/// Returns a copy of this class and its contents.
/// </summary>
public Fsr3UpscalerShaders Clone()
{
return (Fsr3UpscalerShaders)MemberwiseClone();
}
/// <summary>
/// Returns a copy of this class with clones of all its shaders.
/// This can be useful if you're running multiple FSR3 Upscaler instances with different shader configurations.
/// Be sure to clean up these clones through Dispose once you're done with them.
/// </summary>
public Fsr3UpscalerShaders DeepCopy()
{
return new Fsr3UpscalerShaders
{
prepareInputsPass = Object.Instantiate(prepareInputsPass),
lumaPyramidPass = Object.Instantiate(lumaPyramidPass),
shadingChangePyramidPass = Object.Instantiate(shadingChangePyramidPass),
shadingChangePass = Object.Instantiate(shadingChangePass),
prepareReactivityPass = Object.Instantiate(prepareReactivityPass),
lumaInstabilityPass = Object.Instantiate(lumaInstabilityPass),
accumulatePass = Object.Instantiate(accumulatePass),
sharpenPass = Object.Instantiate(sharpenPass),
autoGenReactivePass = Object.Instantiate(autoGenReactivePass),
tcrAutoGenPass = Object.Instantiate(tcrAutoGenPass),
debugViewPass = Object.Instantiate(debugViewPass),
};
}
/// <summary>
/// Destroy all the shaders within this instance.
/// Use this only on clones created through DeepCopy.
/// </summary>
public void Dispose()
{
Object.Destroy(prepareInputsPass);
Object.Destroy(lumaPyramidPass);
Object.Destroy(shadingChangePyramidPass);
Object.Destroy(shadingChangePass);
Object.Destroy(prepareReactivityPass);
Object.Destroy(lumaInstabilityPass);
Object.Destroy(accumulatePass);
Object.Destroy(sharpenPass);
Object.Destroy(autoGenReactivePass);
Object.Destroy(tcrAutoGenPass);
Object.Destroy(debugViewPass);
}
}
}

11
Runtime/FSR3/Fsr3UpscalerAssets.cs.meta

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

81
Runtime/FSR3/Fsr3UpscalerCallbacks.cs

@ -0,0 +1,81 @@
// Copyright (c) 2024 Nico de Poel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using UnityEngine;
namespace FidelityFX
{
/// <summary>
/// A collection of callbacks required by the FSR3 Upscaler process.
/// This allows some customization by the game dev on how to integrate FSR3 upscaling into their own game setup.
/// </summary>
public interface IFsr3UpscalerCallbacks
{
/// <summary>
/// Apply a mipmap bias to in-game textures to prevent them from becoming blurry as the internal rendering resolution lowers.
/// This will need to be customized on a per-game basis, as there is no clear universal way to determine what are "in-game" textures.
/// The default implementation will simply apply a mipmap bias to all 2D textures, which will include things like UI textures and which might miss things like terrain texture arrays.
///
/// Depending on how your game organizes its assets, you will want to create a filter that more specifically selects the textures that need to have this mipmap bias applied.
/// You may also want to store the bias offset value and apply it to any assets that are loaded in on demand.
/// </summary>
void ApplyMipmapBias(float biasOffset);
void UndoMipmapBias();
}
/// <summary>
/// Default implementation of IFsr3UpscalerCallbacks.
/// These are fine for testing but a proper game will want to extend and override these methods.
/// </summary>
public class Fsr3UpscalerCallbacksBase: IFsr3UpscalerCallbacks
{
protected float CurrentBiasOffset = 0;
public virtual void ApplyMipmapBias(float biasOffset)
{
if (float.IsNaN(biasOffset) || float.IsInfinity(biasOffset))
return;
CurrentBiasOffset += biasOffset;
if (Mathf.Approximately(CurrentBiasOffset, 0f))
{
CurrentBiasOffset = 0f;
}
foreach (var texture in Resources.FindObjectsOfTypeAll<Texture2D>())
{
if (texture.mipmapCount <= 1)
continue;
texture.mipMapBias += biasOffset;
}
}
public virtual void UndoMipmapBias()
{
if (CurrentBiasOffset == 0f)
return;
ApplyMipmapBias(-CurrentBiasOffset);
}
}
}

11
Runtime/FSR3/Fsr3UpscalerCallbacks.cs.meta

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

652
Runtime/FSR3/Fsr3UpscalerContext.cs

@ -0,0 +1,652 @@
// Copyright (c) 2024 Nico de Poel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.Rendering;
namespace FidelityFX
{
/// <summary>
/// This class loosely matches the FfxFsr3UpscalerContext struct from the original FSR3 codebase.
/// It manages the various resources and compute passes required by the FSR3 Upscaler process.
/// 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
{
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;
#if UNITY_EDITOR || DEVELOPMENT_BUILD
private Fsr3UpscalerPass _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 bool _firstExecution;
private int _resourceFrameIndex;
private Vector2 _previousJitterOffset;
private float _preExposure;
private float _previousFramePreExposure;
public void Create(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>();
// Set defaults
_firstExecution = true;
_resourceFrameIndex = 0;
UpscalerConsts.maxUpscaleSize = _contextDescription.MaxUpscaleSize;
_resources.Create(_contextDescription);
CreatePasses();
}
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);
#if UNITY_EDITOR || DEVELOPMENT_BUILD
_debugViewPass = new Fsr3UpscalerDebugViewPass(_contextDescription, _resources, _upscalerConstantsBuffer);
#endif
}
public void Destroy()
{
#if UNITY_EDITOR || DEVELOPMENT_BUILD
DestroyPass(ref _debugViewPass);
#endif
DestroyPass(ref _tcrAutogeneratePass);
DestroyPass(ref _generateReactivePass);
DestroyPass(ref _lumaPyramidPass);
DestroyPass(ref _sharpenPass);
DestroyPass(ref _accumulatePass);
DestroyPass(ref _prepareReactivityPass);
DestroyPass(ref _shadingChangePass);
DestroyPass(ref _shadingChangePyramidPass);
DestroyPass(ref _lumaInstabilityPass);
DestroyPass(ref _prepareInputsPass);
_resources.Destroy();
DestroyConstantBuffer(ref _tcrAutogenerateConstantsBuffer);
DestroyConstantBuffer(ref _generateReactiveConstantsBuffer);
DestroyConstantBuffer(ref _rcasConstantsBuffer);
DestroyConstantBuffer(ref _spdConstantsBuffer);
DestroyConstantBuffer(ref _upscalerConstantsBuffer);
if (_commandBuffer != null)
{
_commandBuffer.Dispose();
_commandBuffer = null;
}
}
public void Dispatch(Fsr3Upscaler.DispatchDescription dispatchParams)
{
_commandBuffer.Clear();
Dispatch(dispatchParams, _commandBuffer);
Graphics.ExecuteCommandBuffer(_commandBuffer);
}
public void Dispatch(Fsr3Upscaler.DispatchDescription dispatchParams, CommandBuffer commandBuffer)
{
if ((_contextDescription.Flags & Fsr3Upscaler.InitializationFlags.EnableDebugChecking) != 0)
{
DebugCheckDispatch(dispatchParams);
}
if (_firstExecution)
{
commandBuffer.SetRenderTarget(_resources.Accumulation[0]);
commandBuffer.ClearRenderTarget(false, true, Color.clear);
commandBuffer.SetRenderTarget(_resources.Accumulation[1]);
commandBuffer.ClearRenderTarget(false, true, Color.clear);
commandBuffer.SetRenderTarget(_resources.Luma[0]);
commandBuffer.ClearRenderTarget(false, true, Color.clear);
commandBuffer.SetRenderTarget(_resources.Luma[1]);
commandBuffer.ClearRenderTarget(false, true, Color.clear);
}
int frameIndex = _resourceFrameIndex % 2;
bool resetAccumulation = dispatchParams.Reset || _firstExecution;
_firstExecution = false;
// If auto exposure is enabled use the auto exposure SRV, otherwise what the app sends
if ((_contextDescription.Flags & Fsr3Upscaler.InitializationFlags.EnableAutoExposure) != 0)
dispatchParams.Exposure = new ResourceView(_resources.FrameInfo);
else if (!dispatchParams.Exposure.IsValid)
dispatchParams.Exposure = new ResourceView(_resources.DefaultExposure);
if (dispatchParams.EnableAutoReactive)
{
// Create the auto-TCR resources only when we need them
if (_resources.AutoReactive == null)
_resources.CreateTcrAutogenResources(_contextDescription);
if (resetAccumulation)
{
RenderTargetIdentifier opaqueOnly = dispatchParams.ColorOpaqueOnly.IsValid ? dispatchParams.ColorOpaqueOnly.RenderTarget : Fsr3ShaderIDs.SrvOpaqueOnly;
commandBuffer.Blit(_resources.PrevPreAlpha[frameIndex ^ 1], opaqueOnly);
}
}
else if (_resources.AutoReactive != null)
{
// Destroy the auto-TCR resources if we don't use the feature
_resources.DestroyTcrAutogenResources();
}
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);
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;
// Clear reconstructed depth for max depth store
if (resetAccumulation)
{
commandBuffer.SetRenderTarget(_resources.Accumulation[frameIndex ^ 1]);
commandBuffer.ClearRenderTarget(false, true, Color.clear);
commandBuffer.SetRenderTarget(_resources.SpdMips);
commandBuffer.ClearRenderTarget(false, true, Color.clear);
// Auto exposure always used to track luma changes in locking logic
commandBuffer.SetRenderTarget(_resources.FrameInfo);
commandBuffer.ClearRenderTarget(false, true, new Color(0f, 1e8f, 0f, 0f));
// Reset atomic counter to 0
commandBuffer.SetRenderTarget(_resources.SpdAtomicCounter);
commandBuffer.ClearRenderTarget(false, true, Color.clear);
}
// 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;
commandBuffer.SetRenderTarget(_resources.ReconstructedPrevNearestDepth);
commandBuffer.ClearRenderTarget(false, true, depthInverted ? Color.clear : Color.white);
// Auto exposure
SetupSpdConstants(dispatchParams, out var dispatchThreadGroupCount);
// Initialize constant buffers data
commandBuffer.SetBufferData(_upscalerConstantsBuffer, _upscalerConstantsArray);
commandBuffer.SetBufferData(_spdConstantsBuffer, _spdConstantsArray);
// Auto reactive
if (dispatchParams.EnableAutoReactive)
{
GenerateTransparencyCompositionReactive(dispatchParams, commandBuffer, frameIndex);
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);
_accumulatePass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchDstX, dispatchDstY);
if (dispatchParams.EnableSharpening)
{
// Compute the constants
SetupRcasConstants(dispatchParams);
commandBuffer.SetBufferData(_rcasConstantsBuffer, _rcasConstantsArray);
// 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);
}
#if UNITY_EDITOR || DEVELOPMENT_BUILD
if ((dispatchParams.Flags & Fsr3Upscaler.DispatchFlags.DrawDebugView) != 0)
{
_debugViewPass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchDstX, dispatchDstY);
}
#endif
_resourceFrameIndex = (_resourceFrameIndex + 1) % MaxQueuedFrames;
Fsr3UpscalerResources.DestroyAliasableResources(commandBuffer);
}
public void GenerateReactiveMask(Fsr3Upscaler.GenerateReactiveDescription dispatchParams)
{
_commandBuffer.Clear();
GenerateReactiveMask(dispatchParams, _commandBuffer);
Graphics.ExecuteCommandBuffer(_commandBuffer);
}
public void GenerateReactiveMask(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);
((Fsr3UpscalerGenerateReactivePass)_generateReactivePass).ScheduleDispatch(commandBuffer, dispatchParams, dispatchSrcX, dispatchSrcY);
}
private void GenerateTransparencyCompositionReactive(Fsr3Upscaler.DispatchDescription dispatchParams, CommandBuffer commandBuffer, int frameIndex)
{
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);
_tcrAutogeneratePass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchSrcX, dispatchSrcY);
}
private void SetupConstants(Fsr3Upscaler.DispatchDescription dispatchParams, bool resetAccumulation)
{
ref Fsr3Upscaler.UpscalerConstants constants = ref UpscalerConsts;
constants.previousFrameJitterOffset = constants.jitterOffset;
constants.jitterOffset = dispatchParams.JitterOffset;
constants.previousFrameRenderSize = constants.renderSize;
constants.renderSize = dispatchParams.RenderSize;
constants.maxRenderSize = _contextDescription.MaxRenderSize;
// Compute the horizontal FOV for the shader from the vertical one
float aspectRatio = (float)dispatchParams.RenderSize.x / dispatchParams.RenderSize.y;
float cameraAngleHorizontal = Mathf.Atan(Mathf.Tan(dispatchParams.CameraFovAngleVertical / 2.0f) * aspectRatio) * 2.0f;
constants.tanHalfFOV = Mathf.Tan(cameraAngleHorizontal * 0.5f);
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);
constants.previousFrameUpscaleSize = constants.upscaleSize;
if (dispatchParams.UpscaleSize.x == 0 && dispatchParams.UpscaleSize.y == 0)
{
constants.upscaleSize = _contextDescription.MaxUpscaleSize;
}
else
{
constants.upscaleSize = dispatchParams.UpscaleSize;
}
// To be updated if resource is larger than the actual image size
constants.downscaleFactor = new Vector2((float)constants.renderSize.x / constants.upscaleSize.x, (float)constants.renderSize.y / constants.upscaleSize.y);
// Calculate pre-exposure relevant factors
constants.deltaPreExposure = 1.0f;
_previousFramePreExposure = _preExposure;
_preExposure = dispatchParams.PreExposure != 0.0f ? dispatchParams.PreExposure : 1.0f;
if (_previousFramePreExposure > 0.0f)
{
constants.deltaPreExposure = _preExposure / _previousFramePreExposure;
}
// Motion vector data
Vector2Int motionVectorsTargetSize = (_contextDescription.Flags & Fsr3Upscaler.InitializationFlags.EnableDisplayResolutionMotionVectors) != 0 ? constants.upscaleSize : constants.renderSize;
constants.motionVectorScale = dispatchParams.MotionVectorScale / motionVectorsTargetSize;
// Compute jitter cancellation
if ((_contextDescription.Flags & Fsr3Upscaler.InitializationFlags.EnableMotionVectorsJitterCancellation) != 0)
{
constants.motionVectorJitterCancellation = (_previousJitterOffset - constants.jitterOffset) / motionVectorsTargetSize;
_previousJitterOffset = constants.jitterOffset;
}
int jitterPhaseCount = Fsr3Upscaler.GetJitterPhaseCount(dispatchParams.RenderSize.x, _contextDescription.MaxUpscaleSize.x);
if (resetAccumulation || constants.jitterPhaseCount == 0)
{
constants.jitterPhaseCount = jitterPhaseCount;
}
else
{
int jitterPhaseCountDelta = (int)(jitterPhaseCount - constants.jitterPhaseCount);
if (jitterPhaseCountDelta > 0)
constants.jitterPhaseCount++;
else if (jitterPhaseCountDelta < 0)
constants.jitterPhaseCount--;
}
// Convert delta time to seconds and clamp to [0, 1]
constants.deltaTime = Mathf.Clamp01(dispatchParams.FrameTimeDelta);
if (resetAccumulation)
constants.frameIndex = 0;
else
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)
{
int sharpnessIndex = Mathf.RoundToInt(Mathf.Clamp01(dispatchParams.Sharpness) * (RcasConfigs.Length - 1));
RcasConsts = RcasConfigs[sharpnessIndex];
}
private void SetupSpdConstants(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;
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)
{
if (!dispatchParams.Color.IsValid)
{
Debug.LogError("Color resource is null");
}
if (!dispatchParams.Depth.IsValid)
{
Debug.LogError("Depth resource is null");
}
if (!dispatchParams.MotionVectors.IsValid)
{
Debug.LogError("MotionVectors resource is null");
}
if (dispatchParams.Exposure.IsValid && (_contextDescription.Flags & Fsr3Upscaler.InitializationFlags.EnableAutoExposure) != 0)
{
Debug.LogWarning("Exposure resource provided, however auto exposure flag is present");
}
if (!dispatchParams.Output.IsValid)
{
Debug.LogError("Output resource is null");
}
if (Mathf.Abs(dispatchParams.JitterOffset.x) > 1.0f || Mathf.Abs(dispatchParams.JitterOffset.y) > 1.0f)
{
Debug.LogWarning("JitterOffset contains value outside of expected range [-1.0, 1.0]");
}
if (dispatchParams.MotionVectorScale.x > _contextDescription.MaxRenderSize.x || dispatchParams.MotionVectorScale.y > _contextDescription.MaxRenderSize.y)
{
Debug.LogWarning("MotionVectorScale contains scale value greater than MaxRenderSize");
}
if (dispatchParams.MotionVectorScale.x == 0.0f || dispatchParams.MotionVectorScale.y == 0.0f)
{
Debug.LogWarning("MotionVectorScale contains zero scale value");
}
if (dispatchParams.RenderSize.x > _contextDescription.MaxRenderSize.x || dispatchParams.RenderSize.y > _contextDescription.MaxRenderSize.y)
{
Debug.LogWarning("RenderSize is greater than context MaxRenderSize");
}
if (dispatchParams.RenderSize.x == 0 || dispatchParams.RenderSize.y == 0)
{
Debug.LogWarning("RenderSize contains zero dimension");
}
if (dispatchParams.Sharpness < 0.0f || dispatchParams.Sharpness > 1.0f)
{
Debug.LogWarning("Sharpness contains value outside of expected range [0.0, 1.0]");
}
if (dispatchParams.FrameTimeDelta > 1.0f)
{
Debug.LogWarning("FrameTimeDelta is greater than 1.0f - this value should be seconds (~0.0166 for 60fps)");
}
if (dispatchParams.PreExposure == 0.0f)
{
Debug.LogError("PreExposure provided as 0.0f which is invalid");
}
bool infiniteDepth = (_contextDescription.Flags & Fsr3Upscaler.InitializationFlags.EnableDepthInfinite) != 0;
bool inverseDepth = (_contextDescription.Flags & Fsr3Upscaler.InitializationFlags.EnableDepthInverted) != 0;
if (inverseDepth)
{
if (dispatchParams.CameraNear < dispatchParams.CameraFar)
{
Debug.LogWarning("EnableDepthInverted flag is present yet CameraNear is less than CameraFar");
}
if (infiniteDepth)
{
if (dispatchParams.CameraNear < float.MaxValue)
{
Debug.LogWarning("EnableDepthInfinite and EnableDepthInverted present, yet CameraNear != float.MaxValue");
}
}
if (dispatchParams.CameraFar < 0.075f)
{
Debug.LogWarning("EnableDepthInverted present, CameraFar value is very low which may result in depth separation artefacting");
}
}
else
{
if (dispatchParams.CameraNear > dispatchParams.CameraFar)
{
Debug.LogWarning("CameraNear is greater than CameraFar in non-inverted-depth context");
}
if (infiniteDepth)
{
if (dispatchParams.CameraFar < float.MaxValue)
{
Debug.LogWarning("EnableDepthInfinite present, yet CameraFar != float.MaxValue");
}
}
if (dispatchParams.CameraNear < 0.075f)
{
Debug.LogWarning("CameraNear value is very low which may result in depth separation artefacting");
}
}
if (dispatchParams.CameraFovAngleVertical <= 0.0f)
{
Debug.LogError("CameraFovAngleVertical is 0.0f - this value should be > 0.0f");
}
if (dispatchParams.CameraFovAngleVertical > Mathf.PI)
{
Debug.LogError("CameraFovAngleVertical is greater than 180 degrees/PI");
}
}
/// <summary>
/// The FSR3 C++ codebase uses floats bitwise converted to ints to pass sharpness parameters to the RCAS shader.
/// This is not possible in C# without enabling unsafe code compilation, so to avoid that we instead use a table of precomputed values.
/// </summary>
private static readonly Fsr3Upscaler.RcasConstants[] RcasConfigs = new []
{
new Fsr3Upscaler.RcasConstants(1048576000u, 872428544u),
new Fsr3Upscaler.RcasConstants(1049178080u, 877212745u),
new Fsr3Upscaler.RcasConstants(1049823372u, 882390168u),
new Fsr3Upscaler.RcasConstants(1050514979u, 887895276u),
new Fsr3Upscaler.RcasConstants(1051256227u, 893859143u),
new Fsr3Upscaler.RcasConstants(1052050675u, 900216232u),
new Fsr3Upscaler.RcasConstants(1052902144u, 907032080u),
new Fsr3Upscaler.RcasConstants(1053814727u, 914306687u),
new Fsr3Upscaler.RcasConstants(1054792807u, 922105590u),
new Fsr3Upscaler.RcasConstants(1055841087u, 930494326u),
new Fsr3Upscaler.RcasConstants(1056964608u, 939538432u),
new Fsr3Upscaler.RcasConstants(1057566688u, 944322633u),
new Fsr3Upscaler.RcasConstants(1058211980u, 949500056u),
new Fsr3Upscaler.RcasConstants(1058903587u, 955005164u),
new Fsr3Upscaler.RcasConstants(1059644835u, 960969031u),
new Fsr3Upscaler.RcasConstants(1060439283u, 967326120u),
new Fsr3Upscaler.RcasConstants(1061290752u, 974141968u),
new Fsr3Upscaler.RcasConstants(1062203335u, 981416575u),
new Fsr3Upscaler.RcasConstants(1063181415u, 989215478u),
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;
}
}
}

3
Runtime/FSR3/Fsr3UpscalerContext.cs.meta

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 742dda30b4604d5488e7eeda3cf04d56
timeCreated: 1673442225

478
Runtime/FSR3/Fsr3UpscalerPass.cs

@ -0,0 +1,478 @@
// Copyright (c) 2024 Nico de Poel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.Profiling;
using UnityEngine.Rendering;
namespace FidelityFX
{
/// <summary>
/// Base class for all of the compute passes that make up the FSR3 Upscaler process.
/// 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
{
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)
{
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)
{
if (shader == null)
{
throw new MissingReferenceException($"Shader for FSR3 Upscaler pass '{passName}' could not be loaded! Please ensure it is included in the project correctly.");
}
ComputeShader = shader;
KernelIndex = ComputeShader.FindKernel("CS");
Sampler = CustomSampler.Create(passName);
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)
{
useLut = true;
}
#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 (useLut) ComputeShader.EnableKeyword("FFX_FSR3UPSCALER_OPTION_REPROJECT_USE_LANCZOS_TYPE");
if ((flags & Fsr3Upscaler.InitializationFlags.EnableFP16Usage) != 0) ComputeShader.EnableKeyword("FFX_HALF");
// Inform the shader which render pipeline we're currently using
var pipeline = GraphicsSettings.currentRenderPipeline;
if (pipeline != null && pipeline.GetType().Name.Contains("HDRenderPipeline"))
{
ComputeShader.EnableKeyword("UNITY_FSR_HDRP");
}
}
}
internal class Fsr3UpscalerPrepareInputsPass : Fsr3UpscalerPass
{
public Fsr3UpscalerPrepareInputsPass(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)
{
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.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.UavCurrentLuma, Resources.Luma[frameIndex]);
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants, 0, Marshal.SizeOf<Fsr3Upscaler.UpscalerConstants>());
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
}
}
internal class Fsr3UpscalerLumaPyramidPass : Fsr3UpscalerPass
{
private readonly ComputeBuffer _spdConstants;
public Fsr3UpscalerLumaPyramidPass(Fsr3Upscaler.ContextDescription contextDescription, Fsr3UpscalerResources resources, ComputeBuffer constants, ComputeBuffer spdConstants)
: base(contextDescription, resources, constants)
{
_spdConstants = spdConstants;
InitComputeShader("Compute Luminance Pyramid", contextDescription.Shaders.lumaPyramidPass);
}
protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr3Upscaler.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY)
{
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvCurrentLuma, Resources.Luma[frameIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvFarthestDepth, Fsr3ShaderIDs.UavFarthestDepth);
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.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants, 0, Marshal.SizeOf<Fsr3Upscaler.UpscalerConstants>());
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbSpd, _spdConstants, 0, Marshal.SizeOf<Fsr3Upscaler.SpdConstants>());
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
}
}
internal class Fsr3UpscalerShadingChangePyramidPass : Fsr3UpscalerPass
{
private readonly ComputeBuffer _spdConstants;
public Fsr3UpscalerShadingChangePyramidPass(Fsr3Upscaler.ContextDescription contextDescription, Fsr3UpscalerResources resources, ComputeBuffer constants, ComputeBuffer spdConstants)
: base(contextDescription, resources, constants)
{
_spdConstants = spdConstants;
InitComputeShader("Compute Shading Change Pyramid", contextDescription.Shaders.shadingChangePyramidPass);
}
protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr3Upscaler.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY)
{
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.SrvDilatedMotionVectors, Resources.DilatedVelocity);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputExposure, exposure.RenderTarget, exposure.MipLevel, exposure.SubElement);
// TODO: possibly the atomic counter might have to get cleared in-between passes. Check on MacOS whether we have issues with this or not.
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.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants, 0, Marshal.SizeOf<Fsr3Upscaler.UpscalerConstants>());
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbSpd, _spdConstants, 0, Marshal.SizeOf<Fsr3Upscaler.SpdConstants>());
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
}
}
internal class Fsr3UpscalerShadingChangePass : Fsr3UpscalerPass
{
public Fsr3UpscalerShadingChangePass(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)
{
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvSpdMips, Resources.SpdMips);
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants, 0, Marshal.SizeOf<Fsr3Upscaler.UpscalerConstants>());
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
}
}
internal class Fsr3UpscalerPrepareReactivityPass : Fsr3UpscalerPass
{
public Fsr3UpscalerPrepareReactivityPass(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)
{
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.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.UavAccumulation, Resources.Accumulation[frameIndex]);
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants, 0, Marshal.SizeOf<Fsr3Upscaler.UpscalerConstants>());
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
}
}
internal class Fsr3UpscalerLumaInstabilityPass : Fsr3UpscalerPass
{
public Fsr3UpscalerLumaInstabilityPass(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)
{
ref var exposure = ref dispatchParams.Exposure;
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputExposure, exposure.RenderTarget, exposure.MipLevel, exposure.SubElement);
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.SrvFarthestDepthMip1, Fsr3ShaderIDs.UavFarthestDepthMip1);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvCurrentLuma, Resources.Luma[frameIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavLumaHistory, Resources.LumaHistory[frameIndex]);
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants, 0, Marshal.SizeOf<Fsr3Upscaler.UpscalerConstants>());
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
}
}
internal class Fsr3UpscalerAccumulatePass : Fsr3UpscalerPass
{
private const string SharpeningKeyword = "FFX_FSR3UPSCALER_OPTION_APPLY_SHARPENING";
#if UNITY_2021_2_OR_NEWER
private readonly LocalKeyword _sharpeningKeyword;
#endif
public Fsr3UpscalerAccumulatePass(Fsr3Upscaler.ContextDescription contextDescription, Fsr3UpscalerResources resources, ComputeBuffer constants)
: base(contextDescription, resources, constants)
{
InitComputeShader("Accumulate", contextDescription.Shaders.accumulatePass);
#if UNITY_2021_2_OR_NEWER
_sharpeningKeyword = new LocalKeyword(ComputeShader, SharpeningKeyword);
#endif
}
protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr3Upscaler.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY)
{
#if UNITY_2021_2_OR_NEWER
if (dispatchParams.EnableSharpening)
commandBuffer.EnableKeyword(ComputeShader, _sharpeningKeyword);
else
commandBuffer.DisableKeyword(ComputeShader, _sharpeningKeyword);
#else
if (dispatchParams.EnableSharpening)
commandBuffer.EnableShaderKeyword(SharpeningKeyword);
else
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.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvDilatedReactiveMasks, Fsr3ShaderIDs.UavDilatedReactiveMasks);
if ((ContextDescription.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.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInternalUpscaled, Resources.InternalUpscaled[frameIndex ^ 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.SrvLumaInstability, Fsr3ShaderIDs.UavLumaInstability);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputColor, color.RenderTarget, color.MipLevel, color.SubElement);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavInternalUpscaled, Resources.InternalUpscaled[frameIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavUpscaledOutput, output.RenderTarget, output.MipLevel, output.SubElement);
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants, 0, Marshal.SizeOf<Fsr3Upscaler.UpscalerConstants>());
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
}
}
internal class Fsr3UpscalerSharpenPass : Fsr3UpscalerPass
{
private readonly ComputeBuffer _rcasConstants;
public Fsr3UpscalerSharpenPass(Fsr3Upscaler.ContextDescription contextDescription, Fsr3UpscalerResources resources, ComputeBuffer constants, ComputeBuffer rcasConstants)
: base(contextDescription, resources, constants)
{
_rcasConstants = rcasConstants;
InitComputeShader("RCAS Sharpening", contextDescription.Shaders.sharpenPass);
}
protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr3Upscaler.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY)
{
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]);
ref var output = ref dispatchParams.Output;
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavUpscaledOutput, output.RenderTarget, output.MipLevel, output.SubElement);
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants, 0, Marshal.SizeOf<Fsr3Upscaler.UpscalerConstants>());
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbRcas, _rcasConstants, 0, Marshal.SizeOf<Fsr3Upscaler.RcasConstants>());
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
}
}
internal class Fsr3UpscalerGenerateReactivePass : Fsr3UpscalerPass
{
private readonly ComputeBuffer _generateReactiveConstants;
public Fsr3UpscalerGenerateReactivePass(Fsr3Upscaler.ContextDescription contextDescription, Fsr3UpscalerResources resources, ComputeBuffer generateReactiveConstants)
: base(contextDescription, resources, null)
{
_generateReactiveConstants = generateReactiveConstants;
InitComputeShader("Auto-Generate Reactive Mask", contextDescription.Shaders.autoGenReactivePass);
}
protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr3Upscaler.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY)
{
}
public void ScheduleDispatch(CommandBuffer commandBuffer, 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>());
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
commandBuffer.EndSample(Sampler);
}
}
internal class Fsr3UpscalerTcrAutogeneratePass : Fsr3UpscalerPass
{
private readonly ComputeBuffer _tcrAutogenerateConstants;
public Fsr3UpscalerTcrAutogeneratePass(Fsr3Upscaler.ContextDescription contextDescription, Fsr3UpscalerResources resources, ComputeBuffer constants, ComputeBuffer tcrAutogenerateConstants)
: base(contextDescription, resources, constants)
{
_tcrAutogenerateConstants = tcrAutogenerateConstants;
InitComputeShader("Auto-Generate Transparency & Composition Mask", contextDescription.Shaders.tcrAutoGenPass);
}
protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr3Upscaler.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY)
{
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.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.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants, 0, Marshal.SizeOf<Fsr3Upscaler.UpscalerConstants>());
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbGenReactive, _tcrAutogenerateConstants, 0, Marshal.SizeOf<Fsr3Upscaler.GenerateReactiveConstants2>());
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
}
}
#if UNITY_EDITOR || DEVELOPMENT_BUILD
internal class Fsr3UpscalerDebugViewPass : Fsr3UpscalerPass
{
public Fsr3UpscalerDebugViewPass(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)
{
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);
ref var output = ref dispatchParams.Output;
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavUpscaledOutput, output.RenderTarget, output.MipLevel, output.SubElement);
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants, 0, Marshal.SizeOf<Fsr3Upscaler.UpscalerConstants>());
commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1);
}
}
#endif
}

3
Runtime/FSR3/Fsr3UpscalerPass.cs.meta

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9e0cf27d80d1d4d4c81450791a411ead
timeCreated: 1676885169

248
Runtime/FSR3/Fsr3UpscalerResources.cs

@ -0,0 +1,248 @@
// Copyright (c) 2024 Nico de Poel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering;
namespace FidelityFX
{
/// <summary>
/// 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
{
public Texture2D LanczosLut;
public Texture2D DefaultExposure;
public Texture2D DefaultReactive;
public RenderTexture SpdAtomicCounter;
public RenderTexture SpdMips;
public RenderTexture DilatedVelocity;
public RenderTexture DilatedDepth;
public RenderTexture ReconstructedPrevNearestDepth;
public RenderTexture FrameInfo;
public RenderTexture AutoReactive;
public RenderTexture AutoComposition;
public readonly RenderTexture[] Accumulation = new RenderTexture[2];
public readonly RenderTexture[] Luma = new RenderTexture[2];
public readonly RenderTexture[] InternalUpscaled = new RenderTexture[2];
public readonly RenderTexture[] LumaHistory = new RenderTexture[2];
public readonly RenderTexture[] PrevPreAlpha = new RenderTexture[2];
public readonly RenderTexture[] PrevPostAlpha = new RenderTexture[2];
public void Create(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;
}
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();
// 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();
// 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();
// 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();
// 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();
// 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();
// 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();
// 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();
// 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();
// 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);
// Resources FSR3UPSCALER_Luma1/2: FFX_RESOURCE_USAGE_RENDERTARGET | FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R16_FLOAT, FFX_RESOURCE_FLAGS_NONE
CreateDoubleBufferedResource(Luma, "FSR3UPSCALER_Luma", maxRenderSize, GraphicsFormat.R16_SFloat);
// Resources FSR3UPSCALER_InternalUpscaled1/2: FFX_RESOURCE_USAGE_RENDERTARGET | FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R16G16B16A16_FLOAT, FFX_RESOURCE_FLAGS_NONE
CreateDoubleBufferedResource(InternalUpscaled, "FSR3UPSCALER_InternalUpscaled", contextDescription.MaxUpscaleSize, GraphicsFormat.R16G16B16A16_SFloat);
// Resources FSR3UPSCALER_LumaHistory1/2: FFX_RESOURCE_USAGE_RENDERTARGET | FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R16G16B16A16_FLOAT, FFX_RESOURCE_FLAGS_NONE
CreateDoubleBufferedResource(LumaHistory, "FSR3UPSCALER_LumaHistory", maxRenderSize, GraphicsFormat.R16G16B16A16_SFloat);
}
public void CreateTcrAutogenResources(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();
// 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();
// 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);
// Resources FSR3UPSCALER_PrevPostAlpha0/1: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R11G11B10_FLOAT, FFX_RESOURCE_FLAGS_NONE
CreateDoubleBufferedResource(PrevPostAlpha, "FSR3UPSCALER_PrevPostAlpha", contextDescription.MaxRenderSize, GraphicsFormat.B10G11R11_UFloatPack32);
}
// 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)
{
Vector2Int maxUpscaleSize = contextDescription.MaxUpscaleSize;
Vector2Int maxRenderSize = contextDescription.MaxRenderSize;
Vector2Int maxRenderSizeDiv2 = maxRenderSize / 2;
// FSR3UPSCALER_IntermediateFp16x1: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R16_FLOAT, FFX_RESOURCE_FLAGS_ALIASABLE
// TODO: see if these can be combined into one (this is a reusable temporary intermediate buffer used by different passes for different purposes)
commandBuffer.GetTemporaryRT(Fsr3ShaderIDs.UavFarthestDepth, maxRenderSize.x, maxRenderSize.y, 0, default, GraphicsFormat.R16_SFloat, 1, true);
commandBuffer.GetTemporaryRT(Fsr3ShaderIDs.UavLumaInstability, maxRenderSize.x, maxRenderSize.y, 0, default, GraphicsFormat.R16_SFloat, 1, true);
// FSR3UPSCALER_ShadingChange: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R8_UNORM, FFX_RESOURCE_FLAGS_ALIASABLE
commandBuffer.GetTemporaryRT(Fsr3ShaderIDs.UavShadingChange, maxRenderSizeDiv2.x, maxRenderSizeDiv2.y, 0, default, GraphicsFormat.R8_UNorm, 1, true);
// FSR3UPSCALER_NewLocks: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R8_UNORM, FFX_RESOURCE_FLAGS_ALIASABLE
commandBuffer.GetTemporaryRT(Fsr3ShaderIDs.UavNewLocks, maxUpscaleSize.x, maxUpscaleSize.y, 0, default, GraphicsFormat.R8_UNorm, 1, true);
// FSR3UPSCALER_FarthestDepthMip1: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R16_FLOAT, FFX_RESOURCE_FLAGS_ALIASABLE
commandBuffer.GetTemporaryRT(Fsr3ShaderIDs.UavFarthestDepthMip1, maxRenderSizeDiv2.x, maxRenderSizeDiv2.y, 0, default, GraphicsFormat.R16_SFloat, 1, true);
// FSR3UPSCALER_DilatedReactiveMasks: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R8G8B8A8_UNORM, FFX_RESOURCE_FLAGS_ALIASABLE
commandBuffer.GetTemporaryRT(Fsr3ShaderIDs.UavDilatedReactiveMasks, maxRenderSize.x, maxRenderSize.y, 0, default, GraphicsFormat.R8G8B8A8_UNorm, 1, true);
}
public static void DestroyAliasableResources(CommandBuffer commandBuffer)
{
// Release all of the aliasable resources used this frame
commandBuffer.ReleaseTemporaryRT(Fsr3ShaderIDs.UavDilatedReactiveMasks);
commandBuffer.ReleaseTemporaryRT(Fsr3ShaderIDs.UavFarthestDepthMip1);
commandBuffer.ReleaseTemporaryRT(Fsr3ShaderIDs.UavNewLocks);
commandBuffer.ReleaseTemporaryRT(Fsr3ShaderIDs.UavShadingChange);
commandBuffer.ReleaseTemporaryRT(Fsr3ShaderIDs.UavLumaInstability);
commandBuffer.ReleaseTemporaryRT(Fsr3ShaderIDs.UavFarthestDepth);
}
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();
DestroyResource(LumaHistory);
DestroyResource(InternalUpscaled);
DestroyResource(Luma);
DestroyResource(Accumulation);
DestroyResource(ref FrameInfo);
DestroyResource(ref ReconstructedPrevNearestDepth);
DestroyResource(ref DilatedDepth);
DestroyResource(ref DilatedVelocity);
DestroyResource(ref SpdMips);
DestroyResource(ref SpdAtomicCounter);
DestroyResource(ref DefaultReactive);
DestroyResource(ref DefaultExposure);
DestroyResource(ref LanczosLut);
}
public void DestroyTcrAutogenResources()
{
DestroyResource(PrevPostAlpha);
DestroyResource(PrevPreAlpha);
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]);
}
}
}

3
Runtime/FSR3/Fsr3UpscalerResources.cs.meta

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6749e0e55c9ac5a4f869bc73dfbb7163
timeCreated: 1677236102

16
Runtime/FSR3/fidelityfx.fsr.fsr3upscaler.asmdef

@ -0,0 +1,16 @@
{
"name": "fidelityfx.fsr.fsr3upscaler",
"rootNamespace": "FidelityFX",
"references": [
"GUID:f355c2e9d97d4d8438e24fa268b0f6a5"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

7
Runtime/FSR3/fidelityfx.fsr.fsr3upscaler.asmdef.meta

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: c64cdcb81f02fbf4f9dc91468e49c2b7
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Shaders.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: af3a6660394230a4bb247808bbefe9f4
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

41
Shaders/ffx_fsr2_accumulate_pass.compute

@ -0,0 +1,41 @@
// Copyright (c) 2024 Nico de Poel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma kernel CS
#pragma multi_compile_local __ FFX_HALF
#pragma multi_compile_local __ FFX_FSR2_OPTION_REPROJECT_USE_LANCZOS_TYPE
#pragma multi_compile_local __ FFX_FSR2_OPTION_HDR_COLOR_INPUT
#pragma multi_compile_local __ FFX_FSR2_OPTION_LOW_RESOLUTION_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR2_OPTION_JITTERED_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR2_OPTION_INVERTED_DEPTH
#pragma multi_compile_local __ FFX_FSR2_OPTION_APPLY_SHARPENING
#pragma multi_compile_local __ UNITY_FSR_HDRP
#include "ffx_fsr_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
#undef FFX_FSR2_OPTION_REPROJECT_USE_LANCZOS_TYPE
#define FFX_FSR2_OPTION_REPROJECT_USE_LANCZOS_TYPE 1
#endif
#include "shaders/ffx_fsr2_accumulate_pass.hlsl"

8
Shaders/ffx_fsr2_accumulate_pass.compute.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7e791d69a5be98247a93b63897bc64df
ComputeShaderImporter:
externalObjects: {}
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:

32
Shaders/ffx_fsr2_autogen_reactive_pass.compute

@ -0,0 +1,32 @@
// Copyright (c) 2024 Nico de Poel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma kernel CS
#pragma multi_compile_local __ FFX_HALF
#pragma multi_compile_local __ FFX_FSR2_OPTION_LOW_RESOLUTION_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR2_OPTION_JITTERED_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR2_OPTION_INVERTED_DEPTH
#pragma multi_compile_local __ UNITY_FSR_HDRP
#include "ffx_fsr_unity_common.cginc"
#include "shaders/ffx_fsr2_autogen_reactive_pass.hlsl"

8
Shaders/ffx_fsr2_autogen_reactive_pass.compute.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 67ee1b32ca5e4234db9f06984c783dee
ComputeShaderImporter:
externalObjects: {}
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:

42
Shaders/ffx_fsr2_compute_luminance_pyramid_pass.compute

@ -0,0 +1,42 @@
// Copyright (c) 2024 Nico de Poel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma kernel CS
#pragma multi_compile_local __ FFX_HALF
#pragma multi_compile_local __ FFX_FSR2_OPTION_LOW_RESOLUTION_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR2_OPTION_JITTERED_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR2_OPTION_INVERTED_DEPTH
#pragma multi_compile_local __ UNITY_FSR_HDRP
#include "ffx_fsr_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.
// Uncomment the below lines if you intend to try wave operations on DX12 with the DXC compiler.
//#if defined(UNITY_COMPILER_DXC) && defined(SHADER_API_D3D12)
//#pragma require WaveBasic // Required for WaveGetLaneIndex
//#pragma require WaveBallot // Required for WaveReadLaneAt
//#else
#define FFX_SPD_NO_WAVE_OPERATIONS
//#endif
#include "shaders/ffx_fsr2_compute_luminance_pyramid_pass.hlsl"

8
Shaders/ffx_fsr2_compute_luminance_pyramid_pass.compute.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 04c3480675e29a340808141e68d4cc8b
ComputeShaderImporter:
externalObjects: {}
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:

32
Shaders/ffx_fsr2_depth_clip_pass.compute

@ -0,0 +1,32 @@
// Copyright (c) 2024 Nico de Poel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma kernel CS
#pragma multi_compile_local __ FFX_HALF
#pragma multi_compile_local __ FFX_FSR2_OPTION_LOW_RESOLUTION_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR2_OPTION_JITTERED_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR2_OPTION_INVERTED_DEPTH
#pragma multi_compile_local __ UNITY_FSR_HDRP
#include "ffx_fsr_unity_common.cginc"
#include "shaders/ffx_fsr2_depth_clip_pass.hlsl"

8
Shaders/ffx_fsr2_depth_clip_pass.compute.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b207de122e2c4b844b89dcd7c5c77c80
ComputeShaderImporter:
externalObjects: {}
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:

30
Shaders/ffx_fsr2_lock_pass.compute

@ -0,0 +1,30 @@
// Copyright (c) 2024 Nico de Poel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma kernel CS
#pragma multi_compile_local __ FFX_HALF
#pragma multi_compile_local __ FFX_FSR2_OPTION_LOW_RESOLUTION_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR2_OPTION_JITTERED_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR2_OPTION_INVERTED_DEPTH
#include "ffx_fsr_unity_common.cginc"
#include "shaders/ffx_fsr2_lock_pass.hlsl"

8
Shaders/ffx_fsr2_lock_pass.compute.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 20b7864a7e7258946aaf0f1996febad3
ComputeShaderImporter:
externalObjects: {}
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:

31
Shaders/ffx_fsr2_rcas_pass.compute

@ -0,0 +1,31 @@
// Copyright (c) 2024 Nico de Poel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma kernel CS
#pragma multi_compile_local __ FFX_FSR2_OPTION_LOW_RESOLUTION_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR2_OPTION_JITTERED_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR2_OPTION_INVERTED_DEPTH
#pragma multi_compile_local __ UNITY_FSR_HDRP
#include "ffx_fsr_unity_common.cginc"
#include "shaders/ffx_fsr2_rcas_pass.hlsl"

8
Shaders/ffx_fsr2_rcas_pass.compute.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 40815651f0f5d994cb73da9816a7ff9b
ComputeShaderImporter:
externalObjects: {}
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:

33
Shaders/ffx_fsr2_reconstruct_previous_depth_pass.compute

@ -0,0 +1,33 @@
// Copyright (c) 2024 Nico de Poel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma kernel CS
#pragma multi_compile_local __ FFX_HALF
#pragma multi_compile_local __ FFX_FSR2_OPTION_HDR_COLOR_INPUT
#pragma multi_compile_local __ FFX_FSR2_OPTION_LOW_RESOLUTION_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR2_OPTION_JITTERED_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR2_OPTION_INVERTED_DEPTH
#pragma multi_compile_local __ UNITY_FSR_HDRP
#include "ffx_fsr_unity_common.cginc"
#include "shaders/ffx_fsr2_reconstruct_previous_depth_pass.hlsl"

8
Shaders/ffx_fsr2_reconstruct_previous_depth_pass.compute.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5060dfafe45aa67459629186ceb7464e
ComputeShaderImporter:
externalObjects: {}
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:

32
Shaders/ffx_fsr2_tcr_autogen_pass.compute

@ -0,0 +1,32 @@
// Copyright (c) 2024 Nico de Poel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma kernel CS
#pragma multi_compile_local __ FFX_HALF
#pragma multi_compile_local __ FFX_FSR2_OPTION_LOW_RESOLUTION_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR2_OPTION_JITTERED_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR2_OPTION_INVERTED_DEPTH
#pragma multi_compile_local __ UNITY_FSR_HDRP
#include "ffx_fsr_unity_common.cginc"
#include "shaders/ffx_fsr2_tcr_autogen_pass.hlsl"

8
Shaders/ffx_fsr2_tcr_autogen_pass.compute.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f8b1c27fb6a544b43b38903592240500
ComputeShaderImporter:
externalObjects: {}
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:

41
Shaders/ffx_fsr3upscaler_accumulate_pass.compute

@ -0,0 +1,41 @@
// Copyright (c) 2024 Nico de Poel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma kernel CS
#pragma multi_compile_local __ FFX_HALF
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_REPROJECT_USE_LANCZOS_TYPE
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_HDR_COLOR_INPUT
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_LOW_RESOLUTION_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_JITTERED_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_INVERTED_DEPTH
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_APPLY_SHARPENING
#pragma multi_compile_local __ UNITY_FSR_HDRP
#include "ffx_fsr_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
#undef FFX_FSR3UPSCALER_OPTION_REPROJECT_USE_LANCZOS_TYPE
#define FFX_FSR3UPSCALER_OPTION_REPROJECT_USE_LANCZOS_TYPE 1
#endif
#include "shaders/ffx_fsr3upscaler_accumulate_pass.hlsl"

8
Shaders/ffx_fsr3upscaler_accumulate_pass.compute.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c9b45f0ae7673694ba57a4aadfe212e9
ComputeShaderImporter:
externalObjects: {}
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:

32
Shaders/ffx_fsr3upscaler_autogen_reactive_pass.compute

@ -0,0 +1,32 @@
// Copyright (c) 2024 Nico de Poel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma kernel CS
#pragma multi_compile_local __ FFX_HALF
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_LOW_RESOLUTION_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_JITTERED_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_INVERTED_DEPTH
#pragma multi_compile_local __ UNITY_FSR_HDRP
#include "ffx_fsr_unity_common.cginc"
#include "shaders/ffx_fsr3upscaler_autogen_reactive_pass.hlsl"

8
Shaders/ffx_fsr3upscaler_autogen_reactive_pass.compute.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5716b91fdaa4e9e439df6b96a796fe6e
ComputeShaderImporter:
externalObjects: {}
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:

35
Shaders/ffx_fsr3upscaler_debug_view_pass.compute

@ -0,0 +1,35 @@
// Copyright (c) 2024 Nico de Poel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma kernel CS
#pragma multi_compile_local __ FFX_HALF
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_REPROJECT_USE_LANCZOS_TYPE
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_HDR_COLOR_INPUT
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_LOW_RESOLUTION_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_JITTERED_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_INVERTED_DEPTH
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_APPLY_SHARPENING
#pragma multi_compile_local __ UNITY_FSR_HDRP
#include "ffx_fsr_unity_common.cginc"
#include "shaders/ffx_fsr3upscaler_debug_view_pass.hlsl"

8
Shaders/ffx_fsr3upscaler_debug_view_pass.compute.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: cb24a71d54164c54eb5e86839acd48c5
ComputeShaderImporter:
externalObjects: {}
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:

35
Shaders/ffx_fsr3upscaler_luma_instability_pass.compute

@ -0,0 +1,35 @@
// Copyright (c) 2024 Nico de Poel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma kernel CS
#pragma multi_compile_local __ FFX_HALF
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_REPROJECT_USE_LANCZOS_TYPE
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_HDR_COLOR_INPUT
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_LOW_RESOLUTION_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_JITTERED_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_INVERTED_DEPTH
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_APPLY_SHARPENING
#pragma multi_compile_local __ UNITY_FSR_HDRP
#include "ffx_fsr_unity_common.cginc"
#include "shaders/ffx_fsr3upscaler_luma_instability_pass.hlsl"

8
Shaders/ffx_fsr3upscaler_luma_instability_pass.compute.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a135306e6d1857e43a86ef20db2a47fe
ComputeShaderImporter:
externalObjects: {}
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:

45
Shaders/ffx_fsr3upscaler_luma_pyramid_pass.compute

@ -0,0 +1,45 @@
// Copyright (c) 2024 Nico de Poel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma kernel CS
#pragma multi_compile_local __ FFX_HALF
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_REPROJECT_USE_LANCZOS_TYPE
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_HDR_COLOR_INPUT
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_LOW_RESOLUTION_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_JITTERED_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_INVERTED_DEPTH
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_APPLY_SHARPENING
#pragma multi_compile_local __ UNITY_FSR_HDRP
#include "ffx_fsr_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.
// Uncomment the below lines if you intend to try wave operations on DX12 with the DXC compiler.
//#if defined(UNITY_COMPILER_DXC) && defined(SHADER_API_D3D12)
//#pragma require WaveBasic // Required for WaveGetLaneIndex
//#pragma require WaveBallot // Required for WaveReadLaneAt
//#else
#define FFX_SPD_NO_WAVE_OPERATIONS
//#endif
#include "shaders/ffx_fsr3upscaler_luma_pyramid_pass.hlsl"

8
Shaders/ffx_fsr3upscaler_luma_pyramid_pass.compute.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d253be05abcdc80428503d3e4cce3a36
ComputeShaderImporter:
externalObjects: {}
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:

36
Shaders/ffx_fsr3upscaler_prepare_inputs_pass.compute

@ -0,0 +1,36 @@
// Copyright (c) 2024 Nico de Poel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma kernel CS
// TODO: figure out which of these defines are actually used by this shader (for all shader passes)
#pragma multi_compile_local __ FFX_HALF
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_REPROJECT_USE_LANCZOS_TYPE
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_HDR_COLOR_INPUT
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_LOW_RESOLUTION_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_JITTERED_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_INVERTED_DEPTH
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_APPLY_SHARPENING
#pragma multi_compile_local __ UNITY_FSR_HDRP
#include "ffx_fsr_unity_common.cginc"
#include "shaders/ffx_fsr3upscaler_prepare_inputs_pass.hlsl"

8
Shaders/ffx_fsr3upscaler_prepare_inputs_pass.compute.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4f59e5b9179d74844ae06a30ae1e0629
ComputeShaderImporter:
externalObjects: {}
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:

35
Shaders/ffx_fsr3upscaler_prepare_reactivity_pass.compute

@ -0,0 +1,35 @@
// Copyright (c) 2024 Nico de Poel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma kernel CS
#pragma multi_compile_local __ FFX_HALF
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_REPROJECT_USE_LANCZOS_TYPE
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_HDR_COLOR_INPUT
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_LOW_RESOLUTION_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_JITTERED_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_INVERTED_DEPTH
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_APPLY_SHARPENING
#pragma multi_compile_local __ UNITY_FSR_HDRP
#include "ffx_fsr_unity_common.cginc"
#include "shaders/ffx_fsr3upscaler_prepare_reactivity_pass.hlsl"

8
Shaders/ffx_fsr3upscaler_prepare_reactivity_pass.compute.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 20e44016ed34b0d4b8de499d1b566c69
ComputeShaderImporter:
externalObjects: {}
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:

31
Shaders/ffx_fsr3upscaler_rcas_pass.compute

@ -0,0 +1,31 @@
// Copyright (c) 2024 Nico de Poel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma kernel CS
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_LOW_RESOLUTION_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_JITTERED_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_INVERTED_DEPTH
#pragma multi_compile_local __ UNITY_FSR_HDRP
#include "ffx_fsr_unity_common.cginc"
#include "shaders/ffx_fsr3upscaler_rcas_pass.hlsl"

8
Shaders/ffx_fsr3upscaler_rcas_pass.compute.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7aaf5cfff022de2499e9b0412f947f6c
ComputeShaderImporter:
externalObjects: {}
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:

35
Shaders/ffx_fsr3upscaler_shading_change_pass.compute

@ -0,0 +1,35 @@
// Copyright (c) 2024 Nico de Poel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma kernel CS
#pragma multi_compile_local __ FFX_HALF
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_REPROJECT_USE_LANCZOS_TYPE
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_HDR_COLOR_INPUT
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_LOW_RESOLUTION_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_JITTERED_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_INVERTED_DEPTH
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_APPLY_SHARPENING
#pragma multi_compile_local __ UNITY_FSR_HDRP
#include "ffx_fsr_unity_common.cginc"
#include "shaders/ffx_fsr3upscaler_shading_change_pass.hlsl"

8
Shaders/ffx_fsr3upscaler_shading_change_pass.compute.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9a2bff2f97619ed4989d9b0577ba0641
ComputeShaderImporter:
externalObjects: {}
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:

38
Shaders/ffx_fsr3upscaler_shading_change_pyramid_pass.compute

@ -0,0 +1,38 @@
// Copyright (c) 2024 Nico de Poel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma kernel CS
#pragma multi_compile_local __ FFX_HALF
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_REPROJECT_USE_LANCZOS_TYPE
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_HDR_COLOR_INPUT
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_LOW_RESOLUTION_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_JITTERED_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_INVERTED_DEPTH
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_APPLY_SHARPENING
#pragma multi_compile_local __ UNITY_FSR_HDRP
#include "ffx_fsr_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
#include "shaders/ffx_fsr3upscaler_shading_change_pyramid_pass.hlsl"

8
Shaders/ffx_fsr3upscaler_shading_change_pyramid_pass.compute.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 251e663738905fa4d8817001682d802f
ComputeShaderImporter:
externalObjects: {}
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:

32
Shaders/ffx_fsr3upscaler_tcr_autogen_pass.compute

@ -0,0 +1,32 @@
// Copyright (c) 2024 Nico de Poel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma kernel CS
#pragma multi_compile_local __ FFX_HALF
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_LOW_RESOLUTION_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_JITTERED_MOTION_VECTORS
#pragma multi_compile_local __ FFX_FSR3UPSCALER_OPTION_INVERTED_DEPTH
#pragma multi_compile_local __ UNITY_FSR_HDRP
#include "ffx_fsr_unity_common.cginc"
#include "shaders/ffx_fsr3upscaler_tcr_autogen_pass.hlsl"

8
Shaders/ffx_fsr3upscaler_tcr_autogen_pass.compute.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 75cdc6ef23f08ed498d4da511923fcea
ComputeShaderImporter:
externalObjects: {}
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:

85
Shaders/ffx_fsr_unity_common.cginc

@ -0,0 +1,85 @@
// Copyright (c) 2024 Nico de Poel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// Suppress a few warnings produced by FFX's HLSL code
#pragma warning(disable: 3078) // Loop control variable conflicts
#pragma warning(disable: 3203) // Signed/unsigned mismatch
#pragma warning(disable: 3556) // Integer divides might be much slower, try using uints if possible
#define FFX_GPU // Compiling for GPU
#define FFX_HLSL // Compile for plain HLSL
// Use the DXC shader compiler on modern graphics APIs to enable a few advanced features
// The DXC-related pragmas are disabled by default, as DXC doesn't support all platforms yet and will break on some platforms when enabled.
// Consider this to be an experimental feature. If you want to benefit from 16-bit floating point and wave operations, and don't care about supporting older graphics APIs, then it's worth a try.
//#if defined(SHADER_API_D3D12) || defined(SHADER_API_VULKAN) || defined(SHADER_API_METAL)
//#pragma use_dxc // Using DXC will currently break DX11 support since DX11 and DX12 share the same shader bytecode in Unity.
//#endif
// Enable half precision data types on platforms that support it
//#if defined(UNITY_COMPILER_DXC) && defined(FFX_HALF)
//#pragma require Native16Bit
//#endif
// Hack to work around the lack of texture atomics on Metal
#if defined(SHADER_API_METAL)
#define InterlockedAdd(dest, val, orig) { (orig) = (dest); (dest) += (val); }
#define InterlockedMin(dest, val) { (dest) = min((dest), (val)); }
#define InterlockedMax(dest, val) { (dest) = max((dest), (val)); }
#endif
// Workaround for HDRP using texture arrays for its camera buffers on some platforms
// The below defines are copied from: Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/TextureXR.hlsl
#if defined(UNITY_FSR_HDRP)
// Must be in sync with C# with property useTexArray in TextureXR.cs
#if ((defined(SHADER_API_D3D11) || defined(SHADER_API_D3D12)) && !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_GAMECORE)) || defined(SHADER_API_PSSL) || defined(SHADER_API_VULKAN)
#define UNITY_TEXTURE2D_X_ARRAY_SUPPORTED
#endif
// Control if TEXTURE2D_X macros will expand to texture arrays
#if defined(UNITY_TEXTURE2D_X_ARRAY_SUPPORTED) && !defined(DISABLE_TEXTURE2D_X_ARRAY)
#define USE_TEXTURE2D_X_AS_ARRAY
#endif
// Early defines for single-pass instancing
#if defined(STEREO_INSTANCING_ON) && defined(UNITY_TEXTURE2D_X_ARRAY_SUPPORTED)
#define UNITY_STEREO_INSTANCING_ENABLED
#endif
// Helper macros to handle XR single-pass with Texture2DArray
#if defined(USE_TEXTURE2D_X_AS_ARRAY)
// Only single-pass stereo instancing used array indexing
#if defined(UNITY_STEREO_INSTANCING_ENABLED)
static uint unity_StereoEyeIndex;
#define SLICE_ARRAY_INDEX unity_StereoEyeIndex
#else
#define SLICE_ARRAY_INDEX 0
#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); }
#endif
#endif

7
Shaders/ffx_fsr_unity_common.cginc.meta

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 3ce00ba677bb7e14bb91772fd68bfe6b
ShaderIncludeImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Shaders/shaders.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c3f8af1cab72f0e46acba11c5820d923
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

654
Shaders/shaders/ffx_common_types.h

@ -0,0 +1,654 @@
// This file is part of the FidelityFX SDK.
//
// Copyright (C) 2024 Advanced Micro Devices, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef FFX_COMMON_TYPES_H
#define FFX_COMMON_TYPES_H
#if defined(FFX_CPU)
#define FFX_PARAMETER_IN
#define FFX_PARAMETER_OUT
#define FFX_PARAMETER_INOUT
#define FFX_PARAMETER_UNIFORM
#elif defined(FFX_HLSL)
#define FFX_PARAMETER_IN in
#define FFX_PARAMETER_OUT out
#define FFX_PARAMETER_INOUT inout
#define FFX_PARAMETER_UNIFORM uniform
#elif defined(FFX_GLSL)
#define FFX_PARAMETER_IN in
#define FFX_PARAMETER_OUT out
#define FFX_PARAMETER_INOUT inout
#define FFX_PARAMETER_UNIFORM const //[cacao_placeholder] until a better fit is found!
#endif // #if defined(FFX_CPU)
#if defined(FFX_CPU)
/// A typedef for a boolean value.
///
/// @ingroup CPUTypes
typedef bool FfxBoolean;
/// A typedef for a unsigned 8bit integer.
///
/// @ingroup CPUTypes
typedef uint8_t FfxUInt8;
/// A typedef for a unsigned 16bit integer.
///
/// @ingroup CPUTypes
typedef uint16_t FfxUInt16;
/// A typedef for a unsigned 32bit integer.
///
/// @ingroup CPUTypes
typedef uint32_t FfxUInt32;
/// A typedef for a unsigned 64bit integer.
///
/// @ingroup CPUTypes
typedef uint64_t FfxUInt64;
/// A typedef for a signed 8bit integer.
///
/// @ingroup CPUTypes
typedef int8_t FfxInt8;
/// A typedef for a signed 16bit integer.
///
/// @ingroup CPUTypes
typedef int16_t FfxInt16;
/// A typedef for a signed 32bit integer.
///
/// @ingroup CPUTypes
typedef int32_t FfxInt32;
/// A typedef for a signed 64bit integer.
///
/// @ingroup CPUTypes
typedef int64_t FfxInt64;
/// A typedef for a floating point value.
///
/// @ingroup CPUTypes
typedef float FfxFloat32;
/// A typedef for a 2-dimensional floating point value.
///
/// @ingroup CPUTypes
typedef float FfxFloat32x2[2];
/// A typedef for a 3-dimensional floating point value.
///
/// @ingroup CPUTypes
typedef float FfxFloat32x3[3];
/// A typedef for a 4-dimensional floating point value.
///
/// @ingroup CPUTypes
typedef float FfxFloat32x4[4];
/// A typedef for a 2x2 floating point matrix.
///
/// @ingroup CPUTypes
typedef float FfxFloat32x2x2[4];
/// A typedef for a 3x3 floating point matrix.
///
/// @ingroup CPUTypes
typedef float FfxFloat32x3x3[9];
/// A typedef for a 3x4 floating point matrix.
///
/// @ingroup CPUTypes
typedef float FfxFloat32x3x4[12];
/// A typedef for a 4x4 floating point matrix.
///
/// @ingroup CPUTypes
typedef float FfxFloat32x4x4[16];
/// A typedef for a 2-dimensional 32bit signed integer.
///
/// @ingroup CPUTypes
typedef int32_t FfxInt32x2[2];
/// A typedef for a 3-dimensional 32bit signed integer.
///
/// @ingroup CPUTypes
typedef int32_t FfxInt32x3[3];
/// A typedef for a 4-dimensional 32bit signed integer.
///
/// @ingroup CPUTypes
typedef int32_t FfxInt32x4[4];
/// A typedef for a 2-dimensional 32bit usigned integer.
///
/// @ingroup CPUTypes
typedef uint32_t FfxUInt32x2[2];
/// A typedef for a 3-dimensional 32bit unsigned integer.
///
/// @ingroup CPUTypes
typedef uint32_t FfxUInt32x3[3];
/// A typedef for a 4-dimensional 32bit unsigned integer.
///
/// @ingroup CPUTypes
typedef uint32_t FfxUInt32x4[4];
#endif // #if defined(FFX_CPU)
#if defined(FFX_HLSL)
#define FfxFloat32Mat4 matrix <float, 4, 4>
#define FfxFloat32Mat3 matrix <float, 3, 3>
/// A typedef for a boolean value.
///
/// @ingroup HLSLTypes
typedef bool FfxBoolean;
#if FFX_HLSL_SM>=62
/// @defgroup HLSL62Types HLSL 6.2 And Above Types
/// HLSL 6.2 and above type defines for all commonly used variables
///
/// @ingroup HLSLTypes
/// A typedef for a floating point value.
///
/// @ingroup HLSL62Types
typedef float32_t FfxFloat32;
/// A typedef for a 2-dimensional floating point value.
///
/// @ingroup HLSL62Types
typedef float32_t2 FfxFloat32x2;
/// A typedef for a 3-dimensional floating point value.
///
/// @ingroup HLSL62Types
typedef float32_t3 FfxFloat32x3;
/// A typedef for a 4-dimensional floating point value.
///
/// @ingroup HLSL62Types
typedef float32_t4 FfxFloat32x4;
/// A [cacao_placeholder] typedef for matrix type until confirmed.
typedef float4x4 FfxFloat32x4x4;
typedef float3x4 FfxFloat32x3x4;
typedef float3x3 FfxFloat32x3x3;
typedef float2x2 FfxFloat32x2x2;
/// A typedef for a unsigned 32bit integer.
///
/// @ingroup HLSL62Types
typedef uint32_t FfxUInt32;
/// A typedef for a 2-dimensional 32bit unsigned integer.
///
/// @ingroup HLSL62Types
typedef uint32_t2 FfxUInt32x2;
/// A typedef for a 3-dimensional 32bit unsigned integer.
///
/// @ingroup HLSL62Types
typedef uint32_t3 FfxUInt32x3;
/// A typedef for a 4-dimensional 32bit unsigned integer.
///
/// @ingroup HLSL62Types
typedef uint32_t4 FfxUInt32x4;
/// A typedef for a signed 32bit integer.
///
/// @ingroup HLSL62Types
typedef int32_t FfxInt32;
/// A typedef for a 2-dimensional signed 32bit integer.
///
/// @ingroup HLSL62Types
typedef int32_t2 FfxInt32x2;
/// A typedef for a 3-dimensional signed 32bit integer.
///
/// @ingroup HLSL62Types
typedef int32_t3 FfxInt32x3;
/// A typedef for a 4-dimensional signed 32bit integer.
///
/// @ingroup HLSL62Types
typedef int32_t4 FfxInt32x4;
#else // #if FFX_HLSL_SM>=62
/// @defgroup HLSLBaseTypes HLSL 6.1 And Below Types
/// HLSL 6.1 and below type defines for all commonly used variables
///
/// @ingroup HLSLTypes
#define FfxFloat32 float
#define FfxFloat32x2 float2
#define FfxFloat32x3 float3
#define FfxFloat32x4 float4
/// A [cacao_placeholder] typedef for matrix type until confirmed.
#define FfxFloat32x4x4 float4x4
#define FfxFloat32x3x4 float3x4
#define FfxFloat32x3x3 float3x3
#define FfxFloat32x2x2 float2x2
/// A typedef for a unsigned 32bit integer.
///
/// @ingroup GPU
typedef uint FfxUInt32;
typedef uint2 FfxUInt32x2;
typedef uint3 FfxUInt32x3;
typedef uint4 FfxUInt32x4;
typedef int FfxInt32;
typedef int2 FfxInt32x2;
typedef int3 FfxInt32x3;
typedef int4 FfxInt32x4;
#endif // #if FFX_HLSL_SM>=62
#if FFX_HALF
#if FFX_HLSL_SM >= 62
typedef float16_t FfxFloat16;
typedef float16_t2 FfxFloat16x2;
typedef float16_t3 FfxFloat16x3;
typedef float16_t4 FfxFloat16x4;
/// A typedef for an unsigned 16bit integer.
///
/// @ingroup HLSLTypes
typedef uint16_t FfxUInt16;
typedef uint16_t2 FfxUInt16x2;
typedef uint16_t3 FfxUInt16x3;
typedef uint16_t4 FfxUInt16x4;
/// A typedef for a signed 16bit integer.
///
/// @ingroup HLSLTypes
typedef int16_t FfxInt16;
typedef int16_t2 FfxInt16x2;
typedef int16_t3 FfxInt16x3;
typedef int16_t4 FfxInt16x4;
#elif SHADER_API_PSSL
#pragma argument(realtypes) // Enable true 16-bit types
typedef half FfxFloat16;
typedef half2 FfxFloat16x2;
typedef half3 FfxFloat16x3;
typedef half4 FfxFloat16x4;
/// A typedef for an unsigned 16bit integer.
///
/// @ingroup GPU
typedef ushort FfxUInt16;
typedef ushort2 FfxUInt16x2;
typedef ushort3 FfxUInt16x3;
typedef ushort4 FfxUInt16x4;
/// A typedef for a signed 16bit integer.
///
/// @ingroup GPU
typedef short FfxInt16;
typedef short2 FfxInt16x2;
typedef short3 FfxInt16x3;
typedef short4 FfxInt16x4;
#else // #if FFX_HLSL_SM>=62
typedef min16float FfxFloat16;
typedef min16float2 FfxFloat16x2;
typedef min16float3 FfxFloat16x3;
typedef min16float4 FfxFloat16x4;
/// A typedef for an unsigned 16bit integer.
///
/// @ingroup HLSLTypes
typedef min16uint FfxUInt16;
typedef min16uint2 FfxUInt16x2;
typedef min16uint3 FfxUInt16x3;
typedef min16uint4 FfxUInt16x4;
/// A typedef for a signed 16bit integer.
///
/// @ingroup HLSLTypes
typedef min16int FfxInt16;
typedef min16int2 FfxInt16x2;
typedef min16int3 FfxInt16x3;
typedef min16int4 FfxInt16x4;
#endif // #if FFX_HLSL_SM>=62
#endif // FFX_HALF
#endif // #if defined(FFX_HLSL)
#if defined(FFX_GLSL)
#define FfxFloat32Mat4 mat4
#define FfxFloat32Mat3 mat3
/// A typedef for a boolean value.
///
/// @ingroup GLSLTypes
#define FfxBoolean bool
#define FfxFloat32 float
#define FfxFloat32x2 vec2
#define FfxFloat32x3 vec3
#define FfxFloat32x4 vec4
#define FfxUInt32 uint
#define FfxUInt32x2 uvec2
#define FfxUInt32x3 uvec3
#define FfxUInt32x4 uvec4
#define FfxInt32 int
#define FfxInt32x2 ivec2
#define FfxInt32x3 ivec3
#define FfxInt32x4 ivec4
/// A [cacao_placeholder] typedef for matrix type until confirmed.
#define FfxFloat32x4x4 mat4
#define FfxFloat32x3x4 mat4x3
#define FfxFloat32x3x3 mat3
#define FfxFloat32x2x2 mat2
#if FFX_HALF
#define FfxFloat16 float16_t
#define FfxFloat16x2 f16vec2
#define FfxFloat16x3 f16vec3
#define FfxFloat16x4 f16vec4
#define FfxUInt16 uint16_t
#define FfxUInt16x2 u16vec2
#define FfxUInt16x3 u16vec3
#define FfxUInt16x4 u16vec4
#define FfxInt16 int16_t
#define FfxInt16x2 i16vec2
#define FfxInt16x3 i16vec3
#define FfxInt16x4 i16vec4
#endif // FFX_HALF
#endif // #if defined(FFX_GLSL)
// Global toggles:
// #define FFX_HALF (1)
// #define FFX_HLSL_SM (62)
#if FFX_HALF && !defined(SHADER_API_PSSL)
#if FFX_HLSL_SM >= 62
#define FFX_MIN16_SCALAR( TypeName, BaseComponentType ) typedef BaseComponentType##16_t TypeName;
#define FFX_MIN16_VECTOR( TypeName, BaseComponentType, COL ) typedef vector<BaseComponentType##16_t, COL> TypeName;
#define FFX_MIN16_MATRIX( TypeName, BaseComponentType, ROW, COL ) typedef matrix<BaseComponentType##16_t, ROW, COL> TypeName;
#define FFX_16BIT_SCALAR( TypeName, BaseComponentType ) typedef BaseComponentType##16_t TypeName;
#define FFX_16BIT_VECTOR( TypeName, BaseComponentType, COL ) typedef vector<BaseComponentType##16_t, COL> TypeName;
#define FFX_16BIT_MATRIX( TypeName, BaseComponentType, ROW, COL ) typedef matrix<BaseComponentType##16_t, ROW, COL> TypeName;
#else //FFX_HLSL_SM>=62
#define FFX_MIN16_SCALAR( TypeName, BaseComponentType ) typedef min16##BaseComponentType TypeName;
#define FFX_MIN16_VECTOR( TypeName, BaseComponentType, COL ) typedef vector<min16##BaseComponentType, COL> TypeName;
#define FFX_MIN16_MATRIX( TypeName, BaseComponentType, ROW, COL ) typedef matrix<min16##BaseComponentType, ROW, COL> TypeName;
#define FFX_16BIT_SCALAR( TypeName, BaseComponentType ) FFX_MIN16_SCALAR( TypeName, BaseComponentType );
#define FFX_16BIT_VECTOR( TypeName, BaseComponentType, COL ) FFX_MIN16_VECTOR( TypeName, BaseComponentType, COL );
#define FFX_16BIT_MATRIX( TypeName, BaseComponentType, ROW, COL ) FFX_MIN16_MATRIX( TypeName, BaseComponentType, ROW, COL );
#endif //FFX_HLSL_SM>=62
#else //FFX_HALF
#define FFX_MIN16_SCALAR( TypeName, BaseComponentType ) typedef BaseComponentType TypeName;
#define FFX_MIN16_VECTOR( TypeName, BaseComponentType, COL ) typedef vector<BaseComponentType, COL> TypeName;
#define FFX_MIN16_MATRIX( TypeName, BaseComponentType, ROW, COL ) typedef matrix<BaseComponentType, ROW, COL> TypeName;
#define FFX_16BIT_SCALAR( TypeName, BaseComponentType ) typedef BaseComponentType TypeName;
#define FFX_16BIT_VECTOR( TypeName, BaseComponentType, COL ) typedef vector<BaseComponentType, COL> TypeName;
#define FFX_16BIT_MATRIX( TypeName, BaseComponentType, ROW, COL ) typedef matrix<BaseComponentType, ROW, COL> TypeName;
#endif //FFX_HALF
#if defined(FFX_GPU)
// Common typedefs:
#if defined(FFX_HLSL) && !defined(SHADER_API_PSSL)
FFX_MIN16_SCALAR( FFX_MIN16_F , float );
FFX_MIN16_VECTOR( FFX_MIN16_F2, float, 2 );
FFX_MIN16_VECTOR( FFX_MIN16_F3, float, 3 );
FFX_MIN16_VECTOR( FFX_MIN16_F4, float, 4 );
FFX_MIN16_SCALAR( FFX_MIN16_I, int );
FFX_MIN16_VECTOR( FFX_MIN16_I2, int, 2 );
FFX_MIN16_VECTOR( FFX_MIN16_I3, int, 3 );
FFX_MIN16_VECTOR( FFX_MIN16_I4, int, 4 );
FFX_MIN16_SCALAR( FFX_MIN16_U, uint );
FFX_MIN16_VECTOR( FFX_MIN16_U2, uint, 2 );
FFX_MIN16_VECTOR( FFX_MIN16_U3, uint, 3 );
FFX_MIN16_VECTOR( FFX_MIN16_U4, uint, 4 );
FFX_16BIT_SCALAR( FFX_F16_t , float );
FFX_16BIT_VECTOR( FFX_F16_t2, float, 2 );
FFX_16BIT_VECTOR( FFX_F16_t3, float, 3 );
FFX_16BIT_VECTOR( FFX_F16_t4, float, 4 );
FFX_16BIT_SCALAR( FFX_I16_t, int );
FFX_16BIT_VECTOR( FFX_I16_t2, int, 2 );
FFX_16BIT_VECTOR( FFX_I16_t3, int, 3 );
FFX_16BIT_VECTOR( FFX_I16_t4, int, 4 );
FFX_16BIT_SCALAR( FFX_U16_t, uint );
FFX_16BIT_VECTOR( FFX_U16_t2, uint, 2 );
FFX_16BIT_VECTOR( FFX_U16_t3, uint, 3 );
FFX_16BIT_VECTOR( FFX_U16_t4, uint, 4 );
#define TYPEDEF_MIN16_TYPES(Prefix) \
typedef FFX_MIN16_F Prefix##_F; \
typedef FFX_MIN16_F2 Prefix##_F2; \
typedef FFX_MIN16_F3 Prefix##_F3; \
typedef FFX_MIN16_F4 Prefix##_F4; \
typedef FFX_MIN16_I Prefix##_I; \
typedef FFX_MIN16_I2 Prefix##_I2; \
typedef FFX_MIN16_I3 Prefix##_I3; \
typedef FFX_MIN16_I4 Prefix##_I4; \
typedef FFX_MIN16_U Prefix##_U; \
typedef FFX_MIN16_U2 Prefix##_U2; \
typedef FFX_MIN16_U3 Prefix##_U3; \
typedef FFX_MIN16_U4 Prefix##_U4;
#define TYPEDEF_16BIT_TYPES(Prefix) \
typedef FFX_16BIT_F Prefix##_F; \
typedef FFX_16BIT_F2 Prefix##_F2; \
typedef FFX_16BIT_F3 Prefix##_F3; \
typedef FFX_16BIT_F4 Prefix##_F4; \
typedef FFX_16BIT_I Prefix##_I; \
typedef FFX_16BIT_I2 Prefix##_I2; \
typedef FFX_16BIT_I3 Prefix##_I3; \
typedef FFX_16BIT_I4 Prefix##_I4; \
typedef FFX_16BIT_U Prefix##_U; \
typedef FFX_16BIT_U2 Prefix##_U2; \
typedef FFX_16BIT_U3 Prefix##_U3; \
typedef FFX_16BIT_U4 Prefix##_U4;
#define TYPEDEF_FULL_PRECISION_TYPES(Prefix) \
typedef FfxFloat32 Prefix##_F; \
typedef FfxFloat32x2 Prefix##_F2; \
typedef FfxFloat32x3 Prefix##_F3; \
typedef FfxFloat32x4 Prefix##_F4; \
typedef FfxInt32 Prefix##_I; \
typedef FfxInt32x2 Prefix##_I2; \
typedef FfxInt32x3 Prefix##_I3; \
typedef FfxInt32x4 Prefix##_I4; \
typedef FfxUInt32 Prefix##_U; \
typedef FfxUInt32x2 Prefix##_U2; \
typedef FfxUInt32x3 Prefix##_U3; \
typedef FfxUInt32x4 Prefix##_U4;
#endif // #if defined(FFX_HLSL)
#if defined(SHADER_API_PSSL)
#define unorm
#define globallycoherent
#if FFX_HALF
#define FFX_MIN16_F half
#define FFX_MIN16_F2 half2
#define FFX_MIN16_F3 half3
#define FFX_MIN16_F4 half4
#define FFX_MIN16_I short
#define FFX_MIN16_I2 short2
#define FFX_MIN16_I3 short3
#define FFX_MIN16_I4 short4
#define FFX_MIN16_U ushort
#define FFX_MIN16_U2 ushort2
#define FFX_MIN16_U3 ushort3
#define FFX_MIN16_U4 ushort4
#define FFX_16BIT_F half
#define FFX_16BIT_F2 half2
#define FFX_16BIT_F3 half3
#define FFX_16BIT_F4 half4
#define FFX_16BIT_I short
#define FFX_16BIT_I2 short2
#define FFX_16BIT_I3 short3
#define FFX_16BIT_I4 short4
#define FFX_16BIT_U ushort
#define FFX_16BIT_U2 ushort2
#define FFX_16BIT_U3 ushort3
#define FFX_16BIT_U4 ushort4
#else // FFX_HALF
#define FFX_MIN16_F float
#define FFX_MIN16_F2 float2
#define FFX_MIN16_F3 float3
#define FFX_MIN16_F4 float4
#define FFX_MIN16_I int
#define FFX_MIN16_I2 int2
#define FFX_MIN16_I3 int3
#define FFX_MIN16_I4 int4
#define FFX_MIN16_U uint
#define FFX_MIN16_U2 uint2
#define FFX_MIN16_U3 uint3
#define FFX_MIN16_U4 uint4
#define FFX_16BIT_F float
#define FFX_16BIT_F2 float2
#define FFX_16BIT_F3 float3
#define FFX_16BIT_F4 float4
#define FFX_16BIT_I int
#define FFX_16BIT_I2 int2
#define FFX_16BIT_I3 int3
#define FFX_16BIT_I4 int4
#define FFX_16BIT_U uint
#define FFX_16BIT_U2 uint2
#define FFX_16BIT_U3 uint3
#define FFX_16BIT_U4 uint4
#endif // FFX_HALF
#endif // #if defined(SHADER_API_PSSL)
#if defined(FFX_GLSL)
#if FFX_HALF
#define FFX_MIN16_F float16_t
#define FFX_MIN16_F2 f16vec2
#define FFX_MIN16_F3 f16vec3
#define FFX_MIN16_F4 f16vec4
#define FFX_MIN16_I int16_t
#define FFX_MIN16_I2 i16vec2
#define FFX_MIN16_I3 i16vec3
#define FFX_MIN16_I4 i16vec4
#define FFX_MIN16_U uint16_t
#define FFX_MIN16_U2 u16vec2
#define FFX_MIN16_U3 u16vec3
#define FFX_MIN16_U4 u16vec4
#define FFX_16BIT_F float16_t
#define FFX_16BIT_F2 f16vec2
#define FFX_16BIT_F3 f16vec3
#define FFX_16BIT_F4 f16vec4
#define FFX_16BIT_I int16_t
#define FFX_16BIT_I2 i16vec2
#define FFX_16BIT_I3 i16vec3
#define FFX_16BIT_I4 i16vec4
#define FFX_16BIT_U uint16_t
#define FFX_16BIT_U2 u16vec2
#define FFX_16BIT_U3 u16vec3
#define FFX_16BIT_U4 u16vec4
#else // FFX_HALF
#define FFX_MIN16_F float
#define FFX_MIN16_F2 vec2
#define FFX_MIN16_F3 vec3
#define FFX_MIN16_F4 vec4
#define FFX_MIN16_I int
#define FFX_MIN16_I2 ivec2
#define FFX_MIN16_I3 ivec3
#define FFX_MIN16_I4 ivec4
#define FFX_MIN16_U uint
#define FFX_MIN16_U2 uvec2
#define FFX_MIN16_U3 uvec3
#define FFX_MIN16_U4 uvec4
#define FFX_16BIT_F float
#define FFX_16BIT_F2 vec2
#define FFX_16BIT_F3 vec3
#define FFX_16BIT_F4 vec4
#define FFX_16BIT_I int
#define FFX_16BIT_I2 ivec2
#define FFX_16BIT_I3 ivec3
#define FFX_16BIT_I4 ivec4
#define FFX_16BIT_U uint
#define FFX_16BIT_U2 uvec2
#define FFX_16BIT_U3 uvec3
#define FFX_16BIT_U4 uvec4
#endif // FFX_HALF
#endif // #if defined(FFX_GLSL)
#endif // #if defined(FFX_GPU)
#endif // #ifndef FFX_COMMON_TYPES_H

60
Shaders/shaders/ffx_common_types.h.meta

@ -0,0 +1,60 @@
fileFormatVersion: 2
guid: ec0f8c94ee9930b438b99b82735d181b
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude Editor: 1
Exclude GameCoreScarlett: 1
Exclude GameCoreXboxOne: 1
Exclude Linux64: 1
Exclude OSXUniversal: 1
Exclude PS4: 1
Exclude PS5: 1
Exclude WebGL: 1
Exclude Win: 1
Exclude Win64: 1
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
Standalone: Linux64
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win64
second:
enabled: 0
settings:
CPU: None
userData:
assetBundleName:
assetBundleVariant:

80
Shaders/shaders/ffx_core.h

@ -0,0 +1,80 @@
// This file is part of the FidelityFX SDK.
//
// Copyright (C) 2024 Advanced Micro Devices, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
/// @defgroup FfxGPU GPU
/// The FidelityFX SDK GPU References
///
/// @ingroup ffxSDK
/// @defgroup FfxHLSL HLSL References
/// FidelityFX SDK HLSL GPU References
///
/// @ingroup FfxGPU
/// @defgroup FfxGLSL GLSL References
/// FidelityFX SDK GLSL GPU References
///
/// @ingroup FfxGPU
/// @defgroup FfxGPUEffects FidelityFX GPU References
/// FidelityFX Effect GPU Reference Documentation
///
/// @ingroup FfxGPU
/// @defgroup GPUCore GPU Core
/// GPU defines and functions
///
/// @ingroup FfxGPU
#if !defined(FFX_CORE_H)
#define FFX_CORE_H
#ifdef __hlsl_dx_compiler
#pragma dxc diagnostic push
#pragma dxc diagnostic ignored "-Wambig-lit-shift"
#endif //__hlsl_dx_compiler
#include "ffx_common_types.h"
#if defined(FFX_CPU)
#include "ffx_core_cpu.h"
#endif // #if defined(FFX_CPU)
#if defined(FFX_GLSL) && defined(FFX_GPU)
#include "ffx_core_glsl.h"
#endif // #if defined(FFX_GLSL) && defined(FFX_GPU)
#if defined(FFX_HLSL) && defined(FFX_GPU)
#include "ffx_core_hlsl.h"
#endif // #if defined(FFX_HLSL) && defined(FFX_GPU)
#if defined(FFX_GPU)
#include "ffx_core_gpu_common.h"
#include "ffx_core_gpu_common_half.h"
#include "ffx_core_portability.h"
#endif // #if defined(FFX_GPU)
#ifdef __hlsl_dx_compiler
#pragma dxc diagnostic pop
#endif //__hlsl_dx_compiler
#endif // #if !defined(FFX_CORE_H)

60
Shaders/shaders/ffx_core.h.meta

@ -0,0 +1,60 @@
fileFormatVersion: 2
guid: 223ad96bb47790e4d8658dd82ba950f3
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude Editor: 1
Exclude GameCoreScarlett: 1
Exclude GameCoreXboxOne: 1
Exclude Linux64: 1
Exclude OSXUniversal: 1
Exclude PS4: 1
Exclude PS5: 1
Exclude WebGL: 1
Exclude Win: 1
Exclude Win64: 1
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
Standalone: Linux64
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win64
second:
enabled: 0
settings:
CPU: None
userData:
assetBundleName:
assetBundleVariant:

2736
Shaders/shaders/ffx_core_gpu_common.h
File diff suppressed because it is too large
View File

60
Shaders/shaders/ffx_core_gpu_common.h.meta

@ -0,0 +1,60 @@
fileFormatVersion: 2
guid: 4950d6c78609df549a0ed96137bf3bf1
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude Editor: 1
Exclude GameCoreScarlett: 1
Exclude GameCoreXboxOne: 1
Exclude Linux64: 1
Exclude OSXUniversal: 1
Exclude PS4: 1
Exclude PS5: 1
Exclude WebGL: 1
Exclude Win: 1
Exclude Win64: 1
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
Standalone: Linux64
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win64
second:
enabled: 0
settings:
CPU: None
userData:
assetBundleName:
assetBundleVariant:

2981
Shaders/shaders/ffx_core_gpu_common_half.h
File diff suppressed because it is too large
View File

60
Shaders/shaders/ffx_core_gpu_common_half.h.meta

@ -0,0 +1,60 @@
fileFormatVersion: 2
guid: 93c5f50cadb9ff14cbf03fa7cb1de897
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude Editor: 1
Exclude GameCoreScarlett: 1
Exclude GameCoreXboxOne: 1
Exclude Linux64: 1
Exclude OSXUniversal: 1
Exclude PS4: 1
Exclude PS5: 1
Exclude WebGL: 1
Exclude Win: 1
Exclude Win64: 1
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
Standalone: Linux64
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win64
second:
enabled: 0
settings:
CPU: None
userData:
assetBundleName:
assetBundleVariant:

1898
Shaders/shaders/ffx_core_hlsl.h
File diff suppressed because it is too large
View File

60
Shaders/shaders/ffx_core_hlsl.h.meta

@ -0,0 +1,60 @@
fileFormatVersion: 2
guid: 47a04cb434355164b8da169fbd474688
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude Editor: 1
Exclude GameCoreScarlett: 1
Exclude GameCoreXboxOne: 1
Exclude Linux64: 1
Exclude OSXUniversal: 1
Exclude PS4: 1
Exclude PS5: 1
Exclude WebGL: 1
Exclude Win: 1
Exclude Win64: 1
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
Standalone: Linux64
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win64
second:
enabled: 0
settings:
CPU: None
userData:
assetBundleName:
assetBundleVariant:

46
Shaders/shaders/ffx_core_portability.h

@ -0,0 +1,46 @@
// This file is part of the FidelityFX SDK.
//
// Copyright (C) 2024 Advanced Micro Devices, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
void ffxOpAAddOneF3(FFX_PARAMETER_OUT FfxFloat32x3 d, FfxFloat32x3 a, FfxFloat32 b)
{
d = a + ffxBroadcast3(b);
}
void ffxOpACpyF3(FFX_PARAMETER_OUT FfxFloat32x3 d, FfxFloat32x3 a)
{
d = a;
}
void ffxOpAMulF3(FFX_PARAMETER_OUT FfxFloat32x3 d, FfxFloat32x3 a, FfxFloat32x3 b)
{
d = a * b;
}
void ffxOpAMulOneF3(FFX_PARAMETER_OUT FfxFloat32x3 d, FfxFloat32x3 a, FfxFloat32 b)
{
d = a * b;
}
void ffxOpARcpF3(FFX_PARAMETER_OUT FfxFloat32x3 d, FfxFloat32x3 a)
{
d = ffxReciprocal(a);
}

60
Shaders/shaders/ffx_core_portability.h.meta

@ -0,0 +1,60 @@
fileFormatVersion: 2
guid: 9dc8a5ba90431934588adf0dabbf0cdd
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude Editor: 1
Exclude GameCoreScarlett: 1
Exclude GameCoreXboxOne: 1
Exclude Linux64: 1
Exclude OSXUniversal: 1
Exclude PS4: 1
Exclude PS5: 1
Exclude WebGL: 1
Exclude Win: 1
Exclude Win64: 1
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
Standalone: Linux64
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win64
second:
enabled: 0
settings:
CPU: None
userData:
assetBundleName:
assetBundleVariant:

79
Shaders/shaders/ffx_fsr2_accumulate_pass.hlsl

@ -0,0 +1,79 @@
// This file is part of the FidelityFX SDK.
//
// Copyright (C) 2024 Advanced Micro Devices, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#define FSR2_BIND_SRV_INPUT_EXPOSURE 0
#define FSR2_BIND_SRV_DILATED_REACTIVE_MASKS 1
#if FFX_FSR2_OPTION_LOW_RESOLUTION_MOTION_VECTORS
#define FSR2_BIND_SRV_DILATED_MOTION_VECTORS 2
#else
#define FSR2_BIND_SRV_INPUT_MOTION_VECTORS 2
#endif
#define FSR2_BIND_SRV_INTERNAL_UPSCALED 3
#define FSR2_BIND_SRV_LOCK_STATUS 4
#define FSR2_BIND_SRV_PREPARED_INPUT_COLOR 5
#define FSR2_BIND_SRV_LANCZOS_LUT 6
#define FSR2_BIND_SRV_UPSCALE_MAXIMUM_BIAS_LUT 7
#define FSR2_BIND_SRV_SCENE_LUMINANCE_MIPS 8
#define FSR2_BIND_SRV_AUTO_EXPOSURE 9
#define FSR2_BIND_SRV_LUMA_HISTORY 10
#define FSR2_BIND_UAV_INTERNAL_UPSCALED 0
#define FSR2_BIND_UAV_LOCK_STATUS 1
#define FSR2_BIND_UAV_UPSCALED_OUTPUT 2
#define FSR2_BIND_UAV_NEW_LOCKS 3
#define FSR2_BIND_UAV_LUMA_HISTORY 4
#define FSR2_BIND_CB_FSR2 0
#include "fsr2/ffx_fsr2_callbacks_hlsl.h"
#include "fsr2/ffx_fsr2_common.h"
#include "fsr2/ffx_fsr2_sample.h"
#include "fsr2/ffx_fsr2_upsample.h"
#include "fsr2/ffx_fsr2_postprocess_lock_status.h"
#include "fsr2/ffx_fsr2_reproject.h"
#include "fsr2/ffx_fsr2_accumulate.h"
#ifndef FFX_FSR2_THREAD_GROUP_WIDTH
#define FFX_FSR2_THREAD_GROUP_WIDTH 8
#endif // #ifndef FFX_FSR2_THREAD_GROUP_WIDTH
#ifndef FFX_FSR2_THREAD_GROUP_HEIGHT
#define FFX_FSR2_THREAD_GROUP_HEIGHT 8
#endif // FFX_FSR2_THREAD_GROUP_HEIGHT
#ifndef FFX_FSR2_THREAD_GROUP_DEPTH
#define FFX_FSR2_THREAD_GROUP_DEPTH 1
#endif // #ifndef FFX_FSR2_THREAD_GROUP_DEPTH
#ifndef FFX_FSR2_NUM_THREADS
#define FFX_FSR2_NUM_THREADS [numthreads(FFX_FSR2_THREAD_GROUP_WIDTH, FFX_FSR2_THREAD_GROUP_HEIGHT, FFX_FSR2_THREAD_GROUP_DEPTH)]
#endif // #ifndef FFX_FSR2_NUM_THREADS
FFX_PREFER_WAVE64
FFX_FSR2_NUM_THREADS
FFX_FSR2_EMBED_ROOTSIG_CONTENT
void CS(uint2 uGroupId : SV_GroupID, uint2 uGroupThreadId : SV_GroupThreadID)
{
const uint GroupRows = (uint(DisplaySize().y) + FFX_FSR2_THREAD_GROUP_HEIGHT - 1) / FFX_FSR2_THREAD_GROUP_HEIGHT;
uGroupId.y = GroupRows - uGroupId.y - 1;
uint2 uDispatchThreadId = uGroupId * uint2(FFX_FSR2_THREAD_GROUP_WIDTH, FFX_FSR2_THREAD_GROUP_HEIGHT) + uGroupThreadId;
Accumulate(uDispatchThreadId);
}

7
Shaders/shaders/ffx_fsr2_accumulate_pass.hlsl.meta

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 2587b11e2d882c649ac7fd1a51f6dc8c
ShaderIncludeImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

78
Shaders/shaders/ffx_fsr2_autogen_reactive_pass.hlsl

@ -0,0 +1,78 @@
// This file is part of the FidelityFX SDK.
//
// Copyright (C) 2024 Advanced Micro Devices, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#define FSR2_BIND_SRV_INPUT_OPAQUE_ONLY 0
#define FSR2_BIND_SRV_INPUT_COLOR 1
#define FSR2_BIND_UAV_AUTOREACTIVE 0
#define FSR2_BIND_CB_FSR2 0
#define FSR2_BIND_CB_REACTIVE 1
#include "fsr2/ffx_fsr2_callbacks_hlsl.h"
#include "fsr2/ffx_fsr2_common.h"
#ifndef FFX_FSR2_THREAD_GROUP_WIDTH
#define FFX_FSR2_THREAD_GROUP_WIDTH 8
#endif // #ifndef FFX_FSR2_THREAD_GROUP_WIDTH
#ifndef FFX_FSR2_THREAD_GROUP_HEIGHT
#define FFX_FSR2_THREAD_GROUP_HEIGHT 8
#endif // FFX_FSR2_THREAD_GROUP_HEIGHT
#ifndef FFX_FSR2_THREAD_GROUP_DEPTH
#define FFX_FSR2_THREAD_GROUP_DEPTH 1
#endif // #ifndef FFX_FSR2_THREAD_GROUP_DEPTH
#ifndef FFX_FSR2_NUM_THREADS
#define FFX_FSR2_NUM_THREADS [numthreads(FFX_FSR2_THREAD_GROUP_WIDTH, FFX_FSR2_THREAD_GROUP_HEIGHT, FFX_FSR2_THREAD_GROUP_DEPTH)]
#endif // #ifndef FFX_FSR2_NUM_THREADS
FFX_PREFER_WAVE64
FFX_FSR2_NUM_THREADS
FFX_FSR2_EMBED_ROOTSIG_REACTIVE_CONTENT
void CS(uint2 uGroupId : SV_GroupID, uint2 uGroupThreadId : SV_GroupThreadID)
{
uint2 uDispatchThreadId = uGroupId * uint2(FFX_FSR2_THREAD_GROUP_WIDTH, FFX_FSR2_THREAD_GROUP_HEIGHT) + uGroupThreadId;
float3 ColorPreAlpha = LoadOpaqueOnly( FFX_MIN16_I2(uDispatchThreadId) ).rgb;
float3 ColorPostAlpha = LoadInputColor(uDispatchThreadId).rgb;
if (GenReactiveFlags() & FFX_FSR2_AUTOREACTIVEFLAGS_APPLY_TONEMAP)
{
ColorPreAlpha = Tonemap(ColorPreAlpha);
ColorPostAlpha = Tonemap(ColorPostAlpha);
}
if (GenReactiveFlags() & FFX_FSR2_AUTOREACTIVEFLAGS_APPLY_INVERSETONEMAP)
{
ColorPreAlpha = InverseTonemap(ColorPreAlpha);
ColorPostAlpha = InverseTonemap(ColorPostAlpha);
}
float out_reactive_value = 0.f;
float3 delta = abs(ColorPostAlpha - ColorPreAlpha);
out_reactive_value = (GenReactiveFlags() & FFX_FSR2_AUTOREACTIVEFLAGS_USE_COMPONENTS_MAX) ? max(delta.x, max(delta.y, delta.z)) : length(delta);
out_reactive_value *= GenReactiveScale();
out_reactive_value = (GenReactiveFlags() & FFX_FSR2_AUTOREACTIVEFLAGS_APPLY_THRESHOLD) ? (out_reactive_value < GenReactiveThreshold() ? 0 : GenReactiveBinaryValue()) : out_reactive_value;
rw_output_autoreactive[uDispatchThreadId] = out_reactive_value;
}

7
Shaders/shaders/ffx_fsr2_autogen_reactive_pass.hlsl.meta

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 15c74efa821aaf3429f92b8d5d9901d5
ShaderIncludeImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

56
Shaders/shaders/ffx_fsr2_compute_luminance_pyramid_pass.hlsl

@ -0,0 +1,56 @@
// This file is part of the FidelityFX SDK.
//
// Copyright (C) 2024 Advanced Micro Devices, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#define FSR2_BIND_SRV_INPUT_COLOR 0
#define FSR2_BIND_UAV_SPD_GLOBAL_ATOMIC 0
#define FSR2_BIND_UAV_EXPOSURE_MIP_LUMA_CHANGE 1
#define FSR2_BIND_UAV_EXPOSURE_MIP_5 2
#define FSR2_BIND_UAV_AUTO_EXPOSURE 3
#define FSR2_BIND_CB_FSR2 0
#define FSR2_BIND_CB_SPD 1
#include "fsr2/ffx_fsr2_callbacks_hlsl.h"
#include "fsr2/ffx_fsr2_common.h"
#include "fsr2/ffx_fsr2_compute_luminance_pyramid.h"
#ifndef FFX_FSR2_THREAD_GROUP_WIDTH
#define FFX_FSR2_THREAD_GROUP_WIDTH 256
#endif // #ifndef FFX_FSR2_THREAD_GROUP_WIDTH
#ifndef FFX_FSR2_THREAD_GROUP_HEIGHT
#define FFX_FSR2_THREAD_GROUP_HEIGHT 1
#endif // #ifndef FFX_FSR2_THREAD_GROUP_HEIGHT
#ifndef FFX_FSR2_THREAD_GROUP_DEPTH
#define FFX_FSR2_THREAD_GROUP_DEPTH 1
#endif // #ifndef FFX_FSR2_THREAD_GROUP_DEPTH
#ifndef FFX_FSR2_NUM_THREADS
#define FFX_FSR2_NUM_THREADS [numthreads(FFX_FSR2_THREAD_GROUP_WIDTH, FFX_FSR2_THREAD_GROUP_HEIGHT, FFX_FSR2_THREAD_GROUP_DEPTH)]
#endif // #ifndef FFX_FSR2_NUM_THREADS
FFX_PREFER_WAVE64
FFX_FSR2_NUM_THREADS
FFX_FSR2_EMBED_CB2_ROOTSIG_CONTENT
void CS(uint3 WorkGroupId : SV_GroupID, uint LocalThreadIndex : SV_GroupIndex)
{
ComputeAutoExposure(WorkGroupId, LocalThreadIndex);
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save