0
0
Fork 0

[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:
TSRBerry 2023-06-28 09:26:39 +02:00 committed by GitHub
parent 9becbd7d72
commit 6aa8d71588
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
41 changed files with 1240 additions and 1207 deletions

View file

@ -51,6 +51,6 @@
/*!\brief An iterator reached the end of list.
*
*/
CodecListEnd
CodecListEnd,
}
}

View file

@ -20,7 +20,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common
{
10 => (ushort)Math.Clamp(val, 0, 1023),
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)
{
Debug.Assert(n != 0);
return 31 ^ BitOperations.LeadingZeroCount(n);
}

View file

@ -16,7 +16,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common
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
{
@ -91,4 +91,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common
}
}
}
}
}

View file

@ -14,13 +14,13 @@
public const int MaxRefFrames = 4;
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 MiBlockSize = 1 << MiBlockSizeLog2; // mi-units per max block
public const int MiSize = 1 << MiSizeLog2; // pixels per mi-unit
public const int MiBlockSize = 1 << MiBlockSizeLog2; // mi-units per max block
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 */
public const int MaxMvRefCandidates = 2;
@ -48,9 +48,9 @@
public const int MvLow = -(1 << MvInUseBits);
// Coefficient token alphabet
public const int ZeroToken = 0; // 0 Extra Bits 0+0
public const int OneToken = 1; // 1 Extra Bits 0+1
public const int TwoToken = 2; // 2 Extra Bits 0+1
public const int ZeroToken = 0; // 0 Extra Bits 0+0
public const int OneToken = 1; // 1 Extra Bits 0+1
public const int TwoToken = 2; // 2 Extra Bits 0+1
public const int PivotNode = 2;

View file

@ -9,7 +9,6 @@ using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Mv = Ryujinx.Graphics.Nvdec.Vp9.Types.Mv;
namespace Ryujinx.Graphics.Nvdec.Vp9
{
@ -48,7 +47,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
case TxSize.Tx32x32:
Idct.HighbdIdct32x32Add(dqcoeff.AsSpan(), dst16, stride, eob, xd.Bd);
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)
{
case TxSize.Tx4x4: Idct.Idct4x4Add(dqcoeff.AsSpan(), dst, stride, eob); break;
case TxSize.Tx8x8: 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;
case TxSize.Tx4x4:
Idct.Idct4x4Add(dqcoeff.AsSpan(), dst, stride, eob);
break;
case TxSize.Tx8x8:
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)
{
dqcoeff.AsSpan().Slice(0, 4 * (4 << (int)txSize)).Fill(0);
dqcoeff.AsSpan()[..(4 * (4 << (int)txSize))].Clear();
}
else if (txSize == TxSize.Tx32x32 && eob <= 34)
{
dqcoeff.AsSpan().Slice(0, 256).Fill(0);
dqcoeff.AsSpan()[..256].Clear();
}
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:
Idct.HighbdIdct32x32Add(dqcoeff.AsSpan(), dst16, stride, eob, xd.Bd);
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)
{
case TxSize.Tx4x4: Idct.Iht4x4Add(txType, dqcoeff.AsSpan(), dst, stride, eob); break;
case TxSize.Tx8x8: 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;
case TxSize.Tx4x4:
Idct.Iht4x4Add(txType, dqcoeff.AsSpan(), dst, stride, eob);
break;
case TxSize.Tx8x8:
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)
{
dqcoeff.AsSpan().Slice(0, 4 * (4 << (int)txSize)).Fill(0);
dqcoeff.AsSpan()[..(4 * (4 << (int)txSize))].Clear();
}
else if (txSize == TxSize.Tx32x32 && eob <= 34)
{
dqcoeff.AsSpan().Slice(0, 256).Fill(0);
dqcoeff.AsSpan()[..256].Clear();
}
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;
int dstOffset = 4 * row * pd.Dst.Stride + 4 * col;
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)
{
@ -223,7 +246,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
ref MacroBlockDPlane pd = ref xd.Plane[plane];
var sc = Luts.Vp9DefaultScanOrders[(int)txSize];
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)
{
@ -589,9 +612,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
refr,
xs,
ys);
return;
}
}
if (xd.CurBuf.HighBd)
{
ReconInter.HighbdInterPredictor(
@ -793,6 +818,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
xd.SetMiRowCol(ref tile, miRow, bh, miCol, bw, cm.MiRows, cm.MiCols);
ReconInter.SetupDstPlanes(ref xd.Plane, ref xd.CurBuf, miRow, miCol);
return ref xd.Mi[0].Value;
}
@ -893,7 +919,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
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
// of block sizes larger than the current one to be one, and partition
// bits of smaller block sizes to be zero.
aboveCtx.Slice(0, bw).Fill(Luts.PartitionContextLookup[(int)subsize].Above);
leftCtx.Slice(0, bw).Fill(Luts.PartitionContextLookup[(int)subsize].Left);
aboveCtx[..bw].Fill(Luts.PartitionContextLookup[(int)subsize].Above);
leftCtx[..bw].Fill(Luts.PartitionContextLookup[(int)subsize].Left);
}
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 + hbs, subsize, n8x8L2);
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 tileCols = 1 << cm.Log2TileCols;
int tileRows = 1 << cm.Log2TileRows;
Array4<Array64<TileBuffer>> tileBuffers = new Array4<Array64<TileBuffer>>();
Array4<Array64<TileBuffer>> tileBuffers = new();
int tileRow, tileCol;
int miRow, miCol;
@ -1168,7 +1196,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
for (tileRow = 0; tileRow < tileRows; ++tileRow)
{
TileInfo tile = new TileInfo();
TileInfo tile = new();
tile.SetRow(ref cm, tileRow);
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);
tileData.DataEnd = bitReaderEnd;
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;
@ -1250,8 +1279,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
Debug.Assert(tileCols <= (1 << 6));
Debug.Assert(tileRows == 1);
cm.AboveContext.AsSpan().Fill(0);
cm.AboveSegContext.AsSpan().Fill(0);
cm.AboveContext.AsSpan().Clear();
cm.AboveSegContext.AsSpan().Clear();
for (n = 0; n < numWorkers; ++n)
{
@ -1262,17 +1291,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
tileData.Counts = new Vp9BackwardUpdates();
}
Array64<TileBuffer> tileBuffers = new Array64<TileBuffer>();
Array64<TileBuffer> tileBuffers = new();
GetTileBuffers(ref cm, data, tileCols, ref tileBuffers);
tileBuffers.AsSpan().Slice(0, tileCols).Sort(CompareTileBuffers);
tileBuffers.AsSpan()[..tileCols].Sort(CompareTileBuffers);
if (numWorkers == tileCols)
{
TileBuffer largest = tileBuffers[0];
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;
}
else
@ -1307,9 +1336,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
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];
@ -1335,6 +1364,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
Debug.Assert(!bitReaderEnd.IsNull || cm.Mb.Corrupted);
return bitReaderEnd;
}

View file

