Merge branch 'Ryubing:master' into 111
This commit is contained in:
commit
7230d2033a
@ -42,7 +42,7 @@
|
||||
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.3-build14" />
|
||||
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
|
||||
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
|
||||
<PackageVersion Include="Gommon" Version="2.7.1" />
|
||||
<PackageVersion Include="Gommon" Version="2.7.1.1" />
|
||||
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
|
||||
<PackageVersion Include="Sep" Version="0.6.0" />
|
||||
<PackageVersion Include="shaderc.net" Version="0.1.0" />
|
||||
|
@ -1436,7 +1436,7 @@
|
||||
010083A018262000,"Hitman: Blood Money — Reprisal",deadlock,ingame,2024-09-28 16:28:50
|
||||
01004B100A5CC000,"Hob: The Definitive Edition",,playable,2021-01-13 09:39:19
|
||||
0100F7300ED2C000,"Hoggy2",,playable,2022-10-10 13:53:35
|
||||
0100F7E00C70E000,"Hogwarts Legacy",slow,ingame,2024-09-03 19:53:58
|
||||
0100F7E00C70E000,"Hogwarts Legacy",UE4;slow,ingame,2024-09-03 19:53:58
|
||||
0100633007D48000,"Hollow Knight",nvdec,playable,2023-01-16 15:44:56
|
||||
0100F2100061E800,"Hollow0",UE4;gpu,ingame,2021-03-03 23:42:56
|
||||
0100342009E16000,"Holy Potatoes! What The Hell?!",,playable,2020-07-03 10:48:56
|
||||
@ -1800,6 +1800,7 @@
|
||||
010005A00B312000,"Megaton Rainfall",gpu;opengl,boots,2022-08-04 18:29:43
|
||||
0100EA100DF92000,"Meiji Katsugeki Haikara Ryuuseigumi - Seibai Shimaseu, Yonaoshi Kagyou",32-bit;nvdec,playable,2022-12-05 13:19:12
|
||||
0100B360068B2000,"Mekorama",gpu,boots,2021-06-17 16:37:21
|
||||
010012301932A000,"Melatonin",,playable,2025-02-16 04:08:17
|
||||
01000FA010340000,"Melbits World",nvdec;online,menus,2021-11-26 13:51:22
|
||||
0100F68019636000,"Melon Journey",,playable,2023-04-23 21:20:01
|
||||
010079C012896000,"Memories Off -Innocent Fille- for Dearest",,playable,2020-08-04 07:31:22
|
||||
|
|
@ -31,7 +31,7 @@ namespace ARMeilleure.Translation.Cache
|
||||
private static readonly Lock _lock = new();
|
||||
private static bool _initialized;
|
||||
|
||||
private static readonly List<ReservedRegion> _jitRegions = new();
|
||||
private static readonly List<ReservedRegion> _jitRegions = [];
|
||||
private static int _activeRegionIndex = 0;
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
@ -180,7 +180,7 @@ namespace ARMeilleure.Translation.Cache
|
||||
}
|
||||
|
||||
int exhaustedRegion = _activeRegionIndex;
|
||||
var newRegion = new ReservedRegion(_jitRegions[0].Allocator, CacheSize);
|
||||
ReservedRegion newRegion = new(_jitRegions[0].Allocator, CacheSize);
|
||||
_jitRegions.Add(newRegion);
|
||||
_activeRegionIndex = _jitRegions.Count - 1;
|
||||
|
||||
|
9
src/Ryujinx.Common/SharedConstants.cs
Normal file
9
src/Ryujinx.Common/SharedConstants.cs
Normal file
@ -0,0 +1,9 @@
|
||||
namespace Ryujinx.Common
|
||||
{
|
||||
public static class SharedConstants
|
||||
{
|
||||
public const string DefaultLanPlayHost = "ryuldn.vudjun.com";
|
||||
public const short LanPlayPort = 30456;
|
||||
public const string DefaultLanPlayWebHost = "ryuldnweb.vudjun.com";
|
||||
}
|
||||
}
|
@ -53,10 +53,9 @@ namespace Ryujinx.Common
|
||||
"0100000000010000", // Super Mario Odyssey
|
||||
|
||||
// Further testing is appreciated, I did not test the entire game:
|
||||
"01007300020fa000", // Astral Chain
|
||||
"010076f0049a2000", // Bayonetta
|
||||
"0100cf5010fec000", // Bayonetta Origins: Cereza and the Lost Demon
|
||||
"0100f4300bf2c000", // New Pokemon Snap
|
||||
//"010076f0049a2000", // Bayonetta
|
||||
//"0100cf5010fec000", // Bayonetta Origins: Cereza and the Lost Demon
|
||||
//"0100f4300bf2c000", // New Pokemon Snap
|
||||
];
|
||||
|
||||
public static string GetDiscordGameAsset(string titleId)
|
||||
@ -230,6 +229,7 @@ namespace Ryujinx.Common
|
||||
"01008c8012920000", // Dying Light Platinum Edition
|
||||
"01001cc01b2d4000", // Goat Simulator 3
|
||||
"01003620068ea000", // Hand of Fate 2
|
||||
"0100f7e00c70e000", // Hogwarts Legacy
|
||||
"010085500130a000", // Lego City: Undercover
|
||||
"010073c01af34000", // LEGO Horizon Adventures
|
||||
"0100d71004694000", // Minecraft
|
||||
|
@ -27,7 +27,7 @@ namespace Ryujinx.Cpu.LightningJit.Cache
|
||||
|
||||
private static readonly Lock _lock = new();
|
||||
private static bool _initialized;
|
||||
private static readonly List<ReservedRegion> _jitRegions = new();
|
||||
private static readonly List<ReservedRegion> _jitRegions = [];
|
||||
private static int _activeRegionIndex = 0;
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
|
@ -913,7 +913,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||
|
||||
Span<Rectangle<int>> scissors =
|
||||
[
|
||||
new Rectangle<int>(scissorX, scissorY, scissorW, scissorH)
|
||||
new(scissorX, scissorY, scissorW, scissorH)
|
||||
];
|
||||
|
||||
_context.Renderer.Pipeline.SetScissors(scissors);
|
||||
|
@ -729,7 +729,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
||||
|
||||
ShaderProgram program = translatorContext.Translate();
|
||||
|
||||
CachedShaderStage[] shaders = [new CachedShaderStage(program.Info, shader.Code, shader.Cb1Data)];
|
||||
CachedShaderStage[] shaders = [new(program.Info, shader.Code, shader.Cb1Data)];
|
||||
|
||||
_compilationQueue.Enqueue(new ProgramCompilation([program], shaders, newSpecState, programIndex, isCompute: true));
|
||||
}
|
||||
|
@ -6,4 +6,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
Bits10 = 10, // < 10 bits
|
||||
Bits12 = 12, // < 12 bits
|
||||
}
|
||||
}
|
||||
}
|
@ -1,56 +1,75 @@
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
{
|
||||
internal enum CodecErr
|
||||
{
|
||||
/*!\brief Operation completed without error */
|
||||
CodecOk,
|
||||
/// <summary>
|
||||
/// Operation completed without error
|
||||
/// </summary>
|
||||
Ok,
|
||||
|
||||
/*!\brief Unspecified error */
|
||||
CodecError,
|
||||
/// <summary>
|
||||
/// Unspecified error
|
||||
/// </summary>
|
||||
Error,
|
||||
|
||||
/*!\brief Memory operation failed */
|
||||
CodecMemError,
|
||||
/// <summary>
|
||||
/// Memory operation failed
|
||||
/// </summary>
|
||||
MemError,
|
||||
|
||||
/*!\brief ABI version mismatch */
|
||||
CodecAbiMismatch,
|
||||
/// <summary>
|
||||
/// ABI version mismatch
|
||||
/// </summary>
|
||||
AbiMismatch,
|
||||
|
||||
/*!\brief Algorithm does not have required capability */
|
||||
CodecIncapable,
|
||||
/// <summary>
|
||||
/// Algorithm does not have required capability
|
||||
/// </summary>
|
||||
Incapable,
|
||||
|
||||
/*!\brief The given bitstream is not supported.
|
||||
*
|
||||
* The bitstream was unable to be parsed at the highest level. The decoder
|
||||
* is unable to proceed. This error \ref SHOULD be treated as fatal to the
|
||||
* stream. */
|
||||
CodecUnsupBitstream,
|
||||
/// <summary>
|
||||
/// The given bitstream is not supported.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The bitstream was unable to be parsed at the highest level.<br/>
|
||||
/// The decoder is unable to proceed.<br/>
|
||||
/// This error SHOULD be treated as fatal to the stream.
|
||||
/// </remarks>
|
||||
UnsupBitstream,
|
||||
|
||||
/*!\brief Encoded bitstream uses an unsupported feature
|
||||
*
|
||||
* The decoder does not implement a feature required by the encoder. This
|
||||
* return code should only be used for features that prevent future
|
||||
* pictures from being properly decoded. This error \ref MAY be treated as
|
||||
* fatal to the stream or \ref MAY be treated as fatal to the current GOP.
|
||||
*/
|
||||
CodecUnsupFeature,
|
||||
/// <summary>
|
||||
/// Encoded bitstream uses an unsupported feature
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The decoder does not implement a feature required by the encoder.<br/>
|
||||
/// This return code should only be used for features that prevent future
|
||||
/// pictures from being properly decoded.<br/>
|
||||
/// <br/>
|
||||
/// This error MAY be treated as fatal to the stream or MAY be treated as fatal to the current GOP.
|
||||
/// </remarks>
|
||||
UnsupFeature,
|
||||
|
||||
/*!\brief The coded data for this stream is corrupt or incomplete
|
||||
*
|
||||
* There was a problem decoding the current frame. This return code
|
||||
* should only be used for failures that prevent future pictures from
|
||||
* being properly decoded. This error \ref MAY be treated as fatal to the
|
||||
* stream or \ref MAY be treated as fatal to the current GOP. If decoding
|
||||
* is continued for the current GOP, artifacts may be present.
|
||||
*/
|
||||
CodecCorruptFrame,
|
||||
/// <summary>
|
||||
/// The coded data for this stream is corrupt or incomplete.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// There was a problem decoding the current frame.<br/>
|
||||
/// This return code should only be used
|
||||
/// for failures that prevent future pictures from being properly decoded.<br/>
|
||||
/// <br/>
|
||||
/// This error MAY be treated as fatal to the stream or MAY be treated as fatal to the current GOP.<br/>
|
||||
/// If decoding is continued for the current GOP, artifacts may be present.
|
||||
/// </remarks>
|
||||
CorruptFrame,
|
||||
|
||||
/*!\brief An application-supplied parameter is not valid.
|
||||
*
|
||||
*/
|
||||
CodecInvalidParam,
|
||||
/// <summary>
|
||||
/// An application-supplied parameter is not valid.
|
||||
/// </summary>
|
||||
InvalidParam,
|
||||
|
||||
/*!\brief An iterator reached the end of list.
|
||||
*
|
||||
*/
|
||||
CodecListEnd,
|
||||
/// <summary>
|
||||
/// An iterator reached the end of list.
|
||||
/// </summary>
|
||||
ListEnd
|
||||
}
|
||||
}
|
||||
}
|
@ -10,7 +10,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static byte ClipPixel(int val)
|
||||
{
|
||||
return (byte)((val > 255) ? 255 : (val < 0) ? 0 : val);
|
||||
return (byte)(val > 255 ? 255 : val < 0 ? 0 : val);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
@ -56,4 +56,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common
|
||||
return numValues > 0 ? GetMsb(numValues) + 1 : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -51,6 +51,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common
|
||||
{
|
||||
Marshal.FreeHGlobal(item.Pointer);
|
||||
}
|
||||
|
||||
item.Pointer = ptr;
|
||||
item.Length = lengthInBytes;
|
||||
break;
|
||||
@ -58,7 +59,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common
|
||||
}
|
||||
}
|
||||
|
||||
return new ArrayPtr<T>(ptr, length);
|
||||
ArrayPtr<T> allocation = new(ptr, length);
|
||||
|
||||
allocation.AsSpan().Fill(default);
|
||||
|
||||
return allocation;
|
||||
}
|
||||
|
||||
public unsafe void Free<T>(ArrayPtr<T> arr) where T : unmanaged
|
||||
|
@ -20,4 +20,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common
|
||||
new Span<T>(ptr, length).Fill(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,8 +1,10 @@
|
||||
using Ryujinx.Graphics.Nvdec.Vp9.Types;
|
||||
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
{
|
||||
internal static class Constants
|
||||
{
|
||||
public const int Vp9InterpExtend = 4;
|
||||
public const int InterpExtend = 4;
|
||||
|
||||
public const int MaxMbPlane = 3;
|
||||
|
||||
@ -25,6 +27,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
/* Segment Feature Masks */
|
||||
public const int MaxMvRefCandidates = 2;
|
||||
|
||||
public const int IntraInterContexts = 4;
|
||||
public const int CompInterContexts = 5;
|
||||
public const int RefContexts = 5;
|
||||
|
||||
@ -32,12 +35,26 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
public const int EightTapSmooth = 1;
|
||||
public const int EightTapSharp = 2;
|
||||
public const int SwitchableFilters = 3; /* Number of switchable filters */
|
||||
|
||||
public const int Bilinear = 3;
|
||||
public const int Switchable = 4; /* should be the last one */
|
||||
|
||||
// The codec can operate in four possible inter prediction filter mode:
|
||||
// 8-tap, 8-tap-smooth, 8-tap-sharp, and switching between the three.
|
||||
public const int SwitchableFilterContexts = SwitchableFilters + 1;
|
||||
public const int Switchable = 4; /* Should be the last one */
|
||||
|
||||
// Frame
|
||||
public const int RefsPerFrame = 3;
|
||||
|
||||
public const int RefFramesLog2 = 3;
|
||||
public const int RefFrames = 1 << RefFramesLog2;
|
||||
|
||||
// 1 scratch frame for the new frame, 3 for scaled references on the encoder.
|
||||
public const int FrameBuffers = RefFrames + 4;
|
||||
|
||||
public const int FrameContextsLog2 = 2;
|
||||
public const int FrameContexts = 1 << FrameContextsLog2;
|
||||
|
||||
public const int NumPingPongBuffers = 2;
|
||||
|
||||
public const int Class0Bits = 1; /* bits at integer precision for class 0 */
|
||||
@ -48,9 +65,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
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;
|
||||
|
||||
@ -65,5 +82,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
|
||||
public const int SegmentAbsData = 1;
|
||||
public const int MaxSegments = 8;
|
||||
|
||||
public const int PartitionTypes = (int)PartitionType.PartitionTypes;
|
||||
|
||||
public const int PartitionPlOffset = 4; // Number of probability models per block size
|
||||
public const int PartitionContexts = 4 * PartitionPlOffset;
|
||||
|
||||
public const int PlaneTypes = (int)PlaneType.PlaneTypes;
|
||||
|
||||
public const int IntraModes = (int)PredictionMode.TmPred + 1;
|
||||
|
||||
public const int InterModes = 1 + (int)PredictionMode.NewMv - (int)PredictionMode.NearestMv;
|
||||
|
||||
public const int SkipContexts = 3;
|
||||
public const int InterModeContexts = 7;
|
||||
}
|
||||
}
|
||||
}
|
47
src/Ryujinx.Graphics.Nvdec.Vp9/DSubExp.cs
Normal file
47
src/Ryujinx.Graphics.Nvdec.Vp9/DSubExp.cs
Normal file
@ -0,0 +1,47 @@
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
{
|
||||
internal static class DSubExp
|
||||
{
|
||||
public static int InvRecenterNonneg(int v, int m)
|
||||
{
|
||||
if (v > 2 * m)
|
||||
{
|
||||
return v;
|
||||
}
|
||||
|
||||
return (v & 1) != 0 ? m - ((v + 1) >> 1) : m + (v >> 1);
|
||||
}
|
||||
|
||||
private static readonly byte[] _invMapTable =
|
||||
[
|
||||
7, 20, 33, 46, 59, 72, 85, 98, 111, 124, 137, 150, 163, 176, 189, 202, 215, 228, 241, 254, 1, 2, 3, 4,
|
||||
5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 34,
|
||||
35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 60, 61, 62,
|
||||
63, 64, 65, 66, 67, 68, 69, 70, 71, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 86, 87, 88, 89, 90,
|
||||
91, 92, 93, 94, 95, 96, 97, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 112, 113, 114,
|
||||
115, 116, 117, 118, 119, 120, 121, 122, 123, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136,
|
||||
138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 151, 152, 153, 154, 155, 156, 157, 158, 159,
|
||||
160, 161, 162, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 177, 178, 179, 180, 181, 182,
|
||||
183, 184, 185, 186, 187, 188, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 203, 204, 205,
|
||||
206, 207, 208, 209, 210, 211, 212, 213, 214, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227,
|
||||
229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 242, 243, 244, 245, 246, 247, 248, 249, 250,
|
||||
251, 252, 253, 253
|
||||
];
|
||||
|
||||
public static int InvRemapProb(int v, int m)
|
||||
{
|
||||
Debug.Assert(v < _invMapTable.Length / sizeof(byte));
|
||||
|
||||
v = _invMapTable[v];
|
||||
m--;
|
||||
if (m << 1 <= Prob.MaxProb)
|
||||
{
|
||||
return 1 + InvRecenterNonneg(v, m);
|
||||
}
|
||||
|
||||
return Prob.MaxProb - InvRecenterNonneg(v, Prob.MaxProb - 1 - m);
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Graphics.Nvdec.Vp9.Dsp;
|
||||
using Ryujinx.Graphics.Nvdec.Vp9.Types;
|
||||
using Ryujinx.Graphics.Video;
|
||||
@ -10,11 +10,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
{
|
||||
internal static class DecodeMv
|
||||
{
|
||||
private const int MvrefNeighbours = 8;
|
||||
private const int RefNeighbours = 8;
|
||||
|
||||
private static PredictionMode ReadIntraMode(ref Reader r, ReadOnlySpan<byte> p)
|
||||
{
|
||||
return (PredictionMode)r.ReadTree(Luts.Vp9IntraModeTree, p);
|
||||
return (PredictionMode)r.ReadTree(Luts.IntraModeTree, p);
|
||||
}
|
||||
|
||||
private static PredictionMode ReadIntraModeY(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r, int sizeGroup)
|
||||
@ -41,7 +41,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
|
||||
private static PredictionMode ReadInterMode(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r, int ctx)
|
||||
{
|
||||
int mode = r.ReadTree(Luts.Vp9InterModeTree, cm.Fc.Value.InterModeProb[ctx].AsSpan());
|
||||
int mode = r.ReadTree(Luts.InterModeTree, cm.Fc.Value.InterModeProb[ctx].AsSpan());
|
||||
if (!xd.Counts.IsNull)
|
||||
{
|
||||
++xd.Counts.Value.InterMode[ctx][mode];
|
||||
@ -52,22 +52,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
|
||||
private static int ReadSegmentId(ref Reader r, ref Array7<byte> segTreeProbs)
|
||||
{
|
||||
return r.ReadTree(Luts.Vp9SegmentTree, segTreeProbs.AsSpan());
|
||||
return r.ReadTree(Luts.SegmentTree, segTreeProbs.AsSpan());
|
||||
}
|
||||
|
||||
private static ReadOnlySpan<byte> GetTxProbs(ref Vp9EntropyProbs fc, TxSize maxTxSize, int ctx)
|
||||
{
|
||||
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();
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -76,15 +72,11 @@ 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();
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -94,10 +86,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
int ctx = xd.GetTxSizeContext();
|
||||
ReadOnlySpan<byte> txProbs = GetTxProbs(ref cm.Fc.Value, maxTxSize, ctx);
|
||||
TxSize txSize = (TxSize)r.Read(txProbs[0]);
|
||||
if (txSize != TxSize.Tx4x4 && maxTxSize >= TxSize.Tx16x16)
|
||||
if (txSize != TxSize.Tx4X4 && maxTxSize >= TxSize.Tx16X16)
|
||||
{
|
||||
txSize += r.Read(txProbs[1]);
|
||||
if (txSize != TxSize.Tx8x8 && maxTxSize >= TxSize.Tx32x32)
|
||||
if (txSize != TxSize.Tx8X8 && maxTxSize >= TxSize.Tx32X32)
|
||||
{
|
||||
txSize += r.Read(txProbs[2]);
|
||||
}
|
||||
@ -116,7 +108,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
TxMode txMode = cm.TxMode;
|
||||
BlockSize bsize = xd.Mi[0].Value.SbType;
|
||||
TxSize maxTxSize = Luts.MaxTxSizeLookup[(int)bsize];
|
||||
if (allowSelect && txMode == TxMode.TxModeSelect && bsize >= BlockSize.Block8x8)
|
||||
if (allowSelect && txMode == TxMode.TxModeSelect && bsize >= BlockSize.Block8X8)
|
||||
{
|
||||
return ReadSelectedTxSize(ref cm, ref xd, maxTxSize, ref r);
|
||||
}
|
||||
@ -124,34 +116,32 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
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)
|
||||
private static int DecGetSegmentId(ref Vp9Common cm, ArrayPtr<byte> segmentIds, int miOffset, int xMis,
|
||||
int yMis)
|
||||
{
|
||||
int x, y, segmentId = int.MaxValue;
|
||||
int segmentId = int.MaxValue;
|
||||
|
||||
for (y = 0; y < yMis; y++)
|
||||
for (int y = 0; y < yMis; y++)
|
||||
{
|
||||
for (x = 0; x < xMis; x++)
|
||||
for (int x = 0; x < xMis; x++)
|
||||
{
|
||||
segmentId = Math.Min(segmentId, segmentIds[miOffset + y * cm.MiCols + x]);
|
||||
segmentId = Math.Min(segmentId, segmentIds[miOffset + (y * cm.MiCols) + x]);
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Assert(segmentId >= 0 && segmentId < Constants.MaxSegments);
|
||||
|
||||
return segmentId;
|
||||
}
|
||||
|
||||
private static void SetSegmentId(ref Vp9Common cm, int miOffset, int xMis, int yMis, int segmentId)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
Debug.Assert(segmentId >= 0 && segmentId < Constants.MaxSegments);
|
||||
|
||||
for (y = 0; y < yMis; y++)
|
||||
for (int y = 0; y < yMis; y++)
|
||||
{
|
||||
for (x = 0; x < xMis; x++)
|
||||
for (int x = 0; x < xMis; x++)
|
||||
{
|
||||
cm.CurrentFrameSegMap[miOffset + y * cm.MiCols + x] = (byte)segmentId;
|
||||
cm.CurrentFrameSegMap[miOffset + (y * cm.MiCols) + x] = (byte)segmentId;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -164,13 +154,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
int xMis,
|
||||
int yMis)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
for (y = 0; y < yMis; y++)
|
||||
for (int y = 0; y < yMis; y++)
|
||||
{
|
||||
for (x = 0; x < xMis; x++)
|
||||
for (int x = 0; x < xMis; x++)
|
||||
{
|
||||
currentSegmentIds[miOffset + y * cm.MiCols + x] = (byte)(!lastSegmentIds.IsNull ? lastSegmentIds[miOffset + y * cm.MiCols + x] : 0);
|
||||
currentSegmentIds[miOffset + (y * cm.MiCols) + x] = (byte)(!lastSegmentIds.IsNull
|
||||
? lastSegmentIds[miOffset + (y * cm.MiCols) + x]
|
||||
: 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -188,13 +178,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
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;
|
||||
}
|
||||
|
||||
@ -210,7 +198,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
ref Segmentation seg = ref cm.Seg;
|
||||
ref ModeInfo mi = ref xd.Mi[0].Value;
|
||||
int predictedSegmentId, segmentId;
|
||||
int miOffset = miRow * cm.MiCols + miCol;
|
||||
int miOffset = (miRow * cm.MiCols) + miCol;
|
||||
|
||||
if (!seg.Enabled)
|
||||
{
|
||||
@ -224,7 +212,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
if (!seg.UpdateMap)
|
||||
{
|
||||
CopySegmentId(ref cm, cm.LastFrameSegMap, cm.CurrentFrameSegMap, miOffset, xMis, yMis);
|
||||
|
||||
return predictedSegmentId;
|
||||
}
|
||||
|
||||
@ -232,20 +219,22 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
{
|
||||
byte predProb = Segmentation.GetPredProbSegId(ref cm.Fc.Value.SegPredProb, ref xd);
|
||||
mi.SegIdPredicted = (sbyte)r.Read(predProb);
|
||||
segmentId = mi.SegIdPredicted != 0 ? predictedSegmentId : ReadSegmentId(ref r, ref cm.Fc.Value.SegTreeProb);
|
||||
segmentId = mi.SegIdPredicted != 0
|
||||
? predictedSegmentId
|
||||
: ReadSegmentId(ref r, ref cm.Fc.Value.SegTreeProb);
|
||||
}
|
||||
else
|
||||
{
|
||||
segmentId = ReadSegmentId(ref r, ref cm.Fc.Value.SegTreeProb);
|
||||
}
|
||||
SetSegmentId(ref cm, miOffset, xMis, yMis, segmentId);
|
||||
|
||||
SetSegmentId(ref cm, miOffset, xMis, yMis, segmentId);
|
||||
return segmentId;
|
||||
}
|
||||
|
||||
private static int ReadSkip(ref Vp9Common cm, ref MacroBlockD xd, int segmentId, ref Reader r)
|
||||
{
|
||||
if (cm.Seg.IsSegFeatureActive(segmentId, SegLvlFeatures.SegLvlSkip) != 0)
|
||||
if (cm.Seg.IsSegFeatureActive(segmentId, SegLvlFeatures.Skip) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@ -260,12 +249,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
return skip;
|
||||
}
|
||||
|
||||
private static int ReadMvComponent(ref Reader r, ref Vp9EntropyProbs fc, int mvcomp, bool usehp)
|
||||
private static int ReadComponent(ref Reader r, ref Vp9EntropyProbs fc, int mvcomp, bool usehp)
|
||||
{
|
||||
int mag, d, fr, hp;
|
||||
bool sign = r.Read(fc.Sign[mvcomp]) != 0;
|
||||
MvClassType mvClass = (MvClassType)r.ReadTree(Luts.Vp9MvClassTree, fc.Classes[mvcomp].AsSpan());
|
||||
bool class0 = mvClass == MvClassType.MvClass0;
|
||||
MvClassType mvClass = (MvClassType)r.ReadTree(Luts.MvClassTree, fc.Classes[mvcomp].AsSpan());
|
||||
bool class0 = mvClass == MvClassType.Class0;
|
||||
|
||||
// Integer part
|
||||
if (class0)
|
||||
@ -275,11 +264,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
int n = (int)mvClass + Constants.Class0Bits - 1; // Number of bits
|
||||
|
||||
d = 0;
|
||||
for (i = 0; i < n; ++i)
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
d |= r.Read(fc.Bits[mvcomp][i]) << i;
|
||||
}
|
||||
@ -288,40 +276,39 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
}
|
||||
|
||||
// Fractional part
|
||||
fr = r.ReadTree(Luts.Vp9MvFPTree, class0 ? fc.Class0Fp[mvcomp][d].AsSpan() : fc.Fp[mvcomp].AsSpan());
|
||||
fr = r.ReadTree(Luts.MvFpTree, class0 ? fc.Class0Fp[mvcomp][d].AsSpan() : fc.Fp[mvcomp].AsSpan());
|
||||
|
||||
// High precision part (if hp is not used, the default value of the hp is 1)
|
||||
hp = usehp ? r.Read(class0 ? fc.Class0Hp[mvcomp] : fc.Hp[mvcomp]) : 1;
|
||||
|
||||
// Result
|
||||
mag += ((d << 3) | (fr << 1) | hp) + 1;
|
||||
|
||||
return sign ? -mag : mag;
|
||||
}
|
||||
|
||||
private static void ReadMv(
|
||||
private static void Read(
|
||||
ref Reader r,
|
||||
ref Mv mv,
|
||||
ref Mv refr,
|
||||
ref Vp9EntropyProbs fc,
|
||||
Ptr<Vp9BackwardUpdates> counts,
|
||||
bool allowHP)
|
||||
bool allowHp)
|
||||
{
|
||||
MvJointType jointType = (MvJointType)r.ReadTree(Luts.Vp9MvJointTree, fc.Joints.AsSpan());
|
||||
bool useHP = allowHP && refr.UseMvHp();
|
||||
MvJointType jointType = (MvJointType)r.ReadTree(Luts.MvJointTree, fc.Joints.AsSpan());
|
||||
bool useHp = allowHp && refr.UseHp();
|
||||
Mv diff = new();
|
||||
|
||||
if (Mv.MvJointVertical(jointType))
|
||||
if (Mv.JointVertical(jointType))
|
||||
{
|
||||
diff.Row = (short)ReadMvComponent(ref r, ref fc, 0, useHP);
|
||||
diff.Row = (short)ReadComponent(ref r, ref fc, 0, useHp);
|
||||
}
|
||||
|
||||
if (Mv.MvJointHorizontal(jointType))
|
||||
if (Mv.JointHorizontal(jointType))
|
||||
{
|
||||
diff.Col = (short)ReadMvComponent(ref r, ref fc, 1, useHP);
|
||||
diff.Col = (short)ReadComponent(ref r, ref fc, 1, useHp);
|
||||
}
|
||||
|
||||
diff.IncMv(counts);
|
||||
diff.Inc(counts);
|
||||
|
||||
mv.Row = (short)(refr.Row + diff.Row);
|
||||
mv.Col = (short)(refr.Col + diff.Col);
|
||||
@ -329,7 +316,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
|
||||
private static ReferenceMode ReadBlockReferenceMode(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r)
|
||||
{
|
||||
if (cm.ReferenceMode == ReferenceMode.ReferenceModeSelect)
|
||||
if (cm.ReferenceMode == ReferenceMode.Select)
|
||||
{
|
||||
int ctx = PredCommon.GetReferenceModeContext(ref cm, ref xd);
|
||||
ReferenceMode mode = (ReferenceMode)r.Read(cm.Fc.Value.CompInterProb[ctx]);
|
||||
@ -354,15 +341,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
{
|
||||
ref Vp9EntropyProbs fc = ref cm.Fc.Value;
|
||||
|
||||
if (cm.Seg.IsSegFeatureActive(segmentId, SegLvlFeatures.SegLvlRefFrame) != 0)
|
||||
if (cm.Seg.IsSegFeatureActive(segmentId, SegLvlFeatures.RefFrame) != 0)
|
||||
{
|
||||
refFrame[0] = (sbyte)cm.Seg.GetSegData(segmentId, SegLvlFeatures.SegLvlRefFrame);
|
||||
refFrame[0] = (sbyte)cm.Seg.GetSegData(segmentId, SegLvlFeatures.RefFrame);
|
||||
refFrame[1] = Constants.None;
|
||||
}
|
||||
else
|
||||
{
|
||||
ReferenceMode mode = ReadBlockReferenceMode(ref cm, ref xd, ref r);
|
||||
if (mode == ReferenceMode.CompoundReference)
|
||||
if (mode == ReferenceMode.Compound)
|
||||
{
|
||||
int idx = cm.RefFrameSignBias[cm.CompFixedRef];
|
||||
int ctx = PredCommon.GetPredContextCompRefP(ref cm, ref xd);
|
||||
@ -375,7 +362,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
refFrame[idx] = cm.CompFixedRef;
|
||||
refFrame[idx == 0 ? 1 : 0] = cm.CompVarRef[bit];
|
||||
}
|
||||
else if (mode == ReferenceMode.SingleReference)
|
||||
else if (mode == ReferenceMode.Single)
|
||||
{
|
||||
int ctx0 = PredCommon.GetPredContextSingleRefP1(ref xd);
|
||||
int bit0 = r.Read(fc.SingleRefProb[ctx0][0]);
|
||||
@ -412,7 +399,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
private static byte ReadSwitchableInterpFilter(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r)
|
||||
{
|
||||
int ctx = xd.GetPredContextSwitchableInterp();
|
||||
byte type = (byte)r.ReadTree(Luts.Vp9SwitchableInterpTree, cm.Fc.Value.SwitchableInterpProb[ctx].AsSpan());
|
||||
byte type = (byte)r.ReadTree(Luts.SwitchableInterpTree, cm.Fc.Value.SwitchableInterpProb[ctx].AsSpan());
|
||||
if (!xd.Counts.IsNull)
|
||||
{
|
||||
++xd.Counts.Value.SwitchableInterp[ctx][type];
|
||||
@ -424,23 +411,23 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
private static void ReadIntraBlockModeInfo(ref Vp9Common cm, ref MacroBlockD xd, ref ModeInfo mi, ref Reader r)
|
||||
{
|
||||
BlockSize bsize = mi.SbType;
|
||||
int i;
|
||||
|
||||
|
||||
switch (bsize)
|
||||
{
|
||||
case BlockSize.Block4x4:
|
||||
for (i = 0; i < 4; ++i)
|
||||
case BlockSize.Block4X4:
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
mi.Bmi[i].Mode = ReadIntraModeY(ref cm, ref xd, ref r, 0);
|
||||
}
|
||||
|
||||
mi.Mode = mi.Bmi[3].Mode;
|
||||
break;
|
||||
case BlockSize.Block4x8:
|
||||
case BlockSize.Block4X8:
|
||||
mi.Bmi[0].Mode = mi.Bmi[2].Mode = ReadIntraModeY(ref cm, ref xd, ref r, 0);
|
||||
mi.Bmi[1].Mode = mi.Bmi[3].Mode = mi.Mode = ReadIntraModeY(ref cm, ref xd, ref r, 0);
|
||||
break;
|
||||
case BlockSize.Block8x4:
|
||||
case BlockSize.Block8X4:
|
||||
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;
|
||||
@ -459,27 +446,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
mi.RefFrame[1] = Constants.None;
|
||||
}
|
||||
|
||||
private static bool IsMvValid(ref Mv mv)
|
||||
{
|
||||
return mv.Row > Constants.MvLow &&
|
||||
mv.Row < Constants.MvUpp &&
|
||||
mv.Col > Constants.MvLow &&
|
||||
mv.Col < Constants.MvUpp;
|
||||
}
|
||||
|
||||
private static void CopyMvPair(ref Array2<Mv> dst, ref Array2<Mv> src)
|
||||
private static void CopyPair(ref Array2<Mv> dst, ref Array2<Mv> src)
|
||||
{
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
}
|
||||
|
||||
private static void ZeroMvPair(ref Array2<Mv> dst)
|
||||
private static void ZeroPair(ref Array2<Mv> dst)
|
||||
{
|
||||
dst[0] = new Mv();
|
||||
dst[1] = new Mv();
|
||||
}
|
||||
|
||||
private static bool AssignMv(
|
||||
private static bool Assign(
|
||||
ref Vp9Common cm,
|
||||
ref MacroBlockD xd,
|
||||
PredictionMode mode,
|
||||
@ -487,45 +466,45 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
ref Array2<Mv> refMv,
|
||||
ref Array2<Mv> nearNearestMv,
|
||||
int isCompound,
|
||||
bool allowHP,
|
||||
bool allowHp,
|
||||
ref Reader r)
|
||||
{
|
||||
int i;
|
||||
bool ret = true;
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case PredictionMode.NewMv:
|
||||
{
|
||||
for (i = 0; i < 1 + isCompound; ++i)
|
||||
for (int i = 0; i < 1 + isCompound; ++i)
|
||||
{
|
||||
ReadMv(ref r, ref mv[i], ref refMv[i], ref cm.Fc.Value, xd.Counts, allowHP);
|
||||
ret = ret && IsMvValid(ref mv[i]);
|
||||
Read(ref r, ref mv[i], ref refMv[i], ref cm.Fc.Value, xd.Counts, allowHp);
|
||||
ret = ret && mv[i].IsValid();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case PredictionMode.NearMv:
|
||||
case PredictionMode.NearestMv:
|
||||
{
|
||||
CopyMvPair(ref mv, ref nearNearestMv);
|
||||
CopyPair(ref mv, ref nearNearestMv);
|
||||
break;
|
||||
}
|
||||
case PredictionMode.ZeroMv:
|
||||
{
|
||||
ZeroMvPair(ref mv);
|
||||
ZeroPair(ref mv);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
default: return false;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static bool ReadIsInterBlock(ref Vp9Common cm, ref MacroBlockD xd, int segmentId, ref Reader r)
|
||||
{
|
||||
if (cm.Seg.IsSegFeatureActive(segmentId, SegLvlFeatures.SegLvlRefFrame) != 0)
|
||||
if (cm.Seg.IsSegFeatureActive(segmentId, SegLvlFeatures.RefFrame) != 0)
|
||||
{
|
||||
return cm.Seg.GetSegData(segmentId, SegLvlFeatures.SegLvlRefFrame) != Constants.IntraFrame;
|
||||
return cm.Seg.GetSegData(segmentId, SegLvlFeatures.RefFrame) != Constants.IntraFrame;
|
||||
}
|
||||
|
||||
int ctx = xd.GetIntraInterContext();
|
||||
@ -538,33 +517,30 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
return isInter;
|
||||
}
|
||||
|
||||
private static void DecFindBestRefMvs(bool allowHP, Span<Mv> mvlist, ref Mv bestMv, int refmvCount)
|
||||
private static void DecFindBestRefs(bool allowHp, Span<Mv> mvlist, ref Mv bestMv, int refmvCount)
|
||||
{
|
||||
int i;
|
||||
|
||||
// Make sure all the candidates are properly clamped etc
|
||||
for (i = 0; i < refmvCount; ++i)
|
||||
for (int i = 0; i < refmvCount; ++i)
|
||||
{
|
||||
mvlist[i].LowerMvPrecision(allowHP);
|
||||
mvlist[i].LowerPrecision(allowHp);
|
||||
bestMv = mvlist[i];
|
||||
}
|
||||
}
|
||||
|
||||
private static bool AddMvRefListEb(Mv mv, ref int refMvCount, Span<Mv> mvRefList, bool earlyBreak)
|
||||
private static bool AddRefListEb(Mv mv, ref int refCount, Span<Mv> mvRefList, bool earlyBreak)
|
||||
{
|
||||
if (refMvCount != 0)
|
||||
if (refCount != 0)
|
||||
{
|
||||
if (Unsafe.As<Mv, int>(ref mv) != Unsafe.As<Mv, int>(ref mvRefList[0]))
|
||||
{
|
||||
mvRefList[refMvCount] = mv;
|
||||
refMvCount++;
|
||||
|
||||
mvRefList[refCount] = mv;
|
||||
refCount++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mvRefList[refMvCount++] = mv;
|
||||
mvRefList[refCount++] = mv;
|
||||
if (earlyBreak)
|
||||
{
|
||||
return true;
|
||||
@ -574,19 +550,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
return false;
|
||||
}
|
||||
|
||||
// Performs mv sign inversion if indicated by the reference frame combination.
|
||||
private static Mv ScaleMv(ref ModeInfo mi, int refr, sbyte thisRefFrame, ref Array4<sbyte> refSignBias)
|
||||
{
|
||||
Mv mv = mi.Mv[refr];
|
||||
if (refSignBias[mi.RefFrame[refr]] != refSignBias[thisRefFrame])
|
||||
{
|
||||
mv.Row *= -1;
|
||||
mv.Col *= -1;
|
||||
}
|
||||
return mv;
|
||||
}
|
||||
|
||||
private static bool IsDiffRefFrameAddMvEb(
|
||||
private static bool IsDiffRefFrameAddEb(
|
||||
ref ModeInfo mbmi,
|
||||
sbyte refFrame,
|
||||
ref Array4<sbyte> refSignBias,
|
||||
@ -598,26 +562,30 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
{
|
||||
if (mbmi.RefFrame[0] != refFrame)
|
||||
{
|
||||
if (AddMvRefListEb(ScaleMv(ref mbmi, 0, refFrame, ref refSignBias), ref refmvCount, mvRefList, earlyBreak))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (mbmi.HasSecondRef() && mbmi.RefFrame[1] != refFrame && Unsafe.As<Mv, int>(ref mbmi.Mv[1]) != Unsafe.As<Mv, int>(ref mbmi.Mv[0]))
|
||||
{
|
||||
if (AddMvRefListEb(ScaleMv(ref mbmi, 1, refFrame, ref refSignBias), ref refmvCount, mvRefList, earlyBreak))
|
||||
if (AddRefListEb(mbmi.ScaleMv(0, refFrame, ref refSignBias), ref refmvCount, mvRefList,
|
||||
earlyBreak))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (mbmi.HasSecondRef() && mbmi.RefFrame[1] != refFrame &&
|
||||
Unsafe.As<Mv, int>(ref mbmi.Mv[1]) != Unsafe.As<Mv, int>(ref mbmi.Mv[0]))
|
||||
{
|
||||
if (AddRefListEb(mbmi.ScaleMv(1, refFrame, ref refSignBias), ref refmvCount, mvRefList,
|
||||
earlyBreak))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// This function searches the neighborhood of a given MB/SB
|
||||
// to try and find candidate reference vectors.
|
||||
private static int DecFindMvRefs(
|
||||
private static int DecFindRefs(
|
||||
ref Vp9Common cm,
|
||||
ref MacroBlockD xd,
|
||||
PredictionMode mode,
|
||||
@ -632,14 +600,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
ref Array4<sbyte> refSignBias = ref cm.RefFrameSignBias;
|
||||
int i, refmvCount = 0;
|
||||
bool differentRefFound = false;
|
||||
Ptr<MvRef> prevFrameMvs = cm.UsePrevFrameMvs ? new Ptr<MvRef>(ref cm.PrevFrameMvs[miRow * cm.MiCols + miCol]) : Ptr<MvRef>.Null;
|
||||
Ptr<MvRef> prevFrameMvs = cm.UsePrevFrameMvs
|
||||
? new Ptr<MvRef>(ref cm.PrevFrameMvs[(miRow * cm.MiCols) + miCol])
|
||||
: Ptr<MvRef>.Null;
|
||||
ref TileInfo tile = ref xd.Tile;
|
||||
// If mode is nearestmv or newmv (uses nearestmv as a reference) then stop
|
||||
// searching after the first mv is found.
|
||||
bool earlyBreak = mode != PredictionMode.NearMv;
|
||||
|
||||
// Blank the reference vector list
|
||||
mvRefList[..Constants.MaxMvRefCandidates].Clear();
|
||||
mvRefList.Slice(0, Constants.MaxMvRefCandidates).Fill(new Mv());
|
||||
|
||||
i = 0;
|
||||
if (isSub8X8 != 0)
|
||||
@ -651,19 +621,21 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
ref Position mvRef = ref mvRefSearch[i];
|
||||
if (tile.IsInside(miCol, miRow, cm.MiRows, ref mvRef))
|
||||
{
|
||||
ref ModeInfo candidateMi = ref xd.Mi[mvRef.Col + mvRef.Row * xd.MiStride].Value;
|
||||
ref ModeInfo candidateMi = ref xd.Mi[mvRef.Col + (mvRef.Row * xd.MiStride)].Value;
|
||||
differentRefFound = true;
|
||||
|
||||
if (candidateMi.RefFrame[0] == refFrame)
|
||||
{
|
||||
if (AddMvRefListEb(candidateMi.GetSubBlockMv(0, mvRef.Col, block), ref refmvCount, mvRefList, earlyBreak))
|
||||
if (AddRefListEb(candidateMi.GetSubBlockMv(0, mvRef.Col, block), ref refmvCount,
|
||||
mvRefList, earlyBreak))
|
||||
{
|
||||
goto Done;
|
||||
}
|
||||
}
|
||||
else if (candidateMi.RefFrame[1] == refFrame)
|
||||
{
|
||||
if (AddMvRefListEb(candidateMi.GetSubBlockMv(1, mvRef.Col, block), ref refmvCount, mvRefList, earlyBreak))
|
||||
if (AddRefListEb(candidateMi.GetSubBlockMv(1, mvRef.Col, block), ref refmvCount,
|
||||
mvRefList, earlyBreak))
|
||||
{
|
||||
goto Done;
|
||||
}
|
||||
@ -675,24 +647,24 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
// Check the rest of the neighbors in much the same way
|
||||
// as before except we don't need to keep track of sub blocks or
|
||||
// mode counts.
|
||||
for (; i < MvrefNeighbours; ++i)
|
||||
for (; i < RefNeighbours; ++i)
|
||||
{
|
||||
ref Position mvRef = ref mvRefSearch[i];
|
||||
if (tile.IsInside(miCol, miRow, cm.MiRows, ref mvRef))
|
||||
{
|
||||
ref ModeInfo candidate = ref xd.Mi[mvRef.Col + mvRef.Row * xd.MiStride].Value;
|
||||
ref ModeInfo candidate = ref xd.Mi[mvRef.Col + (mvRef.Row * xd.MiStride)].Value;
|
||||
differentRefFound = true;
|
||||
|
||||
if (candidate.RefFrame[0] == refFrame)
|
||||
{
|
||||
if (AddMvRefListEb(candidate.Mv[0], ref refmvCount, mvRefList, earlyBreak))
|
||||
if (AddRefListEb(candidate.Mv[0], ref refmvCount, mvRefList, earlyBreak))
|
||||
{
|
||||
goto Done;
|
||||
}
|
||||
}
|
||||
else if (candidate.RefFrame[1] == refFrame)
|
||||
{
|
||||
if (AddMvRefListEb(candidate.Mv[1], ref refmvCount, mvRefList, earlyBreak))
|
||||
if (AddRefListEb(candidate.Mv[1], ref refmvCount, mvRefList, earlyBreak))
|
||||
{
|
||||
goto Done;
|
||||
}
|
||||
@ -705,14 +677,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
{
|
||||
if (prevFrameMvs.Value.RefFrame[0] == refFrame)
|
||||
{
|
||||
if (AddMvRefListEb(prevFrameMvs.Value.Mv[0], ref refmvCount, mvRefList, earlyBreak))
|
||||
if (AddRefListEb(prevFrameMvs.Value.Mv[0], ref refmvCount, mvRefList, earlyBreak))
|
||||
{
|
||||
goto Done;
|
||||
}
|
||||
}
|
||||
else if (prevFrameMvs.Value.RefFrame[1] == refFrame)
|
||||
{
|
||||
if (AddMvRefListEb(prevFrameMvs.Value.Mv[1], ref refmvCount, mvRefList, earlyBreak))
|
||||
if (AddRefListEb(prevFrameMvs.Value.Mv[1], ref refmvCount, mvRefList, earlyBreak))
|
||||
{
|
||||
goto Done;
|
||||
}
|
||||
@ -724,15 +696,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
// different reference frames.
|
||||
if (differentRefFound)
|
||||
{
|
||||
for (i = 0; i < MvrefNeighbours; ++i)
|
||||
for (i = 0; i < RefNeighbours; ++i)
|
||||
{
|
||||
ref Position mvRef = ref mvRefSearch[i];
|
||||
if (tile.IsInside(miCol, miRow, cm.MiRows, ref mvRef))
|
||||
{
|
||||
ref ModeInfo candidate = ref xd.Mi[mvRef.Col + mvRef.Row * xd.MiStride].Value;
|
||||
ref ModeInfo candidate = ref xd.Mi[mvRef.Col + (mvRef.Row * xd.MiStride)].Value;
|
||||
|
||||
// If the candidate is Intra we don't want to consider its mv.
|
||||
if (IsDiffRefFrameAddMvEb(ref candidate, refFrame, ref refSignBias, ref refmvCount, mvRefList, earlyBreak))
|
||||
if (IsDiffRefFrameAddEb(ref candidate, refFrame, ref refSignBias, ref refmvCount, mvRefList,
|
||||
earlyBreak))
|
||||
{
|
||||
goto Done;
|
||||
}
|
||||
@ -751,7 +724,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
mv.Row *= -1;
|
||||
mv.Col *= -1;
|
||||
}
|
||||
if (AddMvRefListEb(mv, ref refmvCount, mvRefList, earlyBreak))
|
||||
|
||||
if (AddRefListEb(mv, ref refmvCount, mvRefList, earlyBreak))
|
||||
{
|
||||
goto Done;
|
||||
}
|
||||
@ -759,7 +733,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
|
||||
if (prevFrameMvs.Value.RefFrame[1] > Constants.IntraFrame &&
|
||||
prevFrameMvs.Value.RefFrame[1] != refFrame &&
|
||||
Unsafe.As<Mv, int>(ref prevFrameMvs.Value.Mv[1]) != Unsafe.As<Mv, int>(ref prevFrameMvs.Value.Mv[0]))
|
||||
Unsafe.As<Mv, int>(ref prevFrameMvs.Value.Mv[1]) !=
|
||||
Unsafe.As<Mv, int>(ref prevFrameMvs.Value.Mv[0]))
|
||||
{
|
||||
Mv mv = prevFrameMvs.Value.Mv[1];
|
||||
if (refSignBias[prevFrameMvs.Value.RefFrame[1]] != refSignBias[refFrame])
|
||||
@ -767,7 +742,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
mv.Row *= -1;
|
||||
mv.Col *= -1;
|
||||
}
|
||||
if (AddMvRefListEb(mv, ref refmvCount, mvRefList, earlyBreak))
|
||||
|
||||
if (AddRefListEb(mv, ref refmvCount, mvRefList, earlyBreak))
|
||||
{
|
||||
goto Done;
|
||||
}
|
||||
@ -784,17 +760,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
refmvCount = 1;
|
||||
}
|
||||
|
||||
Done:
|
||||
Done:
|
||||
// Clamp vectors
|
||||
for (i = 0; i < refmvCount; ++i)
|
||||
{
|
||||
mvRefList[i].ClampMvRef(ref xd);
|
||||
mvRefList[i].ClampRef(ref xd);
|
||||
}
|
||||
|
||||
return refmvCount;
|
||||
}
|
||||
|
||||
private static void AppendSub8x8MvsForIdx(
|
||||
private static void AppendSub8X8ForIdx(
|
||||
ref Vp9Common cm,
|
||||
ref MacroBlockD xd,
|
||||
Span<Position> mvRefSearch,
|
||||
@ -803,46 +779,47 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
int refr,
|
||||
int miRow,
|
||||
int miCol,
|
||||
ref Mv bestSub8x8)
|
||||
ref Mv bestSub8X8)
|
||||
{
|
||||
Span<Mv> mvList = stackalloc Mv[Constants.MaxMvRefCandidates];
|
||||
ref ModeInfo mi = ref xd.Mi[0].Value;
|
||||
ref Array4<BModeInfo> bmi = ref mi.Bmi;
|
||||
int n;
|
||||
int refmvCount;
|
||||
|
||||
Debug.Assert(Constants.MaxMvRefCandidates == 2);
|
||||
|
||||
refmvCount = DecFindMvRefs(ref cm, ref xd, bMode, mi.RefFrame[refr], mvRefSearch, mvList, miRow, miCol, block, 1);
|
||||
refmvCount = DecFindRefs(ref cm, ref xd, bMode, mi.RefFrame[refr], mvRefSearch, mvList, miRow, miCol,
|
||||
block, 1);
|
||||
|
||||
switch (block)
|
||||
{
|
||||
case 0:
|
||||
bestSub8x8 = mvList[refmvCount - 1];
|
||||
bestSub8X8 = mvList[refmvCount - 1];
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
if (bMode == PredictionMode.NearestMv)
|
||||
{
|
||||
bestSub8x8 = bmi[0].Mv[refr];
|
||||
bestSub8X8 = bmi[0].Mv[refr];
|
||||
}
|
||||
else
|
||||
{
|
||||
bestSub8x8 = new Mv();
|
||||
for (n = 0; n < refmvCount; ++n)
|
||||
bestSub8X8 = new Mv();
|
||||
for (int n = 0; n < refmvCount; ++n)
|
||||
{
|
||||
if (Unsafe.As<Mv, int>(ref bmi[0].Mv[refr]) != Unsafe.As<Mv, int>(ref mvList[n]))
|
||||
{
|
||||
bestSub8x8 = mvList[n];
|
||||
bestSub8X8 = mvList[n];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case 3:
|
||||
if (bMode == PredictionMode.NearestMv)
|
||||
{
|
||||
bestSub8x8 = bmi[2].Mv[refr];
|
||||
bestSub8X8 = bmi[2].Mv[refr];
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -851,16 +828,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
candidates[1] = bmi[0].Mv[refr];
|
||||
candidates[2] = mvList[0];
|
||||
candidates[3] = mvList[1];
|
||||
bestSub8x8 = new Mv();
|
||||
for (n = 0; n < 2 + Constants.MaxMvRefCandidates; ++n)
|
||||
bestSub8X8 = new Mv();
|
||||
for (int n = 0; n < 2 + Constants.MaxMvRefCandidates; ++n)
|
||||
{
|
||||
if (Unsafe.As<Mv, int>(ref bmi[2].Mv[refr]) != Unsafe.As<Mv, int>(ref candidates[n]))
|
||||
{
|
||||
bestSub8x8 = candidates[n];
|
||||
bestSub8X8 = candidates[n];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
Debug.Assert(false, "Invalid block index.");
|
||||
@ -868,19 +846,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
}
|
||||
}
|
||||
|
||||
private static byte GetModeContext(ref Vp9Common cm, ref MacroBlockD xd, Span<Position> mvRefSearch, int miRow, int miCol)
|
||||
private static byte GetModeContext(ref Vp9Common cm, ref MacroBlockD xd, Span<Position> mvRefSearch, int miRow,
|
||||
int miCol)
|
||||
{
|
||||
int i;
|
||||
int contextCounter = 0;
|
||||
ref TileInfo tile = ref xd.Tile;
|
||||
|
||||
// Get mode count from nearest 2 blocks
|
||||
for (i = 0; i < 2; ++i)
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
ref Position mvRef = ref mvRefSearch[i];
|
||||
if (tile.IsInside(miCol, miRow, cm.MiRows, ref mvRef))
|
||||
{
|
||||
ref ModeInfo candidate = ref xd.Mi[mvRef.Col + mvRef.Row * xd.MiStride].Value;
|
||||
ref ModeInfo candidate = ref xd.Mi[mvRef.Col + (mvRef.Row * xd.MiStride)].Value;
|
||||
// Keep counts for entropy encoding.
|
||||
contextCounter += Luts.Mode2Counter[(int)candidate.Mode];
|
||||
}
|
||||
@ -898,7 +876,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
ref Reader r)
|
||||
{
|
||||
BlockSize bsize = mi.SbType;
|
||||
bool allowHP = cm.AllowHighPrecisionMv;
|
||||
bool allowHp = cm.AllowHighPrecisionMv;
|
||||
Array2<Mv> bestRefMvs = new();
|
||||
int refr, isCompound;
|
||||
byte interModeCtx;
|
||||
@ -908,19 +886,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
isCompound = mi.HasSecondRef() ? 1 : 0;
|
||||
interModeCtx = GetModeContext(ref cm, ref xd, mvRefSearch, miRow, miCol);
|
||||
|
||||
if (cm.Seg.IsSegFeatureActive(mi.SegmentId, SegLvlFeatures.SegLvlSkip) != 0)
|
||||
if (cm.Seg.IsSegFeatureActive(mi.SegmentId, SegLvlFeatures.Skip) != 0)
|
||||
{
|
||||
mi.Mode = PredictionMode.ZeroMv;
|
||||
if (bsize < BlockSize.Block8x8)
|
||||
if (bsize < BlockSize.Block8X8)
|
||||
{
|
||||
xd.ErrorInfo.Value.InternalError(CodecErr.CodecUnsupBitstream, "Invalid usage of segement feature on small blocks");
|
||||
|
||||
xd.ErrorInfo.Value.InternalError(CodecErr.UnsupBitstream,
|
||||
"Invalid usage of segement feature on small blocks");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bsize >= BlockSize.Block8x8)
|
||||
if (bsize >= BlockSize.Block8X8)
|
||||
{
|
||||
mi.Mode = ReadInterMode(ref cm, ref xd, ref r, interModeCtx);
|
||||
}
|
||||
@ -942,42 +920,47 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
sbyte frame = mi.RefFrame[refr];
|
||||
int refmvCount;
|
||||
|
||||
refmvCount = DecFindMvRefs(ref cm, ref xd, mi.Mode, frame, mvRefSearch, tmpMvs, miRow, miCol, -1, 0);
|
||||
refmvCount = DecFindRefs(ref cm, ref xd, mi.Mode, frame, mvRefSearch, tmpMvs, miRow, miCol,
|
||||
-1, 0);
|
||||
|
||||
DecFindBestRefMvs(allowHP, tmpMvs, ref bestRefMvs[refr], refmvCount);
|
||||
DecFindBestRefs(allowHp, tmpMvs, ref bestRefMvs[refr], refmvCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mi.InterpFilter = (cm.InterpFilter == Constants.Switchable) ? ReadSwitchableInterpFilter(ref cm, ref xd, ref r) : cm.InterpFilter;
|
||||
mi.InterpFilter = cm.InterpFilter == Constants.Switchable
|
||||
? ReadSwitchableInterpFilter(ref cm, ref xd, ref r)
|
||||
: cm.InterpFilter;
|
||||
|
||||
if (bsize < BlockSize.Block8x8)
|
||||
if (bsize < BlockSize.Block8X8)
|
||||
{
|
||||
int num4X4W = 1 << xd.BmodeBlocksWl;
|
||||
int num4X4H = 1 << xd.BmodeBlocksHl;
|
||||
int idx, idy;
|
||||
PredictionMode bMode = 0;
|
||||
Array2<Mv> bestSub8x8 = new();
|
||||
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)
|
||||
{
|
||||
int j = idy * 2 + idx;
|
||||
int j = (idy * 2) + idx;
|
||||
bMode = ReadInterMode(ref cm, ref xd, ref r, interModeCtx);
|
||||
|
||||
if (bMode == PredictionMode.NearestMv || bMode == PredictionMode.NearMv)
|
||||
{
|
||||
for (refr = 0; refr < 1 + isCompound; ++refr)
|
||||
{
|
||||
AppendSub8x8MvsForIdx(ref cm, ref xd, mvRefSearch, bMode, j, refr, miRow, miCol, ref bestSub8x8[refr]);
|
||||
AppendSub8X8ForIdx(ref cm, ref xd, mvRefSearch, bMode, j, refr, miRow, miCol,
|
||||
ref bestSub8X8[refr]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!AssignMv(ref cm, ref xd, bMode, ref mi.Bmi[j].Mv, ref bestRefMvs, ref bestSub8x8, isCompound, allowHP, ref r))
|
||||
if (!Assign(ref cm, ref xd, bMode, ref mi.Bmi[j].Mv, ref bestRefMvs, ref bestSub8X8,
|
||||
isCompound, allowHp, ref r))
|
||||
{
|
||||
xd.Corrupted |= true;
|
||||
break;
|
||||
@ -997,11 +980,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
|
||||
mi.Mode = bMode;
|
||||
|
||||
CopyMvPair(ref mi.Mv, ref mi.Bmi[3].Mv);
|
||||
CopyPair(ref mi.Mv, ref mi.Bmi[3].Mv);
|
||||
}
|
||||
else
|
||||
{
|
||||
xd.Corrupted |= !AssignMv(ref cm, ref xd, mi.Mode, ref mi.Mv, ref bestRefMvs, ref bestRefMvs, isCompound, allowHP, ref r);
|
||||
xd.Corrupted |= !Assign(ref cm, ref xd, mi.Mode, ref mi.Mv, ref bestRefMvs, ref bestRefMvs,
|
||||
isCompound, allowHp, ref r);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1045,7 +1029,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
}
|
||||
|
||||
Debug.Assert(b == 1 || b == 3);
|
||||
|
||||
return curMi.Value.Bmi[b - 1].Mode;
|
||||
}
|
||||
|
||||
@ -1062,7 +1045,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
}
|
||||
|
||||
Debug.Assert(b == 2 || b == 3);
|
||||
|
||||
return curMi.Value.Bmi[b - 2].Mode;
|
||||
}
|
||||
|
||||
@ -1075,7 +1057,6 @@ 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();
|
||||
}
|
||||
|
||||
@ -1092,8 +1073,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
Ptr<ModeInfo> aboveMi = xd.AboveMi;
|
||||
Ptr<ModeInfo> leftMi = xd.LeftMi;
|
||||
BlockSize bsize = mi.Value.SbType;
|
||||
int i;
|
||||
int miOffset = miRow * cm.MiCols + miCol;
|
||||
|
||||
int miOffset = (miRow * cm.MiCols) + miCol;
|
||||
|
||||
mi.Value.SegmentId = (sbyte)ReadIntraSegmentId(ref cm, miOffset, xMis, yMis, ref r);
|
||||
mi.Value.Skip = (sbyte)ReadSkip(ref cm, ref xd, mi.Value.SegmentId, ref r);
|
||||
@ -1103,8 +1084,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
|
||||
switch (bsize)
|
||||
{
|
||||
case BlockSize.Block4x4:
|
||||
for (i = 0; i < 4; ++i)
|
||||
case BlockSize.Block4X4:
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
mi.Value.Bmi[i].Mode =
|
||||
ReadIntraMode(ref r, GetYModeProbs(ref cm.Fc.Value, mi, aboveMi, leftMi, i));
|
||||
@ -1112,13 +1093,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
|
||||
mi.Value.Mode = mi.Value.Bmi[3].Mode;
|
||||
break;
|
||||
case BlockSize.Block4x8:
|
||||
case BlockSize.Block4X8:
|
||||
mi.Value.Bmi[0].Mode = mi.Value.Bmi[2].Mode =
|
||||
ReadIntraMode(ref r, GetYModeProbs(ref cm.Fc.Value, mi, aboveMi, leftMi, 0));
|
||||
mi.Value.Bmi[1].Mode = mi.Value.Bmi[3].Mode = mi.Value.Mode =
|
||||
ReadIntraMode(ref r, GetYModeProbs(ref cm.Fc.Value, mi, aboveMi, leftMi, 1));
|
||||
break;
|
||||
case BlockSize.Block8x4:
|
||||
case BlockSize.Block8X4:
|
||||
mi.Value.Bmi[0].Mode = mi.Value.Bmi[1].Mode =
|
||||
ReadIntraMode(ref r, GetYModeProbs(ref cm.Fc.Value, mi, aboveMi, leftMi, 0));
|
||||
mi.Value.Bmi[2].Mode = mi.Value.Bmi[3].Mode = mi.Value.Mode =
|
||||
@ -1149,8 +1130,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
ref Reader r = ref twd.BitReader;
|
||||
ref MacroBlockD xd = ref twd.Xd;
|
||||
ref ModeInfo mi = ref xd.Mi[0].Value;
|
||||
ArrayPtr<MvRef> frameMvs = cm.CurFrameMvs.Slice(miRow * cm.MiCols + miCol);
|
||||
int w, h;
|
||||
ArrayPtr<MvRef> frameMvs = cm.CurFrameMvs.Slice((miRow * cm.MiCols) + miCol);
|
||||
|
||||
if (cm.FrameIsIntraOnly())
|
||||
{
|
||||
@ -1160,17 +1140,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
{
|
||||
ReadInterFrameModeInfo(ref cm, ref xd, miRow, miCol, ref r, xMis, yMis);
|
||||
|
||||
for (h = 0; h < yMis; ++h)
|
||||
for (int h = 0; h < yMis; ++h)
|
||||
{
|
||||
for (w = 0; w < xMis; ++w)
|
||||
for (int w = 0; w < xMis; ++w)
|
||||
{
|
||||
ref MvRef mv = ref frameMvs[w];
|
||||
CopyRefFramePair(ref mv.RefFrame, ref mi.RefFrame);
|
||||
CopyMvPair(ref mv.Mv, ref mi.Mv);
|
||||
CopyPair(ref mv.Mv, ref mi.Mv);
|
||||
}
|
||||
|
||||
frameMvs = frameMvs.Slice(cm.MiCols);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Graphics.Nvdec.Vp9.Common;
|
||||
using Ryujinx.Graphics.Nvdec.Vp9.Types;
|
||||
using Ryujinx.Graphics.Video;
|
||||
@ -12,15 +12,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
|
||||
private readonly MemoryAllocator _allocator = new();
|
||||
|
||||
public ISurface CreateSurface(int width, int height) => new Surface(width, height);
|
||||
|
||||
private static ReadOnlySpan<byte> LiteralToFilter => new byte[]
|
||||
public ISurface CreateSurface(int width, int height)
|
||||
{
|
||||
Constants.EightTapSmooth,
|
||||
Constants.EightTap,
|
||||
Constants.EightTapSharp,
|
||||
Constants.Bilinear,
|
||||
};
|
||||
return new Surface(width, height);
|
||||
}
|
||||
|
||||
private static ReadOnlySpan<byte> LiteralToFilter =>
|
||||
[
|
||||
Constants.EightTapSmooth, Constants.EightTap, Constants.EightTapSharp, Constants.Bilinear
|
||||
];
|
||||
|
||||
public unsafe bool Decode(
|
||||
ref Vp9PictureInfo pictureInfo,
|
||||
@ -29,25 +29,24 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
ReadOnlySpan<Vp9MvRef> mvsIn,
|
||||
Span<Vp9MvRef> mvsOut)
|
||||
{
|
||||
Vp9Common cm = new()
|
||||
{
|
||||
FrameType = pictureInfo.IsKeyFrame ? FrameType.KeyFrame : FrameType.InterFrame,
|
||||
IntraOnly = pictureInfo.IntraOnly,
|
||||
Vp9Common cm = new();
|
||||
|
||||
Width = output.Width,
|
||||
Height = output.Height,
|
||||
SubsamplingX = 1,
|
||||
SubsamplingY = 1,
|
||||
cm.FrameType = pictureInfo.IsKeyFrame ? FrameType.KeyFrame : FrameType.InterFrame;
|
||||
cm.IntraOnly = pictureInfo.IntraOnly;
|
||||
|
||||
UsePrevFrameMvs = pictureInfo.UsePrevInFindMvRefs,
|
||||
cm.Width = output.Width;
|
||||
cm.Height = output.Height;
|
||||
cm.SubsamplingX = 1;
|
||||
cm.SubsamplingY = 1;
|
||||
|
||||
RefFrameSignBias = pictureInfo.RefFrameSignBias,
|
||||
cm.UsePrevFrameMvs = pictureInfo.UsePrevInFindMvRefs;
|
||||
|
||||
BaseQindex = pictureInfo.BaseQIndex,
|
||||
YDcDeltaQ = pictureInfo.YDcDeltaQ,
|
||||
UvAcDeltaQ = pictureInfo.UvAcDeltaQ,
|
||||
UvDcDeltaQ = pictureInfo.UvDcDeltaQ,
|
||||
};
|
||||
cm.RefFrameSignBias = pictureInfo.RefFrameSignBias;
|
||||
|
||||
cm.BaseQindex = pictureInfo.BaseQIndex;
|
||||
cm.YDcDeltaQ = pictureInfo.YDcDeltaQ;
|
||||
cm.UvAcDeltaQ = pictureInfo.UvAcDeltaQ;
|
||||
cm.UvDcDeltaQ = pictureInfo.UvDcDeltaQ;
|
||||
|
||||
cm.Mb.Lossless = pictureInfo.Lossless;
|
||||
cm.Mb.Bd = 8;
|
||||
@ -68,6 +67,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
cm.CompFixedRef = pictureInfo.CompFixedRef;
|
||||
cm.CompVarRef = pictureInfo.CompVarRef;
|
||||
|
||||
cm.BitDepth = BitDepth.Bits8;
|
||||
|
||||
cm.Log2TileCols = pictureInfo.Log2TileCols;
|
||||
cm.Log2TileRows = pictureInfo.Log2TileRows;
|
||||
|
||||
@ -78,6 +79,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
cm.Seg.FeatureMask = pictureInfo.SegmentFeatureEnable;
|
||||
cm.Seg.FeatureData = pictureInfo.SegmentFeatureData;
|
||||
|
||||
cm.Lf.FilterLevel = pictureInfo.LoopFilterLevel;
|
||||
cm.Lf.SharpnessLevel = pictureInfo.LoopFilterSharpnessLevel;
|
||||
cm.Lf.ModeRefDeltaEnabled = pictureInfo.ModeRefDeltaEnabled;
|
||||
cm.Lf.RefDeltas = pictureInfo.RefDeltas;
|
||||
cm.Lf.ModeDeltas = pictureInfo.ModeDeltas;
|
||||
@ -105,7 +108,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
cm.SetupSegmentationDequant();
|
||||
cm.SetupScaleFactors();
|
||||
|
||||
SetMvs(ref cm, mvsIn);
|
||||
cm.SetMvs(mvsIn);
|
||||
|
||||
if (cm.Lf.FilterLevel != 0 && cm.SkipLoopFilter == 0)
|
||||
{
|
||||
LoopFilter.LoopFilterFrameInit(ref cm, cm.Lf.FilterLevel);
|
||||
}
|
||||
|
||||
fixed (byte* dataPtr = bitstream)
|
||||
{
|
||||
@ -114,10 +122,27 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
if (maxThreads > 1 && tileRows == 1 && tileCols > 1)
|
||||
{
|
||||
DecodeFrame.DecodeTilesMt(ref cm, new ArrayPtr<byte>(dataPtr, bitstream.Length), maxThreads);
|
||||
|
||||
LoopFilter.LoopFilterFrameMt(
|
||||
ref cm.Mb.CurBuf,
|
||||
ref cm,
|
||||
ref cm.Mb,
|
||||
cm.Lf.FilterLevel,
|
||||
false,
|
||||
false,
|
||||
maxThreads);
|
||||
}
|
||||
else
|
||||
{
|
||||
DecodeFrame.DecodeTiles(ref cm, new ArrayPtr<byte>(dataPtr, bitstream.Length));
|
||||
|
||||
LoopFilter.LoopFilterFrame(
|
||||
ref cm.Mb.CurBuf,
|
||||
ref cm,
|
||||
ref cm.Mb,
|
||||
cm.Lf.FilterLevel,
|
||||
false,
|
||||
false);
|
||||
}
|
||||
}
|
||||
catch (InternalErrorException)
|
||||
@ -126,7 +151,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
}
|
||||
}
|
||||
|
||||
GetMvs(ref cm, mvsOut);
|
||||
cm.GetMvs(mvsOut);
|
||||
|
||||
cm.FreeTileWorkerData(_allocator);
|
||||
cm.FreeContextBuffers(_allocator);
|
||||
@ -134,48 +159,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void SetMvs(ref Vp9Common cm, ReadOnlySpan<Vp9MvRef> mvs)
|
||||
public void Dispose()
|
||||
{
|
||||
if (mvs.Length > cm.PrevFrameMvs.Length)
|
||||
{
|
||||
throw new ArgumentException($"Size mismatch, expected: {cm.PrevFrameMvs.Length}, but got: {mvs.Length}.");
|
||||
}
|
||||
|
||||
for (int i = 0; i < mvs.Length; i++)
|
||||
{
|
||||
ref var mv = ref cm.PrevFrameMvs[i];
|
||||
|
||||
mv.Mv[0].Row = mvs[i].Mvs[0].Row;
|
||||
mv.Mv[0].Col = mvs[i].Mvs[0].Col;
|
||||
mv.Mv[1].Row = mvs[i].Mvs[1].Row;
|
||||
mv.Mv[1].Col = mvs[i].Mvs[1].Col;
|
||||
|
||||
mv.RefFrame[0] = (sbyte)mvs[i].RefFrames[0];
|
||||
mv.RefFrame[1] = (sbyte)mvs[i].RefFrames[1];
|
||||
}
|
||||
_allocator.Dispose();
|
||||
}
|
||||
|
||||
private static void GetMvs(ref Vp9Common cm, Span<Vp9MvRef> mvs)
|
||||
{
|
||||
if (mvs.Length > cm.CurFrameMvs.Length)
|
||||
{
|
||||
throw new ArgumentException($"Size mismatch, expected: {cm.CurFrameMvs.Length}, but got: {mvs.Length}.");
|
||||
}
|
||||
|
||||
for (int i = 0; i < mvs.Length; i++)
|
||||
{
|
||||
ref var mv = ref cm.CurFrameMvs[i];
|
||||
|
||||
mvs[i].Mvs[0].Row = mv.Mv[0].Row;
|
||||
mvs[i].Mvs[0].Col = mv.Mv[0].Col;
|
||||
mvs[i].Mvs[1].Row = mv.Mv[1].Row;
|
||||
mvs[i].Mvs[1].Col = mv.Mv[1].Col;
|
||||
|
||||
mvs[i].RefFrames[0] = mv.RefFrame[0];
|
||||
mvs[i].RefFrames[1] = mv.RefFrame[1];
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose() => _allocator.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Graphics.Nvdec.Vp9.Dsp;
|
||||
using Ryujinx.Graphics.Nvdec.Vp9.Types;
|
||||
using Ryujinx.Graphics.Video;
|
||||
@ -19,24 +19,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
{
|
||||
const int MaxNeighbors = 2;
|
||||
|
||||
return (1 + tokenCache[neighbors[MaxNeighbors * c + 0]] + tokenCache[neighbors[MaxNeighbors * c + 1]]) >> 1;
|
||||
}
|
||||
|
||||
private static int ReadCoeff(
|
||||
ref Reader r,
|
||||
ReadOnlySpan<byte> probs,
|
||||
int n,
|
||||
ref ulong value,
|
||||
ref int count,
|
||||
ref uint range)
|
||||
{
|
||||
int i, val = 0;
|
||||
for (i = 0; i < n; ++i)
|
||||
{
|
||||
val = (val << 1) | r.ReadBool(probs[i], ref value, ref count, ref range);
|
||||
}
|
||||
|
||||
return val;
|
||||
return (1 + tokenCache[neighbors[(MaxNeighbors * c) + 0]] +
|
||||
tokenCache[neighbors[(MaxNeighbors * c) + 1]]) >> 1;
|
||||
}
|
||||
|
||||
private static int DecodeCoefs(
|
||||
@ -58,13 +42,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
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.GetBandTranslate(txSize);
|
||||
int dqShift = (txSize == TxSize.Tx32x32) ? 1 : 0;
|
||||
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[2..] : Luts.Vp9Cat6Prob;
|
||||
int cat6Bits = (xd.Bd == 12) ? 18 : (xd.Bd == 10) ? 16 : 14;
|
||||
ReadOnlySpan<byte> cat6Prob = xd.Bd == 12
|
||||
? Luts.Cat6ProbHigh12
|
||||
: xd.Bd == 10
|
||||
? Luts.Cat6ProbHigh12.Slice(2)
|
||||
: Luts.Cat6Prob;
|
||||
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.
|
||||
ulong value = r.Value;
|
||||
@ -75,7 +61,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
{
|
||||
int val = -1;
|
||||
band = bandTranslate[0];
|
||||
bandTranslate = bandTranslate[1..];
|
||||
bandTranslate = bandTranslate.Slice(1);
|
||||
ref Array3<byte> prob = ref coefProbs[band][ctx];
|
||||
if (!xd.Counts.IsNull)
|
||||
{
|
||||
@ -107,18 +93,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
r.Value = value;
|
||||
r.Range = range;
|
||||
r.Count = count;
|
||||
|
||||
return c; // Zero tokens at the end (no eob token)
|
||||
}
|
||||
|
||||
ctx = GetCoefContext(nb, tokenCache, c);
|
||||
band = bandTranslate[0];
|
||||
bandTranslate = bandTranslate[1..];
|
||||
bandTranslate = bandTranslate.Slice(1);
|
||||
prob = ref coefProbs[band][ctx];
|
||||
}
|
||||
|
||||
if (r.ReadBool(prob[OneContextNode], ref value, ref count, ref range) != 0)
|
||||
{
|
||||
ReadOnlySpan<byte> p = Luts.Vp9Pareto8Full[prob[Constants.PivotNode] - 1];
|
||||
ReadOnlySpan<byte> p = Luts.Pareto8Full[prob[Constants.PivotNode] - 1];
|
||||
if (!xd.Counts.IsNull)
|
||||
{
|
||||
++counts.Coef[(int)txSize][(int)type][refr][band][ctx][Constants.TwoToken];
|
||||
@ -133,20 +119,24 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
{
|
||||
if (r.ReadBool(p[7], ref value, ref count, ref range) != 0)
|
||||
{
|
||||
val = Constants.Cat6MinVal + ReadCoeff(ref r, cat6Prob, cat6Bits, ref value, ref count, ref range);
|
||||
val = Constants.Cat6MinVal + r.ReadCoeff(cat6Prob, cat6Bits, ref value,
|
||||
ref count, ref range);
|
||||
}
|
||||
else
|
||||
{
|
||||
val = Constants.Cat5MinVal + ReadCoeff(ref r, Luts.Vp9Cat5Prob, 5, ref value, ref count, ref range);
|
||||
val = Constants.Cat5MinVal + r.ReadCoeff(Luts.Cat5Prob, 5, ref value,
|
||||
ref count, ref range);
|
||||
}
|
||||
}
|
||||
else if (r.ReadBool(p[6], ref value, ref count, ref range) != 0)
|
||||
{
|
||||
val = Constants.Cat4MinVal + ReadCoeff(ref r, Luts.Vp9Cat4Prob, 4, ref value, ref count, ref range);
|
||||
val = Constants.Cat4MinVal + r.ReadCoeff(Luts.Cat4Prob, 4, ref value, ref count,
|
||||
ref range);
|
||||
}
|
||||
else
|
||||
{
|
||||
val = Constants.Cat3MinVal + ReadCoeff(ref r, Luts.Vp9Cat3Prob, 3, ref value, ref count, ref range);
|
||||
val = Constants.Cat3MinVal + r.ReadCoeff(Luts.Cat3Prob, 3, ref value, ref count,
|
||||
ref range);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -154,13 +144,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
tokenCache[scan[c]] = 4;
|
||||
if (r.ReadBool(p[4], ref value, ref count, ref range) != 0)
|
||||
{
|
||||
val = Constants.Cat2MinVal + ReadCoeff(ref r, Luts.Vp9Cat2Prob, 2, ref value, ref count, ref range);
|
||||
val = Constants.Cat2MinVal + r.ReadCoeff(Luts.Cat2Prob, 2, ref value, ref count,
|
||||
ref range);
|
||||
}
|
||||
else
|
||||
{
|
||||
val = Constants.Cat1MinVal + ReadCoeff(ref r, Luts.Vp9Cat1Prob, 1, ref value, ref count, ref range);
|
||||
val = Constants.Cat1MinVal + r.ReadCoeff(Luts.Cat1Prob, 1, ref value, ref count,
|
||||
ref range);
|
||||
}
|
||||
}
|
||||
|
||||
// Val may use 18-bits
|
||||
v = (int)(((long)val * dqv) >> dqShift);
|
||||
}
|
||||
@ -188,7 +181,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
tokenCache[scan[c]] = 1;
|
||||
v = dqv >> dqShift;
|
||||
}
|
||||
dqcoeff[scan[c]] = (int)HighbdCheckRange(r.ReadBool(128, ref value, ref count, ref range) != 0 ? -v : v, xd.Bd);
|
||||
|
||||
dqcoeff[scan[c]] = (int)HighbdCheckRange(r.ReadBool(128, ref value, ref count, ref range) != 0 ? -v : v,
|
||||
xd.Bd);
|
||||
++c;
|
||||
ctx = GetCoefContext(nb, tokenCache, c);
|
||||
dqv = dq[1];
|
||||
@ -197,11 +192,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
r.Value = value;
|
||||
r.Range = range;
|
||||
r.Count = count;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
private static void GetCtxShift(ref MacroBlockD xd, ref int ctxShiftA, ref int ctxShiftL, int x, int y, uint txSizeInBlocks)
|
||||
private static void GetCtxShift(ref MacroBlockD xd, ref int ctxShiftA, ref int ctxShiftL, int x, int y,
|
||||
uint txSizeInBlocks)
|
||||
{
|
||||
if (xd.MaxBlocksWide != 0)
|
||||
{
|
||||
@ -210,6 +205,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
ctxShiftA = (int)(txSizeInBlocks - (xd.MaxBlocksWide - x)) * 8;
|
||||
}
|
||||
}
|
||||
|
||||
if (xd.MaxBlocksHigh != 0)
|
||||
{
|
||||
if (txSizeInBlocks + y > xd.MaxBlocksHigh)
|
||||
@ -238,15 +234,15 @@ 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()[x..];
|
||||
Span<sbyte> l = pd.LeftContext.AsSpan()[y..];
|
||||
Span<sbyte> a = pd.AboveContext.AsSpan().Slice(x);
|
||||
Span<sbyte> l = pd.LeftContext.AsSpan().Slice(y);
|
||||
int ctx;
|
||||
int ctxShiftA = 0;
|
||||
int ctxShiftL = 0;
|
||||
|
||||
switch (txSize)
|
||||
{
|
||||
case TxSize.Tx4x4:
|
||||
case TxSize.Tx4X4:
|
||||
ctx = a[0] != 0 ? 1 : 0;
|
||||
ctx += l[0] != 0 ? 1 : 0;
|
||||
eob = DecodeCoefs(
|
||||
@ -261,8 +257,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
ref r);
|
||||
a[0] = l[0] = (sbyte)(eob > 0 ? 1 : 0);
|
||||
break;
|
||||
case TxSize.Tx8x8:
|
||||
GetCtxShift(ref xd, ref ctxShiftA, ref ctxShiftL, x, y, 1 << (int)TxSize.Tx8x8);
|
||||
case TxSize.Tx8X8:
|
||||
GetCtxShift(ref xd, ref ctxShiftA, ref ctxShiftL, x, y, 1 << (int)TxSize.Tx8X8);
|
||||
ctx = MemoryMarshal.Cast<sbyte, ushort>(a)[0] != 0 ? 1 : 0;
|
||||
ctx += MemoryMarshal.Cast<sbyte, ushort>(l)[0] != 0 ? 1 : 0;
|
||||
eob = DecodeCoefs(
|
||||
@ -278,8 +274,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
MemoryMarshal.Cast<sbyte, ushort>(a)[0] = (ushort)((eob > 0 ? 0x0101 : 0) >> ctxShiftA);
|
||||
MemoryMarshal.Cast<sbyte, ushort>(l)[0] = (ushort)((eob > 0 ? 0x0101 : 0) >> ctxShiftL);
|
||||
break;
|
||||
case TxSize.Tx16x16:
|
||||
GetCtxShift(ref xd, ref ctxShiftA, ref ctxShiftL, x, y, 1 << (int)TxSize.Tx16x16);
|
||||
case TxSize.Tx16X16:
|
||||
GetCtxShift(ref xd, ref ctxShiftA, ref ctxShiftL, x, y, 1 << (int)TxSize.Tx16X16);
|
||||
ctx = MemoryMarshal.Cast<sbyte, uint>(a)[0] != 0 ? 1 : 0;
|
||||
ctx += MemoryMarshal.Cast<sbyte, uint>(l)[0] != 0 ? 1 : 0;
|
||||
eob = DecodeCoefs(
|
||||
@ -295,8 +291,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
MemoryMarshal.Cast<sbyte, uint>(a)[0] = (uint)((eob > 0 ? 0x01010101 : 0) >> ctxShiftA);
|
||||
MemoryMarshal.Cast<sbyte, uint>(l)[0] = (uint)((eob > 0 ? 0x01010101 : 0) >> ctxShiftL);
|
||||
break;
|
||||
case TxSize.Tx32x32:
|
||||
GetCtxShift(ref xd, ref ctxShiftA, ref ctxShiftL, x, y, 1 << (int)TxSize.Tx32x32);
|
||||
case TxSize.Tx32X32:
|
||||
GetCtxShift(ref xd, ref ctxShiftA, ref ctxShiftL, x, y, 1 << (int)TxSize.Tx32X32);
|
||||
// NOTE: Casting to ulong here is safe because the default memory
|
||||
// alignment is at least 8 bytes and the Tx32x32 is aligned on 8 byte
|
||||
// boundaries.
|
||||
@ -324,4 +320,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
return eob;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Graphics.Nvdec.Vp9.Common;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
@ -75,17 +75,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||
Vector128<int> zero = Vector128<int>.Zero;
|
||||
Vector128<int> const64 = Vector128.Create(64);
|
||||
|
||||
ulong x, y;
|
||||
src -= SubpelTaps / 2 - 1;
|
||||
src -= (SubpelTaps / 2) - 1;
|
||||
|
||||
fixed (Array8<short>* xFilter = xFilters)
|
||||
{
|
||||
Vector128<short> vfilter = Sse2.LoadVector128((short*)xFilter + (uint)(x0Q4 & SubpelMask) * 8);
|
||||
Vector128<short> vfilter = Sse2.LoadVector128((short*)xFilter + ((uint)(x0Q4 & SubpelMask) * 8));
|
||||
|
||||
for (y = 0; y < (uint)h; ++y)
|
||||
for (ulong y = 0; y < (uint)h; ++y)
|
||||
{
|
||||
ulong srcOffset = (uint)x0Q4 >> SubpelBits;
|
||||
for (x = 0; x < (uint)w; x += 4)
|
||||
for (ulong x = 0; x < (uint)w; x += 4)
|
||||
{
|
||||
Vector128<short> vsrc0 = Sse41.ConvertToVector128Int16(&src[srcOffset + x]);
|
||||
Vector128<short> vsrc1 = Sse41.ConvertToVector128Int16(&src[srcOffset + x + 1]);
|
||||
@ -94,8 +93,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||
|
||||
Vector128<int> sum0123 = MultiplyAddAdjacent(vsrc0, vsrc1, vsrc2, vsrc3, vfilter, zero);
|
||||
|
||||
Sse.StoreScalar((float*)&dst[x], PackUnsignedSaturate(RoundShift(sum0123, const64), zero).AsSingle());
|
||||
Sse.StoreScalar((float*)&dst[x],
|
||||
PackUnsignedSaturate(RoundShift(sum0123, const64), zero).AsSingle());
|
||||
}
|
||||
|
||||
src += srcStride;
|
||||
dst += dstStride;
|
||||
}
|
||||
@ -117,22 +118,20 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||
if (Sse41.IsSupported && UseIntrinsics && xStepQ4 == 1 << SubpelBits)
|
||||
{
|
||||
ConvolveHorizSse41(src, srcStride, dst, dstStride, xFilters, x0Q4, w, h);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int x, y;
|
||||
src -= SubpelTaps / 2 - 1;
|
||||
src -= (SubpelTaps / 2) - 1;
|
||||
|
||||
for (y = 0; y < h; ++y)
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
int xQ4 = x0Q4;
|
||||
for (x = 0; x < w; ++x)
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
byte* srcX = &src[xQ4 >> SubpelBits];
|
||||
ref Array8<short> xFilter = ref xFilters[xQ4 & SubpelMask];
|
||||
int k, sum = 0;
|
||||
for (k = 0; k < SubpelTaps; ++k)
|
||||
int sum = 0;
|
||||
for (int k = 0; k < SubpelTaps; ++k)
|
||||
{
|
||||
sum += srcX[k] * xFilter[k];
|
||||
}
|
||||
@ -140,6 +139,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||
dst[x] = BitUtils.ClipPixel(BitUtils.RoundPowerOfTwo(sum, FilterBits));
|
||||
xQ4 += xStepQ4;
|
||||
}
|
||||
|
||||
src += srcStride;
|
||||
dst += dstStride;
|
||||
}
|
||||
@ -156,25 +156,26 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||
int w,
|
||||
int h)
|
||||
{
|
||||
int x, y;
|
||||
src -= SubpelTaps / 2 - 1;
|
||||
src -= (SubpelTaps / 2) - 1;
|
||||
|
||||
for (y = 0; y < h; ++y)
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
int xQ4 = x0Q4;
|
||||
for (x = 0; x < w; ++x)
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
byte* srcX = &src[xQ4 >> SubpelBits];
|
||||
ref Array8<short> xFilter = ref xFilters[xQ4 & SubpelMask];
|
||||
int k, sum = 0;
|
||||
for (k = 0; k < SubpelTaps; ++k)
|
||||
int sum = 0;
|
||||
for (int k = 0; k < SubpelTaps; ++k)
|
||||
{
|
||||
sum += srcX[k] * xFilter[k];
|
||||
}
|
||||
|
||||
dst[x] = (byte)BitUtils.RoundPowerOfTwo(dst[x] + BitUtils.ClipPixel(BitUtils.RoundPowerOfTwo(sum, FilterBits)), 1);
|
||||
dst[x] = (byte)BitUtils.RoundPowerOfTwo(
|
||||
dst[x] + BitUtils.ClipPixel(BitUtils.RoundPowerOfTwo(sum, FilterBits)), 1);
|
||||
xQ4 += xStepQ4;
|
||||
}
|
||||
|
||||
src += srcStride;
|
||||
dst += dstStride;
|
||||
}
|
||||
@ -203,18 +204,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||
srcStride * 6,
|
||||
srcStride * 7);
|
||||
|
||||
ulong x, y;
|
||||
src -= srcStride * (SubpelTaps / 2 - 1);
|
||||
src -= srcStride * ((SubpelTaps / 2) - 1);
|
||||
|
||||
fixed (Array8<short>* yFilter = yFilters)
|
||||
{
|
||||
Vector128<short> vfilter = Sse2.LoadVector128((short*)yFilter + (uint)(y0Q4 & SubpelMask) * 8);
|
||||
Vector128<short> vfilter = Sse2.LoadVector128((short*)yFilter + ((uint)(y0Q4 & SubpelMask) * 8));
|
||||
|
||||
ulong srcBaseY = (uint)y0Q4 >> SubpelBits;
|
||||
for (y = 0; y < (uint)h; ++y)
|
||||
for (ulong y = 0; y < (uint)h; ++y)
|
||||
{
|
||||
ulong srcOffset = (srcBaseY + y) * (uint)srcStride;
|
||||
for (x = 0; x < (uint)w; x += 4)
|
||||
for (ulong x = 0; x < (uint)w; x += 4)
|
||||
{
|
||||
Vector256<int> vsrc = Avx2.GatherVector256((uint*)&src[srcOffset + x], indices, 1).AsInt32();
|
||||
|
||||
@ -240,8 +240,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||
|
||||
Vector128<int> sum0123 = MultiplyAddAdjacent(vsrc0, vsrc1, vsrc2, vsrc3, vfilter, zero);
|
||||
|
||||
Sse.StoreScalar((float*)&dst[x], PackUnsignedSaturate(RoundShift(sum0123, const64), zero).AsSingle());
|
||||
Sse.StoreScalar((float*)&dst[x],
|
||||
PackUnsignedSaturate(RoundShift(sum0123, const64), zero).AsSingle());
|
||||
}
|
||||
|
||||
dst += dstStride;
|
||||
}
|
||||
}
|
||||
@ -262,22 +264,20 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||
if (Avx2.IsSupported && UseIntrinsics && yStepQ4 == 1 << SubpelBits)
|
||||
{
|
||||
ConvolveVertAvx2(src, srcStride, dst, dstStride, yFilters, y0Q4, w, h);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int x, y;
|
||||
src -= srcStride * (SubpelTaps / 2 - 1);
|
||||
src -= srcStride * ((SubpelTaps / 2) - 1);
|
||||
|
||||
for (x = 0; x < w; ++x)
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
int yQ4 = y0Q4;
|
||||
for (y = 0; y < h; ++y)
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
byte* srcY = &src[(yQ4 >> SubpelBits) * srcStride];
|
||||
ref Array8<short> yFilter = ref yFilters[yQ4 & SubpelMask];
|
||||
int k, sum = 0;
|
||||
for (k = 0; k < SubpelTaps; ++k)
|
||||
int sum = 0;
|
||||
for (int k = 0; k < SubpelTaps; ++k)
|
||||
{
|
||||
sum += srcY[k * srcStride] * yFilter[k];
|
||||
}
|
||||
@ -285,6 +285,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||
dst[y * dstStride] = BitUtils.ClipPixel(BitUtils.RoundPowerOfTwo(sum, FilterBits));
|
||||
yQ4 += yStepQ4;
|
||||
}
|
||||
|
||||
++src;
|
||||
++dst;
|
||||
}
|
||||
@ -301,18 +302,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||
int w,
|
||||
int h)
|
||||
{
|
||||
int x, y;
|
||||
src -= srcStride * (SubpelTaps / 2 - 1);
|
||||
src -= srcStride * ((SubpelTaps / 2) - 1);
|
||||
|
||||
for (x = 0; x < w; ++x)
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
int yQ4 = y0Q4;
|
||||
for (y = 0; y < h; ++y)
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
byte* srcY = &src[(yQ4 >> SubpelBits) * srcStride];
|
||||
ref Array8<short> yFilter = ref yFilters[yQ4 & SubpelMask];
|
||||
int k, sum = 0;
|
||||
for (k = 0; k < SubpelTaps; ++k)
|
||||
int sum = 0;
|
||||
for (int k = 0; k < SubpelTaps; ++k)
|
||||
{
|
||||
sum += srcY[k * srcStride] * yFilter[k];
|
||||
}
|
||||
@ -321,6 +321,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||
dst[y * dstStride] + BitUtils.ClipPixel(BitUtils.RoundPowerOfTwo(sum, FilterBits)), 1);
|
||||
yQ4 += yStepQ4;
|
||||
}
|
||||
|
||||
++src;
|
||||
++dst;
|
||||
}
|
||||
@ -420,15 +421,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||
// ==> yStepQ4 = 64. Since w and h are at most 16, the temp buffer is still
|
||||
// big enough.
|
||||
byte* temp = stackalloc byte[64 * 135];
|
||||
int intermediateHeight = (((h - 1) * yStepQ4 + y0Q4) >> SubpelBits) + SubpelTaps;
|
||||
int intermediateHeight = ((((h - 1) * yStepQ4) + y0Q4) >> SubpelBits) + SubpelTaps;
|
||||
|
||||
Debug.Assert(w <= 64);
|
||||
Debug.Assert(h <= 64);
|
||||
Debug.Assert(yStepQ4 <= 32 || (yStepQ4 <= 64 && h <= 32));
|
||||
Debug.Assert(xStepQ4 <= 64);
|
||||
|
||||
ConvolveHoriz(src - srcStride * (SubpelTaps / 2 - 1), srcStride, temp, 64, filter, x0Q4, xStepQ4, w, intermediateHeight);
|
||||
ConvolveVert(temp + 64 * (SubpelTaps / 2 - 1), 64, dst, dstStride, filter, y0Q4, yStepQ4, w, h);
|
||||
ConvolveHoriz(src - (srcStride * ((SubpelTaps / 2) - 1)), srcStride, temp, 64, filter, x0Q4, xStepQ4, w,
|
||||
intermediateHeight);
|
||||
ConvolveVert(temp + (64 * ((SubpelTaps / 2) - 1)), 64, dst, dstStride, filter, y0Q4, yStepQ4, w, h);
|
||||
}
|
||||
|
||||
public static unsafe void Convolve8Avg(
|
||||
@ -489,11 +491,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||
int w,
|
||||
int h)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
for (y = 0; y < h; ++y)
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
for (x = 0; x < w; ++x)
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
dst[x] = (byte)BitUtils.RoundPowerOfTwo(dst[x] + src[x], 1);
|
||||
}
|
||||
@ -611,18 +611,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||
int h,
|
||||
int bd)
|
||||
{
|
||||
int x, y;
|
||||
src -= SubpelTaps / 2 - 1;
|
||||
src -= (SubpelTaps / 2) - 1;
|
||||
|
||||
for (y = 0; y < h; ++y)
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
int xQ4 = x0Q4;
|
||||
for (x = 0; x < w; ++x)
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
ushort* srcX = &src[xQ4 >> SubpelBits];
|
||||
ref Array8<short> xFilter = ref xFilters[xQ4 & SubpelMask];
|
||||
int k, sum = 0;
|
||||
for (k = 0; k < SubpelTaps; ++k)
|
||||
int sum = 0;
|
||||
for (int k = 0; k < SubpelTaps; ++k)
|
||||
{
|
||||
sum += srcX[k] * xFilter[k];
|
||||
}
|
||||
@ -630,6 +629,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||
dst[x] = BitUtils.ClipPixelHighbd(BitUtils.RoundPowerOfTwo(sum, FilterBits), bd);
|
||||
xQ4 += xStepQ4;
|
||||
}
|
||||
|
||||
src += srcStride;
|
||||
dst += dstStride;
|
||||
}
|
||||
@ -647,25 +647,26 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||
int h,
|
||||
int bd)
|
||||
{
|
||||
int x, y;
|
||||
src -= SubpelTaps / 2 - 1;
|
||||
src -= (SubpelTaps / 2) - 1;
|
||||
|
||||
for (y = 0; y < h; ++y)
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
int xQ4 = x0Q4;
|
||||
for (x = 0; x < w; ++x)
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
ushort* srcX = &src[xQ4 >> SubpelBits];
|
||||
ref Array8<short> xFilter = ref xFilters[xQ4 & SubpelMask];
|
||||
int k, sum = 0;
|
||||
for (k = 0; k < SubpelTaps; ++k)
|
||||
int sum = 0;
|
||||
for (int k = 0; k < SubpelTaps; ++k)
|
||||
{
|
||||
sum += srcX[k] * xFilter[k];
|
||||
}
|
||||
|
||||
dst[x] = (ushort)BitUtils.RoundPowerOfTwo(dst[x] + BitUtils.ClipPixelHighbd(BitUtils.RoundPowerOfTwo(sum, FilterBits), bd), 1);
|
||||
dst[x] = (ushort)BitUtils.RoundPowerOfTwo(
|
||||
dst[x] + BitUtils.ClipPixelHighbd(BitUtils.RoundPowerOfTwo(sum, FilterBits), bd), 1);
|
||||
xQ4 += xStepQ4;
|
||||
}
|
||||
|
||||
src += srcStride;
|
||||
dst += dstStride;
|
||||
}
|
||||
@ -683,18 +684,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||
int h,
|
||||
int bd)
|
||||
{
|
||||
int x, y;
|
||||
src -= srcStride * (SubpelTaps / 2 - 1);
|
||||
src -= srcStride * ((SubpelTaps / 2) - 1);
|
||||
|
||||
for (x = 0; x < w; ++x)
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
int yQ4 = y0Q4;
|
||||
for (y = 0; y < h; ++y)
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
ushort* srcY = &src[(yQ4 >> SubpelBits) * srcStride];
|
||||
ref Array8<short> yFilter = ref yFilters[yQ4 & SubpelMask];
|
||||
int k, sum = 0;
|
||||
for (k = 0; k < SubpelTaps; ++k)
|
||||
int sum = 0;
|
||||
for (int k = 0; k < SubpelTaps; ++k)
|
||||
{
|
||||
sum += srcY[k * srcStride] * yFilter[k];
|
||||
}
|
||||
@ -702,6 +702,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||
dst[y * dstStride] = BitUtils.ClipPixelHighbd(BitUtils.RoundPowerOfTwo(sum, FilterBits), bd);
|
||||
yQ4 += yStepQ4;
|
||||
}
|
||||
|
||||
++src;
|
||||
++dst;
|
||||
}
|
||||
@ -719,26 +720,27 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||
int h,
|
||||
int bd)
|
||||
{
|
||||
int x, y;
|
||||
src -= srcStride * (SubpelTaps / 2 - 1);
|
||||
src -= srcStride * ((SubpelTaps / 2) - 1);
|
||||
|
||||
for (x = 0; x < w; ++x)
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
int yQ4 = y0Q4;
|
||||
for (y = 0; y < h; ++y)
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
ushort* srcY = &src[(yQ4 >> SubpelBits) * srcStride];
|
||||
ref Array8<short> yFilter = ref yFilters[yQ4 & SubpelMask];
|
||||
int k, sum = 0;
|
||||
for (k = 0; k < SubpelTaps; ++k)
|
||||
int sum = 0;
|
||||
for (int k = 0; k < SubpelTaps; ++k)
|
||||
{
|
||||
sum += srcY[k * srcStride] * yFilter[k];
|
||||
}
|
||||
|
||||
dst[y * dstStride] = (ushort)BitUtils.RoundPowerOfTwo(
|
||||
dst[y * dstStride] + BitUtils.ClipPixelHighbd(BitUtils.RoundPowerOfTwo(sum, FilterBits), bd), 1);
|
||||
dst[y * dstStride] + BitUtils.ClipPixelHighbd(BitUtils.RoundPowerOfTwo(sum, FilterBits), bd),
|
||||
1);
|
||||
yQ4 += yStepQ4;
|
||||
}
|
||||
|
||||
++src;
|
||||
++dst;
|
||||
}
|
||||
@ -771,15 +773,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||
// --Require an additional SubpelTaps rows for the 8-tap filter tails.
|
||||
// --((64 - 1) * 32 + 15) >> 4 + 8 = 135.
|
||||
ushort* temp = stackalloc ushort[64 * 135];
|
||||
int intermediateHeight = (((h - 1) * yStepQ4 + y0Q4) >> SubpelBits) + SubpelTaps;
|
||||
int intermediateHeight = ((((h - 1) * yStepQ4) + y0Q4) >> SubpelBits) + SubpelTaps;
|
||||
|
||||
Debug.Assert(w <= 64);
|
||||
Debug.Assert(h <= 64);
|
||||
Debug.Assert(yStepQ4 <= 32);
|
||||
Debug.Assert(xStepQ4 <= 32);
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
public static unsafe void HighbdConvolve8Horiz(
|
||||
@ -928,11 +932,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||
int h,
|
||||
int bd)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
for (y = 0; y < h; ++y)
|
||||
for (int y = 0; y < h; ++y)
|
||||
{
|
||||
for (x = 0; x < w; ++x)
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
dst[x] = (ushort)BitUtils.RoundPowerOfTwo(dst[x] + src[x], 1);
|
||||
}
|
||||
@ -942,4 +944,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -9,4 +9,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||
public const int SubpelShifts = 1 << SubpelBits;
|
||||
public const int SubpelTaps = 8;
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
229
src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/LoopFilterAuto.cs
Normal file
229
src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/LoopFilterAuto.cs
Normal file
@ -0,0 +1,229 @@
|
||||
using Ryujinx.Common.Memory;
|
||||
using System;
|
||||
using System.Runtime.Intrinsics.X86;
|
||||
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||
{
|
||||
internal class LoopFilterAuto
|
||||
{
|
||||
public static void LpfHorizontal4(
|
||||
ArrayPtr<byte> s,
|
||||
int pitch,
|
||||
ReadOnlySpan<byte> blimit,
|
||||
ReadOnlySpan<byte> limit,
|
||||
ReadOnlySpan<byte> thresh)
|
||||
{
|
||||
if (Sse2.IsSupported)
|
||||
{
|
||||
LoopFilterSse2.LpfHorizontal4(s, pitch, blimit, limit, thresh);
|
||||
}
|
||||
else
|
||||
{
|
||||
LoopFilterScalar.LpfHorizontal4(s, pitch, blimit[0], limit[0], thresh[0]);
|
||||
}
|
||||
}
|
||||
|
||||
public static void LpfHorizontal4Dual(
|
||||
ArrayPtr<byte> s,
|
||||
int pitch,
|
||||
ReadOnlySpan<byte> blimit0,
|
||||
ReadOnlySpan<byte> limit0,
|
||||
ReadOnlySpan<byte> thresh0,
|
||||
ReadOnlySpan<byte> blimit1,
|
||||
ReadOnlySpan<byte> limit1,
|
||||
ReadOnlySpan<byte> thresh1)
|
||||
{
|
||||
if (Sse2.IsSupported)
|
||||
{
|
||||
LoopFilterSse2.LpfHorizontal4Dual(s, pitch, blimit0, limit0, thresh0, blimit1, limit1, thresh1);
|
||||
}
|
||||
else
|
||||
{
|
||||
LoopFilterScalar.LpfHorizontal4Dual(s, pitch, blimit0[0], limit0[0], thresh0[0], blimit1[0], limit1[0],
|
||||
thresh1[0]);
|
||||
}
|
||||
}
|
||||
|
||||
public static void LpfHorizontal8(
|
||||
ArrayPtr<byte> s,
|
||||
int pitch,
|
||||
ReadOnlySpan<byte> blimit,
|
||||
ReadOnlySpan<byte> limit,
|
||||
ReadOnlySpan<byte> thresh)
|
||||
{
|
||||
if (Sse2.IsSupported)
|
||||
{
|
||||
LoopFilterSse2.LpfHorizontal8(s, pitch, blimit, limit, thresh);
|
||||
}
|
||||
else
|
||||
{
|
||||
LoopFilterScalar.LpfHorizontal8(s, pitch, blimit[0], limit[0], thresh[0]);
|
||||
}
|
||||
}
|
||||
|
||||
public static void LpfHorizontal8Dual(
|
||||
ArrayPtr<byte> s,
|
||||
int pitch,
|
||||
ReadOnlySpan<byte> blimit0,
|
||||
ReadOnlySpan<byte> limit0,
|
||||
ReadOnlySpan<byte> thresh0,
|
||||
ReadOnlySpan<byte> blimit1,
|
||||
ReadOnlySpan<byte> limit1,
|
||||
ReadOnlySpan<byte> thresh1)
|
||||
{
|
||||
if (Sse2.IsSupported)
|
||||
{
|
||||
LoopFilterSse2.LpfHorizontal8Dual(s, pitch, blimit0, limit0, thresh0, blimit1, limit1, thresh1);
|
||||
}
|
||||
else
|
||||
{
|
||||
LoopFilterScalar.LpfHorizontal8Dual(s, pitch, blimit0[0], limit0[0], thresh0[0], blimit1[0], limit1[0],
|
||||
thresh1[0]);
|
||||
}
|
||||
}
|
||||
|
||||
public static void LpfHorizontal16(
|
||||
ArrayPtr<byte> s,
|
||||
int pitch,
|
||||
ReadOnlySpan<byte> blimit,
|
||||
ReadOnlySpan<byte> limit,
|
||||
ReadOnlySpan<byte> thresh)
|
||||
{
|
||||
if (Sse2.IsSupported)
|
||||
{
|
||||
LoopFilterSse2.LpfHorizontal16(s, pitch, blimit, limit, thresh);
|
||||
}
|
||||
else
|
||||
{
|
||||
LoopFilterScalar.LpfHorizontal16(s, pitch, blimit[0], limit[0], thresh[0]);
|
||||
}
|
||||
}
|
||||
|
||||
public static void LpfHorizontal16Dual(
|
||||
ArrayPtr<byte> s,
|
||||
int pitch,
|
||||
ReadOnlySpan<byte> blimit,
|
||||
ReadOnlySpan<byte> limit,
|
||||
ReadOnlySpan<byte> thresh)
|
||||
{
|
||||
if (Sse2.IsSupported)
|
||||
{
|
||||
LoopFilterSse2.LpfHorizontal16Dual(s, pitch, blimit, limit, thresh);
|
||||
}
|
||||
else
|
||||
{
|
||||
LoopFilterScalar.LpfHorizontal16Dual(s, pitch, blimit[0], limit[0], thresh[0]);
|
||||
}
|
||||
}
|
||||
|
||||
public static void LpfVertical4(
|
||||
ArrayPtr<byte> s,
|
||||
int pitch,
|
||||
ReadOnlySpan<byte> blimit,
|
||||
ReadOnlySpan<byte> limit,
|
||||
ReadOnlySpan<byte> thresh)
|
||||
{
|
||||
if (Sse2.IsSupported)
|
||||
{
|
||||
LoopFilterSse2.LpfVertical4(s, pitch, blimit, limit, thresh);
|
||||
}
|
||||
else
|
||||
{
|
||||
LoopFilterScalar.LpfVertical4(s, pitch, blimit[0], limit[0], thresh[0]);
|
||||
}
|
||||
}
|
||||
|
||||
public static void LpfVertical4Dual(
|
||||
ArrayPtr<byte> s,
|
||||
int pitch,
|
||||
ReadOnlySpan<byte> blimit0,
|
||||
ReadOnlySpan<byte> limit0,
|
||||
ReadOnlySpan<byte> thresh0,
|
||||
ReadOnlySpan<byte> blimit1,
|
||||
ReadOnlySpan<byte> limit1,
|
||||
ReadOnlySpan<byte> thresh1)
|
||||
{
|
||||
if (Sse2.IsSupported)
|
||||
{
|
||||
LoopFilterSse2.LpfVertical4Dual(s, pitch, blimit0, limit0, thresh0, blimit1, limit1, thresh1);
|
||||
}
|
||||
else
|
||||
{
|
||||
LoopFilterScalar.LpfVertical4Dual(s, pitch, blimit0[0], limit0[0], thresh0[0], blimit1[0], limit1[0],
|
||||
thresh1[0]);
|
||||
}
|
||||
}
|
||||
|
||||
public static void LpfVertical8(
|
||||
ArrayPtr<byte> s,
|
||||
int pitch,
|
||||
ReadOnlySpan<byte> blimit,
|
||||
ReadOnlySpan<byte> limit,
|
||||
ReadOnlySpan<byte> thresh)
|
||||
{
|
||||
if (Sse2.IsSupported)
|
||||
{
|
||||
LoopFilterSse2.LpfVertical8(s, pitch, blimit, limit, thresh);
|
||||
}
|
||||
else
|
||||
{
|
||||
LoopFilterScalar.LpfVertical8(s, pitch, blimit[0], limit[0], thresh[0]);
|
||||
}
|
||||
}
|
||||
|
||||
public static void LpfVertical8Dual(
|
||||
ArrayPtr<byte> s,
|
||||
int pitch,
|
||||
ReadOnlySpan<byte> blimit0,
|
||||
ReadOnlySpan<byte> limit0,
|
||||
ReadOnlySpan<byte> thresh0,
|
||||
ReadOnlySpan<byte> blimit1,
|
||||
ReadOnlySpan<byte> limit1,
|
||||
ReadOnlySpan<byte> thresh1)
|
||||
{
|
||||
if (Sse2.IsSupported)
|
||||
{
|
||||
LoopFilterSse2.LpfVertical8Dual(s, pitch, blimit0, limit0, thresh0, blimit1, limit1, thresh1);
|
||||
}
|
||||
else
|
||||
{
|
||||
LoopFilterScalar.LpfVertical8Dual(s, pitch, blimit0[0], limit0[0], thresh0[0], blimit1[0], limit1[0],
|
||||
thresh1[0]);
|
||||
}
|
||||
}
|
||||
|
||||
public static void LpfVertical16(
|
||||
ArrayPtr<byte> s,
|
||||
int pitch,
|
||||
ReadOnlySpan<byte> blimit,
|
||||
ReadOnlySpan<byte> limit,
|
||||
ReadOnlySpan<byte> thresh)
|
||||
{
|
||||
if (Sse2.IsSupported)
|
||||
{
|
||||
LoopFilterSse2.LpfVertical16(s, pitch, blimit, limit, thresh);
|
||||
}
|
||||
else
|
||||
{
|
||||
LoopFilterScalar.LpfVertical16(s, pitch, blimit[0], limit[0], thresh[0]);
|
||||
}
|
||||
}
|
||||
|
||||
public static void LpfVertical16Dual(
|
||||
ArrayPtr<byte> s,
|
||||
int pitch,
|
||||
ReadOnlySpan<byte> blimit,
|
||||
ReadOnlySpan<byte> limit,
|
||||
ReadOnlySpan<byte> thresh)
|
||||
{
|
||||
if (Sse2.IsSupported)
|
||||
{
|
||||
LoopFilterSse2.LpfVertical16Dual(s, pitch, blimit, limit, thresh);
|
||||
}
|
||||
else
|
||||
{
|
||||
LoopFilterScalar.LpfVertical16Dual(s, pitch, blimit[0], limit[0], thresh[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
1093
src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/LoopFilterScalar.cs
Normal file
1093
src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/LoopFilterScalar.cs
Normal file
File diff suppressed because it is too large
Load Diff
1837
src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/LoopFilterSse2.cs
Normal file
1837
src/Ryujinx.Graphics.Nvdec.Vp9/Dsp/LoopFilterSse2.cs
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
using Ryujinx.Graphics.Nvdec.Vp9.Common;
|
||||
using Ryujinx.Graphics.Nvdec.Vp9.Common;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
@ -12,10 +12,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||
{
|
||||
Debug.Assert(den != 0);
|
||||
{
|
||||
int p = (int)(((ulong)num * 256 + (den >> 1)) / den);
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -23,14 +22,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||
/* This function assumes prob1 and prob2 are already within [1,255] range. */
|
||||
public static byte WeightedProb(int prob1, int prob2, int factor)
|
||||
{
|
||||
return (byte)BitUtils.RoundPowerOfTwo(prob1 * (256 - factor) + prob2 * factor, 8);
|
||||
return (byte)BitUtils.RoundPowerOfTwo((prob1 * (256 - factor)) + (prob2 * factor), 8);
|
||||
}
|
||||
|
||||
// MODE_MV_MAX_UPDATE_FACTOR (128) * count / MODE_MV_COUNT_SAT;
|
||||
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,
|
||||
};
|
||||
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
|
||||
];
|
||||
|
||||
private const int ModeMvCountSat = 20;
|
||||
|
||||
@ -41,14 +40,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||
{
|
||||
return preProb;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint count = Math.Min(den, ModeMvCountSat);
|
||||
uint factor = _countToUpdateFactor[(int)count];
|
||||
byte prob = GetProb(ct0, den);
|
||||
|
||||
return WeightedProb(preProb, prob, (int)factor);
|
||||
}
|
||||
uint count = Math.Min(den, ModeMvCountSat);
|
||||
uint factor = _countToUpdateFactor[(int)count];
|
||||
byte prob = GetProb(ct0, den);
|
||||
return WeightedProb(preProb, prob, (int)factor);
|
||||
}
|
||||
|
||||
private static uint TreeMergeProbsImpl(
|
||||
@ -59,17 +55,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||
Span<byte> probs)
|
||||
{
|
||||
int l = tree[i];
|
||||
uint leftCount = (l <= 0) ? counts[-l] : TreeMergeProbsImpl((uint)l, tree, preProbs, counts, probs);
|
||||
uint leftCount = l <= 0 ? counts[-l] : TreeMergeProbsImpl((uint)l, tree, preProbs, counts, probs);
|
||||
int r = tree[i + 1];
|
||||
uint rightCount = (r <= 0) ? counts[-r] : TreeMergeProbsImpl((uint)r, tree, preProbs, counts, probs);
|
||||
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;
|
||||
}
|
||||
|
||||
public static void TreeMergeProbs(sbyte[] tree, ReadOnlySpan<byte> preProbs, ReadOnlySpan<uint> counts, Span<byte> probs)
|
||||
public static void TreeMergeProbs(sbyte[] tree, ReadOnlySpan<byte> preProbs, ReadOnlySpan<uint> counts,
|
||||
Span<byte> probs)
|
||||
{
|
||||
TreeMergeProbsImpl(0, tree, preProbs, counts, probs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
{
|
||||
@ -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,8 +200,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||
|
||||
if (value >= bigsplit)
|
||||
{
|
||||
range -= split;
|
||||
value -= bigsplit;
|
||||
range = range - split;
|
||||
value = value - bigsplit;
|
||||
{
|
||||
int shift = _norm[range];
|
||||
range <<= shift;
|
||||
@ -212,6 +210,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
range = split;
|
||||
{
|
||||
int shift = _norm[range];
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -13,42 +13,42 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
|
||||
// for (int i = 1; i < 32; ++i)
|
||||
// Console.WriteLine("public const short CosPi{0}_64 = {1};", i, MathF.Round(16384 * MathF.Cos(i * MathF.PI / 64)));
|
||||
// Note: sin(k * Pi / 64) = cos((32 - k) * Pi / 64)
|
||||
public const short CosPi1_64 = 16364;
|
||||
public const short CosPi2_64 = 16305;
|
||||
public const short CosPi3_64 = 16207;
|
||||
public const short CosPi4_64 = 16069;
|
||||
public const short CosPi5_64 = 15893;
|
||||
public const short CosPi6_64 = 15679;
|
||||
public const short CosPi7_64 = 15426;
|
||||
public const short CosPi8_64 = 15137;
|
||||
public const short CosPi9_64 = 14811;
|
||||
public const short CosPi10_64 = 14449;
|
||||
public const short CosPi11_64 = 14053;
|
||||
public const short CosPi12_64 = 13623;
|
||||
public const short CosPi13_64 = 13160;
|
||||
public const short CosPi14_64 = 12665;
|
||||
public const short CosPi15_64 = 12140;
|
||||
public const short CosPi16_64 = 11585;
|
||||
public const short CosPi17_64 = 11003;
|
||||
public const short CosPi18_64 = 10394;
|
||||
public const short CosPi19_64 = 9760;
|
||||
public const short CosPi20_64 = 9102;
|
||||
public const short CosPi21_64 = 8423;
|
||||
public const short CosPi22_64 = 7723;
|
||||
public const short CosPi23_64 = 7005;
|
||||
public const short CosPi24_64 = 6270;
|
||||
public const short CosPi25_64 = 5520;
|
||||
public const short CosPi26_64 = 4756;
|
||||
public const short CosPi27_64 = 3981;
|
||||
public const short CosPi28_64 = 3196;
|
||||
public const short CosPi29_64 = 2404;
|
||||
public const short CosPi30_64 = 1606;
|
||||
public const short CosPi31_64 = 804;
|
||||
public const short CosPi164 = 16364;
|
||||
public const short CosPi264 = 16305;
|
||||
public const short CosPi364 = 16207;
|
||||
public const short CosPi464 = 16069;
|
||||
public const short CosPi564 = 15893;
|
||||
public const short CosPi664 = 15679;
|
||||
public const short CosPi764 = 15426;
|
||||
public const short CosPi864 = 15137;
|
||||
public const short CosPi964 = 14811;
|
||||
public const short CosPi1064 = 14449;
|
||||
public const short CosPi1164 = 14053;
|
||||
public const short CosPi1264 = 13623;
|
||||
public const short CosPi1364 = 13160;
|
||||
public const short CosPi1464 = 12665;
|
||||
public const short CosPi1564 = 12140;
|
||||
public const short CosPi1664 = 11585;
|
||||
public const short CosPi1764 = 11003;
|
||||
public const short CosPi1864 = 10394;
|
||||
public const short CosPi1964 = 9760;
|
||||
public const short CosPi2064 = 9102;
|
||||
public const short CosPi2164 = 8423;
|
||||
public const short CosPi2264 = 7723;
|
||||
public const short CosPi2364 = 7005;
|
||||
public const short CosPi2464 = 6270;
|
||||
public const short CosPi2564 = 5520;
|
||||
public const short CosPi2664 = 4756;
|
||||
public const short CosPi2764 = 3981;
|
||||
public const short CosPi2864 = 3196;
|
||||
public const short CosPi2964 = 2404;
|
||||
public const short CosPi3064 = 1606;
|
||||
public const short CosPi3164 = 804;
|
||||
|
||||
// 16384 * sqrt(2) * sin(kPi / 9) * 2 / 3
|
||||
public const short SinPi1_9 = 5283;
|
||||
public const short SinPi2_9 = 9929;
|
||||
public const short SinPi3_9 = 13377;
|
||||
public const short SinPi4_9 = 15212;
|
||||
public const short SinPi19 = 5283;
|
||||
public const short SinPi29 = 9929;
|
||||
public const short SinPi39 = 13377;
|
||||
public const short SinPi49 = 15212;
|
||||
}
|
||||
}
|
||||
}
|
623
src/Ryujinx.Graphics.Nvdec.Vp9/Entropy.cs
Normal file
623
src/Ryujinx.Graphics.Nvdec.Vp9/Entropy.cs
Normal file
@ -0,0 +1,623 @@
|
||||
using Ryujinx.Graphics.Nvdec.Vp9.Types;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
{
|
||||
internal static class Entropy
|
||||
{
|
||||
public const int DiffUpdateProb = 252;
|
||||
|
||||
// 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 ThreeToken = 3; // 3 Extra Bits 0+1
|
||||
public const int FourToken = 4; // 4 Extra Bits 0+1
|
||||
public const int Category1Token = 5; // 5-6 Extra Bits 1+1
|
||||
public const int Category2Token = 6; // 7-10 Extra Bits 2+1
|
||||
public const int Category3Token = 7; // 11-18 Extra Bits 3+1
|
||||
public const int Category4Token = 8; // 19-34 Extra Bits 4+1
|
||||
public const int Category5Token = 9; // 35-66 Extra Bits 5+1
|
||||
public const int Category6Token = 10; // 67+ Extra Bits 14+1
|
||||
public const int EobToken = 11; // EOB Extra Bits 0+0
|
||||
|
||||
public const int EntropyTokens = 12;
|
||||
|
||||
public const int RefTypes = 2; // intra=0, inter=1
|
||||
|
||||
/* Middle dimension reflects the coefficient position within the transform. */
|
||||
public const int CoefBands = 6;
|
||||
|
||||
/* Inside dimension is measure of nearby complexity, that reflects the energy
|
||||
of nearby coefficients are nonzero. For the first coefficient (DC, unless
|
||||
block type is 0), we look at the (already encoded) blocks above and to the
|
||||
left of the current block. The context index is then the number (0,1,or 2)
|
||||
of these blocks having nonzero coefficients.
|
||||
After decoding a coefficient, the measure is determined by the size of the
|
||||
most recently decoded coefficient.
|
||||
Note that the intuitive meaning of this measure changes as coefficients
|
||||
are decoded, e.g., prior to the first token, a zero means that my neighbors
|
||||
are empty while, after the first token, because of the use of end-of-block,
|
||||
a zero means we just decoded a zero and hence guarantees that a non-zero
|
||||
coefficient will appear later in this block. However, this shift
|
||||
in meaning is perfectly OK because our context depends also on the
|
||||
coefficient band (and since zigzag positions 0, 1, and 2 are in
|
||||
distinct bands). */
|
||||
|
||||
public const int CoeffContexts = 6;
|
||||
|
||||
public static int BAND_COEFF_CONTEXTS(int band)
|
||||
{
|
||||
return band == 0 ? 3 : CoeffContexts;
|
||||
}
|
||||
|
||||
public const int UnconstrainedNodes = 3;
|
||||
|
||||
public const int PivotNode = 2;
|
||||
|
||||
public const int Cat1MinVal = 5;
|
||||
public const int Cat2MinVal = 7;
|
||||
public const int Cat3MinVal = 11;
|
||||
public const int Cat4MinVal = 19;
|
||||
public const int Cat5MinVal = 35;
|
||||
public const int Cat6MinVal = 67;
|
||||
|
||||
public static readonly byte[] Cat1Prob = [159];
|
||||
public static readonly byte[] Cat2Prob = [165, 145];
|
||||
public static readonly byte[] Cat3Prob = [173, 148, 140];
|
||||
public static readonly byte[] Cat4Prob = [176, 155, 140, 135];
|
||||
public static readonly byte[] Cat5Prob = [180, 157, 141, 134, 130];
|
||||
|
||||
public static readonly byte[] Cat6Prob =
|
||||
[
|
||||
254, 254, 254, 252, 249, 243, 230, 196, 177, 153, 140, 133, 130, 129
|
||||
];
|
||||
|
||||
public static readonly byte[] Cat6ProbHigh12 =
|
||||
[
|
||||
255, 255, 255, 255, 254, 254, 54, 252, 249, 243, 230, 196, 177, 153, 140, 133, 130, 129
|
||||
];
|
||||
|
||||
public const int EobModelToken = 3;
|
||||
|
||||
private static readonly byte[] _coefbandTrans8X8Plus =
|
||||
[
|
||||
0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5,
|
||||
// beyond MAXBAND_INDEX+1 all values are filled as 5
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
|
||||
];
|
||||
|
||||
private static readonly byte[] _coefbandTrans4X4 = [0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5];
|
||||
|
||||
public static readonly byte[][] Pareto8Full =
|
||||
[
|
||||
[3, 86, 128, 6, 86, 23, 88, 29], [6, 86, 128, 11, 87, 42, 91, 52],
|
||||
[9, 86, 129, 17, 88, 61, 94, 76], [12, 86, 129, 22, 88, 77, 97, 93],
|
||||
[15, 87, 129, 28, 89, 93, 100, 110], [17, 87, 129, 33, 90, 105, 103, 123],
|
||||
[20, 88, 130, 38, 91, 118, 106, 136], [23, 88, 130, 43, 91, 128, 108, 146],
|
||||
[26, 89, 131, 48, 92, 139, 111, 156], [28, 89, 131, 53, 93, 147, 114, 163],
|
||||
[31, 90, 131, 58, 94, 156, 117, 171], [34, 90, 131, 62, 94, 163, 119, 177],
|
||||
[37, 90, 132, 66, 95, 171, 122, 184], [39, 90, 132, 70, 96, 177, 124, 189],
|
||||
[42, 91, 132, 75, 97, 183, 127, 194], [44, 91, 132, 79, 97, 188, 129, 198],
|
||||
[47, 92, 133, 83, 98, 193, 132, 202], [49, 92, 133, 86, 99, 197, 134, 205],
|
||||
[52, 93, 133, 90, 100, 201, 137, 208], [54, 93, 133, 94, 100, 204, 139, 211],
|
||||
[57, 94, 134, 98, 101, 208, 142, 214], [59, 94, 134, 101, 102, 211, 144, 216],
|
||||
[62, 94, 135, 105, 103, 214, 146, 218],
|
||||
[64, 94, 135, 108, 103, 216, 148, 220],
|
||||
[66, 95, 135, 111, 104, 219, 151, 222],
|
||||
[68, 95, 135, 114, 105, 221, 153, 223],
|
||||
[71, 96, 136, 117, 106, 224, 155, 225],
|
||||
[73, 96, 136, 120, 106, 225, 157, 226],
|
||||
[76, 97, 136, 123, 107, 227, 159, 228],
|
||||
[78, 97, 136, 126, 108, 229, 160, 229],
|
||||
[80, 98, 137, 129, 109, 231, 162, 231],
|
||||
[82, 98, 137, 131, 109, 232, 164, 232],
|
||||
[84, 98, 138, 134, 110, 234, 166, 233],
|
||||
[86, 98, 138, 137, 111, 235, 168, 234],
|
||||
[89, 99, 138, 140, 112, 236, 170, 235],
|
||||
[91, 99, 138, 142, 112, 237, 171, 235],
|
||||
[93, 100, 139, 145, 113, 238, 173, 236],
|
||||
[95, 100, 139, 147, 114, 239, 174, 237],
|
||||
[97, 101, 140, 149, 115, 240, 176, 238],
|
||||
[99, 101, 140, 151, 115, 241, 177, 238],
|
||||
[101, 102, 140, 154, 116, 242, 179, 239],
|
||||
[103, 102, 140, 156, 117, 242, 180, 239],
|
||||
[105, 103, 141, 158, 118, 243, 182, 240],
|
||||
[107, 103, 141, 160, 118, 243, 183, 240],
|
||||
[109, 104, 141, 162, 119, 244, 185, 241],
|
||||
[111, 104, 141, 164, 119, 244, 186, 241],
|
||||
[113, 104, 142, 166, 120, 245, 187, 242],
|
||||
[114, 104, 142, 168, 121, 245, 188, 242],
|
||||
[116, 105, 143, 170, 122, 246, 190, 243],
|
||||
[118, 105, 143, 171, 122, 246, 191, 243],
|
||||
[120, 106, 143, 173, 123, 247, 192, 244],
|
||||
[121, 106, 143, 175, 124, 247, 193, 244],
|
||||
[123, 107, 144, 177, 125, 248, 195, 244],
|
||||
[125, 107, 144, 178, 125, 248, 196, 244],
|
||||
[127, 108, 145, 180, 126, 249, 197, 245],
|
||||
[128, 108, 145, 181, 127, 249, 198, 245],
|
||||
[130, 109, 145, 183, 128, 249, 199, 245],
|
||||
[132, 109, 145, 184, 128, 249, 200, 245],
|
||||
[134, 110, 146, 186, 129, 250, 201, 246],
|
||||
[135, 110, 146, 187, 130, 250, 202, 246],
|
||||
[137, 111, 147, 189, 131, 251, 203, 246],
|
||||
[138, 111, 147, 190, 131, 251, 204, 246],
|
||||
[140, 112, 147, 192, 132, 251, 205, 247],
|
||||
[141, 112, 147, 193, 132, 251, 206, 247],
|
||||
[143, 113, 148, 194, 133, 251, 207, 247],
|
||||
[144, 113, 148, 195, 134, 251, 207, 247],
|
||||
[146, 114, 149, 197, 135, 252, 208, 248],
|
||||
[147, 114, 149, 198, 135, 252, 209, 248],
|
||||
[149, 115, 149, 199, 136, 252, 210, 248],
|
||||
[150, 115, 149, 200, 137, 252, 210, 248],
|
||||
[152, 115, 150, 201, 138, 252, 211, 248],
|
||||
[153, 115, 150, 202, 138, 252, 212, 248],
|
||||
[155, 116, 151, 204, 139, 253, 213, 249],
|
||||
[156, 116, 151, 205, 139, 253, 213, 249],
|
||||
[158, 117, 151, 206, 140, 253, 214, 249],
|
||||
[159, 117, 151, 207, 141, 253, 215, 249],
|
||||
[161, 118, 152, 208, 142, 253, 216, 249],
|
||||
[162, 118, 152, 209, 142, 253, 216, 249],
|
||||
[163, 119, 153, 210, 143, 253, 217, 249],
|
||||
[164, 119, 153, 211, 143, 253, 217, 249],
|
||||
[166, 120, 153, 212, 144, 254, 218, 250],
|
||||
[167, 120, 153, 212, 145, 254, 219, 250],
|
||||
[168, 121, 154, 213, 146, 254, 220, 250],
|
||||
[169, 121, 154, 214, 146, 254, 220, 250],
|
||||
[171, 122, 155, 215, 147, 254, 221, 250],
|
||||
[172, 122, 155, 216, 147, 254, 221, 250],
|
||||
[173, 123, 155, 217, 148, 254, 222, 250],
|
||||
[174, 123, 155, 217, 149, 254, 222, 250],
|
||||
[176, 124, 156, 218, 150, 254, 223, 250],
|
||||
[177, 124, 156, 219, 150, 254, 223, 250],
|
||||
[178, 125, 157, 220, 151, 254, 224, 251],
|
||||
[179, 125, 157, 220, 151, 254, 224, 251],
|
||||
[180, 126, 157, 221, 152, 254, 225, 251],
|
||||
[181, 126, 157, 221, 152, 254, 225, 251],
|
||||
[183, 127, 158, 222, 153, 254, 226, 251],
|
||||
[184, 127, 158, 223, 154, 254, 226, 251],
|
||||
[185, 128, 159, 224, 155, 255, 227, 251],
|
||||
[186, 128, 159, 224, 155, 255, 227, 251],
|
||||
[187, 129, 160, 225, 156, 255, 228, 251],
|
||||
[188, 130, 160, 225, 156, 255, 228, 251],
|
||||
[189, 131, 160, 226, 157, 255, 228, 251],
|
||||
[190, 131, 160, 226, 158, 255, 228, 251],
|
||||
[191, 132, 161, 227, 159, 255, 229, 251],
|
||||
[192, 132, 161, 227, 159, 255, 229, 251],
|
||||
[193, 133, 162, 228, 160, 255, 230, 252],
|
||||
[194, 133, 162, 229, 160, 255, 230, 252],
|
||||
[195, 134, 163, 230, 161, 255, 231, 252],
|
||||
[196, 134, 163, 230, 161, 255, 231, 252],
|
||||
[197, 135, 163, 231, 162, 255, 231, 252],
|
||||
[198, 135, 163, 231, 162, 255, 231, 252],
|
||||
[199, 136, 164, 232, 163, 255, 232, 252],
|
||||
[200, 136, 164, 232, 164, 255, 232, 252],
|
||||
[201, 137, 165, 233, 165, 255, 233, 252],
|
||||
[201, 137, 165, 233, 165, 255, 233, 252],
|
||||
[202, 138, 166, 233, 166, 255, 233, 252],
|
||||
[203, 138, 166, 233, 166, 255, 233, 252],
|
||||
[204, 139, 166, 234, 167, 255, 234, 252],
|
||||
[205, 139, 166, 234, 167, 255, 234, 252],
|
||||
[206, 140, 167, 235, 168, 255, 235, 252],
|
||||
[206, 140, 167, 235, 168, 255, 235, 252],
|
||||
[207, 141, 168, 236, 169, 255, 235, 252],
|
||||
[208, 141, 168, 236, 170, 255, 235, 252],
|
||||
[209, 142, 169, 237, 171, 255, 236, 252],
|
||||
[209, 143, 169, 237, 171, 255, 236, 252],
|
||||
[210, 144, 169, 237, 172, 255, 236, 252],
|
||||
[211, 144, 169, 237, 172, 255, 236, 252],
|
||||
[212, 145, 170, 238, 173, 255, 237, 252],
|
||||
[213, 145, 170, 238, 173, 255, 237, 252],
|
||||
[214, 146, 171, 239, 174, 255, 237, 253],
|
||||
[214, 146, 171, 239, 174, 255, 237, 253],
|
||||
[215, 147, 172, 240, 175, 255, 238, 253],
|
||||
[215, 147, 172, 240, 175, 255, 238, 253],
|
||||
[216, 148, 173, 240, 176, 255, 238, 253],
|
||||
[217, 148, 173, 240, 176, 255, 238, 253],
|
||||
[218, 149, 173, 241, 177, 255, 239, 253],
|
||||
[218, 149, 173, 241, 178, 255, 239, 253],
|
||||
[219, 150, 174, 241, 179, 255, 239, 253],
|
||||
[219, 151, 174, 241, 179, 255, 239, 253],
|
||||
[220, 152, 175, 242, 180, 255, 240, 253],
|
||||
[221, 152, 175, 242, 180, 255, 240, 253],
|
||||
[222, 153, 176, 242, 181, 255, 240, 253],
|
||||
[222, 153, 176, 242, 181, 255, 240, 253],
|
||||
[223, 154, 177, 243, 182, 255, 240, 253],
|
||||
[223, 154, 177, 243, 182, 255, 240, 253],
|
||||
[224, 155, 178, 244, 183, 255, 241, 253],
|
||||
[224, 155, 178, 244, 183, 255, 241, 253],
|
||||
[225, 156, 178, 244, 184, 255, 241, 253],
|
||||
[225, 157, 178, 244, 184, 255, 241, 253],
|
||||
[226, 158, 179, 244, 185, 255, 242, 253],
|
||||
[227, 158, 179, 244, 185, 255, 242, 253],
|
||||
[228, 159, 180, 245, 186, 255, 242, 253],
|
||||
[228, 159, 180, 245, 186, 255, 242, 253],
|
||||
[229, 160, 181, 245, 187, 255, 242, 253],
|
||||
[229, 160, 181, 245, 187, 255, 242, 253],
|
||||
[230, 161, 182, 246, 188, 255, 243, 253],
|
||||
[230, 162, 182, 246, 188, 255, 243, 253],
|
||||
[231, 163, 183, 246, 189, 255, 243, 253],
|
||||
[231, 163, 183, 246, 189, 255, 243, 253],
|
||||
[232, 164, 184, 247, 190, 255, 243, 253],
|
||||
[232, 164, 184, 247, 190, 255, 243, 253],
|
||||
[233, 165, 185, 247, 191, 255, 244, 253],
|
||||
[233, 165, 185, 247, 191, 255, 244, 253],
|
||||
[234, 166, 185, 247, 192, 255, 244, 253],
|
||||
[234, 167, 185, 247, 192, 255, 244, 253],
|
||||
[235, 168, 186, 248, 193, 255, 244, 253],
|
||||
[235, 168, 186, 248, 193, 255, 244, 253],
|
||||
[236, 169, 187, 248, 194, 255, 244, 253],
|
||||
[236, 169, 187, 248, 194, 255, 244, 253],
|
||||
[236, 170, 188, 248, 195, 255, 245, 253],
|
||||
[236, 170, 188, 248, 195, 255, 245, 253],
|
||||
[237, 171, 189, 249, 196, 255, 245, 254],
|
||||
[237, 172, 189, 249, 196, 255, 245, 254],
|
||||
[238, 173, 190, 249, 197, 255, 245, 254],
|
||||
[238, 173, 190, 249, 197, 255, 245, 254],
|
||||
[239, 174, 191, 249, 198, 255, 245, 254],
|
||||
[239, 174, 191, 249, 198, 255, 245, 254],
|
||||
[240, 175, 192, 249, 199, 255, 246, 254],
|
||||
[240, 176, 192, 249, 199, 255, 246, 254],
|
||||
[240, 177, 193, 250, 200, 255, 246, 254],
|
||||
[240, 177, 193, 250, 200, 255, 246, 254],
|
||||
[241, 178, 194, 250, 201, 255, 246, 254],
|
||||
[241, 178, 194, 250, 201, 255, 246, 254],
|
||||
[242, 179, 195, 250, 202, 255, 246, 254],
|
||||
[242, 180, 195, 250, 202, 255, 246, 254],
|
||||
[242, 181, 196, 250, 203, 255, 247, 254],
|
||||
[242, 181, 196, 250, 203, 255, 247, 254],
|
||||
[243, 182, 197, 251, 204, 255, 247, 254],
|
||||
[243, 183, 197, 251, 204, 255, 247, 254],
|
||||
[244, 184, 198, 251, 205, 255, 247, 254],
|
||||
[244, 184, 198, 251, 205, 255, 247, 254],
|
||||
[244, 185, 199, 251, 206, 255, 247, 254],
|
||||
[244, 185, 199, 251, 206, 255, 247, 254],
|
||||
[245, 186, 200, 251, 207, 255, 247, 254],
|
||||
[245, 187, 200, 251, 207, 255, 247, 254],
|
||||
[246, 188, 201, 252, 207, 255, 248, 254],
|
||||
[246, 188, 201, 252, 207, 255, 248, 254],
|
||||
[246, 189, 202, 252, 208, 255, 248, 254],
|
||||
[246, 190, 202, 252, 208, 255, 248, 254],
|
||||
[247, 191, 203, 252, 209, 255, 248, 254],
|
||||
[247, 191, 203, 252, 209, 255, 248, 254],
|
||||
[247, 192, 204, 252, 210, 255, 248, 254],
|
||||
[247, 193, 204, 252, 210, 255, 248, 254],
|
||||
[248, 194, 205, 252, 211, 255, 248, 254],
|
||||
[248, 194, 205, 252, 211, 255, 248, 254],
|
||||
[248, 195, 206, 252, 212, 255, 249, 254],
|
||||
[248, 196, 206, 252, 212, 255, 249, 254],
|
||||
[249, 197, 207, 253, 213, 255, 249, 254],
|
||||
[249, 197, 207, 253, 213, 255, 249, 254],
|
||||
[249, 198, 208, 253, 214, 255, 249, 254],
|
||||
[249, 199, 209, 253, 214, 255, 249, 254],
|
||||
[250, 200, 210, 253, 215, 255, 249, 254],
|
||||
[250, 200, 210, 253, 215, 255, 249, 254],
|
||||
[250, 201, 211, 253, 215, 255, 249, 254],
|
||||
[250, 202, 211, 253, 215, 255, 249, 254],
|
||||
[250, 203, 212, 253, 216, 255, 249, 254],
|
||||
[250, 203, 212, 253, 216, 255, 249, 254],
|
||||
[251, 204, 213, 253, 217, 255, 250, 254],
|
||||
[251, 205, 213, 253, 217, 255, 250, 254],
|
||||
[251, 206, 214, 254, 218, 255, 250, 254],
|
||||
[251, 206, 215, 254, 218, 255, 250, 254],
|
||||
[252, 207, 216, 254, 219, 255, 250, 254],
|
||||
[252, 208, 216, 254, 219, 255, 250, 254],
|
||||
[252, 209, 217, 254, 220, 255, 250, 254],
|
||||
[252, 210, 217, 254, 220, 255, 250, 254],
|
||||
[252, 211, 218, 254, 221, 255, 250, 254],
|
||||
[252, 212, 218, 254, 221, 255, 250, 254],
|
||||
[253, 213, 219, 254, 222, 255, 250, 254],
|
||||
[253, 213, 220, 254, 222, 255, 250, 254],
|
||||
[253, 214, 221, 254, 223, 255, 250, 254],
|
||||
[253, 215, 221, 254, 223, 255, 250, 254],
|
||||
[253, 216, 222, 254, 224, 255, 251, 254],
|
||||
[253, 217, 223, 254, 224, 255, 251, 254],
|
||||
[253, 218, 224, 254, 225, 255, 251, 254],
|
||||
[253, 219, 224, 254, 225, 255, 251, 254],
|
||||
[254, 220, 225, 254, 225, 255, 251, 254],
|
||||
[254, 221, 226, 254, 225, 255, 251, 254],
|
||||
[254, 222, 227, 255, 226, 255, 251, 254],
|
||||
[254, 223, 227, 255, 226, 255, 251, 254],
|
||||
[254, 224, 228, 255, 227, 255, 251, 254],
|
||||
[254, 225, 229, 255, 227, 255, 251, 254],
|
||||
[254, 226, 230, 255, 228, 255, 251, 254],
|
||||
[254, 227, 230, 255, 229, 255, 251, 254],
|
||||
[255, 228, 231, 255, 230, 255, 251, 254],
|
||||
[255, 229, 232, 255, 230, 255, 251, 254],
|
||||
[255, 230, 233, 255, 231, 255, 252, 254],
|
||||
[255, 231, 234, 255, 231, 255, 252, 254],
|
||||
[255, 232, 235, 255, 232, 255, 252, 254],
|
||||
[255, 233, 236, 255, 232, 255, 252, 254],
|
||||
[255, 235, 237, 255, 233, 255, 252, 254],
|
||||
[255, 236, 238, 255, 234, 255, 252, 254],
|
||||
[255, 238, 240, 255, 235, 255, 252, 255],
|
||||
[255, 239, 241, 255, 235, 255, 252, 254],
|
||||
[255, 241, 243, 255, 236, 255, 252, 254],
|
||||
[255, 243, 245, 255, 237, 255, 252, 254],
|
||||
[255, 246, 247, 255, 239, 255, 253, 255]
|
||||
];
|
||||
|
||||
internal static readonly byte[] DefaultCoefProbs4X4 =
|
||||
[
|
||||
// Y plane
|
||||
// Intra
|
||||
// Band 0
|
||||
195, 29, 183, 84, 49, 136, 8, 42, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// Band 1
|
||||
31, 107, 169, 35, 99, 159, 17, 82, 140, 8, 66, 114, 2, 44, 76, 1, 19, 32,
|
||||
// Band 2
|
||||
40, 132, 201, 29, 114, 187, 13, 91, 157, 7, 75, 127, 3, 58, 95, 1, 28, 47,
|
||||
// Band 3
|
||||
69, 142, 221, 42, 122, 201, 15, 91, 159, 6, 67, 121, 1, 42, 77, 1, 17, 31,
|
||||
// Band 4
|
||||
102, 148, 228, 67, 117, 204, 17, 82, 154, 6, 59, 114, 2, 39, 75, 1, 15, 29,
|
||||
// Band 5
|
||||
156, 57, 233, 119, 57, 212, 58, 48, 163, 29, 40, 124, 12, 30, 81, 3, 12, 31,
|
||||
// Inter
|
||||
// Band 0
|
||||
191, 107, 226, 124, 117, 204, 25, 99, 155, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// Band 1
|
||||
29, 148, 210, 37, 126, 194, 8, 93, 157, 2, 68, 118, 1, 39, 69, 1, 17, 33,
|
||||
// Band 2
|
||||
41, 151, 213, 27, 123, 193, 3, 82, 144, 1, 58, 105, 1, 32, 60, 1, 13, 26,
|
||||
// Band 3
|
||||
59, 159, 220, 23, 126, 198, 4, 88, 151, 1, 66, 114, 1, 38, 71, 1, 18, 34,
|
||||
// Band 4
|
||||
114, 136, 232, 51, 114, 207, 11, 83, 155, 3, 56, 105, 1, 33, 65, 1, 17, 34,
|
||||
// Band 5
|
||||
149, 65, 234, 121, 57, 215, 61, 49, 166, 28, 36, 114, 12, 25, 76, 3, 16, 42,
|
||||
// UV plane
|
||||
// Intra
|
||||
// Band 0
|
||||
214, 49, 220, 132, 63, 188, 42, 65, 137, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// Band 1
|
||||
85, 137, 221, 104, 131, 216, 49, 111, 192, 21, 87, 155, 2, 49, 87, 1, 16, 28,
|
||||
// Band 2
|
||||
89, 163, 230, 90, 137, 220, 29, 100, 183, 10, 70, 135, 2, 42, 81, 1, 17, 33,
|
||||
// Band 3
|
||||
108, 167, 237, 55, 133, 222, 15, 97, 179, 4, 72, 135, 1, 45, 85, 1, 19, 38,
|
||||
// Band 4
|
||||
124, 146, 240, 66, 124, 224, 17, 88, 175, 4, 58, 122, 1, 36, 75, 1, 18, 37,
|
||||
// Band 5
|
||||
141, 79, 241, 126, 70, 227, 66, 58, 182, 30, 44, 136, 12, 34, 96, 2, 20, 47,
|
||||
// Inter
|
||||
// Band 0
|
||||
229, 99, 249, 143, 111, 235, 46, 109, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// Band 1
|
||||
82, 158, 236, 94, 146, 224, 25, 117, 191, 9, 87, 149, 3, 56, 99, 1, 33, 57,
|
||||
// Band 2
|
||||
83, 167, 237, 68, 145, 222, 10, 103, 177, 2, 72, 131, 1, 41, 79, 1, 20, 39,
|
||||
// Band 3
|
||||
99, 167, 239, 47, 141, 224, 10, 104, 178, 2, 73, 133, 1, 44, 85, 1, 22, 47,
|
||||
// Band 4
|
||||
127, 145, 243, 71, 129, 228, 17, 93, 177, 3, 61, 124, 1, 41, 84, 1, 21, 52,
|
||||
// Band 5
|
||||
157, 78, 244, 140, 72, 231, 69, 58, 184, 31, 44, 137, 14, 38, 105, 8, 23, 61
|
||||
];
|
||||
|
||||
internal static readonly byte[] DefaultCoefProbs8X8 =
|
||||
[
|
||||
// Y plane
|
||||
// Intra
|
||||
// Band 0
|
||||
125, 34, 187, 52, 41, 133, 6, 31, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// Band 1
|
||||
37, 109, 153, 51, 102, 147, 23, 87, 128, 8, 67, 101, 1, 41, 63, 1, 19, 29,
|
||||
// Band 2
|
||||
31, 154, 185, 17, 127, 175, 6, 96, 145, 2, 73, 114, 1, 51, 82, 1, 28, 45,
|
||||
// Band 3
|
||||
23, 163, 200, 10, 131, 185, 2, 93, 148, 1, 67, 111, 1, 41, 69, 1, 14, 24,
|
||||
// Band 4
|
||||
29, 176, 217, 12, 145, 201, 3, 101, 156, 1, 69, 111, 1, 39, 63, 1, 14, 23,
|
||||
// Band 5
|
||||
57, 192, 233, 25, 154, 215, 6, 109, 167, 3, 78, 118, 1, 48, 69, 1, 21, 29,
|
||||
// Inter
|
||||
// Band 0
|
||||
202, 105, 245, 108, 106, 216, 18, 90, 144, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// Band 1
|
||||
33, 172, 219, 64, 149, 206, 14, 117, 177, 5, 90, 141, 2, 61, 95, 1, 37, 57,
|
||||
// Band 2
|
||||
33, 179, 220, 11, 140, 198, 1, 89, 148, 1, 60, 104, 1, 33, 57, 1, 12, 21,
|
||||
// Band 3
|
||||
30, 181, 221, 8, 141, 198, 1, 87, 145, 1, 58, 100, 1, 31, 55, 1, 12, 20,
|
||||
// Band 4
|
||||
32, 186, 224, 7, 142, 198, 1, 86, 143, 1, 58, 100, 1, 31, 55, 1, 12, 22,
|
||||
// Band 5
|
||||
57, 192, 227, 20, 143, 204, 3, 96, 154, 1, 68, 112, 1, 42, 69, 1, 19, 32,
|
||||
// UV plane
|
||||
// Intra
|
||||
// Band 0
|
||||
212, 35, 215, 113, 47, 169, 29, 48, 105, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// Band 1
|
||||
74, 129, 203, 106, 120, 203, 49, 107, 178, 19, 84, 144, 4, 50, 84, 1, 15, 25,
|
||||
// Band 2
|
||||
71, 172, 217, 44, 141, 209, 15, 102, 173, 6, 76, 133, 2, 51, 89, 1, 24, 42,
|
||||
// Band 3
|
||||
64, 185, 231, 31, 148, 216, 8, 103, 175, 3, 74, 131, 1, 46, 81, 1, 18, 30,
|
||||
// Band 4
|
||||
65, 196, 235, 25, 157, 221, 5, 105, 174, 1, 67, 120, 1, 38, 69, 1, 15, 30,
|
||||
// Band 5
|
||||
65, 204, 238, 30, 156, 224, 7, 107, 177, 2, 70, 124, 1, 42, 73, 1, 18, 34,
|
||||
// Inter
|
||||
// Band 0
|
||||
225, 86, 251, 144, 104, 235, 42, 99, 181, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// Band 1
|
||||
85, 175, 239, 112, 165, 229, 29, 136, 200, 12, 103, 162, 6, 77, 123, 2, 53, 84,
|
||||
// Band 2
|
||||
75, 183, 239, 30, 155, 221, 3, 106, 171, 1, 74, 128, 1, 44, 76, 1, 17, 28,
|
||||
// Band 3
|
||||
73, 185, 240, 27, 159, 222, 2, 107, 172, 1, 75, 127, 1, 42, 73, 1, 17, 29,
|
||||
// Band 4
|
||||
62, 190, 238, 21, 159, 222, 2, 107, 172, 1, 72, 122, 1, 40, 71, 1, 18, 32,
|
||||
// Band 5
|
||||
61, 199, 240, 27, 161, 226, 4, 113, 180, 1, 76, 129, 1, 46, 80, 1, 23, 41
|
||||
];
|
||||
|
||||
internal static readonly byte[] DefaultCoefProbs16X16 =
|
||||
[
|
||||
// Y plane
|
||||
// Intra
|
||||
// Band 0
|
||||
7, 27, 153, 5, 30, 95, 1, 16, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// Band 1
|
||||
50, 75, 127, 57, 75, 124, 27, 67, 108, 10, 54, 86, 1, 33, 52, 1, 12, 18,
|
||||
// Band 2
|
||||
43, 125, 151, 26, 108, 148, 7, 83, 122, 2, 59, 89, 1, 38, 60, 1, 17, 27,
|
||||
// Band 3
|
||||
23, 144, 163, 13, 112, 154, 2, 75, 117, 1, 50, 81, 1, 31, 51, 1, 14, 23,
|
||||
// Band 4
|
||||
18, 162, 185, 6, 123, 171, 1, 78, 125, 1, 51, 86, 1, 31, 54, 1, 14, 23,
|
||||
// Band 5
|
||||
15, 199, 227, 3, 150, 204, 1, 91, 146, 1, 55, 95, 1, 30, 53, 1, 11, 20,
|
||||
// Inter
|
||||
// Band 0
|
||||
19, 55, 240, 19, 59, 196, 3, 52, 105, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// Band 1
|
||||
41, 166, 207, 104, 153, 199, 31, 123, 181, 14, 101, 152, 5, 72, 106, 1, 36, 52,
|
||||
// Band 2
|
||||
35, 176, 211, 12, 131, 190, 2, 88, 144, 1, 60, 101, 1, 36, 60, 1, 16, 28,
|
||||
// Band 3
|
||||
28, 183, 213, 8, 134, 191, 1, 86, 142, 1, 56, 96, 1, 30, 53, 1, 12, 20,
|
||||
// Band 4
|
||||
20, 190, 215, 4, 135, 192, 1, 84, 139, 1, 53, 91, 1, 28, 49, 1, 11, 20,
|
||||
// Band 5
|
||||
13, 196, 216, 2, 137, 192, 1, 86, 143, 1, 57, 99, 1, 32, 56, 1, 13, 24,
|
||||
// UV plane
|
||||
// Intra
|
||||
// Band 0
|
||||
211, 29, 217, 96, 47, 156, 22, 43, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// Band 1
|
||||
78, 120, 193, 111, 116, 186, 46, 102, 164, 15, 80, 128, 2, 49, 76, 1, 18, 28,
|
||||
// Band 2
|
||||
71, 161, 203, 42, 132, 192, 10, 98, 150, 3, 69, 109, 1, 44, 70, 1, 18, 29,
|
||||
// Band 3
|
||||
57, 186, 211, 30, 140, 196, 4, 93, 146, 1, 62, 102, 1, 38, 65, 1, 16, 27,
|
||||
// Band 4
|
||||
47, 199, 217, 14, 145, 196, 1, 88, 142, 1, 57, 98, 1, 36, 62, 1, 15, 26,
|
||||
// Band 5
|
||||
26, 219, 229, 5, 155, 207, 1, 94, 151, 1, 60, 104, 1, 36, 62, 1, 16, 28,
|
||||
// Inter
|
||||
// Band 0
|
||||
233, 29, 248, 146, 47, 220, 43, 52, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// Band 1
|
||||
100, 163, 232, 179, 161, 222, 63, 142, 204, 37, 113, 174, 26, 89, 137, 18, 68, 97,
|
||||
// Band 2
|
||||
85, 181, 230, 32, 146, 209, 7, 100, 164, 3, 71, 121, 1, 45, 77, 1, 18, 30,
|
||||
// Band 3
|
||||
65, 187, 230, 20, 148, 207, 2, 97, 159, 1, 68, 116, 1, 40, 70, 1, 14, 29,
|
||||
// Band 4
|
||||
40, 194, 227, 8, 147, 204, 1, 94, 155, 1, 65, 112, 1, 39, 66, 1, 14, 26,
|
||||
// Band 5
|
||||
16, 208, 228, 3, 151, 207, 1, 98, 160, 1, 67, 117, 1, 41, 74, 1, 17, 31
|
||||
];
|
||||
|
||||
internal static readonly byte[] DefaultCoefProbs32X32 =
|
||||
[
|
||||
// Y plane
|
||||
// Intra
|
||||
// Band 0
|
||||
17, 38, 140, 7, 34, 80, 1, 17, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// Band 1
|
||||
37, 75, 128, 41, 76, 128, 26, 66, 116, 12, 52, 94, 2, 32, 55, 1, 10, 16,
|
||||
// Band 2
|
||||
50, 127, 154, 37, 109, 152, 16, 82, 121, 5, 59, 85, 1, 35, 54, 1, 13, 20,
|
||||
// Band 3
|
||||
40, 142, 167, 17, 110, 157, 2, 71, 112, 1, 44, 72, 1, 27, 45, 1, 11, 17,
|
||||
// Band 4
|
||||
30, 175, 188, 9, 124, 169, 1, 74, 116, 1, 48, 78, 1, 30, 49, 1, 11, 18,
|
||||
// Band 5
|
||||
10, 222, 223, 2, 150, 194, 1, 83, 128, 1, 48, 79, 1, 27, 45, 1, 11, 17,
|
||||
// Inter
|
||||
// Band 0
|
||||
36, 41, 235, 29, 36, 193, 10, 27, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// Band 1
|
||||
85, 165, 222, 177, 162, 215, 110, 135, 195, 57, 113, 168, 23, 83, 120, 10, 49, 61,
|
||||
// Band 2
|
||||
85, 190, 223, 36, 139, 200, 5, 90, 146, 1, 60, 103, 1, 38, 65, 1, 18, 30,
|
||||
// Band 3
|
||||
72, 202, 223, 23, 141, 199, 2, 86, 140, 1, 56, 97, 1, 36, 61, 1, 16, 27,
|
||||
// Band 4
|
||||
55, 218, 225, 13, 145, 200, 1, 86, 141, 1, 57, 99, 1, 35, 61, 1, 13, 22,
|
||||
// Band 5
|
||||
15, 235, 212, 1, 132, 184, 1, 84, 139, 1, 57, 97, 1, 34, 56, 1, 14, 23,
|
||||
// UV plane
|
||||
// Intra
|
||||
// Band 0
|
||||
181, 21, 201, 61, 37, 123, 10, 38, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// Band 1
|
||||
47, 106, 172, 95, 104, 173, 42, 93, 159, 18, 77, 131, 4, 50, 81, 1, 17, 23,
|
||||
// Band 2
|
||||
62, 147, 199, 44, 130, 189, 28, 102, 154, 18, 75, 115, 2, 44, 65, 1, 12, 19,
|
||||
// Band 3
|
||||
55, 153, 210, 24, 130, 194, 3, 93, 146, 1, 61, 97, 1, 31, 50, 1, 10, 16,
|
||||
// Band 4
|
||||
49, 186, 223, 17, 148, 204, 1, 96, 142, 1, 53, 83, 1, 26, 44, 1, 11, 17,
|
||||
// Band 5
|
||||
13, 217, 212, 2, 136, 180, 1, 78, 124, 1, 50, 83, 1, 29, 49, 1, 14, 23,
|
||||
// Inter
|
||||
// Band 0
|
||||
197, 13, 247, 82, 17, 222, 25, 17, 162, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// Band 1
|
||||
126, 186, 247, 234, 191, 243, 176, 177, 234, 104, 158, 220, 66, 128, 186, 55, 90, 137,
|
||||
// Band 2
|
||||
111, 197, 242, 46, 158, 219, 9, 104, 171, 2, 65, 125, 1, 44, 80, 1, 17, 91,
|
||||
// Band 3
|
||||
104, 208, 245, 39, 168, 224, 3, 109, 162, 1, 79, 124, 1, 50, 102, 1, 43, 102,
|
||||
// Band 4
|
||||
84, 220, 246, 31, 177, 231, 2, 115, 180, 1, 79, 134, 1, 55, 77, 1, 60, 79,
|
||||
// Band 5
|
||||
43, 243, 240, 8, 180, 217, 1, 115, 166, 1, 84, 121, 1, 51, 67, 1, 16, 6
|
||||
];
|
||||
|
||||
public static byte[] GetBandTranslate(int txSize)
|
||||
{
|
||||
return txSize == (int)TxSize.Tx4X4 ? _coefbandTrans4X4 : _coefbandTrans8X8Plus;
|
||||
}
|
||||
|
||||
public static void CopyProbs<T>(ref T dest, ReadOnlySpan<byte> probs) where T : unmanaged
|
||||
{
|
||||
if (Unsafe.SizeOf<T>() != probs.Length)
|
||||
{
|
||||
throw new Exception("size mismatch expected: " + probs.Length + " got: " + Unsafe.SizeOf<T>());
|
||||
}
|
||||
|
||||
probs.CopyTo(MemoryMarshal.Cast<T, byte>(MemoryMarshal.CreateSpan(ref dest, 1)));
|
||||
}
|
||||
|
||||
internal const int CoefCountSat = 24;
|
||||
internal const int CoefMaxUpdateFactor = 112;
|
||||
internal const int CoefCountSatKey = 24;
|
||||
internal const int CoefMaxUpdateFactorKey = 112;
|
||||
internal const int CoefCountSatAfterKey = 24;
|
||||
internal const int CoefMaxUpdateFactorAfterKey = 128;
|
||||
}
|
||||
}
|
390
src/Ryujinx.Graphics.Nvdec.Vp9/EntropyMode.cs
Normal file
390
src/Ryujinx.Graphics.Nvdec.Vp9/EntropyMode.cs
Normal file
@ -0,0 +1,390 @@
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Graphics.Nvdec.Vp9.Common;
|
||||
using Ryujinx.Graphics.Nvdec.Vp9.Types;
|
||||
using Ryujinx.Graphics.Video;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
{
|
||||
internal class EntropyMode
|
||||
{
|
||||
public const int BlockSizeGroups = 4;
|
||||
|
||||
public const int TxSizeContexts = 2;
|
||||
|
||||
public static readonly byte[][][] KfYModeProb =
|
||||
[
|
||||
[
|
||||
// above = dc
|
||||
[137, 30, 42, 148, 151, 207, 70, 52, 91], // left = dc
|
||||
[92, 45, 102, 136, 116, 180, 74, 90, 100], // left = v
|
||||
[73, 32, 19, 187, 222, 215, 46, 34, 100], // left = h
|
||||
[91, 30, 32, 116, 121, 186, 93, 86, 94], // left = d45
|
||||
[72, 35, 36, 149, 68, 206, 68, 63, 105], // left = d135
|
||||
[73, 31, 28, 138, 57, 124, 55, 122, 151], // left = d117
|
||||
[67, 23, 21, 140, 126, 197, 40, 37, 171], // left = d153
|
||||
[86, 27, 28, 128, 154, 212, 45, 43, 53], // left = d207
|
||||
[74, 32, 27, 107, 86, 160, 63, 134, 102], // left = d63
|
||||
[59, 67, 44, 140, 161, 202, 78, 67, 119] // left = tm
|
||||
],
|
||||
[
|
||||
// above = v
|
||||
[63, 36, 126, 146, 123, 158, 60, 90, 96], // left = dc
|
||||
[43, 46, 168, 134, 107, 128, 69, 142, 92], // left = v
|
||||
[44, 29, 68, 159, 201, 177, 50, 57, 77], // left = h
|
||||
[58, 38, 76, 114, 97, 172, 78, 133, 92], // left = d45
|
||||
[46, 41, 76, 140, 63, 184, 69, 112, 57], // left = d135
|
||||
[38, 32, 85, 140, 46, 112, 54, 151, 133], // left = d117
|
||||
[39, 27, 61, 131, 110, 175, 44, 75, 136], // left = d153
|
||||
[52, 30, 74, 113, 130, 175, 51, 64, 58], // left = d207
|
||||
[47, 35, 80, 100, 74, 143, 64, 163, 74], // left = d63
|
||||
[36, 61, 116, 114, 128, 162, 80, 125, 82] // left = tm
|
||||
],
|
||||
[
|
||||
// above = h
|
||||
[82, 26, 26, 171, 208, 204, 44, 32, 105], // left = dc
|
||||
[55, 44, 68, 166, 179, 192, 57, 57, 108], // left = v
|
||||
[42, 26, 11, 199, 241, 228, 23, 15, 85], // left = h
|
||||
[68, 42, 19, 131, 160, 199, 55, 52, 83], // left = d45
|
||||
[58, 50, 25, 139, 115, 232, 39, 52, 118], // left = d135
|
||||
[50, 35, 33, 153, 104, 162, 64, 59, 131], // left = d117
|
||||
[44, 24, 16, 150, 177, 202, 33, 19, 156], // left = d153
|
||||
[55, 27, 12, 153, 203, 218, 26, 27, 49], // left = d207
|
||||
[53, 49, 21, 110, 116, 168, 59, 80, 76], // left = d63
|
||||
[38, 72, 19, 168, 203, 212, 50, 50, 107] // left = tm
|
||||
],
|
||||
[
|
||||
// above = d45
|
||||
[103, 26, 36, 129, 132, 201, 83, 80, 93], // left = dc
|
||||
[59, 38, 83, 112, 103, 162, 98, 136, 90], // left = v
|
||||
[62, 30, 23, 158, 200, 207, 59, 57, 50], // left = h
|
||||
[67, 30, 29, 84, 86, 191, 102, 91, 59], // left = d45
|
||||
[60, 32, 33, 112, 71, 220, 64, 89, 104], // left = d135
|
||||
[53, 26, 34, 130, 56, 149, 84, 120, 103], // left = d117
|
||||
[53, 21, 23, 133, 109, 210, 56, 77, 172], // left = d153
|
||||
[77, 19, 29, 112, 142, 228, 55, 66, 36], // left = d207
|
||||
[61, 29, 29, 93, 97, 165, 83, 175, 162], // left = d63
|
||||
[47, 47, 43, 114, 137, 181, 100, 99, 95] // left = tm
|
||||
],
|
||||
[
|
||||
// above = d135
|
||||
[69, 23, 29, 128, 83, 199, 46, 44, 101], // left = dc
|
||||
[53, 40, 55, 139, 69, 183, 61, 80, 110], // left = v
|
||||
[40, 29, 19, 161, 180, 207, 43, 24, 91], // left = h
|
||||
[60, 34, 19, 105, 61, 198, 53, 64, 89], // left = d45
|
||||
[52, 31, 22, 158, 40, 209, 58, 62, 89], // left = d135
|
||||
[44, 31, 29, 147, 46, 158, 56, 102, 198], // left = d117
|
||||
[35, 19, 12, 135, 87, 209, 41, 45, 167], // left = d153
|
||||
[55, 25, 21, 118, 95, 215, 38, 39, 66], // left = d207
|
||||
[51, 38, 25, 113, 58, 164, 70, 93, 97], // left = d63
|
||||
[47, 54, 34, 146, 108, 203, 72, 103, 151] // left = tm
|
||||
],
|
||||
[
|
||||
// above = d117
|
||||
[64, 19, 37, 156, 66, 138, 49, 95, 133], // left = dc
|
||||
[46, 27, 80, 150, 55, 124, 55, 121, 135], // left = v
|
||||
[36, 23, 27, 165, 149, 166, 54, 64, 118], // left = h
|
||||
[53, 21, 36, 131, 63, 163, 60, 109, 81], // left = d45
|
||||
[40, 26, 35, 154, 40, 185, 51, 97, 123], // left = d135
|
||||
[35, 19, 34, 179, 19, 97, 48, 129, 124], // left = d117
|
||||
[36, 20, 26, 136, 62, 164, 33, 77, 154], // left = d153
|
||||
[45, 18, 32, 130, 90, 157, 40, 79, 91], // left = d207
|
||||
[45, 26, 28, 129, 45, 129, 49, 147, 123], // left = d63
|
||||
[38, 44, 51, 136, 74, 162, 57, 97, 121] // left = tm
|
||||
],
|
||||
[
|
||||
// above = d153
|
||||
[75, 17, 22, 136, 138, 185, 32, 34, 166], // left = dc
|
||||
[56, 39, 58, 133, 117, 173, 48, 53, 187], // left = v
|
||||
[35, 21, 12, 161, 212, 207, 20, 23, 145], // left = h
|
||||
[56, 29, 19, 117, 109, 181, 55, 68, 112], // left = d45
|
||||
[47, 29, 17, 153, 64, 220, 59, 51, 114], // left = d135
|
||||
[46, 16, 24, 136, 76, 147, 41, 64, 172], // left = d117
|
||||
[34, 17, 11, 108, 152, 187, 13, 15, 209], // left = d153
|
||||
[51, 24, 14, 115, 133, 209, 32, 26, 104], // left = d207
|
||||
[55, 30, 18, 122, 79, 179, 44, 88, 116], // left = d63
|
||||
[37, 49, 25, 129, 168, 164, 41, 54, 148] // left = tm
|
||||
],
|
||||
[
|
||||
// above = d207
|
||||
[82, 22, 32, 127, 143, 213, 39, 41, 70], // left = dc
|
||||
[62, 44, 61, 123, 105, 189, 48, 57, 64], // left = v
|
||||
[47, 25, 17, 175, 222, 220, 24, 30, 86], // left = h
|
||||
[68, 36, 17, 106, 102, 206, 59, 74, 74], // left = d45
|
||||
[57, 39, 23, 151, 68, 216, 55, 63, 58], // left = d135
|
||||
[49, 30, 35, 141, 70, 168, 82, 40, 115], // left = d117
|
||||
[51, 25, 15, 136, 129, 202, 38, 35, 139], // left = d153
|
||||
[68, 26, 16, 111, 141, 215, 29, 28, 28], // left = d207
|
||||
[59, 39, 19, 114, 75, 180, 77, 104, 42], // left = d63
|
||||
[40, 61, 26, 126, 152, 206, 61, 59, 93] // left = tm
|
||||
],
|
||||
[
|
||||
// above = d63
|
||||
[78, 23, 39, 111, 117, 170, 74, 124, 94], // left = dc
|
||||
[48, 34, 86, 101, 92, 146, 78, 179, 134], // left = v
|
||||
[47, 22, 24, 138, 187, 178, 68, 69, 59], // left = h
|
||||
[56, 25, 33, 105, 112, 187, 95, 177, 129], // left = d45
|
||||
[48, 31, 27, 114, 63, 183, 82, 116, 56], // left = d135
|
||||
[43, 28, 37, 121, 63, 123, 61, 192, 169], // left = d117
|
||||
[42, 17, 24, 109, 97, 177, 56, 76, 122], // left = d153
|
||||
[58, 18, 28, 105, 139, 182, 70, 92, 63], // left = d207
|
||||
[46, 23, 32, 74, 86, 150, 67, 183, 88], // left = d63
|
||||
[36, 38, 48, 92, 122, 165, 88, 137, 91] // left = tm
|
||||
],
|
||||
[
|
||||
// above = tm
|
||||
[65, 70, 60, 155, 159, 199, 61, 60, 81], // left = dc
|
||||
[44, 78, 115, 132, 119, 173, 71, 112, 93], // left = v
|
||||
[39, 38, 21, 184, 227, 206, 42, 32, 64], // left = h
|
||||
[58, 47, 36, 124, 137, 193, 80, 82, 78], // left = d45
|
||||
[49, 50, 35, 144, 95, 205, 63, 78, 59], // left = d135
|
||||
[41, 53, 52, 148, 71, 142, 65, 128, 51], // left = d117
|
||||
[40, 36, 28, 143, 143, 202, 40, 55, 137], // left = d153
|
||||
[52, 34, 29, 129, 183, 227, 42, 35, 43], // left = d207
|
||||
[42, 44, 44, 104, 105, 164, 64, 130, 80], // left = d63
|
||||
[43, 81, 53, 140, 169, 204, 68, 84, 72] // left = tm
|
||||
]
|
||||
];
|
||||
|
||||
public static readonly byte[][] KfUvModeProb =
|
||||
[
|
||||
[144, 11, 54, 157, 195, 130, 46, 58, 108], // y = dc
|
||||
[118, 15, 123, 148, 131, 101, 44, 93, 131], // y = v
|
||||
[113, 12, 23, 188, 226, 142, 26, 32, 125], // y = h
|
||||
[120, 11, 50, 123, 163, 135, 64, 77, 103], // y = d45
|
||||
[113, 9, 36, 155, 111, 157, 32, 44, 161], // y = d135
|
||||
[116, 9, 55, 176, 76, 96, 37, 61, 149], // y = d117
|
||||
[115, 9, 28, 141, 161, 167, 21, 25, 193], // y = d153
|
||||
[120, 12, 32, 145, 195, 142, 32, 38, 86], // y = d207
|
||||
[116, 12, 64, 120, 140, 125, 49, 115, 121], // y = d63
|
||||
[102, 19, 66, 162, 182, 122, 35, 59, 128] // y = tm
|
||||
];
|
||||
|
||||
private static readonly byte[] _defaultIfYProbs =
|
||||
[
|
||||
65, 32, 18, 144, 162, 194, 41, 51, 98, // block_size < 8x8
|
||||
132, 68, 18, 165, 217, 196, 45, 40, 78, // block_size < 16x16
|
||||
173, 80, 19, 176, 240, 193, 64, 35, 46, // block_size < 32x32
|
||||
221, 135, 38, 194, 248, 121, 96, 85, 29 // block_size >= 32x32
|
||||
];
|
||||
|
||||
private static readonly byte[] _defaultIfUvProbs =
|
||||
[
|
||||
120, 7, 76, 176, 208, 126, 28, 54, 103, // y = dc
|
||||
48, 12, 154, 155, 139, 90, 34, 117, 119, // y = v
|
||||
67, 6, 25, 204, 243, 158, 13, 21, 96, // y = h
|
||||
97, 5, 44, 131, 176, 139, 48, 68, 97, // y = d45
|
||||
83, 5, 42, 156, 111, 152, 26, 49, 152, // y = d135
|
||||
80, 5, 58, 178, 74, 83, 33, 62, 145, // y = d117
|
||||
86, 5, 32, 154, 192, 168, 14, 22, 163, // y = d153
|
||||
85, 5, 32, 156, 216, 148, 19, 29, 73, // y = d207
|
||||
77, 7, 64, 116, 132, 122, 37, 126, 120, // y = d63
|
||||
101, 21, 107, 181, 192, 103, 19, 67, 125 // y = tm
|
||||
];
|
||||
|
||||
private static readonly byte[] _defaultPartitionProbs =
|
||||
[
|
||||
// 8x8 . 4x4
|
||||
199, 122, 141, // a/l both not split
|
||||
147, 63, 159, // a split, l not split
|
||||
148, 133, 118, // l split, a not split
|
||||
121, 104, 114, // a/l both split
|
||||
// 16x16 . 8x8
|
||||
174, 73, 87, // a/l both not split
|
||||
92, 41, 83, // a split, l not split
|
||||
82, 99, 50, // l split, a not split
|
||||
53, 39, 39, // a/l both split
|
||||
// 32x32 . 16x16
|
||||
177, 58, 59, // a/l both not split
|
||||
68, 26, 63, // a split, l not split
|
||||
52, 79, 25, // l split, a not split
|
||||
17, 14, 12, // a/l both split
|
||||
// 64x64 . 32x32
|
||||
222, 34, 30, // a/l both not split
|
||||
72, 16, 44, // a split, l not split
|
||||
58, 32, 12, // l split, a not split
|
||||
10, 7, 6 // a/l both split
|
||||
];
|
||||
|
||||
private static readonly byte[] _defaultInterModeProbs =
|
||||
[
|
||||
2, 173, 34, // 0 = both zero mv
|
||||
7, 145, 85, // 1 = one zero mv + one a predicted mv
|
||||
7, 166, 63, // 2 = two predicted mvs
|
||||
7, 94, 66, // 3 = one predicted/zero and one new mv
|
||||
8, 64, 46, // 4 = two new mvs
|
||||
17, 81, 31, // 5 = one intra neighbour + x
|
||||
25, 29, 30 // 6 = two intra neighbours
|
||||
];
|
||||
|
||||
/* Array indices are identical to previously-existing INTRAMODECONTEXTNODES. */
|
||||
public static readonly sbyte[] IntraModeTree =
|
||||
[
|
||||
-(int)PredictionMode.DcPred, 2, /* 0 = DC_NODE */ -(int)PredictionMode.TmPred, 4, /* 1 = TM_NODE */
|
||||
-(int)PredictionMode.VPred, 6, /* 2 = V_NODE */ 8, 12, /* 3 = COM_NODE */ -(int)PredictionMode.HPred,
|
||||
10, /* 4 = H_NODE */ -(int)PredictionMode.D135Pred, -(int)PredictionMode.D117Pred, /* 5 = D135_NODE */
|
||||
-(int)PredictionMode.D45Pred, 14, /* 6 = D45_NODE */ -(int)PredictionMode.D63Pred,
|
||||
16, /* 7 = D63_NODE */ -(int)PredictionMode.D153Pred, -(int)PredictionMode.D207Pred /* 8 = D153_NODE */
|
||||
];
|
||||
|
||||
public static readonly sbyte[] InterModeTree =
|
||||
[
|
||||
-((int)PredictionMode.ZeroMv - (int)PredictionMode.NearestMv), 2,
|
||||
-((int)PredictionMode.NearestMv - (int)PredictionMode.NearestMv), 4,
|
||||
-((int)PredictionMode.NearMv - (int)PredictionMode.NearestMv),
|
||||
-((int)PredictionMode.NewMv - (int)PredictionMode.NearestMv)
|
||||
];
|
||||
|
||||
public static readonly sbyte[] PartitionTree =
|
||||
[
|
||||
-(sbyte)PartitionType.PartitionNone, 2, -(sbyte)PartitionType.PartitionHorz, 4,
|
||||
-(sbyte)PartitionType.PartitionVert, -(sbyte)PartitionType.PartitionSplit
|
||||
];
|
||||
|
||||
public static readonly sbyte[] SwitchableInterpTree =
|
||||
[
|
||||
-Constants.EightTap, 2, -Constants.EightTapSmooth, -Constants.EightTapSharp
|
||||
];
|
||||
|
||||
private static readonly byte[] _defaultIntraInterP = [9, 102, 187, 225];
|
||||
private static readonly byte[] _defaultCompInterP = [239, 183, 119, 96, 41];
|
||||
private static readonly byte[] _defaultCompRefP = [50, 126, 123, 221, 226];
|
||||
private static readonly byte[] _defaultSingleRefP = [33, 16, 77, 74, 142, 142, 172, 170, 238, 247];
|
||||
private static readonly byte[] _defaultTxProbs = [3, 136, 37, 5, 52, 13, 20, 152, 15, 101, 100, 66];
|
||||
|
||||
static EntropyMode()
|
||||
{
|
||||
byte[][] kfPartitionProbs =
|
||||
[
|
||||
// 8x8 . 4x4
|
||||
[158, 97, 94], // a/l both not split
|
||||
[93, 24, 99], // a split, l not split
|
||||
[85, 119, 44], // l split, a not split
|
||||
[62, 59, 67], // a/l both split
|
||||
|
||||
// 16x16 . 8x8
|
||||
[149, 53, 53], // a/l both not split
|
||||
[94, 20, 48], // a split, l not split
|
||||
[83, 53, 24], // l split, a not split
|
||||
[52, 18, 18], // a/l both split
|
||||
|
||||
// 32x32 . 16x16
|
||||
[150, 40, 39], // a/l both not split
|
||||
[78, 12, 26], // a split, l not split
|
||||
[67, 33, 11], // l split, a not split
|
||||
[24, 7, 5], // a/l both split
|
||||
|
||||
// 64x64 . 32x32
|
||||
[174, 35, 49], // a/l both not split
|
||||
[68, 11, 27], // a split, l not split
|
||||
[57, 15, 9], // l split, a not split
|
||||
[12, 3, 3] // a/l both split
|
||||
];
|
||||
}
|
||||
|
||||
private static readonly byte[] _defaultSkipProbs = [192, 128, 64];
|
||||
|
||||
private static readonly byte[] _defaultSwitchableInterpProb = [235, 162, 36, 255, 34, 3, 149, 144];
|
||||
|
||||
private static void InitModeProbs(ref Vp9EntropyProbs fc)
|
||||
{
|
||||
Entropy.CopyProbs(ref fc.UvModeProb, _defaultIfUvProbs);
|
||||
Entropy.CopyProbs(ref fc.YModeProb, _defaultIfYProbs);
|
||||
Entropy.CopyProbs(ref fc.SwitchableInterpProb, _defaultSwitchableInterpProb);
|
||||
Entropy.CopyProbs(ref fc.PartitionProb, _defaultPartitionProbs);
|
||||
Entropy.CopyProbs(ref fc.IntraInterProb, _defaultIntraInterP);
|
||||
Entropy.CopyProbs(ref fc.CompInterProb, _defaultCompInterP);
|
||||
Entropy.CopyProbs(ref fc.CompRefProb, _defaultCompRefP);
|
||||
Entropy.CopyProbs(ref fc.SingleRefProb, _defaultSingleRefP);
|
||||
Entropy.CopyProbs(ref fc.Tx32x32Prob, _defaultTxProbs.AsSpan().Slice(0, 6));
|
||||
Entropy.CopyProbs(ref fc.Tx16x16Prob, _defaultTxProbs.AsSpan().Slice(6, 4));
|
||||
Entropy.CopyProbs(ref fc.Tx8x8Prob, _defaultTxProbs.AsSpan().Slice(10, 2));
|
||||
Entropy.CopyProbs(ref fc.SkipProb, _defaultSkipProbs);
|
||||
Entropy.CopyProbs(ref fc.InterModeProb, _defaultInterModeProbs);
|
||||
}
|
||||
|
||||
internal static void TxCountsToBranchCounts32X32(ReadOnlySpan<uint> txCount32X32P,
|
||||
ref Array3<Array2<uint>> ct32X32P)
|
||||
{
|
||||
ct32X32P[0][0] = txCount32X32P[(int)TxSize.Tx4X4];
|
||||
ct32X32P[0][1] = txCount32X32P[(int)TxSize.Tx8X8] + txCount32X32P[(int)TxSize.Tx16X16] +
|
||||
txCount32X32P[(int)TxSize.Tx32X32];
|
||||
ct32X32P[1][0] = txCount32X32P[(int)TxSize.Tx8X8];
|
||||
ct32X32P[1][1] = txCount32X32P[(int)TxSize.Tx16X16] + txCount32X32P[(int)TxSize.Tx32X32];
|
||||
ct32X32P[2][0] = txCount32X32P[(int)TxSize.Tx16X16];
|
||||
ct32X32P[2][1] = txCount32X32P[(int)TxSize.Tx32X32];
|
||||
}
|
||||
|
||||
internal static void TxCountsToBranchCounts16X16(ReadOnlySpan<uint> txCount16X16P,
|
||||
ref Array2<Array2<uint>> ct16X16P)
|
||||
{
|
||||
ct16X16P[0][0] = txCount16X16P[(int)TxSize.Tx4X4];
|
||||
ct16X16P[0][1] = txCount16X16P[(int)TxSize.Tx8X8] + txCount16X16P[(int)TxSize.Tx16X16];
|
||||
ct16X16P[1][0] = txCount16X16P[(int)TxSize.Tx8X8];
|
||||
ct16X16P[1][1] = txCount16X16P[(int)TxSize.Tx16X16];
|
||||
}
|
||||
|
||||
internal static void TxCountsToBranchCounts8X8(ReadOnlySpan<uint> txCount8X8P,
|
||||
ref Array1<Array2<uint>> ct8X8P)
|
||||
{
|
||||
ct8X8P[0][0] = txCount8X8P[(int)TxSize.Tx4X4];
|
||||
ct8X8P[0][1] = txCount8X8P[(int)TxSize.Tx8X8];
|
||||
}
|
||||
|
||||
public static unsafe void SetupPastIndependence(ref Vp9Common cm)
|
||||
{
|
||||
// Reset the segment feature data to the default stats:
|
||||
// Features disabled, 0, with delta coding (Default state).
|
||||
ref Types.LoopFilter lf = ref cm.Lf;
|
||||
|
||||
cm.Seg.ClearAllSegFeatures();
|
||||
cm.Seg.AbsDelta = Segmentation.SegmentDeltadata;
|
||||
|
||||
if (!cm.LastFrameSegMap.IsNull)
|
||||
{
|
||||
MemoryUtil.Fill(cm.LastFrameSegMap.ToPointer(), (byte)0, cm.MiRows * cm.MiCols);
|
||||
}
|
||||
|
||||
if (!cm.CurrentFrameSegMap.IsNull)
|
||||
{
|
||||
MemoryUtil.Fill(cm.CurrentFrameSegMap.ToPointer(), (byte)0, cm.MiRows * cm.MiCols);
|
||||
}
|
||||
|
||||
// Reset the mode ref deltas for loop filter
|
||||
lf.LastRefDeltas = new Array4<sbyte>();
|
||||
lf.LastModeDeltas = new Array2<sbyte>();
|
||||
lf.SetDefaultLfDeltas();
|
||||
|
||||
// To force update of the sharpness
|
||||
lf.LastSharpnessLevel = -1;
|
||||
|
||||
cm.DefaultCoefProbs();
|
||||
InitModeProbs(ref cm.Fc.Value);
|
||||
cm.InitMvProbs();
|
||||
|
||||
if (cm.FrameType == FrameType.KeyFrame || cm.ErrorResilientMode != 0 || cm.ResetFrameContext == 3)
|
||||
{
|
||||
// Reset all frame contexts.
|
||||
for (int i = 0; i < Constants.FrameContexts; ++i)
|
||||
{
|
||||
cm.FrameContexts[i] = cm.Fc.Value;
|
||||
}
|
||||
}
|
||||
else if (cm.ResetFrameContext == 2)
|
||||
{
|
||||
// Reset only the frame context specified in the frame header.
|
||||
cm.FrameContexts[(int)cm.FrameContextIdx] = cm.Fc.Value;
|
||||
}
|
||||
|
||||
// prev_mip will only be allocated in encoder.
|
||||
if (cm.FrameIsIntraOnly() && !cm.PrevMip.IsNull)
|
||||
{
|
||||
cm.PrevMi.Value = new ModeInfo();
|
||||
}
|
||||
|
||||
cm.RefFrameSignBias = new Array4<sbyte>();
|
||||
|
||||
cm.FrameContextIdx = 0;
|
||||
}
|
||||
}
|
||||
}
|
165
src/Ryujinx.Graphics.Nvdec.Vp9/EntropyMv.cs
Normal file
165
src/Ryujinx.Graphics.Nvdec.Vp9/EntropyMv.cs
Normal file
@ -0,0 +1,165 @@
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Graphics.Nvdec.Vp9.Types;
|
||||
using Ryujinx.Graphics.Video;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
{
|
||||
internal static class EntropyMv
|
||||
{
|
||||
public const int UpdateProb = 252;
|
||||
|
||||
/* Symbols for coding which components are zero jointly */
|
||||
public const int Joints = 4;
|
||||
|
||||
|
||||
public static readonly sbyte[] JointTree =
|
||||
[
|
||||
-(sbyte)MvJointType.Zero, 2, -(sbyte)MvJointType.Hnzvz, 4,
|
||||
-(sbyte)MvJointType.Hzvnz, -(sbyte)MvJointType.Hnzvnz
|
||||
];
|
||||
|
||||
public static readonly sbyte[] ClassTree =
|
||||
[
|
||||
-(sbyte)MvClassType.Class0, 2, -(sbyte)MvClassType.Class1, 4, 6, 8, -(sbyte)MvClassType.Class2,
|
||||
-(sbyte)MvClassType.Class3, 10, 12, -(sbyte)MvClassType.Class4, -(sbyte)MvClassType.Class5,
|
||||
-(sbyte)MvClassType.Class6, 14, 16, 18, -(sbyte)MvClassType.Class7, -(sbyte)MvClassType.Class8,
|
||||
-(sbyte)MvClassType.Class9, -(sbyte)MvClassType.Class10
|
||||
];
|
||||
|
||||
public static readonly sbyte[] Class0Tree = [-0, -1];
|
||||
|
||||
public static readonly sbyte[] FpTree = [-0, 2, -1, 4, -2, -3];
|
||||
|
||||
private static bool JointVertical(MvJointType type)
|
||||
{
|
||||
return type == MvJointType.Hzvnz || type == MvJointType.Hnzvnz;
|
||||
}
|
||||
|
||||
private static bool JointHorizontal(MvJointType type)
|
||||
{
|
||||
return type == MvJointType.Hnzvz || type == MvJointType.Hnzvnz;
|
||||
}
|
||||
|
||||
private static readonly byte[] _logInBase2 =
|
||||
[
|
||||
0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 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, 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, 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, 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, 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, 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
|
||||
];
|
||||
|
||||
private static int ClassBase(MvClassType c)
|
||||
{
|
||||
return c != 0 ? Class0Size << ((int)c + 2) : 0;
|
||||
}
|
||||
|
||||
private static MvClassType GetClass(int z, Ptr<int> offset)
|
||||
{
|
||||
MvClassType c = z >= Class0Size * 4096
|
||||
? MvClassType.Class10
|
||||
: (MvClassType)_logInBase2[z >> 3];
|
||||
if (!offset.IsNull)
|
||||
{
|
||||
offset.Value = z - ClassBase(c);
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
private static void IncComponent(int v, ref Vp9BackwardUpdates compCounts, int compIndex, int incr, int usehp)
|
||||
{
|
||||
int o = 0;
|
||||
Debug.Assert(v != 0); /* should not be zero */
|
||||
int s = v < 0 ? 1 : 0;
|
||||
compCounts.Sign[compIndex][s] += (uint)incr;
|
||||
int z = (s != 0 ? -v : v) - 1 /* magnitude - 1 */;
|
||||
|
||||
int c = (int)GetClass(z, new Ptr<int>(ref o));
|
||||
compCounts.Classes[compIndex][c] += (uint)incr;
|
||||
|
||||
int d = o >> 3 /* int mv data */;
|
||||
int f = (o >> 1) & 3 /* fractional pel mv data */;
|
||||
int e = o & 1 /* high precision mv data */;
|
||||
|
||||
if (c == (int)MvClassType.Class0)
|
||||
{
|
||||
compCounts.Class0[compIndex][d] += (uint)incr;
|
||||
compCounts.Class0Fp[compIndex][d][f] += (uint)incr;
|
||||
compCounts.Class0Hp[compIndex][e] += (uint)(usehp * incr);
|
||||
}
|
||||
else
|
||||
{
|
||||
int b = c + Class0Bits - 1; // number of bits
|
||||
for (int i = 0; i < b; ++i)
|
||||
{
|
||||
compCounts.Bits[compIndex][i][(d >> i) & 1] += (uint)incr;
|
||||
}
|
||||
|
||||
compCounts.Fp[compIndex][f] += (uint)incr;
|
||||
compCounts.Hp[compIndex][e] += (uint)(usehp * incr);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Inc(ref Mv mv, Ptr<Vp9BackwardUpdates> counts)
|
||||
{
|
||||
if (!counts.IsNull)
|
||||
{
|
||||
MvJointType j = mv.GetJoint();
|
||||
++counts.Value.Joints[(int)j];
|
||||
|
||||
if (JointVertical(j))
|
||||
{
|
||||
IncComponent(mv.Row, ref counts.Value, 0, 1, 1);
|
||||
}
|
||||
|
||||
if (JointHorizontal(j))
|
||||
{
|
||||
IncComponent(mv.Col, ref counts.Value, 1, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Symbols for coding magnitude class of nonzero components */
|
||||
public const int Classes = 11;
|
||||
|
||||
public const int Class0Bits = 1; /* bits at integer precision for class 0 */
|
||||
public const int Class0Size = 1 << Class0Bits;
|
||||
public const int OffsetBits = Classes + Class0Bits - 2;
|
||||
public const int FpSize = 4;
|
||||
|
||||
public const int MaxBits = Classes + Class0Bits + 2;
|
||||
public const int Max = (1 << MaxBits) - 1;
|
||||
public const int Vals = (Max << 1) + 1;
|
||||
|
||||
public const int InUseBits = 14;
|
||||
public const int Upp = (1 << InUseBits) - 1;
|
||||
public const int Low = -(1 << InUseBits);
|
||||
}
|
||||
}
|
78
src/Ryujinx.Graphics.Nvdec.Vp9/FrameBuffers.cs
Normal file
78
src/Ryujinx.Graphics.Nvdec.Vp9/FrameBuffers.cs
Normal file
@ -0,0 +1,78 @@
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Graphics.Nvdec.Vp9.Common;
|
||||
using Ryujinx.Graphics.Nvdec.Vp9.Types;
|
||||
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
{
|
||||
internal struct InternalFrameBuffer
|
||||
{
|
||||
public ArrayPtr<byte> Data;
|
||||
public bool InUse;
|
||||
}
|
||||
|
||||
internal struct InternalFrameBufferList
|
||||
{
|
||||
public ArrayPtr<InternalFrameBuffer> IntFb;
|
||||
}
|
||||
|
||||
internal static class FrameBuffers
|
||||
{
|
||||
public static int GetFrameBuffer(MemoryAllocator allocator, Ptr<InternalFrameBufferList> cbPriv, ulong minSize,
|
||||
ref VpxCodecFrameBuffer fb)
|
||||
{
|
||||
int i;
|
||||
if (cbPriv.IsNull)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Find a free frame buffer.
|
||||
for (i = 0; i < cbPriv.Value.IntFb.Length; ++i)
|
||||
{
|
||||
if (!cbPriv.Value.IntFb[i].InUse)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == cbPriv.Value.IntFb.Length)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((ulong)cbPriv.Value.IntFb[i].Data.Length < minSize)
|
||||
{
|
||||
if (!cbPriv.Value.IntFb[i].Data.IsNull)
|
||||
{
|
||||
allocator.Free(cbPriv.Value.IntFb[i].Data);
|
||||
}
|
||||
|
||||
// The data must be zeroed to fix a valgrind error from the C loop filter
|
||||
// due to access uninitialized memory in frame border. It could be
|
||||
// skipped if border were totally removed.
|
||||
cbPriv.Value.IntFb[i].Data = allocator.Allocate<byte>((int)minSize);
|
||||
if (cbPriv.Value.IntFb[i].Data.IsNull)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
fb.Data = cbPriv.Value.IntFb[i].Data;
|
||||
cbPriv.Value.IntFb[i].InUse = true;
|
||||
|
||||
// Set the frame buffer's private data to point at the internal frame buffer.
|
||||
fb.Priv = new Ptr<InternalFrameBuffer>(ref cbPriv.Value.IntFb[i]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static int ReleaseFrameBuffer(Ptr<InternalFrameBufferList> cbPriv, ref VpxCodecFrameBuffer fb)
|
||||
{
|
||||
if (!fb.Priv.IsNull)
|
||||
{
|
||||
fb.Priv.Value.InUse = false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
@ -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.InvTxfm;
|
||||
@ -8,11 +8,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
internal static class Idct
|
||||
{
|
||||
private delegate void Transform1D(ReadOnlySpan<int> input, Span<int> output);
|
||||
|
||||
private delegate void HighbdTransform1D(ReadOnlySpan<int> input, Span<int> output, int bd);
|
||||
|
||||
private struct Transform2D
|
||||
{
|
||||
public Transform1D Cols, Rows; // Vertical and horizontal
|
||||
public readonly Transform1D Cols; // Vertical and horizontal
|
||||
public readonly Transform1D Rows; // Vertical and horizontal
|
||||
|
||||
public Transform2D(Transform1D cols, Transform1D rows)
|
||||
{
|
||||
@ -23,7 +25,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
|
||||
private struct HighbdTransform2D
|
||||
{
|
||||
public HighbdTransform1D Cols, Rows; // Vertical and horizontal
|
||||
public readonly HighbdTransform1D Cols; // Vertical and horizontal
|
||||
public readonly HighbdTransform1D Rows; // Vertical and horizontal
|
||||
|
||||
public HighbdTransform2D(HighbdTransform1D cols, HighbdTransform1D rows)
|
||||
{
|
||||
@ -32,55 +35,56 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly Transform2D[] _iht4 = {
|
||||
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
|
||||
};
|
||||
new(Iadst4, Iadst4) // ADST_ADST = 3
|
||||
];
|
||||
|
||||
public static void Iht4x416Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int txType)
|
||||
public static void Iht4X416Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int txType)
|
||||
{
|
||||
int i, j;
|
||||
Span<int> output = stackalloc int[4 * 4];
|
||||
Span<int> outptr = output;
|
||||
Span<int> tempIn = stackalloc int[4];
|
||||
Span<int> tempOut = stackalloc int[4];
|
||||
|
||||
// Inverse transform row vectors
|
||||
for (i = 0; i < 4; ++i)
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
_iht4[txType].Rows(input, outptr);
|
||||
input = input[4..];
|
||||
outptr = outptr[4..];
|
||||
input = input.Slice(4);
|
||||
outptr = outptr.Slice(4);
|
||||
}
|
||||
|
||||
// Inverse transform column vectors
|
||||
for (i = 0; i < 4; ++i)
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
for (j = 0; j < 4; ++j)
|
||||
for (int j = 0; j < 4; ++j)
|
||||
{
|
||||
tempIn[j] = output[j * 4 + i];
|
||||
tempIn[j] = output[(j * 4) + i];
|
||||
}
|
||||
|
||||
_iht4[txType].Cols(tempIn, tempOut);
|
||||
for (j = 0; j < 4; ++j)
|
||||
for (int j = 0; j < 4; ++j)
|
||||
{
|
||||
dest[j * stride + i] = ClipPixelAdd(dest[j * stride + i], BitUtils.RoundPowerOfTwo(tempOut[j], 4));
|
||||
dest[(j * stride) + i] =
|
||||
ClipPixelAdd(dest[(j * stride) + i], BitUtils.RoundPowerOfTwo(tempOut[j], 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly Transform2D[] _iht8 = {
|
||||
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
|
||||
};
|
||||
new(Iadst8, Iadst8) // ADST_ADST = 3
|
||||
];
|
||||
|
||||
public static void Iht8x864Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int txType)
|
||||
public static void Iht8X864Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int txType)
|
||||
{
|
||||
int i, j;
|
||||
Span<int> output = stackalloc int[8 * 8];
|
||||
Span<int> outptr = output;
|
||||
Span<int> tempIn = stackalloc int[8];
|
||||
@ -88,39 +92,40 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
Transform2D ht = _iht8[txType];
|
||||
|
||||
// Inverse transform row vectors
|
||||
for (i = 0; i < 8; ++i)
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
ht.Rows(input, outptr);
|
||||
input = input[8..];
|
||||
outptr = outptr[8..];
|
||||
input = input.Slice(8);
|
||||
outptr = outptr.Slice(8);
|
||||
}
|
||||
|
||||
// Inverse transform column vectors
|
||||
for (i = 0; i < 8; ++i)
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
for (j = 0; j < 8; ++j)
|
||||
for (int j = 0; j < 8; ++j)
|
||||
{
|
||||
tempIn[j] = output[j * 8 + i];
|
||||
tempIn[j] = output[(j * 8) + i];
|
||||
}
|
||||
|
||||
ht.Cols(tempIn, tempOut);
|
||||
for (j = 0; j < 8; ++j)
|
||||
for (int j = 0; j < 8; ++j)
|
||||
{
|
||||
dest[j * stride + i] = ClipPixelAdd(dest[j * stride + i], BitUtils.RoundPowerOfTwo(tempOut[j], 5));
|
||||
dest[(j * stride) + i] =
|
||||
ClipPixelAdd(dest[(j * stride) + i], BitUtils.RoundPowerOfTwo(tempOut[j], 5));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly Transform2D[] _iht16 = {
|
||||
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
|
||||
};
|
||||
new(Iadst16, Iadst16) // ADST_ADST = 3
|
||||
];
|
||||
|
||||
public static void Iht16x16256Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int txType)
|
||||
public static void Iht16X16256Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int txType)
|
||||
{
|
||||
int i, j;
|
||||
Span<int> output = stackalloc int[16 * 16];
|
||||
Span<int> outptr = output;
|
||||
Span<int> tempIn = stackalloc int[16];
|
||||
@ -128,55 +133,56 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
Transform2D ht = _iht16[txType];
|
||||
|
||||
// Rows
|
||||
for (i = 0; i < 16; ++i)
|
||||
for (int i = 0; i < 16; ++i)
|
||||
{
|
||||
ht.Rows(input, outptr);
|
||||
input = input[16..];
|
||||
outptr = outptr[16..];
|
||||
input = input.Slice(16);
|
||||
outptr = outptr.Slice(16);
|
||||
}
|
||||
|
||||
// Columns
|
||||
for (i = 0; i < 16; ++i)
|
||||
for (int i = 0; i < 16; ++i)
|
||||
{
|
||||
for (j = 0; j < 16; ++j)
|
||||
for (int j = 0; j < 16; ++j)
|
||||
{
|
||||
tempIn[j] = output[j * 16 + i];
|
||||
tempIn[j] = output[(j * 16) + i];
|
||||
}
|
||||
|
||||
ht.Cols(tempIn, tempOut);
|
||||
for (j = 0; j < 16; ++j)
|
||||
for (int j = 0; j < 16; ++j)
|
||||
{
|
||||
dest[j * stride + i] = ClipPixelAdd(dest[j * stride + i], BitUtils.RoundPowerOfTwo(tempOut[j], 6));
|
||||
dest[(j * stride) + i] =
|
||||
ClipPixelAdd(dest[(j * stride) + i], BitUtils.RoundPowerOfTwo(tempOut[j], 6));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Idct
|
||||
public static void Idct4x4Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int eob)
|
||||
public static void Idct4X4Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int eob)
|
||||
{
|
||||
if (eob > 1)
|
||||
{
|
||||
Idct4x416Add(input, dest, stride);
|
||||
Idct4X416Add(input, dest, stride);
|
||||
}
|
||||
else
|
||||
{
|
||||
Idct4x41Add(input, dest, stride);
|
||||
Idct4X41Add(input, dest, stride);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Iwht4x4Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int eob)
|
||||
public static void Iwht4X4Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int eob)
|
||||
{
|
||||
if (eob > 1)
|
||||
{
|
||||
Iwht4x416Add(input, dest, stride);
|
||||
Iwht4X416Add(input, dest, stride);
|
||||
}
|
||||
else
|
||||
{
|
||||
Iwht4x41Add(input, dest, stride);
|
||||
Iwht4X41Add(input, dest, stride);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Idct8x8Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int eob)
|
||||
public static void Idct8X8Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int eob)
|
||||
{
|
||||
// If dc is 1, then input[0] is the reconstructed value, do not need
|
||||
// dequantization. Also, when dc is 1, dc is counted in eobs, namely eobs >=1.
|
||||
@ -186,149 +192,150 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
if (eob == 1)
|
||||
{
|
||||
// DC only DCT coefficient
|
||||
Idct8x81Add(input, dest, stride);
|
||||
Idct8X81Add(input, dest, stride);
|
||||
}
|
||||
else if (eob <= 12)
|
||||
{
|
||||
Idct8x812Add(input, dest, stride);
|
||||
Idct8X812Add(input, dest, stride);
|
||||
}
|
||||
else
|
||||
{
|
||||
Idct8x864Add(input, dest, stride);
|
||||
Idct8X864Add(input, dest, stride);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Idct16x16Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int eob)
|
||||
public static void Idct16X16Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int eob)
|
||||
{
|
||||
/* The calculation can be simplified if there are not many non-zero dct
|
||||
* coefficients. Use eobs to separate different cases. */
|
||||
if (eob == 1) /* DC only DCT coefficient. */
|
||||
{
|
||||
Idct16x161Add(input, dest, stride);
|
||||
Idct16X161Add(input, dest, stride);
|
||||
}
|
||||
else if (eob <= 10)
|
||||
{
|
||||
Idct16x1610Add(input, dest, stride);
|
||||
Idct16X1610Add(input, dest, stride);
|
||||
}
|
||||
else if (eob <= 38)
|
||||
{
|
||||
Idct16x1638Add(input, dest, stride);
|
||||
Idct16X1638Add(input, dest, stride);
|
||||
}
|
||||
else
|
||||
{
|
||||
Idct16x16256Add(input, dest, stride);
|
||||
Idct16X16256Add(input, dest, stride);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Idct32x32Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int eob)
|
||||
public static void Idct32X32Add(ReadOnlySpan<int> input, Span<byte> dest, int stride, int eob)
|
||||
{
|
||||
if (eob == 1)
|
||||
{
|
||||
Idct32x321Add(input, dest, stride);
|
||||
Idct32X321Add(input, dest, stride);
|
||||
}
|
||||
else if (eob <= 34)
|
||||
{
|
||||
// Non-zero coeff only in upper-left 8x8
|
||||
Idct32x3234Add(input, dest, stride);
|
||||
Idct32X3234Add(input, dest, stride);
|
||||
}
|
||||
else if (eob <= 135)
|
||||
{
|
||||
// Non-zero coeff only in upper-left 16x16
|
||||
Idct32x32135Add(input, dest, stride);
|
||||
Idct32X32135Add(input, dest, stride);
|
||||
}
|
||||
else
|
||||
{
|
||||
Idct32x321024Add(input, dest, stride);
|
||||
Idct32X321024Add(input, dest, stride);
|
||||
}
|
||||
}
|
||||
|
||||
// Iht
|
||||
public static void Iht4x4Add(TxType txType, ReadOnlySpan<int> input, Span<byte> dest, int stride, int eob)
|
||||
public static void Iht4X4Add(TxType txType, ReadOnlySpan<int> input, Span<byte> dest, int stride, int eob)
|
||||
{
|
||||
if (txType == TxType.DctDct)
|
||||
{
|
||||
Idct4x4Add(input, dest, stride, eob);
|
||||
Idct4X4Add(input, dest, stride, eob);
|
||||
}
|
||||
else
|
||||
{
|
||||
Iht4x416Add(input, dest, stride, (int)txType);
|
||||
Iht4X416Add(input, dest, stride, (int)txType);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Iht8x8Add(TxType txType, ReadOnlySpan<int> input, Span<byte> dest, int stride, int eob)
|
||||
public static void Iht8X8Add(TxType txType, ReadOnlySpan<int> input, Span<byte> dest, int stride, int eob)
|
||||
{
|
||||
if (txType == TxType.DctDct)
|
||||
{
|
||||
Idct8x8Add(input, dest, stride, eob);
|
||||
Idct8X8Add(input, dest, stride, eob);
|
||||
}
|
||||
else
|
||||
{
|
||||
Iht8x864Add(input, dest, stride, (int)txType);
|
||||
Iht8X864Add(input, dest, stride, (int)txType);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Iht16x16Add(TxType txType, ReadOnlySpan<int> input, Span<byte> dest,
|
||||
int stride, int eob)
|
||||
public static void Iht16X16Add(TxType txType, ReadOnlySpan<int> input, Span<byte> dest,
|
||||
int stride, int eob)
|
||||
{
|
||||
if (txType == TxType.DctDct)
|
||||
{
|
||||
Idct16x16Add(input, dest, stride, eob);
|
||||
Idct16X16Add(input, dest, stride, eob);
|
||||
}
|
||||
else
|
||||
{
|
||||
Iht16x16256Add(input, dest, stride, (int)txType);
|
||||
Iht16X16256Add(input, dest, stride, (int)txType);
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly HighbdTransform2D[] _highbdIht4 = {
|
||||
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
|
||||
};
|
||||
new(HighbdIadst4, HighbdIadst4) // ADST_ADST = 3
|
||||
];
|
||||
|
||||
public static void HighbdIht4x416Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int txType, int bd)
|
||||
public static void HighbdIht4X416Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int txType, int bd)
|
||||
{
|
||||
int i, j;
|
||||
Span<int> output = stackalloc int[4 * 4];
|
||||
Span<int> outptr = output;
|
||||
Span<int> tempIn = stackalloc int[4];
|
||||
Span<int> tempOut = stackalloc int[4];
|
||||
|
||||
// Inverse transform row vectors.
|
||||
for (i = 0; i < 4; ++i)
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
_highbdIht4[txType].Rows(input, outptr, bd);
|
||||
input = input[4..];
|
||||
outptr = outptr[4..];
|
||||
input = input.Slice(4);
|
||||
outptr = outptr.Slice(4);
|
||||
}
|
||||
|
||||
// Inverse transform column vectors.
|
||||
for (i = 0; i < 4; ++i)
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
for (j = 0; j < 4; ++j)
|
||||
for (int j = 0; j < 4; ++j)
|
||||
{
|
||||
tempIn[j] = output[j * 4 + i];
|
||||
tempIn[j] = output[(j * 4) + i];
|
||||
}
|
||||
|
||||
_highbdIht4[txType].Cols(tempIn, tempOut, bd);
|
||||
for (j = 0; j < 4; ++j)
|
||||
for (int j = 0; j < 4; ++j)
|
||||
{
|
||||
dest[j * stride + i] = HighbdClipPixelAdd(dest[j * stride + i], BitUtils.RoundPowerOfTwo(tempOut[j], 4), bd);
|
||||
dest[(j * stride) + i] = HighbdClipPixelAdd(dest[(j * stride) + i],
|
||||
BitUtils.RoundPowerOfTwo(tempOut[j], 4), bd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly HighbdTransform2D[] _highIht8 = {
|
||||
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
|
||||
};
|
||||
new(HighbdIadst8, HighbdIadst8) // ADST_ADST = 3
|
||||
];
|
||||
|
||||
public static void HighbdIht8x864Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int txType, int bd)
|
||||
public static void HighbdIht8X864Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int txType, int bd)
|
||||
{
|
||||
int i, j;
|
||||
Span<int> output = stackalloc int[8 * 8];
|
||||
Span<int> outptr = output;
|
||||
Span<int> tempIn = stackalloc int[8];
|
||||
@ -336,39 +343,41 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
HighbdTransform2D ht = _highIht8[txType];
|
||||
|
||||
// Inverse transform row vectors.
|
||||
for (i = 0; i < 8; ++i)
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
ht.Rows(input, outptr, bd);
|
||||
input = input[8..];
|
||||
outptr = output[8..];
|
||||
input = input.Slice(8);
|
||||
outptr = output.Slice(8);
|
||||
}
|
||||
|
||||
// Inverse transform column vectors.
|
||||
for (i = 0; i < 8; ++i)
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
for (j = 0; j < 8; ++j)
|
||||
for (int j = 0; j < 8; ++j)
|
||||
{
|
||||
tempIn[j] = output[j * 8 + i];
|
||||
tempIn[j] = output[(j * 8) + i];
|
||||
}
|
||||
|
||||
ht.Cols(tempIn, tempOut, bd);
|
||||
for (j = 0; j < 8; ++j)
|
||||
for (int j = 0; j < 8; ++j)
|
||||
{
|
||||
dest[j * stride + i] = HighbdClipPixelAdd(dest[j * stride + i], BitUtils.RoundPowerOfTwo(tempOut[j], 5), bd);
|
||||
dest[(j * stride) + i] = HighbdClipPixelAdd(dest[(j * stride) + i],
|
||||
BitUtils.RoundPowerOfTwo(tempOut[j], 5), bd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly HighbdTransform2D[] _highIht16 = {
|
||||
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
|
||||
};
|
||||
new(HighbdIadst16, HighbdIadst16) // ADST_ADST = 3
|
||||
];
|
||||
|
||||
public static void HighbdIht16x16256Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int txType, int bd)
|
||||
public static void HighbdIht16X16256Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int txType,
|
||||
int bd)
|
||||
{
|
||||
int i, j;
|
||||
Span<int> output = stackalloc int[16 * 16];
|
||||
Span<int> outptr = output;
|
||||
Span<int> tempIn = stackalloc int[16];
|
||||
@ -376,55 +385,56 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
HighbdTransform2D ht = _highIht16[txType];
|
||||
|
||||
// Rows
|
||||
for (i = 0; i < 16; ++i)
|
||||
for (int i = 0; i < 16; ++i)
|
||||
{
|
||||
ht.Rows(input, outptr, bd);
|
||||
input = input[16..];
|
||||
outptr = output[16..];
|
||||
input = input.Slice(16);
|
||||
outptr = output.Slice(16);
|
||||
}
|
||||
|
||||
// Columns
|
||||
for (i = 0; i < 16; ++i)
|
||||
for (int i = 0; i < 16; ++i)
|
||||
{
|
||||
for (j = 0; j < 16; ++j)
|
||||
for (int j = 0; j < 16; ++j)
|
||||
{
|
||||
tempIn[j] = output[j * 16 + i];
|
||||
tempIn[j] = output[(j * 16) + i];
|
||||
}
|
||||
|
||||
ht.Cols(tempIn, tempOut, bd);
|
||||
for (j = 0; j < 16; ++j)
|
||||
for (int j = 0; j < 16; ++j)
|
||||
{
|
||||
dest[j * stride + i] = HighbdClipPixelAdd(dest[j * stride + i], BitUtils.RoundPowerOfTwo(tempOut[j], 6), bd);
|
||||
dest[(j * stride) + i] = HighbdClipPixelAdd(dest[(j * stride) + i],
|
||||
BitUtils.RoundPowerOfTwo(tempOut[j], 6), bd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Idct
|
||||
public static void HighbdIdct4x4Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int eob, int bd)
|
||||
public static void HighbdIdct4X4Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int eob, int bd)
|
||||
{
|
||||
if (eob > 1)
|
||||
{
|
||||
HighbdIdct4x416Add(input, dest, stride, bd);
|
||||
HighbdIdct4X416Add(input, dest, stride, bd);
|
||||
}
|
||||
else
|
||||
{
|
||||
HighbdIdct4x41Add(input, dest, stride, bd);
|
||||
HighbdIdct4X41Add(input, dest, stride, bd);
|
||||
}
|
||||
}
|
||||
|
||||
public static void HighbdIwht4x4Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int eob, int bd)
|
||||
public static void HighbdIwht4X4Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int eob, int bd)
|
||||
{
|
||||
if (eob > 1)
|
||||
{
|
||||
HighbdIwht4x416Add(input, dest, stride, bd);
|
||||
HighbdIwht4X416Add(input, dest, stride, bd);
|
||||
}
|
||||
else
|
||||
{
|
||||
HighbdIwht4x41Add(input, dest, stride, bd);
|
||||
HighbdIwht4X41Add(input, dest, stride, bd);
|
||||
}
|
||||
}
|
||||
|
||||
public static void HighbdIdct8x8Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int eob, int bd)
|
||||
public static void HighbdIdct8X8Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int eob, int bd)
|
||||
{
|
||||
// If dc is 1, then input[0] is the reconstructed value, do not need
|
||||
// dequantization. Also, when dc is 1, dc is counted in eobs, namely eobs >=1.
|
||||
@ -434,97 +444,100 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
// DC only DCT coefficient
|
||||
if (eob == 1)
|
||||
{
|
||||
Vpx_Highbdidct8x8_1_add_c(input, dest, stride, bd);
|
||||
VpxHighbdidct8X81AddC(input, dest, stride, bd);
|
||||
}
|
||||
else if (eob <= 12)
|
||||
{
|
||||
HighbdIdct8x812Add(input, dest, stride, bd);
|
||||
HighbdIdct8X812Add(input, dest, stride, bd);
|
||||
}
|
||||
else
|
||||
{
|
||||
HighbdIdct8x864Add(input, dest, stride, bd);
|
||||
HighbdIdct8X864Add(input, dest, stride, bd);
|
||||
}
|
||||
}
|
||||
|
||||
public static void HighbdIdct16x16Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int eob, int bd)
|
||||
public static void HighbdIdct16X16Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int eob, int bd)
|
||||
{
|
||||
// The calculation can be simplified if there are not many non-zero dct
|
||||
// coefficients. Use eobs to separate different cases.
|
||||
// DC only DCT coefficient.
|
||||
if (eob == 1)
|
||||
{
|
||||
HighbdIdct16x161Add(input, dest, stride, bd);
|
||||
HighbdIdct16X161Add(input, dest, stride, bd);
|
||||
}
|
||||
else if (eob <= 10)
|
||||
{
|
||||
HighbdIdct16x1610Add(input, dest, stride, bd);
|
||||
HighbdIdct16X1610Add(input, dest, stride, bd);
|
||||
}
|
||||
else if (eob <= 38)
|
||||
{
|
||||
HighbdIdct16x1638Add(input, dest, stride, bd);
|
||||
HighbdIdct16X1638Add(input, dest, stride, bd);
|
||||
}
|
||||
else
|
||||
{
|
||||
HighbdIdct16x16256Add(input, dest, stride, bd);
|
||||
HighbdIdct16X16256Add(input, dest, stride, bd);
|
||||
}
|
||||
}
|
||||
|
||||
public static void HighbdIdct32x32Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int eob, int bd)
|
||||
public static void HighbdIdct32X32Add(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int eob, int bd)
|
||||
{
|
||||
// Non-zero coeff only in upper-left 8x8
|
||||
if (eob == 1)
|
||||
{
|
||||
HighbdIdct32x321Add(input, dest, stride, bd);
|
||||
HighbdIdct32X321Add(input, dest, stride, bd);
|
||||
}
|
||||
else if (eob <= 34)
|
||||
{
|
||||
HighbdIdct32x3234Add(input, dest, stride, bd);
|
||||
HighbdIdct32X3234Add(input, dest, stride, bd);
|
||||
}
|
||||
else if (eob <= 135)
|
||||
{
|
||||
HighbdIdct32x32135Add(input, dest, stride, bd);
|
||||
HighbdIdct32X32135Add(input, dest, stride, bd);
|
||||
}
|
||||
else
|
||||
{
|
||||
HighbdIdct32x321024Add(input, dest, stride, bd);
|
||||
HighbdIdct32X321024Add(input, dest, stride, bd);
|
||||
}
|
||||
}
|
||||
|
||||
// Iht
|
||||
public static void HighbdIht4x4Add(TxType txType, ReadOnlySpan<int> input, Span<ushort> dest, int stride, int eob, int bd)
|
||||
public static void HighbdIht4X4Add(TxType txType, ReadOnlySpan<int> input, Span<ushort> dest, int stride,
|
||||
int eob, int bd)
|
||||
{
|
||||
if (txType == TxType.DctDct)
|
||||
{
|
||||
HighbdIdct4x4Add(input, dest, stride, eob, bd);
|
||||
HighbdIdct4X4Add(input, dest, stride, eob, bd);
|
||||
}
|
||||
else
|
||||
{
|
||||
HighbdIht4x416Add(input, dest, stride, (int)txType, bd);
|
||||
HighbdIht4X416Add(input, dest, stride, (int)txType, bd);
|
||||
}
|
||||
}
|
||||
|
||||
public static void HighbdIht8x8Add(TxType txType, ReadOnlySpan<int> input, Span<ushort> dest, int stride, int eob, int bd)
|
||||
public static void HighbdIht8X8Add(TxType txType, ReadOnlySpan<int> input, Span<ushort> dest, int stride,
|
||||
int eob, int bd)
|
||||
{
|
||||
if (txType == TxType.DctDct)
|
||||
{
|
||||
HighbdIdct8x8Add(input, dest, stride, eob, bd);
|
||||
HighbdIdct8X8Add(input, dest, stride, eob, bd);
|
||||
}
|
||||
else
|
||||
{
|
||||
HighbdIht8x864Add(input, dest, stride, (int)txType, bd);
|
||||
HighbdIht8X864Add(input, dest, stride, (int)txType, bd);
|
||||
}
|
||||
}
|
||||
|
||||
public static void HighbdIht16x16Add(TxType txType, ReadOnlySpan<int> input, Span<ushort> dest, int stride, int eob, int bd)
|
||||
public static void HighbdIht16X16Add(TxType txType, ReadOnlySpan<int> input, Span<ushort> dest, int stride,
|
||||
int eob, int bd)
|
||||
{
|
||||
if (txType == TxType.DctDct)
|
||||
{
|
||||
HighbdIdct16x16Add(input, dest, stride, eob, bd);
|
||||
HighbdIdct16X16Add(input, dest, stride, eob, bd);
|
||||
}
|
||||
else
|
||||
{
|
||||
HighbdIht16x16256Add(input, dest, stride, (int)txType, bd);
|
||||
HighbdIht16X16256Add(input, dest, stride, (int)txType, bd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@ using System;
|
||||
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
{
|
||||
class InternalErrorException : Exception
|
||||
internal class InternalErrorException : Exception
|
||||
{
|
||||
public InternalErrorException(string message) : base(message)
|
||||
{
|
||||
@ -12,4 +12,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -11,4 +11,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
throw new InternalErrorException(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
94
src/Ryujinx.Graphics.Nvdec.Vp9/Prob.cs
Normal file
94
src/Ryujinx.Graphics.Nvdec.Vp9/Prob.cs
Normal file
@ -0,0 +1,94 @@
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Graphics.Nvdec.Vp9.Common;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
{
|
||||
public static class Prob
|
||||
{
|
||||
public const int MaxProb = 255;
|
||||
|
||||
private static byte GetProb(uint num, uint den)
|
||||
{
|
||||
Debug.Assert(den != 0);
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
private static byte GetBinaryProb(uint n0, uint n1)
|
||||
{
|
||||
uint den = n0 + n1;
|
||||
if (den == 0)
|
||||
{
|
||||
return 128;
|
||||
}
|
||||
|
||||
return GetProb(n0, den);
|
||||
}
|
||||
|
||||
/* This function assumes prob1 and prob2 are already within [1,255] range. */
|
||||
public static byte WeightedProb(int prob1, int prob2, int factor)
|
||||
{
|
||||
return (byte)BitUtils.RoundPowerOfTwo((prob1 * (256 - factor)) + (prob2 * factor), 8);
|
||||
}
|
||||
|
||||
public static byte MergeProbs(byte preProb, ref Array2<uint> ct, uint countSat, uint maxUpdateFactor)
|
||||
{
|
||||
byte prob = GetBinaryProb(ct[0], ct[1]);
|
||||
uint count = Math.Min(ct[0] + ct[1], countSat);
|
||||
uint factor = maxUpdateFactor * count / countSat;
|
||||
return WeightedProb(preProb, prob, (int)factor);
|
||||
}
|
||||
|
||||
// MODE_MV_MAX_UPDATE_FACTOR (128) * count / MODE_MV_COUNT_SAT;
|
||||
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
|
||||
];
|
||||
|
||||
private const int ModeMvCountSat = 20;
|
||||
|
||||
public static byte ModeMvMergeProbs(byte preProb, ref Array2<uint> ct)
|
||||
{
|
||||
uint den = ct[0] + ct[1];
|
||||
if (den == 0)
|
||||
{
|
||||
return preProb;
|
||||
}
|
||||
|
||||
uint count = Math.Min(den, ModeMvCountSat);
|
||||
uint factor = _countToUpdateFactor[(int)count];
|
||||
byte prob = GetProb(ct[0], den);
|
||||
return WeightedProb(preProb, prob, (int)factor);
|
||||
}
|
||||
|
||||
private static uint TreeMergeProbsImpl(
|
||||
uint i,
|
||||
sbyte[] tree,
|
||||
ReadOnlySpan<byte> preProbs,
|
||||
ReadOnlySpan<uint> counts,
|
||||
Span<byte> probs)
|
||||
{
|
||||
int l = tree[i];
|
||||
uint leftCount = l <= 0 ? counts[-l] : TreeMergeProbsImpl((uint)l, tree, preProbs, counts, probs);
|
||||
int r = tree[i + 1];
|
||||
uint rightCount = r <= 0 ? counts[-r] : TreeMergeProbsImpl((uint)r, tree, preProbs, counts, probs);
|
||||
Array2<uint> ct = new();
|
||||
ct[0] = leftCount;
|
||||
ct[1] = rightCount;
|
||||
probs[(int)(i >> 1)] = ModeMvMergeProbs(preProbs[(int)(i >> 1)], ref ct);
|
||||
return leftCount + rightCount;
|
||||
}
|
||||
|
||||
public static void VpxTreeMergeProbs(sbyte[] tree, ReadOnlySpan<byte> preProbs, ReadOnlySpan<uint> counts,
|
||||
Span<byte> probs)
|
||||
{
|
||||
TreeMergeProbsImpl(0, tree, preProbs, counts, probs);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,172 +1,127 @@
|
||||
using Ryujinx.Graphics.Nvdec.Vp9.Types;
|
||||
using System;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
{
|
||||
internal static class QuantCommon
|
||||
{
|
||||
public const int MinQ = 0;
|
||||
public const int MaxQ = 255;
|
||||
public const int QindexBits = 8;
|
||||
|
||||
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,
|
||||
43, 43, 44, 45, 46, 47, 48, 48, 49, 50, 51, 52, 53, 53,
|
||||
54, 55, 56, 57, 57, 58, 59, 60, 61, 62, 62, 63, 64, 65,
|
||||
66, 66, 67, 68, 69, 70, 70, 71, 72, 73, 74, 74, 75, 76,
|
||||
77, 78, 78, 79, 80, 81, 81, 82, 83, 84, 85, 85, 87, 88,
|
||||
90, 92, 93, 95, 96, 98, 99, 101, 102, 104, 105, 107, 108, 110,
|
||||
111, 113, 114, 116, 117, 118, 120, 121, 123, 125, 127, 129, 131, 134,
|
||||
136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 161, 164,
|
||||
166, 169, 172, 174, 177, 180, 182, 185, 187, 190, 192, 195, 199, 202,
|
||||
205, 208, 211, 214, 217, 220, 223, 226, 230, 233, 237, 240, 243, 247,
|
||||
250, 253, 257, 261, 265, 269, 272, 276, 280, 284, 288, 292, 296, 300,
|
||||
304, 309, 313, 317, 322, 326, 330, 335, 340, 344, 349, 354, 359, 364,
|
||||
369, 374, 379, 384, 389, 395, 400, 406, 411, 417, 423, 429, 435, 441,
|
||||
447, 454, 461, 467, 475, 482, 489, 497, 505, 513, 522, 530, 539, 549,
|
||||
559, 569, 579, 590, 602, 614, 626, 640, 654, 668, 684, 700, 717, 736,
|
||||
755, 775, 796, 819, 843, 869, 896, 925, 955, 988, 1022, 1058, 1098, 1139,
|
||||
1184, 1232, 1282, 1336,
|
||||
};
|
||||
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, 43, 43, 44, 45, 46, 47, 48, 48, 49, 50, 51,
|
||||
52, 53, 53, 54, 55, 56, 57, 57, 58, 59, 60, 61, 62, 62, 63, 64, 65, 66, 66, 67, 68, 69, 70, 70, 71, 72,
|
||||
73, 74, 74, 75, 76, 77, 78, 78, 79, 80, 81, 81, 82, 83, 84, 85, 85, 87, 88, 90, 92, 93, 95, 96, 98, 99,
|
||||
101, 102, 104, 105, 107, 108, 110, 111, 113, 114, 116, 117, 118, 120, 121, 123, 125, 127, 129, 131, 134,
|
||||
136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 161, 164, 166, 169, 172, 174, 177, 180, 182,
|
||||
185, 187, 190, 192, 195, 199, 202, 205, 208, 211, 214, 217, 220, 223, 226, 230, 233, 237, 240, 243, 247,
|
||||
250, 253, 257, 261, 265, 269, 272, 276, 280, 284, 288, 292, 296, 300, 304, 309, 313, 317, 322, 326, 330,
|
||||
335, 340, 344, 349, 354, 359, 364, 369, 374, 379, 384, 389, 395, 400, 406, 411, 417, 423, 429, 435, 441,
|
||||
447, 454, 461, 467, 475, 482, 489, 497, 505, 513, 522, 530, 539, 549, 559, 569, 579, 590, 602, 614, 626,
|
||||
640, 654, 668, 684, 700, 717, 736, 755, 775, 796, 819, 843, 869, 896, 925, 955, 988, 1022, 1058, 1098,
|
||||
1139, 1184, 1232, 1282, 1336
|
||||
];
|
||||
|
||||
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,
|
||||
136, 140, 143, 147, 151, 155, 159, 163, 166, 170, 174, 178, 182,
|
||||
185, 189, 193, 197, 200, 204, 208, 212, 215, 219, 223, 226, 230,
|
||||
233, 237, 241, 244, 248, 251, 255, 259, 262, 266, 269, 273, 276,
|
||||
280, 283, 287, 290, 293, 297, 300, 304, 307, 310, 314, 317, 321,
|
||||
324, 327, 331, 334, 337, 343, 350, 356, 362, 369, 375, 381, 387,
|
||||
394, 400, 406, 412, 418, 424, 430, 436, 442, 448, 454, 460, 466,
|
||||
472, 478, 484, 490, 499, 507, 516, 525, 533, 542, 550, 559, 567,
|
||||
576, 584, 592, 601, 609, 617, 625, 634, 644, 655, 666, 676, 687,
|
||||
698, 708, 718, 729, 739, 749, 759, 770, 782, 795, 807, 819, 831,
|
||||
844, 856, 868, 880, 891, 906, 920, 933, 947, 961, 975, 988, 1001,
|
||||
1015, 1030, 1045, 1061, 1076, 1090, 1105, 1120, 1137, 1153, 1170, 1186, 1202,
|
||||
1218, 1236, 1253, 1271, 1288, 1306, 1323, 1342, 1361, 1379, 1398, 1416, 1436,
|
||||
1456, 1476, 1496, 1516, 1537, 1559, 1580, 1601, 1624, 1647, 1670, 1692, 1717,
|
||||
1741, 1766, 1791, 1817, 1844, 1871, 1900, 1929, 1958, 1990, 2021, 2054, 2088,
|
||||
2123, 2159, 2197, 2236, 2276, 2319, 2363, 2410, 2458, 2508, 2561, 2616, 2675,
|
||||
2737, 2802, 2871, 2944, 3020, 3102, 3188, 3280, 3375, 3478, 3586, 3702, 3823,
|
||||
3953, 4089, 4236, 4394, 4559, 4737, 4929, 5130, 5347,
|
||||
};
|
||||
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, 136, 140, 143, 147, 151, 155, 159, 163,
|
||||
166, 170, 174, 178, 182, 185, 189, 193, 197, 200, 204, 208, 212, 215, 219, 223, 226, 230, 233, 237, 241,
|
||||
244, 248, 251, 255, 259, 262, 266, 269, 273, 276, 280, 283, 287, 290, 293, 297, 300, 304, 307, 310, 314,
|
||||
317, 321, 324, 327, 331, 334, 337, 343, 350, 356, 362, 369, 375, 381, 387, 394, 400, 406, 412, 418, 424,
|
||||
430, 436, 442, 448, 454, 460, 466, 472, 478, 484, 490, 499, 507, 516, 525, 533, 542, 550, 559, 567, 576,
|
||||
584, 592, 601, 609, 617, 625, 634, 644, 655, 666, 676, 687, 698, 708, 718, 729, 739, 749, 759, 770, 782,
|
||||
795, 807, 819, 831, 844, 856, 868, 880, 891, 906, 920, 933, 947, 961, 975, 988, 1001, 1015, 1030, 1045,
|
||||
1061, 1076, 1090, 1105, 1120, 1137, 1153, 1170, 1186, 1202, 1218, 1236, 1253, 1271, 1288, 1306, 1323,
|
||||
1342, 1361, 1379, 1398, 1416, 1436, 1456, 1476, 1496, 1516, 1537, 1559, 1580, 1601, 1624, 1647, 1670,
|
||||
1692, 1717, 1741, 1766, 1791, 1817, 1844, 1871, 1900, 1929, 1958, 1990, 2021, 2054, 2088, 2123, 2159,
|
||||
2197, 2236, 2276, 2319, 2363, 2410, 2458, 2508, 2561, 2616, 2675, 2737, 2802, 2871, 2944, 3020, 3102,
|
||||
3188, 3280, 3375, 3478, 3586, 3702, 3823, 3953, 4089, 4236, 4394, 4559, 4737, 4929, 5130, 5347
|
||||
];
|
||||
|
||||
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,
|
||||
421, 437, 453, 469, 484, 500, 516, 532, 548, 564, 580,
|
||||
596, 611, 627, 643, 659, 674, 690, 706, 721, 737, 752,
|
||||
768, 783, 798, 814, 829, 844, 859, 874, 889, 904, 919,
|
||||
934, 949, 964, 978, 993, 1008, 1022, 1037, 1051, 1065, 1080,
|
||||
1094, 1108, 1122, 1136, 1151, 1165, 1179, 1192, 1206, 1220, 1234,
|
||||
1248, 1261, 1275, 1288, 1302, 1315, 1329, 1342, 1368, 1393, 1419,
|
||||
1444, 1469, 1494, 1519, 1544, 1569, 1594, 1618, 1643, 1668, 1692,
|
||||
1717, 1741, 1765, 1789, 1814, 1838, 1862, 1885, 1909, 1933, 1957,
|
||||
1992, 2027, 2061, 2096, 2130, 2165, 2199, 2233, 2267, 2300, 2334,
|
||||
2367, 2400, 2434, 2467, 2499, 2532, 2575, 2618, 2661, 2704, 2746,
|
||||
2788, 2830, 2872, 2913, 2954, 2995, 3036, 3076, 3127, 3177, 3226,
|
||||
3275, 3324, 3373, 3421, 3469, 3517, 3565, 3621, 3677, 3733, 3788,
|
||||
3843, 3897, 3951, 4005, 4058, 4119, 4181, 4241, 4301, 4361, 4420,
|
||||
4479, 4546, 4612, 4677, 4742, 4807, 4871, 4942, 5013, 5083, 5153,
|
||||
5222, 5291, 5367, 5442, 5517, 5591, 5665, 5745, 5825, 5905, 5984,
|
||||
6063, 6149, 6234, 6319, 6404, 6495, 6587, 6678, 6769, 6867, 6966,
|
||||
7064, 7163, 7269, 7376, 7483, 7599, 7715, 7832, 7958, 8085, 8214,
|
||||
8352, 8492, 8635, 8788, 8945, 9104, 9275, 9450, 9639, 9832, 10031,
|
||||
10245, 10465, 10702, 10946, 11210, 11482, 11776, 12081, 12409, 12750, 13118,
|
||||
13501, 13913, 14343, 14807, 15290, 15812, 16356, 16943, 17575, 18237, 18949,
|
||||
19718, 20521, 21387,
|
||||
};
|
||||
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, 421, 437, 453, 469, 484, 500, 516, 532, 548, 564, 580,
|
||||
596, 611, 627, 643, 659, 674, 690, 706, 721, 737, 752, 768, 783, 798, 814, 829, 844, 859, 874, 889, 904,
|
||||
919, 934, 949, 964, 978, 993, 1008, 1022, 1037, 1051, 1065, 1080, 1094, 1108, 1122, 1136, 1151, 1165,
|
||||
1179, 1192, 1206, 1220, 1234, 1248, 1261, 1275, 1288, 1302, 1315, 1329, 1342, 1368, 1393, 1419, 1444,
|
||||
1469, 1494, 1519, 1544, 1569, 1594, 1618, 1643, 1668, 1692, 1717, 1741, 1765, 1789, 1814, 1838, 1862,
|
||||
1885, 1909, 1933, 1957, 1992, 2027, 2061, 2096, 2130, 2165, 2199, 2233, 2267, 2300, 2334, 2367, 2400,
|
||||
2434, 2467, 2499, 2532, 2575, 2618, 2661, 2704, 2746, 2788, 2830, 2872, 2913, 2954, 2995, 3036, 3076,
|
||||
3127, 3177, 3226, 3275, 3324, 3373, 3421, 3469, 3517, 3565, 3621, 3677, 3733, 3788, 3843, 3897, 3951,
|
||||
4005, 4058, 4119, 4181, 4241, 4301, 4361, 4420, 4479, 4546, 4612, 4677, 4742, 4807, 4871, 4942, 5013,
|
||||
5083, 5153, 5222, 5291, 5367, 5442, 5517, 5591, 5665, 5745, 5825, 5905, 5984, 6063, 6149, 6234, 6319,
|
||||
6404, 6495, 6587, 6678, 6769, 6867, 6966, 7064, 7163, 7269, 7376, 7483, 7599, 7715, 7832, 7958, 8085,
|
||||
8214, 8352, 8492, 8635, 8788, 8945, 9104, 9275, 9450, 9639, 9832, 10031, 10245, 10465, 10702, 10946,
|
||||
11210, 11482, 11776, 12081, 12409, 12750, 13118, 13501, 13913, 14343, 14807, 15290, 15812, 16356, 16943,
|
||||
17575, 18237, 18949, 19718, 20521, 21387
|
||||
];
|
||||
|
||||
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,
|
||||
46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
|
||||
59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
|
||||
72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
|
||||
85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
|
||||
98, 99, 100, 101, 102, 104, 106, 108, 110, 112, 114, 116, 118,
|
||||
120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144,
|
||||
146, 148, 150, 152, 155, 158, 161, 164, 167, 170, 173, 176, 179,
|
||||
182, 185, 188, 191, 194, 197, 200, 203, 207, 211, 215, 219, 223,
|
||||
227, 231, 235, 239, 243, 247, 251, 255, 260, 265, 270, 275, 280,
|
||||
285, 290, 295, 300, 305, 311, 317, 323, 329, 335, 341, 347, 353,
|
||||
359, 366, 373, 380, 387, 394, 401, 408, 416, 424, 432, 440, 448,
|
||||
456, 465, 474, 483, 492, 501, 510, 520, 530, 540, 550, 560, 571,
|
||||
582, 593, 604, 615, 627, 639, 651, 663, 676, 689, 702, 715, 729,
|
||||
743, 757, 771, 786, 801, 816, 832, 848, 864, 881, 898, 915, 933,
|
||||
951, 969, 988, 1007, 1026, 1046, 1066, 1087, 1108, 1129, 1151, 1173, 1196,
|
||||
1219, 1243, 1267, 1292, 1317, 1343, 1369, 1396, 1423, 1451, 1479, 1508, 1537,
|
||||
1567, 1597, 1628, 1660, 1692, 1725, 1759, 1793, 1828,
|
||||
};
|
||||
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, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
|
||||
60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
|
||||
86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 104, 106, 108, 110, 112, 114,
|
||||
116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 155, 158,
|
||||
161, 164, 167, 170, 173, 176, 179, 182, 185, 188, 191, 194, 197, 200, 203, 207, 211, 215, 219, 223, 227,
|
||||
231, 235, 239, 243, 247, 251, 255, 260, 265, 270, 275, 280, 285, 290, 295, 300, 305, 311, 317, 323, 329,
|
||||
335, 341, 347, 353, 359, 366, 373, 380, 387, 394, 401, 408, 416, 424, 432, 440, 448, 456, 465, 474, 483,
|
||||
492, 501, 510, 520, 530, 540, 550, 560, 571, 582, 593, 604, 615, 627, 639, 651, 663, 676, 689, 702, 715,
|
||||
729, 743, 757, 771, 786, 801, 816, 832, 848, 864, 881, 898, 915, 933, 951, 969, 988, 1007, 1026, 1046,
|
||||
1066, 1087, 1108, 1129, 1151, 1173, 1196, 1219, 1243, 1267, 1292, 1317, 1343, 1369, 1396, 1423, 1451,
|
||||
1479, 1508, 1537, 1567, 1597, 1628, 1660, 1692, 1725, 1759, 1793, 1828
|
||||
];
|
||||
|
||||
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,
|
||||
154, 158, 163, 168, 172, 177, 181, 186, 190, 195, 199, 204, 208,
|
||||
213, 217, 222, 226, 231, 235, 240, 244, 249, 253, 258, 262, 267,
|
||||
271, 275, 280, 284, 289, 293, 297, 302, 306, 311, 315, 319, 324,
|
||||
328, 332, 337, 341, 345, 349, 354, 358, 362, 367, 371, 375, 379,
|
||||
384, 388, 392, 396, 401, 409, 417, 425, 433, 441, 449, 458, 466,
|
||||
474, 482, 490, 498, 506, 514, 523, 531, 539, 547, 555, 563, 571,
|
||||
579, 588, 596, 604, 616, 628, 640, 652, 664, 676, 688, 700, 713,
|
||||
725, 737, 749, 761, 773, 785, 797, 809, 825, 841, 857, 873, 889,
|
||||
905, 922, 938, 954, 970, 986, 1002, 1018, 1038, 1058, 1078, 1098, 1118,
|
||||
1138, 1158, 1178, 1198, 1218, 1242, 1266, 1290, 1314, 1338, 1362, 1386, 1411,
|
||||
1435, 1463, 1491, 1519, 1547, 1575, 1603, 1631, 1663, 1695, 1727, 1759, 1791,
|
||||
1823, 1859, 1895, 1931, 1967, 2003, 2039, 2079, 2119, 2159, 2199, 2239, 2283,
|
||||
2327, 2371, 2415, 2459, 2507, 2555, 2603, 2651, 2703, 2755, 2807, 2859, 2915,
|
||||
2971, 3027, 3083, 3143, 3203, 3263, 3327, 3391, 3455, 3523, 3591, 3659, 3731,
|
||||
3803, 3876, 3952, 4028, 4104, 4184, 4264, 4348, 4432, 4516, 4604, 4692, 4784,
|
||||
4876, 4972, 5068, 5168, 5268, 5372, 5476, 5584, 5692, 5804, 5916, 6032, 6148,
|
||||
6268, 6388, 6512, 6640, 6768, 6900, 7036, 7172, 7312,
|
||||
};
|
||||
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, 154, 158, 163, 168, 172, 177, 181, 186,
|
||||
190, 195, 199, 204, 208, 213, 217, 222, 226, 231, 235, 240, 244, 249, 253, 258, 262, 267, 271, 275, 280,
|
||||
284, 289, 293, 297, 302, 306, 311, 315, 319, 324, 328, 332, 337, 341, 345, 349, 354, 358, 362, 367, 371,
|
||||
375, 379, 384, 388, 392, 396, 401, 409, 417, 425, 433, 441, 449, 458, 466, 474, 482, 490, 498, 506, 514,
|
||||
523, 531, 539, 547, 555, 563, 571, 579, 588, 596, 604, 616, 628, 640, 652, 664, 676, 688, 700, 713, 725,
|
||||
737, 749, 761, 773, 785, 797, 809, 825, 841, 857, 873, 889, 905, 922, 938, 954, 970, 986, 1002, 1018,
|
||||
1038, 1058, 1078, 1098, 1118, 1138, 1158, 1178, 1198, 1218, 1242, 1266, 1290, 1314, 1338, 1362, 1386,
|
||||
1411, 1435, 1463, 1491, 1519, 1547, 1575, 1603, 1631, 1663, 1695, 1727, 1759, 1791, 1823, 1859, 1895,
|
||||
1931, 1967, 2003, 2039, 2079, 2119, 2159, 2199, 2239, 2283, 2327, 2371, 2415, 2459, 2507, 2555, 2603,
|
||||
2651, 2703, 2755, 2807, 2859, 2915, 2971, 3027, 3083, 3143, 3203, 3263, 3327, 3391, 3455, 3523, 3591,
|
||||
3659, 3731, 3803, 3876, 3952, 4028, 4104, 4184, 4264, 4348, 4432, 4516, 4604, 4692, 4784, 4876, 4972,
|
||||
5068, 5168, 5268, 5372, 5476, 5584, 5692, 5804, 5916, 6032, 6148, 6268, 6388, 6512, 6640, 6768, 6900,
|
||||
7036, 7172, 7312
|
||||
];
|
||||
|
||||
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,
|
||||
475, 493, 511, 530, 548, 567, 586, 604, 623, 642, 660,
|
||||
679, 698, 716, 735, 753, 772, 791, 809, 828, 846, 865,
|
||||
884, 902, 920, 939, 957, 976, 994, 1012, 1030, 1049, 1067,
|
||||
1085, 1103, 1121, 1139, 1157, 1175, 1193, 1211, 1229, 1246, 1264,
|
||||
1282, 1299, 1317, 1335, 1352, 1370, 1387, 1405, 1422, 1440, 1457,
|
||||
1474, 1491, 1509, 1526, 1543, 1560, 1577, 1595, 1627, 1660, 1693,
|
||||
1725, 1758, 1791, 1824, 1856, 1889, 1922, 1954, 1987, 2020, 2052,
|
||||
2085, 2118, 2150, 2183, 2216, 2248, 2281, 2313, 2346, 2378, 2411,
|
||||
2459, 2508, 2556, 2605, 2653, 2701, 2750, 2798, 2847, 2895, 2943,
|
||||
2992, 3040, 3088, 3137, 3185, 3234, 3298, 3362, 3426, 3491, 3555,
|
||||
3619, 3684, 3748, 3812, 3876, 3941, 4005, 4069, 4149, 4230, 4310,
|
||||
4390, 4470, 4550, 4631, 4711, 4791, 4871, 4967, 5064, 5160, 5256,
|
||||
5352, 5448, 5544, 5641, 5737, 5849, 5961, 6073, 6185, 6297, 6410,
|
||||
6522, 6650, 6778, 6906, 7034, 7162, 7290, 7435, 7579, 7723, 7867,
|
||||
8011, 8155, 8315, 8475, 8635, 8795, 8956, 9132, 9308, 9484, 9660,
|
||||
9836, 10028, 10220, 10412, 10604, 10812, 11020, 11228, 11437, 11661, 11885,
|
||||
12109, 12333, 12573, 12813, 13053, 13309, 13565, 13821, 14093, 14365, 14637,
|
||||
14925, 15213, 15502, 15806, 16110, 16414, 16734, 17054, 17390, 17726, 18062,
|
||||
18414, 18766, 19134, 19502, 19886, 20270, 20670, 21070, 21486, 21902, 22334,
|
||||
22766, 23214, 23662, 24126, 24590, 25070, 25551, 26047, 26559, 27071, 27599,
|
||||
28143, 28687, 29247,
|
||||
};
|
||||
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, 475, 493, 511, 530, 548, 567, 586, 604, 623, 642, 660,
|
||||
679, 698, 716, 735, 753, 772, 791, 809, 828, 846, 865, 884, 902, 920, 939, 957, 976, 994, 1012, 1030,
|
||||
1049, 1067, 1085, 1103, 1121, 1139, 1157, 1175, 1193, 1211, 1229, 1246, 1264, 1282, 1299, 1317, 1335,
|
||||
1352, 1370, 1387, 1405, 1422, 1440, 1457, 1474, 1491, 1509, 1526, 1543, 1560, 1577, 1595, 1627, 1660,
|
||||
1693, 1725, 1758, 1791, 1824, 1856, 1889, 1922, 1954, 1987, 2020, 2052, 2085, 2118, 2150, 2183, 2216,
|
||||
2248, 2281, 2313, 2346, 2378, 2411, 2459, 2508, 2556, 2605, 2653, 2701, 2750, 2798, 2847, 2895, 2943,
|
||||
2992, 3040, 3088, 3137, 3185, 3234, 3298, 3362, 3426, 3491, 3555, 3619, 3684, 3748, 3812, 3876, 3941,
|
||||
4005, 4069, 4149, 4230, 4310, 4390, 4470, 4550, 4631, 4711, 4791, 4871, 4967, 5064, 5160, 5256, 5352,
|
||||
5448, 5544, 5641, 5737, 5849, 5961, 6073, 6185, 6297, 6410, 6522, 6650, 6778, 6906, 7034, 7162, 7290,
|
||||
7435, 7579, 7723, 7867, 8011, 8155, 8315, 8475, 8635, 8795, 8956, 9132, 9308, 9484, 9660, 9836, 10028,
|
||||
10220, 10412, 10604, 10812, 11020, 11228, 11437, 11661, 11885, 12109, 12333, 12573, 12813, 13053, 13309,
|
||||
13565, 13821, 14093, 14365, 14637, 14925, 15213, 15502, 15806, 16110, 16414, 16734, 17054, 17390, 17726,
|
||||
18062, 18414, 18766, 19134, 19502, 19886, 20270, 20670, 21070, 21486, 21902, 22334, 22766, 23214, 23662,
|
||||
24126, 24590, 25070, 25551, 26047, 26559, 27071, 27599, 28143, 28687, 29247
|
||||
];
|
||||
|
||||
public static short DcQuant(int qindex, int delta, BitDepth bitDepth)
|
||||
{
|
||||
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");
|
||||
|
||||
Debug.Assert(false, "bitDepth should be Bits8, Bits10 or Bits12");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -175,30 +130,13 @@ 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");
|
||||
|
||||
Debug.Assert(false, "bitDepth should be Bits8, Bits10 or Bits12");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetQIndex(ref Segmentation seg, int segmentId, int baseQIndex)
|
||||
{
|
||||
if (seg.IsSegFeatureActive(segmentId, SegLvlFeatures.SegLvlAltQ) != 0)
|
||||
{
|
||||
int data = seg.GetSegData(segmentId, SegLvlFeatures.SegLvlAltQ);
|
||||
int segQIndex = seg.AbsDelta == Constants.SegmentAbsData ? data : baseQIndex + data;
|
||||
|
||||
return Math.Clamp(segQIndex, 0, MaxQ);
|
||||
}
|
||||
|
||||
return baseQIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
84
src/Ryujinx.Graphics.Nvdec.Vp9/ReadBitBuffer.cs
Normal file
84
src/Ryujinx.Graphics.Nvdec.Vp9/ReadBitBuffer.cs
Normal file
@ -0,0 +1,84 @@
|
||||
using Ryujinx.Graphics.Nvdec.Vp9.Common;
|
||||
using Ryujinx.Graphics.Nvdec.Vp9.Types;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
{
|
||||
public ref struct ReadBitBuffer
|
||||
{
|
||||
public ReadOnlySpan<byte> BitBuffer;
|
||||
public ulong BitOffset;
|
||||
public object ErrorHandlerData;
|
||||
|
||||
public int DecodeUnsignedMax(int max)
|
||||
{
|
||||
int data = ReadLiteral(BitUtils.GetUnsignedBits((uint)max));
|
||||
return data > max ? max : data;
|
||||
}
|
||||
|
||||
public ulong BytesRead()
|
||||
{
|
||||
return (BitOffset + 7) >> 3;
|
||||
}
|
||||
|
||||
public int ReadBit()
|
||||
{
|
||||
ulong off = BitOffset;
|
||||
ulong p = off >> 3;
|
||||
int q = 7 - (int)(off & 0x7);
|
||||
if (p < (ulong)BitBuffer.Length)
|
||||
{
|
||||
int bit = (BitBuffer[(int)p] >> q) & 1;
|
||||
BitOffset = off + 1;
|
||||
return bit;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int ReadLiteral(int bits)
|
||||
{
|
||||
int value = 0, bit;
|
||||
for (bit = bits - 1; bit >= 0; bit--)
|
||||
{
|
||||
value |= ReadBit() << bit;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public int ReadSignedLiteral(int bits)
|
||||
{
|
||||
int value = ReadLiteral(bits);
|
||||
return ReadBit() != 0 ? -value : value;
|
||||
}
|
||||
|
||||
public int ReadInvSignedLiteral(int bits)
|
||||
{
|
||||
return ReadSignedLiteral(bits);
|
||||
}
|
||||
|
||||
public int ReadDeltaQ()
|
||||
{
|
||||
return ReadBit() != 0 ? ReadSignedLiteral(4) : 0;
|
||||
}
|
||||
|
||||
public void ReadFrameSize(out int width, out int height)
|
||||
{
|
||||
width = ReadLiteral(16) + 1;
|
||||
height = ReadLiteral(16) + 1;
|
||||
}
|
||||
|
||||
public BitstreamProfile ReadProfile()
|
||||
{
|
||||
int profile = ReadBit();
|
||||
profile |= ReadBit() << 1;
|
||||
if (profile > 2)
|
||||
{
|
||||
profile += ReadBit();
|
||||
}
|
||||
|
||||
return (BitstreamProfile)profile;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Graphics.Nvdec.Vp9.Types;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
@ -77,65 +77,38 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
bd);
|
||||
}
|
||||
|
||||
private static int RoundMvCompQ4(int value)
|
||||
public static int RoundMvCompQ4(int value)
|
||||
{
|
||||
return (value < 0 ? value - 2 : value + 2) / 4;
|
||||
}
|
||||
|
||||
private static Mv MiMvPredQ4(ref ModeInfo mi, int idx)
|
||||
{
|
||||
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),
|
||||
};
|
||||
}
|
||||
|
||||
private static int RoundMvCompQ2(int value)
|
||||
public static int RoundMvCompQ2(int value)
|
||||
{
|
||||
return (value < 0 ? value - 1 : value + 1) / 2;
|
||||
}
|
||||
|
||||
private static Mv MiMvPredQ2(ref ModeInfo mi, int idx, int block0, int block1)
|
||||
{
|
||||
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),
|
||||
};
|
||||
}
|
||||
|
||||
public static Mv ClampMvToUmvBorderSb(ref MacroBlockD xd, ref Mv srcMv, int bw, int bh, int ssX, int ssY)
|
||||
{
|
||||
// If the MV points so far into the UMV border that no visible pixels
|
||||
// are used for reconstruction, the subpel part of the MV can be
|
||||
// discarded and the MV limited to 16 pixels with equivalent results.
|
||||
int spelLeft = (Constants.Vp9InterpExtend + bw) << SubpelBits;
|
||||
int spelLeft = (Constants.InterpExtend + bw) << SubpelBits;
|
||||
int spelRight = spelLeft - SubpelShifts;
|
||||
int spelTop = (Constants.Vp9InterpExtend + bh) << SubpelBits;
|
||||
int spelTop = (Constants.InterpExtend + bh) << SubpelBits;
|
||||
int spelBottom = spelTop - SubpelShifts;
|
||||
Mv clampedMv = new()
|
||||
{
|
||||
Row = (short)(srcMv.Row * (1 << (1 - ssY))),
|
||||
Col = (short)(srcMv.Col * (1 << (1 - ssX))),
|
||||
Row = (short)(srcMv.Row * (1 << (1 - ssY))), Col = (short)(srcMv.Col * (1 << (1 - ssX)))
|
||||
};
|
||||
|
||||
Debug.Assert(ssX <= 1);
|
||||
Debug.Assert(ssY <= 1);
|
||||
|
||||
clampedMv.ClampMv(
|
||||
xd.MbToLeftEdge * (1 << (1 - ssX)) - spelLeft,
|
||||
xd.MbToRightEdge * (1 << (1 - ssX)) + spelRight,
|
||||
xd.MbToTopEdge * (1 << (1 - ssY)) - spelTop,
|
||||
xd.MbToBottomEdge * (1 << (1 - ssY)) + spelBottom);
|
||||
clampedMv.Clamp(
|
||||
(xd.MbToLeftEdge * (1 << (1 - ssX))) - spelLeft,
|
||||
(xd.MbToRightEdge * (1 << (1 - ssX))) + spelRight,
|
||||
(xd.MbToTopEdge * (1 << (1 - ssY))) - spelTop,
|
||||
(xd.MbToBottomEdge * (1 << (1 - ssY))) + spelBottom);
|
||||
|
||||
return clampedMv;
|
||||
}
|
||||
@ -150,18 +123,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
res = mi.Bmi[block].Mv[refr];
|
||||
break;
|
||||
case 1:
|
||||
res = MiMvPredQ2(ref mi, refr, block, block + 2);
|
||||
res = mi.MvPredQ2(refr, block, block + 2);
|
||||
break;
|
||||
case 2:
|
||||
res = MiMvPredQ2(ref mi, refr, block, block + 1);
|
||||
res = mi.MvPredQ2(refr, block, block + 1);
|
||||
break;
|
||||
case 3:
|
||||
res = MiMvPredQ4(ref mi, refr);
|
||||
res = mi.MvPredQ4(refr);
|
||||
break;
|
||||
default:
|
||||
Debug.Assert(ssIdx <= 3 && ssIdx >= 0);
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -169,8 +143,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;
|
||||
return (y * stride) + x;
|
||||
}
|
||||
|
||||
private static void SetupPredPlanes(
|
||||
@ -203,12 +176,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
strides[0] = src.Stride;
|
||||
strides[1] = src.UvStride;
|
||||
strides[2] = src.UvStride;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < Constants.MaxMbPlane; ++i)
|
||||
for (int i = 0; i < Constants.MaxMbPlane; ++i)
|
||||
{
|
||||
ref MacroBlockDPlane pd = ref planes[i];
|
||||
SetupPredPlanes(ref pd.Dst, buffers[i], strides[i], miRow, miCol, Ptr<ScaleFactors>.Null, pd.SubsamplingX, pd.SubsamplingY);
|
||||
SetupPredPlanes(ref pd.Dst, buffers[i], strides[i], miRow, miCol, Ptr<ScaleFactors>.Null,
|
||||
pd.SubsamplingX, pd.SubsamplingY);
|
||||
}
|
||||
}
|
||||
|
||||
@ -230,14 +203,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
strides[0] = src.Stride;
|
||||
strides[1] = src.UvStride;
|
||||
strides[2] = src.UvStride;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < Constants.MaxMbPlane; ++i)
|
||||
for (int i = 0; i < Constants.MaxMbPlane; ++i)
|
||||
{
|
||||
ref MacroBlockDPlane pd = ref xd.Plane[i];
|
||||
SetupPredPlanes(ref pd.Pre[idx], buffers[i], strides[i], miRow, miCol, sf, pd.SubsamplingX, pd.SubsamplingY);
|
||||
SetupPredPlanes(ref pd.Pre[idx], buffers[i], strides[i], miRow, miCol, sf, pd.SubsamplingX,
|
||||
pd.SubsamplingY);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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,15 +18,15 @@ 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;
|
||||
private const int NeedAbove = 1 << 2;
|
||||
private const int NeedAboveRight = 1 << 3;
|
||||
|
||||
private static ReadOnlySpan<byte> ExtendModes => new byte[]
|
||||
{
|
||||
private static ReadOnlySpan<byte> ExtendModes =>
|
||||
[
|
||||
NeedAbove | NeedLeft, // DC
|
||||
NeedAbove, // V
|
||||
NeedLeft, // H
|
||||
@ -35,232 +36,104 @@ 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 =
|
||||
[
|
||||
[null, null, null, null],
|
||||
[VPredictor4X4, VPredictor8X8, VPredictor16X16, VPredictor32X32],
|
||||
[HPredictor4X4, HPredictor8X8, HPredictor16X16, HPredictor32X32],
|
||||
[D45Predictor4X4, D45Predictor8X8, D45Predictor16X16, D45Predictor32X32],
|
||||
[D135Predictor4X4, D135Predictor8X8, D135Predictor16X16, D135Predictor32X32],
|
||||
[D117Predictor4X4, D117Predictor8X8, D117Predictor16X16, D117Predictor32X32],
|
||||
[D153Predictor4X4, D153Predictor8X8, D153Predictor16X16, D153Predictor32X32],
|
||||
[D207Predictor4X4, D207Predictor8X8, D207Predictor16X16, D207Predictor32X32],
|
||||
[D63Predictor4X4, D63Predictor8X8, D63Predictor16X16, D63Predictor32X32],
|
||||
[TmPredictor4X4, TmPredictor8X8, TmPredictor16X16, TmPredictor32X32]
|
||||
];
|
||||
|
||||
private static readonly unsafe IntraPredFn[][][] _dcPred = {
|
||||
new[]
|
||||
{
|
||||
new IntraPredFn[]
|
||||
{
|
||||
Dc128Predictor4x4,
|
||||
Dc128Predictor8x8,
|
||||
Dc128Predictor16x16,
|
||||
Dc128Predictor32x32,
|
||||
},
|
||||
new IntraPredFn[]
|
||||
{
|
||||
DcTopPredictor4x4,
|
||||
DcTopPredictor8x8,
|
||||
DcTopPredictor16x16,
|
||||
DcTopPredictor32x32,
|
||||
},
|
||||
},
|
||||
new[]
|
||||
{
|
||||
new IntraPredFn[]
|
||||
{
|
||||
DcLeftPredictor4x4,
|
||||
DcLeftPredictor8x8,
|
||||
DcLeftPredictor16x16,
|
||||
DcLeftPredictor32x32,
|
||||
},
|
||||
new IntraPredFn[]
|
||||
{
|
||||
DcPredictor4x4,
|
||||
DcPredictor8x8,
|
||||
DcPredictor16x16,
|
||||
DcPredictor32x32,
|
||||
},
|
||||
},
|
||||
};
|
||||
private static readonly unsafe IntraPredFn[][][] _dcPred =
|
||||
[
|
||||
[
|
||||
[
|
||||
Dc128Predictor4X4, Dc128Predictor8X8, Dc128Predictor16X16, Dc128Predictor32X32
|
||||
],
|
||||
[
|
||||
DcTopPredictor4X4, DcTopPredictor8X8, DcTopPredictor16X16, DcTopPredictor32X32
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
DcLeftPredictor4X4, DcLeftPredictor8X8, DcLeftPredictor16X16, DcLeftPredictor32X32
|
||||
],
|
||||
[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 = {
|
||||
new IntraHighPredFn[]
|
||||
{
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
},
|
||||
new IntraHighPredFn[]
|
||||
{
|
||||
HighbdVPredictor4x4,
|
||||
HighbdVPredictor8x8,
|
||||
HighbdVPredictor16x16,
|
||||
HighbdVPredictor32x32,
|
||||
},
|
||||
new IntraHighPredFn[]
|
||||
{
|
||||
HighbdHPredictor4x4,
|
||||
HighbdHPredictor8x8,
|
||||
HighbdHPredictor16x16,
|
||||
HighbdHPredictor32x32,
|
||||
},
|
||||
new IntraHighPredFn[]
|
||||
{
|
||||
HighbdD45Predictor4x4,
|
||||
HighbdD45Predictor8x8,
|
||||
HighbdD45Predictor16x16,
|
||||
HighbdD45Predictor32x32,
|
||||
},
|
||||
new IntraHighPredFn[]
|
||||
{
|
||||
HighbdD135Predictor4x4,
|
||||
HighbdD135Predictor8x8,
|
||||
HighbdD135Predictor16x16,
|
||||
HighbdD135Predictor32x32,
|
||||
},
|
||||
new IntraHighPredFn[]
|
||||
{
|
||||
HighbdD117Predictor4x4,
|
||||
HighbdD117Predictor8x8,
|
||||
HighbdD117Predictor16x16,
|
||||
HighbdD117Predictor32x32,
|
||||
},
|
||||
new IntraHighPredFn[]
|
||||
{
|
||||
HighbdD153Predictor4x4,
|
||||
HighbdD153Predictor8x8,
|
||||
HighbdD153Predictor16x16,
|
||||
HighbdD153Predictor32x32,
|
||||
},
|
||||
new IntraHighPredFn[]
|
||||
{
|
||||
HighbdD207Predictor4x4,
|
||||
HighbdD207Predictor8x8,
|
||||
HighbdD207Predictor16x16,
|
||||
HighbdD207Predictor32x32,
|
||||
},
|
||||
new IntraHighPredFn[]
|
||||
{
|
||||
HighbdD63Predictor4x4,
|
||||
HighbdD63Predictor8x8,
|
||||
HighbdD63Predictor16x16,
|
||||
HighbdD63Predictor32x32,
|
||||
},
|
||||
new IntraHighPredFn[]
|
||||
{
|
||||
HighbdTMPredictor4x4,
|
||||
HighbdTMPredictor8x8,
|
||||
HighbdTMPredictor16x16,
|
||||
HighbdTMPredictor32x32,
|
||||
},
|
||||
};
|
||||
private static readonly unsafe IntraHighPredFn[][] _predHigh =
|
||||
[
|
||||
[null, null, null, null],
|
||||
[
|
||||
HighbdVPredictor4X4, HighbdVPredictor8X8, HighbdVPredictor16X16, HighbdVPredictor32X32
|
||||
],
|
||||
[
|
||||
HighbdHPredictor4X4, HighbdHPredictor8X8, HighbdHPredictor16X16, HighbdHPredictor32X32
|
||||
],
|
||||
[
|
||||
HighbdD45Predictor4X4, HighbdD45Predictor8X8, HighbdD45Predictor16X16, HighbdD45Predictor32X32
|
||||
],
|
||||
[
|
||||
HighbdD135Predictor4X4, HighbdD135Predictor8X8, HighbdD135Predictor16X16,
|
||||
HighbdD135Predictor32X32
|
||||
],
|
||||
[
|
||||
HighbdD117Predictor4X4, HighbdD117Predictor8X8, HighbdD117Predictor16X16,
|
||||
HighbdD117Predictor32X32
|
||||
],
|
||||
[
|
||||
HighbdD153Predictor4X4, HighbdD153Predictor8X8, HighbdD153Predictor16X16,
|
||||
HighbdD153Predictor32X32
|
||||
],
|
||||
[
|
||||
HighbdD207Predictor4X4, HighbdD207Predictor8X8, HighbdD207Predictor16X16,
|
||||
HighbdD207Predictor32X32
|
||||
],
|
||||
[
|
||||
HighbdD63Predictor4X4, HighbdD63Predictor8X8, HighbdD63Predictor16X16, HighbdD63Predictor32X32
|
||||
],
|
||||
[
|
||||
HighbdTmPredictor4X4, HighbdTmPredictor8X8, HighbdTmPredictor16X16, HighbdTmPredictor32X32
|
||||
]
|
||||
];
|
||||
|
||||
private static readonly unsafe IntraHighPredFn[][][] _dcPredHigh = {
|
||||
new[]
|
||||
{
|
||||
new IntraHighPredFn[]
|
||||
{
|
||||
HighbdDc128Predictor4x4,
|
||||
HighbdDc128Predictor8x8,
|
||||
HighbdDc128Predictor16x16,
|
||||
HighbdDc128Predictor32x32,
|
||||
},
|
||||
new IntraHighPredFn[]
|
||||
{
|
||||
HighbdDcTopPredictor4x4,
|
||||
HighbdDcTopPredictor8x8,
|
||||
HighbdDcTopPredictor16x16,
|
||||
HighbdDcTopPredictor32x32,
|
||||
},
|
||||
},
|
||||
new[]
|
||||
{
|
||||
new IntraHighPredFn[]
|
||||
{
|
||||
HighbdDcLeftPredictor4x4,
|
||||
HighbdDcLeftPredictor8x8,
|
||||
HighbdDcLeftPredictor16x16,
|
||||
HighbdDcLeftPredictor32x32,
|
||||
},
|
||||
new IntraHighPredFn[]
|
||||
{
|
||||
HighbdDcPredictor4x4,
|
||||
HighbdDcPredictor8x8,
|
||||
HighbdDcPredictor16x16,
|
||||
HighbdDcPredictor32x32,
|
||||
},
|
||||
},
|
||||
};
|
||||
private static readonly unsafe IntraHighPredFn[][][] _dcPredHigh =
|
||||
[
|
||||
[
|
||||
[
|
||||
HighbdDc128Predictor4X4, HighbdDc128Predictor8X8, HighbdDc128Predictor16X16,
|
||||
HighbdDc128Predictor32X32
|
||||
],
|
||||
[
|
||||
HighbdDcTopPredictor4X4, HighbdDcTopPredictor8X8, HighbdDcTopPredictor16X16,
|
||||
HighbdDcTopPredictor32X32
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
HighbdDcLeftPredictor4X4, HighbdDcLeftPredictor8X8, HighbdDcLeftPredictor16X16,
|
||||
HighbdDcLeftPredictor32X32
|
||||
],
|
||||
[
|
||||
HighbdDcPredictor4X4, HighbdDcPredictor8X8, HighbdDcPredictor16X16,
|
||||
HighbdDcPredictor32X32
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
private static unsafe void BuildIntraPredictorsHigh(
|
||||
ref MacroBlockD xd,
|
||||
@ -327,7 +200,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 +208,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 +222,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 +264,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
MemoryUtil.Copy(aboveRow, aboveRef, bs);
|
||||
}
|
||||
}
|
||||
|
||||
aboveRow[-1] = leftAvailable != 0 ? aboveRef[-1] : (ushort)(baseVal + 1);
|
||||
}
|
||||
else
|
||||
@ -409,7 +283,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 +301,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 +313,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
|
||||
@ -544,7 +419,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 +427,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 +441,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 +483,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
MemoryUtil.Copy(aboveRow, aboveRef, bs);
|
||||
}
|
||||
}
|
||||
|
||||
aboveRow[-1] = leftAvailable != 0 ? aboveRef[-1] : (byte)129;
|
||||
}
|
||||
else
|
||||
@ -626,7 +502,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 +520,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 +532,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 +555,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aboveRow[-1] = leftAvailable != 0 ? aboveRef[-1] : (byte)129;
|
||||
}
|
||||
else
|
||||
@ -716,7 +593,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 +613,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
x,
|
||||
y,
|
||||
plane);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
BuildIntraPredictors(
|
||||
ref xd,
|
||||
refr,
|
||||
@ -755,4 +632,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
plane);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -8,4 +8,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
public ArrayPtr<byte> Data;
|
||||
public int Size;
|
||||
}
|
||||
}
|
||||
}
|
@ -12,9 +12,20 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
|
||||
public int BufEnd;
|
||||
public Reader BitReader;
|
||||
public Vp9BackwardUpdates Counts;
|
||||
|
||||
public MacroBlockD Xd;
|
||||
|
||||
/* dqcoeff are shared by all the planes. So planes must be decoded serially */
|
||||
public Array32<Array32<int>> Dqcoeff;
|
||||
public InternalErrorInfo ErrorInfo;
|
||||
|
||||
public int DecPartitionPlaneContext(int miRow, int miCol, int bsl)
|
||||
{
|
||||
ref sbyte aboveCtx = ref Xd.AboveSegContext[miCol];
|
||||
ref sbyte leftCtx = ref Xd.LeftSegContext[miRow & Constants.MiMask];
|
||||
int above = (aboveCtx >> bsl) & 1, left = (leftCtx >> bsl) & 1;
|
||||
|
||||
return (left * 2) + above + (bsl * Constants.PartitionPloffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -7,4 +7,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
public PredictionMode Mode;
|
||||
public Array2<Mv> Mv; // First, second inter predictor motion vectors
|
||||
}
|
||||
}
|
||||
}
|
11
src/Ryujinx.Graphics.Nvdec.Vp9/Types/BitstreamProfile.cs
Normal file
11
src/Ryujinx.Graphics.Nvdec.Vp9/Types/BitstreamProfile.cs
Normal file
@ -0,0 +1,11 @@
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
{
|
||||
public enum BitstreamProfile
|
||||
{
|
||||
Profile0,
|
||||
Profile1,
|
||||
Profile2,
|
||||
Profile3,
|
||||
MaxProfiles
|
||||
}
|
||||
}
|
@ -1,21 +1,21 @@
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
{
|
||||
internal enum BlockSize
|
||||
{
|
||||
Block4x4 = 0,
|
||||
Block4x8 = 1,
|
||||
Block8x4 = 2,
|
||||
Block8x8 = 3,
|
||||
Block8x16 = 4,
|
||||
Block16x8 = 5,
|
||||
Block16x16 = 6,
|
||||
Block16x32 = 7,
|
||||
Block32x16 = 8,
|
||||
Block32x32 = 9,
|
||||
Block32x64 = 10,
|
||||
Block64x32 = 11,
|
||||
Block64x64 = 12,
|
||||
BlockSizes = 13,
|
||||
BlockInvalid = BlockSizes,
|
||||
Block4X4,
|
||||
Block4X8,
|
||||
Block8X4,
|
||||
Block8X8,
|
||||
Block8X16,
|
||||
Block16X8,
|
||||
Block16X16,
|
||||
Block16X32,
|
||||
Block32X16,
|
||||
Block32X32,
|
||||
Block32X64,
|
||||
Block64X32,
|
||||
Block64X64,
|
||||
BlockSizes,
|
||||
BlockInvalid = BlockSizes
|
||||
}
|
||||
}
|
||||
}
|
@ -7,4 +7,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
public ArrayPtr<byte> Buf;
|
||||
public int Stride;
|
||||
}
|
||||
}
|
||||
}
|
18
src/Ryujinx.Graphics.Nvdec.Vp9/Types/BufferPool.cs
Normal file
18
src/Ryujinx.Graphics.Nvdec.Vp9/Types/BufferPool.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using Ryujinx.Common.Memory;
|
||||
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
{
|
||||
internal struct BufferPool
|
||||
{
|
||||
// Private data associated with the frame buffer callbacks.
|
||||
public Ptr<InternalFrameBufferList> CbPriv;
|
||||
|
||||
// vpx_get_frame_buffer_cb_fn_t get_fb_cb;
|
||||
// vpx_release_frame_buffer_cb_fn_t release_fb_cb;
|
||||
|
||||
public Array12<RefCntBuffer> FrameBufs;
|
||||
|
||||
// Frame buffers allocated internally by the codec.
|
||||
public InternalFrameBufferList IntFrameBuffers;
|
||||
}
|
||||
}
|
@ -5,4 +5,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
KeyFrame = 0,
|
||||
InterFrame = 1,
|
||||
}
|
||||
}
|
||||
}
|
@ -23,5 +23,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
|
||||
public ArrayPtr<LoopFilterMask> Lfm;
|
||||
public int LfmStride;
|
||||
|
||||
public void SetDefaultLfDeltas()
|
||||
{
|
||||
ModeRefDeltaEnabled = true;
|
||||
ModeRefDeltaUpdate = true;
|
||||
|
||||
RefDeltas[Constants.IntraFrame] = 1;
|
||||
RefDeltas[Constants.LastFrame] = 0;
|
||||
RefDeltas[Constants.GoldenFrame] = -1;
|
||||
RefDeltas[Constants.AltRefFrame] = -1;
|
||||
ModeDeltas[0] = 0;
|
||||
ModeDeltas[1] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -7,4 +7,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
public Array64<LoopFilterThresh> Lfthr;
|
||||
public Array8<Array4<Array2<byte>>> Lvl;
|
||||
}
|
||||
}
|
||||
}
|
@ -15,10 +15,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
{
|
||||
public Array4<ulong> LeftY;
|
||||
public Array4<ulong> AboveY;
|
||||
public ulong Int4x4Y;
|
||||
public ulong Int4X4Y;
|
||||
public Array4<ushort> LeftUv;
|
||||
public Array4<ushort> AboveUv;
|
||||
public ushort Int4x4Uv;
|
||||
public ushort Int4X4Uv;
|
||||
public Array64<byte> LflY;
|
||||
}
|
||||
}
|
||||
}
|
@ -12,4 +12,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
public Array16<byte> HevThr;
|
||||
#pragma warning restore CS0649
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Graphics.Nvdec.Vp9.Common;
|
||||
using Ryujinx.Graphics.Video;
|
||||
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
@ -54,7 +55,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
|
||||
public Ptr<InternalErrorInfo> ErrorInfo;
|
||||
|
||||
public readonly int GetPredContextSegId()
|
||||
public int GetPredContextSegId()
|
||||
{
|
||||
sbyte aboveSip = !AboveMi.IsNull ? AboveMi.Value.SegIdPredicted : (sbyte)0;
|
||||
sbyte leftSip = !LeftMi.IsNull ? LeftMi.Value.SegIdPredicted : (sbyte)0;
|
||||
@ -62,15 +63,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
return aboveSip + leftSip;
|
||||
}
|
||||
|
||||
public readonly int GetSkipContext()
|
||||
public int GetSkipContext()
|
||||
{
|
||||
int aboveSkip = !AboveMi.IsNull ? AboveMi.Value.Skip : 0;
|
||||
int leftSkip = !LeftMi.IsNull ? LeftMi.Value.Skip : 0;
|
||||
|
||||
return aboveSkip + leftSkip;
|
||||
}
|
||||
|
||||
public readonly int GetPredContextSwitchableInterp()
|
||||
public int GetPredContextSwitchableInterp()
|
||||
{
|
||||
// Note:
|
||||
// The mode info data structure has a one element border above and to the
|
||||
@ -83,18 +83,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
{
|
||||
return leftType;
|
||||
}
|
||||
else if (leftType == Constants.SwitchableFilters)
|
||||
|
||||
if (leftType == Constants.SwitchableFilters)
|
||||
{
|
||||
return aboveType;
|
||||
}
|
||||
else if (aboveType == Constants.SwitchableFilters)
|
||||
|
||||
if (aboveType == Constants.SwitchableFilters)
|
||||
{
|
||||
return leftType;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Constants.SwitchableFilters;
|
||||
}
|
||||
|
||||
return Constants.SwitchableFilters;
|
||||
}
|
||||
|
||||
// The mode info data structure has a one element border above and to the
|
||||
@ -104,20 +104,22 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
// 1 - intra/inter, inter/intra
|
||||
// 2 - intra/--, --/intra
|
||||
// 3 - intra/intra
|
||||
public readonly int GetIntraInterContext()
|
||||
public 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);
|
||||
return leftIntra && aboveIntra ? 3 : leftIntra || aboveIntra ? 1 : 0;
|
||||
}
|
||||
|
||||
if (!AboveMi.IsNull || !LeftMi.IsNull)
|
||||
{ // One edge available
|
||||
{
|
||||
// One edge available
|
||||
return 2 * (!(!AboveMi.IsNull ? AboveMi.Value : LeftMi.Value).IsInterBlock() ? 1 : 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -125,11 +127,11 @@ 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 readonly int GetTxSizeContext()
|
||||
public 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;
|
||||
int leftCtx = (!LeftMi.IsNull && LeftMi.Value.Skip == 0) ? (int)LeftMi.Value.TxSize : maxTxSize;
|
||||
int aboveCtx = !AboveMi.IsNull && AboveMi.Value.Skip == 0 ? (int)AboveMi.Value.TxSize : maxTxSize;
|
||||
int leftCtx = !LeftMi.IsNull && LeftMi.Value.Skip == 0 ? (int)LeftMi.Value.TxSize : maxTxSize;
|
||||
if (LeftMi.IsNull)
|
||||
{
|
||||
leftCtx = aboveCtx;
|
||||
@ -140,14 +142,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
aboveCtx = leftCtx;
|
||||
}
|
||||
|
||||
return (aboveCtx + leftCtx) > maxTxSize ? 1 : 0;
|
||||
return aboveCtx + leftCtx > maxTxSize ? 1 : 0;
|
||||
}
|
||||
|
||||
public void SetupBlockPlanes(int ssX, int ssY)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < Constants.MaxMbPlane; i++)
|
||||
for (int i = 0; i < Constants.MaxMbPlane; i++)
|
||||
{
|
||||
Plane[i].SubsamplingX = i != 0 ? ssX : 0;
|
||||
Plane[i].SubsamplingY = i != 0 ? ssY : 0;
|
||||
@ -158,25 +158,36 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
{
|
||||
int aboveIdx = miCol * 2;
|
||||
int leftIdx = (miRow * 2) & 15;
|
||||
int i;
|
||||
for (i = 0; i < Constants.MaxMbPlane; ++i)
|
||||
|
||||
for (int i = 0; i < Constants.MaxMbPlane; ++i)
|
||||
{
|
||||
ref MacroBlockDPlane pd = ref Plane[i];
|
||||
pd.AboveContext = AboveContext[i].Slice(aboveIdx >> pd.SubsamplingX);
|
||||
pd.LeftContext = new ArrayPtr<sbyte>(ref LeftContext[i][leftIdx >> pd.SubsamplingY], 16 - (leftIdx >> pd.SubsamplingY));
|
||||
pd.LeftContext = new ArrayPtr<sbyte>(ref LeftContext[i][leftIdx >> pd.SubsamplingY],
|
||||
16 - (leftIdx >> pd.SubsamplingY));
|
||||
}
|
||||
}
|
||||
|
||||
internal void SetMiRowCol(ref TileInfo tile, int miRow, int bh, int miCol, int bw, int miRows, int miCols)
|
||||
{
|
||||
MbToTopEdge = -((miRow * Constants.MiSize) * 8);
|
||||
MbToBottomEdge = ((miRows - bh - miRow) * Constants.MiSize) * 8;
|
||||
MbToLeftEdge = -((miCol * Constants.MiSize) * 8);
|
||||
MbToRightEdge = ((miCols - bw - miCol) * Constants.MiSize) * 8;
|
||||
MbToTopEdge = -(miRow * Constants.MiSize * 8);
|
||||
MbToBottomEdge = (miRows - bh - miRow) * Constants.MiSize * 8;
|
||||
MbToLeftEdge = -(miCol * Constants.MiSize * 8);
|
||||
MbToRightEdge = (miCols - bw - miCol) * Constants.MiSize * 8;
|
||||
|
||||
// Are edges available for intra prediction?
|
||||
AboveMi = (miRow != 0) ? Mi[-MiStride] : Ptr<ModeInfo>.Null;
|
||||
LeftMi = (miCol > tile.MiColStart) ? Mi[-1] : Ptr<ModeInfo>.Null;
|
||||
AboveMi = miRow != 0 ? Mi[-MiStride] : Ptr<ModeInfo>.Null;
|
||||
LeftMi = miCol > tile.MiColStart ? Mi[-1] : Ptr<ModeInfo>.Null;
|
||||
}
|
||||
|
||||
public unsafe void DecResetSkipContext()
|
||||
{
|
||||
for (int i = 0; i < Constants.MaxMbPlane; i++)
|
||||
{
|
||||
ref MacroBlockDPlane pd = ref Plane[i];
|
||||
MemoryUtil.Fill(pd.AboveContext.ToPointer(), (sbyte)0, pd.N4W);
|
||||
MemoryUtil.Fill(pd.LeftContext.ToPointer(), (sbyte)0, pd.N4H);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -15,7 +15,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
|
||||
// Number of 4x4s in current block
|
||||
public ushort N4W, N4H;
|
||||
|
||||
// Log2 of N4W, N4H
|
||||
public byte N4Wl, N4Hl;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Common.Memory;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
@ -29,14 +29,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
|
||||
public PredictionMode GetYMode(int block)
|
||||
{
|
||||
return SbType < BlockSize.Block8x8 ? Bmi[block].Mode : Mode;
|
||||
return SbType < BlockSize.Block8X8 ? Bmi[block].Mode : Mode;
|
||||
}
|
||||
|
||||
public readonly TxSize GetUvTxSize(ref MacroBlockDPlane pd)
|
||||
public TxSize GetUvTxSize(ref MacroBlockDPlane pd)
|
||||
{
|
||||
Debug.Assert(SbType < BlockSize.Block8x8 ||
|
||||
Luts.SsSizeLookup[(int)SbType][pd.SubsamplingX][pd.SubsamplingY] != BlockSize.BlockInvalid);
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
@ -50,17 +49,59 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
return RefFrame[1] > Constants.IntraFrame;
|
||||
}
|
||||
|
||||
private static readonly int[][] _idxNColumnToSubblock = {
|
||||
new[] { 1, 2 }, new[] { 1, 3 }, new[] { 3, 2 }, new[] { 3, 3 },
|
||||
};
|
||||
private static readonly int[][] _idxNColumnToSubblock =
|
||||
[
|
||||
[1, 2], [1, 3], [3, 2], [3, 3]
|
||||
];
|
||||
|
||||
// This function returns either the appropriate sub block or block's mv
|
||||
// on whether the block_size < 8x8 and we have check_sub_blocks set.
|
||||
public Mv GetSubBlockMv(int whichMv, int searchCol, int blockIdx)
|
||||
{
|
||||
return blockIdx >= 0 && SbType < BlockSize.Block8x8
|
||||
return blockIdx >= 0 && SbType < BlockSize.Block8X8
|
||||
? Bmi[_idxNColumnToSubblock[blockIdx][searchCol == 0 ? 1 : 0]].Mv[whichMv]
|
||||
: Mv[whichMv];
|
||||
}
|
||||
|
||||
public Mv MvPredQ4(int idx)
|
||||
{
|
||||
Mv res = new()
|
||||
{
|
||||
Row = (short)ReconInter.RoundMvCompQ4(
|
||||
Bmi[0].Mv[idx].Row + Bmi[1].Mv[idx].Row +
|
||||
Bmi[2].Mv[idx].Row + Bmi[3].Mv[idx].Row),
|
||||
Col = (short)ReconInter.RoundMvCompQ4(
|
||||
Bmi[0].Mv[idx].Col + Bmi[1].Mv[idx].Col +
|
||||
Bmi[2].Mv[idx].Col + Bmi[3].Mv[idx].Col)
|
||||
};
|
||||
return res;
|
||||
}
|
||||
|
||||
public Mv MvPredQ2(int idx, int block0, int block1)
|
||||
{
|
||||
Mv res = new()
|
||||
{
|
||||
Row = (short)ReconInter.RoundMvCompQ2(
|
||||
Bmi[block0].Mv[idx].Row +
|
||||
Bmi[block1].Mv[idx].Row),
|
||||
Col = (short)ReconInter.RoundMvCompQ2(
|
||||
Bmi[block0].Mv[idx].Col +
|
||||
Bmi[block1].Mv[idx].Col)
|
||||
};
|
||||
return res;
|
||||
}
|
||||
|
||||
// Performs mv sign inversion if indicated by the reference frame combination.
|
||||
public Mv ScaleMv(int refr, sbyte thisRefFrame, ref Array4<sbyte> refSignBias)
|
||||
{
|
||||
Mv mv = Mv[refr];
|
||||
if (refSignBias[RefFrame[refr]] != refSignBias[thisRefFrame])
|
||||
{
|
||||
mv.Row *= -1;
|
||||
mv.Col *= -1;
|
||||
}
|
||||
|
||||
return mv;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -11,4 +11,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
BothIntra = 6,
|
||||
InvalidCase = 9,
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Graphics.Video;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
@ -10,98 +10,88 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
public short Row;
|
||||
public short Col;
|
||||
|
||||
private static ReadOnlySpan<byte> LogInBase2 => new byte[]
|
||||
{
|
||||
0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 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, 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, 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, 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, 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, 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,
|
||||
};
|
||||
private static ReadOnlySpan<byte> LogInBase2 =>
|
||||
[
|
||||
0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 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, 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, 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, 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, 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, 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
|
||||
];
|
||||
|
||||
public readonly bool UseMvHp()
|
||||
public bool UseHp()
|
||||
{
|
||||
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)
|
||||
public static bool JointVertical(MvJointType type)
|
||||
{
|
||||
return type == MvJointType.MvJointHzvnz || type == MvJointType.MvJointHnzvnz;
|
||||
return type == MvJointType.Hzvnz || type == MvJointType.Hnzvnz;
|
||||
}
|
||||
|
||||
public static bool MvJointHorizontal(MvJointType type)
|
||||
public static bool JointHorizontal(MvJointType type)
|
||||
{
|
||||
return type == MvJointType.MvJointHnzvz || type == MvJointType.MvJointHnzvnz;
|
||||
return type == MvJointType.Hnzvz || type == MvJointType.Hnzvnz;
|
||||
}
|
||||
|
||||
private static int MvClassBase(MvClassType c)
|
||||
private static int ClassBase(MvClassType c)
|
||||
{
|
||||
return c != 0 ? Constants.Class0Size << ((int)c + 2) : 0;
|
||||
}
|
||||
|
||||
private static MvClassType GetMvClass(int z, Ptr<int> offset)
|
||||
private static MvClassType GetClass(int z, Ptr<int> offset)
|
||||
{
|
||||
MvClassType c = (z >= Constants.Class0Size * 4096) ? MvClassType.MvClass10 : (MvClassType)LogInBase2[z >> 3];
|
||||
MvClassType c = z >= Constants.Class0Size * 4096 ? MvClassType.Class10 : (MvClassType)LogInBase2[z >> 3];
|
||||
if (!offset.IsNull)
|
||||
{
|
||||
offset.Value = z - MvClassBase(c);
|
||||
offset.Value = z - ClassBase(c);
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
private static void IncMvComponent(int v, ref Vp9BackwardUpdates counts, int comp, int incr, int usehp)
|
||||
private static void IncComponent(int v, ref Vp9BackwardUpdates counts, int comp, int incr, int usehp)
|
||||
{
|
||||
int s, z, c, o = 0, d, e, f;
|
||||
int o = 0;
|
||||
Debug.Assert(v != 0); /* Should not be zero */
|
||||
s = v < 0 ? 1 : 0;
|
||||
int s = v < 0 ? 1 : 0;
|
||||
counts.Sign[comp][s] += (uint)incr;
|
||||
z = (s != 0 ? -v : v) - 1; /* Magnitude - 1 */
|
||||
int z = (s != 0 ? -v : v) - 1 /* Magnitude - 1 */;
|
||||
|
||||
c = (int)GetMvClass(z, new Ptr<int>(ref o));
|
||||
int c = (int)GetClass(z, new Ptr<int>(ref o));
|
||||
counts.Classes[comp][c] += (uint)incr;
|
||||
|
||||
d = (o >> 3); /* Int mv data */
|
||||
f = (o >> 1) & 3; /* Fractional pel mv data */
|
||||
e = (o & 1); /* High precision mv data */
|
||||
int d = o >> 3 /* Int mv data */;
|
||||
int f = (o >> 1) & 3 /* Fractional pel mv data */;
|
||||
int e = o & 1 /* High precision mv data */;
|
||||
|
||||
if (c == (int)MvClassType.MvClass0)
|
||||
if (c == (int)MvClassType.Class0)
|
||||
{
|
||||
counts.Class0[comp][d] += (uint)incr;
|
||||
counts.Class0Fp[comp][d][f] += (uint)incr;
|
||||
@ -109,11 +99,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
int b = c + Constants.Class0Bits - 1; // Number of bits
|
||||
for (i = 0; i < b; ++i)
|
||||
for (int i = 0; i < b; ++i)
|
||||
{
|
||||
counts.Bits[comp][i][((d >> i) & 1)] += (uint)incr;
|
||||
counts.Bits[comp][i][(d >> i) & 1] += (uint)incr;
|
||||
}
|
||||
|
||||
counts.Fp[comp][f] += (uint)incr;
|
||||
@ -121,56 +110,56 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
}
|
||||
}
|
||||
|
||||
private readonly MvJointType GetMvJoint()
|
||||
public MvJointType GetJoint()
|
||||
{
|
||||
if (Row == 0)
|
||||
{
|
||||
return Col == 0 ? MvJointType.MvJointZero : MvJointType.MvJointHnzvz;
|
||||
return Col == 0 ? MvJointType.Zero : MvJointType.Hnzvz;
|
||||
}
|
||||
|
||||
return Col == 0 ? MvJointType.MvJointHzvnz : MvJointType.MvJointHnzvnz;
|
||||
return Col == 0 ? MvJointType.Hzvnz : MvJointType.Hnzvnz;
|
||||
}
|
||||
|
||||
internal readonly void IncMv(Ptr<Vp9BackwardUpdates> counts)
|
||||
internal void Inc(Ptr<Vp9BackwardUpdates> counts)
|
||||
{
|
||||
if (!counts.IsNull)
|
||||
{
|
||||
MvJointType j = GetMvJoint();
|
||||
MvJointType j = GetJoint();
|
||||
++counts.Value.Joints[(int)j];
|
||||
|
||||
if (MvJointVertical(j))
|
||||
if (JointVertical(j))
|
||||
{
|
||||
IncMvComponent(Row, ref counts.Value, 0, 1, 1);
|
||||
IncComponent(Row, ref counts.Value, 0, 1, 1);
|
||||
}
|
||||
|
||||
if (MvJointHorizontal(j))
|
||||
if (JointHorizontal(j))
|
||||
{
|
||||
IncMvComponent(Col, ref counts.Value, 1, 1, 1);
|
||||
IncComponent(Col, ref counts.Value, 1, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ClampMv(int minCol, int maxCol, int minRow, int maxRow)
|
||||
public void Clamp(int minCol, int maxCol, int minRow, int maxRow)
|
||||
{
|
||||
Col = (short)Math.Clamp(Col, minCol, maxCol);
|
||||
Row = (short)Math.Clamp(Row, minRow, maxRow);
|
||||
}
|
||||
|
||||
private const int MvBorder = (16 << 3); // Allow 16 pels in 1/8th pel units
|
||||
private const int Border = 16 << 3; // Allow 16 pels in 1/8th pel units
|
||||
|
||||
public void ClampMvRef(ref MacroBlockD xd)
|
||||
public void ClampRef(ref MacroBlockD xd)
|
||||
{
|
||||
ClampMv(
|
||||
xd.MbToLeftEdge - MvBorder,
|
||||
xd.MbToRightEdge + MvBorder,
|
||||
xd.MbToTopEdge - MvBorder,
|
||||
xd.MbToBottomEdge + MvBorder);
|
||||
Clamp(
|
||||
xd.MbToLeftEdge - Border,
|
||||
xd.MbToRightEdge + Border,
|
||||
xd.MbToTopEdge - Border,
|
||||
xd.MbToBottomEdge + Border);
|
||||
}
|
||||
|
||||
public void LowerMvPrecision(bool allowHP)
|
||||
public void LowerPrecision(bool allowHp)
|
||||
{
|
||||
bool useHP = allowHP && UseMvHp();
|
||||
if (!useHP)
|
||||
bool useHp = allowHp && UseHp();
|
||||
if (!useHp)
|
||||
{
|
||||
if ((Row & 1) != 0)
|
||||
{
|
||||
@ -183,5 +172,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsValid()
|
||||
{
|
||||
return Row is > Constants.MvLow and < Constants.MvUpp &&
|
||||
Col is > Constants.MvLow and < Constants.MvUpp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -5,4 +5,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
public int Row;
|
||||
public int Col;
|
||||
}
|
||||
}
|
||||
}
|
@ -2,16 +2,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
{
|
||||
internal enum MvClassType
|
||||
{
|
||||
MvClass0 = 0, /* (0, 2] integer pel */
|
||||
MvClass1 = 1, /* (2, 4] integer pel */
|
||||
MvClass2 = 2, /* (4, 8] integer pel */
|
||||
MvClass3 = 3, /* (8, 16] integer pel */
|
||||
MvClass4 = 4, /* (16, 32] integer pel */
|
||||
MvClass5 = 5, /* (32, 64] integer pel */
|
||||
MvClass6 = 6, /* (64, 128] integer pel */
|
||||
MvClass7 = 7, /* (128, 256] integer pel */
|
||||
MvClass8 = 8, /* (256, 512] integer pel */
|
||||
MvClass9 = 9, /* (512, 1024] integer pel */
|
||||
MvClass10 = 10, /* (1024,2048] integer pel */
|
||||
Class0, /* (0, 2] integer pel */
|
||||
Class1, /* (2, 4] integer pel */
|
||||
Class2, /* (4, 8] integer pel */
|
||||
Class3, /* (8, 16] integer pel */
|
||||
Class4, /* (16, 32] integer pel */
|
||||
Class5, /* (32, 64] integer pel */
|
||||
Class6, /* (64, 128] integer pel */
|
||||
Class7, /* (128, 256] integer pel */
|
||||
Class8, /* (256, 512] integer pel */
|
||||
Class9, /* (512, 1024] integer pel */
|
||||
Class10 /* (1024,2048] integer pel */
|
||||
}
|
||||
}
|
||||
}
|
@ -2,9 +2,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
{
|
||||
internal enum MvJointType
|
||||
{
|
||||
MvJointZero = 0, /* Zero vector */
|
||||
MvJointHnzvz = 1, /* Vert zero, hor nonzero */
|
||||
MvJointHzvnz = 2, /* Hor zero, vert nonzero */
|
||||
MvJointHnzvnz = 3, /* Both components nonzero */
|
||||
Zero, /* Zero vector */
|
||||
Hnzvz, /* Vert zero, hor nonzero */
|
||||
Hzvnz, /* Hor zero, vert nonzero */
|
||||
Hnzvnz /* Both components nonzero */
|
||||
}
|
||||
}
|
||||
}
|
@ -7,4 +7,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
public Array2<Mv> Mv;
|
||||
public Array2<sbyte> RefFrame;
|
||||
}
|
||||
}
|
||||
}
|
@ -9,4 +9,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
PartitionTypes,
|
||||
PartitionInvalid = PartitionTypes,
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
{
|
||||
internal enum PlaneType
|
||||
{
|
||||
Y = 0,
|
||||
Uv = 1,
|
||||
PlaneTypes,
|
||||
Y,
|
||||
Uv,
|
||||
PlaneTypes
|
||||
}
|
||||
}
|
||||
}
|
@ -11,4 +11,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
Col = col;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,21 +1,21 @@
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
{
|
||||
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
|
||||
NearestMv = 10,
|
||||
NearMv = 11,
|
||||
ZeroMv = 12,
|
||||
NewMv = 13,
|
||||
MbModeCount = 14,
|
||||
DcPred, // Average of above and left pixels
|
||||
VPred, // Vertical
|
||||
HPred, // Horizontal
|
||||
D45Pred, // Directional 45 deg = round(arctan(1 / 1) * 180 / pi)
|
||||
D135Pred, // Directional 135 deg = 180 - 45
|
||||
D117Pred, // Directional 117 deg = 180 - 63
|
||||
D153Pred, // Directional 153 deg = 180 - 27
|
||||
D207Pred, // Directional 207 deg = 180 + 27
|
||||
D63Pred, // Directional 63 deg = round(arctan(2 / 1) * 180 / pi)
|
||||
TmPred, // True-motion
|
||||
NearestMv,
|
||||
NearMv,
|
||||
ZeroMv,
|
||||
NewMv,
|
||||
MbModeCount
|
||||
}
|
||||
}
|
||||
}
|
@ -2,7 +2,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
{
|
||||
internal struct RefBuffer
|
||||
{
|
||||
public const int InvalidIdx = -1; // Invalid buffer index.
|
||||
|
||||
public int Idx;
|
||||
public Surface Buf;
|
||||
public ScaleFactors Sf;
|
||||
}
|
||||
}
|
||||
}
|
12
src/Ryujinx.Graphics.Nvdec.Vp9/Types/RefCntBuffer.cs
Normal file
12
src/Ryujinx.Graphics.Nvdec.Vp9/Types/RefCntBuffer.cs
Normal file
@ -0,0 +1,12 @@
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
{
|
||||
internal struct RefCntBuffer
|
||||
{
|
||||
public int RefCount;
|
||||
public int MiRows;
|
||||
public int MiCols;
|
||||
public byte Released;
|
||||
public VpxCodecFrameBuffer RawFrameBuffer;
|
||||
public Surface Buf;
|
||||
}
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
{
|
||||
internal enum ReferenceMode
|
||||
{
|
||||
SingleReference = 0,
|
||||
CompoundReference = 1,
|
||||
ReferenceModeSelect = 2,
|
||||
ReferenceModes = 3,
|
||||
Single,
|
||||
Compound,
|
||||
Select,
|
||||
ReferenceModes
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Common.Memory;
|
||||
using System.Runtime.CompilerServices;
|
||||
using static Ryujinx.Graphics.Nvdec.Vp9.Dsp.Convolve;
|
||||
using static Ryujinx.Graphics.Nvdec.Vp9.Dsp.Filter;
|
||||
@ -8,7 +8,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
internal struct ScaleFactors
|
||||
{
|
||||
private const int RefScaleShift = 14;
|
||||
private const int RefNoScale = (1 << RefScaleShift);
|
||||
private const int RefNoScale = 1 << RefScaleShift;
|
||||
private const int RefInvalidScale = -1;
|
||||
|
||||
private unsafe delegate void ConvolveFn(
|
||||
@ -38,255 +38,103 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
int h,
|
||||
int bd);
|
||||
|
||||
private static readonly unsafe ConvolveFn[][][] _predictX16Y16 = {
|
||||
new[]
|
||||
{
|
||||
new ConvolveFn[]
|
||||
{
|
||||
ConvolveCopy,
|
||||
ConvolveAvg,
|
||||
},
|
||||
new ConvolveFn[]
|
||||
{
|
||||
Convolve8Vert,
|
||||
Convolve8AvgVert,
|
||||
},
|
||||
},
|
||||
new[]
|
||||
{
|
||||
new ConvolveFn[]
|
||||
{
|
||||
Convolve8Horiz,
|
||||
Convolve8AvgHoriz,
|
||||
},
|
||||
new ConvolveFn[]
|
||||
{
|
||||
Convolve8,
|
||||
Convolve8Avg,
|
||||
},
|
||||
},
|
||||
};
|
||||
private static readonly unsafe ConvolveFn[][][] _predictX16Y16 =
|
||||
[
|
||||
[
|
||||
[ConvolveCopy, ConvolveAvg],
|
||||
[Convolve8Vert, Convolve8AvgVert]
|
||||
],
|
||||
[
|
||||
[Convolve8Horiz, Convolve8AvgHoriz],
|
||||
[Convolve8, Convolve8Avg]
|
||||
]
|
||||
];
|
||||
|
||||
private static readonly unsafe ConvolveFn[][][] _predictX16 = {
|
||||
new[]
|
||||
{
|
||||
new ConvolveFn[]
|
||||
{
|
||||
ScaledVert,
|
||||
ScaledAvgVert,
|
||||
},
|
||||
new ConvolveFn[]
|
||||
{
|
||||
ScaledVert,
|
||||
ScaledAvgVert,
|
||||
},
|
||||
},
|
||||
new[]
|
||||
{
|
||||
new ConvolveFn[]
|
||||
{
|
||||
Scaled2D,
|
||||
ScaledAvg2D,
|
||||
},
|
||||
new ConvolveFn[]
|
||||
{
|
||||
Scaled2D,
|
||||
ScaledAvg2D,
|
||||
},
|
||||
},
|
||||
};
|
||||
private static readonly unsafe ConvolveFn[][][] _predictX16 =
|
||||
[
|
||||
[
|
||||
[ScaledVert, ScaledAvgVert], [ScaledVert, ScaledAvgVert]
|
||||
],
|
||||
[[Scaled2D, ScaledAvg2D], [Scaled2D, ScaledAvg2D]]
|
||||
];
|
||||
|
||||
private static readonly unsafe ConvolveFn[][][] _predictY16 = {
|
||||
new[]
|
||||
{
|
||||
new ConvolveFn[]
|
||||
{
|
||||
ScaledHoriz,
|
||||
ScaledAvgHoriz,
|
||||
},
|
||||
new ConvolveFn[]
|
||||
{
|
||||
Scaled2D,
|
||||
ScaledAvg2D,
|
||||
},
|
||||
},
|
||||
new[]
|
||||
{
|
||||
new ConvolveFn[]
|
||||
{
|
||||
ScaledHoriz,
|
||||
ScaledAvgHoriz,
|
||||
},
|
||||
new ConvolveFn[]
|
||||
{
|
||||
Scaled2D,
|
||||
ScaledAvg2D,
|
||||
},
|
||||
},
|
||||
};
|
||||
private static readonly unsafe ConvolveFn[][][] _predictY16 =
|
||||
[
|
||||
[[ScaledHoriz, ScaledAvgHoriz], [Scaled2D, ScaledAvg2D]],
|
||||
[[ScaledHoriz, ScaledAvgHoriz], [Scaled2D, ScaledAvg2D]]
|
||||
];
|
||||
|
||||
private static readonly unsafe ConvolveFn[][][] _predict = {
|
||||
new[]
|
||||
{
|
||||
new ConvolveFn[]
|
||||
{
|
||||
Scaled2D,
|
||||
ScaledAvg2D,
|
||||
},
|
||||
new ConvolveFn[]
|
||||
{
|
||||
Scaled2D,
|
||||
ScaledAvg2D,
|
||||
},
|
||||
},
|
||||
new[]
|
||||
{
|
||||
new ConvolveFn[]
|
||||
{
|
||||
Scaled2D,
|
||||
ScaledAvg2D,
|
||||
},
|
||||
new ConvolveFn[]
|
||||
{
|
||||
Scaled2D,
|
||||
ScaledAvg2D,
|
||||
},
|
||||
},
|
||||
};
|
||||
private static readonly unsafe ConvolveFn[][][] _predict =
|
||||
[
|
||||
[[Scaled2D, ScaledAvg2D], [Scaled2D, ScaledAvg2D]],
|
||||
[[Scaled2D, ScaledAvg2D], [Scaled2D, ScaledAvg2D]]
|
||||
];
|
||||
|
||||
private static readonly unsafe HighbdConvolveFn[][][] _highbdPredictX16Y16 = {
|
||||
new[]
|
||||
{
|
||||
new HighbdConvolveFn[]
|
||||
{
|
||||
HighbdConvolveCopy,
|
||||
HighbdConvolveAvg,
|
||||
},
|
||||
new HighbdConvolveFn[]
|
||||
{
|
||||
HighbdConvolve8Vert,
|
||||
HighbdConvolve8AvgVert,
|
||||
},
|
||||
},
|
||||
new[]
|
||||
{
|
||||
new HighbdConvolveFn[]
|
||||
{
|
||||
HighbdConvolve8Horiz,
|
||||
HighbdConvolve8AvgHoriz,
|
||||
},
|
||||
new HighbdConvolveFn[]
|
||||
{
|
||||
HighbdConvolve8,
|
||||
HighbdConvolve8Avg,
|
||||
},
|
||||
},
|
||||
};
|
||||
private static readonly unsafe HighbdConvolveFn[][][] _highbdPredictX16Y16 =
|
||||
[
|
||||
[
|
||||
[HighbdConvolveCopy, HighbdConvolveAvg],
|
||||
[HighbdConvolve8Vert, HighbdConvolve8AvgVert]
|
||||
],
|
||||
[
|
||||
[HighbdConvolve8Horiz, HighbdConvolve8AvgHoriz],
|
||||
[HighbdConvolve8, HighbdConvolve8Avg]
|
||||
]
|
||||
];
|
||||
|
||||
private static readonly unsafe HighbdConvolveFn[][][] _highbdPredictX16 = {
|
||||
new[]
|
||||
{
|
||||
new HighbdConvolveFn[]
|
||||
{
|
||||
HighbdConvolve8Vert,
|
||||
HighbdConvolve8AvgVert,
|
||||
},
|
||||
new HighbdConvolveFn[]
|
||||
{
|
||||
HighbdConvolve8Vert,
|
||||
HighbdConvolve8AvgVert,
|
||||
},
|
||||
},
|
||||
new[]
|
||||
{
|
||||
new HighbdConvolveFn[]
|
||||
{
|
||||
HighbdConvolve8,
|
||||
HighbdConvolve8Avg,
|
||||
},
|
||||
new HighbdConvolveFn[]
|
||||
{
|
||||
HighbdConvolve8,
|
||||
HighbdConvolve8Avg,
|
||||
},
|
||||
},
|
||||
};
|
||||
private static readonly unsafe HighbdConvolveFn[][][] _highbdPredictX16 =
|
||||
[
|
||||
[
|
||||
[HighbdConvolve8Vert, HighbdConvolve8AvgVert],
|
||||
[HighbdConvolve8Vert, HighbdConvolve8AvgVert]
|
||||
],
|
||||
[
|
||||
[HighbdConvolve8, HighbdConvolve8Avg],
|
||||
[HighbdConvolve8, HighbdConvolve8Avg]
|
||||
]
|
||||
];
|
||||
|
||||
private static readonly unsafe HighbdConvolveFn[][][] _highbdPredictY16 = {
|
||||
new[]
|
||||
{
|
||||
new HighbdConvolveFn[]
|
||||
{
|
||||
HighbdConvolve8Horiz,
|
||||
HighbdConvolve8AvgHoriz,
|
||||
},
|
||||
new HighbdConvolveFn[]
|
||||
{
|
||||
HighbdConvolve8,
|
||||
HighbdConvolve8Avg,
|
||||
},
|
||||
},
|
||||
new[]
|
||||
{
|
||||
new HighbdConvolveFn[]
|
||||
{
|
||||
HighbdConvolve8Horiz,
|
||||
HighbdConvolve8AvgHoriz,
|
||||
},
|
||||
new HighbdConvolveFn[]
|
||||
{
|
||||
HighbdConvolve8,
|
||||
HighbdConvolve8Avg,
|
||||
},
|
||||
},
|
||||
};
|
||||
private static readonly unsafe HighbdConvolveFn[][][] _highbdPredictY16 =
|
||||
[
|
||||
[
|
||||
[HighbdConvolve8Horiz, HighbdConvolve8AvgHoriz],
|
||||
[HighbdConvolve8, HighbdConvolve8Avg]
|
||||
],
|
||||
[
|
||||
[HighbdConvolve8Horiz, HighbdConvolve8AvgHoriz],
|
||||
[HighbdConvolve8, HighbdConvolve8Avg]
|
||||
]
|
||||
];
|
||||
|
||||
private static readonly unsafe HighbdConvolveFn[][][] _highbdPredict = {
|
||||
new[]
|
||||
{
|
||||
new HighbdConvolveFn[]
|
||||
{
|
||||
HighbdConvolve8,
|
||||
HighbdConvolve8Avg,
|
||||
},
|
||||
new HighbdConvolveFn[]
|
||||
{
|
||||
HighbdConvolve8,
|
||||
HighbdConvolve8Avg,
|
||||
},
|
||||
},
|
||||
new[]
|
||||
{
|
||||
new HighbdConvolveFn[]
|
||||
{
|
||||
HighbdConvolve8,
|
||||
HighbdConvolve8Avg,
|
||||
},
|
||||
new HighbdConvolveFn[]
|
||||
{
|
||||
HighbdConvolve8,
|
||||
HighbdConvolve8Avg,
|
||||
},
|
||||
},
|
||||
};
|
||||
private static readonly unsafe HighbdConvolveFn[][][] _highbdPredict =
|
||||
[
|
||||
[
|
||||
[HighbdConvolve8, HighbdConvolve8Avg],
|
||||
[HighbdConvolve8, HighbdConvolve8Avg]
|
||||
],
|
||||
[
|
||||
[HighbdConvolve8, HighbdConvolve8Avg],
|
||||
[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 readonly int ScaleValueX(int val)
|
||||
public int ScaleValueX(int val)
|
||||
{
|
||||
return IsScaled() ? ScaledX(val) : val;
|
||||
}
|
||||
|
||||
public readonly int ScaleValueY(int val)
|
||||
public int ScaleValueY(int val)
|
||||
{
|
||||
return IsScaled() ? ScaledY(val) : val;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public readonly unsafe void InterPredict(
|
||||
public unsafe void InterPredict(
|
||||
int horiz,
|
||||
int vert,
|
||||
int avg,
|
||||
@ -307,12 +155,14 @@ 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
|
||||
@ -320,7 +170,8 @@ 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
|
||||
{
|
||||
@ -331,7 +182,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public readonly unsafe void HighbdInterPredict(
|
||||
public unsafe void HighbdInterPredict(
|
||||
int horiz,
|
||||
int vert,
|
||||
int avg,
|
||||
@ -353,12 +204,14 @@ 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
|
||||
@ -366,24 +219,26 @@ 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 readonly int ScaledX(int val)
|
||||
private int ScaledX(int val)
|
||||
{
|
||||
return (int)((long)val * XScaleFP >> RefScaleShift);
|
||||
return (int)(((long)val * XScaleFp) >> RefScaleShift);
|
||||
}
|
||||
|
||||
private readonly int ScaledY(int val)
|
||||
private int ScaledY(int val)
|
||||
{
|
||||
return (int)((long)val * YScaleFP >> RefScaleShift);
|
||||
return (int)(((long)val * YScaleFp) >> RefScaleShift);
|
||||
}
|
||||
|
||||
private static int GetFixedPointScaleFactor(int otherSize, int thisSize)
|
||||
@ -399,23 +254,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
{
|
||||
int xOffQ4 = ScaledX(x << SubpelBits) & SubpelMask;
|
||||
int yOffQ4 = ScaledY(y << SubpelBits) & SubpelMask;
|
||||
Mv32 res = new()
|
||||
{
|
||||
Row = ScaledY(mv.Row) + yOffQ4,
|
||||
Col = ScaledX(mv.Col) + xOffQ4,
|
||||
};
|
||||
|
||||
Mv32 res = new() { Row = ScaledY(mv.Row) + yOffQ4, Col = ScaledX(mv.Col) + xOffQ4 };
|
||||
return res;
|
||||
}
|
||||
|
||||
public readonly bool IsValidScale()
|
||||
public bool IsValidScale()
|
||||
{
|
||||
return XScaleFP != RefInvalidScale && YScaleFP != RefInvalidScale;
|
||||
return XScaleFp != RefInvalidScale && YScaleFp != RefInvalidScale;
|
||||
}
|
||||
|
||||
public readonly bool IsScaled()
|
||||
public bool IsScaled()
|
||||
{
|
||||
return IsValidScale() && (XScaleFP != RefNoScale || YScaleFP != RefNoScale);
|
||||
return IsValidScale() && (XScaleFp != RefNoScale || YScaleFp != RefNoScale);
|
||||
}
|
||||
|
||||
public static bool ValidRefFrameSize(int refWidth, int refHeight, int thisWidth, int thisHeight)
|
||||
@ -430,16 +280,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
{
|
||||
if (!ValidRefFrameSize(otherW, otherH, thisW, thisH))
|
||||
{
|
||||
XScaleFP = RefInvalidScale;
|
||||
YScaleFP = RefInvalidScale;
|
||||
|
||||
XScaleFp = RefInvalidScale;
|
||||
YScaleFp = RefInvalidScale;
|
||||
return;
|
||||
}
|
||||
|
||||
XScaleFP = GetFixedPointScaleFactor(otherW, thisW);
|
||||
YScaleFP = GetFixedPointScaleFactor(otherH, thisH);
|
||||
XScaleFp = GetFixedPointScaleFactor(otherW, thisW);
|
||||
YScaleFp = GetFixedPointScaleFactor(otherH, thisH);
|
||||
XStepQ4 = ScaledX(16);
|
||||
YStepQ4 = ScaledY(16);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
{
|
||||
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
|
||||
AltQ, // Use alternate Quantizer ....
|
||||
AltLf, // Use alternate loop filter value...
|
||||
RefFrame, // Optional Segment reference frame
|
||||
Skip, // Optional Segment (0,0) + skip mode
|
||||
Max // Number of features supported
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,6 @@
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Graphics.Video;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
@ -6,8 +8,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
{
|
||||
internal struct Segmentation
|
||||
{
|
||||
private static readonly int[] _segFeatureDataSigned = { 1, 1, 0, 0 };
|
||||
private static readonly int[] _segFeatureDataMax = { QuantCommon.MaxQ, Vp9.LoopFilter.MaxLoopFilter, 3, 0 };
|
||||
public const int SegmentDeltadata = 0;
|
||||
public const int SegmentAbsdata = 1;
|
||||
|
||||
public const int MaxSegments = 8;
|
||||
public const int SegTreeProbs = MaxSegments - 1;
|
||||
|
||||
public const int PredictionProbs = 3;
|
||||
|
||||
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;
|
||||
@ -67,5 +77,88 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
{
|
||||
return FeatureData[segmentId][(int)featureId];
|
||||
}
|
||||
|
||||
public int GetQIndex(int segmentId, int baseQIndex)
|
||||
{
|
||||
if (IsSegFeatureActive(segmentId, SegLvlFeatures.AltQ) != 0)
|
||||
{
|
||||
int data = GetSegData(segmentId, SegLvlFeatures.AltQ);
|
||||
int segQIndex = AbsDelta == Constants.SegmentAbsData ? data : baseQIndex + data;
|
||||
return Math.Clamp(segQIndex, 0, QuantCommon.MaxQ);
|
||||
}
|
||||
|
||||
return baseQIndex;
|
||||
}
|
||||
|
||||
public void SetupSegmentation(ref Vp9EntropyProbs fc, ref ReadBitBuffer rb)
|
||||
{
|
||||
UpdateMap = false;
|
||||
UpdateData = 0;
|
||||
|
||||
Enabled = rb.ReadBit() != 0;
|
||||
if (!Enabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Segmentation map update
|
||||
UpdateMap = rb.ReadBit() != 0;
|
||||
if (UpdateMap)
|
||||
{
|
||||
for (int i = 0; i < SegTreeProbs; i++)
|
||||
{
|
||||
fc.SegTreeProb[i] = rb.ReadBit() != 0
|
||||
? (byte)rb.ReadLiteral(8)
|
||||
: (byte)Prob.MaxProb;
|
||||
}
|
||||
|
||||
TemporalUpdate = rb.ReadBit() != 0;
|
||||
if (TemporalUpdate)
|
||||
{
|
||||
for (int i = 0; i < PredictionProbs; i++)
|
||||
{
|
||||
fc.SegPredProb[i] = rb.ReadBit() != 0
|
||||
? (byte)rb.ReadLiteral(8)
|
||||
: (byte)Prob.MaxProb;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < PredictionProbs; i++)
|
||||
{
|
||||
fc.SegPredProb[i] = Prob.MaxProb;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Segmentation data update
|
||||
UpdateData = (byte)rb.ReadBit();
|
||||
if (UpdateData != 0)
|
||||
{
|
||||
AbsDelta = (byte)rb.ReadBit();
|
||||
|
||||
ClearAllSegFeatures();
|
||||
|
||||
for (int i = 0; i < Constants.MaxSegments; i++)
|
||||
{
|
||||
for (int j = 0; j < (int)SegLvlFeatures.Max; j++)
|
||||
{
|
||||
int data = 0;
|
||||
int featureEnabled = rb.ReadBit();
|
||||
if (featureEnabled != 0)
|
||||
{
|
||||
EnableSegFeature(i, (SegLvlFeatures)j);
|
||||
data = rb.DecodeUnsignedMax(FeatureDataMax((SegLvlFeatures)j));
|
||||
if (IsSegFeatureSigned((SegLvlFeatures)j) != 0)
|
||||
{
|
||||
data = rb.ReadBit() != 0 ? -data : data;
|
||||
}
|
||||
}
|
||||
|
||||
SetSegData(i, (SegLvlFeatures)j, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +1,23 @@
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Graphics.Nvdec.Vp9.Common;
|
||||
using Ryujinx.Graphics.Video;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
{
|
||||
internal delegate int VpxGetFrameBufferCbFnT(MemoryAllocator allocator, Ptr<InternalFrameBufferList> cbPriv,
|
||||
ulong minSize, ref VpxCodecFrameBuffer fb);
|
||||
|
||||
internal struct Surface : ISurface
|
||||
{
|
||||
public const int Innerborderinpixels = 96;
|
||||
public const int InterpExtend = 4;
|
||||
public const int EncBorderInPixels = 160;
|
||||
public const int DecBorderInPixels = 32;
|
||||
|
||||
public const int Yv12FlagHighbitdepth = 8;
|
||||
|
||||
public ArrayPtr<byte> YBuffer;
|
||||
public ArrayPtr<byte> UBuffer;
|
||||
public ArrayPtr<byte> VBuffer;
|
||||
@ -14,43 +26,62 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
public readonly unsafe Plane UPlane => new((nint)UBuffer.ToPointer(), UBuffer.Length);
|
||||
public readonly unsafe Plane VPlane => new((nint)VBuffer.ToPointer(), VBuffer.Length);
|
||||
|
||||
public readonly FrameField Field => FrameField.Progressive;
|
||||
public FrameField Field => FrameField.Progressive;
|
||||
|
||||
public int Width { get; }
|
||||
public int Height { get; }
|
||||
public int AlignedWidth { get; }
|
||||
public int AlignedHeight { get; }
|
||||
public int Stride { get; }
|
||||
public int UvWidth { get; }
|
||||
public int UvHeight { get; }
|
||||
public int UvAlignedWidth { get; }
|
||||
public int UvAlignedHeight { get; }
|
||||
public int UvStride { get; }
|
||||
public int Width { get; private set; }
|
||||
public int Height { get; private set; }
|
||||
public int AlignedWidth { get; private set; }
|
||||
public int AlignedHeight { get; private set; }
|
||||
public int Stride { get; private set; }
|
||||
public int UvWidth { get; private set; }
|
||||
public int UvHeight { get; private set; }
|
||||
public int UvAlignedWidth { get; private set; }
|
||||
public int UvAlignedHeight { get; private set; }
|
||||
public int UvStride { get; private set; }
|
||||
public bool HighBd { get; private set; }
|
||||
|
||||
public bool HighBd { get; }
|
||||
public int FrameSize { get; private set; }
|
||||
public int Border { get; private set; }
|
||||
|
||||
public int YCropWidth => Width;
|
||||
public int YCropHeight => Height;
|
||||
public int UvCropWidth => UvWidth;
|
||||
public int UvCropHeight => UvHeight;
|
||||
|
||||
public ArrayPtr<byte> BufferAlloc;
|
||||
public int BufferAllocSz;
|
||||
public int SubsamplingX;
|
||||
public int SubsamplingY;
|
||||
public uint BitDepth;
|
||||
public VpxColorSpace ColorSpace;
|
||||
public VpxColorRange ColorRange;
|
||||
public int RenderWidth;
|
||||
public int RenderHeight;
|
||||
|
||||
public int Corrupted;
|
||||
public int Flags;
|
||||
|
||||
private readonly nint _pointer;
|
||||
|
||||
public Surface(int width, int height)
|
||||
{
|
||||
HighBd = false;
|
||||
|
||||
const int Border = 32;
|
||||
const int SsX = 1;
|
||||
const int SsY = 1;
|
||||
const bool Highbd = false;
|
||||
|
||||
int alignedWidth = (width + 7) & ~7;
|
||||
int alignedHeight = (height + 7) & ~7;
|
||||
int yStride = ((alignedWidth + 2 * Border) + 31) & ~31;
|
||||
int yplaneSize = (alignedHeight + 2 * Border) * yStride;
|
||||
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 uvplaneSize = (uvHeight + (2 * uvBorderH)) * uvStride;
|
||||
|
||||
int frameSize = (HighBd ? 2 : 1) * (yplaneSize + 2 * uvplaneSize);
|
||||
int frameSize = (Highbd ? 2 : 1) * (yplaneSize + (2 * uvplaneSize));
|
||||
|
||||
nint pointer = Marshal.AllocHGlobal(frameSize);
|
||||
_pointer = pointer;
|
||||
@ -65,9 +96,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
UvAlignedHeight = uvHeight;
|
||||
UvStride = uvStride;
|
||||
|
||||
ArrayPtr<byte> NewPlane(int start, int size, int planeBorder)
|
||||
ArrayPtr<byte> NewPlane(int start, int size, int border)
|
||||
{
|
||||
return new ArrayPtr<byte>(pointer + start + planeBorder, size - planeBorder);
|
||||
return new ArrayPtr<byte>(pointer + start + border, size - border);
|
||||
}
|
||||
|
||||
YBuffer = NewPlane(0, yplaneSize, (Border * yStride) + Border);
|
||||
@ -75,7 +106,132 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
VBuffer = NewPlane(yplaneSize + uvplaneSize, uvplaneSize, (uvBorderH * uvStride) + uvBorderW);
|
||||
}
|
||||
|
||||
public readonly void Dispose()
|
||||
public unsafe int ReallocFrameBuffer(
|
||||
MemoryAllocator allocator,
|
||||
int width,
|
||||
int height,
|
||||
int ssX,
|
||||
int ssY,
|
||||
bool useHighbitdepth,
|
||||
int border,
|
||||
int byteAlignment,
|
||||
Ptr<VpxCodecFrameBuffer> fb,
|
||||
VpxGetFrameBufferCbFnT cb,
|
||||
Ptr<InternalFrameBufferList> cbPriv)
|
||||
{
|
||||
int byteAlign = byteAlignment == 0 ? 1 : byteAlignment; // TODO: Is it safe to ignore the alignment?
|
||||
int alignedWidth = (width + 7) & ~7;
|
||||
int alignedHeight = (height + 7) & ~7;
|
||||
int yStride = (alignedWidth + (2 * border) + 31) & ~31;
|
||||
ulong yplaneSize =
|
||||
((ulong)(alignedHeight + (2 * border)) * (ulong)yStride) + (ulong)byteAlignment;
|
||||
int uvWidth = alignedWidth >> ssX;
|
||||
int uvHeight = alignedHeight >> ssY;
|
||||
int uvStride = yStride >> ssX;
|
||||
int uvBorderW = border >> ssX;
|
||||
int uvBorderH = border >> ssY;
|
||||
ulong uvplaneSize =
|
||||
((ulong)(uvHeight + (2 * uvBorderH)) * (ulong)uvStride) + (ulong)byteAlignment;
|
||||
|
||||
ulong frameSize = (ulong)(1 + (useHighbitdepth ? 1 : 0)) * (yplaneSize + (2 * uvplaneSize));
|
||||
|
||||
ArrayPtr<byte> buf = ArrayPtr<byte>.Null;
|
||||
|
||||
// frame_size is stored in buffer_alloc_sz, which is an int. If it won't
|
||||
// fit, fail early.
|
||||
if (frameSize > int.MaxValue)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cb != null)
|
||||
{
|
||||
const int AlignAddrExtraSize = 31;
|
||||
ulong externalFrameSize = frameSize + AlignAddrExtraSize;
|
||||
|
||||
Debug.Assert(!fb.IsNull);
|
||||
|
||||
// Allocation to hold larger frame, or first allocation.
|
||||
if (cb(allocator, cbPriv, externalFrameSize, ref fb.Value) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fb.Value.Data.IsNull || (ulong)fb.Value.Data.Length < externalFrameSize)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
BufferAlloc = fb.Value.Data;
|
||||
}
|
||||
else if (frameSize > (ulong)BufferAllocSz)
|
||||
{
|
||||
// Allocation to hold larger frame, or first allocation.
|
||||
allocator.Free(BufferAlloc);
|
||||
BufferAlloc = ArrayPtr<byte>.Null;
|
||||
|
||||
BufferAlloc = allocator.Allocate<byte>((int)frameSize);
|
||||
if (BufferAlloc.IsNull)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
BufferAllocSz = (int)frameSize;
|
||||
|
||||
// This memset is needed for fixing valgrind error from C loop filter
|
||||
// due to access uninitialized memory in frame border. It could be
|
||||
// removed if border is totally removed.
|
||||
MemoryUtil.Fill(BufferAlloc.ToPointer(), (byte)0, BufferAllocSz);
|
||||
}
|
||||
|
||||
/* Only support allocating buffers that have a border that's a multiple
|
||||
* of 32. The border restriction is required to get 16-byte alignment of
|
||||
* the start of the chroma rows without introducing an arbitrary gap
|
||||
* between planes, which would break the semantics of things like
|
||||
* vpx_img_set_rect(). */
|
||||
if ((border & 0x1f) != 0)
|
||||
{
|
||||
return -3;
|
||||
}
|
||||
|
||||
Width = width;
|
||||
Height = height;
|
||||
AlignedWidth = alignedWidth;
|
||||
AlignedHeight = alignedHeight;
|
||||
Stride = yStride;
|
||||
|
||||
UvWidth = (width + ssX) >> ssX;
|
||||
UvHeight = (height + ssY) >> ssY;
|
||||
UvAlignedWidth = uvWidth;
|
||||
UvAlignedHeight = uvHeight;
|
||||
UvStride = uvStride;
|
||||
|
||||
Border = border;
|
||||
FrameSize = (int)frameSize;
|
||||
SubsamplingX = ssX;
|
||||
SubsamplingY = ssY;
|
||||
|
||||
buf = BufferAlloc;
|
||||
if (useHighbitdepth)
|
||||
{
|
||||
// Store uint16 addresses when using 16bit framebuffers
|
||||
buf = BufferAlloc;
|
||||
Flags = Yv12FlagHighbitdepth;
|
||||
}
|
||||
else
|
||||
{
|
||||
Flags = 0;
|
||||
}
|
||||
|
||||
YBuffer = buf.Slice((border * yStride) + border);
|
||||
UBuffer = buf.Slice((int)yplaneSize + (uvBorderH * uvStride) + uvBorderW);
|
||||
VBuffer = buf.Slice((int)yplaneSize + (int)uvplaneSize + (uvBorderH * uvStride) + uvBorderW);
|
||||
|
||||
Corrupted = 0; /* assume not corrupted by errors */
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Marshal.FreeHGlobal(_pointer);
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
private static int GetMinLog2TileCols(int sb64Cols)
|
||||
{
|
||||
int minLog2 = 0;
|
||||
while ((MaxTileWidthB64 << minLog2) < sb64Cols)
|
||||
while (MaxTileWidthB64 << minLog2 < sb64Cols)
|
||||
{
|
||||
++minLog2;
|
||||
}
|
||||
@ -67,7 +67,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
private static int GetMaxLog2TileCols(int sb64Cols)
|
||||
{
|
||||
int maxLog2 = 1;
|
||||
while ((sb64Cols >> maxLog2) >= MinTileWidthB64)
|
||||
while (sb64Cols >> maxLog2 >= MinTileWidthB64)
|
||||
{
|
||||
++maxLog2;
|
||||
}
|
||||
@ -75,7 +75,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
return maxLog2 - 1;
|
||||
}
|
||||
|
||||
public static void GetTileNBits(int miCols, ref int minLog2TileCols, ref int maxLog2TileCols)
|
||||
public static void GetTileNBits(int miCols, out int minLog2TileCols, out int maxLog2TileCols)
|
||||
{
|
||||
int sb64Cols = MiColsAlignedToSb(miCols) >> Constants.MiBlockSizeLog2;
|
||||
minLog2TileCols = GetMinLog2TileCols(sb64Cols);
|
||||
@ -83,4 +83,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
Debug.Assert(minLog2TileCols <= maxLog2TileCols);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,12 +1,12 @@
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
{
|
||||
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
|
||||
TxModeSelect = 4, // Transform specified for each block
|
||||
TxModes = 5,
|
||||
Only4X4, // Only 4x4 transform used
|
||||
Allow8X8, // Allow block transform size up to 8x8
|
||||
Allow16X16, // Allow block transform size up to 16x16
|
||||
Allow32X32, // Allow block transform size up to 32x32
|
||||
TxModeSelect, // Transform specified for each block
|
||||
TxModes
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
{
|
||||
public enum TxSize
|
||||
{
|
||||
Tx4x4 = 0, // 4x4 transform
|
||||
Tx8x8 = 1, // 8x8 transform
|
||||
Tx16x16 = 2, // 16x16 transform
|
||||
Tx32x32 = 3, // 32x32 transform
|
||||
TxSizes = 4,
|
||||
Tx4X4, // 4x4 transform
|
||||
Tx8X8, // 8x8 transform
|
||||
Tx16X16, // 16x16 transform
|
||||
Tx32X32, // 32x32 transform
|
||||
TxSizes
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
{
|
||||
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
|
||||
AdstAdst = 3, // ADST in both directions
|
||||
TxTypes = 4,
|
||||
DctDct, // DCT in both horizontal and vertical
|
||||
AdstDct, // ADST in vertical, DCT in horizontal
|
||||
DctAdst, // DCT in vertical, ADST in horizontal
|
||||
AdstAdst, // ADST in both directions
|
||||
TxTypes
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Graphics.Nvdec.Vp9.Common;
|
||||
using Ryujinx.Graphics.Nvdec.Vp9.Dsp;
|
||||
using Ryujinx.Graphics.Video;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
{
|
||||
@ -9,27 +11,62 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
public MacroBlockD Mb;
|
||||
|
||||
public ArrayPtr<TileWorkerData> TileWorkerData;
|
||||
public int TotalTiles;
|
||||
|
||||
public InternalErrorInfo Error;
|
||||
|
||||
public VpxColorSpace ColorSpace;
|
||||
public VpxColorRange ColorRange;
|
||||
|
||||
public int Width;
|
||||
public int Height;
|
||||
|
||||
public int RenderWidth;
|
||||
public int RenderHeight;
|
||||
|
||||
public int LastWidth;
|
||||
public int LastHeight;
|
||||
|
||||
public int SubsamplingX;
|
||||
public int SubsamplingY;
|
||||
|
||||
public bool UseHighBitDepth;
|
||||
|
||||
public ArrayPtr<MvRef> PrevFrameMvs;
|
||||
public ArrayPtr<MvRef> CurFrameMvs;
|
||||
|
||||
public Ptr<Surface> FrameToShow;
|
||||
public Ptr<RefCntBuffer> PrevFrame;
|
||||
|
||||
public Ptr<RefCntBuffer> CurFrame;
|
||||
|
||||
public Array8<int> RefFrameMap; /* maps fb_idx to reference slot */
|
||||
|
||||
// Prepare ref_frame_map for the next frame.
|
||||
// Only used in frame parallel decode.
|
||||
public Array8<int> NextRefFrameMap;
|
||||
|
||||
public Array3<RefBuffer> FrameRefs;
|
||||
|
||||
public int NewFbIdx;
|
||||
|
||||
public int CurShowFrameFbIdx;
|
||||
|
||||
public FrameType LastFrameType;
|
||||
public FrameType FrameType;
|
||||
|
||||
public int ShowFrame;
|
||||
public int LastShowFrame;
|
||||
public int ShowExistingFrame;
|
||||
|
||||
// Flag signaling that the frame is encoded using only Intra modes.
|
||||
public bool IntraOnly;
|
||||
public bool LastIntraOnly;
|
||||
|
||||
public bool AllowHighPrecisionMv;
|
||||
|
||||
public int ResetFrameContext;
|
||||
|
||||
// MBs, MbRows/Cols is in 16-pixel units; MiRows/Cols is in
|
||||
// ModeInfo (8-pixel) units.
|
||||
public int MBs;
|
||||
@ -49,8 +86,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
|
||||
/* We allocate a ModeInfo struct for each macroblock, together with
|
||||
an extra row on top and column on the left to simplify prediction. */
|
||||
public int MiAllocSize;
|
||||
public ArrayPtr<ModeInfo> Mip; /* Base of allocated array */
|
||||
public ArrayPtr<ModeInfo> Mi; /* Corresponds to upper left visible macroblock */
|
||||
public ArrayPtr<ModeInfo> Mi; /* Corresponds to upper left visible macroblock */
|
||||
|
||||
// prev_mip and prev_mi will only be allocated in VP9 encoder.
|
||||
public Ptr<ModeInfo> PrevMip; /* MODE_INFO array 'mip' from last decoded frame */
|
||||
public Ptr<ModeInfo> PrevMi; /* 'mi' from last frame (points into prev_mip) */
|
||||
|
||||
public ArrayPtr<Ptr<ModeInfo>> MiGridBase;
|
||||
public ArrayPtr<Ptr<ModeInfo>> MiGridVisible;
|
||||
@ -70,6 +112,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
|
||||
public LoopFilterInfoN LfInfo;
|
||||
|
||||
public int RefreshFrameContext; /* Two state 0 = NO, 1 = YES */
|
||||
|
||||
public Array4<sbyte> RefFrameSignBias; /* Two state 0, 1 */
|
||||
|
||||
public LoopFilter Lf;
|
||||
@ -81,22 +125,37 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
public ReferenceMode ReferenceMode;
|
||||
|
||||
public Ptr<Vp9EntropyProbs> Fc;
|
||||
public ArrayPtr<Vp9EntropyProbs> FrameContexts; // FRAME_CONTEXTS
|
||||
public uint FrameContextIdx; /* Context to use/update */
|
||||
public Ptr<Vp9BackwardUpdates> Counts;
|
||||
|
||||
public uint CurrentVideoFrame;
|
||||
public BitstreamProfile Profile;
|
||||
|
||||
public BitDepth BitDepth;
|
||||
public BitDepth DequantBitDepth; // bit_depth of current dequantizer
|
||||
|
||||
public int ErrorResilientMode;
|
||||
public int FrameParallelDecodingMode;
|
||||
|
||||
public int Log2TileCols, Log2TileRows;
|
||||
|
||||
public int ByteAlignment;
|
||||
public int SkipLoopFilter;
|
||||
|
||||
public Ptr<BufferPool> BufferPool;
|
||||
|
||||
public ArrayPtr<sbyte> AboveSegContext;
|
||||
public ArrayPtr<sbyte> AboveContext;
|
||||
|
||||
public readonly bool FrameIsIntraOnly()
|
||||
public bool FrameIsIntraOnly()
|
||||
{
|
||||
return FrameType == FrameType.KeyFrame || IntraOnly;
|
||||
}
|
||||
|
||||
public bool CompoundReferenceAllowed()
|
||||
{
|
||||
int i;
|
||||
for (i = 1; i < Constants.RefsPerFrame; ++i)
|
||||
for (int i = 1; i < Constants.RefsPerFrame; ++i)
|
||||
{
|
||||
if (RefFrameSignBias[i + 1] != RefFrameSignBias[1])
|
||||
{
|
||||
@ -107,6 +166,47 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
return false;
|
||||
}
|
||||
|
||||
public ref Surface GetFrameNewBuffer()
|
||||
{
|
||||
return ref BufferPool.Value.FrameBufs[NewFbIdx].Buf;
|
||||
}
|
||||
|
||||
public int GetFreeFb()
|
||||
{
|
||||
ref Array12<RefCntBuffer> frameBufs = ref BufferPool.Value.FrameBufs;
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < Constants.FrameBuffers; ++i)
|
||||
{
|
||||
if (frameBufs[i].RefCount == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i != Constants.FrameBuffers)
|
||||
{
|
||||
frameBufs[i].RefCount = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reset i to be INVALID_IDX to indicate no free buffer found.
|
||||
i = RefBuffer.InvalidIdx;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
public void SwapCurrentAndLastSegMap()
|
||||
{
|
||||
// Swap indices.
|
||||
(SegMapIdx, PrevSegMapIdx) = (PrevSegMapIdx, SegMapIdx);
|
||||
|
||||
CurrentFrameSegMap = SegMapArray[SegMapIdx];
|
||||
LastFrameSegMap = SegMapArray[PrevSegMapIdx];
|
||||
}
|
||||
|
||||
private static int CalcMiSize(int len)
|
||||
{
|
||||
// Len is in mi units.
|
||||
@ -129,19 +229,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
|
||||
public void AllocTileWorkerData(MemoryAllocator allocator, int tileCols, int tileRows, int maxThreads)
|
||||
{
|
||||
TileWorkerData = allocator.Allocate<TileWorkerData>(tileCols * tileRows + (maxThreads > 1 ? maxThreads : 0));
|
||||
TileWorkerData =
|
||||
allocator.Allocate<TileWorkerData>((tileCols * tileRows) + (maxThreads > 1 ? maxThreads : 0));
|
||||
}
|
||||
|
||||
public readonly void FreeTileWorkerData(MemoryAllocator allocator)
|
||||
public void FreeTileWorkerData(MemoryAllocator allocator)
|
||||
{
|
||||
allocator.Free(TileWorkerData);
|
||||
}
|
||||
|
||||
private void AllocSegMap(MemoryAllocator allocator, int segMapSize)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < Constants.NumPingPongBuffers; ++i)
|
||||
for (int i = 0; i < Constants.NumPingPongBuffers; ++i)
|
||||
{
|
||||
SegMapArray[i] = allocator.Allocate<byte>(segMapSize);
|
||||
}
|
||||
@ -156,9 +255,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
|
||||
private void FreeSegMap(MemoryAllocator allocator)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < Constants.NumPingPongBuffers; ++i)
|
||||
for (int i = 0; i < Constants.NumPingPongBuffers; ++i)
|
||||
{
|
||||
allocator.Free(SegMapArray[i]);
|
||||
SegMapArray[i] = ArrayPtr<byte>.Null;
|
||||
@ -194,6 +291,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
Lf.Lfm = ArrayPtr<LoopFilterMask>.Null;
|
||||
allocator.Free(CurFrameMvs);
|
||||
CurFrameMvs = ArrayPtr<MvRef>.Null;
|
||||
|
||||
if (UsePrevFrameMvs)
|
||||
{
|
||||
allocator.Free(PrevFrameMvs);
|
||||
@ -209,7 +307,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
Lf.Lfm = allocator.Allocate<LoopFilterMask>(((MiRows + (Constants.MiBlockSize - 1)) >> 3) * Lf.LfmStride);
|
||||
}
|
||||
|
||||
public void AllocContextBuffers(MemoryAllocator allocator, int width, int height)
|
||||
public bool AllocContextBuffers(MemoryAllocator allocator, int width, int height)
|
||||
{
|
||||
SetMbMi(width, height);
|
||||
int newMiSize = MiStride * CalcMiSize(MiRows);
|
||||
@ -239,6 +337,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
{
|
||||
PrevFrameMvs = allocator.Allocate<MvRef>(MiRows * MiCols);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private unsafe void DecSetupMi()
|
||||
@ -257,7 +357,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
}
|
||||
}
|
||||
|
||||
private readonly void SetPartitionProbs(ref MacroBlockD xd)
|
||||
private void SetPartitionProbs(ref MacroBlockD xd)
|
||||
{
|
||||
xd.PartitionProbs = FrameIsIntraOnly()
|
||||
? new ArrayPtr<Array3<byte>>(ref Fc.Value.KfPartitionProb[0], 16)
|
||||
@ -266,9 +366,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
|
||||
internal void InitMacroBlockD(ref MacroBlockD xd, ArrayPtr<int> dqcoeff)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < Constants.MaxMbPlane; ++i)
|
||||
for (int i = 0; i < Constants.MaxMbPlane; ++i)
|
||||
{
|
||||
xd.Plane[i].DqCoeff = dqcoeff;
|
||||
xd.AboveContext[i] = AboveContext.Slice(i * 2 * TileInfo.MiColsAlignedToSb(MiCols));
|
||||
@ -281,6 +379,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
{
|
||||
MemoryUtil.Copy(ref xd.Plane[i].SegDequant, ref UvDequant);
|
||||
}
|
||||
|
||||
xd.Fc = new Ptr<Vp9EntropyProbs>(ref Fc.Value);
|
||||
}
|
||||
|
||||
@ -293,29 +392,27 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
|
||||
public void SetupSegmentationDequant()
|
||||
{
|
||||
const BitDepth BitDepth = BitDepth.Bits8; // TODO: Configurable
|
||||
// Build y/uv dequant values based on segmentation.
|
||||
if (Seg.Enabled)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < Constants.MaxSegments; ++i)
|
||||
for (int 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);
|
||||
int qindex = Seg.GetQIndex(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);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int qIndex = BaseQindex;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -327,5 +424,576 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
refBuf.Sf.SetupScaleFactorsForFrame(refBuf.Buf.Width, refBuf.Buf.Height, Width, Height);
|
||||
}
|
||||
}
|
||||
|
||||
public void ReadFrameReferenceModeProbs(ref Reader r)
|
||||
{
|
||||
ref Vp9EntropyProbs fc = ref Fc.Value;
|
||||
|
||||
|
||||
if (ReferenceMode == ReferenceMode.Select)
|
||||
{
|
||||
for (int i = 0; i < Constants.CompInterContexts; ++i)
|
||||
{
|
||||
r.DiffUpdateProb(ref fc.CompInterProb[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (ReferenceMode != ReferenceMode.Compound)
|
||||
{
|
||||
for (int i = 0; i < Constants.RefContexts; ++i)
|
||||
{
|
||||
r.DiffUpdateProb(ref fc.SingleRefProb[i][0]);
|
||||
r.DiffUpdateProb(ref fc.SingleRefProb[i][1]);
|
||||
}
|
||||
}
|
||||
|
||||
if (ReferenceMode != ReferenceMode.Single)
|
||||
{
|
||||
for (int i = 0; i < Constants.RefContexts; ++i)
|
||||
{
|
||||
r.DiffUpdateProb(ref fc.CompRefProb[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ReferenceMode ReadFrameReferenceMode(ref Reader r)
|
||||
{
|
||||
if (CompoundReferenceAllowed())
|
||||
{
|
||||
return r.ReadBit() != 0
|
||||
? r.ReadBit() != 0 ? ReferenceMode.Select : ReferenceMode.Compound
|
||||
: ReferenceMode.Single;
|
||||
}
|
||||
|
||||
return ReferenceMode.Single;
|
||||
}
|
||||
|
||||
public void SetupCompoundReferenceMode()
|
||||
{
|
||||
if (RefFrameSignBias[Constants.LastFrame] == RefFrameSignBias[Constants.GoldenFrame])
|
||||
{
|
||||
CompFixedRef = Constants.AltRefFrame;
|
||||
CompVarRef[0] = Constants.LastFrame;
|
||||
CompVarRef[1] = Constants.GoldenFrame;
|
||||
}
|
||||
else if (RefFrameSignBias[Constants.LastFrame] == RefFrameSignBias[Constants.AltRefFrame])
|
||||
{
|
||||
CompFixedRef = Constants.GoldenFrame;
|
||||
CompVarRef[0] = Constants.LastFrame;
|
||||
CompVarRef[1] = Constants.AltRefFrame;
|
||||
}
|
||||
else
|
||||
{
|
||||
CompFixedRef = Constants.LastFrame;
|
||||
CompVarRef[0] = Constants.GoldenFrame;
|
||||
CompVarRef[1] = Constants.AltRefFrame;
|
||||
}
|
||||
}
|
||||
|
||||
public void InitMvProbs()
|
||||
{
|
||||
Fc.Value.Joints[0] = 32;
|
||||
Fc.Value.Joints[1] = 64;
|
||||
Fc.Value.Joints[2] = 96;
|
||||
|
||||
Fc.Value.Sign[0] = 128;
|
||||
Fc.Value.Classes[0][0] = 224;
|
||||
Fc.Value.Classes[0][1] = 144;
|
||||
Fc.Value.Classes[0][2] = 192;
|
||||
Fc.Value.Classes[0][3] = 168;
|
||||
Fc.Value.Classes[0][4] = 192;
|
||||
Fc.Value.Classes[0][5] = 176;
|
||||
Fc.Value.Classes[0][6] = 192;
|
||||
Fc.Value.Classes[0][7] = 198;
|
||||
Fc.Value.Classes[0][8] = 198;
|
||||
Fc.Value.Classes[0][9] = 245;
|
||||
Fc.Value.Class0[0][0] = 216;
|
||||
Fc.Value.Bits[0][0] = 136;
|
||||
Fc.Value.Bits[0][1] = 140;
|
||||
Fc.Value.Bits[0][2] = 148;
|
||||
Fc.Value.Bits[0][3] = 160;
|
||||
Fc.Value.Bits[0][4] = 176;
|
||||
Fc.Value.Bits[0][5] = 192;
|
||||
Fc.Value.Bits[0][6] = 224;
|
||||
Fc.Value.Bits[0][7] = 234;
|
||||
Fc.Value.Bits[0][8] = 234;
|
||||
Fc.Value.Bits[0][9] = 240;
|
||||
Fc.Value.Class0Fp[0][0][0] = 128;
|
||||
Fc.Value.Class0Fp[0][0][1] = 128;
|
||||
Fc.Value.Class0Fp[0][0][2] = 64;
|
||||
Fc.Value.Class0Fp[0][1][0] = 96;
|
||||
Fc.Value.Class0Fp[0][1][1] = 112;
|
||||
Fc.Value.Class0Fp[0][1][2] = 64;
|
||||
Fc.Value.Fp[0][0] = 64;
|
||||
Fc.Value.Fp[0][1] = 96;
|
||||
Fc.Value.Fp[0][2] = 64;
|
||||
Fc.Value.Class0Hp[0] = 160;
|
||||
Fc.Value.Hp[0] = 128;
|
||||
|
||||
Fc.Value.Sign[1] = 128;
|
||||
Fc.Value.Classes[1][0] = 216;
|
||||
Fc.Value.Classes[1][1] = 128;
|
||||
Fc.Value.Classes[1][2] = 176;
|
||||
Fc.Value.Classes[1][3] = 160;
|
||||
Fc.Value.Classes[1][4] = 176;
|
||||
Fc.Value.Classes[1][5] = 176;
|
||||
Fc.Value.Classes[1][6] = 192;
|
||||
Fc.Value.Classes[1][7] = 198;
|
||||
Fc.Value.Classes[1][8] = 198;
|
||||
Fc.Value.Classes[1][9] = 208;
|
||||
Fc.Value.Class0[1][0] = 208;
|
||||
Fc.Value.Bits[1][0] = 136;
|
||||
Fc.Value.Bits[1][1] = 140;
|
||||
Fc.Value.Bits[1][2] = 148;
|
||||
Fc.Value.Bits[1][3] = 160;
|
||||
Fc.Value.Bits[1][4] = 176;
|
||||
Fc.Value.Bits[1][5] = 192;
|
||||
Fc.Value.Bits[1][6] = 224;
|
||||
Fc.Value.Bits[1][7] = 234;
|
||||
Fc.Value.Bits[1][8] = 234;
|
||||
Fc.Value.Bits[1][9] = 240;
|
||||
Fc.Value.Class0Fp[1][0][0] = 128;
|
||||
Fc.Value.Class0Fp[1][0][1] = 128;
|
||||
Fc.Value.Class0Fp[1][0][2] = 64;
|
||||
Fc.Value.Class0Fp[1][1][0] = 96;
|
||||
Fc.Value.Class0Fp[1][1][1] = 112;
|
||||
Fc.Value.Class0Fp[1][1][2] = 64;
|
||||
Fc.Value.Fp[1][0] = 64;
|
||||
Fc.Value.Fp[1][1] = 96;
|
||||
Fc.Value.Fp[1][2] = 64;
|
||||
Fc.Value.Class0Hp[1] = 160;
|
||||
Fc.Value.Hp[1] = 128;
|
||||
}
|
||||
|
||||
public void AdaptMvProbs(bool allowHp)
|
||||
{
|
||||
ref Vp9EntropyProbs fc = ref Fc.Value;
|
||||
ref Vp9EntropyProbs preFc = ref FrameContexts[(int)FrameContextIdx];
|
||||
ref Vp9BackwardUpdates counts = ref Counts.Value;
|
||||
|
||||
Prob.VpxTreeMergeProbs(
|
||||
EntropyMv.JointTree,
|
||||
preFc.Joints.AsSpan(),
|
||||
counts.Joints.AsSpan(),
|
||||
fc.Joints.AsSpan());
|
||||
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
fc.Sign[i] = Prob.ModeMvMergeProbs(preFc.Sign[i], ref counts.Sign[i]);
|
||||
Prob.VpxTreeMergeProbs(
|
||||
EntropyMv.ClassTree,
|
||||
preFc.Classes[i].AsSpan(),
|
||||
counts.Classes[i].AsSpan(),
|
||||
fc.Classes[i].AsSpan());
|
||||
Prob.VpxTreeMergeProbs(
|
||||
EntropyMv.Class0Tree,
|
||||
preFc.Class0[i].AsSpan(),
|
||||
counts.Class0[i].AsSpan(),
|
||||
fc.Class0[i].AsSpan());
|
||||
|
||||
for (int j = 0; j < EntropyMv.OffsetBits; ++j)
|
||||
{
|
||||
fc.Bits[i][j] = Prob.ModeMvMergeProbs(preFc.Bits[i][j], ref counts.Bits[i][j]);
|
||||
}
|
||||
|
||||
for (int j = 0; j < EntropyMv.Class0Size; ++j)
|
||||
{
|
||||
Prob.VpxTreeMergeProbs(
|
||||
EntropyMv.FpTree,
|
||||
preFc.Class0Fp[i][j].AsSpan(),
|
||||
counts.Class0Fp[i][j].AsSpan(),
|
||||
fc.Class0Fp[i][j].AsSpan());
|
||||
}
|
||||
|
||||
Prob.VpxTreeMergeProbs(EntropyMv.FpTree, preFc.Fp[i].AsSpan(), counts.Fp[i].AsSpan(),
|
||||
fc.Fp[i].AsSpan());
|
||||
|
||||
if (allowHp)
|
||||
{
|
||||
fc.Class0Hp[i] = Prob.ModeMvMergeProbs(preFc.Class0Hp[i], ref counts.Class0Hp[i]);
|
||||
fc.Hp[i] = Prob.ModeMvMergeProbs(preFc.Hp[i], ref counts.Hp[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ResizeContextBuffers(MemoryAllocator allocator, int width, int height)
|
||||
{
|
||||
if (Width != width || Height != height)
|
||||
{
|
||||
int newMiRows = BitUtils.AlignPowerOfTwo(height, Constants.MiSizeLog2) >> Constants.MiSizeLog2;
|
||||
int newMiCols = BitUtils.AlignPowerOfTwo(width, Constants.MiSizeLog2) >> Constants.MiSizeLog2;
|
||||
|
||||
// Allocations in AllocContextBuffers() depend on individual
|
||||
// dimensions as well as the overall size.
|
||||
if (newMiCols > MiCols || newMiRows > MiRows)
|
||||
{
|
||||
if (AllocContextBuffers(allocator, width, height))
|
||||
{
|
||||
// The Mi* values have been cleared and any existing context
|
||||
// buffers have been freed. Clear Width and Height to be
|
||||
// consistent and to force a realloc next time.
|
||||
Width = 0;
|
||||
Height = 0;
|
||||
Error.InternalError(CodecErr.MemError, "Failed to allocate context buffers");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetMbMi(width, height);
|
||||
}
|
||||
|
||||
InitContextBuffers();
|
||||
Width = width;
|
||||
Height = height;
|
||||
}
|
||||
|
||||
if (CurFrameMvs.IsNull ||
|
||||
MiRows > CurFrame.Value.MiRows ||
|
||||
MiCols > CurFrame.Value.MiCols)
|
||||
{
|
||||
ResizeMvBuffer(allocator);
|
||||
}
|
||||
}
|
||||
|
||||
public void CheckMemError<T>(ref ArrayPtr<T> lval, ArrayPtr<T> expr)
|
||||
where T : unmanaged
|
||||
{
|
||||
lval = expr;
|
||||
if (lval.IsNull)
|
||||
{
|
||||
Error.InternalError(CodecErr.MemError, "Failed to allocate");
|
||||
}
|
||||
}
|
||||
|
||||
private void ResizeMvBuffer(MemoryAllocator allocator)
|
||||
{
|
||||
allocator.Free(CurFrameMvs);
|
||||
CurFrame.Value.MiRows = MiRows;
|
||||
CurFrame.Value.MiCols = MiCols;
|
||||
CheckMemError(ref CurFrameMvs, allocator.Allocate<MvRef>(MiRows * MiCols));
|
||||
}
|
||||
|
||||
public void CheckMemError<T>(ref Ptr<T> lval, Ptr<T> expr) where T : unmanaged
|
||||
{
|
||||
lval = expr;
|
||||
if (lval.IsNull)
|
||||
{
|
||||
Error.InternalError(CodecErr.MemError, "Failed to allocate");
|
||||
}
|
||||
}
|
||||
|
||||
public void SetupTileInfo(ref ReadBitBuffer rb)
|
||||
{
|
||||
int minLog2TileCols = 0, maxLog2TileCols = 0, maxOnes;
|
||||
TileInfo.GetTileNBits(MiCols, out minLog2TileCols, out maxLog2TileCols);
|
||||
|
||||
// columns
|
||||
maxOnes = maxLog2TileCols - minLog2TileCols;
|
||||
Log2TileCols = minLog2TileCols;
|
||||
while (maxOnes-- != 0 && rb.ReadBit() != 0)
|
||||
{
|
||||
Log2TileCols++;
|
||||
}
|
||||
|
||||
if (Log2TileCols > 6)
|
||||
{
|
||||
Error.InternalError(CodecErr.CorruptFrame, "Invalid number of tile columns");
|
||||
}
|
||||
|
||||
// rows
|
||||
Log2TileRows = rb.ReadBit();
|
||||
if (Log2TileRows != 0)
|
||||
{
|
||||
Log2TileRows += rb.ReadBit();
|
||||
}
|
||||
}
|
||||
|
||||
public void ReadBitdepthColorspaceSampling(ref ReadBitBuffer rb)
|
||||
{
|
||||
if (Profile >= BitstreamProfile.Profile2)
|
||||
{
|
||||
BitDepth = rb.ReadBit() != 0 ? BitDepth.Bits12 : BitDepth.Bits10;
|
||||
UseHighBitDepth = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
BitDepth = BitDepth.Bits8;
|
||||
UseHighBitDepth = false;
|
||||
}
|
||||
|
||||
ColorSpace = (VpxColorSpace)rb.ReadLiteral(3);
|
||||
if (ColorSpace != VpxColorSpace.Srgb)
|
||||
{
|
||||
ColorRange = (VpxColorRange)rb.ReadBit();
|
||||
if (Profile == BitstreamProfile.Profile1 || Profile == BitstreamProfile.Profile3)
|
||||
{
|
||||
SubsamplingX = rb.ReadBit();
|
||||
SubsamplingY = rb.ReadBit();
|
||||
if (SubsamplingX == 1 && SubsamplingY == 1)
|
||||
{
|
||||
Error.InternalError(CodecErr.UnsupBitstream,
|
||||
"4:2:0 color not supported in profile 1 or 3");
|
||||
}
|
||||
|
||||
if (rb.ReadBit() != 0)
|
||||
{
|
||||
Error.InternalError(CodecErr.UnsupBitstream, "Reserved bit set");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SubsamplingY = SubsamplingX = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ColorRange = VpxColorRange.Full;
|
||||
if (Profile == BitstreamProfile.Profile1 || Profile == BitstreamProfile.Profile3)
|
||||
{
|
||||
// Note if colorspace is SRGB then 4:4:4 chroma sampling is assumed.
|
||||
// 4:2:2 or 4:4:0 chroma sampling is not allowed.
|
||||
SubsamplingY = SubsamplingX = 0;
|
||||
if (rb.ReadBit() != 0)
|
||||
{
|
||||
Error.InternalError(CodecErr.UnsupBitstream, "Reserved bit set");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Error.InternalError(CodecErr.UnsupBitstream, "4:4:4 color not supported in profile 0 or 2");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void AdaptModeProbs()
|
||||
{
|
||||
ref Vp9EntropyProbs fc = ref Fc.Value;
|
||||
ref Vp9EntropyProbs preFc = ref FrameContexts[(int)FrameContextIdx];
|
||||
ref Vp9BackwardUpdates counts = ref Counts.Value;
|
||||
|
||||
for (int i = 0; i < Constants.IntraInterContexts; i++)
|
||||
{
|
||||
fc.IntraInterProb[i] = Prob.ModeMvMergeProbs(preFc.IntraInterProb[i], ref counts.IntraInter[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < Constants.CompInterContexts; i++)
|
||||
{
|
||||
fc.CompInterProb[i] = Prob.ModeMvMergeProbs(preFc.CompInterProb[i], ref counts.CompInter[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < Constants.RefContexts; i++)
|
||||
{
|
||||
fc.CompRefProb[i] = Prob.ModeMvMergeProbs(preFc.CompRefProb[i], ref counts.CompRef[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < Constants.RefContexts; i++)
|
||||
{
|
||||
for (int j = 0; j < 2; j++)
|
||||
{
|
||||
fc.SingleRefProb[i][j] =
|
||||
Prob.ModeMvMergeProbs(preFc.SingleRefProb[i][j], ref counts.SingleRef[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < Constants.InterModeContexts; i++)
|
||||
{
|
||||
Prob.VpxTreeMergeProbs(
|
||||
EntropyMode.InterModeTree,
|
||||
preFc.InterModeProb[i].AsSpan(),
|
||||
counts.InterMode[i].AsSpan(),
|
||||
fc.InterModeProb[i].AsSpan());
|
||||
}
|
||||
|
||||
for (int i = 0; i < EntropyMode.BlockSizeGroups; i++)
|
||||
{
|
||||
Prob.VpxTreeMergeProbs(
|
||||
EntropyMode.IntraModeTree,
|
||||
preFc.YModeProb[i].AsSpan(),
|
||||
counts.YMode[i].AsSpan(),
|
||||
fc.YModeProb[i].AsSpan());
|
||||
}
|
||||
|
||||
for (int i = 0; i < Constants.IntraModes; ++i)
|
||||
{
|
||||
Prob.VpxTreeMergeProbs(
|
||||
EntropyMode.IntraModeTree,
|
||||
preFc.UvModeProb[i].AsSpan(),
|
||||
counts.UvMode[i].AsSpan(),
|
||||
fc.UvModeProb[i].AsSpan());
|
||||
}
|
||||
|
||||
for (int i = 0; i < Constants.PartitionContexts; i++)
|
||||
{
|
||||
Prob.VpxTreeMergeProbs(
|
||||
EntropyMode.PartitionTree,
|
||||
preFc.PartitionProb[i].AsSpan(),
|
||||
counts.Partition[i].AsSpan(),
|
||||
fc.PartitionProb[i].AsSpan());
|
||||
}
|
||||
|
||||
if (InterpFilter == Constants.Switchable)
|
||||
{
|
||||
for (int i = 0; i < Constants.SwitchableFilterContexts; i++)
|
||||
{
|
||||
Prob.VpxTreeMergeProbs(
|
||||
EntropyMode.SwitchableInterpTree,
|
||||
preFc.SwitchableInterpProb[i].AsSpan(),
|
||||
counts.SwitchableInterp[i].AsSpan(),
|
||||
fc.SwitchableInterpProb[i].AsSpan());
|
||||
}
|
||||
}
|
||||
|
||||
if (TxMode == TxMode.TxModeSelect)
|
||||
{
|
||||
Array1<Array2<uint>> branchCt8X8P = new();
|
||||
Array2<Array2<uint>> branchCt16X16P = new();
|
||||
Array3<Array2<uint>> branchCt32X32P = new();
|
||||
|
||||
for (int i = 0; i < EntropyMode.TxSizeContexts; ++i)
|
||||
{
|
||||
EntropyMode.TxCountsToBranchCounts8X8(counts.Tx8x8[i].AsSpan(), ref branchCt8X8P);
|
||||
for (int j = 0; j < (int)TxSize.TxSizes - 3; ++j)
|
||||
{
|
||||
fc.Tx8x8Prob[i][j] = Prob.ModeMvMergeProbs(preFc.Tx8x8Prob[i][j], ref branchCt8X8P[j]);
|
||||
}
|
||||
|
||||
EntropyMode.TxCountsToBranchCounts16X16(counts.Tx16x16[i].AsSpan(), ref branchCt16X16P);
|
||||
for (int j = 0; j < (int)TxSize.TxSizes - 2; ++j)
|
||||
{
|
||||
fc.Tx16x16Prob[i][j] =
|
||||
Prob.ModeMvMergeProbs(preFc.Tx16x16Prob[i][j], ref branchCt16X16P[j]);
|
||||
}
|
||||
|
||||
EntropyMode.TxCountsToBranchCounts32X32(counts.Tx32x32[i].AsSpan(), ref branchCt32X32P);
|
||||
for (int j = 0; j < (int)TxSize.TxSizes - 1; ++j)
|
||||
{
|
||||
fc.Tx32x32Prob[i][j] =
|
||||
Prob.ModeMvMergeProbs(preFc.Tx32x32Prob[i][j], ref branchCt32X32P[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < Constants.SkipContexts; ++i)
|
||||
{
|
||||
fc.SkipProb[i] = Prob.ModeMvMergeProbs(preFc.SkipProb[i], ref counts.Skip[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void AdaptCoefProbs()
|
||||
{
|
||||
byte t;
|
||||
uint countSat, updateFactor;
|
||||
|
||||
if (FrameIsIntraOnly())
|
||||
{
|
||||
updateFactor = Entropy.CoefMaxUpdateFactorKey;
|
||||
countSat = Entropy.CoefCountSatKey;
|
||||
}
|
||||
else if (LastFrameType == FrameType.KeyFrame)
|
||||
{
|
||||
updateFactor = Entropy.CoefMaxUpdateFactorAfterKey; /* adapt quickly */
|
||||
countSat = Entropy.CoefCountSatAfterKey;
|
||||
}
|
||||
else
|
||||
{
|
||||
updateFactor = Entropy.CoefMaxUpdateFactor;
|
||||
countSat = Entropy.CoefCountSat;
|
||||
}
|
||||
|
||||
for (t = (int)TxSize.Tx4X4; t <= (int)TxSize.Tx32X32; t++)
|
||||
{
|
||||
AdaptCoefProbs(t, countSat, updateFactor);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetMvs(ReadOnlySpan<Vp9MvRef> mvs)
|
||||
{
|
||||
if (mvs.Length > PrevFrameMvs.Length)
|
||||
{
|
||||
throw new ArgumentException(
|
||||
$"Size mismatch, expected: {PrevFrameMvs.Length}, but got: {mvs.Length}.");
|
||||
}
|
||||
|
||||
for (int i = 0; i < mvs.Length; i++)
|
||||
{
|
||||
ref MvRef mv = ref PrevFrameMvs[i];
|
||||
|
||||
mv.Mv[0].Row = mvs[i].Mvs[0].Row;
|
||||
mv.Mv[0].Col = mvs[i].Mvs[0].Col;
|
||||
mv.Mv[1].Row = mvs[i].Mvs[1].Row;
|
||||
mv.Mv[1].Col = mvs[i].Mvs[1].Col;
|
||||
|
||||
mv.RefFrame[0] = (sbyte)mvs[i].RefFrames[0];
|
||||
mv.RefFrame[1] = (sbyte)mvs[i].RefFrames[1];
|
||||
}
|
||||
}
|
||||
|
||||
public void GetMvs(Span<Vp9MvRef> mvs)
|
||||
{
|
||||
if (mvs.Length > CurFrameMvs.Length)
|
||||
{
|
||||
throw new ArgumentException(
|
||||
$"Size mismatch, expected: {CurFrameMvs.Length}, but got: {mvs.Length}.");
|
||||
}
|
||||
|
||||
for (int i = 0; i < mvs.Length; i++)
|
||||
{
|
||||
ref MvRef mv = ref CurFrameMvs[i];
|
||||
|
||||
mvs[i].Mvs[0].Row = mv.Mv[0].Row;
|
||||
mvs[i].Mvs[0].Col = mv.Mv[0].Col;
|
||||
mvs[i].Mvs[1].Row = mv.Mv[1].Row;
|
||||
mvs[i].Mvs[1].Col = mv.Mv[1].Col;
|
||||
|
||||
mvs[i].RefFrames[0] = mv.RefFrame[0];
|
||||
mvs[i].RefFrames[1] = mv.RefFrame[1];
|
||||
}
|
||||
}
|
||||
|
||||
private void AdaptCoefProbs(byte txSize, uint countSat, uint updateFactor)
|
||||
{
|
||||
ref Vp9EntropyProbs preFc = ref FrameContexts[(int)FrameContextIdx];
|
||||
ref Array2<Array2<Array6<Array6<Array3<byte>>>>> probs = ref Fc.Value.CoefProbs[txSize];
|
||||
ref Array2<Array2<Array6<Array6<Array3<byte>>>>> preProbs = ref preFc.CoefProbs[txSize];
|
||||
ref Array2<Array2<Array6<Array6<Array4<uint>>>>> counts = ref Counts.Value.Coef[txSize];
|
||||
ref Array2<Array2<Array6<Array6<uint>>>> eobCounts = ref Counts.Value.EobBranch[txSize];
|
||||
|
||||
for (int i = 0; i < Constants.PlaneTypes; ++i)
|
||||
{
|
||||
for (int j = 0; j < Entropy.RefTypes; ++j)
|
||||
{
|
||||
for (int k = 0; k < Entropy.CoefBands; ++k)
|
||||
{
|
||||
for (int l = 0; l < Entropy.BAND_COEFF_CONTEXTS(k); ++l)
|
||||
{
|
||||
int n0 = (int)counts[i][j][k][l][Entropy.ZeroToken];
|
||||
int n1 = (int)counts[i][j][k][l][Entropy.OneToken];
|
||||
int n2 = (int)counts[i][j][k][l][Entropy.TwoToken];
|
||||
int neob = (int)counts[i][j][k][l][Entropy.EobModelToken];
|
||||
Array3<Array2<uint>> branchCt = new();
|
||||
branchCt[0][0] = (uint)neob;
|
||||
branchCt[0][1] = (uint)(eobCounts[i][j][k][l] - neob);
|
||||
branchCt[1][0] = (uint)n0;
|
||||
branchCt[1][1] = (uint)(n1 + n2);
|
||||
branchCt[2][0] = (uint)n1;
|
||||
branchCt[2][1] = (uint)n2;
|
||||
for (int m = 0; m < Entropy.UnconstrainedNodes; ++m)
|
||||
{
|
||||
probs[i][j][k][l][m] = Prob.MergeProbs(preProbs[i][j][k][l][m], ref branchCt[m],
|
||||
countSat, updateFactor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void DefaultCoefProbs()
|
||||
{
|
||||
Entropy.CopyProbs(ref Fc.Value.CoefProbs[(int)TxSize.Tx4X4], Entropy.DefaultCoefProbs4X4);
|
||||
Entropy.CopyProbs(ref Fc.Value.CoefProbs[(int)TxSize.Tx8X8], Entropy.DefaultCoefProbs8X8);
|
||||
Entropy.CopyProbs(ref Fc.Value.CoefProbs[(int)TxSize.Tx16X16], Entropy.DefaultCoefProbs16X16);
|
||||
Entropy.CopyProbs(ref Fc.Value.CoefProbs[(int)TxSize.Tx32X32], Entropy.DefaultCoefProbs32X32);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
410
src/Ryujinx.Graphics.Nvdec.Vp9/Types/Vp9Decoder.cs
Normal file
410
src/Ryujinx.Graphics.Nvdec.Vp9/Types/Vp9Decoder.cs
Normal file
@ -0,0 +1,410 @@
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.Graphics.Nvdec.Vp9.Common;
|
||||
using Ryujinx.Graphics.Video;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
{
|
||||
internal struct Vp9Decoder
|
||||
{
|
||||
public Vp9Common Common;
|
||||
|
||||
public int ReadyForNewData;
|
||||
|
||||
public int RefreshFrameFlags;
|
||||
|
||||
public int NeedResync; // Wait for key/intra-only frame.
|
||||
public int HoldRefBuf; // Hold the reference buffer.
|
||||
|
||||
private static void DecreaseRefCount(int idx, ref Array12<RefCntBuffer> frameBufs, ref BufferPool pool)
|
||||
{
|
||||
if (idx >= 0 && frameBufs[idx].RefCount > 0)
|
||||
{
|
||||
--frameBufs[idx].RefCount;
|
||||
// A worker may only get a free framebuffer index when calling GetFreeFb.
|
||||
// But the private buffer is not set up until finish decoding header.
|
||||
// So any error happens during decoding header, the frame_bufs will not
|
||||
// have valid priv buffer.
|
||||
if (frameBufs[idx].Released == 0 && frameBufs[idx].RefCount == 0 &&
|
||||
!frameBufs[idx].RawFrameBuffer.Priv.IsNull)
|
||||
{
|
||||
FrameBuffers.ReleaseFrameBuffer(pool.CbPriv, ref frameBufs[idx].RawFrameBuffer);
|
||||
frameBufs[idx].Released = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Create(MemoryAllocator allocator, ref BufferPool pool)
|
||||
{
|
||||
ref Vp9Common cm = ref Common;
|
||||
|
||||
cm.CheckMemError(ref cm.Fc,
|
||||
new Ptr<Vp9EntropyProbs>(ref allocator.Allocate<Vp9EntropyProbs>(1)[0]));
|
||||
cm.CheckMemError(ref cm.FrameContexts,
|
||||
allocator.Allocate<Vp9EntropyProbs>(Constants.FrameContexts));
|
||||
|
||||
for (int i = 0; i < EntropyMode.KfYModeProb.Length; i++)
|
||||
{
|
||||
for (int j = 0; j < EntropyMode.KfYModeProb[i].Length; j++)
|
||||
{
|
||||
for (int k = 0; k < EntropyMode.KfYModeProb[i][j].Length; k++)
|
||||
{
|
||||
cm.Fc.Value.KfYModeProb[i][j][k] = EntropyMode.KfYModeProb[i][j][k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < EntropyMode.KfUvModeProb.Length; i++)
|
||||
{
|
||||
for (int j = 0; j < EntropyMode.KfUvModeProb[i].Length; j++)
|
||||
{
|
||||
cm.Fc.Value.KfUvModeProb[i][j] = EntropyMode.KfUvModeProb[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
byte[][] kfPartitionProbs =
|
||||
[
|
||||
// 8x8 . 4x4
|
||||
[158, 97, 94], // a/l both not split
|
||||
[93, 24, 99], // a split, l not split
|
||||
[85, 119, 44], // l split, a not split
|
||||
[62, 59, 67], // a/l both split
|
||||
|
||||
// 16x16 . 8x8
|
||||
[149, 53, 53], // a/l both not split
|
||||
[94, 20, 48], // a split, l not split
|
||||
[83, 53, 24], // l split, a not split
|
||||
[52, 18, 18], // a/l both split
|
||||
|
||||
// 32x32 . 16x16
|
||||
[150, 40, 39], // a/l both not split
|
||||
[78, 12, 26], // a split, l not split
|
||||
[67, 33, 11], // l split, a not split
|
||||
[24, 7, 5], // a/l both split
|
||||
|
||||
// 64x64 . 32x32
|
||||
[174, 35, 49], // a/l both not split
|
||||
[68, 11, 27], // a split, l not split
|
||||
[57, 15, 9], // l split, a not split
|
||||
[12, 3, 3] // a/l both split
|
||||
];
|
||||
|
||||
for (int i = 0; i < kfPartitionProbs.Length; i++)
|
||||
{
|
||||
for (int j = 0; j < kfPartitionProbs[i].Length; j++)
|
||||
{
|
||||
cm.Fc.Value.KfPartitionProb[i][j] = kfPartitionProbs[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
cm.Counts = new Ptr<Vp9BackwardUpdates>(ref allocator.Allocate<Vp9BackwardUpdates>(1)[0]);
|
||||
|
||||
NeedResync = 1;
|
||||
|
||||
// Initialize the references to not point to any frame buffers.
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
cm.RefFrameMap[i] = -1;
|
||||
cm.NextRefFrameMap[i] = -1;
|
||||
}
|
||||
|
||||
cm.CurrentVideoFrame = 0;
|
||||
ReadyForNewData = 1;
|
||||
Common.BufferPool = new Ptr<BufferPool>(ref pool);
|
||||
|
||||
cm.BitDepth = BitDepth.Bits8;
|
||||
cm.DequantBitDepth = BitDepth.Bits8;
|
||||
|
||||
// vp9_loop_filter_init(ref cm);
|
||||
}
|
||||
|
||||
/* If any buffer updating is signaled it should be done here. */
|
||||
private void SwapFrameBuffers()
|
||||
{
|
||||
int refIndex = 0, mask;
|
||||
ref Vp9Common cm = ref Common;
|
||||
ref BufferPool pool = ref cm.BufferPool.Value;
|
||||
ref Array12<RefCntBuffer> frameBufs = ref cm.BufferPool.Value.FrameBufs;
|
||||
|
||||
for (mask = RefreshFrameFlags; mask != 0; mask >>= 1)
|
||||
{
|
||||
int oldIdx = cm.RefFrameMap[refIndex];
|
||||
// Current thread releases the holding of reference frame.
|
||||
DecreaseRefCount(oldIdx, ref frameBufs, ref pool);
|
||||
|
||||
// Release the reference frame in reference map.
|
||||
if ((mask & 1) != 0)
|
||||
{
|
||||
DecreaseRefCount(oldIdx, ref frameBufs, ref pool);
|
||||
}
|
||||
|
||||
cm.RefFrameMap[refIndex] = cm.NextRefFrameMap[refIndex];
|
||||
++refIndex;
|
||||
}
|
||||
|
||||
// Current thread releases the holding of reference frame.
|
||||
for (; refIndex < Constants.RefFrames && cm.ShowExistingFrame == 0; ++refIndex)
|
||||
{
|
||||
int oldIdx = cm.RefFrameMap[refIndex];
|
||||
DecreaseRefCount(oldIdx, ref frameBufs, ref pool);
|
||||
cm.RefFrameMap[refIndex] = cm.NextRefFrameMap[refIndex];
|
||||
}
|
||||
|
||||
HoldRefBuf = 0;
|
||||
cm.FrameToShow = new Ptr<Surface>(ref cm.GetFrameNewBuffer());
|
||||
|
||||
--frameBufs[cm.NewFbIdx].RefCount;
|
||||
|
||||
// Invalidate these references until the next frame starts.
|
||||
for (refIndex = 0; refIndex < 3; refIndex++)
|
||||
{
|
||||
cm.FrameRefs[refIndex].Idx = RefBuffer.InvalidIdx;
|
||||
}
|
||||
}
|
||||
|
||||
public CodecErr ReceiveCompressedData(MemoryAllocator allocator, ulong size, ref ArrayPtr<byte> psource)
|
||||
{
|
||||
ref Vp9Common cm = ref Common;
|
||||
ref BufferPool pool = ref cm.BufferPool.Value;
|
||||
ref Array12<RefCntBuffer> frameBufs = ref cm.BufferPool.Value.FrameBufs;
|
||||
ArrayPtr<byte> source = psource;
|
||||
CodecErr retcode = 0;
|
||||
cm.Error.ErrorCode = CodecErr.Ok;
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
// This is used to signal that we are missing frames.
|
||||
// We do not know if the missing frame(s) was supposed to update
|
||||
// any of the reference buffers, but we act conservative and
|
||||
// mark only the last buffer as corrupted.
|
||||
|
||||
if (cm.FrameRefs[0].Idx > 0)
|
||||
{
|
||||
cm.FrameRefs[0].Buf.Corrupted = 1;
|
||||
}
|
||||
}
|
||||
|
||||
ReadyForNewData = 0;
|
||||
|
||||
// Check if the previous frame was a frame without any references to it.
|
||||
if (cm.NewFbIdx >= 0 && frameBufs[cm.NewFbIdx].RefCount == 0 &&
|
||||
frameBufs[cm.NewFbIdx].Released == 0)
|
||||
{
|
||||
FrameBuffers.ReleaseFrameBuffer(pool.CbPriv, ref frameBufs[cm.NewFbIdx].RawFrameBuffer);
|
||||
frameBufs[cm.NewFbIdx].Released = 1;
|
||||
}
|
||||
|
||||
// Find a free frame buffer. Return error if can not find any.
|
||||
cm.NewFbIdx = cm.GetFreeFb();
|
||||
if (cm.NewFbIdx == RefBuffer.InvalidIdx)
|
||||
{
|
||||
ReadyForNewData = 1;
|
||||
cm.Error.InternalError(CodecErr.MemError, "Unable to find free frame buffer");
|
||||
|
||||
return cm.Error.ErrorCode;
|
||||
}
|
||||
|
||||
// Assign a MV array to the frame buffer.
|
||||
cm.CurFrame = new Ptr<RefCntBuffer>(ref pool.FrameBufs[cm.NewFbIdx]);
|
||||
|
||||
HoldRefBuf = 0;
|
||||
|
||||
DecodeFrame.Decode(allocator, ref this, new ArrayPtr<byte>(ref source[0], (int)size), out psource);
|
||||
|
||||
SwapFrameBuffers();
|
||||
|
||||
// vpx_clear_system_state();
|
||||
|
||||
if (cm.ShowExistingFrame == 0)
|
||||
{
|
||||
cm.LastShowFrame = cm.ShowFrame;
|
||||
cm.PrevFrame = cm.CurFrame;
|
||||
|
||||
if (cm.PrevFrameMvs.IsNull || cm.PrevFrameMvs.Length != cm.CurFrameMvs.Length)
|
||||
{
|
||||
allocator.Free(cm.PrevFrameMvs);
|
||||
cm.PrevFrameMvs = allocator.Allocate<MvRef>(cm.CurFrameMvs.Length);
|
||||
}
|
||||
|
||||
cm.CurFrameMvs.AsSpan().CopyTo(cm.PrevFrameMvs.AsSpan());
|
||||
if (cm.Seg.Enabled)
|
||||
{
|
||||
cm.SwapCurrentAndLastSegMap();
|
||||
}
|
||||
}
|
||||
|
||||
if (cm.ShowFrame != 0)
|
||||
{
|
||||
cm.CurShowFrameFbIdx = cm.NewFbIdx;
|
||||
}
|
||||
|
||||
// Update progress in frame parallel decode.
|
||||
cm.LastWidth = cm.Width;
|
||||
cm.LastHeight = cm.Height;
|
||||
if (cm.ShowFrame != 0)
|
||||
{
|
||||
cm.CurrentVideoFrame++;
|
||||
}
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
public int GetRawFrame(ref Surface sd)
|
||||
{
|
||||
ref Vp9Common cm = ref Common;
|
||||
int ret = -1;
|
||||
|
||||
if (ReadyForNewData == 1)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ReadyForNewData = 1;
|
||||
|
||||
if (cm.ShowFrame == 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ReadyForNewData = 1;
|
||||
|
||||
sd = cm.FrameToShow.Value;
|
||||
ret = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public CodecErr Decode(MemoryAllocator allocator, ArrayPtr<byte> data)
|
||||
{
|
||||
ArrayPtr<byte> dataStart = data;
|
||||
CodecErr res;
|
||||
Array8<uint> frameSizes = new();
|
||||
int frameCount = 0;
|
||||
|
||||
res = Decoder.ParseSuperframeIndex(data, (ulong)data.Length, ref frameSizes, out frameCount);
|
||||
if (res != CodecErr.Ok)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
|
||||
// Decode in serial mode.
|
||||
if (frameCount > 0)
|
||||
{
|
||||
for (int i = 0; i < frameCount; ++i)
|
||||
{
|
||||
ArrayPtr<byte> dataStartCopy = dataStart;
|
||||
uint frameSize = frameSizes[i];
|
||||
if (frameSize > (uint)dataStart.Length)
|
||||
{
|
||||
return CodecErr.CorruptFrame;
|
||||
}
|
||||
|
||||
res = ReceiveCompressedData(allocator, frameSize, ref dataStartCopy);
|
||||
if (res != CodecErr.Ok)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
|
||||
dataStart = dataStart.Slice((int)frameSize);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (dataStart.Length != 0)
|
||||
{
|
||||
uint frameSize = (uint)dataStart.Length;
|
||||
res = ReceiveCompressedData(allocator, frameSize, ref dataStart);
|
||||
if (res != CodecErr.Ok)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
|
||||
// Account for suboptimal termination by the encoder.
|
||||
while (dataStart.Length != 0)
|
||||
{
|
||||
byte marker = Decoder.ReadMarker(dataStart);
|
||||
if (marker != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
dataStart = dataStart.Slice(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
internal static class Decoder
|
||||
{
|
||||
public static byte ReadMarker(ArrayPtr<byte> data)
|
||||
{
|
||||
return data[0];
|
||||
}
|
||||
|
||||
public static CodecErr ParseSuperframeIndex(ArrayPtr<byte> data, ulong dataSz, ref Array8<uint> sizes, out int count)
|
||||
{
|
||||
// A chunk ending with a byte matching 0xc0 is an invalid chunk unless
|
||||
// it is a super frame index. If the last byte of real video compression
|
||||
// data is 0xc0 the encoder must add a 0 byte. If we have the marker but
|
||||
// not the associated matching marker byte at the front of the index we have
|
||||
// an invalid bitstream and need to return an error.
|
||||
|
||||
byte marker;
|
||||
|
||||
Debug.Assert(dataSz != 0);
|
||||
marker = ReadMarker(data.Slice((int)dataSz - 1));
|
||||
count = 0;
|
||||
|
||||
if ((marker & 0xe0) == 0xc0)
|
||||
{
|
||||
uint frames = (uint)(marker & 0x7) + 1;
|
||||
uint mag = (uint)((marker >> 3) & 0x3) + 1;
|
||||
ulong indexSz = 2 + (mag * frames);
|
||||
|
||||
// This chunk is marked as having a superframe index but doesn't have
|
||||
// enough data for it, thus it's an invalid superframe index.
|
||||
if (dataSz < indexSz)
|
||||
{
|
||||
return CodecErr.CorruptFrame;
|
||||
}
|
||||
|
||||
{
|
||||
byte marker2 = ReadMarker(data.Slice((int)(dataSz - indexSz)));
|
||||
|
||||
// This chunk is marked as having a superframe index but doesn't have
|
||||
// the matching marker byte at the front of the index therefore it's an
|
||||
// invalid chunk.
|
||||
if (marker != marker2)
|
||||
{
|
||||
return CodecErr.CorruptFrame;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// Found a valid superframe index.
|
||||
ArrayPtr<byte> x = data.Slice((int)(dataSz - indexSz + 1));
|
||||
|
||||
for (int i = 0; i < frames; ++i)
|
||||
{
|
||||
uint thisSz = 0;
|
||||
|
||||
for (int j = 0; j < mag; ++j)
|
||||
{
|
||||
thisSz |= (uint)x[0] << j * 8;
|
||||
x = x.Slice(1);
|
||||
}
|
||||
|
||||
sizes[i] = thisSz;
|
||||
}
|
||||
|
||||
count = (int)frames;
|
||||
}
|
||||
}
|
||||
|
||||
return CodecErr.Ok;
|
||||
}
|
||||
}
|
||||
}
|
10
src/Ryujinx.Graphics.Nvdec.Vp9/Types/VpxCodecFrameBuffer.cs
Normal file
10
src/Ryujinx.Graphics.Nvdec.Vp9/Types/VpxCodecFrameBuffer.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using Ryujinx.Common.Memory;
|
||||
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
{
|
||||
internal struct VpxCodecFrameBuffer
|
||||
{
|
||||
public ArrayPtr<byte> Data;
|
||||
public Ptr<InternalFrameBuffer> Priv;
|
||||
}
|
||||
}
|
11
src/Ryujinx.Graphics.Nvdec.Vp9/Types/VpxColorRange.cs
Normal file
11
src/Ryujinx.Graphics.Nvdec.Vp9/Types/VpxColorRange.cs
Normal file
@ -0,0 +1,11 @@
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
{
|
||||
internal enum VpxColorRange
|
||||
{
|
||||
// Y [16..235], UV [16..240]
|
||||
Studio,
|
||||
|
||||
// YUV/RGB [0..255]
|
||||
Full
|
||||
}
|
||||
}
|
29
src/Ryujinx.Graphics.Nvdec.Vp9/Types/VpxColorSpace.cs
Normal file
29
src/Ryujinx.Graphics.Nvdec.Vp9/Types/VpxColorSpace.cs
Normal file
@ -0,0 +1,29 @@
|
||||
namespace Ryujinx.Graphics.Nvdec.Vp9.Types
|
||||
{
|
||||
internal enum VpxColorSpace
|
||||
{
|
||||
// Unknown
|
||||
Unknown,
|
||||
|
||||
// BT.601
|
||||
Bt601,
|
||||
|
||||
// BT.709
|
||||
Bt709,
|
||||
|
||||
// SMPTE.170
|
||||
Smpte170,
|
||||
|
||||
// SMPTE.240
|
||||
Smpte240,
|
||||
|
||||
// BT.2020
|
||||
Bt2020,
|
||||
|
||||
// Reserved
|
||||
Reserved,
|
||||
|
||||
// sRGB
|
||||
Srgb
|
||||
}
|
||||
}
|
@ -59,6 +59,8 @@ namespace Ryujinx.Graphics.Nvdec.Types.Vp9
|
||||
Flags.HasFlag(FrameFlags.LastShowFrame) &&
|
||||
!Flags.HasFlag(FrameFlags.LastFrameIsKeyFrame),
|
||||
RefFrameSignBias = RefFrameSignBias,
|
||||
LoopFilterLevel = FirstLevel,
|
||||
LoopFilterSharpnessLevel = SharpnessLevel,
|
||||
BaseQIndex = BaseQIndex,
|
||||
YDcDeltaQ = YDcDeltaQ,
|
||||
UvDcDeltaQ = UvDcDeltaQ,
|
||||
|
@ -10,6 +10,8 @@ namespace Ryujinx.Graphics.Video
|
||||
public bool IsKeyFrame;
|
||||
public bool IntraOnly;
|
||||
public Array4<sbyte> RefFrameSignBias;
|
||||
public int LoopFilterLevel;
|
||||
public int LoopFilterSharpnessLevel;
|
||||
public int BaseQIndex;
|
||||
public int YDcDeltaQ;
|
||||
public int UvDcDeltaQ;
|
||||
@ -36,4 +38,4 @@ namespace Ryujinx.Graphics.Video
|
||||
public Vp9EntropyProbs Entropy;
|
||||
public Vp9BackwardUpdates BackwardUpdateCounts;
|
||||
}
|
||||
}
|
||||
}
|
@ -41,7 +41,7 @@ namespace Ryujinx.HLE.HOS.Applets.Browser
|
||||
{
|
||||
List<BrowserOutput> result =
|
||||
[
|
||||
new BrowserOutput(BrowserOutputType.ExitReason, (uint)WebExitReason.ExitButton)
|
||||
new(BrowserOutputType.ExitReason, (uint)WebExitReason.ExitButton)
|
||||
];
|
||||
|
||||
_normalSession.Push(BuildResponseNew(result));
|
||||
|
@ -23,9 +23,6 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator
|
||||
{
|
||||
class IUserLocalCommunicationService : IpcService, IDisposable
|
||||
{
|
||||
public static string DefaultLanPlayHost = "ryuldn.vudjun.com";
|
||||
public static short LanPlayPort = 30456;
|
||||
|
||||
public INetworkClient NetworkClient { get; private set; }
|
||||
|
||||
private const int NifmRequestID = 90;
|
||||
@ -1092,20 +1089,18 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator
|
||||
case MultiplayerMode.LdnRyu:
|
||||
try
|
||||
{
|
||||
string ldnServer = context.Device.Configuration.MultiplayerLdnServer;
|
||||
if (string.IsNullOrEmpty(ldnServer))
|
||||
{
|
||||
ldnServer = DefaultLanPlayHost;
|
||||
}
|
||||
string ldnServer = context.Device.Configuration.MultiplayerLdnServer
|
||||
?? throw new InvalidOperationException("Cannot initialize RyuLDN with a null Multiplayer server.");
|
||||
|
||||
if (!IPAddress.TryParse(ldnServer, out IPAddress ipAddress))
|
||||
{
|
||||
ipAddress = Dns.GetHostEntry(ldnServer).AddressList[0];
|
||||
}
|
||||
NetworkClient = new LdnMasterProxyClient(ipAddress.ToString(), LanPlayPort, context.Device.Configuration);
|
||||
NetworkClient = new LdnMasterProxyClient(ipAddress.ToString(), SharedConstants.LanPlayPort, context.Device.Configuration);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.ServiceLdn, "Could not locate LdnRyu server. Defaulting to stubbed wireless.");
|
||||
Logger.Error?.Print(LogClass.ServiceLdn, "Could not locate RyuLDN server. Defaulting to stubbed wireless.");
|
||||
Logger.Error?.Print(LogClass.ServiceLdn, ex.Message);
|
||||
NetworkClient = new LdnDisabledClient();
|
||||
}
|
||||
|
@ -111,7 +111,7 @@ namespace Ryujinx.Input.SDL2
|
||||
byte blue = packedRgb > 0 ? (byte)(packedRgb % 256) : (byte)0;
|
||||
|
||||
if (SDL_GameControllerSetLED(_gamepadHandle, red, green, blue) != 0)
|
||||
Logger.Error?.Print(LogClass.Hid, "LED setting failed; probably in the middle of disconnecting.");
|
||||
Logger.Debug?.Print(LogClass.Hid, "LED setting failed; probably in the middle of disconnecting.");
|
||||
}
|
||||
|
||||
private GamepadFeaturesFlag GetFeaturesFlag()
|
||||
|
@ -951,7 +951,7 @@ namespace Ryujinx.Ava
|
||||
ConfigurationState.Instance.Multiplayer.Mode,
|
||||
ConfigurationState.Instance.Multiplayer.DisableP2p,
|
||||
ConfigurationState.Instance.Multiplayer.LdnPassphrase,
|
||||
ConfigurationState.Instance.Multiplayer.LdnServer,
|
||||
ConfigurationState.Instance.Multiplayer.GetLdnServer(),
|
||||
ConfigurationState.Instance.Graphics.CustomVSyncInterval.Value,
|
||||
ConfigurationState.Instance.Hacks.ShowDirtyHacks ? ConfigurationState.Instance.Hacks.EnabledHacks : null));
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -289,7 +289,8 @@ namespace Ryujinx.Headless
|
||||
|
||||
DriverUtilities.InitDriverConfig(option.BackendThreading == BackendThreading.Off);
|
||||
|
||||
if (_inputConfiguration.OfType<StandardControllerInputConfig>().Any(ic => ic.Led.UseRainbow))
|
||||
if (_inputConfiguration.OfType<StandardControllerInputConfig>()
|
||||
.Any(ic => ic?.Led?.UseRainbow ?? false))
|
||||
Rainbow.Enable();
|
||||
|
||||
while (true)
|
||||
|
@ -189,7 +189,7 @@ namespace Ryujinx.Ava.UI.Controls
|
||||
DirectoryInfo mainDir = new(Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString, "cache", "cpu", "0"));
|
||||
DirectoryInfo backupDir = new(Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString, "cache", "cpu", "1"));
|
||||
|
||||
List<FileInfo> cacheFiles = new();
|
||||
List<FileInfo> cacheFiles = [];
|
||||
|
||||
if (mainDir.Exists)
|
||||
{
|
||||
|
@ -798,7 +798,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
return false;
|
||||
}
|
||||
|
||||
private async Task HandleFirmwareInstallation(string filename)
|
||||
public async Task HandleFirmwareInstallation(string filename)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -133,12 +133,6 @@
|
||||
<ComboBoxItem>
|
||||
<TextBlock Text="{ext:Locale SettingsTabSystemSystemLanguageBrazilianPortuguese}" />
|
||||
</ComboBoxItem>
|
||||
<ComboBoxItem>
|
||||
<TextBlock Text="{ext:Locale SettingsTabSystemSystemLanguageSwedish}" />
|
||||
</ComboBoxItem>
|
||||
<ComboBoxItem>
|
||||
<TextBlock Text="{ext:Locale SettingsTabSystemSystemLanguageNorwegian}" />
|
||||
</ComboBoxItem>
|
||||
</ComboBox>
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
|
@ -139,8 +139,24 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
base.OnApplyTemplate(e);
|
||||
|
||||
NotificationHelper.SetNotificationManager(this);
|
||||
|
||||
Executor.ExecuteBackgroundAsync(ShowIntelMacWarningAsync);
|
||||
|
||||
Executor.ExecuteBackgroundAsync(async () =>
|
||||
{
|
||||
await ShowIntelMacWarningAsync();
|
||||
FilePath firmwarePath = CommandLineState.FirmwareToInstallPathArg;
|
||||
if (firmwarePath is not null)
|
||||
{
|
||||
if ((firmwarePath.ExistsAsFile && firmwarePath.Extension is "xci" or "zip") ||
|
||||
firmwarePath.ExistsAsDirectory)
|
||||
{
|
||||
await Dispatcher.UIThread.InvokeAsync(() =>
|
||||
ViewModel.HandleFirmwareInstallation(firmwarePath));
|
||||
CommandLineState.FirmwareToInstallPathArg = null;
|
||||
}
|
||||
else
|
||||
Logger.Notice.Print(LogClass.UI, "Invalid firmware type provided. Path must be a directory, or a .zip or .xci file.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void OnScalingChanged(object sender, EventArgs e)
|
||||
@ -173,17 +189,12 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
{
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
List<LdnGameData> ldnGameDataArray = e.LdnData.ToList();
|
||||
ViewModel.LdnData.Clear();
|
||||
foreach (ApplicationData application in ViewModel.Applications.Where(it => it.HasControlHolder))
|
||||
{
|
||||
ref ApplicationControlProperty controlHolder = ref application.ControlHolder.Value;
|
||||
|
||||
ViewModel.LdnData[application.IdString] =
|
||||
LdnGameData.GetArrayForApp(
|
||||
ldnGameDataArray,
|
||||
ref controlHolder
|
||||
);
|
||||
|
||||
ViewModel.LdnData[application.IdString] = e.LdnData.Where(ref controlHolder);
|
||||
|
||||
UpdateApplicationWithLdnData(application);
|
||||
}
|
||||
|
@ -42,7 +42,6 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
|
||||
{
|
||||
public class ApplicationLibrary
|
||||
{
|
||||
public const string DefaultLanPlayWebHost = "ryuldnweb.vudjun.com";
|
||||
public Language DesiredLanguage { get; set; }
|
||||
public event EventHandler<ApplicationCountUpdatedEventArgs> ApplicationCountUpdated;
|
||||
public event Action<LdnGameDataReceivedEventArgs> LdnGameDataReceived;
|
||||
@ -827,7 +826,6 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
|
||||
|
||||
public async Task RefreshLdn()
|
||||
{
|
||||
|
||||
if (ConfigurationState.Instance.Multiplayer.Mode == MultiplayerMode.LdnRyu)
|
||||
{
|
||||
try
|
||||
@ -835,33 +833,22 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
|
||||
string ldnWebHost = ConfigurationState.Instance.Multiplayer.LdnServer;
|
||||
if (string.IsNullOrEmpty(ldnWebHost))
|
||||
{
|
||||
ldnWebHost = DefaultLanPlayWebHost;
|
||||
ldnWebHost = SharedConstants.DefaultLanPlayWebHost;
|
||||
}
|
||||
IEnumerable<LdnGameData> ldnGameDataArray = Array.Empty<LdnGameData>();
|
||||
|
||||
using HttpClient httpClient = new();
|
||||
string ldnGameDataArrayString = await httpClient.GetStringAsync($"https://{ldnWebHost}/api/public_games");
|
||||
ldnGameDataArray = JsonHelper.Deserialize(ldnGameDataArrayString, _ldnDataSerializerContext.IEnumerableLdnGameData);
|
||||
LdnGameDataReceived?.Invoke(new LdnGameDataReceivedEventArgs
|
||||
{
|
||||
LdnData = ldnGameDataArray
|
||||
});
|
||||
LdnGameData[] ldnGameDataArray = JsonHelper.Deserialize(ldnGameDataArrayString, _ldnDataSerializerContext.IEnumerableLdnGameData).ToArray();
|
||||
LdnGameDataReceived?.Invoke(new LdnGameDataReceivedEventArgs(ldnGameDataArray));
|
||||
return;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.Application, $"Failed to fetch the public games JSON from the API. Player and game count in the game list will be unavailable.\n{ex.Message}");
|
||||
LdnGameDataReceived?.Invoke(new LdnGameDataReceivedEventArgs
|
||||
{
|
||||
LdnData = Array.Empty<LdnGameData>()
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LdnGameDataReceived?.Invoke(new LdnGameDataReceivedEventArgs
|
||||
{
|
||||
LdnData = Array.Empty<LdnGameData>()
|
||||
});
|
||||
}
|
||||
|
||||
LdnGameDataReceived?.Invoke(LdnGameDataReceivedEventArgs.Empty);
|
||||
}
|
||||
|
||||
// Replace the currently stored DLC state for the game with the provided DLC state.
|
||||
|
@ -18,7 +18,7 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
|
||||
public IEnumerable<string> Players { get; set; }
|
||||
|
||||
public static Array GetArrayForApp(
|
||||
IEnumerable<LdnGameData> receivedData, ref ApplicationControlProperty acp)
|
||||
LdnGameData[] receivedData, ref ApplicationControlProperty acp)
|
||||
{
|
||||
LibHac.Common.FixedArrays.Array8<ulong> communicationId = acp.LocalCommunicationId;
|
||||
|
||||
@ -40,4 +40,10 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
|
||||
public int GameCount => _ldnDatas.Length;
|
||||
}
|
||||
}
|
||||
|
||||
public static class LdnGameDataHelper
|
||||
{
|
||||
public static LdnGameData.Array Where(this LdnGameData[] unfilteredDatas, ref ApplicationControlProperty acp)
|
||||
=> LdnGameData.GetArrayForApp(unfilteredDatas, ref acp);
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,14 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
|
||||
{
|
||||
public class LdnGameDataReceivedEventArgs : EventArgs
|
||||
{
|
||||
public IEnumerable<LdnGameData> LdnData { get; set; }
|
||||
public static new readonly LdnGameDataReceivedEventArgs Empty = new(null);
|
||||
|
||||
public LdnGameDataReceivedEventArgs(LdnGameData[] ldnData)
|
||||
{
|
||||
LdnData = ldnData ?? [];
|
||||
}
|
||||
|
||||
|
||||
public LdnGameData[] LdnData { get; set; }
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user