Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
6aa8d71588 | ||
|
9becbd7d72 |
@@ -51,6 +51,6 @@
|
||||
/*!\brief An iterator reached the end of list.
|
||||
*
|
||||
*/
|
||||
CodecListEnd
|
||||
CodecListEnd,
|
||||
}
|
||||
}
|
||||
|
@@ -20,7 +20,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common
|
||||
{
|
||||
10 => (ushort)Math.Clamp(val, 0, 1023),
|
||||
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);
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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();
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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(
|
||||
|
@@ -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)
|
||||
|
@@ -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..];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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(
|
||||
|
@@ -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
|
||||
}
|
||||
}
|
||||
|
@@ -16,6 +16,6 @@
|
||||
Block64x32 = 11,
|
||||
Block64x64 = 12,
|
||||
BlockSizes = 13,
|
||||
BlockInvalid = BlockSizes
|
||||
BlockInvalid = BlockSizes,
|
||||
}
|
||||
}
|
||||
|
@@ -3,6 +3,6 @@
|
||||
internal enum FrameType
|
||||
{
|
||||
KeyFrame = 0,
|
||||
InterFrame = 1
|
||||
InterFrame = 1,
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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];
|
||||
}
|
||||
}
|
||||
|
@@ -9,6 +9,6 @@
|
||||
BothNew = 4,
|
||||
IntraPlusNonIntra = 5,
|
||||
BothIntra = 6,
|
||||
InvalidCase = 9
|
||||
InvalidCase = 9,
|
||||
}
|
||||
}
|
||||
|
@@ -51,13 +51,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 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)
|
||||
{
|
||||
|
@@ -7,6 +7,6 @@
|
||||
PartitionVert,
|
||||
PartitionSplit,
|
||||
PartitionTypes,
|
||||
PartitionInvalid = PartitionTypes
|
||||
PartitionInvalid = PartitionTypes,
|
||||
}
|
||||
}
|
||||
|
@@ -4,6 +4,6 @@
|
||||
{
|
||||
Y = 0,
|
||||
Uv = 1,
|
||||
PlaneTypes
|
||||
PlaneTypes,
|
||||
}
|
||||
}
|
||||
|
@@ -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,
|
||||
}
|
||||
}
|
||||
|
@@ -5,6 +5,6 @@
|
||||
SingleReference = 0,
|
||||
CompoundReference = 1,
|
||||
ReferenceModeSelect = 2,
|
||||
ReferenceModes = 3
|
||||
ReferenceModes = 3,
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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 ||
|
||||
|
@@ -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,
|
||||
}
|
||||
}
|
||||
|
@@ -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,
|
||||
}
|
||||
}
|
||||
|
@@ -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,
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -9,6 +9,6 @@ namespace Ryujinx.Graphics.Shader
|
||||
Greater,
|
||||
NotEqual,
|
||||
GreaterOrEqual,
|
||||
Always
|
||||
Always,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -8,7 +8,7 @@ namespace Ryujinx.Graphics.Shader
|
||||
// Generic types.
|
||||
Float,
|
||||
Sint,
|
||||
Uint
|
||||
Uint,
|
||||
}
|
||||
|
||||
static class AttributeTypeExtensions
|
||||
@@ -20,7 +20,7 @@ namespace Ryujinx.Graphics.Shader
|
||||
AttributeType.Float => "vec4",
|
||||
AttributeType.Sint => "ivec4",
|
||||
AttributeType.Uint => "uvec4",
|
||||
_ => throw new ArgumentException($"Invalid attribute type \"{type}\".")
|
||||
_ => throw new ArgumentException($"Invalid attribute type \"{type}\"."),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -31,8 +31,8 @@ namespace Ryujinx.Graphics.Shader
|
||||
AttributeType.Float => AggregateType.FP32,
|
||||
AttributeType.Sint => AggregateType.S32,
|
||||
AttributeType.Uint => AggregateType.U32,
|
||||
_ => throw new ArgumentException($"Invalid attribute type \"{type}\".")
|
||||
_ => throw new ArgumentException($"Invalid attribute type \"{type}\"."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -37,4 +37,4 @@ namespace Ryujinx.Graphics.Shader
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -13,6 +13,6 @@ namespace Ryujinx.Graphics.Shader
|
||||
/// <summary>
|
||||
/// Buffer is written to.
|
||||
/// </summary>
|
||||
Write = 1 << 0
|
||||
Write = 1 << 0,
|
||||
}
|
||||
}
|
||||
|
@@ -92,4 +92,4 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
return indentation;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -244,16 +244,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetTfLayout(TransformFeedbackOutput tfOutput)
|
||||
{
|
||||
if (tfOutput.Valid)
|
||||
{
|
||||
return $"layout (xfb_buffer = {tfOutput.Buffer}, xfb_offset = {tfOutput.Offset}, xfb_stride = {tfOutput.Stride}) ";
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public static void DeclareLocals(CodeGenContext context, StructuredFunction function)
|
||||
{
|
||||
foreach (AstOperand decl in function.Locals)
|
||||
@@ -294,7 +284,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
AggregateType.Vector4 | AggregateType.FP64 => "dvec4",
|
||||
AggregateType.Vector4 | AggregateType.S32 => "ivec4",
|
||||
AggregateType.Vector4 | AggregateType.U32 => "uvec4",
|
||||
_ => throw new ArgumentException($"Invalid variable type \"{type}\".")
|
||||
_ => throw new ArgumentException($"Invalid variable type \"{type}\"."),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -315,7 +305,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
string layout = buffer.Layout switch
|
||||
{
|
||||
BufferLayout.Std140 => "std140",
|
||||
_ => "std430"
|
||||
_ => "std430",
|
||||
};
|
||||
|
||||
string set = string.Empty;
|
||||
@@ -507,7 +497,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
{
|
||||
PixelImap.Constant => "flat ",
|
||||
PixelImap.ScreenLinear => "noperspective ",
|
||||
_ => string.Empty
|
||||
_ => string.Empty,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -524,7 +514,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
2 => "vec2",
|
||||
3 => "vec3",
|
||||
4 => "vec4",
|
||||
_ => "float"
|
||||
_ => "float",
|
||||
};
|
||||
|
||||
context.AppendLine($"layout (location = {attr}) in {type} {name};");
|
||||
@@ -611,7 +601,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
2 => "vec2",
|
||||
3 => "vec3",
|
||||
4 => "vec4",
|
||||
_ => "float"
|
||||
_ => "float",
|
||||
};
|
||||
|
||||
string xfb = string.Empty;
|
||||
@@ -647,7 +637,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
{
|
||||
AttributeType.Sint => "ivec4",
|
||||
AttributeType.Uint => "uvec4",
|
||||
_ => "vec4"
|
||||
_ => "vec4",
|
||||
};
|
||||
|
||||
if (context.Config.GpuAccessor.QueryHostReducedPrecision() && context.Config.Stage == ShaderStage.Vertex && attr == 0)
|
||||
@@ -721,4 +711,4 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
context.AppendLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
public const string LocalNamePrefix = "temp";
|
||||
|
||||
public const string SamplerNamePrefix = "tex";
|
||||
public const string ImageNamePrefix = "img";
|
||||
public const string ImageNamePrefix = "img";
|
||||
|
||||
public const string PerPatchAttributePrefix = "patch_attr_";
|
||||
public const string IAttributePrefix = "in_attr";
|
||||
@@ -15,4 +15,4 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
|
||||
public const string UndefinedName = "undef";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -13,7 +13,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
|
||||
public static string Generate(StructuredProgramInfo info, ShaderConfig config)
|
||||
{
|
||||
CodeGenContext context = new CodeGenContext(info, config);
|
||||
CodeGenContext context = new(info, config);
|
||||
|
||||
Declarations.Declare(context, info);
|
||||
|
||||
@@ -74,7 +74,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
|
||||
private static void PrintBlock(CodeGenContext context, AstBlock block, bool isMainFunction)
|
||||
{
|
||||
AstBlockVisitor visitor = new AstBlockVisitor(block);
|
||||
AstBlockVisitor visitor = new(block);
|
||||
|
||||
visitor.BlockEntered += (sender, e) =>
|
||||
{
|
||||
@@ -96,7 +96,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
context.AppendLine($"if ({GetCondExpr(context, e.Block.Condition)})");
|
||||
break;
|
||||
|
||||
default: throw new InvalidOperationException($"Found unexpected block type \"{e.Block.Type}\".");
|
||||
default:
|
||||
throw new InvalidOperationException($"Found unexpected block type \"{e.Block.Type}\".");
|
||||
}
|
||||
|
||||
context.EnterScope();
|
||||
@@ -173,4 +174,4 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
return ReinterpretCast(context, cond, srcType, AggregateType.Bool);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -5,10 +5,10 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
public static string MultiplyHighS32 = "Helper_MultiplyHighS32";
|
||||
public static string MultiplyHighU32 = "Helper_MultiplyHighU32";
|
||||
|
||||
public static string Shuffle = "Helper_Shuffle";
|
||||
public static string Shuffle = "Helper_Shuffle";
|
||||
public static string ShuffleDown = "Helper_ShuffleDown";
|
||||
public static string ShuffleUp = "Helper_ShuffleUp";
|
||||
public static string ShuffleXor = "Helper_ShuffleXor";
|
||||
public static string SwizzleAdd = "Helper_SwizzleAdd";
|
||||
public static string ShuffleUp = "Helper_ShuffleUp";
|
||||
public static string ShuffleXor = "Helper_ShuffleXor";
|
||||
public static string SwizzleAdd = "Helper_SwizzleAdd";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -197,4 +197,4 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
throw new InvalidOperationException($"Unexpected instruction type \"{info.Type}\".");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -24,4 +24,4 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -26,4 +26,4 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
return $"{function.Name}({string.Join(", ", args)})";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -26,4 +26,4 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -14,6 +14,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
{
|
||||
_infoTable = new InstInfo[(int)Instruction.Count];
|
||||
|
||||
#pragma warning disable IDE0055 // Disable formatting
|
||||
Add(Instruction.AtomicAdd, InstType.AtomicBinary, "atomicAdd");
|
||||
Add(Instruction.AtomicAnd, InstType.AtomicBinary, "atomicAnd");
|
||||
Add(Instruction.AtomicCompareAndSwap, InstType.AtomicTernary, "atomicCompSwap");
|
||||
@@ -125,6 +126,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
Add(Instruction.VoteAll, InstType.CallUnary, "allInvocationsARB");
|
||||
Add(Instruction.VoteAllEqual, InstType.CallUnary, "allInvocationsEqualARB");
|
||||
Add(Instruction.VoteAny, InstType.CallUnary, "anyInvocationARB");
|
||||
#pragma warning restore IDE0055
|
||||
}
|
||||
|
||||
private static void Add(Instruction inst, InstType flags, string opName = null, int precedence = 0)
|
||||
@@ -163,7 +165,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
{
|
||||
// If the node isn't a operation, then it can only be a operand,
|
||||
// and those never needs to be surrounded in parenthesis.
|
||||
if (!(node is AstOperation operation))
|
||||
if (node is not AstOperation operation)
|
||||
{
|
||||
// This is sort of a special case, if this is a negative constant,
|
||||
// and it is consumed by a unary operation, we need to put on the parenthesis,
|
||||
@@ -208,7 +210,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
|
||||
private static bool IsNegativeConst(IAstNode node)
|
||||
{
|
||||
if (!(node is AstOperand operand))
|
||||
if (node is not AstOperand operand)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -216,4 +218,4 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
return operand.Type == OperandType.Constant && operand.Value < 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -3,7 +3,6 @@ using Ryujinx.Graphics.Shader.StructuredIr;
|
||||
using Ryujinx.Graphics.Shader.Translation;
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenHelper;
|
||||
using static Ryujinx.Graphics.Shader.StructuredIr.InstructionInfo;
|
||||
|
||||
@@ -42,14 +41,16 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
}
|
||||
}
|
||||
|
||||
bool isArray = (texOp.Type & SamplerType.Array) != 0;
|
||||
bool isArray = (texOp.Type & SamplerType.Array) != 0;
|
||||
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
|
||||
|
||||
var texCallBuilder = new StringBuilder();
|
||||
|
||||
if (texOp.Inst == Instruction.ImageAtomic)
|
||||
{
|
||||
texCallBuilder.Append((texOp.Flags & TextureFlags.AtomicMask) switch {
|
||||
texCallBuilder.Append((texOp.Flags & TextureFlags.AtomicMask) switch
|
||||
{
|
||||
#pragma warning disable IDE0055 // Disable formatting
|
||||
TextureFlags.Add => "imageAtomicAdd",
|
||||
TextureFlags.Minimum => "imageAtomicMin",
|
||||
TextureFlags.Maximum => "imageAtomicMax",
|
||||
@@ -61,6 +62,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
TextureFlags.Swap => "imageAtomicExchange",
|
||||
TextureFlags.CAS => "imageAtomicCompSwap",
|
||||
_ => "imageAtomicAdd",
|
||||
#pragma warning restore IDE0055
|
||||
});
|
||||
}
|
||||
else
|
||||
@@ -131,7 +133,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
{
|
||||
AggregateType.S32 => NumberFormatter.FormatInt(0),
|
||||
AggregateType.U32 => NumberFormatter.FormatUint(0),
|
||||
_ => NumberFormatter.FormatFloat(0)
|
||||
_ => NumberFormatter.FormatFloat(0),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -140,7 +142,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
{
|
||||
AggregateType.S32 => "i",
|
||||
AggregateType.U32 => "u",
|
||||
_ => string.Empty
|
||||
_ => string.Empty,
|
||||
};
|
||||
|
||||
Append($"{prefix}vec4({string.Join(", ", cElems)})");
|
||||
@@ -159,7 +161,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
{
|
||||
TextureFlags.Increment => NumberFormatter.FormatInt(1, type), // TODO: Clamp value
|
||||
TextureFlags.Decrement => NumberFormatter.FormatInt(-1, type), // TODO: Clamp value
|
||||
_ => Src(type)
|
||||
_ => Src(type),
|
||||
};
|
||||
|
||||
Append(value);
|
||||
@@ -248,25 +250,25 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
{
|
||||
AstTextureOperation texOp = (AstTextureOperation)operation;
|
||||
|
||||
bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;
|
||||
bool isGather = (texOp.Flags & TextureFlags.Gather) != 0;
|
||||
bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;
|
||||
bool isGather = (texOp.Flags & TextureFlags.Gather) != 0;
|
||||
bool hasDerivatives = (texOp.Flags & TextureFlags.Derivatives) != 0;
|
||||
bool intCoords = (texOp.Flags & TextureFlags.IntCoords) != 0;
|
||||
bool hasLodBias = (texOp.Flags & TextureFlags.LodBias) != 0;
|
||||
bool hasLodLevel = (texOp.Flags & TextureFlags.LodLevel) != 0;
|
||||
bool hasOffset = (texOp.Flags & TextureFlags.Offset) != 0;
|
||||
bool hasOffsets = (texOp.Flags & TextureFlags.Offsets) != 0;
|
||||
bool intCoords = (texOp.Flags & TextureFlags.IntCoords) != 0;
|
||||
bool hasLodBias = (texOp.Flags & TextureFlags.LodBias) != 0;
|
||||
bool hasLodLevel = (texOp.Flags & TextureFlags.LodLevel) != 0;
|
||||
bool hasOffset = (texOp.Flags & TextureFlags.Offset) != 0;
|
||||
bool hasOffsets = (texOp.Flags & TextureFlags.Offsets) != 0;
|
||||
|
||||
bool isArray = (texOp.Type & SamplerType.Array) != 0;
|
||||
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
|
||||
bool isArray = (texOp.Type & SamplerType.Array) != 0;
|
||||
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
|
||||
bool isMultisample = (texOp.Type & SamplerType.Multisample) != 0;
|
||||
bool isShadow = (texOp.Type & SamplerType.Shadow) != 0;
|
||||
bool isShadow = (texOp.Type & SamplerType.Shadow) != 0;
|
||||
|
||||
bool colorIsVector = isGather || !isShadow;
|
||||
|
||||
SamplerType type = texOp.Type & SamplerType.Mask;
|
||||
|
||||
bool is2D = type == SamplerType.Texture2D;
|
||||
bool is2D = type == SamplerType.Texture2D;
|
||||
bool isCube = type == SamplerType.TextureCube;
|
||||
|
||||
// 2D Array and Cube shadow samplers with LOD level or bias requires an extension.
|
||||
@@ -500,14 +502,14 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
|
||||
if (hasLodBias)
|
||||
{
|
||||
Append(Src(AggregateType.FP32));
|
||||
Append(Src(AggregateType.FP32));
|
||||
}
|
||||
|
||||
// textureGather* optional extra component index,
|
||||
// not needed for shadow samplers.
|
||||
if (isGather && !isShadow)
|
||||
{
|
||||
Append(Src(AggregateType.S32));
|
||||
Append(Src(AggregateType.S32));
|
||||
}
|
||||
|
||||
texCall += ")" + (colorIsVector ? GetMaskMultiDest(texOp.Index) : "");
|
||||
@@ -584,7 +586,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
{
|
||||
case StorageKind.ConstantBuffer:
|
||||
case StorageKind.StorageBuffer:
|
||||
if (!(operation.GetSource(srcIndex++) is AstOperand bindingIndex) || bindingIndex.Type != OperandType.Constant)
|
||||
if (operation.GetSource(srcIndex++) is not AstOperand bindingIndex || bindingIndex.Type != OperandType.Constant)
|
||||
{
|
||||
throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand.");
|
||||
}
|
||||
@@ -594,7 +596,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
? context.Config.Properties.ConstantBuffers[binding]
|
||||
: context.Config.Properties.StorageBuffers[binding];
|
||||
|
||||
if (!(operation.GetSource(srcIndex++) is AstOperand fieldIndex) || fieldIndex.Type != OperandType.Constant)
|
||||
if (operation.GetSource(srcIndex++) is not AstOperand fieldIndex || fieldIndex.Type != OperandType.Constant)
|
||||
{
|
||||
throw new InvalidOperationException($"Second input of {operation.Inst} with {storageKind} storage must be a constant operand.");
|
||||
}
|
||||
@@ -606,7 +608,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
|
||||
case StorageKind.LocalMemory:
|
||||
case StorageKind.SharedMemory:
|
||||
if (!(operation.GetSource(srcIndex++) is AstOperand bindingId) || bindingId.Type != OperandType.Constant)
|
||||
if (operation.GetSource(srcIndex++) is not AstOperand { Type: OperandType.Constant } bindingId)
|
||||
{
|
||||
throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand.");
|
||||
}
|
||||
@@ -623,7 +625,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
case StorageKind.InputPerPatch:
|
||||
case StorageKind.Output:
|
||||
case StorageKind.OutputPerPatch:
|
||||
if (!(operation.GetSource(srcIndex++) is AstOperand varId) || varId.Type != OperandType.Constant)
|
||||
if (operation.GetSource(srcIndex++) is not AstOperand varId || varId.Type != OperandType.Constant)
|
||||
{
|
||||
throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand.");
|
||||
}
|
||||
@@ -636,7 +638,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
|
||||
if (context.Config.HasPerLocationInputOrOutput(ioVariable, isOutput))
|
||||
{
|
||||
if (!(operation.GetSource(srcIndex++) is AstOperand vecIndex) || vecIndex.Type != OperandType.Constant)
|
||||
if (operation.GetSource(srcIndex++) is not AstOperand vecIndex || vecIndex.Type != OperandType.Constant)
|
||||
{
|
||||
throw new InvalidOperationException($"Second input of {operation.Inst} with {storageKind} storage must be a constant operand.");
|
||||
}
|
||||
@@ -733,4 +735,4 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
return swizzle;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -53,4 +53,4 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
return $".{"xy".AsSpan(index, 1)}";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -29,4 +29,4 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -10,9 +10,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
|
||||
public InstInfo(InstType type, string opName, int precedence)
|
||||
{
|
||||
Type = type;
|
||||
OpName = opName;
|
||||
Type = type;
|
||||
OpName = opName;
|
||||
Precedence = precedence;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,33 +1,35 @@
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
{
|
||||
[Flags]
|
||||
[SuppressMessage("Design", "CA1069: Enums values should not be duplicated")]
|
||||
enum InstType
|
||||
{
|
||||
OpNullary = Op | 0,
|
||||
OpUnary = Op | 1,
|
||||
OpBinary = Op | 2,
|
||||
OpNullary = Op | 0,
|
||||
OpUnary = Op | 1,
|
||||
OpBinary = Op | 2,
|
||||
OpBinaryCom = Op | 2 | Commutative,
|
||||
OpTernary = Op | 3,
|
||||
OpTernary = Op | 3,
|
||||
|
||||
CallNullary = Call | 0,
|
||||
CallUnary = Call | 1,
|
||||
CallBinary = Call | 2,
|
||||
CallTernary = Call | 3,
|
||||
CallNullary = Call | 0,
|
||||
CallUnary = Call | 1,
|
||||
CallBinary = Call | 2,
|
||||
CallTernary = Call | 3,
|
||||
CallQuaternary = Call | 4,
|
||||
|
||||
// The atomic instructions have one extra operand,
|
||||
// for the storage slot and offset pair.
|
||||
AtomicBinary = Call | Atomic | 3,
|
||||
AtomicBinary = Call | Atomic | 3,
|
||||
AtomicTernary = Call | Atomic | 4,
|
||||
|
||||
Commutative = 1 << 8,
|
||||
Op = 1 << 9,
|
||||
Call = 1 << 10,
|
||||
Atomic = 1 << 11,
|
||||
Special = 1 << 12,
|
||||
Op = 1 << 9,
|
||||
Call = 1 << 10,
|
||||
Atomic = 1 << 11,
|
||||
Special = 1 << 12,
|
||||
|
||||
ArityMask = 0xff
|
||||
ArityMask = 0xff,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -28,7 +28,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
IoVariable.FragmentOutputColor => GetFragmentOutputColorVariableName(config, location),
|
||||
IoVariable.FragmentOutputDepth => ("gl_FragDepth", AggregateType.FP32),
|
||||
IoVariable.FrontColorDiffuse => ("gl_FrontColor", AggregateType.Vector4 | AggregateType.FP32), // Deprecated.
|
||||
IoVariable.FrontColorSpecular => ("gl_FrontSecondaryColor", AggregateType.Vector4 | AggregateType.FP32), // Deprecated.
|
||||
IoVariable.FrontColorSpecular => ("gl_FrontSecondaryColor", AggregateType.Vector4 | AggregateType.FP32), // Deprecated.
|
||||
IoVariable.FrontFacing => ("gl_FrontFacing", AggregateType.Bool),
|
||||
IoVariable.InstanceId => ("gl_InstanceID", AggregateType.S32),
|
||||
IoVariable.InstanceIndex => ("gl_InstanceIndex", AggregateType.S32),
|
||||
@@ -56,7 +56,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
IoVariable.VertexIndex => ("gl_VertexIndex", AggregateType.S32),
|
||||
IoVariable.ViewportIndex => ("gl_ViewportIndex", AggregateType.S32),
|
||||
IoVariable.ViewportMask => ("gl_ViewportMask", AggregateType.Array | AggregateType.S32),
|
||||
_ => (null, AggregateType.Invalid)
|
||||
_ => (null, AggregateType.Invalid),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -139,4 +139,4 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||
return (name, config.GetUserDefinedType(location, isOutput));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -101,4 +101,4 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
return "0x" + value.ToString("X", CultureInfo.InvariantCulture) + "u";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -5,7 +5,6 @@ using Ryujinx.Graphics.Shader.Translation;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
using static Ryujinx.Graphics.Shader.StructuredIr.InstructionInfo;
|
||||
|
||||
namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
@@ -14,7 +13,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
{
|
||||
private static readonly string[] _stagePrefixes = new string[] { "cp", "vp", "tcp", "tep", "gp", "fp" };
|
||||
|
||||
private Dictionary<AstOperand, string> _locals;
|
||||
private readonly Dictionary<AstOperand, string> _locals;
|
||||
|
||||
public OperandManager()
|
||||
{
|
||||
@@ -38,7 +37,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
OperandType.Constant => NumberFormatter.FormatInt(operand.Value),
|
||||
OperandType.LocalVariable => _locals[operand],
|
||||
OperandType.Undefined => DefaultNames.UndefinedName,
|
||||
_ => throw new ArgumentException($"Invalid operand type \"{operand.Type}\".")
|
||||
_ => throw new ArgumentException($"Invalid operand type \"{operand.Type}\"."),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -96,11 +95,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
return _stagePrefixes[index];
|
||||
}
|
||||
|
||||
private static char GetSwizzleMask(int value)
|
||||
{
|
||||
return "xyzw"[value];
|
||||
}
|
||||
|
||||
public static string GetArgumentName(int argIndex)
|
||||
{
|
||||
return $"{DefaultNames.ArgumentNamePrefix}{argIndex}";
|
||||
@@ -119,12 +113,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
{
|
||||
case StorageKind.ConstantBuffer:
|
||||
case StorageKind.StorageBuffer:
|
||||
if (!(operation.GetSource(0) is AstOperand bindingIndex) || bindingIndex.Type != OperandType.Constant)
|
||||
if (operation.GetSource(0) is not AstOperand bindingIndex || bindingIndex.Type != OperandType.Constant)
|
||||
{
|
||||
throw new InvalidOperationException($"First input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand.");
|
||||
}
|
||||
|
||||
if (!(operation.GetSource(1) is AstOperand fieldIndex) || fieldIndex.Type != OperandType.Constant)
|
||||
if (operation.GetSource(1) is not AstOperand fieldIndex || fieldIndex.Type != OperandType.Constant)
|
||||
{
|
||||
throw new InvalidOperationException($"Second input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand.");
|
||||
}
|
||||
@@ -138,7 +132,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
|
||||
case StorageKind.LocalMemory:
|
||||
case StorageKind.SharedMemory:
|
||||
if (!(operation.GetSource(0) is AstOperand bindingId) || bindingId.Type != OperandType.Constant)
|
||||
if (operation.GetSource(0) is not AstOperand { Type: OperandType.Constant } bindingId)
|
||||
{
|
||||
throw new InvalidOperationException($"First input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand.");
|
||||
}
|
||||
@@ -153,7 +147,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
case StorageKind.InputPerPatch:
|
||||
case StorageKind.Output:
|
||||
case StorageKind.OutputPerPatch:
|
||||
if (!(operation.GetSource(0) is AstOperand varId) || varId.Type != OperandType.Constant)
|
||||
if (operation.GetSource(0) is not AstOperand varId || varId.Type != OperandType.Constant)
|
||||
{
|
||||
throw new InvalidOperationException($"First input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand.");
|
||||
}
|
||||
@@ -166,7 +160,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
|
||||
if (context.Config.HasPerLocationInputOrOutput(ioVariable, isOutput))
|
||||
{
|
||||
if (!(operation.GetSource(1) is AstOperand vecIndex) || vecIndex.Type != OperandType.Constant)
|
||||
if (operation.GetSource(1) is not AstOperand vecIndex || vecIndex.Type != OperandType.Constant)
|
||||
{
|
||||
throw new InvalidOperationException($"Second input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand.");
|
||||
}
|
||||
@@ -232,4 +226,4 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -10,9 +10,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
{
|
||||
public static string ReinterpretCast(
|
||||
CodeGenContext context,
|
||||
IAstNode node,
|
||||
AggregateType srcType,
|
||||
AggregateType dstType)
|
||||
IAstNode node,
|
||||
AggregateType srcType,
|
||||
AggregateType dstType)
|
||||
{
|
||||
if (node is AstOperand operand && operand.Type == OperandType.Constant)
|
||||
{
|
||||
@@ -38,18 +38,24 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
{
|
||||
switch (dstType)
|
||||
{
|
||||
case AggregateType.Bool: return $"(floatBitsToInt({expr}) != 0)";
|
||||
case AggregateType.S32: return $"floatBitsToInt({expr})";
|
||||
case AggregateType.U32: return $"floatBitsToUint({expr})";
|
||||
case AggregateType.Bool:
|
||||
return $"(floatBitsToInt({expr}) != 0)";
|
||||
case AggregateType.S32:
|
||||
return $"floatBitsToInt({expr})";
|
||||
case AggregateType.U32:
|
||||
return $"floatBitsToUint({expr})";
|
||||
}
|
||||
}
|
||||
else if (dstType == AggregateType.FP32)
|
||||
{
|
||||
switch (srcType)
|
||||
{
|
||||
case AggregateType.Bool: return $"intBitsToFloat({ReinterpretBoolToInt(expr, node, AggregateType.S32)})";
|
||||
case AggregateType.S32: return $"intBitsToFloat({expr})";
|
||||
case AggregateType.U32: return $"uintBitsToFloat({expr})";
|
||||
case AggregateType.Bool:
|
||||
return $"intBitsToFloat({ReinterpretBoolToInt(expr, node, AggregateType.S32)})";
|
||||
case AggregateType.S32:
|
||||
return $"intBitsToFloat({expr})";
|
||||
case AggregateType.U32:
|
||||
return $"uintBitsToFloat({expr})";
|
||||
}
|
||||
}
|
||||
else if (srcType == AggregateType.Bool)
|
||||
@@ -76,7 +82,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
|
||||
private static string ReinterpretBoolToInt(string expr, IAstNode node, AggregateType dstType)
|
||||
{
|
||||
string trueExpr = NumberFormatter.FormatInt(IrConsts.True, dstType);
|
||||
string trueExpr = NumberFormatter.FormatInt(IrConsts.True, dstType);
|
||||
string falseExpr = NumberFormatter.FormatInt(IrConsts.False, dstType);
|
||||
|
||||
expr = InstGenHelper.Enclose(expr, node, Instruction.ConditionalSelect, isLhs: false);
|
||||
@@ -84,4 +90,4 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
||||
return $"({expr} ? {trueExpr} : {falseExpr})";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,13 +1,14 @@
|
||||
using Ryujinx.Graphics.Shader.StructuredIr;
|
||||
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
||||
using Ryujinx.Graphics.Shader.StructuredIr;
|
||||
using Ryujinx.Graphics.Shader.Translation;
|
||||
using Spv.Generator;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static Spv.Specification;
|
||||
using Instruction = Spv.Generator.Instruction;
|
||||
|
||||
namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
{
|
||||
using IrConsts = IntermediateRepresentation.IrConsts;
|
||||
using IrOperandType = IntermediateRepresentation.OperandType;
|
||||
|
||||
partial class CodeGenContext : Module
|
||||
@@ -36,15 +37,15 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
public Dictionary<IoDefinition, Instruction> OutputsPerPatch { get; } = new Dictionary<IoDefinition, Instruction>();
|
||||
|
||||
public StructuredFunction CurrentFunction { get; set; }
|
||||
private readonly Dictionary<AstOperand, Instruction> _locals = new Dictionary<AstOperand, Instruction>();
|
||||
private readonly Dictionary<int, Instruction[]> _localForArgs = new Dictionary<int, Instruction[]>();
|
||||
private readonly Dictionary<int, Instruction> _funcArgs = new Dictionary<int, Instruction>();
|
||||
private readonly Dictionary<int, (StructuredFunction, Instruction)> _functions = new Dictionary<int, (StructuredFunction, Instruction)>();
|
||||
private readonly Dictionary<AstOperand, Instruction> _locals = new();
|
||||
private readonly Dictionary<int, Instruction[]> _localForArgs = new();
|
||||
private readonly Dictionary<int, Instruction> _funcArgs = new();
|
||||
private readonly Dictionary<int, (StructuredFunction, Instruction)> _functions = new();
|
||||
|
||||
private class BlockState
|
||||
{
|
||||
private int _entryCount;
|
||||
private readonly List<Instruction> _labels = new List<Instruction>();
|
||||
private readonly List<Instruction> _labels = new();
|
||||
|
||||
public Instruction GetNextLabel(CodeGenContext context)
|
||||
{
|
||||
@@ -67,7 +68,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Dictionary<AstBlock, BlockState> _labels = new Dictionary<AstBlock, BlockState>();
|
||||
private readonly Dictionary<AstBlock, BlockState> _labels = new();
|
||||
|
||||
public Dictionary<AstBlock, (Instruction, Instruction)> LoopTargets { get; set; }
|
||||
|
||||
@@ -98,7 +99,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
InputTopology.LinesAdjacency => 2,
|
||||
InputTopology.Triangles => 3,
|
||||
InputTopology.TrianglesAdjacency => 3,
|
||||
_ => throw new InvalidOperationException($"Invalid input topology \"{inPrimitive}\".")
|
||||
_ => throw new InvalidOperationException($"Invalid input topology \"{inPrimitive}\"."),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -222,7 +223,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
IrOperandType.Constant => GetConstant(type, operand),
|
||||
IrOperandType.LocalVariable => GetLocal(type, operand),
|
||||
IrOperandType.Undefined => GetUndefined(type),
|
||||
_ => throw new ArgumentException($"Invalid operand type \"{operand.Type}\".")
|
||||
_ => throw new ArgumentException($"Invalid operand type \"{operand.Type}\"."),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -259,7 +260,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
AggregateType.Bool => ConstantFalse(TypeBool()),
|
||||
AggregateType.FP32 => Constant(TypeFP32(), 0f),
|
||||
AggregateType.FP64 => Constant(TypeFP64(), 0d),
|
||||
_ => Constant(GetType(type), 0)
|
||||
_ => Constant(GetType(type), 0),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -272,7 +273,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
AggregateType.FP64 => Constant(TypeFP64(), (double)BitConverter.Int32BitsToSingle(operand.Value)),
|
||||
AggregateType.S32 => Constant(TypeS32(), operand.Value),
|
||||
AggregateType.U32 => Constant(TypeU32(), (uint)operand.Value),
|
||||
_ => throw new ArgumentException($"Invalid type \"{type}\".")
|
||||
_ => throw new ArgumentException($"Invalid type \"{type}\"."),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -328,7 +329,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
AggregateType.Vector2 => 2,
|
||||
AggregateType.Vector3 => 3,
|
||||
AggregateType.Vector4 => 4,
|
||||
_ => 1
|
||||
_ => 1,
|
||||
};
|
||||
|
||||
return TypeVector(GetType(type & ~AggregateType.ElementCountMask), vectorLength);
|
||||
@@ -342,7 +343,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
AggregateType.FP64 => TypeFP64(),
|
||||
AggregateType.S32 => TypeS32(),
|
||||
AggregateType.U32 => TypeU32(),
|
||||
_ => throw new ArgumentException($"Invalid attribute type \"{type}\".")
|
||||
_ => throw new ArgumentException($"Invalid attribute type \"{type}\"."),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -359,7 +360,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
}
|
||||
else if (srcType == AggregateType.Bool)
|
||||
{
|
||||
var intTrue = Constant(TypeS32(), IrConsts.True);
|
||||
var intTrue = Constant(TypeS32(), IrConsts.True);
|
||||
var intFalse = Constant(TypeS32(), IrConsts.False);
|
||||
|
||||
return BitcastIfNeeded(dstType, AggregateType.S32, Select(TypeS32(), value, intTrue, intFalse));
|
||||
|
@@ -1,5 +1,4 @@
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
||||
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
||||
using Ryujinx.Graphics.Shader.StructuredIr;
|
||||
using Ryujinx.Graphics.Shader.Translation;
|
||||
using Spv.Generator;
|
||||
@@ -14,7 +13,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
{
|
||||
static class Declarations
|
||||
{
|
||||
private static readonly string[] StagePrefixes = new string[] { "cp", "vp", "tcp", "tep", "gp", "fp" };
|
||||
private static readonly string[] _stagePrefixes = { "cp", "vp", "tcp", "tep", "gp", "fp" };
|
||||
|
||||
public static void DeclareParameters(CodeGenContext context, StructuredFunction function)
|
||||
{
|
||||
@@ -107,7 +106,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
|
||||
private static void DeclareBuffers(CodeGenContext context, IEnumerable<BufferDefinition> buffers, bool isBuffer)
|
||||
{
|
||||
HashSet<SpvInstruction> decoratedTypes = new HashSet<SpvInstruction>();
|
||||
HashSet<SpvInstruction> decoratedTypes = new();
|
||||
|
||||
foreach (BufferDefinition buffer in buffers)
|
||||
{
|
||||
@@ -199,7 +198,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
SamplerType.Texture3D => Dim.Dim3D,
|
||||
SamplerType.TextureCube => Dim.Cube,
|
||||
SamplerType.TextureBuffer => Dim.Buffer,
|
||||
_ => throw new InvalidOperationException($"Invalid sampler type \"{descriptor.Type & SamplerType.Mask}\".")
|
||||
_ => throw new InvalidOperationException($"Invalid sampler type \"{descriptor.Type & SamplerType.Mask}\"."),
|
||||
};
|
||||
|
||||
var imageType = context.TypeImage(
|
||||
@@ -282,7 +281,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
SamplerType.Texture3D => Dim.Dim3D,
|
||||
SamplerType.TextureCube => Dim.Cube,
|
||||
SamplerType.TextureBuffer => Dim.Buffer,
|
||||
_ => throw new ArgumentException($"Invalid sampler type \"{type & SamplerType.Mask}\".")
|
||||
_ => throw new ArgumentException($"Invalid sampler type \"{type & SamplerType.Mask}\"."),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -330,7 +329,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
TextureFormat.R10G10B10A2Unorm => ImageFormat.Rgb10A2,
|
||||
TextureFormat.R10G10B10A2Uint => ImageFormat.Rgb10a2ui,
|
||||
TextureFormat.R11G11B10Float => ImageFormat.R11fG11fB10f,
|
||||
_ => throw new ArgumentException($"Invalid texture format \"{format}\".")
|
||||
_ => throw new ArgumentException($"Invalid texture format \"{format}\"."),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -352,7 +351,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
(_, AggregateType varType) = IoMap.GetSpirvBuiltIn(ioVariable);
|
||||
AggregateType elemType = varType & AggregateType.ElementTypeMask;
|
||||
|
||||
if (elemType == AggregateType.S32 || elemType == AggregateType.U32)
|
||||
if (elemType is AggregateType.S32 or AggregateType.U32)
|
||||
{
|
||||
iq = PixelImap.Constant;
|
||||
}
|
||||
@@ -410,7 +409,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
2 => AggregateType.Vector2,
|
||||
3 => AggregateType.Vector3,
|
||||
4 => AggregateType.Vector4,
|
||||
_ => AggregateType.Invalid
|
||||
_ => AggregateType.Invalid,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -420,7 +419,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
if (!isPerPatch && IoMap.IsPerVertex(ioVariable, context.Config.Stage, isOutput))
|
||||
{
|
||||
int arraySize = context.Config.Stage == ShaderStage.Geometry ? context.InputVertices : 32;
|
||||
spvType = context.TypeArray(spvType, context.Constant(context.TypeU32(), (LiteralInteger)arraySize));
|
||||
spvType = context.TypeArray(spvType, context.Constant(context.TypeU32(), arraySize));
|
||||
|
||||
if (context.Config.GpPassthrough && context.Config.GpuAccessor.QueryHostSupportsGeometryShaderPassthrough())
|
||||
{
|
||||
@@ -542,7 +541,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
|
||||
private static string GetStagePrefix(ShaderStage stage)
|
||||
{
|
||||
return StagePrefixes[(int)stage];
|
||||
return _stagePrefixes[(int)stage];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -15,7 +15,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
ShaderStage.TessellationEvaluation => ExecutionModel.TessellationEvaluation,
|
||||
ShaderStage.Geometry => ExecutionModel.Geometry,
|
||||
ShaderStage.Fragment => ExecutionModel.Fragment,
|
||||
_ => throw new ArgumentException($"Invalid shader stage \"{stage}\".")
|
||||
_ => throw new ArgumentException($"Invalid shader stage \"{stage}\"."),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@@ -14,19 +14,20 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
|
||||
static class Instructions
|
||||
{
|
||||
private const MemorySemanticsMask DefaultMemorySemantics =
|
||||
private const MemorySemanticsMask DefaultMemorySemantics =
|
||||
MemorySemanticsMask.ImageMemory |
|
||||
MemorySemanticsMask.AtomicCounterMemory |
|
||||
MemorySemanticsMask.WorkgroupMemory |
|
||||
MemorySemanticsMask.UniformMemory |
|
||||
MemorySemanticsMask.AcquireRelease;
|
||||
|
||||
private static readonly Func<CodeGenContext, AstOperation, OperationResult>[] InstTable;
|
||||
private static readonly Func<CodeGenContext, AstOperation, OperationResult>[] _instTable;
|
||||
|
||||
static Instructions()
|
||||
{
|
||||
InstTable = new Func<CodeGenContext, AstOperation, OperationResult>[(int)Instruction.Count];
|
||||
_instTable = new Func<CodeGenContext, AstOperation, OperationResult>[(int)Instruction.Count];
|
||||
|
||||
#pragma warning disable IDE0055 // Disable formatting
|
||||
Add(Instruction.Absolute, GenerateAbsolute);
|
||||
Add(Instruction.Add, GenerateAdd);
|
||||
Add(Instruction.AtomicAdd, GenerateAtomicAdd);
|
||||
@@ -141,16 +142,17 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
Add(Instruction.VoteAll, GenerateVoteAll);
|
||||
Add(Instruction.VoteAllEqual, GenerateVoteAllEqual);
|
||||
Add(Instruction.VoteAny, GenerateVoteAny);
|
||||
#pragma warning restore IDE0055
|
||||
}
|
||||
|
||||
private static void Add(Instruction inst, Func<CodeGenContext, AstOperation, OperationResult> handler)
|
||||
{
|
||||
InstTable[(int)(inst & Instruction.Mask)] = handler;
|
||||
_instTable[(int)(inst & Instruction.Mask)] = handler;
|
||||
}
|
||||
|
||||
public static OperationResult Generate(CodeGenContext context, AstOperation operation)
|
||||
{
|
||||
var handler = InstTable[(int)(operation.Inst & Instruction.Mask)];
|
||||
var handler = _instTable[(int)(operation.Inst & Instruction.Mask)];
|
||||
if (handler != null)
|
||||
{
|
||||
return handler(context, operation);
|
||||
@@ -305,7 +307,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
|
||||
Debug.Assert(funcId.Type == OperandType.Constant);
|
||||
|
||||
(var function, var spvFunc) = context.GetFunction(funcId.Value);
|
||||
var (function, spvFunc) = context.GetFunction(funcId.Value);
|
||||
|
||||
var args = new SpvInstruction[operation.SourcesCount - 1];
|
||||
var spvLocals = context.GetLocalForArgsPointers(funcId.Value);
|
||||
@@ -615,7 +617,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
});
|
||||
}
|
||||
|
||||
bool isArray = (texOp.Type & SamplerType.Array) != 0;
|
||||
bool isArray = (texOp.Type & SamplerType.Array) != 0;
|
||||
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
|
||||
|
||||
int srcIndex = isBindless ? 1 : 0;
|
||||
@@ -625,11 +627,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
return context.Get(type, texOp.GetSource(srcIndex++));
|
||||
}
|
||||
|
||||
SpvInstruction index = null;
|
||||
|
||||
if (isIndexed)
|
||||
{
|
||||
index = Src(AggregateType.S32);
|
||||
Src(AggregateType.S32);
|
||||
}
|
||||
|
||||
int coordsCount = texOp.Type.GetDimensions();
|
||||
@@ -657,9 +657,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
|
||||
SpvInstruction value = Src(componentType);
|
||||
|
||||
(var imageType, var imageVariable) = context.Images[new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format)];
|
||||
(SpvInstruction imageType, SpvInstruction imageVariable) = context.Images[new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format)];
|
||||
|
||||
var image = context.Load(imageType, imageVariable);
|
||||
context.Load(imageType, imageVariable);
|
||||
|
||||
SpvInstruction resultType = context.GetType(componentType);
|
||||
SpvInstruction imagePointerType = context.TypePointer(StorageClass.Image, resultType);
|
||||
@@ -670,21 +670,21 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
|
||||
var result = (texOp.Flags & TextureFlags.AtomicMask) switch
|
||||
{
|
||||
TextureFlags.Add => context.AtomicIAdd(resultType, pointer, one, zero, value),
|
||||
TextureFlags.Minimum => componentType == AggregateType.S32
|
||||
TextureFlags.Add => context.AtomicIAdd(resultType, pointer, one, zero, value),
|
||||
TextureFlags.Minimum => componentType == AggregateType.S32
|
||||
? context.AtomicSMin(resultType, pointer, one, zero, value)
|
||||
: context.AtomicUMin(resultType, pointer, one, zero, value),
|
||||
TextureFlags.Maximum => componentType == AggregateType.S32
|
||||
TextureFlags.Maximum => componentType == AggregateType.S32
|
||||
? context.AtomicSMax(resultType, pointer, one, zero, value)
|
||||
: context.AtomicUMax(resultType, pointer, one, zero, value),
|
||||
TextureFlags.Increment => context.AtomicIIncrement(resultType, pointer, one, zero),
|
||||
TextureFlags.Decrement => context.AtomicIDecrement(resultType, pointer, one, zero),
|
||||
TextureFlags.Increment => context.AtomicIIncrement(resultType, pointer, one, zero),
|
||||
TextureFlags.Decrement => context.AtomicIDecrement(resultType, pointer, one, zero),
|
||||
TextureFlags.BitwiseAnd => context.AtomicAnd(resultType, pointer, one, zero, value),
|
||||
TextureFlags.BitwiseOr => context.AtomicOr(resultType, pointer, one, zero, value),
|
||||
TextureFlags.BitwiseOr => context.AtomicOr(resultType, pointer, one, zero, value),
|
||||
TextureFlags.BitwiseXor => context.AtomicXor(resultType, pointer, one, zero, value),
|
||||
TextureFlags.Swap => context.AtomicExchange(resultType, pointer, one, zero, value),
|
||||
TextureFlags.CAS => context.AtomicCompareExchange(resultType, pointer, one, zero, zero, Src(componentType), value),
|
||||
_ => context.AtomicIAdd(resultType, pointer, one, zero, value),
|
||||
TextureFlags.Swap => context.AtomicExchange(resultType, pointer, one, zero, value),
|
||||
TextureFlags.CAS => context.AtomicCompareExchange(resultType, pointer, one, zero, zero, Src(componentType), value),
|
||||
_ => context.AtomicIAdd(resultType, pointer, one, zero, value),
|
||||
};
|
||||
|
||||
return new OperationResult(componentType, result);
|
||||
@@ -704,7 +704,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
return GetZeroOperationResult(context, texOp, componentType, isVector: true);
|
||||
}
|
||||
|
||||
bool isArray = (texOp.Type & SamplerType.Array) != 0;
|
||||
bool isArray = (texOp.Type & SamplerType.Array) != 0;
|
||||
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
|
||||
|
||||
int srcIndex = isBindless ? 1 : 0;
|
||||
@@ -714,11 +714,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
return context.Get(type, texOp.GetSource(srcIndex++));
|
||||
}
|
||||
|
||||
SpvInstruction index = null;
|
||||
|
||||
if (isIndexed)
|
||||
{
|
||||
index = Src(AggregateType.S32);
|
||||
Src(AggregateType.S32);
|
||||
}
|
||||
|
||||
int coordsCount = texOp.Type.GetDimensions();
|
||||
@@ -744,7 +742,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
pCoords = Src(AggregateType.S32);
|
||||
}
|
||||
|
||||
(var imageType, var imageVariable) = context.Images[new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format)];
|
||||
var (imageType, imageVariable) = context.Images[new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format)];
|
||||
|
||||
var image = context.Load(imageType, imageVariable);
|
||||
var imageComponentType = context.GetType(componentType);
|
||||
@@ -768,7 +766,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
return OperationResult.Invalid;
|
||||
}
|
||||
|
||||
bool isArray = (texOp.Type & SamplerType.Array) != 0;
|
||||
bool isArray = (texOp.Type & SamplerType.Array) != 0;
|
||||
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
|
||||
|
||||
int srcIndex = isBindless ? 1 : 0;
|
||||
@@ -778,11 +776,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
return context.Get(type, texOp.GetSource(srcIndex++));
|
||||
}
|
||||
|
||||
SpvInstruction index = null;
|
||||
|
||||
if (isIndexed)
|
||||
{
|
||||
index = Src(AggregateType.S32);
|
||||
Src(AggregateType.S32);
|
||||
}
|
||||
|
||||
int coordsCount = texOp.Type.GetDimensions();
|
||||
@@ -833,7 +829,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
|
||||
var texel = context.CompositeConstruct(context.TypeVector(context.GetType(componentType), ComponentsCount), cElems);
|
||||
|
||||
(var imageType, var imageVariable) = context.Images[new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format)];
|
||||
var (imageType, imageVariable) = context.Images[new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format)];
|
||||
|
||||
var image = context.Load(imageType, imageVariable);
|
||||
|
||||
@@ -886,11 +882,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
return context.Get(type, texOp.GetSource(srcIndex++));
|
||||
}
|
||||
|
||||
SpvInstruction index = null;
|
||||
|
||||
if (isIndexed)
|
||||
{
|
||||
index = Src(AggregateType.S32);
|
||||
Src(AggregateType.S32);
|
||||
}
|
||||
|
||||
int pCount = texOp.Type.GetDimensions();
|
||||
@@ -916,7 +910,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
|
||||
var meta = new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format);
|
||||
|
||||
(_, var sampledImageType, var sampledImageVariable) = context.Samplers[meta];
|
||||
var (_, sampledImageType, sampledImageVariable) = context.Samplers[meta];
|
||||
|
||||
var image = context.Load(sampledImageType, sampledImageVariable);
|
||||
|
||||
@@ -973,7 +967,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
loopBlock = loopBlock.Parent;
|
||||
}
|
||||
|
||||
(var loopTarget, var continueTarget) = context.LoopTargets[loopBlock];
|
||||
(_, SpvInstruction continueTarget) = context.LoopTargets[loopBlock];
|
||||
|
||||
context.Branch(continueTarget);
|
||||
|
||||
@@ -1278,19 +1272,19 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
{
|
||||
AstTextureOperation texOp = (AstTextureOperation)operation;
|
||||
|
||||
bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;
|
||||
bool isGather = (texOp.Flags & TextureFlags.Gather) != 0;
|
||||
bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;
|
||||
bool isGather = (texOp.Flags & TextureFlags.Gather) != 0;
|
||||
bool hasDerivatives = (texOp.Flags & TextureFlags.Derivatives) != 0;
|
||||
bool intCoords = (texOp.Flags & TextureFlags.IntCoords) != 0;
|
||||
bool hasLodBias = (texOp.Flags & TextureFlags.LodBias) != 0;
|
||||
bool hasLodLevel = (texOp.Flags & TextureFlags.LodLevel) != 0;
|
||||
bool hasOffset = (texOp.Flags & TextureFlags.Offset) != 0;
|
||||
bool hasOffsets = (texOp.Flags & TextureFlags.Offsets) != 0;
|
||||
bool intCoords = (texOp.Flags & TextureFlags.IntCoords) != 0;
|
||||
bool hasLodBias = (texOp.Flags & TextureFlags.LodBias) != 0;
|
||||
bool hasLodLevel = (texOp.Flags & TextureFlags.LodLevel) != 0;
|
||||
bool hasOffset = (texOp.Flags & TextureFlags.Offset) != 0;
|
||||
bool hasOffsets = (texOp.Flags & TextureFlags.Offsets) != 0;
|
||||
|
||||
bool isArray = (texOp.Type & SamplerType.Array) != 0;
|
||||
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
|
||||
bool isArray = (texOp.Type & SamplerType.Array) != 0;
|
||||
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
|
||||
bool isMultisample = (texOp.Type & SamplerType.Multisample) != 0;
|
||||
bool isShadow = (texOp.Type & SamplerType.Shadow) != 0;
|
||||
bool isShadow = (texOp.Type & SamplerType.Shadow) != 0;
|
||||
|
||||
bool colorIsVector = isGather || !isShadow;
|
||||
|
||||
@@ -1307,11 +1301,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
return context.Get(type, texOp.GetSource(srcIndex++));
|
||||
}
|
||||
|
||||
SpvInstruction index = null;
|
||||
|
||||
if (isIndexed)
|
||||
{
|
||||
index = Src(AggregateType.S32);
|
||||
Src(AggregateType.S32);
|
||||
}
|
||||
|
||||
int coordsCount = texOp.Type.GetDimensions();
|
||||
@@ -1395,7 +1387,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
derivatives = new[]
|
||||
{
|
||||
AssembleDerivativesVector(coordsCount), // dPdx
|
||||
AssembleDerivativesVector(coordsCount) // dPdy
|
||||
AssembleDerivativesVector(coordsCount), // dPdy
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1445,7 +1437,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
AssembleOffsetVector(coordsCount),
|
||||
AssembleOffsetVector(coordsCount),
|
||||
AssembleOffsetVector(coordsCount),
|
||||
AssembleOffsetVector(coordsCount)
|
||||
AssembleOffsetVector(coordsCount),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1474,7 +1466,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
// not needed for shadow samplers.
|
||||
if (isGather && !isShadow)
|
||||
{
|
||||
compIdx = Src(AggregateType.S32);
|
||||
compIdx = Src(AggregateType.S32);
|
||||
}
|
||||
|
||||
var operandsList = new List<SpvInstruction>();
|
||||
@@ -1521,7 +1513,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
|
||||
var meta = new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format);
|
||||
|
||||
(var imageType, var sampledImageType, var sampledImageVariable) = context.Samplers[meta];
|
||||
var (imageType, sampledImageType, sampledImageVariable) = context.Samplers[meta];
|
||||
|
||||
var image = context.Load(sampledImageType, sampledImageVariable);
|
||||
|
||||
@@ -1595,16 +1587,14 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
|
||||
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
|
||||
|
||||
SpvInstruction index = null;
|
||||
|
||||
if (isIndexed)
|
||||
{
|
||||
index = context.GetS32(texOp.GetSource(0));
|
||||
context.GetS32(texOp.GetSource(0));
|
||||
}
|
||||
|
||||
var meta = new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format);
|
||||
|
||||
(var imageType, var sampledImageType, var sampledImageVariable) = context.Samplers[meta];
|
||||
(SpvInstruction imageType, SpvInstruction sampledImageType, SpvInstruction sampledImageVariable) = context.Samplers[meta];
|
||||
|
||||
var image = context.Load(sampledImageType, sampledImageVariable);
|
||||
image = context.Image(imageType, image);
|
||||
@@ -1809,12 +1799,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
{
|
||||
case StorageKind.ConstantBuffer:
|
||||
case StorageKind.StorageBuffer:
|
||||
if (!(operation.GetSource(srcIndex++) is AstOperand bindingIndex) || bindingIndex.Type != OperandType.Constant)
|
||||
if (operation.GetSource(srcIndex++) is not AstOperand bindingIndex || bindingIndex.Type != OperandType.Constant)
|
||||
{
|
||||
throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand.");
|
||||
}
|
||||
|
||||
if (!(operation.GetSource(srcIndex) is AstOperand fieldIndex) || fieldIndex.Type != OperandType.Constant)
|
||||
if (operation.GetSource(srcIndex) is not AstOperand fieldIndex || fieldIndex.Type != OperandType.Constant)
|
||||
{
|
||||
throw new InvalidOperationException($"Second input of {operation.Inst} with {storageKind} storage must be a constant operand.");
|
||||
}
|
||||
@@ -1833,7 +1823,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
|
||||
case StorageKind.LocalMemory:
|
||||
case StorageKind.SharedMemory:
|
||||
if (!(operation.GetSource(srcIndex++) is AstOperand bindingId) || bindingId.Type != OperandType.Constant)
|
||||
if (operation.GetSource(srcIndex++) is not AstOperand { Type: OperandType.Constant } bindingId)
|
||||
{
|
||||
throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand.");
|
||||
}
|
||||
@@ -1856,7 +1846,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
case StorageKind.InputPerPatch:
|
||||
case StorageKind.Output:
|
||||
case StorageKind.OutputPerPatch:
|
||||
if (!(operation.GetSource(srcIndex++) is AstOperand varId) || varId.Type != OperandType.Constant)
|
||||
if (operation.GetSource(srcIndex++) is not AstOperand varId || varId.Type != OperandType.Constant)
|
||||
{
|
||||
throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand.");
|
||||
}
|
||||
@@ -1869,7 +1859,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
|
||||
if (context.Config.HasPerLocationInputOrOutput(ioVariable, isOutput))
|
||||
{
|
||||
if (!(operation.GetSource(srcIndex++) is AstOperand vecIndex) || vecIndex.Type != OperandType.Constant)
|
||||
if (operation.GetSource(srcIndex++) is not AstOperand vecIndex || vecIndex.Type != OperandType.Constant)
|
||||
{
|
||||
throw new InvalidOperationException($"Second input of {operation.Inst} with {storageKind} storage must be a constant operand.");
|
||||
}
|
||||
@@ -1964,7 +1954,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
|
||||
private static SpvInstruction GetScalarInput(CodeGenContext context, IoVariable ioVariable)
|
||||
{
|
||||
(_, var varType) = IoMap.GetSpirvBuiltIn(ioVariable);
|
||||
var (_, varType) = IoMap.GetSpirvBuiltIn(ioVariable);
|
||||
varType &= AggregateType.ElementTypeMask;
|
||||
|
||||
var ioDefinition = new IoDefinition(StorageKind.Input, ioVariable);
|
||||
@@ -2061,10 +2051,10 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
return new OperationResult(AggregateType.Bool, emitB(context.TypeBool(), context.Get(AggregateType.Bool, source)));
|
||||
}
|
||||
|
||||
private static OperationResult GenerateUnaryFP32(
|
||||
CodeGenContext context,
|
||||
AstOperation operation,
|
||||
Func<SpvInstruction, SpvInstruction, SpvInstruction> emit)
|
||||
private static OperationResult GenerateUnaryFP32(
|
||||
CodeGenContext context,
|
||||
AstOperation operation,
|
||||
Func<SpvInstruction, SpvInstruction, SpvInstruction> emit)
|
||||
{
|
||||
var source = operation.GetSource(0);
|
||||
return new OperationResult(AggregateType.FP32, emit(context.TypeFP32(), context.GetFP32(source)));
|
||||
|
@@ -45,7 +45,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
IoVariable.VertexIndex => (BuiltIn.VertexIndex, AggregateType.S32),
|
||||
IoVariable.ViewportIndex => (BuiltIn.ViewportIndex, AggregateType.S32),
|
||||
IoVariable.ViewportMask => (BuiltIn.ViewportMaskNV, AggregateType.Array | AggregateType.S32),
|
||||
_ => (default, AggregateType.Invalid)
|
||||
_ => (default, AggregateType.Invalid),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
IoVariable.TessellationLevelOuter => 4,
|
||||
IoVariable.ViewportMask => 1,
|
||||
IoVariable.UserDefined => MaxAttributes,
|
||||
_ => 1
|
||||
_ => 1,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -74,13 +74,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
case IoVariable.ClipDistance:
|
||||
case IoVariable.PointCoord:
|
||||
case IoVariable.ViewportMask:
|
||||
return !isOutput &&
|
||||
(stage == ShaderStage.TessellationControl ||
|
||||
stage == ShaderStage.TessellationEvaluation ||
|
||||
stage == ShaderStage.Geometry);
|
||||
return !isOutput &&
|
||||
stage is ShaderStage.TessellationControl or ShaderStage.TessellationEvaluation or ShaderStage.Geometry;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
{
|
||||
readonly struct OperationResult
|
||||
{
|
||||
public static OperationResult Invalid => new OperationResult(AggregateType.Invalid, null);
|
||||
public static OperationResult Invalid => new(AggregateType.Invalid, null);
|
||||
|
||||
public AggregateType Type { get; }
|
||||
public Instruction Value { get; }
|
||||
|
@@ -17,15 +17,15 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
{
|
||||
// Resource pools for Spirv generation. Note: Increase count when more threads are being used.
|
||||
private const int GeneratorPoolCount = 1;
|
||||
private static ObjectPool<SpvInstructionPool> InstructionPool;
|
||||
private static ObjectPool<SpvLiteralIntegerPool> IntegerPool;
|
||||
private static object PoolLock;
|
||||
private static readonly ObjectPool<SpvInstructionPool> _instructionPool;
|
||||
private static readonly ObjectPool<SpvLiteralIntegerPool> _integerPool;
|
||||
private static readonly object _poolLock;
|
||||
|
||||
static SpirvGenerator()
|
||||
{
|
||||
InstructionPool = new (() => new SpvInstructionPool(), GeneratorPoolCount);
|
||||
IntegerPool = new (() => new SpvLiteralIntegerPool(), GeneratorPoolCount);
|
||||
PoolLock = new object();
|
||||
_instructionPool = new(() => new SpvInstructionPool(), GeneratorPoolCount);
|
||||
_integerPool = new(() => new SpvLiteralIntegerPool(), GeneratorPoolCount);
|
||||
_poolLock = new object();
|
||||
}
|
||||
|
||||
private const HelperFunctionsMask NeedsInvocationIdMask =
|
||||
@@ -40,13 +40,13 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
SpvInstructionPool instPool;
|
||||
SpvLiteralIntegerPool integerPool;
|
||||
|
||||
lock (PoolLock)
|
||||
lock (_poolLock)
|
||||
{
|
||||
instPool = InstructionPool.Allocate();
|
||||
integerPool = IntegerPool.Allocate();
|
||||
instPool = _instructionPool.Allocate();
|
||||
integerPool = _integerPool.Allocate();
|
||||
}
|
||||
|
||||
CodeGenContext context = new CodeGenContext(info, config, instPool, integerPool);
|
||||
CodeGenContext context = new(info, config, instPool, integerPool);
|
||||
|
||||
context.AddCapability(Capability.GroupNonUniformBallot);
|
||||
context.AddCapability(Capability.GroupNonUniformShuffle);
|
||||
@@ -133,10 +133,10 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
|
||||
byte[] result = context.Generate();
|
||||
|
||||
lock (PoolLock)
|
||||
lock (_poolLock)
|
||||
{
|
||||
InstructionPool.Release(instPool);
|
||||
IntegerPool.Release(integerPool);
|
||||
_instructionPool.Release(instPool);
|
||||
_integerPool.Release(integerPool);
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -144,7 +144,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
|
||||
private static void Generate(CodeGenContext context, StructuredProgramInfo info, int funcIndex)
|
||||
{
|
||||
(var function, var spvFunc) = context.GetFunction(funcIndex);
|
||||
var (function, spvFunc) = context.GetFunction(funcIndex);
|
||||
|
||||
context.CurrentFunction = function;
|
||||
context.AddFunction(spvFunc);
|
||||
@@ -160,7 +160,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
Generate(context, function.MainBlock);
|
||||
|
||||
// Functions must always end with a return.
|
||||
if (!(function.MainBlock.Last is AstOperation operation) ||
|
||||
if (function.MainBlock.Last is not AstOperation operation ||
|
||||
(operation.Inst != Instruction.Return && operation.Inst != Instruction.Discard))
|
||||
{
|
||||
context.Return();
|
||||
@@ -232,7 +232,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
InputTopology.LinesAdjacency => ExecutionMode.InputLinesAdjacency,
|
||||
InputTopology.Triangles => ExecutionMode.Triangles,
|
||||
InputTopology.TrianglesAdjacency => ExecutionMode.InputTrianglesAdjacency,
|
||||
_ => throw new InvalidOperationException($"Invalid input topology \"{inputTopology}\".")
|
||||
_ => throw new InvalidOperationException($"Invalid input topology \"{inputTopology}\"."),
|
||||
});
|
||||
|
||||
context.AddExecutionMode(spvFunc, ExecutionMode.Invocations, (SpvLiteralInteger)context.Config.ThreadsPerInputPrimitive);
|
||||
@@ -242,7 +242,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
OutputTopology.PointList => ExecutionMode.OutputPoints,
|
||||
OutputTopology.LineStrip => ExecutionMode.OutputLineStrip,
|
||||
OutputTopology.TriangleStrip => ExecutionMode.OutputTriangleStrip,
|
||||
_ => throw new InvalidOperationException($"Invalid output topology \"{context.Config.OutputTopology}\".")
|
||||
_ => throw new InvalidOperationException($"Invalid output topology \"{context.Config.OutputTopology}\"."),
|
||||
});
|
||||
|
||||
int maxOutputVertices = context.Config.GpPassthrough ? context.InputVertices : context.Config.MaxOutputVertices;
|
||||
@@ -294,7 +294,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
|
||||
private static void Generate(CodeGenContext context, AstBlock block)
|
||||
{
|
||||
AstBlockVisitor visitor = new AstBlockVisitor(block);
|
||||
AstBlockVisitor visitor = new(block);
|
||||
|
||||
var loopTargets = new Dictionary<AstBlock, (SpvInstruction, SpvInstruction)>();
|
||||
|
||||
@@ -346,7 +346,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
// if the condition is true.
|
||||
AstBlock mergeBlock = e.Block.Parent;
|
||||
|
||||
(var loopTarget, var continueTarget) = loopTargets[e.Block];
|
||||
var (loopTarget, continueTarget) = loopTargets[e.Block];
|
||||
|
||||
context.Branch(continueTarget);
|
||||
context.AddLabel(continueTarget);
|
||||
|
@@ -1,4 +1,4 @@
|
||||
namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
||||
{
|
||||
readonly record struct TextureMeta(int CbufSlot, int Handle, TextureFormat Format);
|
||||
}
|
||||
}
|
||||
|
@@ -17,4 +17,4 @@ namespace Ryujinx.Graphics.Shader
|
||||
public const int TfeBufferBaseBinding = 1;
|
||||
public const int TfeBuffersCount = 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -92,7 +92,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
pushOpInfo.Consumers.Add(rightBlock, local);
|
||||
}
|
||||
|
||||
foreach ((ulong key, SyncTarget value) in SyncTargets)
|
||||
foreach ((ulong key, SyncTarget value) in SyncTargets)
|
||||
{
|
||||
rightBlock.SyncTargets.Add(key, value);
|
||||
}
|
||||
@@ -148,7 +148,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
{
|
||||
if (OpCodes.Count != 0)
|
||||
{
|
||||
return OpCodes[OpCodes.Count - 1];
|
||||
return OpCodes[^1];
|
||||
}
|
||||
|
||||
return default;
|
||||
@@ -165,4 +165,4 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
PushOpCodes.Add(new PushOpInfo(op));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -45,4 +45,4 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -54,4 +54,4 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
return GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -3,7 +3,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
||||
|
||||
namespace Ryujinx.Graphics.Shader.Decoders
|
||||
@@ -12,8 +11,8 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
{
|
||||
public static DecodedProgram Decode(ShaderConfig config, ulong startAddress)
|
||||
{
|
||||
Queue<DecodedFunction> functionsQueue = new Queue<DecodedFunction>();
|
||||
Dictionary<ulong, DecodedFunction> functionsVisited = new Dictionary<ulong, DecodedFunction>();
|
||||
Queue<DecodedFunction> functionsQueue = new();
|
||||
Dictionary<ulong, DecodedFunction> functionsVisited = new();
|
||||
|
||||
DecodedFunction EnqueueFunction(ulong address)
|
||||
{
|
||||
@@ -30,9 +29,9 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
|
||||
while (functionsQueue.TryDequeue(out DecodedFunction currentFunction))
|
||||
{
|
||||
List<Block> blocks = new List<Block>();
|
||||
Queue<Block> workQueue = new Queue<Block>();
|
||||
Dictionary<ulong, Block> visited = new Dictionary<ulong, Block>();
|
||||
List<Block> blocks = new();
|
||||
Queue<Block> workQueue = new();
|
||||
Dictionary<ulong, Block> visited = new();
|
||||
|
||||
Block GetBlock(ulong blkAddress)
|
||||
{
|
||||
@@ -168,7 +167,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
{
|
||||
index = 0;
|
||||
|
||||
int left = 0;
|
||||
int left = 0;
|
||||
int right = blocks.Count - 1;
|
||||
|
||||
while (left <= right)
|
||||
@@ -273,12 +272,12 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
int offset;
|
||||
int count = 1;
|
||||
bool isStore = false;
|
||||
bool indexed = false;
|
||||
bool indexed;
|
||||
bool perPatch = false;
|
||||
|
||||
if (name == InstName.Ast)
|
||||
{
|
||||
InstAst opAst = new InstAst(opCode);
|
||||
InstAst opAst = new(opCode);
|
||||
count = (int)opAst.AlSize + 1;
|
||||
offset = opAst.Imm11;
|
||||
indexed = opAst.Phys;
|
||||
@@ -287,7 +286,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
}
|
||||
else if (name == InstName.Ald)
|
||||
{
|
||||
InstAld opAld = new InstAld(opCode);
|
||||
InstAld opAld = new(opCode);
|
||||
count = (int)opAld.AlSize + 1;
|
||||
offset = opAld.Imm11;
|
||||
indexed = opAld.Phys;
|
||||
@@ -296,7 +295,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
}
|
||||
else /* if (name == InstName.Ipa) */
|
||||
{
|
||||
InstIpa opIpa = new InstIpa(opCode);
|
||||
InstIpa opIpa = new(opCode);
|
||||
offset = opIpa.Imm10;
|
||||
indexed = opIpa.Idx;
|
||||
}
|
||||
@@ -370,7 +369,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
|
||||
private static bool IsUnconditional(ref InstOp op)
|
||||
{
|
||||
InstConditional condOp = new InstConditional(op.RawOpCode);
|
||||
InstConditional condOp = new(op.RawOpCode);
|
||||
|
||||
if ((op.Name == InstName.Bra || op.Name == InstName.Exit) && condOp.Ccc != Ccc.T)
|
||||
{
|
||||
@@ -391,9 +390,9 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
|
||||
if (lastOp.Name == InstName.Brx && block.Successors.Count == (hasNext ? 1 : 0))
|
||||
{
|
||||
HashSet<ulong> visited = new HashSet<ulong>();
|
||||
HashSet<ulong> visited = new();
|
||||
|
||||
InstBrx opBrx = new InstBrx(lastOp.RawOpCode);
|
||||
InstBrx opBrx = new(lastOp.RawOpCode);
|
||||
ulong baseOffset = lastOp.GetAbsoluteAddress();
|
||||
|
||||
// An indirect branch could go anywhere,
|
||||
@@ -437,7 +436,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
// On a successful match, "BaseOffset" is the offset in bytes where the jump offsets are
|
||||
// located on the constant buffer, and "UpperBound" is the total number of offsets for the BRX, minus 1.
|
||||
|
||||
HashSet<Block> visited = new HashSet<Block>();
|
||||
HashSet<Block> visited = new();
|
||||
|
||||
var ldcLocation = FindFirstRegWrite(visited, new BlockLocation(block, block.OpCodes.Count - 1), brxReg);
|
||||
if (ldcLocation.Block == null || ldcLocation.Block.OpCodes[ldcLocation.Index].Name != InstName.Ldc)
|
||||
@@ -507,7 +506,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
|
||||
private static BlockLocation FindFirstRegWrite(HashSet<Block> visited, BlockLocation location, int regIndex)
|
||||
{
|
||||
Queue<BlockLocation> toVisit = new Queue<BlockLocation>();
|
||||
Queue<BlockLocation> toVisit = new();
|
||||
toVisit.Enqueue(location);
|
||||
visited.Add(location.Block);
|
||||
|
||||
@@ -554,10 +553,10 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
{
|
||||
Brk,
|
||||
Cont,
|
||||
Sync
|
||||
Sync,
|
||||
}
|
||||
|
||||
private struct PathBlockState
|
||||
private readonly struct PathBlockState
|
||||
{
|
||||
public Block Block { get; }
|
||||
|
||||
@@ -565,37 +564,37 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
{
|
||||
None,
|
||||
PopPushOp,
|
||||
PushBranchOp
|
||||
PushBranchOp,
|
||||
}
|
||||
|
||||
private RestoreType _restoreType;
|
||||
private readonly RestoreType _restoreType;
|
||||
|
||||
private ulong _restoreValue;
|
||||
private MergeType _restoreMergeType;
|
||||
private readonly ulong _restoreValue;
|
||||
private readonly MergeType _restoreMergeType;
|
||||
|
||||
public bool ReturningFromVisit => _restoreType != RestoreType.None;
|
||||
|
||||
public PathBlockState(Block block)
|
||||
{
|
||||
Block = block;
|
||||
_restoreType = RestoreType.None;
|
||||
_restoreValue = 0;
|
||||
Block = block;
|
||||
_restoreType = RestoreType.None;
|
||||
_restoreValue = 0;
|
||||
_restoreMergeType = default;
|
||||
}
|
||||
|
||||
public PathBlockState(int oldStackSize)
|
||||
{
|
||||
Block = null;
|
||||
_restoreType = RestoreType.PopPushOp;
|
||||
_restoreValue = (ulong)oldStackSize;
|
||||
Block = null;
|
||||
_restoreType = RestoreType.PopPushOp;
|
||||
_restoreValue = (ulong)oldStackSize;
|
||||
_restoreMergeType = default;
|
||||
}
|
||||
|
||||
public PathBlockState(ulong syncAddress, MergeType mergeType)
|
||||
{
|
||||
Block = null;
|
||||
_restoreType = RestoreType.PushBranchOp;
|
||||
_restoreValue = syncAddress;
|
||||
Block = null;
|
||||
_restoreType = RestoreType.PushBranchOp;
|
||||
_restoreValue = syncAddress;
|
||||
_restoreMergeType = mergeType;
|
||||
}
|
||||
|
||||
@@ -622,9 +621,9 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
|
||||
Block target = blocks[pushOp.GetAbsoluteAddress()];
|
||||
|
||||
Stack<PathBlockState> workQueue = new Stack<PathBlockState>();
|
||||
HashSet<Block> visited = new HashSet<Block>();
|
||||
Stack<(ulong, MergeType)> branchStack = new Stack<(ulong, MergeType)>();
|
||||
Stack<PathBlockState> workQueue = new();
|
||||
HashSet<Block> visited = new();
|
||||
Stack<(ulong, MergeType)> branchStack = new();
|
||||
|
||||
void Push(PathBlockState pbs)
|
||||
{
|
||||
@@ -759,7 +758,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
{
|
||||
InstName.Pbk => MergeType.Brk,
|
||||
InstName.Pcnt => MergeType.Cont,
|
||||
_ => MergeType.Sync
|
||||
_ => MergeType.Sync,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -769,8 +768,8 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
{
|
||||
InstName.Brk => MergeType.Brk,
|
||||
InstName.Cont => MergeType.Cont,
|
||||
_ => MergeType.Sync
|
||||
_ => MergeType.Sync,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -185,4 +185,4 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
Vshr,
|
||||
Xmad,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -24,4 +24,4 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
return (ulong)((long)Address + (((int)(RawOpCode >> 20) << 8) >> 8) + 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -26,6 +26,6 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
Tex = 1 << 12,
|
||||
TexB = 1 << 13,
|
||||
Bra = 1 << 14,
|
||||
NoPred = 1 << 15
|
||||
NoPred = 1 << 15,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -24,13 +24,14 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
}
|
||||
}
|
||||
|
||||
private static TableEntry[] _opCodes;
|
||||
private static readonly TableEntry[] _opCodes;
|
||||
|
||||
static InstTable()
|
||||
{
|
||||
_opCodes = new TableEntry[1 << EncodingBits];
|
||||
|
||||
#region Instructions
|
||||
#pragma warning disable IDE0055 // Disable formatting
|
||||
Add("1110111110100xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Al2p, InstEmit.Al2p, InstProps.Rd | InstProps.Ra);
|
||||
Add("1110111111011xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ald, InstEmit.Ald, InstProps.Rd | InstProps.Ra);
|
||||
Add("1110111111110xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ast, InstEmit.Ast, InstProps.Ra | InstProps.Rb2 | InstProps.Rc);
|
||||
@@ -325,6 +326,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
Add("0011011x00xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Xmad, InstEmit.XmadI, InstProps.Rd | InstProps.Ra | InstProps.Ib | InstProps.Rc);
|
||||
Add("0100111xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Xmad, InstEmit.XmadC, InstProps.Rd | InstProps.Ra | InstProps.Rc);
|
||||
Add("010100010xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Xmad, InstEmit.XmadRc, InstProps.Rd | InstProps.Ra | InstProps.Rc);
|
||||
#pragma warning restore IDE0055
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -357,7 +359,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
|
||||
xMask = ~xMask;
|
||||
|
||||
TableEntry entry = new TableEntry(name, emitter, props, xBits);
|
||||
TableEntry entry = new(name, emitter, props, xBits);
|
||||
|
||||
for (int index = 0; index < (1 << xBits); index++)
|
||||
{
|
||||
@@ -387,4 +389,4 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
return new InstOp(address, opCode, InstName.Invalid, null, InstProps.None);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -8,13 +8,13 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
|
||||
public RegisterType Type { get; }
|
||||
|
||||
public bool IsRZ => Type == RegisterType.Gpr && Index == RegisterConsts.RegisterZeroIndex;
|
||||
public bool IsRZ => Type == RegisterType.Gpr && Index == RegisterConsts.RegisterZeroIndex;
|
||||
public bool IsPT => Type == RegisterType.Predicate && Index == RegisterConsts.PredicateTrueIndex;
|
||||
|
||||
public Register(int index, RegisterType type)
|
||||
{
|
||||
Index = index;
|
||||
Type = type;
|
||||
Type = type;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
@@ -30,7 +30,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
public bool Equals(Register other)
|
||||
{
|
||||
return other.Index == Index &&
|
||||
other.Type == Type;
|
||||
other.Type == Type;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -2,12 +2,12 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
{
|
||||
static class RegisterConsts
|
||||
{
|
||||
public const int GprsCount = 255;
|
||||
public const int GprsCount = 255;
|
||||
public const int PredsCount = 7;
|
||||
public const int FlagsCount = 4;
|
||||
public const int TotalCount = GprsCount + PredsCount + FlagsCount;
|
||||
|
||||
public const int RegisterZeroIndex = GprsCount;
|
||||
public const int RegisterZeroIndex = GprsCount;
|
||||
public const int PredicateTrueIndex = PredsCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -6,4 +6,4 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||
Gpr,
|
||||
Predicate,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -6,7 +6,7 @@ namespace Ryujinx.Graphics.Shader
|
||||
Lines,
|
||||
LinesAdjacency,
|
||||
Triangles,
|
||||
TrianglesAdjacency
|
||||
TrianglesAdjacency,
|
||||
}
|
||||
|
||||
static class InputTopologyExtensions
|
||||
@@ -20,7 +20,7 @@ namespace Ryujinx.Graphics.Shader
|
||||
InputTopology.LinesAdjacency => "lines_adjacency",
|
||||
InputTopology.Triangles => "triangles",
|
||||
InputTopology.TrianglesAdjacency => "triangles_adjacency",
|
||||
_ => "points"
|
||||
_ => "points",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -33,8 +33,8 @@ namespace Ryujinx.Graphics.Shader
|
||||
InputTopology.LinesAdjacency => 2,
|
||||
InputTopology.Triangles or
|
||||
InputTopology.TrianglesAdjacency => 3,
|
||||
_ => 1
|
||||
_ => 1,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,6 @@
|
||||
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
||||
using Ryujinx.Graphics.Shader.Translation;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
||||
|
||||
namespace Ryujinx.Graphics.Shader.Instructions
|
||||
@@ -21,10 +20,10 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
Tessellation = TessellationControl | TessellationEvaluation,
|
||||
VertexTessellationGeometry = Vertex | Tessellation | Geometry,
|
||||
TessellationGeometryFragment = Tessellation | Geometry | Fragment,
|
||||
AllGraphics = Vertex | Tessellation | Geometry | Fragment
|
||||
AllGraphics = Vertex | Tessellation | Geometry | Fragment,
|
||||
}
|
||||
|
||||
private struct AttributeEntry
|
||||
private readonly struct AttributeEntry
|
||||
{
|
||||
public int BaseOffset { get; }
|
||||
public AggregateType Type { get; }
|
||||
@@ -344,8 +343,8 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
AggregateType.Vector2 => 2,
|
||||
AggregateType.Vector3 => 3,
|
||||
AggregateType.Vector4 => 4,
|
||||
_ => 1
|
||||
_ => 1,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -7,352 +7,352 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
{
|
||||
public static void AtomCas(EmitterContext context)
|
||||
{
|
||||
InstAtomCas op = context.GetOp<InstAtomCas>();
|
||||
context.GetOp<InstAtomCas>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction AtomCas is not implemented.");
|
||||
}
|
||||
|
||||
public static void AtomsCas(EmitterContext context)
|
||||
{
|
||||
InstAtomsCas op = context.GetOp<InstAtomsCas>();
|
||||
context.GetOp<InstAtomsCas>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction AtomsCas is not implemented.");
|
||||
}
|
||||
|
||||
public static void B2r(EmitterContext context)
|
||||
{
|
||||
InstB2r op = context.GetOp<InstB2r>();
|
||||
context.GetOp<InstB2r>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction B2r is not implemented.");
|
||||
}
|
||||
|
||||
public static void Bpt(EmitterContext context)
|
||||
{
|
||||
InstBpt op = context.GetOp<InstBpt>();
|
||||
context.GetOp<InstBpt>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction Bpt is not implemented.");
|
||||
}
|
||||
|
||||
public static void Cctl(EmitterContext context)
|
||||
{
|
||||
InstCctl op = context.GetOp<InstCctl>();
|
||||
context.GetOp<InstCctl>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction Cctl is not implemented.");
|
||||
}
|
||||
|
||||
public static void Cctll(EmitterContext context)
|
||||
{
|
||||
InstCctll op = context.GetOp<InstCctll>();
|
||||
context.GetOp<InstCctll>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction Cctll is not implemented.");
|
||||
}
|
||||
|
||||
public static void Cctlt(EmitterContext context)
|
||||
{
|
||||
InstCctlt op = context.GetOp<InstCctlt>();
|
||||
context.GetOp<InstCctlt>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction Cctlt is not implemented.");
|
||||
}
|
||||
|
||||
public static void Cs2r(EmitterContext context)
|
||||
{
|
||||
InstCs2r op = context.GetOp<InstCs2r>();
|
||||
context.GetOp<InstCs2r>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction Cs2r is not implemented.");
|
||||
}
|
||||
|
||||
public static void FchkR(EmitterContext context)
|
||||
{
|
||||
InstFchkR op = context.GetOp<InstFchkR>();
|
||||
context.GetOp<InstFchkR>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction FchkR is not implemented.");
|
||||
}
|
||||
|
||||
public static void FchkI(EmitterContext context)
|
||||
{
|
||||
InstFchkI op = context.GetOp<InstFchkI>();
|
||||
context.GetOp<InstFchkI>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction FchkI is not implemented.");
|
||||
}
|
||||
|
||||
public static void FchkC(EmitterContext context)
|
||||
{
|
||||
InstFchkC op = context.GetOp<InstFchkC>();
|
||||
context.GetOp<InstFchkC>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction FchkC is not implemented.");
|
||||
}
|
||||
|
||||
public static void Getcrsptr(EmitterContext context)
|
||||
{
|
||||
InstGetcrsptr op = context.GetOp<InstGetcrsptr>();
|
||||
context.GetOp<InstGetcrsptr>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction Getcrsptr is not implemented.");
|
||||
}
|
||||
|
||||
public static void Getlmembase(EmitterContext context)
|
||||
{
|
||||
InstGetlmembase op = context.GetOp<InstGetlmembase>();
|
||||
context.GetOp<InstGetlmembase>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction Getlmembase is not implemented.");
|
||||
}
|
||||
|
||||
public static void Ide(EmitterContext context)
|
||||
{
|
||||
InstIde op = context.GetOp<InstIde>();
|
||||
context.GetOp<InstIde>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction Ide is not implemented.");
|
||||
}
|
||||
|
||||
public static void IdpR(EmitterContext context)
|
||||
{
|
||||
InstIdpR op = context.GetOp<InstIdpR>();
|
||||
context.GetOp<InstIdpR>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction IdpR is not implemented.");
|
||||
}
|
||||
|
||||
public static void IdpC(EmitterContext context)
|
||||
{
|
||||
InstIdpC op = context.GetOp<InstIdpC>();
|
||||
context.GetOp<InstIdpC>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction IdpC is not implemented.");
|
||||
}
|
||||
|
||||
public static void ImadspR(EmitterContext context)
|
||||
{
|
||||
InstImadspR op = context.GetOp<InstImadspR>();
|
||||
context.GetOp<InstImadspR>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction ImadspR is not implemented.");
|
||||
}
|
||||
|
||||
public static void ImadspI(EmitterContext context)
|
||||
{
|
||||
InstImadspI op = context.GetOp<InstImadspI>();
|
||||
context.GetOp<InstImadspI>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction ImadspI is not implemented.");
|
||||
}
|
||||
|
||||
public static void ImadspC(EmitterContext context)
|
||||
{
|
||||
InstImadspC op = context.GetOp<InstImadspC>();
|
||||
context.GetOp<InstImadspC>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction ImadspC is not implemented.");
|
||||
}
|
||||
|
||||
public static void ImadspRc(EmitterContext context)
|
||||
{
|
||||
InstImadspRc op = context.GetOp<InstImadspRc>();
|
||||
context.GetOp<InstImadspRc>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction ImadspRc is not implemented.");
|
||||
}
|
||||
|
||||
public static void Jcal(EmitterContext context)
|
||||
{
|
||||
InstJcal op = context.GetOp<InstJcal>();
|
||||
context.GetOp<InstJcal>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction Jcal is not implemented.");
|
||||
}
|
||||
|
||||
public static void Jmp(EmitterContext context)
|
||||
{
|
||||
InstJmp op = context.GetOp<InstJmp>();
|
||||
context.GetOp<InstJmp>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction Jmp is not implemented.");
|
||||
}
|
||||
|
||||
public static void Jmx(EmitterContext context)
|
||||
{
|
||||
InstJmx op = context.GetOp<InstJmx>();
|
||||
context.GetOp<InstJmx>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction Jmx is not implemented.");
|
||||
}
|
||||
|
||||
public static void Ld(EmitterContext context)
|
||||
{
|
||||
InstLd op = context.GetOp<InstLd>();
|
||||
context.GetOp<InstLd>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction Ld is not implemented.");
|
||||
}
|
||||
|
||||
public static void Lepc(EmitterContext context)
|
||||
{
|
||||
InstLepc op = context.GetOp<InstLepc>();
|
||||
context.GetOp<InstLepc>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction Lepc is not implemented.");
|
||||
}
|
||||
|
||||
public static void Longjmp(EmitterContext context)
|
||||
{
|
||||
InstLongjmp op = context.GetOp<InstLongjmp>();
|
||||
context.GetOp<InstLongjmp>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction Longjmp is not implemented.");
|
||||
}
|
||||
|
||||
public static void Pexit(EmitterContext context)
|
||||
{
|
||||
InstPexit op = context.GetOp<InstPexit>();
|
||||
context.GetOp<InstPexit>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction Pexit is not implemented.");
|
||||
}
|
||||
|
||||
public static void Pixld(EmitterContext context)
|
||||
{
|
||||
InstPixld op = context.GetOp<InstPixld>();
|
||||
context.GetOp<InstPixld>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction Pixld is not implemented.");
|
||||
}
|
||||
|
||||
public static void Plongjmp(EmitterContext context)
|
||||
{
|
||||
InstPlongjmp op = context.GetOp<InstPlongjmp>();
|
||||
context.GetOp<InstPlongjmp>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction Plongjmp is not implemented.");
|
||||
}
|
||||
|
||||
public static void Pret(EmitterContext context)
|
||||
{
|
||||
InstPret op = context.GetOp<InstPret>();
|
||||
context.GetOp<InstPret>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction Pret is not implemented.");
|
||||
}
|
||||
|
||||
public static void PrmtR(EmitterContext context)
|
||||
{
|
||||
InstPrmtR op = context.GetOp<InstPrmtR>();
|
||||
context.GetOp<InstPrmtR>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction PrmtR is not implemented.");
|
||||
}
|
||||
|
||||
public static void PrmtI(EmitterContext context)
|
||||
{
|
||||
InstPrmtI op = context.GetOp<InstPrmtI>();
|
||||
context.GetOp<InstPrmtI>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction PrmtI is not implemented.");
|
||||
}
|
||||
|
||||
public static void PrmtC(EmitterContext context)
|
||||
{
|
||||
InstPrmtC op = context.GetOp<InstPrmtC>();
|
||||
context.GetOp<InstPrmtC>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction PrmtC is not implemented.");
|
||||
}
|
||||
|
||||
public static void PrmtRc(EmitterContext context)
|
||||
{
|
||||
InstPrmtRc op = context.GetOp<InstPrmtRc>();
|
||||
context.GetOp<InstPrmtRc>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction PrmtRc is not implemented.");
|
||||
}
|
||||
|
||||
public static void R2b(EmitterContext context)
|
||||
{
|
||||
InstR2b op = context.GetOp<InstR2b>();
|
||||
context.GetOp<InstR2b>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction R2b is not implemented.");
|
||||
}
|
||||
|
||||
public static void Ram(EmitterContext context)
|
||||
{
|
||||
InstRam op = context.GetOp<InstRam>();
|
||||
context.GetOp<InstRam>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction Ram is not implemented.");
|
||||
}
|
||||
|
||||
public static void Rtt(EmitterContext context)
|
||||
{
|
||||
InstRtt op = context.GetOp<InstRtt>();
|
||||
context.GetOp<InstRtt>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction Rtt is not implemented.");
|
||||
}
|
||||
|
||||
public static void Sam(EmitterContext context)
|
||||
{
|
||||
InstSam op = context.GetOp<InstSam>();
|
||||
context.GetOp<InstSam>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction Sam is not implemented.");
|
||||
}
|
||||
|
||||
public static void Setcrsptr(EmitterContext context)
|
||||
{
|
||||
InstSetcrsptr op = context.GetOp<InstSetcrsptr>();
|
||||
context.GetOp<InstSetcrsptr>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction Setcrsptr is not implemented.");
|
||||
}
|
||||
|
||||
public static void Setlmembase(EmitterContext context)
|
||||
{
|
||||
InstSetlmembase op = context.GetOp<InstSetlmembase>();
|
||||
context.GetOp<InstSetlmembase>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction Setlmembase is not implemented.");
|
||||
}
|
||||
|
||||
public static void St(EmitterContext context)
|
||||
{
|
||||
InstSt op = context.GetOp<InstSt>();
|
||||
context.GetOp<InstSt>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction St is not implemented.");
|
||||
}
|
||||
|
||||
public static void Stp(EmitterContext context)
|
||||
{
|
||||
InstStp op = context.GetOp<InstStp>();
|
||||
context.GetOp<InstStp>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction Stp is not implemented.");
|
||||
}
|
||||
|
||||
public static void Txa(EmitterContext context)
|
||||
{
|
||||
InstTxa op = context.GetOp<InstTxa>();
|
||||
context.GetOp<InstTxa>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction Txa is not implemented.");
|
||||
}
|
||||
|
||||
public static void Vabsdiff(EmitterContext context)
|
||||
{
|
||||
InstVabsdiff op = context.GetOp<InstVabsdiff>();
|
||||
context.GetOp<InstVabsdiff>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction Vabsdiff is not implemented.");
|
||||
}
|
||||
|
||||
public static void Vabsdiff4(EmitterContext context)
|
||||
{
|
||||
InstVabsdiff4 op = context.GetOp<InstVabsdiff4>();
|
||||
context.GetOp<InstVabsdiff4>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction Vabsdiff4 is not implemented.");
|
||||
}
|
||||
|
||||
public static void Vadd(EmitterContext context)
|
||||
{
|
||||
InstVadd op = context.GetOp<InstVadd>();
|
||||
context.GetOp<InstVadd>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction Vadd is not implemented.");
|
||||
}
|
||||
|
||||
public static void Votevtg(EmitterContext context)
|
||||
{
|
||||
InstVotevtg op = context.GetOp<InstVotevtg>();
|
||||
context.GetOp<InstVotevtg>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction Votevtg is not implemented.");
|
||||
}
|
||||
|
||||
public static void Vset(EmitterContext context)
|
||||
{
|
||||
InstVset op = context.GetOp<InstVset>();
|
||||
context.GetOp<InstVset>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction Vset is not implemented.");
|
||||
}
|
||||
|
||||
public static void Vshl(EmitterContext context)
|
||||
{
|
||||
InstVshl op = context.GetOp<InstVshl>();
|
||||
context.GetOp<InstVshl>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction Vshl is not implemented.");
|
||||
}
|
||||
|
||||
public static void Vshr(EmitterContext context)
|
||||
{
|
||||
InstVshr op = context.GetOp<InstVshr>();
|
||||
context.GetOp<InstVshr>();
|
||||
|
||||
context.Config.GpuAccessor.Log("Shader instruction Vshr is not implemented.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -2,7 +2,6 @@ using Ryujinx.Graphics.Shader.Decoders;
|
||||
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
||||
using Ryujinx.Graphics.Shader.Translation;
|
||||
using System;
|
||||
|
||||
using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper;
|
||||
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
||||
|
||||
@@ -18,7 +17,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
IDstFmt.S16 => short.MinValue,
|
||||
IDstFmt.U32 => uint.MinValue,
|
||||
IDstFmt.S32 => int.MinValue,
|
||||
_ => throw new ArgumentException($"The type \"{type}\" is not a supported integer type.")
|
||||
_ => throw new ArgumentException($"The type \"{type}\" is not a supported integer type."),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -30,7 +29,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
IDstFmt.S16 => short.MaxValue,
|
||||
IDstFmt.U32 => uint.MaxValue,
|
||||
IDstFmt.S32 => int.MaxValue,
|
||||
_ => throw new ArgumentException($"The type \"{type}\" is not a supported integer type.")
|
||||
_ => throw new ArgumentException($"The type \"{type}\" is not a supported integer type."),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -44,7 +43,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
ISrcDstFmt.S16 => short.MinValue,
|
||||
ISrcDstFmt.U32 => uint.MinValue,
|
||||
ISrcDstFmt.S32 => int.MinValue,
|
||||
_ => throw new ArgumentException($"The type \"{type}\" is not a supported integer type.")
|
||||
_ => throw new ArgumentException($"The type \"{type}\" is not a supported integer type."),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -58,7 +57,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
ISrcDstFmt.S16 => short.MaxValue,
|
||||
ISrcDstFmt.U32 => uint.MaxValue,
|
||||
ISrcDstFmt.S32 => int.MaxValue,
|
||||
_ => throw new ArgumentException($"The type \"{type}\" is not a supported integer type.")
|
||||
_ => throw new ArgumentException($"The type \"{type}\" is not a supported integer type."),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -69,7 +68,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
BoolOp.And => context.BitwiseAnd(input, pred),
|
||||
BoolOp.Or => context.BitwiseOr(input, pred),
|
||||
BoolOp.Xor => context.BitwiseExclusiveOr(input, pred),
|
||||
_ => input
|
||||
_ => input,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -89,7 +88,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
VectorSelect.S8B3 => SignExtendTo32(context, context.ShiftRightU32(src, Const(24)), 8),
|
||||
VectorSelect.S16H0 => SignExtendTo32(context, context.ShiftRightU32(src, Const(0)), 16),
|
||||
VectorSelect.S16H1 => SignExtendTo32(context, context.ShiftRightU32(src, Const(16)), 16),
|
||||
_ => src
|
||||
_ => src,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -134,7 +133,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
}
|
||||
|
||||
context.Copy(GetZF(), context.FPCompareEqual(dest, zero, fpType));
|
||||
context.Copy(GetNF(), context.FPCompareLess (dest, zero, fpType));
|
||||
context.Copy(GetNF(), context.FPCompareLess(dest, zero, fpType));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,4 +156,4 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -33,7 +33,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
|
||||
for (int index = 0; index < (int)op.AlSize + 1; index++)
|
||||
{
|
||||
Register rd = new Register(op.Dest + index, RegisterType.Gpr);
|
||||
Register rd = new(op.Dest + index, RegisterType.Gpr);
|
||||
|
||||
if (rd.IsRZ)
|
||||
{
|
||||
@@ -91,7 +91,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
break;
|
||||
}
|
||||
|
||||
Register rd = new Register(op.SrcB + index, RegisterType.Gpr);
|
||||
Register rd = new(op.SrcB + index, RegisterType.Gpr);
|
||||
|
||||
if (op.Phys)
|
||||
{
|
||||
@@ -380,4 +380,4 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -22,7 +22,9 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
|
||||
public static void Depbar(EmitterContext context)
|
||||
{
|
||||
#pragma warning disable IDE0059 // Remove unnecessary value assignment
|
||||
InstDepbar op = context.GetOp<InstDepbar>();
|
||||
#pragma warning restore IDE0059
|
||||
|
||||
// No operation.
|
||||
}
|
||||
@@ -41,4 +43,4 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -191,4 +191,4 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
context.Copy(GetDest(rd), res);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,6 @@
|
||||
using Ryujinx.Graphics.Shader.Decoders;
|
||||
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
||||
using Ryujinx.Graphics.Shader.Translation;
|
||||
|
||||
using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper;
|
||||
using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper;
|
||||
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
||||
@@ -80,8 +79,8 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
Ccc.Oft => GetVF(),
|
||||
Ccc.Rle => context.BitwiseOr(GetNF(), GetZF()),
|
||||
Ccc.Rgt => context.BitwiseNot(context.BitwiseOr(GetNF(), GetZF())),
|
||||
_ => Const(defaultCond)
|
||||
_ => Const(defaultCond),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -2,7 +2,6 @@ using Ryujinx.Graphics.Shader.Decoders;
|
||||
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
||||
using Ryujinx.Graphics.Shader.Translation;
|
||||
using System;
|
||||
|
||||
using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper;
|
||||
using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper;
|
||||
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
||||
@@ -140,7 +139,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
IntegerRound.Floor => context.FPFloor(srcB, srcType.ToInstFPType()),
|
||||
IntegerRound.Ceil => context.FPCeiling(srcB, srcType.ToInstFPType()),
|
||||
IntegerRound.Trunc => context.FPTruncate(srcB, srcType.ToInstFPType()),
|
||||
_ => srcB
|
||||
_ => srcB,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -191,7 +190,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
RoundMode2.Floor => context.FPFloor(srcB, fpType),
|
||||
RoundMode2.Ceil => context.FPCeiling(srcB, fpType),
|
||||
RoundMode2.Trunc => context.FPTruncate(srcB, fpType),
|
||||
_ => srcB
|
||||
_ => srcB,
|
||||
};
|
||||
|
||||
if (!isSignedInt)
|
||||
@@ -422,4 +421,4 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
return type == DstFmt.F64 ? Instruction.FP64 : Instruction.FP32;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,6 @@
|
||||
using Ryujinx.Graphics.Shader.Decoders;
|
||||
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
||||
using Ryujinx.Graphics.Shader.Translation;
|
||||
|
||||
using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper;
|
||||
using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper;
|
||||
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
||||
@@ -458,7 +457,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
MultiplyScale.M2 => ConstF(2f),
|
||||
MultiplyScale.M4 => ConstF(4f),
|
||||
MultiplyScale.M8 => ConstF(8f),
|
||||
_ => ConstF(1f) // Invalid, behave as if it had no scale.
|
||||
_ => ConstF(1f), // Invalid, behave as if it had no scale.
|
||||
};
|
||||
|
||||
if (scaleConst.AsFloat() == 1f)
|
||||
@@ -529,4 +528,4 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
context.Copy(GetDest(rd), GetHalfPacked(context, swizzle, res, rd));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -2,7 +2,6 @@ using Ryujinx.Graphics.Shader.Decoders;
|
||||
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
||||
using Ryujinx.Graphics.Shader.Translation;
|
||||
using System;
|
||||
|
||||
using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper;
|
||||
using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper;
|
||||
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
||||
@@ -484,8 +483,8 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
}
|
||||
else
|
||||
{
|
||||
Operand low = context.BitwiseAnd(res[0], Const(0xffff));
|
||||
Operand high = context.ShiftLeft (res[1], Const(16));
|
||||
Operand low = context.BitwiseAnd(res[0], Const(0xffff));
|
||||
Operand high = context.ShiftLeft(res[1], Const(16));
|
||||
|
||||
Operand packed = context.BitwiseOr(low, high);
|
||||
|
||||
@@ -546,20 +545,16 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
}
|
||||
else
|
||||
{
|
||||
Instruction inst;
|
||||
|
||||
switch (cond & ~FComp.Nan)
|
||||
var inst = (cond & ~FComp.Nan) switch
|
||||
{
|
||||
case FComp.Lt: inst = Instruction.CompareLess; break;
|
||||
case FComp.Eq: inst = Instruction.CompareEqual; break;
|
||||
case FComp.Le: inst = Instruction.CompareLessOrEqual; break;
|
||||
case FComp.Gt: inst = Instruction.CompareGreater; break;
|
||||
case FComp.Ne: inst = Instruction.CompareNotEqual; break;
|
||||
case FComp.Ge: inst = Instruction.CompareGreaterOrEqual; break;
|
||||
|
||||
default: throw new ArgumentException($"Unexpected condition \"{cond}\".");
|
||||
}
|
||||
|
||||
FComp.Lt => Instruction.CompareLess,
|
||||
FComp.Eq => Instruction.CompareEqual,
|
||||
FComp.Le => Instruction.CompareLessOrEqual,
|
||||
FComp.Gt => Instruction.CompareGreater,
|
||||
FComp.Ne => Instruction.CompareNotEqual,
|
||||
FComp.Ge => Instruction.CompareGreaterOrEqual,
|
||||
_ => throw new ArgumentException($"Unexpected condition \"{cond}\"."),
|
||||
};
|
||||
res = context.Add(inst | fpType, Local(), srcA, srcB);
|
||||
|
||||
if ((cond & FComp.Nan) != 0)
|
||||
@@ -572,4 +567,4 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -103,4 +103,4 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
SetFPZnFlags(context, res, writeCC, fpType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -3,8 +3,6 @@ using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
||||
using Ryujinx.Graphics.Shader.Translation;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper;
|
||||
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
||||
|
||||
namespace Ryujinx.Graphics.Shader.Instructions
|
||||
@@ -13,14 +11,14 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
{
|
||||
public static void Bra(EmitterContext context)
|
||||
{
|
||||
InstBra op = context.GetOp<InstBra>();
|
||||
context.GetOp<InstBra>();
|
||||
|
||||
EmitBranch(context, context.CurrBlock.Successors[^1].Address);
|
||||
}
|
||||
|
||||
public static void Brk(EmitterContext context)
|
||||
{
|
||||
InstBrk op = context.GetOp<InstBrk>();
|
||||
context.GetOp<InstBrk>();
|
||||
|
||||
EmitBrkContSync(context);
|
||||
}
|
||||
@@ -123,7 +121,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
|
||||
public static void Cal(EmitterContext context)
|
||||
{
|
||||
InstCal op = context.GetOp<InstCal>();
|
||||
context.GetOp<InstCal>();
|
||||
|
||||
DecodedFunction function = context.Program.GetFunctionByAddress(context.CurrOp.GetAbsoluteAddress());
|
||||
|
||||
@@ -147,7 +145,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
|
||||
public static void Cont(EmitterContext context)
|
||||
{
|
||||
InstCont op = context.GetOp<InstCont>();
|
||||
context.GetOp<InstCont>();
|
||||
|
||||
EmitBrkContSync(context);
|
||||
}
|
||||
@@ -185,28 +183,28 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
|
||||
public static void Kil(EmitterContext context)
|
||||
{
|
||||
InstKil op = context.GetOp<InstKil>();
|
||||
context.GetOp<InstKil>();
|
||||
|
||||
context.Discard();
|
||||
}
|
||||
|
||||
public static void Pbk(EmitterContext context)
|
||||
{
|
||||
InstPbk op = context.GetOp<InstPbk>();
|
||||
context.GetOp<InstPbk>();
|
||||
|
||||
EmitPbkPcntSsy(context);
|
||||
}
|
||||
|
||||
public static void Pcnt(EmitterContext context)
|
||||
{
|
||||
InstPcnt op = context.GetOp<InstPcnt>();
|
||||
context.GetOp<InstPcnt>();
|
||||
|
||||
EmitPbkPcntSsy(context);
|
||||
}
|
||||
|
||||
public static void Ret(EmitterContext context)
|
||||
{
|
||||
InstRet op = context.GetOp<InstRet>();
|
||||
context.GetOp<InstRet>();
|
||||
|
||||
if (context.IsNonMain)
|
||||
{
|
||||
@@ -220,14 +218,14 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
|
||||
public static void Ssy(EmitterContext context)
|
||||
{
|
||||
InstSsy op = context.GetOp<InstSsy>();
|
||||
context.GetOp<InstSsy>();
|
||||
|
||||
EmitPbkPcntSsy(context);
|
||||
}
|
||||
|
||||
public static void Sync(EmitterContext context)
|
||||
{
|
||||
InstSync op = context.GetOp<InstSync>();
|
||||
context.GetOp<InstSync>();
|
||||
|
||||
EmitBrkContSync(context);
|
||||
}
|
||||
@@ -275,7 +273,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
private static void EmitBranch(EmitterContext context, ulong address)
|
||||
{
|
||||
InstOp op = context.CurrOp;
|
||||
InstConditional opCond = new InstConditional(op.RawOpCode);
|
||||
InstConditional opCond = new(op.RawOpCode);
|
||||
|
||||
// If we're branching to the next instruction, then the branch
|
||||
// is useless and we can ignore it.
|
||||
@@ -321,4 +319,4 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -3,7 +3,6 @@ using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
||||
using Ryujinx.Graphics.Shader.Translation;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
||||
|
||||
namespace Ryujinx.Graphics.Shader.Instructions
|
||||
@@ -111,7 +110,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
return new Operand[]
|
||||
{
|
||||
ConstF((float)Unsafe.As<ushort, Half>(ref low)),
|
||||
ConstF((float)Unsafe.As<ushort, Half>(ref high))
|
||||
ConstF((float)Unsafe.As<ushort, Half>(ref high)),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -123,7 +122,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
return new Operand[]
|
||||
{
|
||||
ConstF((float)Unsafe.As<ushort, Half>(ref low)),
|
||||
ConstF((float)Unsafe.As<ushort, Half>(ref high))
|
||||
ConstF((float)Unsafe.As<ushort, Half>(ref high)),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -139,56 +138,51 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
|
||||
public static Operand[] GetHalfUnpacked(EmitterContext context, Operand src, HalfSwizzle swizzle)
|
||||
{
|
||||
switch (swizzle)
|
||||
return swizzle switch
|
||||
{
|
||||
case HalfSwizzle.F16:
|
||||
return new Operand[]
|
||||
{
|
||||
HalfSwizzle.F16 => new Operand[]
|
||||
{
|
||||
context.UnpackHalf2x16Low (src),
|
||||
context.UnpackHalf2x16High(src)
|
||||
};
|
||||
|
||||
case HalfSwizzle.F32: return new Operand[] { src, src };
|
||||
|
||||
case HalfSwizzle.H0H0:
|
||||
return new Operand[]
|
||||
context.UnpackHalf2x16High(src),
|
||||
},
|
||||
HalfSwizzle.F32 => new Operand[] { src, src },
|
||||
HalfSwizzle.H0H0 => new Operand[]
|
||||
{
|
||||
context.UnpackHalf2x16Low(src),
|
||||
context.UnpackHalf2x16Low(src)
|
||||
};
|
||||
|
||||
case HalfSwizzle.H1H1:
|
||||
return new Operand[]
|
||||
context.UnpackHalf2x16Low(src),
|
||||
},
|
||||
HalfSwizzle.H1H1 => new Operand[]
|
||||
{
|
||||
context.UnpackHalf2x16High(src),
|
||||
context.UnpackHalf2x16High(src)
|
||||
};
|
||||
}
|
||||
|
||||
throw new ArgumentException($"Invalid swizzle \"{swizzle}\".");
|
||||
context.UnpackHalf2x16High(src),
|
||||
},
|
||||
_ => throw new ArgumentException($"Invalid swizzle \"{swizzle}\"."),
|
||||
};
|
||||
}
|
||||
|
||||
public static Operand GetHalfPacked(EmitterContext context, OFmt swizzle, Operand[] results, int rd)
|
||||
{
|
||||
switch (swizzle)
|
||||
{
|
||||
case OFmt.F16: return context.PackHalf2x16(results[0], results[1]);
|
||||
case OFmt.F16:
|
||||
return context.PackHalf2x16(results[0], results[1]);
|
||||
|
||||
case OFmt.F32: return results[0];
|
||||
case OFmt.F32:
|
||||
return results[0];
|
||||
|
||||
case OFmt.MrgH0:
|
||||
{
|
||||
Operand h1 = GetHalfDest(context, rd, isHigh: true);
|
||||
{
|
||||
Operand h1 = GetHalfDest(context, rd, isHigh: true);
|
||||
|
||||
return context.PackHalf2x16(results[0], h1);
|
||||
}
|
||||
return context.PackHalf2x16(results[0], h1);
|
||||
}
|
||||
|
||||
case OFmt.MrgH1:
|
||||
{
|
||||
Operand h0 = GetHalfDest(context, rd, isHigh: false);
|
||||
{
|
||||
Operand h0 = GetHalfDest(context, rd, isHigh: false);
|
||||
|
||||
return context.PackHalf2x16(h0, results[1]);
|
||||
}
|
||||
return context.PackHalf2x16(h0, results[1]);
|
||||
}
|
||||
}
|
||||
|
||||
throw new ArgumentException($"Invalid swizzle \"{swizzle}\".");
|
||||
@@ -263,4 +257,4 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
return context.BitwiseAnd(src, Const(mask));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -510,7 +510,9 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
aLow = context.BitwiseNot(aLow);
|
||||
aHigh = context.BitwiseNot(aHigh);
|
||||
|
||||
#pragma warning disable IDE0059 // Remove unnecessary value assignment
|
||||
aLow = AddWithCarry(context, aLow, Const(1), out Operand aLowCOut);
|
||||
#pragma warning restore IDE0059
|
||||
aHigh = context.IAdd(aHigh, aLowCOut);
|
||||
}
|
||||
|
||||
@@ -696,4 +698,4 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||
SetZnFlags(context, res, setCC: true, extended: extended);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user