Implement VP9 loop filtering
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user