aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Nvdec.Vp9/Types/ScaleFactors.cs
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2020-07-12 00:07:01 -0300
committerGitHub <noreply@github.com>2020-07-12 05:07:01 +0200
commit4d02a2d2c0451b4de1f6de3bbce54c457cacebe2 (patch)
tree120fe4fb8cfa1ac1c6ef4c97d92be47e955e8c0f /Ryujinx.Graphics.Nvdec.Vp9/Types/ScaleFactors.cs
parent38b26cf4242999fa7d8c550993ac0940cd03d55f (diff)
New NVDEC and VIC implementation (#1384)
* Initial NVDEC and VIC implementation * Update FFmpeg.AutoGen to 4.3.0 * Add nvdec dependencies for Windows * Unify some VP9 structures * Rename VP9 structure fields * Improvements to Video API * XML docs for Common.Memory * Remove now unused or redundant overloads from MemoryAccessor * NVDEC UV surface read/write scalar paths * Add FIXME comments about hacky things/stuff that will need to be fixed in the future * Cleaned up VP9 memory allocation * Remove some debug logs * Rename some VP9 structs * Remove unused struct * No need to compile Ryujinx.Graphics.Host1x with unsafe anymore * Name AsyncWorkQueue threads to make debugging easier * Make Vp9PictureInfo a ref struct * LayoutConverter no longer needs the depth argument (broken by rebase) * Pooling of VP9 buffers, plus fix a memory leak on VP9 * Really wish VS could rename projects properly... * Address feedback * Remove using * Catch OperationCanceledException * Add licensing informations * Add THIRDPARTY.md to release too Co-authored-by: Thog <me@thog.eu>
Diffstat (limited to 'Ryujinx.Graphics.Nvdec.Vp9/Types/ScaleFactors.cs')
-rw-r--r--Ryujinx.Graphics.Nvdec.Vp9/Types/ScaleFactors.cs451
1 files changed, 451 insertions, 0 deletions
diff --git a/Ryujinx.Graphics.Nvdec.Vp9/Types/ScaleFactors.cs b/Ryujinx.Graphics.Nvdec.Vp9/Types/ScaleFactors.cs
new file mode 100644
index 00000000..970f9680
--- /dev/null
+++ b/Ryujinx.Graphics.Nvdec.Vp9/Types/ScaleFactors.cs
@@ -0,0 +1,451 @@
+using Ryujinx.Common.Memory;
+using System.Runtime.CompilerServices;
+using static Ryujinx.Graphics.Nvdec.Vp9.Dsp.Convolve;
+using static Ryujinx.Graphics.Nvdec.Vp9.Dsp.Filter;
+
+namespace Ryujinx.Graphics.Nvdec.Vp9.Types
+{
+ internal struct ScaleFactors
+ {
+ private const int RefScaleShift = 14;
+ private const int RefNoScale = (1 << RefScaleShift);
+ private const int RefInvalidScale = -1;
+
+ private unsafe delegate void ConvolveFn(
+ byte* src,
+ int srcStride,
+ byte* dst,
+ int dstStride,
+ Array8<short>[] filter,
+ int x0Q4,
+ int xStepQ4,
+ int y0Q4,
+ int yStepQ4,
+ int w,
+ int h);
+
+ private unsafe delegate void HighbdConvolveFn(
+ ushort* src,
+ int srcStride,
+ ushort* dst,
+ int dstStride,
+ Array8<short>[] filter,
+ int x0Q4,
+ int xStepQ4,
+ int y0Q4,
+ int yStepQ4,
+ int w,
+ int h,
+ int bd);
+
+ private static readonly unsafe ConvolveFn[][][] PredictX16Y16 = new ConvolveFn[][][]
+ {
+ new ConvolveFn[][]
+ {
+ new ConvolveFn[]
+ {
+ ConvolveCopy,
+ ConvolveAvg
+ },
+ new ConvolveFn[]
+ {
+ Convolve8Vert,
+ Convolve8AvgVert
+ }
+ },
+ new ConvolveFn[][]
+ {
+ new ConvolveFn[]
+ {
+ Convolve8Horiz,
+ Convolve8AvgHoriz
+ },
+ new ConvolveFn[]
+ {
+ Convolve8,
+ Convolve8Avg
+ }
+ }
+ };
+
+ private static readonly unsafe ConvolveFn[][][] PredictX16 = new ConvolveFn[][][]
+ {
+ new ConvolveFn[][]
+ {
+ new ConvolveFn[]
+ {
+ ScaledVert,
+ ScaledAvgVert
+ },
+ new ConvolveFn[]
+ {
+ ScaledVert,
+ ScaledAvgVert
+ }
+ },
+ new ConvolveFn[][]
+ {
+ new ConvolveFn[]
+ {
+ Scaled2D,
+ ScaledAvg2D
+ },
+ new ConvolveFn[]
+ {
+ Scaled2D,
+ ScaledAvg2D
+ }
+ }
+ };
+
+ private static readonly unsafe ConvolveFn[][][] PredictY16 = new ConvolveFn[][][]
+ {
+ new ConvolveFn[][]
+ {
+ new ConvolveFn[]
+ {
+ ScaledHoriz,
+ ScaledAvgHoriz
+ },
+ new ConvolveFn[]
+ {
+ Scaled2D,
+ ScaledAvg2D
+ }
+ },
+ new ConvolveFn[][]
+ {
+ new ConvolveFn[]
+ {
+ ScaledHoriz,
+ ScaledAvgHoriz
+ },
+ new ConvolveFn[]
+ {
+ Scaled2D,
+ ScaledAvg2D
+ }
+ }
+ };
+
+ private static readonly unsafe ConvolveFn[][][] Predict = new ConvolveFn[][][]
+ {
+ new ConvolveFn[][]
+ {
+ new ConvolveFn[]
+ {
+ Scaled2D,
+ ScaledAvg2D
+ },
+ new ConvolveFn[]
+ {
+ Scaled2D,
+ ScaledAvg2D
+ }
+ },
+ new ConvolveFn[][]
+ {
+ new ConvolveFn[]
+ {
+ Scaled2D,
+ ScaledAvg2D
+ },
+ new ConvolveFn[]
+ {
+ Scaled2D,
+ ScaledAvg2D
+ }
+ }
+ };
+
+ private static readonly unsafe HighbdConvolveFn[][][] HighbdPredictX16Y16 = new HighbdConvolveFn[][][]
+ {
+ new HighbdConvolveFn[][]
+ {
+ new HighbdConvolveFn[]
+ {
+ HighbdConvolveCopy,
+ HighbdConvolveAvg
+ },
+ new HighbdConvolveFn[]
+ {
+ HighbdConvolve8Vert,
+ HighbdConvolve8AvgVert
+ }
+ },
+ new HighbdConvolveFn[][]
+ {
+ new HighbdConvolveFn[]
+ {
+ HighbdConvolve8Horiz,
+ HighbdConvolve8AvgHoriz
+ },
+ new HighbdConvolveFn[]
+ {
+ HighbdConvolve8,
+ HighbdConvolve8Avg
+ }
+ }
+ };
+
+ private static readonly unsafe HighbdConvolveFn[][][] HighbdPredictX16 = new HighbdConvolveFn[][][]
+ {
+ new HighbdConvolveFn[][]
+ {
+ new HighbdConvolveFn[]
+ {
+ HighbdConvolve8Vert,
+ HighbdConvolve8AvgVert
+ },
+ new HighbdConvolveFn[]
+ {
+ HighbdConvolve8Vert,
+ HighbdConvolve8AvgVert
+ }
+ },
+ new HighbdConvolveFn[][]
+ {
+ new HighbdConvolveFn[]
+ {
+ HighbdConvolve8,
+ HighbdConvolve8Avg
+ },
+ new HighbdConvolveFn[]
+ {
+ HighbdConvolve8,
+ HighbdConvolve8Avg
+ }
+ }
+ };
+
+ private static readonly unsafe HighbdConvolveFn[][][] HighbdPredictY16 = new HighbdConvolveFn[][][]
+ {
+ new HighbdConvolveFn[][]
+ {
+ new HighbdConvolveFn[]
+ {
+ HighbdConvolve8Horiz,
+ HighbdConvolve8AvgHoriz
+ },
+ new HighbdConvolveFn[]
+ {
+ HighbdConvolve8,
+ HighbdConvolve8Avg
+ }
+ },
+ new HighbdConvolveFn[][]
+ {
+ new HighbdConvolveFn[]
+ {
+ HighbdConvolve8Horiz,
+ HighbdConvolve8AvgHoriz
+ },
+ new HighbdConvolveFn[]
+ {
+ HighbdConvolve8,
+ HighbdConvolve8Avg
+ }
+ }
+ };
+
+ private static readonly unsafe HighbdConvolveFn[][][] HighbdPredict = new HighbdConvolveFn[][][]
+ {
+ new HighbdConvolveFn[][]
+ {
+ new HighbdConvolveFn[]
+ {
+ HighbdConvolve8,
+ HighbdConvolve8Avg
+ },
+ new HighbdConvolveFn[]
+ {
+ HighbdConvolve8,
+ HighbdConvolve8Avg
+ }
+ },
+ new HighbdConvolveFn[][]
+ {
+ new HighbdConvolveFn[]
+ {
+ HighbdConvolve8,
+ HighbdConvolve8Avg
+ },
+ new HighbdConvolveFn[]
+ {
+ HighbdConvolve8,
+ HighbdConvolve8Avg
+ }
+ }
+ };
+
+ public int XScaleFP; // Horizontal fixed point scale factor
+ public int YScaleFP; // Vertical fixed point scale factor
+ public int XStepQ4;
+ public int YStepQ4;
+
+ public int ScaleValueX(int val)
+ {
+ return IsScaled() ? ScaledX(val) : val;
+ }
+
+ public int ScaleValueY(int val)
+ {
+ return IsScaled() ? ScaledY(val) : val;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public unsafe void InterPredict(
+ int horiz,
+ int vert,
+ int avg,
+ byte* src,
+ int srcStride,
+ byte* dst,
+ int dstStride,
+ int subpelX,
+ int subpelY,
+ int w,
+ int h,
+ Array8<short>[] kernel,
+ int xs,
+ int ys)
+ {
+ if (XStepQ4 == 16)
+ {
+ if (YStepQ4 == 16)
+ {
+ // No scaling in either direction.
+ PredictX16Y16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h);
+ }
+ else
+ {
+ // No scaling in x direction. Must always scale in the y direction.
+ PredictX16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h);
+ }
+ }
+ else
+ {
+ if (YStepQ4 == 16)
+ {
+ // No scaling in the y direction. Must always scale in the x direction.
+ PredictY16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h);
+ }
+ else
+ {
+ // Must always scale in both directions.
+ Predict[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h);
+ }
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public unsafe void HighbdInterPredict(
+ int horiz,
+ int vert,
+ int avg,
+ ushort* src,
+ int srcStride,
+ ushort* dst,
+ int dstStride,
+ int subpelX,
+ int subpelY,
+ int w,
+ int h,
+ Array8<short>[] kernel,
+ int xs,
+ int ys,
+ int bd)
+ {
+ if (XStepQ4 == 16)
+ {
+ if (YStepQ4 == 16)
+ {
+ // No scaling in either direction.
+ HighbdPredictX16Y16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd);
+ }
+ else
+ {
+ // No scaling in x direction. Must always scale in the y direction.
+ HighbdPredictX16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd);
+ }
+ }
+ else
+ {
+ if (YStepQ4 == 16)
+ {
+ // No scaling in the y direction. Must always scale in the x direction.
+ HighbdPredictY16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd);
+ }
+ else
+ {
+ // Must always scale in both directions.
+ HighbdPredict[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd);
+ }
+ }
+ }
+
+ private int ScaledX(int val)
+ {
+ return (int)((long)val * XScaleFP >> RefScaleShift);
+ }
+
+ private int ScaledY(int val)
+ {
+ return (int)((long)val * YScaleFP >> RefScaleShift);
+ }
+
+ private static int GetFixedPointScaleFactor(int otherSize, int thisSize)
+ {
+ // Calculate scaling factor once for each reference frame
+ // and use fixed point scaling factors in decoding and encoding routines.
+ // Hardware implementations can calculate scale factor in device driver
+ // and use multiplication and shifting on hardware instead of division.
+ return (otherSize << RefScaleShift) / thisSize;
+ }
+
+ public Mv32 ScaleMv(ref Mv mv, int x, int y)
+ {
+ int xOffQ4 = ScaledX(x << SubpelBits) & SubpelMask;
+ int yOffQ4 = ScaledY(y << SubpelBits) & SubpelMask;
+ Mv32 res = new Mv32()
+ {
+ Row = ScaledY(mv.Row) + yOffQ4,
+ Col = ScaledX(mv.Col) + xOffQ4
+ };
+ return res;
+ }
+
+ public bool IsValidScale()
+ {
+ return XScaleFP != RefInvalidScale && YScaleFP != RefInvalidScale;
+ }
+
+ public bool IsScaled()
+ {
+ return IsValidScale() && (XScaleFP != RefNoScale || YScaleFP != RefNoScale);
+ }
+
+ public static bool ValidRefFrameSize(int refWidth, int refHeight, int thisWidth, int thisHeight)
+ {
+ return 2 * thisWidth >= refWidth &&
+ 2 * thisHeight >= refHeight &&
+ thisWidth <= 16 * refWidth &&
+ thisHeight <= 16 * refHeight;
+ }
+
+ public void SetupScaleFactorsForFrame(int otherW, int otherH, int thisW, int thisH)
+ {
+ if (!ValidRefFrameSize(otherW, otherH, thisW, thisH))
+ {
+ XScaleFP = RefInvalidScale;
+ YScaleFP = RefInvalidScale;
+ return;
+ }
+
+ XScaleFP = GetFixedPointScaleFactor(otherW, thisW);
+ YScaleFP = GetFixedPointScaleFactor(otherH, thisH);
+ XStepQ4 = ScaledX(16);
+ YStepQ4 = ScaledY(16);
+ }
+ }
+}