diff --git a/Assets/Scripts/Fsr2Controller.cs b/Assets/Scripts/Fsr2Controller.cs
index f1b2287..54ab307 100644
--- a/Assets/Scripts/Fsr2Controller.cs
+++ b/Assets/Scripts/Fsr2Controller.cs
@@ -5,29 +5,42 @@ using UnityEngine.Rendering;
namespace FidelityFX
{
+ ///
+ /// This class is responsible for hooking into various Unity events and translating them to the FSR2 subsystem.
+ /// 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.
+ ///
[RequireComponent(typeof(Camera))]
public class Fsr2Controller : MonoBehaviour
{
[SerializeField] private Fsr2.QualityMode qualityMode;
+
+ [SerializeField] private bool performSharpenPass = true;
+
+ [SerializeField, Range(0, 1)] private float sharpness = 0.8f;
+ private Fsr2Context _context;
+
private Camera _renderCamera;
private RenderTexture _originalRenderTarget;
+ private DepthTextureMode _originalDepthTextureMode;
private GameObject _displayCameraObject;
private Camera _displayCamera;
private Fsr2Dispatcher _dispatcher;
+ private readonly Fsr2.DispatchDescription _dispatchDescription = new Fsr2.DispatchDescription();
private Fsr2.QualityMode _prevQualityMode;
private Vector2Int _prevScreenSize;
private CommandBuffer _opaqueOnlyCommandBuffer;
private CommandBuffer _inputsCommandBuffer;
-
+
private void OnEnable()
{
- _renderCamera = GetComponent();
if (_displayCameraObject == null)
{
+ // Create a helper object with a camera that outputs at screen resolution
_displayCameraObject = new GameObject("FSR2 Camera Object");
_displayCameraObject.transform.SetParent(transform);
_displayCameraObject.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity);
@@ -45,15 +58,19 @@ namespace FidelityFX
_displayCamera.renderingPath = RenderingPath.Forward;
_dispatcher = _displayCameraObject.AddComponent();
+ _dispatcher.DispatchDescription = _dispatchDescription;
}
+
+ Fsr2.GetRenderResolutionFromQualityMode(out var renderWidth, out var renderHeight, Screen.width, Screen.height, qualityMode);
+ _context = Fsr2.CreateContext(new Vector2Int(Screen.width, Screen.height), new Vector2Int(renderWidth, renderHeight), Fsr2.InitializationFlags.EnableMotionVectorsJitterCancellation);
- _dispatcher.renderCamera = _renderCamera;
- _dispatcher.renderScale = 1.0f / Fsr2.GetUpscaleRatioFromQualityMode(qualityMode);
+ _dispatcher.Context = _context;
_dispatcher.enabled = true;
- Fsr2.GetRenderResolutionFromQualityMode(out var renderWidth, out var renderHeight, Screen.width, Screen.height, qualityMode);
-
+ // Set up the original camera to output all of the required FSR2 input resources at the desired resolution
+ _renderCamera = GetComponent();
_originalRenderTarget = _renderCamera.targetTexture; // TODO: if this isn't null, could maybe reuse this for the output texture?
+ _originalDepthTextureMode = _renderCamera.depthTextureMode;
_renderCamera.targetTexture = new RenderTexture(
renderWidth, renderHeight,
@@ -64,6 +81,7 @@ namespace FidelityFX
_renderCamera.depthTextureMode |= DepthTextureMode.Depth | DepthTextureMode.MotionVectors;
+ // Create command buffers to bind the camera's output at the right moments in the rendering pipeline
_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);
@@ -99,9 +117,17 @@ namespace FidelityFX
_renderCamera.targetTexture.Release();
_renderCamera.targetTexture = _originalRenderTarget;
+ _renderCamera.depthTextureMode = _originalDepthTextureMode;
+ _dispatcher.Context = null;
_dispatcher.enabled = false;
_displayCamera.enabled = false;
+
+ if (_context != null)
+ {
+ _context.Destroy();
+ _context = null;
+ }
}
private void Update()
@@ -116,21 +142,48 @@ namespace FidelityFX
}
}
- private Rect _tempRect;
+ public void Reset()
+ {
+ _reset = true;
+ }
+ private Rect _tempRect;
+ private bool _reset;
+
private void OnPreRender()
{
_tempRect = _renderCamera.rect;
_renderCamera.aspect = (Screen.width * _tempRect.width) / (Screen.height * _tempRect.height);
_renderCamera.rect = new Rect(0, 0, 1, 1);
+ var targetTexture = _renderCamera.targetTexture;
+
+ _dispatchDescription.Color = null;
+ _dispatchDescription.Depth = null;
+ _dispatchDescription.MotionVectors = null;
+ _dispatchDescription.Output = null;
+ _dispatchDescription.Exposure = null;
+ _dispatchDescription.Reactive = null;
+ _dispatchDescription.PreExposure = 0;
+ _dispatchDescription.EnableSharpening = performSharpenPass;
+ _dispatchDescription.Sharpness = sharpness;
+ _dispatchDescription.MotionVectorScale.x = -_renderCamera.pixelWidth;
+ _dispatchDescription.MotionVectorScale.y = -_renderCamera.pixelHeight;
+ _dispatchDescription.RenderSize = new Vector2Int(targetTexture.width, targetTexture.height);
+ _dispatchDescription.FrameTimeDelta = Time.unscaledDeltaTime;
+ _dispatchDescription.CameraNear = _renderCamera.nearClipPlane;
+ _dispatchDescription.CameraFar = _renderCamera.farClipPlane;
+ _dispatchDescription.CameraFovAngleVertical = _renderCamera.fieldOfView * Mathf.Deg2Rad;
+ _dispatchDescription.ViewSpaceToMetersFactor = 1.0f; // 1 unit is 1 meter in Unity
+ _dispatchDescription.Reset = _reset;
+ _reset = false;
+
// Perform custom jittering of the camera's projection matrix according to FSR2's instructions
- int jitterPhaseCount = Fsr2.GetJitterPhaseCount(_renderCamera.targetTexture.width, Screen.width);
+ int jitterPhaseCount = Fsr2.GetJitterPhaseCount(targetTexture.width, Screen.width);
Fsr2.GetJitterOffset(out float jitterX, out float jitterY, Time.frameCount, jitterPhaseCount);
- _dispatcher.SetJitterOffset(new Vector2(jitterX, jitterY));
+ _dispatchDescription.JitterOffset = new Vector2(jitterX, jitterY);
- var targetTexture = _renderCamera.targetTexture;
jitterX = 2.0f * jitterX / targetTexture.width;
jitterY = 2.0f * jitterY / targetTexture.height;
@@ -146,44 +199,17 @@ namespace FidelityFX
}
///
- /// This class is responsible for hooking into various Unity events and translating them to the FSR2 subsystem.
- /// 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.
+ /// Helper class to dispatch FSR2 commands on the display camera object, and render the final output texture.
///
internal class Fsr2Dispatcher : MonoBehaviour
{
- [SerializeField] private bool performSharpenPass = true;
-
- [SerializeField, Range(0, 1)] private float sharpness = 0.8f;
-
- [SerializeField] private bool reset;
-
- [HideInInspector] public Camera renderCamera;
-
- [HideInInspector] public float renderScale;
-
- private bool _started;
-
- private Vector2Int DisplaySize => new Vector2Int(Screen.width, Screen.height);
- private Vector2Int RenderSize => new Vector2Int(Mathf.FloorToInt(Screen.width * renderScale), Mathf.FloorToInt(Screen.height * renderScale));
-
- private Fsr2Context _context;
- private readonly Fsr2.DispatchDescription _dispatchDescription = new Fsr2.DispatchDescription();
+ public Fsr2Context Context;
+ public Fsr2.DispatchDescription DispatchDescription;
+
private CommandBuffer _commandBuffer;
- private void Start()
- {
- _started = true;
- OnEnable();
- }
-
private void OnEnable()
{
- // Delay OnEnable until we're sure all fields and properties are set
- if (!_started)
- return;
-
- _context = Fsr2.CreateContext(DisplaySize, RenderSize, Fsr2.InitializationFlags.EnableMotionVectorsJitterCancellation);
_commandBuffer = new CommandBuffer { name = "FSR2 Dispatch" };
}
@@ -194,20 +220,8 @@ namespace FidelityFX
_commandBuffer.Release();
_commandBuffer = null;
}
-
- if (_context != null)
- {
- _context.Destroy();
- _context = null;
- }
- }
-
- public void SetJitterOffset(Vector2 jitterOffset)
- {
- _dispatchDescription.JitterOffset = jitterOffset;
}
- // For legacy built-in render pipeline
private void OnRenderImage(RenderTexture src, RenderTexture dest)
{
_commandBuffer.Clear();
@@ -221,30 +235,10 @@ namespace FidelityFX
else
{
// We are rendering to the backbuffer, so we need a temporary render texture for FSR2 to output to
- _commandBuffer.GetTemporaryRT(Fsr2Pipeline.UavUpscaledOutput, DisplaySize.x, DisplaySize.y, 0, default, GraphicsFormat.R16G16B16A16_SFloat, 1, true);
+ _commandBuffer.GetTemporaryRT(Fsr2Pipeline.UavUpscaledOutput, Screen.width, Screen.height, 0, default, GraphicsFormat.R16G16B16A16_SFloat, 1, true);
}
- _dispatchDescription.Color = null;
- _dispatchDescription.Depth = null;
- _dispatchDescription.MotionVectors = null;
- _dispatchDescription.Output = null;
- _dispatchDescription.Exposure = null;
- _dispatchDescription.Reactive = null;
- _dispatchDescription.PreExposure = 0;
- _dispatchDescription.EnableSharpening = performSharpenPass;
- _dispatchDescription.Sharpness = sharpness;
- _dispatchDescription.MotionVectorScale.x = -renderCamera.pixelWidth;
- _dispatchDescription.MotionVectorScale.y = -renderCamera.pixelHeight;
- _dispatchDescription.RenderSize = RenderSize;
- _dispatchDescription.FrameTimeDelta = Time.unscaledDeltaTime;
- _dispatchDescription.CameraNear = renderCamera.nearClipPlane;
- _dispatchDescription.CameraFar = renderCamera.farClipPlane;
- _dispatchDescription.CameraFovAngleVertical = renderCamera.fieldOfView * Mathf.Deg2Rad;
- _dispatchDescription.ViewSpaceToMetersFactor = 1.0f; // 1 unit is 1 meter in Unity
- _dispatchDescription.Reset = reset;
- reset = false;
-
- _context.Dispatch(_dispatchDescription, _commandBuffer);
+ Context.Dispatch(DispatchDescription, _commandBuffer);
// Output upscaled image to screen
// TODO: if `dest` is null, we likely don't care about the depth & motion vectors anymore