Browse Source

- Replaced all input/output parameters with RenderTargetIdentifiers, allowing more flexibility in how these resources are assigned

- Cleaned up main MonoBehaviour ahead of a big refactor, and added camera event-based command buffers to set opaque-only and motion vector resources
mac-autoexp
Nico de Poel 3 years ago
parent
commit
86c16e3694
  1. 18
      Assets/Scripts/Fsr2.cs
  2. 13
      Assets/Scripts/Fsr2Context.cs
  3. 17
      Assets/Scripts/Fsr2Controller.cs
  4. 157
      Assets/Scripts/Fsr2Pipeline.cs
  5. 143
      Assets/Scripts/SubsampleTest.cs

18
Assets/Scripts/Fsr2.cs

@ -138,12 +138,12 @@ namespace FidelityFX
public class DispatchDescription
{
public Texture ColorDepth;
public Texture MotionVectors;
public Texture Exposure;
public Texture Reactive;
public Texture TransparencyAndComposition;
public RenderTexture Output;
public RenderTargetIdentifier? Color;
public RenderTargetIdentifier? Depth;
public RenderTargetIdentifier? MotionVectors;
public RenderTargetIdentifier? Exposure;
public RenderTargetIdentifier? Reactive;
public RenderTargetIdentifier? Output;
public Vector2 JitterOffset;
public Vector2 MotionVectorScale;
public Vector2Int RenderSize;
@ -160,9 +160,9 @@ namespace FidelityFX
public class GenerateReactiveDescription
{
public Texture ColorOpaqueOnly;
public Texture ColorPreUpscale;
public RenderTexture OutReactive;
public RenderTargetIdentifier? ColorOpaqueOnly;
public RenderTargetIdentifier? ColorPreUpscale;
public RenderTargetIdentifier? OutReactive;
public Vector2Int RenderSize;
public float Scale;
public float CutoffThreshold;

13
Assets/Scripts/Fsr2Context.cs

@ -198,7 +198,12 @@ namespace FidelityFX
public void GenerateReactiveMask(Fsr2.GenerateReactiveDescription dispatchParams)
{
_commandBuffer.Clear();
GenerateReactiveMask(dispatchParams, _commandBuffer);
Graphics.ExecuteCommandBuffer(_commandBuffer);
}
public void GenerateReactiveMask(Fsr2.GenerateReactiveDescription dispatchParams, CommandBuffer commandBuffer)
{
const int threadGroupWorkRegionDim = 8;
int dispatchSrcX = (dispatchParams.RenderSize.x + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
int dispatchSrcY = (dispatchParams.RenderSize.y + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
@ -210,8 +215,6 @@ namespace FidelityFX
_generateReactiveConstantsBuffer.SetData(_generateReactiveConstantsArray);
((Fsr2GenerateReactivePipeline)_generateReactivePipeline).ScheduleDispatch(_commandBuffer, dispatchParams, dispatchSrcX, dispatchSrcY);
Graphics.ExecuteCommandBuffer(_commandBuffer);
}
private void SetupConstants(Fsr2.DispatchDescription dispatchParams, bool resetAccumulation)
@ -219,11 +222,9 @@ namespace FidelityFX
ref Fsr2.Fsr2Constants constants = ref Constants;
constants.jitterOffset = dispatchParams.JitterOffset;
constants.renderSize = new Vector2Int(
dispatchParams.RenderSize.x > 0 ? dispatchParams.RenderSize.x : dispatchParams.ColorDepth.width,
dispatchParams.RenderSize.y > 0 ? dispatchParams.RenderSize.y : dispatchParams.ColorDepth.height);
constants.renderSize = dispatchParams.RenderSize;
constants.maxRenderSize = _contextDescription.MaxRenderSize;
constants.inputColorResourceDimensions = new Vector2Int(dispatchParams.ColorDepth.width, dispatchParams.ColorDepth.height);
constants.inputColorResourceDimensions = dispatchParams.RenderSize; // We have no way to query the actual width & height of the input resources, so trust that it matches the render size
// Compute the horizontal FOV for the shader from the vertical one
float aspectRatio = (float)dispatchParams.RenderSize.x / dispatchParams.RenderSize.y;

17
Assets/Scripts/Fsr2Controller.cs

@ -12,7 +12,7 @@ using UnityEngine.Rendering;
/// This includes creation and destruction of the FSR2 context, as well as dispatching commands at the right time.
/// This class also exposes various FSR2 parameters to the Unity inspector.
/// </summary>
public class Fsr2Controller : MonoBehaviour
public class Fsr2Controller : MonoBehaviour // TODO: rename this to Fsr2Dispatcher and move most of the functionality to Fsr2Controller (now SubsampleTest)
{
[SerializeField]
private bool performSharpenPass = true;
@ -40,6 +40,8 @@ public class Fsr2Controller : MonoBehaviour
private Fsr2Context _context;
private readonly Fsr2.DispatchDescription _dispatchDescription = new Fsr2.DispatchDescription();
public Fsr2Context Context => _context;
private RenderTexture _upscaledOutput;
private Material _copyMotionMat;
@ -102,15 +104,15 @@ public class Fsr2Controller : MonoBehaviour
{
var renderBuffer = gameCamera.targetTexture;
var commandBuffer = new CommandBuffer { name = "FSR2" };
var commandBuffer = new CommandBuffer { name = "FSR2 Main" };
int motionVectorsId = Shader.PropertyToID("r_input_motion_vectors");
// int motionVectorsId = Shader.PropertyToID("r_input_motion_vectors");
int upscaledOutputId = Shader.PropertyToID("rw_upscaled_output");
// I hate having to allocate extra RTs just to duplicate already existing Unity render buffers, but AFAIK there is no way to directly address motion vectors from code
// TODO: or can we? Look at RenderTargetIdentifier.MotionVectors with SetGlobalTexture!! (Possibly in gameCamera OnRenderImage)
commandBuffer.GetTemporaryRT(motionVectorsId, renderBuffer.width, renderBuffer.height, 0, default, RenderTextureFormat.RGHalf);
commandBuffer.Blit(renderBuffer, motionVectorsId, CopyMotionVectorsMaterial);
// commandBuffer.GetTemporaryRT(motionVectorsId, renderBuffer.width, renderBuffer.height, 0, default, RenderTextureFormat.RGHalf);
// commandBuffer.Blit(renderBuffer, motionVectorsId, CopyMotionVectorsMaterial);
if (dest != null)
{
@ -124,7 +126,8 @@ public class Fsr2Controller : MonoBehaviour
commandBuffer.GetTemporaryRT(upscaledOutputId, DisplaySize.x, DisplaySize.y, 0, default, GraphicsFormat.R16G16B16A16_SFloat, 1, true);
}
_dispatchDescription.ColorDepth = renderBuffer;
_dispatchDescription.Color = null;
_dispatchDescription.Depth = null;
_dispatchDescription.MotionVectors = null;
_dispatchDescription.Output = null;
_dispatchDescription.Exposure = null;
@ -153,7 +156,7 @@ public class Fsr2Controller : MonoBehaviour
commandBuffer.ReleaseTemporaryRT(upscaledOutputId);
}
commandBuffer.ReleaseTemporaryRT(motionVectorsId);
// commandBuffer.ReleaseTemporaryRT(motionVectorsId);
Graphics.ExecuteCommandBuffer(commandBuffer);
commandBuffer.Release();

157
Assets/Scripts/Fsr2Pipeline.cs

@ -18,41 +18,41 @@ namespace FidelityFX
protected int KernelIndex;
// Shader resource views, i.e. read-only bindings
protected static readonly int SrvInputColor = Shader.PropertyToID("r_input_color_jittered");
protected static readonly int SrvOpaqueOnly = Shader.PropertyToID("r_input_opaque_only");
protected static readonly int SrvInputMotionVectors = Shader.PropertyToID("r_input_motion_vectors");
protected static readonly int SrvInputDepth = Shader.PropertyToID("r_input_depth");
protected static readonly int SrvInputExposure = Shader.PropertyToID("r_input_exposure");
protected static readonly int SrvDilatedMotionVectors = Shader.PropertyToID("r_dilated_motion_vectors");
protected static readonly int SrvReactiveMask = Shader.PropertyToID("r_reactive_mask");
protected static readonly int SrvTransparencyAndCompositionMask = Shader.PropertyToID("r_transparency_and_composition_mask");
protected static readonly int SrvPrevDilatedMotionVectors = Shader.PropertyToID("r_previous_dilated_motion_vectors");
protected static readonly int SrvInternalUpscaled = Shader.PropertyToID("r_internal_upscaled_color");
protected static readonly int SrvLockStatus = Shader.PropertyToID("r_lock_status");
protected static readonly int SrvLanczosLut = Shader.PropertyToID("r_lanczos_lut");
protected static readonly int SrvUpscaleMaximumBiasLut = Shader.PropertyToID("r_upsample_maximum_bias_lut");
protected static readonly int SrvSceneLuminanceMips = Shader.PropertyToID("r_imgMips");
protected static readonly int SrvAutoExposure = Shader.PropertyToID("r_auto_exposure");
protected static readonly int SrvLumaHistory = Shader.PropertyToID("r_luma_history");
protected static readonly int SrvRcasInput = Shader.PropertyToID("r_rcas_input");
internal static readonly int SrvInputColor = Shader.PropertyToID("r_input_color_jittered");
internal static readonly int SrvOpaqueOnly = Shader.PropertyToID("r_input_opaque_only");
internal static readonly int SrvInputMotionVectors = Shader.PropertyToID("r_input_motion_vectors");
internal static readonly int SrvInputDepth = Shader.PropertyToID("r_input_depth");
internal static readonly int SrvInputExposure = Shader.PropertyToID("r_input_exposure");
internal static readonly int SrvDilatedMotionVectors = Shader.PropertyToID("r_dilated_motion_vectors");
internal static readonly int SrvReactiveMask = Shader.PropertyToID("r_reactive_mask");
internal static readonly int SrvTransparencyAndCompositionMask = Shader.PropertyToID("r_transparency_and_composition_mask");
internal static readonly int SrvPrevDilatedMotionVectors = Shader.PropertyToID("r_previous_dilated_motion_vectors");
internal static readonly int SrvInternalUpscaled = Shader.PropertyToID("r_internal_upscaled_color");
internal static readonly int SrvLockStatus = Shader.PropertyToID("r_lock_status");
internal static readonly int SrvLanczosLut = Shader.PropertyToID("r_lanczos_lut");
internal static readonly int SrvUpscaleMaximumBiasLut = Shader.PropertyToID("r_upsample_maximum_bias_lut");
internal static readonly int SrvSceneLuminanceMips = Shader.PropertyToID("r_imgMips");
internal static readonly int SrvAutoExposure = Shader.PropertyToID("r_auto_exposure");
internal static readonly int SrvLumaHistory = Shader.PropertyToID("r_luma_history");
internal static readonly int SrvRcasInput = Shader.PropertyToID("r_rcas_input");
// Unordered access views, i.e. random read/write bindings
protected static readonly int UavUpscaledOutput = Shader.PropertyToID("rw_upscaled_output");
protected static readonly int UavExposureMipLumaChange = Shader.PropertyToID("rw_img_mip_shading_change");
protected static readonly int UavExposureMip5 = Shader.PropertyToID("rw_img_mip_5");
protected static readonly int UavAutoExposure = Shader.PropertyToID("rw_auto_exposure");
protected static readonly int UavSpdAtomicCount = Shader.PropertyToID("rw_spd_global_atomic");
protected static readonly int UavReconstructedPrevNearestDepth = Shader.PropertyToID("rw_reconstructed_previous_nearest_depth");
protected static readonly int UavDilatedMotionVectors = Shader.PropertyToID("rw_dilated_motion_vectors");
protected static readonly int UavDilatedDepth = Shader.PropertyToID("rw_dilatedDepth");
protected static readonly int UavLockInputLuma = Shader.PropertyToID("rw_lock_input_luma");
protected static readonly int UavDilatedReactiveMasks = Shader.PropertyToID("rw_dilated_reactive_masks");
protected static readonly int UavPreparedInputColor = Shader.PropertyToID("rw_prepared_input_color");
protected static readonly int UavNewLocks = Shader.PropertyToID("rw_new_locks");
protected static readonly int UavInternalUpscaled = Shader.PropertyToID("rw_internal_upscaled_color");
protected static readonly int UavLockStatus = Shader.PropertyToID("rw_lock_status");
protected static readonly int UavLumaHistory = Shader.PropertyToID("rw_luma_history");
protected static readonly int UavAutoReactive = Shader.PropertyToID("rw_output_autoreactive");
internal static readonly int UavUpscaledOutput = Shader.PropertyToID("rw_upscaled_output");
internal static readonly int UavExposureMipLumaChange = Shader.PropertyToID("rw_img_mip_shading_change");
internal static readonly int UavExposureMip5 = Shader.PropertyToID("rw_img_mip_5");
internal static readonly int UavAutoExposure = Shader.PropertyToID("rw_auto_exposure");
internal static readonly int UavSpdAtomicCount = Shader.PropertyToID("rw_spd_global_atomic");
internal static readonly int UavReconstructedPrevNearestDepth = Shader.PropertyToID("rw_reconstructed_previous_nearest_depth");
internal static readonly int UavDilatedMotionVectors = Shader.PropertyToID("rw_dilated_motion_vectors");
internal static readonly int UavDilatedDepth = Shader.PropertyToID("rw_dilatedDepth");
internal static readonly int UavLockInputLuma = Shader.PropertyToID("rw_lock_input_luma");
internal static readonly int UavDilatedReactiveMasks = Shader.PropertyToID("rw_dilated_reactive_masks");
internal static readonly int UavPreparedInputColor = Shader.PropertyToID("rw_prepared_input_color");
internal static readonly int UavNewLocks = Shader.PropertyToID("rw_new_locks");
internal static readonly int UavInternalUpscaled = Shader.PropertyToID("rw_internal_upscaled_color");
internal static readonly int UavLockStatus = Shader.PropertyToID("rw_lock_status");
internal static readonly int UavLumaHistory = Shader.PropertyToID("rw_luma_history");
internal static readonly int UavAutoReactive = Shader.PropertyToID("rw_output_autoreactive");
// Constant buffer bindings
protected static readonly int CbFsr2 = Shader.PropertyToID("cbFSR2");
@ -181,10 +181,8 @@ namespace FidelityFX
public override void ScheduleDispatch(CommandBuffer commandBuffer, Fsr2.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY)
{
if (dispatchParams.ColorDepth != null)
{
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputColor, dispatchParams.ColorDepth, 0, RenderTextureSubElement.Color);
}
if (dispatchParams.Color.HasValue)
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputColor, dispatchParams.Color.Value, 0, RenderTextureSubElement.Color);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, UavExposureMipLumaChange, Resources.SceneLuminance, ShadingChangeMipLevel);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, UavExposureMip5, Resources.SceneLuminance, 5);
@ -207,16 +205,17 @@ namespace FidelityFX
public override void ScheduleDispatch(CommandBuffer commandBuffer, Fsr2.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY)
{
if (dispatchParams.ColorDepth != null)
{
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputColor, dispatchParams.ColorDepth, 0, RenderTextureSubElement.Color);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputDepth, dispatchParams.ColorDepth, 0, RenderTextureSubElement.Depth);
}
if (dispatchParams.MotionVectors != null)
{
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputMotionVectors, dispatchParams.MotionVectors);
}
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputExposure, dispatchParams.Exposure);
if (dispatchParams.Color.HasValue)
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputColor, dispatchParams.Color.Value, 0, RenderTextureSubElement.Color);
if (dispatchParams.Depth.HasValue)
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputDepth, dispatchParams.Depth.Value, 0, RenderTextureSubElement.Depth);
if (dispatchParams.MotionVectors.HasValue)
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputMotionVectors, dispatchParams.MotionVectors.Value);
if (dispatchParams.Exposure.HasValue)
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputExposure, dispatchParams.Exposure.Value);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, UavDilatedMotionVectors, Resources.DilatedMotionVectors[frameIndex]);
@ -236,20 +235,24 @@ namespace FidelityFX
public override void ScheduleDispatch(CommandBuffer commandBuffer, Fsr2.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY)
{
if (dispatchParams.Color.HasValue)
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputColor, dispatchParams.Color.Value, 0, RenderTextureSubElement.Color);
if (dispatchParams.Depth.HasValue)
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputDepth, dispatchParams.Depth.Value, 0, RenderTextureSubElement.Depth);
if (dispatchParams.MotionVectors.HasValue)
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputMotionVectors, dispatchParams.MotionVectors.Value);
if (dispatchParams.Exposure.HasValue)
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputExposure, dispatchParams.Exposure.Value);
if (dispatchParams.Reactive.HasValue)
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvReactiveMask, dispatchParams.Reactive.Value);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvDilatedMotionVectors, Resources.DilatedMotionVectors[frameIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvReactiveMask, dispatchParams.Reactive);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvTransparencyAndCompositionMask, Resources.DefaultReactive); // Default reactive mask, as we don't support TCR (yet)
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvPrevDilatedMotionVectors, Resources.DilatedMotionVectors[frameIndex ^ 1]);
if (dispatchParams.MotionVectors != null)
{
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputMotionVectors, dispatchParams.MotionVectors);
}
if (dispatchParams.ColorDepth != null)
{
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputColor, dispatchParams.ColorDepth, 0, RenderTextureSubElement.Color);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputDepth, dispatchParams.ColorDepth, 0, RenderTextureSubElement.Depth);
}
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputExposure, dispatchParams.Exposure);
commandBuffer.SetComputeConstantBufferParam(ComputeShader, CbFsr2, Constants, 0, Marshal.SizeOf<Fsr2.Fsr2Constants>());
@ -286,11 +289,13 @@ namespace FidelityFX
public override void ScheduleDispatch(CommandBuffer commandBuffer, Fsr2.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY)
{
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputExposure, dispatchParams.Exposure);
if ((ContextDescription.Flags & Fsr2.InitializationFlags.EnableDisplayResolutionMotionVectors) == 0)
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvDilatedMotionVectors, Resources.DilatedMotionVectors[frameIndex]);
else if (dispatchParams.MotionVectors != null)
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputMotionVectors, dispatchParams.MotionVectors);
else if (dispatchParams.MotionVectors.HasValue)
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputMotionVectors, dispatchParams.MotionVectors.Value);
if (dispatchParams.Exposure.HasValue)
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputExposure, dispatchParams.Exposure.Value);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInternalUpscaled, Resources.InternalUpscaled[frameIndex ^ 1]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvLockStatus, Resources.LockStatus[frameIndex ^ 1]);
@ -302,11 +307,10 @@ namespace FidelityFX
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, UavInternalUpscaled, Resources.InternalUpscaled[frameIndex]);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, UavLockStatus, Resources.LockStatus[frameIndex]);
if (dispatchParams.Output != null)
{
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, UavUpscaledOutput, dispatchParams.Output);
}
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, UavLumaHistory, Resources.LumaHistory[frameIndex]);
if (dispatchParams.Output.HasValue)
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, UavUpscaledOutput, dispatchParams.Output.Value);
commandBuffer.SetComputeConstantBufferParam(ComputeShader, CbFsr2, Constants, 0, Marshal.SizeOf<Fsr2.Fsr2Constants>());
@ -362,12 +366,14 @@ namespace FidelityFX
public override void ScheduleDispatch(CommandBuffer commandBuffer, Fsr2.DispatchDescription dispatchParams, int frameIndex, int dispatchX, int dispatchY)
{
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputExposure, dispatchParams.Exposure);
if (dispatchParams.Exposure.HasValue)
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputExposure, dispatchParams.Exposure.Value);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvRcasInput, Resources.InternalUpscaled[frameIndex]);
if (dispatchParams.Output != null)
{
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, UavUpscaledOutput, dispatchParams.Output);
}
if (dispatchParams.Output.HasValue)
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, UavUpscaledOutput, dispatchParams.Output.Value);
commandBuffer.SetComputeConstantBufferParam(ComputeShader, CbFsr2, Constants, 0, Marshal.SizeOf<Fsr2.Fsr2Constants>());
commandBuffer.SetComputeConstantBufferParam(ComputeShader, CbRcas, _rcasConstants, 0, Marshal.SizeOf<Fsr2.RcasConstants>());
@ -393,9 +399,14 @@ namespace FidelityFX
public void ScheduleDispatch(CommandBuffer commandBuffer, Fsr2.GenerateReactiveDescription dispatchParams, int dispatchX, int dispatchY)
{
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvOpaqueOnly, dispatchParams.ColorOpaqueOnly);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputColor, dispatchParams.ColorPreUpscale);
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, UavAutoExposure, dispatchParams.OutReactive);
if (dispatchParams.ColorOpaqueOnly.HasValue)
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvOpaqueOnly, dispatchParams.ColorOpaqueOnly.Value, 0, RenderTextureSubElement.Color);
if (dispatchParams.ColorPreUpscale.HasValue)
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, SrvInputColor, dispatchParams.ColorPreUpscale.Value, 0, RenderTextureSubElement.Color);
if (dispatchParams.OutReactive.HasValue)
commandBuffer.SetComputeTextureParam(ComputeShader, KernelIndex, UavAutoExposure, dispatchParams.OutReactive.Value);
commandBuffer.SetComputeConstantBufferParam(ComputeShader, CbGenReactive, _generateReactiveConstants, 0, Marshal.SizeOf<Fsr2.GenerateReactiveConstants>());

