Compare commits

...

8 Commits

Author SHA1 Message Date
TSRBerry
cebfa54467 [Ryujinx.Graphics.Texture] Address dotnet-format issues (#5375)
* dotnet format style --severity info

Some changes were manually reverted.

* Restore a few unused methods and variables

* Silence dotnet format IDE0060 warnings

* Silence dotnet format IDE0059 warnings

* Address or silence dotnet format CA2208 warnings

* Address most dotnet format whitespace warnings

* Apply dotnet format whitespace formatting

A few of them have been manually reverted and the corresponding warning was silenced

* Format if-blocks correctly

* Add comments to disabled warnings

* Simplify properties and array initialization, Use const when possible, Remove trailing commas

* Address IDE0251 warnings

* Silence IDE0060 in .editorconfig

* Revert "Simplify properties and array initialization, Use const when possible, Remove trailing commas"

This reverts commit 9462e4136c0a2100dc28b20cf9542e06790aa67e.

* dotnet format whitespace after rebase

* First dotnet format pass

* Apply suggestions from code review

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Address review feedback

* Update src/Ryujinx.Graphics.Texture/Astc/AstcDecoder.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

---------

Co-authored-by: Ac_K <Acoustik666@gmail.com>
2023-06-28 18:46:18 +02:00
TSRBerry
fc20d9b925 [Ryujinx.Common] Address dotnet-format issues (#5358)
* dotnet format style --severity info

Some changes were manually reverted.

* dotnet format analyzers --serverity info

Some changes have been minimally adapted.

* Restore a few unused methods and variables

* Silence dotnet format IDE0060 warnings

* Silence dotnet format IDE0059 warnings

* Address or silence dotnet format IDE1006 warnings

* Address dotnet format CA1816 warnings

* Address or silence dotnet format CA2211 warnings

* Silence CA1806 and CA1834 issues

* Fix formatting for switch expressions

* Address most dotnet format whitespace warnings

* Apply dotnet format whitespace formatting

A few of them have been manually reverted and the corresponding warning was silenced

* Revert formatting changes for while and for-loops

* Format if-blocks correctly

* Run dotnet format whitespace after rebase

* Run dotnet format style after rebase

* Run dotnet format analyzers after rebase

* Run dotnet format after rebase and remove unused usings

- analyzers
- style
- whitespace

* Add comments to disabled warnings

* Remove a few unused parameters

* Replace MmeShadowScratch with Array256<uint>

* Simplify properties and array initialization, Use const when possible, Remove trailing commas

* Run dotnet format after rebase

* Address IDE0251 warnings

* Revert "Simplify properties and array initialization, Use const when possible, Remove trailing commas"

This reverts commit 9462e4136c0a2100dc28b20cf9542e06790aa67e.

* dotnet format whitespace after rebase

* First dotnet format pass

* Second dotnet format pass

* Fix build issues

* Fix StructArrayHelpers.cs

* Apply suggestions from code review

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Fix return statements

* Fix naming rule violations

* Update src/Ryujinx.Common/Utilities/StreamUtils.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Add trailing commas

* Address review feedback

* Address review feedback

* Rename remaining type parameters to TKey and TValue

* Fix manual formatting for logging levels

* Fix spacing before comments

---------

Co-authored-by: Ac_K <Acoustik666@gmail.com>
2023-06-28 18:41:38 +02:00
TSRBerry
0a75b73fa4 [Ryujinx.Memory] Address dotnet-format issues (#5386)
* dotnet format style --severity info

Some changes were manually reverted.

* dotnet format analyzers --serverity info

Some changes have been minimally adapted.

* Silence dotnet format IDE0059 warnings

* Address or silence dotnet format IDE1006 warnings

* Address dotnet format CA1816 warnings

* Address or silence dotnet format CA1069 warnings

* Address remaining dotnet format analyzer warnings

* Address review comments

* Address most dotnet format whitespace warnings

* Apply dotnet format whitespace formatting

A few of them have been manually reverted and the corresponding warning was silenced

* Format if-blocks correctly

* Another rebase, another dotnet format run

* Run dotnet format after rebase and remove unused usings

- analyzers
- style
- whitespace

* Add comments to disabled warnings

* Simplify properties and array initialization, Use const when possible, Remove trailing commas

* Revert "Simplify properties and array initialization, Use const when possible, Remove trailing commas"

This reverts commit 9462e4136c0a2100dc28b20cf9542e06790aa67e.

* dotnet format whitespace after rebase

* Address review feedback

* Assign Decommit to ReplacePlaceholder

* Run final dotnet format pass

* Organize imports again

* Add trailing commas

* Add missing newline
2023-06-28 18:34:00 +02:00
TSRBerry
46b7c905f5 [Ryujinx.Input] Address dotnet-format issues (#5384)
* dotnet format style --severity info

Some changes were manually reverted.

* dotnet format analyzers --serverity info

Some changes have been minimally adapted.

* Restore a few unused methods and variables

* Address dotnet format CA1816 warnings

* Address or silence dotnet format CA1806 and a few CA1854 warnings

* Address most dotnet format whitespace warnings

* Apply dotnet format whitespace formatting

A few of them have been manually reverted and the corresponding warning was silenced

* Add comments to disabled warnings

* Simplify properties and array initialization, Use const when possible, Remove trailing commas

* Revert "Simplify properties and array initialization, Use const when possible, Remove trailing commas"

This reverts commit 9462e4136c0a2100dc28b20cf9542e06790aa67e.

* dotnet format whitespace after rebase

* Remove redundant code, convert to auto-properties and fix naming rule violations

* Remove bogus change

* Address review feedback
2023-06-28 18:23:00 +02:00
TSRBerry
40f2bd37e3 [Ryujinx.Graphics.OpenGL] Address dotnet-format issues (#5372)
* dotnet format style --severity info

Some changes were manually reverted.

* dotnet format analyzers --serverity info

Some changes have been minimally adapted.

* Restore a few unused methods and variables

* Silence dotnet format IDE0060 warnings

* Address or silence dotnet format IDE1006 warnings

* Fix IDE0090 after rebase

* Address most dotnet format whitespace warnings

* Apply dotnet format whitespace formatting

A few of them have been manually reverted and the corresponding warning was silenced

* Format if-blocks correctly

* Another rebase, another dotnet format run

* Run dotnet format after rebase and remove unused usings

- analyzers
- style
- whitespace

* Add comments to disabled warnings

* Simplify properties and array initialization, Use const when possible, Remove trailing commas

* Start working on disabled warnings

* Address a few disabled IDE0060 warnings

* Silence IDE0060 in .editorconfig

* Revert "Simplify properties and array initialization, Use const when possible, Remove trailing commas"

This reverts commit 9462e4136c0a2100dc28b20cf9542e06790aa67e.

* dotnet format whitespace after rebase

* First dotnet format pass

* Address review feedback
2023-06-28 18:10:55 +02:00
Ac_K
9288ffd26d Cpu: Implement VCVT (between floating-point and fixed-point) instruction (#5343)
* cpu: Implement VCVT (between floating-point and fixed-point) instruction

Rebase, fix and superseed of https://github.com/Ryujinx/Ryujinx/pull/2915

(Since I only have little CPU knowledge, I hope I have done everything good)

* Update Ptc.cs

* Fix wrong cast

* Rename tests

* Addresses feedback

Co-Authored-By: gdkchan <5624669+gdkchan@users.noreply.github.com>

* Remove extra empty line

---------

Co-authored-by: gdkchan <5624669+gdkchan@users.noreply.github.com>
2023-06-28 17:36:30 +02:00
dependabot[bot]
2cdc82cb91 nuget: bump Microsoft.NET.Test.Sdk from 17.6.2 to 17.6.3 (#5406)
Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 17.6.2 to 17.6.3.
- [Release notes](https://github.com/microsoft/vstest/releases)
- [Changelog](https://github.com/microsoft/vstest/blob/main/docs/releases.md)
- [Commits](https://github.com/microsoft/vstest/compare/v17.6.2...v17.6.3)

---
updated-dependencies:
- dependency-name: Microsoft.NET.Test.Sdk
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-28 09:36:22 +02:00
TSRBerry
6aa8d71588 [Ryujinx.Graphics.Nvdec.Vp9] Address dotnet-format issues (#5371)
* dotnet format style --severity info

Some changes were manually reverted.

* dotnet format analyzers --serverity info

Some changes have been minimally adapted.

* Restore a few unused methods and variables

* Silence dotnet format IDE0060 warnings

* Address or silence dotnet format IDE1006 warnings

* Address most dotnet format whitespace warnings

* Apply dotnet format whitespace formatting

A few of them have been manually reverted and the corresponding warning was silenced

* Add comments to disabled warnings

* Simplify properties and array initialization, Use const when possible, Remove trailing commas

* Address IDE0251 warnings

* Address a few disabled IDE0060 warnings

* Silence IDE0060 in .editorconfig

* Revert "Simplify properties and array initialization, Use const when possible, Remove trailing commas"

This reverts commit 9462e4136c0a2100dc28b20cf9542e06790aa67e.

* dotnet format whitespace after rebase

* Fix empty lines before return

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Add trailing commas, remove redundant code and remove static modifier from Surface.HighBd

* Fix naming rule violations

* Fix naming rule violations

* Fix empty line before return

* Fix comment style

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Remove comment alignment

* Address review feedback

* Separate comments by 2 spaces and fix other formatting issues

* Make HighBd an auto-property

* Replace if-chain with if-else-chain

* Fix new naming rule violations

---------

Co-authored-by: Ac_K <Acoustik666@gmail.com>
2023-06-28 09:26:39 +02:00
250 changed files with 3896 additions and 3589 deletions

View File

@@ -21,7 +21,7 @@
<PackageVersion Include="LibHac" Version="0.18.0" /> <PackageVersion Include="LibHac" Version="0.18.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" /> <PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.5.0" /> <PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.5.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.6.2" /> <PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.6.3" />
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="2.3.2" /> <PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="2.3.2" />
<PackageVersion Include="MsgPack.Cli" Version="1.0.1" /> <PackageVersion Include="MsgPack.Cli" Version="1.0.1" />
<PackageVersion Include="NUnit" Version="3.13.3" /> <PackageVersion Include="NUnit" Version="3.13.3" />

View File

@@ -0,0 +1,23 @@
namespace ARMeilleure.Decoders
{
class OpCode32SimdCvtFFixed : OpCode32Simd
{
public int Fbits { get; protected set; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdCvtFFixed(inst, address, opCode, false);
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdCvtFFixed(inst, address, opCode, true);
public OpCode32SimdCvtFFixed(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
{
Opc = (opCode >> 8) & 0x1;
Size = Opc == 1 ? 0 : 2;
Fbits = 64 - ((opCode >> 16) & 0x3f);
if (DecoderHelper.VectorArgumentsInvalid(Q, Vd, Vm))
{
Instruction = InstDescriptor.Undefined;
}
}
}
}

View File

@@ -918,6 +918,7 @@ namespace ARMeilleure.Decoders
SetAsimd("111100111x11xx01xxxx0x100xx0xxxx", InstName.Vclt, InstEmit32.Vclt_Z, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32); SetAsimd("111100111x11xx01xxxx0x100xx0xxxx", InstName.Vclt, InstEmit32.Vclt_Z, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
SetAsimd("111100111x110000xxxx01010xx0xxxx", InstName.Vcnt, InstEmit32.Vcnt, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32); SetAsimd("111100111x110000xxxx01010xx0xxxx", InstName.Vcnt, InstEmit32.Vcnt, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
SetAsimd("111100111x111011xxxx011xxxx0xxxx", InstName.Vcvt, InstEmit32.Vcvt_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32); // FP and integer, vector. SetAsimd("111100111x111011xxxx011xxxx0xxxx", InstName.Vcvt, InstEmit32.Vcvt_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32); // FP and integer, vector.
SetAsimd("1111001x1x1xxxxxxxxx111x0xx1xxxx", InstName.Vcvt, InstEmit32.Vcvt_V_Fixed, OpCode32SimdCvtFFixed.Create, OpCode32SimdCvtFFixed.CreateT32); // Between floating point and fixed point, vector.
SetAsimd("111100111x11xxxxxxxx11000xx0xxxx", InstName.Vdup, InstEmit32.Vdup_1, OpCode32SimdDupElem.Create, OpCode32SimdDupElem.CreateT32); SetAsimd("111100111x11xxxxxxxx11000xx0xxxx", InstName.Vdup, InstEmit32.Vdup_1, OpCode32SimdDupElem.Create, OpCode32SimdDupElem.CreateT32);
SetAsimd("111100110x00xxxxxxxx0001xxx1xxxx", InstName.Veor, InstEmit32.Veor_I, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32); SetAsimd("111100110x00xxxxxxxx0001xxx1xxxx", InstName.Veor, InstEmit32.Veor_I, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32);
SetAsimd("111100101x11xxxxxxxxxxxxxxx0xxxx", InstName.Vext, InstEmit32.Vext, OpCode32SimdExt.Create, OpCode32SimdExt.CreateT32); SetAsimd("111100101x11xxxxxxxxxxxxxxx0xxxx", InstName.Vext, InstEmit32.Vext, OpCode32SimdExt.Create, OpCode32SimdExt.CreateT32);
@@ -1130,7 +1131,7 @@ namespace ARMeilleure.Decoders
SetT16("1101<<<xxxxxxxxx", InstName.B, InstEmit32.B, OpCodeT16BImm8.Create); SetT16("1101<<<xxxxxxxxx", InstName.B, InstEmit32.B, OpCodeT16BImm8.Create);
SetT16("11011111xxxxxxxx", InstName.Svc, InstEmit32.Svc, OpCodeT16Exception.Create); SetT16("11011111xxxxxxxx", InstName.Svc, InstEmit32.Svc, OpCodeT16Exception.Create);
SetT16("11100xxxxxxxxxxx", InstName.B, InstEmit32.B, OpCodeT16BImm11.Create); SetT16("11100xxxxxxxxxxx", InstName.B, InstEmit32.B, OpCodeT16BImm11.Create);
#endregion #endregion
#region "OpCode Table (AArch32, T32)" #region "OpCode Table (AArch32, T32)"
// Base // Base
@@ -1298,7 +1299,7 @@ namespace ARMeilleure.Decoders
SetT32("11110011101011111000000000000010", InstName.Wfe, InstEmit32.Nop, OpCodeT32.Create); SetT32("11110011101011111000000000000010", InstName.Wfe, InstEmit32.Nop, OpCodeT32.Create);
SetT32("11110011101011111000000000000011", InstName.Wfi, InstEmit32.Nop, OpCodeT32.Create); SetT32("11110011101011111000000000000011", InstName.Wfi, InstEmit32.Nop, OpCodeT32.Create);
SetT32("11110011101011111000000000000001", InstName.Yield, InstEmit32.Nop, OpCodeT32.Create); SetT32("11110011101011111000000000000001", InstName.Yield, InstEmit32.Nop, OpCodeT32.Create);
#endregion #endregion
FillFastLookupTable(_instA32FastLookup, _allInstA32, ToFastLookupIndexA); FillFastLookupTable(_instA32FastLookup, _allInstA32, ToFastLookupIndexA);
FillFastLookupTable(_instT32FastLookup, _allInstT32, ToFastLookupIndexT); FillFastLookupTable(_instT32FastLookup, _allInstT32, ToFastLookupIndexT);

View File

@@ -114,6 +114,35 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Vcvt_V_Fixed(ArmEmitterContext context)
{
OpCode32SimdCvtFFixed op = (OpCode32SimdCvtFFixed)context.CurrOp;
var toFixed = op.Opc == 1;
int fracBits = op.Fbits;
var unsigned = op.U;
if (toFixed) // F32 to S32 or U32 (fixed)
{
EmitVectorUnaryOpF32(context, (op1) =>
{
var scaledValue = context.Multiply(op1, ConstF(MathF.Pow(2f, fracBits)));
MethodInfo info = unsigned ? typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToU32)) : typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToS32));
return context.Call(info, scaledValue);
});
}
else // S32 or U32 (fixed) to F32
{
EmitVectorUnaryOpI32(context, (op1) =>
{
var floatValue = unsigned ? context.ConvertToFPUI(OperandType.FP32, op1) : context.ConvertToFP(OperandType.FP32, op1);
return context.Multiply(floatValue, ConstF(1f / MathF.Pow(2f, fracBits)));
}, !unsigned);
}
}
public static void Vcvt_FD(ArmEmitterContext context) public static void Vcvt_FD(ArmEmitterContext context)
{ {
OpCode32SimdS op = (OpCode32SimdS)context.CurrOp; OpCode32SimdS op = (OpCode32SimdS)context.CurrOp;

View File

@@ -29,7 +29,7 @@ namespace ARMeilleure.Translation.PTC
private const string OuterHeaderMagicString = "PTCohd\0\0"; private const string OuterHeaderMagicString = "PTCohd\0\0";
private const string InnerHeaderMagicString = "PTCihd\0\0"; private const string InnerHeaderMagicString = "PTCihd\0\0";
private const uint InternalVersion = 5292; //! To be incremented manually for each change to the ARMeilleure project. private const uint InternalVersion = 5343; //! To be incremented manually for each change to the ARMeilleure project.
private const string ActualDir = "0"; private const string ActualDir = "0";
private const string BackupDir = "1"; private const string BackupDir = "1";

View File

@@ -7,9 +7,9 @@ namespace Ryujinx.Common.Collections
/// <summary> /// <summary>
/// An Augmented Interval Tree based off of the "TreeDictionary"'s Red-Black Tree. Allows fast overlap checking of ranges. /// An Augmented Interval Tree based off of the "TreeDictionary"'s Red-Black Tree. Allows fast overlap checking of ranges.
/// </summary> /// </summary>
/// <typeparam name="K">Key</typeparam> /// <typeparam name="TKey">Key</typeparam>
/// <typeparam name="V">Value</typeparam> /// <typeparam name="TValue">Value</typeparam>
public class IntervalTree<K, V> : IntrusiveRedBlackTreeImpl<IntervalTreeNode<K, V>> where K : IComparable<K> public class IntervalTree<TKey, TValue> : IntrusiveRedBlackTreeImpl<IntervalTreeNode<TKey, TValue>> where TKey : IComparable<TKey>
{ {
private const int ArrayGrowthSize = 32; private const int ArrayGrowthSize = 32;
@@ -22,11 +22,11 @@ namespace Ryujinx.Common.Collections
/// <param name="overlaps">Overlaps array to place results in</param> /// <param name="overlaps">Overlaps array to place results in</param>
/// <returns>Number of values found</returns> /// <returns>Number of values found</returns>
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception> /// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
public int Get(K key, ref V[] overlaps) public int Get(TKey key, ref TValue[] overlaps)
{ {
ArgumentNullException.ThrowIfNull(key); ArgumentNullException.ThrowIfNull(key);
IntervalTreeNode<K, V> node = GetNode(key); IntervalTreeNode<TKey, TValue> node = GetNode(key);
if (node == null) if (node == null)
{ {
@@ -39,7 +39,7 @@ namespace Ryujinx.Common.Collections
} }
int overlapsCount = 0; int overlapsCount = 0;
foreach (RangeNode<K, V> value in node.Values) foreach (RangeNode<TKey, TValue> value in node.Values)
{ {
overlaps[overlapsCount++] = value.Value; overlaps[overlapsCount++] = value.Value;
} }
@@ -56,7 +56,7 @@ namespace Ryujinx.Common.Collections
/// <param name="overlapCount">Index to start writing results into the array. Defaults to 0</param> /// <param name="overlapCount">Index to start writing results into the array. Defaults to 0</param>
/// <returns>Number of values found</returns> /// <returns>Number of values found</returns>
/// <exception cref="ArgumentNullException"><paramref name="start"/> or <paramref name="end"/> is null</exception> /// <exception cref="ArgumentNullException"><paramref name="start"/> or <paramref name="end"/> is null</exception>
public int Get(K start, K end, ref V[] overlaps, int overlapCount = 0) public int Get(TKey start, TKey end, ref TValue[] overlaps, int overlapCount = 0)
{ {
ArgumentNullException.ThrowIfNull(start); ArgumentNullException.ThrowIfNull(start);
ArgumentNullException.ThrowIfNull(end); ArgumentNullException.ThrowIfNull(end);
@@ -73,7 +73,7 @@ namespace Ryujinx.Common.Collections
/// <param name="end">End of the range to insert</param> /// <param name="end">End of the range to insert</param>
/// <param name="value">Value to add</param> /// <param name="value">Value to add</param>
/// <exception cref="ArgumentNullException"><paramref name="start"/>, <paramref name="end"/> or <paramref name="value"/> are null</exception> /// <exception cref="ArgumentNullException"><paramref name="start"/>, <paramref name="end"/> or <paramref name="value"/> are null</exception>
public void Add(K start, K end, V value) public void Add(TKey start, TKey end, TValue value)
{ {
ArgumentNullException.ThrowIfNull(start); ArgumentNullException.ThrowIfNull(start);
ArgumentNullException.ThrowIfNull(end); ArgumentNullException.ThrowIfNull(end);
@@ -89,7 +89,7 @@ namespace Ryujinx.Common.Collections
/// <param name="value">Value to remove</param> /// <param name="value">Value to remove</param>
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception> /// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
/// <returns>Number of deleted values</returns> /// <returns>Number of deleted values</returns>
public int Remove(K key, V value) public int Remove(TKey key, TValue value)
{ {
ArgumentNullException.ThrowIfNull(key); ArgumentNullException.ThrowIfNull(key);
@@ -104,9 +104,9 @@ namespace Ryujinx.Common.Collections
/// Adds all the nodes in the dictionary into <paramref name="list"/>. /// Adds all the nodes in the dictionary into <paramref name="list"/>.
/// </summary> /// </summary>
/// <returns>A list of all RangeNodes sorted by Key Order</returns> /// <returns>A list of all RangeNodes sorted by Key Order</returns>
public List<RangeNode<K, V>> AsList() public List<RangeNode<TKey, TValue>> AsList()
{ {
List<RangeNode<K, V>> list = new List<RangeNode<K, V>>(); List<RangeNode<TKey, TValue>> list = new();
AddToList(Root, list); AddToList(Root, list);
@@ -122,7 +122,7 @@ namespace Ryujinx.Common.Collections
/// </summary> /// </summary>
/// <param name="node">The node to search for RangeNodes within</param> /// <param name="node">The node to search for RangeNodes within</param>
/// <param name="list">The list to add RangeNodes to</param> /// <param name="list">The list to add RangeNodes to</param>
private void AddToList(IntervalTreeNode<K, V> node, List<RangeNode<K, V>> list) private void AddToList(IntervalTreeNode<TKey, TValue> node, List<RangeNode<TKey, TValue>> list)
{ {
if (node == null) if (node == null)
{ {
@@ -142,11 +142,11 @@ namespace Ryujinx.Common.Collections
/// <param name="key">Key of the node to get</param> /// <param name="key">Key of the node to get</param>
/// <returns>Node reference in the tree</returns> /// <returns>Node reference in the tree</returns>
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception> /// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
private IntervalTreeNode<K, V> GetNode(K key) private IntervalTreeNode<TKey, TValue> GetNode(TKey key)
{ {
ArgumentNullException.ThrowIfNull(key); ArgumentNullException.ThrowIfNull(key);
IntervalTreeNode<K, V> node = Root; IntervalTreeNode<TKey, TValue> node = Root;
while (node != null) while (node != null)
{ {
int cmp = key.CompareTo(node.Start); int cmp = key.CompareTo(node.Start);
@@ -173,7 +173,7 @@ namespace Ryujinx.Common.Collections
/// <param name="end">End of the range</param> /// <param name="end">End of the range</param>
/// <param name="overlaps">Overlaps array to place results in</param> /// <param name="overlaps">Overlaps array to place results in</param>
/// <param name="overlapCount">Overlaps count to update</param> /// <param name="overlapCount">Overlaps count to update</param>
private void GetValues(IntervalTreeNode<K, V> node, K start, K end, ref V[] overlaps, ref int overlapCount) private void GetValues(IntervalTreeNode<TKey, TValue> node, TKey start, TKey end, ref TValue[] overlaps, ref int overlapCount)
{ {
if (node == null || start.CompareTo(node.Max) >= 0) if (node == null || start.CompareTo(node.Max) >= 0)
{ {
@@ -188,7 +188,7 @@ namespace Ryujinx.Common.Collections
if (start.CompareTo(node.End) < 0) if (start.CompareTo(node.End) < 0)
{ {
// Contains this node. Add overlaps to list. // Contains this node. Add overlaps to list.
foreach (RangeNode<K,V> overlap in node.Values) foreach (RangeNode<TKey, TValue> overlap in node.Values)
{ {
if (start.CompareTo(overlap.End) < 0) if (start.CompareTo(overlap.End) < 0)
{ {
@@ -212,9 +212,9 @@ namespace Ryujinx.Common.Collections
/// <param name="start">Start of the range to insert</param> /// <param name="start">Start of the range to insert</param>
/// <param name="end">End of the range to insert</param> /// <param name="end">End of the range to insert</param>
/// <param name="value">Value to insert</param> /// <param name="value">Value to insert</param>
private void Insert(K start, K end, V value) private void Insert(TKey start, TKey end, TValue value)
{ {
IntervalTreeNode<K, V> newNode = BSTInsert(start, end, value); IntervalTreeNode<TKey, TValue> newNode = BSTInsert(start, end, value);
RestoreBalanceAfterInsertion(newNode); RestoreBalanceAfterInsertion(newNode);
} }
@@ -223,10 +223,10 @@ namespace Ryujinx.Common.Collections
/// This should only be called if the max increases - not for rebalancing or removals. /// This should only be called if the max increases - not for rebalancing or removals.
/// </summary> /// </summary>
/// <param name="node">The node to start propagating from</param> /// <param name="node">The node to start propagating from</param>
private void PropagateIncrease(IntervalTreeNode<K, V> node) private static void PropagateIncrease(IntervalTreeNode<TKey, TValue> node)
{ {
K max = node.Max; TKey max = node.Max;
IntervalTreeNode<K, V> ptr = node; IntervalTreeNode<TKey, TValue> ptr = node;
while ((ptr = ptr.Parent) != null) while ((ptr = ptr.Parent) != null)
{ {
@@ -246,13 +246,13 @@ namespace Ryujinx.Common.Collections
/// This fully recalculates the max value from all children when there is potential for it to decrease. /// This fully recalculates the max value from all children when there is potential for it to decrease.
/// </summary> /// </summary>
/// <param name="node">The node to start propagating from</param> /// <param name="node">The node to start propagating from</param>
private void PropagateFull(IntervalTreeNode<K, V> node) private static void PropagateFull(IntervalTreeNode<TKey, TValue> node)
{ {
IntervalTreeNode<K, V> ptr = node; IntervalTreeNode<TKey, TValue> ptr = node;
do do
{ {
K max = ptr.End; TKey max = ptr.End;
if (ptr.Left != null && ptr.Left.Max.CompareTo(max) > 0) if (ptr.Left != null && ptr.Left.Max.CompareTo(max) > 0)
{ {
@@ -278,10 +278,10 @@ namespace Ryujinx.Common.Collections
/// <param name="end">End of the range to insert</param> /// <param name="end">End of the range to insert</param>
/// <param name="value">Value to insert</param> /// <param name="value">Value to insert</param>
/// <returns>The inserted Node</returns> /// <returns>The inserted Node</returns>
private IntervalTreeNode<K, V> BSTInsert(K start, K end, V value) private IntervalTreeNode<TKey, TValue> BSTInsert(TKey start, TKey end, TValue value)
{ {
IntervalTreeNode<K, V> parent = null; IntervalTreeNode<TKey, TValue> parent = null;
IntervalTreeNode<K, V> node = Root; IntervalTreeNode<TKey, TValue> node = Root;
while (node != null) while (node != null)
{ {
@@ -297,7 +297,7 @@ namespace Ryujinx.Common.Collections
} }
else else
{ {
node.Values.Add(new RangeNode<K, V>(start, end, value)); node.Values.Add(new RangeNode<TKey, TValue>(start, end, value));
if (end.CompareTo(node.End) > 0) if (end.CompareTo(node.End) > 0)
{ {
@@ -313,7 +313,7 @@ namespace Ryujinx.Common.Collections
return node; return node;
} }
} }
IntervalTreeNode<K, V> newNode = new IntervalTreeNode<K, V>(start, end, value, parent); IntervalTreeNode<TKey, TValue> newNode = new(start, end, value, parent);
if (newNode.Parent == null) if (newNode.Parent == null)
{ {
Root = newNode; Root = newNode;
@@ -338,9 +338,9 @@ namespace Ryujinx.Common.Collections
/// <param name="key">Key to search for</param> /// <param name="key">Key to search for</param>
/// <param name="value">Value to delete</param> /// <param name="value">Value to delete</param>
/// <returns>Number of deleted values</returns> /// <returns>Number of deleted values</returns>
private int Delete(K key, V value) private int Delete(TKey key, TValue value)
{ {
IntervalTreeNode<K, V> nodeToDelete = GetNode(key); IntervalTreeNode<TKey, TValue> nodeToDelete = GetNode(key);
if (nodeToDelete == null) if (nodeToDelete == null)
{ {
@@ -362,7 +362,7 @@ namespace Ryujinx.Common.Collections
return removed; return removed;
} }
IntervalTreeNode<K, V> replacementNode; IntervalTreeNode<TKey, TValue> replacementNode;
if (LeftOf(nodeToDelete) == null || RightOf(nodeToDelete) == null) if (LeftOf(nodeToDelete) == null || RightOf(nodeToDelete) == null)
{ {
@@ -373,7 +373,7 @@ namespace Ryujinx.Common.Collections
replacementNode = PredecessorOf(nodeToDelete); replacementNode = PredecessorOf(nodeToDelete);
} }
IntervalTreeNode<K, V> tmp = LeftOf(replacementNode) ?? RightOf(replacementNode); IntervalTreeNode<TKey, TValue> tmp = LeftOf(replacementNode) ?? RightOf(replacementNode);
if (tmp != null) if (tmp != null)
{ {
@@ -413,7 +413,7 @@ namespace Ryujinx.Common.Collections
#endregion #endregion
protected override void RotateLeft(IntervalTreeNode<K, V> node) protected override void RotateLeft(IntervalTreeNode<TKey, TValue> node)
{ {
if (node != null) if (node != null)
{ {
@@ -423,7 +423,7 @@ namespace Ryujinx.Common.Collections
} }
} }
protected override void RotateRight(IntervalTreeNode<K, V> node) protected override void RotateRight(IntervalTreeNode<TKey, TValue> node)
{ {
if (node != null) if (node != null)
{ {
@@ -433,7 +433,7 @@ namespace Ryujinx.Common.Collections
} }
} }
public bool ContainsKey(K key) public bool ContainsKey(TKey key)
{ {
ArgumentNullException.ThrowIfNull(key); ArgumentNullException.ThrowIfNull(key);
@@ -444,15 +444,15 @@ namespace Ryujinx.Common.Collections
/// <summary> /// <summary>
/// Represents a value and its start and end keys. /// Represents a value and its start and end keys.
/// </summary> /// </summary>
/// <typeparam name="K"></typeparam> /// <typeparam name="TKey"></typeparam>
/// <typeparam name="V"></typeparam> /// <typeparam name="TValue"></typeparam>
public readonly struct RangeNode<K, V> public readonly struct RangeNode<TKey, TValue>
{ {
public readonly K Start; public readonly TKey Start;
public readonly K End; public readonly TKey End;
public readonly V Value; public readonly TValue Value;
public RangeNode(K start, K end, V value) public RangeNode(TKey start, TKey end, TValue value)
{ {
Start = start; Start = start;
End = end; End = end;
@@ -463,36 +463,36 @@ namespace Ryujinx.Common.Collections
/// <summary> /// <summary>
/// Represents a node in the IntervalTree which contains start and end keys of type K, and a value of generic type V. /// Represents a node in the IntervalTree which contains start and end keys of type K, and a value of generic type V.
/// </summary> /// </summary>
/// <typeparam name="K">Key type of the node</typeparam> /// <typeparam name="TKey">Key type of the node</typeparam>
/// <typeparam name="V">Value type of the node</typeparam> /// <typeparam name="TValue">Value type of the node</typeparam>
public class IntervalTreeNode<K, V> : IntrusiveRedBlackTreeNode<IntervalTreeNode<K, V>> public class IntervalTreeNode<TKey, TValue> : IntrusiveRedBlackTreeNode<IntervalTreeNode<TKey, TValue>>
{ {
/// <summary> /// <summary>
/// The start of the range. /// The start of the range.
/// </summary> /// </summary>
internal K Start; internal TKey Start;
/// <summary> /// <summary>
/// The end of the range - maximum of all in the Values list. /// The end of the range - maximum of all in the Values list.
/// </summary> /// </summary>
internal K End; internal TKey End;
/// <summary> /// <summary>
/// The maximum end value of this node and all its children. /// The maximum end value of this node and all its children.
/// </summary> /// </summary>
internal K Max; internal TKey Max;
/// <summary> /// <summary>
/// Values contained on the node that shares a common Start value. /// Values contained on the node that shares a common Start value.
/// </summary> /// </summary>
internal List<RangeNode<K, V>> Values; internal List<RangeNode<TKey, TValue>> Values;
internal IntervalTreeNode(K start, K end, V value, IntervalTreeNode<K, V> parent) internal IntervalTreeNode(TKey start, TKey end, TValue value, IntervalTreeNode<TKey, TValue> parent)
{ {
Start = start; Start = start;
End = end; End = end;
Max = end; Max = end;
Values = new List<RangeNode<K, V>> { new RangeNode<K, V>(start, end, value) }; Values = new List<RangeNode<TKey, TValue>> { new RangeNode<TKey, TValue>(start, end, value) };
Parent = parent; Parent = parent;
} }
} }

View File

@@ -180,11 +180,6 @@ namespace Ryujinx.Common.Collections
parent.Right = child; parent.Right = child;
} }
if (ParentOf(element) == old)
{
parent = element;
}
element.Color = old.Color; element.Color = old.Color;
element.Left = old.Left; element.Left = old.Left;
element.Right = old.Right; element.Right = old.Right;
@@ -258,11 +253,11 @@ namespace Ryujinx.Common.Collections
/// <param name="tree">Tree to search at</param> /// <param name="tree">Tree to search at</param>
/// <param name="key">Key of the node to be found</param> /// <param name="key">Key of the node to be found</param>
/// <returns>Node that is equal to <paramref name="key"/></returns> /// <returns>Node that is equal to <paramref name="key"/></returns>
public static N GetNodeByKey<N, K>(this IntrusiveRedBlackTree<N> tree, K key) public static TNode GetNodeByKey<TNode, TKey>(this IntrusiveRedBlackTree<TNode> tree, TKey key)
where N : IntrusiveRedBlackTreeNode<N>, IComparable<N>, IComparable<K> where TNode : IntrusiveRedBlackTreeNode<TNode>, IComparable<TNode>, IComparable<TKey>
where K : struct where TKey : struct
{ {
N node = tree.RootNode; TNode node = tree.RootNode;
while (node != null) while (node != null)
{ {
int cmp = node.CompareTo(key); int cmp = node.CompareTo(key);

View File

@@ -10,7 +10,7 @@ namespace Ryujinx.Common.Collections
{ {
protected const bool Black = true; protected const bool Black = true;
protected const bool Red = false; protected const bool Red = false;
protected T Root = null; protected T Root;
internal T RootNode => Root; internal T RootNode => Root;

View File

@@ -8,9 +8,9 @@ namespace Ryujinx.Common.Collections
/// <summary> /// <summary>
/// Dictionary that provides the ability for O(logN) Lookups for keys that exist in the Dictionary, and O(logN) lookups for keys immediately greater than or less than a specified key. /// Dictionary that provides the ability for O(logN) Lookups for keys that exist in the Dictionary, and O(logN) lookups for keys immediately greater than or less than a specified key.
/// </summary> /// </summary>
/// <typeparam name="K">Key</typeparam> /// <typeparam name="TKey">Key</typeparam>
/// <typeparam name="V">Value</typeparam> /// <typeparam name="TValue">Value</typeparam>
public class TreeDictionary<K, V> : IntrusiveRedBlackTreeImpl<Node<K, V>>, IDictionary<K, V> where K : IComparable<K> public class TreeDictionary<TKey, TValue> : IntrusiveRedBlackTreeImpl<Node<TKey, TValue>>, IDictionary<TKey, TValue> where TKey : IComparable<TKey>
{ {
#region Public Methods #region Public Methods
@@ -20,11 +20,11 @@ namespace Ryujinx.Common.Collections
/// <param name="key">Key of the node value to get</param> /// <param name="key">Key of the node value to get</param>
/// <returns>Value associated w/ <paramref name="key"/></returns> /// <returns>Value associated w/ <paramref name="key"/></returns>
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception> /// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
public V Get(K key) public TValue Get(TKey key)
{ {
ArgumentNullException.ThrowIfNull(key); ArgumentNullException.ThrowIfNull(key);
Node<K, V> node = GetNode(key); Node<TKey, TValue> node = GetNode(key);
if (node == null) if (node == null)
{ {
@@ -42,7 +42,7 @@ namespace Ryujinx.Common.Collections
/// <param name="key">Key of the node to add</param> /// <param name="key">Key of the node to add</param>
/// <param name="value">Value of the node to add</param> /// <param name="value">Value of the node to add</param>
/// <exception cref="ArgumentNullException"><paramref name="key"/> or <paramref name="value"/> are null</exception> /// <exception cref="ArgumentNullException"><paramref name="key"/> or <paramref name="value"/> are null</exception>
public void Add(K key, V value) public void Add(TKey key, TValue value)
{ {
ArgumentNullException.ThrowIfNull(key); ArgumentNullException.ThrowIfNull(key);
ArgumentNullException.ThrowIfNull(value); ArgumentNullException.ThrowIfNull(value);
@@ -55,7 +55,7 @@ namespace Ryujinx.Common.Collections
/// </summary> /// </summary>
/// <param name="key">Key of the node to remove</param> /// <param name="key">Key of the node to remove</param>
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception> /// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
public void Remove(K key) public void Remove(TKey key)
{ {
ArgumentNullException.ThrowIfNull(key); ArgumentNullException.ThrowIfNull(key);
@@ -71,9 +71,9 @@ namespace Ryujinx.Common.Collections
/// <param name="key">Key for which to find the floor value of</param> /// <param name="key">Key for which to find the floor value of</param>
/// <returns>Key of node immediately less than <paramref name="key"/></returns> /// <returns>Key of node immediately less than <paramref name="key"/></returns>
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception> /// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
public K Floor(K key) public TKey Floor(TKey key)
{ {
Node<K, V> node = FloorNode(key); Node<TKey, TValue> node = FloorNode(key);
if (node != null) if (node != null)
{ {
return node.Key; return node.Key;
@@ -87,9 +87,9 @@ namespace Ryujinx.Common.Collections
/// <param name="key">Key for which to find the ceiling node of</param> /// <param name="key">Key for which to find the ceiling node of</param>
/// <returns>Key of node immediately greater than <paramref name="key"/></returns> /// <returns>Key of node immediately greater than <paramref name="key"/></returns>
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception> /// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
public K Ceiling(K key) public TKey Ceiling(TKey key)
{ {
Node<K, V> node = CeilingNode(key); Node<TKey, TValue> node = CeilingNode(key);
if (node != null) if (node != null)
{ {
return node.Key; return node.Key;
@@ -102,12 +102,12 @@ namespace Ryujinx.Common.Collections
/// </summary> /// </summary>
/// <param name="key">Key to find the successor of</param> /// <param name="key">Key to find the successor of</param>
/// <returns>Value</returns> /// <returns>Value</returns>
public K SuccessorOf(K key) public TKey SuccessorOf(TKey key)
{ {
Node<K, V> node = GetNode(key); Node<TKey, TValue> node = GetNode(key);
if (node != null) if (node != null)
{ {
Node<K, V> successor = SuccessorOf(node); Node<TKey, TValue> successor = SuccessorOf(node);
return successor != null ? successor.Key : default; return successor != null ? successor.Key : default;
} }
@@ -119,12 +119,12 @@ namespace Ryujinx.Common.Collections
/// </summary> /// </summary>
/// <param name="key">Key to find the predecessor of</param> /// <param name="key">Key to find the predecessor of</param>
/// <returns>Value</returns> /// <returns>Value</returns>
public K PredecessorOf(K key) public TKey PredecessorOf(TKey key)
{ {
Node<K, V> node = GetNode(key); Node<TKey, TValue> node = GetNode(key);
if (node != null) if (node != null)
{ {
Node<K, V> predecessor = PredecessorOf(node); Node<TKey, TValue> predecessor = PredecessorOf(node);
return predecessor != null ? predecessor.Key : default; return predecessor != null ? predecessor.Key : default;
} }
@@ -137,19 +137,19 @@ namespace Ryujinx.Common.Collections
/// The key/value pairs will be added in Level Order. /// The key/value pairs will be added in Level Order.
/// </summary> /// </summary>
/// <param name="list">List to add the tree pairs into</param> /// <param name="list">List to add the tree pairs into</param>
public List<KeyValuePair<K, V>> AsLevelOrderList() public List<KeyValuePair<TKey, TValue>> AsLevelOrderList()
{ {
List<KeyValuePair<K, V>> list = new List<KeyValuePair<K, V>>(); List<KeyValuePair<TKey, TValue>> list = new();
Queue<Node<K, V>> nodes = new Queue<Node<K, V>>(); Queue<Node<TKey, TValue>> nodes = new();
if (this.Root != null) if (this.Root != null)
{ {
nodes.Enqueue(this.Root); nodes.Enqueue(this.Root);
} }
while (nodes.TryDequeue(out Node<K, V> node)) while (nodes.TryDequeue(out Node<TKey, TValue> node))
{ {
list.Add(new KeyValuePair<K, V>(node.Key, node.Value)); list.Add(new KeyValuePair<TKey, TValue>(node.Key, node.Value));
if (node.Left != null) if (node.Left != null)
{ {
nodes.Enqueue(node.Left); nodes.Enqueue(node.Left);
@@ -166,9 +166,9 @@ namespace Ryujinx.Common.Collections
/// Adds all the nodes in the dictionary into <paramref name="list"/>. /// Adds all the nodes in the dictionary into <paramref name="list"/>.
/// </summary> /// </summary>
/// <returns>A list of all KeyValuePairs sorted by Key Order</returns> /// <returns>A list of all KeyValuePairs sorted by Key Order</returns>
public List<KeyValuePair<K, V>> AsList() public List<KeyValuePair<TKey, TValue>> AsList()
{ {
List<KeyValuePair<K, V>> list = new List<KeyValuePair<K, V>>(); List<KeyValuePair<TKey, TValue>> list = new();
AddToList(Root, list); AddToList(Root, list);
@@ -184,7 +184,7 @@ namespace Ryujinx.Common.Collections
/// </summary> /// </summary>
/// <param name="node">The node to search for nodes within</param> /// <param name="node">The node to search for nodes within</param>
/// <param name="list">The list to add node to</param> /// <param name="list">The list to add node to</param>
private void AddToList(Node<K, V> node, List<KeyValuePair<K, V>> list) private void AddToList(Node<TKey, TValue> node, List<KeyValuePair<TKey, TValue>> list)
{ {
if (node == null) if (node == null)
{ {
@@ -193,7 +193,7 @@ namespace Ryujinx.Common.Collections
AddToList(node.Left, list); AddToList(node.Left, list);
list.Add(new KeyValuePair<K, V>(node.Key, node.Value)); list.Add(new KeyValuePair<TKey, TValue>(node.Key, node.Value));
AddToList(node.Right, list); AddToList(node.Right, list);
} }
@@ -204,11 +204,11 @@ namespace Ryujinx.Common.Collections
/// <param name="key">Key of the node to get</param> /// <param name="key">Key of the node to get</param>
/// <returns>Node reference in the tree</returns> /// <returns>Node reference in the tree</returns>
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception> /// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
private Node<K, V> GetNode(K key) private Node<TKey, TValue> GetNode(TKey key)
{ {
ArgumentNullException.ThrowIfNull(key); ArgumentNullException.ThrowIfNull(key);
Node<K, V> node = Root; Node<TKey, TValue> node = Root;
while (node != null) while (node != null)
{ {
int cmp = key.CompareTo(node.Key); int cmp = key.CompareTo(node.Key);
@@ -235,9 +235,9 @@ namespace Ryujinx.Common.Collections
/// </summary> /// </summary>
/// <param name="key">Key of the node to insert</param> /// <param name="key">Key of the node to insert</param>
/// <param name="value">Value of the node to insert</param> /// <param name="value">Value of the node to insert</param>
private void Insert(K key, V value) private void Insert(TKey key, TValue value)
{ {
Node<K, V> newNode = BSTInsert(key, value); Node<TKey, TValue> newNode = BSTInsert(key, value);
RestoreBalanceAfterInsertion(newNode); RestoreBalanceAfterInsertion(newNode);
} }
@@ -251,10 +251,10 @@ namespace Ryujinx.Common.Collections
/// <param name="key">Key of the node to insert</param> /// <param name="key">Key of the node to insert</param>
/// <param name="value">Value of the node to insert</param> /// <param name="value">Value of the node to insert</param>
/// <returns>The inserted Node</returns> /// <returns>The inserted Node</returns>
private Node<K, V> BSTInsert(K key, V value) private Node<TKey, TValue> BSTInsert(TKey key, TValue value)
{ {
Node<K, V> parent = null; Node<TKey, TValue> parent = null;
Node<K, V> node = Root; Node<TKey, TValue> node = Root;
while (node != null) while (node != null)
{ {
@@ -274,7 +274,7 @@ namespace Ryujinx.Common.Collections
return node; return node;
} }
} }
Node<K, V> newNode = new Node<K, V>(key, value, parent); Node<TKey, TValue> newNode = new(key, value, parent);
if (newNode.Parent == null) if (newNode.Parent == null)
{ {
Root = newNode; Root = newNode;
@@ -296,14 +296,17 @@ namespace Ryujinx.Common.Collections
/// </summary> /// </summary>
/// <param name="key">Key of the node to delete</param> /// <param name="key">Key of the node to delete</param>
/// <returns>The deleted Node</returns> /// <returns>The deleted Node</returns>
private Node<K, V> Delete(K key) private Node<TKey, TValue> Delete(TKey key)
{ {
// O(1) Retrieval // O(1) Retrieval
Node<K, V> nodeToDelete = GetNode(key); Node<TKey, TValue> nodeToDelete = GetNode(key);
if (nodeToDelete == null) return null; if (nodeToDelete == null)
{
return null;
}
Node<K, V> replacementNode; Node<TKey, TValue> replacementNode;
if (LeftOf(nodeToDelete) == null || RightOf(nodeToDelete) == null) if (LeftOf(nodeToDelete) == null || RightOf(nodeToDelete) == null)
{ {
@@ -314,7 +317,7 @@ namespace Ryujinx.Common.Collections
replacementNode = PredecessorOf(nodeToDelete); replacementNode = PredecessorOf(nodeToDelete);
} }
Node<K, V> tmp = LeftOf(replacementNode) ?? RightOf(replacementNode); Node<TKey, TValue> tmp = LeftOf(replacementNode) ?? RightOf(replacementNode);
if (tmp != null) if (tmp != null)
{ {
@@ -354,11 +357,11 @@ namespace Ryujinx.Common.Collections
/// <param name="key">Key for which to find the floor node of</param> /// <param name="key">Key for which to find the floor node of</param>
/// <returns>Node whose key is immediately less than or equal to <paramref name="key"/>, or null if no such node is found.</returns> /// <returns>Node whose key is immediately less than or equal to <paramref name="key"/>, or null if no such node is found.</returns>
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception> /// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
private Node<K, V> FloorNode(K key) private Node<TKey, TValue> FloorNode(TKey key)
{ {
ArgumentNullException.ThrowIfNull(key); ArgumentNullException.ThrowIfNull(key);
Node<K, V> tmp = Root; Node<TKey, TValue> tmp = Root;
while (tmp != null) while (tmp != null)
{ {
@@ -382,8 +385,8 @@ namespace Ryujinx.Common.Collections
} }
else else
{ {
Node<K, V> parent = tmp.Parent; Node<TKey, TValue> parent = tmp.Parent;
Node<K, V> ptr = tmp; Node<TKey, TValue> ptr = tmp;
while (parent != null && ptr == parent.Left) while (parent != null && ptr == parent.Left)
{ {
ptr = parent; ptr = parent;
@@ -406,11 +409,11 @@ namespace Ryujinx.Common.Collections
/// <param name="key">Key for which to find the ceiling node of</param> /// <param name="key">Key for which to find the ceiling node of</param>
/// <returns>Node whose key is immediately greater than or equal to <paramref name="key"/>, or null if no such node is found.</returns> /// <returns>Node whose key is immediately greater than or equal to <paramref name="key"/>, or null if no such node is found.</returns>
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception> /// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
private Node<K, V> CeilingNode(K key) private Node<TKey, TValue> CeilingNode(TKey key)
{ {
ArgumentNullException.ThrowIfNull(key); ArgumentNullException.ThrowIfNull(key);
Node<K, V> tmp = Root; Node<TKey, TValue> tmp = Root;
while (tmp != null) while (tmp != null)
{ {
@@ -434,8 +437,8 @@ namespace Ryujinx.Common.Collections
} }
else else
{ {
Node<K, V> parent = tmp.Parent; Node<TKey, TValue> parent = tmp.Parent;
Node<K, V> ptr = tmp; Node<TKey, TValue> ptr = tmp;
while (parent != null && ptr == parent.Right) while (parent != null && ptr == parent.Right)
{ {
ptr = parent; ptr = parent;
@@ -457,44 +460,44 @@ namespace Ryujinx.Common.Collections
#region Interface Implementations #region Interface Implementations
// Method descriptions are not provided as they are already included as part of the interface. // Method descriptions are not provided as they are already included as part of the interface.
public bool ContainsKey(K key) public bool ContainsKey(TKey key)
{ {
ArgumentNullException.ThrowIfNull(key); ArgumentNullException.ThrowIfNull(key);
return GetNode(key) != null; return GetNode(key) != null;
} }
bool IDictionary<K, V>.Remove(K key) bool IDictionary<TKey, TValue>.Remove(TKey key)
{ {
int count = Count; int count = Count;
Remove(key); Remove(key);
return count > Count; return count > Count;
} }
public bool TryGetValue(K key, [MaybeNullWhen(false)] out V value) public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
{ {
ArgumentNullException.ThrowIfNull(key); ArgumentNullException.ThrowIfNull(key);
Node<K, V> node = GetNode(key); Node<TKey, TValue> node = GetNode(key);
value = node != null ? node.Value : default; value = node != null ? node.Value : default;
return node != null; return node != null;
} }
public void Add(KeyValuePair<K, V> item) public void Add(KeyValuePair<TKey, TValue> item)
{ {
ArgumentNullException.ThrowIfNull(item.Key); ArgumentNullException.ThrowIfNull(item.Key);
Add(item.Key, item.Value); Add(item.Key, item.Value);
} }
public bool Contains(KeyValuePair<K, V> item) public bool Contains(KeyValuePair<TKey, TValue> item)
{ {
if (item.Key == null) if (item.Key == null)
{ {
return false; return false;
} }
Node<K, V> node = GetNode(item.Key); Node<TKey, TValue> node = GetNode(item.Key);
if (node != null) if (node != null)
{ {
return node.Key.Equals(item.Key) && node.Value.Equals(item.Value); return node.Key.Equals(item.Key) && node.Value.Equals(item.Value);
@@ -502,27 +505,27 @@ namespace Ryujinx.Common.Collections
return false; return false;
} }
public void CopyTo(KeyValuePair<K, V>[] array, int arrayIndex) public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{ {
if (arrayIndex < 0 || array.Length - arrayIndex < this.Count) if (arrayIndex < 0 || array.Length - arrayIndex < this.Count)
{ {
throw new ArgumentOutOfRangeException(nameof(arrayIndex)); throw new ArgumentOutOfRangeException(nameof(arrayIndex));
} }
SortedList<K, V> list = GetKeyValues(); SortedList<TKey, TValue> list = GetKeyValues();
int offset = 0; int offset = 0;
for (int i = arrayIndex; i < array.Length && offset < list.Count; i++) for (int i = arrayIndex; i < array.Length && offset < list.Count; i++)
{ {
array[i] = new KeyValuePair<K, V>(list.Keys[i], list.Values[i]); array[i] = new KeyValuePair<TKey, TValue>(list.Keys[i], list.Values[i]);
offset++; offset++;
} }
} }
public bool Remove(KeyValuePair<K, V> item) public bool Remove(KeyValuePair<TKey, TValue> item)
{ {
Node<K, V> node = GetNode(item.Key); Node<TKey, TValue> node = GetNode(item.Key);
if (node == null) if (node == null)
{ {
@@ -539,7 +542,7 @@ namespace Ryujinx.Common.Collections
return false; return false;
} }
public IEnumerator<KeyValuePair<K, V>> GetEnumerator() public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{ {
return GetKeyValues().GetEnumerator(); return GetKeyValues().GetEnumerator();
} }
@@ -549,13 +552,13 @@ namespace Ryujinx.Common.Collections
return GetKeyValues().GetEnumerator(); return GetKeyValues().GetEnumerator();
} }
public ICollection<K> Keys => GetKeyValues().Keys; public ICollection<TKey> Keys => GetKeyValues().Keys;
public ICollection<V> Values => GetKeyValues().Values; public ICollection<TValue> Values => GetKeyValues().Values;
public bool IsReadOnly => false; public bool IsReadOnly => false;
public V this[K key] public TValue this[TKey key]
{ {
get => Get(key); get => Get(key);
set => Add(key, value); set => Add(key, value);
@@ -569,16 +572,16 @@ namespace Ryujinx.Common.Collections
/// Returns a sorted list of all the node keys / values in the tree. /// Returns a sorted list of all the node keys / values in the tree.
/// </summary> /// </summary>
/// <returns>List of node keys</returns> /// <returns>List of node keys</returns>
private SortedList<K, V> GetKeyValues() private SortedList<TKey, TValue> GetKeyValues()
{ {
SortedList<K, V> set = new SortedList<K, V>(); SortedList<TKey, TValue> set = new();
Queue<Node<K, V>> queue = new Queue<Node<K, V>>(); Queue<Node<TKey, TValue>> queue = new();
if (Root != null) if (Root != null)
{ {
queue.Enqueue(Root); queue.Enqueue(Root);
} }
while (queue.TryDequeue(out Node<K, V> node)) while (queue.TryDequeue(out Node<TKey, TValue> node))
{ {
set.Add(node.Key, node.Value); set.Add(node.Key, node.Value);
if (null != node.Left) if (null != node.Left)
@@ -600,14 +603,14 @@ namespace Ryujinx.Common.Collections
/// <summary> /// <summary>
/// Represents a node in the TreeDictionary which contains a key and value of generic type K and V, respectively. /// Represents a node in the TreeDictionary which contains a key and value of generic type K and V, respectively.
/// </summary> /// </summary>
/// <typeparam name="K">Key of the node</typeparam> /// <typeparam name="TKey">Key of the node</typeparam>
/// <typeparam name="V">Value of the node</typeparam> /// <typeparam name="TValue">Value of the node</typeparam>
public class Node<K, V> : IntrusiveRedBlackTreeNode<Node<K, V>> where K : IComparable<K> public class Node<TKey, TValue> : IntrusiveRedBlackTreeNode<Node<TKey, TValue>> where TKey : IComparable<TKey>
{ {
internal K Key; internal TKey Key;
internal V Value; internal TValue Value;
internal Node(K key, V value, Node<K, V> parent) internal Node(TKey key, TValue value, Node<TKey, TValue> parent)
{ {
Key = key; Key = key;
Value = value; Value = value;

View File

@@ -11,6 +11,6 @@ namespace Ryujinx.Common.Configuration
SmaaLow, SmaaLow,
SmaaMedium, SmaaMedium,
SmaaHigh, SmaaHigh,
SmaaUltra SmaaUltra,
} }
} }

View File

@@ -18,7 +18,7 @@ namespace Ryujinx.Common.Configuration
{ {
UserProfile, UserProfile,
Portable, Portable,
Custom Custom,
} }
public static LaunchMode Mode { get; private set; } public static LaunchMode Mode { get; private set; }
@@ -34,7 +34,7 @@ namespace Ryujinx.Common.Configuration
private const string DefaultModsDir = "mods"; private const string DefaultModsDir = "mods";
public static string CustomModsPath { get; set; } public static string CustomModsPath { get; set; }
public static string CustomSdModsPath {get; set; } public static string CustomSdModsPath { get; set; }
public static string CustomNandPath { get; set; } // TODO: Actually implement this into VFS public static string CustomNandPath { get; set; } // TODO: Actually implement this into VFS
public static string CustomSdCardPath { get; set; } // TODO: Actually implement this into VFS public static string CustomSdCardPath { get; set; } // TODO: Actually implement this into VFS

View File

@@ -11,7 +11,7 @@ namespace Ryujinx.Common.Configuration
Fixed16x10, Fixed16x10,
Fixed21x9, Fixed21x9,
Fixed32x9, Fixed32x9,
Stretched Stretched,
} }
public static class AspectRatioExtensions public static class AspectRatioExtensions
@@ -25,12 +25,14 @@ namespace Ryujinx.Common.Configuration
{ {
return aspectRatio switch return aspectRatio switch
{ {
#pragma warning disable IDE0055 // Disable formatting
AspectRatio.Fixed4x3 => 4.0f, AspectRatio.Fixed4x3 => 4.0f,
AspectRatio.Fixed16x9 => 16.0f, AspectRatio.Fixed16x9 => 16.0f,
AspectRatio.Fixed16x10 => 16.0f, AspectRatio.Fixed16x10 => 16.0f,
AspectRatio.Fixed21x9 => 21.0f, AspectRatio.Fixed21x9 => 21.0f,
AspectRatio.Fixed32x9 => 32.0f, AspectRatio.Fixed32x9 => 32.0f,
_ => 16.0f _ => 16.0f,
#pragma warning restore IDE0055
}; };
} }
@@ -38,12 +40,14 @@ namespace Ryujinx.Common.Configuration
{ {
return aspectRatio switch return aspectRatio switch
{ {
#pragma warning disable IDE0055 // Disable formatting
AspectRatio.Fixed4x3 => 3.0f, AspectRatio.Fixed4x3 => 3.0f,
AspectRatio.Fixed16x9 => 9.0f, AspectRatio.Fixed16x9 => 9.0f,
AspectRatio.Fixed16x10 => 10.0f, AspectRatio.Fixed16x10 => 10.0f,
AspectRatio.Fixed21x9 => 9.0f, AspectRatio.Fixed21x9 => 9.0f,
AspectRatio.Fixed32x9 => 9.0f, AspectRatio.Fixed32x9 => 9.0f,
_ => 9.0f _ => 9.0f,
#pragma warning restore IDE0055
}; };
} }
@@ -51,12 +55,14 @@ namespace Ryujinx.Common.Configuration
{ {
return aspectRatio switch return aspectRatio switch
{ {
#pragma warning disable IDE0055 // Disable formatting
AspectRatio.Fixed4x3 => "4:3", AspectRatio.Fixed4x3 => "4:3",
AspectRatio.Fixed16x9 => "16:9", AspectRatio.Fixed16x9 => "16:9",
AspectRatio.Fixed16x10 => "16:10", AspectRatio.Fixed16x10 => "16:10",
AspectRatio.Fixed21x9 => "21:9", AspectRatio.Fixed21x9 => "21:9",
AspectRatio.Fixed32x9 => "32:9", AspectRatio.Fixed32x9 => "32:9",
_ => "Stretched" _ => "Stretched",
#pragma warning restore IDE0055
}; };
} }
} }

View File

@@ -53,6 +53,6 @@ namespace Ryujinx.Common.Configuration.Hid.Controller
SingleLeftTrigger1, SingleLeftTrigger1,
SingleRightTrigger1, SingleRightTrigger1,
Count Count,
} }
} }

View File

@@ -4,7 +4,7 @@ using System.Text.Json.Serialization;
namespace Ryujinx.Common.Configuration.Hid.Controller namespace Ryujinx.Common.Configuration.Hid.Controller
{ {
public class GenericControllerInputConfig<Button, Stick> : GenericInputConfigurationCommon<Button> where Button : unmanaged where Stick : unmanaged public class GenericControllerInputConfig<TButton, TStick> : GenericInputConfigurationCommon<TButton> where TButton : unmanaged where TStick : unmanaged
{ {
[JsonIgnore] [JsonIgnore]
private float _deadzoneLeft; private float _deadzoneLeft;
@@ -16,12 +16,12 @@ namespace Ryujinx.Common.Configuration.Hid.Controller
/// <summary> /// <summary>
/// Left JoyCon Controller Stick Bindings /// Left JoyCon Controller Stick Bindings
/// </summary> /// </summary>
public JoyconConfigControllerStick<Button, Stick> LeftJoyconStick { get; set; } public JoyconConfigControllerStick<TButton, TStick> LeftJoyconStick { get; set; }
/// <summary> /// <summary>
/// Right JoyCon Controller Stick Bindings /// Right JoyCon Controller Stick Bindings
/// </summary> /// </summary>
public JoyconConfigControllerStick<Button, Stick> RightJoyconStick { get; set; } public JoyconConfigControllerStick<TButton, TStick> RightJoyconStick { get; set; }
/// <summary> /// <summary>
/// Controller Left Analog Stick Deadzone /// Controller Left Analog Stick Deadzone

View File

@@ -1,11 +1,11 @@
namespace Ryujinx.Common.Configuration.Hid.Controller namespace Ryujinx.Common.Configuration.Hid.Controller
{ {
public class JoyconConfigControllerStick<Button, Stick> where Button: unmanaged where Stick: unmanaged public class JoyconConfigControllerStick<TButton, TStick> where TButton : unmanaged where TStick : unmanaged
{ {
public Stick Joystick { get; set; } public TStick Joystick { get; set; }
public bool InvertStickX { get; set; } public bool InvertStickX { get; set; }
public bool InvertStickY { get; set; } public bool InvertStickY { get; set; }
public bool Rotate90CW { get; set; } public bool Rotate90CW { get; set; }
public Button StickButton { get; set; } public TButton StickButton { get; set; }
} }
} }

View File

@@ -7,7 +7,7 @@ namespace Ryujinx.Common.Configuration.Hid.Controller.Motion
{ {
class JsonMotionConfigControllerConverter : JsonConverter<MotionConfigController> class JsonMotionConfigControllerConverter : JsonConverter<MotionConfigController>
{ {
private static readonly MotionConfigJsonSerializerContext SerializerContext = new(JsonHelper.GetDefaultSerializerOptions()); private static readonly MotionConfigJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
private static MotionInputBackendType GetMotionInputBackendType(ref Utf8JsonReader reader) private static MotionInputBackendType GetMotionInputBackendType(ref Utf8JsonReader reader)
{ {
@@ -55,8 +55,8 @@ namespace Ryujinx.Common.Configuration.Hid.Controller.Motion
return motionBackendType switch return motionBackendType switch
{ {
MotionInputBackendType.GamepadDriver => JsonSerializer.Deserialize(ref reader, SerializerContext.StandardMotionConfigController), MotionInputBackendType.GamepadDriver => JsonSerializer.Deserialize(ref reader, _serializerContext.StandardMotionConfigController),
MotionInputBackendType.CemuHook => JsonSerializer.Deserialize(ref reader, SerializerContext.CemuHookMotionConfigController), MotionInputBackendType.CemuHook => JsonSerializer.Deserialize(ref reader, _serializerContext.CemuHookMotionConfigController),
_ => throw new InvalidOperationException($"Unknown backend type {motionBackendType}"), _ => throw new InvalidOperationException($"Unknown backend type {motionBackendType}"),
}; };
} }
@@ -66,10 +66,10 @@ namespace Ryujinx.Common.Configuration.Hid.Controller.Motion
switch (value.MotionBackend) switch (value.MotionBackend)
{ {
case MotionInputBackendType.GamepadDriver: case MotionInputBackendType.GamepadDriver:
JsonSerializer.Serialize(writer, value as StandardMotionConfigController, SerializerContext.StandardMotionConfigController); JsonSerializer.Serialize(writer, value as StandardMotionConfigController, _serializerContext.StandardMotionConfigController);
break; break;
case MotionInputBackendType.CemuHook: case MotionInputBackendType.CemuHook:
JsonSerializer.Serialize(writer, value as CemuHookMotionConfigController, SerializerContext.CemuHookMotionConfigController); JsonSerializer.Serialize(writer, value as CemuHookMotionConfigController, _serializerContext.CemuHookMotionConfigController);
break; break;
default: default:
throw new ArgumentException($"Unknown motion backend type {value.MotionBackend}"); throw new ArgumentException($"Unknown motion backend type {value.MotionBackend}");

View File

@@ -10,6 +10,6 @@ namespace Ryujinx.Common.Configuration.Hid.Controller
Left, Left,
Right, Right,
Count Count,
} }
} }

View File

@@ -18,6 +18,6 @@ namespace Ryujinx.Common.Configuration.Hid
Invalid = 1 << 5, Invalid = 1 << 5,
Pokeball = 1 << 6, Pokeball = 1 << 6,
SystemExternal = 1 << 29, SystemExternal = 1 << 29,
System = 1 << 30 System = 1 << 30,
} }
} }

View File

@@ -1,15 +1,15 @@
namespace Ryujinx.Common.Configuration.Hid namespace Ryujinx.Common.Configuration.Hid
{ {
public class GenericInputConfigurationCommon<Button> : InputConfig where Button : unmanaged public class GenericInputConfigurationCommon<TButton> : InputConfig where TButton : unmanaged
{ {
/// <summary> /// <summary>
/// Left JoyCon Controller Bindings /// Left JoyCon Controller Bindings
/// </summary> /// </summary>
public LeftJoyconCommonConfig<Button> LeftJoycon { get; set; } public LeftJoyconCommonConfig<TButton> LeftJoycon { get; set; }
/// <summary> /// <summary>
/// Right JoyCon Controller Bindings /// Right JoyCon Controller Bindings
/// </summary> /// </summary>
public RightJoyconCommonConfig<Button> RightJoycon { get; set; } public RightJoyconCommonConfig<TButton> RightJoycon { get; set; }
} }
} }

View File

@@ -9,7 +9,7 @@ namespace Ryujinx.Common.Configuration.Hid
{ {
public class JsonInputConfigConverter : JsonConverter<InputConfig> public class JsonInputConfigConverter : JsonConverter<InputConfig>
{ {
private static readonly InputConfigJsonSerializerContext SerializerContext = new(JsonHelper.GetDefaultSerializerOptions()); private static readonly InputConfigJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
private static InputBackendType GetInputBackendType(ref Utf8JsonReader reader) private static InputBackendType GetInputBackendType(ref Utf8JsonReader reader)
{ {
@@ -57,8 +57,8 @@ namespace Ryujinx.Common.Configuration.Hid
return backendType switch return backendType switch
{ {
InputBackendType.WindowKeyboard => JsonSerializer.Deserialize(ref reader, SerializerContext.StandardKeyboardInputConfig), InputBackendType.WindowKeyboard => JsonSerializer.Deserialize(ref reader, _serializerContext.StandardKeyboardInputConfig),
InputBackendType.GamepadSDL2 => JsonSerializer.Deserialize(ref reader, SerializerContext.StandardControllerInputConfig), InputBackendType.GamepadSDL2 => JsonSerializer.Deserialize(ref reader, _serializerContext.StandardControllerInputConfig),
_ => throw new InvalidOperationException($"Unknown backend type {backendType}"), _ => throw new InvalidOperationException($"Unknown backend type {backendType}"),
}; };
} }
@@ -68,10 +68,10 @@ namespace Ryujinx.Common.Configuration.Hid
switch (value.Backend) switch (value.Backend)
{ {
case InputBackendType.WindowKeyboard: case InputBackendType.WindowKeyboard:
JsonSerializer.Serialize(writer, value as StandardKeyboardInputConfig, SerializerContext.StandardKeyboardInputConfig); JsonSerializer.Serialize(writer, value as StandardKeyboardInputConfig, _serializerContext.StandardKeyboardInputConfig);
break; break;
case InputBackendType.GamepadSDL2: case InputBackendType.GamepadSDL2:
JsonSerializer.Serialize(writer, value as StandardControllerInputConfig, SerializerContext.StandardControllerInputConfig); JsonSerializer.Serialize(writer, value as StandardControllerInputConfig, _serializerContext.StandardControllerInputConfig);
break; break;
default: default:
throw new ArgumentException($"Unknown backend type {value.Backend}"); throw new ArgumentException($"Unknown backend type {value.Backend}");

View File

@@ -138,6 +138,6 @@ namespace Ryujinx.Common.Configuration.Hid
BackSlash, BackSlash,
Unbound, Unbound,
Count Count,
} }
} }

View File

@@ -1,15 +1,15 @@
namespace Ryujinx.Common.Configuration.Hid.Keyboard namespace Ryujinx.Common.Configuration.Hid.Keyboard
{ {
public class GenericKeyboardInputConfig<Key> : GenericInputConfigurationCommon<Key> where Key : unmanaged public class GenericKeyboardInputConfig<TKey> : GenericInputConfigurationCommon<TKey> where TKey : unmanaged
{ {
/// <summary> /// <summary>
/// Left JoyCon Controller Stick Bindings /// Left JoyCon Controller Stick Bindings
/// </summary> /// </summary>
public JoyconConfigKeyboardStick<Key> LeftJoyconStick { get; set; } public JoyconConfigKeyboardStick<TKey> LeftJoyconStick { get; set; }
/// <summary> /// <summary>
/// Right JoyCon Controller Stick Bindings /// Right JoyCon Controller Stick Bindings
/// </summary> /// </summary>
public JoyconConfigKeyboardStick<Key> RightJoyconStick { get; set; } public JoyconConfigKeyboardStick<TKey> RightJoyconStick { get; set; }
} }
} }

View File

@@ -1,11 +1,11 @@
namespace Ryujinx.Common.Configuration.Hid.Keyboard namespace Ryujinx.Common.Configuration.Hid.Keyboard
{ {
public class JoyconConfigKeyboardStick<Key> where Key: unmanaged public class JoyconConfigKeyboardStick<TKey> where TKey : unmanaged
{ {
public Key StickUp { get; set; } public TKey StickUp { get; set; }
public Key StickDown { get; set; } public TKey StickDown { get; set; }
public Key StickLeft { get; set; } public TKey StickLeft { get; set; }
public Key StickRight { get; set; } public TKey StickRight { get; set; }
public Key StickButton { get; set; } public TKey StickButton { get; set; }
} }
} }

View File

@@ -1,15 +1,15 @@
namespace Ryujinx.Common.Configuration.Hid namespace Ryujinx.Common.Configuration.Hid
{ {
public class LeftJoyconCommonConfig<Button> public class LeftJoyconCommonConfig<TButton>
{ {
public Button ButtonMinus { get; set; } public TButton ButtonMinus { get; set; }
public Button ButtonL { get; set; } public TButton ButtonL { get; set; }
public Button ButtonZl { get; set; } public TButton ButtonZl { get; set; }
public Button ButtonSl { get; set; } public TButton ButtonSl { get; set; }
public Button ButtonSr { get; set; } public TButton ButtonSr { get; set; }
public Button DpadUp { get; set; } public TButton DpadUp { get; set; }
public Button DpadDown { get; set; } public TButton DpadDown { get; set; }
public Button DpadLeft { get; set; } public TButton DpadLeft { get; set; }
public Button DpadRight { get; set; } public TButton DpadRight { get; set; }
} }
} }

View File

@@ -17,6 +17,6 @@ namespace Ryujinx.Common.Configuration.Hid
Player8 = 7, Player8 = 7,
Handheld = 8, Handheld = 8,
Unknown = 9, Unknown = 9,
Auto = 10 // Shouldn't be used directly Auto = 10, // Shouldn't be used directly
} }
} }

View File

@@ -1,15 +1,15 @@
namespace Ryujinx.Common.Configuration.Hid namespace Ryujinx.Common.Configuration.Hid
{ {
public class RightJoyconCommonConfig<Button> public class RightJoyconCommonConfig<TButton>
{ {
public Button ButtonPlus { get; set; } public TButton ButtonPlus { get; set; }
public Button ButtonR { get; set; } public TButton ButtonR { get; set; }
public Button ButtonZr { get; set; } public TButton ButtonZr { get; set; }
public Button ButtonSl { get; set; } public TButton ButtonSl { get; set; }
public Button ButtonSr { get; set; } public TButton ButtonSr { get; set; }
public Button ButtonX { get; set; } public TButton ButtonX { get; set; }
public Button ButtonB { get; set; } public TButton ButtonB { get; set; }
public Button ButtonY { get; set; } public TButton ButtonY { get; set; }
public Button ButtonA { get; set; } public TButton ButtonA { get; set; }
} }
} }

View File

@@ -4,6 +4,6 @@ namespace Ryujinx.Common.Configuration
{ {
Never, Never,
OnIdle, OnIdle,
Always Always,
} }
} }

View File

@@ -8,6 +8,6 @@ namespace Ryujinx.Common.Configuration
{ {
Bilinear, Bilinear,
Nearest, Nearest,
Fsr Fsr,
} }
} }

View File

@@ -1,5 +1,4 @@
using System; using System.IO;
using System.IO;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@@ -7,8 +6,7 @@ namespace Ryujinx.Common
{ {
public static class BinaryReaderExtensions public static class BinaryReaderExtensions
{ {
public unsafe static T ReadStruct<T>(this BinaryReader reader) public static T ReadStruct<T>(this BinaryReader reader) where T : unmanaged
where T : unmanaged
{ {
return MemoryMarshal.Cast<byte, T>(reader.ReadBytes(Unsafe.SizeOf<T>()))[0]; return MemoryMarshal.Cast<byte, T>(reader.ReadBytes(Unsafe.SizeOf<T>()))[0];
} }

View File

@@ -6,8 +6,7 @@ namespace Ryujinx.Common
{ {
public static class BinaryWriterExtensions public static class BinaryWriterExtensions
{ {
public unsafe static void WriteStruct<T>(this BinaryWriter writer, T value) public static void WriteStruct<T>(this BinaryWriter writer, T value) where T : unmanaged
where T : unmanaged
{ {
ReadOnlySpan<byte> data = MemoryMarshal.Cast<T, byte>(MemoryMarshal.CreateReadOnlySpan(ref value, 1)); ReadOnlySpan<byte> data = MemoryMarshal.Cast<T, byte>(MemoryMarshal.CreateReadOnlySpan(ref value, 1));

View File

@@ -13,7 +13,7 @@ namespace Ryujinx.Common.GraphicsDriver.NVAPI
Set(text); Set(text);
} }
public string Get() public readonly string Get()
{ {
fixed (byte* data = _data) fixed (byte* data = _data)
{ {
@@ -29,7 +29,7 @@ namespace Ryujinx.Common.GraphicsDriver.NVAPI
} }
} }
public void Set(string text) public readonly void Set(string text)
{ {
text += '\0'; text += '\0';
fixed (char* textPtr = text) fixed (char* textPtr = text)

View File

@@ -3,7 +3,7 @@
namespace Ryujinx.Common.GraphicsDriver.NVAPI namespace Ryujinx.Common.GraphicsDriver.NVAPI
{ {
[StructLayout(LayoutKind.Sequential, Pack = 4)] [StructLayout(LayoutKind.Sequential, Pack = 4)]
unsafe struct NvdrsApplicationV4 struct NvdrsApplicationV4
{ {
public uint Version; public uint Version;
public uint IsPredefined; public uint IsPredefined;

View File

@@ -3,7 +3,7 @@
namespace Ryujinx.Common.GraphicsDriver.NVAPI namespace Ryujinx.Common.GraphicsDriver.NVAPI
{ {
[StructLayout(LayoutKind.Sequential, Pack = 1)] [StructLayout(LayoutKind.Sequential, Pack = 1)]
unsafe struct NvdrsProfile struct NvdrsProfile
{ {
public uint Version; public uint Version;
public NvapiUnicodeString ProfileName; public NvapiUnicodeString ProfileName;

View File

@@ -19,7 +19,7 @@ namespace Ryujinx.Common.GraphicsDriver.NVAPI
} }
[StructLayout(LayoutKind.Explicit, Size = 0x3020)] [StructLayout(LayoutKind.Explicit, Size = 0x3020)]
unsafe struct NvdrsSetting struct NvdrsSetting
{ {
[FieldOffset(0x0)] [FieldOffset(0x0)]
public uint Version; public uint Version;

View File

@@ -97,27 +97,26 @@ namespace Ryujinx.Common.GraphicsDriver
Check(NvAPI_DRS_LoadSettings(handle)); Check(NvAPI_DRS_LoadSettings(handle));
IntPtr profileHandle;
// Check if the profile already exists. // Check if the profile already exists.
int status = NvAPI_DRS_FindProfileByName(handle, new NvapiUnicodeString(ProfileName), out profileHandle); int status = NvAPI_DRS_FindProfileByName(handle, new NvapiUnicodeString(ProfileName), out nint profileHandle);
if (status != 0) if (status != 0)
{ {
NvdrsProfile profile = new NvdrsProfile { NvdrsProfile profile = new()
{
Version = MakeVersion<NvdrsProfile>(1), Version = MakeVersion<NvdrsProfile>(1),
IsPredefined = 0, IsPredefined = 0,
GpuSupport = uint.MaxValue GpuSupport = uint.MaxValue,
}; };
profile.ProfileName.Set(ProfileName); profile.ProfileName.Set(ProfileName);
Check(NvAPI_DRS_CreateProfile(handle, ref profile, out profileHandle)); Check(NvAPI_DRS_CreateProfile(handle, ref profile, out profileHandle));
NvdrsApplicationV4 application = new NvdrsApplicationV4 NvdrsApplicationV4 application = new()
{ {
Version = MakeVersion<NvdrsApplicationV4>(4), Version = MakeVersion<NvdrsApplicationV4>(4),
IsPredefined = 0, IsPredefined = 0,
Flags = 3 // IsMetro, IsCommandLine Flags = 3, // IsMetro, IsCommandLine
}; };
application.AppName.Set("Ryujinx.exe"); application.AppName.Set("Ryujinx.exe");
application.UserFriendlyName.Set("Ryujinx"); application.UserFriendlyName.Set("Ryujinx");
@@ -127,7 +126,7 @@ namespace Ryujinx.Common.GraphicsDriver
Check(NvAPI_DRS_CreateApplication(handle, profileHandle, ref application)); Check(NvAPI_DRS_CreateApplication(handle, profileHandle, ref application));
} }
NvdrsSetting setting = new NvdrsSetting NvdrsSetting setting = new()
{ {
Version = MakeVersion<NvdrsSetting>(1), Version = MakeVersion<NvdrsSetting>(1),
SettingId = Nvapi.OglThreadControlId, SettingId = Nvapi.OglThreadControlId,
@@ -136,7 +135,7 @@ namespace Ryujinx.Common.GraphicsDriver
IsCurrentPredefined = 0, IsCurrentPredefined = 0,
IsPredefinedValid = 0, IsPredefinedValid = 0,
CurrentValue = targetValue, CurrentValue = targetValue,
PredefinedValue = targetValue PredefinedValue = targetValue,
}; };
Check(NvAPI_DRS_SetSetting(handle, profileHandle, ref setting)); Check(NvAPI_DRS_SetSetting(handle, profileHandle, ref setting));
@@ -154,10 +153,8 @@ namespace Ryujinx.Common.GraphicsDriver
{ {
return Marshal.GetDelegateForFunctionPointer<T>(ptr); return Marshal.GetDelegateForFunctionPointer<T>(ptr);
} }
else
{
return null; return null;
} }
} }
}
} }

View File

@@ -15,7 +15,7 @@ namespace Ryujinx.Common
High = high; High = high;
} }
public override string ToString() public readonly override string ToString()
{ {
return $"{High:x16}{Low:x16}"; return $"{High:x16}{Low:x16}";
} }
@@ -30,17 +30,17 @@ namespace Ryujinx.Common
return !x.Equals(y); return !x.Equals(y);
} }
public override bool Equals(object obj) public readonly override bool Equals(object obj)
{ {
return obj is Hash128 hash128 && Equals(hash128); return obj is Hash128 hash128 && Equals(hash128);
} }
public bool Equals(Hash128 cmpObj) public readonly bool Equals(Hash128 cmpObj)
{ {
return Low == cmpObj.Low && High == cmpObj.High; return Low == cmpObj.Low && High == cmpObj.High;
} }
public override int GetHashCode() public readonly override int GetHashCode()
{ {
return HashCode.Combine(Low, High); return HashCode.Combine(Low, High);
} }

View File

@@ -5,11 +5,11 @@ namespace Ryujinx.Common.Logging.Formatters
{ {
internal class DefaultLogFormatter : ILogFormatter internal class DefaultLogFormatter : ILogFormatter
{ {
private static readonly ObjectPool<StringBuilder> StringBuilderPool = SharedPools.Default<StringBuilder>(); private static readonly ObjectPool<StringBuilder> _stringBuilderPool = SharedPools.Default<StringBuilder>();
public string Format(LogEventArgs args) public string Format(LogEventArgs args)
{ {
StringBuilder sb = StringBuilderPool.Allocate(); StringBuilder sb = _stringBuilderPool.Allocate();
try try
{ {
@@ -44,7 +44,7 @@ namespace Ryujinx.Common.Logging.Formatters
} }
finally finally
{ {
StringBuilderPool.Release(sb); _stringBuilderPool.Release(sb);
} }
} }
} }

View File

@@ -7,7 +7,7 @@ namespace Ryujinx.Common.Logging.Formatters
{ {
internal static class DynamicObjectFormatter internal static class DynamicObjectFormatter
{ {
private static readonly ObjectPool<StringBuilder> StringBuilderPool = SharedPools.Default<StringBuilder>(); private static readonly ObjectPool<StringBuilder> _stringBuilderPool = SharedPools.Default<StringBuilder>();
public static string? Format(object? dynamicObject) public static string? Format(object? dynamicObject)
{ {
@@ -16,7 +16,7 @@ namespace Ryujinx.Common.Logging.Formatters
return null; return null;
} }
StringBuilder sb = StringBuilderPool.Allocate(); StringBuilder sb = _stringBuilderPool.Allocate();
try try
{ {
@@ -26,7 +26,7 @@ namespace Ryujinx.Common.Logging.Formatters
} }
finally finally
{ {
StringBuilderPool.Release(sb); _stringBuilderPool.Release(sb);
} }
} }
@@ -48,7 +48,7 @@ namespace Ryujinx.Common.Logging.Formatters
if (typeof(Array).IsAssignableFrom(prop.PropertyType)) if (typeof(Array).IsAssignableFrom(prop.PropertyType))
{ {
Array? array = (Array?) prop.GetValue(dynamicObject); Array? array = (Array?)prop.GetValue(dynamicObject);
if (array is not null) if (array is not null)
{ {

View File

@@ -71,6 +71,6 @@ namespace Ryujinx.Common.Logging
SurfaceFlinger, SurfaceFlinger,
TamperMachine, TamperMachine,
Ui, Ui,
Vic Vic,
} }
} }

View File

@@ -10,11 +10,11 @@ namespace Ryujinx.Common.Logging
{ {
public static class Logger public static class Logger
{ {
private static readonly Stopwatch m_Time; private static readonly Stopwatch _time;
private static readonly bool[] m_EnabledClasses; private static readonly bool[] _enabledClasses;
private static readonly List<ILogTarget> m_LogTargets; private static readonly List<ILogTarget> _logTargets;
private static readonly StdErrAdapter _stdErrAdapter; private static readonly StdErrAdapter _stdErrAdapter;
@@ -32,27 +32,27 @@ namespace Ryujinx.Common.Logging
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PrintMsg(LogClass logClass, string message) public void PrintMsg(LogClass logClass, string message)
{ {
if (m_EnabledClasses[(int)logClass]) if (_enabledClasses[(int)logClass])
{ {
Updated?.Invoke(null, new LogEventArgs(Level, m_Time.Elapsed, Thread.CurrentThread.Name, FormatMessage(logClass, "", message))); Updated?.Invoke(null, new LogEventArgs(Level, _time.Elapsed, Thread.CurrentThread.Name, FormatMessage(logClass, "", message)));
} }
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Print(LogClass logClass, string message, [CallerMemberName] string caller = "") public void Print(LogClass logClass, string message, [CallerMemberName] string caller = "")
{ {
if (m_EnabledClasses[(int)logClass]) if (_enabledClasses[(int)logClass])
{ {
Updated?.Invoke(null, new LogEventArgs(Level, m_Time.Elapsed, Thread.CurrentThread.Name, FormatMessage(logClass, caller, message))); Updated?.Invoke(null, new LogEventArgs(Level, _time.Elapsed, Thread.CurrentThread.Name, FormatMessage(logClass, caller, message)));
} }
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Print(LogClass logClass, string message, object data, [CallerMemberName] string caller = "") public void Print(LogClass logClass, string message, object data, [CallerMemberName] string caller = "")
{ {
if (m_EnabledClasses[(int)logClass]) if (_enabledClasses[(int)logClass])
{ {
Updated?.Invoke(null, new LogEventArgs(Level, m_Time.Elapsed, Thread.CurrentThread.Name, FormatMessage(logClass, caller, message), data)); Updated?.Invoke(null, new LogEventArgs(Level, _time.Elapsed, Thread.CurrentThread.Name, FormatMessage(logClass, caller, message), data));
} }
} }
@@ -60,47 +60,47 @@ namespace Ryujinx.Common.Logging
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PrintStack(LogClass logClass, string message, [CallerMemberName] string caller = "") public void PrintStack(LogClass logClass, string message, [CallerMemberName] string caller = "")
{ {
if (m_EnabledClasses[(int)logClass]) if (_enabledClasses[(int)logClass])
{ {
Updated?.Invoke(null, new LogEventArgs(Level, m_Time.Elapsed, Thread.CurrentThread.Name, FormatMessage(logClass, caller, message), new StackTrace(true))); Updated?.Invoke(null, new LogEventArgs(Level, _time.Elapsed, Thread.CurrentThread.Name, FormatMessage(logClass, caller, message), new StackTrace(true)));
} }
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PrintStub(LogClass logClass, string message = "", [CallerMemberName] string caller = "") public void PrintStub(LogClass logClass, string message = "", [CallerMemberName] string caller = "")
{ {
if (m_EnabledClasses[(int)logClass]) if (_enabledClasses[(int)logClass])
{ {
Updated?.Invoke(null, new LogEventArgs(Level, m_Time.Elapsed, Thread.CurrentThread.Name, FormatMessage(logClass, caller, "Stubbed. " + message))); Updated?.Invoke(null, new LogEventArgs(Level, _time.Elapsed, Thread.CurrentThread.Name, FormatMessage(logClass, caller, "Stubbed. " + message)));
} }
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PrintStub(LogClass logClass, object data, [CallerMemberName] string caller = "") public void PrintStub(LogClass logClass, object data, [CallerMemberName] string caller = "")
{ {
if (m_EnabledClasses[(int)logClass]) if (_enabledClasses[(int)logClass])
{ {
Updated?.Invoke(null, new LogEventArgs(Level, m_Time.Elapsed, Thread.CurrentThread.Name, FormatMessage(logClass, caller, "Stubbed."), data)); Updated?.Invoke(null, new LogEventArgs(Level, _time.Elapsed, Thread.CurrentThread.Name, FormatMessage(logClass, caller, "Stubbed."), data));
} }
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PrintStub(LogClass logClass, string message, object data, [CallerMemberName] string caller = "") public void PrintStub(LogClass logClass, string message, object data, [CallerMemberName] string caller = "")
{ {
if (m_EnabledClasses[(int)logClass]) if (_enabledClasses[(int)logClass])
{ {
Updated?.Invoke(null, new LogEventArgs(Level, m_Time.Elapsed, Thread.CurrentThread.Name, FormatMessage(logClass, caller, "Stubbed. " + message), data)); Updated?.Invoke(null, new LogEventArgs(Level, _time.Elapsed, Thread.CurrentThread.Name, FormatMessage(logClass, caller, "Stubbed. " + message), data));
} }
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PrintRawMsg(string message) public void PrintRawMsg(string message)
{ {
Updated?.Invoke(null, new LogEventArgs(Level, m_Time.Elapsed, Thread.CurrentThread.Name, message)); Updated?.Invoke(null, new LogEventArgs(Level, _time.Elapsed, Thread.CurrentThread.Name, message));
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private static string FormatMessage(LogClass Class, string Caller, string Message) => $"{Class} {Caller}: {Message}"; private static string FormatMessage(LogClass logClass, string caller, string message) => $"{logClass} {caller}: {message}";
} }
public static Log? Debug { get; private set; } public static Log? Debug { get; private set; }
@@ -115,16 +115,16 @@ namespace Ryujinx.Common.Logging
static Logger() static Logger()
{ {
m_EnabledClasses = new bool[Enum.GetNames<LogClass>().Length]; _enabledClasses = new bool[Enum.GetNames<LogClass>().Length];
for (int index = 0; index < m_EnabledClasses.Length; index++) for (int index = 0; index < _enabledClasses.Length; index++)
{ {
m_EnabledClasses[index] = true; _enabledClasses[index] = true;
} }
m_LogTargets = new List<ILogTarget>(); _logTargets = new List<ILogTarget>();
m_Time = Stopwatch.StartNew(); _time = Stopwatch.StartNew();
// Logger should log to console by default // Logger should log to console by default
AddTarget(new AsyncLogTargetWrapper( AddTarget(new AsyncLogTargetWrapper(
@@ -145,12 +145,12 @@ namespace Ryujinx.Common.Logging
public static void RestartTime() public static void RestartTime()
{ {
m_Time.Restart(); _time.Restart();
} }
private static ILogTarget GetTarget(string targetName) private static ILogTarget GetTarget(string targetName)
{ {
foreach (var target in m_LogTargets) foreach (var target in _logTargets)
{ {
if (target.Name.Equals(targetName)) if (target.Name.Equals(targetName))
{ {
@@ -163,7 +163,7 @@ namespace Ryujinx.Common.Logging
public static void AddTarget(ILogTarget target) public static void AddTarget(ILogTarget target)
{ {
m_LogTargets.Add(target); _logTargets.Add(target);
Updated += target.Log; Updated += target.Log;
} }
@@ -176,7 +176,7 @@ namespace Ryujinx.Common.Logging
{ {
Updated -= logTarget.Log; Updated -= logTarget.Log;
m_LogTargets.Remove(logTarget); _logTargets.Remove(logTarget);
logTarget.Dispose(); logTarget.Dispose();
} }
@@ -188,18 +188,18 @@ namespace Ryujinx.Common.Logging
_stdErrAdapter.Dispose(); _stdErrAdapter.Dispose();
foreach (var target in m_LogTargets) foreach (var target in _logTargets)
{ {
target.Dispose(); target.Dispose();
} }
m_LogTargets.Clear(); _logTargets.Clear();
} }
public static IReadOnlyCollection<LogLevel> GetEnabledLevels() public static IReadOnlyCollection<LogLevel> GetEnabledLevels()
{ {
var logs = new Log?[] { Debug, Info, Warning, Error, Guest, AccessLog, Stub, Trace }; var logs = new[] { Debug, Info, Warning, Error, Guest, AccessLog, Stub, Trace };
List<LogLevel> levels = new List<LogLevel>(logs.Length); List<LogLevel> levels = new(logs.Length);
foreach (var log in logs) foreach (var log in logs)
{ {
if (log.HasValue) if (log.HasValue)
@@ -215,21 +215,23 @@ namespace Ryujinx.Common.Logging
{ {
switch (logLevel) switch (logLevel)
{ {
#pragma warning disable IDE0055 // Disable formatting
case LogLevel.Debug : Debug = enabled ? new Log(LogLevel.Debug) : new Log?(); break; case LogLevel.Debug : Debug = enabled ? new Log(LogLevel.Debug) : new Log?(); break;
case LogLevel.Info : Info = enabled ? new Log(LogLevel.Info) : new Log?(); break; case LogLevel.Info : Info = enabled ? new Log(LogLevel.Info) : new Log?(); break;
case LogLevel.Warning : Warning = enabled ? new Log(LogLevel.Warning) : new Log?(); break; case LogLevel.Warning : Warning = enabled ? new Log(LogLevel.Warning) : new Log?(); break;
case LogLevel.Error : Error = enabled ? new Log(LogLevel.Error) : new Log?(); break; case LogLevel.Error : Error = enabled ? new Log(LogLevel.Error) : new Log?(); break;
case LogLevel.Guest : Guest = enabled ? new Log(LogLevel.Guest) : new Log?(); break; case LogLevel.Guest : Guest = enabled ? new Log(LogLevel.Guest) : new Log?(); break;
case LogLevel.AccessLog : AccessLog = enabled ? new Log(LogLevel.AccessLog): new Log?(); break; case LogLevel.AccessLog : AccessLog = enabled ? new Log(LogLevel.AccessLog) : new Log?(); break;
case LogLevel.Stub : Stub = enabled ? new Log(LogLevel.Stub) : new Log?(); break; case LogLevel.Stub : Stub = enabled ? new Log(LogLevel.Stub) : new Log?(); break;
case LogLevel.Trace : Trace = enabled ? new Log(LogLevel.Trace) : new Log?(); break; case LogLevel.Trace : Trace = enabled ? new Log(LogLevel.Trace) : new Log?(); break;
default: throw new ArgumentException("Unknown Log Level"); default: throw new ArgumentException("Unknown Log Level");
#pragma warning restore IDE0055
} }
} }
public static void SetEnable(LogClass logClass, bool enabled) public static void SetEnable(LogClass logClass, bool enabled)
{ {
m_EnabledClasses[(int)logClass] = enabled; _enabledClasses[(int)logClass] = enabled;
} }
} }
} }

View File

@@ -14,16 +14,16 @@ namespace Ryujinx.Common.Logging.Targets
/// <summary> /// <summary>
/// Discard the overflowing item /// Discard the overflowing item
/// </summary> /// </summary>
Discard = 1 Discard = 1,
} }
public class AsyncLogTargetWrapper : ILogTarget public class AsyncLogTargetWrapper : ILogTarget
{ {
private ILogTarget _target; private readonly ILogTarget _target;
private Thread _messageThread; private readonly Thread _messageThread;
private BlockingCollection<LogEventArgs> _messageQueue; private readonly BlockingCollection<LogEventArgs> _messageQueue;
private readonly int _overflowTimeout; private readonly int _overflowTimeout;
@@ -39,7 +39,8 @@ namespace Ryujinx.Common.Logging.Targets
_messageQueue = new BlockingCollection<LogEventArgs>(queueLimit); _messageQueue = new BlockingCollection<LogEventArgs>(queueLimit);
_overflowTimeout = overflowAction == AsyncLogTargetOverflowAction.Block ? -1 : 0; _overflowTimeout = overflowAction == AsyncLogTargetOverflowAction.Block ? -1 : 0;
_messageThread = new Thread(() => { _messageThread = new Thread(() =>
{
while (!_messageQueue.IsCompleted) while (!_messageQueue.IsCompleted)
{ {
try try
@@ -55,10 +56,11 @@ namespace Ryujinx.Common.Logging.Targets
// on the next iteration. // on the next iteration.
} }
} }
}); })
{
_messageThread.Name = "Logger.MessageThread"; Name = "Logger.MessageThread",
_messageThread.IsBackground = true; IsBackground = true,
};
_messageThread.Start(); _messageThread.Start();
} }
@@ -72,6 +74,7 @@ namespace Ryujinx.Common.Logging.Targets
public void Dispose() public void Dispose()
{ {
GC.SuppressFinalize(this);
_messageQueue.CompleteAdding(); _messageQueue.CompleteAdding();
_messageThread.Join(); _messageThread.Join();
} }

View File

@@ -11,7 +11,8 @@ namespace Ryujinx.Common.Logging.Targets
string ILogTarget.Name { get => _name; } string ILogTarget.Name { get => _name; }
private static ConsoleColor GetLogColor(LogLevel level) => level switch { private static ConsoleColor GetLogColor(LogLevel level) => level switch
{
LogLevel.Info => ConsoleColor.White, LogLevel.Info => ConsoleColor.White,
LogLevel.Warning => ConsoleColor.Yellow, LogLevel.Warning => ConsoleColor.Yellow,
LogLevel.Error => ConsoleColor.Red, LogLevel.Error => ConsoleColor.Red,
@@ -36,6 +37,7 @@ namespace Ryujinx.Common.Logging.Targets
public void Dispose() public void Dispose()
{ {
GC.SuppressFinalize(this);
Console.ResetColor(); Console.ResetColor();
} }
} }

View File

@@ -20,7 +20,7 @@ namespace Ryujinx.Common.Logging.Targets
public FileLogTarget(string path, string name, FileShare fileShare, FileMode fileMode) public FileLogTarget(string path, string name, FileShare fileShare, FileMode fileMode)
{ {
// Ensure directory is present // Ensure directory is present
DirectoryInfo logDir = new DirectoryInfo(Path.Combine(path, "Logs")); DirectoryInfo logDir = new(Path.Combine(path, "Logs"));
logDir.Create(); logDir.Create();
// Clean up old logs, should only keep 3 // Clean up old logs, should only keep 3
@@ -33,7 +33,7 @@ namespace Ryujinx.Common.Logging.Targets
string version = ReleaseInformation.GetVersion(); string version = ReleaseInformation.GetVersion();
// Get path for the current time // Get path for the current time
path = Path.Combine(logDir.FullName, $"Ryujinx_{version}_{DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss")}.log"); path = Path.Combine(logDir.FullName, $"Ryujinx_{version}_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.log");
_name = name; _name = name;
_logWriter = new StreamWriter(File.Open(path, fileMode, FileAccess.Write, fileShare)); _logWriter = new StreamWriter(File.Open(path, fileMode, FileAccess.Write, fileShare));
@@ -48,6 +48,7 @@ namespace Ryujinx.Common.Logging.Targets
public void Dispose() public void Dispose()
{ {
GC.SuppressFinalize(this);
_logWriter.WriteLine("---- End of Log ----"); _logWriter.WriteLine("---- End of Log ----");
_logWriter.Flush(); _logWriter.Flush();
_logWriter.Dispose(); _logWriter.Dispose();

View File

@@ -1,13 +1,14 @@
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;
using System;
using System.IO; using System.IO;
namespace Ryujinx.Common.Logging.Targets namespace Ryujinx.Common.Logging.Targets
{ {
public class JsonLogTarget : ILogTarget public class JsonLogTarget : ILogTarget
{ {
private Stream _stream; private readonly Stream _stream;
private bool _leaveOpen; private readonly bool _leaveOpen;
private string _name; private readonly string _name;
string ILogTarget.Name { get => _name; } string ILogTarget.Name { get => _name; }
@@ -31,6 +32,7 @@ namespace Ryujinx.Common.Logging.Targets
public void Dispose() public void Dispose()
{ {
GC.SuppressFinalize(this);
if (!_leaveOpen) if (!_leaveOpen)
{ {
_stream.Dispose(); _stream.Dispose();

View File

@@ -16,12 +16,12 @@ namespace Ryujinx.Common.Memory
/// <summary> /// <summary>
/// Null pointer. /// Null pointer.
/// </summary> /// </summary>
public static ArrayPtr<T> Null => new ArrayPtr<T>() { _ptr = IntPtr.Zero }; public static ArrayPtr<T> Null => new() { _ptr = IntPtr.Zero };
/// <summary> /// <summary>
/// True if the pointer is null, false otherwise. /// True if the pointer is null, false otherwise.
/// </summary> /// </summary>
public bool IsNull => _ptr == IntPtr.Zero; public readonly bool IsNull => _ptr == IntPtr.Zero;
/// <summary> /// <summary>
/// Number of elements on the array. /// Number of elements on the array.
@@ -37,7 +37,7 @@ namespace Ryujinx.Common.Memory
/// </remarks> /// </remarks>
/// <param name="index">Index of the element</param> /// <param name="index">Index of the element</param>
/// <returns>Reference to the element at the given index</returns> /// <returns>Reference to the element at the given index</returns>
public ref T this[int index] => ref Unsafe.AsRef<T>((T*)_ptr + index); public readonly ref T this[int index] => ref Unsafe.AsRef<T>((T*)_ptr + index);
/// <summary> /// <summary>
/// Creates a new array from a given reference. /// Creates a new array from a given reference.
@@ -81,7 +81,7 @@ namespace Ryujinx.Common.Memory
/// </summary> /// </summary>
/// <param name="start">Index where the new array should start</param> /// <param name="start">Index where the new array should start</param>
/// <returns>New array starting at the specified position</returns> /// <returns>New array starting at the specified position</returns>
public ArrayPtr<T> Slice(int start) => new ArrayPtr<T>(ref this[start], Length - start); public ArrayPtr<T> Slice(int start) => new(ref this[start], Length - start);
/// <summary> /// <summary>
/// Gets a span from the array. /// Gets a span from the array.
@@ -93,19 +93,19 @@ namespace Ryujinx.Common.Memory
/// Gets the array base pointer. /// Gets the array base pointer.
/// </summary> /// </summary>
/// <returns>Base pointer</returns> /// <returns>Base pointer</returns>
public T* ToPointer() => (T*)_ptr; public readonly T* ToPointer() => (T*)_ptr;
public override bool Equals(object obj) public readonly override bool Equals(object obj)
{ {
return obj is ArrayPtr<T> other && Equals(other); return obj is ArrayPtr<T> other && Equals(other);
} }
public bool Equals([AllowNull] ArrayPtr<T> other) public readonly bool Equals([AllowNull] ArrayPtr<T> other)
{ {
return _ptr == other._ptr && Length == other.Length; return _ptr == other._ptr && Length == other.Length;
} }
public override int GetHashCode() public readonly override int GetHashCode()
{ {
return HashCode.Combine(_ptr, Length); return HashCode.Combine(_ptr, Length);
} }

View File

@@ -8,7 +8,7 @@ namespace Ryujinx.Common.Memory
/// </summary> /// </summary>
public sealed partial class ByteMemoryPool public sealed partial class ByteMemoryPool
{ {
private static readonly ByteMemoryPool _shared = new ByteMemoryPool(); private static readonly ByteMemoryPool _shared = new();
/// <summary> /// <summary>
/// Constructs a <see cref="ByteMemoryPool"/> instance. Private to force access through /// Constructs a <see cref="ByteMemoryPool"/> instance. Private to force access through
@@ -27,7 +27,7 @@ namespace Ryujinx.Common.Memory
/// <summary> /// <summary>
/// Returns the maximum buffer size supported by this pool. /// Returns the maximum buffer size supported by this pool.
/// </summary> /// </summary>
public int MaxBufferSize => Array.MaxLength; public static int MaxBufferSize => Array.MaxLength;
/// <summary> /// <summary>
/// Rents a byte memory buffer from <see cref="ArrayPool{Byte}.Shared"/>. /// Rents a byte memory buffer from <see cref="ArrayPool{Byte}.Shared"/>.
@@ -36,7 +36,7 @@ namespace Ryujinx.Common.Memory
/// <param name="length">The buffer's required length in bytes</param> /// <param name="length">The buffer's required length in bytes</param>
/// <returns>A <see cref="IMemoryOwner{Byte}"/> wrapping the rented memory</returns> /// <returns>A <see cref="IMemoryOwner{Byte}"/> wrapping the rented memory</returns>
/// <exception cref="ArgumentOutOfRangeException"></exception> /// <exception cref="ArgumentOutOfRangeException"></exception>
public IMemoryOwner<byte> Rent(long length) public static IMemoryOwner<byte> Rent(long length)
=> RentImpl(checked((int)length)); => RentImpl(checked((int)length));
/// <summary> /// <summary>
@@ -46,7 +46,7 @@ namespace Ryujinx.Common.Memory
/// <param name="length">The buffer's required length in bytes</param> /// <param name="length">The buffer's required length in bytes</param>
/// <returns>A <see cref="IMemoryOwner{Byte}"/> wrapping the rented memory</returns> /// <returns>A <see cref="IMemoryOwner{Byte}"/> wrapping the rented memory</returns>
/// <exception cref="ArgumentOutOfRangeException"></exception> /// <exception cref="ArgumentOutOfRangeException"></exception>
public IMemoryOwner<byte> Rent(ulong length) public static IMemoryOwner<byte> Rent(ulong length)
=> RentImpl(checked((int)length)); => RentImpl(checked((int)length));
/// <summary> /// <summary>
@@ -56,7 +56,7 @@ namespace Ryujinx.Common.Memory
/// <param name="length">The buffer's required length in bytes</param> /// <param name="length">The buffer's required length in bytes</param>
/// <returns>A <see cref="IMemoryOwner{Byte}"/> wrapping the rented memory</returns> /// <returns>A <see cref="IMemoryOwner{Byte}"/> wrapping the rented memory</returns>
/// <exception cref="ArgumentOutOfRangeException"></exception> /// <exception cref="ArgumentOutOfRangeException"></exception>
public IMemoryOwner<byte> Rent(int length) public static IMemoryOwner<byte> Rent(int length)
=> RentImpl(length); => RentImpl(length);
/// <summary> /// <summary>
@@ -66,7 +66,7 @@ namespace Ryujinx.Common.Memory
/// <param name="length">The buffer's required length in bytes</param> /// <param name="length">The buffer's required length in bytes</param>
/// <returns>A <see cref="IMemoryOwner{Byte}"/> wrapping the rented memory</returns> /// <returns>A <see cref="IMemoryOwner{Byte}"/> wrapping the rented memory</returns>
/// <exception cref="ArgumentOutOfRangeException"></exception> /// <exception cref="ArgumentOutOfRangeException"></exception>
public IMemoryOwner<byte> RentCleared(long length) public static IMemoryOwner<byte> RentCleared(long length)
=> RentCleared(checked((int)length)); => RentCleared(checked((int)length));
/// <summary> /// <summary>
@@ -76,7 +76,7 @@ namespace Ryujinx.Common.Memory
/// <param name="length">The buffer's required length in bytes</param> /// <param name="length">The buffer's required length in bytes</param>
/// <returns>A <see cref="IMemoryOwner{Byte}"/> wrapping the rented memory</returns> /// <returns>A <see cref="IMemoryOwner{Byte}"/> wrapping the rented memory</returns>
/// <exception cref="ArgumentOutOfRangeException"></exception> /// <exception cref="ArgumentOutOfRangeException"></exception>
public IMemoryOwner<byte> RentCleared(ulong length) public static IMemoryOwner<byte> RentCleared(ulong length)
=> RentCleared(checked((int)length)); => RentCleared(checked((int)length));
/// <summary> /// <summary>
@@ -86,7 +86,7 @@ namespace Ryujinx.Common.Memory
/// <param name="length">The buffer's required length in bytes</param> /// <param name="length">The buffer's required length in bytes</param>
/// <returns>A <see cref="IMemoryOwner{Byte}"/> wrapping the rented memory</returns> /// <returns>A <see cref="IMemoryOwner{Byte}"/> wrapping the rented memory</returns>
/// <exception cref="ArgumentOutOfRangeException"></exception> /// <exception cref="ArgumentOutOfRangeException"></exception>
public IMemoryOwner<byte> RentCleared(int length) public static IMemoryOwner<byte> RentCleared(int length)
{ {
var buffer = RentImpl(length); var buffer = RentImpl(length);

View File

@@ -5,7 +5,7 @@ namespace Ryujinx.Common.Memory
{ {
public static class MemoryStreamManager public static class MemoryStreamManager
{ {
private static readonly RecyclableMemoryStreamManager _shared = new RecyclableMemoryStreamManager(); private static readonly RecyclableMemoryStreamManager _shared = new();
/// <summary> /// <summary>
/// We don't expose the <c>RecyclableMemoryStreamManager</c> directly because version 2.x /// We don't expose the <c>RecyclableMemoryStreamManager</c> directly because version 2.x
@@ -19,7 +19,7 @@ namespace Ryujinx.Common.Memory
/// </summary> /// </summary>
/// <returns>A <c>RecyclableMemoryStream</c></returns> /// <returns>A <c>RecyclableMemoryStream</c></returns>
public static RecyclableMemoryStream GetStream() public static RecyclableMemoryStream GetStream()
=> new RecyclableMemoryStream(_shared); => new(_shared);
/// <summary> /// <summary>
/// Retrieve a new <c>MemoryStream</c> object with the contents copied from the provided /// Retrieve a new <c>MemoryStream</c> object with the contents copied from the provided

View File

@@ -1,6 +1,5 @@
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
using static Ryujinx.Common.Memory.PartialUnmaps.PartialUnmapHelpers; using static Ryujinx.Common.Memory.PartialUnmaps.PartialUnmapHelpers;
namespace Ryujinx.Common.Memory.PartialUnmaps namespace Ryujinx.Common.Memory.PartialUnmaps
@@ -14,15 +13,15 @@ namespace Ryujinx.Common.Memory.PartialUnmaps
public int WriteLock; public int WriteLock;
public int ReaderCount; public int ReaderCount;
public static int WriteLockOffset; public static readonly int WriteLockOffset;
public static int ReaderCountOffset; public static readonly int ReaderCountOffset;
/// <summary> /// <summary>
/// Populates the field offsets for use when emitting native code. /// Populates the field offsets for use when emitting native code.
/// </summary> /// </summary>
static NativeReaderWriterLock() static NativeReaderWriterLock()
{ {
NativeReaderWriterLock instance = new NativeReaderWriterLock(); NativeReaderWriterLock instance = new();
WriteLockOffset = OffsetOf(ref instance, ref instance.WriteLock); WriteLockOffset = OffsetOf(ref instance, ref instance.WriteLock);
ReaderCountOffset = OffsetOf(ref instance, ref instance.ReaderCount); ReaderCountOffset = OffsetOf(ref instance, ref instance.ReaderCount);
@@ -35,7 +34,9 @@ namespace Ryujinx.Common.Memory.PartialUnmaps
{ {
// Must take write lock for a very short time to become a reader. // Must take write lock for a very short time to become a reader.
while (Interlocked.CompareExchange(ref WriteLock, 1, 0) != 0) { } while (Interlocked.CompareExchange(ref WriteLock, 1, 0) != 0)
{
}
Interlocked.Increment(ref ReaderCount); Interlocked.Increment(ref ReaderCount);
@@ -60,11 +61,15 @@ namespace Ryujinx.Common.Memory.PartialUnmaps
Interlocked.Decrement(ref ReaderCount); Interlocked.Decrement(ref ReaderCount);
while (Interlocked.CompareExchange(ref WriteLock, 1, 0) != 0) { } while (Interlocked.CompareExchange(ref WriteLock, 1, 0) != 0)
{
}
// Wait for reader count to drop to 0, then take the lock again as the only reader. // Wait for reader count to drop to 0, then take the lock again as the only reader.
while (Interlocked.CompareExchange(ref ReaderCount, 1, 0) != 0) { } while (Interlocked.CompareExchange(ref ReaderCount, 1, 0) != 0)
{
}
} }
/// <summary> /// <summary>

View File

@@ -1,10 +1,8 @@
using System; using System;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
using System.Runtime.Versioning; using System.Runtime.Versioning;
using System.Threading; using System.Threading;
using static Ryujinx.Common.Memory.PartialUnmaps.PartialUnmapHelpers; using static Ryujinx.Common.Memory.PartialUnmaps.PartialUnmapHelpers;
namespace Ryujinx.Common.Memory.PartialUnmaps namespace Ryujinx.Common.Memory.PartialUnmaps
@@ -35,7 +33,7 @@ namespace Ryujinx.Common.Memory.PartialUnmaps
[SupportedOSPlatform("windows")] [SupportedOSPlatform("windows")]
[LibraryImport("kernel32.dll", SetLastError = true)] [LibraryImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs (UnmanagedType.Bool)] [return: MarshalAs(UnmanagedType.Bool)]
private static partial bool CloseHandle(IntPtr hObject); private static partial bool CloseHandle(IntPtr hObject);
[SupportedOSPlatform("windows")] [SupportedOSPlatform("windows")]
@@ -48,7 +46,7 @@ namespace Ryujinx.Common.Memory.PartialUnmaps
/// </summary> /// </summary>
static unsafe PartialUnmapState() static unsafe PartialUnmapState()
{ {
PartialUnmapState instance = new PartialUnmapState(); PartialUnmapState instance = new();
PartialUnmapLockOffset = OffsetOf(ref instance, ref instance.PartialUnmapLock); PartialUnmapLockOffset = OffsetOf(ref instance, ref instance.PartialUnmapLock);
PartialUnmapsCountOffset = OffsetOf(ref instance, ref instance.PartialUnmapsCount); PartialUnmapsCountOffset = OffsetOf(ref instance, ref instance.PartialUnmapsCount);

View File

@@ -1,6 +1,5 @@
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
using static Ryujinx.Common.Memory.PartialUnmaps.PartialUnmapHelpers; using static Ryujinx.Common.Memory.PartialUnmaps.PartialUnmapHelpers;
namespace Ryujinx.Common.Memory.PartialUnmaps namespace Ryujinx.Common.Memory.PartialUnmaps
@@ -18,15 +17,15 @@ namespace Ryujinx.Common.Memory.PartialUnmaps
public Array20<int> ThreadIds; public Array20<int> ThreadIds;
public Array20<T> Structs; public Array20<T> Structs;
public static int ThreadIdsOffset; public static readonly int ThreadIdsOffset;
public static int StructsOffset; public static readonly int StructsOffset;
/// <summary> /// <summary>
/// Populates the field offsets for use when emitting native code. /// Populates the field offsets for use when emitting native code.
/// </summary> /// </summary>
static ThreadLocalMap() static ThreadLocalMap()
{ {
ThreadLocalMap<T> instance = new ThreadLocalMap<T>(); ThreadLocalMap<T> instance = new();
ThreadIdsOffset = OffsetOf(ref instance, ref instance.ThreadIds); ThreadIdsOffset = OffsetOf(ref instance, ref instance.ThreadIds);
StructsOffset = OffsetOf(ref instance, ref instance.Structs); StructsOffset = OffsetOf(ref instance, ref instance.Structs);

View File

@@ -15,17 +15,17 @@ namespace Ryujinx.Common.Memory
/// <summary> /// <summary>
/// Null pointer. /// Null pointer.
/// </summary> /// </summary>
public static Ptr<T> Null => new Ptr<T>() { _ptr = IntPtr.Zero }; public static Ptr<T> Null => new() { _ptr = IntPtr.Zero };
/// <summary> /// <summary>
/// True if the pointer is null, false otherwise. /// True if the pointer is null, false otherwise.
/// </summary> /// </summary>
public bool IsNull => _ptr == IntPtr.Zero; public readonly bool IsNull => _ptr == IntPtr.Zero;
/// <summary> /// <summary>
/// Gets a reference to the value. /// Gets a reference to the value.
/// </summary> /// </summary>
public ref T Value => ref Unsafe.AsRef<T>((void*)_ptr); public readonly ref T Value => ref Unsafe.AsRef<T>((void*)_ptr);
/// <summary> /// <summary>
/// Creates a new pointer to an unmanaged resource. /// Creates a new pointer to an unmanaged resource.
@@ -40,17 +40,17 @@ namespace Ryujinx.Common.Memory
_ptr = (IntPtr)Unsafe.AsPointer(ref value); _ptr = (IntPtr)Unsafe.AsPointer(ref value);
} }
public override bool Equals(object obj) public readonly override bool Equals(object obj)
{ {
return obj is Ptr<T> other && Equals(other); return obj is Ptr<T> other && Equals(other);
} }
public bool Equals([AllowNull] Ptr<T> other) public readonly bool Equals([AllowNull] Ptr<T> other)
{ {
return _ptr == other._ptr; return _ptr == other._ptr;
} }
public override int GetHashCode() public readonly override int GetHashCode()
{ {
return _ptr.GetHashCode(); return _ptr.GetHashCode();
} }

View File

@@ -8,7 +8,7 @@ namespace Ryujinx.Common.Memory
{ {
private ReadOnlySpan<byte> _input; private ReadOnlySpan<byte> _input;
public int Length => _input.Length; public readonly int Length => _input.Length;
public SpanReader(ReadOnlySpan<byte> input) public SpanReader(ReadOnlySpan<byte> input)
{ {
@@ -19,7 +19,7 @@ namespace Ryujinx.Common.Memory
{ {
T value = MemoryMarshal.Cast<byte, T>(_input)[0]; T value = MemoryMarshal.Cast<byte, T>(_input)[0];
_input = _input.Slice(Unsafe.SizeOf<T>()); _input = _input[Unsafe.SizeOf<T>()..];
return value; return value;
} }
@@ -37,16 +37,16 @@ namespace Ryujinx.Common.Memory
value = MemoryMarshal.Cast<byte, T>(_input)[0]; value = MemoryMarshal.Cast<byte, T>(_input)[0];
_input = _input.Slice(valueSize); _input = _input[valueSize..];
return true; return true;
} }
public ReadOnlySpan<byte> GetSpan(int size) public ReadOnlySpan<byte> GetSpan(int size)
{ {
ReadOnlySpan<byte> data = _input.Slice(0, size); ReadOnlySpan<byte> data = _input[..size];
_input = _input.Slice(size); _input = _input[size..];
return data; return data;
} }
@@ -56,19 +56,19 @@ namespace Ryujinx.Common.Memory
return GetSpan((int)Math.Min((uint)_input.Length, (uint)size)); return GetSpan((int)Math.Min((uint)_input.Length, (uint)size));
} }
public T ReadAt<T>(int offset) where T : unmanaged public readonly T ReadAt<T>(int offset) where T : unmanaged
{ {
return MemoryMarshal.Cast<byte, T>(_input.Slice(offset))[0]; return MemoryMarshal.Cast<byte, T>(_input[offset..])[0];
} }
public ReadOnlySpan<byte> GetSpanAt(int offset, int size) public readonly ReadOnlySpan<byte> GetSpanAt(int offset, int size)
{ {
return _input.Slice(offset, size); return _input.Slice(offset, size);
} }
public void Skip(int size) public void Skip(int size)
{ {
_input = _input.Slice(size); _input = _input[size..];
} }
} }
} }

View File

@@ -8,7 +8,7 @@ namespace Ryujinx.Common.Memory
{ {
private Span<byte> _output; private Span<byte> _output;
public int Length => _output.Length; public readonly int Length => _output.Length;
public SpanWriter(Span<byte> output) public SpanWriter(Span<byte> output)
{ {
@@ -18,28 +18,28 @@ namespace Ryujinx.Common.Memory
public void Write<T>(T value) where T : unmanaged public void Write<T>(T value) where T : unmanaged
{ {
MemoryMarshal.Cast<byte, T>(_output)[0] = value; MemoryMarshal.Cast<byte, T>(_output)[0] = value;
_output = _output.Slice(Unsafe.SizeOf<T>()); _output = _output[Unsafe.SizeOf<T>()..];
} }
public void Write(ReadOnlySpan<byte> data) public void Write(ReadOnlySpan<byte> data)
{ {
data.CopyTo(_output.Slice(0, data.Length)); data.CopyTo(_output[..data.Length]);
_output = _output.Slice(data.Length); _output = _output[data.Length..];
} }
public void WriteAt<T>(int offset, T value) where T : unmanaged public readonly void WriteAt<T>(int offset, T value) where T : unmanaged
{ {
MemoryMarshal.Cast<byte, T>(_output.Slice(offset))[0] = value; MemoryMarshal.Cast<byte, T>(_output[offset..])[0] = value;
} }
public void WriteAt(int offset, ReadOnlySpan<byte> data) public readonly void WriteAt(int offset, ReadOnlySpan<byte> data)
{ {
data.CopyTo(_output.Slice(offset, data.Length)); data.CopyTo(_output.Slice(offset, data.Length));
} }
public void Skip(int size) public void Skip(int size)
{ {
_output = _output.Slice(size); _output = _output[size..];
} }
} }
} }

View File

@@ -1,654 +1,658 @@
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
#pragma warning disable CS0169, IDE0051 // Remove unused private member
namespace Ryujinx.Common.Memory namespace Ryujinx.Common.Memory
{ {
public struct Array1<T> : IArray<T> where T : unmanaged public struct Array1<T> : IArray<T> where T : unmanaged
{ {
T _e0; T _e0;
public int Length => 1; public readonly int Length => 1;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 1); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array2<T> : IArray<T> where T : unmanaged public struct Array2<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array1<T> _other; Array1<T> _other;
#pragma warning restore CS0169 public readonly int Length => 2;
public int Length => 2;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 2); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array3<T> : IArray<T> where T : unmanaged public struct Array3<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array2<T> _other; Array2<T> _other;
#pragma warning restore CS0169 public readonly int Length => 3;
public int Length => 3;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 3); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array4<T> : IArray<T> where T : unmanaged public struct Array4<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array3<T> _other; Array3<T> _other;
#pragma warning restore CS0169 public readonly int Length => 4;
public int Length => 4;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 4); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array5<T> : IArray<T> where T : unmanaged public struct Array5<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array4<T> _other; Array4<T> _other;
#pragma warning restore CS0169 public readonly int Length => 5;
public int Length => 5;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 5); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array6<T> : IArray<T> where T : unmanaged public struct Array6<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array5<T> _other; Array5<T> _other;
#pragma warning restore CS0169 public readonly int Length => 6;
public int Length => 6;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 6); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array7<T> : IArray<T> where T : unmanaged public struct Array7<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array6<T> _other; Array6<T> _other;
#pragma warning restore CS0169 public readonly int Length => 7;
public int Length => 7;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 7); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array8<T> : IArray<T> where T : unmanaged public struct Array8<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array7<T> _other; Array7<T> _other;
#pragma warning restore CS0169 public readonly int Length => 8;
public int Length => 8;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 8); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array9<T> : IArray<T> where T : unmanaged public struct Array9<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array8<T> _other; Array8<T> _other;
#pragma warning restore CS0169 public readonly int Length => 9;
public int Length => 9;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 9); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array10<T> : IArray<T> where T : unmanaged public struct Array10<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array9<T> _other; Array9<T> _other;
#pragma warning restore CS0169 public readonly int Length => 10;
public int Length => 10;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 10); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array11<T> : IArray<T> where T : unmanaged public struct Array11<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array10<T> _other; Array10<T> _other;
#pragma warning restore CS0169 public readonly int Length => 11;
public int Length => 11;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 11); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array12<T> : IArray<T> where T : unmanaged public struct Array12<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array11<T> _other; Array11<T> _other;
#pragma warning restore CS0169 public readonly int Length => 12;
public int Length => 12;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 12); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array13<T> : IArray<T> where T : unmanaged public struct Array13<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array12<T> _other; Array12<T> _other;
#pragma warning restore CS0169 public readonly int Length => 13;
public int Length => 13;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 13); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array14<T> : IArray<T> where T : unmanaged public struct Array14<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array13<T> _other; Array13<T> _other;
#pragma warning restore CS0169 public readonly int Length => 14;
public int Length => 14;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 14); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array15<T> : IArray<T> where T : unmanaged public struct Array15<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array14<T> _other; Array14<T> _other;
#pragma warning restore CS0169 public readonly int Length => 15;
public int Length => 15;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 15); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array16<T> : IArray<T> where T : unmanaged public struct Array16<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array15<T> _other; Array15<T> _other;
#pragma warning restore CS0169 public readonly int Length => 16;
public int Length => 16;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 16); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array17<T> : IArray<T> where T : unmanaged public struct Array17<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array16<T> _other; Array16<T> _other;
#pragma warning restore CS0169 public readonly int Length => 17;
public int Length => 17;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 17); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array18<T> : IArray<T> where T : unmanaged public struct Array18<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array17<T> _other; Array17<T> _other;
#pragma warning restore CS0169 public readonly int Length => 18;
public int Length => 18;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 18); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array19<T> : IArray<T> where T : unmanaged public struct Array19<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array18<T> _other; Array18<T> _other;
#pragma warning restore CS0169 public readonly int Length => 19;
public int Length => 19;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 19); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array20<T> : IArray<T> where T : unmanaged public struct Array20<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array19<T> _other; Array19<T> _other;
#pragma warning restore CS0169 public readonly int Length => 20;
public int Length => 20;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 20); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array21<T> : IArray<T> where T : unmanaged public struct Array21<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array20<T> _other; Array20<T> _other;
#pragma warning restore CS0169 public readonly int Length => 21;
public int Length => 21;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 21); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array22<T> : IArray<T> where T : unmanaged public struct Array22<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array21<T> _other; Array21<T> _other;
#pragma warning restore CS0169 public readonly int Length => 22;
public int Length => 22;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 22); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array23<T> : IArray<T> where T : unmanaged public struct Array23<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array22<T> _other; Array22<T> _other;
#pragma warning restore CS0169 public readonly int Length => 23;
public int Length => 23;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 23); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array24<T> : IArray<T> where T : unmanaged public struct Array24<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array23<T> _other; Array23<T> _other;
#pragma warning restore CS0169
public int Length => 24; public readonly int Length => 24;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 24); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array25<T> : IArray<T> where T : unmanaged public struct Array25<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array24<T> _other; Array24<T> _other;
#pragma warning restore CS0169
public int Length => 25; public readonly int Length => 25;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 25); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array26<T> : IArray<T> where T : unmanaged public struct Array26<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array25<T> _other; Array25<T> _other;
#pragma warning restore CS0169
public int Length => 26; public readonly int Length => 26;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 26); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array27<T> : IArray<T> where T : unmanaged public struct Array27<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array26<T> _other; Array26<T> _other;
#pragma warning restore CS0169
public int Length => 27; public readonly int Length => 27;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 27); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array28<T> : IArray<T> where T : unmanaged public struct Array28<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array27<T> _other; Array27<T> _other;
#pragma warning restore CS0169
public int Length => 28; public readonly int Length => 28;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 28); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array29<T> : IArray<T> where T : unmanaged public struct Array29<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array28<T> _other; Array28<T> _other;
#pragma warning restore CS0169
public int Length => 29; public readonly int Length => 29;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 29); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array30<T> : IArray<T> where T : unmanaged public struct Array30<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array29<T> _other; Array29<T> _other;
#pragma warning restore CS0169
public int Length => 30; public readonly int Length => 30;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 30); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array31<T> : IArray<T> where T : unmanaged public struct Array31<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array30<T> _other; Array30<T> _other;
#pragma warning restore CS0169
public int Length => 31; public readonly int Length => 31;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 31); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array32<T> : IArray<T> where T : unmanaged public struct Array32<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array31<T> _other; Array31<T> _other;
#pragma warning restore CS0169
public int Length => 32; public readonly int Length => 32;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 32); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array33<T> : IArray<T> where T : unmanaged public struct Array33<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array32<T> _other; Array32<T> _other;
#pragma warning restore CS0169
public int Length => 33; public readonly int Length => 33;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 33); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array34<T> : IArray<T> where T : unmanaged public struct Array34<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array33<T> _other; Array33<T> _other;
#pragma warning restore CS0169
public int Length => 34; public readonly int Length => 34;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 34); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array35<T> : IArray<T> where T : unmanaged public struct Array35<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array34<T> _other; Array34<T> _other;
#pragma warning restore CS0169
public int Length => 35; public readonly int Length => 35;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 35); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array36<T> : IArray<T> where T : unmanaged public struct Array36<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array35<T> _other; Array35<T> _other;
#pragma warning restore CS0169
public int Length => 36; public readonly int Length => 36;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 36); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array37<T> : IArray<T> where T : unmanaged public struct Array37<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array36<T> _other; Array36<T> _other;
#pragma warning restore CS0169
public int Length => 37; public readonly int Length => 37;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 37); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array38<T> : IArray<T> where T : unmanaged public struct Array38<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array37<T> _other; Array37<T> _other;
#pragma warning restore CS0169
public int Length => 38; public readonly int Length => 38;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 38); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array39<T> : IArray<T> where T : unmanaged public struct Array39<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array38<T> _other; Array38<T> _other;
#pragma warning restore CS0169
public int Length => 39; public readonly int Length => 39;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 39); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array40<T> : IArray<T> where T : unmanaged public struct Array40<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array39<T> _other; Array39<T> _other;
#pragma warning restore CS0169
public int Length => 40; public readonly int Length => 40;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 40); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array41<T> : IArray<T> where T : unmanaged public struct Array41<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array40<T> _other; Array40<T> _other;
#pragma warning restore CS0169
public int Length => 41; public readonly int Length => 41;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 41); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array42<T> : IArray<T> where T : unmanaged public struct Array42<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array41<T> _other; Array41<T> _other;
#pragma warning restore CS0169
public int Length => 42; public readonly int Length => 42;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 42); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array43<T> : IArray<T> where T : unmanaged public struct Array43<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array42<T> _other; Array42<T> _other;
#pragma warning restore CS0169
public int Length => 43; public readonly int Length => 43;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 43); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array44<T> : IArray<T> where T : unmanaged public struct Array44<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array43<T> _other; Array43<T> _other;
#pragma warning restore CS0169
public int Length => 44; public readonly int Length => 44;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 44); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array45<T> : IArray<T> where T : unmanaged public struct Array45<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array44<T> _other; Array44<T> _other;
#pragma warning restore CS0169
public int Length => 45; public readonly int Length => 45;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 45); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array46<T> : IArray<T> where T : unmanaged public struct Array46<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array45<T> _other; Array45<T> _other;
#pragma warning restore CS0169
public int Length => 46; public readonly int Length => 46;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 46); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array47<T> : IArray<T> where T : unmanaged public struct Array47<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array46<T> _other; Array46<T> _other;
#pragma warning restore CS0169
public int Length => 47; public readonly int Length => 47;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 47); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array48<T> : IArray<T> where T : unmanaged public struct Array48<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array47<T> _other; Array47<T> _other;
#pragma warning restore CS0169
public int Length => 48; public readonly int Length => 48;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 48); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array49<T> : IArray<T> where T : unmanaged public struct Array49<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array48<T> _other; Array48<T> _other;
#pragma warning restore CS0169
public int Length => 49; public readonly int Length => 49;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 49); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array50<T> : IArray<T> where T : unmanaged public struct Array50<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array49<T> _other; Array49<T> _other;
#pragma warning restore CS0169
public int Length => 50; public readonly int Length => 50;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 50); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array51<T> : IArray<T> where T : unmanaged public struct Array51<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array50<T> _other; Array50<T> _other;
#pragma warning restore CS0169
public int Length => 51; public readonly int Length => 51;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 51); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array52<T> : IArray<T> where T : unmanaged public struct Array52<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array51<T> _other; Array51<T> _other;
#pragma warning restore CS0169
public int Length => 52; public readonly int Length => 52;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 52); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array53<T> : IArray<T> where T : unmanaged public struct Array53<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array52<T> _other; Array52<T> _other;
#pragma warning restore CS0169
public int Length => 53; public readonly int Length => 53;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 53); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array54<T> : IArray<T> where T : unmanaged public struct Array54<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array53<T> _other; Array53<T> _other;
#pragma warning restore CS0169
public int Length => 54; public readonly int Length => 54;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 54); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array55<T> : IArray<T> where T : unmanaged public struct Array55<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array54<T> _other; Array54<T> _other;
#pragma warning restore CS0169
public int Length => 55; public readonly int Length => 55;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 55); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array56<T> : IArray<T> where T : unmanaged public struct Array56<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array55<T> _other; Array55<T> _other;
#pragma warning restore CS0169
public int Length => 56; public readonly int Length => 56;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 56); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array57<T> : IArray<T> where T : unmanaged public struct Array57<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array56<T> _other; Array56<T> _other;
#pragma warning restore CS0169
public int Length => 57; public readonly int Length => 57;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 57); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array58<T> : IArray<T> where T : unmanaged public struct Array58<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array57<T> _other; Array57<T> _other;
#pragma warning restore CS0169
public int Length => 58; public readonly int Length => 58;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 58); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array59<T> : IArray<T> where T : unmanaged public struct Array59<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array58<T> _other; Array58<T> _other;
#pragma warning restore CS0169
public int Length => 59; public readonly int Length => 59;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 59); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array60<T> : IArray<T> where T : unmanaged public struct Array60<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array59<T> _other; Array59<T> _other;
#pragma warning restore CS0169 public readonly int Length => 60;
public int Length => 60;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 60); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array61<T> : IArray<T> where T : unmanaged public struct Array61<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array60<T> _other; Array60<T> _other;
#pragma warning restore CS0169 public readonly int Length => 61;
public int Length => 61;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 61); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array62<T> : IArray<T> where T : unmanaged public struct Array62<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array61<T> _other; Array61<T> _other;
#pragma warning restore CS0169 public readonly int Length => 62;
public int Length => 62;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 62); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array63<T> : IArray<T> where T : unmanaged public struct Array63<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array62<T> _other; Array62<T> _other;
#pragma warning restore CS0169 public readonly int Length => 63;
public int Length => 63;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 63); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array64<T> : IArray<T> where T : unmanaged public struct Array64<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array63<T> _other; Array63<T> _other;
#pragma warning restore CS0169 public readonly int Length => 64;
public int Length => 64;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 64); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
public struct Array73<T> : IArray<T> where T : unmanaged public struct Array73<T> : IArray<T> where T : unmanaged
{ {
#pragma warning disable CS0169
T _e0; T _e0;
Array64<T> _other; Array64<T> _other;
Array8<T> _other2; Array8<T> _other2;
#pragma warning restore CS0169 public readonly int Length => 73;
public int Length => 73;
public ref T this[int index] => ref AsSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 73); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
}
public struct Array127<T> : IArray<T> where T : unmanaged
{
T _e0;
Array64<T> _other;
Array62<T> _other2;
public readonly int Length => 127;
public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
}
public struct Array128<T> : IArray<T> where T : unmanaged
{
T _e0;
Array64<T> _other;
Array63<T> _other2;
public readonly int Length => 128;
public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
}
public struct Array256<T> : IArray<T> where T : unmanaged
{
T _e0;
Array128<T> _other;
Array127<T> _other2;
public readonly int Length => 256;
public ref T this[int index] => ref AsSpan()[index];
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
} }
} }
#pragma warning restore CS0169, IDE0051

View File

@@ -10,7 +10,7 @@ namespace Ryujinx.Common.Memory
byte _element; byte _element;
public int Length => Size; public readonly int Length => Size;
public ref byte this[int index] => ref AsSpan()[index]; public ref byte this[int index] => ref AsSpan()[index];
public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size); public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
} }
@@ -22,7 +22,7 @@ namespace Ryujinx.Common.Memory
byte _element; byte _element;
public int Length => Size; public readonly int Length => Size;
public ref byte this[int index] => ref AsSpan()[index]; public ref byte this[int index] => ref AsSpan()[index];
public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size); public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
} }
@@ -34,7 +34,7 @@ namespace Ryujinx.Common.Memory
byte _element; byte _element;
public int Length => Size; public readonly int Length => Size;
public ref byte this[int index] => ref AsSpan()[index]; public ref byte this[int index] => ref AsSpan()[index];
public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size); public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
} }
@@ -46,7 +46,7 @@ namespace Ryujinx.Common.Memory
byte _element; byte _element;
public int Length => Size; public readonly int Length => Size;
public ref byte this[int index] => ref AsSpan()[index]; public ref byte this[int index] => ref AsSpan()[index];
public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size); public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
} }
@@ -58,7 +58,7 @@ namespace Ryujinx.Common.Memory
byte _element; byte _element;
public int Length => Size; public readonly int Length => Size;
public ref byte this[int index] => ref AsSpan()[index]; public ref byte this[int index] => ref AsSpan()[index];
public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size); public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
} }
@@ -70,7 +70,7 @@ namespace Ryujinx.Common.Memory
byte _element; byte _element;
public int Length => Size; public readonly int Length => Size;
public ref byte this[int index] => ref AsSpan()[index]; public ref byte this[int index] => ref AsSpan()[index];
public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size); public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
} }

View File

@@ -1,10 +1,10 @@
using System.Diagnostics; using System.Diagnostics;
namespace Ryujinx.Common namespace Ryujinx.Common
{ {
public static class PerformanceCounter public static class PerformanceCounter
{ {
private static double _ticksToNs; private static readonly double _ticksToNs;
/// <summary> /// <summary>
/// Represents the number of ticks in 1 day. /// Represents the number of ticks in 1 day.

View File

@@ -5,7 +5,7 @@
private static class DefaultPool<T> private static class DefaultPool<T>
where T : class, new() where T : class, new()
{ {
public static readonly ObjectPool<T> Instance = new ObjectPool<T>(() => new T(), 20); public static readonly ObjectPool<T> Instance = new(() => new T(), 20);
} }
public static ObjectPool<T> Default<T>() public static ObjectPool<T> Default<T>()

View File

@@ -9,10 +9,7 @@ namespace Ryujinx.Common.Pools
public static ref T[] Get() public static ref T[] Get()
{ {
if (_array == null) _array ??= new T[1];
{
_array = new T[1];
}
return ref _array; return ref _array;
} }

View File

@@ -5,8 +5,8 @@ namespace Ryujinx.Common
{ {
public class ReactiveObject<T> public class ReactiveObject<T>
{ {
private ReaderWriterLock _readerWriterLock = new ReaderWriterLock(); private readonly ReaderWriterLock _readerWriterLock = new();
private bool _isInitialized = false; private bool _isInitialized;
private T _value; private T _value;
public event EventHandler<ReactiveEventArgs<T>> Event; public event EventHandler<ReactiveEventArgs<T>> Event;

View File

@@ -9,11 +9,11 @@ namespace Ryujinx.Common
{ {
private const string FlatHubChannelOwner = "flathub"; private const string FlatHubChannelOwner = "flathub";
public static string BuildVersion = "%%RYUJINX_BUILD_VERSION%%"; public const string BuildVersion = "%%RYUJINX_BUILD_VERSION%%";
public static string BuildGitHash = "%%RYUJINX_BUILD_GIT_HASH%%"; public const string BuildGitHash = "%%RYUJINX_BUILD_GIT_HASH%%";
public static string ReleaseChannelName = "%%RYUJINX_TARGET_RELEASE_CHANNEL_NAME%%"; public const string ReleaseChannelName = "%%RYUJINX_TARGET_RELEASE_CHANNEL_NAME%%";
public static string ReleaseChannelOwner = "%%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER%%"; public const string ReleaseChannelOwner = "%%RYUJINX_TARGET_RELEASE_CHANNEL_OWNER%%";
public static string ReleaseChannelRepo = "%%RYUJINX_TARGET_RELEASE_CHANNEL_REPO%%"; public const string ReleaseChannelRepo = "%%RYUJINX_TARGET_RELEASE_CHANNEL_REPO%%";
public static bool IsValid() public static bool IsValid()
{ {
@@ -34,11 +34,9 @@ namespace Ryujinx.Common
{ {
return BuildVersion; return BuildVersion;
} }
else
{
return Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion; return Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion;
} }
}
#if FORCE_EXTERNAL_BASE_DIR #if FORCE_EXTERNAL_BASE_DIR
public static string GetBaseApplicationDirectory() public static string GetBaseApplicationDirectory()

View File

@@ -20,7 +20,7 @@ namespace Ryujinx.Common.SystemInfo
{ {
["model name"] = null, ["model name"] = null,
["Processor"] = null, ["Processor"] = null,
["Hardware"] = null ["Hardware"] = null,
}; };
ParseKeyValues("/proc/cpuinfo", cpuDict); ParseKeyValues("/proc/cpuinfo", cpuDict);
@@ -31,7 +31,7 @@ namespace Ryujinx.Common.SystemInfo
var memDict = new Dictionary<string, string>(StringComparer.Ordinal) var memDict = new Dictionary<string, string>(StringComparer.Ordinal)
{ {
["MemTotal"] = null, ["MemTotal"] = null,
["MemAvailable"] = null ["MemAvailable"] = null,
}; };
ParseKeyValues("/proc/meminfo", memDict); ParseKeyValues("/proc/meminfo", memDict);
@@ -56,14 +56,17 @@ namespace Ryujinx.Common.SystemInfo
int count = itemDict.Count; int count = itemDict.Count;
using (StreamReader file = new StreamReader(filePath)) using StreamReader file = new(filePath);
{
string line; string line;
while ((line = file.ReadLine()) != null) while ((line = file.ReadLine()) != null)
{ {
string[] kvPair = line.Split(':', 2, StringSplitOptions.TrimEntries); string[] kvPair = line.Split(':', 2, StringSplitOptions.TrimEntries);
if (kvPair.Length < 2) continue; if (kvPair.Length < 2)
{
continue;
}
string key = kvPair[0]; string key = kvPair[0];
@@ -71,7 +74,9 @@ namespace Ryujinx.Common.SystemInfo
{ {
itemDict[key] = kvPair[1]; itemDict[key] = kvPair[1];
if (--count <= 0) break; if (--count <= 0)
{
break;
} }
} }
} }

View File

@@ -14,14 +14,14 @@ namespace Ryujinx.Common.SystemInfo
{ {
string cpuName = GetCpuidCpuName(); string cpuName = GetCpuidCpuName();
if (cpuName == null && sysctlbyname("machdep.cpu.brand_string", out cpuName) != 0) if (cpuName == null && SysctlByName("machdep.cpu.brand_string", out cpuName) != 0)
{ {
cpuName = "Unknown"; cpuName = "Unknown";
} }
ulong totalRAM = 0; ulong totalRAM = 0;
if (sysctlbyname("hw.memsize", ref totalRAM) != 0) // Bytes if (SysctlByName("hw.memsize", ref totalRAM) != 0) // Bytes
{ {
totalRAM = 0; totalRAM = 0;
} }
@@ -63,7 +63,7 @@ namespace Ryujinx.Common.SystemInfo
[LibraryImport(SystemLibraryName, SetLastError = true)] [LibraryImport(SystemLibraryName, SetLastError = true)]
private static partial int sysctlbyname([MarshalAs(UnmanagedType.LPStr)] string name, IntPtr oldValue, ref ulong oldSize, IntPtr newValue, ulong newValueSize); private static partial int sysctlbyname([MarshalAs(UnmanagedType.LPStr)] string name, IntPtr oldValue, ref ulong oldSize, IntPtr newValue, ulong newValueSize);
private static int sysctlbyname(string name, IntPtr oldValue, ref ulong oldSize) private static int SysctlByName(string name, IntPtr oldValue, ref ulong oldSize)
{ {
if (sysctlbyname(name, oldValue, ref oldSize, IntPtr.Zero, 0) == -1) if (sysctlbyname(name, oldValue, ref oldSize, IntPtr.Zero, 0) == -1)
{ {
@@ -77,23 +77,23 @@ namespace Ryujinx.Common.SystemInfo
return 0; return 0;
} }
private static int sysctlbyname<T>(string name, ref T oldValue) private static int SysctlByName<T>(string name, ref T oldValue)
{ {
unsafe unsafe
{ {
ulong oldValueSize = (ulong)Unsafe.SizeOf<T>(); ulong oldValueSize = (ulong)Unsafe.SizeOf<T>();
return sysctlbyname(name, (IntPtr)Unsafe.AsPointer(ref oldValue), ref oldValueSize); return SysctlByName(name, (IntPtr)Unsafe.AsPointer(ref oldValue), ref oldValueSize);
} }
} }
private static int sysctlbyname(string name, out string oldValue) private static int SysctlByName(string name, out string oldValue)
{ {
oldValue = default; oldValue = default;
ulong strSize = 0; ulong strSize = 0;
int res = sysctlbyname(name, IntPtr.Zero, ref strSize); int res = SysctlByName(name, IntPtr.Zero, ref strSize);
if (res == 0) if (res == 0)
{ {
@@ -103,7 +103,7 @@ namespace Ryujinx.Common.SystemInfo
{ {
fixed (byte* rawDataPtr = rawData) fixed (byte* rawDataPtr = rawData)
{ {
res = sysctlbyname(name, (IntPtr)rawDataPtr, ref strSize); res = SysctlByName(name, (IntPtr)rawDataPtr, ref strSize);
} }
if (res == 0) if (res == 0)
@@ -152,6 +152,6 @@ namespace Ryujinx.Common.SystemInfo
} }
[LibraryImport(SystemLibraryName, SetLastError = true)] [LibraryImport(SystemLibraryName, SetLastError = true)]
private static partial int host_statistics64(uint host_priv, int host_flavor, ref VMStatistics64 host_info64_out, ref uint host_info64_outCnt); private static partial int host_statistics64(uint hostPriv, int hostFlavor, ref VMStatistics64 hostInfo64Out, ref uint hostInfo64OutCnt);
} }
} }

View File

@@ -43,13 +43,11 @@ namespace Ryujinx.Common.SystemInfo
{ {
return new MacOSSystemInfo(); return new MacOSSystemInfo();
} }
else
{
Logger.Error?.Print(LogClass.Application, "SystemInfo unsupported on this platform"); Logger.Error?.Print(LogClass.Application, "SystemInfo unsupported on this platform");
return new SystemInfo(); return new SystemInfo();
} }
}
// x86 exposes a 48 byte ASCII "CPU brand" string via CPUID leaves 0x80000002-0x80000004. // x86 exposes a 48 byte ASCII "CPU brand" string via CPUID leaves 0x80000002-0x80000004.
internal static string GetCpuidCpuName() internal static string GetCpuidCpuName()

View File

@@ -17,15 +17,13 @@ namespace Ryujinx.Common.SystemInfo
private static (ulong Total, ulong Available) GetMemoryStats() private static (ulong Total, ulong Available) GetMemoryStats()
{ {
MemoryStatusEx memStatus = new MemoryStatusEx(); MemoryStatusEx memStatus = new();
if (GlobalMemoryStatusEx(ref memStatus)) if (GlobalMemoryStatusEx(ref memStatus))
{ {
return (memStatus.TotalPhys, memStatus.AvailPhys); // Bytes return (memStatus.TotalPhys, memStatus.AvailPhys); // Bytes
} }
else
{
Logger.Error?.Print(LogClass.Application, $"GlobalMemoryStatusEx failed. Error {Marshal.GetLastWin32Error():X}"); Logger.Error?.Print(LogClass.Application, $"GlobalMemoryStatusEx failed. Error {Marshal.GetLastWin32Error():X}");
}
return (0, 0); return (0, 0);
} }

View File

@@ -10,7 +10,7 @@ namespace Ryujinx.Common.SystemInterop
{ {
ES_CONTINUOUS = 0x80000000, ES_CONTINUOUS = 0x80000000,
ES_DISPLAY_REQUIRED = 0x00000002, ES_DISPLAY_REQUIRED = 0x00000002,
ES_SYSTEM_REQUIRED = 0x00000001 ES_SYSTEM_REQUIRED = 0x00000001,
} }
[LibraryImport("kernel32.dll", SetLastError = true)] [LibraryImport("kernel32.dll", SetLastError = true)]

View File

@@ -63,14 +63,14 @@ namespace Ryujinx.Common.SystemInterop
string dpiString = Marshal.PtrToStringAnsi(XGetDefault(display, "Xft", "dpi")); string dpiString = Marshal.PtrToStringAnsi(XGetDefault(display, "Xft", "dpi"));
if (dpiString == null || !double.TryParse(dpiString, NumberStyles.Any, CultureInfo.InvariantCulture, out userDpiScale)) if (dpiString == null || !double.TryParse(dpiString, NumberStyles.Any, CultureInfo.InvariantCulture, out userDpiScale))
{ {
userDpiScale = (double)XDisplayWidth(display, 0) * 25.4 / (double)XDisplayWidthMM(display, 0); userDpiScale = XDisplayWidth(display, 0) * 25.4 / XDisplayWidthMM(display, 0);
} }
XCloseDisplay(display); _ = XCloseDisplay(display);
} }
else if (xdgSessionType == "wayland") else if (xdgSessionType == "wayland")
{ {
// TODO // TODO
Logger.Warning?.Print(LogClass.Application, $"Couldn't determine monitor DPI: Wayland not yet supported"); Logger.Warning?.Print(LogClass.Application, "Couldn't determine monitor DPI: Wayland not yet supported");
} }
else else
{ {

View File

@@ -28,14 +28,14 @@ namespace Ryujinx.Common.SystemInterop
{ {
public int GdiplusVersion; public int GdiplusVersion;
#pragma warning disable CS0649 #pragma warning disable CS0649 // Field is never assigned to
public IntPtr DebugEventCallback; public IntPtr DebugEventCallback;
public int SuppressBackgroundThread; public int SuppressBackgroundThread;
public int SuppressExternalCodecs; public int SuppressExternalCodecs;
public int StartupParameters; public int StartupParameters;
#pragma warning restore CS0649 #pragma warning restore CS0649
public static StartupInputEx Default => new StartupInputEx public static StartupInputEx Default => new()
{ {
// We assume Windows 8 and upper // We assume Windows 8 and upper
GdiplusVersion = 2, GdiplusVersion = 2,

View File

@@ -11,7 +11,7 @@ namespace Ryujinx.Common.SystemInterop
{ {
public partial class StdErrAdapter : IDisposable public partial class StdErrAdapter : IDisposable
{ {
private bool _disposable = false; private bool _disposable;
private Stream _pipeReader; private Stream _pipeReader;
private Stream _pipeWriter; private Stream _pipeWriter;
private CancellationTokenSource _cancellationTokenSource; private CancellationTokenSource _cancellationTokenSource;
@@ -54,8 +54,10 @@ namespace Ryujinx.Common.SystemInterop
} }
} }
private void Dispose(bool disposing) public void Dispose()
{ {
GC.SuppressFinalize(this);
if (_disposable) if (_disposable)
{ {
_disposable = false; _disposable = false;
@@ -70,11 +72,6 @@ namespace Ryujinx.Common.SystemInterop
} }
} }
public void Dispose()
{
Dispose(true);
}
[LibraryImport("libc", SetLastError = true)] [LibraryImport("libc", SetLastError = true)]
private static partial int dup2(int fd, int fd2); private static partial int dup2(int fd, int fd2);
@@ -89,18 +86,16 @@ namespace Ryujinx.Common.SystemInterop
{ {
return (pipefd[0], pipefd[1]); return (pipefd[0], pipefd[1]);
} }
else
{
throw new(); throw new();
} }
}
[SupportedOSPlatform("linux")] [SupportedOSPlatform("linux")]
[SupportedOSPlatform("macos")] [SupportedOSPlatform("macos")]
private static Stream CreateFileDescriptorStream(int fd) private static Stream CreateFileDescriptorStream(int fd)
{ {
return new FileStream( return new FileStream(
new SafeFileHandle((IntPtr)fd, ownsHandle: true), new SafeFileHandle(fd, ownsHandle: true),
FileAccess.ReadWrite FileAccess.ReadWrite
); );
} }

View File

@@ -17,7 +17,7 @@ namespace Ryujinx.Common.SystemInterop
{ {
public uint wPeriodMin; public uint wPeriodMin;
public uint wPeriodMax; public uint wPeriodMax;
}; }
[LibraryImport("winmm.dll", EntryPoint = "timeGetDevCaps", SetLastError = true)] [LibraryImport("winmm.dll", EntryPoint = "timeGetDevCaps", SetLastError = true)]
private static partial uint TimeGetDevCaps(ref TimeCaps timeCaps, uint sizeTimeCaps); private static partial uint TimeGetDevCaps(ref TimeCaps timeCaps, uint sizeTimeCaps);

View File

@@ -1,4 +1,3 @@
using System;
using System.Numerics; using System.Numerics;
namespace Ryujinx.Common namespace Ryujinx.Common
@@ -48,10 +47,10 @@ namespace Ryujinx.Common
private static ulong ReverseBits64(ulong value) private static ulong ReverseBits64(ulong value)
{ {
value = ((value & 0xaaaaaaaaaaaaaaaa) >> 1 ) | ((value & 0x5555555555555555) << 1 ); value = ((value & 0xaaaaaaaaaaaaaaaa) >> 1) | ((value & 0x5555555555555555) << 1);
value = ((value & 0xcccccccccccccccc) >> 2 ) | ((value & 0x3333333333333333) << 2 ); value = ((value & 0xcccccccccccccccc) >> 2) | ((value & 0x3333333333333333) << 2);
value = ((value & 0xf0f0f0f0f0f0f0f0) >> 4 ) | ((value & 0x0f0f0f0f0f0f0f0f) << 4 ); value = ((value & 0xf0f0f0f0f0f0f0f0) >> 4) | ((value & 0x0f0f0f0f0f0f0f0f) << 4);
value = ((value & 0xff00ff00ff00ff00) >> 8 ) | ((value & 0x00ff00ff00ff00ff) << 8 ); value = ((value & 0xff00ff00ff00ff00) >> 8) | ((value & 0x00ff00ff00ff00ff) << 8);
value = ((value & 0xffff0000ffff0000) >> 16) | ((value & 0x0000ffff0000ffff) << 16); value = ((value & 0xffff0000ffff0000) >> 16) | ((value & 0x0000ffff0000ffff) << 16);
return (value >> 32) | (value << 32); return (value >> 32) | (value << 32);

View File

@@ -9,8 +9,8 @@ namespace Ryujinx.Common.Utilities
[StructLayout(LayoutKind.Sequential, Size = 16)] [StructLayout(LayoutKind.Sequential, Size = 16)]
public struct Buffer16 public struct Buffer16
{ {
[DebuggerBrowsable(DebuggerBrowsableState.Never)] private ulong _dummy0; [DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly ulong _dummy0;
[DebuggerBrowsable(DebuggerBrowsableState.Never)] private ulong _dummy1; [DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly ulong _dummy1;
public byte this[int i] public byte this[int i]
{ {

View File

@@ -1,4 +1,3 @@
using Ryujinx.Common.Memory;
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;
using System; using System;
using System.IO; using System.IO;
@@ -10,11 +9,11 @@ namespace Ryujinx.Common
{ {
public static class EmbeddedResources public static class EmbeddedResources
{ {
private readonly static Assembly ResourceAssembly; private readonly static Assembly _resourceAssembly;
static EmbeddedResources() static EmbeddedResources()
{ {
ResourceAssembly = Assembly.GetAssembly(typeof(EmbeddedResources)); _resourceAssembly = Assembly.GetAssembly(typeof(EmbeddedResources));
} }
public static byte[] Read(string filename) public static byte[] Read(string filename)
@@ -33,8 +32,7 @@ namespace Ryujinx.Common
public static byte[] Read(Assembly assembly, string filename) public static byte[] Read(Assembly assembly, string filename)
{ {
using (var stream = GetStream(assembly, filename)) using var stream = GetStream(assembly, filename);
{
if (stream == null) if (stream == null)
{ {
return null; return null;
@@ -42,12 +40,10 @@ namespace Ryujinx.Common
return StreamUtils.StreamToBytes(stream); return StreamUtils.StreamToBytes(stream);
} }
}
public async static Task<byte[]> ReadAsync(Assembly assembly, string filename) public async static Task<byte[]> ReadAsync(Assembly assembly, string filename)
{ {
using (var stream = GetStream(assembly, filename)) using var stream = GetStream(assembly, filename);
{
if (stream == null) if (stream == null)
{ {
return null; return null;
@@ -55,7 +51,6 @@ namespace Ryujinx.Common
return await StreamUtils.StreamToBytesAsync(stream); return await StreamUtils.StreamToBytesAsync(stream);
} }
}
public static string ReadAllText(string filename) public static string ReadAllText(string filename)
{ {
@@ -73,35 +68,27 @@ namespace Ryujinx.Common
public static string ReadAllText(Assembly assembly, string filename) public static string ReadAllText(Assembly assembly, string filename)
{ {
using (var stream = GetStream(assembly, filename)) using var stream = GetStream(assembly, filename);
{
if (stream == null) if (stream == null)
{ {
return null; return null;
} }
using (var reader = new StreamReader(stream)) using var reader = new StreamReader(stream);
{
return reader.ReadToEnd(); return reader.ReadToEnd();
} }
}
}
public async static Task<string> ReadAllTextAsync(Assembly assembly, string filename) public async static Task<string> ReadAllTextAsync(Assembly assembly, string filename)
{ {
using (var stream = GetStream(assembly, filename)) using var stream = GetStream(assembly, filename);
{
if (stream == null) if (stream == null)
{ {
return null; return null;
} }
using (var reader = new StreamReader(stream)) using var reader = new StreamReader(stream);
{
return await reader.ReadToEndAsync(); return await reader.ReadToEndAsync();
} }
}
}
public static Stream GetStream(string filename) public static Stream GetStream(string filename)
{ {
@@ -112,8 +99,8 @@ namespace Ryujinx.Common
public static Stream GetStream(Assembly assembly, string filename) public static Stream GetStream(Assembly assembly, string filename)
{ {
var namespace_ = assembly.GetName().Name; var @namespace = assembly.GetName().Name;
var manifestUri = namespace_ + "." + filename.Replace('/', '.'); var manifestUri = @namespace + "." + filename.Replace('/', '.');
var stream = assembly.GetManifestResourceStream(manifestUri); var stream = assembly.GetManifestResourceStream(manifestUri);
@@ -142,7 +129,7 @@ namespace Ryujinx.Common
} }
} }
return (ResourceAssembly, filename); return (_resourceAssembly, filename);
} }
} }
} }

View File

@@ -5,7 +5,7 @@ namespace Ryujinx.Common
{ {
public static class HexUtils public static class HexUtils
{ {
private static readonly char[] HexChars = "0123456789ABCDEF".ToCharArray(); private static readonly char[] _hexChars = "0123456789ABCDEF".ToCharArray();
private const int HexTableColumnWidth = 8; private const int HexTableColumnWidth = 8;
private const int HexTableColumnSpace = 3; private const int HexTableColumnSpace = 3;
@@ -39,18 +39,18 @@ namespace Ryujinx.Common
int expectedLines = (bytesLength + bytesPerLine - 1) / bytesPerLine; int expectedLines = (bytesLength + bytesPerLine - 1) / bytesPerLine;
StringBuilder result = new StringBuilder(expectedLines * lineLength); StringBuilder result = new(expectedLines * lineLength);
for (int i = 0; i < bytesLength; i += bytesPerLine) for (int i = 0; i < bytesLength; i += bytesPerLine)
{ {
line[0] = HexChars[(i >> 28) & 0xF]; line[0] = _hexChars[(i >> 28) & 0xF];
line[1] = HexChars[(i >> 24) & 0xF]; line[1] = _hexChars[(i >> 24) & 0xF];
line[2] = HexChars[(i >> 20) & 0xF]; line[2] = _hexChars[(i >> 20) & 0xF];
line[3] = HexChars[(i >> 16) & 0xF]; line[3] = _hexChars[(i >> 16) & 0xF];
line[4] = HexChars[(i >> 12) & 0xF]; line[4] = _hexChars[(i >> 12) & 0xF];
line[5] = HexChars[(i >> 8) & 0xF]; line[5] = _hexChars[(i >> 8) & 0xF];
line[6] = HexChars[(i >> 4) & 0xF]; line[6] = _hexChars[(i >> 4) & 0xF];
line[7] = HexChars[(i >> 0) & 0xF]; line[7] = _hexChars[(i >> 0) & 0xF];
int hexColumn = firstHexColumn; int hexColumn = firstHexColumn;
int charColumn = firstCharColumn; int charColumn = firstCharColumn;
@@ -72,8 +72,8 @@ namespace Ryujinx.Common
{ {
byte b = bytes[i + j]; byte b = bytes[i + j];
line[hexColumn] = HexChars[(b >> 4) & 0xF]; line[hexColumn] = _hexChars[(b >> 4) & 0xF];
line[hexColumn + 1] = HexChars[b & 0xF]; line[hexColumn + 1] = _hexChars[b & 0xF];
line[charColumn] = (b < 32 ? '·' : (char)b); line[charColumn] = (b < 32 ? '·' : (char)b);
} }

View File

@@ -7,7 +7,7 @@ namespace Ryujinx.Common.Utilities
{ {
public class JsonHelper public class JsonHelper
{ {
private static readonly JsonNamingPolicy SnakeCasePolicy = new SnakeCaseNamingPolicy(); private static readonly JsonNamingPolicy _snakeCasePolicy = new SnakeCaseNamingPolicy();
private const int DefaultFileWriteBufferSize = 4096; private const int DefaultFileWriteBufferSize = 4096;
/// <summary> /// <summary>
@@ -21,11 +21,11 @@ namespace Ryujinx.Common.Utilities
{ {
JsonSerializerOptions options = new() JsonSerializerOptions options = new()
{ {
DictionaryKeyPolicy = SnakeCasePolicy, DictionaryKeyPolicy = _snakeCasePolicy,
PropertyNamingPolicy = SnakeCasePolicy, PropertyNamingPolicy = _snakeCasePolicy,
WriteIndented = indented, WriteIndented = indented,
AllowTrailingCommas = true, AllowTrailingCommas = true,
ReadCommentHandling = JsonCommentHandling.Skip ReadCommentHandling = JsonCommentHandling.Skip,
}; };
return options; return options;

View File

@@ -12,11 +12,9 @@ namespace Ryujinx.Common.Utilities
{ {
return Format(obj); return Format(obj);
} }
else
{
return obj.ToString(); return obj.ToString();
} }
}
public static string Format(MessagePackObject obj) public static string Format(MessagePackObject obj)
{ {
@@ -179,19 +177,17 @@ namespace Ryujinx.Common.Utilities
{ {
return unchecked((char)('0' + b)); return unchecked((char)('0' + b));
} }
else
{
return unchecked((char)('A' + (b - 10))); return unchecked((char)('A' + (b - 10)));
} }
}
internal class IndentedStringBuilder internal class IndentedStringBuilder
{ {
const string DefaultIndent = " "; const string DefaultIndent = " ";
private int _indentCount = 0; private int _indentCount;
private int _newLineIndex = 0; private int _newLineIndex;
private StringBuilder _builder; private readonly StringBuilder _builder;
public string IndentString { get; set; } = DefaultIndent; public string IndentString { get; set; } = DefaultIndent;

View File

@@ -1,5 +1,4 @@
using Microsoft.IO; using Ryujinx.Common.Memory;
using Ryujinx.Common.Memory;
using System.IO; using System.IO;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@@ -10,22 +9,21 @@ namespace Ryujinx.Common.Utilities
{ {
public static byte[] StreamToBytes(Stream input) public static byte[] StreamToBytes(Stream input)
{ {
using (MemoryStream stream = MemoryStreamManager.Shared.GetStream()) using MemoryStream stream = MemoryStreamManager.Shared.GetStream();
{
input.CopyTo(stream); input.CopyTo(stream);
return stream.ToArray(); return stream.ToArray();
} }
}
public static async Task<byte[]> StreamToBytesAsync(Stream input, CancellationToken cancellationToken = default) public static async Task<byte[]> StreamToBytesAsync(Stream input, CancellationToken cancellationToken = default)
{ {
using (MemoryStream stream = MemoryStreamManager.Shared.GetStream()) using MemoryStream stream = MemoryStreamManager.Shared.GetStream();
{
await input.CopyToAsync(stream, cancellationToken); await input.CopyToAsync(stream, cancellationToken);
return stream.ToArray(); return stream.ToArray();
} }
} }
}
} }

View File

@@ -31,8 +31,7 @@ namespace Ryujinx.Common
private const ulong Prime64_4 = 0x85EBCA77C2B2AE63UL; private const ulong Prime64_4 = 0x85EBCA77C2B2AE63UL;
private const ulong Prime64_5 = 0x27D4EB2F165667C5UL; private const ulong Prime64_5 = 0x27D4EB2F165667C5UL;
private static readonly ulong[] Xxh3InitAcc = new ulong[] private static readonly ulong[] _xxh3InitAcc = {
{
Prime32_3, Prime32_3,
Prime64_1, Prime64_1,
Prime64_2, Prime64_2,
@@ -40,7 +39,7 @@ namespace Ryujinx.Common
Prime64_4, Prime64_4,
Prime32_2, Prime32_2,
Prime64_5, Prime64_5,
Prime32_1 Prime32_1,
}; };
private static ReadOnlySpan<byte> Xxh3KSecret => new byte[] private static ReadOnlySpan<byte> Xxh3KSecret => new byte[]
@@ -56,23 +55,24 @@ namespace Ryujinx.Common
0xea, 0xc5, 0xac, 0x83, 0x34, 0xd3, 0xeb, 0xc3, 0xc5, 0x81, 0xa0, 0xff, 0xfa, 0x13, 0x63, 0xeb, 0xea, 0xc5, 0xac, 0x83, 0x34, 0xd3, 0xeb, 0xc3, 0xc5, 0x81, 0xa0, 0xff, 0xfa, 0x13, 0x63, 0xeb,
0x17, 0x0d, 0xdd, 0x51, 0xb7, 0xf0, 0xda, 0x49, 0xd3, 0x16, 0x55, 0x26, 0x29, 0xd4, 0x68, 0x9e, 0x17, 0x0d, 0xdd, 0x51, 0xb7, 0xf0, 0xda, 0x49, 0xd3, 0x16, 0x55, 0x26, 0x29, 0xd4, 0x68, 0x9e,
0x2b, 0x16, 0xbe, 0x58, 0x7d, 0x47, 0xa1, 0xfc, 0x8f, 0xf8, 0xb8, 0xd1, 0x7a, 0xd0, 0x31, 0xce, 0x2b, 0x16, 0xbe, 0x58, 0x7d, 0x47, 0xa1, 0xfc, 0x8f, 0xf8, 0xb8, 0xd1, 0x7a, 0xd0, 0x31, 0xce,
0x45, 0xcb, 0x3a, 0x8f, 0x95, 0x16, 0x04, 0x28, 0xaf, 0xd7, 0xfb, 0xca, 0xbb, 0x4b, 0x40, 0x7e 0x45, 0xcb, 0x3a, 0x8f, 0x95, 0x16, 0x04, 0x28, 0xaf, 0xd7, 0xfb, 0xca, 0xbb, 0x4b, 0x40, 0x7e,
}; };
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private static ulong Mult32To64(ulong x, ulong y) private static ulong Mult32To64(ulong x, ulong y)
{ {
return (ulong)(uint)x * (ulong)(uint)y; return (uint)x * (ulong)(uint)y;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private static Hash128 Mult64To128(ulong lhs, ulong rhs) private static Hash128 Mult64To128(ulong lhs, ulong rhs)
{ {
ulong high = Math.BigMul(lhs, rhs, out ulong low); ulong high = Math.BigMul(lhs, rhs, out ulong low);
return new Hash128 return new Hash128
{ {
Low = low, Low = low,
High = high High = high,
}; };
} }
@@ -80,6 +80,7 @@ namespace Ryujinx.Common
private static ulong Mul128Fold64(ulong lhs, ulong rhs) private static ulong Mul128Fold64(ulong lhs, ulong rhs)
{ {
Hash128 product = Mult64To128(lhs, rhs); Hash128 product = Mult64To128(lhs, rhs);
return product.Low ^ product.High; return product.Low ^ product.High;
} }
@@ -87,6 +88,7 @@ namespace Ryujinx.Common
private static ulong XorShift64(ulong v64, int shift) private static ulong XorShift64(ulong v64, int shift)
{ {
Debug.Assert(0 <= shift && shift < 64); Debug.Assert(0 <= shift && shift < 64);
return v64 ^ (v64 >> shift); return v64 ^ (v64 >> shift);
} }
@@ -96,6 +98,7 @@ namespace Ryujinx.Common
h64 = XorShift64(h64, 37); h64 = XorShift64(h64, 37);
h64 *= 0x165667919E3779F9UL; h64 *= 0x165667919E3779F9UL;
h64 = XorShift64(h64, 32); h64 = XorShift64(h64, 32);
return h64; return h64;
} }
@@ -107,6 +110,7 @@ namespace Ryujinx.Common
h64 ^= h64 >> 29; h64 ^= h64 >> 29;
h64 *= Prime64_3; h64 *= Prime64_3;
h64 ^= h64 >> 32; h64 ^= h64 >> 32;
return h64; return h64;
} }
@@ -165,8 +169,8 @@ namespace Ryujinx.Common
{ {
for (int i = 0; i < AccNb; i++) for (int i = 0; i < AccNb; i++)
{ {
ulong dataVal = BinaryPrimitives.ReadUInt64LittleEndian(input.Slice(i * sizeof(ulong))); ulong dataVal = BinaryPrimitives.ReadUInt64LittleEndian(input[(i * sizeof(ulong))..]);
ulong dataKey = dataVal ^ BinaryPrimitives.ReadUInt64LittleEndian(secret.Slice(i * sizeof(ulong))); ulong dataKey = dataVal ^ BinaryPrimitives.ReadUInt64LittleEndian(secret[(i * sizeof(ulong))..]);
acc[i ^ 1] += dataVal; acc[i ^ 1] += dataVal;
acc[i] += Mult32To64((uint)dataKey, dataKey >> 32); acc[i] += Mult32To64((uint)dataKey, dataKey >> 32);
} }
@@ -236,7 +240,7 @@ namespace Ryujinx.Common
{ {
for (int i = 0; i < AccNb; i++) for (int i = 0; i < AccNb; i++)
{ {
ulong key64 = BinaryPrimitives.ReadUInt64LittleEndian(secret.Slice(i * sizeof(ulong))); ulong key64 = BinaryPrimitives.ReadUInt64LittleEndian(secret[(i * sizeof(ulong))..]);
ulong acc64 = acc[i]; ulong acc64 = acc[i];
acc64 = XorShift64(acc64, 47); acc64 = XorShift64(acc64, 47);
acc64 ^= key64; acc64 ^= key64;
@@ -251,8 +255,8 @@ namespace Ryujinx.Common
{ {
for (int n = 0; n < nbStripes; n++) for (int n = 0; n < nbStripes; n++)
{ {
ReadOnlySpan<byte> inData = input.Slice(n * StripeLen); ReadOnlySpan<byte> inData = input[(n * StripeLen)..];
Xxh3Accumulate512(acc, inData, secret.Slice(n * SecretConsumeRate)); Xxh3Accumulate512(acc, inData, secret[(n * SecretConsumeRate)..]);
} }
} }
@@ -266,18 +270,18 @@ namespace Ryujinx.Common
for (int n = 0; n < nbBlocks; n++) for (int n = 0; n < nbBlocks; n++)
{ {
Xxh3Accumulate(acc, input.Slice(n * blockLen), secret, nbStripesPerBlock); Xxh3Accumulate(acc, input[(n * blockLen)..], secret, nbStripesPerBlock);
Xxh3ScrambleAcc(acc, secret.Slice(secret.Length - StripeLen)); Xxh3ScrambleAcc(acc, secret[^StripeLen..]);
} }
Debug.Assert(input.Length > StripeLen); Debug.Assert(input.Length > StripeLen);
int nbStripes = (input.Length - 1 - (blockLen * nbBlocks)) / StripeLen; int nbStripes = (input.Length - 1 - (blockLen * nbBlocks)) / StripeLen;
Debug.Assert(nbStripes <= (secret.Length / SecretConsumeRate)); Debug.Assert(nbStripes <= (secret.Length / SecretConsumeRate));
Xxh3Accumulate(acc, input.Slice(nbBlocks * blockLen), secret, nbStripes); Xxh3Accumulate(acc, input[(nbBlocks * blockLen)..], secret, nbStripes);
ReadOnlySpan<byte> p = input.Slice(input.Length - StripeLen); ReadOnlySpan<byte> p = input[^StripeLen..];
Xxh3Accumulate512(acc, p, secret.Slice(secret.Length - StripeLen - SecretLastAccStart)); Xxh3Accumulate512(acc, p, secret[(secret.Length - StripeLen - SecretLastAccStart)..]);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -285,7 +289,7 @@ namespace Ryujinx.Common
{ {
return Mul128Fold64( return Mul128Fold64(
acc[0] ^ BinaryPrimitives.ReadUInt64LittleEndian(secret), acc[0] ^ BinaryPrimitives.ReadUInt64LittleEndian(secret),
acc[1] ^ BinaryPrimitives.ReadUInt64LittleEndian(secret.Slice(8))); acc[1] ^ BinaryPrimitives.ReadUInt64LittleEndian(secret[8..]));
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -295,7 +299,7 @@ namespace Ryujinx.Common
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
result64 += Xxh3Mix2Accs(acc.Slice(2 * i), secret.Slice(16 * i)); result64 += Xxh3Mix2Accs(acc[(2 * i)..], secret[(16 * i)..]);
} }
return Xxh3Avalanche(result64); return Xxh3Avalanche(result64);
@@ -305,7 +309,7 @@ namespace Ryujinx.Common
private static Hash128 Xxh3HashLong128bInternal(ReadOnlySpan<byte> input, ReadOnlySpan<byte> secret) private static Hash128 Xxh3HashLong128bInternal(ReadOnlySpan<byte> input, ReadOnlySpan<byte> secret)
{ {
Span<ulong> acc = stackalloc ulong[AccNb]; Span<ulong> acc = stackalloc ulong[AccNb];
Xxh3InitAcc.CopyTo(acc); _xxh3InitAcc.CopyTo(acc);
Xxh3HashLongInternalLoop(acc, input, secret); Xxh3HashLongInternalLoop(acc, input, secret);
@@ -314,11 +318,11 @@ namespace Ryujinx.Common
return new Hash128 return new Hash128
{ {
Low = Xxh3MergeAccs(acc, secret.Slice(SecretMergeAccsStart), (ulong)input.Length * Prime64_1), Low = Xxh3MergeAccs(acc, secret[SecretMergeAccsStart..], (ulong)input.Length * Prime64_1),
High = Xxh3MergeAccs( High = Xxh3MergeAccs(
acc, acc,
secret.Slice(secret.Length - acc.Length * sizeof(ulong) - SecretMergeAccsStart), secret[(secret.Length - acc.Length * sizeof(ulong) - SecretMergeAccsStart)..],
~((ulong)input.Length * Prime64_2)) ~((ulong)input.Length * Prime64_2)),
}; };
} }
@@ -332,15 +336,15 @@ namespace Ryujinx.Common
uint combinedL = ((uint)c1 << 16) | ((uint)c2 << 24) | c3 | ((uint)input.Length << 8); uint combinedL = ((uint)c1 << 16) | ((uint)c2 << 24) | c3 | ((uint)input.Length << 8);
uint combinedH = BitOperations.RotateLeft(BinaryPrimitives.ReverseEndianness(combinedL), 13); uint combinedH = BitOperations.RotateLeft(BinaryPrimitives.ReverseEndianness(combinedL), 13);
ulong bitFlipL = (BinaryPrimitives.ReadUInt32LittleEndian(secret) ^ BinaryPrimitives.ReadUInt32LittleEndian(secret.Slice(4))) + seed; ulong bitFlipL = (BinaryPrimitives.ReadUInt32LittleEndian(secret) ^ BinaryPrimitives.ReadUInt32LittleEndian(secret[4..])) + seed;
ulong bitFlipH = (BinaryPrimitives.ReadUInt32LittleEndian(secret.Slice(8)) ^ BinaryPrimitives.ReadUInt32LittleEndian(secret.Slice(12))) - seed; ulong bitFlipH = (BinaryPrimitives.ReadUInt32LittleEndian(secret[8..]) ^ BinaryPrimitives.ReadUInt32LittleEndian(secret[12..])) - seed;
ulong keyedLo = combinedL ^ bitFlipL; ulong keyedLo = combinedL ^ bitFlipL;
ulong keyedHi = combinedH ^ bitFlipH; ulong keyedHi = combinedH ^ bitFlipH;
return new Hash128 return new Hash128
{ {
Low = Xxh64Avalanche(keyedLo), Low = Xxh64Avalanche(keyedLo),
High = Xxh64Avalanche(keyedHi) High = Xxh64Avalanche(keyedHi),
}; };
} }
@@ -351,9 +355,9 @@ namespace Ryujinx.Common
seed ^= BinaryPrimitives.ReverseEndianness((uint)seed) << 32; seed ^= BinaryPrimitives.ReverseEndianness((uint)seed) << 32;
uint inputLo = BinaryPrimitives.ReadUInt32LittleEndian(input); uint inputLo = BinaryPrimitives.ReadUInt32LittleEndian(input);
uint inputHi = BinaryPrimitives.ReadUInt32LittleEndian(input.Slice(input.Length - 4)); uint inputHi = BinaryPrimitives.ReadUInt32LittleEndian(input[^4..]);
ulong input64 = inputLo + ((ulong)inputHi << 32); ulong input64 = inputLo + ((ulong)inputHi << 32);
ulong bitFlip = (BinaryPrimitives.ReadUInt64LittleEndian(secret.Slice(16)) ^ BinaryPrimitives.ReadUInt64LittleEndian(secret.Slice(24))) + seed; ulong bitFlip = (BinaryPrimitives.ReadUInt64LittleEndian(secret[16..]) ^ BinaryPrimitives.ReadUInt64LittleEndian(secret[24..])) + seed;
ulong keyed = input64 ^ bitFlip; ulong keyed = input64 ^ bitFlip;
Hash128 m128 = Mult64To128(keyed, Prime64_1 + ((ulong)input.Length << 2)); Hash128 m128 = Mult64To128(keyed, Prime64_1 + ((ulong)input.Length << 2));
@@ -365,6 +369,7 @@ namespace Ryujinx.Common
m128.Low *= 0x9FB21C651E98DF25UL; m128.Low *= 0x9FB21C651E98DF25UL;
m128.Low = XorShift64(m128.Low, 28); m128.Low = XorShift64(m128.Low, 28);
m128.High = Xxh3Avalanche(m128.High); m128.High = Xxh3Avalanche(m128.High);
return m128; return m128;
} }
@@ -372,10 +377,10 @@ namespace Ryujinx.Common
{ {
Debug.Assert(9 <= input.Length && input.Length <= 16); Debug.Assert(9 <= input.Length && input.Length <= 16);
ulong bitFlipL = (BinaryPrimitives.ReadUInt64LittleEndian(secret.Slice(32)) ^ BinaryPrimitives.ReadUInt64LittleEndian(secret.Slice(40))) - seed; ulong bitFlipL = (BinaryPrimitives.ReadUInt64LittleEndian(secret[32..]) ^ BinaryPrimitives.ReadUInt64LittleEndian(secret[40..])) - seed;
ulong bitFlipH = (BinaryPrimitives.ReadUInt64LittleEndian(secret.Slice(48)) ^ BinaryPrimitives.ReadUInt64LittleEndian(secret.Slice(56))) + seed; ulong bitFlipH = (BinaryPrimitives.ReadUInt64LittleEndian(secret[48..]) ^ BinaryPrimitives.ReadUInt64LittleEndian(secret[56..])) + seed;
ulong inputLo = BinaryPrimitives.ReadUInt64LittleEndian(input); ulong inputLo = BinaryPrimitives.ReadUInt64LittleEndian(input);
ulong inputHi = BinaryPrimitives.ReadUInt64LittleEndian(input.Slice(input.Length - 8)); ulong inputHi = BinaryPrimitives.ReadUInt64LittleEndian(input[^8..]);
Hash128 m128 = Mult64To128(inputLo ^ inputHi ^ bitFlipL, Prime64_1); Hash128 m128 = Mult64To128(inputLo ^ inputHi ^ bitFlipL, Prime64_1);
m128.Low += ((ulong)input.Length - 1) << 54; m128.Low += ((ulong)input.Length - 1) << 54;
@@ -387,6 +392,7 @@ namespace Ryujinx.Common
h128.High += m128.High * Prime64_2; h128.High += m128.High * Prime64_2;
h128.Low = Xxh3Avalanche(h128.Low); h128.Low = Xxh3Avalanche(h128.Low);
h128.High = Xxh3Avalanche(h128.High); h128.High = Xxh3Avalanche(h128.High);
return h128; return h128;
} }
@@ -398,40 +404,43 @@ namespace Ryujinx.Common
{ {
return Xxh3Len9To16128b(input, secret, seed); return Xxh3Len9To16128b(input, secret, seed);
} }
else if (input.Length >= 4)
if (input.Length >= 4)
{ {
return Xxh3Len4To8128b(input, secret, seed); return Xxh3Len4To8128b(input, secret, seed);
} }
else if (input.Length != 0)
if (input.Length != 0)
{ {
return Xxh3Len1To3128b(input, secret, seed); return Xxh3Len1To3128b(input, secret, seed);
} }
else
{ Hash128 h128 = new();
Hash128 h128 = new Hash128(); ulong bitFlipL = BinaryPrimitives.ReadUInt64LittleEndian(secret[64..]) ^ BinaryPrimitives.ReadUInt64LittleEndian(secret[72..]);
ulong bitFlipL = BinaryPrimitives.ReadUInt64LittleEndian(secret.Slice(64)) ^ BinaryPrimitives.ReadUInt64LittleEndian(secret.Slice(72)); ulong bitFlipH = BinaryPrimitives.ReadUInt64LittleEndian(secret[80..]) ^ BinaryPrimitives.ReadUInt64LittleEndian(secret[88..]);
ulong bitFlipH = BinaryPrimitives.ReadUInt64LittleEndian(secret.Slice(80)) ^ BinaryPrimitives.ReadUInt64LittleEndian(secret.Slice(88));
h128.Low = Xxh64Avalanche(seed ^ bitFlipL); h128.Low = Xxh64Avalanche(seed ^ bitFlipL);
h128.High = Xxh64Avalanche(seed ^ bitFlipH); h128.High = Xxh64Avalanche(seed ^ bitFlipH);
return h128; return h128;
} }
}
private static ulong Xxh3Mix16b(ReadOnlySpan<byte> input, ReadOnlySpan<byte> secret, ulong seed) private static ulong Xxh3Mix16b(ReadOnlySpan<byte> input, ReadOnlySpan<byte> secret, ulong seed)
{ {
ulong inputLo = BinaryPrimitives.ReadUInt64LittleEndian(input); ulong inputLo = BinaryPrimitives.ReadUInt64LittleEndian(input);
ulong inputHi = BinaryPrimitives.ReadUInt64LittleEndian(input.Slice(8)); ulong inputHi = BinaryPrimitives.ReadUInt64LittleEndian(input[8..]);
return Mul128Fold64( return Mul128Fold64(
inputLo ^ (BinaryPrimitives.ReadUInt64LittleEndian(secret) + seed), inputLo ^ (BinaryPrimitives.ReadUInt64LittleEndian(secret) + seed),
inputHi ^ (BinaryPrimitives.ReadUInt64LittleEndian(secret.Slice(8)) - seed)); inputHi ^ (BinaryPrimitives.ReadUInt64LittleEndian(secret[8..]) - seed));
} }
private static Hash128 Xxh128Mix32b(Hash128 acc, ReadOnlySpan<byte> input, ReadOnlySpan<byte> input2, ReadOnlySpan<byte> secret, ulong seed) private static Hash128 Xxh128Mix32b(Hash128 acc, ReadOnlySpan<byte> input, ReadOnlySpan<byte> input2, ReadOnlySpan<byte> secret, ulong seed)
{ {
acc.Low += Xxh3Mix16b(input, secret, seed); acc.Low += Xxh3Mix16b(input, secret, seed);
acc.Low ^= BinaryPrimitives.ReadUInt64LittleEndian(input2) + BinaryPrimitives.ReadUInt64LittleEndian(input2.Slice(8)); acc.Low ^= BinaryPrimitives.ReadUInt64LittleEndian(input2) + BinaryPrimitives.ReadUInt64LittleEndian(input2[8..]);
acc.High += Xxh3Mix16b(input2, secret.Slice(16), seed); acc.High += Xxh3Mix16b(input2, secret[16..], seed);
acc.High ^= BinaryPrimitives.ReadUInt64LittleEndian(input) + BinaryPrimitives.ReadUInt64LittleEndian(input.Slice(8)); acc.High ^= BinaryPrimitives.ReadUInt64LittleEndian(input) + BinaryPrimitives.ReadUInt64LittleEndian(input[8..]);
return acc; return acc;
} }
@@ -440,10 +449,10 @@ namespace Ryujinx.Common
Debug.Assert(secret.Length >= SecretSizeMin); Debug.Assert(secret.Length >= SecretSizeMin);
Debug.Assert(16 < input.Length && input.Length <= 128); Debug.Assert(16 < input.Length && input.Length <= 128);
Hash128 acc = new Hash128 Hash128 acc = new()
{ {
Low = (ulong)input.Length * Prime64_1, Low = (ulong)input.Length * Prime64_1,
High = 0 High = 0,
}; };
if (input.Length > 32) if (input.Length > 32)
@@ -452,21 +461,22 @@ namespace Ryujinx.Common
{ {
if (input.Length > 96) if (input.Length > 96)
{ {
acc = Xxh128Mix32b(acc, input.Slice(48), input.Slice(input.Length - 64), secret.Slice(96), seed); acc = Xxh128Mix32b(acc, input[48..], input[^64..], secret[96..], seed);
} }
acc = Xxh128Mix32b(acc, input.Slice(32), input.Slice(input.Length - 48), secret.Slice(64), seed); acc = Xxh128Mix32b(acc, input[32..], input[^48..], secret[64..], seed);
} }
acc = Xxh128Mix32b(acc, input.Slice(16), input.Slice(input.Length - 32), secret.Slice(32), seed); acc = Xxh128Mix32b(acc, input[16..], input[^32..], secret[32..], seed);
} }
acc = Xxh128Mix32b(acc, input, input.Slice(input.Length - 16), secret, seed); acc = Xxh128Mix32b(acc, input, input[^16..], secret, seed);
Hash128 h128 = new Hash128 Hash128 h128 = new()
{ {
Low = acc.Low + acc.High, Low = acc.Low + acc.High,
High = acc.Low * Prime64_1 + acc.High * Prime64_4 + ((ulong)input.Length - seed) * Prime64_2 High = acc.Low * Prime64_1 + acc.High * Prime64_4 + ((ulong)input.Length - seed) * Prime64_2,
}; };
h128.Low = Xxh3Avalanche(h128.Low); h128.Low = Xxh3Avalanche(h128.Low);
h128.High = 0UL - Xxh3Avalanche(h128.High); h128.High = 0UL - Xxh3Avalanche(h128.High);
return h128; return h128;
} }
@@ -475,7 +485,7 @@ namespace Ryujinx.Common
Debug.Assert(secret.Length >= SecretSizeMin); Debug.Assert(secret.Length >= SecretSizeMin);
Debug.Assert(128 < input.Length && input.Length <= 240); Debug.Assert(128 < input.Length && input.Length <= 240);
Hash128 acc = new Hash128(); Hash128 acc = new();
int nbRounds = input.Length / 32; int nbRounds = input.Length / 32;
acc.Low = (ulong)input.Length * Prime64_1; acc.Low = (ulong)input.Length * Prime64_1;
@@ -483,7 +493,7 @@ namespace Ryujinx.Common
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
acc = Xxh128Mix32b(acc, input.Slice(32 * i), input.Slice(32 * i + 16), secret.Slice(32 * i), seed); acc = Xxh128Mix32b(acc, input[(32 * i)..], input[(32 * i + 16)..], secret[(32 * i)..], seed);
} }
acc.Low = Xxh3Avalanche(acc.Low); acc.Low = Xxh3Avalanche(acc.Low);
@@ -492,18 +502,19 @@ namespace Ryujinx.Common
for (int i = 4; i < nbRounds; i++) for (int i = 4; i < nbRounds; i++)
{ {
acc = Xxh128Mix32b(acc, input.Slice(32 * i), input.Slice(32 * i + 16), secret.Slice(MidSizeStartOffset + 32 * (i - 4)), seed); acc = Xxh128Mix32b(acc, input[(32 * i)..], input[(32 * i + 16)..], secret[(MidSizeStartOffset + 32 * (i - 4))..], seed);
} }
acc = Xxh128Mix32b(acc, input.Slice(input.Length - 16), input.Slice(input.Length - 32), secret.Slice(SecretSizeMin - MidSizeLastOffset - 16), 0UL - seed); acc = Xxh128Mix32b(acc, input[^16..], input[^32..], secret[(SecretSizeMin - MidSizeLastOffset - 16)..], 0UL - seed);
Hash128 h128 = new Hash128 Hash128 h128 = new()
{ {
Low = acc.Low + acc.High, Low = acc.Low + acc.High,
High = acc.Low * Prime64_1 + acc.High * Prime64_4 + ((ulong)input.Length - seed) * Prime64_2 High = acc.Low * Prime64_1 + acc.High * Prime64_4 + ((ulong)input.Length - seed) * Prime64_2,
}; };
h128.Low = Xxh3Avalanche(h128.Low); h128.Low = Xxh3Avalanche(h128.Low);
h128.High = 0UL - Xxh3Avalanche(h128.High); h128.High = 0UL - Xxh3Avalanche(h128.High);
return h128; return h128;
} }
@@ -515,19 +526,19 @@ namespace Ryujinx.Common
{ {
return Xxh3Len0To16128b(input, secret, seed); return Xxh3Len0To16128b(input, secret, seed);
} }
else if (input.Length <= 128)
if (input.Length <= 128)
{ {
return Xxh3Len17To128128b(input, secret, seed); return Xxh3Len17To128128b(input, secret, seed);
} }
else if (input.Length <= 240)
if (input.Length <= 240)
{ {
return Xxh3Len129To240128b(input, secret, seed); return Xxh3Len129To240128b(input, secret, seed);
} }
else
{
return Xxh3HashLong128bInternal(input, secret); return Xxh3HashLong128bInternal(input, secret);
} }
}
public static Hash128 ComputeHash(ReadOnlySpan<byte> input) public static Hash128 ComputeHash(ReadOnlySpan<byte> input)
{ {

View File

@@ -51,6 +51,6 @@
/*!\brief An iterator reached the end of list. /*!\brief An iterator reached the end of list.
* *
*/ */
CodecListEnd CodecListEnd,
} }
} }

View File

@@ -20,7 +20,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common
{ {
10 => (ushort)Math.Clamp(val, 0, 1023), 10 => (ushort)Math.Clamp(val, 0, 1023),
12 => (ushort)Math.Clamp(val, 0, 4095), 12 => (ushort)Math.Clamp(val, 0, 4095),
_ => (ushort)Math.Clamp(val, 0, 255) _ => (ushort)Math.Clamp(val, 0, 255),
}; };
} }
@@ -46,6 +46,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common
private static int GetMsb(uint n) private static int GetMsb(uint n)
{ {
Debug.Assert(n != 0); Debug.Assert(n != 0);
return 31 ^ BitOperations.LeadingZeroCount(n); return 31 ^ BitOperations.LeadingZeroCount(n);
} }

View File

@@ -16,7 +16,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common
public bool InUse; public bool InUse;
} }
private PoolItem[] _pool = new PoolItem[PoolEntries]; private readonly PoolItem[] _pool = new PoolItem[PoolEntries];
public ArrayPtr<T> Allocate<T>(int length) where T : unmanaged public ArrayPtr<T> Allocate<T>(int length) where T : unmanaged
{ {

View File

@@ -9,7 +9,6 @@ using System.Diagnostics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Threading.Tasks; using System.Threading.Tasks;
using Mv = Ryujinx.Graphics.Nvdec.Vp9.Types.Mv;
namespace Ryujinx.Graphics.Nvdec.Vp9 namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
@@ -48,7 +47,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
case TxSize.Tx32x32: case TxSize.Tx32x32:
Idct.HighbdIdct32x32Add(dqcoeff.AsSpan(), dst16, stride, eob, xd.Bd); Idct.HighbdIdct32x32Add(dqcoeff.AsSpan(), dst16, stride, eob, xd.Bd);
break; break;
default: Debug.Assert(false, "Invalid transform size"); break; default:
Debug.Assert(false, "Invalid transform size");
break;
} }
} }
} }
@@ -62,11 +63,21 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
switch (txSize) switch (txSize)
{ {
case TxSize.Tx4x4: Idct.Idct4x4Add(dqcoeff.AsSpan(), dst, stride, eob); break; case TxSize.Tx4x4:
case TxSize.Tx8x8: Idct.Idct8x8Add(dqcoeff.AsSpan(), dst, stride, eob); break; Idct.Idct4x4Add(dqcoeff.AsSpan(), dst, stride, eob);
case TxSize.Tx16x16: Idct.Idct16x16Add(dqcoeff.AsSpan(), dst, stride, eob); break; break;
case TxSize.Tx32x32: Idct.Idct32x32Add(dqcoeff.AsSpan(), dst, stride, eob); break; case TxSize.Tx8x8:
default: Debug.Assert(false, "Invalid transform size"); return; Idct.Idct8x8Add(dqcoeff.AsSpan(), dst, stride, eob);
break;
case TxSize.Tx16x16:
Idct.Idct16x16Add(dqcoeff.AsSpan(), dst, stride, eob);
break;
case TxSize.Tx32x32:
Idct.Idct32x32Add(dqcoeff.AsSpan(), dst, stride, eob);
break;
default:
Debug.Assert(false, "Invalid transform size");
return;
} }
} }
} }
@@ -79,15 +90,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
if (txSize <= TxSize.Tx16x16 && eob <= 10) if (txSize <= TxSize.Tx16x16 && eob <= 10)
{ {
dqcoeff.AsSpan().Slice(0, 4 * (4 << (int)txSize)).Fill(0); dqcoeff.AsSpan()[..(4 * (4 << (int)txSize))].Clear();
} }
else if (txSize == TxSize.Tx32x32 && eob <= 34) else if (txSize == TxSize.Tx32x32 && eob <= 34)
{ {
dqcoeff.AsSpan().Slice(0, 256).Fill(0); dqcoeff.AsSpan()[..256].Clear();
} }
else else
{ {
dqcoeff.AsSpan().Slice(0, 16 << ((int)txSize << 1)).Fill(0); dqcoeff.AsSpan()[..(16 << ((int)txSize << 1))].Clear();
} }
} }
} }
@@ -127,7 +138,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
case TxSize.Tx32x32: case TxSize.Tx32x32:
Idct.HighbdIdct32x32Add(dqcoeff.AsSpan(), dst16, stride, eob, xd.Bd); Idct.HighbdIdct32x32Add(dqcoeff.AsSpan(), dst16, stride, eob, xd.Bd);
break; break;
default: Debug.Assert(false, "Invalid transform size"); break; default:
Debug.Assert(false, "Invalid transform size");
break;
} }
} }
} }
@@ -141,11 +154,21 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
switch (txSize) switch (txSize)
{ {
case TxSize.Tx4x4: Idct.Iht4x4Add(txType, dqcoeff.AsSpan(), dst, stride, eob); break; case TxSize.Tx4x4:
case TxSize.Tx8x8: Idct.Iht8x8Add(txType, dqcoeff.AsSpan(), dst, stride, eob); break; Idct.Iht4x4Add(txType, dqcoeff.AsSpan(), dst, stride, eob);
case TxSize.Tx16x16: Idct.Iht16x16Add(txType, dqcoeff.AsSpan(), dst, stride, eob); break; break;
case TxSize.Tx32x32: Idct.Idct32x32Add(dqcoeff.AsSpan(), dst, stride, eob); break; case TxSize.Tx8x8:
default: Debug.Assert(false, "Invalid transform size"); return; Idct.Iht8x8Add(txType, dqcoeff.AsSpan(), dst, stride, eob);
break;
case TxSize.Tx16x16:
Idct.Iht16x16Add(txType, dqcoeff.AsSpan(), dst, stride, eob);
break;
case TxSize.Tx32x32:
Idct.Idct32x32Add(dqcoeff.AsSpan(), dst, stride, eob);
break;
default:
Debug.Assert(false, "Invalid transform size");
return;
} }
} }
} }
@@ -158,15 +181,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
if (txType == TxType.DctDct && txSize <= TxSize.Tx16x16 && eob <= 10) if (txType == TxType.DctDct && txSize <= TxSize.Tx16x16 && eob <= 10)
{ {
dqcoeff.AsSpan().Slice(0, 4 * (4 << (int)txSize)).Fill(0); dqcoeff.AsSpan()[..(4 * (4 << (int)txSize))].Clear();
} }
else if (txSize == TxSize.Tx32x32 && eob <= 34) else if (txSize == TxSize.Tx32x32 && eob <= 34)
{ {
dqcoeff.AsSpan().Slice(0, 256).Fill(0); dqcoeff.AsSpan()[..256].Clear();
} }
else else
{ {
dqcoeff.AsSpan().Slice(0, 16 << ((int)txSize << 1)).Fill(0); dqcoeff.AsSpan()[..(16 << ((int)txSize << 1))].Clear();
} }
} }
} }
@@ -184,7 +207,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
PredictionMode mode = (plane == 0) ? mi.Mode : mi.UvMode; PredictionMode mode = (plane == 0) ? mi.Mode : mi.UvMode;
int dstOffset = 4 * row * pd.Dst.Stride + 4 * col; int dstOffset = 4 * row * pd.Dst.Stride + 4 * col;
byte* dst = &pd.Dst.Buf.ToPointer()[dstOffset]; byte* dst = &pd.Dst.Buf.ToPointer()[dstOffset];
Span<byte> dstSpan = pd.Dst.Buf.AsSpan().Slice(dstOffset); Span<byte> dstSpan = pd.Dst.Buf.AsSpan()[dstOffset..];
if (mi.SbType < BlockSize.Block8x8) if (mi.SbType < BlockSize.Block8x8)
{ {
@@ -223,7 +246,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
ref MacroBlockDPlane pd = ref xd.Plane[plane]; ref MacroBlockDPlane pd = ref xd.Plane[plane];
var sc = Luts.Vp9DefaultScanOrders[(int)txSize]; var sc = Luts.Vp9DefaultScanOrders[(int)txSize];
int eob = Detokenize.DecodeBlockTokens(ref twd, plane, sc, col, row, txSize, mi.SegmentId); int eob = Detokenize.DecodeBlockTokens(ref twd, plane, sc, col, row, txSize, mi.SegmentId);
Span<byte> dst = pd.Dst.Buf.AsSpan().Slice(4 * row * pd.Dst.Stride + 4 * col); Span<byte> dst = pd.Dst.Buf.AsSpan()[(4 * row * pd.Dst.Stride + 4 * col)..];
if (eob > 0) if (eob > 0)
{ {
@@ -589,9 +612,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
refr, refr,
xs, xs,
ys); ys);
return; return;
} }
} }
if (xd.CurBuf.HighBd) if (xd.CurBuf.HighBd)
{ {
ReconInter.HighbdInterPredictor( ReconInter.HighbdInterPredictor(
@@ -793,6 +818,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
xd.SetMiRowCol(ref tile, miRow, bh, miCol, bw, cm.MiRows, cm.MiCols); xd.SetMiRowCol(ref tile, miRow, bh, miCol, bw, cm.MiRows, cm.MiCols);
ReconInter.SetupDstPlanes(ref xd.Plane, ref xd.CurBuf, miRow, miCol); ReconInter.SetupDstPlanes(ref xd.Plane, ref xd.CurBuf, miRow, miCol);
return ref xd.Mi[0].Value; return ref xd.Mi[0].Value;
} }
@@ -928,8 +954,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// Update the partition context at the end notes. Set partition bits // Update the partition context at the end notes. Set partition bits
// of block sizes larger than the current one to be one, and partition // of block sizes larger than the current one to be one, and partition
// bits of smaller block sizes to be zero. // bits of smaller block sizes to be zero.
aboveCtx.Slice(0, bw).Fill(Luts.PartitionContextLookup[(int)subsize].Above); aboveCtx[..bw].Fill(Luts.PartitionContextLookup[(int)subsize].Above);
leftCtx.Slice(0, bw).Fill(Luts.PartitionContextLookup[(int)subsize].Left); leftCtx[..bw].Fill(Luts.PartitionContextLookup[(int)subsize].Left);
} }
private static PartitionType ReadPartition( private static PartitionType ReadPartition(
@@ -1030,7 +1056,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
DecodePartition(ref twd, ref cm, miRow + hbs, miCol, subsize, n8x8L2); DecodePartition(ref twd, ref cm, miRow + hbs, miCol, subsize, n8x8L2);
DecodePartition(ref twd, ref cm, miRow + hbs, miCol + hbs, subsize, n8x8L2); DecodePartition(ref twd, ref cm, miRow + hbs, miCol + hbs, subsize, n8x8L2);
break; break;
default: Debug.Assert(false, "Invalid partition type"); break; default:
Debug.Assert(false, "Invalid partition type");
break;
} }
} }
@@ -1134,7 +1162,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
int alignedCols = TileInfo.MiColsAlignedToSb(cm.MiCols); int alignedCols = TileInfo.MiColsAlignedToSb(cm.MiCols);
int tileCols = 1 << cm.Log2TileCols; int tileCols = 1 << cm.Log2TileCols;
int tileRows = 1 << cm.Log2TileRows; int tileRows = 1 << cm.Log2TileRows;
Array4<Array64<TileBuffer>> tileBuffers = new Array4<Array64<TileBuffer>>(); Array4<Array64<TileBuffer>> tileBuffers = new();
int tileRow, tileCol; int tileRow, tileCol;
int miRow, miCol; int miRow, miCol;
@@ -1168,7 +1196,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
for (tileRow = 0; tileRow < tileRows; ++tileRow) for (tileRow = 0; tileRow < tileRows; ++tileRow)
{ {
TileInfo tile = new TileInfo(); TileInfo tile = new();
tile.SetRow(ref cm, tileRow); tile.SetRow(ref cm, tileRow);
for (miRow = tile.MiRowStart; miRow < tile.MiRowEnd; miRow += Constants.MiBlockSize) for (miRow = tile.MiRowStart; miRow < tile.MiRowEnd; miRow += Constants.MiBlockSize)
{ {
@@ -1234,10 +1262,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} while (!tileData.Xd.Corrupted && ++n <= tileData.BufEnd); } while (!tileData.Xd.Corrupted && ++n <= tileData.BufEnd);
tileData.DataEnd = bitReaderEnd; tileData.DataEnd = bitReaderEnd;
return !tileData.Xd.Corrupted; return !tileData.Xd.Corrupted;
} }
public static unsafe ArrayPtr<byte> DecodeTilesMt(ref Vp9Common cm, ArrayPtr<byte> data, int maxThreads) public static ArrayPtr<byte> DecodeTilesMt(ref Vp9Common cm, ArrayPtr<byte> data, int maxThreads)
{ {
ArrayPtr<byte> bitReaderEnd = ArrayPtr<byte>.Null; ArrayPtr<byte> bitReaderEnd = ArrayPtr<byte>.Null;
@@ -1250,8 +1279,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
Debug.Assert(tileCols <= (1 << 6)); Debug.Assert(tileCols <= (1 << 6));
Debug.Assert(tileRows == 1); Debug.Assert(tileRows == 1);
cm.AboveContext.AsSpan().Fill(0); cm.AboveContext.AsSpan().Clear();
cm.AboveSegContext.AsSpan().Fill(0); cm.AboveSegContext.AsSpan().Clear();
for (n = 0; n < numWorkers; ++n) for (n = 0; n < numWorkers; ++n)
{ {
@@ -1262,17 +1291,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
tileData.Counts = new Vp9BackwardUpdates(); tileData.Counts = new Vp9BackwardUpdates();
} }
Array64<TileBuffer> tileBuffers = new Array64<TileBuffer>(); Array64<TileBuffer> tileBuffers = new();
GetTileBuffers(ref cm, data, tileCols, ref tileBuffers); GetTileBuffers(ref cm, data, tileCols, ref tileBuffers);
tileBuffers.AsSpan().Slice(0, tileCols).Sort(CompareTileBuffers); tileBuffers.AsSpan()[..tileCols].Sort(CompareTileBuffers);
if (numWorkers == tileCols) if (numWorkers == tileCols)
{ {
TileBuffer largest = tileBuffers[0]; TileBuffer largest = tileBuffers[0];
Span<TileBuffer> buffers = tileBuffers.AsSpan(); Span<TileBuffer> buffers = tileBuffers.AsSpan();
buffers.Slice(1).CopyTo(buffers.Slice(0, tileBuffers.Length - 1)); buffers[1..].CopyTo(buffers[..(tileBuffers.Length - 1)]);
tileBuffers[tileCols - 1] = largest; tileBuffers[tileCols - 1] = largest;
} }
else else
@@ -1307,9 +1336,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
bufStart += count; bufStart += count;
} }
Ptr<Vp9Common> cmPtr = new Ptr<Vp9Common>(ref cm); Ptr<Vp9Common> cmPtr = new(ref cm);
Parallel.For(0, numWorkers, (n) => Parallel.For(0, numWorkers, n =>
{ {
ref TileWorkerData tileData = ref cmPtr.Value.TileWorkerData[n + totalTiles]; ref TileWorkerData tileData = ref cmPtr.Value.TileWorkerData[n + totalTiles];
@@ -1335,6 +1364,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
Debug.Assert(!bitReaderEnd.IsNull || cm.Mb.Corrupted); Debug.Assert(!bitReaderEnd.IsNull || cm.Mb.Corrupted);
return bitReaderEnd; return bitReaderEnd;
} }

View File

@@ -5,8 +5,6 @@ using Ryujinx.Graphics.Video;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using Mv = Ryujinx.Graphics.Nvdec.Vp9.Types.Mv;
using MvRef = Ryujinx.Graphics.Nvdec.Vp9.Types.MvRef;
namespace Ryujinx.Graphics.Nvdec.Vp9 namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
@@ -61,10 +59,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
switch (maxTxSize) switch (maxTxSize)
{ {
case TxSize.Tx8x8: return fc.Tx8x8Prob[ctx].AsSpan(); case TxSize.Tx8x8:
case TxSize.Tx16x16: return fc.Tx16x16Prob[ctx].AsSpan(); return fc.Tx8x8Prob[ctx].AsSpan();
case TxSize.Tx32x32: return fc.Tx32x32Prob[ctx].AsSpan(); case TxSize.Tx16x16:
default: Debug.Assert(false, "Invalid maxTxSize."); return ReadOnlySpan<byte>.Empty; return fc.Tx16x16Prob[ctx].AsSpan();
case TxSize.Tx32x32:
return fc.Tx32x32Prob[ctx].AsSpan();
default:
Debug.Assert(false, "Invalid maxTxSize.");
return ReadOnlySpan<byte>.Empty;
} }
} }
@@ -72,10 +76,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
switch (maxTxSize) switch (maxTxSize)
{ {
case TxSize.Tx8x8: return counts.Tx8x8[ctx].AsSpan(); case TxSize.Tx8x8:
case TxSize.Tx16x16: return counts.Tx16x16[ctx].AsSpan(); return counts.Tx8x8[ctx].AsSpan();
case TxSize.Tx32x32: return counts.Tx32x32[ctx].AsSpan(); case TxSize.Tx16x16:
default: Debug.Assert(false, "Invalid maxTxSize."); return Span<uint>.Empty; return counts.Tx16x16[ctx].AsSpan();
case TxSize.Tx32x32:
return counts.Tx32x32[ctx].AsSpan();
default:
Debug.Assert(false, "Invalid maxTxSize.");
return Span<uint>.Empty;
} }
} }
@@ -110,11 +120,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
return ReadSelectedTxSize(ref cm, ref xd, maxTxSize, ref r); return ReadSelectedTxSize(ref cm, ref xd, maxTxSize, ref r);
} }
else
{
return (TxSize)Math.Min((int)maxTxSize, (int)Luts.TxModeToBiggestTxSize[(int)txMode]); 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)
{ {
@@ -129,6 +137,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
Debug.Assert(segmentId >= 0 && segmentId < Constants.MaxSegments); Debug.Assert(segmentId >= 0 && segmentId < Constants.MaxSegments);
return segmentId; return segmentId;
} }
@@ -179,11 +188,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
if (!seg.UpdateMap) if (!seg.UpdateMap)
{ {
CopySegmentId(ref cm, cm.LastFrameSegMap, cm.CurrentFrameSegMap, miOffset, xMis, yMis); CopySegmentId(ref cm, cm.LastFrameSegMap, cm.CurrentFrameSegMap, miOffset, xMis, yMis);
return 0; return 0;
} }
segmentId = ReadSegmentId(ref r, ref cm.Fc.Value.SegTreeProb); 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; return segmentId;
} }
@@ -213,6 +224,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
if (!seg.UpdateMap) if (!seg.UpdateMap)
{ {
CopySegmentId(ref cm, cm.LastFrameSegMap, cm.CurrentFrameSegMap, miOffset, xMis, yMis); CopySegmentId(ref cm, cm.LastFrameSegMap, cm.CurrentFrameSegMap, miOffset, xMis, yMis);
return predictedSegmentId; return predictedSegmentId;
} }
@@ -227,6 +239,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
segmentId = ReadSegmentId(ref r, ref cm.Fc.Value.SegTreeProb); 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; return segmentId;
} }
@@ -236,8 +249,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
return 1; return 1;
} }
else
{
int ctx = xd.GetSkipContext(); int ctx = xd.GetSkipContext();
int skip = r.Read(cm.Fc.Value.SkipProb[ctx]); int skip = r.Read(cm.Fc.Value.SkipProb[ctx]);
if (!xd.Counts.IsNull) if (!xd.Counts.IsNull)
@@ -247,7 +259,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
return skip; return skip;
} }
}
private static int ReadMvComponent(ref Reader r, ref Vp9EntropyProbs fc, int mvcomp, bool usehp) private static int ReadMvComponent(ref Reader r, ref Vp9EntropyProbs fc, int mvcomp, bool usehp)
{ {
@@ -284,6 +295,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// Result // Result
mag += ((d << 3) | (fr << 1) | hp) + 1; mag += ((d << 3) | (fr << 1) | hp) + 1;
return sign ? -mag : mag; return sign ? -mag : mag;
} }
@@ -297,7 +309,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
MvJointType jointType = (MvJointType)r.ReadTree(Luts.Vp9MvJointTree, fc.Joints.AsSpan()); MvJointType jointType = (MvJointType)r.ReadTree(Luts.Vp9MvJointTree, fc.Joints.AsSpan());
bool useHP = allowHP && refr.UseMvHp(); bool useHP = allowHP && refr.UseMvHp();
Mv diff = new Mv(); Mv diff = new();
if (Mv.MvJointVertical(jointType)) if (Mv.MvJointVertical(jointType))
{ {
@@ -328,11 +340,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
return mode; // SingleReference or CompoundReference return mode; // SingleReference or CompoundReference
} }
else
{
return cm.ReferenceMode; return cm.ReferenceMode;
} }
}
// Read the referncence frame // Read the referncence frame
private static void ReadRefFrames( private static void ReadRefFrames(
@@ -434,7 +444,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
mi.Bmi[0].Mode = mi.Bmi[1].Mode = ReadIntraModeY(ref cm, ref xd, ref r, 0); 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); mi.Bmi[2].Mode = mi.Bmi[3].Mode = mi.Mode = ReadIntraModeY(ref cm, ref xd, ref r, 0);
break; break;
default: mi.Mode = ReadIntraModeY(ref cm, ref xd, ref r, Luts.SizeGroupLookup[(int)bsize]); break; default:
mi.Mode = ReadIntraModeY(ref cm, ref xd, ref r, Luts.SizeGroupLookup[(int)bsize]);
break;
} }
mi.UvMode = ReadIntraModeUv(ref cm, ref xd, ref r, (byte)mi.Mode); mi.UvMode = ReadIntraModeUv(ref cm, ref xd, ref r, (byte)mi.Mode);
@@ -503,7 +515,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
ZeroMvPair(ref mv); ZeroMvPair(ref mv);
break; break;
} }
default: return false; default:
return false;
} }
return ret; return ret;
} }
@@ -514,8 +527,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
return cm.Seg.GetSegData(segmentId, SegLvlFeatures.SegLvlRefFrame) != Constants.IntraFrame; return cm.Seg.GetSegData(segmentId, SegLvlFeatures.SegLvlRefFrame) != Constants.IntraFrame;
} }
else
{
int ctx = xd.GetIntraInterContext(); int ctx = xd.GetIntraInterContext();
bool isInter = r.Read(cm.Fc.Value.IntraInterProb[ctx]) != 0; bool isInter = r.Read(cm.Fc.Value.IntraInterProb[ctx]) != 0;
if (!xd.Counts.IsNull) if (!xd.Counts.IsNull)
@@ -525,7 +537,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
return isInter; return isInter;
} }
}
private static void DecFindBestRefMvs(bool allowHP, Span<Mv> mvlist, ref Mv bestMv, int refmvCount) private static void DecFindBestRefMvs(bool allowHP, Span<Mv> mvlist, ref Mv bestMv, int refmvCount)
{ {
@@ -547,6 +558,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
mvRefList[refMvCount] = mv; mvRefList[refMvCount] = mv;
refMvCount++; refMvCount++;
return true; return true;
} }
} }
@@ -605,7 +617,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// This function searches the neighborhood of a given MB/SB // This function searches the neighborhood of a given MB/SB
// to try and find candidate reference vectors. // to try and find candidate reference vectors.
private static unsafe int DecFindMvRefs( private static int DecFindMvRefs(
ref Vp9Common cm, ref Vp9Common cm,
ref MacroBlockD xd, ref MacroBlockD xd,
PredictionMode mode, PredictionMode mode,
@@ -627,7 +639,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
bool earlyBreak = mode != PredictionMode.NearMv; bool earlyBreak = mode != PredictionMode.NearMv;
// Blank the reference vector list // Blank the reference vector list
mvRefList.Slice(0, Constants.MaxMvRefCandidates).Fill(new Mv()); mvRefList[..Constants.MaxMvRefCandidates].Clear();
i = 0; i = 0;
if (isSub8X8 != 0) if (isSub8X8 != 0)
@@ -805,7 +817,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
switch (block) switch (block)
{ {
case 0: bestSub8x8 = mvList[refmvCount - 1]; break; case 0:
bestSub8x8 = mvList[refmvCount - 1];
break;
case 1: case 1:
case 2: case 2:
if (bMode == PredictionMode.NearestMv) if (bMode == PredictionMode.NearestMv)
@@ -848,7 +862,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
} }
break; break;
default: Debug.Assert(false, "Invalid block index."); break; default:
Debug.Assert(false, "Invalid block index.");
break;
} }
} }
@@ -883,7 +899,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
BlockSize bsize = mi.SbType; BlockSize bsize = mi.SbType;
bool allowHP = cm.AllowHighPrecisionMv; bool allowHP = cm.AllowHighPrecisionMv;
Array2<Mv> bestRefMvs = new Array2<Mv>(); Array2<Mv> bestRefMvs = new();
int refr, isCompound; int refr, isCompound;
byte interModeCtx; byte interModeCtx;
Span<Position> mvRefSearch = Luts.MvRefBlocks[(int)bsize]; Span<Position> mvRefSearch = Luts.MvRefBlocks[(int)bsize];
@@ -898,6 +914,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
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.CodecUnsupBitstream, "Invalid usage of segement feature on small blocks");
return; return;
} }
} }
@@ -940,11 +957,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
int num4X4H = 1 << xd.BmodeBlocksHl; int num4X4H = 1 << xd.BmodeBlocksHl;
int idx, idy; int idx, idy;
PredictionMode bMode = 0; PredictionMode bMode = 0;
Array2<Mv> bestSub8x8 = new Array2<Mv>(); Array2<Mv> bestSub8x8 = new();
const uint invalidMv = 0x80008000; const uint InvalidMv = 0x80008000;
// Initialize the 2nd element as even though it won't be used meaningfully // Initialize the 2nd element as even though it won't be used meaningfully
// if isCompound is false. // 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 (idy = 0; idy < 2; idy += num4X4H)
{ {
for (idx = 0; idx < 2; idx += num4X4W) for (idx = 0; idx < 2; idx += num4X4W)
@@ -1026,12 +1043,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
return leftMi.Value.GetYMode(b + 1); return leftMi.Value.GetYMode(b + 1);
} }
else
{
Debug.Assert(b == 1 || b == 3); Debug.Assert(b == 1 || b == 3);
return curMi.Value.Bmi[b - 1].Mode; return curMi.Value.Bmi[b - 1].Mode;
} }
}
private static PredictionMode AboveBlockMode(Ptr<ModeInfo> curMi, Ptr<ModeInfo> aboveMi, int b) private static PredictionMode AboveBlockMode(Ptr<ModeInfo> curMi, Ptr<ModeInfo> aboveMi, int b)
{ {
@@ -1044,12 +1060,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
return aboveMi.Value.GetYMode(b + 2); return aboveMi.Value.GetYMode(b + 2);
} }
else
{
Debug.Assert(b == 2 || b == 3); Debug.Assert(b == 2 || b == 3);
return curMi.Value.Bmi[b - 2].Mode; return curMi.Value.Bmi[b - 2].Mode;
} }
}
private static ReadOnlySpan<byte> GetYModeProbs( private static ReadOnlySpan<byte> GetYModeProbs(
ref Vp9EntropyProbs fc, ref Vp9EntropyProbs fc,
@@ -1060,6 +1075,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
PredictionMode above = AboveBlockMode(mi, aboveMi, block); PredictionMode above = AboveBlockMode(mi, aboveMi, block);
PredictionMode left = LeftBlockMode(mi, leftMi, block); PredictionMode left = LeftBlockMode(mi, leftMi, block);
return fc.KfYModeProb[(int)above][(int)left].AsSpan(); return fc.KfYModeProb[(int)above][(int)left].AsSpan();
} }

View File

@@ -3,7 +3,6 @@ using Ryujinx.Graphics.Nvdec.Vp9.Common;
using Ryujinx.Graphics.Nvdec.Vp9.Types; using Ryujinx.Graphics.Nvdec.Vp9.Types;
using Ryujinx.Graphics.Video; using Ryujinx.Graphics.Video;
using System; using System;
using Vp9MvRef = Ryujinx.Graphics.Video.Vp9MvRef;
namespace Ryujinx.Graphics.Nvdec.Vp9 namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
@@ -11,7 +10,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
public bool IsHardwareAccelerated => false; public bool IsHardwareAccelerated => false;
private readonly MemoryAllocator _allocator = new MemoryAllocator(); private readonly MemoryAllocator _allocator = new();
public ISurface CreateSurface(int width, int height) => new Surface(width, height); public ISurface CreateSurface(int width, int height) => new Surface(width, height);
@@ -20,7 +19,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
Constants.EightTapSmooth, Constants.EightTapSmooth,
Constants.EightTap, Constants.EightTap,
Constants.EightTapSharp, Constants.EightTapSharp,
Constants.Bilinear Constants.Bilinear,
}; };
public unsafe bool Decode( public unsafe bool Decode(
@@ -30,24 +29,25 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
ReadOnlySpan<Vp9MvRef> mvsIn, ReadOnlySpan<Vp9MvRef> mvsIn,
Span<Vp9MvRef> mvsOut) Span<Vp9MvRef> mvsOut)
{ {
Vp9Common cm = new Vp9Common(); Vp9Common cm = new()
{
FrameType = pictureInfo.IsKeyFrame ? FrameType.KeyFrame : FrameType.InterFrame,
IntraOnly = pictureInfo.IntraOnly,
cm.FrameType = pictureInfo.IsKeyFrame ? FrameType.KeyFrame : FrameType.InterFrame; Width = output.Width,
cm.IntraOnly = pictureInfo.IntraOnly; Height = output.Height,
SubsamplingX = 1,
SubsamplingY = 1,
cm.Width = output.Width; UsePrevFrameMvs = pictureInfo.UsePrevInFindMvRefs,
cm.Height = output.Height;
cm.SubsamplingX = 1;
cm.SubsamplingY = 1;
cm.UsePrevFrameMvs = pictureInfo.UsePrevInFindMvRefs; RefFrameSignBias = pictureInfo.RefFrameSignBias,
cm.RefFrameSignBias = pictureInfo.RefFrameSignBias; BaseQindex = pictureInfo.BaseQIndex,
YDcDeltaQ = pictureInfo.YDcDeltaQ,
cm.BaseQindex = pictureInfo.BaseQIndex; UvAcDeltaQ = pictureInfo.UvAcDeltaQ,
cm.YDcDeltaQ = pictureInfo.YDcDeltaQ; UvDcDeltaQ = pictureInfo.UvDcDeltaQ,
cm.UvAcDeltaQ = pictureInfo.UvAcDeltaQ; };
cm.UvDcDeltaQ = pictureInfo.UvDcDeltaQ;
cm.Mb.Lossless = pictureInfo.Lossless; cm.Mb.Lossless = pictureInfo.Lossless;
cm.Mb.Bd = 8; cm.Mb.Bd = 8;

View File

@@ -17,9 +17,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
private static int GetCoefContext(ReadOnlySpan<short> neighbors, ReadOnlySpan<byte> tokenCache, int c) private static int GetCoefContext(ReadOnlySpan<short> neighbors, ReadOnlySpan<byte> tokenCache, int c)
{ {
const int maxNeighbors = 2; const int MaxNeighbors = 2;
return (1 + tokenCache[neighbors[maxNeighbors * c + 0]] + tokenCache[neighbors[maxNeighbors * c + 1]]) >> 1; return (1 + tokenCache[neighbors[MaxNeighbors * c + 0]] + tokenCache[neighbors[MaxNeighbors * c + 1]]) >> 1;
} }
private static int ReadCoeff( private static int ReadCoeff(
@@ -57,13 +57,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
int band, c = 0; int band, c = 0;
ref Array6<Array6<Array3<byte>>> coefProbs = ref fc.CoefProbs[(int)txSize][(int)type][refr]; ref Array6<Array6<Array3<byte>>> coefProbs = ref fc.CoefProbs[(int)txSize][(int)type][refr];
Span<byte> tokenCache = stackalloc byte[32 * 32]; Span<byte> tokenCache = stackalloc byte[32 * 32];
ReadOnlySpan<byte> bandTranslate = Luts.get_band_translate(txSize); ReadOnlySpan<byte> bandTranslate = Luts.GetBandTranslate(txSize);
int dqShift = (txSize == TxSize.Tx32x32) ? 1 : 0; int dqShift = (txSize == TxSize.Tx32x32) ? 1 : 0;
int v; int v;
short dqv = dq[0]; short dqv = dq[0];
ReadOnlySpan<byte> cat6Prob = (xd.Bd == 12) ReadOnlySpan<byte> cat6Prob = (xd.Bd == 12)
? Luts.Vp9Cat6ProbHigh12 ? Luts.Vp9Cat6ProbHigh12
: (xd.Bd == 10) ? Luts.Vp9Cat6ProbHigh12.Slice(2) : Luts.Vp9Cat6Prob; : (xd.Bd == 10) ? Luts.Vp9Cat6ProbHigh12[2..] : Luts.Vp9Cat6Prob;
int cat6Bits = (xd.Bd == 12) ? 18 : (xd.Bd == 10) ? 16 : 14; int cat6Bits = (xd.Bd == 12) ? 18 : (xd.Bd == 10) ? 16 : 14;
// Keep value, range, and count as locals. The compiler produces better // Keep value, range, and count as locals. The compiler produces better
// results with the locals than using r directly. // results with the locals than using r directly.
@@ -75,7 +75,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
int val = -1; int val = -1;
band = bandTranslate[0]; band = bandTranslate[0];
bandTranslate = bandTranslate.Slice(1); bandTranslate = bandTranslate[1..];
ref Array3<byte> prob = ref coefProbs[band][ctx]; ref Array3<byte> prob = ref coefProbs[band][ctx];
if (!xd.Counts.IsNull) if (!xd.Counts.IsNull)
{ {
@@ -107,11 +107,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
r.Value = value; r.Value = value;
r.Range = range; r.Range = range;
r.Count = count; r.Count = count;
return c; // Zero tokens at the end (no eob token) return c; // Zero tokens at the end (no eob token)
} }
ctx = GetCoefContext(nb, tokenCache, c); ctx = GetCoefContext(nb, tokenCache, c);
band = bandTranslate[0]; band = bandTranslate[0];
bandTranslate = bandTranslate.Slice(1); bandTranslate = bandTranslate[1..];
prob = ref coefProbs[band][ctx]; prob = ref coefProbs[band][ctx];
} }
@@ -196,6 +197,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
r.Value = value; r.Value = value;
r.Range = range; r.Range = range;
r.Count = count; r.Count = count;
return c; return c;
} }
@@ -236,8 +238,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
ref MacroBlockDPlane pd = ref xd.Plane[plane]; ref MacroBlockDPlane pd = ref xd.Plane[plane];
ref Array2<short> dequant = ref pd.SegDequant[segId]; ref Array2<short> dequant = ref pd.SegDequant[segId];
int eob; int eob;
Span<sbyte> a = pd.AboveContext.AsSpan().Slice(x); Span<sbyte> a = pd.AboveContext.AsSpan()[x..];
Span<sbyte> l = pd.LeftContext.AsSpan().Slice(y); Span<sbyte> l = pd.LeftContext.AsSpan()[y..];
int ctx; int ctx;
int ctxShiftA = 0; int ctxShiftA = 0;
int ctxShiftL = 0; int ctxShiftL = 0;

View File

@@ -117,6 +117,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
if (Sse41.IsSupported && UseIntrinsics && xStepQ4 == 1 << SubpelBits) if (Sse41.IsSupported && UseIntrinsics && xStepQ4 == 1 << SubpelBits)
{ {
ConvolveHorizSse41(src, srcStride, dst, dstStride, xFilters, x0Q4, w, h); ConvolveHorizSse41(src, srcStride, dst, dstStride, xFilters, x0Q4, w, h);
return; return;
} }
@@ -261,6 +262,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
if (Avx2.IsSupported && UseIntrinsics && yStepQ4 == 1 << SubpelBits) if (Avx2.IsSupported && UseIntrinsics && yStepQ4 == 1 << SubpelBits)
{ {
ConvolveVertAvx2(src, srcStride, dst, dstStride, yFilters, y0Q4, w, h); ConvolveVertAvx2(src, srcStride, dst, dstStride, yFilters, y0Q4, w, h);
return; return;
} }

View File

@@ -35,6 +35,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
// of this range for invalid/corrupt VP9 streams. // of this range for invalid/corrupt VP9 streams.
Debug.Assert(short.MinValue <= input); Debug.Assert(short.MinValue <= input);
Debug.Assert(input <= short.MaxValue); Debug.Assert(input <= short.MaxValue);
return input; return input;
} }
@@ -70,6 +71,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
public static byte ClipPixelAdd(byte dest, long trans) public static byte ClipPixelAdd(byte dest, long trans)
{ {
trans = WrapLow(trans); trans = WrapLow(trans);
return BitUtils.ClipPixel(dest + (int)trans); return BitUtils.ClipPixel(dest + (int)trans);
} }
@@ -77,6 +79,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
public static ushort HighbdClipPixelAdd(ushort dest, long trans, int bd) public static ushort HighbdClipPixelAdd(ushort dest, long trans, int bd)
{ {
trans = HighbdWrapLow(trans, bd); trans = HighbdWrapLow(trans, bd);
return BitUtils.ClipPixelHighbd(dest + (int)trans, bd); return BitUtils.ClipPixelHighbd(dest + (int)trans, bd);
} }
@@ -84,6 +87,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
private static long DctConstRoundShift(long input) private static long DctConstRoundShift(long input)
{ {
long rv = BitUtils.RoundPowerOfTwo(input, DctConstBits); long rv = BitUtils.RoundPowerOfTwo(input, DctConstBits);
return rv; return rv;
} }
@@ -115,8 +119,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
op[1] = WrapLow(b1); op[1] = WrapLow(b1);
op[2] = WrapLow(c1); op[2] = WrapLow(c1);
op[3] = WrapLow(d1); op[3] = WrapLow(d1);
ip = ip.Slice(4); ip = ip[4..];
op = op.Slice(4); op = op[4..];
} }
Span<int> ip2 = output; Span<int> ip2 = output;
@@ -138,8 +142,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
dest[stride * 2] = ClipPixelAdd(dest[stride * 2], WrapLow(c1)); dest[stride * 2] = ClipPixelAdd(dest[stride * 2], WrapLow(c1));
dest[stride * 3] = ClipPixelAdd(dest[stride * 3], WrapLow(d1)); dest[stride * 3] = ClipPixelAdd(dest[stride * 3], WrapLow(d1));
ip2 = ip2.Slice(1); ip2 = ip2[1..];
dest = dest.Slice(1); dest = dest[1..];
} }
} }
@@ -167,8 +171,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
dest[stride * 1] = ClipPixelAdd(dest[stride * 1], e1); dest[stride * 1] = ClipPixelAdd(dest[stride * 1], e1);
dest[stride * 2] = ClipPixelAdd(dest[stride * 2], e1); dest[stride * 2] = ClipPixelAdd(dest[stride * 2], e1);
dest[stride * 3] = ClipPixelAdd(dest[stride * 3], e1); dest[stride * 3] = ClipPixelAdd(dest[stride * 3], e1);
ip2 = ip2.Slice(1); ip2 = ip2[1..];
dest = dest.Slice(1); dest = dest[1..];
} }
} }
@@ -182,7 +186,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
if ((x0 | x1 | x2 | x3) == 0) if ((x0 | x1 | x2 | x3) == 0)
{ {
output.Slice(0, 4).Fill(0); output[..4].Clear();
return; return;
} }
@@ -247,8 +252,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
for (i = 0; i < 4; ++i) for (i = 0; i < 4; ++i)
{ {
Idct4(input, outptr); Idct4(input, outptr);
input = input.Slice(4); input = input[4..];
outptr = outptr.Slice(4); outptr = outptr[4..];
} }
// Columns // Columns
@@ -282,7 +287,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
dest[1] = ClipPixelAdd(dest[1], a1); dest[1] = ClipPixelAdd(dest[1], a1);
dest[2] = ClipPixelAdd(dest[2], a1); dest[2] = ClipPixelAdd(dest[2], a1);
dest[3] = ClipPixelAdd(dest[3], a1); dest[3] = ClipPixelAdd(dest[3], a1);
dest = dest.Slice(stride); dest = dest[stride..];
} }
} }
@@ -300,7 +305,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
if ((x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7) == 0) if ((x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7) == 0)
{ {
output.Slice(0, 8).Fill(0); output[..8].Clear();
return; return;
} }
@@ -434,8 +440,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
for (i = 0; i < 8; ++i) for (i = 0; i < 8; ++i)
{ {
Idct8(input, outptr); Idct8(input, outptr);
input = input.Slice(8); input = input[8..];
outptr = outptr.Slice(8); outptr = outptr[8..];
} }
// Then transform columns // Then transform columns
@@ -464,15 +470,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Span<int> tempIn = stackalloc int[8]; Span<int> tempIn = stackalloc int[8];
Span<int> tempOut = stackalloc int[8]; Span<int> tempOut = stackalloc int[8];
output.Fill(0); output.Clear();
// First transform rows // First transform rows
// Only first 4 row has non-zero coefs // Only first 4 row has non-zero coefs
for (i = 0; i < 4; ++i) for (i = 0; i < 4; ++i)
{ {
Idct8(input, outptr); Idct8(input, outptr);
input = input.Slice(8); input = input[8..];
outptr = outptr.Slice(8); outptr = outptr[8..];
} }
// Then transform columns // Then transform columns
@@ -506,7 +512,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
dest[i] = ClipPixelAdd(dest[i], a1); dest[i] = ClipPixelAdd(dest[i], a1);
} }
dest = dest.Slice(stride); dest = dest[stride..];
} }
} }
@@ -533,7 +539,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
if ((x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | x10 | x11 | x12 | x13 | x14 | x15) == 0) if ((x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | x10 | x11 | x12 | x13 | x14 | x15) == 0)
{ {
output.Slice(0, 16).Fill(0); output[..16].Clear();
return; return;
} }
@@ -860,8 +867,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
for (i = 0; i < 16; ++i) for (i = 0; i < 16; ++i)
{ {
Idct16(input, outptr); Idct16(input, outptr);
input = input.Slice(16); input = input[16..];
outptr = outptr.Slice(16); outptr = outptr[16..];
} }
// Then transform columns // Then transform columns
@@ -889,15 +896,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Span<int> tempIn = stackalloc int[16]; Span<int> tempIn = stackalloc int[16];
Span<int> tempOut = stackalloc int[16]; Span<int> tempOut = stackalloc int[16];
output.Fill(0); output.Clear();
// First transform rows. Since all non-zero dct coefficients are in // First transform rows. Since all non-zero dct coefficients are in
// upper-left 8x8 area, we only need to calculate first 8 rows here. // upper-left 8x8 area, we only need to calculate first 8 rows here.
for (i = 0; i < 8; ++i) for (i = 0; i < 8; ++i)
{ {
Idct16(input, outptr); Idct16(input, outptr);
input = input.Slice(16); input = input[16..];
outptr = outptr.Slice(16); outptr = outptr[16..];
} }
// Then transform columns // Then transform columns
@@ -925,15 +932,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Span<int> tempIn = stackalloc int[16]; Span<int> tempIn = stackalloc int[16];
Span<int> tempOut = stackalloc int[16]; Span<int> tempOut = stackalloc int[16];
output.Fill(0); output.Clear();
// First transform rows. Since all non-zero dct coefficients are in // First transform rows. Since all non-zero dct coefficients are in
// upper-left 4x4 area, we only need to calculate first 4 rows here. // upper-left 4x4 area, we only need to calculate first 4 rows here.
for (i = 0; i < 4; ++i) for (i = 0; i < 4; ++i)
{ {
Idct16(input, outptr); Idct16(input, outptr);
input = input.Slice(16); input = input[16..];
outptr = outptr.Slice(16); outptr = outptr[16..];
} }
// Then transform columns // Then transform columns
@@ -967,7 +974,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
dest[i] = ClipPixelAdd(dest[i], a1); dest[i] = ClipPixelAdd(dest[i], a1);
} }
dest = dest.Slice(stride); dest = dest[stride..];
} }
} }
@@ -1365,11 +1372,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
} }
else else
{ {
outptr.Slice(0, 32).Fill(0); outptr[..32].Clear();
} }
input = input.Slice(32); input = input[32..];
outptr = outptr.Slice(32); outptr = outptr[32..];
} }
// Columns // Columns
@@ -1397,15 +1404,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Span<int> tempIn = stackalloc int[32]; Span<int> tempIn = stackalloc int[32];
Span<int> tempOut = stackalloc int[32]; Span<int> tempOut = stackalloc int[32];
output.Fill(0); output.Clear();
// Rows // Rows
// Only upper-left 16x16 has non-zero coeff // Only upper-left 16x16 has non-zero coeff
for (i = 0; i < 16; ++i) for (i = 0; i < 16; ++i)
{ {
Idct32(input, outptr); Idct32(input, outptr);
input = input.Slice(32); input = input[32..];
outptr = outptr.Slice(32); outptr = outptr[32..];
} }
// Columns // Columns
@@ -1433,15 +1440,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Span<int> tempIn = stackalloc int[32]; Span<int> tempIn = stackalloc int[32];
Span<int> tempOut = stackalloc int[32]; Span<int> tempOut = stackalloc int[32];
output.Fill(0); output.Clear();
// Rows // Rows
// Only upper-left 8x8 has non-zero coeff // Only upper-left 8x8 has non-zero coeff
for (i = 0; i < 8; ++i) for (i = 0; i < 8; ++i)
{ {
Idct32(input, outptr); Idct32(input, outptr);
input = input.Slice(32); input = input[32..];
outptr = outptr.Slice(32); outptr = outptr[32..];
} }
// Columns // Columns
@@ -1476,7 +1483,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
dest[i] = ClipPixelAdd(dest[i], a1); dest[i] = ClipPixelAdd(dest[i], a1);
} }
dest = dest.Slice(stride); dest = dest[stride..];
} }
} }
@@ -1508,8 +1515,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
op[1] = HighbdWrapLow(b1, bd); op[1] = HighbdWrapLow(b1, bd);
op[2] = HighbdWrapLow(c1, bd); op[2] = HighbdWrapLow(c1, bd);
op[3] = HighbdWrapLow(d1, bd); op[3] = HighbdWrapLow(d1, bd);
ip = ip.Slice(4); ip = ip[4..];
op = op.Slice(4); op = op[4..];
} }
ReadOnlySpan<int> ip2 = output; ReadOnlySpan<int> ip2 = output;
@@ -1531,8 +1538,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
dest[stride * 2] = HighbdClipPixelAdd(dest[stride * 2], HighbdWrapLow(c1, bd), bd); dest[stride * 2] = HighbdClipPixelAdd(dest[stride * 2], HighbdWrapLow(c1, bd), bd);
dest[stride * 3] = HighbdClipPixelAdd(dest[stride * 3], HighbdWrapLow(d1, bd), bd); dest[stride * 3] = HighbdClipPixelAdd(dest[stride * 3], HighbdWrapLow(d1, bd), bd);
ip2 = ip2.Slice(1); ip2 = ip2[1..];
dest = dest.Slice(1); dest = dest[1..];
} }
} }
@@ -1560,8 +1567,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
dest[stride * 1] = HighbdClipPixelAdd(dest[stride * 1], e1, bd); dest[stride * 1] = HighbdClipPixelAdd(dest[stride * 1], e1, bd);
dest[stride * 2] = HighbdClipPixelAdd(dest[stride * 2], e1, bd); dest[stride * 2] = HighbdClipPixelAdd(dest[stride * 2], e1, bd);
dest[stride * 3] = HighbdClipPixelAdd(dest[stride * 3], e1, bd); dest[stride * 3] = HighbdClipPixelAdd(dest[stride * 3], e1, bd);
ip2 = ip2.Slice(1); ip2 = ip2[1..];
dest = dest.Slice(1); dest = dest[1..];
} }
} }
@@ -1576,13 +1583,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
if (DetectInvalidHighbdInput(input, 4) != 0) if (DetectInvalidHighbdInput(input, 4) != 0)
{ {
Debug.Assert(false, "invalid highbd txfm input"); Debug.Assert(false, "invalid highbd txfm input");
output.Slice(0, 4).Fill(0); output[..4].Clear();
return; return;
} }
if ((x0 | x1 | x2 | x3) == 0) if ((x0 | x1 | x2 | x3) == 0)
{ {
output.Slice(0, 4).Fill(0); output[..4].Clear();
return; return;
} }
@@ -1619,7 +1628,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
if (DetectInvalidHighbdInput(input, 4) != 0) if (DetectInvalidHighbdInput(input, 4) != 0)
{ {
Debug.Assert(false, "invalid highbd txfm input"); Debug.Assert(false, "invalid highbd txfm input");
output.Slice(0, 4).Fill(0); output[..4].Clear();
return; return;
} }
@@ -1653,8 +1663,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
for (i = 0; i < 4; ++i) for (i = 0; i < 4; ++i)
{ {
HighbdIdct4(input, outptr, bd); HighbdIdct4(input, outptr, bd);
input = input.Slice(4); input = input[4..];
outptr = outptr.Slice(4); outptr = outptr[4..];
} }
// Columns // Columns
@@ -1688,7 +1698,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
dest[1] = HighbdClipPixelAdd(dest[1], a1, bd); dest[1] = HighbdClipPixelAdd(dest[1], a1, bd);
dest[2] = HighbdClipPixelAdd(dest[2], a1, bd); dest[2] = HighbdClipPixelAdd(dest[2], a1, bd);
dest[3] = HighbdClipPixelAdd(dest[3], a1, bd); dest[3] = HighbdClipPixelAdd(dest[3], a1, bd);
dest = dest.Slice(stride); dest = dest[stride..];
} }
} }
@@ -1707,13 +1717,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
if (DetectInvalidHighbdInput(input, 8) != 0) if (DetectInvalidHighbdInput(input, 8) != 0)
{ {
Debug.Assert(false, "invalid highbd txfm input"); Debug.Assert(false, "invalid highbd txfm input");
output.Slice(0, 8).Fill(0); output[..8].Clear();
return; return;
} }
if ((x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7) == 0) if ((x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7) == 0)
{ {
output.Slice(0, 8).Fill(0); output[..8].Clear();
return; return;
} }
@@ -1786,7 +1798,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
if (DetectInvalidHighbdInput(input, 8) != 0) if (DetectInvalidHighbdInput(input, 8) != 0)
{ {
Debug.Assert(false, "invalid highbd txfm input"); Debug.Assert(false, "invalid highbd txfm input");
output.Slice(0, 8).Fill(0); output[..8].Clear();
return; return;
} }
@@ -1845,8 +1858,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
for (i = 0; i < 8; ++i) for (i = 0; i < 8; ++i)
{ {
HighbdIdct8(input, outptr, bd); HighbdIdct8(input, outptr, bd);
input = input.Slice(8); input = input[8..];
outptr = outptr.Slice(8); outptr = outptr[8..];
} }
// Then transform columns // Then transform columns
@@ -1874,15 +1887,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Span<int> tempIn = stackalloc int[8]; Span<int> tempIn = stackalloc int[8];
Span<int> tempOut = stackalloc int[8]; Span<int> tempOut = stackalloc int[8];
output.Fill(0); output.Clear();
// First transform rows // First transform rows
// Only first 4 row has non-zero coefs // Only first 4 row has non-zero coefs
for (i = 0; i < 4; ++i) for (i = 0; i < 4; ++i)
{ {
HighbdIdct8(input, outptr, bd); HighbdIdct8(input, outptr, bd);
input = input.Slice(8); input = input[8..];
outptr = outptr.Slice(8); outptr = outptr[8..];
} }
// Then transform columns // Then transform columns
@@ -1901,7 +1914,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
} }
} }
public static void vpx_Highbdidct8x8_1_add_c(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int bd) public static void Vpx_Highbdidct8x8_1_add_c(ReadOnlySpan<int> input, Span<ushort> dest, int stride, int bd)
{ {
int i, j; int i, j;
long a1; long a1;
@@ -1916,7 +1929,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
dest[i] = HighbdClipPixelAdd(dest[i], a1, bd); dest[i] = HighbdClipPixelAdd(dest[i], a1, bd);
} }
dest = dest.Slice(stride); dest = dest[stride..];
} }
} }
@@ -1940,16 +1953,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
int x13 = input[12]; int x13 = input[12];
int x14 = input[1]; int x14 = input[1];
int x15 = input[14]; int x15 = input[14];
if (DetectInvalidHighbdInput(input, 16) != 0) if (DetectInvalidHighbdInput(input, 16) != 0)
{ {
Debug.Assert(false, "invalid highbd txfm input"); Debug.Assert(false, "invalid highbd txfm input");
output.Slice(0, 16).Fill(0); output[..16].Clear();
return; return;
} }
if ((x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | x10 | x11 | x12 | x13 | x14 | x15) == 0) if ((x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | x10 | x11 | x12 | x13 | x14 | x15) == 0)
{ {
output.Slice(0, 16).Fill(0); output[..16].Clear();
return; return;
} }
@@ -2105,7 +2121,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
if (DetectInvalidHighbdInput(input, 16) != 0) if (DetectInvalidHighbdInput(input, 16) != 0)
{ {
Debug.Assert(false, "invalid highbd txfm input"); Debug.Assert(false, "invalid highbd txfm input");
output.Slice(0, 16).Fill(0); output[..16].Clear();
return; return;
} }
@@ -2283,8 +2300,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
for (i = 0; i < 16; ++i) for (i = 0; i < 16; ++i)
{ {
HighbdIdct16(input, outptr, bd); HighbdIdct16(input, outptr, bd);
input = input.Slice(16); input = input[16..];
outptr = outptr.Slice(16); outptr = outptr[16..];
} }
// Then transform columns // Then transform columns
@@ -2312,15 +2329,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Span<int> tempIn = stackalloc int[16]; Span<int> tempIn = stackalloc int[16];
Span<int> tempOut = stackalloc int[16]; Span<int> tempOut = stackalloc int[16];
output.Fill(0); output.Clear();
// First transform rows. Since all non-zero dct coefficients are in // First transform rows. Since all non-zero dct coefficients are in
// upper-left 8x8 area, we only need to calculate first 8 rows here. // upper-left 8x8 area, we only need to calculate first 8 rows here.
for (i = 0; i < 8; ++i) for (i = 0; i < 8; ++i)
{ {
HighbdIdct16(input, outptr, bd); HighbdIdct16(input, outptr, bd);
input = input.Slice(16); input = input[16..];
outptr = outptr.Slice(16); outptr = outptr[16..];
} }
// Then transform columns // Then transform columns
@@ -2336,7 +2353,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
for (j = 0; j < 16; ++j) for (j = 0; j < 16; ++j)
{ {
destT[i] = HighbdClipPixelAdd(destT[i], BitUtils.RoundPowerOfTwo(tempOut[j], 6), bd); destT[i] = HighbdClipPixelAdd(destT[i], BitUtils.RoundPowerOfTwo(tempOut[j], 6), bd);
destT = destT.Slice(stride); destT = destT[stride..];
} }
} }
} }
@@ -2350,15 +2367,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Span<int> tempIn = stackalloc int[16]; Span<int> tempIn = stackalloc int[16];
Span<int> tempOut = stackalloc int[16]; Span<int> tempOut = stackalloc int[16];
output.Fill(0); output.Clear();
// First transform rows. Since all non-zero dct coefficients are in // First transform rows. Since all non-zero dct coefficients are in
// upper-left 4x4 area, we only need to calculate first 4 rows here. // upper-left 4x4 area, we only need to calculate first 4 rows here.
for (i = 0; i < 4; ++i) for (i = 0; i < 4; ++i)
{ {
HighbdIdct16(input, outptr, bd); HighbdIdct16(input, outptr, bd);
input = input.Slice(16); input = input[16..];
outptr = outptr.Slice(16); outptr = outptr[16..];
} }
// Then transform columns // Then transform columns
@@ -2392,7 +2409,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
dest[i] = HighbdClipPixelAdd(dest[i], a1, bd); dest[i] = HighbdClipPixelAdd(dest[i], a1, bd);
} }
dest = dest.Slice(stride); dest = dest[stride..];
} }
} }
@@ -2406,7 +2423,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
if (DetectInvalidHighbdInput(input, 32) != 0) if (DetectInvalidHighbdInput(input, 32) != 0)
{ {
Debug.Assert(false, "invalid highbd txfm input"); Debug.Assert(false, "invalid highbd txfm input");
output.Slice(0, 32).Fill(0); output[..32].Clear();
return; return;
} }
@@ -2797,11 +2815,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
} }
else else
{ {
outptr.Slice(0, 32).Fill(0); outptr[..32].Clear();
} }
input = input.Slice(32); input = input[32..];
outptr = outptr.Slice(32); outptr = outptr[32..];
} }
// Columns // Columns
@@ -2829,15 +2847,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Span<int> tempIn = stackalloc int[32]; Span<int> tempIn = stackalloc int[32];
Span<int> tempOut = stackalloc int[32]; Span<int> tempOut = stackalloc int[32];
output.Fill(0); output.Clear();
// Rows // Rows
// Only upper-left 16x16 has non-zero coeff // Only upper-left 16x16 has non-zero coeff
for (i = 0; i < 16; ++i) for (i = 0; i < 16; ++i)
{ {
HighbdIdct32(input, outptr, bd); HighbdIdct32(input, outptr, bd);
input = input.Slice(32); input = input[32..];
outptr = outptr.Slice(32); outptr = outptr[32..];
} }
// Columns // Columns
@@ -2853,7 +2871,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
for (j = 0; j < 32; ++j) for (j = 0; j < 32; ++j)
{ {
destT[i] = HighbdClipPixelAdd(destT[i], BitUtils.RoundPowerOfTwo(tempOut[j], 6), bd); destT[i] = HighbdClipPixelAdd(destT[i], BitUtils.RoundPowerOfTwo(tempOut[j], 6), bd);
destT = destT.Slice(stride); destT = destT[stride..];
} }
} }
} }
@@ -2867,15 +2885,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Span<int> tempIn = stackalloc int[32]; Span<int> tempIn = stackalloc int[32];
Span<int> tempOut = stackalloc int[32]; Span<int> tempOut = stackalloc int[32];
output.Fill(0); output.Clear();
// Rows // Rows
// Only upper-left 8x8 has non-zero coeff // Only upper-left 8x8 has non-zero coeff
for (i = 0; i < 8; ++i) for (i = 0; i < 8; ++i)
{ {
HighbdIdct32(input, outptr, bd); HighbdIdct32(input, outptr, bd);
input = input.Slice(32); input = input[32..];
outptr = outptr.Slice(32); outptr = outptr[32..];
} }
// Columns // Columns
@@ -2910,7 +2928,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
dest[i] = HighbdClipPixelAdd(dest[i], a1, bd); dest[i] = HighbdClipPixelAdd(dest[i], a1, bd);
} }
dest = dest.Slice(stride); dest = dest[stride..];
} }
} }
} }

