From d088d440f577f209cfa32fe27c40c5c1ae9fbea3 Mon Sep 17 00:00:00 2001 From: Nico de Poel Date: Mon, 24 Mar 2025 12:08:53 +0100 Subject: [PATCH 1/3] Allow live switching between FP16 and FP32 --- .../PostProcessing/Editor/PostProcessLayerEditor.cs | 3 +++ .../PostProcessing/Runtime/Effects/Upscaling.cs | 6 +++++- .../PostProcessing/Runtime/Effects/Upscaling/ASRUpscaler.cs | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Editor/PostProcessLayerEditor.cs b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Editor/PostProcessLayerEditor.cs index c89b4bd..d4e5f8d 100644 --- a/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Editor/PostProcessLayerEditor.cs +++ b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Editor/PostProcessLayerEditor.cs @@ -34,6 +34,7 @@ namespace UnityEditor.Rendering.PostProcessing SerializedProperty m_FsrQualityMode; SerializedProperty m_FsrPerformSharpen; SerializedProperty m_FsrSharpness; + SerializedProperty m_FsrEnableFP16; SerializedProperty m_FsrExposureSource; SerializedProperty m_FsrExposureTexture; SerializedProperty m_FsrPreExposure; @@ -94,6 +95,7 @@ namespace UnityEditor.Rendering.PostProcessing m_FsrQualityMode = FindProperty(x => x.upscaling.qualityMode); m_FsrPerformSharpen = FindProperty(x => x.upscaling.performSharpenPass); m_FsrSharpness = FindProperty(x => x.upscaling.sharpness); + m_FsrEnableFP16 = FindProperty(x => x.upscaling.enableFP16); m_FsrExposureSource = FindProperty(x => x.upscaling.exposureSource); m_FsrExposureTexture = FindProperty(x => x.upscaling.exposure); m_FsrPreExposure = FindProperty(x => x.upscaling.preExposure); @@ -230,6 +232,7 @@ namespace UnityEditor.Rendering.PostProcessing EditorGUILayout.PropertyField(m_FsrQualityMode); EditorGUILayout.PropertyField(m_FsrPerformSharpen); EditorGUILayout.PropertyField(m_FsrSharpness); + EditorGUILayout.PropertyField(m_FsrEnableFP16); EditorGUILayout.PropertyField(m_FsrExposureSource); if (m_FsrExposureSource.intValue == (int)Upscaling.ExposureSource.Manual) EditorGUILayout.PropertyField(m_FsrExposureTexture); EditorGUILayout.PropertyField(m_FsrPreExposure); diff --git a/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling.cs b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling.cs index 68727e5..1edb208 100644 --- a/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling.cs +++ b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling.cs @@ -34,6 +34,8 @@ namespace UnityEngine.Rendering.PostProcessing public bool performSharpenPass = true; [Tooltip("Strength of the sharpening effect.")] [Range(0, 1)] public float sharpness = 0.8f; + + public bool enableFP16 = true; [Tooltip("Choose where to get the exposure value from. Use auto-exposure from either the upscaler or Unity, provide a manual exposure texture, or use a default value.")] public ExposureSource exposureSource = ExposureSource.Auto; @@ -112,6 +114,7 @@ namespace UnityEngine.Rendering.PostProcessing private Fsr2.QualityMode _prevQualityMode; private ExposureSource _prevExposureSource; private Vector2Int _prevUpscaleSize; + private bool _prevFP16; private Rect _originalRect; @@ -165,7 +168,7 @@ namespace UnityEngine.Rendering.PostProcessing // Monitor for any resolution changes and recreate the upscaler context if necessary // We can't create an upscaler context without info from the post-processing context, so delay the initial setup until here if (!_initialized || _upscaler == null || _upscaleSize.x != _prevUpscaleSize.x || _upscaleSize.y != _prevUpscaleSize.y || - upscalerType != _prevUpscalerType || qualityMode != _prevQualityMode || exposureSource != _prevExposureSource) + upscalerType != _prevUpscalerType || qualityMode != _prevQualityMode || exposureSource != _prevExposureSource || enableFP16 != _prevFP16) { DestroyUpscaler(); CreateUpscaler(context); @@ -199,6 +202,7 @@ namespace UnityEngine.Rendering.PostProcessing _prevQualityMode = qualityMode; _prevExposureSource = exposureSource; _prevUpscaleSize = _upscaleSize; + _prevFP16 = enableFP16; _callbacks = callbacksFactory(context); diff --git a/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASRUpscaler.cs b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASRUpscaler.cs index bf08c6f..172520f 100644 --- a/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASRUpscaler.cs +++ b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASRUpscaler.cs @@ -17,7 +17,7 @@ namespace UnityEngine.Rendering.PostProcessing public override void CreateContext(PostProcessRenderContext context, Upscaling config) { // Initialize ASR context - Asr.InitializationFlags flags = Asr.InitializationFlags.EnableFP16Usage; + Asr.InitializationFlags flags = config.enableFP16 ? Asr.InitializationFlags.EnableFP16Usage : 0; if (context.camera.allowHDR) flags |= Asr.InitializationFlags.EnableHighDynamicRange; if (config.exposureSource == Upscaling.ExposureSource.Auto) flags |= Asr.InitializationFlags.EnableAutoExposure; if (RuntimeUtilities.IsDynamicResolutionEnabled(context.camera)) flags |= Asr.InitializationFlags.EnableDynamicResolution; From 090b9135e8c72563c869515ed15155b26a14a316 Mon Sep 17 00:00:00 2001 From: Nico de Poel Date: Mon, 24 Mar 2025 13:56:39 +0100 Subject: [PATCH 2/3] Reworked auto-exposure to use a double buffered render texture, which allows the smooth exposure transition logic to load a value that's guaranteed to be from the previous frame. Fixes artifacting and flickering issues caused by loading & storing to the same texture. --- .../Effects/Upscaling/ASR/Runtime/AsrContext.cs | 8 ++++---- .../Runtime/Effects/Upscaling/ASR/Runtime/AsrPass.cs | 5 +++-- .../Effects/Upscaling/ASR/Runtime/AsrResources.cs | 11 +++++------ .../ffxm_fsr2_compute_luminance_pyramid_pass.hlsl | 1 + .../Shaders/shaders/fsr2/ffxm_fsr2_callbacks_hlsl.h | 4 +++- 5 files changed, 16 insertions(+), 13 deletions(-) diff --git a/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrContext.cs b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrContext.cs index 9bd1cc0..cdcca6b 100644 --- a/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrContext.cs +++ b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrContext.cs @@ -148,7 +148,7 @@ namespace ArmASR // If auto exposure is enabled use the auto exposure SRV, otherwise what the app sends if ((_contextDescription.Flags & Asr.InitializationFlags.EnableAutoExposure) != 0) - dispatchParams.Exposure = new ResourceView(_resources.AutoExposure); + dispatchParams.Exposure = new ResourceView(_resources.AutoExposure[frameIndex]); else if (!dispatchParams.Exposure.IsValid) dispatchParams.Exposure = new ResourceView(_resources.DefaultExposure); @@ -185,9 +185,9 @@ namespace ArmASR commandBuffer.ClearRenderTarget(false, true, Color.clear); // Auto exposure always used to track luma changes in locking logic - commandBuffer.SetRenderTarget(_resources.AutoExposure); - commandBuffer.ClearRenderTarget(false, true, new Color(0f, 1e8f, 0f, 0f)); - + commandBuffer.SetRenderTarget(_resources.AutoExposure[frameIndex ^ 1]); + commandBuffer.ClearRenderTarget(false, true, new Color(-1f, 1e8f, 0f, 0f)); + // Reset atomic counter to 0 commandBuffer.SetRenderTarget(_resources.SpdAtomicCounter); commandBuffer.ClearRenderTarget(false, true, Color.clear); diff --git a/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrPass.cs b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrPass.cs index 7c7d191..4139b64 100644 --- a/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrPass.cs +++ b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrPass.cs @@ -147,11 +147,12 @@ namespace ArmASR protected override void DoScheduleDispatch(CommandBuffer commandBuffer, Asr.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY) { commandBuffer.SetComputeResourceParam(ComputeShader, KernelIndex, AsrShaderIDs.SrvInputColor, dispatchParams.Color); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.SrvAutoExposure, Resources.AutoExposure[frameIndex ^ 1]); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.UavSpdAtomicCount, Resources.SpdAtomicCounter); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.UavExposureMipLumaChange, Resources.SceneLuminance, ShadingChangeMipLevel); commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.UavExposureMip5, Resources.SceneLuminance, 5); - commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.UavAutoExposure, Resources.AutoExposure); + commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, AsrShaderIDs.UavAutoExposure, Resources.AutoExposure[frameIndex]); commandBuffer.SetComputeConstantBufferParam(ComputeShader, AsrShaderIDs.CbFsr2, Constants, 0, Constants.stride); commandBuffer.SetComputeConstantBufferParam(ComputeShader, AsrShaderIDs.CbSpd, _spdConstants, 0, _spdConstants.stride); @@ -273,7 +274,7 @@ namespace ArmASR commandBuffer.SetGlobalTexture(AsrShaderIDs.SrvLanczosLut, Resources.LanczosLut); commandBuffer.SetGlobalTexture(AsrShaderIDs.SrvUpscaleMaximumBiasLut, Resources.MaximumBiasLut); commandBuffer.SetGlobalTexture(AsrShaderIDs.SrvSceneLuminanceMips, Resources.SceneLuminance); - commandBuffer.SetGlobalTexture(AsrShaderIDs.SrvAutoExposure, Resources.AutoExposure); + commandBuffer.SetGlobalTexture(AsrShaderIDs.SrvAutoExposure, Resources.AutoExposure[frameIndex]); commandBuffer.SetGlobalTexture(AsrShaderIDs.SrvLumaHistory, Resources.LumaHistory[frameIndex ^ 1]); commandBuffer.SetGlobalTexture(AsrShaderIDs.SrvInternalTemporalReactive, Resources.InternalReactive[frameIndex ^ 1]); diff --git a/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrResources.cs b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrResources.cs index 1d9fd89..89ab6f8 100644 --- a/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrResources.cs +++ b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Runtime/AsrResources.cs @@ -36,8 +36,8 @@ namespace ArmASR public Texture2D LanczosLut; public Texture2D MaximumBiasLut; public RenderTexture SpdAtomicCounter; - public RenderTexture AutoExposure; public RenderTexture SceneLuminance; + public readonly RenderTexture[] AutoExposure = new RenderTexture[2]; public readonly RenderTexture[] DilatedMotionVectors = new RenderTexture[2]; public readonly RenderTexture[] LockStatus = new RenderTexture[2]; public readonly RenderTexture[] InternalUpscaled = new RenderTexture[2]; @@ -90,10 +90,6 @@ namespace ArmASR SpdAtomicCounter = new RenderTexture(1, 1, 0, GraphicsFormat.R32_UInt) { name = "ASR_SpdAtomicCounter", enableRandomWrite = true }; SpdAtomicCounter.Create(); - // Resource FSR2_AutoExposure: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R32G32_FLOAT, FFX_RESOURCE_FLAGS_NONE - AutoExposure = new RenderTexture(1, 1, 0, rg16Format) { name = "ASR_AutoExposure", enableRandomWrite = true }; - AutoExposure.Create(); - // 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; @@ -101,6 +97,9 @@ namespace ArmASR SceneLuminance = new RenderTexture(w, h, 0, r16Format, mipCount) { name = "ASR_ExposureMips", enableRandomWrite = true, useMipMap = true, autoGenerateMips = false }; SceneLuminance.Create(); + // Resource FSR2_AutoExposure: FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R32G32_FLOAT, FFX_RESOURCE_FLAGS_NONE + CreateDoubleBufferedResource(AutoExposure, "ASR_AutoExposure", Vector2Int.one, rg16Format); + // Resources FSR2_InternalDilatedVelocity1/2: FFX_RESOURCE_USAGE_RENDERTARGET | FFX_RESOURCE_USAGE_UAV, FFX_SURFACE_FORMAT_R16G16_FLOAT, FFX_RESOURCE_FLAGS_NONE CreateDoubleBufferedResource(DilatedMotionVectors, "ASR_InternalDilatedVelocity", contextDescription.MaxRenderSize, GraphicsFormat.R16G16_SFloat); @@ -194,8 +193,8 @@ namespace ArmASR DestroyResource(InternalUpscaled); DestroyResource(LockStatus); DestroyResource(DilatedMotionVectors); + DestroyResource(AutoExposure); DestroyResource(ref SceneLuminance); - DestroyResource(ref AutoExposure); DestroyResource(ref DefaultReactive); DestroyResource(ref DefaultExposure); DestroyResource(ref MaximumBiasLut); diff --git a/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Shaders/shaders/ffxm_fsr2_compute_luminance_pyramid_pass.hlsl b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Shaders/shaders/ffxm_fsr2_compute_luminance_pyramid_pass.hlsl index cba3d0b..314e189 100644 --- a/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Shaders/shaders/ffxm_fsr2_compute_luminance_pyramid_pass.hlsl +++ b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Shaders/shaders/ffxm_fsr2_compute_luminance_pyramid_pass.hlsl @@ -20,6 +20,7 @@ // SOFTWARE. #define FSR2_BIND_SRV_INPUT_COLOR 0 +#define FSR2_BIND_SRV_AUTO_EXPOSURE 1 #define FSR2_BIND_UAV_SPD_GLOBAL_ATOMIC 1 #define FSR2_BIND_UAV_EXPOSURE_MIP_LUMA_CHANGE 2 diff --git a/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Shaders/shaders/fsr2/ffxm_fsr2_callbacks_hlsl.h b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Shaders/shaders/fsr2/ffxm_fsr2_callbacks_hlsl.h index c277f7d..6159912 100644 --- a/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Shaders/shaders/fsr2/ffxm_fsr2_callbacks_hlsl.h +++ b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Shaders/shaders/fsr2/ffxm_fsr2_callbacks_hlsl.h @@ -946,7 +946,9 @@ FfxFloat32x3 LoadOpaqueOnly(FFXM_PARAMETER_IN FFXM_MIN16_I2 iPxPos) FfxFloat32x2 SPD_LoadExposureBuffer() { -#if defined FSR2_BIND_UAV_AUTO_EXPOSURE +#if defined FSR2_BIND_SRV_AUTO_EXPOSURE + return r_auto_exposure[FfxInt32x2(0, 0)].rg; +#elif defined FSR2_BIND_UAV_AUTO_EXPOSURE return rw_auto_exposure[FfxInt32x2(0, 0)].rg; #else return FfxFloat32x2(0.f, 0.f); From 8d85253def913103c019073fdd1aa664977f370a Mon Sep 17 00:00:00 2001 From: Nico de Poel Date: Mon, 24 Mar 2025 14:34:13 +0100 Subject: [PATCH 3/3] Enabled Native16Bit requirement for Vulkan, which sets a precedent for other graphics APIs to use this as well --- .../Effects/Upscaling/ASR/Shaders/ffxm_fsr2_common.cginc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Shaders/ffxm_fsr2_common.cginc b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Shaders/ffxm_fsr2_common.cginc index 895e4cf..2e3c9b2 100644 --- a/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Shaders/ffxm_fsr2_common.cginc +++ b/Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/ASR/Shaders/ffxm_fsr2_common.cginc @@ -3,6 +3,13 @@ #pragma warning(disable: 3205) // Conversion from larger type to smaller, possible loss of data #pragma warning(disable: 3556) // Integer divides might be much slower, try using uints if possible +// Doesn't work for: +// - DX11: forces use of DXC which is not supported +// - XB1: native FP16 seems to be unsupported +#if defined(SHADER_API_VULKAN) +#pragma require Native16Bit +#endif + // If these keywords are set by Unity, redefine them to have a truthy value #ifdef FFXM_FSR2_OPTION_SHADER_OPT_PERFORMANCE #undef FFXM_FSR2_OPTION_SHADER_OPT_PERFORMANCE