@ -5,8 +5,6 @@ using Ryujinx.Graphics.Video;
using System;
using System.Diagnostics;
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
{
@ -61,10 +59,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{
switch (maxTxSize)
{
case TxSize.Tx8x8: return fc.Tx8x8Prob[ctx].AsSpan();
case TxSize.Tx16x16: return fc.Tx16x16Prob[ctx].AsSpan();
case TxSize.Tx32x32: return fc.Tx32x32Prob[ctx].AsSpan();
default: Debug.Assert(false, "Invalid maxTxSize."); return ReadOnlySpan<byte>.Empty;
case TxSize.Tx8x8:
return fc.Tx8x8Prob[ctx].AsSpan();
case TxSize.Tx16x16:
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)
{
case TxSize.Tx8x8: return counts.Tx8x8[ctx].AsSpan();
case TxSize.Tx16x16: return counts.Tx16x16[ctx].AsSpan();
case TxSize.Tx32x32: return counts.Tx32x32[ctx].AsSpan();
default: Debug.Assert(false, "Invalid maxTxSize."); return Span<uint>.Empty;
case TxSize.Tx8x8:
return counts.Tx8x8[ctx].AsSpan();
case TxSize.Tx16x16:
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);
}
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)
@ -129,6 +137,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
Debug.Assert(segmentId >= 0 && segmentId < Constants.MaxSegments);
return segmentId;
}
@ -173,17 +182,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
if (!seg.Enabled)
{
return 0; // Default for disabled segmentation
return 0; // Default for disabled segmentation
}
if (!seg.UpdateMap)
{
CopySegmentId(ref cm, cm.LastFrameSegMap, cm.CurrentFrameSegMap, miOffset, xMis, yMis);
return 0;
}
segmentId = ReadSegmentId(ref r, ref cm.Fc.Value.SegTreeProb);
SetSegmentId(ref cm, miOffset, xMis, yMis, segmentId);
return segmentId;
}
@ -203,7 +214,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
if (!seg.Enabled)
{
return 0; // Default for disabled segmentation
return 0; // Default for disabled segmentation
}
predictedSegmentId = !cm.LastFrameSegMap.IsNull
@ -213,6 +224,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
if (!seg.UpdateMap)
{
CopySegmentId(ref cm, cm.LastFrameSegMap, cm.CurrentFrameSegMap, miOffset, xMis, yMis);
return predictedSegmentId;
}
@ -227,6 +239,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
segmentId = ReadSegmentId(ref r, ref cm.Fc.Value.SegTreeProb);
}
SetSegmentId(ref cm, miOffset, xMis, yMis, segmentId);
return segmentId;
}
@ -236,17 +249,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{
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)
@ -265,7 +276,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
else
{
int i;
int n = (int)mvClass + Constants.Class0Bits - 1; // Number of bits
int n = (int)mvClass + Constants.Class0Bits - 1; // Number of bits
d = 0;
for (i = 0; i < n; ++i)
@ -284,6 +295,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// Result
mag += ((d << 3) | (fr << 1) | hp) + 1;
return sign ? -mag : mag;
}
@ -297,7 +309,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{
MvJointType jointType = (MvJointType)r.ReadTree(Luts.Vp9MvJointTree, fc.Joints.AsSpan());
bool useHP = allowHP && refr.UseMvHp();
Mv diff = new Mv();
Mv diff = new();
if (Mv.MvJointVertical(jointType))
{
@ -326,12 +338,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
++xd.Counts.Value.CompInter[ctx][(int)mode];
}
return mode; // SingleReference or CompoundReference
}
else
{
return cm.ReferenceMode;
return mode; // SingleReference or CompoundReference
}
return cm.ReferenceMode;
}
// 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[2].Mode = mi.Bmi[3].Mode = mi.Mode = ReadIntraModeY(ref cm, ref xd, ref r, 0);
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);
@ -503,7 +515,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
ZeroMvPair(ref mv);
break;
}
default: return false;
default:
return false;
}
return ret;
}
@ -514,17 +527,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{
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)
@ -547,6 +558,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{
mvRefList[refMvCount] = mv;
refMvCount++;
return true;
}
}
@ -605,7 +617,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// This function searches the neighborhood of a given MB/SB
// to try and find candidate reference vectors.
private static unsafe int DecFindMvRefs(
private static int DecFindMvRefs(
ref Vp9Common cm,
ref MacroBlockD xd,
PredictionMode mode,
@ -627,7 +639,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
bool earlyBreak = mode != PredictionMode.NearMv;
// Blank the reference vector list
mvRefList.Slice(0, Constants.MaxMvRefCandidates).Fill(new Mv());
mvRefList[..Constants.MaxMvRefCandidates].Clear();
i = 0;
if (isSub8X8 != 0)
@ -805,7 +817,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
switch (block)
{
case 0: bestSub8x8 = mvList[refmvCount - 1]; break;
case 0:
bestSub8x8 = mvList[refmvCount - 1];
break;
case 1:
case 2:
if (bMode == PredictionMode.NearestMv)
@ -848,7 +862,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
}
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;
bool allowHP = cm.AllowHighPrecisionMv;
Array2<Mv> bestRefMvs = new Array2<Mv>();
Array2<Mv> bestRefMvs = new();
int refr, isCompound;
byte interModeCtx;
Span<Position> mvRefSearch = Luts.MvRefBlocks[(int)bsize];
@ -898,6 +914,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
if (bsize < BlockSize.Block8x8)
{
xd.ErrorInfo.Value.InternalError(CodecErr.CodecUnsupBitstream, "Invalid usage of segement feature on small blocks");
return;
}
}
@ -940,11 +957,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
int num4X4H = 1 << xd.BmodeBlocksHl;
int idx, idy;
PredictionMode bMode = 0;
Array2<Mv> bestSub8x8 = new Array2<Mv>();
const uint invalidMv = 0x80008000;
Array2<Mv> bestSub8x8 = new();
const uint InvalidMv = 0x80008000;
// Initialize the 2nd element as even though it won't be used meaningfully
// 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 (idx = 0; idx < 2; idx += num4X4W)
@ -1026,11 +1043,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
return leftMi.Value.GetYMode(b + 1);
}
else
{
Debug.Assert(b == 1 || b == 3);
return curMi.Value.Bmi[b - 1].Mode;
}
Debug.Assert(b == 1 || b == 3);
return curMi.Value.Bmi[b - 1].Mode;
}
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);
}
else
{
Debug.Assert(b == 2 || b == 3);
return curMi.Value.Bmi[b - 2].Mode;
}
Debug.Assert(b == 2 || b == 3);
return curMi.Value.Bmi[b - 2].Mode;
}
private static ReadOnlySpan<byte> GetYModeProbs(
@ -1060,6 +1075,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{
PredictionMode above = AboveBlockMode(mi, aboveMi, block);
PredictionMode left = LeftBlockMode(mi, leftMi, block);
return fc.KfYModeProb[(int)above][(int)left].AsSpan();
}

View file

@ -3,7 +3,6 @@ using Ryujinx.Graphics.Nvdec.Vp9.Common;
using Ryujinx.Graphics.Nvdec.Vp9.Types;
using Ryujinx.Graphics.Video;
using System;
using Vp9MvRef = Ryujinx.Graphics.Video.Vp9MvRef;
namespace Ryujinx.Graphics.Nvdec.Vp9
{
@ -11,7 +10,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{
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);
@ -20,7 +19,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
Constants.EightTapSmooth,
Constants.EightTap,
Constants.EightTapSharp,
Constants.Bilinear
Constants.Bilinear,
};
public unsafe bool Decode(
@ -30,24 +29,25 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
ReadOnlySpan<Vp9MvRef> mvsIn,
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;
cm.IntraOnly = pictureInfo.IntraOnly;
Width = output.Width,
Height = output.Height,
SubsamplingX = 1,
SubsamplingY = 1,
cm.Width = output.Width;
cm.Height = output.Height;
cm.SubsamplingX = 1;
cm.SubsamplingY = 1;
UsePrevFrameMvs = pictureInfo.UsePrevInFindMvRefs,
cm.UsePrevFrameMvs = pictureInfo.UsePrevInFindMvRefs;
RefFrameSignBias = pictureInfo.RefFrameSignBias,
cm.RefFrameSignBias = pictureInfo.RefFrameSignBias;
cm.BaseQindex = pictureInfo.BaseQIndex;
cm.YDcDeltaQ = pictureInfo.YDcDeltaQ;
cm.UvAcDeltaQ = pictureInfo.UvAcDeltaQ;
cm.UvDcDeltaQ = pictureInfo.UvDcDeltaQ;
BaseQindex = pictureInfo.BaseQIndex,
YDcDeltaQ = pictureInfo.YDcDeltaQ,
UvAcDeltaQ = pictureInfo.UvAcDeltaQ,
UvDcDeltaQ = pictureInfo.UvDcDeltaQ,
};
cm.Mb.Lossless = pictureInfo.Lossless;
cm.Mb.Bd = 8;

View file

@ -17,9 +17,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
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(
@ -57,13 +57,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
int band, c = 0;
ref Array6<Array6<Array3<byte>>> coefProbs = ref fc.CoefProbs[(int)txSize][(int)type][refr];
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 v;
short dqv = dq[0];
ReadOnlySpan<byte> cat6Prob = (xd.Bd == 12)
? 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;
// Keep value, range, and count as locals. The compiler produces better
// results with the locals than using r directly.
@ -75,7 +75,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{
int val = -1;
band = bandTranslate[0];
bandTranslate = bandTranslate.Slice(1);
bandTranslate = bandTranslate[1..];
ref Array3<byte> prob = ref coefProbs[band][ctx];
if (!xd.Counts.IsNull)
{
@ -107,11 +107,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
r.Value = value;
r.Range = range;
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);
band = bandTranslate[0];
bandTranslate = bandTranslate.Slice(1);
bandTranslate = bandTranslate[1..];
prob = ref coefProbs[band][ctx];
}
@ -196,6 +197,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
r.Value = value;
r.Range = range;
r.Count = count;
return c;
}
@ -236,8 +238,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
ref MacroBlockDPlane pd = ref xd.Plane[plane];
ref Array2<short> dequant = ref pd.SegDequant[segId];
int eob;
Span<sbyte> a = pd.AboveContext.AsSpan().Slice(x);
Span<sbyte> l = pd.LeftContext.AsSpan().Slice(y);
Span<sbyte> a = pd.AboveContext.AsSpan()[x..];
Span<sbyte> l = pd.LeftContext.AsSpan()[y..];
int ctx;
int ctxShiftA = 0;
int ctxShiftL = 0;

View file

@ -117,6 +117,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
if (Sse41.IsSupported && UseIntrinsics && xStepQ4 == 1 << SubpelBits)
{
ConvolveHorizSse41(src, srcStride, dst, dstStride, xFilters, x0Q4, w, h);
return;
}
@ -261,6 +262,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
if (Avx2.IsSupported && UseIntrinsics && yStepQ4 == 1 << SubpelBits)
{
ConvolveVertAvx2(src, srcStride, dst, dstStride, yFilters, y0Q4, w, h);
return;
}
@ -776,7 +778,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Debug.Assert(yStepQ4 <= 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);
}
@ -811,7 +813,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
int h,
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(

View file

@ -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)
{
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
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, 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, 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, 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, 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)
@ -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, 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, 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)
@ -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)
{
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
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, 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, 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, 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, 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)
@ -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, 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, 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)

View file

@ -35,6 +35,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
// of this range for invalid/corrupt VP9 streams.
Debug.Assert(short.MinValue <= input);
Debug.Assert(input <= short.MaxValue);
return input;
}
@ -70,6 +71,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
public static byte ClipPixelAdd(byte dest, long trans)
{
trans = WrapLow(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)
{
trans = HighbdWrapLow(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)
{
long rv = BitUtils.RoundPowerOfTwo(input, DctConstBits);
return rv;
}
@ -115,8 +119,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
op[1] = WrapLow(b1);
op[2] = WrapLow(c1);
op[3] = WrapLow(d1);
ip = ip.Slice(4);
op = op.Slice(4);
ip = ip[4..];
op = op[4..];
}
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 * 3] = ClipPixelAdd(dest[stride * 3], WrapLow(d1));
ip2 = ip2.Slice(1);
dest = dest.Slice(1);
ip2 = ip2[1..];
dest = dest[1..];
}
}
@ -167,8 +171,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
dest[stride * 1] = ClipPixelAdd(dest[stride * 1], e1);
dest[stride * 2] = ClipPixelAdd(dest[stride * 2], e1);
dest[stride * 3] = ClipPixelAdd(dest[stride * 3], e1);
ip2 = ip2.Slice(1);
dest = dest.Slice(1);
ip2 = ip2[1..];
dest = dest[1..];
}
}
@ -182,7 +186,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
if ((x0 | x1 | x2 | x3) == 0)
{
output.Slice(0, 4).Fill(0);
output[..4].Clear();
return;
}
@ -247,8 +252,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
for (i = 0; i < 4; ++i)
{
Idct4(input, outptr);
input = input.Slice(4);
outptr = outptr.Slice(4);
input = input[4..];
outptr = outptr[4..];
}
// Columns
@ -282,7 +287,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
dest[1] = ClipPixelAdd(dest[1], a1);
dest[2] = ClipPixelAdd(dest[2], 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)
{
output.Slice(0, 8).Fill(0);
output[..8].Clear();
return;
}
@ -434,8 +440,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
for (i = 0; i < 8; ++i)
{
Idct8(input, outptr);
input = input.Slice(8);
outptr = outptr.Slice(8);
input = input[8..];
outptr = outptr[8..];
}
// Then transform columns
@ -464,15 +470,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Span<int> tempIn = stackalloc int[8];
Span<int> tempOut = stackalloc int[8];
output.Fill(0);
output.Clear();
// First transform rows
// Only first 4 row has non-zero coefs
for (i = 0; i < 4; ++i)
{
Idct8(input, outptr);
input = input.Slice(8);
outptr = outptr.Slice(8);
input = input[8..];
outptr = outptr[8..];
}
// Then transform columns
@ -506,7 +512,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
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)
{
output.Slice(0, 16).Fill(0);
output[..16].Clear();
return;
}
@ -860,8 +867,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
for (i = 0; i < 16; ++i)
{
Idct16(input, outptr);
input = input.Slice(16);
outptr = outptr.Slice(16);
input = input[16..];
outptr = outptr[16..];
}
// Then transform columns
@ -889,15 +896,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Span<int> tempIn = 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
// upper-left 8x8 area, we only need to calculate first 8 rows here.
for (i = 0; i < 8; ++i)
{
Idct16(input, outptr);
input = input.Slice(16);
outptr = outptr.Slice(16);
input = input[16..];
outptr = outptr[16..];
}
// Then transform columns
@ -925,15 +932,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Span<int> tempIn = 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
// upper-left 4x4 area, we only need to calculate first 4 rows here.
for (i = 0; i < 4; ++i)
{
Idct16(input, outptr);
input = input.Slice(16);
outptr = outptr.Slice(16);
input = input[16..];
outptr = outptr[16..];
}
// Then transform columns
@ -967,7 +974,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
dest[i] = ClipPixelAdd(dest[i], a1);
}
dest = dest.Slice(stride);
dest = dest[stride..];
}
}
@ -1365,11 +1372,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
}
else
{
outptr.Slice(0, 32).Fill(0);
outptr[..32].Clear();
}
input = input.Slice(32);
outptr = outptr.Slice(32);
input = input[32..];
outptr = outptr[32..];
}
// Columns
@ -1397,15 +1404,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Span<int> tempIn = stackalloc int[32];
Span<int> tempOut = stackalloc int[32];
output.Fill(0);
output.Clear();
// Rows
// Only upper-left 16x16 has non-zero coeff
for (i = 0; i < 16; ++i)
{
Idct32(input, outptr);
input = input.Slice(32);
outptr = outptr.Slice(32);
input = input[32..];
outptr = outptr[32..];
}
// Columns
@ -1433,15 +1440,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Span<int> tempIn = stackalloc int[32];
Span<int> tempOut = stackalloc int[32];
output.Fill(0);
output.Clear();
// Rows
// Only upper-left 8x8 has non-zero coeff
for (i = 0; i < 8; ++i)
{
Idct32(input, outptr);
input = input.Slice(32);
outptr = outptr.Slice(32);
input = input[32..];
outptr = outptr[32..];
}
// Columns
@ -1476,7 +1483,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
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[2] = HighbdWrapLow(c1, bd);
op[3] = HighbdWrapLow(d1, bd);
ip = ip.Slice(4);
op = op.Slice(4);
ip = ip[4..];
op = op[4..];
}
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 * 3] = HighbdClipPixelAdd(dest[stride * 3], HighbdWrapLow(d1, bd), bd);
ip2 = ip2.Slice(1);
dest = dest.Slice(1);
ip2 = ip2[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 * 2] = HighbdClipPixelAdd(dest[stride * 2], e1, bd);
dest[stride * 3] = HighbdClipPixelAdd(dest[stride * 3], e1, bd);
ip2 = ip2.Slice(1);
dest = dest.Slice(1);
ip2 = ip2[1..];
dest = dest[1..];
}
}
@ -1576,13 +1583,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
if (DetectInvalidHighbdInput(input, 4) != 0)
{
Debug.Assert(false, "invalid highbd txfm input");
output.Slice(0, 4).Fill(0);
output[..4].Clear();
return;
}
if ((x0 | x1 | x2 | x3) == 0)
{
output.Slice(0, 4).Fill(0);
output[..4].Clear();
return;
}
@ -1619,7 +1628,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
if (DetectInvalidHighbdInput(input, 4) != 0)
{
Debug.Assert(false, "invalid highbd txfm input");
output.Slice(0, 4).Fill(0);
output[..4].Clear();
return;
}
@ -1653,8 +1663,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
for (i = 0; i < 4; ++i)
{
HighbdIdct4(input, outptr, bd);
input = input.Slice(4);
outptr = outptr.Slice(4);
input = input[4..];
outptr = outptr[4..];
}
// Columns
@ -1688,7 +1698,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
dest[1] = HighbdClipPixelAdd(dest[1], a1, bd);
dest[2] = HighbdClipPixelAdd(dest[2], 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)
{
Debug.Assert(false, "invalid highbd txfm input");
output.Slice(0, 8).Fill(0);
output[..8].Clear();
return;
}
if ((x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7) == 0)
{
output.Slice(0, 8).Fill(0);
output[..8].Clear();
return;
}
@ -1786,7 +1798,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
if (DetectInvalidHighbdInput(input, 8) != 0)
{
Debug.Assert(false, "invalid highbd txfm input");
output.Slice(0, 8).Fill(0);
output[..8].Clear();
return;
}
@ -1845,8 +1858,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
for (i = 0; i < 8; ++i)
{
HighbdIdct8(input, outptr, bd);
input = input.Slice(8);
outptr = outptr.Slice(8);
input = input[8..];
outptr = outptr[8..];
}
// Then transform columns
@ -1874,15 +1887,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Span<int> tempIn = stackalloc int[8];
Span<int> tempOut = stackalloc int[8];
output.Fill(0);
output.Clear();
// First transform rows
// Only first 4 row has non-zero coefs
for (i = 0; i < 4; ++i)
{
HighbdIdct8(input, outptr, bd);
input = input.Slice(8);
outptr = outptr.Slice(8);
input = input[8..];
outptr = outptr[8..];
}
// 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;
long a1;
@ -1916,7 +1929,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
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 x14 = input[1];
int x15 = input[14];
if (DetectInvalidHighbdInput(input, 16) != 0)
{
Debug.Assert(false, "invalid highbd txfm input");
output.Slice(0, 16).Fill(0);
output[..16].Clear();
return;
}
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;
}
@ -2105,7 +2121,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
if (DetectInvalidHighbdInput(input, 16) != 0)
{
Debug.Assert(false, "invalid highbd txfm input");
output.Slice(0, 16).Fill(0);
output[..16].Clear();
return;
}
@ -2283,8 +2300,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
for (i = 0; i < 16; ++i)
{
HighbdIdct16(input, outptr, bd);
input = input.Slice(16);
outptr = outptr.Slice(16);
input = input[16..];
outptr = outptr[16..];
}
// Then transform columns
@ -2312,15 +2329,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Span<int> tempIn = 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
// upper-left 8x8 area, we only need to calculate first 8 rows here.
for (i = 0; i < 8; ++i)
{
HighbdIdct16(input, outptr, bd);
input = input.Slice(16);
outptr = outptr.Slice(16);
input = input[16..];
outptr = outptr[16..];
}
// Then transform columns
@ -2336,7 +2353,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
for (j = 0; j < 16; ++j)
{
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> tempOut = stackalloc int[16];
output.Fill(0);
output.Clear();
// First transform rows. Since all non-zero dct coefficients are in
// upper-left 4x4 area, we only need to calculate first 4 rows here.
for (i = 0; i < 4; ++i)
{
HighbdIdct16(input, outptr, bd);
input = input.Slice(16);
outptr = outptr.Slice(16);
input = input[16..];
outptr = outptr[16..];
}
// Then transform columns
@ -2392,7 +2409,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
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)
{
Debug.Assert(false, "invalid highbd txfm input");
output.Slice(0, 32).Fill(0);
output[..32].Clear();
return;
}
@ -2797,11 +2815,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
}
else
{
outptr.Slice(0, 32).Fill(0);
outptr[..32].Clear();
}
input = input.Slice(32);
outptr = outptr.Slice(32);
input = input[32..];
outptr = outptr[32..];
}
// Columns
@ -2829,15 +2847,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Span<int> tempIn = stackalloc int[32];
Span<int> tempOut = stackalloc int[32];
output.Fill(0);
output.Clear();
// Rows
// Only upper-left 16x16 has non-zero coeff
for (i = 0; i < 16; ++i)
{
HighbdIdct32(input, outptr, bd);
input = input.Slice(32);
outptr = outptr.Slice(32);
input = input[32..];
outptr = outptr[32..];
}
// Columns
@ -2853,7 +2871,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
for (j = 0; j < 32; ++j)
{
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> tempOut = stackalloc int[32];
output.Fill(0);
output.Clear();
// Rows
// Only upper-left 8x8 has non-zero coeff
for (i = 0; i < 8; ++i)
{
HighbdIdct32(input, outptr, bd);
input = input.Slice(32);
outptr = outptr.Slice(32);
input = input[32..];
outptr = outptr[32..];
}
// Columns
@ -2910,7 +2928,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
dest[i] = HighbdClipPixelAdd(dest[i], a1, bd);
}
dest = dest.Slice(stride);
dest = dest[stride..];
}
}
}