View File

@@ -15,6 +15,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
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; // (p > 255) ? 255 : (p < 1) ? 1 : p;
int clippedProb = p | ((255 - p) >> 23) | (p == 0 ? 1 : 0); int clippedProb = p | ((255 - p) >> 23) | (p == 0 ? 1 : 0);
return (byte)clippedProb; return (byte)clippedProb;
} }
} }
@@ -26,10 +27,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
} }
// MODE_MV_MAX_UPDATE_FACTOR (128) * count / MODE_MV_COUNT_SAT; // MODE_MV_MAX_UPDATE_FACTOR (128) * count / MODE_MV_COUNT_SAT;
private static readonly uint[] CountToUpdateFactor = new uint[] private static readonly uint[] _countToUpdateFactor = {
{
0, 6, 12, 19, 25, 32, 38, 44, 51, 57, 64, 0, 6, 12, 19, 25, 32, 38, 44, 51, 57, 64,
70, 76, 83, 89, 96, 102, 108, 115, 121, 128 70, 76, 83, 89, 96, 102, 108, 115, 121, 128,
}; };
private const int ModeMvCountSat = 20; private const int ModeMvCountSat = 20;
@@ -44,8 +44,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
else else
{ {
uint count = Math.Min(den, ModeMvCountSat); uint count = Math.Min(den, ModeMvCountSat);
uint factor = CountToUpdateFactor[(int)count]; uint factor = _countToUpdateFactor[(int)count];
byte prob = GetProb(ct0, den); byte prob = GetProb(ct0, den);
return WeightedProb(preProb, prob, (int)factor); return WeightedProb(preProb, prob, (int)factor);
} }
} }
@@ -62,6 +63,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
int r = tree[i + 1]; 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); probs[(int)(i >> 1)] = ModeMvMergeProbs(preProbs[(int)(i >> 1)], leftCount, rightCount);
return leftCount + rightCount; return leftCount + rightCount;
} }