143
Assets/Scripts/SubsampleTest.cs

@ -1,71 +1,82 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using FidelityFX;
using UnityEngine;
using UnityEngine.Rendering;
[RequireComponent(typeof(Camera))]
public class SubsampleTest : MonoBehaviour
public class SubsampleTest : MonoBehaviour // TODO: rename this to Fsr2Controller
{
private Camera gameCamera;
private Camera _renderCamera;
private GameObject outputCameraObject;
private Camera outputCamera;
private GameObject _displayCameraObject;
private Camera _displayCamera;
[SerializeField]
private Fsr2.QualityMode qualityMode;
[SerializeField]
private bool enableJitter;
private Fsr2Controller _fsr2Controller;
private float _renderScale;
private Fsr2.QualityMode _prevQualityMode;
private Vector2Int _prevScreenSize;
private CommandBuffer _opaqueOnlyCommandBuffer;
private CommandBuffer _reactiveCommandBuffer;
private void OnEnable()
{
_renderScale = 1.0f / Fsr2.GetUpscaleRatioFromQualityMode(qualityMode);
gameCamera = GetComponent<Camera>();
if (outputCameraObject == null)
_renderCamera = GetComponent<Camera>();
if (_displayCameraObject == null)
{
outputCameraObject = new GameObject("FSR2 Camera Object");
outputCameraObject.transform.SetParent(transform);
outputCameraObject.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity);
_displayCameraObject = new GameObject("FSR2 Camera Object");
_displayCameraObject.transform.SetParent(transform);
_displayCameraObject.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity);
//outputCameraObject.transform.hideFlags = HideFlags.HideInHierarchy | HideFlags.HideInInspector;
outputCamera = outputCameraObject.AddComponent<Camera>();
outputCamera.backgroundColor = Color.clear;
outputCamera.clearFlags = CameraClearFlags.Nothing;
outputCamera.eventMask = 0;
outputCamera.cullingMask = 0;
outputCamera.useOcclusionCulling = false;
outputCamera.orthographic = true;
outputCamera.allowMSAA = false;
outputCamera.renderingPath = RenderingPath.Forward;
_fsr2Controller = outputCameraObject.AddComponent<Fsr2Controller>();
// Create a camera that does nothing except output the upscaled image
_displayCamera = _displayCameraObject.AddComponent<Camera>();
_displayCamera.backgroundColor = Color.clear;
_displayCamera.clearFlags = CameraClearFlags.Nothing;
_displayCamera.eventMask = 0;
_displayCamera.cullingMask = 0;
_displayCamera.useOcclusionCulling = false;
_displayCamera.orthographic = true;
_displayCamera.allowMSAA = false;
_displayCamera.renderingPath = RenderingPath.Forward;
_fsr2Controller = _displayCameraObject.AddComponent<Fsr2Controller>();
}
_fsr2Controller.gameCamera = gameCamera;
_fsr2Controller.outputCamera = outputCamera;
_fsr2Controller.gameCamera = _renderCamera;
_fsr2Controller.outputCamera = _displayCamera;
_fsr2Controller.renderScale = _renderScale;
_fsr2Controller.enabled = true;
Fsr2.GetRenderResolutionFromQualityMode(out var renderWidth, out var renderHeight, Screen.width, Screen.height, qualityMode);
gameCamera.targetTexture = new RenderTexture(
// TODO: check if the camera doesn't already have a target texture
_renderCamera.targetTexture = new RenderTexture(
renderWidth, renderHeight,
24, // Can we copy depth value from original camera?
RenderTextureFormat.ARGBHalf); // Can we copy format from original camera? Or renderer quality settings?
gameCamera.depthTextureMode |= DepthTextureMode.Depth | DepthTextureMode.MotionVectors;
_renderCamera.depthTextureMode |= DepthTextureMode.Depth | DepthTextureMode.MotionVectors;
gameCamera.targetTexture.name = "FSR2 Input Texture";
gameCamera.targetTexture.Create();
_renderCamera.targetTexture.name = "FSR2 Input Texture";
_renderCamera.targetTexture.Create();
_opaqueOnlyCommandBuffer = new CommandBuffer { name = "FSR2 Opaque Input" };
// TODO: may need to copy the opaque-only render buffer to a temp RT here, in which case we'll need an additional CommandBuffer to release the temp RT again
_opaqueOnlyCommandBuffer.SetGlobalTexture(Fsr2Pipeline.SrvOpaqueOnly, BuiltinRenderTextureType.CameraTarget, RenderTextureSubElement.Color);
_renderCamera.AddCommandBuffer(CameraEvent.BeforeImageEffectsOpaque, _opaqueOnlyCommandBuffer);
_reactiveCommandBuffer = new CommandBuffer { name = "FSR2 Inputs" };
_reactiveCommandBuffer.SetGlobalTexture(Fsr2Pipeline.SrvInputColor, BuiltinRenderTextureType.CameraTarget, RenderTextureSubElement.Color);
_reactiveCommandBuffer.SetGlobalTexture(Fsr2Pipeline.SrvInputDepth, BuiltinRenderTextureType.CameraTarget, RenderTextureSubElement.Depth);
_reactiveCommandBuffer.SetGlobalTexture(Fsr2Pipeline.SrvInputMotionVectors, BuiltinRenderTextureType.MotionVectors);
_renderCamera.AddCommandBuffer(CameraEvent.BeforeImageEffects, _reactiveCommandBuffer);
// 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
@ -81,28 +92,30 @@ public class SubsampleTest : MonoBehaviour
float biasOffset = Fsr2.GetMipmapBiasOffset(_renderScale);
Fsr2.GlobalCallbacks.ApplyMipmapBias(-biasOffset);
gameCamera.targetTexture.Release();
gameCamera.targetTexture = null;
_renderCamera.RemoveCommandBuffer(CameraEvent.BeforeImageEffectsOpaque, _opaqueOnlyCommandBuffer);
_opaqueOnlyCommandBuffer.Release();
_opaqueOnlyCommandBuffer = null;
_renderCamera.RemoveCommandBuffer(CameraEvent.BeforeImageEffects, _reactiveCommandBuffer);
_reactiveCommandBuffer.Release();
_reactiveCommandBuffer = null;
_renderCamera.targetTexture.Release();
_renderCamera.targetTexture = null;
_fsr2Controller.enabled = false;
outputCamera.enabled = false;
_displayCamera.enabled = false;
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.F12))
{
string path = Path.Combine(Directory.GetCurrentDirectory(), $"screenshot-{DateTime.Now:yyyyMMdd-HHmmss}.png");
ScreenCapture.CaptureScreenshot(path);
Debug.Log($"Screenshot saved to: {path}");
}
outputCamera.enabled = gameCamera.enabled;
_displayCamera.enabled = _renderCamera.enabled;
if (Screen.width != _prevScreenSize.x || Screen.height != _prevScreenSize.y || qualityMode != _prevQualityMode)
{
enabled = false;
enabled = true;
// Force all resources to be destroyed and recreated with the new settings
OnDisable();
OnEnable();
}
}
@ -110,35 +123,27 @@ public class SubsampleTest : MonoBehaviour
private void OnPreRender()
{
gameCamera.aspect = (Screen.width * gameCamera.rect.width) / (Screen.height * gameCamera.rect.height);
_tempRect = _renderCamera.rect;
_renderCamera.aspect = (Screen.width * _tempRect.width) / (Screen.height * _tempRect.height);
_renderCamera.rect = new Rect(0, 0, 1, 1);
// Perform custom jittering of the camera's projection matrix according to FSR2's instructions
int jitterPhaseCount = Fsr2.GetJitterPhaseCount(_renderCamera.targetTexture.width, Screen.width);
Fsr2.GetJitterOffset(out float jitterX, out float jitterY, Time.frameCount, jitterPhaseCount);
_tempRect = gameCamera.rect;
gameCamera.rect = new Rect(0, 0, 1, 1);
_fsr2Controller.SetJitterOffset(new Vector2(jitterX, jitterY));
if (enableJitter)
{
// Perform custom jittering of the camera's projection matrix according to FSR2's instructions
// Unity already does jittering behind the scenes for certain post-effects, so can we perhaps integrate with that?
int jitterPhaseCount = Fsr2.GetJitterPhaseCount(gameCamera.targetTexture.width, Screen.width);
Fsr2.GetJitterOffset(out float jitterX, out float jitterY, Time.frameCount, jitterPhaseCount);
_fsr2Controller.SetJitterOffset(new Vector2(jitterX, jitterY));
jitterX = 2.0f * jitterX / gameCamera.targetTexture.width;
jitterY = 2.0f * jitterY / gameCamera.targetTexture.height;
var jitterTranslationMatrix = Matrix4x4.Translate(new Vector3(jitterX, jitterY, 0));
gameCamera.projectionMatrix = jitterTranslationMatrix * gameCamera.nonJitteredProjectionMatrix;
}
else
{
_fsr2Controller.SetJitterOffset(Vector2.zero);
}
var targetTexture = _renderCamera.targetTexture;
jitterX = 2.0f * jitterX / targetTexture.width;
jitterY = 2.0f * jitterY / targetTexture.height;
var jitterTranslationMatrix = Matrix4x4.Translate(new Vector3(jitterX, jitterY, 0));
_renderCamera.projectionMatrix = jitterTranslationMatrix * _renderCamera.nonJitteredProjectionMatrix;
}
private void OnPostRender()
{
gameCamera.rect = _tempRect;
gameCamera.ResetProjectionMatrix();
_renderCamera.rect = _tempRect;
_renderCamera.ResetProjectionMatrix();
}
}
Loading…
Cancel
Save