diff --git a/Assets/Scripts/Fsr2Context.cs b/Assets/Scripts/Fsr2Context.cs index 9031ccc..1cf085b 100644 --- a/Assets/Scripts/Fsr2Context.cs +++ b/Assets/Scripts/Fsr2Context.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Runtime.InteropServices; using UnityEngine; -using UnityEngine.Experimental.Rendering; using UnityEngine.Rendering; namespace FidelityFX @@ -24,11 +23,7 @@ namespace FidelityFX private Fsr2Pipeline _generateReactivePipeline; private Fsr2Pipeline _tcrAutogeneratePipeline; - private Texture2D _defaultExposureResource; - private Texture2D _defaultReactiveResource; - private Texture2D _lanczosLutResource; - private RenderTexture _autoExposureResource; - private readonly RenderTexture[] _dilatedMotionVectorResources = new RenderTexture[2]; + private readonly Fsr2Resources _resources = new Fsr2Resources(); private ComputeBuffer _fsr2ConstantsBuffer; private readonly Fsr2.Fsr2Constants[] _fsr2ConstantsArray = { new Fsr2.Fsr2Constants() }; @@ -65,57 +60,10 @@ namespace FidelityFX Constants.displaySize = _contextDescription.DisplaySize; - CreateResources(); + _resources.Create(_contextDescription); CreatePipelines(); } - private void CreateResources() - { - // 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; - } - - // TODO: create resources, i.e. render textures used for intermediate results. - // Note that "aliasable" resources should be equivalent to GetTemporary render textures - // UAVs *may* be an issue with the PS4 not handling simultaneous reading and writing to an RT properly - // Unity does have Graphics.SetRandomWriteTarget for enabling UAV on ComputeBuffers or RTs - // Unity doesn't do 1D textures so just default to Texture2D - - // 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 R16_SFloat and upload pre-normalized float data. - _lanczosLutResource = new Texture2D(lanczos2LutWidth, 1, GraphicsFormat.R16_SFloat, TextureCreationFlags.None) { name = "FSR2_LanczosLutData" }; - _lanczosLutResource.SetPixelData(lanczos2Weights, 0); - _lanczosLutResource.Apply(); - - // Resource FSR2_DefaultExposure: FFX_RESOURCE_USAGE_READ_ONLY, FFX_SURFACE_FORMAT_R32G32_FLOAT, FFX_RESOURCE_FLAGS_NONE - _defaultExposureResource = new Texture2D(1, 1, GraphicsFormat.R32G32_SFloat, TextureCreationFlags.None) { name = "FSR2_DefaultExposure" }; - _defaultExposureResource.SetPixel(0, 0, Color.black); - _defaultExposureResource.Apply(); - - // Resource FSR2_DefaultReactivityMask: FFX_RESOURCE_USAGE_READ_ONLY, FFX_SURFACE_FORMAT_R8_UNORM, FFX_RESOURCE_FLAGS_NONE - _defaultReactiveResource = new Texture2D(1, 1, GraphicsFormat.R8_UNorm, TextureCreationFlags.None) { name = "FSR2_DefaultReactivityMask" }; - _defaultReactiveResource.SetPixel(0, 0, Color.black); - _defaultReactiveResource.Apply(); - - // Resource FSR2_AutoExposure: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R32G32_FLOAT, FFX_RESOURCE_FLAGS_NONE - _autoExposureResource = new RenderTexture(1, 1, 1, GraphicsFormat.R32G32_SFloat) { name = "FSR2_AutoExposure", enableRandomWrite = true }; - _autoExposureResource.Create(); - - // Resources FSR2_InternalDilatedVelocity1/2: FFX_RESOURCE_USAGE_RENDERTARGET | FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R16G16_FLOAT, FFX_RESOURCE_FLAGS_NONE - for (int i = 0; i < 2; ++i) - { - _dilatedMotionVectorResources[i] = new RenderTexture(_contextDescription.MaxRenderSize.x, _contextDescription.MaxRenderSize.y, 1, GraphicsFormat.R16G16_SFloat) - { name = "FSR2_InternalDilatedVelocity" + (i + 1), enableRandomWrite = true }; - _dilatedMotionVectorResources[i].Create(); - } - } - // private void InitShaders() // { // LoadComputeShader("FSR2/ffx_fsr2_autogen_reactive_pass", ref _generateReactiveShader, out _generateReactiveKernel); @@ -123,13 +71,13 @@ namespace FidelityFX private void CreatePipelines() { - _computeLuminancePyramidPipeline = new Fsr2ComputeLuminancePyramidPipeline(_contextDescription, _fsr2ConstantsBuffer, _spdConstantsBuffer, _autoExposureResource); - _reconstructPreviousDepthPipeline = new Fsr2ReconstructPreviousDepthPipeline(_contextDescription, _fsr2ConstantsBuffer, _dilatedMotionVectorResources); - _depthClipPipeline = new Fsr2DepthClipPipeline(_contextDescription, _fsr2ConstantsBuffer, _dilatedMotionVectorResources); - _lockPipeline = new Fsr2LockPipeline(_contextDescription, _fsr2ConstantsBuffer); - _accumulatePipeline = new Fsr2AccumulatePipeline(_contextDescription, _fsr2ConstantsBuffer); - _accumulateSharpenPipeline = new Fsr2AccumulateSharpenPipeline(_contextDescription, _fsr2ConstantsBuffer); - _rcasPipeline = new Fsr2RcasPipeline(_contextDescription, _fsr2ConstantsBuffer, _rcasConstantsBuffer); + _computeLuminancePyramidPipeline = new Fsr2ComputeLuminancePyramidPipeline(_contextDescription, _resources, _fsr2ConstantsBuffer, _spdConstantsBuffer); + _reconstructPreviousDepthPipeline = new Fsr2ReconstructPreviousDepthPipeline(_contextDescription, _resources, _fsr2ConstantsBuffer); + _depthClipPipeline = new Fsr2DepthClipPipeline(_contextDescription, _resources, _fsr2ConstantsBuffer); + _lockPipeline = new Fsr2LockPipeline(_contextDescription, _resources, _fsr2ConstantsBuffer); + _accumulatePipeline = new Fsr2AccumulatePipeline(_contextDescription, _resources, _fsr2ConstantsBuffer); + _accumulateSharpenPipeline = new Fsr2AccumulateSharpenPipeline(_contextDescription, _resources, _fsr2ConstantsBuffer); + _rcasPipeline = new Fsr2RcasPipeline(_contextDescription, _resources, _fsr2ConstantsBuffer, _rcasConstantsBuffer); } public void Destroy() @@ -144,11 +92,7 @@ namespace FidelityFX DestroyPipeline(ref _reconstructPreviousDepthPipeline); DestroyPipeline(ref _depthClipPipeline); - DestroyResources(_dilatedMotionVectorResources); - DestroyResource(ref _autoExposureResource); - DestroyResource(ref _defaultReactiveResource); - DestroyResource(ref _defaultExposureResource); - DestroyResource(ref _lanczosLutResource); + _resources.Destroy(); DestroyConstantBuffer(ref _rcasConstantsBuffer); DestroyConstantBuffer(ref _spdConstantsBuffer); @@ -175,8 +119,8 @@ namespace FidelityFX bool resetAccumulation = dispatchParams.Reset || _firstExecution; _firstExecution = false; - if (dispatchParams.Exposure == null) dispatchParams.Exposure = _defaultExposureResource; - if (dispatchParams.Reactive == null) dispatchParams.Reactive = _defaultReactiveResource; + if (dispatchParams.Exposure == null) dispatchParams.Exposure = _resources.DefaultExposure; + if (dispatchParams.Reactive == null) dispatchParams.Reactive = _resources.DefaultReactive; Fsr2Pipeline.RegisterResources(_commandBuffer, _contextDescription, dispatchParams); SetupConstants(dispatchParams, resetAccumulation); @@ -426,39 +370,6 @@ namespace FidelityFX bufferRef = null; } - private static void DestroyResource(ref ComputeBuffer resource) - { - if (resource == null) - return; - - resource.Release(); - resource = null; - } - - private static void DestroyResource(ref Texture2D resource) - { - if (resource == null) - return; - - UnityEngine.Object.Destroy(resource); - resource = null; - } - - private static void DestroyResource(ref RenderTexture resource) - { - if (resource == null) - return; - - resource.Release(); - resource = null; - } - - private static void DestroyResources(RenderTexture[] resources) - { - for (int i = 0; i < resources.Length; ++i) - DestroyResource(ref resources[i]); - } - private static void DestroyPipeline(ref Fsr2Pipeline pipeline) { if (pipeline == null) diff --git a/Assets/Scripts/Fsr2Pipeline.cs b/Assets/Scripts/Fsr2Pipeline.cs index f72d734..0ad293b 100644 --- a/Assets/Scripts/Fsr2Pipeline.cs +++ b/Assets/Scripts/Fsr2Pipeline.cs @@ -11,6 +11,7 @@ namespace FidelityFX internal const int ShadingChangeMipLevel = 4; // This matches the FFX_FSR2_SHADING_CHANGE_MIP_LEVEL define protected readonly Fsr2.ContextDescription ContextDescription; + protected readonly Fsr2Resources Resources; protected readonly ComputeBuffer Constants; protected ComputeShader ComputeShader; @@ -49,9 +50,10 @@ namespace FidelityFX protected static readonly int CbRcas = Shader.PropertyToID("cbRCAS"); protected static readonly int CbGenReactive = Shader.PropertyToID("cbGenerateReactive"); - protected Fsr2Pipeline(Fsr2.ContextDescription contextDescription, ComputeBuffer constants) + protected Fsr2Pipeline(Fsr2.ContextDescription contextDescription, Fsr2Resources resources, ComputeBuffer constants) { ContextDescription = contextDescription; + Resources = resources; Constants = constants; } @@ -155,13 +157,11 @@ namespace FidelityFX internal class Fsr2ComputeLuminancePyramidPipeline : Fsr2Pipeline { private readonly ComputeBuffer _spdConstants; - private readonly RenderTexture _autoExposure; - public Fsr2ComputeLuminancePyramidPipeline(Fsr2.ContextDescription contextDescription, ComputeBuffer constants, ComputeBuffer spdConstants, RenderTexture autoExposure) - : base(contextDescription, constants) + public Fsr2ComputeLuminancePyramidPipeline(Fsr2.ContextDescription contextDescription, Fsr2Resources resources, ComputeBuffer constants, ComputeBuffer spdConstants) + : base(contextDescription, resources, constants) { _spdConstants = spdConstants; - _autoExposure = autoExposure; LoadComputeShader("FSR2/ffx_fsr2_compute_luminance_pyramid_pass"); } @@ -175,7 +175,7 @@ namespace FidelityFX // - Shouldn't we use a ComputeBuffer for resources that are one-dimensional and clearly not image data? e.g. SPD atomic counter & Lanczos LUT data commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputColor, dispatchParams.ColorDepth, 0, RenderTextureSubElement.Color); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, UavAutoExposure, _autoExposure); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, UavAutoExposure, Resources.AutoExposure); commandBuffer.SetComputeConstantBufferParam(ComputeShader, CbFsr2, Constants, 0, Marshal.SizeOf()); commandBuffer.SetComputeConstantBufferParam(ComputeShader, CbSpd, _spdConstants, 0, Marshal.SizeOf()); @@ -185,13 +185,9 @@ namespace FidelityFX internal class Fsr2ReconstructPreviousDepthPipeline : Fsr2Pipeline { - private readonly RenderTexture[] _dilatedMotionVectors; - - public Fsr2ReconstructPreviousDepthPipeline(Fsr2.ContextDescription contextDescription, ComputeBuffer constants, RenderTexture[] dilatedMotionVectors) - : base(contextDescription, constants) + public Fsr2ReconstructPreviousDepthPipeline(Fsr2.ContextDescription contextDescription, Fsr2Resources resources, ComputeBuffer constants) + : base(contextDescription, resources, constants) { - _dilatedMotionVectors = dilatedMotionVectors; - LoadComputeShader("FSR2/ffx_fsr2_reconstruct_previous_depth_pass"); } @@ -202,7 +198,7 @@ namespace FidelityFX commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputMotionVectors, dispatchParams.MotionVectors); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputExposure, dispatchParams.Exposure); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, UavDilatedMotionVectors, _dilatedMotionVectors[frameIndex]); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, UavDilatedMotionVectors, Resources.DilatedMotionVectors[frameIndex]); commandBuffer.SetComputeConstantBufferParam(ComputeShader, CbFsr2, Constants, 0, Marshal.SizeOf()); @@ -212,22 +208,18 @@ namespace FidelityFX internal class Fsr2DepthClipPipeline : Fsr2Pipeline { - private readonly RenderTexture[] _dilatedMotionVectors; - - public Fsr2DepthClipPipeline(Fsr2.ContextDescription contextDescription, ComputeBuffer constants, RenderTexture[] dilatedMotionVectors) - : base(contextDescription, constants) + public Fsr2DepthClipPipeline(Fsr2.ContextDescription contextDescription, Fsr2Resources resources, ComputeBuffer constants) + : base(contextDescription, resources, constants) { - _dilatedMotionVectors = dilatedMotionVectors; - LoadComputeShader("FSR2/ffx_fsr2_depth_clip_pass"); } public override void ScheduleDispatch(CommandBuffer commandBuffer, Fsr2.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY) { - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvDilatedMotionVectors, _dilatedMotionVectors[frameIndex]); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvDilatedMotionVectors, Resources.DilatedMotionVectors[frameIndex]); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvReactiveMask, dispatchParams.Reactive); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvTransparencyAndCompositionMask, dispatchParams.Reactive); // Default reactive mask, as we don't support TCR (yet) - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvPrevDilatedMotionVectors, _dilatedMotionVectors[frameIndex ^ 1]); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvPrevDilatedMotionVectors, Resources.DilatedMotionVectors[frameIndex ^ 1]); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputMotionVectors, dispatchParams.MotionVectors); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputColor, dispatchParams.ColorDepth, 0, RenderTextureSubElement.Color); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputDepth, dispatchParams.ColorDepth, 0, RenderTextureSubElement.Depth); @@ -241,8 +233,8 @@ namespace FidelityFX internal class Fsr2LockPipeline : Fsr2Pipeline { - public Fsr2LockPipeline(Fsr2.ContextDescription contextDescription, ComputeBuffer constants) - : base(contextDescription, constants) + public Fsr2LockPipeline(Fsr2.ContextDescription contextDescription, Fsr2Resources resources, ComputeBuffer constants) + : base(contextDescription, resources, constants) { LoadComputeShader("FSR2/ffx_fsr2_lock_pass"); } @@ -257,8 +249,8 @@ namespace FidelityFX internal class Fsr2AccumulatePipeline : Fsr2Pipeline { - public Fsr2AccumulatePipeline(Fsr2.ContextDescription contextDescription, ComputeBuffer constants) - : base(contextDescription, constants) + public Fsr2AccumulatePipeline(Fsr2.ContextDescription contextDescription, Fsr2Resources resources, ComputeBuffer constants) + : base(contextDescription, resources, constants) { LoadComputeShader("FSR2/ffx_fsr2_accumulate_pass"); } @@ -273,8 +265,8 @@ namespace FidelityFX { private readonly ComputeShader _shaderCopy; - public Fsr2AccumulateSharpenPipeline(Fsr2.ContextDescription contextDescription, ComputeBuffer constants) - : base(contextDescription, constants) + public Fsr2AccumulateSharpenPipeline(Fsr2.ContextDescription contextDescription, Fsr2Resources resources, ComputeBuffer constants) + : base(contextDescription, resources, constants) { // Simply loading the accumulate_pass compute shader will give us the same instance as the non-sharpen pipeline // So we have to clone the shader instance and set the extra keyword on the new copy @@ -307,8 +299,8 @@ namespace FidelityFX { private readonly ComputeBuffer _rcasConstants; - public Fsr2RcasPipeline(Fsr2.ContextDescription contextDescription, ComputeBuffer constants, ComputeBuffer rcasConstants) - : base(contextDescription, constants) + public Fsr2RcasPipeline(Fsr2.ContextDescription contextDescription, Fsr2Resources resources, ComputeBuffer constants, ComputeBuffer rcasConstants) + : base(contextDescription, resources, constants) { _rcasConstants = rcasConstants; diff --git a/Assets/Scripts/Fsr2Resources.cs b/Assets/Scripts/Fsr2Resources.cs new file mode 100644 index 0000000..f5bf01c --- /dev/null +++ b/Assets/Scripts/Fsr2Resources.cs @@ -0,0 +1,112 @@ +using UnityEngine; +using UnityEngine.Experimental.Rendering; + +namespace FidelityFX +{ + internal class Fsr2Resources + { + public Texture2D DefaultExposure; + public Texture2D DefaultReactive; + public Texture2D LanczosLut; + public RenderTexture AutoExposure; + public readonly RenderTexture[] DilatedMotionVectors = new RenderTexture[2]; + public readonly RenderTexture[] LockStatus = new RenderTexture[2]; + public readonly RenderTexture[] InternalUpscaled = new RenderTexture[2]; + public readonly RenderTexture[] LumaHistory = new RenderTexture[2]; + + public void Create(Fsr2.ContextDescription contextDescription) + { + // Generate the data for the LUT + const int lanczos2LutWidth = 128; + float[] lanczos2Weights = new float[lanczos2LutWidth]; + for (int currentLanczosWidthIndex = 0; currentLanczosWidthIndex < lanczos2LutWidth; ++currentLanczosWidthIndex) + { + float x = 2.0f * currentLanczosWidthIndex / (lanczos2LutWidth - 1); + float y = Fsr2.Lanczos2(x); + lanczos2Weights[currentLanczosWidthIndex] = y; + } + + // TODO: create resources, i.e. render textures used for intermediate results. + // Note that "aliasable" resources should be equivalent to GetTemporary render textures + // UAVs *may* be an issue with the PS4 not handling simultaneous reading and writing to an RT properly + // Unity does have Graphics.SetRandomWriteTarget for enabling UAV on ComputeBuffers or RTs + // Unity doesn't do 1D textures so just default to Texture2D + + // 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 R16_SFloat and upload pre-normalized float data. + LanczosLut = new Texture2D(lanczos2LutWidth, 1, GraphicsFormat.R16_SFloat, TextureCreationFlags.None) { name = "FSR2_LanczosLutData" }; + LanczosLut.SetPixelData(lanczos2Weights, 0); + LanczosLut.Apply(); + + // Resource FSR2_DefaultExposure: FFX_RESOURCE_USAGE_READ_ONLY, FFX_SURFACE_FORMAT_R32G32_FLOAT, FFX_RESOURCE_FLAGS_NONE + DefaultExposure = new Texture2D(1, 1, GraphicsFormat.R32G32_SFloat, TextureCreationFlags.None) { name = "FSR2_DefaultExposure" }; + DefaultExposure.SetPixel(0, 0, Color.black); + DefaultExposure.Apply(); + + // Resource FSR2_DefaultReactivityMask: FFX_RESOURCE_USAGE_READ_ONLY, FFX_SURFACE_FORMAT_R8_UNORM, FFX_RESOURCE_FLAGS_NONE + DefaultReactive = new Texture2D(1, 1, GraphicsFormat.R8_UNorm, TextureCreationFlags.None) { name = "FSR2_DefaultReactivityMask" }; + DefaultReactive.SetPixel(0, 0, Color.black); + DefaultReactive.Apply(); + + // Resource FSR2_AutoExposure: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R32G32_FLOAT, FFX_RESOURCE_FLAGS_NONE + AutoExposure = new RenderTexture(1, 1, 1, GraphicsFormat.R32G32_SFloat) { name = "FSR2_AutoExposure", enableRandomWrite = true }; + AutoExposure.Create(); + + // 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); + + // Resources FSR2_LockStatus1/2: FFX_RESOURCE_USAGE_RENDERTARGET | FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R16G16_FLOAT, FFX_RESOURCE_FLAGS_NONE + CreateDoubleBufferedResource(LockStatus, "FSR2_LockStatus", contextDescription.DisplaySize, GraphicsFormat.R16G16_SFloat); + + // Resources FSR2_InternalUpscaled1/2: FFX_RESOURCE_USAGE_RENDERTARGET | FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R16G16B16A16_FLOAT, FFX_RESOURCE_FLAGS_NONE + CreateDoubleBufferedResource(InternalUpscaled, "FSR2_InternalUpscaled", contextDescription.DisplaySize, GraphicsFormat.R16G16B16A16_SFloat); + + // Resources FSR2_LumaHistory1/2: FFX_RESOURCE_USAGE_RENDERTARGET | FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R8G8B8A8_UNORM, FFX_RESOURCE_FLAGS_NONE + CreateDoubleBufferedResource(LumaHistory, "FSR2_LumaHistory", contextDescription.DisplaySize, GraphicsFormat.R8G8B8A8_UNorm); + } + + 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, 1, format) { name = name + (i + 1), enableRandomWrite = true }; + resource[i].Create(); + } + } + + public void Destroy() + { + DestroyResource(LumaHistory); + DestroyResource(InternalUpscaled); + DestroyResource(LockStatus); + DestroyResource(DilatedMotionVectors); + DestroyResource(ref AutoExposure); + DestroyResource(ref DefaultReactive); + DestroyResource(ref DefaultExposure); + DestroyResource(ref LanczosLut); + } + private static void DestroyResource(ref Texture2D resource) + { + if (resource == null) + return; + + Object.Destroy(resource); + 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]); + } + } +} diff --git a/Assets/Scripts/Fsr2Resources.cs.meta b/Assets/Scripts/Fsr2Resources.cs.meta new file mode 100644 index 0000000..0e993b4 --- /dev/null +++ b/Assets/Scripts/Fsr2Resources.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 22ad49193f244ab4a36d0a1512f3015f +timeCreated: 1677236102 \ No newline at end of file