View File

@@ -6,8 +6,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
{ {
internal struct Reader internal struct Reader
{ {
private static readonly byte[] Norm = new byte[] 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, 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, 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, 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,
@@ -17,7 +16,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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; private const int BdValueSize = sizeof(ulong) * 8;
@@ -44,6 +43,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Count = -8; Count = -8;
Range = 255; Range = 255;
Fill(); Fill();
return ReadBit() != 0; // Marker bit return ReadBit() != 0; // Marker bit
} }
} }
@@ -65,7 +65,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
ulong bigEndianValues = BinaryPrimitives.ReadUInt64BigEndian(buffer); ulong bigEndianValues = BinaryPrimitives.ReadUInt64BigEndian(buffer);
nv = bigEndianValues >> (BdValueSize - bits); nv = bigEndianValues >> (BdValueSize - bits);
count += bits; count += bits;
buffer = buffer.Slice(bits >> 3); buffer = buffer[(bits >> 3)..];
value = Value | (nv << (shift & 0x7)); value = Value | (nv << (shift & 0x7));
} }
else else
@@ -84,7 +84,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
{ {
count += 8; count += 8;
value |= (ulong)buffer[0] << shift; value |= (ulong)buffer[0] << shift;
buffer = buffer.Slice(1); buffer = buffer[1..];
shift -= 8; shift -= 8;
} }
} }
@@ -98,7 +98,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Count = count; Count = count;
} }
public bool HasError() public readonly bool HasError()
{ {
// Check if we have reached the end of the buffer. // Check if we have reached the end of the buffer.
// //
@@ -146,7 +146,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
} }
{ {
int shift = Norm[range]; int shift = _norm[range];
range <<= shift; range <<= shift;
value <<= shift; value <<= shift;
count -= shift; count -= shift;
@@ -181,7 +181,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
while ((i = tree[i + Read(probs[i >> 1])]) > 0) while ((i = tree[i + Read(probs[i >> 1])]) > 0)
{ {
continue;
} }
return -i; return -i;
@@ -203,10 +202,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
if (value >= bigsplit) if (value >= bigsplit)
{ {
range = range - split; range -= split;
value = value - bigsplit; value -= bigsplit;
{ {
int shift = Norm[range]; int shift = _norm[range];
range <<= shift; range <<= shift;
value <<= shift; value <<= shift;
count -= shift; count -= shift;
@@ -215,7 +214,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
} }
range = split; range = split;
{ {
int shift = Norm[range]; int shift = _norm[range];
range <<= shift; range <<= shift;
value <<= shift; value <<= shift;
count -= shift; count -= shift;

View File

@@ -32,12 +32,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
} }
private static readonly Transform2D[] Iht4 = new Transform2D[] private static readonly Transform2D[] _iht4 = {
{ new(Idct4, Idct4), // DCT_DCT = 0
new Transform2D(Idct4, Idct4), // DCT_DCT = 0 new(Iadst4, Idct4), // ADST_DCT = 1
new Transform2D(Iadst4, Idct4), // ADST_DCT = 1 new(Idct4, Iadst4), // DCT_ADST = 2
new Transform2D(Idct4, Iadst4), // DCT_ADST = 2 new(Iadst4, Iadst4), // ADST_ADST = 3
new Transform2D(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)
@@ -51,9 +50,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// Inverse transform row vectors // Inverse transform row vectors
for (i = 0; i < 4; ++i) for (i = 0; i < 4; ++i)
{ {
Iht4[txType].Rows(input, outptr); _iht4[txType].Rows(input, outptr);
input = input.Slice(4); input = input[4..];
outptr = outptr.Slice(4); outptr = outptr[4..];
} }
// Inverse transform column vectors // Inverse transform column vectors
@@ -64,7 +63,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
tempIn[j] = output[j * 4 + i]; tempIn[j] = output[j * 4 + i];
} }
Iht4[txType].Cols(tempIn, tempOut); _iht4[txType].Cols(tempIn, tempOut);
for (j = 0; j < 4; ++j) for (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));
@@ -72,12 +71,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
} }
private static readonly Transform2D[] Iht8 = new Transform2D[] private static readonly Transform2D[] _iht8 = {
{ new(Idct8, Idct8), // DCT_DCT = 0
new Transform2D(Idct8, Idct8), // DCT_DCT = 0 new(Iadst8, Idct8), // ADST_DCT = 1
new Transform2D(Iadst8, Idct8), // ADST_DCT = 1 new(Idct8, Iadst8), // DCT_ADST = 2
new Transform2D(Idct8, Iadst8), // DCT_ADST = 2 new(Iadst8, Iadst8), // ADST_ADST = 3
new Transform2D(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)
@@ -87,14 +85,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
Span<int> outptr = output; Span<int> outptr = output;
Span<int> tempIn = stackalloc int[8]; Span<int> tempIn = stackalloc int[8];
Span<int> tempOut = stackalloc int[8]; Span<int> tempOut = stackalloc int[8];
Transform2D ht = Iht8[txType]; Transform2D ht = _iht8[txType];
// Inverse transform row vectors // Inverse transform row vectors
for (i = 0; i < 8; ++i) for (i = 0; i < 8; ++i)
{ {
ht.Rows(input, outptr); ht.Rows(input, outptr);
input = input.Slice(8); input = input[8..];
outptr = outptr.Slice(8); outptr = outptr[8..];
} }
// Inverse transform column vectors // Inverse transform column vectors
@@ -113,12 +111,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
} }
private static readonly Transform2D[] Iht16 = new Transform2D[] private static readonly Transform2D[] _iht16 = {
{ new(Idct16, Idct16), // DCT_DCT = 0
new Transform2D(Idct16, Idct16), // DCT_DCT = 0 new(Iadst16, Idct16), // ADST_DCT = 1
new Transform2D(Iadst16, Idct16), // ADST_DCT = 1 new(Idct16, Iadst16), // DCT_ADST = 2
new Transform2D(Idct16, Iadst16), // DCT_ADST = 2 new(Iadst16, Iadst16), // ADST_ADST = 3
new Transform2D(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)
@@ -128,14 +125,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
Span<int> outptr = output; Span<int> outptr = output;
Span<int> tempIn = stackalloc int[16]; Span<int> tempIn = stackalloc int[16];
Span<int> tempOut = stackalloc int[16]; Span<int> tempOut = stackalloc int[16];
Transform2D ht = Iht16[txType]; Transform2D ht = _iht16[txType];
// Rows // Rows
for (i = 0; i < 16; ++i) for (i = 0; i < 16; ++i)
{ {
ht.Rows(input, outptr); ht.Rows(input, outptr);
input = input.Slice(16); input = input[16..];
outptr = outptr.Slice(16); outptr = outptr[16..];
} }
// Columns // Columns
@@ -283,12 +280,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
} }
private static readonly HighbdTransform2D[] HighbdIht4 = new HighbdTransform2D[] private static readonly HighbdTransform2D[] _highbdIht4 = {
{ new(HighbdIdct4, HighbdIdct4), // DCT_DCT = 0
new HighbdTransform2D(HighbdIdct4, HighbdIdct4), // DCT_DCT = 0 new(HighbdIadst4, HighbdIdct4), // ADST_DCT = 1
new HighbdTransform2D(HighbdIadst4, HighbdIdct4), // ADST_DCT = 1 new(HighbdIdct4, HighbdIadst4), // DCT_ADST = 2
new HighbdTransform2D(HighbdIdct4, HighbdIadst4), // DCT_ADST = 2 new(HighbdIadst4, HighbdIadst4), // ADST_ADST = 3
new HighbdTransform2D(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)
@@ -302,9 +298,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// Inverse transform row vectors. // Inverse transform row vectors.
for (i = 0; i < 4; ++i) for (i = 0; i < 4; ++i)
{ {
HighbdIht4[txType].Rows(input, outptr, bd); _highbdIht4[txType].Rows(input, outptr, bd);
input = input.Slice(4); input = input[4..];
outptr = outptr.Slice(4); outptr = outptr[4..];
} }
// Inverse transform column vectors. // Inverse transform column vectors.
@@ -315,7 +311,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
tempIn[j] = output[j * 4 + i]; tempIn[j] = output[j * 4 + i];
} }
HighbdIht4[txType].Cols(tempIn, tempOut, bd); _highbdIht4[txType].Cols(tempIn, tempOut, bd);
for (j = 0; j < 4; ++j) for (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);
@@ -323,12 +319,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
} }
private static readonly HighbdTransform2D[] HighIht8 = new HighbdTransform2D[] private static readonly HighbdTransform2D[] _highIht8 = {
{ new(HighbdIdct8, HighbdIdct8), // DCT_DCT = 0
new HighbdTransform2D(HighbdIdct8, HighbdIdct8), // DCT_DCT = 0 new(HighbdIadst8, HighbdIdct8), // ADST_DCT = 1
new HighbdTransform2D(HighbdIadst8, HighbdIdct8), // ADST_DCT = 1 new(HighbdIdct8, HighbdIadst8), // DCT_ADST = 2
new HighbdTransform2D(HighbdIdct8, HighbdIadst8), // DCT_ADST = 2 new(HighbdIadst8, HighbdIadst8), // ADST_ADST = 3
new HighbdTransform2D(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)
@@ -338,14 +333,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
Span<int> outptr = output; Span<int> outptr = output;
Span<int> tempIn = stackalloc int[8]; Span<int> tempIn = stackalloc int[8];
Span<int> tempOut = stackalloc int[8]; Span<int> tempOut = stackalloc int[8];
HighbdTransform2D ht = HighIht8[txType]; HighbdTransform2D ht = _highIht8[txType];
// Inverse transform row vectors. // Inverse transform row vectors.
for (i = 0; i < 8; ++i) for (i = 0; i < 8; ++i)
{ {
ht.Rows(input, outptr, bd); ht.Rows(input, outptr, bd);
input = input.Slice(8); input = input[8..];
outptr = output.Slice(8); outptr = output[8..];
} }
// Inverse transform column vectors. // Inverse transform column vectors.
@@ -364,12 +359,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
} }
private static readonly HighbdTransform2D[] HighIht16 = new HighbdTransform2D[] private static readonly HighbdTransform2D[] _highIht16 = {
{ new(HighbdIdct16, HighbdIdct16), // DCT_DCT = 0
new HighbdTransform2D(HighbdIdct16, HighbdIdct16), // DCT_DCT = 0 new(HighbdIadst16, HighbdIdct16), // ADST_DCT = 1
new HighbdTransform2D(HighbdIadst16, HighbdIdct16), // ADST_DCT = 1 new(HighbdIdct16, HighbdIadst16), // DCT_ADST = 2
new HighbdTransform2D(HighbdIdct16, HighbdIadst16), // DCT_ADST = 2 new(HighbdIadst16, HighbdIadst16), // ADST_ADST = 3
new HighbdTransform2D(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)
@@ -379,14 +373,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
Span<int> outptr = output; Span<int> outptr = output;
Span<int> tempIn = stackalloc int[16]; Span<int> tempIn = stackalloc int[16];
Span<int> tempOut = stackalloc int[16]; Span<int> tempOut = stackalloc int[16];
HighbdTransform2D ht = HighIht16[txType]; HighbdTransform2D ht = _highIht16[txType];
// Rows // Rows
for (i = 0; i < 16; ++i) for (i = 0; i < 16; ++i)
{ {
ht.Rows(input, outptr, bd); ht.Rows(input, outptr, bd);
input = input.Slice(16); input = input[16..];
outptr = output.Slice(16); outptr = output[16..];
} }
// Columns // Columns
@@ -440,7 +434,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// DC only DCT coefficient // DC only DCT coefficient
if (eob == 1) if (eob == 1)
{ {
vpx_Highbdidct8x8_1_add_c(input, dest, stride, bd); Vpx_Highbdidct8x8_1_add_c(input, dest, stride, bd);
} }
else if (eob <= 12) else if (eob <= 12)
{ {

View File

@@ -30,8 +30,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// 10101010 // 10101010
// //
// A loopfilter should be applied to every other 8x8 horizontally. // A loopfilter should be applied to every other 8x8 horizontally.
private static readonly ulong[] Left64X64TxformMask = new ulong[] private static readonly ulong[] _left64X64TxformMask = {
{
0xffffffffffffffffUL, // TX_4X4 0xffffffffffffffffUL, // TX_4X4
0xffffffffffffffffUL, // TX_8x8 0xffffffffffffffffUL, // TX_8x8
0x5555555555555555UL, // TX_16x16 0x5555555555555555UL, // TX_16x16
@@ -55,8 +54,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// 00000000 // 00000000
// //
// A loopfilter should be applied to every other 4 the row vertically. // A loopfilter should be applied to every other 4 the row vertically.
private static readonly ulong[] Above64X64TxformMask = new ulong[] private static readonly ulong[] _above64X64TxformMask = {
{
0xffffffffffffffffUL, // TX_4X4 0xffffffffffffffffUL, // TX_4X4
0xffffffffffffffffUL, // TX_8x8 0xffffffffffffffffUL, // TX_8x8
0x00ff00ff00ff00ffUL, // TX_16x16 0x00ff00ff00ff00ffUL, // TX_16x16
@@ -78,8 +76,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// 00000000 // 00000000
// 00000000 // 00000000
// 00000000 // 00000000
private static readonly ulong[] LeftPredictionMask = new ulong[] private static readonly ulong[] _leftPredictionMask = {
{
0x0000000000000001UL, // BLOCK_4X4, 0x0000000000000001UL, // BLOCK_4X4,
0x0000000000000001UL, // BLOCK_4X8, 0x0000000000000001UL, // BLOCK_4X8,
0x0000000000000001UL, // BLOCK_8X4, 0x0000000000000001UL, // BLOCK_8X4,
@@ -96,8 +93,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}; };
// 64 bit mask to shift and set for each prediction size. // 64 bit mask to shift and set for each prediction size.
private static readonly ulong[] AbovePredictionMask = new ulong[] private static readonly ulong[] _abovePredictionMask = {
{
0x0000000000000001UL, // BLOCK_4X4 0x0000000000000001UL, // BLOCK_4X4
0x0000000000000001UL, // BLOCK_4X8 0x0000000000000001UL, // BLOCK_4X8
0x0000000000000001UL, // BLOCK_8X4 0x0000000000000001UL, // BLOCK_8X4
@@ -116,8 +112,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// 64 bit mask to shift and set for each prediction size. A bit is set for // 64 bit mask to shift and set for each prediction size. A bit is set for
// each 8x8 block that would be in the left most block of the given block // each 8x8 block that would be in the left most block of the given block
// size in the 64x64 block. // size in the 64x64 block.
private static readonly ulong[] SizeMask = new ulong[] private static readonly ulong[] _sizeMask = {
{
0x0000000000000001UL, // BLOCK_4X4 0x0000000000000001UL, // BLOCK_4X4
0x0000000000000001UL, // BLOCK_4X8 0x0000000000000001UL, // BLOCK_4X8
0x0000000000000001UL, // BLOCK_8X4 0x0000000000000001UL, // BLOCK_8X4
@@ -134,20 +129,20 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}; };
// These are used for masking the left and above borders. // These are used for masking the left and above borders.
#pragma warning disable IDE0051 // Remove unused private member
private const ulong LeftBorder = 0x1111111111111111UL; private const ulong LeftBorder = 0x1111111111111111UL;
private const ulong AboveBorder = 0x000000ff000000ffUL; private const ulong AboveBorder = 0x000000ff000000ffUL;
#pragma warning restore IDE0051
// 16 bit masks for uv transform sizes. // 16 bit masks for uv transform sizes.
private static readonly ushort[] Left64X64TxformMaskUv = new ushort[] private static readonly ushort[] _left64X64TxformMaskUv = {
{
0xffff, // TX_4X4 0xffff, // TX_4X4
0xffff, // TX_8x8 0xffff, // TX_8x8
0x5555, // TX_16x16 0x5555, // TX_16x16
0x1111, // TX_32x32 0x1111, // TX_32x32
}; };
private static readonly ushort[] Above64X64TxformMaskUv = new ushort[] private static readonly ushort[] _above64X64TxformMaskUv = {
{
0xffff, // TX_4X4 0xffff, // TX_4X4
0xffff, // TX_8x8 0xffff, // TX_8x8
0x0f0f, // TX_16x16 0x0f0f, // TX_16x16
@@ -155,8 +150,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}; };
// 16 bit left mask to shift and set for each uv prediction size. // 16 bit left mask to shift and set for each uv prediction size.
private static readonly ushort[] LeftPredictionMaskUv = new ushort[] private static readonly ushort[] _leftPredictionMaskUv = {
{
0x0001, // BLOCK_4X4, 0x0001, // BLOCK_4X4,
0x0001, // BLOCK_4X8, 0x0001, // BLOCK_4X8,
0x0001, // BLOCK_8X4, 0x0001, // BLOCK_8X4,
@@ -173,8 +167,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}; };
// 16 bit above mask to shift and set for uv each prediction size. // 16 bit above mask to shift and set for uv each prediction size.
private static readonly ushort[] AbovePredictionMaskUv = new ushort[] private static readonly ushort[] _abovePredictionMaskUv = {
{
0x0001, // BLOCK_4X4 0x0001, // BLOCK_4X4
0x0001, // BLOCK_4X8 0x0001, // BLOCK_4X8
0x0001, // BLOCK_8X4 0x0001, // BLOCK_8X4
@@ -191,8 +184,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
}; };
// 64 bit mask to shift and set for each uv prediction size // 64 bit mask to shift and set for each uv prediction size
private static readonly ushort[] SizeMaskUv = new ushort[] private static readonly ushort[] _sizeMaskUv = {
{
0x0001, // BLOCK_4X4 0x0001, // BLOCK_4X4
0x0001, // BLOCK_4X8 0x0001, // BLOCK_4X8
0x0001, // BLOCK_8X4 0x0001, // BLOCK_8X4
@@ -208,18 +200,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
0xffff, // BLOCK_64X64 0xffff, // BLOCK_64X64
}; };
#pragma warning disable IDE0051 // Remove unused private member
private const ushort LeftBorderUv = 0x1111; private const ushort LeftBorderUv = 0x1111;
private const ushort AboveBorderUv = 0x000f; private const ushort AboveBorderUv = 0x000f;
#pragma warning restore IDE0051
private static readonly int[] ModeLfLut = new int[] private static readonly int[] _modeLfLut = {
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // INTRA_MODES 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // INTRA_MODES
1, 1, 0, 1 // INTER_MODES (ZEROMV == 0) 1, 1, 0, 1, // INTER_MODES (ZEROMV == 0)
}; };
private static byte GetFilterLevel(ref LoopFilterInfoN lfiN, ref ModeInfo mi) private static byte GetFilterLevel(ref LoopFilterInfoN lfiN, ref ModeInfo mi)
{ {
return lfiN.Lvl[mi.SegmentId][mi.RefFrame[0]][ModeLfLut[(int)mi.Mode]]; return lfiN.Lvl[mi.SegmentId][mi.RefFrame[0]][_modeLfLut[(int)mi.Mode]];
} }
private static ref LoopFilterMask GetLfm(ref Types.LoopFilter lf, int miRow, int miCol) private static ref LoopFilterMask GetLfm(ref Types.LoopFilter lf, int miRow, int miCol)
@@ -229,12 +222,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// 8x8 blocks in a superblock. A "1" represents the first block in a 16x16 // 8x8 blocks in a superblock. A "1" represents the first block in a 16x16
// or greater area. // or greater area.
private static readonly byte[][] FirstBlockIn16x16 = new byte[][] private static readonly byte[][] _firstBlockIn16X16 = {
{ new byte[] { 1, 0, 1, 0, 1, 0, 1, 0 }, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 },
new byte[] { 1, 0, 1, 0, 1, 0, 1, 0 }, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, new byte[] { 1, 0, 1, 0, 1, 0, 1, 0 }, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 },
new byte[] { 1, 0, 1, 0, 1, 0, 1, 0 }, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, new byte[] { 1, 0, 1, 0, 1, 0, 1, 0 }, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 },
new byte[] { 1, 0, 1, 0, 1, 0, 1, 0 }, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, new byte[] { 1, 0, 1, 0, 1, 0, 1, 0 }, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 },
new byte[] { 1, 0, 1, 0, 1, 0, 1, 0 }, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }
}; };
// This function sets up the bit masks for a block represented // This function sets up the bit masks for a block represented
@@ -257,22 +249,20 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
int colInSb = (miCol & 7); int colInSb = (miCol & 7);
int shiftY = colInSb + (rowInSb << 3); int shiftY = colInSb + (rowInSb << 3);
int shiftUv = (colInSb >> 1) + ((rowInSb >> 1) << 2); int shiftUv = (colInSb >> 1) + ((rowInSb >> 1) << 2);
int buildUv = FirstBlockIn16x16[rowInSb][colInSb]; int buildUv = _firstBlockIn16X16[rowInSb][colInSb];
if (filterLevel == 0) if (filterLevel == 0)
{ {
return; return;
} }
else
{
int index = shiftY; int index = shiftY;
int i; int i;
for (i = 0; i < bh; i++) for (i = 0; i < bh; i++)
{ {
MemoryMarshal.CreateSpan(ref lfm.LflY[index], 64 - index).Slice(0, bw).Fill((byte)filterLevel); MemoryMarshal.CreateSpan(ref lfm.LflY[index], 64 - index)[..bw].Fill((byte)filterLevel);
index += 8; index += 8;
} }
}
// These set 1 in the current block size for the block size edges. // These set 1 in the current block size for the block size edges.
// For instance if the block size is 32x16, we'll set: // For instance if the block size is 32x16, we'll set:
@@ -286,13 +276,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// //
// U and V set things on a 16 bit scale. // U and V set things on a 16 bit scale.
// //
aboveY |= AbovePredictionMask[(int)blockSize] << shiftY; aboveY |= _abovePredictionMask[(int)blockSize] << shiftY;
leftY |= LeftPredictionMask[(int)blockSize] << shiftY; leftY |= _leftPredictionMask[(int)blockSize] << shiftY;
if (buildUv != 0) if (buildUv != 0)
{ {
aboveUv |= (ushort)(AbovePredictionMaskUv[(int)blockSize] << shiftUv); aboveUv |= (ushort)(_abovePredictionMaskUv[(int)blockSize] << shiftUv);
leftUv |= (ushort)(LeftPredictionMaskUv[(int)blockSize] << shiftUv); leftUv |= (ushort)(_leftPredictionMaskUv[(int)blockSize] << shiftUv);
} }
// If the block has no coefficients and is not intra we skip applying // If the block has no coefficients and is not intra we skip applying
@@ -305,13 +295,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// Add a mask for the transform size. The transform size mask is set to // Add a mask for the transform size. The transform size mask is set to
// be correct for a 64x64 prediction block size. Mask to match the size of // be correct for a 64x64 prediction block size. Mask to match the size of
// the block we are working on and then shift it into place. // the block we are working on and then shift it into place.
aboveY |= (SizeMask[(int)blockSize] & Above64X64TxformMask[(int)txSizeY]) << shiftY; aboveY |= (_sizeMask[(int)blockSize] & _above64X64TxformMask[(int)txSizeY]) << shiftY;
leftY |= (SizeMask[(int)blockSize] & Left64X64TxformMask[(int)txSizeY]) << shiftY; leftY |= (_sizeMask[(int)blockSize] & _left64X64TxformMask[(int)txSizeY]) << shiftY;
if (buildUv != 0) if (buildUv != 0)
{ {
aboveUv |= (ushort)((SizeMaskUv[(int)blockSize] & Above64X64TxformMaskUv[(int)txSizeUv]) << shiftUv); aboveUv |= (ushort)((_sizeMaskUv[(int)blockSize] & _above64X64TxformMaskUv[(int)txSizeUv]) << shiftUv);
leftUv |= (ushort)((SizeMaskUv[(int)blockSize] & Left64X64TxformMaskUv[(int)txSizeUv]) << shiftUv); leftUv |= (ushort)((_sizeMaskUv[(int)blockSize] & _left64X64TxformMaskUv[(int)txSizeUv]) << shiftUv);
} }
// Try to determine what to do with the internal 4x4 block boundaries. These // Try to determine what to do with the internal 4x4 block boundaries. These
@@ -319,12 +309,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// internal ones can be skipped and don't depend on the prediction block size. // internal ones can be skipped and don't depend on the prediction block size.
if (txSizeY == TxSize.Tx4x4) if (txSizeY == TxSize.Tx4x4)
{ {
int4X4Y |= SizeMask[(int)blockSize] << shiftY; int4X4Y |= _sizeMask[(int)blockSize] << shiftY;
} }
if (buildUv != 0 && txSizeUv == TxSize.Tx4x4) if (buildUv != 0 && txSizeUv == TxSize.Tx4x4)
{ {
int4X4Uv |= (ushort)((SizeMaskUv[(int)blockSize] & 0xffff) << shiftUv); int4X4Uv |= (ushort)((_sizeMaskUv[(int)blockSize] & 0xffff) << shiftUv);
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -55,6 +55,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
ctx = 1; ctx = 1;
} }
Debug.Assert(ctx >= 0 && ctx < Constants.CompInterContexts); Debug.Assert(ctx >= 0 && ctx < Constants.CompInterContexts);
return ctx; return ctx;
} }
@@ -170,6 +171,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
predContext = 2; predContext = 2;
} }
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts); Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
return predContext; return predContext;
} }
@@ -262,6 +264,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
predContext = 2; predContext = 2;
} }
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts); Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
return predContext; return predContext;
} }
@@ -383,6 +386,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
predContext = 2; predContext = 2;
} }
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts); Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
return predContext; return predContext;
} }
} }

