From 834c3963216bff810510a832b49d4940ab4bef14 Mon Sep 17 00:00:00 2001 From: Nico de Poel Date: Thu, 23 Feb 2023 12:11:36 +0100 Subject: [PATCH] Color, depth and motion vectors are now provided as regular texture inputs to the compute shaders, by blitting them from the game camera ahead of time. --- Assets/Resources/Shaders/FSR2CopyDepth.shader | 34 ++++++++ .../Shaders/FSR2CopyDepth.shader.meta | 10 +++ .../Shaders/FSR2CopyMotionVectors.shader | 34 ++++++++ .../Shaders/FSR2CopyMotionVectors.shader.meta | 10 +++ Assets/Scripts/Fsr2.cs | 9 +-- Assets/Scripts/Fsr2Context.cs | 8 +- Assets/Scripts/Fsr2Controller.cs | 81 ++++++++++++++----- Assets/Scripts/Fsr2Pipeline.cs | 10 +-- Assets/Scripts/SubsampleTest.cs | 7 +- 9 files changed, 167 insertions(+), 36 deletions(-) create mode 100644 Assets/Resources/Shaders/FSR2CopyDepth.shader create mode 100644 Assets/Resources/Shaders/FSR2CopyDepth.shader.meta create mode 100644 Assets/Resources/Shaders/FSR2CopyMotionVectors.shader create mode 100644 Assets/Resources/Shaders/FSR2CopyMotionVectors.shader.meta diff --git a/Assets/Resources/Shaders/FSR2CopyDepth.shader b/Assets/Resources/Shaders/FSR2CopyDepth.shader new file mode 100644 index 0000000..ea4ad66 --- /dev/null +++ b/Assets/Resources/Shaders/FSR2CopyDepth.shader @@ -0,0 +1,34 @@ +Shader "FSR2/FSR2CopyDepth" +{ + Properties + { + _MainTex ("Texture", 2D) = "" {} + } + SubShader { + + Pass { + ZTest Always Cull Off ZWrite Off + + HLSLPROGRAM + #include "UnityCG.cginc" + + struct v2f { + float4 vertex : SV_POSITION; + float2 texCoord : TEXCOORD0; + }; + + #pragma vertex vert_img + #pragma fragment frag + + sampler2D _CameraDepthTexture; + + fixed4 frag(v2f i) : COLOR + { + return tex2D(_CameraDepthTexture, i.texCoord); + } + ENDHLSL + + } + } + Fallback Off +} diff --git a/Assets/Resources/Shaders/FSR2CopyDepth.shader.meta b/Assets/Resources/Shaders/FSR2CopyDepth.shader.meta new file mode 100644 index 0000000..2646f0f --- /dev/null +++ b/Assets/Resources/Shaders/FSR2CopyDepth.shader.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: f9861a441b68ea4409f6d6828d4ef5b2 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + preprocessorOverride: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/Shaders/FSR2CopyMotionVectors.shader b/Assets/Resources/Shaders/FSR2CopyMotionVectors.shader new file mode 100644 index 0000000..781dec3 --- /dev/null +++ b/Assets/Resources/Shaders/FSR2CopyMotionVectors.shader @@ -0,0 +1,34 @@ +Shader "FSR2/CopyMotionVectors" +{ + Properties + { + _MainTex ("Texture", 2D) = "" {} + } + SubShader { + + Pass { + ZTest Always Cull Off ZWrite Off + + HLSLPROGRAM + #include "UnityCG.cginc" + + struct v2f { + float4 vertex : SV_POSITION; + float2 texCoord : TEXCOORD0; + }; + + #pragma vertex vert_img + #pragma fragment frag + + sampler2D_half _CameraMotionVectorsTexture; + + fixed4 frag(v2f i) : COLOR + { + return tex2D(_CameraMotionVectorsTexture, i.texCoord); + } + ENDHLSL + + } + } + Fallback Off +} diff --git a/Assets/Resources/Shaders/FSR2CopyMotionVectors.shader.meta b/Assets/Resources/Shaders/FSR2CopyMotionVectors.shader.meta new file mode 100644 index 0000000..83db780 --- /dev/null +++ b/Assets/Resources/Shaders/FSR2CopyMotionVectors.shader.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: ea3aa42789e56b84db6c1326db8b6c37 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + preprocessorOverride: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Fsr2.cs b/Assets/Scripts/Fsr2.cs index d290b27..8297e29 100644 --- a/Assets/Scripts/Fsr2.cs +++ b/Assets/Scripts/Fsr2.cs @@ -131,11 +131,10 @@ namespace FidelityFX public class DispatchDescription { - // Texture2D Color, Depth, MotionVectors; // Will be passed using ComputeShader.SetTextureFromGlobal - public Texture2D Exposure; - public Texture2D Reactive; - public Texture2D TransparencyAndComposition; - public RenderTexture Input; + public Texture Color, Depth, MotionVectors; + public Texture Exposure; + public Texture Reactive; + public Texture TransparencyAndComposition; public RenderTexture Output; public Vector2 JitterOffset; public Vector2 MotionVectorScale; diff --git a/Assets/Scripts/Fsr2Context.cs b/Assets/Scripts/Fsr2Context.cs index 98d8d8b..13578dd 100644 --- a/Assets/Scripts/Fsr2Context.cs +++ b/Assets/Scripts/Fsr2Context.cs @@ -230,7 +230,7 @@ namespace FidelityFX } else { - _commandBuffer.Blit(dispatchParams.Input, dispatchParams.Output); + _commandBuffer.Blit(dispatchParams.Color, dispatchParams.Output); } _resourceFrameIndex = (_resourceFrameIndex + 1) % MaxQueuedFrames; @@ -246,10 +246,10 @@ namespace FidelityFX constants.jitterOffset = dispatchParams.JitterOffset; constants.renderSize = new Vector2Int( - dispatchParams.RenderSize.x > 0 ? dispatchParams.RenderSize.x : dispatchParams.Input.width, - dispatchParams.RenderSize.y > 0 ? dispatchParams.RenderSize.y : dispatchParams.Input.height); + dispatchParams.RenderSize.x > 0 ? dispatchParams.RenderSize.x : dispatchParams.Color.width, + dispatchParams.RenderSize.y > 0 ? dispatchParams.RenderSize.y : dispatchParams.Color.height); constants.maxRenderSize = _contextDescription.MaxRenderSize; - constants.inputColorResourceDimensions = new Vector2Int(dispatchParams.Input.width, dispatchParams.Input.height); + constants.inputColorResourceDimensions = new Vector2Int(dispatchParams.Color.width, dispatchParams.Color.height); // Compute the horizontal FOV for the shader from the vertical one float aspectRatio = (float)dispatchParams.RenderSize.x / dispatchParams.RenderSize.y; diff --git a/Assets/Scripts/Fsr2Controller.cs b/Assets/Scripts/Fsr2Controller.cs index 3d7c174..483a5cf 100644 --- a/Assets/Scripts/Fsr2Controller.cs +++ b/Assets/Scripts/Fsr2Controller.cs @@ -36,22 +36,37 @@ public class Fsr2Controller : MonoBehaviour private Fsr2Context _context; private readonly Fsr2.DispatchDescription _dispatchDescription = new Fsr2.DispatchDescription(); - private RenderTexture _upscaleRT; + private RenderTexture _colorRT, _depthRT, _motionVectorsRT; private RenderTexture _outputRT; private Texture2D _exposure; - - private Material _testMaterial; - private Material TestMaterial + + private Material _copyDepthMat; + private Material CopyDepthMaterial + { + get + { + if (_copyDepthMat == null) + { + var copyDepthShader = Fsr2.GlobalCallbacks.LoadShader("Shaders/FSR2CopyDepth"); + _copyDepthMat = new Material(copyDepthShader); + } + + return _copyDepthMat; + } + } + + private Material _copyMotionMat; + private Material CopyMotionVectorsMaterial { get { - if (_testMaterial == null) + if (_copyMotionMat == null) { - var testShader = Fsr2.GlobalCallbacks.LoadShader("Shaders/FSRTest"); - _testMaterial = new Material(testShader); + var copyMotionShader = Fsr2.GlobalCallbacks.LoadShader("Shaders/FSR2CopyMotionVectors"); + _copyMotionMat = new Material(copyMotionShader); } - return _testMaterial; + return _copyMotionMat; } } @@ -70,17 +85,23 @@ public class Fsr2Controller : MonoBehaviour RenderPipelineManager.endContextRendering += OnEndContextRendering; // TODO: destroy and recreate context on screen resolution and/or quality mode change + // TODO: enable motion vector jitter cancellation or not? _context = Fsr2.CreateContext(DisplaySize, RenderSize); - _upscaleRT = new RenderTexture(Screen.width, Screen.height, 24, RenderTextureFormat.ARGBHalf); - _upscaleRT.Create(); + // TODO: could make these temporary RTs + _colorRT = new RenderTexture(RenderSize.x, RenderSize.y, 0, RenderTextureFormat.ARGBHalf) { name = "FSR2 Color Input" }; + _colorRT.Create(); + + _depthRT = new RenderTexture(RenderSize.x, RenderSize.y, 0, RenderTextureFormat.RFloat) { name = "FSR2 Depth Input" }; + _depthRT.Create(); - _outputRT = new RenderTexture(Screen.width, Screen.height, 24, RenderTextureFormat.ARGBHalf); - _outputRT.enableRandomWrite = true; + _motionVectorsRT = new RenderTexture(RenderSize.x, RenderSize.y, 0, RenderTextureFormat.RGHalf) { name = "FSR2 Motion Vectors Input" }; + _motionVectorsRT.Create(); + + _outputRT = new RenderTexture(Screen.width, Screen.height, 24, RenderTextureFormat.ARGBHalf) { enableRandomWrite = true }; // TODO: does this need to be a UAV? _outputRT.Create(); - _exposure = new Texture2D(1, 1); - _exposure.name = "FSR2 Exposure"; + _exposure = new Texture2D(1, 1) { name = "FSR2 Exposure" }; _exposure.SetPixel(0, 0, Color.white); _exposure.Apply(); } @@ -99,10 +120,22 @@ public class Fsr2Controller : MonoBehaviour _outputRT = null; } - if (_upscaleRT != null) + if (_motionVectorsRT != null) + { + _motionVectorsRT.Release(); + _motionVectorsRT = null; + } + + if (_depthRT != null) { - _upscaleRT.Release(); - _upscaleRT = null; + _depthRT.Release(); + _depthRT = null; + } + + if (_colorRT != null) + { + _colorRT.Release(); + _colorRT = null; } if (_context != null) @@ -114,6 +147,13 @@ public class Fsr2Controller : MonoBehaviour RenderPipelineManager.endContextRendering -= OnEndContextRendering; } + public void UpdateInputResources(RenderTexture src) + { + Graphics.Blit(src, _colorRT); + Graphics.Blit(src, _depthRT, CopyDepthMaterial); + Graphics.Blit(src, _motionVectorsRT, CopyMotionVectorsMaterial); + } + // For scriptable rendering pipeline private void OnEndContextRendering(ScriptableRenderContext context, List cameras) { @@ -123,10 +163,9 @@ public class Fsr2Controller : MonoBehaviour // For legacy built-in render pipeline private void OnRenderImage(RenderTexture src, RenderTexture dest) { - // Do a dumb upscale first - Graphics.Blit(gameCamera.targetTexture, _upscaleRT, TestMaterial); - - _dispatchDescription.Input = _upscaleRT; + _dispatchDescription.Color = _colorRT; + _dispatchDescription.Depth = _depthRT; + _dispatchDescription.MotionVectors = _motionVectorsRT; _dispatchDescription.Output = _outputRT; _dispatchDescription.Exposure = _exposure; _dispatchDescription.PreExposure = 1.0f; diff --git a/Assets/Scripts/Fsr2Pipeline.cs b/Assets/Scripts/Fsr2Pipeline.cs index b9b99fe..6236859 100644 --- a/Assets/Scripts/Fsr2Pipeline.cs +++ b/Assets/Scripts/Fsr2Pipeline.cs @@ -151,7 +151,7 @@ namespace FidelityFX // - How do we clear the resources that need to be cleared at dispatch? (SetBufferData) // - 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, new RenderTargetIdentifier(BuiltinRenderTextureType.CurrentActive)); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputColor, dispatchParams.Color); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, UavAutoExposure, _autoExposure); commandBuffer.SetComputeConstantBufferParam(ComputeShader, CbFsr2, Constants, 0, Marshal.SizeOf()); commandBuffer.SetComputeConstantBufferParam(ComputeShader, CbSpd, _spdConstants, 0, Marshal.SizeOf()); @@ -174,9 +174,9 @@ namespace FidelityFX public override void ScheduleDispatch(CommandBuffer commandBuffer, Fsr2.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY) { - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputMotionVectors, new RenderTargetIdentifier(BuiltinRenderTextureType.MotionVectors)); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputDepth, new RenderTargetIdentifier(BuiltinRenderTextureType.Depth)); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputColor, new RenderTargetIdentifier(BuiltinRenderTextureType.CurrentActive)); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputColor, dispatchParams.Color); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputDepth, dispatchParams.Depth); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputMotionVectors, dispatchParams.MotionVectors); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputExposure, dispatchParams.Exposure); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, UavDilatedMotionVectors, _dilatedMotionVectors[frameIndex]); @@ -251,7 +251,7 @@ namespace FidelityFX { // Run the RCAS sharpening filter on the upscaled image commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputExposure, dispatchParams.Exposure); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvRcasInput, dispatchParams.Input); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvRcasInput, dispatchParams.Color); // TODO: should be output from accumulate pass commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, UavUpscaledOutput, dispatchParams.Output); commandBuffer.SetComputeConstantBufferParam(ComputeShader, CbFsr2, Constants, 0, Marshal.SizeOf()); commandBuffer.SetComputeConstantBufferParam(ComputeShader, CbRcas, _rcasConstants, 0, Marshal.SizeOf()); diff --git a/Assets/Scripts/SubsampleTest.cs b/Assets/Scripts/SubsampleTest.cs index d1e2723..f8f9044 100644 --- a/Assets/Scripts/SubsampleTest.cs +++ b/Assets/Scripts/SubsampleTest.cs @@ -113,7 +113,12 @@ public class SubsampleTest : MonoBehaviour gameCamera.projectionMatrix = jitterTranslationMatrix * gameCamera.nonJitteredProjectionMatrix; } } - + + private void OnRenderImage(RenderTexture src, RenderTexture dest) + { + _fsr2Controller.UpdateInputResources(src); + } + private void OnPostRender() { gameCamera.rect = tempRect;