mirror of
https://github.com/Ryujinx/Ryujinx.git
synced 2024-08-20 07:38:42 +02:00
* 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>
452 lines
13 KiB
C#
452 lines
13 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|