View File

@@ -9,8 +9,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
public const int MinQ = 0; public const int MinQ = 0;
public const int MaxQ = 255; public const int MaxQ = 255;
private static readonly short[] DcQlookup = new short[] private static readonly short[] _dcQlookup = {
{
4, 8, 8, 9, 10, 11, 12, 12, 13, 14, 15, 16, 17, 18, 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, 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, 31, 32, 32, 33, 34, 35, 36, 37, 38, 38, 39, 40, 41, 42,
@@ -32,8 +31,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
1184, 1232, 1282, 1336, 1184, 1232, 1282, 1336,
}; };
private static readonly short[] DcQlookup10 = new short[] private static readonly short[] _dcQlookup10 = {
{
4, 9, 10, 13, 15, 17, 20, 22, 25, 28, 31, 34, 37, 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, 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, 86, 90, 93, 97, 101, 105, 109, 113, 116, 120, 124, 128, 132,
@@ -56,8 +54,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
3953, 4089, 4236, 4394, 4559, 4737, 4929, 5130, 5347, 3953, 4089, 4236, 4394, 4559, 4737, 4929, 5130, 5347,
}; };
private static readonly short[] DcQlookup12 = new short[] private static readonly short[] _dcQlookup12 = {
{
4, 12, 18, 25, 33, 41, 50, 60, 70, 80, 91, 4, 12, 18, 25, 33, 41, 50, 60, 70, 80, 91,
103, 115, 127, 140, 153, 166, 180, 194, 208, 222, 237, 103, 115, 127, 140, 153, 166, 180, 194, 208, 222, 237,
251, 266, 281, 296, 312, 327, 343, 358, 374, 390, 405, 251, 266, 281, 296, 312, 327, 343, 358, 374, 390, 405,
@@ -84,8 +81,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
19718, 20521, 21387, 19718, 20521, 21387,
}; };
private static readonly short[] AcQlookup = new short[] private static readonly short[] _acQlookup = {
{
4, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 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, 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, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
@@ -108,8 +104,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
1567, 1597, 1628, 1660, 1692, 1725, 1759, 1793, 1828, 1567, 1597, 1628, 1660, 1692, 1725, 1759, 1793, 1828,
}; };
private static readonly short[] AcQlookup10 = new short[] private static readonly short[] _acQlookup10 = {
{
4, 9, 11, 13, 16, 18, 21, 24, 27, 30, 33, 37, 40, 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, 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, 96, 100, 105, 109, 114, 118, 122, 127, 131, 136, 140, 145, 149,
@@ -132,8 +127,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
6268, 6388, 6512, 6640, 6768, 6900, 7036, 7172, 7312, 6268, 6388, 6512, 6640, 6768, 6900, 7036, 7172, 7312,
}; };
private static readonly short[] AcQlookup12 = new short[] private static readonly short[] _acQlookup12 = {
{
4, 13, 19, 27, 35, 44, 54, 64, 75, 87, 99, 4, 13, 19, 27, 35, 44, 54, 64, 75, 87, 99,
112, 126, 139, 154, 168, 183, 199, 214, 230, 247, 263, 112, 126, 139, 154, 168, 183, 199, 214, 230, 247, 263,
280, 297, 314, 331, 349, 366, 384, 402, 420, 438, 456, 280, 297, 314, 331, 349, 366, 384, 402, 420, 438, 456,
@@ -164,11 +158,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
switch (bitDepth) switch (bitDepth)
{ {
case BitDepth.Bits8: return DcQlookup[Math.Clamp(qindex + delta, 0, MaxQ)]; case BitDepth.Bits8:
case BitDepth.Bits10: return DcQlookup10[Math.Clamp(qindex + delta, 0, MaxQ)]; return _dcQlookup[Math.Clamp(qindex + delta, 0, MaxQ)];
case BitDepth.Bits12: return DcQlookup12[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: default:
Debug.Assert(false, "bit_depth should be VPX_BITS_8, VPX_BITS_10 or VPX_BITS_12"); Debug.Assert(false, "bit_depth should be VPX_BITS_8, VPX_BITS_10 or VPX_BITS_12");
return -1; return -1;
} }
} }
@@ -177,11 +175,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
switch (bitDepth) switch (bitDepth)
{ {
case BitDepth.Bits8: return AcQlookup[Math.Clamp(qindex + delta, 0, MaxQ)]; case BitDepth.Bits8:
case BitDepth.Bits10: return AcQlookup10[Math.Clamp(qindex + delta, 0, MaxQ)]; return _acQlookup[Math.Clamp(qindex + delta, 0, MaxQ)];
case BitDepth.Bits12: return AcQlookup12[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: default:
Debug.Assert(false, "bit_depth should be VPX_BITS_8, VPX_BITS_10 or VPX_BITS_12"); Debug.Assert(false, "bit_depth should be VPX_BITS_8, VPX_BITS_10 or VPX_BITS_12");
return -1; return -1;
} }
} }
@@ -192,12 +194,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
int data = seg.GetSegData(segmentId, SegLvlFeatures.SegLvlAltQ); int data = seg.GetSegData(segmentId, SegLvlFeatures.SegLvlAltQ);
int segQIndex = seg.AbsDelta == Constants.SegmentAbsData ? data : baseQIndex + data; int segQIndex = seg.AbsDelta == Constants.SegmentAbsData ? data : baseQIndex + data;
return Math.Clamp(segQIndex, 0, MaxQ); return Math.Clamp(segQIndex, 0, MaxQ);
} }
else
{
return baseQIndex; return baseQIndex;
} }
} }
}
} }

