Implement VP9 loop filtering

This commit is contained in:
gdkchan
2023-02-04 19:44:30 -03:00
committed by KeatonTheBot
parent d135385cab
commit b69b432b4c
79 changed files with 11301 additions and 3006 deletions

View File

@@ -1,4 +1,4 @@
using Ryujinx.Graphics.Nvdec.Vp9.Common;
using Ryujinx.Graphics.Nvdec.Vp9.Common;
using Ryujinx.Graphics.Nvdec.Vp9.Types;
using System;
using static Ryujinx.Graphics.Nvdec.Vp9.Dsp.IntraPred;
@@ -7,7 +7,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{
internal static class ReconIntra
{
public static readonly TxType[] IntraModeToTxTypeLookup = {
public static readonly TxType[] IntraModeToTxTypeLookup =
{
TxType.DctDct, // DC
TxType.AdstDct, // V
TxType.DctAdst, // H
@@ -17,7 +18,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
TxType.DctAdst, // D153
TxType.DctAdst, // D207
TxType.AdstDct, // D63
TxType.AdstAdst, // TM
TxType.AdstAdst // TM
};
private const int NeedLeft = 1 << 1;
@@ -35,231 +36,123 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
NeedLeft | NeedAbove, // D153
NeedLeft, // D207
NeedAboveRight, // D63
NeedLeft | NeedAbove, // TM
NeedLeft | NeedAbove // TM
};
private unsafe delegate void IntraPredFn(byte* dst, int stride, byte* above, byte* left);
private static readonly unsafe IntraPredFn[][] _pred = {
new IntraPredFn[]
{
null,
null,
null,
null,
},
new IntraPredFn[]
{
VPredictor4x4,
VPredictor8x8,
VPredictor16x16,
VPredictor32x32,
},
new IntraPredFn[]
{
HPredictor4x4,
HPredictor8x8,
HPredictor16x16,
HPredictor32x32,
},
new IntraPredFn[]
{
D45Predictor4x4,
D45Predictor8x8,
D45Predictor16x16,
D45Predictor32x32,
},
new IntraPredFn[]
{
D135Predictor4x4,
D135Predictor8x8,
D135Predictor16x16,
D135Predictor32x32,
},
new IntraPredFn[]
{
D117Predictor4x4,
D117Predictor8x8,
D117Predictor16x16,
D117Predictor32x32,
},
new IntraPredFn[]
{
D153Predictor4x4,
D153Predictor8x8,
D153Predictor16x16,
D153Predictor32x32,
},
new IntraPredFn[]
{
D207Predictor4x4,
D207Predictor8x8,
D207Predictor16x16,
D207Predictor32x32,
},
new IntraPredFn[]
{
D63Predictor4x4,
D63Predictor8x8,
D63Predictor16x16,
D63Predictor32x32,
},
new IntraPredFn[]
{
TMPredictor4x4,
TMPredictor8x8,
TMPredictor16x16,
TMPredictor32x32,
},
private static readonly unsafe IntraPredFn[][] Pred =
{
new IntraPredFn[] { null, null, null, null },
new IntraPredFn[] { VPredictor4x4, VPredictor8x8, VPredictor16x16, VPredictor32x32 },
new IntraPredFn[] { HPredictor4x4, HPredictor8x8, HPredictor16x16, HPredictor32x32 },
new IntraPredFn[] { D45Predictor4x4, D45Predictor8x8, D45Predictor16x16, D45Predictor32x32 },
new IntraPredFn[] { D135Predictor4x4, D135Predictor8x8, D135Predictor16x16, D135Predictor32x32 },
new IntraPredFn[] { D117Predictor4x4, D117Predictor8x8, D117Predictor16x16, D117Predictor32x32 },
new IntraPredFn[] { D153Predictor4x4, D153Predictor8x8, D153Predictor16x16, D153Predictor32x32 },
new IntraPredFn[] { D207Predictor4x4, D207Predictor8x8, D207Predictor16x16, D207Predictor32x32 },
new IntraPredFn[] { D63Predictor4x4, D63Predictor8x8, D63Predictor16x16, D63Predictor32x32 },
new IntraPredFn[] { TmPredictor4x4, TmPredictor8x8, TmPredictor16x16, TmPredictor32x32 }
};
private static readonly unsafe IntraPredFn[][][] _dcPred = {
private static readonly unsafe IntraPredFn[][][] DcPred =
{
new[]
{
new IntraPredFn[]
{
Dc128Predictor4x4,
Dc128Predictor8x8,
Dc128Predictor16x16,
Dc128Predictor32x32,
Dc128Predictor4x4, Dc128Predictor8x8, Dc128Predictor16x16, Dc128Predictor32x32
},
new IntraPredFn[]
{
DcTopPredictor4x4,
DcTopPredictor8x8,
DcTopPredictor16x16,
DcTopPredictor32x32,
},
DcTopPredictor4x4, DcTopPredictor8x8, DcTopPredictor16x16, DcTopPredictor32x32
}
},
new[]
{
new IntraPredFn[]
{
DcLeftPredictor4x4,
DcLeftPredictor8x8,
DcLeftPredictor16x16,
DcLeftPredictor32x32,
DcLeftPredictor4x4, DcLeftPredictor8x8, DcLeftPredictor16x16, DcLeftPredictor32x32
},
new IntraPredFn[]
{
DcPredictor4x4,
DcPredictor8x8,
DcPredictor16x16,
DcPredictor32x32,
},
},
new IntraPredFn[] { DcPredictor4x4, DcPredictor8x8, DcPredictor16x16, DcPredictor32x32 }
}
};
private unsafe delegate void IntraHighPredFn(ushort* dst, int stride, ushort* above, ushort* left, int bd);
private static readonly unsafe IntraHighPredFn[][] _predHigh = {
private static readonly unsafe IntraHighPredFn[][] PredHigh =
{
new IntraHighPredFn[] { null, null, null, null },
new IntraHighPredFn[]
{
null,
null,
null,
null,
HighbdVPredictor4x4, HighbdVPredictor8x8, HighbdVPredictor16x16, HighbdVPredictor32x32
},
new IntraHighPredFn[]
{
HighbdVPredictor4x4,
HighbdVPredictor8x8,
HighbdVPredictor16x16,
HighbdVPredictor32x32,
HighbdHPredictor4x4, HighbdHPredictor8x8, HighbdHPredictor16x16, HighbdHPredictor32x32
},
new IntraHighPredFn[]
{
HighbdHPredictor4x4,
HighbdHPredictor8x8,
HighbdHPredictor16x16,
HighbdHPredictor32x32,
HighbdD45Predictor4x4, HighbdD45Predictor8x8, HighbdD45Predictor16x16, HighbdD45Predictor32x32
},
new IntraHighPredFn[]
{
HighbdD45Predictor4x4,
HighbdD45Predictor8x8,
HighbdD45Predictor16x16,
HighbdD45Predictor32x32,
HighbdD135Predictor4x4, HighbdD135Predictor8x8, HighbdD135Predictor16x16,
HighbdD135Predictor32x32
},
new IntraHighPredFn[]
{
HighbdD135Predictor4x4,
HighbdD135Predictor8x8,
HighbdD135Predictor16x16,
HighbdD135Predictor32x32,
HighbdD117Predictor4x4, HighbdD117Predictor8x8, HighbdD117Predictor16x16,
HighbdD117Predictor32x32
},
new IntraHighPredFn[]
{
HighbdD117Predictor4x4,
HighbdD117Predictor8x8,
HighbdD117Predictor16x16,
HighbdD117Predictor32x32,
HighbdD153Predictor4x4, HighbdD153Predictor8x8, HighbdD153Predictor16x16,
HighbdD153Predictor32x32
},
new IntraHighPredFn[]
{
HighbdD153Predictor4x4,
HighbdD153Predictor8x8,
HighbdD153Predictor16x16,
HighbdD153Predictor32x32,
HighbdD207Predictor4x4, HighbdD207Predictor8x8, HighbdD207Predictor16x16,
HighbdD207Predictor32x32
},
new IntraHighPredFn[]
{
HighbdD207Predictor4x4,
HighbdD207Predictor8x8,
HighbdD207Predictor16x16,
HighbdD207Predictor32x32,
HighbdD63Predictor4x4, HighbdD63Predictor8x8, HighbdD63Predictor16x16, HighbdD63Predictor32x32
},
new IntraHighPredFn[]
{
HighbdD63Predictor4x4,
HighbdD63Predictor8x8,
HighbdD63Predictor16x16,
HighbdD63Predictor32x32,
},
new IntraHighPredFn[]
{
HighbdTMPredictor4x4,
HighbdTMPredictor8x8,
HighbdTMPredictor16x16,
HighbdTMPredictor32x32,
},
HighbdTmPredictor4x4, HighbdTmPredictor8x8, HighbdTmPredictor16x16, HighbdTmPredictor32x32
}
};
private static readonly unsafe IntraHighPredFn[][][] _dcPredHigh = {
private static readonly unsafe IntraHighPredFn[][][] DcPredHigh =
{
new[]
{
new IntraHighPredFn[]
{
HighbdDc128Predictor4x4,
HighbdDc128Predictor8x8,
HighbdDc128Predictor16x16,
HighbdDc128Predictor32x32,
HighbdDc128Predictor4x4, HighbdDc128Predictor8x8, HighbdDc128Predictor16x16,
HighbdDc128Predictor32x32
},
new IntraHighPredFn[]
{
HighbdDcTopPredictor4x4,
HighbdDcTopPredictor8x8,
HighbdDcTopPredictor16x16,
HighbdDcTopPredictor32x32,
},
HighbdDcTopPredictor4x4, HighbdDcTopPredictor8x8, HighbdDcTopPredictor16x16,
HighbdDcTopPredictor32x32
}
},
new[]
{
new IntraHighPredFn[]
{
HighbdDcLeftPredictor4x4,
HighbdDcLeftPredictor8x8,
HighbdDcLeftPredictor16x16,
HighbdDcLeftPredictor32x32,
HighbdDcLeftPredictor4x4, HighbdDcLeftPredictor8x8, HighbdDcLeftPredictor16x16,
HighbdDcLeftPredictor32x32
},
new IntraHighPredFn[]
{
HighbdDcPredictor4x4,
HighbdDcPredictor8x8,
HighbdDcPredictor16x16,
HighbdDcPredictor32x32,
},
},
HighbdDcPredictor4x4, HighbdDcPredictor8x8, HighbdDcPredictor16x16,
HighbdDcPredictor32x32
}
}
};
private static unsafe void BuildIntraPredictorsHigh(
@@ -327,7 +220,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{
for (i = 0; i < bs; ++i)
{
leftCol[i] = refr[i * refStride - 1];
leftCol[i] = refr[(i * refStride) - 1];
}
}
else
@@ -335,12 +228,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
int extendBottom = frameHeight - y0;
for (i = 0; i < extendBottom; ++i)
{
leftCol[i] = refr[i * refStride - 1];
leftCol[i] = refr[(i * refStride) - 1];
}
for (; i < bs; ++i)
{
leftCol[i] = refr[(extendBottom - 1) * refStride - 1];
leftCol[i] = refr[((extendBottom - 1) * refStride) - 1];
}
}
}
@@ -349,7 +242,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
/* faster path if the block does not need extension */
for (i = 0; i < bs; ++i)
{
leftCol[i] = refr[i * refStride - 1];
leftCol[i] = refr[(i * refStride) - 1];
}
}
}
@@ -391,6 +284,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
MemoryUtil.Copy(aboveRow, aboveRef, bs);
}
}
aboveRow[-1] = leftAvailable != 0 ? aboveRef[-1] : (ushort)(baseVal + 1);
}
else
@@ -409,7 +303,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
if (xd.MbToRightEdge < 0)
{
/* slower path if the block needs border extension */
if (x0 + 2 * bs <= frameWidth)
if (x0 + (2 * bs) <= frameWidth)
{
if (rightAvailable != 0 && bs == 4)
{
@@ -427,7 +321,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
if (rightAvailable != 0 && bs == 4)
{
MemoryUtil.Copy(aboveRow, aboveRef, r);
MemoryUtil.Fill(aboveRow + r, aboveRow[r - 1], x0 + 2 * bs - frameWidth);
MemoryUtil.Fill(aboveRow + r, aboveRow[r - 1], x0 + (2 * bs) - frameWidth);
}
else
{
@@ -439,8 +333,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{
int r = frameWidth - x0;
MemoryUtil.Copy(aboveRow, aboveRef, r);
MemoryUtil.Fill(aboveRow + r, aboveRow[r - 1], x0 + 2 * bs - frameWidth);
MemoryUtil.Fill(aboveRow + r, aboveRow[r - 1], x0 + (2 * bs) - frameWidth);
}
aboveRow[-1] = leftAvailable != 0 ? aboveRef[-1] : (ushort)(baseVal + 1);
}
else
@@ -476,11 +371,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// Predict
if (mode == PredictionMode.DcPred)
{
_dcPredHigh[leftAvailable][upAvailable][(int)txSize](dst, dstStride, constAboveRow, leftCol, xd.Bd);
DcPredHigh[leftAvailable][upAvailable][(int)txSize](dst, dstStride, constAboveRow, leftCol, xd.Bd);
}
else
{
_predHigh[(int)mode][(int)txSize](dst, dstStride, constAboveRow, leftCol, xd.Bd);
PredHigh[(int)mode][(int)txSize](dst, dstStride, constAboveRow, leftCol, xd.Bd);
}
}
@@ -544,7 +439,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{
for (i = 0; i < bs; ++i)
{
leftCol[i] = refr[i * refStride - 1];
leftCol[i] = refr[(i * refStride) - 1];
}
}
else
@@ -552,12 +447,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
int extendBottom = frameHeight - y0;
for (i = 0; i < extendBottom; ++i)
{
leftCol[i] = refr[i * refStride - 1];
leftCol[i] = refr[(i * refStride) - 1];
}
for (; i < bs; ++i)
{
leftCol[i] = refr[(extendBottom - 1) * refStride - 1];
leftCol[i] = refr[((extendBottom - 1) * refStride) - 1];
}
}
}
@@ -566,7 +461,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
/* Faster path if the block does not need extension */
for (i = 0; i < bs; ++i)
{
leftCol[i] = refr[i * refStride - 1];
leftCol[i] = refr[(i * refStride) - 1];
}
}
}
@@ -608,6 +503,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
MemoryUtil.Copy(aboveRow, aboveRef, bs);
}
}
aboveRow[-1] = leftAvailable != 0 ? aboveRef[-1] : (byte)129;
}
else
@@ -626,7 +522,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
if (xd.MbToRightEdge < 0)
{
/* Slower path if the block needs border extension */
if (x0 + 2 * bs <= frameWidth)
if (x0 + (2 * bs) <= frameWidth)
{
if (rightAvailable != 0 && bs == 4)
{
@@ -644,7 +540,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
if (rightAvailable != 0 && bs == 4)
{
MemoryUtil.Copy(aboveRow, aboveRef, r);
MemoryUtil.Fill(aboveRow + r, aboveRow[r - 1], x0 + 2 * bs - frameWidth);
MemoryUtil.Fill(aboveRow + r, aboveRow[r - 1], x0 + (2 * bs) - frameWidth);
}
else
{
@@ -656,7 +552,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{
int r = frameWidth - x0;
MemoryUtil.Copy(aboveRow, aboveRef, r);
MemoryUtil.Fill(aboveRow + r, aboveRow[r - 1], x0 + 2 * bs - frameWidth);
MemoryUtil.Fill(aboveRow + r, aboveRow[r - 1], x0 + (2 * bs) - frameWidth);
}
}
else
@@ -679,6 +575,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
}
}
aboveRow[-1] = leftAvailable != 0 ? aboveRef[-1] : (byte)129;
}
else
@@ -691,11 +588,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// Predict
if (mode == PredictionMode.DcPred)
{
_dcPred[leftAvailable][upAvailable][(int)txSize](dst, dstStride, constAboveRow, leftCol);
DcPred[leftAvailable][upAvailable][(int)txSize](dst, dstStride, constAboveRow, leftCol);
}
else
{
_pred[(int)mode][(int)txSize](dst, dstStride, constAboveRow, leftCol);
Pred[(int)mode][(int)txSize](dst, dstStride, constAboveRow, leftCol);
}
}
@@ -716,7 +613,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
int txw = 1 << (int)txSize;
int haveTop = loff != 0 || !xd.AboveMi.IsNull ? 1 : 0;
int haveLeft = aoff != 0 || !xd.LeftMi.IsNull ? 1 : 0;
int haveRight = (aoff + txw) < bw ? 1 : 0;
int haveRight = aoff + txw < bw ? 1 : 0;
int x = aoff * 4;
int y = loff * 4;
@@ -736,9 +633,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
x,
y,
plane);
return;
}
BuildIntraPredictors(
ref xd,
refr,
@@ -755,4 +652,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
plane);
}
}
}
}