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.Types;
using Ryujinx.Graphics.Nvdec.Vp9.Types;
using System.Diagnostics;
namespace Ryujinx.Graphics.Nvdec.Vp9
@@ -13,7 +13,8 @@ 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)
@@ -23,12 +24,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
else if (!xd.AboveMi.Value.HasSecondRef())
{
// One of two edges uses comp pred (2/3)
ctx = 2 + (xd.AboveMi.Value.RefFrame[0] == cm.CompFixedRef || !xd.AboveMi.Value.IsInterBlock() ? 1 : 0);
ctx = 2 + (xd.AboveMi.Value.RefFrame[0] == cm.CompFixedRef || !xd.AboveMi.Value.IsInterBlock()
? 1
: 0);
}
else if (!xd.LeftMi.Value.HasSecondRef())
{
// One of two edges uses comp pred (2/3)
ctx = 2 + (xd.LeftMi.Value.RefFrame[0] == cm.CompFixedRef || !xd.LeftMi.Value.IsInterBlock() ? 1 : 0);
ctx = 2 +
(xd.LeftMi.Value.RefFrame[0] == cm.CompFixedRef || !xd.LeftMi.Value.IsInterBlock() ? 1 : 0);
}
else // Both edges use comp pred (4)
{
@@ -36,7 +40,8 @@ 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.HasSecondRef())
@@ -51,11 +56,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
}
else
{ // No edges available (1)
{
// No edges available (1)
ctx = 1;
}
Debug.Assert(ctx >= 0 && ctx < Constants.CompInterContexts);
Debug.Assert(ctx >= 0 && ctx < Constants.CompInterContexts);
return ctx;
}
@@ -71,29 +77,33 @@ 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)
{
predContext = 1 + 2 * (edgeMi.RefFrame[0] != cm.CompVarRef[1] ? 1 : 0);
predContext = 1 + (2 * (edgeMi.RefFrame[0] != cm.CompVarRef[1] ? 1 : 0));
}
else // Comp pred (1/3)
{
predContext = 1 + 2 * (edgeMi.RefFrame[varRefIdx] != cm.CompVarRef[1] ? 1 : 0);
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];
@@ -104,7 +114,8 @@ 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]))
{
@@ -120,7 +131,8 @@ 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])
@@ -137,7 +149,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
}
else if (vrfa == vrfl)
{ // Comp/Comp
{
// Comp/Comp
predContext = 4;
}
else
@@ -147,7 +160,8 @@ 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())
@@ -167,11 +181,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
}
else
{ // No edges available (2)
{
// No edges available (2)
predContext = 2;
}
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
return predContext;
}
@@ -183,16 +198,19 @@ 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())
{
@@ -201,11 +219,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
else
{
predContext = 1 + (edgeMi.RefFrame[0] == Constants.LastFrame ||
edgeMi.RefFrame[1] == Constants.LastFrame ? 1 : 0);
edgeMi.RefFrame[1] == Constants.LastFrame
? 1
: 0);
}
}
else
{ // Inter/Inter
{
// Inter/Inter
bool aboveHasSecond = xd.AboveMi.Value.HasSecondRef();
bool leftHasSecond = xd.LeftMi.Value.HasSecondRef();
sbyte above0 = xd.AboveMi.Value.RefFrame[0];
@@ -216,7 +237,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
if (aboveHasSecond && leftHasSecond)
{
predContext = 1 + (above0 == Constants.LastFrame || above1 == Constants.LastFrame ||
left0 == Constants.LastFrame || left1 == Constants.LastFrame ? 1 : 0);
left0 == Constants.LastFrame || left1 == Constants.LastFrame
? 1
: 0);
}
else if (aboveHasSecond || leftHasSecond)
{
@@ -230,24 +253,28 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
else
{
predContext = (crf1 == Constants.LastFrame || crf2 == Constants.LastFrame ? 1 : 0);
predContext = crf1 == Constants.LastFrame || crf2 == Constants.LastFrame ? 1 : 0;
}
}
else
{
predContext = 2 * (above0 == Constants.LastFrame ? 1 : 0) + 2 * (left0 == Constants.LastFrame ? 1 : 0);
predContext = (2 * (above0 == Constants.LastFrame ? 1 : 0)) +
(2 * (left0 == Constants.LastFrame ? 1 : 0));
}
}
}
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);
@@ -255,16 +282,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
else
{
predContext = 1 + (edgeMi.RefFrame[0] == Constants.LastFrame ||
edgeMi.RefFrame[1] == Constants.LastFrame ? 1 : 0);
edgeMi.RefFrame[1] == Constants.LastFrame
? 1
: 0);
}
}
}
else
{ // No edges available
{
// No edges available
predContext = 2;
}
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
return predContext;
}
@@ -277,16 +307,19 @@ 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())
{
@@ -301,12 +334,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
else
{
predContext = 1 + 2 * (edgeMi.RefFrame[0] == Constants.GoldenFrame ||
edgeMi.RefFrame[1] == Constants.GoldenFrame ? 1 : 0);
predContext = 1 + (2 * (edgeMi.RefFrame[0] == Constants.GoldenFrame ||
edgeMi.RefFrame[1] == Constants.GoldenFrame
? 1
: 0));
}
}
else
{ // Inter/Inter
{
// Inter/Inter
bool aboveHasSecond = xd.AboveMi.Value.HasSecondRef();
bool leftHasSecond = xd.LeftMi.Value.HasSecondRef();
sbyte above0 = xd.AboveMi.Value.RefFrame[0];
@@ -319,7 +355,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
if (above0 == left0 && above1 == left1)
{
predContext = 3 * (above0 == Constants.GoldenFrame || above1 == Constants.GoldenFrame ||
left0 == Constants.GoldenFrame || left1 == Constants.GoldenFrame ? 1 : 0);
left0 == Constants.GoldenFrame || left1 == Constants.GoldenFrame
? 1
: 0);
}
else
{
@@ -342,7 +380,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
else
{
predContext = 1 + 2 * (crf1 == Constants.GoldenFrame || crf2 == Constants.GoldenFrame ? 1 : 0);
predContext =
1 + (2 * (crf1 == Constants.GoldenFrame || crf2 == Constants.GoldenFrame ? 1 : 0));
}
}
else
@@ -353,18 +392,20 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}
else if (above0 == Constants.LastFrame || left0 == Constants.LastFrame)
{
sbyte edge0 = (above0 == Constants.LastFrame) ? left0 : above0;
sbyte edge0 = above0 == Constants.LastFrame ? left0 : above0;
predContext = 4 * (edge0 == Constants.GoldenFrame ? 1 : 0);
}
else
{
predContext = 2 * (above0 == Constants.GoldenFrame ? 1 : 0) + 2 * (left0 == Constants.GoldenFrame ? 1 : 0);
predContext = (2 * (above0 == Constants.GoldenFrame ? 1 : 0)) +
(2 * (left0 == Constants.GoldenFrame ? 1 : 0));
}
}
}
}
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()))
@@ -378,16 +419,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
else
{
predContext = 3 * (edgeMi.RefFrame[0] == Constants.GoldenFrame ||
edgeMi.RefFrame[1] == Constants.GoldenFrame ? 1 : 0);
edgeMi.RefFrame[1] == Constants.GoldenFrame
? 1
: 0);
}
}
else
{ // No edges available (2)
{
// No edges available (2)
predContext = 2;
}
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
return predContext;
}
}
}
}