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,5 @@
using Ryujinx.Common.Memory;
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.Nvdec.Vp9.Types;
using System;
using System.Buffers.Binary;
@@ -6,18 +7,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
{
internal struct Reader
{
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,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 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, 0, 0, 0, 0, 0, 0,
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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 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, 0, 0, 0, 0, 0, 0
};
private const int BdValueSize = sizeof(ulong) * 8;
// This is meant to be a large, positive constant that can still be efficiently
@@ -36,16 +37,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
{
return true;
}
else
{
_buffer = new ArrayPtr<byte>(ref buffer[0], size);
Value = 0;
Count = -8;
Range = 255;
Fill();
return ReadBit() != 0; // Marker bit
}
_buffer = new ArrayPtr<byte>(ref buffer[0], size);
Value = 0;
Count = -8;
Range = 255;
Fill();
return ReadBit() != 0; // Marker bit
}
private void Fill()
@@ -65,7 +63,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
ulong bigEndianValues = BinaryPrimitives.ReadUInt64BigEndian(buffer);
nv = bigEndianValues >> (BdValueSize - bits);
count += bits;
buffer = buffer[(bits >> 3)..];
buffer = buffer.Slice(bits >> 3);
value = Value | (nv << (shift & 0x7));
}
else
@@ -84,7 +82,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
{
count += 8;
value |= (ulong)buffer[0] << shift;
buffer = buffer[1..];
buffer = buffer.Slice(1);
shift -= 8;
}
}
@@ -98,7 +96,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Count = count;
}
public readonly bool HasError()
public bool HasError()
{
// Check if we have reached the end of the buffer.
//
@@ -124,7 +122,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
ulong bigsplit;
int count;
uint range;
uint split = (Range * (uint)prob + (256 - (uint)prob)) >> 8;
uint split = ((Range * (uint)prob) + (256 - (uint)prob)) >> 8;
if (Count < 0)
{
@@ -146,7 +144,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
}
{
int shift = _norm[range];
int shift = Norm[range];
range <<= shift;
value <<= shift;
count -= shift;
@@ -188,7 +186,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
public int ReadBool(int prob, ref ulong value, ref int count, ref uint range)
{
uint split = (range * (uint)prob + (256 - (uint)prob)) >> 8;
uint split = ((range * (uint)prob) + (256 - (uint)prob)) >> 8;
ulong bigsplit = (ulong)split << (BdValueSize - 8);
if (count < 0)
@@ -202,19 +200,20 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
if (value >= bigsplit)
{
range -= split;
value -= bigsplit;
range = range - split;
value = value - bigsplit;
{
int shift = _norm[range];
int shift = Norm[range];
range <<= shift;
value <<= shift;
count -= shift;
}
return 1;
}
range = split;
{
int shift = _norm[range];
int shift = Norm[range];
range <<= shift;
value <<= shift;
count -= shift;
@@ -230,7 +229,82 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Count -= 8;
_buffer = _buffer.Slice(-1);
}
return _buffer;
}
private int DecodeUniform()
{
const int l = 8;
const int m = (1 << l) - 191;
int v = ReadLiteral(l - 1);
return v < m ? v : (v << 1) - m + ReadBit();
}
public int DecodeTermSubexp()
{
if (ReadBit() == 0)
{
return ReadLiteral(4);
}
if (ReadBit() == 0)
{
return ReadLiteral(4) + 16;
}
if (ReadBit() == 0)
{
return ReadLiteral(5) + 32;
}
return DecodeUniform() + 64;
}
public TxMode ReadTxMode()
{
TxMode txMode = (TxMode)ReadLiteral(2);
if (txMode == TxMode.Allow32x32)
{
txMode += ReadBit();
}
return txMode;
}
public int ReadCoeff(
ReadOnlySpan<byte> probs,
int n,
ref ulong value,
ref int count,
ref uint range)
{
int val = 0;
for (int i = 0; i < n; ++i)
{
val = (val << 1) | ReadBool(probs[i], ref value, ref count, ref range);
}
return val;
}
public void DiffUpdateProb(ref byte p)
{
if (Read(Entropy.DiffUpdateProb) != 0)
{
p = (byte)DSubExp.InvRemapProb(DecodeTermSubexp(), p);
}
}
public void UpdateMvProbs(Span<byte> p, int n)
{
for (int i = 0; i < n; ++i)
{
if (Read(EntropyMv.UpdateProb) != 0)
{
p[i] = (byte)((ReadLiteral(7) << 1) | 1);
}
}
}
}
}
}