diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2020-07-12 00:07:01 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-07-12 05:07:01 +0200 |
| commit | 4d02a2d2c0451b4de1f6de3bbce54c457cacebe2 (patch) | |
| tree | 120fe4fb8cfa1ac1c6ef4c97d92be47e955e8c0f /Ryujinx.Graphics.Nvdec.Vp9/Types/ScaleFactors.cs | |
| parent | 38b26cf4242999fa7d8c550993ac0940cd03d55f (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.cs | 451 |
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); + } + } +} |
