diff --git a/Runtime/FrameInterpolation/FrameInterpolation.cs b/Runtime/FrameInterpolation/FrameInterpolation.cs index 7839029..0b8bc23 100644 --- a/Runtime/FrameInterpolation/FrameInterpolation.cs +++ b/Runtime/FrameInterpolation/FrameInterpolation.cs @@ -1,5 +1,7 @@ using System; using System.Runtime.InteropServices; +using UnityEngine; +using UnityEngine.Experimental.Rendering; namespace FidelityFX.FrameGen { @@ -7,7 +9,11 @@ namespace FidelityFX.FrameGen { public struct ContextDescription { - + public InitializationFlags flags; + public Vector2Int maxRenderSize; + public Vector2Int displaySize; + public GraphicsFormat backBufferFormat; + public FrameInterpolationShaders shaders; } // TODO: turn all of these into structs @@ -38,7 +44,43 @@ namespace FidelityFX.FrameGen [Serializable, StructLayout(LayoutKind.Sequential)] internal struct Constants { - + public Vector2Int renderSize; + public Vector2Int displaySize; + + public Vector2 displaySizeRcp; + public float cameraNear; + public float cameraFar; + + public Vector2Int upscalerTargetSize; + public int mode; + public int reset; + + public Vector4 deviceToViewDepth; + + public float deltaTime; + public int HUDLessAttachedFactor; + public Vector2 unused; + + public Vector2 opticalFlowScale; + public int opticalFlowBlockSize; + public uint dispatchFlags; + + public Vector2Int maxRenderSize; + public int opticalFlowHalfResMode; + public int numInstances; + + public Vector2Int interpolationRectBase; + public Vector2Int interpolationRectSize; + + public Vector3 debugBarColor; + public uint backBufferTransferFunction; + + public Vector2 minMaxLuminance; + public float tanHalfFOV; + public float pad; + + public Vector2 jitter; + public Vector2 motionVectorScale; } [Serializable, StructLayout(LayoutKind.Sequential)] diff --git a/Runtime/FrameInterpolation/FrameInterpolationContext.cs b/Runtime/FrameInterpolation/FrameInterpolationContext.cs index 6c7d432..97e08ab 100644 --- a/Runtime/FrameInterpolation/FrameInterpolationContext.cs +++ b/Runtime/FrameInterpolation/FrameInterpolationContext.cs @@ -32,6 +32,11 @@ namespace FidelityFX.FrameGen private ref FrameInterpolation.InpaintingPyramidConstants SpdConstants => ref _spdConstantsArray[0]; private readonly CustomSampler _sampler = CustomSampler.Create("Frame Interpolation"); + + private bool _firstExecution; + private bool _asyncSupported; + private ulong _previousFrameID; + private ulong _dispatchCount; public void Create(in FrameInterpolation.ContextDescription contextDescription) { @@ -39,13 +44,24 @@ namespace FidelityFX.FrameGen _frameInterpolationConstantsBuffer = CreateConstantBuffer(); _spdConstantsBuffer = CreateConstantBuffer(); + + _firstExecution = true; + _asyncSupported = (_contextDescription.flags & FrameInterpolation.InitializationFlags.EnableAsyncSupport) == FrameInterpolation.InitializationFlags.EnableAsyncSupport; + + Constants.maxRenderSize = _contextDescription.maxRenderSize; + Constants.displaySize = _contextDescription.displaySize; + Constants.displaySizeRcp.x = 1.0f / _contextDescription.displaySize.x; + Constants.displaySizeRcp.y = 1.0f / _contextDescription.displaySize.y; + Constants.interpolationRectBase = Vector2Int.zero; + Constants.interpolationRectSize = _contextDescription.displaySize; + _resources.Create(_contextDescription); CreatePasses(); } private void CreatePasses() { - + // TODO } public void Destroy() diff --git a/Runtime/FrameInterpolation/FrameInterpolationResources.cs b/Runtime/FrameInterpolation/FrameInterpolationResources.cs index 0b2186f..443a374 100644 --- a/Runtime/FrameInterpolation/FrameInterpolationResources.cs +++ b/Runtime/FrameInterpolation/FrameInterpolationResources.cs @@ -1,10 +1,115 @@ -namespace FidelityFX.FrameGen +using System; +using System.Runtime.InteropServices; +using UnityEngine; +using UnityEngine.Experimental.Rendering; + +namespace FidelityFX.FrameGen { internal class FrameInterpolationResources { + public RenderTexture ReconstructedDepthInterpolatedFrame; + public RenderTexture GameMotionVectorFieldX; + public RenderTexture GameMotionVectorFieldY; + public RenderTexture InpaintingPyramid; + public ComputeBuffer Counters; + public RenderTexture OpticalFlowMotionVectorFieldX; + public RenderTexture OpticalFlowMotionVectorFieldY; + public RenderTexture PreviousInterpolationSource; + public RenderTexture DisocclusionMask; + + public readonly RenderTexture[] DilatedDepth = new RenderTexture[2]; + public readonly RenderTexture[] DilatedMotionVectors = new RenderTexture[2]; + public readonly RenderTexture[] ReconstructedDepth = new RenderTexture[2]; + + public void Create(in FrameInterpolation.ContextDescription contextDescription) + { + Vector2Int displaySize = contextDescription.displaySize; + Vector2Int displaySizeDiv2 = new Vector2Int(displaySize.x / 2, displaySize.y / 2); + Vector2Int maxRenderSize = contextDescription.maxRenderSize; + + ReconstructedDepthInterpolatedFrame = CreateResource("FI_ReconstructedDepthInterpolatedFrame", maxRenderSize, GraphicsFormat.R32_UInt); + GameMotionVectorFieldX = CreateResource("FI_GameMotionVectorFieldX", maxRenderSize, GraphicsFormat.R32_UInt); + GameMotionVectorFieldY = CreateResource("FI_GameMotionVectorFieldY", maxRenderSize, GraphicsFormat.R32_UInt); + InpaintingPyramid = CreateResourceMips("FI_InpaintingPyramid", displaySizeDiv2, GraphicsFormat.R16G16B16A16_SFloat); + Counters = CreateBuffer("FI_Counters", 2); // structured buffer containing 2 UINT values + OpticalFlowMotionVectorFieldX = CreateResource("FI_OpticalFlowMotionVectorFieldX", maxRenderSize, GraphicsFormat.R32_UInt); + OpticalFlowMotionVectorFieldY = CreateResource("FI_OpticalFlowMotionVectorFieldY", maxRenderSize, GraphicsFormat.R32_UInt); + PreviousInterpolationSource = CreateResource("FI_PreviousInterpolationSource", displaySize, contextDescription.backBufferFormat); + DisocclusionMask = CreateResource("FI_DisocclusionMask", maxRenderSize, GraphicsFormat.R8G8_UNorm); + + CreateDoubleBufferedResource(DilatedDepth, "FI_DilatedDepth_", maxRenderSize, GraphicsFormat.R32_SFloat); + CreateDoubleBufferedResource(DilatedMotionVectors, "FI_DilatedMVs_", maxRenderSize, GraphicsFormat.R16G16_SFloat); + CreateDoubleBufferedResource(ReconstructedDepth, "FI_ReconstructedDepth_", maxRenderSize, GraphicsFormat.R32_UInt); + } + public void Destroy() { + DestroyResource(ReconstructedDepth); + DestroyResource(DilatedMotionVectors); + DestroyResource(DilatedDepth); + DestroyResource(ref DisocclusionMask); + DestroyResource(ref PreviousInterpolationSource); + DestroyResource(ref OpticalFlowMotionVectorFieldY); + DestroyResource(ref OpticalFlowMotionVectorFieldX); + DestroyResource(ref Counters); + DestroyResource(ref InpaintingPyramid); + DestroyResource(ref GameMotionVectorFieldY); + DestroyResource(ref GameMotionVectorFieldX); + DestroyResource(ref ReconstructedDepthInterpolatedFrame); + } + + private static RenderTexture CreateResource(string name, Vector2Int size, GraphicsFormat format) + { + var rt = new RenderTexture(size.x, size.y, 0, format) { name = name, enableRandomWrite = true }; + rt.Create(); + return rt; + } + + private static RenderTexture CreateResourceMips(string name, Vector2Int size, GraphicsFormat format) + { + int mipCount = 1 + Mathf.FloorToInt(Mathf.Log(Math.Max(size.x, size.y), 2.0f)); + var rt = new RenderTexture(size.x, size.y, 0, format, mipCount) { name = name, enableRandomWrite = true, useMipMap = true, autoGenerateMips = false }; + rt.Create(); + return rt; + } + + private static ComputeBuffer CreateBuffer(string name, int count) + { + return new ComputeBuffer(count, Marshal.SizeOf()); + } + + private static void CreateDoubleBufferedResource(RenderTexture[] resource, string name, Vector2Int size, GraphicsFormat format) + { + for (int i = 0; i < 2; ++i) + { + resource[i] = new RenderTexture(size.x, size.y, 0, format) { name = name + (i + 1), enableRandomWrite = true }; + resource[i].Create(); + } + } + + private static void DestroyResource(ref RenderTexture resource) + { + if (resource == null) + return; + + resource.Release(); + resource = null; + } + + private static void DestroyResource(ref ComputeBuffer resource) + { + if (resource == null) + return; + + resource.Release(); + resource = null; + } + + private static void DestroyResource(RenderTexture[] resource) + { + for (int i = 0; i < resource.Length; ++i) + DestroyResource(ref resource[i]); } } }