From fddefa816598516bead1435252e88b69d2d79cd1 Mon Sep 17 00:00:00 2001 From: Nico de Poel Date: Sun, 11 May 2025 12:05:43 +0200 Subject: [PATCH] Changed auto-exposure texture into a double buffered resource (FSR3), to avoid issues with reading and writing to the same texture in the compute luminance pass. This allows fast exposure convergence without issues on OpenGL and Metal. --- Runtime/FSR3/Fsr3UpscalerContext.cs | 6 +++--- Runtime/FSR3/Fsr3UpscalerPass.cs | 5 +++-- Runtime/FSR3/Fsr3UpscalerResources.cs | 7 +++---- Shaders/shaders/ffx_fsr3upscaler_luma_pyramid_pass.hlsl | 1 + .../shaders/fsr3upscaler/ffx_fsr3upscaler_luma_pyramid.h | 4 ++-- 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/Runtime/FSR3/Fsr3UpscalerContext.cs b/Runtime/FSR3/Fsr3UpscalerContext.cs index e4a3fd9..7d16e57 100644 --- a/Runtime/FSR3/Fsr3UpscalerContext.cs +++ b/Runtime/FSR3/Fsr3UpscalerContext.cs @@ -189,7 +189,7 @@ namespace FidelityFX.FSR3 // If auto exposure is enabled use the auto exposure SRV, otherwise what the app sends if ((_contextDescription.Flags & Fsr3Upscaler.InitializationFlags.EnableAutoExposure) != 0) - dispatchParams.Exposure = new ResourceView(_resources.FrameInfo); + dispatchParams.Exposure = new ResourceView(_resources.FrameInfo[frameIndex]); else if (!dispatchParams.Exposure.IsValid) dispatchParams.Exposure = new ResourceView(_resources.DefaultExposure); @@ -236,8 +236,8 @@ namespace FidelityFX.FSR3 commandBuffer.ClearRenderTarget(false, true, Color.clear); // Auto exposure always used to track luma changes in locking logic - commandBuffer.SetRenderTarget(_resources.FrameInfo); - commandBuffer.ClearRenderTarget(false, true, new Color(0f, 1f, 0f, 0f)); + commandBuffer.SetRenderTarget(_resources.FrameInfo[frameIndex ^ 1]); + commandBuffer.ClearRenderTarget(false, true, new Color(0f, 1e8f, 0f, 0f)); // Reset atomic counter to 0 commandBuffer.SetRenderTarget(_resources.SpdAtomicCounter); diff --git a/Runtime/FSR3/Fsr3UpscalerPass.cs b/Runtime/FSR3/Fsr3UpscalerPass.cs index f60e1f6..7444b95 100644 --- a/Runtime/FSR3/Fsr3UpscalerPass.cs +++ b/Runtime/FSR3/Fsr3UpscalerPass.cs @@ -155,9 +155,10 @@ namespace FidelityFX.FSR3 { commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvCurrentLuma, Resources.Luma[frameIndex]); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvFarthestDepth, Fsr3ShaderIDs.UavIntermediate); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvFrameInfo, Resources.FrameInfo[frameIndex ^ 1]); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavSpdAtomicCount, Resources.SpdAtomicCounter); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavFrameInfo, Resources.FrameInfo); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.UavFrameInfo, Resources.FrameInfo[frameIndex]); 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); @@ -273,7 +274,7 @@ namespace FidelityFX.FSR3 commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvInputExposure, exposure.RenderTarget, exposure.MipLevel, exposure.SubElement); 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.SrvFrameInfo, Resources.FrameInfo[frameIndex]); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvLumaHistory, Resources.LumaHistory[frameIndex ^ 1]); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvFarthestDepthMip1, Fsr3ShaderIDs.UavFarthestDepthMip1); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr3ShaderIDs.SrvCurrentLuma, Resources.Luma[frameIndex]); diff --git a/Runtime/FSR3/Fsr3UpscalerResources.cs b/Runtime/FSR3/Fsr3UpscalerResources.cs index 112b98d..203ad6e 100644 --- a/Runtime/FSR3/Fsr3UpscalerResources.cs +++ b/Runtime/FSR3/Fsr3UpscalerResources.cs @@ -40,10 +40,10 @@ namespace FidelityFX.FSR3 public RenderTexture DilatedVelocity; public RenderTexture DilatedDepth; public RenderTexture ReconstructedPrevNearestDepth; - public RenderTexture FrameInfo; public RenderTexture AutoReactive; public RenderTexture AutoComposition; + public readonly RenderTexture[] FrameInfo = new RenderTexture[2]; public readonly RenderTexture[] Accumulation = new RenderTexture[2]; public readonly RenderTexture[] Luma = new RenderTexture[2]; public readonly RenderTexture[] InternalUpscaled = new RenderTexture[2]; @@ -106,8 +106,7 @@ namespace FidelityFX.FSR3 ReconstructedPrevNearestDepth.Create(); // 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(); + CreateDoubleBufferedResource(FrameInfo, "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); @@ -190,8 +189,8 @@ namespace FidelityFX.FSR3 DestroyResource(InternalUpscaled); DestroyResource(Luma); DestroyResource(Accumulation); + DestroyResource(FrameInfo); - DestroyResource(ref FrameInfo); DestroyResource(ref ReconstructedPrevNearestDepth); DestroyResource(ref DilatedDepth); DestroyResource(ref DilatedVelocity); diff --git a/Shaders/shaders/ffx_fsr3upscaler_luma_pyramid_pass.hlsl b/Shaders/shaders/ffx_fsr3upscaler_luma_pyramid_pass.hlsl index 0d6b67d..7a7526d 100644 --- a/Shaders/shaders/ffx_fsr3upscaler_luma_pyramid_pass.hlsl +++ b/Shaders/shaders/ffx_fsr3upscaler_luma_pyramid_pass.hlsl @@ -22,6 +22,7 @@ #define FSR3UPSCALER_BIND_SRV_CURRENT_LUMA 0 #define FSR3UPSCALER_BIND_SRV_FARTHEST_DEPTH 1 +#define FSR3UPSCALER_BIND_SRV_FRAME_INFO 2 #define FSR3UPSCALER_BIND_UAV_SPD_GLOBAL_ATOMIC 0 #define FSR3UPSCALER_BIND_UAV_FRAME_INFO 1 diff --git a/Shaders/shaders/fsr3upscaler/ffx_fsr3upscaler_luma_pyramid.h b/Shaders/shaders/fsr3upscaler/ffx_fsr3upscaler_luma_pyramid.h index c545579..6d6b629 100644 --- a/Shaders/shaders/fsr3upscaler/ffx_fsr3upscaler_luma_pyramid.h +++ b/Shaders/shaders/fsr3upscaler/ffx_fsr3upscaler_luma_pyramid.h @@ -20,7 +20,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -FFX_GROUPSHARED FfxUInt32 spdCounter; +FFX_GROUPSHARED FfxUInt32 spdCounter = 0u; void SpdIncreaseAtomicCounter(FfxUInt32 slice) { @@ -95,7 +95,7 @@ void SpdStore(FfxInt32x2 pix, FfxFloat32x4 outValue, FfxUInt32 index, FfxUInt32 if (all(FFX_EQUAL(pix, FfxInt32x2(0, 0)))) { - FfxFloat32x4 frameInfo = LoadFrameInfo(); + FfxFloat32x4 frameInfo = FrameInfo(); const FfxFloat32 fSceneAvgLuma = outValue[LUMA]; const FfxFloat32 fPrevLogLuma = frameInfo[FRAME_INFO_LOG_LUMA]; FfxFloat32 fLogLuma = outValue[LOG_LUMA];