View File

@@ -84,16 +84,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
private static Mv MiMvPredQ4(ref ModeInfo mi, int idx) private static Mv MiMvPredQ4(ref ModeInfo mi, int idx)
{ {
Mv res = new Mv() return new Mv
{ {
Row = (short)RoundMvCompQ4( Row = (short)RoundMvCompQ4(
mi.Bmi[0].Mv[idx].Row + mi.Bmi[1].Mv[idx].Row + mi.Bmi[0].Mv[idx].Row + mi.Bmi[1].Mv[idx].Row +
mi.Bmi[2].Mv[idx].Row + mi.Bmi[3].Mv[idx].Row), mi.Bmi[2].Mv[idx].Row + mi.Bmi[3].Mv[idx].Row),
Col = (short)RoundMvCompQ4( Col = (short)RoundMvCompQ4(
mi.Bmi[0].Mv[idx].Col + mi.Bmi[1].Mv[idx].Col + mi.Bmi[0].Mv[idx].Col + mi.Bmi[1].Mv[idx].Col +
mi.Bmi[2].Mv[idx].Col + mi.Bmi[3].Mv[idx].Col) mi.Bmi[2].Mv[idx].Col + mi.Bmi[3].Mv[idx].Col),
}; };
return res;
} }
private static int RoundMvCompQ2(int value) private static int RoundMvCompQ2(int value)
@@ -103,16 +102,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
private static Mv MiMvPredQ2(ref ModeInfo mi, int idx, int block0, int block1) private static Mv MiMvPredQ2(ref ModeInfo mi, int idx, int block0, int block1)
{ {
Mv res = new Mv() return new Mv
{ {
Row = (short)RoundMvCompQ2( Row = (short)RoundMvCompQ2(
mi.Bmi[block0].Mv[idx].Row + mi.Bmi[block0].Mv[idx].Row +
mi.Bmi[block1].Mv[idx].Row), mi.Bmi[block1].Mv[idx].Row),
Col = (short)RoundMvCompQ2( Col = (short)RoundMvCompQ2(
mi.Bmi[block0].Mv[idx].Col + mi.Bmi[block0].Mv[idx].Col +
mi.Bmi[block1].Mv[idx].Col) mi.Bmi[block1].Mv[idx].Col),
}; };
return res;
} }
public static Mv ClampMvToUmvBorderSb(ref MacroBlockD xd, ref Mv srcMv, int bw, int bh, int ssX, int ssY) public static Mv ClampMvToUmvBorderSb(ref MacroBlockD xd, ref Mv srcMv, int bw, int bh, int ssX, int ssY)
@@ -124,10 +122,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
int spelRight = spelLeft - SubpelShifts; int spelRight = spelLeft - SubpelShifts;
int spelTop = (Constants.Vp9InterpExtend + bh) << SubpelBits; int spelTop = (Constants.Vp9InterpExtend + bh) << SubpelBits;
int spelBottom = spelTop - SubpelShifts; int spelBottom = spelTop - SubpelShifts;
Mv clampedMv = new Mv() Mv clampedMv = new()
{ {
Row = (short)(srcMv.Row * (1 << (1 - ssY))), Row = (short)(srcMv.Row * (1 << (1 - ssY))),
Col = (short)(srcMv.Col * (1 << (1 - ssX))) Col = (short)(srcMv.Col * (1 << (1 - ssX))),
}; };
Debug.Assert(ssX <= 1); Debug.Assert(ssX <= 1);
@@ -145,14 +143,24 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
public static Mv AverageSplitMvs(ref MacroBlockDPlane pd, ref ModeInfo mi, int refr, int block) public static Mv AverageSplitMvs(ref MacroBlockDPlane pd, ref ModeInfo mi, int refr, int block)
{ {
int ssIdx = ((pd.SubsamplingX > 0 ? 1 : 0) << 1) | (pd.SubsamplingY > 0 ? 1 : 0); int ssIdx = ((pd.SubsamplingX > 0 ? 1 : 0) << 1) | (pd.SubsamplingY > 0 ? 1 : 0);
Mv res = new Mv(); Mv res = new();
switch (ssIdx) switch (ssIdx)
{ {
case 0: res = mi.Bmi[block].Mv[refr]; break; case 0:
case 1: res = MiMvPredQ2(ref mi, refr, block, block + 2); break; res = mi.Bmi[block].Mv[refr];
case 2: res = MiMvPredQ2(ref mi, refr, block, block + 1); break; break;
case 3: res = MiMvPredQ4(ref mi, refr); break; case 1:
default: Debug.Assert(ssIdx <= 3 && ssIdx >= 0); break; res = MiMvPredQ2(ref mi, refr, block, block + 2);
break;
case 2:
res = MiMvPredQ2(ref mi, refr, block, block + 1);
break;
case 3:
res = MiMvPredQ4(ref mi, refr);
break;
default:
Debug.Assert(ssIdx <= 3 && ssIdx >= 0);
break;
} }
return res; return res;
} }
@@ -161,6 +169,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
int x = !sf.IsNull ? sf.Value.ScaleValueX(xOffset) : xOffset; int x = !sf.IsNull ? sf.Value.ScaleValueX(xOffset) : xOffset;
int y = !sf.IsNull ? sf.Value.ScaleValueY(yOffset) : yOffset; int y = !sf.IsNull ? sf.Value.ScaleValueY(yOffset) : yOffset;
return y * stride + x; return y * stride + x;
} }

