diff --git a/Runtime/OpticalFlow/OpticalFlow.cs b/Runtime/OpticalFlow/OpticalFlow.cs index c3fa045..03cd009 100644 --- a/Runtime/OpticalFlow/OpticalFlow.cs +++ b/Runtime/OpticalFlow/OpticalFlow.cs @@ -6,6 +6,11 @@ namespace FidelityFX.OpticalFlow { public static class OpticalFlow { + internal const int OpticalFlowMaxPyramidLevels = 7; + internal const int HistogramBins = 256; + internal const int HistogramsPerDim = 3; + internal const int HistogramShifts = 3; + public static OpticalFlowContext CreateContext(in ContextDescription contextDescription) { throw new NotImplementedException(); @@ -27,6 +32,38 @@ namespace FidelityFX.OpticalFlow public Vector2 minMaxLuminance; } + internal static Vector2Int GetOpticalFlowTextureSize(Vector2Int displaySize, int opticalFlowBlockSize) + { + int width = (displaySize.x + opticalFlowBlockSize - 1) / opticalFlowBlockSize; + int height = (displaySize.y + opticalFlowBlockSize - 1) / opticalFlowBlockSize; + return new Vector2Int(width, height); + } + + internal static Vector2Int GetOpticalFlowHistogramSize(int level) + { + const int searchRadius = 8; + int maxVelocity = searchRadius * (1 << (OpticalFlowMaxPyramidLevels - 1 - level)); + int binsPerDimension = 2 * maxVelocity + 1; + return new Vector2Int(binsPerDimension, binsPerDimension); + } + + internal static Vector2Int GetGlobalMotionSearchDispatchSize(int level) + { + const int threadGroupSizeX = 16; + const int threadGroupSizeY = 16; + Vector2Int opticalFlowHistogramSize = GetOpticalFlowHistogramSize(level); + int additionalElementsDueToShiftsX = opticalFlowHistogramSize.x / threadGroupSizeX; + int additionalElementsDueToShiftsY = opticalFlowHistogramSize.y / threadGroupSizeY; + int dispatchX = (opticalFlowHistogramSize.x + additionalElementsDueToShiftsX + threadGroupSizeX - 1) / threadGroupSizeX; + int dispatchY = (opticalFlowHistogramSize.y + additionalElementsDueToShiftsY + threadGroupSizeY - 1) / threadGroupSizeY; + return new Vector2Int(dispatchX, dispatchY); + } + + internal static int GetSCDHistogramTextureWidth() + { + return HistogramBins * (HistogramsPerDim * HistogramsPerDim); + } + [Serializable, StructLayout(LayoutKind.Sequential)] internal struct OpticalFlowConstants { diff --git a/Runtime/OpticalFlow/OpticalFlowContext.cs b/Runtime/OpticalFlow/OpticalFlowContext.cs index b556ca2..5ca8a1f 100644 --- a/Runtime/OpticalFlow/OpticalFlowContext.cs +++ b/Runtime/OpticalFlow/OpticalFlowContext.cs @@ -32,7 +32,7 @@ namespace FidelityFX.OpticalFlow private bool _firstExecution; private int _resourceFrameIndex; - private readonly Vector2Int[] _opticalFlowTextureSizes = new Vector2Int[OpticalFlowResources.OpticalFlowMaxPyramidLevels]; + private readonly Vector2Int[] _opticalFlowTextureSizes = new Vector2Int[OpticalFlow.OpticalFlowMaxPyramidLevels]; public void Create(OpticalFlow.ContextDescription contextDescription) { @@ -143,23 +143,23 @@ namespace FidelityFX.OpticalFlow { const int threadGroupSizeX = 32; const int threadGroupSizeY = 8; - int strataWidth = (_contextDescription.resolution.x / 4) / OpticalFlowResources.HistogramsPerDim; - int strataHeight = _contextDescription.resolution.y / OpticalFlowResources.HistogramsPerDim; + int strataWidth = (_contextDescription.resolution.x / 4) / OpticalFlow.HistogramsPerDim; + int strataHeight = _contextDescription.resolution.y / OpticalFlow.HistogramsPerDim; int dispatchX = (strataWidth + threadGroupSizeX - 1) / threadGroupSizeX; const int dispatchY = 16; - const int dispatchZ = OpticalFlowResources.HistogramsPerDim * OpticalFlowResources.HistogramsPerDim; + const int dispatchZ = OpticalFlow.HistogramsPerDim * OpticalFlow.HistogramsPerDim; _generateScdHistogramPass.ScheduleDispatch(commandBuffer, dispatchDescription, frameIndex, dispatchX, dispatchY, dispatchZ); } { - const int dispatchX = OpticalFlowResources.HistogramsPerDim * OpticalFlowResources.HistogramsPerDim; - const int dispatchY = OpticalFlowResources.HistogramShifts; + const int dispatchX = OpticalFlow.HistogramsPerDim * OpticalFlow.HistogramsPerDim; + const int dispatchY = OpticalFlow.HistogramShifts; _computeScdDivergencePass.ScheduleDispatch(commandBuffer, dispatchDescription, frameIndex, dispatchX, dispatchY); } const int pyramidMaxIterations = advancedAlgorithmIterations; - Assert.IsTrue(pyramidMaxIterations <= OpticalFlowResources.OpticalFlowMaxPyramidLevels); + Assert.IsTrue(pyramidMaxIterations <= OpticalFlow.OpticalFlowMaxPyramidLevels); - _opticalFlowTextureSizes[0] = OpticalFlowResources.GetOpticalFlowTextureSize(_contextDescription.resolution, opticalFlowBlockSize); + _opticalFlowTextureSizes[0] = OpticalFlow.GetOpticalFlowTextureSize(_contextDescription.resolution, opticalFlowBlockSize); for (int i = 1; i < pyramidMaxIterations; ++i) { _opticalFlowTextureSizes[i] = new Vector2Int( diff --git a/Runtime/OpticalFlow/OpticalFlowResources.cs b/Runtime/OpticalFlow/OpticalFlowResources.cs index 7856543..42c1ebc 100644 --- a/Runtime/OpticalFlow/OpticalFlowResources.cs +++ b/Runtime/OpticalFlow/OpticalFlowResources.cs @@ -5,11 +5,6 @@ namespace FidelityFX.OpticalFlow { internal class OpticalFlowResources { - internal const int OpticalFlowMaxPyramidLevels = 7; - internal const int HistogramBins = 256; - internal const int HistogramsPerDim = 3; - internal const int HistogramShifts = 3; - public readonly RenderTexture[] OpticalFlowInput = new RenderTexture[2]; public readonly RenderTexture[] OpticalFlowInputLevel1 = new RenderTexture[2]; public readonly RenderTexture[] OpticalFlowInputLevel2 = new RenderTexture[2]; @@ -18,7 +13,7 @@ namespace FidelityFX.OpticalFlow public readonly RenderTexture[] OpticalFlowInputLevel5 = new RenderTexture[2]; public readonly RenderTexture[] OpticalFlowInputLevel6 = new RenderTexture[2]; - public readonly RenderTexture[] OpticalFlow = new RenderTexture[2]; + public readonly RenderTexture[] OpticalFlowLevel0 = new RenderTexture[2]; public readonly RenderTexture[] OpticalFlowLevel1 = new RenderTexture[2]; public readonly RenderTexture[] OpticalFlowLevel2 = new RenderTexture[2]; public readonly RenderTexture[] OpticalFlowLevel3 = new RenderTexture[2]; @@ -35,7 +30,7 @@ namespace FidelityFX.OpticalFlow Vector2Int opticalFlowInputTextureSize = contextDescription.resolution; const int minBlockSize = 8; - Vector2Int opticalFlowTextureSize = GetOpticalFlowTextureSize(contextDescription.resolution, minBlockSize); + Vector2Int opticalFlowTextureSize = OpticalFlow.GetOpticalFlowTextureSize(contextDescription.resolution, minBlockSize); Vector2Int opticalFlowLevel1TextureSize = NextLevelSize(opticalFlowTextureSize); Vector2Int opticalFlowLevel2TextureSize = NextLevelSize(opticalFlowLevel1TextureSize); Vector2Int opticalFlowLevel3TextureSize = NextLevelSize(opticalFlowLevel2TextureSize); @@ -43,8 +38,8 @@ namespace FidelityFX.OpticalFlow Vector2Int opticalFlowLevel5TextureSize = NextLevelSize(opticalFlowLevel4TextureSize); Vector2Int opticalFlowLevel6TextureSize = NextLevelSize(opticalFlowLevel5TextureSize); - Vector2Int opticalFlowHistogramTextureSize = GetOpticalFlowHistogramSize(0); - Vector2Int globalMotionSearchMaxDispatchSize = GetGlobalMotionSearchDispatchSize(0); + Vector2Int opticalFlowHistogramTextureSize = OpticalFlow.GetOpticalFlowHistogramSize(0); + Vector2Int globalMotionSearchMaxDispatchSize = OpticalFlow.GetGlobalMotionSearchDispatchSize(0); int globalMotionSearchTextureWidth = 4 + (globalMotionSearchMaxDispatchSize.x * globalMotionSearchMaxDispatchSize.y); CreateDoubleBufferedResource(OpticalFlowInput, "OPTICALFLOW_OpticalFlowInput", opticalFlowInputTextureSize, GraphicsFormat.R8_UInt); @@ -61,7 +56,7 @@ namespace FidelityFX.OpticalFlow opticalFlowInputTextureSize = new Vector2Int(opticalFlowInputTextureSize.x >> 1, opticalFlowInputTextureSize.y >> 1); CreateDoubleBufferedResource(OpticalFlowInputLevel6, "OPTICALFLOW_OpticalFlowInputLevel6-", opticalFlowInputTextureSize, GraphicsFormat.R8_UInt); - CreateDoubleBufferedResource(OpticalFlow, "OPTICALFLOW_OpticalFlow", opticalFlowTextureSize, GraphicsFormat.R16G16_SInt); + CreateDoubleBufferedResource(OpticalFlowLevel0, "OPTICALFLOW_OpticalFlow", opticalFlowTextureSize, GraphicsFormat.R16G16_SInt); CreateDoubleBufferedResource(OpticalFlowLevel1, "OPTICALFLOW_OpticalFlowLevel1-", opticalFlowLevel1TextureSize, GraphicsFormat.R16G16_SInt); CreateDoubleBufferedResource(OpticalFlowLevel2, "OPTICALFLOW_OpticalFlowLevel2-", opticalFlowLevel2TextureSize, GraphicsFormat.R16G16_SInt); CreateDoubleBufferedResource(OpticalFlowLevel3, "OPTICALFLOW_OpticalFlowLevel3-", opticalFlowLevel3TextureSize, GraphicsFormat.R16G16_SInt); @@ -69,8 +64,8 @@ namespace FidelityFX.OpticalFlow CreateDoubleBufferedResource(OpticalFlowLevel5, "OPTICALFLOW_OpticalFlowLevel5-", opticalFlowLevel5TextureSize, GraphicsFormat.R16G16_SInt); CreateDoubleBufferedResource(OpticalFlowLevel6, "OPTICALFLOW_OpticalFlowLevel6-", opticalFlowLevel6TextureSize, GraphicsFormat.R16G16_SInt); - OpticalFlowSCDHistogram = CreateResource("OPTICALFLOW_OpticalFlowSCDHistogram", new Vector2Int(GetSCDHistogramTextureWidth(), 1), GraphicsFormat.R32_UInt); - OpticalFlowSCDPreviousHistogram = CreateResource("OPTICALFLOW_OpticalFlowSCDPreviousHistogram", new Vector2Int(GetSCDHistogramTextureWidth(), 1), GraphicsFormat.R32_SFloat); + OpticalFlowSCDHistogram = CreateResource("OPTICALFLOW_OpticalFlowSCDHistogram", new Vector2Int(OpticalFlow.GetSCDHistogramTextureWidth(), 1), GraphicsFormat.R32_UInt); + OpticalFlowSCDPreviousHistogram = CreateResource("OPTICALFLOW_OpticalFlowSCDPreviousHistogram", new Vector2Int(OpticalFlow.GetSCDHistogramTextureWidth(), 1), GraphicsFormat.R32_SFloat); OpticalFlowSCDTemp = CreateResource("OPTICALFLOW_OpticalFlowSCDTemp", new Vector2Int(3, 1), GraphicsFormat.R32_UInt); } @@ -86,7 +81,7 @@ namespace FidelityFX.OpticalFlow DestroyResource(OpticalFlowLevel3); DestroyResource(OpticalFlowLevel2); DestroyResource(OpticalFlowLevel1); - DestroyResource(OpticalFlow); + DestroyResource(OpticalFlowLevel0); DestroyResource(OpticalFlowInputLevel6); DestroyResource(OpticalFlowInputLevel5); @@ -107,39 +102,6 @@ namespace FidelityFX.OpticalFlow return (x + (y - 1)) & ~(y - 1); } - // TODO: move these to OpticalFlow class - internal static Vector2Int GetOpticalFlowTextureSize(Vector2Int displaySize, int opticalFlowBlockSize) - { - int width = (displaySize.x + opticalFlowBlockSize - 1) / opticalFlowBlockSize; - int height = (displaySize.y + opticalFlowBlockSize - 1) / opticalFlowBlockSize; - return new Vector2Int(width, height); - } - - private static Vector2Int GetOpticalFlowHistogramSize(int level) - { - const int searchRadius = 8; - int maxVelocity = searchRadius * (1 << (OpticalFlowMaxPyramidLevels - 1 - level)); - int binsPerDimension = 2 * maxVelocity + 1; - return new Vector2Int(binsPerDimension, binsPerDimension); - } - - private static Vector2Int GetGlobalMotionSearchDispatchSize(int level) - { - const int threadGroupSizeX = 16; - const int threadGroupSizeY = 16; - Vector2Int opticalFlowHistogramSize = GetOpticalFlowHistogramSize(level); - int additionalElementsDueToShiftsX = opticalFlowHistogramSize.x / threadGroupSizeX; - int additionalElementsDueToShiftsY = opticalFlowHistogramSize.y / threadGroupSizeY; - int dispatchX = (opticalFlowHistogramSize.x + additionalElementsDueToShiftsX + threadGroupSizeX - 1) / threadGroupSizeX; - int dispatchY = (opticalFlowHistogramSize.y + additionalElementsDueToShiftsY + threadGroupSizeY - 1) / threadGroupSizeY; - return new Vector2Int(dispatchX, dispatchY); - } - - private static int GetSCDHistogramTextureWidth() - { - return HistogramBins * (HistogramsPerDim * HistogramsPerDim); - } - private static RenderTexture CreateResource(string name, Vector2Int size, GraphicsFormat format) { var rt = new RenderTexture(size.x, size.y, 0, format) { name = name, enableRandomWrite = true }; @@ -155,22 +117,6 @@ namespace FidelityFX.OpticalFlow resource[i].Create(); } } - - private static void DestroyResource(ref Texture2D resource) - { - if (resource == null) - return; - -#if UNITY_EDITOR - if (Application.isPlaying && !UnityEditor.EditorApplication.isPaused) - UnityEngine.Object.Destroy(resource); - else - UnityEngine.Object.DestroyImmediate(resource); -#else - UnityEngine.Object.Destroy(resource); -#endif - resource = null; - } private static void DestroyResource(ref RenderTexture resource) {