Browse Source

Moved Fsr2Dispatcher into Fsr2Controller source file and made it internal. Placed everything into the FidelityFX namespace.

mac-autoexp
Nico de Poel 3 years ago
parent
commit
a9997e1a02
  1. 326
      Assets/Scripts/Fsr2Controller.cs
  2. 127
      Assets/Scripts/Fsr2Dispatcher.cs
  3. 11
      Assets/Scripts/Fsr2Dispatcher.cs.meta

326
Assets/Scripts/Fsr2Controller.cs

@ -1,145 +1,263 @@
using System.Collections;
using FidelityFX;
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering;
[RequireComponent(typeof(Camera))]
public class Fsr2Controller : MonoBehaviour
namespace FidelityFX
{
[SerializeField]
private Fsr2.QualityMode qualityMode;
[RequireComponent(typeof(Camera))]
public class Fsr2Controller : MonoBehaviour
{
[SerializeField] private Fsr2.QualityMode qualityMode;
private Camera _renderCamera;
private RenderTexture _originalRenderTarget;
private Camera _renderCamera;
private RenderTexture _originalRenderTarget;
private GameObject _displayCameraObject;
private Camera _displayCamera;
private Fsr2Dispatcher _dispatcher;
private GameObject _displayCameraObject;
private Camera _displayCamera;
private Fsr2Dispatcher _dispatcher;
private Fsr2.QualityMode _prevQualityMode;
private Vector2Int _prevScreenSize;
private Fsr2.QualityMode _prevQualityMode;
private Vector2Int _prevScreenSize;
private CommandBuffer _opaqueOnlyCommandBuffer;
private CommandBuffer _inputsCommandBuffer;
private CommandBuffer _opaqueOnlyCommandBuffer;
private CommandBuffer _inputsCommandBuffer;
private void OnEnable()
{
_renderCamera = GetComponent<Camera>();
if (_displayCameraObject == null)
private void OnEnable()
{
_displayCameraObject = new GameObject("FSR2 Camera Object");
_displayCameraObject.transform.SetParent(transform);
_displayCameraObject.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity);
//outputCameraObject.transform.hideFlags = HideFlags.HideInHierarchy | HideFlags.HideInInspector;
// 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;
_dispatcher = _displayCameraObject.AddComponent<Fsr2Dispatcher>();
_renderCamera = GetComponent<Camera>();
if (_displayCameraObject == null)
{
_displayCameraObject = new GameObject("FSR2 Camera Object");
_displayCameraObject.transform.SetParent(transform);
_displayCameraObject.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity);
//outputCameraObject.transform.hideFlags = HideFlags.HideInHierarchy | HideFlags.HideInInspector;
// 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;
_dispatcher = _displayCameraObject.AddComponent<Fsr2Dispatcher>();
}
_dispatcher.renderCamera = _renderCamera;
_dispatcher.renderScale = 1.0f / Fsr2.GetUpscaleRatioFromQualityMode(qualityMode);
_dispatcher.enabled = true;
Fsr2.GetRenderResolutionFromQualityMode(out var renderWidth, out var renderHeight, Screen.width, Screen.height, qualityMode);
_originalRenderTarget = _renderCamera.targetTexture; // TODO: if this isn't null, could maybe reuse this for the output texture?
_renderCamera.targetTexture = new RenderTexture(
renderWidth, renderHeight,
_originalRenderTarget != null ? _originalRenderTarget.depth : 32,
_originalRenderTarget != null ? _originalRenderTarget.format : RenderTextureFormat.ARGBHalf) { name = "FSR2 Input Texture" };
_renderCamera.targetTexture.Create();
_renderCamera.depthTextureMode |= DepthTextureMode.Depth | DepthTextureMode.MotionVectors;
_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);
_inputsCommandBuffer = new CommandBuffer { name = "FSR2 Inputs" };
_inputsCommandBuffer.SetGlobalTexture(Fsr2Pipeline.SrvInputColor, BuiltinRenderTextureType.CameraTarget, RenderTextureSubElement.Color);
_inputsCommandBuffer.SetGlobalTexture(Fsr2Pipeline.SrvInputDepth, BuiltinRenderTextureType.CameraTarget, RenderTextureSubElement.Depth);
_inputsCommandBuffer.SetGlobalTexture(Fsr2Pipeline.SrvInputMotionVectors, BuiltinRenderTextureType.MotionVectors);
_renderCamera.AddCommandBuffer(CameraEvent.BeforeImageEffects, _inputsCommandBuffer);
// 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
float biasOffset = Fsr2.GetMipmapBiasOffset(renderWidth, Screen.width);
Fsr2.GlobalCallbacks.ApplyMipmapBias(biasOffset);
_prevScreenSize = new Vector2Int(Screen.width, Screen.height);
_prevQualityMode = qualityMode;
}
_dispatcher.renderCamera = _renderCamera;
_dispatcher.renderScale = 1.0f / Fsr2.GetUpscaleRatioFromQualityMode(qualityMode);
_dispatcher.enabled = true;
private void OnDisable()
{
float biasOffset = Fsr2.GetMipmapBiasOffset(_renderCamera.targetTexture.width, _prevScreenSize.x);
Fsr2.GlobalCallbacks.ApplyMipmapBias(-biasOffset);
_renderCamera.RemoveCommandBuffer(CameraEvent.BeforeImageEffectsOpaque, _opaqueOnlyCommandBuffer);
_opaqueOnlyCommandBuffer.Release();
_opaqueOnlyCommandBuffer = null;
Fsr2.GetRenderResolutionFromQualityMode(out var renderWidth, out var renderHeight, Screen.width, Screen.height, qualityMode);
_renderCamera.RemoveCommandBuffer(CameraEvent.BeforeImageEffects, _inputsCommandBuffer);
_inputsCommandBuffer.Release();
_inputsCommandBuffer = null;
_originalRenderTarget = _renderCamera.targetTexture; // TODO: if this isn't null, could maybe reuse this for the output texture?
_renderCamera.targetTexture.Release();
_renderCamera.targetTexture = _originalRenderTarget;
_dispatcher.enabled = false;
_displayCamera.enabled = false;
}
private void Update()
{
_displayCamera.enabled = _renderCamera.enabled;
if (Screen.width != _prevScreenSize.x || Screen.height != _prevScreenSize.y || qualityMode != _prevQualityMode)
{
// Force all resources to be destroyed and recreated with the new settings
OnDisable();
OnEnable();
}
}
_renderCamera.targetTexture = new RenderTexture(
renderWidth, renderHeight,
_originalRenderTarget != null ? _originalRenderTarget.depth : 32,
_originalRenderTarget != null ? _originalRenderTarget.format : RenderTextureFormat.ARGBHalf) { name = "FSR2 Input Texture" };
private Rect _tempRect;
_renderCamera.targetTexture.Create();
private void OnPreRender()
{
_tempRect = _renderCamera.rect;
_renderCamera.aspect = (Screen.width * _tempRect.width) / (Screen.height * _tempRect.height);
_renderCamera.rect = new Rect(0, 0, 1, 1);
_renderCamera.depthTextureMode |= DepthTextureMode.Depth | DepthTextureMode.MotionVectors;
// 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);
_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);
_dispatcher.SetJitterOffset(new Vector2(jitterX, jitterY));
_inputsCommandBuffer = new CommandBuffer { name = "FSR2 Inputs" };
_inputsCommandBuffer.SetGlobalTexture(Fsr2Pipeline.SrvInputColor, BuiltinRenderTextureType.CameraTarget, RenderTextureSubElement.Color);
_inputsCommandBuffer.SetGlobalTexture(Fsr2Pipeline.SrvInputDepth, BuiltinRenderTextureType.CameraTarget, RenderTextureSubElement.Depth);
_inputsCommandBuffer.SetGlobalTexture(Fsr2Pipeline.SrvInputMotionVectors, BuiltinRenderTextureType.MotionVectors);
_renderCamera.AddCommandBuffer(CameraEvent.BeforeImageEffects, _inputsCommandBuffer);
var targetTexture = _renderCamera.targetTexture;
jitterX = 2.0f * jitterX / targetTexture.width;
jitterY = 2.0f * jitterY / targetTexture.height;
// 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
float biasOffset = Fsr2.GetMipmapBiasOffset(renderWidth, Screen.width);
Fsr2.GlobalCallbacks.ApplyMipmapBias(biasOffset);
var jitterTranslationMatrix = Matrix4x4.Translate(new Vector3(jitterX, jitterY, 0));
_renderCamera.projectionMatrix = jitterTranslationMatrix * _renderCamera.nonJitteredProjectionMatrix;
}
_prevScreenSize = new Vector2Int(Screen.width, Screen.height);
_prevQualityMode = qualityMode;
private void OnPostRender()
{
_renderCamera.rect = _tempRect;
_renderCamera.ResetProjectionMatrix();
}
}
private void OnDisable()
/// <summary>
/// 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.
/// </summary>
internal class Fsr2Dispatcher : MonoBehaviour
{
float biasOffset = Fsr2.GetMipmapBiasOffset(_renderCamera.targetTexture.width, _prevScreenSize.x);
Fsr2.GlobalCallbacks.ApplyMipmapBias(-biasOffset);
[SerializeField] private bool performSharpenPass = true;
_renderCamera.RemoveCommandBuffer(CameraEvent.BeforeImageEffectsOpaque, _opaqueOnlyCommandBuffer);
_opaqueOnlyCommandBuffer.Release();
_opaqueOnlyCommandBuffer = null;
[SerializeField, Range(0, 1)] private float sharpness = 0.8f;
_renderCamera.RemoveCommandBuffer(CameraEvent.BeforeImageEffects, _inputsCommandBuffer);
_inputsCommandBuffer.Release();
_inputsCommandBuffer = null;
[SerializeField] private bool reset;
_renderCamera.targetTexture.Release();
_renderCamera.targetTexture = _originalRenderTarget;
[HideInInspector] public Camera renderCamera;
_dispatcher.enabled = false;
_displayCamera.enabled = false;
}
[HideInInspector] public float renderScale;
private void Update()
{
_displayCamera.enabled = _renderCamera.enabled;
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));
if (Screen.width != _prevScreenSize.x || Screen.height != _prevScreenSize.y || qualityMode != _prevQualityMode)
private Fsr2Context _context;
private readonly Fsr2.DispatchDescription _dispatchDescription = new Fsr2.DispatchDescription();
private CommandBuffer _commandBuffer;
private void Start()
{
// Force all resources to be destroyed and recreated with the new settings
OnDisable();
_started = true;
OnEnable();
}
}
private Rect _tempRect;
private void OnPreRender()
{
_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);
private void OnEnable()
{
// Delay OnEnable until we're sure all fields and properties are set
if (!_started)
return;
_dispatcher.SetJitterOffset(new Vector2(jitterX, jitterY));
_context = Fsr2.CreateContext(DisplaySize, RenderSize, Fsr2.InitializationFlags.EnableMotionVectorsJitterCancellation);
_commandBuffer = new CommandBuffer { name = "FSR2 Dispatch" };
}
var targetTexture = _renderCamera.targetTexture;
jitterX = 2.0f * jitterX / targetTexture.width;
jitterY = 2.0f * jitterY / targetTexture.height;
private void OnDisable()
{
if (_commandBuffer != null)
{
_commandBuffer.Release();
_commandBuffer = null;
}
if (_context != null)
{
_context.Destroy();
_context = null;
}
}
var jitterTranslationMatrix = Matrix4x4.Translate(new Vector3(jitterX, jitterY, 0));
_renderCamera.projectionMatrix = jitterTranslationMatrix * _renderCamera.nonJitteredProjectionMatrix;
}
public void SetJitterOffset(Vector2 jitterOffset)
{
_dispatchDescription.JitterOffset = jitterOffset;
}
private void OnPostRender()
{
_renderCamera.rect = _tempRect;
_renderCamera.ResetProjectionMatrix();
// For legacy built-in render pipeline
private void OnRenderImage(RenderTexture src, RenderTexture dest)
{
_commandBuffer.Clear();
if (dest != null)
{
// We have more image effects lined up after this, so FSR2 can output straight to the intermediate render texture
// TODO: we should probably use a shader to include depth & motion vectors into the output
_commandBuffer.SetGlobalTexture(Fsr2Pipeline.UavUpscaledOutput, dest);
}
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);
}
_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);
// Output upscaled image to screen
// TODO: if `dest` is null, we likely don't care about the depth & motion vectors anymore
if (dest == null)
{
_commandBuffer.Blit(Fsr2Pipeline.UavUpscaledOutput, dest);
_commandBuffer.ReleaseTemporaryRT(Fsr2Pipeline.UavUpscaledOutput);
}
Graphics.ExecuteCommandBuffer(_commandBuffer);
// Shut up the Unity warning about not writing to the destination texture
Graphics.SetRenderTarget(dest);
}
}
}