View File

@@ -7,8 +7,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
internal static class ReconIntra internal static class ReconIntra
{ {
public static readonly TxType[] IntraModeToTxTypeLookup = new TxType[] public static readonly TxType[] IntraModeToTxTypeLookup = {
{
TxType.DctDct, // DC TxType.DctDct, // DC
TxType.AdstDct, // V TxType.AdstDct, // V
TxType.DctAdst, // H TxType.DctAdst, // H
@@ -18,7 +17,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
TxType.DctAdst, // D153 TxType.DctAdst, // D153
TxType.DctAdst, // D207 TxType.DctAdst, // D207
TxType.AdstDct, // D63 TxType.AdstDct, // D63
TxType.AdstAdst // TM TxType.AdstAdst, // TM
}; };
private const int NeedLeft = 1 << 1; private const int NeedLeft = 1 << 1;
@@ -41,230 +40,226 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
private unsafe delegate void IntraPredFn(byte* dst, int stride, byte* above, byte* left); private unsafe delegate void IntraPredFn(byte* dst, int stride, byte* above, byte* left);
private static unsafe IntraPredFn[][] _pred = new IntraPredFn[][] private static readonly unsafe IntraPredFn[][] _pred = {
{
new IntraPredFn[] new IntraPredFn[]
{ {
null, null,
null, null,
null, null,
null null,
}, },
new IntraPredFn[] new IntraPredFn[]
{ {
VPredictor4x4, VPredictor4x4,
VPredictor8x8, VPredictor8x8,
VPredictor16x16, VPredictor16x16,
VPredictor32x32 VPredictor32x32,
}, },
new IntraPredFn[] new IntraPredFn[]
{ {
HPredictor4x4, HPredictor4x4,
HPredictor8x8, HPredictor8x8,
HPredictor16x16, HPredictor16x16,
HPredictor32x32 HPredictor32x32,
}, },
new IntraPredFn[] new IntraPredFn[]
{ {
D45Predictor4x4, D45Predictor4x4,
D45Predictor8x8, D45Predictor8x8,
D45Predictor16x16, D45Predictor16x16,
D45Predictor32x32 D45Predictor32x32,
}, },
new IntraPredFn[] new IntraPredFn[]
{ {
D135Predictor4x4, D135Predictor4x4,
D135Predictor8x8, D135Predictor8x8,
D135Predictor16x16, D135Predictor16x16,
D135Predictor32x32 D135Predictor32x32,
}, },
new IntraPredFn[] new IntraPredFn[]
{ {
D117Predictor4x4, D117Predictor4x4,
D117Predictor8x8, D117Predictor8x8,
D117Predictor16x16, D117Predictor16x16,
D117Predictor32x32 D117Predictor32x32,
}, },
new IntraPredFn[] new IntraPredFn[]
{ {
D153Predictor4x4, D153Predictor4x4,
D153Predictor8x8, D153Predictor8x8,
D153Predictor16x16, D153Predictor16x16,
D153Predictor32x32 D153Predictor32x32,
}, },
new IntraPredFn[] new IntraPredFn[]
{ {
D207Predictor4x4, D207Predictor4x4,
D207Predictor8x8, D207Predictor8x8,
D207Predictor16x16, D207Predictor16x16,
D207Predictor32x32 D207Predictor32x32,
}, },
new IntraPredFn[] new IntraPredFn[]
{ {
D63Predictor4x4, D63Predictor4x4,
D63Predictor8x8, D63Predictor8x8,
D63Predictor16x16, D63Predictor16x16,
D63Predictor32x32 D63Predictor32x32,
}, },
new IntraPredFn[] new IntraPredFn[]
{ {
TMPredictor4x4, TMPredictor4x4,
TMPredictor8x8, TMPredictor8x8,
TMPredictor16x16, TMPredictor16x16,
TMPredictor32x32 TMPredictor32x32,
} },
}; };
private static unsafe IntraPredFn[][][] _dcPred = new IntraPredFn[][][] private static readonly unsafe IntraPredFn[][][] _dcPred = {
{ new[]
new IntraPredFn[][]
{ {
new IntraPredFn[] new IntraPredFn[]
{ {
Dc128Predictor4x4, Dc128Predictor4x4,
Dc128Predictor8x8, Dc128Predictor8x8,
Dc128Predictor16x16, Dc128Predictor16x16,
Dc128Predictor32x32 Dc128Predictor32x32,
}, },
new IntraPredFn[] new IntraPredFn[]
{ {
DcTopPredictor4x4, DcTopPredictor4x4,
DcTopPredictor8x8, DcTopPredictor8x8,
DcTopPredictor16x16, DcTopPredictor16x16,
DcTopPredictor32x32 DcTopPredictor32x32,
}
}, },
new IntraPredFn[][] },
new[]
{ {
new IntraPredFn[] new IntraPredFn[]
{ {
DcLeftPredictor4x4, DcLeftPredictor4x4,
DcLeftPredictor8x8, DcLeftPredictor8x8,
DcLeftPredictor16x16, DcLeftPredictor16x16,
DcLeftPredictor32x32 DcLeftPredictor32x32,
}, },
new IntraPredFn[] new IntraPredFn[]
{ {
DcPredictor4x4, DcPredictor4x4,
DcPredictor8x8, DcPredictor8x8,
DcPredictor16x16, DcPredictor16x16,
DcPredictor32x32 DcPredictor32x32,
} },
} },
}; };
private unsafe delegate void IntraHighPredFn(ushort* dst, int stride, ushort* above, ushort* left, int bd); private unsafe delegate void IntraHighPredFn(ushort* dst, int stride, ushort* above, ushort* left, int bd);
private static unsafe IntraHighPredFn[][] _predHigh = new IntraHighPredFn[][] private static readonly unsafe IntraHighPredFn[][] _predHigh = {
{
new IntraHighPredFn[] new IntraHighPredFn[]
{ {
null, null,
null, null,
null, null,
null null,
}, },
new IntraHighPredFn[] new IntraHighPredFn[]
{ {
HighbdVPredictor4x4, HighbdVPredictor4x4,
HighbdVPredictor8x8, HighbdVPredictor8x8,
HighbdVPredictor16x16, HighbdVPredictor16x16,
HighbdVPredictor32x32 HighbdVPredictor32x32,
}, },
new IntraHighPredFn[] new IntraHighPredFn[]
{ {
HighbdHPredictor4x4, HighbdHPredictor4x4,
HighbdHPredictor8x8, HighbdHPredictor8x8,
HighbdHPredictor16x16, HighbdHPredictor16x16,
HighbdHPredictor32x32 HighbdHPredictor32x32,
}, },
new IntraHighPredFn[] new IntraHighPredFn[]
{ {
HighbdD45Predictor4x4, HighbdD45Predictor4x4,
HighbdD45Predictor8x8, HighbdD45Predictor8x8,
HighbdD45Predictor16x16, HighbdD45Predictor16x16,
HighbdD45Predictor32x32 HighbdD45Predictor32x32,
}, },
new IntraHighPredFn[] new IntraHighPredFn[]
{ {
HighbdD135Predictor4x4, HighbdD135Predictor4x4,
HighbdD135Predictor8x8, HighbdD135Predictor8x8,
HighbdD135Predictor16x16, HighbdD135Predictor16x16,
HighbdD135Predictor32x32 HighbdD135Predictor32x32,
}, },
new IntraHighPredFn[] new IntraHighPredFn[]
{ {
HighbdD117Predictor4x4, HighbdD117Predictor4x4,
HighbdD117Predictor8x8, HighbdD117Predictor8x8,
HighbdD117Predictor16x16, HighbdD117Predictor16x16,
HighbdD117Predictor32x32 HighbdD117Predictor32x32,
}, },
new IntraHighPredFn[] new IntraHighPredFn[]
{ {
HighbdD153Predictor4x4, HighbdD153Predictor4x4,
HighbdD153Predictor8x8, HighbdD153Predictor8x8,
HighbdD153Predictor16x16, HighbdD153Predictor16x16,
HighbdD153Predictor32x32 HighbdD153Predictor32x32,
}, },
new IntraHighPredFn[] new IntraHighPredFn[]
{ {
HighbdD207Predictor4x4, HighbdD207Predictor4x4,
HighbdD207Predictor8x8, HighbdD207Predictor8x8,
HighbdD207Predictor16x16, HighbdD207Predictor16x16,
HighbdD207Predictor32x32 HighbdD207Predictor32x32,
}, },
new IntraHighPredFn[] new IntraHighPredFn[]
{ {
HighbdD63Predictor4x4, HighbdD63Predictor4x4,
HighbdD63Predictor8x8, HighbdD63Predictor8x8,
HighbdD63Predictor16x16, HighbdD63Predictor16x16,
HighbdD63Predictor32x32 HighbdD63Predictor32x32,
}, },
new IntraHighPredFn[] new IntraHighPredFn[]
{ {
HighbdTMPredictor4x4, HighbdTMPredictor4x4,
HighbdTMPredictor8x8, HighbdTMPredictor8x8,
HighbdTMPredictor16x16, HighbdTMPredictor16x16,
HighbdTMPredictor32x32 HighbdTMPredictor32x32,
} },
}; };
private static unsafe IntraHighPredFn[][][] _dcPredHigh = new IntraHighPredFn[][][] private static readonly unsafe IntraHighPredFn[][][] _dcPredHigh = {
{ new[]
new IntraHighPredFn[][]
{ {
new IntraHighPredFn[] new IntraHighPredFn[]
{ {
HighbdDc128Predictor4x4, HighbdDc128Predictor4x4,
HighbdDc128Predictor8x8, HighbdDc128Predictor8x8,
HighbdDc128Predictor16x16, HighbdDc128Predictor16x16,
HighbdDc128Predictor32x32 HighbdDc128Predictor32x32,
}, },
new IntraHighPredFn[] new IntraHighPredFn[]
{ {
HighbdDcTopPredictor4x4, HighbdDcTopPredictor4x4,
HighbdDcTopPredictor8x8, HighbdDcTopPredictor8x8,
HighbdDcTopPredictor16x16, HighbdDcTopPredictor16x16,
HighbdDcTopPredictor32x32 HighbdDcTopPredictor32x32,
}
}, },
new IntraHighPredFn[][] },
new[]
{ {
new IntraHighPredFn[] new IntraHighPredFn[]
{ {
HighbdDcLeftPredictor4x4, HighbdDcLeftPredictor4x4,
HighbdDcLeftPredictor8x8, HighbdDcLeftPredictor8x8,
HighbdDcLeftPredictor16x16, HighbdDcLeftPredictor16x16,
HighbdDcLeftPredictor32x32 HighbdDcLeftPredictor32x32,
}, },
new IntraHighPredFn[] new IntraHighPredFn[]
{ {
HighbdDcPredictor4x4, HighbdDcPredictor4x4,
HighbdDcPredictor8x8, HighbdDcPredictor8x8,
HighbdDcPredictor16x16, HighbdDcPredictor16x16,
HighbdDcPredictor32x32 HighbdDcPredictor32x32,
} },
} },
}; };
private static unsafe void BuildIntraPredictorsHigh( private static unsafe void BuildIntraPredictorsHigh(
@@ -741,6 +736,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
x, x,
y, y,
plane); plane);
return; return;
} }
BuildIntraPredictors( BuildIntraPredictors(

View File

@@ -16,6 +16,6 @@
Block64x32 = 11, Block64x32 = 11,
Block64x64 = 12, Block64x64 = 12,
BlockSizes = 13, BlockSizes = 13,
BlockInvalid = BlockSizes BlockInvalid = BlockSizes,
} }
} }

