From 79d8aa49b61d0ac188a3f116d2abca8229fe1177 Mon Sep 17 00:00:00 2001 From: Nico de Poel Date: Wed, 11 Jan 2023 12:14:47 +0100 Subject: [PATCH] - Implemented main FSR2 constants buffer, which now supplies the pre-exposure value to the RCAS shader. - Converted thread groups calculation from FSR2 code --- .../Shaders/ffx_fsr2_callbacks_hlsl.h | 3 +- Assets/Scripts/FSR2Thing.cs | 89 ++++++++++++++----- Assets/Scripts/SubsampleTest.cs | 3 +- 3 files changed, 70 insertions(+), 25 deletions(-) diff --git a/Assets/Resources/Shaders/ffx_fsr2_callbacks_hlsl.h b/Assets/Resources/Shaders/ffx_fsr2_callbacks_hlsl.h index 4a5fbca..4641927 100644 --- a/Assets/Resources/Shaders/ffx_fsr2_callbacks_hlsl.h +++ b/Assets/Resources/Shaders/ffx_fsr2_callbacks_hlsl.h @@ -482,8 +482,7 @@ FfxFloat32 SampleTransparencyAndCompositionMask(FfxFloat32x2 fUV) FfxFloat32 PreExposure() { - //return fPreExposure; - return 1.0f; + return fPreExposure; } FfxFloat32x3 LoadInputColor(FfxUInt32x2 iPxPos) diff --git a/Assets/Scripts/FSR2Thing.cs b/Assets/Scripts/FSR2Thing.cs index eadd723..90fb35f 100644 --- a/Assets/Scripts/FSR2Thing.cs +++ b/Assets/Scripts/FSR2Thing.cs @@ -50,7 +50,7 @@ public class FSR2Thing : MonoBehaviour { if (_rcasComputeShader == null) { - // TODO: this is nasty, I don't like this. How do we manage/bind compute shaders best? + // TODO: this is nasty, I don't like this. How do we manage/bind compute shaders best? => make a Callbacks class/interface with overridable implementation // GPUInstancer used Resources, we modified that to load stuff from asset bundles instead. Maybe provide a custom loader callback interface? _rcasComputeShader = Resources.Load("Shaders/ffx_fsr2_rcas_pass"); } @@ -59,8 +59,11 @@ public class FSR2Thing : MonoBehaviour } } - private ComputeBuffer _rcasConstantBuffer; - private RcasConfig[] _rcasConfig = new RcasConfig[1]; + private ComputeBuffer _fsr2ConstantsBuffer; + private readonly Fsr2Constants[] _fsr2ConstantsArray = { new Fsr2Constants() }; + + private ComputeBuffer _rcasConstantsBuffer; + private readonly RcasConstants[] _rcasConstantsArray = new RcasConstants[1]; private void OnEnable() { @@ -77,16 +80,23 @@ public class FSR2Thing : MonoBehaviour _exposure.name = "FSR2 Exposure"; _exposure.SetPixel(0, 0, Color.white); _exposure.Apply(); - - _rcasConstantBuffer = new ComputeBuffer(1, Marshal.SizeOf(), ComputeBufferType.Constant); + + _fsr2ConstantsBuffer = new ComputeBuffer(1, Marshal.SizeOf(), ComputeBufferType.Constant); + _rcasConstantsBuffer = new ComputeBuffer(1, Marshal.SizeOf(), ComputeBufferType.Constant); } private void OnDisable() { - if (_rcasConstantBuffer != null) + if (_rcasConstantsBuffer != null) { - _rcasConstantBuffer.Release(); - _rcasConstantBuffer = null; + _rcasConstantsBuffer.Release(); + _rcasConstantsBuffer = null; + } + + if (_fsr2ConstantsBuffer != null) + { + _fsr2ConstantsBuffer.Release(); + _fsr2ConstantsBuffer = null; } if (_exposure != null) @@ -122,20 +132,28 @@ public class FSR2Thing : MonoBehaviour // Do a dumb upscale first Graphics.Blit(gameCamera.targetTexture, _upscaleRT, TestMaterial); + _fsr2ConstantsArray[0].preExposure = 1.0f; + _fsr2ConstantsBuffer.SetData(_fsr2ConstantsArray); + if (performSharpenPass) { int sharpnessIndex = Mathf.RoundToInt(Mathf.Clamp01(sharpness) * (RcasConfigs.Count - 1)); - _rcasConfig[0] = RcasConfigs[sharpnessIndex]; - _rcasConstantBuffer.SetData(_rcasConfig); + _rcasConstantsArray[0] = RcasConfigs[sharpnessIndex]; + _rcasConstantsBuffer.SetData(_rcasConstantsArray); // Run the RCAS sharpening filter on the upscaled image int rcasKernel = RCASComputeShader.FindKernel("CS"); - // TODO: create constant buffer (cbFSR2) with fPreExposure set to 1.0 RCASComputeShader.SetTexture(rcasKernel, "r_exposure", _exposure); RCASComputeShader.SetTexture(rcasKernel, "r_rcas_input", _upscaleRT); RCASComputeShader.SetTexture(rcasKernel, "rw_upscaled_output", _rcasOutput); - RCASComputeShader.SetConstantBuffer("cbRCAS", _rcasConstantBuffer, 0, Marshal.SizeOf()); - RCASComputeShader.Dispatch(rcasKernel, Screen.width, Screen.height, 1); // TODO: not sure how these thread groups work... + RCASComputeShader.SetConstantBuffer("cbFSR2", _fsr2ConstantsBuffer, 0, Marshal.SizeOf()); + RCASComputeShader.SetConstantBuffer("cbRCAS", _rcasConstantsBuffer, 0, Marshal.SizeOf()); + + const int threadGroupWorkRegionDimRcas = 16; + int threadGroupsX = (Screen.width + threadGroupWorkRegionDimRcas - 1) / threadGroupWorkRegionDimRcas; + int threadGroupsY = (Screen.height + threadGroupWorkRegionDimRcas - 1) / threadGroupWorkRegionDimRcas; + + RCASComputeShader.Dispatch(rcasKernel, threadGroupsX, threadGroupsY, 1); // Output sharpened image to screen Graphics.Blit(_rcasOutput, dest); @@ -146,23 +164,50 @@ public class FSR2Thing : MonoBehaviour } } - [Serializable] - private struct RcasConfig + [Serializable, StructLayout(LayoutKind.Sequential)] + private struct RcasConstants { - public RcasConfig(uint sharpness, uint halfSharp) + public RcasConstants(uint sharpness, uint halfSharp) { this.sharpness = sharpness; this.halfSharp = halfSharp; dummy0 = dummy1 = 0; } - public uint sharpness; - public uint halfSharp; - public uint dummy0; - public uint dummy1; + public readonly uint sharpness; + public readonly uint halfSharp; + public readonly uint dummy0; + public readonly uint dummy1; } - - private static readonly List RcasConfigs = new() + + [Serializable, StructLayout(LayoutKind.Sequential)] + private struct Fsr2Constants + { + public Vector2Int renderSize; + public Vector2Int displaySize; + public uint lumaMipDimensionsX, lumaMipDimensionsY; + public uint lumaMipLevelToUse; + public uint frameIndex; + public Vector2 displaySizeRcp; + public Vector2 jitterOffset; + public Vector4 deviceToViewDepth; + public Vector2 depthClipUVScale; + public Vector2 postLockStatusUVScale; + public Vector2 reactiveMaskDimRcp; + public Vector2 motionVectorScale; + public Vector2 downscaleFactor; + public float preExposure; + public float tanHalfFOV; + public Vector2 motionVectorJitterCancellation; + public float jitterPhaseCount; + public float lockInitialLifetime; + public float lockTickDelta; + public float deltaTime; + public float dynamicResChangeFactor; + public float lumaMipRcp; + } + + private static readonly List RcasConfigs = new() { new(1048576000u, 872428544u), new(1049178080u, 877212745u), diff --git a/Assets/Scripts/SubsampleTest.cs b/Assets/Scripts/SubsampleTest.cs index 7c0c21e..6043e2c 100644 --- a/Assets/Scripts/SubsampleTest.cs +++ b/Assets/Scripts/SubsampleTest.cs @@ -58,8 +58,9 @@ public class SubsampleTest : MonoBehaviour gameCamera.targetTexture.name = "FSR2 Source Texture"; gameCamera.targetTexture.Create(); - // TODO: adjust texture mipmap LOD bias by log2(renderResolution/displayResolution) - 1.0; + // Adjust texture mipmap LOD bias by log2(renderResolution/displayResolution) - 1.0; // May need to leave this to the game dev, as we don't know which textures do and don't belong to the 3D scene + // TODO: add to Callbacks class/interface (ApplyMipmapBias) float biasOffset = GetMipmapBiasOffset(); foreach (var tex in Resources.FindObjectsOfTypeAll()) {