View file

@ -15,6 +15,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
int p = (int)(((ulong)num * 256 + (den >> 1)) / den);
// (p > 255) ? 255 : (p < 1) ? 1 : p;
int clippedProb = p | ((255 - p) >> 23) | (p == 0 ? 1 : 0);
return (byte)clippedProb;
}
}
@ -26,10 +27,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
}
// 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,
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;
@ -44,8 +44,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
else
{
uint count = Math.Min(den, ModeMvCountSat);
uint factor = CountToUpdateFactor[(int)count];
uint factor = _countToUpdateFactor[(int)count];
byte prob = GetProb(ct0, den);
return WeightedProb(preProb, prob, (int)factor);
}
}
@ -62,6 +63,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
int r = tree[i + 1];
uint rightCount = (r <= 0) ? counts[-r] : TreeMergeProbsImpl((uint)r, tree, preProbs, counts, probs);
probs[(int)(i >> 1)] = ModeMvMergeProbs(preProbs[(int)(i >> 1)], leftCount, rightCount);
return leftCount + rightCount;
}

View file

@ -6,8 +6,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
{
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,
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,
@ -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,
};
private const int BdValueSize = sizeof(ulong) * 8;
@ -44,7 +43,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Count = -8;
Range = 255;
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);
nv = bigEndianValues >> (BdValueSize - bits);
count += bits;
buffer = buffer.Slice(bits >> 3);
buffer = buffer[(bits >> 3)..];
value = Value | (nv << (shift & 0x7));
}
else
@ -84,7 +84,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
{
count += 8;
value |= (ulong)buffer[0] << shift;
buffer = buffer.Slice(1);
buffer = buffer[1..];
shift -= 8;
}
}
@ -98,7 +98,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Count = count;
}
public bool HasError()
public readonly bool HasError()
{
// 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;
value <<= shift;
count -= shift;
@ -160,7 +160,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
public int ReadBit()
{
return Read(128); // vpx_prob_half
return Read(128); // vpx_prob_half
}
public int ReadLiteral(int bits)
@ -181,7 +181,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
while ((i = tree[i + Read(probs[i >> 1])]) > 0)
{
continue;
}
return -i;
@ -203,10 +202,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
if (value >= bigsplit)
{
range = range - split;
value = value - bigsplit;
range -= split;
value -= bigsplit;
{
int shift = Norm[range];
int shift = _norm[range];
range <<= shift;
value <<= shift;
count -= shift;
@ -215,7 +214,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
}
range = split;
{
int shift = Norm[range];
int shift = _norm[range];
range <<= shift;
value <<= shift;
count -= shift;

View file

@ -12,7 +12,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
private struct Transform2D
{
public Transform1D Cols, Rows; // Vertical and horizontal
public Transform1D Cols, Rows; // Vertical and horizontal
public Transform2D(Transform1D cols, Transform1D rows)
{
@ -23,7 +23,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
private struct HighbdTransform2D
{
public HighbdTransform1D Cols, Rows; // Vertical and horizontal
public HighbdTransform1D Cols, Rows; // Vertical and horizontal
public HighbdTransform2D(HighbdTransform1D cols, HighbdTransform1D rows)
{
@ -32,12 +32,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
}
private static readonly Transform2D[] Iht4 = new Transform2D[]
{
new Transform2D(Idct4, Idct4), // DCT_DCT = 0
new Transform2D(Iadst4, Idct4), // ADST_DCT = 1
new Transform2D(Idct4, Iadst4), // DCT_ADST = 2
new Transform2D(Iadst4, Iadst4) // ADST_ADST = 3
private static readonly Transform2D[] _iht4 = {
new(Idct4, Idct4), // DCT_DCT = 0
new(Iadst4, Idct4), // ADST_DCT = 1
new(Idct4, Iadst4), // DCT_ADST = 2
new(Iadst4, Iadst4), // ADST_ADST = 3
};
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
for (i = 0; i < 4; ++i)
{
Iht4[txType].Rows(input, outptr);
input = input.Slice(4);
outptr = outptr.Slice(4);
_iht4[txType].Rows(input, outptr);
input = input[4..];
outptr = outptr[4..];
}
// Inverse transform column vectors
@ -64,7 +63,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
tempIn[j] = output[j * 4 + i];
}
Iht4[txType].Cols(tempIn, tempOut);
_iht4[txType].Cols(tempIn, tempOut);
for (j = 0; j < 4; ++j)
{
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[]
{
new Transform2D(Idct8, Idct8), // DCT_DCT = 0
new Transform2D(Iadst8, Idct8), // ADST_DCT = 1
new Transform2D(Idct8, Iadst8), // DCT_ADST = 2
new Transform2D(Iadst8, Iadst8) // ADST_ADST = 3
private static readonly Transform2D[] _iht8 = {
new(Idct8, Idct8), // DCT_DCT = 0
new(Iadst8, Idct8), // ADST_DCT = 1
new(Idct8, Iadst8), // DCT_ADST = 2
new(Iadst8, Iadst8), // ADST_ADST = 3
};
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> tempIn = stackalloc int[8];
Span<int> tempOut = stackalloc int[8];
Transform2D ht = Iht8[txType];
Transform2D ht = _iht8[txType];
// Inverse transform row vectors
for (i = 0; i < 8; ++i)
{
ht.Rows(input, outptr);
input = input.Slice(8);
outptr = outptr.Slice(8);
input = input[8..];
outptr = outptr[8..];
}
// Inverse transform column vectors
@ -113,12 +111,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
}
private static readonly Transform2D[] Iht16 = new Transform2D[]
{
new Transform2D(Idct16, Idct16), // DCT_DCT = 0
new Transform2D(Iadst16, Idct16), // ADST_DCT = 1
new Transform2D(Idct16, Iadst16), // DCT_ADST = 2
new Transform2D(Iadst16, Iadst16) // ADST_ADST = 3
private static readonly Transform2D[] _iht16 = {
new(Idct16, Idct16), // DCT_DCT = 0
new(Iadst16, Idct16), // ADST_DCT = 1
new(Idct16, Iadst16), // DCT_ADST = 2
new(Iadst16, Iadst16), // ADST_ADST = 3
};
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> tempIn = stackalloc int[16];
Span<int> tempOut = stackalloc int[16];
Transform2D ht = Iht16[txType];
Transform2D ht = _iht16[txType];
// Rows
for (i = 0; i < 16; ++i)
{
ht.Rows(input, outptr);
input = input.Slice(16);
outptr = outptr.Slice(16);
input = input[16..];
outptr = outptr[16..];
}
// Columns
@ -283,12 +280,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
}
private static readonly HighbdTransform2D[] HighbdIht4 = new HighbdTransform2D[]
{
new HighbdTransform2D(HighbdIdct4, HighbdIdct4), // DCT_DCT = 0
new HighbdTransform2D(HighbdIadst4, HighbdIdct4), // ADST_DCT = 1
new HighbdTransform2D(HighbdIdct4, HighbdIadst4), // DCT_ADST = 2
new HighbdTransform2D(HighbdIadst4, HighbdIadst4) // ADST_ADST = 3
private static readonly HighbdTransform2D[] _highbdIht4 = {
new(HighbdIdct4, HighbdIdct4), // DCT_DCT = 0
new(HighbdIadst4, HighbdIdct4), // ADST_DCT = 1
new(HighbdIdct4, HighbdIadst4), // DCT_ADST = 2
new(HighbdIadst4, HighbdIadst4), // ADST_ADST = 3
};
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.
for (i = 0; i < 4; ++i)
{
HighbdIht4[txType].Rows(input, outptr, bd);
input = input.Slice(4);
outptr = outptr.Slice(4);
_highbdIht4[txType].Rows(input, outptr, bd);
input = input[4..];
outptr = outptr[4..];
}
// Inverse transform column vectors.
@ -315,7 +311,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
tempIn[j] = output[j * 4 + i];
}
HighbdIht4[txType].Cols(tempIn, tempOut, bd);
_highbdIht4[txType].Cols(tempIn, tempOut, bd);
for (j = 0; j < 4; ++j)
{
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[]
{
new HighbdTransform2D(HighbdIdct8, HighbdIdct8), // DCT_DCT = 0
new HighbdTransform2D(HighbdIadst8, HighbdIdct8), // ADST_DCT = 1
new HighbdTransform2D(HighbdIdct8, HighbdIadst8), // DCT_ADST = 2
new HighbdTransform2D(HighbdIadst8, HighbdIadst8) // ADST_ADST = 3
private static readonly HighbdTransform2D[] _highIht8 = {
new(HighbdIdct8, HighbdIdct8), // DCT_DCT = 0
new(HighbdIadst8, HighbdIdct8), // ADST_DCT = 1
new(HighbdIdct8, HighbdIadst8), // DCT_ADST = 2
new(HighbdIadst8, HighbdIadst8), // ADST_ADST = 3
};
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> tempIn = stackalloc int[8];
Span<int> tempOut = stackalloc int[8];
HighbdTransform2D ht = HighIht8[txType];
HighbdTransform2D ht = _highIht8[txType];
// Inverse transform row vectors.
for (i = 0; i < 8; ++i)
{
ht.Rows(input, outptr, bd);
input = input.Slice(8);
outptr = output.Slice(8);
input = input[8..];
outptr = output[8..];
}
// Inverse transform column vectors.
@ -364,12 +359,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
}
private static readonly HighbdTransform2D[] HighIht16 = new HighbdTransform2D[]
{
new HighbdTransform2D(HighbdIdct16, HighbdIdct16), // DCT_DCT = 0
new HighbdTransform2D(HighbdIadst16, HighbdIdct16), // ADST_DCT = 1
new HighbdTransform2D(HighbdIdct16, HighbdIadst16), // DCT_ADST = 2
new HighbdTransform2D(HighbdIadst16, HighbdIadst16) // ADST_ADST = 3
private static readonly HighbdTransform2D[] _highIht16 = {
new(HighbdIdct16, HighbdIdct16), // DCT_DCT = 0
new(HighbdIadst16, HighbdIdct16), // ADST_DCT = 1
new(HighbdIdct16, HighbdIadst16), // DCT_ADST = 2
new(HighbdIadst16, HighbdIadst16), // ADST_ADST = 3
};
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> tempIn = stackalloc int[16];
Span<int> tempOut = stackalloc int[16];
HighbdTransform2D ht = HighIht16[txType];
HighbdTransform2D ht = _highIht16[txType];
// Rows
for (i = 0; i < 16; ++i)
{
ht.Rows(input, outptr, bd);
input = input.Slice(16);
outptr = output.Slice(16);
input = input[16..];
outptr = output[16..];
}
// Columns
@ -440,7 +434,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// DC only DCT coefficient
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)
{

View file

@ -30,12 +30,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// 10101010
//
// A loopfilter should be applied to every other 8x8 horizontally.
private static readonly ulong[] Left64X64TxformMask = new ulong[]
{
0xffffffffffffffffUL, // TX_4X4
0xffffffffffffffffUL, // TX_8x8
0x5555555555555555UL, // TX_16x16
0x1111111111111111UL, // TX_32x32
private static readonly ulong[] _left64X64TxformMask = {
0xffffffffffffffffUL, // TX_4X4
0xffffffffffffffffUL, // TX_8x8
0x5555555555555555UL, // TX_16x16
0x1111111111111111UL, // TX_32x32
};
// 64 bit masks for above transform size. Each 1 represents a position where
@ -55,12 +54,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// 00000000
//
// A loopfilter should be applied to every other 4 the row vertically.
private static readonly ulong[] Above64X64TxformMask = new ulong[]
{
0xffffffffffffffffUL, // TX_4X4
0xffffffffffffffffUL, // TX_8x8
0x00ff00ff00ff00ffUL, // TX_16x16
0x000000ff000000ffUL, // TX_32x32
private static readonly ulong[] _above64X64TxformMask = {
0xffffffffffffffffUL, // TX_4X4
0xffffffffffffffffUL, // TX_8x8
0x00ff00ff00ff00ffUL, // TX_16x16
0x000000ff000000ffUL, // TX_32x32
};
// 64 bit masks for prediction sizes (left). Each 1 represents a position
@ -78,148 +76,143 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// 00000000
// 00000000
// 00000000
private static readonly ulong[] LeftPredictionMask = new ulong[]
{
0x0000000000000001UL, // BLOCK_4X4,
0x0000000000000001UL, // BLOCK_4X8,
0x0000000000000001UL, // BLOCK_8X4,
0x0000000000000001UL, // BLOCK_8X8,
0x0000000000000101UL, // BLOCK_8X16,
0x0000000000000001UL, // BLOCK_16X8,
0x0000000000000101UL, // BLOCK_16X16,
0x0000000001010101UL, // BLOCK_16X32,
0x0000000000000101UL, // BLOCK_32X16,
0x0000000001010101UL, // BLOCK_32X32,
0x0101010101010101UL, // BLOCK_32X64,
0x0000000001010101UL, // BLOCK_64X32,
0x0101010101010101UL, // BLOCK_64X64
private static readonly ulong[] _leftPredictionMask = {
0x0000000000000001UL, // BLOCK_4X4,
0x0000000000000001UL, // BLOCK_4X8,
0x0000000000000001UL, // BLOCK_8X4,
0x0000000000000001UL, // BLOCK_8X8,
0x0000000000000101UL, // BLOCK_8X16,
0x0000000000000001UL, // BLOCK_16X8,
0x0000000000000101UL, // BLOCK_16X16,
0x0000000001010101UL, // BLOCK_16X32,
0x0000000000000101UL, // BLOCK_32X16,
0x0000000001010101UL, // BLOCK_32X32,
0x0101010101010101UL, // BLOCK_32X64,
0x0000000001010101UL, // BLOCK_64X32,
0x0101010101010101UL, // BLOCK_64X64
};
// 64 bit mask to shift and set for each prediction size.
private static readonly ulong[] AbovePredictionMask = new ulong[]
{
0x0000000000000001UL, // BLOCK_4X4
0x0000000000000001UL, // BLOCK_4X8
0x0000000000000001UL, // BLOCK_8X4
0x0000000000000001UL, // BLOCK_8X8
0x0000000000000001UL, // BLOCK_8X16,
0x0000000000000003UL, // BLOCK_16X8
0x0000000000000003UL, // BLOCK_16X16
0x0000000000000003UL, // BLOCK_16X32,
0x000000000000000fUL, // BLOCK_32X16,
0x000000000000000fUL, // BLOCK_32X32,
0x000000000000000fUL, // BLOCK_32X64,
0x00000000000000ffUL, // BLOCK_64X32,
0x00000000000000ffUL, // BLOCK_64X64
private static readonly ulong[] _abovePredictionMask = {
0x0000000000000001UL, // BLOCK_4X4
0x0000000000000001UL, // BLOCK_4X8
0x0000000000000001UL, // BLOCK_8X4
0x0000000000000001UL, // BLOCK_8X8
0x0000000000000001UL, // BLOCK_8X16,
0x0000000000000003UL, // BLOCK_16X8
0x0000000000000003UL, // BLOCK_16X16
0x0000000000000003UL, // BLOCK_16X32,
0x000000000000000fUL, // BLOCK_32X16,
0x000000000000000fUL, // BLOCK_32X32,
0x000000000000000fUL, // BLOCK_32X64,
0x00000000000000ffUL, // BLOCK_64X32,
0x00000000000000ffUL, // BLOCK_64X64
};
// 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
// size in the 64x64 block.
private static readonly ulong[] SizeMask = new ulong[]
{
0x0000000000000001UL, // BLOCK_4X4
0x0000000000000001UL, // BLOCK_4X8
0x0000000000000001UL, // BLOCK_8X4
0x0000000000000001UL, // BLOCK_8X8
0x0000000000000101UL, // BLOCK_8X16,
0x0000000000000003UL, // BLOCK_16X8
0x0000000000000303UL, // BLOCK_16X16
0x0000000003030303UL, // BLOCK_16X32,
0x0000000000000f0fUL, // BLOCK_32X16,
0x000000000f0f0f0fUL, // BLOCK_32X32,
0x0f0f0f0f0f0f0f0fUL, // BLOCK_32X64,
0x00000000ffffffffUL, // BLOCK_64X32,
0xffffffffffffffffUL, // BLOCK_64X64
private static readonly ulong[] _sizeMask = {
0x0000000000000001UL, // BLOCK_4X4
0x0000000000000001UL, // BLOCK_4X8
0x0000000000000001UL, // BLOCK_8X4
0x0000000000000001UL, // BLOCK_8X8
0x0000000000000101UL, // BLOCK_8X16,
0x0000000000000003UL, // BLOCK_16X8
0x0000000000000303UL, // BLOCK_16X16
0x0000000003030303UL, // BLOCK_16X32,
0x0000000000000f0fUL, // BLOCK_32X16,
0x000000000f0f0f0fUL, // BLOCK_32X32,
0x0f0f0f0f0f0f0f0fUL, // BLOCK_32X64,
0x00000000ffffffffUL, // BLOCK_64X32,
0xffffffffffffffffUL, // BLOCK_64X64
};
// 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 AboveBorder = 0x000000ff000000ffUL;
#pragma warning restore IDE0051
// 16 bit masks for uv transform sizes.
private static readonly ushort[] Left64X64TxformMaskUv = new ushort[]
{
0xffff, // TX_4X4
0xffff, // TX_8x8
0x5555, // TX_16x16
0x1111, // TX_32x32
private static readonly ushort[] _left64X64TxformMaskUv = {
0xffff, // TX_4X4
0xffff, // TX_8x8
0x5555, // TX_16x16
0x1111, // TX_32x32
};
private static readonly ushort[] Above64X64TxformMaskUv = new ushort[]
{
0xffff, // TX_4X4
0xffff, // TX_8x8
0x0f0f, // TX_16x16
0x000f, // TX_32x32
private static readonly ushort[] _above64X64TxformMaskUv = {
0xffff, // TX_4X4
0xffff, // TX_8x8
0x0f0f, // TX_16x16
0x000f, // TX_32x32
};
// 16 bit left mask to shift and set for each uv prediction size.
private static readonly ushort[] LeftPredictionMaskUv = new ushort[]
{
0x0001, // BLOCK_4X4,
0x0001, // BLOCK_4X8,
0x0001, // BLOCK_8X4,
0x0001, // BLOCK_8X8,
0x0001, // BLOCK_8X16,
0x0001, // BLOCK_16X8,
0x0001, // BLOCK_16X16,
0x0011, // BLOCK_16X32,
0x0001, // BLOCK_32X16,
0x0011, // BLOCK_32X32,
0x1111, // BLOCK_32X64
0x0011, // BLOCK_64X32,
0x1111, // BLOCK_64X64
private static readonly ushort[] _leftPredictionMaskUv = {
0x0001, // BLOCK_4X4,
0x0001, // BLOCK_4X8,
0x0001, // BLOCK_8X4,
0x0001, // BLOCK_8X8,
0x0001, // BLOCK_8X16,
0x0001, // BLOCK_16X8,
0x0001, // BLOCK_16X16,
0x0011, // BLOCK_16X32,
0x0001, // BLOCK_32X16,
0x0011, // BLOCK_32X32,
0x1111, // BLOCK_32X64
0x0011, // BLOCK_64X32,
0x1111, // BLOCK_64X64
};
// 16 bit above mask to shift and set for uv each prediction size.
private static readonly ushort[] AbovePredictionMaskUv = new ushort[]
{
0x0001, // BLOCK_4X4
0x0001, // BLOCK_4X8
0x0001, // BLOCK_8X4
0x0001, // BLOCK_8X8
0x0001, // BLOCK_8X16,
0x0001, // BLOCK_16X8
0x0001, // BLOCK_16X16
0x0001, // BLOCK_16X32,
0x0003, // BLOCK_32X16,
0x0003, // BLOCK_32X32,
0x0003, // BLOCK_32X64,
0x000f, // BLOCK_64X32,
0x000f, // BLOCK_64X64
private static readonly ushort[] _abovePredictionMaskUv = {
0x0001, // BLOCK_4X4
0x0001, // BLOCK_4X8
0x0001, // BLOCK_8X4
0x0001, // BLOCK_8X8
0x0001, // BLOCK_8X16,
0x0001, // BLOCK_16X8
0x0001, // BLOCK_16X16
0x0001, // BLOCK_16X32,
0x0003, // BLOCK_32X16,
0x0003, // BLOCK_32X32,
0x0003, // BLOCK_32X64,
0x000f, // BLOCK_64X32,
0x000f, // BLOCK_64X64
};
// 64 bit mask to shift and set for each uv prediction size
private static readonly ushort[] SizeMaskUv = new ushort[]
{
0x0001, // BLOCK_4X4
0x0001, // BLOCK_4X8
0x0001, // BLOCK_8X4
0x0001, // BLOCK_8X8
0x0001, // BLOCK_8X16,
0x0001, // BLOCK_16X8
0x0001, // BLOCK_16X16
0x0011, // BLOCK_16X32,
0x0003, // BLOCK_32X16,
0x0033, // BLOCK_32X32,
0x3333, // BLOCK_32X64,
0x00ff, // BLOCK_64X32,
0xffff, // BLOCK_64X64
private static readonly ushort[] _sizeMaskUv = {
0x0001, // BLOCK_4X4
0x0001, // BLOCK_4X8
0x0001, // BLOCK_8X4
0x0001, // BLOCK_8X8
0x0001, // BLOCK_8X16,
0x0001, // BLOCK_16X8
0x0001, // BLOCK_16X16
0x0011, // BLOCK_16X32,
0x0003, // BLOCK_32X16,
0x0033, // BLOCK_32X32,
0x3333, // BLOCK_32X64,
0x00ff, // BLOCK_64X32,
0xffff, // BLOCK_64X64
};
#pragma warning disable IDE0051 // Remove unused private member
private const ushort LeftBorderUv = 0x1111;
private const ushort AboveBorderUv = 0x000f;
#pragma warning restore IDE0051
private static readonly int[] ModeLfLut = new int[]
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // INTRA_MODES
1, 1, 0, 1 // INTER_MODES (ZEROMV == 0)
private static readonly int[] _modeLfLut = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // INTRA_MODES
1, 1, 0, 1, // INTER_MODES (ZEROMV == 0)
};
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)
@ -229,12 +222,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// 8x8 blocks in a superblock. A "1" represents the first block in a 16x16
// 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 }
};
// 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 shiftY = colInSb + (rowInSb << 3);
int shiftUv = (colInSb >> 1) + ((rowInSb >> 1) << 2);
int buildUv = FirstBlockIn16x16[rowInSb][colInSb];
int buildUv = _firstBlockIn16X16[rowInSb][colInSb];
if (filterLevel == 0)
{
return;
}
else
int index = shiftY;
int i;
for (i = 0; i < bh; i++)
{
int index = shiftY;
int i;
for (i = 0; i < bh; i++)
{
MemoryMarshal.CreateSpan(ref lfm.LflY[index], 64 - index).Slice(0, bw).Fill((byte)filterLevel);
index += 8;
}
MemoryMarshal.CreateSpan(ref lfm.LflY[index], 64 - index)[..bw].Fill((byte)filterLevel);
index += 8;
}
// 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.
//
aboveY |= AbovePredictionMask[(int)blockSize] << shiftY;
leftY |= LeftPredictionMask[(int)blockSize] << shiftY;
aboveY |= _abovePredictionMask[(int)blockSize] << shiftY;
leftY |= _leftPredictionMask[(int)blockSize] << shiftY;
if (buildUv != 0)
{
aboveUv |= (ushort)(AbovePredictionMaskUv[(int)blockSize] << shiftUv);
leftUv |= (ushort)(LeftPredictionMaskUv[(int)blockSize] << shiftUv);
aboveUv |= (ushort)(_abovePredictionMaskUv[(int)blockSize] << shiftUv);
leftUv |= (ushort)(_leftPredictionMaskUv[(int)blockSize] << shiftUv);
}
// 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
// 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.
aboveY |= (SizeMask[(int)blockSize] & Above64X64TxformMask[(int)txSizeY]) << shiftY;
leftY |= (SizeMask[(int)blockSize] & Left64X64TxformMask[(int)txSizeY]) << shiftY;
aboveY |= (_sizeMask[(int)blockSize] & _above64X64TxformMask[(int)txSizeY]) << shiftY;
leftY |= (_sizeMask[(int)blockSize] & _left64X64TxformMask[(int)txSizeY]) << shiftY;
if (buildUv != 0)
{
aboveUv |= (ushort)((SizeMaskUv[(int)blockSize] & Above64X64TxformMaskUv[(int)txSizeUv]) << shiftUv);
leftUv |= (ushort)((SizeMaskUv[(int)blockSize] & Left64X64TxformMaskUv[(int)txSizeUv]) << shiftUv);
aboveUv |= (ushort)((_sizeMaskUv[(int)blockSize] & _above64X64TxformMaskUv[(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
@ -319,12 +309,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// internal ones can be skipped and don't depend on the prediction block size.
if (txSizeY == TxSize.Tx4x4)
{
int4X4Y |= SizeMask[(int)blockSize] << shiftY;
int4X4Y |= _sizeMask[(int)blockSize] << shiftY;
}
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

View file

@ -13,7 +13,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// left of the entries corresponding to real macroblocks.
// The prediction flags in these dummy entries are initialized to 0.
if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
{ // both edges available
{ // both edges available
if (!xd.AboveMi.Value.HasSecondRef() && !xd.LeftMi.Value.HasSecondRef())
{
// 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)
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;
}
}
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;
if (!edgeMi.HasSecondRef())
@ -51,10 +51,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
}
else
{ // No edges available (1)
{ // No edges available (1)
ctx = 1;
}
Debug.Assert(ctx >= 0 && ctx < Constants.CompInterContexts);
return ctx;
}
@ -70,29 +71,29 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
int varRefIdx = fixRefIdx == 0 ? 1 : 0;
if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
{ // Both edges available
{ // Both edges available
bool aboveIntra = !xd.AboveMi.Value.IsInterBlock();
bool leftIntra = !xd.LeftMi.Value.IsInterBlock();
if (aboveIntra && leftIntra)
{ // Intra/Intra (2)
{ // Intra/Intra (2)
predContext = 2;
}
else if (aboveIntra || leftIntra)
{ // Intra/Inter
{ // Intra/Inter
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);
}
else // Comp pred (1/3)
else // Comp pred (1/3)
{
predContext = 1 + 2 * (edgeMi.RefFrame[varRefIdx] != cm.CompVarRef[1] ? 1 : 0);
}
}
else
{ // Inter/Inter
{ // Inter/Inter
bool lSg = !xd.LeftMi.Value.HasSecondRef();
bool aSg = !xd.AboveMi.Value.HasSecondRef();
sbyte vrfa = aSg ? xd.AboveMi.Value.RefFrame[0] : xd.AboveMi.Value.RefFrame[varRefIdx];
@ -103,7 +104,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
predContext = 0;
}
else if (lSg && aSg)
{ // Single/Single
{ // Single/Single
if ((vrfa == cm.CompFixedRef && vrfl == cm.CompVarRef[0]) ||
(vrfl == cm.CompFixedRef && vrfa == cm.CompVarRef[0]))
{
@ -119,7 +120,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
}
else if (lSg || aSg)
{ // Single/Comp
{ // Single/Comp
sbyte vrfc = lSg ? vrfa : vrfl;
sbyte rfs = aSg ? vrfa : vrfl;
if (vrfc == cm.CompVarRef[1] && rfs != cm.CompVarRef[1])
@ -136,7 +137,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
}
else if (vrfa == vrfl)
{ // Comp/Comp
{ // Comp/Comp
predContext = 4;
}
else
@ -146,7 +147,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
}
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;
if (!edgeMi.IsInterBlock())
@ -166,10 +167,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
}
else
{ // No edges available (2)
{ // No edges available (2)
predContext = 2;
}
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
return predContext;
}
@ -181,16 +183,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// left of the entries corresponding to real macroblocks.
// The prediction flags in these dummy entries are initialized to 0.
if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
{ // Both edges available
{ // Both edges available
bool aboveIntra = !xd.AboveMi.Value.IsInterBlock();
bool leftIntra = !xd.LeftMi.Value.IsInterBlock();
if (aboveIntra && leftIntra)
{ // Intra/Intra
{ // Intra/Intra
predContext = 2;
}
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;
if (!edgeMi.HasSecondRef())
{
@ -203,7 +205,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
}
else
{ // Inter/Inter
{ // Inter/Inter
bool aboveHasSecond = xd.AboveMi.Value.HasSecondRef();
bool leftHasSecond = xd.LeftMi.Value.HasSecondRef();
sbyte above0 = xd.AboveMi.Value.RefFrame[0];
@ -238,14 +240,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
}
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;
if (!edgeMi.IsInterBlock())
{ // Intra
{ // Intra
predContext = 2;
}
else
{ // Inter
{ // Inter
if (!edgeMi.HasSecondRef())
{
predContext = 4 * (edgeMi.RefFrame[0] == Constants.LastFrame ? 1 : 0);
@ -258,10 +260,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
}
else
{ // No edges available
{ // No edges available
predContext = 2;
}
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
return predContext;
}
@ -274,16 +277,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// left of the entries corresponding to real macroblocks.
// The prediction flags in these dummy entries are initialized to 0.
if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
{ // Both edges available
{ // Both edges available
bool aboveIntra = !xd.AboveMi.Value.IsInterBlock();
bool leftIntra = !xd.LeftMi.Value.IsInterBlock();
if (aboveIntra && leftIntra)
{ // Intra/Intra
{ // Intra/Intra
predContext = 2;
}
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;
if (!edgeMi.HasSecondRef())
{
@ -303,7 +306,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
}
else
{ // Inter/Inter
{ // Inter/Inter
bool aboveHasSecond = xd.AboveMi.Value.HasSecondRef();
bool leftHasSecond = xd.LeftMi.Value.HasSecondRef();
sbyte above0 = xd.AboveMi.Value.RefFrame[0];
@ -361,7 +364,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
}
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;
if (!edgeMi.IsInterBlock() || (edgeMi.RefFrame[0] == Constants.LastFrame && !edgeMi.HasSecondRef()))
@ -379,10 +382,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
}
else
{ // No edges available (2)
{ // No edges available (2)
predContext = 2;
}
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
return predContext;
}
}

View file

@ -9,8 +9,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
public const int MinQ = 0;
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,
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,
@ -32,8 +31,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
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,
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,
@ -56,8 +54,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
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,
103, 115, 127, 140, 153, 166, 180, 194, 208, 222, 237,
251, 266, 281, 296, 312, 327, 343, 358, 374, 390, 405,
@ -84,8 +81,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
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,
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,
@ -108,8 +104,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
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,
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,
@ -132,8 +127,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
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,
112, 126, 139, 154, 168, 183, 199, 214, 230, 247, 263,
280, 297, 314, 331, 349, 366, 384, 402, 420, 438, 456,
@ -164,11 +158,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{
switch (bitDepth)
{
case BitDepth.Bits8: return DcQlookup[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)];
case BitDepth.Bits8:
return _dcQlookup[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:
Debug.Assert(false, "bit_depth should be VPX_BITS_8, VPX_BITS_10 or VPX_BITS_12");
return -1;
}
}
@ -177,11 +175,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{
switch (bitDepth)
{
case BitDepth.Bits8: return AcQlookup[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)];
case BitDepth.Bits8:
return _acQlookup[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:
Debug.Assert(false, "bit_depth should be VPX_BITS_8, VPX_BITS_10 or VPX_BITS_12");
return -1;
}
}
@ -192,12 +194,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{
int data = seg.GetSegData(segmentId, SegLvlFeatures.SegLvlAltQ);
int segQIndex = seg.AbsDelta == Constants.SegmentAbsData ? data : baseQIndex + data;
return Math.Clamp(segQIndex, 0, MaxQ);
}
else
{
return baseQIndex;
}
return baseQIndex;
}
}
}

View file

@ -84,16 +84,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
private static Mv MiMvPredQ4(ref ModeInfo mi, int idx)
{
Mv res = new Mv()
return new Mv
{
Row = (short)RoundMvCompQ4(
mi.Bmi[0].Mv[idx].Row + mi.Bmi[1].Mv[idx].Row +
mi.Bmi[2].Mv[idx].Row + mi.Bmi[3].Mv[idx].Row),
Col = (short)RoundMvCompQ4(
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)
@ -103,16 +102,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
private static Mv MiMvPredQ2(ref ModeInfo mi, int idx, int block0, int block1)
{
Mv res = new Mv()
return new Mv
{
Row = (short)RoundMvCompQ2(
mi.Bmi[block0].Mv[idx].Row +
mi.Bmi[block1].Mv[idx].Row),
Col = (short)RoundMvCompQ2(
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)
@ -124,10 +122,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
int spelRight = spelLeft - SubpelShifts;
int spelTop = (Constants.Vp9InterpExtend + bh) << SubpelBits;
int spelBottom = spelTop - SubpelShifts;
Mv clampedMv = new Mv()
Mv clampedMv = new()
{
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);
@ -145,14 +143,24 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
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);
Mv res = new Mv();
Mv res = new();
switch (ssIdx)
{
case 0: res = mi.Bmi[block].Mv[refr]; break;
case 1: 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;
case 0:
res = mi.Bmi[block].Mv[refr];
break;
case 1:
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;
}
@ -161,6 +169,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{
int x = !sf.IsNull ? sf.Value.ScaleValueX(xOffset) : xOffset;
int y = !sf.IsNull ? sf.Value.ScaleValueY(yOffset) : yOffset;
return y * stride + x;
}

View file

@ -7,18 +7,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{
internal static class ReconIntra
{
public static readonly TxType[] IntraModeToTxTypeLookup = new TxType[]
{
TxType.DctDct, // DC
TxType.AdstDct, // V
TxType.DctAdst, // H
TxType.DctDct, // D45
TxType.AdstAdst, // D135
TxType.AdstDct, // D117
TxType.DctAdst, // D153
TxType.DctAdst, // D207
TxType.AdstDct, // D63
TxType.AdstAdst // TM
public static readonly TxType[] IntraModeToTxTypeLookup = {
TxType.DctDct, // DC
TxType.AdstDct, // V
TxType.DctAdst, // H
TxType.DctDct, // D45
TxType.AdstAdst, // D135
TxType.AdstDct, // D117
TxType.DctAdst, // D153
TxType.DctAdst, // D207
TxType.AdstDct, // D63
TxType.AdstAdst, // TM
};
private const int NeedLeft = 1 << 1;
@ -27,244 +26,240 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
private static ReadOnlySpan<byte> ExtendModes => new byte[]
{
NeedAbove | NeedLeft, // DC
NeedAbove, // V
NeedLeft, // H
NeedAboveRight, // D45
NeedLeft | NeedAbove, // D135
NeedLeft | NeedAbove, // D117
NeedLeft | NeedAbove, // D153
NeedLeft, // D207
NeedAboveRight, // D63
NeedLeft | NeedAbove, // TM
NeedAbove | NeedLeft, // DC
NeedAbove, // V
NeedLeft, // H
NeedAboveRight, // D45
NeedLeft | NeedAbove, // D135
NeedLeft | NeedAbove, // D117
NeedLeft | NeedAbove, // D153
NeedLeft, // D207
NeedAboveRight, // D63
NeedLeft | NeedAbove, // TM
};
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[]
{
null,
null,
null,
null
null,
},
new IntraPredFn[]
{
VPredictor4x4,
VPredictor8x8,
VPredictor16x16,
VPredictor32x32
VPredictor32x32,
},
new IntraPredFn[]
{
HPredictor4x4,
HPredictor8x8,
HPredictor16x16,
HPredictor32x32
HPredictor32x32,
},
new IntraPredFn[]
{
D45Predictor4x4,
D45Predictor8x8,
D45Predictor16x16,
D45Predictor32x32
D45Predictor32x32,
},
new IntraPredFn[]
{
D135Predictor4x4,
D135Predictor8x8,
D135Predictor16x16,
D135Predictor32x32
D135Predictor32x32,
},
new IntraPredFn[]
{
D117Predictor4x4,
D117Predictor8x8,
D117Predictor16x16,
D117Predictor32x32
D117Predictor32x32,
},
new IntraPredFn[]
{
D153Predictor4x4,
D153Predictor8x8,
D153Predictor16x16,
D153Predictor32x32
D153Predictor32x32,
},
new IntraPredFn[]
{
D207Predictor4x4,
D207Predictor8x8,
D207Predictor16x16,
D207Predictor32x32
D207Predictor32x32,
},
new IntraPredFn[]
{
D63Predictor4x4,
D63Predictor8x8,
D63Predictor16x16,
D63Predictor32x32
D63Predictor32x32,
},
new IntraPredFn[]
{
TMPredictor4x4,
TMPredictor8x8,
TMPredictor16x16,
TMPredictor32x32
}
TMPredictor32x32,
},
};
private static unsafe IntraPredFn[][][] _dcPred = new IntraPredFn[][][]
{
new IntraPredFn[][]
private static readonly unsafe IntraPredFn[][][] _dcPred = {
new[]
{
new IntraPredFn[]
{
Dc128Predictor4x4,
Dc128Predictor8x8,
Dc128Predictor16x16,
Dc128Predictor32x32
Dc128Predictor32x32,
},
new IntraPredFn[]
{
DcTopPredictor4x4,
DcTopPredictor8x8,
DcTopPredictor16x16,
DcTopPredictor32x32
}
DcTopPredictor32x32,
},
},
new IntraPredFn[][]
new[]
{
new IntraPredFn[]
{
DcLeftPredictor4x4,
DcLeftPredictor8x8,
DcLeftPredictor16x16,
DcLeftPredictor32x32
DcLeftPredictor32x32,
},
new IntraPredFn[]
{
DcPredictor4x4,
DcPredictor8x8,
DcPredictor16x16,
DcPredictor32x32
}
}
DcPredictor32x32,
},
},
};
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[]
{
null,
null,
null,
null
null,
},
new IntraHighPredFn[]
{
HighbdVPredictor4x4,
HighbdVPredictor8x8,
HighbdVPredictor16x16,
HighbdVPredictor32x32
HighbdVPredictor32x32,
},
new IntraHighPredFn[]
{
HighbdHPredictor4x4,
HighbdHPredictor8x8,
HighbdHPredictor16x16,
HighbdHPredictor32x32
HighbdHPredictor32x32,
},
new IntraHighPredFn[]
{
HighbdD45Predictor4x4,
HighbdD45Predictor8x8,
HighbdD45Predictor16x16,
HighbdD45Predictor32x32
HighbdD45Predictor32x32,
},
new IntraHighPredFn[]
{
HighbdD135Predictor4x4,
HighbdD135Predictor8x8,
HighbdD135Predictor16x16,
HighbdD135Predictor32x32
HighbdD135Predictor32x32,
},
new IntraHighPredFn[]
{
HighbdD117Predictor4x4,
HighbdD117Predictor8x8,
HighbdD117Predictor16x16,
HighbdD117Predictor32x32
HighbdD117Predictor32x32,
},
new IntraHighPredFn[]
{
HighbdD153Predictor4x4,
HighbdD153Predictor8x8,
HighbdD153Predictor16x16,
HighbdD153Predictor32x32
HighbdD153Predictor32x32,
},
new IntraHighPredFn[]
{
HighbdD207Predictor4x4,
HighbdD207Predictor8x8,
HighbdD207Predictor16x16,
HighbdD207Predictor32x32
HighbdD207Predictor32x32,
},
new IntraHighPredFn[]
{
HighbdD63Predictor4x4,
HighbdD63Predictor8x8,
HighbdD63Predictor16x16,
HighbdD63Predictor32x32
HighbdD63Predictor32x32,
},
new IntraHighPredFn[]
{
HighbdTMPredictor4x4,
HighbdTMPredictor8x8,
HighbdTMPredictor16x16,
HighbdTMPredictor32x32
}
HighbdTMPredictor32x32,
},
};
private static unsafe IntraHighPredFn[][][] _dcPredHigh = new IntraHighPredFn[][][]
{
new IntraHighPredFn[][]
private static readonly unsafe IntraHighPredFn[][][] _dcPredHigh = {
new[]
{
new IntraHighPredFn[]
{
HighbdDc128Predictor4x4,
HighbdDc128Predictor8x8,
HighbdDc128Predictor16x16,
HighbdDc128Predictor32x32
HighbdDc128Predictor32x32,
},
new IntraHighPredFn[]
{
HighbdDcTopPredictor4x4,
HighbdDcTopPredictor8x8,
HighbdDcTopPredictor16x16,
HighbdDcTopPredictor32x32
}
HighbdDcTopPredictor32x32,
},
},
new IntraHighPredFn[][]
new[]
{
new IntraHighPredFn[]
{
HighbdDcLeftPredictor4x4,
HighbdDcLeftPredictor8x8,
HighbdDcLeftPredictor16x16,
HighbdDcLeftPredictor32x32
HighbdDcLeftPredictor32x32,
},
new IntraHighPredFn[]
{
HighbdDcPredictor4x4,
HighbdDcPredictor8x8,
HighbdDcPredictor16x16,
HighbdDcPredictor32x32
}
}
HighbdDcPredictor32x32,
},
},
};
private static unsafe void BuildIntraPredictorsHigh(
@ -741,6 +736,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
x,
y,
plane);
return;
}
BuildIntraPredictors(

View file

@ -5,6 +5,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
internal struct BModeInfo
{
public PredictionMode Mode;
public Array2<Mv> Mv; // First, second inter predictor motion vectors
public Array2<Mv> Mv; // First, second inter predictor motion vectors
}
}

View file

@ -16,6 +16,6 @@
Block64x32 = 11,
Block64x64 = 12,
BlockSizes = 13,
BlockInvalid = BlockSizes
BlockInvalid = BlockSizes,
}
}

View file

@ -3,6 +3,6 @@
internal enum FrameType
{
KeyFrame = 0,
InterFrame = 1
InterFrame = 1,
}
}

View file

@ -6,7 +6,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
// passed it can be loaded into vector registers.
internal struct LoopFilterThresh
{
#pragma warning disable CS0649
#pragma warning disable CS0649 // Field is never assigned to
public Array16<byte> Mblim;
public Array16<byte> Lim;
public Array16<byte> HevThr;

View file

@ -54,7 +54,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
public Ptr<InternalErrorInfo> ErrorInfo;
public int GetPredContextSegId()
public readonly int GetPredContextSegId()
{
sbyte aboveSip = !AboveMi.IsNull ? AboveMi.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;
}
public int GetSkipContext()
public readonly int GetSkipContext()
{
int aboveSkip = !AboveMi.IsNull ? AboveMi.Value.Skip : 0;
int leftSkip = !LeftMi.IsNull ? LeftMi.Value.Skip : 0;
return aboveSkip + leftSkip;
}
public int GetPredContextSwitchableInterp()
public readonly int GetPredContextSwitchableInterp()
{
// Note:
// 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
// 2 - intra/--, --/intra
// 3 - intra/intra
public int GetIntraInterContext()
public readonly int GetIntraInterContext()
{
if (!AboveMi.IsNull && !LeftMi.IsNull)
{ // Both edges available
{ // Both edges available
bool aboveIntra = !AboveMi.Value.IsInterBlock();
bool leftIntra = !LeftMi.Value.IsInterBlock();
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 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
// left of the entries corresponding to real blocks.
// 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 aboveCtx = (!AboveMi.IsNull && AboveMi.Value.Skip == 0) ? (int)AboveMi.Value.TxSize : maxTxSize;

View file

@ -11,7 +11,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
public TxSize TxSize;
public sbyte Skip;
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
public PredictionMode UvMode;
@ -32,10 +32,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
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 ||
Luts.SsSizeLookup[(int)SbType][pd.SubsamplingX][pd.SubsamplingY] != BlockSize.BlockInvalid);
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;
}
private static readonly int[][] IdxNColumnToSubblock = new int[][]
{
new int[] { 1, 2 }, new int[] { 1, 3 }, new int[] { 3, 2 }, new int[] { 3, 3 }
private static readonly int[][] _idxNColumnToSubblock = {
new[] { 1, 2 }, new[] { 1, 3 }, new[] { 3, 2 }, new[] { 3, 3 },
};
// 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)
{
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];
}
}

View file

@ -9,6 +9,6 @@
BothNew = 4,
IntraPlusNonIntra = 5,
BothIntra = 6,
InvalidCase = 9
InvalidCase = 9,
}
}

View file

@ -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, 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
return Math.Abs(Row) < kMvRefThresh && Math.Abs(Col) < kMvRefThresh;
const int KMvRefThresh = 64; // Threshold for use of high-precision 1/8 mv
return Math.Abs(Row) < KMvRefThresh && Math.Abs(Col) < KMvRefThresh;
}
public static bool MvJointVertical(MvJointType type)
@ -110,7 +110,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
else
{
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)
{
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)
{
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)
{
@ -158,7 +156,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
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)
{

View file

@ -7,6 +7,6 @@
PartitionVert,
PartitionSplit,
PartitionTypes,
PartitionInvalid = PartitionTypes
PartitionInvalid = PartitionTypes,
}
}

View file

@ -4,6 +4,6 @@
{
Y = 0,
Uv = 1,
PlaneTypes
PlaneTypes,
}
}

View file

@ -2,20 +2,20 @@
{
internal enum PredictionMode
{
DcPred = 0, // Average of above and left pixels
VPred = 1, // Vertical
HPred = 2, // Horizontal
D45Pred = 3, // Directional 45 deg = round(arctan(1 / 1) * 180 / pi)
D135Pred = 4, // Directional 135 deg = 180 - 45
D117Pred = 5, // Directional 117 deg = 180 - 63
D153Pred = 6, // Directional 153 deg = 180 - 27
D207Pred = 7, // Directional 207 deg = 180 + 27
D63Pred = 8, // Directional 63 deg = round(arctan(2 / 1) * 180 / pi)
TmPred = 9, // True-motion
DcPred = 0, // Average of above and left pixels
VPred = 1, // Vertical
HPred = 2, // Horizontal
D45Pred = 3, // Directional 45 deg = round(arctan(1 / 1) * 180 / pi)
D135Pred = 4, // Directional 135 deg = 180 - 45
D117Pred = 5, // Directional 117 deg = 180 - 63
D153Pred = 6, // Directional 153 deg = 180 - 27
D207Pred = 7, // Directional 207 deg = 180 + 27
D63Pred = 8, // Directional 63 deg = round(arctan(2 / 1) * 180 / pi)
TmPred = 9, // True-motion
NearestMv = 10,
NearMv = 11,
ZeroMv = 12,
NewMv = 13,
MbModeCount = 14
MbModeCount = 14,
}
}

View file

@ -5,6 +5,6 @@
SingleReference = 0,
CompoundReference = 1,
ReferenceModeSelect = 2,
ReferenceModes = 3
ReferenceModes = 3,
}
}

View file

@ -38,263 +38,255 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
int h,
int bd);
private static readonly unsafe ConvolveFn[][][] PredictX16Y16 = new ConvolveFn[][][]
{
new ConvolveFn[][]
private static readonly unsafe ConvolveFn[][][] _predictX16Y16 = {
new[]
{
new ConvolveFn[]
{
ConvolveCopy,
ConvolveAvg
ConvolveAvg,
},
new ConvolveFn[]
{
Convolve8Vert,
Convolve8AvgVert
}
Convolve8AvgVert,
},
},
new ConvolveFn[][]
new[]
{
new ConvolveFn[]
{
Convolve8Horiz,
Convolve8AvgHoriz
Convolve8AvgHoriz,
},
new ConvolveFn[]
{
Convolve8,
Convolve8Avg
}
}
Convolve8Avg,
},
},
};
private static readonly unsafe ConvolveFn[][][] PredictX16 = new ConvolveFn[][][]
{
new ConvolveFn[][]
private static readonly unsafe ConvolveFn[][][] _predictX16 = {
new[]
{
new ConvolveFn[]
{
ScaledVert,
ScaledAvgVert
ScaledAvgVert,
},
new ConvolveFn[]
{
ScaledVert,
ScaledAvgVert
}
ScaledAvgVert,
},
},
new ConvolveFn[][]
new[]
{
new ConvolveFn[]
{
Scaled2D,
ScaledAvg2D
ScaledAvg2D,
},
new ConvolveFn[]
{
Scaled2D,
ScaledAvg2D
}
}
ScaledAvg2D,
},
},
};
private static readonly unsafe ConvolveFn[][][] PredictY16 = new ConvolveFn[][][]
{
new ConvolveFn[][]
private static readonly unsafe ConvolveFn[][][] _predictY16 = {
new[]
{
new ConvolveFn[]
{
ScaledHoriz,
ScaledAvgHoriz
ScaledAvgHoriz,
},
new ConvolveFn[]
{
Scaled2D,
ScaledAvg2D
}
ScaledAvg2D,
},
},
new ConvolveFn[][]
new[]
{
new ConvolveFn[]
{
ScaledHoriz,
ScaledAvgHoriz
ScaledAvgHoriz,
},
new ConvolveFn[]
{
Scaled2D,
ScaledAvg2D
}
}
};
private static readonly unsafe ConvolveFn[][][] Predict = new ConvolveFn[][][]
{
new ConvolveFn[][]
{
new ConvolveFn[]
{
Scaled2D,
ScaledAvg2D
ScaledAvg2D,
},
new ConvolveFn[]
{
Scaled2D,
ScaledAvg2D
}
},
new ConvolveFn[][]
};
private static readonly unsafe ConvolveFn[][][] _predict = {
new[]
{
new ConvolveFn[]
{
Scaled2D,
ScaledAvg2D
ScaledAvg2D,
},
new ConvolveFn[]
{
Scaled2D,
ScaledAvg2D
}
}
ScaledAvg2D,
},
},
new[]
{
new ConvolveFn[]
{
Scaled2D,
ScaledAvg2D,
},
new ConvolveFn[]
{
Scaled2D,
ScaledAvg2D,
},
},
};
private static readonly unsafe HighbdConvolveFn[][][] HighbdPredictX16Y16 = new HighbdConvolveFn[][][]
{
new HighbdConvolveFn[][]
private static readonly unsafe HighbdConvolveFn[][][] _highbdPredictX16Y16 = {
new[]
{
new HighbdConvolveFn[]
{
HighbdConvolveCopy,
HighbdConvolveAvg
HighbdConvolveAvg,
},
new HighbdConvolveFn[]
{
HighbdConvolve8Vert,
HighbdConvolve8AvgVert
}
HighbdConvolve8AvgVert,
},
},
new HighbdConvolveFn[][]
new[]
{
new HighbdConvolveFn[]
{
HighbdConvolve8Horiz,
HighbdConvolve8AvgHoriz
HighbdConvolve8AvgHoriz,
},
new HighbdConvolveFn[]
{
HighbdConvolve8,
HighbdConvolve8Avg
}
}
HighbdConvolve8Avg,
},
},
};
private static readonly unsafe HighbdConvolveFn[][][] HighbdPredictX16 = new HighbdConvolveFn[][][]
{
new HighbdConvolveFn[][]
private static readonly unsafe HighbdConvolveFn[][][] _highbdPredictX16 = {
new[]
{
new HighbdConvolveFn[]
{
HighbdConvolve8Vert,
HighbdConvolve8AvgVert
HighbdConvolve8AvgVert,
},
new HighbdConvolveFn[]
{
HighbdConvolve8Vert,
HighbdConvolve8AvgVert
}
HighbdConvolve8AvgVert,
},
},
new HighbdConvolveFn[][]
new[]
{
new HighbdConvolveFn[]
{
HighbdConvolve8,
HighbdConvolve8Avg
HighbdConvolve8Avg,
},
new HighbdConvolveFn[]
{
HighbdConvolve8,
HighbdConvolve8Avg
}
}
HighbdConvolve8Avg,
},
},
};
private static readonly unsafe HighbdConvolveFn[][][] HighbdPredictY16 = new HighbdConvolveFn[][][]
{
new HighbdConvolveFn[][]
private static readonly unsafe HighbdConvolveFn[][][] _highbdPredictY16 = {
new[]
{
new HighbdConvolveFn[]
{
HighbdConvolve8Horiz,
HighbdConvolve8AvgHoriz
HighbdConvolve8AvgHoriz,
},
new HighbdConvolveFn[]
{
HighbdConvolve8,
HighbdConvolve8Avg
}
HighbdConvolve8Avg,
},
},
new HighbdConvolveFn[][]
new[]
{
new HighbdConvolveFn[]
{
HighbdConvolve8Horiz,
HighbdConvolve8AvgHoriz
HighbdConvolve8AvgHoriz,
},
new HighbdConvolveFn[]
{
HighbdConvolve8,
HighbdConvolve8Avg
}
}
};
private static readonly unsafe HighbdConvolveFn[][][] HighbdPredict = new HighbdConvolveFn[][][]
{
new HighbdConvolveFn[][]
{
new HighbdConvolveFn[]
{
HighbdConvolve8,
HighbdConvolve8Avg
HighbdConvolve8Avg,
},
new HighbdConvolveFn[]
{
HighbdConvolve8,
HighbdConvolve8Avg
}
},
new HighbdConvolveFn[][]
};
private static readonly unsafe HighbdConvolveFn[][][] _highbdPredict = {
new[]
{
new HighbdConvolveFn[]
{
HighbdConvolve8,
HighbdConvolve8Avg
HighbdConvolve8Avg,
},
new HighbdConvolveFn[]
{
HighbdConvolve8,
HighbdConvolve8Avg
}
}
HighbdConvolve8Avg,
},
},
new[]
{
new HighbdConvolveFn[]
{
HighbdConvolve8,
HighbdConvolve8Avg,
},
new HighbdConvolveFn[]
{
HighbdConvolve8,
HighbdConvolve8Avg,
},
},
};
public int XScaleFP; // Horizontal fixed point scale factor
public int YScaleFP; // Vertical fixed point scale factor
public int XScaleFP; // Horizontal fixed point scale factor
public int YScaleFP; // Vertical fixed point scale factor
public int XStepQ4;
public int YStepQ4;
public int ScaleValueX(int val)
public readonly int ScaleValueX(int val)
{
return IsScaled() ? ScaledX(val) : val;
}
public int ScaleValueY(int val)
public readonly int ScaleValueY(int val)
{
return IsScaled() ? ScaledY(val) : val;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe void InterPredict(
public readonly unsafe void InterPredict(
int horiz,
int vert,
int avg,
@ -315,12 +307,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
if (YStepQ4 == 16)
{
// 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
{
// 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
@ -328,18 +320,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
if (YStepQ4 == 16)
{
// No scaling in the y direction. Must always scale in the x direction.
PredictY16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h);
_predictY16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h);
}
else
{
// Must always scale in both directions.
Predict[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h);
_predict[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h);
}
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe void HighbdInterPredict(
public readonly unsafe void HighbdInterPredict(
int horiz,
int vert,
int avg,
@ -361,12 +353,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
if (YStepQ4 == 16)
{
// 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
{
// 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
@ -374,22 +366,22 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
if (YStepQ4 == 16)
{
// No scaling in the y direction. Must always scale in the x direction.
HighbdPredictY16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd);
_highbdPredictY16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd);
}
else
{
// Must always scale in both directions.
HighbdPredict[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd);
_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);
}
private int ScaledY(int val)
private readonly int ScaledY(int val)
{
return (int)((long)val * YScaleFP >> RefScaleShift);
}
@ -407,20 +399,21 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{
int xOffQ4 = ScaledX(x << SubpelBits) & SubpelMask;
int yOffQ4 = ScaledY(y << SubpelBits) & SubpelMask;
Mv32 res = new Mv32()
Mv32 res = new()
{
Row = ScaledY(mv.Row) + yOffQ4,
Col = ScaledX(mv.Col) + xOffQ4
Col = ScaledX(mv.Col) + xOffQ4,
};
return res;
}
public bool IsValidScale()
public readonly bool IsValidScale()
{
return XScaleFP != RefInvalidScale && YScaleFP != RefInvalidScale;
}
public bool IsScaled()
public readonly bool IsScaled()
{
return IsValidScale() && (XScaleFP != RefNoScale || YScaleFP != RefNoScale);
}
@ -439,6 +432,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{
XScaleFP = RefInvalidScale;
YScaleFP = RefInvalidScale;
return;
}

View file

@ -2,10 +2,10 @@
{
internal enum SegLvlFeatures
{
SegLvlAltQ = 0, // Use alternate Quantizer ....
SegLvlAltLf = 1, // Use alternate loop filter value...
SegLvlRefFrame = 2, // Optional Segment reference frame
SegLvlSkip = 3, // Optional Segment (0,0) + skip mode
SegLvlMax = 4 // Number of features supported
SegLvlAltQ = 0, // Use alternate Quantizer ....
SegLvlAltLf = 1, // Use alternate loop filter value...
SegLvlRefFrame = 2, // Optional Segment reference frame
SegLvlSkip = 3, // Optional Segment (0,0) + skip mode
SegLvlMax = 4, // Number of features supported
}
}

View file

@ -6,8 +6,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{
internal struct Segmentation
{
private static readonly int[] SegFeatureDataSigned = new int[] { 1, 1, 0, 0 };
private static readonly int[] SegFeatureDataMax = new int[] { QuantCommon.MaxQ, Vp9.LoopFilter.MaxLoopFilter, 3, 0 };
private static readonly int[] _segFeatureDataSigned = { 1, 1, 0, 0 };
private static readonly int[] _segFeatureDataMax = { QuantCommon.MaxQ, Vp9.LoopFilter.MaxLoopFilter, 3, 0 };
public bool Enabled;
public bool UpdateMap;
@ -26,8 +26,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
public void ClearAllSegFeatures()
{
MemoryMarshal.CreateSpan(ref FeatureData[0][0], 8 * 4).Fill(0);
MemoryMarshal.CreateSpan(ref FeatureMask[0], 8).Fill(0);
MemoryMarshal.CreateSpan(ref FeatureData[0][0], 8 * 4).Clear();
MemoryMarshal.CreateSpan(ref FeatureMask[0], 8).Clear();
AqAvOffset = 0;
}
@ -38,21 +38,21 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
internal static int FeatureDataMax(SegLvlFeatures featureId)
{
return SegFeatureDataMax[(int)featureId];
return _segFeatureDataMax[(int)featureId];
}
internal static int IsSegFeatureSigned(SegLvlFeatures featureId)
{
return SegFeatureDataSigned[(int)featureId];
return _segFeatureDataSigned[(int)featureId];
}
internal void SetSegData(int segmentId, SegLvlFeatures featureId, int segData)
{
Debug.Assert(segData <= SegFeatureDataMax[(int)featureId]);
Debug.Assert(segData <= _segFeatureDataMax[(int)featureId]);
if (segData < 0)
{
Debug.Assert(SegFeatureDataSigned[(int)featureId] != 0);
Debug.Assert(-segData <= SegFeatureDataMax[(int)featureId]);
Debug.Assert(_segFeatureDataSigned[(int)featureId] != 0);
Debug.Assert(-segData <= _segFeatureDataMax[(int)featureId]);
}
FeatureData[segmentId][(int)featureId] = (short)segData;

View file

@ -11,11 +11,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
public ArrayPtr<byte> UBuffer;
public ArrayPtr<byte> VBuffer;
public unsafe Plane YPlane => new Plane((IntPtr)YBuffer.ToPointer(), YBuffer.Length);
public unsafe Plane UPlane => new Plane((IntPtr)UBuffer.ToPointer(), UBuffer.Length);
public unsafe Plane VPlane => new Plane((IntPtr)VBuffer.ToPointer(), VBuffer.Length);
public readonly unsafe Plane YPlane => new((IntPtr)YBuffer.ToPointer(), YBuffer.Length);
public readonly unsafe Plane UPlane => new((IntPtr)UBuffer.ToPointer(), UBuffer.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 Height { get; }
@ -27,29 +27,31 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
public int UvAlignedWidth { get; }
public int UvAlignedHeight { get; }
public int UvStride { get; }
public bool HighBd => false;
public bool HighBd { get; }
private readonly IntPtr _pointer;
public Surface(int width, int height)
{
const int border = 32;
const int ssX = 1;
const int ssY = 1;
const bool highbd = false;
HighBd = false;
const int Border = 32;
const int SsX = 1;
const int SsY = 1;
int alignedWidth = (width + 7) & ~7;
int alignedHeight = (height + 7) & ~7;
int yStride = ((alignedWidth + 2 * border) + 31) & ~31;
int yplaneSize = (alignedHeight + 2 * border) * yStride;
int uvWidth = alignedWidth >> ssX;
int uvHeight = alignedHeight >> ssY;
int uvStride = yStride >> ssX;
int uvBorderW = border >> ssX;
int uvBorderH = border >> ssY;
int yStride = ((alignedWidth + 2 * Border) + 31) & ~31;
int yplaneSize = (alignedHeight + 2 * Border) * yStride;
int uvWidth = alignedWidth >> SsX;
int uvHeight = alignedHeight >> SsY;
int uvStride = yStride >> SsX;
int uvBorderW = Border >> SsX;
int uvBorderH = Border >> SsY;
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);
_pointer = pointer;
@ -58,23 +60,23 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
AlignedWidth = alignedWidth;
AlignedHeight = alignedHeight;
Stride = yStride;
UvWidth = (width + ssX) >> ssX;
UvHeight = (height + ssY) >> ssY;
UvWidth = (width + SsX) >> SsX;
UvHeight = (height + SsY) >> SsY;
UvAlignedWidth = uvWidth;
UvAlignedHeight = uvHeight;
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);
VBuffer = NewPlane(yplaneSize + uvplaneSize, uvplaneSize, (uvBorderH * uvStride) + uvBorderW);
}
public void Dispose()
public readonly void Dispose()
{
Marshal.FreeHGlobal(_pointer);
}

View file

@ -21,6 +21,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{
int sbCols = MiColsAlignedToSb(mis) >> Constants.MiBlockSizeLog2;
int offset = ((idx * sbCols) >> log2) << Constants.MiBlockSizeLog2;
return Math.Min(offset, mis);
}
@ -44,7 +45,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
// Checks that the given miRow, miCol and search point
// 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 ||
miCol + miPos.Col < MiColStart ||

View file

@ -2,11 +2,11 @@
{
public enum TxMode
{
Only4X4 = 0, // Only 4x4 transform used
Allow8X8 = 1, // Allow block transform size up to 8x8
Allow16X16 = 2, // Allow block transform size up to 16x16
Allow32X32 = 3, // Allow block transform size up to 32x32
Only4X4 = 0, // Only 4x4 transform used
Allow8X8 = 1, // Allow block transform size up to 8x8
Allow16X16 = 2, // Allow block transform size up to 16x16
Allow32X32 = 3, // Allow block transform size up to 32x32
TxModeSelect = 4, // Transform specified for each block
TxModes = 5
TxModes = 5,
}
}

View file

@ -2,10 +2,10 @@
{
public enum TxSize
{
Tx4x4 = 0, // 4x4 transform
Tx8x8 = 1, // 8x8 transform
Tx4x4 = 0, // 4x4 transform
Tx8x8 = 1, // 8x8 transform
Tx16x16 = 2, // 16x16 transform
Tx32x32 = 3, // 32x32 transform
TxSizes = 4
TxSizes = 4,
}
}

View file

@ -2,10 +2,10 @@
{
internal enum TxType
{
DctDct = 0, // DCT in both horizontal and vertical
AdstDct = 1, // ADST in vertical, DCT in horizontal
DctAdst = 2, // DCT in vertical, ADST in horizontal
DctDct = 0, // DCT in both horizontal and vertical
AdstDct = 1, // ADST in vertical, DCT in horizontal
DctAdst = 2, // DCT in vertical, ADST in horizontal
AdstAdst = 3, // ADST in both directions
TxTypes = 4
TxTypes = 4,
}
}

View file

@ -88,7 +88,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
public ArrayPtr<sbyte> AboveSegContext;
public ArrayPtr<sbyte> AboveContext;
public bool FrameIsIntraOnly()
public readonly bool FrameIsIntraOnly()
{
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));
}
public void FreeTileWorkerData(MemoryAllocator allocator)
public readonly void FreeTileWorkerData(MemoryAllocator allocator)
{
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()
? new ArrayPtr<Array3<byte>>(ref Fc.Value.KfPartitionProb[0], 16)
@ -293,7 +293,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
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.
if (Seg.Enabled)
{
@ -301,10 +301,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
for (i = 0; i < Constants.MaxSegments; ++i)
{
int qIndex = QuantCommon.GetQIndex(ref Seg, i, BaseQindex);
YDequant[i][0] = QuantCommon.DcQuant(qIndex, YDcDeltaQ, bitDepth);
YDequant[i][1] = QuantCommon.AcQuant(qIndex, 0, bitDepth);
UvDequant[i][0] = QuantCommon.DcQuant(qIndex, UvDcDeltaQ, bitDepth);
UvDequant[i][1] = QuantCommon.AcQuant(qIndex, UvAcDeltaQ, bitDepth);
YDequant[i][0] = QuantCommon.DcQuant(qIndex, YDcDeltaQ, BitDepth);
YDequant[i][1] = QuantCommon.AcQuant(qIndex, 0, BitDepth);
UvDequant[i][0] = QuantCommon.DcQuant(qIndex, UvDcDeltaQ, BitDepth);
UvDequant[i][1] = QuantCommon.AcQuant(qIndex, UvAcDeltaQ, BitDepth);
}
}
else
@ -312,10 +312,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
int qIndex = BaseQindex;
// When segmentation is disabled, only the first value is used. The
// remaining are don't cares.
YDequant[0][0] = QuantCommon.DcQuant(qIndex, YDcDeltaQ, bitDepth);
YDequant[0][1] = QuantCommon.AcQuant(qIndex, 0, bitDepth);
UvDequant[0][0] = QuantCommon.DcQuant(qIndex, UvDcDeltaQ, bitDepth);
UvDequant[0][1] = QuantCommon.AcQuant(qIndex, UvAcDeltaQ, bitDepth);
YDequant[0][0] = QuantCommon.DcQuant(qIndex, YDcDeltaQ, BitDepth);
YDequant[0][1] = QuantCommon.AcQuant(qIndex, 0, BitDepth);
UvDequant[0][0] = QuantCommon.DcQuant(qIndex, UvDcDeltaQ, BitDepth);
UvDequant[0][1] = QuantCommon.AcQuant(qIndex, UvAcDeltaQ, BitDepth);
}
}