127
Assets/Scripts/Fsr2Dispatcher.cs

@ -1,127 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using FidelityFX;
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering;
/// <summary>
/// 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.
/// </summary>
public class Fsr2Dispatcher : MonoBehaviour // TODO: rename this to Fsr2Dispatcher and move most of the functionality to Fsr2Controller (now SubsampleTest)
{
[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();
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" };
}
private void OnDisable()
{
if (_commandBuffer != null)
{
_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();
if (dest != null)
{
// We have more image effects lined up after this, so FSR2 can output straight to the intermediate render texture
// TODO: we should probably use a shader to include depth & motion vectors into the output
_commandBuffer.SetGlobalTexture(Fsr2Pipeline.UavUpscaledOutput, dest);
}
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);
}
_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);
// Output upscaled image to screen
// TODO: if `dest` is null, we likely don't care about the depth & motion vectors anymore
if (dest == null)
{
_commandBuffer.Blit(Fsr2Pipeline.UavUpscaledOutput, dest);
_commandBuffer.ReleaseTemporaryRT(Fsr2Pipeline.UavUpscaledOutput);
}
Graphics.ExecuteCommandBuffer(_commandBuffer);
// Shut up the Unity warning about not writing to the destination texture
Graphics.SetRenderTarget(dest);
}
}

11
Assets/Scripts/Fsr2Dispatcher.cs.meta

@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: d59d37e0744f1344e95cf689136fc9d9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
Loading…
Cancel
Save