View File

@@ -3,6 +3,6 @@
internal enum FrameType internal enum FrameType
{ {
KeyFrame = 0, KeyFrame = 0,
InterFrame = 1 InterFrame = 1,
} }
} }

View File

@@ -6,7 +6,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
// passed it can be loaded into vector registers. // passed it can be loaded into vector registers.
internal struct LoopFilterThresh internal struct LoopFilterThresh
{ {
#pragma warning disable CS0649 #pragma warning disable CS0649 // Field is never assigned to
public Array16<byte> Mblim; public Array16<byte> Mblim;
public Array16<byte> Lim; public Array16<byte> Lim;
public Array16<byte> HevThr; public Array16<byte> HevThr;

View File

@@ -54,7 +54,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
public Ptr<InternalErrorInfo> ErrorInfo; public Ptr<InternalErrorInfo> ErrorInfo;
public int GetPredContextSegId() public readonly int GetPredContextSegId()
{ {
sbyte aboveSip = !AboveMi.IsNull ? AboveMi.Value.SegIdPredicted : (sbyte)0; sbyte aboveSip = !AboveMi.IsNull ? AboveMi.Value.SegIdPredicted : (sbyte)0;
sbyte leftSip = !LeftMi.IsNull ? LeftMi.Value.SegIdPredicted : (sbyte)0; sbyte leftSip = !LeftMi.IsNull ? LeftMi.Value.SegIdPredicted : (sbyte)0;
@@ -62,14 +62,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
return aboveSip + leftSip; return aboveSip + leftSip;
} }
public int GetSkipContext() public readonly int GetSkipContext()
{ {
int aboveSkip = !AboveMi.IsNull ? AboveMi.Value.Skip : 0; int aboveSkip = !AboveMi.IsNull ? AboveMi.Value.Skip : 0;
int leftSkip = !LeftMi.IsNull ? LeftMi.Value.Skip : 0; int leftSkip = !LeftMi.IsNull ? LeftMi.Value.Skip : 0;
return aboveSkip + leftSkip; return aboveSkip + leftSkip;
} }
public int GetPredContextSwitchableInterp() public readonly int GetPredContextSwitchableInterp()
{ {
// Note: // Note:
// The mode info data structure has a one element border above and to the // The mode info data structure has a one element border above and to the
@@ -103,15 +104,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
// 1 - intra/inter, inter/intra // 1 - intra/inter, inter/intra
// 2 - intra/--, --/intra // 2 - intra/--, --/intra
// 3 - intra/intra // 3 - intra/intra
public int GetIntraInterContext() public readonly int GetIntraInterContext()
{ {
if (!AboveMi.IsNull && !LeftMi.IsNull) if (!AboveMi.IsNull && !LeftMi.IsNull)
{ // Both edges available { // Both edges available
bool aboveIntra = !AboveMi.Value.IsInterBlock(); bool aboveIntra = !AboveMi.Value.IsInterBlock();
bool leftIntra = !LeftMi.Value.IsInterBlock(); bool leftIntra = !LeftMi.Value.IsInterBlock();
return leftIntra && aboveIntra ? 3 : (leftIntra || aboveIntra ? 1 : 0); return leftIntra && aboveIntra ? 3 : (leftIntra || aboveIntra ? 1 : 0);
} }
else if (!AboveMi.IsNull || !LeftMi.IsNull)
if (!AboveMi.IsNull || !LeftMi.IsNull)
{ // One edge available { // One edge available
return 2 * (!(!AboveMi.IsNull ? AboveMi.Value : LeftMi.Value).IsInterBlock() ? 1 : 0); return 2 * (!(!AboveMi.IsNull ? AboveMi.Value : LeftMi.Value).IsInterBlock() ? 1 : 0);
} }
@@ -122,7 +125,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
// The mode info data structure has a one element border above and to the // The mode info data structure has a one element border above and to the
// left of the entries corresponding to real blocks. // left of the entries corresponding to real blocks.
// The prediction flags in these dummy entries are initialized to 0. // The prediction flags in these dummy entries are initialized to 0.
public int GetTxSizeContext() public readonly int GetTxSizeContext()
{ {
int maxTxSize = (int)Luts.MaxTxSizeLookup[(int)Mi[0].Value.SbType]; int maxTxSize = (int)Luts.MaxTxSizeLookup[(int)Mi[0].Value.SbType];
int aboveCtx = (!AboveMi.IsNull && AboveMi.Value.Skip == 0) ? (int)AboveMi.Value.TxSize : maxTxSize; int aboveCtx = (!AboveMi.IsNull && AboveMi.Value.Skip == 0) ? (int)AboveMi.Value.TxSize : maxTxSize;

View File

@@ -32,10 +32,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
return SbType < BlockSize.Block8x8 ? Bmi[block].Mode : Mode; return SbType < BlockSize.Block8x8 ? Bmi[block].Mode : Mode;
} }
public TxSize GetUvTxSize(ref MacroBlockDPlane pd) public readonly TxSize GetUvTxSize(ref MacroBlockDPlane pd)
{ {
Debug.Assert(SbType < BlockSize.Block8x8 || Debug.Assert(SbType < BlockSize.Block8x8 ||
Luts.SsSizeLookup[(int)SbType][pd.SubsamplingX][pd.SubsamplingY] != BlockSize.BlockInvalid); Luts.SsSizeLookup[(int)SbType][pd.SubsamplingX][pd.SubsamplingY] != BlockSize.BlockInvalid);
return Luts.UvTxsizeLookup[(int)SbType][(int)TxSize][pd.SubsamplingX][pd.SubsamplingY]; return Luts.UvTxsizeLookup[(int)SbType][(int)TxSize][pd.SubsamplingX][pd.SubsamplingY];
} }
@@ -49,9 +50,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
return RefFrame[1] > Constants.IntraFrame; return RefFrame[1] > Constants.IntraFrame;
} }
private static readonly int[][] IdxNColumnToSubblock = new int[][] private static readonly int[][] _idxNColumnToSubblock = {
{ new[] { 1, 2 }, new[] { 1, 3 }, new[] { 3, 2 }, new[] { 3, 3 },
new int[] { 1, 2 }, new int[] { 1, 3 }, new int[] { 3, 2 }, new int[] { 3, 3 }
}; };
// This function returns either the appropriate sub block or block's mv // This function returns either the appropriate sub block or block's mv
@@ -59,7 +59,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
public Mv GetSubBlockMv(int whichMv, int searchCol, int blockIdx) 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] ? Bmi[_idxNColumnToSubblock[blockIdx][searchCol == 0 ? 1 : 0]].Mv[whichMv]
: Mv[whichMv]; : Mv[whichMv];
} }
} }

Some files were not shown because too many files have changed in this diff Show More