From d3f60e2650e5018374f35f86140e97fe9ce637f9 Mon Sep 17 00:00:00 2001 From: Nico de Poel Date: Thu, 20 Mar 2025 22:10:54 +0100 Subject: [PATCH] Added ASR runtime source files, as a copy of the FSR2 sources, with a bunch of renaming and stripped of some parts that we know we're not going to need. --- .../Effects/Upscaling/ASR/Runtime.meta | 8 + .../Effects/Upscaling/ASR/Runtime/Asr.cs | 292 +++++++++ .../Effects/Upscaling/ASR/Runtime/Asr.cs.meta | 11 + .../Upscaling/ASR/Runtime/AsrAssets.cs | 152 +++++ .../Upscaling/ASR/Runtime/AsrAssets.cs.meta | 11 + .../Upscaling/ASR/Runtime/AsrCallbacks.cs | 81 +++ .../ASR/Runtime/AsrCallbacks.cs.meta | 11 + .../Upscaling/ASR/Runtime/AsrContext.cs | 570 ++++++++++++++++++ .../Upscaling/ASR/Runtime/AsrContext.cs.meta | 11 + .../Effects/Upscaling/ASR/Runtime/AsrPass.cs | 339 +++++++++++ .../Upscaling/ASR/Runtime/AsrPass.cs.meta | 11 + .../Upscaling/ASR/Runtime/AsrResources.cs | 227 +++++++ .../ASR/Runtime/AsrResources.cs.meta | 11 + .../Upscaling/ASR/Runtime/AsrShaderIDs.cs | 75 +++ .../ASR/Runtime/AsrShaderIDs.cs.meta | 11 + .../Upscaling/ASR/Runtime/ResourceView.cs | 55 ++ .../ASR/Runtime/ResourceView.cs.meta | 11 + 17 files changed, 1887 insertions(+) create mode 100644 Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime.meta create mode 100644 Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/Asr.cs create mode 100644 Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/Asr.cs.meta create mode 100644 Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrAssets.cs create mode 100644 Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrAssets.cs.meta create mode 100644 Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrCallbacks.cs create mode 100644 Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrCallbacks.cs.meta create mode 100644 Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrContext.cs create mode 100644 Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrContext.cs.meta create mode 100644 Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrPass.cs create mode 100644 Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrPass.cs.meta create mode 100644 Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrResources.cs create mode 100644 Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrResources.cs.meta create mode 100644 Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrShaderIDs.cs create mode 100644 Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrShaderIDs.cs.meta create mode 100644 Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/ResourceView.cs create mode 100644 Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/ResourceView.cs.meta diff --git a/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime.meta b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime.meta new file mode 100644 index 0000000..3e15b23 --- /dev/null +++ b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6bbfbdd9fd482bd4ea5e998953ae9972 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/Asr.cs b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/Asr.cs new file mode 100644 index 0000000..a75fab0 --- /dev/null +++ b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/Asr.cs @@ -0,0 +1,292 @@ +// 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; + +namespace ArmASR +{ + /// + /// A collection of helper functions and data structures required by the ASR process. + /// + public static class Asr + { + /// + /// Creates a new ASR context with standard parameters that are appropriate for the current platform. + /// + public static AsrContext CreateContext(Vector2Int displaySize, Vector2Int maxRenderSize, AsrShaders 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 Arm ASR 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 AsrContext(); + 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, + } + + /// + /// A structure encapsulating the parameters required to initialize FidelityFX Super Resolution 2 upscaling. + /// + public struct ContextDescription + { + public InitializationFlags Flags; + public Vector2Int MaxRenderSize; + public Vector2Int DisplaySize; + public AsrShaders Shaders; + } + + /// + /// A structure encapsulating the parameters for dispatching the various passes of FidelityFX Super Resolution 2. + /// + 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; + public bool UseTextureArrays; // Enable texture array bindings, primarily used for HDRP and XR + } + + /// + /// A structure encapsulating the parameters for automatic generation of a reactive mask. + /// + 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; + } + } +} diff --git a/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/Asr.cs.meta b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/Asr.cs.meta new file mode 100644 index 0000000..e36c358 --- /dev/null +++ b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/Asr.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c7350363c6d8a2b4096a9ed97dc4ed95 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrAssets.cs b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrAssets.cs new file mode 100644 index 0000000..95ff401 --- /dev/null +++ b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrAssets.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 ArmASR +{ + /// + /// Scriptable object containing all shader resources required by Arm Accuracy Super Resolution (ASR). + /// 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. + /// + [CreateAssetMenu(fileName = "ASR Assets", menuName = "ARM/ASR Assets", order = 1102)] + public class AsrAssets : ScriptableObject + { + public AsrShaders shaders; + +#if UNITY_EDITOR + private void Reset() + { + shaders = new AsrShaders + { + computeLuminancePyramidPass = FindComputeShader("ffxm_fsr2_compute_luminance_pyramid_pass"), + reconstructPreviousDepthPass = FindComputeShader("ffx_fsr2_reconstruct_previous_depth_pass"), + depthClipPass = FindComputeShader("ffx_fsr2_depth_clip_pass"), + lockPass = FindComputeShader("ffxm_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(assetPath); + } +#endif + } + + /// + /// All the compute shaders used by ASR. + /// + [System.Serializable] + public class AsrShaders + { + /// + /// The compute shader used by the luminance pyramid computation pass. + /// + public ComputeShader computeLuminancePyramidPass; + + /// + /// The compute shader used by the previous depth reconstruction pass. + /// + public ComputeShader reconstructPreviousDepthPass; + + /// + /// The compute shader used by the depth clip pass. + /// + public ComputeShader depthClipPass; + + /// + /// The compute shader used by the lock pass. + /// + public ComputeShader lockPass; + + /// + /// The compute shader used by the accumulation pass. + /// + public ComputeShader accumulatePass; + + /// + /// The compute shader used by the RCAS sharpening pass. + /// + public ComputeShader sharpenPass; + + /// + /// The compute shader used to auto-generate a reactive mask. + /// + public ComputeShader autoGenReactivePass; + + /// + /// The compute shader used to auto-generate a transparency & composition mask. + /// + public ComputeShader tcrAutoGenPass; + + /// + /// Returns a copy of this class and its contents. + /// + public AsrShaders Clone() + { + return (AsrShaders)MemberwiseClone(); + } + + /// + /// Returns a copy of this class with clones of all its shaders. + /// This can be useful if you're running multiple ASR instances with different shader configurations. + /// Be sure to clean up these clones through Dispose once you're done with them. + /// + public AsrShaders DeepCopy() + { + return new AsrShaders + { + 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), + }; + } + + /// + /// Destroy all the shaders within this instance. + /// Use this only on clones created through DeepCopy. + /// + 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); + } + } +} diff --git a/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrAssets.cs.meta b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrAssets.cs.meta new file mode 100644 index 0000000..022b8ab --- /dev/null +++ b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrAssets.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7a41695239eb36740847744b34c5af43 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrCallbacks.cs b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrCallbacks.cs new file mode 100644 index 0000000..50fe7a6 --- /dev/null +++ b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrCallbacks.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 ArmASR +{ + /// + /// A collection of callbacks required by the ASR process. + /// This allows some customization by the game dev on how to integrate ASR upscaling into their own game setup. + /// + public interface IAsrCallbacks + { + /// + /// 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. + /// + void ApplyMipmapBias(float biasOffset); + + void UndoMipmapBias(); + } + + /// + /// Default implementation of IAsrCallbacks. + /// These are fine for testing but a proper game will want to extend and override these methods. + /// + public class AsrCallbacksBase: IAsrCallbacks + { + 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()) + { + if (texture.mipmapCount <= 1) + continue; + + texture.mipMapBias += biasOffset; + } + } + + public virtual void UndoMipmapBias() + { + if (CurrentBiasOffset == 0f) + return; + + ApplyMipmapBias(-CurrentBiasOffset); + } + } +} diff --git a/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrCallbacks.cs.meta b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrCallbacks.cs.meta new file mode 100644 index 0000000..2724280 --- /dev/null +++ b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrCallbacks.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 78f16fcb80e6325429dfa567a4ed5d4a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrContext.cs b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrContext.cs new file mode 100644 index 0000000..245a87b --- /dev/null +++ b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrContext.cs @@ -0,0 +1,570 @@ +// 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 ArmASR +{ + /// + /// This class loosely matches the FfxFsr2Context struct from the original FSR2 codebase. + /// It manages the various resources and compute passes required by the ASR 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. + /// + public class AsrContext + { + private const int MaxQueuedFrames = 16; + + private Asr.ContextDescription _contextDescription; + private CommandBuffer _commandBuffer; + + private AsrPass _computeLuminancePyramidPass; + private AsrPass _reconstructPreviousDepthPass; + private AsrPass _depthClipPass; + private AsrPass _lockPass; + private AsrPass _accumulatePass; + private AsrPass _sharpenPass; + private AsrPass _generateReactivePass; + private AsrPass _tcrAutogeneratePass; + + private readonly AsrResources _resources = new AsrResources(); + + private ComputeBuffer _upscalerConstantsBuffer; + private readonly Asr.UpscalerConstants[] _upscalerConstantsArray = { new Asr.UpscalerConstants() }; + private ref Asr.UpscalerConstants UpscalerConsts => ref _upscalerConstantsArray[0]; + + private ComputeBuffer _spdConstantsBuffer; + private readonly Asr.SpdConstants[] _spdConstantsArray = { new Asr.SpdConstants() }; + private ref Asr.SpdConstants SpdConsts => ref _spdConstantsArray[0]; + + private ComputeBuffer _rcasConstantsBuffer; + private readonly Asr.RcasConstants[] _rcasConstantsArray = new Asr.RcasConstants[1]; + private ref Asr.RcasConstants RcasConsts => ref _rcasConstantsArray[0]; + + private ComputeBuffer _generateReactiveConstantsBuffer; + private readonly Asr.GenerateReactiveConstants[] _generateReactiveConstantsArray = { new Asr.GenerateReactiveConstants() }; + private ref Asr.GenerateReactiveConstants GenReactiveConsts => ref _generateReactiveConstantsArray[0]; + + private bool _firstExecution; + private Vector2 _previousJitterOffset; + private int _resourceFrameIndex; + + public void Create(Asr.ContextDescription contextDescription) + { + _contextDescription = contextDescription; + _commandBuffer = new CommandBuffer { name = "Arm ASR" }; + + _upscalerConstantsBuffer = CreateConstantBuffer(); + _spdConstantsBuffer = CreateConstantBuffer(); + _rcasConstantsBuffer = CreateConstantBuffer(); + _generateReactiveConstantsBuffer = CreateConstantBuffer(); + + // Set defaults + _firstExecution = true; + _resourceFrameIndex = 0; + + UpscalerConsts.displaySize = _contextDescription.DisplaySize; + + _resources.Create(_contextDescription); + CreatePasses(); + } + + private void CreatePasses() + { + _computeLuminancePyramidPass = new AsrComputeLuminancePyramidPass(_contextDescription, _resources, _upscalerConstantsBuffer, _spdConstantsBuffer); + _reconstructPreviousDepthPass = new AsrReconstructPreviousDepthPass(_contextDescription, _resources, _upscalerConstantsBuffer); + _depthClipPass = new AsrDepthClipPass(_contextDescription, _resources, _upscalerConstantsBuffer); + _lockPass = new AsrLockPass(_contextDescription, _resources, _upscalerConstantsBuffer); + _accumulatePass = new AsrAccumulatePass(_contextDescription, _resources, _upscalerConstantsBuffer); + _sharpenPass = new AsrSharpenPass(_contextDescription, _resources, _upscalerConstantsBuffer, _rcasConstantsBuffer); + _generateReactivePass = new AsrGenerateReactivePass(_contextDescription, _resources, _generateReactiveConstantsBuffer); + } + + 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 _generateReactiveConstantsBuffer); + DestroyConstantBuffer(ref _rcasConstantsBuffer); + DestroyConstantBuffer(ref _spdConstantsBuffer); + DestroyConstantBuffer(ref _upscalerConstantsBuffer); + + if (_commandBuffer != null) + { + _commandBuffer.Dispose(); + _commandBuffer = null; + } + } + + public void Dispatch(Asr.DispatchDescription dispatchParams) + { + _commandBuffer.Clear(); + Dispatch(dispatchParams, _commandBuffer); + Graphics.ExecuteCommandBuffer(_commandBuffer); + } + + public void Dispatch(Asr.DispatchDescription dispatchParams, CommandBuffer commandBuffer) + { + if ((_contextDescription.Flags & Asr.InitializationFlags.EnableDebugChecking) != 0) + { + DebugCheckDispatch(dispatchParams); + } + + if (dispatchParams.UseTextureArrays) + commandBuffer.EnableShaderKeyword("UNITY_FFXM_TEXTURE2D_X_ARRAY"); + + 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 & Asr.InitializationFlags.EnableAutoExposure) != 0) + dispatchParams.Exposure = new ResourceView(_resources.AutoExposure); + else if (!dispatchParams.Exposure.IsValid) + dispatchParams.Exposure = new ResourceView(_resources.DefaultExposure); + + if (!dispatchParams.Reactive.IsValid) dispatchParams.Reactive = new ResourceView(_resources.DefaultReactive); + if (!dispatchParams.TransparencyAndComposition.IsValid) dispatchParams.TransparencyAndComposition = new ResourceView(_resources.DefaultReactive); + AsrResources.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 & Asr.InitializationFlags.EnableDepthInverted) == Asr.InitializationFlags.EnableDepthInverted; + commandBuffer.SetRenderTarget(AsrShaderIDs.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); + + // 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; + + AsrResources.DestroyAliasableResources(commandBuffer); + + commandBuffer.DisableShaderKeyword("UNITY_FFXM_TEXTURE2D_X_ARRAY"); + } + + public void GenerateReactiveMask(Asr.GenerateReactiveDescription dispatchParams) + { + _commandBuffer.Clear(); + GenerateReactiveMask(dispatchParams, _commandBuffer); + Graphics.ExecuteCommandBuffer(_commandBuffer); + } + + public void GenerateReactiveMask(Asr.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); + + ((AsrGenerateReactivePass)_generateReactivePass).ScheduleDispatch(commandBuffer, dispatchParams, dispatchSrcX, dispatchSrcY); + } + + private void SetupConstants(Asr.DispatchDescription dispatchParams, bool resetAccumulation) + { + ref Asr.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 & Asr.InitializationFlags.EnableDisplayResolutionMotionVectors) != 0 ? constants.displaySize : constants.renderSize; + constants.motionVectorScale = dispatchParams.MotionVectorScale / motionVectorsTargetSize; + + // Compute jitter cancellation + if ((_contextDescription.Flags & Asr.InitializationFlags.EnableMotionVectorsJitterCancellation) != 0) + { + constants.motionVectorJitterCancellation = (_previousJitterOffset - constants.jitterOffset) / motionVectorsTargetSize; + _previousJitterOffset = constants.jitterOffset; + } + + int jitterPhaseCount = Asr.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 = AsrPass.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(Asr.DispatchDescription dispatchParams) + { + bool inverted = (_contextDescription.Flags & Asr.InitializationFlags.EnableDepthInverted) != 0; + bool infinite = (_contextDescription.Flags & Asr.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(Asr.DispatchDescription dispatchParams) + { + int sharpnessIndex = Mathf.RoundToInt(Mathf.Clamp01(dispatchParams.Sharpness) * (RcasConfigs.Length - 1)); + RcasConsts = RcasConfigs[sharpnessIndex]; + } + + private void SetupSpdConstants(Asr.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 Asr.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(Asr.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 & Asr.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 & Asr.InitializationFlags.EnableDepthInfinite) != 0; + bool inverseDepth = (_contextDescription.Flags & Asr.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"); + } + } + + /// + /// The ASR 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. + /// + private static readonly Asr.RcasConstants[] RcasConfigs = new [] + { + new Asr.RcasConstants(1048576000u, 872428544u), + new Asr.RcasConstants(1049178080u, 877212745u), + new Asr.RcasConstants(1049823372u, 882390168u), + new Asr.RcasConstants(1050514979u, 887895276u), + new Asr.RcasConstants(1051256227u, 893859143u), + new Asr.RcasConstants(1052050675u, 900216232u), + new Asr.RcasConstants(1052902144u, 907032080u), + new Asr.RcasConstants(1053814727u, 914306687u), + new Asr.RcasConstants(1054792807u, 922105590u), + new Asr.RcasConstants(1055841087u, 930494326u), + new Asr.RcasConstants(1056964608u, 939538432u), + new Asr.RcasConstants(1057566688u, 944322633u), + new Asr.RcasConstants(1058211980u, 949500056u), + new Asr.RcasConstants(1058903587u, 955005164u), + new Asr.RcasConstants(1059644835u, 960969031u), + new Asr.RcasConstants(1060439283u, 967326120u), + new Asr.RcasConstants(1061290752u, 974141968u), + new Asr.RcasConstants(1062203335u, 981416575u), + new Asr.RcasConstants(1063181415u, 989215478u), + new Asr.RcasConstants(1064229695u, 997604214u), + new Asr.RcasConstants(1065353216u, 1006648320), + }; + + private static ComputeBuffer CreateConstantBuffer() where TConstants: struct + { + return new ComputeBuffer(1, Marshal.SizeOf(), ComputeBufferType.Constant); + } + + private static void DestroyConstantBuffer(ref ComputeBuffer bufferRef) + { + if (bufferRef == null) + return; + + bufferRef.Release(); + bufferRef = null; + } + + private static void DestroyPass(ref AsrPass pass) + { + if (pass == null) + return; + + pass.Dispose(); + pass = null; + } + } +} diff --git a/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrContext.cs.meta b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrContext.cs.meta new file mode 100644 index 0000000..3a18521 --- /dev/null +++ b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrContext.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c348b7c44539db74994c5846caec5871 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrPass.cs b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrPass.cs new file mode 100644 index 0000000..5a76b16 --- /dev/null +++ b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrPass.cs @@ -0,0 +1,339 @@ +// 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.Profiling; +using UnityEngine.Rendering; + +namespace ArmASR +{ + /// + /// Base class for all the compute passes that make up the ASR process. + /// This loosely matches the FfxPipelineState struct from the original ASR 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. + /// + internal abstract class AsrPass: IDisposable + { + internal const int ShadingChangeMipLevel = 4; // This matches the FFXM_FSR2_SHADING_CHANGE_MIP_LEVEL define + + protected readonly Asr.ContextDescription ContextDescription; + protected readonly AsrResources Resources; + protected readonly ComputeBuffer Constants; + + protected ComputeShader ComputeShader; + protected int KernelIndex; + + protected CustomSampler Sampler; + + protected AsrPass(Asr.ContextDescription contextDescription, AsrResources resources, ComputeBuffer constants) + { + ContextDescription = contextDescription; + Resources = resources; + Constants = constants; + } + + public virtual void Dispose() + { + } + + public void ScheduleDispatch(CommandBuffer commandBuffer, Asr.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, Asr.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, Asr.InitializationFlags flags) + { + if (shader == null) + { + throw new MissingReferenceException($"Shader for ASR pass '{passName}' could not be loaded! Please ensure it is included in the project correctly."); + } + + ComputeShader = shader; + KernelIndex = ComputeShader.FindKernel("main"); + 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 & Asr.InitializationFlags.EnableHighDynamicRange) != 0) ComputeShader.EnableKeyword("FFXM_FSR2_OPTION_HDR_COLOR_INPUT"); + if ((flags & Asr.InitializationFlags.EnableDisplayResolutionMotionVectors) == 0) ComputeShader.EnableKeyword("FFXM_FSR2_OPTION_LOW_RESOLUTION_MOTION_VECTORS"); + if ((flags & Asr.InitializationFlags.EnableMotionVectorsJitterCancellation) != 0) ComputeShader.EnableKeyword("FFXM_FSR2_OPTION_JITTERED_MOTION_VECTORS"); + if ((flags & Asr.InitializationFlags.EnableDepthInverted) != 0) ComputeShader.EnableKeyword("FFXM_FSR2_OPTION_INVERTED_DEPTH"); + if (useLut) ComputeShader.EnableKeyword("FFXM_FSR2_OPTION_REPROJECT_USE_LANCZOS_TYPE"); + if ((flags & Asr.InitializationFlags.EnableFP16Usage) != 0) ComputeShader.EnableKeyword("FFXM_HALF"); + } + } + + internal class AsrComputeLuminancePyramidPass : AsrPass + { + private readonly ComputeBuffer _spdConstants; + + public AsrComputeLuminancePyramidPass(Asr.ContextDescription contextDescription, AsrResources resources, ComputeBuffer constants, ComputeBuffer spdConstants) + : base(contextDescription, resources, constants) + { + _spdConstants = spdConstants; + + InitComputeShader("Compute Luminance Pyramid", contextDescription.Shaders.computeLuminancePyramidPass); + } + + protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Asr.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY) + { + ref var color = ref dispatchParams.Color; + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.SrvInputColor, color.RenderTarget, color.MipLevel, color.SubElement); + + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.UavSpdAtomicCount, Resources.SpdAtomicCounter); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.UavExposureMipLumaChange, Resources.SceneLuminance, ShadingChangeMipLevel); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.UavExposureMip5, Resources.SceneLuminance, 5); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.UavAutoExposure, Resources.AutoExposure); + + commandBuffer.SetComputeConstantBufferParam(ComputeShader, AsrShaderIDs.CbFsr2, Constants, 0, Constants.stride); + commandBuffer.SetComputeConstantBufferParam(ComputeShader, AsrShaderIDs.CbSpd, _spdConstants, 0, _spdConstants.stride); + + commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1); + } + } + + internal class AsrReconstructPreviousDepthPass : AsrPass + { + public AsrReconstructPreviousDepthPass(Asr.ContextDescription contextDescription, AsrResources resources, ComputeBuffer constants) + : base(contextDescription, resources, constants) + { + InitComputeShader("Reconstruct & Dilate", contextDescription.Shaders.reconstructPreviousDepthPass); + } + + protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Asr.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, AsrShaderIDs.SrvInputColor, color.RenderTarget, color.MipLevel, color.SubElement); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.SrvInputDepth, depth.RenderTarget, depth.MipLevel, depth.SubElement); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.SrvInputMotionVectors, motionVectors.RenderTarget, motionVectors.MipLevel, motionVectors.SubElement); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.SrvInputExposure, exposure.RenderTarget, exposure.MipLevel, exposure.SubElement); + + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.UavDilatedMotionVectors, Resources.DilatedMotionVectors[frameIndex]); + + commandBuffer.SetComputeConstantBufferParam(ComputeShader, AsrShaderIDs.CbFsr2, Constants, 0, Constants.stride); + + commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1); + } + } + + internal class AsrDepthClipPass : AsrPass + { + public AsrDepthClipPass(Asr.ContextDescription contextDescription, AsrResources resources, ComputeBuffer constants) + : base(contextDescription, resources, constants) + { + InitComputeShader("Depth Clip", contextDescription.Shaders.depthClipPass); + } + + protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Asr.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, AsrShaderIDs.SrvInputColor, color.RenderTarget, color.MipLevel, color.SubElement); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.SrvInputDepth, depth.RenderTarget, depth.MipLevel, depth.SubElement); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.SrvInputMotionVectors, motionVectors.RenderTarget, motionVectors.MipLevel, motionVectors.SubElement); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.SrvInputExposure, exposure.RenderTarget, exposure.MipLevel, exposure.SubElement); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.SrvReactiveMask, reactive.RenderTarget, reactive.MipLevel, reactive.SubElement); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.SrvTransparencyAndCompositionMask, tac.RenderTarget, tac.MipLevel, tac.SubElement); + + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.SrvReconstructedPrevNearestDepth, AsrShaderIDs.UavReconstructedPrevNearestDepth); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.SrvDilatedMotionVectors, Resources.DilatedMotionVectors[frameIndex]); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.SrvDilatedDepth, AsrShaderIDs.UavDilatedDepth); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.SrvPrevDilatedMotionVectors, Resources.DilatedMotionVectors[frameIndex ^ 1]); + + commandBuffer.SetComputeConstantBufferParam(ComputeShader, AsrShaderIDs.CbFsr2, Constants, 0, Constants.stride); + + commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1); + } + } + + internal class AsrLockPass : AsrPass + { + public AsrLockPass(Asr.ContextDescription contextDescription, AsrResources resources, ComputeBuffer constants) + : base(contextDescription, resources, constants) + { + InitComputeShader("Create Locks", contextDescription.Shaders.lockPass); + } + + protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Asr.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY) + { + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.SrvLockInputLuma, AsrShaderIDs.UavLockInputLuma); + commandBuffer.SetComputeConstantBufferParam(ComputeShader, AsrShaderIDs.CbFsr2, Constants, 0, Constants.stride); + + commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1); + } + } + + internal class AsrAccumulatePass : AsrPass + { + private const string SharpeningKeyword = "FFXM_FSR2_OPTION_APPLY_SHARPENING"; + +#if UNITY_2021_2_OR_NEWER + private readonly LocalKeyword _sharpeningKeyword; +#endif + + public AsrAccumulatePass(Asr.ContextDescription contextDescription, AsrResources 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, Asr.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 & Asr.InitializationFlags.EnableDisplayResolutionMotionVectors) == 0) + { + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.SrvDilatedMotionVectors, Resources.DilatedMotionVectors[frameIndex]); + } + else + { + ref var motionVectors = ref dispatchParams.MotionVectors; + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.SrvInputMotionVectors, motionVectors.RenderTarget, motionVectors.MipLevel, motionVectors.SubElement); + } + + ref var exposure = ref dispatchParams.Exposure; + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.SrvInputExposure, exposure.RenderTarget, exposure.MipLevel, exposure.SubElement); + + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.SrvDilatedReactiveMasks, AsrShaderIDs.UavDilatedReactiveMasks); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.SrvInternalUpscaled, Resources.InternalUpscaled[frameIndex ^ 1]); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.SrvLockStatus, Resources.LockStatus[frameIndex ^ 1]); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.SrvPreparedInputColor, AsrShaderIDs.UavPreparedInputColor); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.SrvLanczosLut, Resources.LanczosLut); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.SrvUpscaleMaximumBiasLut, Resources.MaximumBiasLut); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.SrvSceneLuminanceMips, Resources.SceneLuminance); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.SrvAutoExposure, Resources.AutoExposure); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.SrvLumaHistory, Resources.LumaHistory[frameIndex ^ 1]); + + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.UavInternalUpscaled, Resources.InternalUpscaled[frameIndex]); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.UavLockStatus, Resources.LockStatus[frameIndex]); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.UavLumaHistory, Resources.LumaHistory[frameIndex]); + + ref var output = ref dispatchParams.Output; + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.UavUpscaledOutput, output.RenderTarget, output.MipLevel, output.SubElement); + + commandBuffer.SetComputeConstantBufferParam(ComputeShader, AsrShaderIDs.CbFsr2, Constants, 0, Constants.stride); + + commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1); + } + } + + internal class AsrSharpenPass : AsrPass + { + private readonly ComputeBuffer _rcasConstants; + + public AsrSharpenPass(Asr.ContextDescription contextDescription, AsrResources resources, ComputeBuffer constants, ComputeBuffer rcasConstants) + : base(contextDescription, resources, constants) + { + _rcasConstants = rcasConstants; + + InitComputeShader("RCAS Sharpening", contextDescription.Shaders.sharpenPass); + } + + protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Asr.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY) + { + ref var exposure = ref dispatchParams.Exposure; + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.SrvInputExposure, exposure.RenderTarget, exposure.MipLevel, exposure.SubElement); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.SrvRcasInput, Resources.InternalUpscaled[frameIndex]); + + ref var output = ref dispatchParams.Output; + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.UavUpscaledOutput, output.RenderTarget, output.MipLevel, output.SubElement); + + commandBuffer.SetComputeConstantBufferParam(ComputeShader, AsrShaderIDs.CbFsr2, Constants, 0, Constants.stride); + commandBuffer.SetComputeConstantBufferParam(ComputeShader, AsrShaderIDs.CbRcas, _rcasConstants, 0, _rcasConstants.stride); + + commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1); + } + } + + internal class AsrGenerateReactivePass : AsrPass + { + private readonly ComputeBuffer _generateReactiveConstants; + + public AsrGenerateReactivePass(Asr.ContextDescription contextDescription, AsrResources resources, ComputeBuffer generateReactiveConstants) + : base(contextDescription, resources, null) + { + _generateReactiveConstants = generateReactiveConstants; + + InitComputeShader("Auto-Generate Reactive Mask", contextDescription.Shaders.autoGenReactivePass); + } + + protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Asr.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY) + { + } + + public void ScheduleDispatch(CommandBuffer commandBuffer, Asr.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, AsrShaderIDs.SrvOpaqueOnly, opaqueOnly.RenderTarget, opaqueOnly.MipLevel, opaqueOnly.SubElement); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.SrvInputColor, color.RenderTarget, color.MipLevel, color.SubElement); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.UavAutoReactive, reactive.RenderTarget, reactive.MipLevel, reactive.SubElement); + + commandBuffer.SetComputeConstantBufferParam(ComputeShader, AsrShaderIDs.CbGenReactive, _generateReactiveConstants, 0, _generateReactiveConstants.stride); + + commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1); + + commandBuffer.EndSample(Sampler); + } + } +} diff --git a/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrPass.cs.meta b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrPass.cs.meta new file mode 100644 index 0000000..5b01d20 --- /dev/null +++ b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrPass.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7fb53d9f929886c4ab35be8d9010b9c3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrResources.cs b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrResources.cs new file mode 100644 index 0000000..44dd65a --- /dev/null +++ b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrResources.cs @@ -0,0 +1,227 @@ +// 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 ArmASR +{ + /// + /// Helper class for bundling and managing persistent resources required by the ASR process. + /// This includes lookup tables, default fallback resources and double-buffered resources that get swapped between frames. + /// + internal class AsrResources + { + public Texture2D DefaultExposure; + public Texture2D DefaultReactive; + public Texture2D LanczosLut; + public Texture2D MaximumBiasLut; + public RenderTexture SpdAtomicCounter; + public RenderTexture AutoExposure; + public RenderTexture SceneLuminance; + 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 void Create(Asr.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 = Asr.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 FSR2_LanczosLutData: FFX_RESOURCE_USAGE_READ_ONLY, FFX_SURFACE_FORMAT_R16_SNORM, FFX_RESOURCE_FLAGS_NONE + // R16_SNorm textures are not supported by Unity on most platforms, strangely enough. So instead we use R32_SFloat and upload pre-normalized float data. + LanczosLut = new Texture2D(lanczos2LutWidth, 1, GraphicsFormat.R32_SFloat, TextureCreationFlags.None) { name = "ASR_LanczosLutData" }; + LanczosLut.SetPixelData(lanczos2Weights, 0); + LanczosLut.Apply(); + + // Resource FSR2_MaximumUpsampleBias: FFX_RESOURCE_USAGE_READ_ONLY, FFX_SURFACE_FORMAT_R16_SNORM, FFX_RESOURCE_FLAGS_NONE + MaximumBiasLut = new Texture2D(MaximumBiasTextureWidth, MaximumBiasTextureHeight, GraphicsFormat.R32_SFloat, TextureCreationFlags.None) { name = "ASR_MaximumUpsampleBias" }; + MaximumBiasLut.SetPixelData(maximumBias, 0); + MaximumBiasLut.Apply(); + + // Resource FSR2_DefaultExposure: FFX_RESOURCE_USAGE_READ_ONLY, FFX_SURFACE_FORMAT_R32G32_FLOAT, FFX_RESOURCE_FLAGS_NONE + DefaultExposure = new Texture2D(1, 1, GraphicsFormat.R32G32_SFloat, TextureCreationFlags.None) { name = "ASR_DefaultExposure" }; + DefaultExposure.SetPixel(0, 0, Color.clear); + DefaultExposure.Apply(); + + // Resource FSR2_DefaultReactivityMask: FFX_RESOURCE_USAGE_READ_ONLY, FFX_SURFACE_FORMAT_R8_UNORM, FFX_RESOURCE_FLAGS_NONE + DefaultReactive = new Texture2D(1, 1, GraphicsFormat.R8_UNorm, TextureCreationFlags.None) { name = "ASR_DefaultReactivityMask" }; + DefaultReactive.SetPixel(0, 0, Color.clear); + DefaultReactive.Apply(); + + // Resource FSR2_SpdAtomicCounter: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R32_UINT, FFX_RESOURCE_FLAGS_ALIASABLE + // Despite what the original FSR2 codebase says, this resource really isn't aliasable. Resetting this counter to 0 every frame breaks auto-exposure on MacOS Metal. + SpdAtomicCounter = new RenderTexture(1, 1, 0, GraphicsFormat.R32_UInt) { name = "ASR_SpdAtomicCounter", enableRandomWrite = true }; + SpdAtomicCounter.Create(); + + // Resource FSR2_AutoExposure: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R32G32_FLOAT, FFX_RESOURCE_FLAGS_NONE + AutoExposure = new RenderTexture(1, 1, 0, GraphicsFormat.R32G32_SFloat) { name = "ASR_AutoExposure", enableRandomWrite = true }; + AutoExposure.Create(); + + // Resource FSR2_ExposureMips: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R16_FLOAT, FFX_RESOURCE_FLAGS_ALIASABLE + // This is a rather special case: it's an aliasable resource, but because we require a mipmap chain and bind specific mip levels per shader, we can't easily use temporary RTs for this. + int w = contextDescription.MaxRenderSize.x / 2, h = contextDescription.MaxRenderSize.y / 2; + int mipCount = 1 + Mathf.FloorToInt(Mathf.Log(Math.Max(w, h), 2.0f)); + SceneLuminance = new RenderTexture(w, h, 0, GraphicsFormat.R16_SFloat, mipCount) { name = "ASR_ExposureMips", enableRandomWrite = true, useMipMap = true, autoGenerateMips = false }; + SceneLuminance.Create(); + + // Resources FSR2_InternalDilatedVelocity1/2: FFX_RESOURCE_USAGE_RENDERTARGET | FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R16G16_FLOAT, FFX_RESOURCE_FLAGS_NONE + CreateDoubleBufferedResource(DilatedMotionVectors, "ASR_InternalDilatedVelocity", contextDescription.MaxRenderSize, GraphicsFormat.R16G16_SFloat); + + // Resources FSR2_LockStatus1/2: FFX_RESOURCE_USAGE_RENDERTARGET | FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R16G16_FLOAT, FFX_RESOURCE_FLAGS_NONE + CreateDoubleBufferedResource(LockStatus, "ASR_LockStatus", contextDescription.DisplaySize, GraphicsFormat.R16G16_SFloat); + + // Resources FSR2_InternalUpscaled1/2: FFX_RESOURCE_USAGE_RENDERTARGET | FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R16G16B16A16_FLOAT, FFX_RESOURCE_FLAGS_NONE + CreateDoubleBufferedResource(InternalUpscaled, "ASR_InternalUpscaled", contextDescription.DisplaySize, GraphicsFormat.R16G16B16A16_SFloat); + + // Resources FSR2_LumaHistory1/2: FFX_RESOURCE_USAGE_RENDERTARGET | FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R8G8B8A8_UNORM, FFX_RESOURCE_FLAGS_NONE + CreateDoubleBufferedResource(LumaHistory, "ASR_LumaHistory", contextDescription.DisplaySize, GraphicsFormat.R8G8B8A8_UNorm); + } + + // 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, Asr.ContextDescription contextDescription, Asr.DispatchDescription dispatchParams) + { + Vector2Int displaySize = contextDescription.DisplaySize; + Vector2Int maxRenderSize = contextDescription.MaxRenderSize; + + // FSR2_ReconstructedPrevNearestDepth: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R32_UINT, FFX_RESOURCE_FLAGS_ALIASABLE + commandBuffer.GetTemporaryRT(AsrShaderIDs.UavReconstructedPrevNearestDepth, maxRenderSize.x, maxRenderSize.y, 0, default, GraphicsFormat.R32_UInt, 1, true); + + // FSR2_DilatedDepth: FFX_RESOURCE_USAGE_RENDERTARGET | FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R32_FLOAT, FFX_RESOURCE_FLAGS_ALIASABLE + commandBuffer.GetTemporaryRT(AsrShaderIDs.UavDilatedDepth, maxRenderSize.x, maxRenderSize.y, 0, default, GraphicsFormat.R32_SFloat, 1, true); + + // FSR2_LockInputLuma: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R16_FLOAT, FFX_RESOURCE_FLAGS_ALIASABLE + commandBuffer.GetTemporaryRT(AsrShaderIDs.UavLockInputLuma, maxRenderSize.x, maxRenderSize.y, 0, default, GraphicsFormat.R16_SFloat, 1, true); + + // FSR2_DilatedReactiveMasks: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R8G8_UNORM, FFX_RESOURCE_FLAGS_ALIASABLE + commandBuffer.GetTemporaryRT(AsrShaderIDs.UavDilatedReactiveMasks, maxRenderSize.x, maxRenderSize.y, 0, default, GraphicsFormat.R8G8_UNorm, 1, true); + + // FSR2_PreparedInputColor: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R16G16B16A16_FLOAT, FFX_RESOURCE_FLAGS_ALIASABLE + commandBuffer.GetTemporaryRT(AsrShaderIDs.UavPreparedInputColor, maxRenderSize.x, maxRenderSize.y, 0, default, GraphicsFormat.R16G16B16A16_SFloat, 1, true); + + // FSR2_NewLocks: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R8_UNORM, FFX_RESOURCE_FLAGS_ALIASABLE + commandBuffer.GetTemporaryRT(AsrShaderIDs.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(AsrShaderIDs.UavReconstructedPrevNearestDepth); + commandBuffer.ReleaseTemporaryRT(AsrShaderIDs.UavDilatedDepth); + commandBuffer.ReleaseTemporaryRT(AsrShaderIDs.UavLockInputLuma); + commandBuffer.ReleaseTemporaryRT(AsrShaderIDs.UavDilatedReactiveMasks); + commandBuffer.ReleaseTemporaryRT(AsrShaderIDs.UavPreparedInputColor); + commandBuffer.ReleaseTemporaryRT(AsrShaderIDs.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() + { + 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); + } + + 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, + }; + } +} diff --git a/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrResources.cs.meta b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrResources.cs.meta new file mode 100644 index 0000000..b0f5f23 --- /dev/null +++ b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrResources.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 538f6eefa95c8ee4d9f6a9bc4bb3188e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrShaderIDs.cs b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrShaderIDs.cs new file mode 100644 index 0000000..8f829bb --- /dev/null +++ b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrShaderIDs.cs @@ -0,0 +1,75 @@ +// 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 ArmASR +{ + public static class AsrShaderIDs + { + // 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"); + + // 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"); + + // 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"); + } +} diff --git a/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrShaderIDs.cs.meta b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrShaderIDs.cs.meta new file mode 100644 index 0000000..c65dbb6 --- /dev/null +++ b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrShaderIDs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e0173241f8bd75e419590b43a3739e0e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/ResourceView.cs b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/ResourceView.cs new file mode 100644 index 0000000..fab2113 --- /dev/null +++ b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/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 ArmASR +{ + /// + /// An immutable structure wrapping all the necessary information to bind a specific buffer or attachment of a render target to a compute shader. + /// + public readonly struct ResourceView + { + /// + /// 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. + /// + public static readonly ResourceView Unassigned = new ResourceView(default); + + /// + /// 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. + /// + 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; + } +} diff --git a/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/ResourceView.cs.meta b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/ResourceView.cs.meta new file mode 100644 index 0000000..f7e1122 --- /dev/null +++ b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/ResourceView.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6e2e3cd4f5c3d4146b6fe3f93685751b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: