mirror of
https://git.naxdy.org/Mirror/Ryujinx.git
synced 2024-11-15 01:25:25 +00:00
[Ryujinx.Graphics.Nvdec.Vp9] Address dotnet-format issues (#5371)
* dotnet format style --severity info Some changes were manually reverted. * dotnet format analyzers --serverity info Some changes have been minimally adapted. * Restore a few unused methods and variables * Silence dotnet format IDE0060 warnings * Address or silence dotnet format IDE1006 warnings * Address most dotnet format whitespace warnings * Apply dotnet format whitespace formatting A few of them have been manually reverted and the corresponding warning was silenced * Add comments to disabled warnings * Simplify properties and array initialization, Use const when possible, Remove trailing commas * Address IDE0251 warnings * Address a few disabled IDE0060 warnings * Silence IDE0060 in .editorconfig * Revert "Simplify properties and array initialization, Use const when possible, Remove trailing commas" This reverts commit 9462e4136c0a2100dc28b20cf9542e06790aa67e. * dotnet format whitespace after rebase * Fix empty lines before return Co-authored-by: Ac_K <Acoustik666@gmail.com> * Add trailing commas, remove redundant code and remove static modifier from Surface.HighBd * Fix naming rule violations * Fix naming rule violations * Fix empty line before return * Fix comment style Co-authored-by: Ac_K <Acoustik666@gmail.com> * Remove comment alignment * Address review feedback * Separate comments by 2 spaces and fix other formatting issues * Make HighBd an auto-property * Replace if-chain with if-else-chain * Fix new naming rule violations --------- Co-authored-by: Ac_K <Acoustik666@gmail.com>
This commit is contained in:
parent
9becbd7d72
commit
6aa8d71588
|
@ -51,6 +51,6 @@
|
||||||
/*!\brief An iterator reached the end of list.
|
/*!\brief An iterator reached the end of list.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
CodecListEnd
|
CodecListEnd,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common
|
||||||
{
|
{
|
||||||
10 => (ushort)Math.Clamp(val, 0, 1023),
|
10 => (ushort)Math.Clamp(val, 0, 1023),
|
||||||
12 => (ushort)Math.Clamp(val, 0, 4095),
|
12 => (ushort)Math.Clamp(val, 0, 4095),
|
||||||
_ => (ushort)Math.Clamp(val, 0, 255)
|
_ => (ushort)Math.Clamp(val, 0, 255),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,6 +46,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common
|
||||||
private static int GetMsb(uint n)
|
private static int GetMsb(uint n)
|
||||||
{
|
{
|
||||||
Debug.Assert(n != 0);
|
Debug.Assert(n != 0);
|
||||||
|
|
||||||
return 31 ^ BitOperations.LeadingZeroCount(n);
|
return 31 ^ BitOperations.LeadingZeroCount(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common
|
||||||
public bool InUse;
|
public bool InUse;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PoolItem[] _pool = new PoolItem[PoolEntries];
|
private readonly PoolItem[] _pool = new PoolItem[PoolEntries];
|
||||||
|
|
||||||
public ArrayPtr<T> Allocate<T>(int length) where T : unmanaged
|
public ArrayPtr<T> Allocate<T>(int length) where T : unmanaged
|
||||||
{
|
{
|
||||||
|
@ -91,4 +91,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,13 +14,13 @@
|
||||||
public const int MaxRefFrames = 4;
|
public const int MaxRefFrames = 4;
|
||||||
|
|
||||||
public const int MiSizeLog2 = 3;
|
public const int MiSizeLog2 = 3;
|
||||||
public const int MiBlockSizeLog2 = 6 - MiSizeLog2; // 64 = 2^6
|
public const int MiBlockSizeLog2 = 6 - MiSizeLog2; // 64 = 2^6
|
||||||
|
|
||||||
public const int MiSize = 1 << MiSizeLog2; // pixels per mi-unit
|
public const int MiSize = 1 << MiSizeLog2; // pixels per mi-unit
|
||||||
public const int MiBlockSize = 1 << MiBlockSizeLog2; // mi-units per max block
|
public const int MiBlockSize = 1 << MiBlockSizeLog2; // mi-units per max block
|
||||||
public const int MiMask = MiBlockSize - 1;
|
public const int MiMask = MiBlockSize - 1;
|
||||||
|
|
||||||
public const int PartitionPloffset = 4; // number of probability models per block size
|
public const int PartitionPloffset = 4; // number of probability models per block size
|
||||||
|
|
||||||
/* Segment Feature Masks */
|
/* Segment Feature Masks */
|
||||||
public const int MaxMvRefCandidates = 2;
|
public const int MaxMvRefCandidates = 2;
|
||||||
|
@ -48,9 +48,9 @@
|
||||||
public const int MvLow = -(1 << MvInUseBits);
|
public const int MvLow = -(1 << MvInUseBits);
|
||||||
|
|
||||||
// Coefficient token alphabet
|
// Coefficient token alphabet
|
||||||
public const int ZeroToken = 0; // 0 Extra Bits 0+0
|
public const int ZeroToken = 0; // 0 Extra Bits 0+0
|
||||||
public const int OneToken = 1; // 1 Extra Bits 0+1
|
public const int OneToken = 1; // 1 Extra Bits 0+1
|
||||||
public const int TwoToken = 2; // 2 Extra Bits 0+1
|
public const int TwoToken = 2; // 2 Extra Bits 0+1
|
||||||
|
|
||||||
public const int PivotNode = 2;
|
public const int PivotNode = 2;
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@ using System.Diagnostics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Mv = Ryujinx.Graphics.Nvdec.Vp9.Types.Mv;
|
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Nvdec.Vp9
|
namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
|
@ -48,7 +47,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
case TxSize.Tx32x32:
|
case TxSize.Tx32x32:
|
||||||
Idct.HighbdIdct32x32Add(dqcoeff.AsSpan(), dst16, stride, eob, xd.Bd);
|
Idct.HighbdIdct32x32Add(dqcoeff.AsSpan(), dst16, stride, eob, xd.Bd);
|
||||||
break;
|
break;
|
||||||
default: Debug.Assert(false, "Invalid transform size"); break;
|
default:
|
||||||
|
Debug.Assert(false, "Invalid transform size");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,11 +63,21 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
switch (txSize)
|
switch (txSize)
|
||||||
{
|
{
|
||||||
case TxSize.Tx4x4: Idct.Idct4x4Add(dqcoeff.AsSpan(), dst, stride, eob); break;
|
case TxSize.Tx4x4:
|
||||||
case TxSize.Tx8x8: Idct.Idct8x8Add(dqcoeff.AsSpan(), dst, stride, eob); break;
|
Idct.Idct4x4Add(dqcoeff.AsSpan(), dst, stride, eob);
|
||||||
case TxSize.Tx16x16: Idct.Idct16x16Add(dqcoeff.AsSpan(), dst, stride, eob); break;
|
break;
|
||||||
case TxSize.Tx32x32: Idct.Idct32x32Add(dqcoeff.AsSpan(), dst, stride, eob); break;
|
case TxSize.Tx8x8:
|
||||||
default: Debug.Assert(false, "Invalid transform size"); return;
|
Idct.Idct8x8Add(dqcoeff.AsSpan(), dst, stride, eob);
|
||||||
|
break;
|
||||||
|
case TxSize.Tx16x16:
|
||||||
|
Idct.Idct16x16Add(dqcoeff.AsSpan(), dst, stride, eob);
|
||||||
|
break;
|
||||||
|
case TxSize.Tx32x32:
|
||||||
|
Idct.Idct32x32Add(dqcoeff.AsSpan(), dst, stride, eob);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Debug.Assert(false, "Invalid transform size");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,15 +90,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
if (txSize <= TxSize.Tx16x16 && eob <= 10)
|
if (txSize <= TxSize.Tx16x16 && eob <= 10)
|
||||||
{
|
{
|
||||||
dqcoeff.AsSpan().Slice(0, 4 * (4 << (int)txSize)).Fill(0);
|
dqcoeff.AsSpan()[..(4 * (4 << (int)txSize))].Clear();
|
||||||
}
|
}
|
||||||
else if (txSize == TxSize.Tx32x32 && eob <= 34)
|
else if (txSize == TxSize.Tx32x32 && eob <= 34)
|
||||||
{
|
{
|
||||||
dqcoeff.AsSpan().Slice(0, 256).Fill(0);
|
dqcoeff.AsSpan()[..256].Clear();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dqcoeff.AsSpan().Slice(0, 16 << ((int)txSize << 1)).Fill(0);
|
dqcoeff.AsSpan()[..(16 << ((int)txSize << 1))].Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -127,7 +138,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
case TxSize.Tx32x32:
|
case TxSize.Tx32x32:
|
||||||
Idct.HighbdIdct32x32Add(dqcoeff.AsSpan(), dst16, stride, eob, xd.Bd);
|
Idct.HighbdIdct32x32Add(dqcoeff.AsSpan(), dst16, stride, eob, xd.Bd);
|
||||||
break;
|
break;
|
||||||
default: Debug.Assert(false, "Invalid transform size"); break;
|
default:
|
||||||
|
Debug.Assert(false, "Invalid transform size");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,11 +154,21 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
switch (txSize)
|
switch (txSize)
|
||||||
{
|
{
|
||||||
case TxSize.Tx4x4: Idct.Iht4x4Add(txType, dqcoeff.AsSpan(), dst, stride, eob); break;
|
case TxSize.Tx4x4:
|
||||||
case TxSize.Tx8x8: Idct.Iht8x8Add(txType, dqcoeff.AsSpan(), dst, stride, eob); break;
|
Idct.Iht4x4Add(txType, dqcoeff.AsSpan(), dst, stride, eob);
|
||||||
case TxSize.Tx16x16: Idct.Iht16x16Add(txType, dqcoeff.AsSpan(), dst, stride, eob); break;
|
break;
|
||||||
case TxSize.Tx32x32: Idct.Idct32x32Add(dqcoeff.AsSpan(), dst, stride, eob); break;
|
case TxSize.Tx8x8:
|
||||||
default: Debug.Assert(false, "Invalid transform size"); return;
|
Idct.Iht8x8Add(txType, dqcoeff.AsSpan(), dst, stride, eob);
|
||||||
|
break;
|
||||||
|
case TxSize.Tx16x16:
|
||||||
|
Idct.Iht16x16Add(txType, dqcoeff.AsSpan(), dst, stride, eob);
|
||||||
|
break;
|
||||||
|
case TxSize.Tx32x32:
|
||||||
|
Idct.Idct32x32Add(dqcoeff.AsSpan(), dst, stride, eob);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Debug.Assert(false, "Invalid transform size");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -158,15 +181,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
if (txType == TxType.DctDct && txSize <= TxSize.Tx16x16 && eob <= 10)
|
if (txType == TxType.DctDct && txSize <= TxSize.Tx16x16 && eob <= 10)
|
||||||
{
|
{
|
||||||
dqcoeff.AsSpan().Slice(0, 4 * (4 << (int)txSize)).Fill(0);
|
dqcoeff.AsSpan()[..(4 * (4 << (int)txSize))].Clear();
|
||||||
}
|
}
|
||||||
else if (txSize == TxSize.Tx32x32 && eob <= 34)
|
else if (txSize == TxSize.Tx32x32 && eob <= 34)
|
||||||
{
|
{
|
||||||
dqcoeff.AsSpan().Slice(0, 256).Fill(0);
|
dqcoeff.AsSpan()[..256].Clear();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dqcoeff.AsSpan().Slice(0, 16 << ((int)txSize << 1)).Fill(0);
|
dqcoeff.AsSpan()[..(16 << ((int)txSize << 1))].Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -184,7 +207,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
PredictionMode mode = (plane == 0) ? mi.Mode : mi.UvMode;
|
PredictionMode mode = (plane == 0) ? mi.Mode : mi.UvMode;
|
||||||
int dstOffset = 4 * row * pd.Dst.Stride + 4 * col;
|
int dstOffset = 4 * row * pd.Dst.Stride + 4 * col;
|
||||||
byte* dst = &pd.Dst.Buf.ToPointer()[dstOffset];
|
byte* dst = &pd.Dst.Buf.ToPointer()[dstOffset];
|
||||||
Span<byte> dstSpan = pd.Dst.Buf.AsSpan().Slice(dstOffset);
|
Span<byte> dstSpan = pd.Dst.Buf.AsSpan()[dstOffset..];
|
||||||
|
|
||||||
if (mi.SbType < BlockSize.Block8x8)
|
if (mi.SbType < BlockSize.Block8x8)
|
||||||
{
|
{
|
||||||
|
@ -223,7 +246,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
ref MacroBlockDPlane pd = ref xd.Plane[plane];
|
ref MacroBlockDPlane pd = ref xd.Plane[plane];
|
||||||
var sc = Luts.Vp9DefaultScanOrders[(int)txSize];
|
var sc = Luts.Vp9DefaultScanOrders[(int)txSize];
|
||||||
int eob = Detokenize.DecodeBlockTokens(ref twd, plane, sc, col, row, txSize, mi.SegmentId);
|
int eob = Detokenize.DecodeBlockTokens(ref twd, plane, sc, col, row, txSize, mi.SegmentId);
|
||||||
Span<byte> dst = pd.Dst.Buf.AsSpan().Slice(4 * row * pd.Dst.Stride + 4 * col);
|
Span<byte> dst = pd.Dst.Buf.AsSpan()[(4 * row * pd.Dst.Stride + 4 * col)..];
|
||||||
|
|
||||||
if (eob > 0)
|
if (eob > 0)
|
||||||
{
|
{
|
||||||
|
@ -589,9 +612,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
refr,
|
refr,
|
||||||
xs,
|
xs,
|
||||||
ys);
|
ys);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xd.CurBuf.HighBd)
|
if (xd.CurBuf.HighBd)
|
||||||
{
|
{
|
||||||
ReconInter.HighbdInterPredictor(
|
ReconInter.HighbdInterPredictor(
|
||||||
|
@ -793,6 +818,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
xd.SetMiRowCol(ref tile, miRow, bh, miCol, bw, cm.MiRows, cm.MiCols);
|
xd.SetMiRowCol(ref tile, miRow, bh, miCol, bw, cm.MiRows, cm.MiCols);
|
||||||
|
|
||||||
ReconInter.SetupDstPlanes(ref xd.Plane, ref xd.CurBuf, miRow, miCol);
|
ReconInter.SetupDstPlanes(ref xd.Plane, ref xd.CurBuf, miRow, miCol);
|
||||||
|
|
||||||
return ref xd.Mi[0].Value;
|
return ref xd.Mi[0].Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -893,7 +919,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
|
|
||||||
if (!less8x8 && eobtotal == 0)
|
if (!less8x8 && eobtotal == 0)
|
||||||
{
|
{
|
||||||
mi.Skip = 1; // Skip loopfilter
|
mi.Skip = 1; // Skip loopfilter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -928,8 +954,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
// Update the partition context at the end notes. Set partition bits
|
// Update the partition context at the end notes. Set partition bits
|
||||||
// of block sizes larger than the current one to be one, and partition
|
// of block sizes larger than the current one to be one, and partition
|
||||||
// bits of smaller block sizes to be zero.
|
// bits of smaller block sizes to be zero.
|
||||||
aboveCtx.Slice(0, bw).Fill(Luts.PartitionContextLookup[(int)subsize].Above);
|
aboveCtx[..bw].Fill(Luts.PartitionContextLookup[(int)subsize].Above);
|
||||||
leftCtx.Slice(0, bw).Fill(Luts.PartitionContextLookup[(int)subsize].Left);
|
leftCtx[..bw].Fill(Luts.PartitionContextLookup[(int)subsize].Left);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PartitionType ReadPartition(
|
private static PartitionType ReadPartition(
|
||||||
|
@ -1030,7 +1056,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
DecodePartition(ref twd, ref cm, miRow + hbs, miCol, subsize, n8x8L2);
|
DecodePartition(ref twd, ref cm, miRow + hbs, miCol, subsize, n8x8L2);
|
||||||
DecodePartition(ref twd, ref cm, miRow + hbs, miCol + hbs, subsize, n8x8L2);
|
DecodePartition(ref twd, ref cm, miRow + hbs, miCol + hbs, subsize, n8x8L2);
|
||||||
break;
|
break;
|
||||||
default: Debug.Assert(false, "Invalid partition type"); break;
|
default:
|
||||||
|
Debug.Assert(false, "Invalid partition type");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1134,7 +1162,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
int alignedCols = TileInfo.MiColsAlignedToSb(cm.MiCols);
|
int alignedCols = TileInfo.MiColsAlignedToSb(cm.MiCols);
|
||||||
int tileCols = 1 << cm.Log2TileCols;
|
int tileCols = 1 << cm.Log2TileCols;
|
||||||
int tileRows = 1 << cm.Log2TileRows;
|
int tileRows = 1 << cm.Log2TileRows;
|
||||||
Array4<Array64<TileBuffer>> tileBuffers = new Array4<Array64<TileBuffer>>();
|
Array4<Array64<TileBuffer>> tileBuffers = new();
|
||||||
int tileRow, tileCol;
|
int tileRow, tileCol;
|
||||||
int miRow, miCol;
|
int miRow, miCol;
|
||||||
|
|
||||||
|
@ -1168,7 +1196,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
|
|
||||||
for (tileRow = 0; tileRow < tileRows; ++tileRow)
|
for (tileRow = 0; tileRow < tileRows; ++tileRow)
|
||||||
{
|
{
|
||||||
TileInfo tile = new TileInfo();
|
TileInfo tile = new();
|
||||||
tile.SetRow(ref cm, tileRow);
|
tile.SetRow(ref cm, tileRow);
|
||||||
for (miRow = tile.MiRowStart; miRow < tile.MiRowEnd; miRow += Constants.MiBlockSize)
|
for (miRow = tile.MiRowStart; miRow < tile.MiRowEnd; miRow += Constants.MiBlockSize)
|
||||||
{
|
{
|
||||||
|
@ -1234,10 +1262,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
} while (!tileData.Xd.Corrupted && ++n <= tileData.BufEnd);
|
} while (!tileData.Xd.Corrupted && ++n <= tileData.BufEnd);
|
||||||
|
|
||||||
tileData.DataEnd = bitReaderEnd;
|
tileData.DataEnd = bitReaderEnd;
|
||||||
|
|
||||||
return !tileData.Xd.Corrupted;
|
return !tileData.Xd.Corrupted;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unsafe ArrayPtr<byte> DecodeTilesMt(ref Vp9Common cm, ArrayPtr<byte> data, int maxThreads)
|
public static ArrayPtr<byte> DecodeTilesMt(ref Vp9Common cm, ArrayPtr<byte> data, int maxThreads)
|
||||||
{
|
{
|
||||||
ArrayPtr<byte> bitReaderEnd = ArrayPtr<byte>.Null;
|
ArrayPtr<byte> bitReaderEnd = ArrayPtr<byte>.Null;
|
||||||
|
|
||||||
|
@ -1250,8 +1279,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
Debug.Assert(tileCols <= (1 << 6));
|
Debug.Assert(tileCols <= (1 << 6));
|
||||||
Debug.Assert(tileRows == 1);
|
Debug.Assert(tileRows == 1);
|
||||||
|
|
||||||
cm.AboveContext.AsSpan().Fill(0);
|
cm.AboveContext.AsSpan().Clear();
|
||||||
cm.AboveSegContext.AsSpan().Fill(0);
|
cm.AboveSegContext.AsSpan().Clear();
|
||||||
|
|
||||||
for (n = 0; n < numWorkers; ++n)
|
for (n = 0; n < numWorkers; ++n)
|
||||||
{
|
{
|
||||||
|
@ -1262,17 +1291,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
tileData.Counts = new Vp9BackwardUpdates();
|
tileData.Counts = new Vp9BackwardUpdates();
|
||||||
}
|
}
|
||||||
|
|
||||||
Array64<TileBuffer> tileBuffers = new Array64<TileBuffer>();
|
Array64<TileBuffer> tileBuffers = new();
|
||||||
|
|
||||||
GetTileBuffers(ref cm, data, tileCols, ref tileBuffers);
|
GetTileBuffers(ref cm, data, tileCols, ref tileBuffers);
|
||||||
|
|
||||||
tileBuffers.AsSpan().Slice(0, tileCols).Sort(CompareTileBuffers);
|
tileBuffers.AsSpan()[..tileCols].Sort(CompareTileBuffers);
|
||||||
|
|
||||||
if (numWorkers == tileCols)
|
if (numWorkers == tileCols)
|
||||||
{
|
{
|
||||||
TileBuffer largest = tileBuffers[0];
|
TileBuffer largest = tileBuffers[0];
|
||||||
Span<TileBuffer> buffers = tileBuffers.AsSpan();
|
Span<TileBuffer> buffers = tileBuffers.AsSpan();
|
||||||
buffers.Slice(1).CopyTo(buffers.Slice(0, tileBuffers.Length - 1));
|
buffers[1..].CopyTo(buffers[..(tileBuffers.Length - 1)]);
|
||||||
tileBuffers[tileCols - 1] = largest;
|
tileBuffers[tileCols - 1] = largest;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1307,9 +1336,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
bufStart += count;
|
bufStart += count;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr<Vp9Common> cmPtr = new Ptr<Vp9Common>(ref cm);
|
Ptr<Vp9Common> cmPtr = new(ref cm);
|
||||||
|
|
||||||
Parallel.For(0, numWorkers, (n) =>
|
Parallel.For(0, numWorkers, n =>
|
||||||
{
|
{
|
||||||
ref TileWorkerData tileData = ref cmPtr.Value.TileWorkerData[n + totalTiles];
|
ref TileWorkerData tileData = ref cmPtr.Value.TileWorkerData[n + totalTiles];
|
||||||
|
|
||||||
|
@ -1335,6 +1364,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Assert(!bitReaderEnd.IsNull || cm.Mb.Corrupted);
|
Debug.Assert(!bitReaderEnd.IsNull || cm.Mb.Corrupted);
|
||||||
|
|
||||||
return bitReaderEnd;
|
return bitReaderEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,6 @@ using Ryujinx.Graphics.Video;
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using Mv = Ryujinx.Graphics.Nvdec.Vp9.Types.Mv;
|
|
||||||
using MvRef = Ryujinx.Graphics.Nvdec.Vp9.Types.MvRef;
|
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Nvdec.Vp9
|
namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
|
@ -61,10 +59,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
switch (maxTxSize)
|
switch (maxTxSize)
|
||||||
{
|
{
|
||||||
case TxSize.Tx8x8: return fc.Tx8x8Prob[ctx].AsSpan();
|
case TxSize.Tx8x8:
|
||||||
case TxSize.Tx16x16: return fc.Tx16x16Prob[ctx].AsSpan();
|
return fc.Tx8x8Prob[ctx].AsSpan();
|
||||||
case TxSize.Tx32x32: return fc.Tx32x32Prob[ctx].AsSpan();
|
case TxSize.Tx16x16:
|
||||||
default: Debug.Assert(false, "Invalid maxTxSize."); return ReadOnlySpan<byte>.Empty;
|
return fc.Tx16x16Prob[ctx].AsSpan();
|
||||||
|
case TxSize.Tx32x32:
|
||||||
|
return fc.Tx32x32Prob[ctx].AsSpan();
|
||||||
|
default:
|
||||||
|
Debug.Assert(false, "Invalid maxTxSize.");
|
||||||
|
|
||||||
|
return ReadOnlySpan<byte>.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,10 +76,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
switch (maxTxSize)
|
switch (maxTxSize)
|
||||||
{
|
{
|
||||||
case TxSize.Tx8x8: return counts.Tx8x8[ctx].AsSpan();
|
case TxSize.Tx8x8:
|
||||||
case TxSize.Tx16x16: return counts.Tx16x16[ctx].AsSpan();
|
return counts.Tx8x8[ctx].AsSpan();
|
||||||
case TxSize.Tx32x32: return counts.Tx32x32[ctx].AsSpan();
|
case TxSize.Tx16x16:
|
||||||
default: Debug.Assert(false, "Invalid maxTxSize."); return Span<uint>.Empty;
|
return counts.Tx16x16[ctx].AsSpan();
|
||||||
|
case TxSize.Tx32x32:
|
||||||
|
return counts.Tx32x32[ctx].AsSpan();
|
||||||
|
default:
|
||||||
|
Debug.Assert(false, "Invalid maxTxSize.");
|
||||||
|
|
||||||
|
return Span<uint>.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,10 +120,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
return ReadSelectedTxSize(ref cm, ref xd, maxTxSize, ref r);
|
return ReadSelectedTxSize(ref cm, ref xd, maxTxSize, ref r);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
return (TxSize)Math.Min((int)maxTxSize, (int)Luts.TxModeToBiggestTxSize[(int)txMode]);
|
||||||
return (TxSize)Math.Min((int)maxTxSize, (int)Luts.TxModeToBiggestTxSize[(int)txMode]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int DecGetSegmentId(ref Vp9Common cm, ArrayPtr<byte> segmentIds, int miOffset, int xMis, int yMis)
|
private static int DecGetSegmentId(ref Vp9Common cm, ArrayPtr<byte> segmentIds, int miOffset, int xMis, int yMis)
|
||||||
|
@ -129,6 +137,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Assert(segmentId >= 0 && segmentId < Constants.MaxSegments);
|
Debug.Assert(segmentId >= 0 && segmentId < Constants.MaxSegments);
|
||||||
|
|
||||||
return segmentId;
|
return segmentId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,17 +182,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
|
|
||||||
if (!seg.Enabled)
|
if (!seg.Enabled)
|
||||||
{
|
{
|
||||||
return 0; // Default for disabled segmentation
|
return 0; // Default for disabled segmentation
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!seg.UpdateMap)
|
if (!seg.UpdateMap)
|
||||||
{
|
{
|
||||||
CopySegmentId(ref cm, cm.LastFrameSegMap, cm.CurrentFrameSegMap, miOffset, xMis, yMis);
|
CopySegmentId(ref cm, cm.LastFrameSegMap, cm.CurrentFrameSegMap, miOffset, xMis, yMis);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
segmentId = ReadSegmentId(ref r, ref cm.Fc.Value.SegTreeProb);
|
segmentId = ReadSegmentId(ref r, ref cm.Fc.Value.SegTreeProb);
|
||||||
SetSegmentId(ref cm, miOffset, xMis, yMis, segmentId);
|
SetSegmentId(ref cm, miOffset, xMis, yMis, segmentId);
|
||||||
|
|
||||||
return segmentId;
|
return segmentId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,7 +214,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
|
|
||||||
if (!seg.Enabled)
|
if (!seg.Enabled)
|
||||||
{
|
{
|
||||||
return 0; // Default for disabled segmentation
|
return 0; // Default for disabled segmentation
|
||||||
}
|
}
|
||||||
|
|
||||||
predictedSegmentId = !cm.LastFrameSegMap.IsNull
|
predictedSegmentId = !cm.LastFrameSegMap.IsNull
|
||||||
|
@ -213,6 +224,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
if (!seg.UpdateMap)
|
if (!seg.UpdateMap)
|
||||||
{
|
{
|
||||||
CopySegmentId(ref cm, cm.LastFrameSegMap, cm.CurrentFrameSegMap, miOffset, xMis, yMis);
|
CopySegmentId(ref cm, cm.LastFrameSegMap, cm.CurrentFrameSegMap, miOffset, xMis, yMis);
|
||||||
|
|
||||||
return predictedSegmentId;
|
return predictedSegmentId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,6 +239,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
segmentId = ReadSegmentId(ref r, ref cm.Fc.Value.SegTreeProb);
|
segmentId = ReadSegmentId(ref r, ref cm.Fc.Value.SegTreeProb);
|
||||||
}
|
}
|
||||||
SetSegmentId(ref cm, miOffset, xMis, yMis, segmentId);
|
SetSegmentId(ref cm, miOffset, xMis, yMis, segmentId);
|
||||||
|
|
||||||
return segmentId;
|
return segmentId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,17 +249,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
int ctx = xd.GetSkipContext();
|
|
||||||
int skip = r.Read(cm.Fc.Value.SkipProb[ctx]);
|
|
||||||
if (!xd.Counts.IsNull)
|
|
||||||
{
|
|
||||||
++xd.Counts.Value.Skip[ctx][skip];
|
|
||||||
}
|
|
||||||
|
|
||||||
return skip;
|
int ctx = xd.GetSkipContext();
|
||||||
|
int skip = r.Read(cm.Fc.Value.SkipProb[ctx]);
|
||||||
|
if (!xd.Counts.IsNull)
|
||||||
|
{
|
||||||
|
++xd.Counts.Value.Skip[ctx][skip];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return skip;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int ReadMvComponent(ref Reader r, ref Vp9EntropyProbs fc, int mvcomp, bool usehp)
|
private static int ReadMvComponent(ref Reader r, ref Vp9EntropyProbs fc, int mvcomp, bool usehp)
|
||||||
|
@ -265,7 +276,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int n = (int)mvClass + Constants.Class0Bits - 1; // Number of bits
|
int n = (int)mvClass + Constants.Class0Bits - 1; // Number of bits
|
||||||
|
|
||||||
d = 0;
|
d = 0;
|
||||||
for (i = 0; i < n; ++i)
|
for (i = 0; i < n; ++i)
|
||||||
|
@ -284,6 +295,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
|
|
||||||
// Result
|
// Result
|
||||||
mag += ((d << 3) | (fr << 1) | hp) + 1;
|
mag += ((d << 3) | (fr << 1) | hp) + 1;
|
||||||
|
|
||||||
return sign ? -mag : mag;
|
return sign ? -mag : mag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,7 +309,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
MvJointType jointType = (MvJointType)r.ReadTree(Luts.Vp9MvJointTree, fc.Joints.AsSpan());
|
MvJointType jointType = (MvJointType)r.ReadTree(Luts.Vp9MvJointTree, fc.Joints.AsSpan());
|
||||||
bool useHP = allowHP && refr.UseMvHp();
|
bool useHP = allowHP && refr.UseMvHp();
|
||||||
Mv diff = new Mv();
|
Mv diff = new();
|
||||||
|
|
||||||
if (Mv.MvJointVertical(jointType))
|
if (Mv.MvJointVertical(jointType))
|
||||||
{
|
{
|
||||||
|
@ -326,12 +338,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
++xd.Counts.Value.CompInter[ctx][(int)mode];
|
++xd.Counts.Value.CompInter[ctx][(int)mode];
|
||||||
}
|
}
|
||||||
|
|
||||||
return mode; // SingleReference or CompoundReference
|
return mode; // SingleReference or CompoundReference
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return cm.ReferenceMode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return cm.ReferenceMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the referncence frame
|
// Read the referncence frame
|
||||||
|
@ -434,7 +444,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
mi.Bmi[0].Mode = mi.Bmi[1].Mode = ReadIntraModeY(ref cm, ref xd, ref r, 0);
|
mi.Bmi[0].Mode = mi.Bmi[1].Mode = ReadIntraModeY(ref cm, ref xd, ref r, 0);
|
||||||
mi.Bmi[2].Mode = mi.Bmi[3].Mode = mi.Mode = ReadIntraModeY(ref cm, ref xd, ref r, 0);
|
mi.Bmi[2].Mode = mi.Bmi[3].Mode = mi.Mode = ReadIntraModeY(ref cm, ref xd, ref r, 0);
|
||||||
break;
|
break;
|
||||||
default: mi.Mode = ReadIntraModeY(ref cm, ref xd, ref r, Luts.SizeGroupLookup[(int)bsize]); break;
|
default:
|
||||||
|
mi.Mode = ReadIntraModeY(ref cm, ref xd, ref r, Luts.SizeGroupLookup[(int)bsize]);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
mi.UvMode = ReadIntraModeUv(ref cm, ref xd, ref r, (byte)mi.Mode);
|
mi.UvMode = ReadIntraModeUv(ref cm, ref xd, ref r, (byte)mi.Mode);
|
||||||
|
@ -503,7 +515,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
ZeroMvPair(ref mv);
|
ZeroMvPair(ref mv);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: return false;
|
default:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -514,17 +527,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
return cm.Seg.GetSegData(segmentId, SegLvlFeatures.SegLvlRefFrame) != Constants.IntraFrame;
|
return cm.Seg.GetSegData(segmentId, SegLvlFeatures.SegLvlRefFrame) != Constants.IntraFrame;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
int ctx = xd.GetIntraInterContext();
|
|
||||||
bool isInter = r.Read(cm.Fc.Value.IntraInterProb[ctx]) != 0;
|
|
||||||
if (!xd.Counts.IsNull)
|
|
||||||
{
|
|
||||||
++xd.Counts.Value.IntraInter[ctx][isInter ? 1 : 0];
|
|
||||||
}
|
|
||||||
|
|
||||||
return isInter;
|
int ctx = xd.GetIntraInterContext();
|
||||||
|
bool isInter = r.Read(cm.Fc.Value.IntraInterProb[ctx]) != 0;
|
||||||
|
if (!xd.Counts.IsNull)
|
||||||
|
{
|
||||||
|
++xd.Counts.Value.IntraInter[ctx][isInter ? 1 : 0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return isInter;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void DecFindBestRefMvs(bool allowHP, Span<Mv> mvlist, ref Mv bestMv, int refmvCount)
|
private static void DecFindBestRefMvs(bool allowHP, Span<Mv> mvlist, ref Mv bestMv, int refmvCount)
|
||||||
|
@ -547,6 +558,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
mvRefList[refMvCount] = mv;
|
mvRefList[refMvCount] = mv;
|
||||||
refMvCount++;
|
refMvCount++;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -605,7 +617,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
|
|
||||||
// This function searches the neighborhood of a given MB/SB
|
// This function searches the neighborhood of a given MB/SB
|
||||||
// to try and find candidate reference vectors.
|
// to try and find candidate reference vectors.
|
||||||
private static unsafe int DecFindMvRefs(
|
private static int DecFindMvRefs(
|
||||||
ref Vp9Common cm,
|
ref Vp9Common cm,
|
||||||
ref MacroBlockD xd,
|
ref MacroBlockD xd,
|
||||||
PredictionMode mode,
|
PredictionMode mode,
|
||||||
|
@ -627,7 +639,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
bool earlyBreak = mode != PredictionMode.NearMv;
|
bool earlyBreak = mode != PredictionMode.NearMv;
|
||||||
|
|
||||||
// Blank the reference vector list
|
// Blank the reference vector list
|
||||||
mvRefList.Slice(0, Constants.MaxMvRefCandidates).Fill(new Mv());
|
mvRefList[..Constants.MaxMvRefCandidates].Clear();
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
if (isSub8X8 != 0)
|
if (isSub8X8 != 0)
|
||||||
|
@ -805,7 +817,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
|
|
||||||
switch (block)
|
switch (block)
|
||||||
{
|
{
|
||||||
case 0: bestSub8x8 = mvList[refmvCount - 1]; break;
|
case 0:
|
||||||
|
bestSub8x8 = mvList[refmvCount - 1];
|
||||||
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
case 2:
|
case 2:
|
||||||
if (bMode == PredictionMode.NearestMv)
|
if (bMode == PredictionMode.NearestMv)
|
||||||
|
@ -848,7 +862,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default: Debug.Assert(false, "Invalid block index."); break;
|
default:
|
||||||
|
Debug.Assert(false, "Invalid block index.");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -883,7 +899,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
BlockSize bsize = mi.SbType;
|
BlockSize bsize = mi.SbType;
|
||||||
bool allowHP = cm.AllowHighPrecisionMv;
|
bool allowHP = cm.AllowHighPrecisionMv;
|
||||||
Array2<Mv> bestRefMvs = new Array2<Mv>();
|
Array2<Mv> bestRefMvs = new();
|
||||||
int refr, isCompound;
|
int refr, isCompound;
|
||||||
byte interModeCtx;
|
byte interModeCtx;
|
||||||
Span<Position> mvRefSearch = Luts.MvRefBlocks[(int)bsize];
|
Span<Position> mvRefSearch = Luts.MvRefBlocks[(int)bsize];
|
||||||
|
@ -898,6 +914,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
if (bsize < BlockSize.Block8x8)
|
if (bsize < BlockSize.Block8x8)
|
||||||
{
|
{
|
||||||
xd.ErrorInfo.Value.InternalError(CodecErr.CodecUnsupBitstream, "Invalid usage of segement feature on small blocks");
|
xd.ErrorInfo.Value.InternalError(CodecErr.CodecUnsupBitstream, "Invalid usage of segement feature on small blocks");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -940,11 +957,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
int num4X4H = 1 << xd.BmodeBlocksHl;
|
int num4X4H = 1 << xd.BmodeBlocksHl;
|
||||||
int idx, idy;
|
int idx, idy;
|
||||||
PredictionMode bMode = 0;
|
PredictionMode bMode = 0;
|
||||||
Array2<Mv> bestSub8x8 = new Array2<Mv>();
|
Array2<Mv> bestSub8x8 = new();
|
||||||
const uint invalidMv = 0x80008000;
|
const uint InvalidMv = 0x80008000;
|
||||||
// Initialize the 2nd element as even though it won't be used meaningfully
|
// Initialize the 2nd element as even though it won't be used meaningfully
|
||||||
// if isCompound is false.
|
// if isCompound is false.
|
||||||
Unsafe.As<Mv, uint>(ref bestSub8x8[1]) = invalidMv;
|
Unsafe.As<Mv, uint>(ref bestSub8x8[1]) = InvalidMv;
|
||||||
for (idy = 0; idy < 2; idy += num4X4H)
|
for (idy = 0; idy < 2; idy += num4X4H)
|
||||||
{
|
{
|
||||||
for (idx = 0; idx < 2; idx += num4X4W)
|
for (idx = 0; idx < 2; idx += num4X4W)
|
||||||
|
@ -1026,11 +1043,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
|
|
||||||
return leftMi.Value.GetYMode(b + 1);
|
return leftMi.Value.GetYMode(b + 1);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
Debug.Assert(b == 1 || b == 3);
|
||||||
Debug.Assert(b == 1 || b == 3);
|
|
||||||
return curMi.Value.Bmi[b - 1].Mode;
|
return curMi.Value.Bmi[b - 1].Mode;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PredictionMode AboveBlockMode(Ptr<ModeInfo> curMi, Ptr<ModeInfo> aboveMi, int b)
|
private static PredictionMode AboveBlockMode(Ptr<ModeInfo> curMi, Ptr<ModeInfo> aboveMi, int b)
|
||||||
|
@ -1044,11 +1060,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
|
|
||||||
return aboveMi.Value.GetYMode(b + 2);
|
return aboveMi.Value.GetYMode(b + 2);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
Debug.Assert(b == 2 || b == 3);
|
||||||
Debug.Assert(b == 2 || b == 3);
|
|
||||||
return curMi.Value.Bmi[b - 2].Mode;
|
return curMi.Value.Bmi[b - 2].Mode;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ReadOnlySpan<byte> GetYModeProbs(
|
private static ReadOnlySpan<byte> GetYModeProbs(
|
||||||
|
@ -1060,6 +1075,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
PredictionMode above = AboveBlockMode(mi, aboveMi, block);
|
PredictionMode above = AboveBlockMode(mi, aboveMi, block);
|
||||||
PredictionMode left = LeftBlockMode(mi, leftMi, block);
|
PredictionMode left = LeftBlockMode(mi, leftMi, block);
|
||||||
|
|
||||||
return fc.KfYModeProb[(int)above][(int)left].AsSpan();
|
return fc.KfYModeProb[(int)above][(int)left].AsSpan();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ using Ryujinx.Graphics.Nvdec.Vp9.Common;
|
||||||
using Ryujinx.Graphics.Nvdec.Vp9.Types;
|
using Ryujinx.Graphics.Nvdec.Vp9.Types;
|
||||||
using Ryujinx.Graphics.Video;
|
using Ryujinx.Graphics.Video;
|
||||||
using System;
|
using System;
|
||||||
using Vp9MvRef = Ryujinx.Graphics.Video.Vp9MvRef;
|
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Nvdec.Vp9
|
namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
|
@ -11,7 +10,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
public bool IsHardwareAccelerated => false;
|
public bool IsHardwareAccelerated => false;
|
||||||
|
|
||||||
private readonly MemoryAllocator _allocator = new MemoryAllocator();
|
private readonly MemoryAllocator _allocator = new();
|
||||||
|
|
||||||
public ISurface CreateSurface(int width, int height) => new Surface(width, height);
|
public ISurface CreateSurface(int width, int height) => new Surface(width, height);
|
||||||
|
|
||||||
|
@ -20,7 +19,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
Constants.EightTapSmooth,
|
Constants.EightTapSmooth,
|
||||||
Constants.EightTap,
|
Constants.EightTap,
|
||||||
Constants.EightTapSharp,
|
Constants.EightTapSharp,
|
||||||
Constants.Bilinear
|
Constants.Bilinear,
|
||||||
};
|
};
|
||||||
|
|
||||||
public unsafe bool Decode(
|
public unsafe bool Decode(
|
||||||
|
@ -30,24 +29,25 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
ReadOnlySpan<Vp9MvRef> mvsIn,
|
ReadOnlySpan<Vp9MvRef> mvsIn,
|
||||||
Span<Vp9MvRef> mvsOut)
|
Span<Vp9MvRef> mvsOut)
|
||||||
{
|
{
|
||||||
Vp9Common cm = new Vp9Common();
|
Vp9Common cm = new()
|
||||||
|
{
|
||||||
|
FrameType = pictureInfo.IsKeyFrame ? FrameType.KeyFrame : FrameType.InterFrame,
|
||||||
|
IntraOnly = pictureInfo.IntraOnly,
|
||||||
|
|
||||||
cm.FrameType = pictureInfo.IsKeyFrame ? FrameType.KeyFrame : FrameType.InterFrame;
|
Width = output.Width,
|
||||||
cm.IntraOnly = pictureInfo.IntraOnly;
|
Height = output.Height,
|
||||||
|
SubsamplingX = 1,
|
||||||
|
SubsamplingY = 1,
|
||||||
|
|
||||||
cm.Width = output.Width;
|
UsePrevFrameMvs = pictureInfo.UsePrevInFindMvRefs,
|
||||||
cm.Height = output.Height;
|
|
||||||
cm.SubsamplingX = 1;
|
|
||||||
cm.SubsamplingY = 1;
|
|
||||||
|
|
||||||
cm.UsePrevFrameMvs = pictureInfo.UsePrevInFindMvRefs;
|
RefFrameSignBias = pictureInfo.RefFrameSignBias,
|
||||||
|
|
||||||
cm.RefFrameSignBias = pictureInfo.RefFrameSignBias;
|
BaseQindex = pictureInfo.BaseQIndex,
|
||||||
|
YDcDeltaQ = pictureInfo.YDcDeltaQ,
|
||||||
cm.BaseQindex = pictureInfo.BaseQIndex;
|
UvAcDeltaQ = pictureInfo.UvAcDeltaQ,
|
||||||
cm.YDcDeltaQ = pictureInfo.YDcDeltaQ;
|
UvDcDeltaQ = pictureInfo.UvDcDeltaQ,
|
||||||
cm.UvAcDeltaQ = pictureInfo.UvAcDeltaQ;
|
};
|
||||||
cm.UvDcDeltaQ = pictureInfo.UvDcDeltaQ;
|
|
||||||
|
|
||||||
cm.Mb.Lossless = pictureInfo.Lossless;
|
cm.Mb.Lossless = pictureInfo.Lossless;
|
||||||
cm.Mb.Bd = 8;
|
cm.Mb.Bd = 8;
|
||||||
|
|
|
@ -17,9 +17,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
|
|
||||||
private static int GetCoefContext(ReadOnlySpan<short> neighbors, ReadOnlySpan<byte> tokenCache, int c)
|
private static int GetCoefContext(ReadOnlySpan<short> neighbors, ReadOnlySpan<byte> tokenCache, int c)
|
||||||
{
|
{
|
||||||
const int maxNeighbors = 2;
|
const int MaxNeighbors = 2;
|
||||||
|
|
||||||
return (1 + tokenCache[neighbors[maxNeighbors * c + 0]] + tokenCache[neighbors[maxNeighbors * c + 1]]) >> 1;
|
return (1 + tokenCache[neighbors[MaxNeighbors * c + 0]] + tokenCache[neighbors[MaxNeighbors * c + 1]]) >> 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int ReadCoeff(
|
private static int ReadCoeff(
|
||||||
|
@ -57,13 +57,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
int band, c = 0;
|
int band, c = 0;
|
||||||
ref Array6<Array6<Array3<byte>>> coefProbs = ref fc.CoefProbs[(int)txSize][(int)type][refr];
|
ref Array6<Array6<Array3<byte>>> coefProbs = ref fc.CoefProbs[(int)txSize][(int)type][refr];
|
||||||
Span<byte> tokenCache = stackalloc byte[32 * 32];
|
Span<byte> tokenCache = stackalloc byte[32 * 32];
|
||||||
ReadOnlySpan<byte> bandTranslate = Luts.get_band_translate(txSize);
|
ReadOnlySpan<byte> bandTranslate = Luts.GetBandTranslate(txSize);
|
||||||
int dqShift = (txSize == TxSize.Tx32x32) ? 1 : 0;
|
int dqShift = (txSize == TxSize.Tx32x32) ? 1 : 0;
|
||||||
int v;
|
int v;
|
||||||
short dqv = dq[0];
|
short dqv = dq[0];
|
||||||
ReadOnlySpan<byte> cat6Prob = (xd.Bd == 12)
|
ReadOnlySpan<byte> cat6Prob = (xd.Bd == 12)
|
||||||
? Luts.Vp9Cat6ProbHigh12
|
? Luts.Vp9Cat6ProbHigh12
|
||||||
: (xd.Bd == 10) ? Luts.Vp9Cat6ProbHigh12.Slice(2) : Luts.Vp9Cat6Prob;
|
: (xd.Bd == 10) ? Luts.Vp9Cat6ProbHigh12[2..] : Luts.Vp9Cat6Prob;
|
||||||
int cat6Bits = (xd.Bd == 12) ? 18 : (xd.Bd == 10) ? 16 : 14;
|
int cat6Bits = (xd.Bd == 12) ? 18 : (xd.Bd == 10) ? 16 : 14;
|
||||||
// Keep value, range, and count as locals. The compiler produces better
|
// Keep value, range, and count as locals. The compiler produces better
|
||||||
// results with the locals than using r directly.
|
// results with the locals than using r directly.
|
||||||
|
@ -75,7 +75,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
int val = -1;
|
int val = -1;
|
||||||
band = bandTranslate[0];
|
band = bandTranslate[0];
|
||||||
bandTranslate = bandTranslate.Slice(1);
|
bandTranslate = bandTranslate[1..];
|
||||||
ref Array3<byte> prob = ref coefProbs[band][ctx];
|
ref Array3<byte> prob = ref coefProbs[band][ctx];
|
||||||
if (!xd.Counts.IsNull)
|
if (!xd.Counts.IsNull)
|
||||||
{
|
{
|
||||||
|
@ -107,11 +107,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
r.Value = value;
|
r.Value = value;
|
||||||
r.Range = range;
|
r.Range = range;
|
||||||
r.Count = count;
|
r.Count = count;
|
||||||
return c; // Zero tokens at the end (no eob token)
|
|
||||||
|
return c; // Zero tokens at the end (no eob token)
|
||||||
}
|
}
|
||||||
ctx = GetCoefContext(nb, tokenCache, c);
|
ctx = GetCoefContext(nb, tokenCache, c);
|
||||||
band = bandTranslate[0];
|
band = bandTranslate[0];
|
||||||
bandTranslate = bandTranslate.Slice(1);
|
bandTranslate = bandTranslate[1..];
|
||||||
prob = ref coefProbs[band][ctx];
|
prob = ref coefProbs[band][ctx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,6 +197,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
r.Value = value;
|
r.Value = value;
|
||||||
r.Range = range;
|
r.Range = range;
|
||||||
r.Count = count;
|
r.Count = count;
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,8 +238,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
ref MacroBlockDPlane pd = ref xd.Plane[plane];
|
ref MacroBlockDPlane pd = ref xd.Plane[plane];
|
||||||
ref Array2<short> dequant = ref pd.SegDequant[segId];
|
ref Array2<short> dequant = ref pd.SegDequant[segId];
|
||||||
int eob;
|
int eob;
|
||||||
Span<sbyte> a = pd.AboveContext.AsSpan().Slice(x);
|
Span<sbyte> a = pd.AboveContext.AsSpan()[x..];
|
||||||
Span<sbyte> l = pd.LeftContext.AsSpan().Slice(y);
|
Span<sbyte> l = pd.LeftContext.AsSpan()[y..];
|
||||||
int ctx;
|
int ctx;
|
||||||
int ctxShiftA = 0;
|
int ctxShiftA = 0;
|
||||||
int ctxShiftL = 0;
|
int ctxShiftL = 0;
|
||||||
|
|
|
@ -117,6 +117,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
if (Sse41.IsSupported && UseIntrinsics && xStepQ4 == 1 << SubpelBits)
|
if (Sse41.IsSupported && UseIntrinsics && xStepQ4 == 1 << SubpelBits)
|
||||||
{
|
{
|
||||||
ConvolveHorizSse41(src, srcStride, dst, dstStride, xFilters, x0Q4, w, h);
|
ConvolveHorizSse41(src, srcStride, dst, dstStride, xFilters, x0Q4, w, h);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,6 +262,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
if (Avx2.IsSupported && UseIntrinsics && yStepQ4 == 1 << SubpelBits)
|
if (Avx2.IsSupported && UseIntrinsics && yStepQ4 == 1 << SubpelBits)
|
||||||
{
|
{
|
||||||
ConvolveVertAvx2(src, srcStride, dst, dstStride, yFilters, y0Q4, w, h);
|
ConvolveVertAvx2(src, srcStride, dst, dstStride, yFilters, y0Q4, w, h);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -776,7 +778,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
Debug.Assert(yStepQ4 <= 32);
|
Debug.Assert(yStepQ4 <= 32);
|
||||||
Debug.Assert(xStepQ4 <= 32);
|
Debug.Assert(xStepQ4 <= 32);
|
||||||
|
|
||||||
HighbdConvolveHoriz(src - srcStride * (SubpelTaps / 2 - 1), srcStride, temp, 64, filter, x0Q4, xStepQ4, w, intermediateHeight, bd);
|
HighbdConvolveHoriz(src - srcStride * (SubpelTaps / 2 - 1), srcStride, temp, 64, filter, x0Q4, xStepQ4, w, intermediateHeight, bd);
|
||||||
HighbdConvolveVert(temp + 64 * (SubpelTaps / 2 - 1), 64, dst, dstStride, filter, y0Q4, yStepQ4, w, h, bd);
|
HighbdConvolveVert(temp + 64 * (SubpelTaps / 2 - 1), 64, dst, dstStride, filter, y0Q4, yStepQ4, w, h, bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -811,7 +813,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
int h,
|
int h,
|
||||||
int bd)
|
int bd)
|
||||||
{
|
{
|
||||||
HighbdConvolveAvgHoriz(src, srcStride, dst, dstStride, filter, x0Q4, xStepQ4, w, h, bd);
|
HighbdConvolveAvgHoriz(src, srcStride, dst, dstStride, filter, x0Q4, xStepQ4, w, h, bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unsafe void HighbdConvolve8Vert(
|
public static unsafe void HighbdConvolve8Vert(
|
||||||
|
|
|
@ -227,7 +227,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
private static unsafe void D135Predictor(byte* dst, int stride, int bs, byte* above, byte* left)
|
private static unsafe void D135Predictor(byte* dst, int stride, int bs, byte* above, byte* left)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
byte* border = stackalloc byte[32 + 32 - 1]; // outer border from bottom-left to top-right
|
byte* border = stackalloc byte[32 + 32 - 1]; // outer border from bottom-left to top-right
|
||||||
|
|
||||||
// Dst(dst, stride, bs, bs - 2)[0], i.e., border starting at bottom-left
|
// Dst(dst, stride, bs, bs - 2)[0], i.e., border starting at bottom-left
|
||||||
for (i = 0; i < bs - 2; ++i)
|
for (i = 0; i < bs - 2; ++i)
|
||||||
|
@ -607,13 +607,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
Dst(dst, stride, 1, 0) = Dst(dst, stride, 0, 2) = Avg2(b, c);
|
Dst(dst, stride, 1, 0) = Dst(dst, stride, 0, 2) = Avg2(b, c);
|
||||||
Dst(dst, stride, 2, 0) = Dst(dst, stride, 1, 2) = Avg2(c, d);
|
Dst(dst, stride, 2, 0) = Dst(dst, stride, 1, 2) = Avg2(c, d);
|
||||||
Dst(dst, stride, 3, 0) = Dst(dst, stride, 2, 2) = Avg2(d, e);
|
Dst(dst, stride, 3, 0) = Dst(dst, stride, 2, 2) = Avg2(d, e);
|
||||||
Dst(dst, stride, 3, 2) = Avg2(e, f); // Differs from vp8
|
Dst(dst, stride, 3, 2) = Avg2(e, f); // Differs from vp8
|
||||||
|
|
||||||
Dst(dst, stride, 0, 1) = Avg3(a, b, c);
|
Dst(dst, stride, 0, 1) = Avg3(a, b, c);
|
||||||
Dst(dst, stride, 1, 1) = Dst(dst, stride, 0, 3) = Avg3(b, c, d);
|
Dst(dst, stride, 1, 1) = Dst(dst, stride, 0, 3) = Avg3(b, c, d);
|
||||||
Dst(dst, stride, 2, 1) = Dst(dst, stride, 1, 3) = Avg3(c, d, e);
|
Dst(dst, stride, 2, 1) = Dst(dst, stride, 1, 3) = Avg3(c, d, e);
|
||||||
Dst(dst, stride, 3, 1) = Dst(dst, stride, 2, 3) = Avg3(d, e, f);
|
Dst(dst, stride, 3, 1) = Dst(dst, stride, 2, 3) = Avg3(d, e, f);
|
||||||
Dst(dst, stride, 3, 3) = Avg3(e, f, g); // Differs from vp8
|
Dst(dst, stride, 3, 3) = Avg3(e, f, g); // Differs from vp8
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unsafe void D63ePredictor4x4(byte* dst, int stride, byte* above, byte* left)
|
public static unsafe void D63ePredictor4x4(byte* dst, int stride, byte* above, byte* left)
|
||||||
|
@ -655,7 +655,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
Dst(dst, stride, 3, 0) = Dst(dst, stride, 2, 1) = Dst(dst, stride, 1, 2) = Dst(dst, stride, 0, 3) = Avg3(d, e, f);
|
Dst(dst, stride, 3, 0) = Dst(dst, stride, 2, 1) = Dst(dst, stride, 1, 2) = Dst(dst, stride, 0, 3) = Avg3(d, e, f);
|
||||||
Dst(dst, stride, 3, 1) = Dst(dst, stride, 2, 2) = Dst(dst, stride, 1, 3) = Avg3(e, f, g);
|
Dst(dst, stride, 3, 1) = Dst(dst, stride, 2, 2) = Dst(dst, stride, 1, 3) = Avg3(e, f, g);
|
||||||
Dst(dst, stride, 3, 2) = Dst(dst, stride, 2, 3) = Avg3(f, g, h);
|
Dst(dst, stride, 3, 2) = Dst(dst, stride, 2, 3) = Avg3(f, g, h);
|
||||||
Dst(dst, stride, 3, 3) = h; // differs from vp8
|
Dst(dst, stride, 3, 3) = h; // differs from vp8
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unsafe void D45ePredictor4x4(byte* dst, int stride, byte* above, byte* left)
|
public static unsafe void D45ePredictor4x4(byte* dst, int stride, byte* above, byte* left)
|
||||||
|
@ -935,7 +935,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
private static unsafe void HighbdD135Predictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, int bd)
|
private static unsafe void HighbdD135Predictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, int bd)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
ushort* border = stackalloc ushort[32 + 32 - 1]; // Outer border from bottom-left to top-right
|
ushort* border = stackalloc ushort[32 + 32 - 1]; // Outer border from bottom-left to top-right
|
||||||
|
|
||||||
// Dst(dst, stride, bs, bs - 2)[0], i.e., border starting at bottom-left
|
// Dst(dst, stride, bs, bs - 2)[0], i.e., border starting at bottom-left
|
||||||
for (i = 0; i < bs - 2; ++i)
|
for (i = 0; i < bs - 2; ++i)
|
||||||
|
@ -1281,13 +1281,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
Dst(dst, stride, 1, 0) = Dst(dst, stride, 0, 2) = Avg2(b, c);
|
Dst(dst, stride, 1, 0) = Dst(dst, stride, 0, 2) = Avg2(b, c);
|
||||||
Dst(dst, stride, 2, 0) = Dst(dst, stride, 1, 2) = Avg2(c, d);
|
Dst(dst, stride, 2, 0) = Dst(dst, stride, 1, 2) = Avg2(c, d);
|
||||||
Dst(dst, stride, 3, 0) = Dst(dst, stride, 2, 2) = Avg2(d, e);
|
Dst(dst, stride, 3, 0) = Dst(dst, stride, 2, 2) = Avg2(d, e);
|
||||||
Dst(dst, stride, 3, 2) = Avg2(e, f); // Differs from vp8
|
Dst(dst, stride, 3, 2) = Avg2(e, f); // Differs from vp8
|
||||||
|
|
||||||
Dst(dst, stride, 0, 1) = Avg3(a, b, c);
|
Dst(dst, stride, 0, 1) = Avg3(a, b, c);
|
||||||
Dst(dst, stride, 1, 1) = Dst(dst, stride, 0, 3) = Avg3(b, c, d);
|
Dst(dst, stride, 1, 1) = Dst(dst, stride, 0, 3) = Avg3(b, c, d);
|
||||||
Dst(dst, stride, 2, 1) = Dst(dst, stride, 1, 3) = Avg3(c, d, e);
|
Dst(dst, stride, 2, 1) = Dst(dst, stride, 1, 3) = Avg3(c, d, e);
|
||||||
Dst(dst, stride, 3, 1) = Dst(dst, stride, 2, 3) = Avg3(d, e, f);
|
Dst(dst, stride, 3, 1) = Dst(dst, stride, 2, 3) = Avg3(d, e, f);
|
||||||
Dst(dst, stride, 3, 3) = Avg3(e, f, g); // Differs from vp8
|
Dst(dst, stride, 3, 3) = Avg3(e, f, g); // Differs from vp8
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unsafe void HighbdD45Predictor4x4(ushort* dst, int stride, ushort* above, ushort* left, int bd)
|
public static unsafe void HighbdD45Predictor4x4(ushort* dst, int stride, ushort* above, ushort* left, int bd)
|
||||||
|
@ -1306,7 +1306,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
Dst(dst, stride, 3, 0) = Dst(dst, stride, 2, 1) = Dst(dst, stride, 1, 2) = Dst(dst, stride, 0, 3) = Avg3(d, e, f);
|
Dst(dst, stride, 3, 0) = Dst(dst, stride, 2, 1) = Dst(dst, stride, 1, 2) = Dst(dst, stride, 0, 3) = Avg3(d, e, f);
|
||||||
Dst(dst, stride, 3, 1) = Dst(dst, stride, 2, 2) = Dst(dst, stride, 1, 3) = Avg3(e, f, g);
|
Dst(dst, stride, 3, 1) = Dst(dst, stride, 2, 2) = Dst(dst, stride, 1, 3) = Avg3(e, f, g);
|
||||||
Dst(dst, stride, 3, 2) = Dst(dst, stride, 2, 3) = Avg3(f, g, h);
|
Dst(dst, stride, 3, 2) = Dst(dst, stride, 2, 3) = Avg3(f, g, h);
|
||||||
Dst(dst, stride, 3, 3) = h; // Differs from vp8
|
Dst(dst, stride, 3, 3) = h; // Differs from vp8
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unsafe void HighbdD117Predictor4x4(ushort* dst, int stride, ushort* above, ushort* left, int bd)
|
public static unsafe void HighbdD117Predictor4x4(ushort* dst, int stride, ushort* above, ushort* left, int bd)
|
||||||
|
|
|
@ -35,6 +35,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
// of this range for invalid/corrupt VP9 streams.
|
// of this range for invalid/corrupt VP9 streams.
|
||||||
Debug.Assert(short.MinValue <= input);
|
Debug.Assert(short.MinValue <= input);
|
||||||
Debug.Assert(input <= short.MaxValue);
|
Debug.Assert(input <= short.MaxValue);
|
||||||
|
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,6 +71,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
public static byte ClipPixelAdd(byte dest, long trans)
|
public static byte ClipPixelAdd(byte dest, long trans)
|
||||||
{
|
{
|
||||||
trans = WrapLow(trans);
|
trans = WrapLow(trans);
|
||||||
|
|
||||||
return BitUtils.ClipPixel(dest + (int)trans);
|
return BitUtils.ClipPixel(dest + (int)trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,6 +79,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
public static ushort HighbdClipPixelAdd(ushort dest, long trans, int bd)
|
public static ushort HighbdClipPixelAdd(ushort dest, long trans, int bd)
|
||||||
{
|
{
|
||||||
trans = HighbdWrapLow(trans, bd);
|
trans = HighbdWrapLow(trans, bd);
|
||||||
|
|
||||||
return BitUtils.ClipPixelHighbd(dest + (int)trans, bd);
|
return BitUtils.ClipPixelHighbd(dest + (int)trans, bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,6 +87,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
private static long DctConstRoundShift(long input)
|
private static long DctConstRoundShift(long input)
|
||||||
{
|
{
|
||||||
long rv = BitUtils.RoundPowerOfTwo(input, DctConstBits);
|
long rv = BitUtils.RoundPowerOfTwo(input, DctConstBits);
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,8 +119,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
op[1] = WrapLow(b1);
|
op[1] = WrapLow(b1);
|
||||||
op[2] = WrapLow(c1);
|
op[2] = WrapLow(c1);
|
||||||
op[3] = WrapLow(d1);
|
op[3] = WrapLow(d1);
|
||||||
ip = ip.Slice(4);
|
ip = ip[4..];
|
||||||
op = op.Slice(4);
|
op = op[4..];
|
||||||
}
|
}
|
||||||
|
|
||||||
Span<int> ip2 = output;
|
Span<int> ip2 = output;
|
||||||
|
@ -138,8 +142,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
dest[stride * 2] = ClipPixelAdd(dest[stride * 2], WrapLow(c1));
|
dest[stride * 2] = ClipPixelAdd(dest[stride * 2], WrapLow(c1));
|
||||||
dest[stride * 3] = ClipPixelAdd(dest[stride * 3], WrapLow(d1));
|
dest[stride * 3] = ClipPixelAdd(dest[stride * 3], WrapLow(d1));
|
||||||
|
|
||||||
ip2 = ip2.Slice(1);
|
ip2 = ip2[1..];
|
||||||
dest = dest.Slice(1);
|
dest = dest[1..];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,8 +171,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
dest[stride * 1] = ClipPixelAdd(dest[stride * 1], e1);
|
dest[stride * 1] = ClipPixelAdd(dest[stride * 1], e1);
|
||||||
dest[stride * 2] = ClipPixelAdd(dest[stride * 2], e1);
|
dest[stride * 2] = ClipPixelAdd(dest[stride * 2], e1);
|
||||||
dest[stride * 3] = ClipPixelAdd(dest[stride * 3], e1);
|
dest[stride * 3] = ClipPixelAdd(dest[stride * 3], e1);
|
||||||
ip2 = ip2.Slice(1);
|
ip2 = ip2[1..];
|
||||||
dest = dest.Slice(1);
|
dest = dest[1..];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,7 +186,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
|
|
||||||
if ((x0 | x1 | x2 | x3) == 0)
|
if ((x0 | x1 | x2 | x3) == 0)
|
||||||
{
|
{
|
||||||
output.Slice(0, 4).Fill(0);
|
output[..4].Clear();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,8 +252,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
for (i = 0; i < 4; ++i)
|
for (i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
Idct4(input, outptr);
|
Idct4(input, outptr);
|
||||||
input = input.Slice(4);
|
input = input[4..];
|
||||||
outptr = outptr.Slice(4);
|
outptr = outptr[4..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Columns
|
// Columns
|
||||||
|
@ -282,7 +287,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
dest[1] = ClipPixelAdd(dest[1], a1);
|
dest[1] = ClipPixelAdd(dest[1], a1);
|
||||||
dest[2] = ClipPixelAdd(dest[2], a1);
|
dest[2] = ClipPixelAdd(dest[2], a1);
|
||||||
dest[3] = ClipPixelAdd(dest[3], a1);
|
dest[3] = ClipPixelAdd(dest[3], a1);
|
||||||
dest = dest.Slice(stride);
|
dest = dest[stride..];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,7 +305,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
|
|
||||||
if ((x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7) == 0)
|
if ((x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7) == 0)
|
||||||
{
|
{
|
||||||
output.Slice(0, 8).Fill(0);
|
output[..8].Clear();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -434,8 +440,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
for (i = 0; i < 8; ++i)
|
for (i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
Idct8(input, outptr);
|
Idct8(input, outptr);
|
||||||
input = input.Slice(8);
|
input = input[8..];
|
||||||
outptr = outptr.Slice(8);
|
outptr = outptr[8..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then transform columns
|
// Then transform columns
|
||||||
|
@ -464,15 +470,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
Span<int> tempIn = stackalloc int[8];
|
Span<int> tempIn = stackalloc int[8];
|
||||||
Span<int> tempOut = stackalloc int[8];
|
Span<int> tempOut = stackalloc int[8];
|
||||||
|
|
||||||
output.Fill(0);
|
output.Clear();
|
||||||
|
|
||||||
// First transform rows
|
// First transform rows
|
||||||
// Only first 4 row has non-zero coefs
|
// Only first 4 row has non-zero coefs
|
||||||
for (i = 0; i < 4; ++i)
|
for (i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
Idct8(input, outptr);
|
Idct8(input, outptr);
|
||||||
input = input.Slice(8);
|
input = input[8..];
|
||||||
outptr = outptr.Slice(8);
|
outptr = outptr[8..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then transform columns
|
// Then transform columns
|
||||||
|
@ -506,7 +512,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
dest[i] = ClipPixelAdd(dest[i], a1);
|
dest[i] = ClipPixelAdd(dest[i], a1);
|
||||||
}
|
}
|
||||||
|
|
||||||
dest = dest.Slice(stride);
|
dest = dest[stride..];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -533,7 +539,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
|
|
||||||
if ((x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | x10 | x11 | x12 | x13 | x14 | x15) == 0)
|
if ((x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | x10 | x11 | x12 | x13 | x14 | x15) == 0)
|
||||||
{
|
{
|
||||||
output.Slice(0, 16).Fill(0);
|
output[..16].Clear();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -860,8 +867,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
for (i = 0; i < 16; ++i)
|
for (i = 0; i < 16; ++i)
|
||||||
{
|
{
|
||||||
Idct16(input, outptr);
|
Idct16(input, outptr);
|
||||||
input = input.Slice(16);
|
input = input[16..];
|
||||||
outptr = outptr.Slice(16);
|
outptr = outptr[16..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then transform columns
|
// Then transform columns
|
||||||
|
@ -889,15 +896,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
Span<int> tempIn = stackalloc int[16];
|
Span<int> tempIn = stackalloc int[16];
|
||||||
Span<int> tempOut = stackalloc int[16];
|
Span<int> tempOut = stackalloc int[16];
|
||||||
|
|
||||||
output.Fill(0);
|
output.Clear();
|
||||||
|
|
||||||
// First transform rows. Since all non-zero dct coefficients are in
|
// First transform rows. Since all non-zero dct coefficients are in
|
||||||
// upper-left 8x8 area, we only need to calculate first 8 rows here.
|
// upper-left 8x8 area, we only need to calculate first 8 rows here.
|
||||||
for (i = 0; i < 8; ++i)
|
for (i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
Idct16(input, outptr);
|
Idct16(input, outptr);
|
||||||
input = input.Slice(16);
|
input = input[16..];
|
||||||
outptr = outptr.Slice(16);
|
outptr = outptr[16..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then transform columns
|
// Then transform columns
|
||||||
|
@ -925,15 +932,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
Span<int> tempIn = stackalloc int[16];
|
Span<int> tempIn = stackalloc int[16];
|
||||||
Span<int> tempOut = stackalloc int[16];
|
Span<int> tempOut = stackalloc int[16];
|
||||||
|
|
||||||
output.Fill(0);
|
output.Clear();
|
||||||
|
|
||||||
// First transform rows. Since all non-zero dct coefficients are in
|
// First transform rows. Since all non-zero dct coefficients are in
|
||||||
// upper-left 4x4 area, we only need to calculate first 4 rows here.
|
// upper-left 4x4 area, we only need to calculate first 4 rows here.
|
||||||
for (i = 0; i < 4; ++i)
|
for (i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
Idct16(input, outptr);
|
Idct16(input, outptr);
|
||||||
input = input.Slice(16);
|
input = input[16..];
|
||||||
outptr = outptr.Slice(16);
|
outptr = outptr[16..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then transform columns
|
// Then transform columns
|
||||||
|
@ -967,7 +974,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
dest[i] = ClipPixelAdd(dest[i], a1);
|
dest[i] = ClipPixelAdd(dest[i], a1);
|
||||||
}
|
}
|
||||||
|
|
||||||
dest = dest.Slice(stride);
|
dest = dest[stride..];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1365,11 +1372,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
outptr.Slice(0, 32).Fill(0);
|
outptr[..32].Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
input = input.Slice(32);
|
input = input[32..];
|
||||||
outptr = outptr.Slice(32);
|
outptr = outptr[32..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Columns
|
// Columns
|
||||||
|
@ -1397,15 +1404,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
Span<int> tempIn = stackalloc int[32];
|
Span<int> tempIn = stackalloc int[32];
|
||||||
Span<int> tempOut = stackalloc int[32];
|
Span<int> tempOut = stackalloc int[32];
|
||||||
|
|
||||||
output.Fill(0);
|
output.Clear();
|
||||||
|
|
||||||
// Rows
|
// Rows
|
||||||
// Only upper-left 16x16 has non-zero coeff
|
// Only upper-left 16x16 has non-zero coeff
|
||||||
for (i = 0; i < 16; ++i)
|
for (i = 0; i < 16; ++i)
|
||||||
{
|
{
|
||||||
Idct32(input, outptr);
|
Idct32(input, outptr);
|
||||||
input = input.Slice(32);
|
input = input[32..];
|
||||||
outptr = outptr.Slice(32);
|
outptr = outptr[32..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Columns
|
// Columns
|
||||||
|
@ -1433,15 +1440,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
Span<int> tempIn = stackalloc int[32];
|
Span<int> tempIn = stackalloc int[32];
|
||||||
Span<int> tempOut = stackalloc int[32];
|
Span<int> tempOut = stackalloc int[32];
|
||||||
|
|
||||||
output.Fill(0);
|
output.Clear();
|
||||||
|
|
||||||
// Rows
|
// Rows
|
||||||
// Only upper-left 8x8 has non-zero coeff
|
// Only upper-left 8x8 has non-zero coeff
|
||||||
for (i = 0; i < 8; ++i)
|
for (i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
Idct32(input, outptr);
|
Idct32(input, outptr);
|
||||||
input = input.Slice(32);
|
input = input[32..];
|
||||||
outptr = outptr.Slice(32);
|
outptr = outptr[32..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Columns
|
// Columns
|
||||||
|
@ -1476,7 +1483,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
dest[i] = ClipPixelAdd(dest[i], a1);
|
dest[i] = ClipPixelAdd(dest[i], a1);
|
||||||
}
|
}
|
||||||
|
|
||||||
dest = dest.Slice(stride);
|
dest = dest[stride..];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1508,8 +1515,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
op[1] = HighbdWrapLow(b1, bd);
|
op[1] = HighbdWrapLow(b1, bd);
|
||||||
op[2] = HighbdWrapLow(c1, bd);
|
op[2] = HighbdWrapLow(c1, bd);
|
||||||
op[3] = HighbdWrapLow(d1, bd);
|
op[3] = HighbdWrapLow(d1, bd);
|
||||||
ip = ip.Slice(4);
|
ip = ip[4..];
|
||||||
op = op.Slice(4);
|
op = op[4..];
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadOnlySpan<int> ip2 = output;
|
ReadOnlySpan<int> ip2 = output;
|
||||||
|
@ -1531,8 +1538,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
dest[stride * 2] = HighbdClipPixelAdd(dest[stride * 2], HighbdWrapLow(c1, bd), bd);
|
dest[stride * 2] = HighbdClipPixelAdd(dest[stride * 2], HighbdWrapLow(c1, bd), bd);
|
||||||
dest[stride * 3] = HighbdClipPixelAdd(dest[stride * 3], HighbdWrapLow(d1, bd), bd);
|
dest[stride * 3] = HighbdClipPixelAdd(dest[stride * 3], HighbdWrapLow(d1, bd), bd);
|
||||||
|
|
||||||
ip2 = ip2.Slice(1);
|
ip2 = ip2[1..];
|
||||||
dest = dest.Slice(1);
|
dest = dest[1..];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1560,8 +1567,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
dest[stride * 1] = HighbdClipPixelAdd(dest[stride * 1], e1, bd);
|
dest[stride * 1] = HighbdClipPixelAdd(dest[stride * 1], e1, bd);
|
||||||
dest[stride * 2] = HighbdClipPixelAdd(dest[stride * 2], e1, bd);
|
dest[stride * 2] = HighbdClipPixelAdd(dest[stride * 2], e1, bd);
|
||||||
dest[stride * 3] = HighbdClipPixelAdd(dest[stride * 3], e1, bd);
|
dest[stride * 3] = HighbdClipPixelAdd(dest[stride * 3], e1, bd);
|
||||||
ip2 = ip2.Slice(1);
|
ip2 = ip2[1..];
|
||||||
dest = dest.Slice(1);
|
dest = dest[1..];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1576,13 +1583,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
if (DetectInvalidHighbdInput(input, 4) != 0)
|
if (DetectInvalidHighbdInput(input, 4) != 0)
|
||||||
{
|
{
|
||||||
Debug.Assert(false, "invalid highbd txfm input");
|
Debug.Assert(false, "invalid highbd txfm input");
|
||||||
output.Slice(0, 4).Fill(0);
|
output[..4].Clear();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((x0 | x1 | x2 | x3) == 0)
|
if ((x0 | x1 | x2 | x3) == 0)
|
||||||
{
|
{
|
||||||
output.Slice(0, 4).Fill(0);
|
output[..4].Clear();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1619,7 +1628,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
if (DetectInvalidHighbdInput(input, 4) != 0)
|
if (DetectInvalidHighbdInput(input, 4) != 0)
|
||||||
{
|
{
|
||||||
Debug.Assert(false, "invalid highbd txfm input");
|
Debug.Assert(false, "invalid highbd txfm input");
|
||||||
output.Slice(0, 4).Fill(0);
|
output[..4].Clear();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1653,8 +1663,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
for (i = 0; i < 4; ++i)
|
for (i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
HighbdIdct4(input, outptr, bd);
|
HighbdIdct4(input, outptr, bd);
|
||||||
input = input.Slice(4);
|
input = input[4..];
|
||||||
outptr = outptr.Slice(4);
|
outptr = outptr[4..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Columns
|
// Columns
|
||||||
|
@ -1688,7 +1698,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
dest[1] = HighbdClipPixelAdd(dest[1], a1, bd);
|
dest[1] = HighbdClipPixelAdd(dest[1], a1, bd);
|
||||||
dest[2] = HighbdClipPixelAdd(dest[2], a1, bd);
|
dest[2] = HighbdClipPixelAdd(dest[2], a1, bd);
|
||||||
dest[3] = HighbdClipPixelAdd(dest[3], a1, bd);
|
dest[3] = HighbdClipPixelAdd(dest[3], a1, bd);
|
||||||
dest = dest.Slice(stride);
|
dest = dest[stride..];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1707,13 +1717,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
if (DetectInvalidHighbdInput(input, 8) != 0)
|
if (DetectInvalidHighbdInput(input, 8) != 0)
|
||||||
{
|
{
|
||||||
Debug.Assert(false, "invalid highbd txfm input");
|
Debug.Assert(false, "invalid highbd txfm input");
|
||||||
output.Slice(0, 8).Fill(0);
|
output[..8].Clear();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7) == 0)
|
if ((x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7) == 0)
|
||||||
{
|
{
|
||||||
output.Slice(0, 8).Fill(0);
|
output[..8].Clear();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1786,7 +1798,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
if (DetectInvalidHighbdInput(input, 8) != 0)
|
if (DetectInvalidHighbdInput(input, 8) != 0)
|
||||||
{
|
{
|
||||||
Debug.Assert(false, "invalid highbd txfm input");
|
Debug.Assert(false, "invalid highbd txfm input");
|
||||||
output.Slice(0, 8).Fill(0);
|
output[..8].Clear();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1845,8 +1858,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
for (i = 0; i < 8; ++i)
|
for (i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
HighbdIdct8(input, outptr, bd);
|
HighbdIdct8(input, outptr, bd);
|
||||||
input = input.Slice(8);
|
input = input[8..];
|
||||||
outptr = outptr.Slice(8);
|
outptr = outptr[8..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then transform columns
|
// Then transform columns
|
||||||
|
@ -1874,15 +1887,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
Span<int> tempIn = stackalloc int[8];
|
Span<int> tempIn = stackalloc int[8];
|
||||||
Span<int> tempOut = stackalloc int[8];
|
Span<int> tempOut = stackalloc int[8];
|
||||||
|
|
||||||
output.Fill(0);
|
output.Clear();
|
||||||
|
|
||||||
// First transform rows
|
// First transform rows
|
||||||
// Only first 4 row has non-zero coefs
|
// Only first 4 row has non-zero coefs
|
||||||
for (i = 0; i < 4; ++i)
|
for (i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
HighbdIdct8(input, outptr, bd);
|
HighbdIdct8(input, outptr, bd);
|
||||||
input = input.Slice(8);
|
input = input[8..];
|
||||||
outptr = outptr.Slice(8);
|
outptr = outptr[8..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then transform columns
|
// Then transform columns
|
||||||
|
@ -1901,7 +1914,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void vpx_Highbdidct8x8_1_add_c(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int bd)
|
public static void Vpx_Highbdidct8x8_1_add_c(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int bd)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
long a1;
|
long a1;
|
||||||
|
@ -1916,7 +1929,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
dest[i] = HighbdClipPixelAdd(dest[i], a1, bd);
|
dest[i] = HighbdClipPixelAdd(dest[i], a1, bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
dest = dest.Slice(stride);
|
dest = dest[stride..];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1940,16 +1953,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
int x13 = input[12];
|
int x13 = input[12];
|
||||||
int x14 = input[1];
|
int x14 = input[1];
|
||||||
int x15 = input[14];
|
int x15 = input[14];
|
||||||
|
|
||||||
if (DetectInvalidHighbdInput(input, 16) != 0)
|
if (DetectInvalidHighbdInput(input, 16) != 0)
|
||||||
{
|
{
|
||||||
Debug.Assert(false, "invalid highbd txfm input");
|
Debug.Assert(false, "invalid highbd txfm input");
|
||||||
output.Slice(0, 16).Fill(0);
|
output[..16].Clear();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | x10 | x11 | x12 | x13 | x14 | x15) == 0)
|
if ((x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | x10 | x11 | x12 | x13 | x14 | x15) == 0)
|
||||||
{
|
{
|
||||||
output.Slice(0, 16).Fill(0);
|
output[..16].Clear();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2105,7 +2121,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
if (DetectInvalidHighbdInput(input, 16) != 0)
|
if (DetectInvalidHighbdInput(input, 16) != 0)
|
||||||
{
|
{
|
||||||
Debug.Assert(false, "invalid highbd txfm input");
|
Debug.Assert(false, "invalid highbd txfm input");
|
||||||
output.Slice(0, 16).Fill(0);
|
output[..16].Clear();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2283,8 +2300,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
for (i = 0; i < 16; ++i)
|
for (i = 0; i < 16; ++i)
|
||||||
{
|
{
|
||||||
HighbdIdct16(input, outptr, bd);
|
HighbdIdct16(input, outptr, bd);
|
||||||
input = input.Slice(16);
|
input = input[16..];
|
||||||
outptr = outptr.Slice(16);
|
outptr = outptr[16..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then transform columns
|
// Then transform columns
|
||||||
|
@ -2312,15 +2329,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
Span<int> tempIn = stackalloc int[16];
|
Span<int> tempIn = stackalloc int[16];
|
||||||
Span<int> tempOut = stackalloc int[16];
|
Span<int> tempOut = stackalloc int[16];
|
||||||
|
|
||||||
output.Fill(0);
|
output.Clear();
|
||||||
|
|
||||||
// First transform rows. Since all non-zero dct coefficients are in
|
// First transform rows. Since all non-zero dct coefficients are in
|
||||||
// upper-left 8x8 area, we only need to calculate first 8 rows here.
|
// upper-left 8x8 area, we only need to calculate first 8 rows here.
|
||||||
for (i = 0; i < 8; ++i)
|
for (i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
HighbdIdct16(input, outptr, bd);
|
HighbdIdct16(input, outptr, bd);
|
||||||
input = input.Slice(16);
|
input = input[16..];
|
||||||
outptr = outptr.Slice(16);
|
outptr = outptr[16..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then transform columns
|
// Then transform columns
|
||||||
|
@ -2336,7 +2353,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
for (j = 0; j < 16; ++j)
|
for (j = 0; j < 16; ++j)
|
||||||
{
|
{
|
||||||
destT[i] = HighbdClipPixelAdd(destT[i], BitUtils.RoundPowerOfTwo(tempOut[j], 6), bd);
|
destT[i] = HighbdClipPixelAdd(destT[i], BitUtils.RoundPowerOfTwo(tempOut[j], 6), bd);
|
||||||
destT = destT.Slice(stride);
|
destT = destT[stride..];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2350,15 +2367,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
Span<int> tempIn = stackalloc int[16];
|
Span<int> tempIn = stackalloc int[16];
|
||||||
Span<int> tempOut = stackalloc int[16];
|
Span<int> tempOut = stackalloc int[16];
|
||||||
|
|
||||||
output.Fill(0);
|
output.Clear();
|
||||||
|
|
||||||
// First transform rows. Since all non-zero dct coefficients are in
|
// First transform rows. Since all non-zero dct coefficients are in
|
||||||
// upper-left 4x4 area, we only need to calculate first 4 rows here.
|
// upper-left 4x4 area, we only need to calculate first 4 rows here.
|
||||||
for (i = 0; i < 4; ++i)
|
for (i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
HighbdIdct16(input, outptr, bd);
|
HighbdIdct16(input, outptr, bd);
|
||||||
input = input.Slice(16);
|
input = input[16..];
|
||||||
outptr = outptr.Slice(16);
|
outptr = outptr[16..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then transform columns
|
// Then transform columns
|
||||||
|
@ -2392,7 +2409,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
dest[i] = HighbdClipPixelAdd(dest[i], a1, bd);
|
dest[i] = HighbdClipPixelAdd(dest[i], a1, bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
dest = dest.Slice(stride);
|
dest = dest[stride..];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2406,7 +2423,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
if (DetectInvalidHighbdInput(input, 32) != 0)
|
if (DetectInvalidHighbdInput(input, 32) != 0)
|
||||||
{
|
{
|
||||||
Debug.Assert(false, "invalid highbd txfm input");
|
Debug.Assert(false, "invalid highbd txfm input");
|
||||||
output.Slice(0, 32).Fill(0);
|
output[..32].Clear();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2797,11 +2815,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
outptr.Slice(0, 32).Fill(0);
|
outptr[..32].Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
input = input.Slice(32);
|
input = input[32..];
|
||||||
outptr = outptr.Slice(32);
|
outptr = outptr[32..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Columns
|
// Columns
|
||||||
|
@ -2829,15 +2847,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
Span<int> tempIn = stackalloc int[32];
|
Span<int> tempIn = stackalloc int[32];
|
||||||
Span<int> tempOut = stackalloc int[32];
|
Span<int> tempOut = stackalloc int[32];
|
||||||
|
|
||||||
output.Fill(0);
|
output.Clear();
|
||||||
|
|
||||||
// Rows
|
// Rows
|
||||||
// Only upper-left 16x16 has non-zero coeff
|
// Only upper-left 16x16 has non-zero coeff
|
||||||
for (i = 0; i < 16; ++i)
|
for (i = 0; i < 16; ++i)
|
||||||
{
|
{
|
||||||
HighbdIdct32(input, outptr, bd);
|
HighbdIdct32(input, outptr, bd);
|
||||||
input = input.Slice(32);
|
input = input[32..];
|
||||||
outptr = outptr.Slice(32);
|
outptr = outptr[32..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Columns
|
// Columns
|
||||||
|
@ -2853,7 +2871,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
for (j = 0; j < 32; ++j)
|
for (j = 0; j < 32; ++j)
|
||||||
{
|
{
|
||||||
destT[i] = HighbdClipPixelAdd(destT[i], BitUtils.RoundPowerOfTwo(tempOut[j], 6), bd);
|
destT[i] = HighbdClipPixelAdd(destT[i], BitUtils.RoundPowerOfTwo(tempOut[j], 6), bd);
|
||||||
destT = destT.Slice(stride);
|
destT = destT[stride..];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2867,15 +2885,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
Span<int> tempIn = stackalloc int[32];
|
Span<int> tempIn = stackalloc int[32];
|
||||||
Span<int> tempOut = stackalloc int[32];
|
Span<int> tempOut = stackalloc int[32];
|
||||||
|
|
||||||
output.Fill(0);
|
output.Clear();
|
||||||
|
|
||||||
// Rows
|
// Rows
|
||||||
// Only upper-left 8x8 has non-zero coeff
|
// Only upper-left 8x8 has non-zero coeff
|
||||||
for (i = 0; i < 8; ++i)
|
for (i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
HighbdIdct32(input, outptr, bd);
|
HighbdIdct32(input, outptr, bd);
|
||||||
input = input.Slice(32);
|
input = input[32..];
|
||||||
outptr = outptr.Slice(32);
|
outptr = outptr[32..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Columns
|
// Columns
|
||||||
|
@ -2910,7 +2928,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
dest[i] = HighbdClipPixelAdd(dest[i], a1, bd);
|
dest[i] = HighbdClipPixelAdd(dest[i], a1, bd);
|
||||||
}
|
}
|
||||||
|
|
||||||
dest = dest.Slice(stride);
|
dest = dest[stride..];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
int p = (int)(((ulong)num * 256 + (den >> 1)) / den);
|
int p = (int)(((ulong)num * 256 + (den >> 1)) / den);
|
||||||
// (p > 255) ? 255 : (p < 1) ? 1 : p;
|
// (p > 255) ? 255 : (p < 1) ? 1 : p;
|
||||||
int clippedProb = p | ((255 - p) >> 23) | (p == 0 ? 1 : 0);
|
int clippedProb = p | ((255 - p) >> 23) | (p == 0 ? 1 : 0);
|
||||||
|
|
||||||
return (byte)clippedProb;
|
return (byte)clippedProb;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,10 +27,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
}
|
}
|
||||||
|
|
||||||
// MODE_MV_MAX_UPDATE_FACTOR (128) * count / MODE_MV_COUNT_SAT;
|
// MODE_MV_MAX_UPDATE_FACTOR (128) * count / MODE_MV_COUNT_SAT;
|
||||||
private static readonly uint[] CountToUpdateFactor = new uint[]
|
private static readonly uint[] _countToUpdateFactor = {
|
||||||
{
|
|
||||||
0, 6, 12, 19, 25, 32, 38, 44, 51, 57, 64,
|
0, 6, 12, 19, 25, 32, 38, 44, 51, 57, 64,
|
||||||
70, 76, 83, 89, 96, 102, 108, 115, 121, 128
|
70, 76, 83, 89, 96, 102, 108, 115, 121, 128,
|
||||||
};
|
};
|
||||||
|
|
||||||
private const int ModeMvCountSat = 20;
|
private const int ModeMvCountSat = 20;
|
||||||
|
@ -44,8 +44,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint count = Math.Min(den, ModeMvCountSat);
|
uint count = Math.Min(den, ModeMvCountSat);
|
||||||
uint factor = CountToUpdateFactor[(int)count];
|
uint factor = _countToUpdateFactor[(int)count];
|
||||||
byte prob = GetProb(ct0, den);
|
byte prob = GetProb(ct0, den);
|
||||||
|
|
||||||
return WeightedProb(preProb, prob, (int)factor);
|
return WeightedProb(preProb, prob, (int)factor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,6 +63,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
int r = tree[i + 1];
|
int r = tree[i + 1];
|
||||||
uint rightCount = (r <= 0) ? counts[-r] : TreeMergeProbsImpl((uint)r, tree, preProbs, counts, probs);
|
uint rightCount = (r <= 0) ? counts[-r] : TreeMergeProbsImpl((uint)r, tree, preProbs, counts, probs);
|
||||||
probs[(int)(i >> 1)] = ModeMvMergeProbs(preProbs[(int)(i >> 1)], leftCount, rightCount);
|
probs[(int)(i >> 1)] = ModeMvMergeProbs(preProbs[(int)(i >> 1)], leftCount, rightCount);
|
||||||
|
|
||||||
return leftCount + rightCount;
|
return leftCount + rightCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
{
|
{
|
||||||
internal struct Reader
|
internal struct Reader
|
||||||
{
|
{
|
||||||
private static readonly byte[] Norm = new byte[]
|
private static readonly byte[] _norm = {
|
||||||
{
|
|
||||||
0, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
0, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||||
3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
@ -17,7 +16,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
};
|
};
|
||||||
private const int BdValueSize = sizeof(ulong) * 8;
|
private const int BdValueSize = sizeof(ulong) * 8;
|
||||||
|
|
||||||
|
@ -44,7 +43,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
Count = -8;
|
Count = -8;
|
||||||
Range = 255;
|
Range = 255;
|
||||||
Fill();
|
Fill();
|
||||||
return ReadBit() != 0; // Marker bit
|
|
||||||
|
return ReadBit() != 0; // Marker bit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
ulong bigEndianValues = BinaryPrimitives.ReadUInt64BigEndian(buffer);
|
ulong bigEndianValues = BinaryPrimitives.ReadUInt64BigEndian(buffer);
|
||||||
nv = bigEndianValues >> (BdValueSize - bits);
|
nv = bigEndianValues >> (BdValueSize - bits);
|
||||||
count += bits;
|
count += bits;
|
||||||
buffer = buffer.Slice(bits >> 3);
|
buffer = buffer[(bits >> 3)..];
|
||||||
value = Value | (nv << (shift & 0x7));
|
value = Value | (nv << (shift & 0x7));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -84,7 +84,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
{
|
{
|
||||||
count += 8;
|
count += 8;
|
||||||
value |= (ulong)buffer[0] << shift;
|
value |= (ulong)buffer[0] << shift;
|
||||||
buffer = buffer.Slice(1);
|
buffer = buffer[1..];
|
||||||
shift -= 8;
|
shift -= 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
Count = count;
|
Count = count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasError()
|
public readonly bool HasError()
|
||||||
{
|
{
|
||||||
// Check if we have reached the end of the buffer.
|
// Check if we have reached the end of the buffer.
|
||||||
//
|
//
|
||||||
|
@ -146,7 +146,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
int shift = Norm[range];
|
int shift = _norm[range];
|
||||||
range <<= shift;
|
range <<= shift;
|
||||||
value <<= shift;
|
value <<= shift;
|
||||||
count -= shift;
|
count -= shift;
|
||||||
|
@ -160,7 +160,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
|
|
||||||
public int ReadBit()
|
public int ReadBit()
|
||||||
{
|
{
|
||||||
return Read(128); // vpx_prob_half
|
return Read(128); // vpx_prob_half
|
||||||
}
|
}
|
||||||
|
|
||||||
public int ReadLiteral(int bits)
|
public int ReadLiteral(int bits)
|
||||||
|
@ -181,7 +181,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
|
|
||||||
while ((i = tree[i + Read(probs[i >> 1])]) > 0)
|
while ((i = tree[i + Read(probs[i >> 1])]) > 0)
|
||||||
{
|
{
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return -i;
|
return -i;
|
||||||
|
@ -203,10 +202,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
|
|
||||||
if (value >= bigsplit)
|
if (value >= bigsplit)
|
||||||
{
|
{
|
||||||
range = range - split;
|
range -= split;
|
||||||
value = value - bigsplit;
|
value -= bigsplit;
|
||||||
{
|
{
|
||||||
int shift = Norm[range];
|
int shift = _norm[range];
|
||||||
range <<= shift;
|
range <<= shift;
|
||||||
value <<= shift;
|
value <<= shift;
|
||||||
count -= shift;
|
count -= shift;
|
||||||
|
@ -215,7 +214,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||||
}
|
}
|
||||||
range = split;
|
range = split;
|
||||||
{
|
{
|
||||||
int shift = Norm[range];
|
int shift = _norm[range];
|
||||||
range <<= shift;
|
range <<= shift;
|
||||||
value <<= shift;
|
value <<= shift;
|
||||||
count -= shift;
|
count -= shift;
|
||||||
|
|
|
@ -12,7 +12,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
|
|
||||||
private struct Transform2D
|
private struct Transform2D
|
||||||
{
|
{
|
||||||
public Transform1D Cols, Rows; // Vertical and horizontal
|
public Transform1D Cols, Rows; // Vertical and horizontal
|
||||||
|
|
||||||
public Transform2D(Transform1D cols, Transform1D rows)
|
public Transform2D(Transform1D cols, Transform1D rows)
|
||||||
{
|
{
|
||||||
|
@ -23,7 +23,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
|
|
||||||
private struct HighbdTransform2D
|
private struct HighbdTransform2D
|
||||||
{
|
{
|
||||||
public HighbdTransform1D Cols, Rows; // Vertical and horizontal
|
public HighbdTransform1D Cols, Rows; // Vertical and horizontal
|
||||||
|
|
||||||
public HighbdTransform2D(HighbdTransform1D cols, HighbdTransform1D rows)
|
public HighbdTransform2D(HighbdTransform1D cols, HighbdTransform1D rows)
|
||||||
{
|
{
|
||||||
|
@ -32,12 +32,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly Transform2D[] Iht4 = new Transform2D[]
|
private static readonly Transform2D[] _iht4 = {
|
||||||
{
|
new(Idct4, Idct4), // DCT_DCT = 0
|
||||||
new Transform2D(Idct4, Idct4), // DCT_DCT = 0
|
new(Iadst4, Idct4), // ADST_DCT = 1
|
||||||
new Transform2D(Iadst4, Idct4), // ADST_DCT = 1
|
new(Idct4, Iadst4), // DCT_ADST = 2
|
||||||
new Transform2D(Idct4, Iadst4), // DCT_ADST = 2
|
new(Iadst4, Iadst4), // ADST_ADST = 3
|
||||||
new Transform2D(Iadst4, Iadst4) // ADST_ADST = 3
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public static void Iht4x416Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int txType)
|
public static void Iht4x416Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int txType)
|
||||||
|
@ -51,9 +50,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
// Inverse transform row vectors
|
// Inverse transform row vectors
|
||||||
for (i = 0; i < 4; ++i)
|
for (i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
Iht4[txType].Rows(input, outptr);
|
_iht4[txType].Rows(input, outptr);
|
||||||
input = input.Slice(4);
|
input = input[4..];
|
||||||
outptr = outptr.Slice(4);
|
outptr = outptr[4..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inverse transform column vectors
|
// Inverse transform column vectors
|
||||||
|
@ -64,7 +63,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
tempIn[j] = output[j * 4 + i];
|
tempIn[j] = output[j * 4 + i];
|
||||||
}
|
}
|
||||||
|
|
||||||
Iht4[txType].Cols(tempIn, tempOut);
|
_iht4[txType].Cols(tempIn, tempOut);
|
||||||
for (j = 0; j < 4; ++j)
|
for (j = 0; j < 4; ++j)
|
||||||
{
|
{
|
||||||
dest[j * stride + i] = ClipPixelAdd(dest[j * stride + i], BitUtils.RoundPowerOfTwo(tempOut[j], 4));
|
dest[j * stride + i] = ClipPixelAdd(dest[j * stride + i], BitUtils.RoundPowerOfTwo(tempOut[j], 4));
|
||||||
|
@ -72,12 +71,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly Transform2D[] Iht8 = new Transform2D[]
|
private static readonly Transform2D[] _iht8 = {
|
||||||
{
|
new(Idct8, Idct8), // DCT_DCT = 0
|
||||||
new Transform2D(Idct8, Idct8), // DCT_DCT = 0
|
new(Iadst8, Idct8), // ADST_DCT = 1
|
||||||
new Transform2D(Iadst8, Idct8), // ADST_DCT = 1
|
new(Idct8, Iadst8), // DCT_ADST = 2
|
||||||
new Transform2D(Idct8, Iadst8), // DCT_ADST = 2
|
new(Iadst8, Iadst8), // ADST_ADST = 3
|
||||||
new Transform2D(Iadst8, Iadst8) // ADST_ADST = 3
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public static void Iht8x864Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int txType)
|
public static void Iht8x864Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int txType)
|
||||||
|
@ -87,14 +85,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
Span<int> outptr = output;
|
Span<int> outptr = output;
|
||||||
Span<int> tempIn = stackalloc int[8];
|
Span<int> tempIn = stackalloc int[8];
|
||||||
Span<int> tempOut = stackalloc int[8];
|
Span<int> tempOut = stackalloc int[8];
|
||||||
Transform2D ht = Iht8[txType];
|
Transform2D ht = _iht8[txType];
|
||||||
|
|
||||||
// Inverse transform row vectors
|
// Inverse transform row vectors
|
||||||
for (i = 0; i < 8; ++i)
|
for (i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
ht.Rows(input, outptr);
|
ht.Rows(input, outptr);
|
||||||
input = input.Slice(8);
|
input = input[8..];
|
||||||
outptr = outptr.Slice(8);
|
outptr = outptr[8..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inverse transform column vectors
|
// Inverse transform column vectors
|
||||||
|
@ -113,12 +111,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly Transform2D[] Iht16 = new Transform2D[]
|
private static readonly Transform2D[] _iht16 = {
|
||||||
{
|
new(Idct16, Idct16), // DCT_DCT = 0
|
||||||
new Transform2D(Idct16, Idct16), // DCT_DCT = 0
|
new(Iadst16, Idct16), // ADST_DCT = 1
|
||||||
new Transform2D(Iadst16, Idct16), // ADST_DCT = 1
|
new(Idct16, Iadst16), // DCT_ADST = 2
|
||||||
new Transform2D(Idct16, Iadst16), // DCT_ADST = 2
|
new(Iadst16, Iadst16), // ADST_ADST = 3
|
||||||
new Transform2D(Iadst16, Iadst16) // ADST_ADST = 3
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public static void Iht16x16256Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int txType)
|
public static void Iht16x16256Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int txType)
|
||||||
|
@ -128,14 +125,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
Span<int> outptr = output;
|
Span<int> outptr = output;
|
||||||
Span<int> tempIn = stackalloc int[16];
|
Span<int> tempIn = stackalloc int[16];
|
||||||
Span<int> tempOut = stackalloc int[16];
|
Span<int> tempOut = stackalloc int[16];
|
||||||
Transform2D ht = Iht16[txType];
|
Transform2D ht = _iht16[txType];
|
||||||
|
|
||||||
// Rows
|
// Rows
|
||||||
for (i = 0; i < 16; ++i)
|
for (i = 0; i < 16; ++i)
|
||||||
{
|
{
|
||||||
ht.Rows(input, outptr);
|
ht.Rows(input, outptr);
|
||||||
input = input.Slice(16);
|
input = input[16..];
|
||||||
outptr = outptr.Slice(16);
|
outptr = outptr[16..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Columns
|
// Columns
|
||||||
|
@ -283,12 +280,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly HighbdTransform2D[] HighbdIht4 = new HighbdTransform2D[]
|
private static readonly HighbdTransform2D[] _highbdIht4 = {
|
||||||
{
|
new(HighbdIdct4, HighbdIdct4), // DCT_DCT = 0
|
||||||
new HighbdTransform2D(HighbdIdct4, HighbdIdct4), // DCT_DCT = 0
|
new(HighbdIadst4, HighbdIdct4), // ADST_DCT = 1
|
||||||
new HighbdTransform2D(HighbdIadst4, HighbdIdct4), // ADST_DCT = 1
|
new(HighbdIdct4, HighbdIadst4), // DCT_ADST = 2
|
||||||
new HighbdTransform2D(HighbdIdct4, HighbdIadst4), // DCT_ADST = 2
|
new(HighbdIadst4, HighbdIadst4), // ADST_ADST = 3
|
||||||
new HighbdTransform2D(HighbdIadst4, HighbdIadst4) // ADST_ADST = 3
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public static void HighbdIht4x416Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int txType, int bd)
|
public static void HighbdIht4x416Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int txType, int bd)
|
||||||
|
@ -302,9 +298,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
// Inverse transform row vectors.
|
// Inverse transform row vectors.
|
||||||
for (i = 0; i < 4; ++i)
|
for (i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
HighbdIht4[txType].Rows(input, outptr, bd);
|
_highbdIht4[txType].Rows(input, outptr, bd);
|
||||||
input = input.Slice(4);
|
input = input[4..];
|
||||||
outptr = outptr.Slice(4);
|
outptr = outptr[4..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inverse transform column vectors.
|
// Inverse transform column vectors.
|
||||||
|
@ -315,7 +311,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
tempIn[j] = output[j * 4 + i];
|
tempIn[j] = output[j * 4 + i];
|
||||||
}
|
}
|
||||||
|
|
||||||
HighbdIht4[txType].Cols(tempIn, tempOut, bd);
|
_highbdIht4[txType].Cols(tempIn, tempOut, bd);
|
||||||
for (j = 0; j < 4; ++j)
|
for (j = 0; j < 4; ++j)
|
||||||
{
|
{
|
||||||
dest[j * stride + i] = HighbdClipPixelAdd(dest[j * stride + i], BitUtils.RoundPowerOfTwo(tempOut[j], 4), bd);
|
dest[j * stride + i] = HighbdClipPixelAdd(dest[j * stride + i], BitUtils.RoundPowerOfTwo(tempOut[j], 4), bd);
|
||||||
|
@ -323,12 +319,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly HighbdTransform2D[] HighIht8 = new HighbdTransform2D[]
|
private static readonly HighbdTransform2D[] _highIht8 = {
|
||||||
{
|
new(HighbdIdct8, HighbdIdct8), // DCT_DCT = 0
|
||||||
new HighbdTransform2D(HighbdIdct8, HighbdIdct8), // DCT_DCT = 0
|
new(HighbdIadst8, HighbdIdct8), // ADST_DCT = 1
|
||||||
new HighbdTransform2D(HighbdIadst8, HighbdIdct8), // ADST_DCT = 1
|
new(HighbdIdct8, HighbdIadst8), // DCT_ADST = 2
|
||||||
new HighbdTransform2D(HighbdIdct8, HighbdIadst8), // DCT_ADST = 2
|
new(HighbdIadst8, HighbdIadst8), // ADST_ADST = 3
|
||||||
new HighbdTransform2D(HighbdIadst8, HighbdIadst8) // ADST_ADST = 3
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public static void HighbdIht8x864Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int txType, int bd)
|
public static void HighbdIht8x864Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int txType, int bd)
|
||||||
|
@ -338,14 +333,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
Span<int> outptr = output;
|
Span<int> outptr = output;
|
||||||
Span<int> tempIn = stackalloc int[8];
|
Span<int> tempIn = stackalloc int[8];
|
||||||
Span<int> tempOut = stackalloc int[8];
|
Span<int> tempOut = stackalloc int[8];
|
||||||
HighbdTransform2D ht = HighIht8[txType];
|
HighbdTransform2D ht = _highIht8[txType];
|
||||||
|
|
||||||
// Inverse transform row vectors.
|
// Inverse transform row vectors.
|
||||||
for (i = 0; i < 8; ++i)
|
for (i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
ht.Rows(input, outptr, bd);
|
ht.Rows(input, outptr, bd);
|
||||||
input = input.Slice(8);
|
input = input[8..];
|
||||||
outptr = output.Slice(8);
|
outptr = output[8..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inverse transform column vectors.
|
// Inverse transform column vectors.
|
||||||
|
@ -364,12 +359,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly HighbdTransform2D[] HighIht16 = new HighbdTransform2D[]
|
private static readonly HighbdTransform2D[] _highIht16 = {
|
||||||
{
|
new(HighbdIdct16, HighbdIdct16), // DCT_DCT = 0
|
||||||
new HighbdTransform2D(HighbdIdct16, HighbdIdct16), // DCT_DCT = 0
|
new(HighbdIadst16, HighbdIdct16), // ADST_DCT = 1
|
||||||
new HighbdTransform2D(HighbdIadst16, HighbdIdct16), // ADST_DCT = 1
|
new(HighbdIdct16, HighbdIadst16), // DCT_ADST = 2
|
||||||
new HighbdTransform2D(HighbdIdct16, HighbdIadst16), // DCT_ADST = 2
|
new(HighbdIadst16, HighbdIadst16), // ADST_ADST = 3
|
||||||
new HighbdTransform2D(HighbdIadst16, HighbdIadst16) // ADST_ADST = 3
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public static void HighbdIht16x16256Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int txType, int bd)
|
public static void HighbdIht16x16256Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int txType, int bd)
|
||||||
|
@ -379,14 +373,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
Span<int> outptr = output;
|
Span<int> outptr = output;
|
||||||
Span<int> tempIn = stackalloc int[16];
|
Span<int> tempIn = stackalloc int[16];
|
||||||
Span<int> tempOut = stackalloc int[16];
|
Span<int> tempOut = stackalloc int[16];
|
||||||
HighbdTransform2D ht = HighIht16[txType];
|
HighbdTransform2D ht = _highIht16[txType];
|
||||||
|
|
||||||
// Rows
|
// Rows
|
||||||
for (i = 0; i < 16; ++i)
|
for (i = 0; i < 16; ++i)
|
||||||
{
|
{
|
||||||
ht.Rows(input, outptr, bd);
|
ht.Rows(input, outptr, bd);
|
||||||
input = input.Slice(16);
|
input = input[16..];
|
||||||
outptr = output.Slice(16);
|
outptr = output[16..];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Columns
|
// Columns
|
||||||
|
@ -440,7 +434,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
// DC only DCT coefficient
|
// DC only DCT coefficient
|
||||||
if (eob == 1)
|
if (eob == 1)
|
||||||
{
|
{
|
||||||
vpx_Highbdidct8x8_1_add_c(input, dest, stride, bd);
|
Vpx_Highbdidct8x8_1_add_c(input, dest, stride, bd);
|
||||||
}
|
}
|
||||||
else if (eob <= 12)
|
else if (eob <= 12)
|
||||||
{
|
{
|
||||||
|
|
|
@ -30,12 +30,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
// 10101010
|
// 10101010
|
||||||
//
|
//
|
||||||
// A loopfilter should be applied to every other 8x8 horizontally.
|
// A loopfilter should be applied to every other 8x8 horizontally.
|
||||||
private static readonly ulong[] Left64X64TxformMask = new ulong[]
|
private static readonly ulong[] _left64X64TxformMask = {
|
||||||
{
|
0xffffffffffffffffUL, // TX_4X4
|
||||||
0xffffffffffffffffUL, // TX_4X4
|
0xffffffffffffffffUL, // TX_8x8
|
||||||
0xffffffffffffffffUL, // TX_8x8
|
0x5555555555555555UL, // TX_16x16
|
||||||
0x5555555555555555UL, // TX_16x16
|
0x1111111111111111UL, // TX_32x32
|
||||||
0x1111111111111111UL, // TX_32x32
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 64 bit masks for above transform size. Each 1 represents a position where
|
// 64 bit masks for above transform size. Each 1 represents a position where
|
||||||
|
@ -55,12 +54,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
// 00000000
|
// 00000000
|
||||||
//
|
//
|
||||||
// A loopfilter should be applied to every other 4 the row vertically.
|
// A loopfilter should be applied to every other 4 the row vertically.
|
||||||
private static readonly ulong[] Above64X64TxformMask = new ulong[]
|
private static readonly ulong[] _above64X64TxformMask = {
|
||||||
{
|
0xffffffffffffffffUL, // TX_4X4
|
||||||
0xffffffffffffffffUL, // TX_4X4
|
0xffffffffffffffffUL, // TX_8x8
|
||||||
0xffffffffffffffffUL, // TX_8x8
|
0x00ff00ff00ff00ffUL, // TX_16x16
|
||||||
0x00ff00ff00ff00ffUL, // TX_16x16
|
0x000000ff000000ffUL, // TX_32x32
|
||||||
0x000000ff000000ffUL, // TX_32x32
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 64 bit masks for prediction sizes (left). Each 1 represents a position
|
// 64 bit masks for prediction sizes (left). Each 1 represents a position
|
||||||
|
@ -78,148 +76,143 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
// 00000000
|
// 00000000
|
||||||
// 00000000
|
// 00000000
|
||||||
// 00000000
|
// 00000000
|
||||||
private static readonly ulong[] LeftPredictionMask = new ulong[]
|
private static readonly ulong[] _leftPredictionMask = {
|
||||||
{
|
0x0000000000000001UL, // BLOCK_4X4,
|
||||||
0x0000000000000001UL, // BLOCK_4X4,
|
0x0000000000000001UL, // BLOCK_4X8,
|
||||||
0x0000000000000001UL, // BLOCK_4X8,
|
0x0000000000000001UL, // BLOCK_8X4,
|
||||||
0x0000000000000001UL, // BLOCK_8X4,
|
0x0000000000000001UL, // BLOCK_8X8,
|
||||||
0x0000000000000001UL, // BLOCK_8X8,
|
0x0000000000000101UL, // BLOCK_8X16,
|
||||||
0x0000000000000101UL, // BLOCK_8X16,
|
0x0000000000000001UL, // BLOCK_16X8,
|
||||||
0x0000000000000001UL, // BLOCK_16X8,
|
0x0000000000000101UL, // BLOCK_16X16,
|
||||||
0x0000000000000101UL, // BLOCK_16X16,
|
0x0000000001010101UL, // BLOCK_16X32,
|
||||||
0x0000000001010101UL, // BLOCK_16X32,
|
0x0000000000000101UL, // BLOCK_32X16,
|
||||||
0x0000000000000101UL, // BLOCK_32X16,
|
0x0000000001010101UL, // BLOCK_32X32,
|
||||||
0x0000000001010101UL, // BLOCK_32X32,
|
0x0101010101010101UL, // BLOCK_32X64,
|
||||||
0x0101010101010101UL, // BLOCK_32X64,
|
0x0000000001010101UL, // BLOCK_64X32,
|
||||||
0x0000000001010101UL, // BLOCK_64X32,
|
0x0101010101010101UL, // BLOCK_64X64
|
||||||
0x0101010101010101UL, // BLOCK_64X64
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 64 bit mask to shift and set for each prediction size.
|
// 64 bit mask to shift and set for each prediction size.
|
||||||
private static readonly ulong[] AbovePredictionMask = new ulong[]
|
private static readonly ulong[] _abovePredictionMask = {
|
||||||
{
|
0x0000000000000001UL, // BLOCK_4X4
|
||||||
0x0000000000000001UL, // BLOCK_4X4
|
0x0000000000000001UL, // BLOCK_4X8
|
||||||
0x0000000000000001UL, // BLOCK_4X8
|
0x0000000000000001UL, // BLOCK_8X4
|
||||||
0x0000000000000001UL, // BLOCK_8X4
|
0x0000000000000001UL, // BLOCK_8X8
|
||||||
0x0000000000000001UL, // BLOCK_8X8
|
0x0000000000000001UL, // BLOCK_8X16,
|
||||||
0x0000000000000001UL, // BLOCK_8X16,
|
0x0000000000000003UL, // BLOCK_16X8
|
||||||
0x0000000000000003UL, // BLOCK_16X8
|
0x0000000000000003UL, // BLOCK_16X16
|
||||||
0x0000000000000003UL, // BLOCK_16X16
|
0x0000000000000003UL, // BLOCK_16X32,
|
||||||
0x0000000000000003UL, // BLOCK_16X32,
|
0x000000000000000fUL, // BLOCK_32X16,
|
||||||
0x000000000000000fUL, // BLOCK_32X16,
|
0x000000000000000fUL, // BLOCK_32X32,
|
||||||
0x000000000000000fUL, // BLOCK_32X32,
|
0x000000000000000fUL, // BLOCK_32X64,
|
||||||
0x000000000000000fUL, // BLOCK_32X64,
|
0x00000000000000ffUL, // BLOCK_64X32,
|
||||||
0x00000000000000ffUL, // BLOCK_64X32,
|
0x00000000000000ffUL, // BLOCK_64X64
|
||||||
0x00000000000000ffUL, // BLOCK_64X64
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 64 bit mask to shift and set for each prediction size. A bit is set for
|
// 64 bit mask to shift and set for each prediction size. A bit is set for
|
||||||
// each 8x8 block that would be in the left most block of the given block
|
// each 8x8 block that would be in the left most block of the given block
|
||||||
// size in the 64x64 block.
|
// size in the 64x64 block.
|
||||||
private static readonly ulong[] SizeMask = new ulong[]
|
private static readonly ulong[] _sizeMask = {
|
||||||
{
|
0x0000000000000001UL, // BLOCK_4X4
|
||||||
0x0000000000000001UL, // BLOCK_4X4
|
0x0000000000000001UL, // BLOCK_4X8
|
||||||
0x0000000000000001UL, // BLOCK_4X8
|
0x0000000000000001UL, // BLOCK_8X4
|
||||||
0x0000000000000001UL, // BLOCK_8X4
|
0x0000000000000001UL, // BLOCK_8X8
|
||||||
0x0000000000000001UL, // BLOCK_8X8
|
0x0000000000000101UL, // BLOCK_8X16,
|
||||||
0x0000000000000101UL, // BLOCK_8X16,
|
0x0000000000000003UL, // BLOCK_16X8
|
||||||
0x0000000000000003UL, // BLOCK_16X8
|
0x0000000000000303UL, // BLOCK_16X16
|
||||||
0x0000000000000303UL, // BLOCK_16X16
|
0x0000000003030303UL, // BLOCK_16X32,
|
||||||
0x0000000003030303UL, // BLOCK_16X32,
|
0x0000000000000f0fUL, // BLOCK_32X16,
|
||||||
0x0000000000000f0fUL, // BLOCK_32X16,
|
0x000000000f0f0f0fUL, // BLOCK_32X32,
|
||||||
0x000000000f0f0f0fUL, // BLOCK_32X32,
|
0x0f0f0f0f0f0f0f0fUL, // BLOCK_32X64,
|
||||||
0x0f0f0f0f0f0f0f0fUL, // BLOCK_32X64,
|
0x00000000ffffffffUL, // BLOCK_64X32,
|
||||||
0x00000000ffffffffUL, // BLOCK_64X32,
|
0xffffffffffffffffUL, // BLOCK_64X64
|
||||||
0xffffffffffffffffUL, // BLOCK_64X64
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// These are used for masking the left and above borders.
|
// These are used for masking the left and above borders.
|
||||||
|
#pragma warning disable IDE0051 // Remove unused private member
|
||||||
private const ulong LeftBorder = 0x1111111111111111UL;
|
private const ulong LeftBorder = 0x1111111111111111UL;
|
||||||
private const ulong AboveBorder = 0x000000ff000000ffUL;
|
private const ulong AboveBorder = 0x000000ff000000ffUL;
|
||||||
|
#pragma warning restore IDE0051
|
||||||
|
|
||||||
// 16 bit masks for uv transform sizes.
|
// 16 bit masks for uv transform sizes.
|
||||||
private static readonly ushort[] Left64X64TxformMaskUv = new ushort[]
|
private static readonly ushort[] _left64X64TxformMaskUv = {
|
||||||
{
|
0xffff, // TX_4X4
|
||||||
0xffff, // TX_4X4
|
0xffff, // TX_8x8
|
||||||
0xffff, // TX_8x8
|
0x5555, // TX_16x16
|
||||||
0x5555, // TX_16x16
|
0x1111, // TX_32x32
|
||||||
0x1111, // TX_32x32
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly ushort[] Above64X64TxformMaskUv = new ushort[]
|
private static readonly ushort[] _above64X64TxformMaskUv = {
|
||||||
{
|
0xffff, // TX_4X4
|
||||||
0xffff, // TX_4X4
|
0xffff, // TX_8x8
|
||||||
0xffff, // TX_8x8
|
0x0f0f, // TX_16x16
|
||||||
0x0f0f, // TX_16x16
|
0x000f, // TX_32x32
|
||||||
0x000f, // TX_32x32
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 16 bit left mask to shift and set for each uv prediction size.
|
// 16 bit left mask to shift and set for each uv prediction size.
|
||||||
private static readonly ushort[] LeftPredictionMaskUv = new ushort[]
|
private static readonly ushort[] _leftPredictionMaskUv = {
|
||||||
{
|
0x0001, // BLOCK_4X4,
|
||||||
0x0001, // BLOCK_4X4,
|
0x0001, // BLOCK_4X8,
|
||||||
0x0001, // BLOCK_4X8,
|
0x0001, // BLOCK_8X4,
|
||||||
0x0001, // BLOCK_8X4,
|
0x0001, // BLOCK_8X8,
|
||||||
0x0001, // BLOCK_8X8,
|
0x0001, // BLOCK_8X16,
|
||||||
0x0001, // BLOCK_8X16,
|
0x0001, // BLOCK_16X8,
|
||||||
0x0001, // BLOCK_16X8,
|
0x0001, // BLOCK_16X16,
|
||||||
0x0001, // BLOCK_16X16,
|
0x0011, // BLOCK_16X32,
|
||||||
0x0011, // BLOCK_16X32,
|
0x0001, // BLOCK_32X16,
|
||||||
0x0001, // BLOCK_32X16,
|
0x0011, // BLOCK_32X32,
|
||||||
0x0011, // BLOCK_32X32,
|
0x1111, // BLOCK_32X64
|
||||||
0x1111, // BLOCK_32X64
|
0x0011, // BLOCK_64X32,
|
||||||
0x0011, // BLOCK_64X32,
|
0x1111, // BLOCK_64X64
|
||||||
0x1111, // BLOCK_64X64
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 16 bit above mask to shift and set for uv each prediction size.
|
// 16 bit above mask to shift and set for uv each prediction size.
|
||||||
private static readonly ushort[] AbovePredictionMaskUv = new ushort[]
|
private static readonly ushort[] _abovePredictionMaskUv = {
|
||||||
{
|
0x0001, // BLOCK_4X4
|
||||||
0x0001, // BLOCK_4X4
|
0x0001, // BLOCK_4X8
|
||||||
0x0001, // BLOCK_4X8
|
0x0001, // BLOCK_8X4
|
||||||
0x0001, // BLOCK_8X4
|
0x0001, // BLOCK_8X8
|
||||||
0x0001, // BLOCK_8X8
|
0x0001, // BLOCK_8X16,
|
||||||
0x0001, // BLOCK_8X16,
|
0x0001, // BLOCK_16X8
|
||||||
0x0001, // BLOCK_16X8
|
0x0001, // BLOCK_16X16
|
||||||
0x0001, // BLOCK_16X16
|
0x0001, // BLOCK_16X32,
|
||||||
0x0001, // BLOCK_16X32,
|
0x0003, // BLOCK_32X16,
|
||||||
0x0003, // BLOCK_32X16,
|
0x0003, // BLOCK_32X32,
|
||||||
0x0003, // BLOCK_32X32,
|
0x0003, // BLOCK_32X64,
|
||||||
0x0003, // BLOCK_32X64,
|
0x000f, // BLOCK_64X32,
|
||||||
0x000f, // BLOCK_64X32,
|
0x000f, // BLOCK_64X64
|
||||||
0x000f, // BLOCK_64X64
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 64 bit mask to shift and set for each uv prediction size
|
// 64 bit mask to shift and set for each uv prediction size
|
||||||
private static readonly ushort[] SizeMaskUv = new ushort[]
|
private static readonly ushort[] _sizeMaskUv = {
|
||||||
{
|
0x0001, // BLOCK_4X4
|
||||||
0x0001, // BLOCK_4X4
|
0x0001, // BLOCK_4X8
|
||||||
0x0001, // BLOCK_4X8
|
0x0001, // BLOCK_8X4
|
||||||
0x0001, // BLOCK_8X4
|
0x0001, // BLOCK_8X8
|
||||||
0x0001, // BLOCK_8X8
|
0x0001, // BLOCK_8X16,
|
||||||
0x0001, // BLOCK_8X16,
|
0x0001, // BLOCK_16X8
|
||||||
0x0001, // BLOCK_16X8
|
0x0001, // BLOCK_16X16
|
||||||
0x0001, // BLOCK_16X16
|
0x0011, // BLOCK_16X32,
|
||||||
0x0011, // BLOCK_16X32,
|
0x0003, // BLOCK_32X16,
|
||||||
0x0003, // BLOCK_32X16,
|
0x0033, // BLOCK_32X32,
|
||||||
0x0033, // BLOCK_32X32,
|
0x3333, // BLOCK_32X64,
|
||||||
0x3333, // BLOCK_32X64,
|
0x00ff, // BLOCK_64X32,
|
||||||
0x00ff, // BLOCK_64X32,
|
0xffff, // BLOCK_64X64
|
||||||
0xffff, // BLOCK_64X64
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#pragma warning disable IDE0051 // Remove unused private member
|
||||||
private const ushort LeftBorderUv = 0x1111;
|
private const ushort LeftBorderUv = 0x1111;
|
||||||
private const ushort AboveBorderUv = 0x000f;
|
private const ushort AboveBorderUv = 0x000f;
|
||||||
|
#pragma warning restore IDE0051
|
||||||
|
|
||||||
private static readonly int[] ModeLfLut = new int[]
|
private static readonly int[] _modeLfLut = {
|
||||||
{
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // INTRA_MODES
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // INTRA_MODES
|
1, 1, 0, 1, // INTER_MODES (ZEROMV == 0)
|
||||||
1, 1, 0, 1 // INTER_MODES (ZEROMV == 0)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private static byte GetFilterLevel(ref LoopFilterInfoN lfiN, ref ModeInfo mi)
|
private static byte GetFilterLevel(ref LoopFilterInfoN lfiN, ref ModeInfo mi)
|
||||||
{
|
{
|
||||||
return lfiN.Lvl[mi.SegmentId][mi.RefFrame[0]][ModeLfLut[(int)mi.Mode]];
|
return lfiN.Lvl[mi.SegmentId][mi.RefFrame[0]][_modeLfLut[(int)mi.Mode]];
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ref LoopFilterMask GetLfm(ref Types.LoopFilter lf, int miRow, int miCol)
|
private static ref LoopFilterMask GetLfm(ref Types.LoopFilter lf, int miRow, int miCol)
|
||||||
|
@ -229,12 +222,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
|
|
||||||
// 8x8 blocks in a superblock. A "1" represents the first block in a 16x16
|
// 8x8 blocks in a superblock. A "1" represents the first block in a 16x16
|
||||||
// or greater area.
|
// or greater area.
|
||||||
private static readonly byte[][] FirstBlockIn16x16 = new byte[][]
|
private static readonly byte[][] _firstBlockIn16X16 = {
|
||||||
{
|
new byte[] { 1, 0, 1, 0, 1, 0, 1, 0 }, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||||
new byte[] { 1, 0, 1, 0, 1, 0, 1, 0 }, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 },
|
new byte[] { 1, 0, 1, 0, 1, 0, 1, 0 }, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||||
new byte[] { 1, 0, 1, 0, 1, 0, 1, 0 }, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 },
|
new byte[] { 1, 0, 1, 0, 1, 0, 1, 0 }, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||||
new byte[] { 1, 0, 1, 0, 1, 0, 1, 0 }, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 },
|
new byte[] { 1, 0, 1, 0, 1, 0, 1, 0 }, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||||
new byte[] { 1, 0, 1, 0, 1, 0, 1, 0 }, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// This function sets up the bit masks for a block represented
|
// This function sets up the bit masks for a block represented
|
||||||
|
@ -257,21 +249,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
int colInSb = (miCol & 7);
|
int colInSb = (miCol & 7);
|
||||||
int shiftY = colInSb + (rowInSb << 3);
|
int shiftY = colInSb + (rowInSb << 3);
|
||||||
int shiftUv = (colInSb >> 1) + ((rowInSb >> 1) << 2);
|
int shiftUv = (colInSb >> 1) + ((rowInSb >> 1) << 2);
|
||||||
int buildUv = FirstBlockIn16x16[rowInSb][colInSb];
|
int buildUv = _firstBlockIn16X16[rowInSb][colInSb];
|
||||||
|
|
||||||
if (filterLevel == 0)
|
if (filterLevel == 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
int index = shiftY;
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < bh; i++)
|
||||||
{
|
{
|
||||||
int index = shiftY;
|
MemoryMarshal.CreateSpan(ref lfm.LflY[index], 64 - index)[..bw].Fill((byte)filterLevel);
|
||||||
int i;
|
index += 8;
|
||||||
for (i = 0; i < bh; i++)
|
|
||||||
{
|
|
||||||
MemoryMarshal.CreateSpan(ref lfm.LflY[index], 64 - index).Slice(0, bw).Fill((byte)filterLevel);
|
|
||||||
index += 8;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// These set 1 in the current block size for the block size edges.
|
// These set 1 in the current block size for the block size edges.
|
||||||
|
@ -286,13 +276,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
//
|
//
|
||||||
// U and V set things on a 16 bit scale.
|
// U and V set things on a 16 bit scale.
|
||||||
//
|
//
|
||||||
aboveY |= AbovePredictionMask[(int)blockSize] << shiftY;
|
aboveY |= _abovePredictionMask[(int)blockSize] << shiftY;
|
||||||
leftY |= LeftPredictionMask[(int)blockSize] << shiftY;
|
leftY |= _leftPredictionMask[(int)blockSize] << shiftY;
|
||||||
|
|
||||||
if (buildUv != 0)
|
if (buildUv != 0)
|
||||||
{
|
{
|
||||||
aboveUv |= (ushort)(AbovePredictionMaskUv[(int)blockSize] << shiftUv);
|
aboveUv |= (ushort)(_abovePredictionMaskUv[(int)blockSize] << shiftUv);
|
||||||
leftUv |= (ushort)(LeftPredictionMaskUv[(int)blockSize] << shiftUv);
|
leftUv |= (ushort)(_leftPredictionMaskUv[(int)blockSize] << shiftUv);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the block has no coefficients and is not intra we skip applying
|
// If the block has no coefficients and is not intra we skip applying
|
||||||
|
@ -305,13 +295,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
// Add a mask for the transform size. The transform size mask is set to
|
// Add a mask for the transform size. The transform size mask is set to
|
||||||
// be correct for a 64x64 prediction block size. Mask to match the size of
|
// be correct for a 64x64 prediction block size. Mask to match the size of
|
||||||
// the block we are working on and then shift it into place.
|
// the block we are working on and then shift it into place.
|
||||||
aboveY |= (SizeMask[(int)blockSize] & Above64X64TxformMask[(int)txSizeY]) << shiftY;
|
aboveY |= (_sizeMask[(int)blockSize] & _above64X64TxformMask[(int)txSizeY]) << shiftY;
|
||||||
leftY |= (SizeMask[(int)blockSize] & Left64X64TxformMask[(int)txSizeY]) << shiftY;
|
leftY |= (_sizeMask[(int)blockSize] & _left64X64TxformMask[(int)txSizeY]) << shiftY;
|
||||||
|
|
||||||
if (buildUv != 0)
|
if (buildUv != 0)
|
||||||
{
|
{
|
||||||
aboveUv |= (ushort)((SizeMaskUv[(int)blockSize] & Above64X64TxformMaskUv[(int)txSizeUv]) << shiftUv);
|
aboveUv |= (ushort)((_sizeMaskUv[(int)blockSize] & _above64X64TxformMaskUv[(int)txSizeUv]) << shiftUv);
|
||||||
leftUv |= (ushort)((SizeMaskUv[(int)blockSize] & Left64X64TxformMaskUv[(int)txSizeUv]) << shiftUv);
|
leftUv |= (ushort)((_sizeMaskUv[(int)blockSize] & _left64X64TxformMaskUv[(int)txSizeUv]) << shiftUv);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to determine what to do with the internal 4x4 block boundaries. These
|
// Try to determine what to do with the internal 4x4 block boundaries. These
|
||||||
|
@ -319,12 +309,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
// internal ones can be skipped and don't depend on the prediction block size.
|
// internal ones can be skipped and don't depend on the prediction block size.
|
||||||
if (txSizeY == TxSize.Tx4x4)
|
if (txSizeY == TxSize.Tx4x4)
|
||||||
{
|
{
|
||||||
int4X4Y |= SizeMask[(int)blockSize] << shiftY;
|
int4X4Y |= _sizeMask[(int)blockSize] << shiftY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buildUv != 0 && txSizeUv == TxSize.Tx4x4)
|
if (buildUv != 0 && txSizeUv == TxSize.Tx4x4)
|
||||||
{
|
{
|
||||||
int4X4Uv |= (ushort)((SizeMaskUv[(int)blockSize] & 0xffff) << shiftUv);
|
int4X4Uv |= (ushort)((_sizeMaskUv[(int)blockSize] & 0xffff) << shiftUv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -13,7 +13,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
// left of the entries corresponding to real macroblocks.
|
// left of the entries corresponding to real macroblocks.
|
||||||
// The prediction flags in these dummy entries are initialized to 0.
|
// The prediction flags in these dummy entries are initialized to 0.
|
||||||
if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
|
if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
|
||||||
{ // both edges available
|
{ // both edges available
|
||||||
if (!xd.AboveMi.Value.HasSecondRef() && !xd.LeftMi.Value.HasSecondRef())
|
if (!xd.AboveMi.Value.HasSecondRef() && !xd.LeftMi.Value.HasSecondRef())
|
||||||
{
|
{
|
||||||
// Neither edge uses comp pred (0/1)
|
// Neither edge uses comp pred (0/1)
|
||||||
|
@ -30,13 +30,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
// One of two edges uses comp pred (2/3)
|
// One of two edges uses comp pred (2/3)
|
||||||
ctx = 2 + (xd.LeftMi.Value.RefFrame[0] == cm.CompFixedRef || !xd.LeftMi.Value.IsInterBlock() ? 1 : 0);
|
ctx = 2 + (xd.LeftMi.Value.RefFrame[0] == cm.CompFixedRef || !xd.LeftMi.Value.IsInterBlock() ? 1 : 0);
|
||||||
}
|
}
|
||||||
else // Both edges use comp pred (4)
|
else // Both edges use comp pred (4)
|
||||||
{
|
{
|
||||||
ctx = 4;
|
ctx = 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull)
|
else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull)
|
||||||
{ // One edge available
|
{ // One edge available
|
||||||
ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value;
|
ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value;
|
||||||
|
|
||||||
if (!edgeMi.HasSecondRef())
|
if (!edgeMi.HasSecondRef())
|
||||||
|
@ -51,10 +51,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // No edges available (1)
|
{ // No edges available (1)
|
||||||
ctx = 1;
|
ctx = 1;
|
||||||
}
|
}
|
||||||
Debug.Assert(ctx >= 0 && ctx < Constants.CompInterContexts);
|
Debug.Assert(ctx >= 0 && ctx < Constants.CompInterContexts);
|
||||||
|
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,29 +71,29 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
int varRefIdx = fixRefIdx == 0 ? 1 : 0;
|
int varRefIdx = fixRefIdx == 0 ? 1 : 0;
|
||||||
|
|
||||||
if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
|
if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
|
||||||
{ // Both edges available
|
{ // Both edges available
|
||||||
bool aboveIntra = !xd.AboveMi.Value.IsInterBlock();
|
bool aboveIntra = !xd.AboveMi.Value.IsInterBlock();
|
||||||
bool leftIntra = !xd.LeftMi.Value.IsInterBlock();
|
bool leftIntra = !xd.LeftMi.Value.IsInterBlock();
|
||||||
|
|
||||||
if (aboveIntra && leftIntra)
|
if (aboveIntra && leftIntra)
|
||||||
{ // Intra/Intra (2)
|
{ // Intra/Intra (2)
|
||||||
predContext = 2;
|
predContext = 2;
|
||||||
}
|
}
|
||||||
else if (aboveIntra || leftIntra)
|
else if (aboveIntra || leftIntra)
|
||||||
{ // Intra/Inter
|
{ // Intra/Inter
|
||||||
ref ModeInfo edgeMi = ref aboveIntra ? ref xd.LeftMi.Value : ref xd.AboveMi.Value;
|
ref ModeInfo edgeMi = ref aboveIntra ? ref xd.LeftMi.Value : ref xd.AboveMi.Value;
|
||||||
|
|
||||||
if (!edgeMi.HasSecondRef()) // single pred (1/3)
|
if (!edgeMi.HasSecondRef()) // single pred (1/3)
|
||||||
{
|
{
|
||||||
predContext = 1 + 2 * (edgeMi.RefFrame[0] != cm.CompVarRef[1] ? 1 : 0);
|
predContext = 1 + 2 * (edgeMi.RefFrame[0] != cm.CompVarRef[1] ? 1 : 0);
|
||||||
}
|
}
|
||||||
else // Comp pred (1/3)
|
else // Comp pred (1/3)
|
||||||
{
|
{
|
||||||
predContext = 1 + 2 * (edgeMi.RefFrame[varRefIdx] != cm.CompVarRef[1] ? 1 : 0);
|
predContext = 1 + 2 * (edgeMi.RefFrame[varRefIdx] != cm.CompVarRef[1] ? 1 : 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // Inter/Inter
|
{ // Inter/Inter
|
||||||
bool lSg = !xd.LeftMi.Value.HasSecondRef();
|
bool lSg = !xd.LeftMi.Value.HasSecondRef();
|
||||||
bool aSg = !xd.AboveMi.Value.HasSecondRef();
|
bool aSg = !xd.AboveMi.Value.HasSecondRef();
|
||||||
sbyte vrfa = aSg ? xd.AboveMi.Value.RefFrame[0] : xd.AboveMi.Value.RefFrame[varRefIdx];
|
sbyte vrfa = aSg ? xd.AboveMi.Value.RefFrame[0] : xd.AboveMi.Value.RefFrame[varRefIdx];
|
||||||
|
@ -103,7 +104,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
predContext = 0;
|
predContext = 0;
|
||||||
}
|
}
|
||||||
else if (lSg && aSg)
|
else if (lSg && aSg)
|
||||||
{ // Single/Single
|
{ // Single/Single
|
||||||
if ((vrfa == cm.CompFixedRef && vrfl == cm.CompVarRef[0]) ||
|
if ((vrfa == cm.CompFixedRef && vrfl == cm.CompVarRef[0]) ||
|
||||||
(vrfl == cm.CompFixedRef && vrfa == cm.CompVarRef[0]))
|
(vrfl == cm.CompFixedRef && vrfa == cm.CompVarRef[0]))
|
||||||
{
|
{
|
||||||
|
@ -119,7 +120,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (lSg || aSg)
|
else if (lSg || aSg)
|
||||||
{ // Single/Comp
|
{ // Single/Comp
|
||||||
sbyte vrfc = lSg ? vrfa : vrfl;
|
sbyte vrfc = lSg ? vrfa : vrfl;
|
||||||
sbyte rfs = aSg ? vrfa : vrfl;
|
sbyte rfs = aSg ? vrfa : vrfl;
|
||||||
if (vrfc == cm.CompVarRef[1] && rfs != cm.CompVarRef[1])
|
if (vrfc == cm.CompVarRef[1] && rfs != cm.CompVarRef[1])
|
||||||
|
@ -136,7 +137,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (vrfa == vrfl)
|
else if (vrfa == vrfl)
|
||||||
{ // Comp/Comp
|
{ // Comp/Comp
|
||||||
predContext = 4;
|
predContext = 4;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -146,7 +147,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull)
|
else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull)
|
||||||
{ // One edge available
|
{ // One edge available
|
||||||
ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value;
|
ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value;
|
||||||
|
|
||||||
if (!edgeMi.IsInterBlock())
|
if (!edgeMi.IsInterBlock())
|
||||||
|
@ -166,10 +167,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // No edges available (2)
|
{ // No edges available (2)
|
||||||
predContext = 2;
|
predContext = 2;
|
||||||
}
|
}
|
||||||
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
|
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
|
||||||
|
|
||||||
return predContext;
|
return predContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,16 +183,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
// left of the entries corresponding to real macroblocks.
|
// left of the entries corresponding to real macroblocks.
|
||||||
// The prediction flags in these dummy entries are initialized to 0.
|
// The prediction flags in these dummy entries are initialized to 0.
|
||||||
if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
|
if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
|
||||||
{ // Both edges available
|
{ // Both edges available
|
||||||
bool aboveIntra = !xd.AboveMi.Value.IsInterBlock();
|
bool aboveIntra = !xd.AboveMi.Value.IsInterBlock();
|
||||||
bool leftIntra = !xd.LeftMi.Value.IsInterBlock();
|
bool leftIntra = !xd.LeftMi.Value.IsInterBlock();
|
||||||
|
|
||||||
if (aboveIntra && leftIntra)
|
if (aboveIntra && leftIntra)
|
||||||
{ // Intra/Intra
|
{ // Intra/Intra
|
||||||
predContext = 2;
|
predContext = 2;
|
||||||
}
|
}
|
||||||
else if (aboveIntra || leftIntra)
|
else if (aboveIntra || leftIntra)
|
||||||
{ // Intra/Inter or Inter/Intra
|
{ // Intra/Inter or Inter/Intra
|
||||||
ref ModeInfo edgeMi = ref aboveIntra ? ref xd.LeftMi.Value : ref xd.AboveMi.Value;
|
ref ModeInfo edgeMi = ref aboveIntra ? ref xd.LeftMi.Value : ref xd.AboveMi.Value;
|
||||||
if (!edgeMi.HasSecondRef())
|
if (!edgeMi.HasSecondRef())
|
||||||
{
|
{
|
||||||
|
@ -203,7 +205,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // Inter/Inter
|
{ // Inter/Inter
|
||||||
bool aboveHasSecond = xd.AboveMi.Value.HasSecondRef();
|
bool aboveHasSecond = xd.AboveMi.Value.HasSecondRef();
|
||||||
bool leftHasSecond = xd.LeftMi.Value.HasSecondRef();
|
bool leftHasSecond = xd.LeftMi.Value.HasSecondRef();
|
||||||
sbyte above0 = xd.AboveMi.Value.RefFrame[0];
|
sbyte above0 = xd.AboveMi.Value.RefFrame[0];
|
||||||
|
@ -238,14 +240,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull)
|
else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull)
|
||||||
{ // One edge available
|
{ // One edge available
|
||||||
ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value;
|
ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value;
|
||||||
if (!edgeMi.IsInterBlock())
|
if (!edgeMi.IsInterBlock())
|
||||||
{ // Intra
|
{ // Intra
|
||||||
predContext = 2;
|
predContext = 2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // Inter
|
{ // Inter
|
||||||
if (!edgeMi.HasSecondRef())
|
if (!edgeMi.HasSecondRef())
|
||||||
{
|
{
|
||||||
predContext = 4 * (edgeMi.RefFrame[0] == Constants.LastFrame ? 1 : 0);
|
predContext = 4 * (edgeMi.RefFrame[0] == Constants.LastFrame ? 1 : 0);
|
||||||
|
@ -258,10 +260,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // No edges available
|
{ // No edges available
|
||||||
predContext = 2;
|
predContext = 2;
|
||||||
}
|
}
|
||||||
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
|
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
|
||||||
|
|
||||||
return predContext;
|
return predContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,16 +277,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
// left of the entries corresponding to real macroblocks.
|
// left of the entries corresponding to real macroblocks.
|
||||||
// The prediction flags in these dummy entries are initialized to 0.
|
// The prediction flags in these dummy entries are initialized to 0.
|
||||||
if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
|
if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
|
||||||
{ // Both edges available
|
{ // Both edges available
|
||||||
bool aboveIntra = !xd.AboveMi.Value.IsInterBlock();
|
bool aboveIntra = !xd.AboveMi.Value.IsInterBlock();
|
||||||
bool leftIntra = !xd.LeftMi.Value.IsInterBlock();
|
bool leftIntra = !xd.LeftMi.Value.IsInterBlock();
|
||||||
|
|
||||||
if (aboveIntra && leftIntra)
|
if (aboveIntra && leftIntra)
|
||||||
{ // Intra/Intra
|
{ // Intra/Intra
|
||||||
predContext = 2;
|
predContext = 2;
|
||||||
}
|
}
|
||||||
else if (aboveIntra || leftIntra)
|
else if (aboveIntra || leftIntra)
|
||||||
{ // Intra/Inter or Inter/Intra
|
{ // Intra/Inter or Inter/Intra
|
||||||
ref ModeInfo edgeMi = ref aboveIntra ? ref xd.LeftMi.Value : ref xd.AboveMi.Value;
|
ref ModeInfo edgeMi = ref aboveIntra ? ref xd.LeftMi.Value : ref xd.AboveMi.Value;
|
||||||
if (!edgeMi.HasSecondRef())
|
if (!edgeMi.HasSecondRef())
|
||||||
{
|
{
|
||||||
|
@ -303,7 +306,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // Inter/Inter
|
{ // Inter/Inter
|
||||||
bool aboveHasSecond = xd.AboveMi.Value.HasSecondRef();
|
bool aboveHasSecond = xd.AboveMi.Value.HasSecondRef();
|
||||||
bool leftHasSecond = xd.LeftMi.Value.HasSecondRef();
|
bool leftHasSecond = xd.LeftMi.Value.HasSecondRef();
|
||||||
sbyte above0 = xd.AboveMi.Value.RefFrame[0];
|
sbyte above0 = xd.AboveMi.Value.RefFrame[0];
|
||||||
|
@ -361,7 +364,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull)
|
else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull)
|
||||||
{ // One edge available
|
{ // One edge available
|
||||||
ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value;
|
ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value;
|
||||||
|
|
||||||
if (!edgeMi.IsInterBlock() || (edgeMi.RefFrame[0] == Constants.LastFrame && !edgeMi.HasSecondRef()))
|
if (!edgeMi.IsInterBlock() || (edgeMi.RefFrame[0] == Constants.LastFrame && !edgeMi.HasSecondRef()))
|
||||||
|
@ -379,10 +382,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // No edges available (2)
|
{ // No edges available (2)
|
||||||
predContext = 2;
|
predContext = 2;
|
||||||
}
|
}
|
||||||
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
|
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
|
||||||
|
|
||||||
return predContext;
|
return predContext;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
public const int MinQ = 0;
|
public const int MinQ = 0;
|
||||||
public const int MaxQ = 255;
|
public const int MaxQ = 255;
|
||||||
|
|
||||||
private static readonly short[] DcQlookup = new short[]
|
private static readonly short[] _dcQlookup = {
|
||||||
{
|
|
||||||
4, 8, 8, 9, 10, 11, 12, 12, 13, 14, 15, 16, 17, 18,
|
4, 8, 8, 9, 10, 11, 12, 12, 13, 14, 15, 16, 17, 18,
|
||||||
19, 19, 20, 21, 22, 23, 24, 25, 26, 26, 27, 28, 29, 30,
|
19, 19, 20, 21, 22, 23, 24, 25, 26, 26, 27, 28, 29, 30,
|
||||||
31, 32, 32, 33, 34, 35, 36, 37, 38, 38, 39, 40, 41, 42,
|
31, 32, 32, 33, 34, 35, 36, 37, 38, 38, 39, 40, 41, 42,
|
||||||
|
@ -32,8 +31,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
1184, 1232, 1282, 1336,
|
1184, 1232, 1282, 1336,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly short[] DcQlookup10 = new short[]
|
private static readonly short[] _dcQlookup10 = {
|
||||||
{
|
|
||||||
4, 9, 10, 13, 15, 17, 20, 22, 25, 28, 31, 34, 37,
|
4, 9, 10, 13, 15, 17, 20, 22, 25, 28, 31, 34, 37,
|
||||||
40, 43, 47, 50, 53, 57, 60, 64, 68, 71, 75, 78, 82,
|
40, 43, 47, 50, 53, 57, 60, 64, 68, 71, 75, 78, 82,
|
||||||
86, 90, 93, 97, 101, 105, 109, 113, 116, 120, 124, 128, 132,
|
86, 90, 93, 97, 101, 105, 109, 113, 116, 120, 124, 128, 132,
|
||||||
|
@ -56,8 +54,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
3953, 4089, 4236, 4394, 4559, 4737, 4929, 5130, 5347,
|
3953, 4089, 4236, 4394, 4559, 4737, 4929, 5130, 5347,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly short[] DcQlookup12 = new short[]
|
private static readonly short[] _dcQlookup12 = {
|
||||||
{
|
|
||||||
4, 12, 18, 25, 33, 41, 50, 60, 70, 80, 91,
|
4, 12, 18, 25, 33, 41, 50, 60, 70, 80, 91,
|
||||||
103, 115, 127, 140, 153, 166, 180, 194, 208, 222, 237,
|
103, 115, 127, 140, 153, 166, 180, 194, 208, 222, 237,
|
||||||
251, 266, 281, 296, 312, 327, 343, 358, 374, 390, 405,
|
251, 266, 281, 296, 312, 327, 343, 358, 374, 390, 405,
|
||||||
|
@ -84,8 +81,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
19718, 20521, 21387,
|
19718, 20521, 21387,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly short[] AcQlookup = new short[]
|
private static readonly short[] _acQlookup = {
|
||||||
{
|
|
||||||
4, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
|
4, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
|
||||||
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
|
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
|
||||||
33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
|
33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
|
||||||
|
@ -108,8 +104,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
1567, 1597, 1628, 1660, 1692, 1725, 1759, 1793, 1828,
|
1567, 1597, 1628, 1660, 1692, 1725, 1759, 1793, 1828,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly short[] AcQlookup10 = new short[]
|
private static readonly short[] _acQlookup10 = {
|
||||||
{
|
|
||||||
4, 9, 11, 13, 16, 18, 21, 24, 27, 30, 33, 37, 40,
|
4, 9, 11, 13, 16, 18, 21, 24, 27, 30, 33, 37, 40,
|
||||||
44, 48, 51, 55, 59, 63, 67, 71, 75, 79, 83, 88, 92,
|
44, 48, 51, 55, 59, 63, 67, 71, 75, 79, 83, 88, 92,
|
||||||
96, 100, 105, 109, 114, 118, 122, 127, 131, 136, 140, 145, 149,
|
96, 100, 105, 109, 114, 118, 122, 127, 131, 136, 140, 145, 149,
|
||||||
|
@ -132,8 +127,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
6268, 6388, 6512, 6640, 6768, 6900, 7036, 7172, 7312,
|
6268, 6388, 6512, 6640, 6768, 6900, 7036, 7172, 7312,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly short[] AcQlookup12 = new short[]
|
private static readonly short[] _acQlookup12 = {
|
||||||
{
|
|
||||||
4, 13, 19, 27, 35, 44, 54, 64, 75, 87, 99,
|
4, 13, 19, 27, 35, 44, 54, 64, 75, 87, 99,
|
||||||
112, 126, 139, 154, 168, 183, 199, 214, 230, 247, 263,
|
112, 126, 139, 154, 168, 183, 199, 214, 230, 247, 263,
|
||||||
280, 297, 314, 331, 349, 366, 384, 402, 420, 438, 456,
|
280, 297, 314, 331, 349, 366, 384, 402, 420, 438, 456,
|
||||||
|
@ -164,11 +158,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
switch (bitDepth)
|
switch (bitDepth)
|
||||||
{
|
{
|
||||||
case BitDepth.Bits8: return DcQlookup[Math.Clamp(qindex + delta, 0, MaxQ)];
|
case BitDepth.Bits8:
|
||||||
case BitDepth.Bits10: return DcQlookup10[Math.Clamp(qindex + delta, 0, MaxQ)];
|
return _dcQlookup[Math.Clamp(qindex + delta, 0, MaxQ)];
|
||||||
case BitDepth.Bits12: return DcQlookup12[Math.Clamp(qindex + delta, 0, MaxQ)];
|
case BitDepth.Bits10:
|
||||||
|
return _dcQlookup10[Math.Clamp(qindex + delta, 0, MaxQ)];
|
||||||
|
case BitDepth.Bits12:
|
||||||
|
return _dcQlookup12[Math.Clamp(qindex + delta, 0, MaxQ)];
|
||||||
default:
|
default:
|
||||||
Debug.Assert(false, "bit_depth should be VPX_BITS_8, VPX_BITS_10 or VPX_BITS_12");
|
Debug.Assert(false, "bit_depth should be VPX_BITS_8, VPX_BITS_10 or VPX_BITS_12");
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -177,11 +175,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
switch (bitDepth)
|
switch (bitDepth)
|
||||||
{
|
{
|
||||||
case BitDepth.Bits8: return AcQlookup[Math.Clamp(qindex + delta, 0, MaxQ)];
|
case BitDepth.Bits8:
|
||||||
case BitDepth.Bits10: return AcQlookup10[Math.Clamp(qindex + delta, 0, MaxQ)];
|
return _acQlookup[Math.Clamp(qindex + delta, 0, MaxQ)];
|
||||||
case BitDepth.Bits12: return AcQlookup12[Math.Clamp(qindex + delta, 0, MaxQ)];
|
case BitDepth.Bits10:
|
||||||
|
return _acQlookup10[Math.Clamp(qindex + delta, 0, MaxQ)];
|
||||||
|
case BitDepth.Bits12:
|
||||||
|
return _acQlookup12[Math.Clamp(qindex + delta, 0, MaxQ)];
|
||||||
default:
|
default:
|
||||||
Debug.Assert(false, "bit_depth should be VPX_BITS_8, VPX_BITS_10 or VPX_BITS_12");
|
Debug.Assert(false, "bit_depth should be VPX_BITS_8, VPX_BITS_10 or VPX_BITS_12");
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -192,12 +194,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
int data = seg.GetSegData(segmentId, SegLvlFeatures.SegLvlAltQ);
|
int data = seg.GetSegData(segmentId, SegLvlFeatures.SegLvlAltQ);
|
||||||
int segQIndex = seg.AbsDelta == Constants.SegmentAbsData ? data : baseQIndex + data;
|
int segQIndex = seg.AbsDelta == Constants.SegmentAbsData ? data : baseQIndex + data;
|
||||||
|
|
||||||
return Math.Clamp(segQIndex, 0, MaxQ);
|
return Math.Clamp(segQIndex, 0, MaxQ);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
return baseQIndex;
|
||||||
return baseQIndex;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,16 +84,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
|
|
||||||
private static Mv MiMvPredQ4(ref ModeInfo mi, int idx)
|
private static Mv MiMvPredQ4(ref ModeInfo mi, int idx)
|
||||||
{
|
{
|
||||||
Mv res = new Mv()
|
return new Mv
|
||||||
{
|
{
|
||||||
Row = (short)RoundMvCompQ4(
|
Row = (short)RoundMvCompQ4(
|
||||||
mi.Bmi[0].Mv[idx].Row + mi.Bmi[1].Mv[idx].Row +
|
mi.Bmi[0].Mv[idx].Row + mi.Bmi[1].Mv[idx].Row +
|
||||||
mi.Bmi[2].Mv[idx].Row + mi.Bmi[3].Mv[idx].Row),
|
mi.Bmi[2].Mv[idx].Row + mi.Bmi[3].Mv[idx].Row),
|
||||||
Col = (short)RoundMvCompQ4(
|
Col = (short)RoundMvCompQ4(
|
||||||
mi.Bmi[0].Mv[idx].Col + mi.Bmi[1].Mv[idx].Col +
|
mi.Bmi[0].Mv[idx].Col + mi.Bmi[1].Mv[idx].Col +
|
||||||
mi.Bmi[2].Mv[idx].Col + mi.Bmi[3].Mv[idx].Col)
|
mi.Bmi[2].Mv[idx].Col + mi.Bmi[3].Mv[idx].Col),
|
||||||
};
|
};
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int RoundMvCompQ2(int value)
|
private static int RoundMvCompQ2(int value)
|
||||||
|
@ -103,16 +102,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
|
|
||||||
private static Mv MiMvPredQ2(ref ModeInfo mi, int idx, int block0, int block1)
|
private static Mv MiMvPredQ2(ref ModeInfo mi, int idx, int block0, int block1)
|
||||||
{
|
{
|
||||||
Mv res = new Mv()
|
return new Mv
|
||||||
{
|
{
|
||||||
Row = (short)RoundMvCompQ2(
|
Row = (short)RoundMvCompQ2(
|
||||||
mi.Bmi[block0].Mv[idx].Row +
|
mi.Bmi[block0].Mv[idx].Row +
|
||||||
mi.Bmi[block1].Mv[idx].Row),
|
mi.Bmi[block1].Mv[idx].Row),
|
||||||
Col = (short)RoundMvCompQ2(
|
Col = (short)RoundMvCompQ2(
|
||||||
mi.Bmi[block0].Mv[idx].Col +
|
mi.Bmi[block0].Mv[idx].Col +
|
||||||
mi.Bmi[block1].Mv[idx].Col)
|
mi.Bmi[block1].Mv[idx].Col),
|
||||||
};
|
};
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Mv ClampMvToUmvBorderSb(ref MacroBlockD xd, ref Mv srcMv, int bw, int bh, int ssX, int ssY)
|
public static Mv ClampMvToUmvBorderSb(ref MacroBlockD xd, ref Mv srcMv, int bw, int bh, int ssX, int ssY)
|
||||||
|
@ -124,10 +122,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
int spelRight = spelLeft - SubpelShifts;
|
int spelRight = spelLeft - SubpelShifts;
|
||||||
int spelTop = (Constants.Vp9InterpExtend + bh) << SubpelBits;
|
int spelTop = (Constants.Vp9InterpExtend + bh) << SubpelBits;
|
||||||
int spelBottom = spelTop - SubpelShifts;
|
int spelBottom = spelTop - SubpelShifts;
|
||||||
Mv clampedMv = new Mv()
|
Mv clampedMv = new()
|
||||||
{
|
{
|
||||||
Row = (short)(srcMv.Row * (1 << (1 - ssY))),
|
Row = (short)(srcMv.Row * (1 << (1 - ssY))),
|
||||||
Col = (short)(srcMv.Col * (1 << (1 - ssX)))
|
Col = (short)(srcMv.Col * (1 << (1 - ssX))),
|
||||||
};
|
};
|
||||||
|
|
||||||
Debug.Assert(ssX <= 1);
|
Debug.Assert(ssX <= 1);
|
||||||
|
@ -145,14 +143,24 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
public static Mv AverageSplitMvs(ref MacroBlockDPlane pd, ref ModeInfo mi, int refr, int block)
|
public static Mv AverageSplitMvs(ref MacroBlockDPlane pd, ref ModeInfo mi, int refr, int block)
|
||||||
{
|
{
|
||||||
int ssIdx = ((pd.SubsamplingX > 0 ? 1 : 0) << 1) | (pd.SubsamplingY > 0 ? 1 : 0);
|
int ssIdx = ((pd.SubsamplingX > 0 ? 1 : 0) << 1) | (pd.SubsamplingY > 0 ? 1 : 0);
|
||||||
Mv res = new Mv();
|
Mv res = new();
|
||||||
switch (ssIdx)
|
switch (ssIdx)
|
||||||
{
|
{
|
||||||
case 0: res = mi.Bmi[block].Mv[refr]; break;
|
case 0:
|
||||||
case 1: res = MiMvPredQ2(ref mi, refr, block, block + 2); break;
|
res = mi.Bmi[block].Mv[refr];
|
||||||
case 2: res = MiMvPredQ2(ref mi, refr, block, block + 1); break;
|
break;
|
||||||
case 3: res = MiMvPredQ4(ref mi, refr); break;
|
case 1:
|
||||||
default: Debug.Assert(ssIdx <= 3 && ssIdx >= 0); break;
|
res = MiMvPredQ2(ref mi, refr, block, block + 2);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
res = MiMvPredQ2(ref mi, refr, block, block + 1);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
res = MiMvPredQ4(ref mi, refr);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Debug.Assert(ssIdx <= 3 && ssIdx >= 0);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -161,6 +169,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
int x = !sf.IsNull ? sf.Value.ScaleValueX(xOffset) : xOffset;
|
int x = !sf.IsNull ? sf.Value.ScaleValueX(xOffset) : xOffset;
|
||||||
int y = !sf.IsNull ? sf.Value.ScaleValueY(yOffset) : yOffset;
|
int y = !sf.IsNull ? sf.Value.ScaleValueY(yOffset) : yOffset;
|
||||||
|
|
||||||
return y * stride + x;
|
return y * stride + x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,18 +7,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
{
|
{
|
||||||
internal static class ReconIntra
|
internal static class ReconIntra
|
||||||
{
|
{
|
||||||
public static readonly TxType[] IntraModeToTxTypeLookup = new TxType[]
|
public static readonly TxType[] IntraModeToTxTypeLookup = {
|
||||||
{
|
TxType.DctDct, // DC
|
||||||
TxType.DctDct, // DC
|
TxType.AdstDct, // V
|
||||||
TxType.AdstDct, // V
|
TxType.DctAdst, // H
|
||||||
TxType.DctAdst, // H
|
TxType.DctDct, // D45
|
||||||
TxType.DctDct, // D45
|
TxType.AdstAdst, // D135
|
||||||
TxType.AdstAdst, // D135
|
TxType.AdstDct, // D117
|
||||||
TxType.AdstDct, // D117
|
TxType.DctAdst, // D153
|
||||||
TxType.DctAdst, // D153
|
TxType.DctAdst, // D207
|
||||||
TxType.DctAdst, // D207
|
TxType.AdstDct, // D63
|
||||||
TxType.AdstDct, // D63
|
TxType.AdstAdst, // TM
|
||||||
TxType.AdstAdst // TM
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private const int NeedLeft = 1 << 1;
|
private const int NeedLeft = 1 << 1;
|
||||||
|
@ -27,244 +26,240 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
|
|
||||||
private static ReadOnlySpan<byte> ExtendModes => new byte[]
|
private static ReadOnlySpan<byte> ExtendModes => new byte[]
|
||||||
{
|
{
|
||||||
NeedAbove | NeedLeft, // DC
|
NeedAbove | NeedLeft, // DC
|
||||||
NeedAbove, // V
|
NeedAbove, // V
|
||||||
NeedLeft, // H
|
NeedLeft, // H
|
||||||
NeedAboveRight, // D45
|
NeedAboveRight, // D45
|
||||||
NeedLeft | NeedAbove, // D135
|
NeedLeft | NeedAbove, // D135
|
||||||
NeedLeft | NeedAbove, // D117
|
NeedLeft | NeedAbove, // D117
|
||||||
NeedLeft | NeedAbove, // D153
|
NeedLeft | NeedAbove, // D153
|
||||||
NeedLeft, // D207
|
NeedLeft, // D207
|
||||||
NeedAboveRight, // D63
|
NeedAboveRight, // D63
|
||||||
NeedLeft | NeedAbove, // TM
|
NeedLeft | NeedAbove, // TM
|
||||||
};
|
};
|
||||||
|
|
||||||
private unsafe delegate void IntraPredFn(byte* dst, int stride, byte* above, byte* left);
|
private unsafe delegate void IntraPredFn(byte* dst, int stride, byte* above, byte* left);
|
||||||
|
|
||||||
private static unsafe IntraPredFn[][] _pred = new IntraPredFn[][]
|
private static readonly unsafe IntraPredFn[][] _pred = {
|
||||||
{
|
|
||||||
new IntraPredFn[]
|
new IntraPredFn[]
|
||||||
{
|
{
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null
|
null,
|
||||||
},
|
},
|
||||||
new IntraPredFn[]
|
new IntraPredFn[]
|
||||||
{
|
{
|
||||||
VPredictor4x4,
|
VPredictor4x4,
|
||||||
VPredictor8x8,
|
VPredictor8x8,
|
||||||
VPredictor16x16,
|
VPredictor16x16,
|
||||||
VPredictor32x32
|
VPredictor32x32,
|
||||||
},
|
},
|
||||||
new IntraPredFn[]
|
new IntraPredFn[]
|
||||||
{
|
{
|
||||||
HPredictor4x4,
|
HPredictor4x4,
|
||||||
HPredictor8x8,
|
HPredictor8x8,
|
||||||
HPredictor16x16,
|
HPredictor16x16,
|
||||||
HPredictor32x32
|
HPredictor32x32,
|
||||||
},
|
},
|
||||||
new IntraPredFn[]
|
new IntraPredFn[]
|
||||||
{
|
{
|
||||||
D45Predictor4x4,
|
D45Predictor4x4,
|
||||||
D45Predictor8x8,
|
D45Predictor8x8,
|
||||||
D45Predictor16x16,
|
D45Predictor16x16,
|
||||||
D45Predictor32x32
|
D45Predictor32x32,
|
||||||
},
|
},
|
||||||
new IntraPredFn[]
|
new IntraPredFn[]
|
||||||
{
|
{
|
||||||
D135Predictor4x4,
|
D135Predictor4x4,
|
||||||
D135Predictor8x8,
|
D135Predictor8x8,
|
||||||
D135Predictor16x16,
|
D135Predictor16x16,
|
||||||
D135Predictor32x32
|
D135Predictor32x32,
|
||||||
},
|
},
|
||||||
new IntraPredFn[]
|
new IntraPredFn[]
|
||||||
{
|
{
|
||||||
D117Predictor4x4,
|
D117Predictor4x4,
|
||||||
D117Predictor8x8,
|
D117Predictor8x8,
|
||||||
D117Predictor16x16,
|
D117Predictor16x16,
|
||||||
D117Predictor32x32
|
D117Predictor32x32,
|
||||||
},
|
},
|
||||||
new IntraPredFn[]
|
new IntraPredFn[]
|
||||||
{
|
{
|
||||||
D153Predictor4x4,
|
D153Predictor4x4,
|
||||||
D153Predictor8x8,
|
D153Predictor8x8,
|
||||||
D153Predictor16x16,
|
D153Predictor16x16,
|
||||||
D153Predictor32x32
|
D153Predictor32x32,
|
||||||
},
|
},
|
||||||
new IntraPredFn[]
|
new IntraPredFn[]
|
||||||
{
|
{
|
||||||
D207Predictor4x4,
|
D207Predictor4x4,
|
||||||
D207Predictor8x8,
|
D207Predictor8x8,
|
||||||
D207Predictor16x16,
|
D207Predictor16x16,
|
||||||
D207Predictor32x32
|
D207Predictor32x32,
|
||||||
},
|
},
|
||||||
new IntraPredFn[]
|
new IntraPredFn[]
|
||||||
{
|
{
|
||||||
D63Predictor4x4,
|
D63Predictor4x4,
|
||||||
D63Predictor8x8,
|
D63Predictor8x8,
|
||||||
D63Predictor16x16,
|
D63Predictor16x16,
|
||||||
D63Predictor32x32
|
D63Predictor32x32,
|
||||||
},
|
},
|
||||||
new IntraPredFn[]
|
new IntraPredFn[]
|
||||||
{
|
{
|
||||||
TMPredictor4x4,
|
TMPredictor4x4,
|
||||||
TMPredictor8x8,
|
TMPredictor8x8,
|
||||||
TMPredictor16x16,
|
TMPredictor16x16,
|
||||||
TMPredictor32x32
|
TMPredictor32x32,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
private static unsafe IntraPredFn[][][] _dcPred = new IntraPredFn[][][]
|
private static readonly unsafe IntraPredFn[][][] _dcPred = {
|
||||||
{
|
new[]
|
||||||
new IntraPredFn[][]
|
|
||||||
{
|
{
|
||||||
new IntraPredFn[]
|
new IntraPredFn[]
|
||||||
{
|
{
|
||||||
Dc128Predictor4x4,
|
Dc128Predictor4x4,
|
||||||
Dc128Predictor8x8,
|
Dc128Predictor8x8,
|
||||||
Dc128Predictor16x16,
|
Dc128Predictor16x16,
|
||||||
Dc128Predictor32x32
|
Dc128Predictor32x32,
|
||||||
},
|
},
|
||||||
new IntraPredFn[]
|
new IntraPredFn[]
|
||||||
{
|
{
|
||||||
DcTopPredictor4x4,
|
DcTopPredictor4x4,
|
||||||
DcTopPredictor8x8,
|
DcTopPredictor8x8,
|
||||||
DcTopPredictor16x16,
|
DcTopPredictor16x16,
|
||||||
DcTopPredictor32x32
|
DcTopPredictor32x32,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
new IntraPredFn[][]
|
new[]
|
||||||
{
|
{
|
||||||
new IntraPredFn[]
|
new IntraPredFn[]
|
||||||
{
|
{
|
||||||
DcLeftPredictor4x4,
|
DcLeftPredictor4x4,
|
||||||
DcLeftPredictor8x8,
|
DcLeftPredictor8x8,
|
||||||
DcLeftPredictor16x16,
|
DcLeftPredictor16x16,
|
||||||
DcLeftPredictor32x32
|
DcLeftPredictor32x32,
|
||||||
},
|
},
|
||||||
new IntraPredFn[]
|
new IntraPredFn[]
|
||||||
{
|
{
|
||||||
DcPredictor4x4,
|
DcPredictor4x4,
|
||||||
DcPredictor8x8,
|
DcPredictor8x8,
|
||||||
DcPredictor16x16,
|
DcPredictor16x16,
|
||||||
DcPredictor32x32
|
DcPredictor32x32,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
private unsafe delegate void IntraHighPredFn(ushort* dst, int stride, ushort* above, ushort* left, int bd);
|
private unsafe delegate void IntraHighPredFn(ushort* dst, int stride, ushort* above, ushort* left, int bd);
|
||||||
|
|
||||||
private static unsafe IntraHighPredFn[][] _predHigh = new IntraHighPredFn[][]
|
private static readonly unsafe IntraHighPredFn[][] _predHigh = {
|
||||||
{
|
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null
|
null,
|
||||||
},
|
},
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
HighbdVPredictor4x4,
|
HighbdVPredictor4x4,
|
||||||
HighbdVPredictor8x8,
|
HighbdVPredictor8x8,
|
||||||
HighbdVPredictor16x16,
|
HighbdVPredictor16x16,
|
||||||
HighbdVPredictor32x32
|
HighbdVPredictor32x32,
|
||||||
},
|
},
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
HighbdHPredictor4x4,
|
HighbdHPredictor4x4,
|
||||||
HighbdHPredictor8x8,
|
HighbdHPredictor8x8,
|
||||||
HighbdHPredictor16x16,
|
HighbdHPredictor16x16,
|
||||||
HighbdHPredictor32x32
|
HighbdHPredictor32x32,
|
||||||
},
|
},
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
HighbdD45Predictor4x4,
|
HighbdD45Predictor4x4,
|
||||||
HighbdD45Predictor8x8,
|
HighbdD45Predictor8x8,
|
||||||
HighbdD45Predictor16x16,
|
HighbdD45Predictor16x16,
|
||||||
HighbdD45Predictor32x32
|
HighbdD45Predictor32x32,
|
||||||
},
|
},
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
HighbdD135Predictor4x4,
|
HighbdD135Predictor4x4,
|
||||||
HighbdD135Predictor8x8,
|
HighbdD135Predictor8x8,
|
||||||
HighbdD135Predictor16x16,
|
HighbdD135Predictor16x16,
|
||||||
HighbdD135Predictor32x32
|
HighbdD135Predictor32x32,
|
||||||
},
|
},
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
HighbdD117Predictor4x4,
|
HighbdD117Predictor4x4,
|
||||||
HighbdD117Predictor8x8,
|
HighbdD117Predictor8x8,
|
||||||
HighbdD117Predictor16x16,
|
HighbdD117Predictor16x16,
|
||||||
HighbdD117Predictor32x32
|
HighbdD117Predictor32x32,
|
||||||
},
|
},
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
HighbdD153Predictor4x4,
|
HighbdD153Predictor4x4,
|
||||||
HighbdD153Predictor8x8,
|
HighbdD153Predictor8x8,
|
||||||
HighbdD153Predictor16x16,
|
HighbdD153Predictor16x16,
|
||||||
HighbdD153Predictor32x32
|
HighbdD153Predictor32x32,
|
||||||
},
|
},
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
HighbdD207Predictor4x4,
|
HighbdD207Predictor4x4,
|
||||||
HighbdD207Predictor8x8,
|
HighbdD207Predictor8x8,
|
||||||
HighbdD207Predictor16x16,
|
HighbdD207Predictor16x16,
|
||||||
HighbdD207Predictor32x32
|
HighbdD207Predictor32x32,
|
||||||
},
|
},
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
HighbdD63Predictor4x4,
|
HighbdD63Predictor4x4,
|
||||||
HighbdD63Predictor8x8,
|
HighbdD63Predictor8x8,
|
||||||
HighbdD63Predictor16x16,
|
HighbdD63Predictor16x16,
|
||||||
HighbdD63Predictor32x32
|
HighbdD63Predictor32x32,
|
||||||
},
|
},
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
HighbdTMPredictor4x4,
|
HighbdTMPredictor4x4,
|
||||||
HighbdTMPredictor8x8,
|
HighbdTMPredictor8x8,
|
||||||
HighbdTMPredictor16x16,
|
HighbdTMPredictor16x16,
|
||||||
HighbdTMPredictor32x32
|
HighbdTMPredictor32x32,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
private static unsafe IntraHighPredFn[][][] _dcPredHigh = new IntraHighPredFn[][][]
|
private static readonly unsafe IntraHighPredFn[][][] _dcPredHigh = {
|
||||||
{
|
new[]
|
||||||
new IntraHighPredFn[][]
|
|
||||||
{
|
{
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
HighbdDc128Predictor4x4,
|
HighbdDc128Predictor4x4,
|
||||||
HighbdDc128Predictor8x8,
|
HighbdDc128Predictor8x8,
|
||||||
HighbdDc128Predictor16x16,
|
HighbdDc128Predictor16x16,
|
||||||
HighbdDc128Predictor32x32
|
HighbdDc128Predictor32x32,
|
||||||
},
|
},
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
HighbdDcTopPredictor4x4,
|
HighbdDcTopPredictor4x4,
|
||||||
HighbdDcTopPredictor8x8,
|
HighbdDcTopPredictor8x8,
|
||||||
HighbdDcTopPredictor16x16,
|
HighbdDcTopPredictor16x16,
|
||||||
HighbdDcTopPredictor32x32
|
HighbdDcTopPredictor32x32,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
new IntraHighPredFn[][]
|
new[]
|
||||||
{
|
{
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
HighbdDcLeftPredictor4x4,
|
HighbdDcLeftPredictor4x4,
|
||||||
HighbdDcLeftPredictor8x8,
|
HighbdDcLeftPredictor8x8,
|
||||||
HighbdDcLeftPredictor16x16,
|
HighbdDcLeftPredictor16x16,
|
||||||
HighbdDcLeftPredictor32x32
|
HighbdDcLeftPredictor32x32,
|
||||||
},
|
},
|
||||||
new IntraHighPredFn[]
|
new IntraHighPredFn[]
|
||||||
{
|
{
|
||||||
HighbdDcPredictor4x4,
|
HighbdDcPredictor4x4,
|
||||||
HighbdDcPredictor8x8,
|
HighbdDcPredictor8x8,
|
||||||
HighbdDcPredictor16x16,
|
HighbdDcPredictor16x16,
|
||||||
HighbdDcPredictor32x32
|
HighbdDcPredictor32x32,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
private static unsafe void BuildIntraPredictorsHigh(
|
private static unsafe void BuildIntraPredictorsHigh(
|
||||||
|
@ -741,6 +736,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
plane);
|
plane);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
BuildIntraPredictors(
|
BuildIntraPredictors(
|
||||||
|
|
|
@ -5,6 +5,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
internal struct BModeInfo
|
internal struct BModeInfo
|
||||||
{
|
{
|
||||||
public PredictionMode Mode;
|
public PredictionMode Mode;
|
||||||
public Array2<Mv> Mv; // First, second inter predictor motion vectors
|
public Array2<Mv> Mv; // First, second inter predictor motion vectors
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,6 @@
|
||||||
Block64x32 = 11,
|
Block64x32 = 11,
|
||||||
Block64x64 = 12,
|
Block64x64 = 12,
|
||||||
BlockSizes = 13,
|
BlockSizes = 13,
|
||||||
BlockInvalid = BlockSizes
|
BlockInvalid = BlockSizes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,6 @@
|
||||||
internal enum FrameType
|
internal enum FrameType
|
||||||
{
|
{
|
||||||
KeyFrame = 0,
|
KeyFrame = 0,
|
||||||
InterFrame = 1
|
InterFrame = 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
// passed it can be loaded into vector registers.
|
// passed it can be loaded into vector registers.
|
||||||
internal struct LoopFilterThresh
|
internal struct LoopFilterThresh
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0649
|
#pragma warning disable CS0649 // Field is never assigned to
|
||||||
public Array16<byte> Mblim;
|
public Array16<byte> Mblim;
|
||||||
public Array16<byte> Lim;
|
public Array16<byte> Lim;
|
||||||
public Array16<byte> HevThr;
|
public Array16<byte> HevThr;
|
||||||
|
|
|
@ -54,7 +54,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
|
|
||||||
public Ptr<InternalErrorInfo> ErrorInfo;
|
public Ptr<InternalErrorInfo> ErrorInfo;
|
||||||
|
|
||||||
public int GetPredContextSegId()
|
public readonly int GetPredContextSegId()
|
||||||
{
|
{
|
||||||
sbyte aboveSip = !AboveMi.IsNull ? AboveMi.Value.SegIdPredicted : (sbyte)0;
|
sbyte aboveSip = !AboveMi.IsNull ? AboveMi.Value.SegIdPredicted : (sbyte)0;
|
||||||
sbyte leftSip = !LeftMi.IsNull ? LeftMi.Value.SegIdPredicted : (sbyte)0;
|
sbyte leftSip = !LeftMi.IsNull ? LeftMi.Value.SegIdPredicted : (sbyte)0;
|
||||||
|
@ -62,14 +62,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
return aboveSip + leftSip;
|
return aboveSip + leftSip;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetSkipContext()
|
public readonly int GetSkipContext()
|
||||||
{
|
{
|
||||||
int aboveSkip = !AboveMi.IsNull ? AboveMi.Value.Skip : 0;
|
int aboveSkip = !AboveMi.IsNull ? AboveMi.Value.Skip : 0;
|
||||||
int leftSkip = !LeftMi.IsNull ? LeftMi.Value.Skip : 0;
|
int leftSkip = !LeftMi.IsNull ? LeftMi.Value.Skip : 0;
|
||||||
|
|
||||||
return aboveSkip + leftSkip;
|
return aboveSkip + leftSkip;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetPredContextSwitchableInterp()
|
public readonly int GetPredContextSwitchableInterp()
|
||||||
{
|
{
|
||||||
// Note:
|
// Note:
|
||||||
// The mode info data structure has a one element border above and to the
|
// The mode info data structure has a one element border above and to the
|
||||||
|
@ -103,16 +104,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
// 1 - intra/inter, inter/intra
|
// 1 - intra/inter, inter/intra
|
||||||
// 2 - intra/--, --/intra
|
// 2 - intra/--, --/intra
|
||||||
// 3 - intra/intra
|
// 3 - intra/intra
|
||||||
public int GetIntraInterContext()
|
public readonly int GetIntraInterContext()
|
||||||
{
|
{
|
||||||
if (!AboveMi.IsNull && !LeftMi.IsNull)
|
if (!AboveMi.IsNull && !LeftMi.IsNull)
|
||||||
{ // Both edges available
|
{ // Both edges available
|
||||||
bool aboveIntra = !AboveMi.Value.IsInterBlock();
|
bool aboveIntra = !AboveMi.Value.IsInterBlock();
|
||||||
bool leftIntra = !LeftMi.Value.IsInterBlock();
|
bool leftIntra = !LeftMi.Value.IsInterBlock();
|
||||||
|
|
||||||
return leftIntra && aboveIntra ? 3 : (leftIntra || aboveIntra ? 1 : 0);
|
return leftIntra && aboveIntra ? 3 : (leftIntra || aboveIntra ? 1 : 0);
|
||||||
}
|
}
|
||||||
else if (!AboveMi.IsNull || !LeftMi.IsNull)
|
|
||||||
{ // One edge available
|
if (!AboveMi.IsNull || !LeftMi.IsNull)
|
||||||
|
{ // One edge available
|
||||||
return 2 * (!(!AboveMi.IsNull ? AboveMi.Value : LeftMi.Value).IsInterBlock() ? 1 : 0);
|
return 2 * (!(!AboveMi.IsNull ? AboveMi.Value : LeftMi.Value).IsInterBlock() ? 1 : 0);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -122,7 +125,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
// The mode info data structure has a one element border above and to the
|
// The mode info data structure has a one element border above and to the
|
||||||
// left of the entries corresponding to real blocks.
|
// left of the entries corresponding to real blocks.
|
||||||
// The prediction flags in these dummy entries are initialized to 0.
|
// The prediction flags in these dummy entries are initialized to 0.
|
||||||
public int GetTxSizeContext()
|
public readonly int GetTxSizeContext()
|
||||||
{
|
{
|
||||||
int maxTxSize = (int)Luts.MaxTxSizeLookup[(int)Mi[0].Value.SbType];
|
int maxTxSize = (int)Luts.MaxTxSizeLookup[(int)Mi[0].Value.SbType];
|
||||||
int aboveCtx = (!AboveMi.IsNull && AboveMi.Value.Skip == 0) ? (int)AboveMi.Value.TxSize : maxTxSize;
|
int aboveCtx = (!AboveMi.IsNull && AboveMi.Value.Skip == 0) ? (int)AboveMi.Value.TxSize : maxTxSize;
|
||||||
|
|
|
@ -11,7 +11,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
public TxSize TxSize;
|
public TxSize TxSize;
|
||||||
public sbyte Skip;
|
public sbyte Skip;
|
||||||
public sbyte SegmentId;
|
public sbyte SegmentId;
|
||||||
public sbyte SegIdPredicted; // Valid only when TemporalUpdate is enabled
|
public sbyte SegIdPredicted; // Valid only when TemporalUpdate is enabled
|
||||||
|
|
||||||
// Only for Intra blocks
|
// Only for Intra blocks
|
||||||
public PredictionMode UvMode;
|
public PredictionMode UvMode;
|
||||||
|
@ -32,10 +32,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
return SbType < BlockSize.Block8x8 ? Bmi[block].Mode : Mode;
|
return SbType < BlockSize.Block8x8 ? Bmi[block].Mode : Mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TxSize GetUvTxSize(ref MacroBlockDPlane pd)
|
public readonly TxSize GetUvTxSize(ref MacroBlockDPlane pd)
|
||||||
{
|
{
|
||||||
Debug.Assert(SbType < BlockSize.Block8x8 ||
|
Debug.Assert(SbType < BlockSize.Block8x8 ||
|
||||||
Luts.SsSizeLookup[(int)SbType][pd.SubsamplingX][pd.SubsamplingY] != BlockSize.BlockInvalid);
|
Luts.SsSizeLookup[(int)SbType][pd.SubsamplingX][pd.SubsamplingY] != BlockSize.BlockInvalid);
|
||||||
|
|
||||||
return Luts.UvTxsizeLookup[(int)SbType][(int)TxSize][pd.SubsamplingX][pd.SubsamplingY];
|
return Luts.UvTxsizeLookup[(int)SbType][(int)TxSize][pd.SubsamplingX][pd.SubsamplingY];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,9 +50,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
return RefFrame[1] > Constants.IntraFrame;
|
return RefFrame[1] > Constants.IntraFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly int[][] IdxNColumnToSubblock = new int[][]
|
private static readonly int[][] _idxNColumnToSubblock = {
|
||||||
{
|
new[] { 1, 2 }, new[] { 1, 3 }, new[] { 3, 2 }, new[] { 3, 3 },
|
||||||
new int[] { 1, 2 }, new int[] { 1, 3 }, new int[] { 3, 2 }, new int[] { 3, 3 }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// This function returns either the appropriate sub block or block's mv
|
// This function returns either the appropriate sub block or block's mv
|
||||||
|
@ -59,7 +59,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
public Mv GetSubBlockMv(int whichMv, int searchCol, int blockIdx)
|
public Mv GetSubBlockMv(int whichMv, int searchCol, int blockIdx)
|
||||||
{
|
{
|
||||||
return blockIdx >= 0 && SbType < BlockSize.Block8x8
|
return blockIdx >= 0 && SbType < BlockSize.Block8x8
|
||||||
? Bmi[IdxNColumnToSubblock[blockIdx][searchCol == 0 ? 1 : 0]].Mv[whichMv]
|
? Bmi[_idxNColumnToSubblock[blockIdx][searchCol == 0 ? 1 : 0]].Mv[whichMv]
|
||||||
: Mv[whichMv];
|
: Mv[whichMv];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,6 @@
|
||||||
BothNew = 4,
|
BothNew = 4,
|
||||||
IntraPlusNonIntra = 5,
|
IntraPlusNonIntra = 5,
|
||||||
BothIntra = 6,
|
BothIntra = 6,
|
||||||
InvalidCase = 9
|
InvalidCase = 9,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,13 +51,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10
|
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10,
|
||||||
};
|
};
|
||||||
|
|
||||||
public bool UseMvHp()
|
public readonly bool UseMvHp()
|
||||||
{
|
{
|
||||||
const int kMvRefThresh = 64; // Threshold for use of high-precision 1/8 mv
|
const int KMvRefThresh = 64; // Threshold for use of high-precision 1/8 mv
|
||||||
return Math.Abs(Row) < kMvRefThresh && Math.Abs(Col) < kMvRefThresh;
|
return Math.Abs(Row) < KMvRefThresh && Math.Abs(Col) < KMvRefThresh;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool MvJointVertical(MvJointType type)
|
public static bool MvJointVertical(MvJointType type)
|
||||||
|
@ -110,7 +110,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int b = c + Constants.Class0Bits - 1; // Number of bits
|
int b = c + Constants.Class0Bits - 1; // Number of bits
|
||||||
for (i = 0; i < b; ++i)
|
for (i = 0; i < b; ++i)
|
||||||
{
|
{
|
||||||
counts.Bits[comp][i][((d >> i) & 1)] += (uint)incr;
|
counts.Bits[comp][i][((d >> i) & 1)] += (uint)incr;
|
||||||
|
@ -121,19 +121,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private MvJointType GetMvJoint()
|
private readonly MvJointType GetMvJoint()
|
||||||
{
|
{
|
||||||
if (Row == 0)
|
if (Row == 0)
|
||||||
{
|
{
|
||||||
return Col == 0 ? MvJointType.MvJointZero : MvJointType.MvJointHnzvz;
|
return Col == 0 ? MvJointType.MvJointZero : MvJointType.MvJointHnzvz;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
return Col == 0 ? MvJointType.MvJointHzvnz : MvJointType.MvJointHnzvnz;
|
||||||
return Col == 0 ? MvJointType.MvJointHzvnz : MvJointType.MvJointHnzvnz;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void IncMv(Ptr<Vp9BackwardUpdates> counts)
|
internal readonly void IncMv(Ptr<Vp9BackwardUpdates> counts)
|
||||||
{
|
{
|
||||||
if (!counts.IsNull)
|
if (!counts.IsNull)
|
||||||
{
|
{
|
||||||
|
@ -158,7 +156,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
Row = (short)Math.Clamp(Row, minRow, maxRow);
|
Row = (short)Math.Clamp(Row, minRow, maxRow);
|
||||||
}
|
}
|
||||||
|
|
||||||
private const int MvBorder = (16 << 3); // Allow 16 pels in 1/8th pel units
|
private const int MvBorder = (16 << 3); // Allow 16 pels in 1/8th pel units
|
||||||
|
|
||||||
public void ClampMvRef(ref MacroBlockD xd)
|
public void ClampMvRef(ref MacroBlockD xd)
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,6 +7,6 @@
|
||||||
PartitionVert,
|
PartitionVert,
|
||||||
PartitionSplit,
|
PartitionSplit,
|
||||||
PartitionTypes,
|
PartitionTypes,
|
||||||
PartitionInvalid = PartitionTypes
|
PartitionInvalid = PartitionTypes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,6 @@
|
||||||
{
|
{
|
||||||
Y = 0,
|
Y = 0,
|
||||||
Uv = 1,
|
Uv = 1,
|
||||||
PlaneTypes
|
PlaneTypes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,20 +2,20 @@
|
||||||
{
|
{
|
||||||
internal enum PredictionMode
|
internal enum PredictionMode
|
||||||
{
|
{
|
||||||
DcPred = 0, // Average of above and left pixels
|
DcPred = 0, // Average of above and left pixels
|
||||||
VPred = 1, // Vertical
|
VPred = 1, // Vertical
|
||||||
HPred = 2, // Horizontal
|
HPred = 2, // Horizontal
|
||||||
D45Pred = 3, // Directional 45 deg = round(arctan(1 / 1) * 180 / pi)
|
D45Pred = 3, // Directional 45 deg = round(arctan(1 / 1) * 180 / pi)
|
||||||
D135Pred = 4, // Directional 135 deg = 180 - 45
|
D135Pred = 4, // Directional 135 deg = 180 - 45
|
||||||
D117Pred = 5, // Directional 117 deg = 180 - 63
|
D117Pred = 5, // Directional 117 deg = 180 - 63
|
||||||
D153Pred = 6, // Directional 153 deg = 180 - 27
|
D153Pred = 6, // Directional 153 deg = 180 - 27
|
||||||
D207Pred = 7, // Directional 207 deg = 180 + 27
|
D207Pred = 7, // Directional 207 deg = 180 + 27
|
||||||
D63Pred = 8, // Directional 63 deg = round(arctan(2 / 1) * 180 / pi)
|
D63Pred = 8, // Directional 63 deg = round(arctan(2 / 1) * 180 / pi)
|
||||||
TmPred = 9, // True-motion
|
TmPred = 9, // True-motion
|
||||||
NearestMv = 10,
|
NearestMv = 10,
|
||||||
NearMv = 11,
|
NearMv = 11,
|
||||||
ZeroMv = 12,
|
ZeroMv = 12,
|
||||||
NewMv = 13,
|
NewMv = 13,
|
||||||
MbModeCount = 14
|
MbModeCount = 14,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,6 @@
|
||||||
SingleReference = 0,
|
SingleReference = 0,
|
||||||
CompoundReference = 1,
|
CompoundReference = 1,
|
||||||
ReferenceModeSelect = 2,
|
ReferenceModeSelect = 2,
|
||||||
ReferenceModes = 3
|
ReferenceModes = 3,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,263 +38,255 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
int h,
|
int h,
|
||||||
int bd);
|
int bd);
|
||||||
|
|
||||||
private static readonly unsafe ConvolveFn[][][] PredictX16Y16 = new ConvolveFn[][][]
|
private static readonly unsafe ConvolveFn[][][] _predictX16Y16 = {
|
||||||
{
|
new[]
|
||||||
new ConvolveFn[][]
|
|
||||||
{
|
{
|
||||||
new ConvolveFn[]
|
new ConvolveFn[]
|
||||||
{
|
{
|
||||||
ConvolveCopy,
|
ConvolveCopy,
|
||||||
ConvolveAvg
|
ConvolveAvg,
|
||||||
},
|
},
|
||||||
new ConvolveFn[]
|
new ConvolveFn[]
|
||||||
{
|
{
|
||||||
Convolve8Vert,
|
Convolve8Vert,
|
||||||
Convolve8AvgVert
|
Convolve8AvgVert,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
new ConvolveFn[][]
|
new[]
|
||||||
{
|
{
|
||||||
new ConvolveFn[]
|
new ConvolveFn[]
|
||||||
{
|
{
|
||||||
Convolve8Horiz,
|
Convolve8Horiz,
|
||||||
Convolve8AvgHoriz
|
Convolve8AvgHoriz,
|
||||||
},
|
},
|
||||||
new ConvolveFn[]
|
new ConvolveFn[]
|
||||||
{
|
{
|
||||||
Convolve8,
|
Convolve8,
|
||||||
Convolve8Avg
|
Convolve8Avg,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly unsafe ConvolveFn[][][] PredictX16 = new ConvolveFn[][][]
|
private static readonly unsafe ConvolveFn[][][] _predictX16 = {
|
||||||
{
|
new[]
|
||||||
new ConvolveFn[][]
|
|
||||||
{
|
{
|
||||||
new ConvolveFn[]
|
new ConvolveFn[]
|
||||||
{
|
{
|
||||||
ScaledVert,
|
ScaledVert,
|
||||||
ScaledAvgVert
|
ScaledAvgVert,
|
||||||
},
|
},
|
||||||
new ConvolveFn[]
|
new ConvolveFn[]
|
||||||
{
|
{
|
||||||
ScaledVert,
|
ScaledVert,
|
||||||
ScaledAvgVert
|
ScaledAvgVert,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
new ConvolveFn[][]
|
new[]
|
||||||
{
|
{
|
||||||
new ConvolveFn[]
|
new ConvolveFn[]
|
||||||
{
|
{
|
||||||
Scaled2D,
|
Scaled2D,
|
||||||
ScaledAvg2D
|
ScaledAvg2D,
|
||||||
},
|
},
|
||||||
new ConvolveFn[]
|
new ConvolveFn[]
|
||||||
{
|
{
|
||||||
Scaled2D,
|
Scaled2D,
|
||||||
ScaledAvg2D
|
ScaledAvg2D,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly unsafe ConvolveFn[][][] PredictY16 = new ConvolveFn[][][]
|
private static readonly unsafe ConvolveFn[][][] _predictY16 = {
|
||||||
{
|
new[]
|
||||||
new ConvolveFn[][]
|
|
||||||
{
|
{
|
||||||
new ConvolveFn[]
|
new ConvolveFn[]
|
||||||
{
|
{
|
||||||
ScaledHoriz,
|
ScaledHoriz,
|
||||||
ScaledAvgHoriz
|
ScaledAvgHoriz,
|
||||||
},
|
},
|
||||||
new ConvolveFn[]
|
new ConvolveFn[]
|
||||||
{
|
{
|
||||||
Scaled2D,
|
Scaled2D,
|
||||||
ScaledAvg2D
|
ScaledAvg2D,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
new ConvolveFn[][]
|
new[]
|
||||||
{
|
{
|
||||||
new ConvolveFn[]
|
new ConvolveFn[]
|
||||||
{
|
{
|
||||||
ScaledHoriz,
|
ScaledHoriz,
|
||||||
ScaledAvgHoriz
|
ScaledAvgHoriz,
|
||||||
},
|
},
|
||||||
new ConvolveFn[]
|
new ConvolveFn[]
|
||||||
{
|
{
|
||||||
Scaled2D,
|
Scaled2D,
|
||||||
ScaledAvg2D
|
ScaledAvg2D,
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private static readonly unsafe ConvolveFn[][][] Predict = new ConvolveFn[][][]
|
|
||||||
{
|
|
||||||
new ConvolveFn[][]
|
|
||||||
{
|
|
||||||
new ConvolveFn[]
|
|
||||||
{
|
|
||||||
Scaled2D,
|
|
||||||
ScaledAvg2D
|
|
||||||
},
|
},
|
||||||
new ConvolveFn[]
|
|
||||||
{
|
|
||||||
Scaled2D,
|
|
||||||
ScaledAvg2D
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
new ConvolveFn[][]
|
};
|
||||||
|
|
||||||
|
private static readonly unsafe ConvolveFn[][][] _predict = {
|
||||||
|
new[]
|
||||||
{
|
{
|
||||||
new ConvolveFn[]
|
new ConvolveFn[]
|
||||||
{
|
{
|
||||||
Scaled2D,
|
Scaled2D,
|
||||||
ScaledAvg2D
|
ScaledAvg2D,
|
||||||
},
|
},
|
||||||
new ConvolveFn[]
|
new ConvolveFn[]
|
||||||
{
|
{
|
||||||
Scaled2D,
|
Scaled2D,
|
||||||
ScaledAvg2D
|
ScaledAvg2D,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new ConvolveFn[]
|
||||||
|
{
|
||||||
|
Scaled2D,
|
||||||
|
ScaledAvg2D,
|
||||||
|
},
|
||||||
|
new ConvolveFn[]
|
||||||
|
{
|
||||||
|
Scaled2D,
|
||||||
|
ScaledAvg2D,
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly unsafe HighbdConvolveFn[][][] HighbdPredictX16Y16 = new HighbdConvolveFn[][][]
|
private static readonly unsafe HighbdConvolveFn[][][] _highbdPredictX16Y16 = {
|
||||||
{
|
new[]
|
||||||
new HighbdConvolveFn[][]
|
|
||||||
{
|
{
|
||||||
new HighbdConvolveFn[]
|
new HighbdConvolveFn[]
|
||||||
{
|
{
|
||||||
HighbdConvolveCopy,
|
HighbdConvolveCopy,
|
||||||
HighbdConvolveAvg
|
HighbdConvolveAvg,
|
||||||
},
|
},
|
||||||
new HighbdConvolveFn[]
|
new HighbdConvolveFn[]
|
||||||
{
|
{
|
||||||
HighbdConvolve8Vert,
|
HighbdConvolve8Vert,
|
||||||
HighbdConvolve8AvgVert
|
HighbdConvolve8AvgVert,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
new HighbdConvolveFn[][]
|
new[]
|
||||||
{
|
{
|
||||||
new HighbdConvolveFn[]
|
new HighbdConvolveFn[]
|
||||||
{
|
{
|
||||||
HighbdConvolve8Horiz,
|
HighbdConvolve8Horiz,
|
||||||
HighbdConvolve8AvgHoriz
|
HighbdConvolve8AvgHoriz,
|
||||||
},
|
},
|
||||||
new HighbdConvolveFn[]
|
new HighbdConvolveFn[]
|
||||||
{
|
{
|
||||||
HighbdConvolve8,
|
HighbdConvolve8,
|
||||||
HighbdConvolve8Avg
|
HighbdConvolve8Avg,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly unsafe HighbdConvolveFn[][][] HighbdPredictX16 = new HighbdConvolveFn[][][]
|
private static readonly unsafe HighbdConvolveFn[][][] _highbdPredictX16 = {
|
||||||
{
|
new[]
|
||||||
new HighbdConvolveFn[][]
|
|
||||||
{
|
{
|
||||||
new HighbdConvolveFn[]
|
new HighbdConvolveFn[]
|
||||||
{
|
{
|
||||||
HighbdConvolve8Vert,
|
HighbdConvolve8Vert,
|
||||||
HighbdConvolve8AvgVert
|
HighbdConvolve8AvgVert,
|
||||||
},
|
},
|
||||||
new HighbdConvolveFn[]
|
new HighbdConvolveFn[]
|
||||||
{
|
{
|
||||||
HighbdConvolve8Vert,
|
HighbdConvolve8Vert,
|
||||||
HighbdConvolve8AvgVert
|
HighbdConvolve8AvgVert,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
new HighbdConvolveFn[][]
|
new[]
|
||||||
{
|
{
|
||||||
new HighbdConvolveFn[]
|
new HighbdConvolveFn[]
|
||||||
{
|
{
|
||||||
HighbdConvolve8,
|
HighbdConvolve8,
|
||||||
HighbdConvolve8Avg
|
HighbdConvolve8Avg,
|
||||||
},
|
},
|
||||||
new HighbdConvolveFn[]
|
new HighbdConvolveFn[]
|
||||||
{
|
{
|
||||||
HighbdConvolve8,
|
HighbdConvolve8,
|
||||||
HighbdConvolve8Avg
|
HighbdConvolve8Avg,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly unsafe HighbdConvolveFn[][][] HighbdPredictY16 = new HighbdConvolveFn[][][]
|
private static readonly unsafe HighbdConvolveFn[][][] _highbdPredictY16 = {
|
||||||
{
|
new[]
|
||||||
new HighbdConvolveFn[][]
|
|
||||||
{
|
{
|
||||||
new HighbdConvolveFn[]
|
new HighbdConvolveFn[]
|
||||||
{
|
{
|
||||||
HighbdConvolve8Horiz,
|
HighbdConvolve8Horiz,
|
||||||
HighbdConvolve8AvgHoriz
|
HighbdConvolve8AvgHoriz,
|
||||||
},
|
},
|
||||||
new HighbdConvolveFn[]
|
new HighbdConvolveFn[]
|
||||||
{
|
{
|
||||||
HighbdConvolve8,
|
HighbdConvolve8,
|
||||||
HighbdConvolve8Avg
|
HighbdConvolve8Avg,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
new HighbdConvolveFn[][]
|
new[]
|
||||||
{
|
{
|
||||||
new HighbdConvolveFn[]
|
new HighbdConvolveFn[]
|
||||||
{
|
{
|
||||||
HighbdConvolve8Horiz,
|
HighbdConvolve8Horiz,
|
||||||
HighbdConvolve8AvgHoriz
|
HighbdConvolve8AvgHoriz,
|
||||||
},
|
},
|
||||||
new HighbdConvolveFn[]
|
new HighbdConvolveFn[]
|
||||||
{
|
{
|
||||||
HighbdConvolve8,
|
HighbdConvolve8,
|
||||||
HighbdConvolve8Avg
|
HighbdConvolve8Avg,
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private static readonly unsafe HighbdConvolveFn[][][] HighbdPredict = new HighbdConvolveFn[][][]
|
|
||||||
{
|
|
||||||
new HighbdConvolveFn[][]
|
|
||||||
{
|
|
||||||
new HighbdConvolveFn[]
|
|
||||||
{
|
|
||||||
HighbdConvolve8,
|
|
||||||
HighbdConvolve8Avg
|
|
||||||
},
|
},
|
||||||
new HighbdConvolveFn[]
|
|
||||||
{
|
|
||||||
HighbdConvolve8,
|
|
||||||
HighbdConvolve8Avg
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
new HighbdConvolveFn[][]
|
};
|
||||||
|
|
||||||
|
private static readonly unsafe HighbdConvolveFn[][][] _highbdPredict = {
|
||||||
|
new[]
|
||||||
{
|
{
|
||||||
new HighbdConvolveFn[]
|
new HighbdConvolveFn[]
|
||||||
{
|
{
|
||||||
HighbdConvolve8,
|
HighbdConvolve8,
|
||||||
HighbdConvolve8Avg
|
HighbdConvolve8Avg,
|
||||||
},
|
},
|
||||||
new HighbdConvolveFn[]
|
new HighbdConvolveFn[]
|
||||||
{
|
{
|
||||||
HighbdConvolve8,
|
HighbdConvolve8,
|
||||||
HighbdConvolve8Avg
|
HighbdConvolve8Avg,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
new HighbdConvolveFn[]
|
||||||
|
{
|
||||||
|
HighbdConvolve8,
|
||||||
|
HighbdConvolve8Avg,
|
||||||
|
},
|
||||||
|
new HighbdConvolveFn[]
|
||||||
|
{
|
||||||
|
HighbdConvolve8,
|
||||||
|
HighbdConvolve8Avg,
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
public int XScaleFP; // Horizontal fixed point scale factor
|
public int XScaleFP; // Horizontal fixed point scale factor
|
||||||
public int YScaleFP; // Vertical fixed point scale factor
|
public int YScaleFP; // Vertical fixed point scale factor
|
||||||
public int XStepQ4;
|
public int XStepQ4;
|
||||||
public int YStepQ4;
|
public int YStepQ4;
|
||||||
|
|
||||||
public int ScaleValueX(int val)
|
public readonly int ScaleValueX(int val)
|
||||||
{
|
{
|
||||||
return IsScaled() ? ScaledX(val) : val;
|
return IsScaled() ? ScaledX(val) : val;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int ScaleValueY(int val)
|
public readonly int ScaleValueY(int val)
|
||||||
{
|
{
|
||||||
return IsScaled() ? ScaledY(val) : val;
|
return IsScaled() ? ScaledY(val) : val;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public unsafe void InterPredict(
|
public readonly unsafe void InterPredict(
|
||||||
int horiz,
|
int horiz,
|
||||||
int vert,
|
int vert,
|
||||||
int avg,
|
int avg,
|
||||||
|
@ -315,12 +307,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
if (YStepQ4 == 16)
|
if (YStepQ4 == 16)
|
||||||
{
|
{
|
||||||
// No scaling in either direction.
|
// No scaling in either direction.
|
||||||
PredictX16Y16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h);
|
_predictX16Y16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// No scaling in x direction. Must always scale in the y direction.
|
// 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);
|
_predictX16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -328,18 +320,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
if (YStepQ4 == 16)
|
if (YStepQ4 == 16)
|
||||||
{
|
{
|
||||||
// No scaling in the y direction. Must always scale in the x direction.
|
// 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);
|
_predictY16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Must always scale in both directions.
|
// Must always scale in both directions.
|
||||||
Predict[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h);
|
_predict[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public unsafe void HighbdInterPredict(
|
public readonly unsafe void HighbdInterPredict(
|
||||||
int horiz,
|
int horiz,
|
||||||
int vert,
|
int vert,
|
||||||
int avg,
|
int avg,
|
||||||
|
@ -361,12 +353,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
if (YStepQ4 == 16)
|
if (YStepQ4 == 16)
|
||||||
{
|
{
|
||||||
// No scaling in either direction.
|
// No scaling in either direction.
|
||||||
HighbdPredictX16Y16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd);
|
_highbdPredictX16Y16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// No scaling in x direction. Must always scale in the y direction.
|
// 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);
|
_highbdPredictX16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -374,22 +366,22 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
if (YStepQ4 == 16)
|
if (YStepQ4 == 16)
|
||||||
{
|
{
|
||||||
// No scaling in the y direction. Must always scale in the x direction.
|
// 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);
|
_highbdPredictY16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Must always scale in both directions.
|
// Must always scale in both directions.
|
||||||
HighbdPredict[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd);
|
_highbdPredict[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int ScaledX(int val)
|
private readonly int ScaledX(int val)
|
||||||
{
|
{
|
||||||
return (int)((long)val * XScaleFP >> RefScaleShift);
|
return (int)((long)val * XScaleFP >> RefScaleShift);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int ScaledY(int val)
|
private readonly int ScaledY(int val)
|
||||||
{
|
{
|
||||||
return (int)((long)val * YScaleFP >> RefScaleShift);
|
return (int)((long)val * YScaleFP >> RefScaleShift);
|
||||||
}
|
}
|
||||||
|
@ -407,20 +399,21 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
{
|
{
|
||||||
int xOffQ4 = ScaledX(x << SubpelBits) & SubpelMask;
|
int xOffQ4 = ScaledX(x << SubpelBits) & SubpelMask;
|
||||||
int yOffQ4 = ScaledY(y << SubpelBits) & SubpelMask;
|
int yOffQ4 = ScaledY(y << SubpelBits) & SubpelMask;
|
||||||
Mv32 res = new Mv32()
|
Mv32 res = new()
|
||||||
{
|
{
|
||||||
Row = ScaledY(mv.Row) + yOffQ4,
|
Row = ScaledY(mv.Row) + yOffQ4,
|
||||||
Col = ScaledX(mv.Col) + xOffQ4
|
Col = ScaledX(mv.Col) + xOffQ4,
|
||||||
};
|
};
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsValidScale()
|
public readonly bool IsValidScale()
|
||||||
{
|
{
|
||||||
return XScaleFP != RefInvalidScale && YScaleFP != RefInvalidScale;
|
return XScaleFP != RefInvalidScale && YScaleFP != RefInvalidScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsScaled()
|
public readonly bool IsScaled()
|
||||||
{
|
{
|
||||||
return IsValidScale() && (XScaleFP != RefNoScale || YScaleFP != RefNoScale);
|
return IsValidScale() && (XScaleFP != RefNoScale || YScaleFP != RefNoScale);
|
||||||
}
|
}
|
||||||
|
@ -439,6 +432,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
{
|
{
|
||||||
XScaleFP = RefInvalidScale;
|
XScaleFP = RefInvalidScale;
|
||||||
YScaleFP = RefInvalidScale;
|
YScaleFP = RefInvalidScale;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
{
|
{
|
||||||
internal enum SegLvlFeatures
|
internal enum SegLvlFeatures
|
||||||
{
|
{
|
||||||
SegLvlAltQ = 0, // Use alternate Quantizer ....
|
SegLvlAltQ = 0, // Use alternate Quantizer ....
|
||||||
SegLvlAltLf = 1, // Use alternate loop filter value...
|
SegLvlAltLf = 1, // Use alternate loop filter value...
|
||||||
SegLvlRefFrame = 2, // Optional Segment reference frame
|
SegLvlRefFrame = 2, // Optional Segment reference frame
|
||||||
SegLvlSkip = 3, // Optional Segment (0,0) + skip mode
|
SegLvlSkip = 3, // Optional Segment (0,0) + skip mode
|
||||||
SegLvlMax = 4 // Number of features supported
|
SegLvlMax = 4, // Number of features supported
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
{
|
{
|
||||||
internal struct Segmentation
|
internal struct Segmentation
|
||||||
{
|
{
|
||||||
private static readonly int[] SegFeatureDataSigned = new int[] { 1, 1, 0, 0 };
|
private static readonly int[] _segFeatureDataSigned = { 1, 1, 0, 0 };
|
||||||
private static readonly int[] SegFeatureDataMax = new int[] { QuantCommon.MaxQ, Vp9.LoopFilter.MaxLoopFilter, 3, 0 };
|
private static readonly int[] _segFeatureDataMax = { QuantCommon.MaxQ, Vp9.LoopFilter.MaxLoopFilter, 3, 0 };
|
||||||
|
|
||||||
public bool Enabled;
|
public bool Enabled;
|
||||||
public bool UpdateMap;
|
public bool UpdateMap;
|
||||||
|
@ -26,8 +26,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
|
|
||||||
public void ClearAllSegFeatures()
|
public void ClearAllSegFeatures()
|
||||||
{
|
{
|
||||||
MemoryMarshal.CreateSpan(ref FeatureData[0][0], 8 * 4).Fill(0);
|
MemoryMarshal.CreateSpan(ref FeatureData[0][0], 8 * 4).Clear();
|
||||||
MemoryMarshal.CreateSpan(ref FeatureMask[0], 8).Fill(0);
|
MemoryMarshal.CreateSpan(ref FeatureMask[0], 8).Clear();
|
||||||
AqAvOffset = 0;
|
AqAvOffset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,21 +38,21 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
|
|
||||||
internal static int FeatureDataMax(SegLvlFeatures featureId)
|
internal static int FeatureDataMax(SegLvlFeatures featureId)
|
||||||
{
|
{
|
||||||
return SegFeatureDataMax[(int)featureId];
|
return _segFeatureDataMax[(int)featureId];
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static int IsSegFeatureSigned(SegLvlFeatures featureId)
|
internal static int IsSegFeatureSigned(SegLvlFeatures featureId)
|
||||||
{
|
{
|
||||||
return SegFeatureDataSigned[(int)featureId];
|
return _segFeatureDataSigned[(int)featureId];
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void SetSegData(int segmentId, SegLvlFeatures featureId, int segData)
|
internal void SetSegData(int segmentId, SegLvlFeatures featureId, int segData)
|
||||||
{
|
{
|
||||||
Debug.Assert(segData <= SegFeatureDataMax[(int)featureId]);
|
Debug.Assert(segData <= _segFeatureDataMax[(int)featureId]);
|
||||||
if (segData < 0)
|
if (segData < 0)
|
||||||
{
|
{
|
||||||
Debug.Assert(SegFeatureDataSigned[(int)featureId] != 0);
|
Debug.Assert(_segFeatureDataSigned[(int)featureId] != 0);
|
||||||
Debug.Assert(-segData <= SegFeatureDataMax[(int)featureId]);
|
Debug.Assert(-segData <= _segFeatureDataMax[(int)featureId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
FeatureData[segmentId][(int)featureId] = (short)segData;
|
FeatureData[segmentId][(int)featureId] = (short)segData;
|
||||||
|
|
|
@ -11,11 +11,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
public ArrayPtr<byte> UBuffer;
|
public ArrayPtr<byte> UBuffer;
|
||||||
public ArrayPtr<byte> VBuffer;
|
public ArrayPtr<byte> VBuffer;
|
||||||
|
|
||||||
public unsafe Plane YPlane => new Plane((IntPtr)YBuffer.ToPointer(), YBuffer.Length);
|
public readonly unsafe Plane YPlane => new((IntPtr)YBuffer.ToPointer(), YBuffer.Length);
|
||||||
public unsafe Plane UPlane => new Plane((IntPtr)UBuffer.ToPointer(), UBuffer.Length);
|
public readonly unsafe Plane UPlane => new((IntPtr)UBuffer.ToPointer(), UBuffer.Length);
|
||||||
public unsafe Plane VPlane => new Plane((IntPtr)VBuffer.ToPointer(), VBuffer.Length);
|
public readonly unsafe Plane VPlane => new((IntPtr)VBuffer.ToPointer(), VBuffer.Length);
|
||||||
|
|
||||||
public FrameField Field => FrameField.Progressive;
|
public readonly FrameField Field => FrameField.Progressive;
|
||||||
|
|
||||||
public int Width { get; }
|
public int Width { get; }
|
||||||
public int Height { get; }
|
public int Height { get; }
|
||||||
|
@ -27,29 +27,31 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
public int UvAlignedWidth { get; }
|
public int UvAlignedWidth { get; }
|
||||||
public int UvAlignedHeight { get; }
|
public int UvAlignedHeight { get; }
|
||||||
public int UvStride { get; }
|
public int UvStride { get; }
|
||||||
public bool HighBd => false;
|
|
||||||
|
public bool HighBd { get; }
|
||||||
|
|
||||||
private readonly IntPtr _pointer;
|
private readonly IntPtr _pointer;
|
||||||
|
|
||||||
public Surface(int width, int height)
|
public Surface(int width, int height)
|
||||||
{
|
{
|
||||||
const int border = 32;
|
HighBd = false;
|
||||||
const int ssX = 1;
|
|
||||||
const int ssY = 1;
|
const int Border = 32;
|
||||||
const bool highbd = false;
|
const int SsX = 1;
|
||||||
|
const int SsY = 1;
|
||||||
|
|
||||||
int alignedWidth = (width + 7) & ~7;
|
int alignedWidth = (width + 7) & ~7;
|
||||||
int alignedHeight = (height + 7) & ~7;
|
int alignedHeight = (height + 7) & ~7;
|
||||||
int yStride = ((alignedWidth + 2 * border) + 31) & ~31;
|
int yStride = ((alignedWidth + 2 * Border) + 31) & ~31;
|
||||||
int yplaneSize = (alignedHeight + 2 * border) * yStride;
|
int yplaneSize = (alignedHeight + 2 * Border) * yStride;
|
||||||
int uvWidth = alignedWidth >> ssX;
|
int uvWidth = alignedWidth >> SsX;
|
||||||
int uvHeight = alignedHeight >> ssY;
|
int uvHeight = alignedHeight >> SsY;
|
||||||
int uvStride = yStride >> ssX;
|
int uvStride = yStride >> SsX;
|
||||||
int uvBorderW = border >> ssX;
|
int uvBorderW = Border >> SsX;
|
||||||
int uvBorderH = border >> ssY;
|
int uvBorderH = Border >> SsY;
|
||||||
int uvplaneSize = (uvHeight + 2 * uvBorderH) * uvStride;
|
int uvplaneSize = (uvHeight + 2 * uvBorderH) * uvStride;
|
||||||
|
|
||||||
int frameSize = (highbd ? 2 : 1) * (yplaneSize + 2 * uvplaneSize);
|
int frameSize = (HighBd ? 2 : 1) * (yplaneSize + 2 * uvplaneSize);
|
||||||
|
|
||||||
IntPtr pointer = Marshal.AllocHGlobal(frameSize);
|
IntPtr pointer = Marshal.AllocHGlobal(frameSize);
|
||||||
_pointer = pointer;
|
_pointer = pointer;
|
||||||
|
@ -58,23 +60,23 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
AlignedWidth = alignedWidth;
|
AlignedWidth = alignedWidth;
|
||||||
AlignedHeight = alignedHeight;
|
AlignedHeight = alignedHeight;
|
||||||
Stride = yStride;
|
Stride = yStride;
|
||||||
UvWidth = (width + ssX) >> ssX;
|
UvWidth = (width + SsX) >> SsX;
|
||||||
UvHeight = (height + ssY) >> ssY;
|
UvHeight = (height + SsY) >> SsY;
|
||||||
UvAlignedWidth = uvWidth;
|
UvAlignedWidth = uvWidth;
|
||||||
UvAlignedHeight = uvHeight;
|
UvAlignedHeight = uvHeight;
|
||||||
UvStride = uvStride;
|
UvStride = uvStride;
|
||||||
|
|
||||||
ArrayPtr<byte> NewPlane(int start, int size, int border)
|
ArrayPtr<byte> NewPlane(int start, int size, int planeBorder)
|
||||||
{
|
{
|
||||||
return new ArrayPtr<byte>(pointer + start + border, size - border);
|
return new ArrayPtr<byte>(pointer + start + planeBorder, size - planeBorder);
|
||||||
}
|
}
|
||||||
|
|
||||||
YBuffer = NewPlane(0, yplaneSize, (border * yStride) + border);
|
YBuffer = NewPlane(0, yplaneSize, (Border * yStride) + Border);
|
||||||
UBuffer = NewPlane(yplaneSize, uvplaneSize, (uvBorderH * uvStride) + uvBorderW);
|
UBuffer = NewPlane(yplaneSize, uvplaneSize, (uvBorderH * uvStride) + uvBorderW);
|
||||||
VBuffer = NewPlane(yplaneSize + uvplaneSize, uvplaneSize, (uvBorderH * uvStride) + uvBorderW);
|
VBuffer = NewPlane(yplaneSize + uvplaneSize, uvplaneSize, (uvBorderH * uvStride) + uvBorderW);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public readonly void Dispose()
|
||||||
{
|
{
|
||||||
Marshal.FreeHGlobal(_pointer);
|
Marshal.FreeHGlobal(_pointer);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
{
|
{
|
||||||
int sbCols = MiColsAlignedToSb(mis) >> Constants.MiBlockSizeLog2;
|
int sbCols = MiColsAlignedToSb(mis) >> Constants.MiBlockSizeLog2;
|
||||||
int offset = ((idx * sbCols) >> log2) << Constants.MiBlockSizeLog2;
|
int offset = ((idx * sbCols) >> log2) << Constants.MiBlockSizeLog2;
|
||||||
|
|
||||||
return Math.Min(offset, mis);
|
return Math.Min(offset, mis);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +45,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
|
|
||||||
// Checks that the given miRow, miCol and search point
|
// Checks that the given miRow, miCol and search point
|
||||||
// are inside the borders of the tile.
|
// are inside the borders of the tile.
|
||||||
public bool IsInside(int miCol, int miRow, int miRows, ref Position miPos)
|
public readonly bool IsInside(int miCol, int miRow, int miRows, ref Position miPos)
|
||||||
{
|
{
|
||||||
return !(miRow + miPos.Row < 0 ||
|
return !(miRow + miPos.Row < 0 ||
|
||||||
miCol + miPos.Col < MiColStart ||
|
miCol + miPos.Col < MiColStart ||
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
{
|
{
|
||||||
public enum TxMode
|
public enum TxMode
|
||||||
{
|
{
|
||||||
Only4X4 = 0, // Only 4x4 transform used
|
Only4X4 = 0, // Only 4x4 transform used
|
||||||
Allow8X8 = 1, // Allow block transform size up to 8x8
|
Allow8X8 = 1, // Allow block transform size up to 8x8
|
||||||
Allow16X16 = 2, // Allow block transform size up to 16x16
|
Allow16X16 = 2, // Allow block transform size up to 16x16
|
||||||
Allow32X32 = 3, // Allow block transform size up to 32x32
|
Allow32X32 = 3, // Allow block transform size up to 32x32
|
||||||
TxModeSelect = 4, // Transform specified for each block
|
TxModeSelect = 4, // Transform specified for each block
|
||||||
TxModes = 5
|
TxModes = 5,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
{
|
{
|
||||||
public enum TxSize
|
public enum TxSize
|
||||||
{
|
{
|
||||||
Tx4x4 = 0, // 4x4 transform
|
Tx4x4 = 0, // 4x4 transform
|
||||||
Tx8x8 = 1, // 8x8 transform
|
Tx8x8 = 1, // 8x8 transform
|
||||||
Tx16x16 = 2, // 16x16 transform
|
Tx16x16 = 2, // 16x16 transform
|
||||||
Tx32x32 = 3, // 32x32 transform
|
Tx32x32 = 3, // 32x32 transform
|
||||||
TxSizes = 4
|
TxSizes = 4,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
{
|
{
|
||||||
internal enum TxType
|
internal enum TxType
|
||||||
{
|
{
|
||||||
DctDct = 0, // DCT in both horizontal and vertical
|
DctDct = 0, // DCT in both horizontal and vertical
|
||||||
AdstDct = 1, // ADST in vertical, DCT in horizontal
|
AdstDct = 1, // ADST in vertical, DCT in horizontal
|
||||||
DctAdst = 2, // DCT in vertical, ADST in horizontal
|
DctAdst = 2, // DCT in vertical, ADST in horizontal
|
||||||
AdstAdst = 3, // ADST in both directions
|
AdstAdst = 3, // ADST in both directions
|
||||||
TxTypes = 4
|
TxTypes = 4,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,7 +88,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
public ArrayPtr<sbyte> AboveSegContext;
|
public ArrayPtr<sbyte> AboveSegContext;
|
||||||
public ArrayPtr<sbyte> AboveContext;
|
public ArrayPtr<sbyte> AboveContext;
|
||||||
|
|
||||||
public bool FrameIsIntraOnly()
|
public readonly bool FrameIsIntraOnly()
|
||||||
{
|
{
|
||||||
return FrameType == FrameType.KeyFrame || IntraOnly;
|
return FrameType == FrameType.KeyFrame || IntraOnly;
|
||||||
}
|
}
|
||||||
|
@ -132,7 +132,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
TileWorkerData = allocator.Allocate<TileWorkerData>(tileCols * tileRows + (maxThreads > 1 ? maxThreads : 0));
|
TileWorkerData = allocator.Allocate<TileWorkerData>(tileCols * tileRows + (maxThreads > 1 ? maxThreads : 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void FreeTileWorkerData(MemoryAllocator allocator)
|
public readonly void FreeTileWorkerData(MemoryAllocator allocator)
|
||||||
{
|
{
|
||||||
allocator.Free(TileWorkerData);
|
allocator.Free(TileWorkerData);
|
||||||
}
|
}
|
||||||
|
@ -257,7 +257,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetPartitionProbs(ref MacroBlockD xd)
|
private readonly void SetPartitionProbs(ref MacroBlockD xd)
|
||||||
{
|
{
|
||||||
xd.PartitionProbs = FrameIsIntraOnly()
|
xd.PartitionProbs = FrameIsIntraOnly()
|
||||||
? new ArrayPtr<Array3<byte>>(ref Fc.Value.KfPartitionProb[0], 16)
|
? new ArrayPtr<Array3<byte>>(ref Fc.Value.KfPartitionProb[0], 16)
|
||||||
|
@ -293,7 +293,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
|
|
||||||
public void SetupSegmentationDequant()
|
public void SetupSegmentationDequant()
|
||||||
{
|
{
|
||||||
const BitDepth bitDepth = BitDepth.Bits8; // TODO: Configurable
|
const BitDepth BitDepth = BitDepth.Bits8; // TODO: Configurable
|
||||||
// Build y/uv dequant values based on segmentation.
|
// Build y/uv dequant values based on segmentation.
|
||||||
if (Seg.Enabled)
|
if (Seg.Enabled)
|
||||||
{
|
{
|
||||||
|
@ -301,10 +301,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
for (i = 0; i < Constants.MaxSegments; ++i)
|
for (i = 0; i < Constants.MaxSegments; ++i)
|
||||||
{
|
{
|
||||||
int qIndex = QuantCommon.GetQIndex(ref Seg, i, BaseQindex);
|
int qIndex = QuantCommon.GetQIndex(ref Seg, i, BaseQindex);
|
||||||
YDequant[i][0] = QuantCommon.DcQuant(qIndex, YDcDeltaQ, bitDepth);
|
YDequant[i][0] = QuantCommon.DcQuant(qIndex, YDcDeltaQ, BitDepth);
|
||||||
YDequant[i][1] = QuantCommon.AcQuant(qIndex, 0, bitDepth);
|
YDequant[i][1] = QuantCommon.AcQuant(qIndex, 0, BitDepth);
|
||||||
UvDequant[i][0] = QuantCommon.DcQuant(qIndex, UvDcDeltaQ, bitDepth);
|
UvDequant[i][0] = QuantCommon.DcQuant(qIndex, UvDcDeltaQ, BitDepth);
|
||||||
UvDequant[i][1] = QuantCommon.AcQuant(qIndex, UvAcDeltaQ, bitDepth);
|
UvDequant[i][1] = QuantCommon.AcQuant(qIndex, UvAcDeltaQ, BitDepth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -312,10 +312,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||||
int qIndex = BaseQindex;
|
int qIndex = BaseQindex;
|
||||||
// When segmentation is disabled, only the first value is used. The
|
// When segmentation is disabled, only the first value is used. The
|
||||||
// remaining are don't cares.
|
// remaining are don't cares.
|
||||||
YDequant[0][0] = QuantCommon.DcQuant(qIndex, YDcDeltaQ, bitDepth);
|
YDequant[0][0] = QuantCommon.DcQuant(qIndex, YDcDeltaQ, BitDepth);
|
||||||
YDequant[0][1] = QuantCommon.AcQuant(qIndex, 0, bitDepth);
|
YDequant[0][1] = QuantCommon.AcQuant(qIndex, 0, BitDepth);
|
||||||
UvDequant[0][0] = QuantCommon.DcQuant(qIndex, UvDcDeltaQ, bitDepth);
|
UvDequant[0][0] = QuantCommon.DcQuant(qIndex, UvDcDeltaQ, BitDepth);
|
||||||
UvDequant[0][1] = QuantCommon.AcQuant(qIndex, UvAcDeltaQ, bitDepth);
|
UvDequant[0][1] = QuantCommon.AcQuant(qIndex, UvAcDeltaQ, BitDepth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue