Browse Source

Changed auto-exposure texture into a double buffered resource (FSR2), 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.

fsr3.1.4
Nico de Poel 9 months ago
parent
commit
97af0d9d8a
  1. 6
      Runtime/FSR2/Fsr2Context.cs
  2. 5
      Runtime/FSR2/Fsr2Pass.cs
  3. 11
      Runtime/FSR2/Fsr2Resources.cs
  4. 1
      Shaders/shaders/ffx_fsr2_compute_luminance_pyramid_pass.hlsl
  5. 4
      Shaders/shaders/fsr2/ffx_fsr2_callbacks_hlsl.h
  6. 2
      Shaders/shaders/fsr2/ffx_fsr2_compute_luminance_pyramid.h

6
Runtime/FSR2/Fsr2Context.cs

@ -163,7 +163,7 @@ namespace FidelityFX.FSR2
// If auto exposure is enabled use the auto exposure SRV, otherwise what the app sends
if ((_contextDescription.Flags & Fsr2.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);
@ -211,8 +211,8 @@ namespace FidelityFX.FSR2
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, 1f, 0f, 0f));
commandBuffer.SetRenderTarget(_resources.AutoExposure[frameIndex ^ 1]);
commandBuffer.ClearRenderTarget(false, true, new Color(0f, 1e8f, 0f, 0f));
// Reset atomic counter to 0
commandBuffer.SetRenderTarget(_resources.SpdAtomicCounter);

5
Runtime/FSR2/Fsr2Pass.cs

@ -127,11 +127,12 @@ namespace FidelityFX.FSR2
{
ref var color = ref dispatchParams.Color;
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvInputColor, color.RenderTarget, color.MipLevel, color.SubElement);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvAutoExposure, Resources.AutoExposure[frameIndex ^ 1]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavSpdAtomicCount, Resources.SpdAtomicCounter);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavExposureMipLumaChange, Resources.SceneLuminance, ShadingChangeMipLevel);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavExposureMip5, Resources.SceneLuminance, 5);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavAutoExposure, Resources.AutoExposure);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavAutoExposure, Resources.AutoExposure[frameIndex]);
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbFsr2, Constants, 0, Marshal.SizeOf<Fsr2.UpscalerConstants>());
commandBuffer.SetComputeConstantBufferParam(ComputeShader, Fsr2ShaderIDs.CbSpd, _spdConstants, 0, Marshal.SizeOf<Fsr2.SpdConstants>());
@ -271,7 +272,7 @@ namespace FidelityFX.FSR2
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvLanczosLut, Resources.LanczosLut);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvUpscaleMaximumBiasLut, Resources.MaximumBiasLut);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvSceneLuminanceMips, Resources.SceneLuminance);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvAutoExposure, Resources.AutoExposure);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvAutoExposure, Resources.AutoExposure[frameIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.SrvLumaHistory, Resources.LumaHistory[frameIndex ^ 1]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, Fsr2ShaderIDs.UavInternalUpscaled, Resources.InternalUpscaled[frameIndex]);

11
Runtime/FSR2/Fsr2Resources.cs

@ -36,10 +36,10 @@ namespace FidelityFX.FSR2
public Texture2D LanczosLut;
public Texture2D MaximumBiasLut;
public RenderTexture SpdAtomicCounter;
public RenderTexture AutoExposure;
public RenderTexture SceneLuminance;
public RenderTexture AutoReactive;
public RenderTexture AutoComposition;
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];
@ -91,10 +91,6 @@ namespace FidelityFX.FSR2
SpdAtomicCounter = new RenderTexture(1, 1, 0, GraphicsFormat.R32_UInt) { name = "FSR2_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, GraphicsFormat.R32G32_SFloat) { name = "FSR2_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;
@ -102,6 +98,9 @@ namespace FidelityFX.FSR2
SceneLuminance = new RenderTexture(w, h, 0, GraphicsFormat.R16_SFloat, mipCount) { name = "FSR2_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, "FSR2_AutoExposure", Vector2Int.one, GraphicsFormat.R32G32_SFloat);
// 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);
@ -186,8 +185,8 @@ namespace FidelityFX.FSR2
DestroyResource(InternalUpscaled);
DestroyResource(LockStatus);
DestroyResource(DilatedMotionVectors);
DestroyResource(AutoExposure);
DestroyResource(ref SceneLuminance);
DestroyResource(ref AutoExposure);
DestroyResource(ref DefaultReactive);
DestroyResource(ref DefaultExposure);
DestroyResource(ref MaximumBiasLut);

1
Shaders/shaders/ffx_fsr2_compute_luminance_pyramid_pass.hlsl

@ -21,6 +21,7 @@
// THE SOFTWARE.
#define FSR2_BIND_SRV_INPUT_COLOR 0
#define FSR2_BIND_SRV_AUTO_EXPOSURE 1
#define FSR2_BIND_UAV_SPD_GLOBAL_ATOMIC 0
#define FSR2_BIND_UAV_EXPOSURE_MIP_LUMA_CHANGE 1

4
Shaders/shaders/fsr2/ffx_fsr2_callbacks_hlsl.h

@ -908,7 +908,9 @@ void StorePrevPostAlpha(FFX_PARAMETER_IN FFX_MIN16_I2 iPxPos, FFX_PARAMETER_IN F
FfxFloat32x2 SPD_LoadExposureBuffer()
{
#if defined FSR2_BIND_UAV_AUTO_EXPOSURE
#if defined FSR2_BIND_SRV_AUTO_EXPOSURE
return r_auto_exposure[FfxInt32x2(0, 0)];
#elif defined FSR2_BIND_UAV_AUTO_EXPOSURE
return rw_auto_exposure[FfxInt32x2(0, 0)];
#else
return FfxFloat32x2(0.f, 0.f);

2
Shaders/shaders/fsr2/ffx_fsr2_compute_luminance_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)
{

Loading…
Cancel
Save