diff --git a/Runtime/Common/FfxContextBase.cs b/Runtime/Common/FfxContextBase.cs new file mode 100644 index 0000000..22595c2 --- /dev/null +++ b/Runtime/Common/FfxContextBase.cs @@ -0,0 +1,57 @@ +using System; +using System.Runtime.InteropServices; +using UnityEngine; +using UnityEngine.Rendering; + +namespace FidelityFX +{ + public abstract class FfxContextBase + { + protected static void DestroyPass(ref TPass pass) + where TPass: class, IDisposable + { + if (pass == null) + return; + + pass.Dispose(); + pass = null; + } + + /// + /// Convenience class for handling a constants buffer containing a single struct item. + /// This wraps the compute buffer and the value array, as well as providing easy access to both. + /// + protected class ConstantsBuffer + where TConst: struct + { + private ComputeBuffer _computeBuffer; + + private readonly TConst[] _constArray = { new TConst() }; + public ref TConst Value => ref _constArray[0]; + + public void Create() + { + _computeBuffer = new ComputeBuffer(1, Marshal.SizeOf(), ComputeBufferType.Constant); + } + + public void UpdateBufferData(CommandBuffer commandBuffer) + { + commandBuffer.SetBufferData(_computeBuffer, _constArray); + } + + public void Destroy() + { + if (_computeBuffer == null) + return; + + _computeBuffer.Release(); + _computeBuffer = null; + } + + public static implicit operator ComputeBuffer(ConstantsBuffer constants) + { + return constants._computeBuffer; + } + } + } +} diff --git a/Runtime/Common/FfxContextBase.cs.meta b/Runtime/Common/FfxContextBase.cs.meta new file mode 100644 index 0000000..0aceb0b --- /dev/null +++ b/Runtime/Common/FfxContextBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f4aeccbeb6e61434eb2e50b7190fda8d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Common/FfxPassBase.cs b/Runtime/Common/FfxPassBase.cs new file mode 100644 index 0000000..3e9e4aa --- /dev/null +++ b/Runtime/Common/FfxPassBase.cs @@ -0,0 +1,63 @@ +using System; +using UnityEngine; +using UnityEngine.Profiling; +using UnityEngine.Rendering; + +namespace FidelityFX +{ + internal abstract class FfxPassBase: IDisposable + //where TDispatch: struct + { + private readonly string _techName; + + protected ComputeShader ComputeShader; + protected int KernelIndex; + + protected CustomSampler Sampler; + + protected FfxPassBase(string techName) + { + _techName = techName; + } + + public void ScheduleDispatch(CommandBuffer commandBuffer, in TDispatch dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ = 1) + { + commandBuffer.BeginSample(Sampler); + DoScheduleDispatch(commandBuffer, dispatchParams, bufferIndex, dispatchX, dispatchY, dispatchZ); + commandBuffer.EndSample(Sampler); + } + + protected abstract void DoScheduleDispatch(CommandBuffer commandBuffer, in TDispatch dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ); + + protected void InitComputeShader(string passName, ComputeShader shader, string kernelName = "CS") + { + if (shader == null) + { + throw new MissingReferenceException($"Shader for {_techName} pass '{passName}' could not be loaded! Please ensure it is included in the project correctly."); + } + + ComputeShader = shader; + KernelIndex = ComputeShader.FindKernel(kernelName); + Sampler = CustomSampler.Create(passName); + } + + public virtual void Dispose() + { + } + } + + internal abstract class FfxPassWithFlags : FfxPassBase + //where TDispatch: struct + where TFlags: Enum + { + protected FfxPassWithFlags(string techName): base(techName) { } + + protected void InitComputeShader(string passName, ComputeShader shader, TFlags flags, string kernelName = "CS") + { + InitComputeShader(passName, shader, kernelName); + SetupShaderKeywords(flags); + } + + protected abstract void SetupShaderKeywords(TFlags flags); + } +} diff --git a/Runtime/Common/FfxPassBase.cs.meta b/Runtime/Common/FfxPassBase.cs.meta new file mode 100644 index 0000000..f89a6b8 --- /dev/null +++ b/Runtime/Common/FfxPassBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: deac9cc5a4c6df64db05956030e79425 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Common/FfxResourcesBase.cs b/Runtime/Common/FfxResourcesBase.cs new file mode 100644 index 0000000..8f1c58f --- /dev/null +++ b/Runtime/Common/FfxResourcesBase.cs @@ -0,0 +1,96 @@ +using System; +using System.Runtime.InteropServices; +using UnityEngine; +using UnityEngine.Experimental.Rendering; + +namespace FidelityFX +{ + internal abstract class FfxResourcesBase + { + protected static ComputeBuffer CreateBuffer(string name, int count) + { + return new ComputeBuffer(count, Marshal.SizeOf()); + } + + protected static Texture2D CreateLookup(string name, GraphicsFormat format, Color data) + { + var tex = new Texture2D(1, 1, format, TextureCreationFlags.None) { name = name }; + tex.SetPixel(0, 0, data); + tex.Apply(); + return tex; + } + + protected static Texture2D CreateLookup(string name, in Vector2Int size, GraphicsFormat format, T[] data) + { + var tex = new Texture2D(size.x, size.y, format, TextureCreationFlags.None) { name = name }; + tex.SetPixelData(data, 0); + tex.Apply(); + return tex; + } + + protected static RenderTexture CreateResource(string name, in Vector2Int size, GraphicsFormat format) + { + var rt = new RenderTexture(size.x, size.y, 0, format) { name = name, enableRandomWrite = true }; + rt.Create(); + return rt; + } + + protected static RenderTexture CreateResourceMips(string name, in Vector2Int size, GraphicsFormat format) + { + int mipCount = 1 + Mathf.FloorToInt(Mathf.Log(Math.Max(size.x, size.y), 2.0f)); + var rt = new RenderTexture(size.x, size.y, 0, format, mipCount) { name = name, enableRandomWrite = true, useMipMap = true, autoGenerateMips = false }; + rt.Create(); + return rt; + } + + protected static void CreateDoubleBufferedResource(RenderTexture[] resource, string name, in Vector2Int size, GraphicsFormat format, int numElements = 2) + { + numElements = Math.Min(resource.Length, numElements); + for (int i = 0; i < numElements; ++i) + { + resource[i] = new RenderTexture(size.x, size.y, 0, format) { name = name + (i + 1), enableRandomWrite = true }; + resource[i].Create(); + } + } + + protected static void DestroyResource(ref Texture2D resource) + { + if (resource == null) + return; + +#if UNITY_EDITOR + if (Application.isPlaying && !UnityEditor.EditorApplication.isPaused) + UnityEngine.Object.Destroy(resource); + else + UnityEngine.Object.DestroyImmediate(resource); +#else + UnityEngine.Object.Destroy(resource); +#endif + resource = null; + } + + protected static void DestroyResource(ref RenderTexture resource) + { + if (resource == null) + return; + + resource.Release(); + resource = null; + } + + protected static void DestroyResource(ref ComputeBuffer resource) + { + if (resource == null) + return; + + resource.Release(); + resource = null; + } + + protected static void DestroyResource(RenderTexture[] resource) + { + for (int i = 0; i < resource.Length; ++i) + DestroyResource(ref resource[i]); + } + } +} diff --git a/Runtime/Common/FfxResourcesBase.cs.meta b/Runtime/Common/FfxResourcesBase.cs.meta new file mode 100644 index 0000000..7398dad --- /dev/null +++ b/Runtime/Common/FfxResourcesBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2a46b97ac72c45545a80a896462e1112 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Common/FfxSpd.cs b/Runtime/Common/FfxSpd.cs new file mode 100644 index 0000000..cd2138e --- /dev/null +++ b/Runtime/Common/FfxSpd.cs @@ -0,0 +1,46 @@ +using System; +using System.Runtime.InteropServices; +using UnityEngine; + +namespace FidelityFX +{ + public static class FfxSpd + { + public static void SetupSpdConstants(Vector2Int resolution, ref SpdConstants spdConstants, out Vector2Int dispatchThreadGroupCount, int mips = -1) + { + RectInt rectInfo = new RectInt(0, 0, resolution.x, resolution.y); + SpdSetup(rectInfo, out dispatchThreadGroupCount, out Vector2Int workGroupOffset, out Vector2Int numWorkGroupsAndMips, mips); + + spdConstants.numWorkGroups = (uint)numWorkGroupsAndMips.x; + spdConstants.mips = (uint)numWorkGroupsAndMips.y; + spdConstants.workGroupOffsetX = (uint)workGroupOffset.x; + spdConstants.workGroupOffsetY = (uint)workGroupOffset.y; + } + + public static void SpdSetup(RectInt rectInfo, out Vector2Int dispatchThreadGroupCount, out Vector2Int workGroupOffset, out Vector2Int numWorkGroupsAndMips, int mips = -1) + { + workGroupOffset = new Vector2Int(rectInfo.x / 64, rectInfo.y / 64); + + int endIndexX = (rectInfo.x + rectInfo.width - 1) / 64; + int endIndexY = (rectInfo.y + rectInfo.height - 1) / 64; + + dispatchThreadGroupCount = new Vector2Int(endIndexX + 1 - workGroupOffset.x, endIndexY + 1 - workGroupOffset.y); + + numWorkGroupsAndMips = new Vector2Int(dispatchThreadGroupCount.x * dispatchThreadGroupCount.y, mips); + if (mips < 0) + { + float resolution = Math.Max(rectInfo.width, rectInfo.height); + numWorkGroupsAndMips.y = Math.Min(Mathf.FloorToInt(Mathf.Log(resolution, 2.0f)), 12); + } + } + + [Serializable, StructLayout(LayoutKind.Sequential)] + public struct SpdConstants + { + public uint mips; + public uint numWorkGroups; + public uint workGroupOffsetX; + public uint workGroupOffsetY; + } + } +} diff --git a/Runtime/Common/FfxSpd.cs.meta b/Runtime/Common/FfxSpd.cs.meta new file mode 100644 index 0000000..bf34fa1 --- /dev/null +++ b/Runtime/Common/FfxSpd.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: aee0f42dc1676ab4db5c01520b0b925a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Common/FfxUtils.cs b/Runtime/Common/FfxUtils.cs new file mode 100644 index 0000000..192f4cb --- /dev/null +++ b/Runtime/Common/FfxUtils.cs @@ -0,0 +1,118 @@ +using System; +using System.Runtime.InteropServices; +using UnityEngine; +using UnityEngine.Rendering; + +namespace FidelityFX +{ + public static class FfxUtils + { + public static float GetMipmapBiasOffset(int renderWidth, int displayWidth) + { + return Mathf.Log((float)renderWidth / displayWidth, 2.0f) - 1.0f; + } + + public static int GetJitterPhaseCount(int renderWidth, int displayWidth) + { + const float basePhaseCount = 8.0f; + int jitterPhaseCount = (int)(basePhaseCount * Mathf.Pow((float)displayWidth / renderWidth, 2.0f)); + return jitterPhaseCount; + } + + public static void GetJitterOffset(out float outX, out float outY, int index, int phaseCount) + { + outX = Halton((index % phaseCount) + 1, 2) - 0.5f; + outY = Halton((index % phaseCount) + 1, 3) - 0.5f; + } + + // Calculate halton number for index and base. + private static float Halton(int index, int @base) + { + float f = 1.0f, result = 0.0f; + + for (int currentIndex = index; currentIndex > 0;) { + + f /= @base; + result += f * (currentIndex % @base); + currentIndex = (int)Mathf.Floor((float)currentIndex / @base); + } + + return result; + } + + public static float Lanczos2(float value) + { + return Mathf.Abs(value) < Mathf.Epsilon ? 1.0f : Mathf.Sin(Mathf.PI * value) / (Mathf.PI * value) * (Mathf.Sin(0.5f * Mathf.PI * value) / (0.5f * Mathf.PI * value)); + } + + public static float[] GenerateLanczos2Table(int width) + { + float[] lanczos2Weights = new float[width]; + for (int currentLanczosWidthIndex = 0; currentLanczosWidthIndex < width; ++currentLanczosWidthIndex) + { + float x = 2.0f * currentLanczosWidthIndex / (width - 1); + float y = Lanczos2(x); + lanczos2Weights[currentLanczosWidthIndex] = y; + } + + return lanczos2Weights; + } + + public static Vector4 SetupDeviceDepthToViewSpaceDepthParams(Vector2Int renderSize, float cameraNear, float cameraFar, float cameraFovAngleVertical, bool inverted, bool infinite) + { + // make sure it has no impact if near and far plane values are swapped in dispatch params + // the flags "inverted" and "infinite" will decide what transform to use + float min = Mathf.Min(cameraNear, cameraFar); + float max = Mathf.Max(cameraNear, cameraFar); + + if (inverted) + { + (min, max) = (max, min); + } + + float q = max / (min - max); + float d = -1.0f; + + Vector4 matrixElemC = new Vector4(q, -1.0f - Mathf.Epsilon, q, 0.0f + Mathf.Epsilon); + Vector4 matrixElemE = new Vector4(q * min, -min - Mathf.Epsilon, q * min, max); + + // Revert x and y coords + float aspect = (float)renderSize.x / renderSize.y; + float cotHalfFovY = Mathf.Cos(0.5f * cameraFovAngleVertical) / Mathf.Sin(0.5f * cameraFovAngleVertical); + + int matrixIndex = (inverted ? 2 : 0) + (infinite ? 1 : 0); + return new Vector4( + d * matrixElemC[matrixIndex], + matrixElemE[matrixIndex], + aspect / cotHalfFovY, + 1.0f / cotHalfFovY); + } + +#if !UNITY_2021_1_OR_NEWER + internal static void SetBufferData(this CommandBuffer commandBuffer, ComputeBuffer computeBuffer, Array data) + { + commandBuffer.SetComputeBufferData(computeBuffer, data); + } +#endif + + /// + /// Alternative for CommandBuffer.SetComputeTextureParam that guards against attempts to bind mip levels that don't exist. + /// + internal static void SetComputeTextureMipParam(this CommandBuffer commandBuffer, ComputeShader computeShader, int kernelIndex, int nameID, Texture texture, int mipLevel) + { + mipLevel = Math.Min(mipLevel, texture.mipmapCount - 1); + commandBuffer.SetComputeTextureParam(computeShader, kernelIndex, nameID, texture, mipLevel); + } + + internal static void SetComputeResourceParam(this CommandBuffer commandBuffer, ComputeShader computeShader, int kernelIndex, int nameID, in ResourceView resource) + { + commandBuffer.SetComputeTextureParam(computeShader, kernelIndex, nameID, resource.RenderTarget, resource.MipLevel, resource.SubElement); + } + + internal static void SetComputeConstantBufferParam(this CommandBuffer commandBuffer, ComputeShader computeShader, int nameID, ComputeBuffer buffer) + where TBuf: struct + { + commandBuffer.SetComputeConstantBufferParam(computeShader, nameID, buffer, 0, Marshal.SizeOf()); + } + } +} diff --git a/Runtime/Common/FfxUtils.cs.meta b/Runtime/Common/FfxUtils.cs.meta new file mode 100644 index 0000000..8e2e1ff --- /dev/null +++ b/Runtime/Common/FfxUtils.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9c5c0f0b987cca64c8dfd8051e09962e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/FSR2/Fsr2.cs b/Runtime/FSR2/Fsr2.cs index 4632b96..db979c4 100644 --- a/Runtime/FSR2/Fsr2.cs +++ b/Runtime/FSR2/Fsr2.cs @@ -89,51 +89,6 @@ namespace FidelityFX.FSR2 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, @@ -259,9 +214,7 @@ namespace FidelityFX.FSR2 [Serializable, StructLayout(LayoutKind.Sequential)] internal struct SpdConstants { - public uint mips; - public uint numWorkGroups; - public uint workGroupOffsetX, workGroupOffsetY; + public FfxSpd.SpdConstants spd; public uint renderSizeX, renderSizeY; } diff --git a/Runtime/FSR2/Fsr2Context.cs b/Runtime/FSR2/Fsr2Context.cs index 38d380b..afb173c 100644 --- a/Runtime/FSR2/Fsr2Context.cs +++ b/Runtime/FSR2/Fsr2Context.cs @@ -19,8 +19,8 @@ // THE SOFTWARE. using System; -using System.Runtime.InteropServices; using UnityEngine; +using UnityEngine.Profiling; using UnityEngine.Rendering; namespace FidelityFX.FSR2 @@ -31,7 +31,7 @@ namespace FidelityFX.FSR2 /// Note that this class does not know anything about Unity render pipelines; all it knows is CommandBuffers and RenderTargetIdentifiers. /// This should make it suitable for integration with any of the available Unity render pipelines. /// - public class Fsr2Context + public class Fsr2Context: FfxContextBase { private const int MaxQueuedFrames = 16; @@ -49,46 +49,34 @@ namespace FidelityFX.FSR2 private readonly Fsr2Resources _resources = new Fsr2Resources(); - private ComputeBuffer _upscalerConstantsBuffer; - private readonly Fsr2.UpscalerConstants[] _upscalerConstantsArray = { new Fsr2.UpscalerConstants() }; - private ref Fsr2.UpscalerConstants UpscalerConsts => ref _upscalerConstantsArray[0]; - - private ComputeBuffer _spdConstantsBuffer; - private readonly Fsr2.SpdConstants[] _spdConstantsArray = { new Fsr2.SpdConstants() }; - private ref Fsr2.SpdConstants SpdConsts => ref _spdConstantsArray[0]; - - private ComputeBuffer _rcasConstantsBuffer; - private readonly Fsr2.RcasConstants[] _rcasConstantsArray = new Fsr2.RcasConstants[1]; - private ref Fsr2.RcasConstants RcasConsts => ref _rcasConstantsArray[0]; - - private ComputeBuffer _generateReactiveConstantsBuffer; - private readonly Fsr2.GenerateReactiveConstants[] _generateReactiveConstantsArray = { new Fsr2.GenerateReactiveConstants() }; - private ref Fsr2.GenerateReactiveConstants GenReactiveConsts => ref _generateReactiveConstantsArray[0]; - - private ComputeBuffer _tcrAutogenerateConstantsBuffer; - private readonly Fsr2.GenerateReactiveConstants2[] _tcrAutogenerateConstantsArray = { new Fsr2.GenerateReactiveConstants2() }; - private ref Fsr2.GenerateReactiveConstants2 TcrAutoGenConsts => ref _tcrAutogenerateConstantsArray[0]; - + private readonly ConstantsBuffer _upscalerConstants = new ConstantsBuffer(); + private readonly ConstantsBuffer _spdConstants = new ConstantsBuffer(); + private readonly ConstantsBuffer _rcasConstants = new ConstantsBuffer(); + private readonly ConstantsBuffer _generateReactiveConstants = new ConstantsBuffer(); + private readonly ConstantsBuffer _tcrAutogenerateConstants = new ConstantsBuffer(); + private bool _firstExecution; private Vector2 _previousJitterOffset; private int _resourceFrameIndex; + + private readonly CustomSampler _sampler = CustomSampler.Create("FSR2"); public void Create(Fsr2.ContextDescription contextDescription) { _contextDescription = contextDescription; _commandBuffer = new CommandBuffer { name = "FSR2" }; - _upscalerConstantsBuffer = CreateConstantBuffer(); - _spdConstantsBuffer = CreateConstantBuffer(); - _rcasConstantsBuffer = CreateConstantBuffer(); - _generateReactiveConstantsBuffer = CreateConstantBuffer(); - _tcrAutogenerateConstantsBuffer = CreateConstantBuffer(); + _upscalerConstants.Create(); + _spdConstants.Create(); + _rcasConstants.Create(); + _generateReactiveConstants.Create(); + _tcrAutogenerateConstants.Create(); // Set defaults _firstExecution = true; _resourceFrameIndex = 0; - UpscalerConsts.displaySize = _contextDescription.DisplaySize; + _upscalerConstants.Value.displaySize = _contextDescription.DisplaySize; _resources.Create(_contextDescription); CreatePasses(); @@ -96,14 +84,14 @@ namespace FidelityFX.FSR2 private void CreatePasses() { - _computeLuminancePyramidPass = new Fsr2ComputeLuminancePyramidPass(_contextDescription, _resources, _upscalerConstantsBuffer, _spdConstantsBuffer); - _reconstructPreviousDepthPass = new Fsr2ReconstructPreviousDepthPass(_contextDescription, _resources, _upscalerConstantsBuffer); - _depthClipPass = new Fsr2DepthClipPass(_contextDescription, _resources, _upscalerConstantsBuffer); - _lockPass = new Fsr2LockPass(_contextDescription, _resources, _upscalerConstantsBuffer); - _accumulatePass = new Fsr2AccumulatePass(_contextDescription, _resources, _upscalerConstantsBuffer); - _sharpenPass = new Fsr2SharpenPass(_contextDescription, _resources, _upscalerConstantsBuffer, _rcasConstantsBuffer); - _generateReactivePass = new Fsr2GenerateReactivePass(_contextDescription, _resources, _generateReactiveConstantsBuffer); - _tcrAutogeneratePass = new Fsr2TcrAutogeneratePass(_contextDescription, _resources, _upscalerConstantsBuffer, _tcrAutogenerateConstantsBuffer); + _computeLuminancePyramidPass = new Fsr2ComputeLuminancePyramidPass(_contextDescription, _resources, _upscalerConstants, _spdConstants); + _reconstructPreviousDepthPass = new Fsr2ReconstructPreviousDepthPass(_contextDescription, _resources, _upscalerConstants); + _depthClipPass = new Fsr2DepthClipPass(_contextDescription, _resources, _upscalerConstants); + _lockPass = new Fsr2LockPass(_contextDescription, _resources, _upscalerConstants); + _accumulatePass = new Fsr2AccumulatePass(_contextDescription, _resources, _upscalerConstants); + _sharpenPass = new Fsr2SharpenPass(_contextDescription, _resources, _upscalerConstants, _rcasConstants); + _generateReactivePass = new Fsr2GenerateReactivePass(_contextDescription, _resources, _generateReactiveConstants); + _tcrAutogeneratePass = new Fsr2TcrAutogeneratePass(_contextDescription, _resources, _upscalerConstants, _tcrAutogenerateConstants); } public void Destroy() @@ -119,11 +107,11 @@ namespace FidelityFX.FSR2 _resources.Destroy(); - DestroyConstantBuffer(ref _tcrAutogenerateConstantsBuffer); - DestroyConstantBuffer(ref _generateReactiveConstantsBuffer); - DestroyConstantBuffer(ref _rcasConstantsBuffer); - DestroyConstantBuffer(ref _spdConstantsBuffer); - DestroyConstantBuffer(ref _upscalerConstantsBuffer); + _tcrAutogenerateConstants.Destroy(); + _generateReactiveConstants.Destroy(); + _rcasConstants.Destroy(); + _spdConstants.Destroy(); + _upscalerConstants.Destroy(); if (_commandBuffer != null) { @@ -141,6 +129,8 @@ namespace FidelityFX.FSR2 public void Dispatch(Fsr2.DispatchDescription dispatchParams, CommandBuffer commandBuffer) { + commandBuffer.BeginSample(_sampler); + if ((_contextDescription.Flags & Fsr2.InitializationFlags.EnableDebugChecking) != 0) { DebugCheckDispatch(dispatchParams); @@ -157,7 +147,7 @@ namespace FidelityFX.FSR2 commandBuffer.ClearRenderTarget(false, true, Color.clear); } - int frameIndex = _resourceFrameIndex % 2; + int bufferIndex = _resourceFrameIndex % 2; bool resetAccumulation = dispatchParams.Reset || _firstExecution; _firstExecution = false; @@ -176,7 +166,7 @@ namespace FidelityFX.FSR2 if (resetAccumulation) { RenderTargetIdentifier opaqueOnly = dispatchParams.ColorOpaqueOnly.IsValid ? dispatchParams.ColorOpaqueOnly.RenderTarget : Fsr2ShaderIDs.SrvOpaqueOnly; - commandBuffer.Blit(_resources.PrevPreAlpha[frameIndex ^ 1], opaqueOnly); + commandBuffer.Blit(_resources.PrevPreAlpha[bufferIndex ^ 1], opaqueOnly); } } else if (_resources.AutoReactive != null) @@ -193,18 +183,18 @@ namespace FidelityFX.FSR2 // Reactive mask bias const int threadGroupWorkRegionDim = 8; - int dispatchSrcX = (UpscalerConsts.renderSize.x + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; - int dispatchSrcY = (UpscalerConsts.renderSize.y + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; + int dispatchSrcX = (_upscalerConstants.Value.renderSize.x + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; + int dispatchSrcY = (_upscalerConstants.Value.renderSize.y + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; int dispatchDstX = (_contextDescription.DisplaySize.x + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; int dispatchDstY = (_contextDescription.DisplaySize.y + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; // Clear reconstructed depth for max depth store if (resetAccumulation) { - commandBuffer.SetRenderTarget(_resources.LockStatus[frameIndex ^ 1]); + commandBuffer.SetRenderTarget(_resources.LockStatus[bufferIndex ^ 1]); commandBuffer.ClearRenderTarget(false, true, Color.clear); - commandBuffer.SetRenderTarget(_resources.InternalUpscaled[frameIndex ^ 1]); + commandBuffer.SetRenderTarget(_resources.InternalUpscaled[bufferIndex ^ 1]); commandBuffer.ClearRenderTarget(false, true, Color.clear); commandBuffer.SetRenderTarget(_resources.SceneLuminance); @@ -228,43 +218,43 @@ namespace FidelityFX.FSR2 SetupSpdConstants(dispatchParams, out var dispatchThreadGroupCount); // Initialize constant buffers data - commandBuffer.SetBufferData(_upscalerConstantsBuffer, _upscalerConstantsArray); - commandBuffer.SetBufferData(_spdConstantsBuffer, _spdConstantsArray); + _upscalerConstants.UpdateBufferData(commandBuffer); + _spdConstants.UpdateBufferData(commandBuffer); // Auto reactive if (dispatchParams.EnableAutoReactive) { - GenerateTransparencyCompositionReactive(dispatchParams, commandBuffer, frameIndex); + GenerateTransparencyCompositionReactive(dispatchParams, commandBuffer, bufferIndex); dispatchParams.Reactive = new ResourceView(_resources.AutoReactive); dispatchParams.TransparencyAndComposition = new ResourceView(_resources.AutoComposition); } // Compute luminance pyramid - _computeLuminancePyramidPass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchThreadGroupCount.x, dispatchThreadGroupCount.y); + _computeLuminancePyramidPass.ScheduleDispatch(commandBuffer, dispatchParams, bufferIndex, dispatchThreadGroupCount.x, dispatchThreadGroupCount.y); // Reconstruct previous depth - _reconstructPreviousDepthPass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchSrcX, dispatchSrcY); + _reconstructPreviousDepthPass.ScheduleDispatch(commandBuffer, dispatchParams, bufferIndex, dispatchSrcX, dispatchSrcY); // Depth clip - _depthClipPass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchSrcX, dispatchSrcY); + _depthClipPass.ScheduleDispatch(commandBuffer, dispatchParams, bufferIndex, dispatchSrcX, dispatchSrcY); // Create locks - _lockPass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchSrcX, dispatchSrcY); + _lockPass.ScheduleDispatch(commandBuffer, dispatchParams, bufferIndex, dispatchSrcX, dispatchSrcY); // Accumulate - _accumulatePass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchDstX, dispatchDstY); + _accumulatePass.ScheduleDispatch(commandBuffer, dispatchParams, bufferIndex, dispatchDstX, dispatchDstY); if (dispatchParams.EnableSharpening) { // Compute the constants SetupRcasConstants(dispatchParams); - commandBuffer.SetBufferData(_rcasConstantsBuffer, _rcasConstantsArray); + _rcasConstants.UpdateBufferData(commandBuffer); // Dispatch RCAS const int threadGroupWorkRegionDimRcas = 16; int threadGroupsX = (Screen.width + threadGroupWorkRegionDimRcas - 1) / threadGroupWorkRegionDimRcas; int threadGroupsY = (Screen.height + threadGroupWorkRegionDimRcas - 1) / threadGroupWorkRegionDimRcas; - _sharpenPass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, threadGroupsX, threadGroupsY); + _sharpenPass.ScheduleDispatch(commandBuffer, dispatchParams, bufferIndex, threadGroupsX, threadGroupsY); } _resourceFrameIndex = (_resourceFrameIndex + 1) % MaxQueuedFrames; @@ -272,6 +262,7 @@ namespace FidelityFX.FSR2 Fsr2Resources.DestroyAliasableResources(commandBuffer); commandBuffer.DisableShaderKeyword("UNITY_FSR_TEXTURE2D_X_ARRAY"); + commandBuffer.EndSample(_sampler); } public void GenerateReactiveMask(Fsr2.GenerateReactiveDescription dispatchParams) @@ -287,11 +278,12 @@ namespace FidelityFX.FSR2 int dispatchSrcX = (dispatchParams.RenderSize.x + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; int dispatchSrcY = (dispatchParams.RenderSize.y + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; - GenReactiveConsts.scale = dispatchParams.Scale; - GenReactiveConsts.threshold = dispatchParams.CutoffThreshold; - GenReactiveConsts.binaryValue = dispatchParams.BinaryValue; - GenReactiveConsts.flags = (uint)dispatchParams.Flags; - commandBuffer.SetBufferData(_generateReactiveConstantsBuffer, _generateReactiveConstantsArray); + ref var genReactiveConsts = ref _generateReactiveConstants.Value; + genReactiveConsts.scale = dispatchParams.Scale; + genReactiveConsts.threshold = dispatchParams.CutoffThreshold; + genReactiveConsts.binaryValue = dispatchParams.BinaryValue; + genReactiveConsts.flags = (uint)dispatchParams.Flags; + _generateReactiveConstants.UpdateBufferData(commandBuffer); ((Fsr2GenerateReactivePass)_generateReactivePass).ScheduleDispatch(commandBuffer, dispatchParams, dispatchSrcX, dispatchSrcY); } @@ -302,18 +294,19 @@ namespace FidelityFX.FSR2 int dispatchSrcX = (dispatchParams.RenderSize.x + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; int dispatchSrcY = (dispatchParams.RenderSize.y + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; - TcrAutoGenConsts.autoTcThreshold = dispatchParams.AutoTcThreshold; - TcrAutoGenConsts.autoTcScale = dispatchParams.AutoTcScale; - TcrAutoGenConsts.autoReactiveScale = dispatchParams.AutoReactiveScale; - TcrAutoGenConsts.autoReactiveMax = dispatchParams.AutoReactiveMax; - commandBuffer.SetBufferData(_tcrAutogenerateConstantsBuffer, _tcrAutogenerateConstantsArray); + ref var tcrAutoGenConsts = ref _tcrAutogenerateConstants.Value; + tcrAutoGenConsts.autoTcThreshold = dispatchParams.AutoTcThreshold; + tcrAutoGenConsts.autoTcScale = dispatchParams.AutoTcScale; + tcrAutoGenConsts.autoReactiveScale = dispatchParams.AutoReactiveScale; + tcrAutoGenConsts.autoReactiveMax = dispatchParams.AutoReactiveMax; + _tcrAutogenerateConstants.UpdateBufferData(commandBuffer); _tcrAutogeneratePass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchSrcX, dispatchSrcY); } private void SetupConstants(Fsr2.DispatchDescription dispatchParams, bool resetAccumulation) { - ref Fsr2.UpscalerConstants constants = ref UpscalerConsts; + ref Fsr2.UpscalerConstants constants = ref _upscalerConstants.Value; constants.jitterOffset = dispatchParams.JitterOffset; constants.renderSize = dispatchParams.RenderSize; @@ -327,7 +320,10 @@ namespace FidelityFX.FSR2 constants.viewSpaceToMetersFactor = (dispatchParams.ViewSpaceToMetersFactor > 0.0f) ? dispatchParams.ViewSpaceToMetersFactor : 1.0f; // Compute params to enable device depth to view space depth computation in shader - constants.deviceToViewDepth = SetupDeviceDepthToViewSpaceDepthParams(dispatchParams); + bool inverted = (_contextDescription.Flags & Fsr2.InitializationFlags.EnableDepthInverted) != 0; + bool infinite = (_contextDescription.Flags & Fsr2.InitializationFlags.EnableDepthInfinite) != 0; + constants.deviceToViewDepth = FfxUtils.SetupDeviceDepthToViewSpaceDepthParams( + dispatchParams.RenderSize, dispatchParams.CameraNear, dispatchParams.CameraFar, dispatchParams.CameraFovAngleVertical, inverted, infinite); // To be updated if resource is larger than the actual image size constants.downscaleFactor = new Vector2((float)constants.renderSize.x / _contextDescription.DisplaySize.x, (float)constants.renderSize.y / _contextDescription.DisplaySize.y); @@ -345,7 +341,7 @@ namespace FidelityFX.FSR2 _previousJitterOffset = constants.jitterOffset; } - int jitterPhaseCount = Fsr2.GetJitterPhaseCount(dispatchParams.RenderSize.x, _contextDescription.DisplaySize.x); + int jitterPhaseCount = FfxUtils.GetJitterPhaseCount(dispatchParams.RenderSize.x, _contextDescription.DisplaySize.x); if (resetAccumulation || constants.jitterPhaseCount == 0) { constants.jitterPhaseCount = jitterPhaseCount; @@ -374,78 +370,22 @@ namespace FidelityFX.FSR2 constants.lumaMipDimensions.x = (int)(constants.maxRenderSize.x / mipDiv); constants.lumaMipDimensions.y = (int)(constants.maxRenderSize.y / mipDiv); } - - private Vector4 SetupDeviceDepthToViewSpaceDepthParams(Fsr2.DispatchDescription dispatchParams) - { - bool inverted = (_contextDescription.Flags & Fsr2.InitializationFlags.EnableDepthInverted) != 0; - bool infinite = (_contextDescription.Flags & Fsr2.InitializationFlags.EnableDepthInfinite) != 0; - - // make sure it has no impact if near and far plane values are swapped in dispatch params - // the flags "inverted" and "infinite" will decide what transform to use - float min = Mathf.Min(dispatchParams.CameraNear, dispatchParams.CameraFar); - float max = Mathf.Max(dispatchParams.CameraNear, dispatchParams.CameraFar); - - if (inverted) - { - (min, max) = (max, min); - } - - float q = max / (min - max); - float d = -1.0f; - - Vector4 matrixElemC = new Vector4(q, -1.0f - Mathf.Epsilon, q, 0.0f + Mathf.Epsilon); - Vector4 matrixElemE = new Vector4(q * min, -min - Mathf.Epsilon, q * min, max); - - // Revert x and y coords - float aspect = (float)dispatchParams.RenderSize.x / dispatchParams.RenderSize.y; - float cotHalfFovY = Mathf.Cos(0.5f * dispatchParams.CameraFovAngleVertical) / Mathf.Sin(0.5f * dispatchParams.CameraFovAngleVertical); - - int matrixIndex = (inverted ? 2 : 0) + (infinite ? 1 : 0); - return new Vector4( - d * matrixElemC[matrixIndex], - matrixElemE[matrixIndex], - aspect / cotHalfFovY, - 1.0f / cotHalfFovY); - } private void SetupRcasConstants(Fsr2.DispatchDescription dispatchParams) { int sharpnessIndex = Mathf.RoundToInt(Mathf.Clamp01(dispatchParams.Sharpness) * (RcasConfigs.Length - 1)); - RcasConsts = RcasConfigs[sharpnessIndex]; + _rcasConstants.Value = RcasConfigs[sharpnessIndex]; } private void SetupSpdConstants(Fsr2.DispatchDescription dispatchParams, out Vector2Int dispatchThreadGroupCount) { - RectInt rectInfo = new RectInt(0, 0, dispatchParams.RenderSize.x, dispatchParams.RenderSize.y); - SpdSetup(rectInfo, out dispatchThreadGroupCount, out var workGroupOffset, out var numWorkGroupsAndMips); - // Downsample - ref Fsr2.SpdConstants spdConstants = ref SpdConsts; - spdConstants.numWorkGroups = (uint)numWorkGroupsAndMips.x; - spdConstants.mips = (uint)numWorkGroupsAndMips.y; - spdConstants.workGroupOffsetX = (uint)workGroupOffset.x; - spdConstants.workGroupOffsetY = (uint)workGroupOffset.y; + ref Fsr2.SpdConstants spdConstants = ref _spdConstants.Value; + FfxSpd.SetupSpdConstants(dispatchParams.RenderSize, ref spdConstants.spd, out dispatchThreadGroupCount); spdConstants.renderSizeX = (uint)dispatchParams.RenderSize.x; spdConstants.renderSizeY = (uint)dispatchParams.RenderSize.y; } - private static void SpdSetup(RectInt rectInfo, out Vector2Int dispatchThreadGroupCount, out Vector2Int workGroupOffset, out Vector2Int numWorkGroupsAndMips, int mips = -1) - { - workGroupOffset = new Vector2Int(rectInfo.x / 64, rectInfo.y / 64); - - int endIndexX = (rectInfo.x + rectInfo.width - 1) / 64; - int endIndexY = (rectInfo.y + rectInfo.height - 1) / 64; - - dispatchThreadGroupCount = new Vector2Int(endIndexX + 1 - workGroupOffset.x, endIndexY + 1 - workGroupOffset.y); - - numWorkGroupsAndMips = new Vector2Int(dispatchThreadGroupCount.x * dispatchThreadGroupCount.y, mips); - if (mips < 0) - { - float resolution = Math.Max(rectInfo.width, rectInfo.height); - numWorkGroupsAndMips.y = Math.Min(Mathf.FloorToInt(Mathf.Log(resolution, 2.0f)), 12); - } - } - private void DebugCheckDispatch(Fsr2.DispatchDescription dispatchParams) { if (!dispatchParams.Color.IsValid) @@ -591,28 +531,5 @@ namespace FidelityFX.FSR2 new Fsr2.RcasConstants(1064229695u, 997604214u), new Fsr2.RcasConstants(1065353216u, 1006648320), }; - - private static ComputeBuffer CreateConstantBuffer() 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 Fsr2Pass pass) - { - if (pass == null) - return; - - pass.Dispose(); - pass = null; - } } } diff --git a/Runtime/FSR2/Fsr2Pass.cs b/Runtime/FSR2/Fsr2Pass.cs index bda5092..7384454 100644 --- a/Runtime/FSR2/Fsr2Pass.cs +++ b/Runtime/FSR2/Fsr2Pass.cs @@ -18,10 +18,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -using System; -using System.Runtime.InteropServices; using UnityEngine; -using UnityEngine.Profiling; using UnityEngine.Rendering; namespace FidelityFX.FSR2 @@ -31,7 +28,7 @@ namespace FidelityFX.FSR2 /// This loosely matches the FfxPipelineState struct from the original FSR2 codebase, wrapped in an object-oriented blanket. /// These classes are responsible for loading compute shaders, managing temporary resources, binding resources to shader kernels and dispatching said shaders. /// - internal abstract class Fsr2Pass: IDisposable + internal abstract class Fsr2Pass: FfxPassWithFlags { internal const int ShadingChangeMipLevel = 4; // This matches the FFX_FSR2_SHADING_CHANGE_MIP_LEVEL define @@ -39,47 +36,21 @@ namespace FidelityFX.FSR2 protected readonly Fsr2Resources Resources; protected readonly ComputeBuffer Constants; - protected ComputeShader ComputeShader; - protected int KernelIndex; - - protected CustomSampler Sampler; - protected Fsr2Pass(Fsr2.ContextDescription contextDescription, Fsr2Resources resources, ComputeBuffer constants) + : base("FSR2") { ContextDescription = contextDescription; Resources = resources; Constants = constants; } - public virtual void Dispose() - { - } - - public void ScheduleDispatch(CommandBuffer commandBuffer, Fsr2.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY) - { - commandBuffer.BeginSample(Sampler); - DoScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchX, dispatchY); - commandBuffer.EndSample(Sampler); - } - - protected abstract void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr2.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY); - protected void InitComputeShader(string passName, ComputeShader shader) { InitComputeShader(passName, shader, ContextDescription.Flags); } - private void InitComputeShader(string passName, ComputeShader shader, Fsr2.InitializationFlags flags) + protected override void SetupShaderKeywords(Fsr2.InitializationFlags flags) { - if (shader == null) - { - throw new MissingReferenceException($"Shader for FSR2 pass '{passName}' could not be loaded! Please ensure it is included in the project correctly."); - } - - ComputeShader = shader; - KernelIndex = ComputeShader.FindKernel("CS"); - Sampler = CustomSampler.Create(passName); - bool useLut = false; #if UNITY_2022_1_OR_NEWER // This will also work in 2020.3.43+ and 2021.3.14+ if (SystemInfo.computeSubGroupSize == 64) @@ -110,20 +81,19 @@ namespace FidelityFX.FSR2 InitComputeShader("Compute Luminance Pyramid", contextDescription.Shaders.computeLuminancePyramidPass); } - protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr2.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY) + protected override void DoScheduleDispatch(CommandBuffer commandBuffer, in Fsr2.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ) { - ref var color = ref dispatchParams.Color; - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputColor, color.RenderTarget, color.MipLevel, color.SubElement); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputColor, dispatchParams.Color); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavSpdAtomicCount, Resources.SpdAtomicCounter); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavExposureMipLumaChange, Resources.SceneLuminance, ShadingChangeMipLevel); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavExposureMip5, Resources.SceneLuminance, 5); + commandBuffer.SetComputeTextureMipParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavExposureMipLumaChange, Resources.SceneLuminance, ShadingChangeMipLevel); + commandBuffer.SetComputeTextureMipParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavExposureMip5, Resources.SceneLuminance, 5); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavAutoExposure, Resources.AutoExposure); - commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbFsr2, Constants, 0, Marshal.SizeOf()); - commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbSpd, _spdConstants, 0, Marshal.SizeOf()); + commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbFsr2, Constants); + commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbSpd, _spdConstants); - commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1); + commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, dispatchZ); } } @@ -135,23 +105,18 @@ namespace FidelityFX.FSR2 InitComputeShader("Reconstruct & Dilate", contextDescription.Shaders.reconstructPreviousDepthPass); } - protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr2.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY) + protected override void DoScheduleDispatch(CommandBuffer commandBuffer, in Fsr2.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ) { - ref var color = ref dispatchParams.Color; - ref var depth = ref dispatchParams.Depth; - ref var motionVectors = ref dispatchParams.MotionVectors; - ref var exposure = ref dispatchParams.Exposure; - - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputColor, color.RenderTarget, color.MipLevel, color.SubElement); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputDepth, depth.RenderTarget, depth.MipLevel, depth.SubElement); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputMotionVectors, motionVectors.RenderTarget, motionVectors.MipLevel, motionVectors.SubElement); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputExposure, exposure.RenderTarget, exposure.MipLevel, exposure.SubElement); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputColor, dispatchParams.Color); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputDepth, dispatchParams.Depth); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputMotionVectors, dispatchParams.MotionVectors); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputExposure, dispatchParams.Exposure); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavDilatedMotionVectors, Resources.DilatedMotionVectors[frameIndex]); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavDilatedMotionVectors, Resources.DilatedMotionVectors[bufferIndex]); - commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbFsr2, Constants, 0, Marshal.SizeOf()); + commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbFsr2, Constants); - commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1); + commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, dispatchZ); } } @@ -163,30 +128,23 @@ namespace FidelityFX.FSR2 InitComputeShader("Depth Clip", contextDescription.Shaders.depthClipPass); } - protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr2.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY) + protected override void DoScheduleDispatch(CommandBuffer commandBuffer, in Fsr2.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ) { - ref var color = ref dispatchParams.Color; - ref var depth = ref dispatchParams.Depth; - ref var motionVectors = ref dispatchParams.MotionVectors; - ref var exposure = ref dispatchParams.Exposure; - ref var reactive = ref dispatchParams.Reactive; - ref var tac = ref dispatchParams.TransparencyAndComposition; - - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputColor, color.RenderTarget, color.MipLevel, color.SubElement); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputDepth, depth.RenderTarget, depth.MipLevel, depth.SubElement); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputMotionVectors, motionVectors.RenderTarget, motionVectors.MipLevel, motionVectors.SubElement); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputExposure, exposure.RenderTarget, exposure.MipLevel, exposure.SubElement); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvReactiveMask, reactive.RenderTarget, reactive.MipLevel, reactive.SubElement); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvTransparencyAndCompositionMask, tac.RenderTarget, tac.MipLevel, tac.SubElement); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputColor, dispatchParams.Color); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputDepth, dispatchParams.Depth); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputMotionVectors, dispatchParams.MotionVectors); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputExposure, dispatchParams.Exposure); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvReactiveMask, dispatchParams.Reactive); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvTransparencyAndCompositionMask, dispatchParams.TransparencyAndComposition); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvReconstructedPrevNearestDepth, Fsr2ShaderIDs.UavReconstructedPrevNearestDepth); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvDilatedMotionVectors, Resources.DilatedMotionVectors[frameIndex]); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvDilatedMotionVectors, Resources.DilatedMotionVectors[bufferIndex]); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvDilatedDepth, Fsr2ShaderIDs.UavDilatedDepth); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvPrevDilatedMotionVectors, Resources.DilatedMotionVectors[frameIndex ^ 1]); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvPrevDilatedMotionVectors, Resources.DilatedMotionVectors[bufferIndex ^ 1]); - commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbFsr2, Constants, 0, Marshal.SizeOf()); + commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbFsr2, Constants); - commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1); + commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, dispatchZ); } } @@ -198,12 +156,12 @@ namespace FidelityFX.FSR2 InitComputeShader("Create Locks", contextDescription.Shaders.lockPass); } - protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr2.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY) + protected override void DoScheduleDispatch(CommandBuffer commandBuffer, in Fsr2.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ) { commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvLockInputLuma, Fsr2ShaderIDs.UavLockInputLuma); - commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbFsr2, Constants, 0, Marshal.SizeOf()); + commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbFsr2, Constants); - commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1); + commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, dispatchZ); } } @@ -224,7 +182,7 @@ namespace FidelityFX.FSR2 #endif } - protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr2.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY) + protected override void DoScheduleDispatch(CommandBuffer commandBuffer, in Fsr2.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ) { #if UNITY_2021_2_OR_NEWER if (dispatchParams.EnableSharpening) @@ -240,37 +198,34 @@ namespace FidelityFX.FSR2 if ((ContextDescription.Flags & Fsr2.InitializationFlags.EnableDisplayResolutionMotionVectors) == 0) { - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvDilatedMotionVectors, Resources.DilatedMotionVectors[frameIndex]); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvDilatedMotionVectors, Resources.DilatedMotionVectors[bufferIndex]); } else { - ref var motionVectors = ref dispatchParams.MotionVectors; - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputMotionVectors, motionVectors.RenderTarget, motionVectors.MipLevel, motionVectors.SubElement); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputMotionVectors, dispatchParams.MotionVectors); } - ref var exposure = ref dispatchParams.Exposure; - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputExposure, exposure.RenderTarget, exposure.MipLevel, exposure.SubElement); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputExposure, dispatchParams.Exposure); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvDilatedReactiveMasks, Fsr2ShaderIDs.UavDilatedReactiveMasks); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInternalUpscaled, Resources.InternalUpscaled[frameIndex ^ 1]); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvLockStatus, Resources.LockStatus[frameIndex ^ 1]); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInternalUpscaled, Resources.InternalUpscaled[bufferIndex ^ 1]); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvLockStatus, Resources.LockStatus[bufferIndex ^ 1]); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvPreparedInputColor, Fsr2ShaderIDs.UavPreparedInputColor); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvLanczosLut, Resources.LanczosLut); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvUpscaleMaximumBiasLut, Resources.MaximumBiasLut); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvSceneLuminanceMips, Resources.SceneLuminance); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvAutoExposure, Resources.AutoExposure); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvLumaHistory, Resources.LumaHistory[frameIndex ^ 1]); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvLumaHistory, Resources.LumaHistory[bufferIndex ^ 1]); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavInternalUpscaled, Resources.InternalUpscaled[frameIndex]); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavLockStatus, Resources.LockStatus[frameIndex]); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavLumaHistory, Resources.LumaHistory[frameIndex]); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavInternalUpscaled, Resources.InternalUpscaled[bufferIndex]); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavLockStatus, Resources.LockStatus[bufferIndex]); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavLumaHistory, Resources.LumaHistory[bufferIndex]); - ref var output = ref dispatchParams.Output; - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavUpscaledOutput, output.RenderTarget, output.MipLevel, output.SubElement); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavUpscaledOutput, dispatchParams.Output); - commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbFsr2, Constants, 0, Marshal.SizeOf()); + commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbFsr2, Constants); - commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1); + commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, dispatchZ); } } @@ -286,19 +241,17 @@ namespace FidelityFX.FSR2 InitComputeShader("RCAS Sharpening", contextDescription.Shaders.sharpenPass); } - protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr2.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY) + protected override void DoScheduleDispatch(CommandBuffer commandBuffer, in Fsr2.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ) { - ref var exposure = ref dispatchParams.Exposure; - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputExposure, exposure.RenderTarget, exposure.MipLevel, exposure.SubElement); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvRcasInput, Resources.InternalUpscaled[frameIndex]); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputExposure, dispatchParams.Exposure); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvRcasInput, Resources.InternalUpscaled[bufferIndex]); - ref var output = ref dispatchParams.Output; - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavUpscaledOutput, output.RenderTarget, output.MipLevel, output.SubElement); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavUpscaledOutput, dispatchParams.Output); - commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbFsr2, Constants, 0, Marshal.SizeOf()); - commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbRcas, _rcasConstants, 0, Marshal.SizeOf()); + commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbFsr2, Constants); + commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbRcas, _rcasConstants); - commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1); + commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, dispatchZ); } } @@ -314,7 +267,7 @@ namespace FidelityFX.FSR2 InitComputeShader("Auto-Generate Reactive Mask", contextDescription.Shaders.autoGenReactivePass); } - protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr2.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY) + protected override void DoScheduleDispatch(CommandBuffer commandBuffer, in Fsr2.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ) { } @@ -322,15 +275,11 @@ namespace FidelityFX.FSR2 { commandBuffer.BeginSample(Sampler); - ref var opaqueOnly = ref dispatchParams.ColorOpaqueOnly; - ref var color = ref dispatchParams.ColorPreUpscale; - ref var reactive = ref dispatchParams.OutReactive; + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvOpaqueOnly, dispatchParams.ColorOpaqueOnly); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputColor, dispatchParams.ColorPreUpscale); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavAutoReactive, dispatchParams.OutReactive); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvOpaqueOnly, opaqueOnly.RenderTarget, opaqueOnly.MipLevel, opaqueOnly.SubElement); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputColor, color.RenderTarget, color.MipLevel, color.SubElement); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavAutoReactive, reactive.RenderTarget, reactive.MipLevel, reactive.SubElement); - - commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbGenReactive, _generateReactiveConstants, 0, Marshal.SizeOf()); + commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbGenReactive, _generateReactiveConstants); commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1); @@ -350,31 +299,25 @@ namespace FidelityFX.FSR2 InitComputeShader("Auto-Generate Transparency & Composition Mask", contextDescription.Shaders.tcrAutoGenPass); } - protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr2.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY) + protected override void DoScheduleDispatch(CommandBuffer commandBuffer, in Fsr2.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ) { - ref var color = ref dispatchParams.Color; - ref var motionVectors = ref dispatchParams.MotionVectors; - ref var opaqueOnly = ref dispatchParams.ColorOpaqueOnly; - ref var reactive = ref dispatchParams.Reactive; - ref var tac = ref dispatchParams.TransparencyAndComposition; - - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvOpaqueOnly, opaqueOnly.RenderTarget, opaqueOnly.MipLevel, opaqueOnly.SubElement); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputColor, color.RenderTarget, color.MipLevel, color.SubElement); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputMotionVectors, motionVectors.RenderTarget, motionVectors.MipLevel, motionVectors.SubElement); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvPrevColorPreAlpha, Resources.PrevPreAlpha[frameIndex ^ 1]); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvPrevColorPostAlpha, Resources.PrevPostAlpha[frameIndex ^ 1]); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvReactiveMask, reactive.RenderTarget, reactive.MipLevel, reactive.SubElement); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvTransparencyAndCompositionMask, tac.RenderTarget, tac.MipLevel, tac.SubElement); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvOpaqueOnly, dispatchParams.ColorOpaqueOnly); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputColor, dispatchParams.Color); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputMotionVectors, dispatchParams.MotionVectors); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvPrevColorPreAlpha, Resources.PrevPreAlpha[bufferIndex ^ 1]); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvPrevColorPostAlpha, Resources.PrevPostAlpha[bufferIndex ^ 1]); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvReactiveMask, dispatchParams.Reactive); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvTransparencyAndCompositionMask, dispatchParams.TransparencyAndComposition); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavAutoReactive, Resources.AutoReactive); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavAutoComposition, Resources.AutoComposition); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavPrevColorPreAlpha, Resources.PrevPreAlpha[frameIndex]); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavPrevColorPostAlpha, Resources.PrevPostAlpha[frameIndex]); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavPrevColorPreAlpha, Resources.PrevPreAlpha[bufferIndex]); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavPrevColorPostAlpha, Resources.PrevPostAlpha[bufferIndex]); - commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbFsr2, Constants, 0, Marshal.SizeOf()); - commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbGenReactive, _tcrAutogenerateConstants, 0, Marshal.SizeOf()); + commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbFsr2, Constants); + commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbGenReactive, _tcrAutogenerateConstants); - commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1); + commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, dispatchZ); } } } diff --git a/Runtime/FSR2/Fsr2Resources.cs b/Runtime/FSR2/Fsr2Resources.cs index 4c1c50e..e268040 100644 --- a/Runtime/FSR2/Fsr2Resources.cs +++ b/Runtime/FSR2/Fsr2Resources.cs @@ -29,7 +29,7 @@ namespace FidelityFX.FSR2 /// Helper class for bundling and managing persistent resources required by the FSR2 process. /// This includes lookup tables, default fallback resources and double-buffered resources that get swapped between frames. /// - internal class Fsr2Resources + internal class Fsr2Resources: FfxResourcesBase { public Texture2D DefaultExposure; public Texture2D DefaultReactive; @@ -51,13 +51,7 @@ namespace FidelityFX.FSR2 { // Generate the data for the LUT const int lanczos2LutWidth = 128; - float[] lanczos2Weights = new float[lanczos2LutWidth]; - for (int currentLanczosWidthIndex = 0; currentLanczosWidthIndex < lanczos2LutWidth; ++currentLanczosWidthIndex) - { - float x = 2.0f * currentLanczosWidthIndex / (lanczos2LutWidth - 1); - float y = Fsr2.Lanczos2(x); - lanczos2Weights[currentLanczosWidthIndex] = y; - } + float[] lanczos2Weights = FfxUtils.GenerateLanczos2Table(lanczos2LutWidth); float[] maximumBias = new float[MaximumBiasTextureWidth * MaximumBiasTextureHeight]; for (int i = 0; i < maximumBias.Length; ++i) @@ -67,40 +61,27 @@ namespace FidelityFX.FSR2 // Resource FSR2_LanczosLutData: FFX_RESOURCE_USAGE_READ_ONLY, FFX_SURFACE_FORMAT_R16_SNORM, FFX_RESOURCE_FLAGS_NONE // R16_SNorm textures are not supported by Unity on most platforms, strangely enough. So instead we use R32_SFloat and upload pre-normalized float data. - LanczosLut = new Texture2D(lanczos2LutWidth, 1, GraphicsFormat.R32_SFloat, TextureCreationFlags.None) { name = "FSR2_LanczosLutData" }; - LanczosLut.SetPixelData(lanczos2Weights, 0); - LanczosLut.Apply(); + LanczosLut = CreateLookup("FSR2_LanczosLutData", new Vector2Int(lanczos2LutWidth, 1), GraphicsFormat.R32_SFloat, lanczos2Weights); // Resource FSR2_MaximumUpsampleBias: FFX_RESOURCE_USAGE_READ_ONLY, FFX_SURFACE_FORMAT_R16_SNORM, FFX_RESOURCE_FLAGS_NONE - MaximumBiasLut = new Texture2D(MaximumBiasTextureWidth, MaximumBiasTextureHeight, GraphicsFormat.R32_SFloat, TextureCreationFlags.None) { name = "FSR2_MaximumUpsampleBias" }; - MaximumBiasLut.SetPixelData(maximumBias, 0); - MaximumBiasLut.Apply(); + MaximumBiasLut = CreateLookup("FSR2_MaximumUpsampleBias", new Vector2Int(MaximumBiasTextureWidth, MaximumBiasTextureHeight), GraphicsFormat.R32_SFloat, maximumBias); // Resource FSR2_DefaultExposure: FFX_RESOURCE_USAGE_READ_ONLY, FFX_SURFACE_FORMAT_R32G32_FLOAT, FFX_RESOURCE_FLAGS_NONE - DefaultExposure = new Texture2D(1, 1, GraphicsFormat.R32G32_SFloat, TextureCreationFlags.None) { name = "FSR2_DefaultExposure" }; - DefaultExposure.SetPixel(0, 0, Color.clear); - DefaultExposure.Apply(); + DefaultExposure = CreateLookup("FSR2_DefaultExposure", GraphicsFormat.R32G32_SFloat, Color.clear); // Resource FSR2_DefaultReactivityMask: FFX_RESOURCE_USAGE_READ_ONLY, FFX_SURFACE_FORMAT_R8_UNORM, FFX_RESOURCE_FLAGS_NONE - DefaultReactive = new Texture2D(1, 1, GraphicsFormat.R8_UNorm, TextureCreationFlags.None) { name = "FSR2_DefaultReactivityMask" }; - DefaultReactive.SetPixel(0, 0, Color.clear); - DefaultReactive.Apply(); + DefaultReactive = CreateLookup("FSR2_DefaultReactivityMask", GraphicsFormat.R8_UNorm, Color.clear); // Resource FSR2_SpdAtomicCounter: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R32_UINT, FFX_RESOURCE_FLAGS_ALIASABLE // Despite what the original FSR2 codebase says, this resource really isn't aliasable. Resetting this counter to 0 every frame breaks auto-exposure on MacOS Metal. - SpdAtomicCounter = new RenderTexture(1, 1, 0, GraphicsFormat.R32_UInt) { name = "FSR2_SpdAtomicCounter", enableRandomWrite = true }; - SpdAtomicCounter.Create(); + SpdAtomicCounter = CreateResource("FSR2_SpdAtomicCounter", Vector2Int.one, GraphicsFormat.R32_UInt); // Resource FSR2_AutoExposure: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R32G32_FLOAT, FFX_RESOURCE_FLAGS_NONE - AutoExposure = new RenderTexture(1, 1, 0, GraphicsFormat.R32G32_SFloat) { name = "FSR2_AutoExposure", enableRandomWrite = true }; - AutoExposure.Create(); + AutoExposure = CreateResource("FSR2_AutoExposure", Vector2Int.one, GraphicsFormat.R32G32_SFloat); // Resource FSR2_ExposureMips: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R16_FLOAT, FFX_RESOURCE_FLAGS_ALIASABLE // This is a rather special case: it's an aliasable resource, but because we require a mipmap chain and bind specific mip levels per shader, we can't easily use temporary RTs for this. - int w = contextDescription.MaxRenderSize.x / 2, h = contextDescription.MaxRenderSize.y / 2; - int mipCount = 1 + Mathf.FloorToInt(Mathf.Log(Math.Max(w, h), 2.0f)); - SceneLuminance = new RenderTexture(w, h, 0, GraphicsFormat.R16_SFloat, mipCount) { name = "FSR2_ExposureMips", enableRandomWrite = true, useMipMap = true, autoGenerateMips = false }; - SceneLuminance.Create(); + SceneLuminance = CreateResourceMips("FSR2_ExposureMips", contextDescription.MaxRenderSize / 2, GraphicsFormat.R16_SFloat); // Resources FSR2_InternalDilatedVelocity1/2: FFX_RESOURCE_USAGE_RENDERTARGET | FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R16G16_FLOAT, FFX_RESOURCE_FLAGS_NONE CreateDoubleBufferedResource(DilatedMotionVectors, "FSR2_InternalDilatedVelocity", contextDescription.MaxRenderSize, GraphicsFormat.R16G16_SFloat); @@ -118,12 +99,10 @@ namespace FidelityFX.FSR2 public void CreateTcrAutogenResources(Fsr2.ContextDescription contextDescription) { // Resource FSR2_AutoReactive: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R8_UNORM, FFX_RESOURCE_FLAGS_NONE - AutoReactive = new RenderTexture(contextDescription.MaxRenderSize.x, contextDescription.MaxRenderSize.y, 0, GraphicsFormat.R8_UNorm) { name = "FSR2_AutoReactive", enableRandomWrite = true }; - AutoReactive.Create(); + AutoReactive = CreateResource("FSR2_AutoReactive", contextDescription.MaxRenderSize, GraphicsFormat.R8_UNorm); // Resource FSR2_AutoComposition: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R8_UNORM, FFX_RESOURCE_FLAGS_NONE - AutoComposition = new RenderTexture(contextDescription.MaxRenderSize.x, contextDescription.MaxRenderSize.y, 0, GraphicsFormat.R8_UNorm) { name = "FSR2_AutoComposition", enableRandomWrite = true }; - AutoComposition.Create(); + AutoComposition = CreateResource("FSR2_AutoComposition", contextDescription.MaxRenderSize, GraphicsFormat.R8_UNorm); // Resources FSR2_PrevPreAlpha0/1: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R11G11B10_FLOAT, FFX_RESOURCE_FLAGS_NONE CreateDoubleBufferedResource(PrevPreAlpha, "FSR2_PrevPreAlpha", contextDescription.MaxRenderSize, GraphicsFormat.B10G11R11_UFloatPack32); @@ -169,15 +148,6 @@ namespace FidelityFX.FSR2 commandBuffer.ReleaseTemporaryRT(Fsr2ShaderIDs.UavNewLocks); } - private static void CreateDoubleBufferedResource(RenderTexture[] resource, string name, Vector2Int size, GraphicsFormat format) - { - for (int i = 0; i < 2; ++i) - { - resource[i] = new RenderTexture(size.x, size.y, 0, format) { name = name + (i + 1), enableRandomWrite = true }; - resource[i].Create(); - } - } - public void Destroy() { DestroyTcrAutogenResources(); @@ -201,37 +171,6 @@ namespace FidelityFX.FSR2 DestroyResource(ref AutoComposition); DestroyResource(ref AutoReactive); } - - private static void DestroyResource(ref Texture2D resource) - { - if (resource == null) - return; - -#if UNITY_EDITOR - if (Application.isPlaying && !UnityEditor.EditorApplication.isPaused) - UnityEngine.Object.Destroy(resource); - else - UnityEngine.Object.DestroyImmediate(resource); -#else - UnityEngine.Object.Destroy(resource); -#endif - resource = null; - } - - private static void DestroyResource(ref RenderTexture resource) - { - if (resource == null) - return; - - resource.Release(); - resource = null; - } - - private static void DestroyResource(RenderTexture[] resource) - { - for (int i = 0; i < resource.Length; ++i) - DestroyResource(ref resource[i]); - } private const int MaximumBiasTextureWidth = 16; private const int MaximumBiasTextureHeight = 16; diff --git a/Runtime/FSR3/Fsr3Upscaler.cs b/Runtime/FSR3/Fsr3Upscaler.cs index d69aa29..20282fb 100644 --- a/Runtime/FSR3/Fsr3Upscaler.cs +++ b/Runtime/FSR3/Fsr3Upscaler.cs @@ -89,51 +89,6 @@ namespace FidelityFX.FSR3 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, @@ -270,9 +225,7 @@ namespace FidelityFX.FSR3 [Serializable, StructLayout(LayoutKind.Sequential)] internal struct SpdConstants { - public uint mips; - public uint numWorkGroups; - public uint workGroupOffsetX, workGroupOffsetY; + public FfxSpd.SpdConstants spd; public uint renderSizeX, renderSizeY; } diff --git a/Runtime/FSR3/Fsr3UpscalerContext.cs b/Runtime/FSR3/Fsr3UpscalerContext.cs index 2b7f2ef..c0f2977 100644 --- a/Runtime/FSR3/Fsr3UpscalerContext.cs +++ b/Runtime/FSR3/Fsr3UpscalerContext.cs @@ -21,6 +21,7 @@ using System; using System.Runtime.InteropServices; using UnityEngine; +using UnityEngine.Profiling; using UnityEngine.Rendering; namespace FidelityFX.FSR3 @@ -31,7 +32,7 @@ namespace FidelityFX.FSR3 /// Note that this class does not know anything about Unity render pipelines; all it knows is CommandBuffers and RenderTargetIdentifiers. /// This should make it suitable for integration with any of the available Unity render pipelines. /// - public class Fsr3UpscalerContext + public class Fsr3UpscalerContext: FfxContextBase { private const int MaxQueuedFrames = 16; @@ -54,48 +55,36 @@ namespace FidelityFX.FSR3 private readonly Fsr3UpscalerResources _resources = new Fsr3UpscalerResources(); - private ComputeBuffer _upscalerConstantsBuffer; - private readonly Fsr3Upscaler.UpscalerConstants[] _upscalerConstantsArray = { new Fsr3Upscaler.UpscalerConstants() }; - private ref Fsr3Upscaler.UpscalerConstants UpscalerConsts => ref _upscalerConstantsArray[0]; - - private ComputeBuffer _spdConstantsBuffer; - private readonly Fsr3Upscaler.SpdConstants[] _spdConstantsArray = { new Fsr3Upscaler.SpdConstants() }; - private ref Fsr3Upscaler.SpdConstants SpdConsts => ref _spdConstantsArray[0]; - - private ComputeBuffer _rcasConstantsBuffer; - private readonly Fsr3Upscaler.RcasConstants[] _rcasConstantsArray = new Fsr3Upscaler.RcasConstants[1]; - private ref Fsr3Upscaler.RcasConstants RcasConsts => ref _rcasConstantsArray[0]; - - private ComputeBuffer _generateReactiveConstantsBuffer; - private readonly Fsr3Upscaler.GenerateReactiveConstants[] _generateReactiveConstantsArray = { new Fsr3Upscaler.GenerateReactiveConstants() }; - private ref Fsr3Upscaler.GenerateReactiveConstants GenReactiveConsts => ref _generateReactiveConstantsArray[0]; - - private ComputeBuffer _tcrAutogenerateConstantsBuffer; - private readonly Fsr3Upscaler.GenerateReactiveConstants2[] _tcrAutogenerateConstantsArray = { new Fsr3Upscaler.GenerateReactiveConstants2() }; - private ref Fsr3Upscaler.GenerateReactiveConstants2 TcrAutoGenConsts => ref _tcrAutogenerateConstantsArray[0]; + private readonly ConstantsBuffer _upscalerConstants = new ConstantsBuffer(); + private readonly ConstantsBuffer _spdConstants = new ConstantsBuffer(); + private readonly ConstantsBuffer _rcasConstants = new ConstantsBuffer(); + private readonly ConstantsBuffer _generateReactiveConstants = new ConstantsBuffer(); + private readonly ConstantsBuffer _tcrAutogenerateConstants = new ConstantsBuffer(); private bool _firstExecution; private int _resourceFrameIndex; private Vector2 _previousJitterOffset; private float _preExposure; private float _previousFramePreExposure; + + private readonly CustomSampler _sampler = CustomSampler.Create("FSR3 Upscaler"); public void Create(Fsr3Upscaler.ContextDescription contextDescription) { _contextDescription = contextDescription; _commandBuffer = new CommandBuffer { name = "FSR3 Upscaler" }; - _upscalerConstantsBuffer = CreateConstantBuffer(); - _spdConstantsBuffer = CreateConstantBuffer(); - _rcasConstantsBuffer = CreateConstantBuffer(); - _generateReactiveConstantsBuffer = CreateConstantBuffer(); - _tcrAutogenerateConstantsBuffer = CreateConstantBuffer(); + _upscalerConstants.Create(); + _spdConstants.Create(); + _rcasConstants.Create(); + _generateReactiveConstants.Create(); + _tcrAutogenerateConstants.Create(); // Set defaults _firstExecution = true; _resourceFrameIndex = 0; - UpscalerConsts.maxUpscaleSize = _contextDescription.MaxUpscaleSize; + _upscalerConstants.Value.maxUpscaleSize = _contextDescription.MaxUpscaleSize; _resources.Create(_contextDescription); CreatePasses(); @@ -103,18 +92,18 @@ namespace FidelityFX.FSR3 private void CreatePasses() { - _prepareInputsPass = new Fsr3UpscalerPrepareInputsPass(_contextDescription, _resources, _upscalerConstantsBuffer); - _lumaPyramidPass = new Fsr3UpscalerLumaPyramidPass(_contextDescription, _resources, _upscalerConstantsBuffer, _spdConstantsBuffer); - _shadingChangePyramidPass = new Fsr3UpscalerShadingChangePyramidPass(_contextDescription, _resources, _upscalerConstantsBuffer, _spdConstantsBuffer); - _shadingChangePass = new Fsr3UpscalerShadingChangePass(_contextDescription, _resources, _upscalerConstantsBuffer); - _prepareReactivityPass = new Fsr3UpscalerPrepareReactivityPass(_contextDescription, _resources, _upscalerConstantsBuffer); - _lumaInstabilityPass = new Fsr3UpscalerLumaInstabilityPass(_contextDescription, _resources, _upscalerConstantsBuffer); - _accumulatePass = new Fsr3UpscalerAccumulatePass(_contextDescription, _resources, _upscalerConstantsBuffer); - _sharpenPass = new Fsr3UpscalerSharpenPass(_contextDescription, _resources, _upscalerConstantsBuffer, _rcasConstantsBuffer); - _generateReactivePass = new Fsr3UpscalerGenerateReactivePass(_contextDescription, _resources, _generateReactiveConstantsBuffer); - _tcrAutogeneratePass = new Fsr3UpscalerTcrAutogeneratePass(_contextDescription, _resources, _upscalerConstantsBuffer, _tcrAutogenerateConstantsBuffer); + _prepareInputsPass = new Fsr3UpscalerPrepareInputsPass(_contextDescription, _resources, _upscalerConstants); + _lumaPyramidPass = new Fsr3UpscalerLumaPyramidPass(_contextDescription, _resources, _upscalerConstants, _spdConstants); + _shadingChangePyramidPass = new Fsr3UpscalerShadingChangePyramidPass(_contextDescription, _resources, _upscalerConstants, _spdConstants); + _shadingChangePass = new Fsr3UpscalerShadingChangePass(_contextDescription, _resources, _upscalerConstants); + _prepareReactivityPass = new Fsr3UpscalerPrepareReactivityPass(_contextDescription, _resources, _upscalerConstants); + _lumaInstabilityPass = new Fsr3UpscalerLumaInstabilityPass(_contextDescription, _resources, _upscalerConstants); + _accumulatePass = new Fsr3UpscalerAccumulatePass(_contextDescription, _resources, _upscalerConstants); + _sharpenPass = new Fsr3UpscalerSharpenPass(_contextDescription, _resources, _upscalerConstants, _rcasConstants); + _generateReactivePass = new Fsr3UpscalerGenerateReactivePass(_contextDescription, _resources, _upscalerConstants); + _tcrAutogeneratePass = new Fsr3UpscalerTcrAutogeneratePass(_contextDescription, _resources, _upscalerConstants, _tcrAutogenerateConstants); #if UNITY_EDITOR || DEVELOPMENT_BUILD - _debugViewPass = new Fsr3UpscalerDebugViewPass(_contextDescription, _resources, _upscalerConstantsBuffer); + _debugViewPass = new Fsr3UpscalerDebugViewPass(_contextDescription, _resources, _upscalerConstants); #endif } @@ -136,11 +125,11 @@ namespace FidelityFX.FSR3 _resources.Destroy(); - DestroyConstantBuffer(ref _tcrAutogenerateConstantsBuffer); - DestroyConstantBuffer(ref _generateReactiveConstantsBuffer); - DestroyConstantBuffer(ref _rcasConstantsBuffer); - DestroyConstantBuffer(ref _spdConstantsBuffer); - DestroyConstantBuffer(ref _upscalerConstantsBuffer); + _tcrAutogenerateConstants.Destroy(); + _generateReactiveConstants.Destroy(); + _rcasConstants.Destroy(); + _spdConstants.Destroy(); + _upscalerConstants.Destroy(); if (_commandBuffer != null) { @@ -158,6 +147,8 @@ namespace FidelityFX.FSR3 public void Dispatch(Fsr3Upscaler.DispatchDescription dispatchParams, CommandBuffer commandBuffer) { + commandBuffer.BeginSample(_sampler); + if ((_contextDescription.Flags & Fsr3Upscaler.InitializationFlags.EnableDebugChecking) != 0) { DebugCheckDispatch(dispatchParams); @@ -178,7 +169,7 @@ namespace FidelityFX.FSR3 commandBuffer.ClearRenderTarget(false, true, Color.clear); } - int frameIndex = _resourceFrameIndex % 2; + int bufferIndex = _resourceFrameIndex % 2; bool resetAccumulation = dispatchParams.Reset || _firstExecution; _firstExecution = false; @@ -197,7 +188,7 @@ namespace FidelityFX.FSR3 if (resetAccumulation) { RenderTargetIdentifier opaqueOnly = dispatchParams.ColorOpaqueOnly.IsValid ? dispatchParams.ColorOpaqueOnly.RenderTarget : Fsr3ShaderIDs.SrvOpaqueOnly; - commandBuffer.Blit(_resources.PrevPreAlpha[frameIndex ^ 1], opaqueOnly); + commandBuffer.Blit(_resources.PrevPreAlpha[bufferIndex ^ 1], opaqueOnly); } } else if (_resources.AutoReactive != null) @@ -214,17 +205,19 @@ namespace FidelityFX.FSR3 // Reactive mask bias const int threadGroupWorkRegionDim = 8; - int dispatchSrcX = (UpscalerConsts.renderSize.x + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; - int dispatchSrcY = (UpscalerConsts.renderSize.y + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; - int dispatchDstX = (UpscalerConsts.upscaleSize.x + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; - int dispatchDstY = (UpscalerConsts.upscaleSize.y + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; - int dispatchShadingChangePassX = ((UpscalerConsts.renderSize.x / 2) + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; - int dispatchShadingChangePassY = ((UpscalerConsts.renderSize.y / 2) + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; + var renderSize = _upscalerConstants.Value.renderSize; + var upscaleSize = _upscalerConstants.Value.upscaleSize; + int dispatchSrcX = (renderSize.x + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; + int dispatchSrcY = (renderSize.y + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; + int dispatchDstX = (upscaleSize.x + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; + int dispatchDstY = (upscaleSize.y + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; + int dispatchShadingChangePassX = ((renderSize.x / 2) + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; + int dispatchShadingChangePassY = ((renderSize.y / 2) + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; // Clear reconstructed depth for max depth store if (resetAccumulation) { - commandBuffer.SetRenderTarget(_resources.Accumulation[frameIndex ^ 1]); + commandBuffer.SetRenderTarget(_resources.Accumulation[bufferIndex ^ 1]); commandBuffer.ClearRenderTarget(false, true, Color.clear); commandBuffer.SetRenderTarget(_resources.SpdMips); @@ -248,43 +241,43 @@ namespace FidelityFX.FSR3 SetupSpdConstants(dispatchParams, out var dispatchThreadGroupCount); // Initialize constant buffers data - commandBuffer.SetBufferData(_upscalerConstantsBuffer, _upscalerConstantsArray); - commandBuffer.SetBufferData(_spdConstantsBuffer, _spdConstantsArray); + _upscalerConstants.UpdateBufferData(commandBuffer); + _spdConstants.UpdateBufferData(commandBuffer); // Auto reactive if (dispatchParams.EnableAutoReactive) { - GenerateTransparencyCompositionReactive(dispatchParams, commandBuffer, frameIndex); + GenerateTransparencyCompositionReactive(dispatchParams, commandBuffer, bufferIndex); dispatchParams.Reactive = new ResourceView(_resources.AutoReactive); dispatchParams.TransparencyAndComposition = new ResourceView(_resources.AutoComposition); } - _prepareInputsPass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchSrcX, dispatchSrcY); - _lumaPyramidPass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchThreadGroupCount.x, dispatchThreadGroupCount.y); - _shadingChangePyramidPass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchThreadGroupCount.x, dispatchThreadGroupCount.y); - _shadingChangePass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchShadingChangePassX, dispatchShadingChangePassY); - _prepareReactivityPass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchSrcX, dispatchSrcY); - _lumaInstabilityPass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchSrcX, dispatchSrcY); + _prepareInputsPass.ScheduleDispatch(commandBuffer, dispatchParams, bufferIndex, dispatchSrcX, dispatchSrcY); + _lumaPyramidPass.ScheduleDispatch(commandBuffer, dispatchParams, bufferIndex, dispatchThreadGroupCount.x, dispatchThreadGroupCount.y); + _shadingChangePyramidPass.ScheduleDispatch(commandBuffer, dispatchParams, bufferIndex, dispatchThreadGroupCount.x, dispatchThreadGroupCount.y); + _shadingChangePass.ScheduleDispatch(commandBuffer, dispatchParams, bufferIndex, dispatchShadingChangePassX, dispatchShadingChangePassY); + _prepareReactivityPass.ScheduleDispatch(commandBuffer, dispatchParams, bufferIndex, dispatchSrcX, dispatchSrcY); + _lumaInstabilityPass.ScheduleDispatch(commandBuffer, dispatchParams, bufferIndex, dispatchSrcX, dispatchSrcY); - _accumulatePass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchDstX, dispatchDstY); + _accumulatePass.ScheduleDispatch(commandBuffer, dispatchParams, bufferIndex, dispatchDstX, dispatchDstY); if (dispatchParams.EnableSharpening) { // Compute the constants SetupRcasConstants(dispatchParams); - commandBuffer.SetBufferData(_rcasConstantsBuffer, _rcasConstantsArray); + _rcasConstants.UpdateBufferData(commandBuffer); // Dispatch RCAS const int threadGroupWorkRegionDimRcas = 16; - int threadGroupsX = (UpscalerConsts.upscaleSize.x + threadGroupWorkRegionDimRcas - 1) / threadGroupWorkRegionDimRcas; - int threadGroupsY = (UpscalerConsts.upscaleSize.y + threadGroupWorkRegionDimRcas - 1) / threadGroupWorkRegionDimRcas; - _sharpenPass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, threadGroupsX, threadGroupsY); + int threadGroupsX = (upscaleSize.x + threadGroupWorkRegionDimRcas - 1) / threadGroupWorkRegionDimRcas; + int threadGroupsY = (upscaleSize.y + threadGroupWorkRegionDimRcas - 1) / threadGroupWorkRegionDimRcas; + _sharpenPass.ScheduleDispatch(commandBuffer, dispatchParams, bufferIndex, threadGroupsX, threadGroupsY); } #if UNITY_EDITOR || DEVELOPMENT_BUILD if ((dispatchParams.Flags & Fsr3Upscaler.DispatchFlags.DrawDebugView) != 0) { - _debugViewPass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchDstX, dispatchDstY); + _debugViewPass.ScheduleDispatch(commandBuffer, dispatchParams, bufferIndex, dispatchDstX, dispatchDstY); } #endif @@ -293,6 +286,7 @@ namespace FidelityFX.FSR3 Fsr3UpscalerResources.DestroyAliasableResources(commandBuffer); commandBuffer.DisableShaderKeyword("UNITY_FSR_TEXTURE2D_X_ARRAY"); + commandBuffer.EndSample(_sampler); } public void GenerateReactiveMask(Fsr3Upscaler.GenerateReactiveDescription dispatchParams) @@ -308,11 +302,12 @@ namespace FidelityFX.FSR3 int dispatchSrcX = (dispatchParams.RenderSize.x + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; int dispatchSrcY = (dispatchParams.RenderSize.y + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; - GenReactiveConsts.scale = dispatchParams.Scale; - GenReactiveConsts.threshold = dispatchParams.CutoffThreshold; - GenReactiveConsts.binaryValue = dispatchParams.BinaryValue; - GenReactiveConsts.flags = (uint)dispatchParams.Flags; - commandBuffer.SetBufferData(_generateReactiveConstantsBuffer, _generateReactiveConstantsArray); + ref var genReactiveConsts = ref _generateReactiveConstants.Value; + genReactiveConsts.scale = dispatchParams.Scale; + genReactiveConsts.threshold = dispatchParams.CutoffThreshold; + genReactiveConsts.binaryValue = dispatchParams.BinaryValue; + genReactiveConsts.flags = (uint)dispatchParams.Flags; + _generateReactiveConstants.UpdateBufferData(commandBuffer); ((Fsr3UpscalerGenerateReactivePass)_generateReactivePass).ScheduleDispatch(commandBuffer, dispatchParams, dispatchSrcX, dispatchSrcY); } @@ -323,18 +318,19 @@ namespace FidelityFX.FSR3 int dispatchSrcX = (dispatchParams.RenderSize.x + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; int dispatchSrcY = (dispatchParams.RenderSize.y + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim; - TcrAutoGenConsts.autoTcThreshold = dispatchParams.AutoTcThreshold; - TcrAutoGenConsts.autoTcScale = dispatchParams.AutoTcScale; - TcrAutoGenConsts.autoReactiveScale = dispatchParams.AutoReactiveScale; - TcrAutoGenConsts.autoReactiveMax = dispatchParams.AutoReactiveMax; - commandBuffer.SetBufferData(_tcrAutogenerateConstantsBuffer, _tcrAutogenerateConstantsArray); + ref var tcrAutoGenConsts = ref _tcrAutogenerateConstants.Value; + tcrAutoGenConsts.autoTcThreshold = dispatchParams.AutoTcThreshold; + tcrAutoGenConsts.autoTcScale = dispatchParams.AutoTcScale; + tcrAutoGenConsts.autoReactiveScale = dispatchParams.AutoReactiveScale; + tcrAutoGenConsts.autoReactiveMax = dispatchParams.AutoReactiveMax; + _tcrAutogenerateConstants.UpdateBufferData(commandBuffer); _tcrAutogeneratePass.ScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchSrcX, dispatchSrcY); } private void SetupConstants(Fsr3Upscaler.DispatchDescription dispatchParams, bool resetAccumulation) { - ref Fsr3Upscaler.UpscalerConstants constants = ref UpscalerConsts; + ref Fsr3Upscaler.UpscalerConstants constants = ref _upscalerConstants.Value; constants.previousFrameJitterOffset = constants.jitterOffset; constants.jitterOffset = dispatchParams.JitterOffset; @@ -350,7 +346,10 @@ namespace FidelityFX.FSR3 constants.viewSpaceToMetersFactor = (dispatchParams.ViewSpaceToMetersFactor > 0.0f) ? dispatchParams.ViewSpaceToMetersFactor : 1.0f; // Compute params to enable device depth to view space depth computation in shader - constants.deviceToViewDepth = SetupDeviceDepthToViewSpaceDepthParams(dispatchParams); + bool inverted = (_contextDescription.Flags & Fsr3Upscaler.InitializationFlags.EnableDepthInverted) != 0; + bool infinite = (_contextDescription.Flags & Fsr3Upscaler.InitializationFlags.EnableDepthInfinite) != 0; + constants.deviceToViewDepth = FfxUtils.SetupDeviceDepthToViewSpaceDepthParams( + dispatchParams.RenderSize, dispatchParams.CameraNear, dispatchParams.CameraFar, dispatchParams.CameraFovAngleVertical, inverted, infinite); constants.previousFrameUpscaleSize = constants.upscaleSize; if (dispatchParams.UpscaleSize.x == 0 && dispatchParams.UpscaleSize.y == 0) @@ -386,7 +385,7 @@ namespace FidelityFX.FSR3 _previousJitterOffset = constants.jitterOffset; } - int jitterPhaseCount = Fsr3Upscaler.GetJitterPhaseCount(dispatchParams.RenderSize.x, _contextDescription.MaxUpscaleSize.x); + int jitterPhaseCount = FfxUtils.GetJitterPhaseCount(dispatchParams.RenderSize.x, _contextDescription.MaxUpscaleSize.x); if (resetAccumulation || constants.jitterPhaseCount == 0) { constants.jitterPhaseCount = jitterPhaseCount; @@ -408,78 +407,22 @@ namespace FidelityFX.FSR3 else constants.frameIndex += 1.0f; } - - private Vector4 SetupDeviceDepthToViewSpaceDepthParams(Fsr3Upscaler.DispatchDescription dispatchParams) - { - bool inverted = (_contextDescription.Flags & Fsr3Upscaler.InitializationFlags.EnableDepthInverted) != 0; - bool infinite = (_contextDescription.Flags & Fsr3Upscaler.InitializationFlags.EnableDepthInfinite) != 0; - - // make sure it has no impact if near and far plane values are swapped in dispatch params - // the flags "inverted" and "infinite" will decide what transform to use - float min = Mathf.Min(dispatchParams.CameraNear, dispatchParams.CameraFar); - float max = Mathf.Max(dispatchParams.CameraNear, dispatchParams.CameraFar); - - if (inverted) - { - (min, max) = (max, min); - } - - float q = max / (min - max); - float d = -1.0f; - - Vector4 matrixElemC = new Vector4(q, -1.0f - Mathf.Epsilon, q, 0.0f + Mathf.Epsilon); - Vector4 matrixElemE = new Vector4(q * min, -min - Mathf.Epsilon, q * min, max); - - // Revert x and y coords - float aspect = (float)dispatchParams.RenderSize.x / dispatchParams.RenderSize.y; - float cotHalfFovY = Mathf.Cos(0.5f * dispatchParams.CameraFovAngleVertical) / Mathf.Sin(0.5f * dispatchParams.CameraFovAngleVertical); - - int matrixIndex = (inverted ? 2 : 0) + (infinite ? 1 : 0); - return new Vector4( - d * matrixElemC[matrixIndex], - matrixElemE[matrixIndex], - aspect / cotHalfFovY, - 1.0f / cotHalfFovY); - } private void SetupRcasConstants(Fsr3Upscaler.DispatchDescription dispatchParams) { int sharpnessIndex = Mathf.RoundToInt(Mathf.Clamp01(dispatchParams.Sharpness) * (RcasConfigs.Length - 1)); - RcasConsts = RcasConfigs[sharpnessIndex]; + _rcasConstants.Value = RcasConfigs[sharpnessIndex]; } private void SetupSpdConstants(Fsr3Upscaler.DispatchDescription dispatchParams, out Vector2Int dispatchThreadGroupCount) { - RectInt rectInfo = new RectInt(0, 0, dispatchParams.RenderSize.x, dispatchParams.RenderSize.y); - SpdSetup(rectInfo, out dispatchThreadGroupCount, out var workGroupOffset, out var numWorkGroupsAndMips); - // Downsample - ref Fsr3Upscaler.SpdConstants spdConstants = ref SpdConsts; - spdConstants.numWorkGroups = (uint)numWorkGroupsAndMips.x; - spdConstants.mips = (uint)numWorkGroupsAndMips.y; - spdConstants.workGroupOffsetX = (uint)workGroupOffset.x; - spdConstants.workGroupOffsetY = (uint)workGroupOffset.y; + ref Fsr3Upscaler.SpdConstants spdConstants = ref _spdConstants.Value; + FfxSpd.SetupSpdConstants(dispatchParams.RenderSize, ref spdConstants.spd, out dispatchThreadGroupCount); spdConstants.renderSizeX = (uint)dispatchParams.RenderSize.x; spdConstants.renderSizeY = (uint)dispatchParams.RenderSize.y; } - private static void SpdSetup(RectInt rectInfo, out Vector2Int dispatchThreadGroupCount, out Vector2Int workGroupOffset, out Vector2Int numWorkGroupsAndMips, int mips = -1) - { - workGroupOffset = new Vector2Int(rectInfo.x / 64, rectInfo.y / 64); - - int endIndexX = (rectInfo.x + rectInfo.width - 1) / 64; - int endIndexY = (rectInfo.y + rectInfo.height - 1) / 64; - - dispatchThreadGroupCount = new Vector2Int(endIndexX + 1 - workGroupOffset.x, endIndexY + 1 - workGroupOffset.y); - - numWorkGroupsAndMips = new Vector2Int(dispatchThreadGroupCount.x * dispatchThreadGroupCount.y, mips); - if (mips < 0) - { - float resolution = Math.Max(rectInfo.width, rectInfo.height); - numWorkGroupsAndMips.y = Math.Min(Mathf.FloorToInt(Mathf.Log(resolution, 2.0f)), 12); - } - } - private void DebugCheckDispatch(Fsr3Upscaler.DispatchDescription dispatchParams) { if (!dispatchParams.Color.IsValid) @@ -630,28 +573,5 @@ namespace FidelityFX.FSR3 new Fsr3Upscaler.RcasConstants(1064229695u, 997604214u), new Fsr3Upscaler.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 Fsr3UpscalerPass pass) - { - if (pass == null) - return; - - pass.Dispose(); - pass = null; - } } } diff --git a/Runtime/FSR3/Fsr3UpscalerPass.cs b/Runtime/FSR3/Fsr3UpscalerPass.cs index 3b76eb4..941971c 100644 --- a/Runtime/FSR3/Fsr3UpscalerPass.cs +++ b/Runtime/FSR3/Fsr3UpscalerPass.cs @@ -18,10 +18,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -using System; -using System.Runtime.InteropServices; using UnityEngine; -using UnityEngine.Profiling; using UnityEngine.Rendering; namespace FidelityFX.FSR3 @@ -31,53 +28,27 @@ namespace FidelityFX.FSR3 /// This loosely matches the FfxPipelineState struct from the original FSR3 codebase, wrapped in an object-oriented blanket. /// These classes are responsible for loading compute shaders, managing temporary resources, binding resources to shader kernels and dispatching said shaders. /// - internal abstract class Fsr3UpscalerPass: IDisposable + internal abstract class Fsr3UpscalerPass: FfxPassWithFlags { protected readonly Fsr3Upscaler.ContextDescription ContextDescription; protected readonly Fsr3UpscalerResources Resources; protected readonly ComputeBuffer Constants; - protected ComputeShader ComputeShader; - protected int KernelIndex; - - protected CustomSampler Sampler; - protected Fsr3UpscalerPass(Fsr3Upscaler.ContextDescription contextDescription, Fsr3UpscalerResources resources, ComputeBuffer constants) + : base("FSR3 Upscaler") { ContextDescription = contextDescription; Resources = resources; Constants = constants; } - - public virtual void Dispose() - { - } - - public void ScheduleDispatch(CommandBuffer commandBuffer, Fsr3Upscaler.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY) - { - commandBuffer.BeginSample(Sampler); - DoScheduleDispatch(commandBuffer, dispatchParams, frameIndex, dispatchX, dispatchY); - commandBuffer.EndSample(Sampler); - } - - protected abstract void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr3Upscaler.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY); protected void InitComputeShader(string passName, ComputeShader shader) { InitComputeShader(passName, shader, ContextDescription.Flags); } - private void InitComputeShader(string passName, ComputeShader shader, Fsr3Upscaler.InitializationFlags flags) + protected override void SetupShaderKeywords(Fsr3Upscaler.InitializationFlags flags) { - if (shader == null) - { - throw new MissingReferenceException($"Shader for FSR3 Upscaler pass '{passName}' could not be loaded! Please ensure it is included in the project correctly."); - } - - ComputeShader = shader; - KernelIndex = ComputeShader.FindKernel("CS"); - Sampler = CustomSampler.Create(passName); - bool useLut = false; #if UNITY_2022_1_OR_NEWER // This will also work in 2020.3.43+ and 2021.3.14+ if (SystemInfo.computeSubGroupSize == 64) @@ -104,25 +75,21 @@ namespace FidelityFX.FSR3 InitComputeShader("Prepare Inputs", contextDescription.Shaders.prepareInputsPass); } - protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr3Upscaler.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY) + protected override void DoScheduleDispatch(CommandBuffer commandBuffer, in Fsr3Upscaler.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ) { - ref var color = ref dispatchParams.Color; - ref var depth = ref dispatchParams.Depth; - ref var motionVectors = ref dispatchParams.MotionVectors; - - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputColor, color.RenderTarget, color.MipLevel, color.SubElement); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputDepth, depth.RenderTarget, depth.MipLevel, depth.SubElement); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputMotionVectors, motionVectors.RenderTarget, motionVectors.MipLevel, motionVectors.SubElement); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputColor, dispatchParams.Color); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputDepth, dispatchParams.Depth); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputMotionVectors, dispatchParams.MotionVectors); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavDilatedMotionVectors, Resources.DilatedVelocity); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavDilatedDepth, Resources.DilatedDepth); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavReconstructedPrevNearestDepth, Resources.ReconstructedPrevNearestDepth); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavFarthestDepth, Fsr3ShaderIDs.UavIntermediate); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavCurrentLuma, Resources.Luma[frameIndex]); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavCurrentLuma, Resources.Luma[bufferIndex]); - commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants, 0, Marshal.SizeOf()); + commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants); - commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1); + commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, dispatchZ); } } @@ -138,24 +105,24 @@ namespace FidelityFX.FSR3 InitComputeShader("Compute Luminance Pyramid", contextDescription.Shaders.lumaPyramidPass); } - protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr3Upscaler.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY) + protected override void DoScheduleDispatch(CommandBuffer commandBuffer, in Fsr3Upscaler.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ) { - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvCurrentLuma, Resources.Luma[frameIndex]); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvCurrentLuma, Resources.Luma[bufferIndex]); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvFarthestDepth, Fsr3ShaderIDs.UavIntermediate); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdAtomicCount, Resources.SpdAtomicCounter); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavFrameInfo, Resources.FrameInfo); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip0, Resources.SpdMips, 0); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip1, Resources.SpdMips, 1); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip2, Resources.SpdMips, 2); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip3, Resources.SpdMips, 3); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip4, Resources.SpdMips, 4); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip5, Resources.SpdMips, 5); + commandBuffer.SetComputeTextureMipParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip0, Resources.SpdMips, 0); + commandBuffer.SetComputeTextureMipParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip1, Resources.SpdMips, 1); + commandBuffer.SetComputeTextureMipParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip2, Resources.SpdMips, 2); + commandBuffer.SetComputeTextureMipParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip3, Resources.SpdMips, 3); + commandBuffer.SetComputeTextureMipParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip4, Resources.SpdMips, 4); + commandBuffer.SetComputeTextureMipParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip5, Resources.SpdMips, 5); - commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants, 0, Marshal.SizeOf()); - commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbSpd, _spdConstants, 0, Marshal.SizeOf()); + commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants); + commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbSpd, _spdConstants); - commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1); + commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, dispatchZ); } } @@ -171,27 +138,25 @@ namespace FidelityFX.FSR3 InitComputeShader("Compute Shading Change Pyramid", contextDescription.Shaders.shadingChangePyramidPass); } - protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr3Upscaler.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY) + protected override void DoScheduleDispatch(CommandBuffer commandBuffer, in Fsr3Upscaler.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ) { - ref var exposure = ref dispatchParams.Exposure; - - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvCurrentLuma, Resources.Luma[frameIndex]); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvPreviousLuma, Resources.Luma[frameIndex ^ 1]); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvCurrentLuma, Resources.Luma[bufferIndex]); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvPreviousLuma, Resources.Luma[bufferIndex ^ 1]); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvDilatedMotionVectors, Resources.DilatedVelocity); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputExposure, exposure.RenderTarget, exposure.MipLevel, exposure.SubElement); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputExposure, dispatchParams.Exposure); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdAtomicCount, Resources.SpdAtomicCounter); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip0, Resources.SpdMips, 0); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip1, Resources.SpdMips, 1); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip2, Resources.SpdMips, 2); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip3, Resources.SpdMips, 3); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip4, Resources.SpdMips, 4); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip5, Resources.SpdMips, 5); + commandBuffer.SetComputeTextureMipParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip0, Resources.SpdMips, 0); + commandBuffer.SetComputeTextureMipParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip1, Resources.SpdMips, 1); + commandBuffer.SetComputeTextureMipParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip2, Resources.SpdMips, 2); + commandBuffer.SetComputeTextureMipParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip3, Resources.SpdMips, 3); + commandBuffer.SetComputeTextureMipParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip4, Resources.SpdMips, 4); + commandBuffer.SetComputeTextureMipParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdMip5, Resources.SpdMips, 5); - commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants, 0, Marshal.SizeOf()); - commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbSpd, _spdConstants, 0, Marshal.SizeOf()); + commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants); + commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbSpd, _spdConstants); - commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1); + commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, dispatchZ); } } @@ -203,13 +168,13 @@ namespace FidelityFX.FSR3 InitComputeShader("Compute Shading Change", contextDescription.Shaders.shadingChangePass); } - protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr3Upscaler.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY) + protected override void DoScheduleDispatch(CommandBuffer commandBuffer, in Fsr3Upscaler.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ) { commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvSpdMips, Resources.SpdMips); - commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants, 0, Marshal.SizeOf()); + commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants); - commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1); + commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, dispatchZ); } } @@ -221,27 +186,23 @@ namespace FidelityFX.FSR3 InitComputeShader("Prepare Reactivity", contextDescription.Shaders.prepareReactivityPass); } - protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr3Upscaler.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY) + protected override void DoScheduleDispatch(CommandBuffer commandBuffer, in Fsr3Upscaler.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ) { - ref var exposure = ref dispatchParams.Exposure; - ref var reactive = ref dispatchParams.Reactive; - ref var tac = ref dispatchParams.TransparencyAndComposition; - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvReconstructedPrevNearestDepth, Resources.ReconstructedPrevNearestDepth); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvDilatedMotionVectors, Resources.DilatedVelocity); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvDilatedDepth, Resources.DilatedDepth); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvReactiveMask, reactive.RenderTarget, reactive.MipLevel, reactive.SubElement); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvTransparencyAndCompositionMask, tac.RenderTarget, tac.MipLevel, tac.SubElement); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvAccumulation, Resources.Accumulation[frameIndex ^ 1]); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvReactiveMask, dispatchParams.Reactive); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvTransparencyAndCompositionMask, dispatchParams.TransparencyAndComposition); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvAccumulation, Resources.Accumulation[bufferIndex ^ 1]); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvShadingChange, Fsr3ShaderIDs.UavShadingChange); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvCurrentLuma, Resources.Luma[frameIndex]); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputExposure, exposure.RenderTarget, exposure.MipLevel, exposure.SubElement); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvCurrentLuma, Resources.Luma[bufferIndex]); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputExposure, dispatchParams.Exposure); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavAccumulation, Resources.Accumulation[frameIndex]); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavAccumulation, Resources.Accumulation[bufferIndex]); - commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants, 0, Marshal.SizeOf()); + commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants); - commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1); + commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, dispatchZ); } } @@ -253,24 +214,22 @@ namespace FidelityFX.FSR3 InitComputeShader("Compute Luminance Instability", contextDescription.Shaders.lumaInstabilityPass); } - protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr3Upscaler.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY) + protected override void DoScheduleDispatch(CommandBuffer commandBuffer, in Fsr3Upscaler.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ) { - ref var exposure = ref dispatchParams.Exposure; - - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputExposure, exposure.RenderTarget, exposure.MipLevel, exposure.SubElement); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputExposure, dispatchParams.Exposure); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvDilatedReactiveMasks, Fsr3ShaderIDs.UavDilatedReactiveMasks); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvDilatedMotionVectors, Resources.DilatedVelocity); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvFrameInfo, Resources.FrameInfo); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvLumaHistory, Resources.LumaHistory[frameIndex ^ 1]); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvLumaHistory, Resources.LumaHistory[bufferIndex ^ 1]); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvFarthestDepthMip1, Fsr3ShaderIDs.UavFarthestDepthMip1); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvCurrentLuma, Resources.Luma[frameIndex]); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvCurrentLuma, Resources.Luma[bufferIndex]); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavLumaHistory, Resources.LumaHistory[frameIndex]); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavLumaHistory, Resources.LumaHistory[bufferIndex]); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavLumaInstability, Fsr3ShaderIDs.UavIntermediate); - commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants, 0, Marshal.SizeOf()); + commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants); - commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1); + commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, dispatchZ); } } @@ -291,7 +250,7 @@ namespace FidelityFX.FSR3 #endif } - protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr3Upscaler.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY) + protected override void DoScheduleDispatch(CommandBuffer commandBuffer, in Fsr3Upscaler.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ) { #if UNITY_2021_2_OR_NEWER if (dispatchParams.EnableSharpening) @@ -305,11 +264,7 @@ namespace FidelityFX.FSR3 commandBuffer.DisableShaderKeyword(SharpeningKeyword); #endif - ref var color = ref dispatchParams.Color; - ref var exposure = ref dispatchParams.Exposure; - ref var output = ref dispatchParams.Output; - - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputExposure, exposure.RenderTarget, exposure.MipLevel, exposure.SubElement); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputExposure, dispatchParams.Exposure); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvDilatedReactiveMasks, Fsr3ShaderIDs.UavDilatedReactiveMasks); if ((ContextDescription.Flags & Fsr3Upscaler.InitializationFlags.EnableDisplayResolutionMotionVectors) == 0) @@ -318,23 +273,22 @@ namespace FidelityFX.FSR3 } else { - ref var motionVectors = ref dispatchParams.MotionVectors; - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputMotionVectors, motionVectors.RenderTarget, motionVectors.MipLevel, motionVectors.SubElement); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputMotionVectors, dispatchParams.MotionVectors); } - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInternalUpscaled, Resources.InternalUpscaled[frameIndex ^ 1]); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInternalUpscaled, Resources.InternalUpscaled[bufferIndex ^ 1]); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvLanczosLut, Resources.LanczosLut); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvFarthestDepthMip1, Fsr3ShaderIDs.UavFarthestDepthMip1); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvCurrentLuma, Resources.Luma[frameIndex]); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvCurrentLuma, Resources.Luma[bufferIndex]); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvLumaInstability, Fsr3ShaderIDs.UavIntermediate); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputColor, color.RenderTarget, color.MipLevel, color.SubElement); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputColor, dispatchParams.Color); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavInternalUpscaled, Resources.InternalUpscaled[frameIndex]); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavUpscaledOutput, output.RenderTarget, output.MipLevel, output.SubElement); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavInternalUpscaled, Resources.InternalUpscaled[bufferIndex]); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavUpscaledOutput, dispatchParams.Output); - commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants, 0, Marshal.SizeOf()); + commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants); - commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1); + commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, dispatchZ); } } @@ -350,19 +304,17 @@ namespace FidelityFX.FSR3 InitComputeShader("RCAS Sharpening", contextDescription.Shaders.sharpenPass); } - protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr3Upscaler.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY) + protected override void DoScheduleDispatch(CommandBuffer commandBuffer, in Fsr3Upscaler.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ) { - ref var exposure = ref dispatchParams.Exposure; - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputExposure, exposure.RenderTarget, exposure.MipLevel, exposure.SubElement); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvRcasInput, Resources.InternalUpscaled[frameIndex]); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputExposure, dispatchParams.Exposure); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvRcasInput, Resources.InternalUpscaled[bufferIndex]); - ref var output = ref dispatchParams.Output; - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavUpscaledOutput, output.RenderTarget, output.MipLevel, output.SubElement); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavUpscaledOutput, dispatchParams.Output); - commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants, 0, Marshal.SizeOf()); - commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbRcas, _rcasConstants, 0, Marshal.SizeOf()); + commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants); + commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbRcas, _rcasConstants); - commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1); + commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, dispatchZ); } } @@ -378,7 +330,7 @@ namespace FidelityFX.FSR3 InitComputeShader("Auto-Generate Reactive Mask", contextDescription.Shaders.autoGenReactivePass); } - protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr3Upscaler.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY) + protected override void DoScheduleDispatch(CommandBuffer commandBuffer, in Fsr3Upscaler.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ) { } @@ -386,15 +338,11 @@ namespace FidelityFX.FSR3 { commandBuffer.BeginSample(Sampler); - ref var opaqueOnly = ref dispatchParams.ColorOpaqueOnly; - ref var color = ref dispatchParams.ColorPreUpscale; - ref var reactive = ref dispatchParams.OutReactive; + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvOpaqueOnly, dispatchParams.ColorOpaqueOnly); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputColor, dispatchParams.ColorPreUpscale); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavAutoReactive, dispatchParams.OutReactive); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvOpaqueOnly, opaqueOnly.RenderTarget, opaqueOnly.MipLevel, opaqueOnly.SubElement); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputColor, color.RenderTarget, color.MipLevel, color.SubElement); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavAutoReactive, reactive.RenderTarget, reactive.MipLevel, reactive.SubElement); - - commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbGenReactive, _generateReactiveConstants, 0, Marshal.SizeOf()); + commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbGenReactive, _generateReactiveConstants); commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1); @@ -414,31 +362,25 @@ namespace FidelityFX.FSR3 InitComputeShader("Auto-Generate Transparency & Composition Mask", contextDescription.Shaders.tcrAutoGenPass); } - protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr3Upscaler.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY) + protected override void DoScheduleDispatch(CommandBuffer commandBuffer, in Fsr3Upscaler.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ) { - ref var color = ref dispatchParams.Color; - ref var motionVectors = ref dispatchParams.MotionVectors; - ref var opaqueOnly = ref dispatchParams.ColorOpaqueOnly; - ref var reactive = ref dispatchParams.Reactive; - ref var tac = ref dispatchParams.TransparencyAndComposition; - - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvOpaqueOnly, opaqueOnly.RenderTarget, opaqueOnly.MipLevel, opaqueOnly.SubElement); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputColor, color.RenderTarget, color.MipLevel, color.SubElement); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputMotionVectors, motionVectors.RenderTarget, motionVectors.MipLevel, motionVectors.SubElement); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvPrevColorPreAlpha, Resources.PrevPreAlpha[frameIndex ^ 1]); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvPrevColorPostAlpha, Resources.PrevPostAlpha[frameIndex ^ 1]); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvReactiveMask, reactive.RenderTarget, reactive.MipLevel, reactive.SubElement); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvTransparencyAndCompositionMask, tac.RenderTarget, tac.MipLevel, tac.SubElement); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvOpaqueOnly, dispatchParams.ColorOpaqueOnly); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputColor, dispatchParams.Color); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputMotionVectors, dispatchParams.MotionVectors); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvPrevColorPreAlpha, Resources.PrevPreAlpha[bufferIndex ^ 1]); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvPrevColorPostAlpha, Resources.PrevPostAlpha[bufferIndex ^ 1]); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvReactiveMask, dispatchParams.Reactive); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvTransparencyAndCompositionMask, dispatchParams.TransparencyAndComposition); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavAutoReactive, Resources.AutoReactive); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavAutoComposition, Resources.AutoComposition); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavPrevColorPreAlpha, Resources.PrevPreAlpha[frameIndex]); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavPrevColorPostAlpha, Resources.PrevPostAlpha[frameIndex]); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavPrevColorPreAlpha, Resources.PrevPreAlpha[bufferIndex]); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavPrevColorPostAlpha, Resources.PrevPostAlpha[bufferIndex]); - commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants, 0, Marshal.SizeOf()); - commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbGenReactive, _tcrAutogenerateConstants, 0, Marshal.SizeOf()); + commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants); + commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbGenReactive, _tcrAutogenerateConstants); - commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1); + commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, dispatchZ); } } @@ -451,21 +393,19 @@ namespace FidelityFX.FSR3 InitComputeShader("Debug View", contextDescription.Shaders.debugViewPass); } - protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Fsr3Upscaler.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY) + protected override void DoScheduleDispatch(CommandBuffer commandBuffer, in Fsr3Upscaler.DispatchDescription dispatchParams, int bufferIndex, int dispatchX, int dispatchY, int dispatchZ) { - ref var exposure = ref dispatchParams.Exposure; commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvDilatedReactiveMasks, Fsr3ShaderIDs.UavDilatedReactiveMasks); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvDilatedMotionVectors, Resources.DilatedVelocity); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvDilatedDepth, Resources.DilatedDepth); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInternalUpscaled, Resources.InternalUpscaled[frameIndex]); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputExposure, exposure.RenderTarget, exposure.MipLevel, exposure.SubElement); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInternalUpscaled, Resources.InternalUpscaled[bufferIndex]); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputExposure, dispatchParams.Exposure); - ref var output = ref dispatchParams.Output; - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavUpscaledOutput, output.RenderTarget, output.MipLevel, output.SubElement); + commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavUpscaledOutput, dispatchParams.Output); - commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants, 0, Marshal.SizeOf()); + commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr3ShaderIDs.CbFsr3Upscaler, Constants); - commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, 1); + commandBuffer.DispatchCompute(ComputeShader, KernelIndex, dispatchX, dispatchY, dispatchZ); } } #endif diff --git a/Runtime/FSR3/Fsr3UpscalerResources.cs b/Runtime/FSR3/Fsr3UpscalerResources.cs index 112b98d..6a5f33d 100644 --- a/Runtime/FSR3/Fsr3UpscalerResources.cs +++ b/Runtime/FSR3/Fsr3UpscalerResources.cs @@ -29,7 +29,7 @@ namespace FidelityFX.FSR3 /// Helper class for bundling and managing persistent resources required by the FSR3 Upscaler process. /// This includes lookup tables, default fallback resources and double-buffered resources that get swapped between frames. /// - internal class Fsr3UpscalerResources + internal class Fsr3UpscalerResources: FfxResourcesBase { public Texture2D LanczosLut; public Texture2D DefaultExposure; @@ -55,59 +55,40 @@ namespace FidelityFX.FSR3 { // Generate the data for the LUT const int lanczos2LutWidth = 128; - float[] lanczos2Weights = new float[lanczos2LutWidth]; - for (int currentLanczosWidthIndex = 0; currentLanczosWidthIndex < lanczos2LutWidth; ++currentLanczosWidthIndex) - { - float x = 2.0f * currentLanczosWidthIndex / (lanczos2LutWidth - 1); - float y = Fsr3Upscaler.Lanczos2(x); - lanczos2Weights[currentLanczosWidthIndex] = y; - } + float[] lanczos2Weights = FfxUtils.GenerateLanczos2Table(lanczos2LutWidth); Vector2Int maxRenderSize = contextDescription.MaxRenderSize; Vector2Int maxRenderSizeDiv2 = maxRenderSize / 2; // Resource FSR3UPSCALER_LanczosLutData: FFX_RESOURCE_USAGE_READ_ONLY, FFX_SURFACE_FORMAT_R16_SNORM, FFX_RESOURCE_FLAGS_NONE // R16_SNorm textures are not supported by Unity on most platforms, strangely enough. So instead we use R32_SFloat and upload pre-normalized float data. - LanczosLut = new Texture2D(lanczos2LutWidth, 1, GraphicsFormat.R32_SFloat, TextureCreationFlags.None) { name = "FSR3UPSCALER_LanczosLutData" }; - LanczosLut.SetPixelData(lanczos2Weights, 0); - LanczosLut.Apply(); + LanczosLut = CreateLookup("FSR3UPSCALER_LanczosLutData", new Vector2Int(lanczos2LutWidth, 1), GraphicsFormat.R32_SFloat, lanczos2Weights); // Resource FSR3UPSCALER_DefaultReactivityMask: FFX_RESOURCE_USAGE_READ_ONLY, FFX_SURFACE_FORMAT_R8_UNORM, FFX_RESOURCE_FLAGS_NONE - DefaultReactive = new Texture2D(1, 1, GraphicsFormat.R8_UNorm, TextureCreationFlags.None) { name = "FSR3UPSCALER_DefaultReactivityMask" }; - DefaultReactive.SetPixel(0, 0, Color.clear); - DefaultReactive.Apply(); + DefaultReactive = CreateLookup("FSR3UPSCALER_DefaultReactivityMask", GraphicsFormat.R8_UNorm, Color.clear); // Resource FSR3UPSCALER_DefaultExposure: FFX_RESOURCE_USAGE_READ_ONLY, FFX_SURFACE_FORMAT_R32G32_FLOAT, FFX_RESOURCE_FLAGS_NONE - DefaultExposure = new Texture2D(1, 1, GraphicsFormat.R32G32_SFloat, TextureCreationFlags.None) { name = "FSR3UPSCALER_DefaultExposure" }; - DefaultExposure.SetPixel(0, 0, Color.clear); - DefaultExposure.Apply(); + DefaultExposure = CreateLookup("FSR3UPSCALER_DefaultExposure", GraphicsFormat.R32G32_SFloat, Color.clear); // Resource FSR3UPSCALER_SpdAtomicCounter: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R32_UINT, FFX_RESOURCE_FLAGS_ALIASABLE // Despite what the original FSR3 codebase says, this resource really isn't aliasable. Resetting this counter to 0 every frame breaks auto-exposure on MacOS Metal. - SpdAtomicCounter = new RenderTexture(1, 1, 0, GraphicsFormat.R32_UInt) { name = "FSR3UPSCALER_SpdAtomicCounter", enableRandomWrite = true }; - SpdAtomicCounter.Create(); + SpdAtomicCounter = CreateResource("FSR3UPSCALER_SpdAtomicCounter", Vector2Int.one, GraphicsFormat.R32_UInt); // Resource FSR3UPSCALER_SpdMips: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R16G16_FLOAT, FFX_RESOURCE_FLAGS_ALIASABLE // This is a rather special case: it's an aliasable resource, but because we require a mipmap chain and bind specific mip levels per shader, we can't easily use temporary RTs for this. - int mipCount = 1 + Mathf.FloorToInt(Mathf.Log(Math.Max(maxRenderSizeDiv2.x, maxRenderSizeDiv2.y), 2.0f)); - SpdMips = new RenderTexture(maxRenderSizeDiv2.x, maxRenderSizeDiv2.y, 0, GraphicsFormat.R16G16_SFloat, mipCount) { name = "FSR3UPSCALER_SpdMips", enableRandomWrite = true, useMipMap = true, autoGenerateMips = false }; - SpdMips.Create(); + SpdMips = CreateResourceMips("FSR3UPSCALER_SpdMips", maxRenderSizeDiv2, GraphicsFormat.R16G16_SFloat); // Resource FSR3UPSCALER_DilatedVelocity: FFX_RESOURCE_USAGE_RENDERTARGET | FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R16G16_FLOAT, FFX_RESOURCE_FLAGS_NONE - DilatedVelocity = new RenderTexture(maxRenderSize.x, maxRenderSize.y, 0, GraphicsFormat.R16G16_SFloat) { name = "FSR3UPSCALER_DilatedVelocity", enableRandomWrite = true }; - DilatedVelocity.Create(); + DilatedVelocity = CreateResource("FSR3UPSCALER_DilatedVelocity", maxRenderSize, GraphicsFormat.R16G16_SFloat); // Resource FSR3UPSCALER_DilatedDepth: FFX_RESOURCE_USAGE_RENDERTARGET | FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R32_FLOAT, FFX_RESOURCE_FLAGS_NONE - DilatedDepth = new RenderTexture(maxRenderSize.x, maxRenderSize.y, 0, GraphicsFormat.R32_SFloat) { name = "FSR3UPSCALER_DilatedDepth", enableRandomWrite = true }; - DilatedDepth.Create(); + DilatedDepth = CreateResource("FSR3UPSCALER_DilatedDepth", maxRenderSize, GraphicsFormat.R32_SFloat); // Resource FSR3UPSCALER_ReconstructedPrevNearestDepth: FFX_RESOURCE_USAGE_RENDERTARGET | FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R32_UINT, FFX_RESOURCE_FLAGS_NONE - ReconstructedPrevNearestDepth = new RenderTexture(maxRenderSize.x, maxRenderSize.y, 0, GraphicsFormat.R32_UInt) { name = "FSR3UPSCALER_ReconstructedPrevNearestDepth", enableRandomWrite = true }; - ReconstructedPrevNearestDepth.Create(); + ReconstructedPrevNearestDepth = CreateResource("FSR3UPSCALER_ReconstructedPrevNearestDepth", maxRenderSize, GraphicsFormat.R32_UInt); // Resource FSR3UPSCALER_FrameInfo: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R32G32B32A32_FLOAT, FFX_RESOURCE_FLAGS_NONE - FrameInfo = new RenderTexture(1, 1, 0, GraphicsFormat.R32G32B32A32_SFloat) { name = "FSR3UPSCALER_FrameInfo", enableRandomWrite = true }; - FrameInfo.Create(); + FrameInfo = CreateResource("FSR3UPSCALER_FrameInfo", Vector2Int.one, GraphicsFormat.R32G32B32A32_SFloat); // Resources FSR3UPSCALER_Accumulation1/2: FFX_RESOURCE_USAGE_RENDERTARGET | FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R8_UNORM, FFX_RESOURCE_FLAGS_NONE CreateDoubleBufferedResource(Accumulation, "FSR3UPSCALER_Accumulation", maxRenderSize, GraphicsFormat.R8_UNorm); @@ -125,12 +106,10 @@ namespace FidelityFX.FSR3 public void CreateTcrAutogenResources(Fsr3Upscaler.ContextDescription contextDescription) { // Resource FSR3UPSCALER_AutoReactive: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R8_UNORM, FFX_RESOURCE_FLAGS_NONE - AutoReactive = new RenderTexture(contextDescription.MaxRenderSize.x, contextDescription.MaxRenderSize.y, 0, GraphicsFormat.R8_UNorm) { name = "FSR3UPSCALER_AutoReactive", enableRandomWrite = true }; - AutoReactive.Create(); + AutoReactive = CreateResource("FSR3UPSCALER_AutoReactive", contextDescription.MaxRenderSize, GraphicsFormat.R8_UNorm); // Resource FSR3UPSCALER_AutoComposition: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R8_UNORM, FFX_RESOURCE_FLAGS_NONE - AutoComposition = new RenderTexture(contextDescription.MaxRenderSize.x, contextDescription.MaxRenderSize.y, 0, GraphicsFormat.R8_UNorm) { name = "FSR3UPSCALER_AutoComposition", enableRandomWrite = true }; - AutoComposition.Create(); + AutoComposition = CreateResource("FSR3UPSCALER_AutoComposition", contextDescription.MaxRenderSize, GraphicsFormat.R8_UNorm); // Resources FSR3UPSCALER_PrevPreAlpha0/1: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R11G11B10_FLOAT, FFX_RESOURCE_FLAGS_NONE CreateDoubleBufferedResource(PrevPreAlpha, "FSR3UPSCALER_PrevPreAlpha", contextDescription.MaxRenderSize, GraphicsFormat.B10G11R11_UFloatPack32); @@ -173,15 +152,6 @@ namespace FidelityFX.FSR3 commandBuffer.ReleaseTemporaryRT(Fsr3ShaderIDs.UavIntermediate); } - private static void CreateDoubleBufferedResource(RenderTexture[] resource, string name, Vector2Int size, GraphicsFormat format) - { - for (int i = 0; i < 2; ++i) - { - resource[i] = new RenderTexture(size.x, size.y, 0, format) { name = name + (i + 1), enableRandomWrite = true }; - resource[i].Create(); - } - } - public void Destroy() { DestroyTcrAutogenResources(); @@ -210,36 +180,5 @@ namespace FidelityFX.FSR3 DestroyResource(ref AutoComposition); DestroyResource(ref AutoReactive); } - - private static void DestroyResource(ref Texture2D resource) - { - if (resource == null) - return; - -#if UNITY_EDITOR - if (Application.isPlaying && !UnityEditor.EditorApplication.isPaused) - UnityEngine.Object.Destroy(resource); - else - UnityEngine.Object.DestroyImmediate(resource); -#else - UnityEngine.Object.Destroy(resource); -#endif - resource = null; - } - - private static void DestroyResource(ref RenderTexture resource) - { - if (resource == null) - return; - - resource.Release(); - resource = null; - } - - private static void DestroyResource(RenderTexture[] resource) - { - for (int i = 0; i < resource.Length; ++i) - DestroyResource(ref resource[i]); - } } }