Compare commits

...

7 Commits

Author SHA1 Message Date
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
TSRBerry
9becbd7d72 [Ryujinx.Graphics.Shader] Address dotnet-format issues (#5373)
* 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 IDE0052 warnings

* Silence dotnet format IDE0059 warnings

* Address or silence dotnet format CA1069 warnings

* Address or silence dotnet format CA2211 warnings

* Address review comments

* 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

* Format if-blocks correctly

* Run dotnet format whitespace after rebase

* Run dotnet format style after rebase

* Run dotnet format whitespace after rebase

* Run dotnet format style after rebase

* Run dotnet format after rebase and remove unused usings

- analyzers
- style
- whitespace

* Disable 'prefer switch expression' rule

* Add comments to disabled warnings

* Fix naming rule violation, Convert shader properties to auto-property and convert values to const

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

* Run dotnet format after rebase

* Address IDE0251 warnings

* Address a few disabled IDE0060 warnings

* Silence IDE0060 in .editorconfig

* Run dotnet format after rebase

* 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

* Fix naming rule violations

* Add trailing commas

* Remove unused members and most unnecessary value assignments

* Remove more unnecessary assignments

* Remove NRE suppressor
2023-06-28 08:59:13 +02:00
TSRBerry
e055217292 [Ryujinx.Horizon.Kernel.Generators] Address dotnet-format issues (#5376)
* 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

* 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

* Run dotnet format pass

* Remove left-over files and adjust namespaces

* Fix alignment
2023-06-27 23:27:48 +00:00
TSRBerry
fbaf62c230 Apply new naming rule to all projects except Vp9 (#5407) 2023-06-28 01:18:19 +02:00
TSRBerry
b186ec9fc5 [Ryujinx.Graphics.Video] Address dotnet-format issues (#5377)
* Address most dotnet format whitespace warnings

* dotnet format whitespace after rebase
2023-06-27 16:45:33 +02:00
255 changed files with 3505 additions and 3356 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

@@ -1296,11 +1296,11 @@ namespace ARMeilleure.CodeGen.X86
} }
else else
{ {
const byte mask = 0b01_00_11_10; const byte Mask = 0b01_00_11_10;
context.Assembler.Pshufd(src1, src1, mask); context.Assembler.Pshufd(src1, src1, Mask);
context.Assembler.Movq(dest, src1); context.Assembler.Movq(dest, src1);
context.Assembler.Pshufd(src1, src1, mask); context.Assembler.Pshufd(src1, src1, Mask);
} }
} }
else else
@@ -1853,9 +1853,9 @@ namespace ARMeilleure.CodeGen.X86
// that the OS will map all pages that we'll use. We do that by // that the OS will map all pages that we'll use. We do that by
// doing a dummy read on those pages, forcing a page fault and // doing a dummy read on those pages, forcing a page fault and
// the OS to map them. If they are already mapped, nothing happens. // the OS to map them. If they are already mapped, nothing happens.
const int pageMask = PageSize - 1; const int PageMask = PageSize - 1;
size = (size + pageMask) & ~pageMask; size = (size + PageMask) & ~PageMask;
Operand rsp = Register(X86Register.Rsp); Operand rsp = Register(X86Register.Rsp);
Operand temp = Register(CallingConvention.GetIntReturnRegister()); Operand temp = Register(CallingConvention.GetIntReturnRegister());

View File

@@ -304,9 +304,9 @@ namespace ARMeilleure.Decoders
} }
else if (opCode is IOpCode32MemMult opMemMult) else if (opCode is IOpCode32MemMult opMemMult)
{ {
const int pcMask = 1 << RegisterAlias.Aarch32Pc; const int PCMask = 1 << RegisterAlias.Aarch32Pc;
rt = (opMemMult.RegisterMask & pcMask) != 0 ? RegisterAlias.Aarch32Pc : 0; rt = (opMemMult.RegisterMask & PCMask) != 0 ? RegisterAlias.Aarch32Pc : 0;
rn = opMemMult.Rn; rn = opMemMult.Rn;
wBack = opMemMult.PostOffset != 0; wBack = opMemMult.PostOffset != 0;
isLoad = opMemMult.IsLoad; isLoad = opMemMult.IsLoad;

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

@@ -883,174 +883,175 @@ namespace ARMeilleure.Decoders
SetVfp("<<<<11100x11xxxxxxxx101xx1x0xxxx", InstName.Vsub, InstEmit32.Vsub_S, OpCode32SimdRegS.Create, OpCode32SimdRegS.CreateT32); SetVfp("<<<<11100x11xxxxxxxx101xx1x0xxxx", InstName.Vsub, InstEmit32.Vsub_S, OpCode32SimdRegS.Create, OpCode32SimdRegS.CreateT32);
// ASIMD // ASIMD
SetAsimd("111100111x110000xxx0001101x0xxx0", InstName.Aesd_V, InstEmit32.Aesd_V, OpCode32Simd.Create, OpCode32Simd.CreateT32); SetAsimd("111100111x110000xxx0001101x0xxx0", InstName.Aesd_V, InstEmit32.Aesd_V, OpCode32Simd.Create, OpCode32Simd.CreateT32);
SetAsimd("111100111x110000xxx0001100x0xxx0", InstName.Aese_V, InstEmit32.Aese_V, OpCode32Simd.Create, OpCode32Simd.CreateT32); SetAsimd("111100111x110000xxx0001100x0xxx0", InstName.Aese_V, InstEmit32.Aese_V, OpCode32Simd.Create, OpCode32Simd.CreateT32);
SetAsimd("111100111x110000xxx0001111x0xxx0", InstName.Aesimc_V, InstEmit32.Aesimc_V, OpCode32Simd.Create, OpCode32Simd.CreateT32); SetAsimd("111100111x110000xxx0001111x0xxx0", InstName.Aesimc_V, InstEmit32.Aesimc_V, OpCode32Simd.Create, OpCode32Simd.CreateT32);
SetAsimd("111100111x110000xxx0001110x0xxx0", InstName.Aesmc_V, InstEmit32.Aesmc_V, OpCode32Simd.Create, OpCode32Simd.CreateT32); SetAsimd("111100111x110000xxx0001110x0xxx0", InstName.Aesmc_V, InstEmit32.Aesmc_V, OpCode32Simd.Create, OpCode32Simd.CreateT32);
SetAsimd("111100110x00xxx0xxx01100x1x0xxx0", InstName.Sha256h_V, InstEmit32.Sha256h_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("111100110x00xxx0xxx01100x1x0xxx0", InstName.Sha256h_V, InstEmit32.Sha256h_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("111100110x01xxx0xxx01100x1x0xxx0", InstName.Sha256h2_V, InstEmit32.Sha256h2_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("111100110x01xxx0xxx01100x1x0xxx0", InstName.Sha256h2_V, InstEmit32.Sha256h2_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("111100111x111010xxx0001111x0xxx0", InstName.Sha256su0_V, InstEmit32.Sha256su0_V, OpCode32Simd.Create, OpCode32Simd.CreateT32); SetAsimd("111100111x111010xxx0001111x0xxx0", InstName.Sha256su0_V, InstEmit32.Sha256su0_V, OpCode32Simd.Create, OpCode32Simd.CreateT32);
SetAsimd("111100110x10xxx0xxx01100x1x0xxx0", InstName.Sha256su1_V, InstEmit32.Sha256su1_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("111100110x10xxx0xxx01100x1x0xxx0", InstName.Sha256su1_V, InstEmit32.Sha256su1_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("1111001x0x<<xxxxxxxx0111xxx0xxxx", InstName.Vabd, InstEmit32.Vabd_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("1111001x0x<<xxxxxxxx0111xxx0xxxx", InstName.Vabd, InstEmit32.Vabd_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("1111001x1x<<xxxxxxxx0111x0x0xxxx", InstName.Vabdl, InstEmit32.Vabdl_I, OpCode32SimdRegLong.Create, OpCode32SimdRegLong.CreateT32); SetAsimd("1111001x1x<<xxxxxxxx0111x0x0xxxx", InstName.Vabdl, InstEmit32.Vabdl_I, OpCode32SimdRegLong.Create, OpCode32SimdRegLong.CreateT32);
SetAsimd("111100111x11<<01xxxx00110xx0xxxx", InstName.Vabs, InstEmit32.Vabs_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32); SetAsimd("111100111x11<<01xxxx00110xx0xxxx", InstName.Vabs, InstEmit32.Vabs_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
SetAsimd("111100111x111001xxxx01110xx0xxxx", InstName.Vabs, InstEmit32.Vabs_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32); SetAsimd("111100111x111001xxxx01110xx0xxxx", InstName.Vabs, InstEmit32.Vabs_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
SetAsimd("111100100xxxxxxxxxxx1000xxx0xxxx", InstName.Vadd, InstEmit32.Vadd_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("111100100xxxxxxxxxxx1000xxx0xxxx", InstName.Vadd, InstEmit32.Vadd_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("111100100x00xxxxxxxx1101xxx0xxxx", InstName.Vadd, InstEmit32.Vadd_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("111100100x00xxxxxxxx1101xxx0xxxx", InstName.Vadd, InstEmit32.Vadd_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("1111001x1x<<xxxxxxx00000x0x0xxxx", InstName.Vaddl, InstEmit32.Vaddl_I, OpCode32SimdRegLong.Create, OpCode32SimdRegLong.CreateT32); SetAsimd("1111001x1x<<xxxxxxx00000x0x0xxxx", InstName.Vaddl, InstEmit32.Vaddl_I, OpCode32SimdRegLong.Create, OpCode32SimdRegLong.CreateT32);
SetAsimd("1111001x1x<<xxxxxxx00001x0x0xxxx", InstName.Vaddw, InstEmit32.Vaddw_I, OpCode32SimdRegWide.Create, OpCode32SimdRegWide.CreateT32); SetAsimd("1111001x1x<<xxxxxxx00001x0x0xxxx", InstName.Vaddw, InstEmit32.Vaddw_I, OpCode32SimdRegWide.Create, OpCode32SimdRegWide.CreateT32);
SetAsimd("111100100x00xxxxxxxx0001xxx1xxxx", InstName.Vand, InstEmit32.Vand_I, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32); SetAsimd("111100100x00xxxxxxxx0001xxx1xxxx", InstName.Vand, InstEmit32.Vand_I, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32);
SetAsimd("111100100x01xxxxxxxx0001xxx1xxxx", InstName.Vbic, InstEmit32.Vbic_I, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32); SetAsimd("111100100x01xxxxxxxx0001xxx1xxxx", InstName.Vbic, InstEmit32.Vbic_I, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32);
SetAsimd("1111001x1x000xxxxxxx<<x10x11xxxx", InstName.Vbic, InstEmit32.Vbic_II, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32); SetAsimd("1111001x1x000xxxxxxx<<x10x11xxxx", InstName.Vbic, InstEmit32.Vbic_II, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32);
SetAsimd("111100110x11xxxxxxxx0001xxx1xxxx", InstName.Vbif, InstEmit32.Vbif, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32); SetAsimd("111100110x11xxxxxxxx0001xxx1xxxx", InstName.Vbif, InstEmit32.Vbif, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32);
SetAsimd("111100110x10xxxxxxxx0001xxx1xxxx", InstName.Vbit, InstEmit32.Vbit, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32); SetAsimd("111100110x10xxxxxxxx0001xxx1xxxx", InstName.Vbit, InstEmit32.Vbit, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32);
SetAsimd("111100110x01xxxxxxxx0001xxx1xxxx", InstName.Vbsl, InstEmit32.Vbsl, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32); SetAsimd("111100110x01xxxxxxxx0001xxx1xxxx", InstName.Vbsl, InstEmit32.Vbsl, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32);
SetAsimd("111100110x<<xxxxxxxx1000xxx1xxxx", InstName.Vceq, InstEmit32.Vceq_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("111100110x<<xxxxxxxx1000xxx1xxxx", InstName.Vceq, InstEmit32.Vceq_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("111100100x00xxxxxxxx1110xxx0xxxx", InstName.Vceq, InstEmit32.Vceq_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("111100100x00xxxxxxxx1110xxx0xxxx", InstName.Vceq, InstEmit32.Vceq_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("111100111x11xx01xxxx0x010xx0xxxx", InstName.Vceq, InstEmit32.Vceq_Z, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32); SetAsimd("111100111x11xx01xxxx0x010xx0xxxx", InstName.Vceq, InstEmit32.Vceq_Z, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
SetAsimd("1111001x0x<<xxxxxxxx0011xxx1xxxx", InstName.Vcge, InstEmit32.Vcge_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("1111001x0x<<xxxxxxxx0011xxx1xxxx", InstName.Vcge, InstEmit32.Vcge_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("111100110x00xxxxxxxx1110xxx0xxxx", InstName.Vcge, InstEmit32.Vcge_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("111100110x00xxxxxxxx1110xxx0xxxx", InstName.Vcge, InstEmit32.Vcge_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("111100111x11xx01xxxx0x001xx0xxxx", InstName.Vcge, InstEmit32.Vcge_Z, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32); SetAsimd("111100111x11xx01xxxx0x001xx0xxxx", InstName.Vcge, InstEmit32.Vcge_Z, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
SetAsimd("1111001x0x<<xxxxxxxx0011xxx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("1111001x0x<<xxxxxxxx0011xxx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("111100110x10xxxxxxxx1110xxx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("111100110x10xxxxxxxx1110xxx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("111100111x11xx01xxxx0x000xx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_Z, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32); SetAsimd("111100111x11xx01xxxx0x000xx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_Z, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
SetAsimd("111100111x11xx01xxxx0x011xx0xxxx", InstName.Vcle, InstEmit32.Vcle_Z, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32); SetAsimd("111100111x11xx01xxxx0x011xx0xxxx", InstName.Vcle, InstEmit32.Vcle_Z, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
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("111100111x11xxxxxxxx11000xx0xxxx", InstName.Vdup, InstEmit32.Vdup_1, OpCode32SimdDupElem.Create, OpCode32SimdDupElem.CreateT32); SetAsimd("1111001x1x1xxxxxxxxx111x0xx1xxxx", InstName.Vcvt, InstEmit32.Vcvt_V_Fixed, OpCode32SimdCvtFFixed.Create, OpCode32SimdCvtFFixed.CreateT32); // Between floating point and fixed point, vector.
SetAsimd("111100110x00xxxxxxxx0001xxx1xxxx", InstName.Veor, InstEmit32.Veor_I, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32); SetAsimd("111100111x11xxxxxxxx11000xx0xxxx", InstName.Vdup, InstEmit32.Vdup_1, OpCode32SimdDupElem.Create, OpCode32SimdDupElem.CreateT32);
SetAsimd("111100101x11xxxxxxxxxxxxxxx0xxxx", InstName.Vext, InstEmit32.Vext, OpCode32SimdExt.Create, OpCode32SimdExt.CreateT32); SetAsimd("111100110x00xxxxxxxx0001xxx1xxxx", InstName.Veor, InstEmit32.Veor_I, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32);
SetAsimd("111100100x00xxxxxxxx1100xxx1xxxx", InstName.Vfma, InstEmit32.Vfma_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("111100101x11xxxxxxxxxxxxxxx0xxxx", InstName.Vext, InstEmit32.Vext, OpCode32SimdExt.Create, OpCode32SimdExt.CreateT32);
SetAsimd("111100100x10xxxxxxxx1100xxx1xxxx", InstName.Vfms, InstEmit32.Vfms_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("111100100x00xxxxxxxx1100xxx1xxxx", InstName.Vfma, InstEmit32.Vfma_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("1111001x0x<<xxxxxxxx0000xxx0xxxx", InstName.Vhadd, InstEmit32.Vhadd, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("111100100x10xxxxxxxx1100xxx1xxxx", InstName.Vfms, InstEmit32.Vfms_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("111101001x10xxxxxxxx0000xxx0xxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32); SetAsimd("1111001x0x<<xxxxxxxx0000xxx0xxxx", InstName.Vhadd, InstEmit32.Vhadd, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("111101001x10xxxxxxxx0100xx0xxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32); SetAsimd("111101001x10xxxxxxxx0000xxx0xxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetAsimd("111101001x10xxxxxxxx1000x000xxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32); SetAsimd("111101001x10xxxxxxxx0100xx0xxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetAsimd("111101001x10xxxxxxxx1000x011xxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32); SetAsimd("111101001x10xxxxxxxx1000x000xxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetAsimd("111101001x10xxxxxxxx110000x0xxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32); SetAsimd("111101001x10xxxxxxxx1000x011xxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetAsimd("111101001x10xxxxxxxx110001xxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32); SetAsimd("111101001x10xxxxxxxx110000x0xxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetAsimd("111101001x10xxxxxxxx110010xxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32); SetAsimd("111101001x10xxxxxxxx110001xxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetAsimd("111101000x10xxxxxxxx0111xx0xxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 1. SetAsimd("111101001x10xxxxxxxx110010xxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetAsimd("111101000x10xxxxxxxx1010xx<<xxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 2. SetAsimd("111101000x10xxxxxxxx0111xx0xxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 1.
SetAsimd("111101000x10xxxxxxxx0110xx0xxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 3. SetAsimd("111101000x10xxxxxxxx1010xx<<xxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 2.
SetAsimd("111101000x10xxxxxxxx0010xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 4. SetAsimd("111101000x10xxxxxxxx0110xx0xxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 3.
SetAsimd("111101001x10xxxxxxxx0x01xxxxxxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32); SetAsimd("111101000x10xxxxxxxx0010xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 4.
SetAsimd("111101001x10xxxxxxxx1001xx0xxxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32); SetAsimd("111101001x10xxxxxxxx0x01xxxxxxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetAsimd("111101001x10xxxxxxxx1101<<xxxxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32); SetAsimd("111101001x10xxxxxxxx1001xx0xxxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetAsimd("111101000x10xxxxxxxx100x<<0xxxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 1, inc = 1/2 (itype). SetAsimd("111101001x10xxxxxxxx1101<<xxxxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetAsimd("111101000x10xxxxxxxx100x<<10xxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 1, inc = 1/2 (itype). SetAsimd("111101000x10xxxxxxxx100x<<0xxxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 1, inc = 1/2 (itype).
SetAsimd("111101000x10xxxxxxxx0011<<xxxxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 2, inc = 2. SetAsimd("111101000x10xxxxxxxx100x<<10xxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 1, inc = 1/2 (itype).
SetAsimd("111101001x10xxxxxxxx0x10xxx0xxxx", InstName.Vld3, InstEmit32.Vld3, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32); SetAsimd("111101000x10xxxxxxxx0011<<xxxxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 2, inc = 2.
SetAsimd("111101001x10xxxxxxxx1010xx00xxxx", InstName.Vld3, InstEmit32.Vld3, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32); SetAsimd("111101001x10xxxxxxxx0x10xxx0xxxx", InstName.Vld3, InstEmit32.Vld3, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetAsimd("111101001x10xxxxxxxx1110<<x0xxxx", InstName.Vld3, InstEmit32.Vld3, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32); SetAsimd("111101001x10xxxxxxxx1010xx00xxxx", InstName.Vld3, InstEmit32.Vld3, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetAsimd("111101000x10xxxxxxxx010x<<0xxxxx", InstName.Vld3, InstEmit32.Vld3, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Inc = 1/2 (itype). SetAsimd("111101001x10xxxxxxxx1110<<x0xxxx", InstName.Vld3, InstEmit32.Vld3, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetAsimd("111101001x10xxxxxxxx0x11xxxxxxxx", InstName.Vld4, InstEmit32.Vld4, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32); SetAsimd("111101000x10xxxxxxxx010x<<0xxxxx", InstName.Vld3, InstEmit32.Vld3, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Inc = 1/2 (itype).
SetAsimd("111101001x10xxxxxxxx1011xx<<xxxx", InstName.Vld4, InstEmit32.Vld4, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32); SetAsimd("111101001x10xxxxxxxx0x11xxxxxxxx", InstName.Vld4, InstEmit32.Vld4, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetAsimd("111101001x10xxxxxxxx1111<<x>xxxx", InstName.Vld4, InstEmit32.Vld4, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32); SetAsimd("111101001x10xxxxxxxx1011xx<<xxxx", InstName.Vld4, InstEmit32.Vld4, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetAsimd("111101000x10xxxxxxxx000x<<xxxxxx", InstName.Vld4, InstEmit32.Vld4, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Inc = 1/2 (itype). SetAsimd("111101001x10xxxxxxxx1111<<x>xxxx", InstName.Vld4, InstEmit32.Vld4, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetAsimd("1111001x0x<<xxxxxxxx0110xxx0xxxx", InstName.Vmax, InstEmit32.Vmax_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("111101000x10xxxxxxxx000x<<xxxxxx", InstName.Vld4, InstEmit32.Vld4, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Inc = 1/2 (itype).
SetAsimd("111100100x00xxxxxxxx1111xxx0xxxx", InstName.Vmax, InstEmit32.Vmax_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("1111001x0x<<xxxxxxxx0110xxx0xxxx", InstName.Vmax, InstEmit32.Vmax_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("1111001x0x<<xxxxxxxx0110xxx1xxxx", InstName.Vmin, InstEmit32.Vmin_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("111100100x00xxxxxxxx1111xxx0xxxx", InstName.Vmax, InstEmit32.Vmax_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("111100100x10xxxxxxxx1111xxx0xxxx", InstName.Vmin, InstEmit32.Vmin_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("1111001x0x<<xxxxxxxx0110xxx1xxxx", InstName.Vmin, InstEmit32.Vmin_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("111100110x0xxxxxxxxx1111xxx1xxxx", InstName.Vmaxnm, InstEmit32.Vmaxnm_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("111100100x10xxxxxxxx1111xxx0xxxx", InstName.Vmin, InstEmit32.Vmin_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("111100110x1xxxxxxxxx1111xxx1xxxx", InstName.Vminnm, InstEmit32.Vminnm_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("111100110x0xxxxxxxxx1111xxx1xxxx", InstName.Vmaxnm, InstEmit32.Vmaxnm_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("1111001x1x<<xxxxxxxx000xx1x0xxxx", InstName.Vmla, InstEmit32.Vmla_1, OpCode32SimdRegElem.Create, OpCode32SimdRegElem.CreateT32); SetAsimd("111100110x1xxxxxxxxx1111xxx1xxxx", InstName.Vminnm, InstEmit32.Vminnm_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("111100100xxxxxxxxxxx1001xxx0xxxx", InstName.Vmla, InstEmit32.Vmla_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("1111001x1x<<xxxxxxxx000xx1x0xxxx", InstName.Vmla, InstEmit32.Vmla_1, OpCode32SimdRegElem.Create, OpCode32SimdRegElem.CreateT32);
SetAsimd("111100100x00xxxxxxxx1101xxx1xxxx", InstName.Vmla, InstEmit32.Vmla_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("111100100xxxxxxxxxxx1001xxx0xxxx", InstName.Vmla, InstEmit32.Vmla_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("1111001x1x<<xxxxxxx01000x0x0xxxx", InstName.Vmlal, InstEmit32.Vmlal_I, OpCode32SimdRegLong.Create, OpCode32SimdRegLong.CreateT32); SetAsimd("111100100x00xxxxxxxx1101xxx1xxxx", InstName.Vmla, InstEmit32.Vmla_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("1111001x1x<<xxxxxxxx010xx1x0xxxx", InstName.Vmls, InstEmit32.Vmls_1, OpCode32SimdRegElem.Create, OpCode32SimdRegElem.CreateT32); SetAsimd("1111001x1x<<xxxxxxx01000x0x0xxxx", InstName.Vmlal, InstEmit32.Vmlal_I, OpCode32SimdRegLong.Create, OpCode32SimdRegLong.CreateT32);
SetAsimd("111100100x10xxxxxxxx1101xxx1xxxx", InstName.Vmls, InstEmit32.Vmls_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("1111001x1x<<xxxxxxxx010xx1x0xxxx", InstName.Vmls, InstEmit32.Vmls_1, OpCode32SimdRegElem.Create, OpCode32SimdRegElem.CreateT32);
SetAsimd("111100110xxxxxxxxxxx1001xxx0xxxx", InstName.Vmls, InstEmit32.Vmls_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("111100100x10xxxxxxxx1101xxx1xxxx", InstName.Vmls, InstEmit32.Vmls_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("1111001x1x<<xxxxxxx01010x0x0xxxx", InstName.Vmlsl, InstEmit32.Vmlsl_I, OpCode32SimdRegLong.Create, OpCode32SimdRegLong.CreateT32); SetAsimd("111100110xxxxxxxxxxx1001xxx0xxxx", InstName.Vmls, InstEmit32.Vmls_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("1111001x1x000xxxxxxx0xx00x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32); // D/Q vector I32. SetAsimd("1111001x1x<<xxxxxxx01010x0x0xxxx", InstName.Vmlsl, InstEmit32.Vmlsl_I, OpCode32SimdRegLong.Create, OpCode32SimdRegLong.CreateT32);
SetAsimd("1111001x1x000xxxxxxx10x00x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32); // D/Q I16. SetAsimd("1111001x1x000xxxxxxx0xx00x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32); // D/Q vector I32.
SetAsimd("1111001x1x000xxxxxxx11xx0x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32); // D/Q (dt - from cmode). SetAsimd("1111001x1x000xxxxxxx10x00x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32); // D/Q I16.
SetAsimd("1111001x1x000xxxxxxx11100x11xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32); // D/Q I64. SetAsimd("1111001x1x000xxxxxxx11xx0x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32); // D/Q (dt - from cmode).
SetAsimd("1111001x1x001000xxx0101000x1xxxx", InstName.Vmovl, InstEmit32.Vmovl, OpCode32SimdLong.Create, OpCode32SimdLong.CreateT32); SetAsimd("1111001x1x000xxxxxxx11100x11xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32); // D/Q I64.
SetAsimd("1111001x1x010000xxx0101000x1xxxx", InstName.Vmovl, InstEmit32.Vmovl, OpCode32SimdLong.Create, OpCode32SimdLong.CreateT32); SetAsimd("1111001x1x001000xxx0101000x1xxxx", InstName.Vmovl, InstEmit32.Vmovl, OpCode32SimdLong.Create, OpCode32SimdLong.CreateT32);
SetAsimd("1111001x1x100000xxx0101000x1xxxx", InstName.Vmovl, InstEmit32.Vmovl, OpCode32SimdLong.Create, OpCode32SimdLong.CreateT32); SetAsimd("1111001x1x010000xxx0101000x1xxxx", InstName.Vmovl, InstEmit32.Vmovl, OpCode32SimdLong.Create, OpCode32SimdLong.CreateT32);
SetAsimd("111100111x11<<10xxxx001000x0xxx0", InstName.Vmovn, InstEmit32.Vmovn, OpCode32SimdMovn.Create, OpCode32SimdMovn.CreateT32); SetAsimd("1111001x1x100000xxx0101000x1xxxx", InstName.Vmovl, InstEmit32.Vmovl, OpCode32SimdLong.Create, OpCode32SimdLong.CreateT32);
SetAsimd("1111001x1x<<xxxxxxxx100xx1x0xxxx", InstName.Vmul, InstEmit32.Vmul_1, OpCode32SimdRegElem.Create, OpCode32SimdRegElem.CreateT32); SetAsimd("111100111x11<<10xxxx001000x0xxx0", InstName.Vmovn, InstEmit32.Vmovn, OpCode32SimdMovn.Create, OpCode32SimdMovn.CreateT32);
SetAsimd("111100100x<<xxxxxxxx1001xxx1xxxx", InstName.Vmul, InstEmit32.Vmul_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("1111001x1x<<xxxxxxxx100xx1x0xxxx", InstName.Vmul, InstEmit32.Vmul_1, OpCode32SimdRegElem.Create, OpCode32SimdRegElem.CreateT32);
SetAsimd("111100110x00xxxxxxxx1001xxx1xxxx", InstName.Vmul, InstEmit32.Vmul_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("111100100x<<xxxxxxxx1001xxx1xxxx", InstName.Vmul, InstEmit32.Vmul_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("111100110x00xxxxxxxx1101xxx1xxxx", InstName.Vmul, InstEmit32.Vmul_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("111100110x00xxxxxxxx1001xxx1xxxx", InstName.Vmul, InstEmit32.Vmul_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("1111001x1x<<xxxxxxx01010x1x0xxxx", InstName.Vmull, InstEmit32.Vmull_1, OpCode32SimdRegElemLong.Create, OpCode32SimdRegElemLong.CreateT32); SetAsimd("111100110x00xxxxxxxx1101xxx1xxxx", InstName.Vmul, InstEmit32.Vmul_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("1111001x1x<<xxxxxxx01100x0x0xxxx", InstName.Vmull, InstEmit32.Vmull_I, OpCode32SimdRegLong.Create, OpCode32SimdRegLong.CreateT32); SetAsimd("1111001x1x<<xxxxxxx01010x1x0xxxx", InstName.Vmull, InstEmit32.Vmull_1, OpCode32SimdRegElemLong.Create, OpCode32SimdRegElemLong.CreateT32);
SetAsimd("111100101xx0xxxxxxx01110x0x0xxxx", InstName.Vmull, InstEmit32.Vmull_I, OpCode32SimdRegLong.Create, OpCode32SimdRegLong.CreateT32); // P8/P64 SetAsimd("1111001x1x<<xxxxxxx01100x0x0xxxx", InstName.Vmull, InstEmit32.Vmull_I, OpCode32SimdRegLong.Create, OpCode32SimdRegLong.CreateT32);
SetAsimd("111100111x110000xxxx01011xx0xxxx", InstName.Vmvn, InstEmit32.Vmvn_I, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32); SetAsimd("111100101xx0xxxxxxx01110x0x0xxxx", InstName.Vmull, InstEmit32.Vmull_I, OpCode32SimdRegLong.Create, OpCode32SimdRegLong.CreateT32); // P8/P64
SetAsimd("1111001x1x000xxxxxxx0xx00x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_II, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32); // D/Q vector I32. SetAsimd("111100111x110000xxxx01011xx0xxxx", InstName.Vmvn, InstEmit32.Vmvn_I, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32);
SetAsimd("1111001x1x000xxxxxxx10x00x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_II, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32); SetAsimd("1111001x1x000xxxxxxx0xx00x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_II, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32); // D/Q vector I32.
SetAsimd("1111001x1x000xxxxxxx110x0x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_II, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32); SetAsimd("1111001x1x000xxxxxxx10x00x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_II, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32);
SetAsimd("111100111x11<<01xxxx00111xx0xxxx", InstName.Vneg, InstEmit32.Vneg_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32); SetAsimd("1111001x1x000xxxxxxx110x0x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_II, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32);
SetAsimd("111100111x111001xxxx01111xx0xxxx", InstName.Vneg, InstEmit32.Vneg_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32); SetAsimd("111100111x11<<01xxxx00111xx0xxxx", InstName.Vneg, InstEmit32.Vneg_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
SetAsimd("111100100x11xxxxxxxx0001xxx1xxxx", InstName.Vorn, InstEmit32.Vorn_I, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32); SetAsimd("111100111x111001xxxx01111xx0xxxx", InstName.Vneg, InstEmit32.Vneg_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
SetAsimd("111100100x10xxxxxxxx0001xxx1xxxx", InstName.Vorr, InstEmit32.Vorr_I, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32); SetAsimd("111100100x11xxxxxxxx0001xxx1xxxx", InstName.Vorn, InstEmit32.Vorn_I, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32);
SetAsimd("1111001x1x000xxxxxxx<<x10x01xxxx", InstName.Vorr, InstEmit32.Vorr_II, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32); SetAsimd("111100100x10xxxxxxxx0001xxx1xxxx", InstName.Vorr, InstEmit32.Vorr_I, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32);
SetAsimd("111100100x<<xxxxxxxx1011x0x1xxxx", InstName.Vpadd, InstEmit32.Vpadd_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("1111001x1x000xxxxxxx<<x10x01xxxx", InstName.Vorr, InstEmit32.Vorr_II, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32);
SetAsimd("111100110x00xxxxxxxx1101x0x0xxxx", InstName.Vpadd, InstEmit32.Vpadd_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("111100100x<<xxxxxxxx1011x0x1xxxx", InstName.Vpadd, InstEmit32.Vpadd_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("111100111x11<<00xxxx0010xxx0xxxx", InstName.Vpaddl, InstEmit32.Vpaddl, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32); SetAsimd("111100110x00xxxxxxxx1101x0x0xxxx", InstName.Vpadd, InstEmit32.Vpadd_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("1111001x0x<<xxxxxxxx1010x0x0xxxx", InstName.Vpmax, InstEmit32.Vpmax_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("111100111x11<<00xxxx0010xxx0xxxx", InstName.Vpaddl, InstEmit32.Vpaddl, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
SetAsimd("111100110x00xxxxxxxx1111x0x0xxxx", InstName.Vpmax, InstEmit32.Vpmax_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("1111001x0x<<xxxxxxxx1010x0x0xxxx", InstName.Vpmax, InstEmit32.Vpmax_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("1111001x0x<<xxxxxxxx1010x0x1xxxx", InstName.Vpmin, InstEmit32.Vpmin_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("111100110x00xxxxxxxx1111x0x0xxxx", InstName.Vpmax, InstEmit32.Vpmax_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("111100110x10xxxxxxxx1111x0x0xxxx", InstName.Vpmin, InstEmit32.Vpmin_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("1111001x0x<<xxxxxxxx1010x0x1xxxx", InstName.Vpmin, InstEmit32.Vpmin_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("1111001x0xxxxxxxxxxx0000xxx1xxxx", InstName.Vqadd, InstEmit32.Vqadd, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("111100110x10xxxxxxxx1111x0x0xxxx", InstName.Vpmin, InstEmit32.Vpmin_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("111100100x01xxxxxxxx1011xxx0xxxx", InstName.Vqdmulh, InstEmit32.Vqdmulh, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("1111001x0xxxxxxxxxxx0000xxx1xxxx", InstName.Vqadd, InstEmit32.Vqadd, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("111100100x10xxxxxxxx1011xxx0xxxx", InstName.Vqdmulh, InstEmit32.Vqdmulh, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("111100100x01xxxxxxxx1011xxx0xxxx", InstName.Vqdmulh, InstEmit32.Vqdmulh, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("111100111x11<<10xxxx00101xx0xxx0", InstName.Vqmovn, InstEmit32.Vqmovn, OpCode32SimdMovn.Create, OpCode32SimdMovn.CreateT32); SetAsimd("111100100x10xxxxxxxx1011xxx0xxxx", InstName.Vqdmulh, InstEmit32.Vqdmulh, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("111100111x11<<10xxxx001001x0xxx0", InstName.Vqmovun, InstEmit32.Vqmovun, OpCode32SimdMovn.Create, OpCode32SimdMovn.CreateT32); SetAsimd("111100111x11<<10xxxx00101xx0xxx0", InstName.Vqmovn, InstEmit32.Vqmovn, OpCode32SimdMovn.Create, OpCode32SimdMovn.CreateT32);
SetAsimd("1111001x1x>>>xxxxxxx100101x1xxx0", InstName.Vqrshrn, InstEmit32.Vqrshrn, OpCode32SimdShImmNarrow.Create, OpCode32SimdShImmNarrow.CreateT32); SetAsimd("111100111x11<<10xxxx001001x0xxx0", InstName.Vqmovun, InstEmit32.Vqmovun, OpCode32SimdMovn.Create, OpCode32SimdMovn.CreateT32);
SetAsimd("111100111x>>>xxxxxxx100001x1xxx0", InstName.Vqrshrun, InstEmit32.Vqrshrun, OpCode32SimdShImmNarrow.Create, OpCode32SimdShImmNarrow.CreateT32); SetAsimd("1111001x1x>>>xxxxxxx100101x1xxx0", InstName.Vqrshrn, InstEmit32.Vqrshrn, OpCode32SimdShImmNarrow.Create, OpCode32SimdShImmNarrow.CreateT32);
SetAsimd("1111001x1x>>>xxxxxxx100100x1xxx0", InstName.Vqshrn, InstEmit32.Vqshrn, OpCode32SimdShImmNarrow.Create, OpCode32SimdShImmNarrow.CreateT32); SetAsimd("111100111x>>>xxxxxxx100001x1xxx0", InstName.Vqrshrun, InstEmit32.Vqrshrun, OpCode32SimdShImmNarrow.Create, OpCode32SimdShImmNarrow.CreateT32);
SetAsimd("111100111x>>>xxxxxxx100000x1xxx0", InstName.Vqshrun, InstEmit32.Vqshrun, OpCode32SimdShImmNarrow.Create, OpCode32SimdShImmNarrow.CreateT32); SetAsimd("1111001x1x>>>xxxxxxx100100x1xxx0", InstName.Vqshrn, InstEmit32.Vqshrn, OpCode32SimdShImmNarrow.Create, OpCode32SimdShImmNarrow.CreateT32);
SetAsimd("1111001x0xxxxxxxxxxx0010xxx1xxxx", InstName.Vqsub, InstEmit32.Vqsub, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("111100111x>>>xxxxxxx100000x1xxx0", InstName.Vqshrun, InstEmit32.Vqshrun, OpCode32SimdShImmNarrow.Create, OpCode32SimdShImmNarrow.CreateT32);
SetAsimd("111100111x111011xxxx010x0xx0xxxx", InstName.Vrecpe, InstEmit32.Vrecpe, OpCode32SimdSqrte.Create, OpCode32SimdSqrte.CreateT32); SetAsimd("1111001x0xxxxxxxxxxx0010xxx1xxxx", InstName.Vqsub, InstEmit32.Vqsub, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("111100100x00xxxxxxxx1111xxx1xxxx", InstName.Vrecps, InstEmit32.Vrecps, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("111100111x111011xxxx010x0xx0xxxx", InstName.Vrecpe, InstEmit32.Vrecpe, OpCode32SimdSqrte.Create, OpCode32SimdSqrte.CreateT32);
SetAsimd("111100111x11xx00xxxx000<<xx0xxxx", InstName.Vrev, InstEmit32.Vrev, OpCode32SimdRev.Create, OpCode32SimdRev.CreateT32); SetAsimd("111100100x00xxxxxxxx1111xxx1xxxx", InstName.Vrecps, InstEmit32.Vrecps, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("1111001x0x<<xxxxxxxx0001xxx0xxxx", InstName.Vrhadd, InstEmit32.Vrhadd, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("111100111x11xx00xxxx000<<xx0xxxx", InstName.Vrev, InstEmit32.Vrev, OpCode32SimdRev.Create, OpCode32SimdRev.CreateT32);
SetAsimd("111100111x111010xxxx01010xx0xxxx", InstName.Vrinta, InstEmit32.Vrinta_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32); SetAsimd("1111001x0x<<xxxxxxxx0001xxx0xxxx", InstName.Vrhadd, InstEmit32.Vrhadd, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("111100111x111010xxxx01101xx0xxxx", InstName.Vrintm, InstEmit32.Vrintm_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32); SetAsimd("111100111x111010xxxx01010xx0xxxx", InstName.Vrinta, InstEmit32.Vrinta_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
SetAsimd("111100111x111010xxxx01000xx0xxxx", InstName.Vrintn, InstEmit32.Vrintn_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32); SetAsimd("111100111x111010xxxx01101xx0xxxx", InstName.Vrintm, InstEmit32.Vrintm_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
SetAsimd("111100111x111010xxxx01111xx0xxxx", InstName.Vrintp, InstEmit32.Vrintp_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32); SetAsimd("111100111x111010xxxx01000xx0xxxx", InstName.Vrintn, InstEmit32.Vrintn_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
SetAsimd("1111001x1x>>>xxxxxxx0010>xx1xxxx", InstName.Vrshr, InstEmit32.Vrshr, OpCode32SimdShImm.Create, OpCode32SimdShImm.CreateT32); SetAsimd("111100111x111010xxxx01111xx0xxxx", InstName.Vrintp, InstEmit32.Vrintp_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
SetAsimd("111100101x>>>xxxxxxx100001x1xxx0", InstName.Vrshrn, InstEmit32.Vrshrn, OpCode32SimdShImmNarrow.Create, OpCode32SimdShImmNarrow.CreateT32); SetAsimd("1111001x1x>>>xxxxxxx0010>xx1xxxx", InstName.Vrshr, InstEmit32.Vrshr, OpCode32SimdShImm.Create, OpCode32SimdShImm.CreateT32);
SetAsimd("111100111x111011xxxx010x1xx0xxxx", InstName.Vrsqrte, InstEmit32.Vrsqrte, OpCode32SimdSqrte.Create, OpCode32SimdSqrte.CreateT32); SetAsimd("111100101x>>>xxxxxxx100001x1xxx0", InstName.Vrshrn, InstEmit32.Vrshrn, OpCode32SimdShImmNarrow.Create, OpCode32SimdShImmNarrow.CreateT32);
SetAsimd("111100100x10xxxxxxxx1111xxx1xxxx", InstName.Vrsqrts, InstEmit32.Vrsqrts, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("111100111x111011xxxx010x1xx0xxxx", InstName.Vrsqrte, InstEmit32.Vrsqrte, OpCode32SimdSqrte.Create, OpCode32SimdSqrte.CreateT32);
SetAsimd("1111001x1x>>>xxxxxxx0011>xx1xxxx", InstName.Vrsra, InstEmit32.Vrsra, OpCode32SimdShImm.Create, OpCode32SimdShImm.CreateT32); SetAsimd("111100100x10xxxxxxxx1111xxx1xxxx", InstName.Vrsqrts, InstEmit32.Vrsqrts, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("111100101x>>>xxxxxxx0101>xx1xxxx", InstName.Vshl, InstEmit32.Vshl, OpCode32SimdShImm.Create, OpCode32SimdShImm.CreateT32); SetAsimd("1111001x1x>>>xxxxxxx0011>xx1xxxx", InstName.Vrsra, InstEmit32.Vrsra, OpCode32SimdShImm.Create, OpCode32SimdShImm.CreateT32);
SetAsimd("1111001x0xxxxxxxxxxx0100xxx0xxxx", InstName.Vshl, InstEmit32.Vshl_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("111100101x>>>xxxxxxx0101>xx1xxxx", InstName.Vshl, InstEmit32.Vshl, OpCode32SimdShImm.Create, OpCode32SimdShImm.CreateT32);
SetAsimd("1111001x1x>>>xxxxxxx101000x1xxxx", InstName.Vshll, InstEmit32.Vshll, OpCode32SimdShImmLong.Create, OpCode32SimdShImmLong.CreateT32); // A1 encoding. SetAsimd("1111001x0xxxxxxxxxxx0100xxx0xxxx", InstName.Vshl, InstEmit32.Vshl_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("1111001x1x>>>xxxxxxx0000>xx1xxxx", InstName.Vshr, InstEmit32.Vshr, OpCode32SimdShImm.Create, OpCode32SimdShImm.CreateT32); SetAsimd("1111001x1x>>>xxxxxxx101000x1xxxx", InstName.Vshll, InstEmit32.Vshll, OpCode32SimdShImmLong.Create, OpCode32SimdShImmLong.CreateT32); // A1 encoding.
SetAsimd("111100101x>>>xxxxxxx100000x1xxx0", InstName.Vshrn, InstEmit32.Vshrn, OpCode32SimdShImmNarrow.Create, OpCode32SimdShImmNarrow.CreateT32); SetAsimd("1111001x1x>>>xxxxxxx0000>xx1xxxx", InstName.Vshr, InstEmit32.Vshr, OpCode32SimdShImm.Create, OpCode32SimdShImm.CreateT32);
SetAsimd("1111001x1x>>>xxxxxxx0001>xx1xxxx", InstName.Vsra, InstEmit32.Vsra, OpCode32SimdShImm.Create, OpCode32SimdShImm.CreateT32); SetAsimd("111100101x>>>xxxxxxx100000x1xxx0", InstName.Vshrn, InstEmit32.Vshrn, OpCode32SimdShImmNarrow.Create, OpCode32SimdShImmNarrow.CreateT32);
SetAsimd("111101001x00xxxxxxxx0000xxx0xxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32); SetAsimd("1111001x1x>>>xxxxxxx0001>xx1xxxx", InstName.Vsra, InstEmit32.Vsra, OpCode32SimdShImm.Create, OpCode32SimdShImm.CreateT32);
SetAsimd("111101001x00xxxxxxxx0100xx0xxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32); SetAsimd("111101001x00xxxxxxxx0000xxx0xxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetAsimd("111101001x00xxxxxxxx1000x000xxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32); SetAsimd("111101001x00xxxxxxxx0100xx0xxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetAsimd("111101001x00xxxxxxxx1000x011xxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32); SetAsimd("111101001x00xxxxxxxx1000x000xxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetAsimd("111101000x00xxxxxxxx0111xx0xxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 1. SetAsimd("111101001x00xxxxxxxx1000x011xxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetAsimd("111101000x00xxxxxxxx1010xx<<xxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 2. SetAsimd("111101000x00xxxxxxxx0111xx0xxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 1.
SetAsimd("111101000x00xxxxxxxx0110xx0xxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 3. SetAsimd("111101000x00xxxxxxxx1010xx<<xxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 2.
SetAsimd("111101000x00xxxxxxxx0010xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 4. SetAsimd("111101000x00xxxxxxxx0110xx0xxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 3.
SetAsimd("111101001x00xxxxxxxx0x01xxxxxxxx", InstName.Vst2, InstEmit32.Vst2, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32); SetAsimd("111101000x00xxxxxxxx0010xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 4.
SetAsimd("111101001x00xxxxxxxx1001xx0xxxxx", InstName.Vst2, InstEmit32.Vst2, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32); SetAsimd("111101001x00xxxxxxxx0x01xxxxxxxx", InstName.Vst2, InstEmit32.Vst2, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetAsimd("111101000x00xxxxxxxx100x<<0xxxxx", InstName.Vst2, InstEmit32.Vst2, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 1, inc = 1/2 (itype). SetAsimd("111101001x00xxxxxxxx1001xx0xxxxx", InstName.Vst2, InstEmit32.Vst2, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetAsimd("111101000x00xxxxxxxx100x<<10xxxx", InstName.Vst2, InstEmit32.Vst2, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 1, inc = 1/2 (itype). SetAsimd("111101000x00xxxxxxxx100x<<0xxxxx", InstName.Vst2, InstEmit32.Vst2, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 1, inc = 1/2 (itype).
SetAsimd("111101000x00xxxxxxxx0011<<xxxxxx", InstName.Vst2, InstEmit32.Vst2, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 2, inc = 2. SetAsimd("111101000x00xxxxxxxx100x<<10xxxx", InstName.Vst2, InstEmit32.Vst2, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 1, inc = 1/2 (itype).
SetAsimd("111101001x00xxxxxxxx0x10xxx0xxxx", InstName.Vst3, InstEmit32.Vst3, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32); SetAsimd("111101000x00xxxxxxxx0011<<xxxxxx", InstName.Vst2, InstEmit32.Vst2, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 2, inc = 2.
SetAsimd("111101001x00xxxxxxxx1010xx00xxxx", InstName.Vst3, InstEmit32.Vst3, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32); SetAsimd("111101001x00xxxxxxxx0x10xxx0xxxx", InstName.Vst3, InstEmit32.Vst3, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetAsimd("111101000x00xxxxxxxx010x<<0xxxxx", InstName.Vst3, InstEmit32.Vst3, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Inc = 1/2 (itype). SetAsimd("111101001x00xxxxxxxx1010xx00xxxx", InstName.Vst3, InstEmit32.Vst3, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetAsimd("111101001x00xxxxxxxx0x11xxxxxxxx", InstName.Vst4, InstEmit32.Vst4, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32); SetAsimd("111101000x00xxxxxxxx010x<<0xxxxx", InstName.Vst3, InstEmit32.Vst3, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Inc = 1/2 (itype).
SetAsimd("111101001x00xxxxxxxx1011xx<<xxxx", InstName.Vst4, InstEmit32.Vst4, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32); SetAsimd("111101001x00xxxxxxxx0x11xxxxxxxx", InstName.Vst4, InstEmit32.Vst4, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetAsimd("111101000x00xxxxxxxx000x<<xxxxxx", InstName.Vst4, InstEmit32.Vst4, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Inc = 1/2 (itype). SetAsimd("111101001x00xxxxxxxx1011xx<<xxxx", InstName.Vst4, InstEmit32.Vst4, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
SetAsimd("111100110xxxxxxxxxxx1000xxx0xxxx", InstName.Vsub, InstEmit32.Vsub_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("111101000x00xxxxxxxx000x<<xxxxxx", InstName.Vst4, InstEmit32.Vst4, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Inc = 1/2 (itype).
SetAsimd("111100100x10xxxxxxxx1101xxx0xxxx", InstName.Vsub, InstEmit32.Vsub_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("111100110xxxxxxxxxxx1000xxx0xxxx", InstName.Vsub, InstEmit32.Vsub_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("1111001x1x<<xxxxxxx00010x0x0xxxx", InstName.Vsubl, InstEmit32.Vsubl_I, OpCode32SimdRegLong.Create, OpCode32SimdRegLong.CreateT32); SetAsimd("111100100x10xxxxxxxx1101xxx0xxxx", InstName.Vsub, InstEmit32.Vsub_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("1111001x1x<<xxxxxxx00011x0x0xxxx", InstName.Vsubw, InstEmit32.Vsubw_I, OpCode32SimdRegWide.Create, OpCode32SimdRegWide.CreateT32); SetAsimd("1111001x1x<<xxxxxxx00010x0x0xxxx", InstName.Vsubl, InstEmit32.Vsubl_I, OpCode32SimdRegLong.Create, OpCode32SimdRegLong.CreateT32);
SetAsimd("111100111x11xxxxxxxx10xxxxx0xxxx", InstName.Vtbl, InstEmit32.Vtbl, OpCode32SimdTbl.Create, OpCode32SimdTbl.CreateT32); SetAsimd("1111001x1x<<xxxxxxx00011x0x0xxxx", InstName.Vsubw, InstEmit32.Vsubw_I, OpCode32SimdRegWide.Create, OpCode32SimdRegWide.CreateT32);
SetAsimd("111100111x11<<10xxxx00001xx0xxxx", InstName.Vtrn, InstEmit32.Vtrn, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32); SetAsimd("111100111x11xxxxxxxx10xxxxx0xxxx", InstName.Vtbl, InstEmit32.Vtbl, OpCode32SimdTbl.Create, OpCode32SimdTbl.CreateT32);
SetAsimd("111100100x<<xxxxxxxx1000xxx1xxxx", InstName.Vtst, InstEmit32.Vtst, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32); SetAsimd("111100111x11<<10xxxx00001xx0xxxx", InstName.Vtrn, InstEmit32.Vtrn, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
SetAsimd("111100111x11<<10xxxx00010xx0xxxx", InstName.Vuzp, InstEmit32.Vuzp, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32); SetAsimd("111100100x<<xxxxxxxx1000xxx1xxxx", InstName.Vtst, InstEmit32.Vtst, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("111100111x11<<10xxxx00011xx0xxxx", InstName.Vzip, InstEmit32.Vzip, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32); SetAsimd("111100111x11<<10xxxx00010xx0xxxx", InstName.Vuzp, InstEmit32.Vuzp, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
SetAsimd("111100111x11<<10xxxx00011xx0xxxx", InstName.Vzip, InstEmit32.Vzip, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
#endregion #endregion
#region "OpCode Table (AArch32, T16)" #region "OpCode Table (AArch32, T16)"
@@ -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

@@ -17,7 +17,7 @@ namespace ARMeilleure.Decoders.Optimizations
throw new InvalidOperationException("Function entry point is not contained in a block."); throw new InvalidOperationException("Function entry point is not contained in a block.");
} }
const ulong allowance = 4; const ulong Allowance = 4;
Block entryBlock = blocks[entryBlockId]; Block entryBlock = blocks[entryBlockId];
@@ -31,7 +31,7 @@ namespace ARMeilleure.Decoders.Optimizations
{ {
Block block = blocks[i]; Block block = blocks[i];
if (endBlock.EndAddress < block.Address - allowance) if (endBlock.EndAddress < block.Address - Allowance)
{ {
break; // End of contiguous function. break; // End of contiguous function.
} }
@@ -44,7 +44,7 @@ namespace ARMeilleure.Decoders.Optimizations
{ {
Block block = blocks[i]; Block block = blocks[i];
if (startBlock.Address > block.EndAddress + allowance) if (startBlock.Address > block.EndAddress + Allowance)
{ {
break; // End of contiguous function. break; // End of contiguous function.
} }

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

@@ -1299,17 +1299,17 @@ namespace ARMeilleure.Instructions
Debug.Assert((op.Size & 1) == 0 && op.RegisterSize == RegisterSize.Simd128); Debug.Assert((op.Size & 1) == 0 && op.RegisterSize == RegisterSize.Simd128);
const int sm0 = 0 << 6 | 0 << 4 | 0 << 2 | 0 << 0; const int SM0 = 0 << 6 | 0 << 4 | 0 << 2 | 0 << 0;
const int sm1 = 1 << 6 | 1 << 4 | 1 << 2 | 1 << 0; const int SM1 = 1 << 6 | 1 << 4 | 1 << 2 | 1 << 0;
const int sm2 = 2 << 6 | 2 << 4 | 2 << 2 | 2 << 0; const int SM2 = 2 << 6 | 2 << 4 | 2 << 2 | 2 << 0;
const int sm3 = 3 << 6 | 3 << 4 | 3 << 2 | 3 << 0; const int SM3 = 3 << 6 | 3 << 4 | 3 << 2 | 3 << 0;
Operand nCopy = context.Copy(GetVec(op.Rn)); Operand nCopy = context.Copy(GetVec(op.Rn));
Operand part0 = context.AddIntrinsic(Intrinsic.X86Shufps, nCopy, nCopy, Const(sm0)); Operand part0 = context.AddIntrinsic(Intrinsic.X86Shufps, nCopy, nCopy, Const(SM0));
Operand part1 = context.AddIntrinsic(Intrinsic.X86Shufps, nCopy, nCopy, Const(sm1)); Operand part1 = context.AddIntrinsic(Intrinsic.X86Shufps, nCopy, nCopy, Const(SM1));
Operand part2 = context.AddIntrinsic(Intrinsic.X86Shufps, nCopy, nCopy, Const(sm2)); Operand part2 = context.AddIntrinsic(Intrinsic.X86Shufps, nCopy, nCopy, Const(SM2));
Operand part3 = context.AddIntrinsic(Intrinsic.X86Shufps, nCopy, nCopy, Const(sm3)); Operand part3 = context.AddIntrinsic(Intrinsic.X86Shufps, nCopy, nCopy, Const(SM3));
Operand res = emit(emit(part0, part1), emit(part2, part3)); Operand res = emit(emit(part0, part1), emit(part2, part3));
@@ -1340,13 +1340,13 @@ namespace ARMeilleure.Instructions
if ((op.Size & 1) == 0) if ((op.Size & 1) == 0)
{ {
const int sm0 = 2 << 6 | 2 << 4 | 2 << 2 | 0 << 0; const int SM0 = 2 << 6 | 2 << 4 | 2 << 2 | 0 << 0;
const int sm1 = 2 << 6 | 2 << 4 | 2 << 2 | 1 << 0; const int SM1 = 2 << 6 | 2 << 4 | 2 << 2 | 1 << 0;
Operand zeroN = context.VectorZeroUpper64(n); Operand zeroN = context.VectorZeroUpper64(n);
op0 = context.AddIntrinsic(Intrinsic.X86Pshufd, zeroN, Const(sm0)); op0 = context.AddIntrinsic(Intrinsic.X86Pshufd, zeroN, Const(SM0));
op1 = context.AddIntrinsic(Intrinsic.X86Pshufd, zeroN, Const(sm1)); op1 = context.AddIntrinsic(Intrinsic.X86Pshufd, zeroN, Const(SM1));
} }
else /* if ((op.Size & 1) == 1) */ else /* if ((op.Size & 1) == 1) */
{ {
@@ -1412,11 +1412,11 @@ namespace ARMeilleure.Instructions
} }
else /* if (op.RegisterSize == RegisterSize.Simd128) */ else /* if (op.RegisterSize == RegisterSize.Simd128) */
{ {
const int sm0 = 2 << 6 | 0 << 4 | 2 << 2 | 0 << 0; const int SM0 = 2 << 6 | 0 << 4 | 2 << 2 | 0 << 0;
const int sm1 = 3 << 6 | 1 << 4 | 3 << 2 | 1 << 0; const int SM1 = 3 << 6 | 1 << 4 | 3 << 2 | 1 << 0;
Operand part0 = context.AddIntrinsic(Intrinsic.X86Shufps, nCopy, mCopy, Const(sm0)); Operand part0 = context.AddIntrinsic(Intrinsic.X86Shufps, nCopy, mCopy, Const(SM0));
Operand part1 = context.AddIntrinsic(Intrinsic.X86Shufps, nCopy, mCopy, Const(sm1)); Operand part1 = context.AddIntrinsic(Intrinsic.X86Shufps, nCopy, mCopy, Const(SM1));
context.Copy(GetVec(op.Rd), emit(part0, part1)); context.Copy(GetVec(op.Rd), emit(part0, part1));
} }

View File

@@ -408,7 +408,7 @@ namespace ARMeilleure.Instructions
if (Optimizations.UseGfni) if (Optimizations.UseGfni)
{ {
const long bitMatrix = const long BitMatrix =
(0b10000000L << 56) | (0b10000000L << 56) |
(0b01000000L << 48) | (0b01000000L << 48) |
(0b00100000L << 40) | (0b00100000L << 40) |
@@ -418,7 +418,7 @@ namespace ARMeilleure.Instructions
(0b00000010L << 8) | (0b00000010L << 8) |
(0b00000001L << 0); (0b00000001L << 0);
Operand vBitMatrix = X86GetAllElements(context, bitMatrix); Operand vBitMatrix = X86GetAllElements(context, BitMatrix);
Operand res = context.AddIntrinsic(Intrinsic.X86Gf2p8affineqb, GetVec(op.Rn), vBitMatrix, Const(0)); Operand res = context.AddIntrinsic(Intrinsic.X86Gf2p8affineqb, GetVec(op.Rn), vBitMatrix, Const(0));
@@ -469,12 +469,12 @@ namespace ARMeilleure.Instructions
Operand n = GetVec(op.Rn); Operand n = GetVec(op.Rn);
const long maskE0 = 06L << 56 | 07L << 48 | 04L << 40 | 05L << 32 | 02L << 24 | 03L << 16 | 00L << 8 | 01L << 0; const long MaskE0 = 06L << 56 | 07L << 48 | 04L << 40 | 05L << 32 | 02L << 24 | 03L << 16 | 00L << 8 | 01L << 0;
const long maskE1 = 14L << 56 | 15L << 48 | 12L << 40 | 13L << 32 | 10L << 24 | 11L << 16 | 08L << 8 | 09L << 0; const long MaskE1 = 14L << 56 | 15L << 48 | 12L << 40 | 13L << 32 | 10L << 24 | 11L << 16 | 08L << 8 | 09L << 0;
Operand mask = X86GetScalar(context, maskE0); Operand mask = X86GetScalar(context, MaskE0);
mask = EmitVectorInsert(context, mask, Const(maskE1), 1, 3); mask = EmitVectorInsert(context, mask, Const(MaskE1), 1, 3);
Operand res = context.AddIntrinsic(Intrinsic.X86Pshufb, n, mask); Operand res = context.AddIntrinsic(Intrinsic.X86Pshufb, n, mask);
@@ -503,21 +503,21 @@ namespace ARMeilleure.Instructions
if (op.Size == 0) if (op.Size == 0)
{ {
const long maskE0 = 04L << 56 | 05L << 48 | 06L << 40 | 07L << 32 | 00L << 24 | 01L << 16 | 02L << 8 | 03L << 0; const long MaskE0 = 04L << 56 | 05L << 48 | 06L << 40 | 07L << 32 | 00L << 24 | 01L << 16 | 02L << 8 | 03L << 0;
const long maskE1 = 12L << 56 | 13L << 48 | 14L << 40 | 15L << 32 | 08L << 24 | 09L << 16 | 10L << 8 | 11L << 0; const long MaskE1 = 12L << 56 | 13L << 48 | 14L << 40 | 15L << 32 | 08L << 24 | 09L << 16 | 10L << 8 | 11L << 0;
mask = X86GetScalar(context, maskE0); mask = X86GetScalar(context, MaskE0);
mask = EmitVectorInsert(context, mask, Const(maskE1), 1, 3); mask = EmitVectorInsert(context, mask, Const(MaskE1), 1, 3);
} }
else /* if (op.Size == 1) */ else /* if (op.Size == 1) */
{ {
const long maskE0 = 05L << 56 | 04L << 48 | 07L << 40 | 06L << 32 | 01L << 24 | 00L << 16 | 03L << 8 | 02L << 0; const long MaskE0 = 05L << 56 | 04L << 48 | 07L << 40 | 06L << 32 | 01L << 24 | 00L << 16 | 03L << 8 | 02L << 0;
const long maskE1 = 13L << 56 | 12L << 48 | 15L << 40 | 14L << 32 | 09L << 24 | 08L << 16 | 11L << 8 | 10L << 0; const long MaskE1 = 13L << 56 | 12L << 48 | 15L << 40 | 14L << 32 | 09L << 24 | 08L << 16 | 11L << 8 | 10L << 0;
mask = X86GetScalar(context, maskE0); mask = X86GetScalar(context, MaskE0);
mask = EmitVectorInsert(context, mask, Const(maskE1), 1, 3); mask = EmitVectorInsert(context, mask, Const(MaskE1), 1, 3);
} }
Operand res = context.AddIntrinsic(Intrinsic.X86Pshufb, n, mask); Operand res = context.AddIntrinsic(Intrinsic.X86Pshufb, n, mask);
@@ -547,30 +547,30 @@ namespace ARMeilleure.Instructions
if (op.Size == 0) if (op.Size == 0)
{ {
const long maskE0 = 00L << 56 | 01L << 48 | 02L << 40 | 03L << 32 | 04L << 24 | 05L << 16 | 06L << 8 | 07L << 0; const long MaskE0 = 00L << 56 | 01L << 48 | 02L << 40 | 03L << 32 | 04L << 24 | 05L << 16 | 06L << 8 | 07L << 0;
const long maskE1 = 08L << 56 | 09L << 48 | 10L << 40 | 11L << 32 | 12L << 24 | 13L << 16 | 14L << 8 | 15L << 0; const long MaskE1 = 08L << 56 | 09L << 48 | 10L << 40 | 11L << 32 | 12L << 24 | 13L << 16 | 14L << 8 | 15L << 0;
mask = X86GetScalar(context, maskE0); mask = X86GetScalar(context, MaskE0);
mask = EmitVectorInsert(context, mask, Const(maskE1), 1, 3); mask = EmitVectorInsert(context, mask, Const(MaskE1), 1, 3);
} }
else if (op.Size == 1) else if (op.Size == 1)
{ {
const long maskE0 = 01L << 56 | 00L << 48 | 03L << 40 | 02L << 32 | 05L << 24 | 04L << 16 | 07L << 8 | 06L << 0; const long MaskE0 = 01L << 56 | 00L << 48 | 03L << 40 | 02L << 32 | 05L << 24 | 04L << 16 | 07L << 8 | 06L << 0;
const long maskE1 = 09L << 56 | 08L << 48 | 11L << 40 | 10L << 32 | 13L << 24 | 12L << 16 | 15L << 8 | 14L << 0; const long MaskE1 = 09L << 56 | 08L << 48 | 11L << 40 | 10L << 32 | 13L << 24 | 12L << 16 | 15L << 8 | 14L << 0;
mask = X86GetScalar(context, maskE0); mask = X86GetScalar(context, MaskE0);
mask = EmitVectorInsert(context, mask, Const(maskE1), 1, 3); mask = EmitVectorInsert(context, mask, Const(MaskE1), 1, 3);
} }
else /* if (op.Size == 2) */ else /* if (op.Size == 2) */
{ {
const long maskE0 = 03L << 56 | 02L << 48 | 01L << 40 | 00L << 32 | 07L << 24 | 06L << 16 | 05L << 8 | 04L << 0; const long MaskE0 = 03L << 56 | 02L << 48 | 01L << 40 | 00L << 32 | 07L << 24 | 06L << 16 | 05L << 8 | 04L << 0;
const long maskE1 = 11L << 56 | 10L << 48 | 09L << 40 | 08L << 32 | 15L << 24 | 14L << 16 | 13L << 8 | 12L << 0; const long MaskE1 = 11L << 56 | 10L << 48 | 09L << 40 | 08L << 32 | 15L << 24 | 14L << 16 | 13L << 8 | 12L << 0;
mask = X86GetScalar(context, maskE0); mask = X86GetScalar(context, MaskE0);
mask = EmitVectorInsert(context, mask, Const(maskE1), 1, 3); mask = EmitVectorInsert(context, mask, Const(MaskE1), 1, 3);
} }
Operand res = context.AddIntrinsic(Intrinsic.X86Pshufb, n, mask); Operand res = context.AddIntrinsic(Intrinsic.X86Pshufb, n, mask);

View File

@@ -175,10 +175,10 @@ namespace ARMeilleure.Instructions
public static ushort FPRoundCv(double real, ExecutionContext context) public static ushort FPRoundCv(double real, ExecutionContext context)
{ {
const int minimumExp = -14; const int MinimumExp = -14;
const int e = 5; const int E = 5;
const int f = 10; const int F = 10;
bool sign; bool sign;
double mantissa; double mantissa;
@@ -208,15 +208,15 @@ namespace ARMeilleure.Instructions
exponent++; exponent++;
} }
uint biasedExp = (uint)Math.Max(exponent - minimumExp + 1, 0); uint biasedExp = (uint)Math.Max(exponent - MinimumExp + 1, 0);
if (biasedExp == 0u) if (biasedExp == 0u)
{ {
mantissa /= Math.Pow(2d, minimumExp - exponent); mantissa /= Math.Pow(2d, MinimumExp - exponent);
} }
uint intMant = (uint)Math.Floor(mantissa * Math.Pow(2d, f)); uint intMant = (uint)Math.Floor(mantissa * Math.Pow(2d, F));
double error = mantissa * Math.Pow(2d, f) - (double)intMant; double error = mantissa * Math.Pow(2d, F) - (double)intMant;
if (biasedExp == 0u && (error != 0d || (context.Fpcr & FPCR.Ufe) != 0)) if (biasedExp == 0u && (error != 0d || (context.Fpcr & FPCR.Ufe) != 0))
{ {
@@ -256,12 +256,12 @@ namespace ARMeilleure.Instructions
{ {
intMant++; intMant++;
if (intMant == 1u << f) if (intMant == 1u << F)
{ {
biasedExp = 1u; biasedExp = 1u;
} }
if (intMant == 1u << (f + 1)) if (intMant == 1u << (F + 1))
{ {
biasedExp++; biasedExp++;
intMant >>= 1; intMant >>= 1;
@@ -272,7 +272,7 @@ namespace ARMeilleure.Instructions
if ((context.Fpcr & FPCR.Ahp) == 0) if ((context.Fpcr & FPCR.Ahp) == 0)
{ {
if (biasedExp >= (1u << e) - 1u) if (biasedExp >= (1u << E) - 1u)
{ {
resultBits = overflowToInf ? FPInfinity(sign) : FPMaxNormal(sign); resultBits = overflowToInf ? FPInfinity(sign) : FPMaxNormal(sign);
@@ -287,7 +287,7 @@ namespace ARMeilleure.Instructions
} }
else else
{ {
if (biasedExp >= 1u << e) if (biasedExp >= 1u << E)
{ {
resultBits = (ushort)((sign ? 1u : 0u) << 15 | 0x7FFFu); resultBits = (ushort)((sign ? 1u : 0u) << 15 | 0x7FFFu);
@@ -354,10 +354,10 @@ namespace ARMeilleure.Instructions
private static float FPRoundCv(double real, ExecutionContext context) private static float FPRoundCv(double real, ExecutionContext context)
{ {
const int minimumExp = -126; const int MinimumExp = -126;
const int e = 8; const int E = 8;
const int f = 23; const int F = 23;
bool sign; bool sign;
double mantissa; double mantissa;
@@ -387,22 +387,22 @@ namespace ARMeilleure.Instructions
exponent++; exponent++;
} }
if ((context.Fpcr & FPCR.Fz) != 0 && exponent < minimumExp) if ((context.Fpcr & FPCR.Fz) != 0 && exponent < MinimumExp)
{ {
context.Fpsr |= FPSR.Ufc; context.Fpsr |= FPSR.Ufc;
return SoftFloat32.FPZero(sign); return SoftFloat32.FPZero(sign);
} }
uint biasedExp = (uint)Math.Max(exponent - minimumExp + 1, 0); uint biasedExp = (uint)Math.Max(exponent - MinimumExp + 1, 0);
if (biasedExp == 0u) if (biasedExp == 0u)
{ {
mantissa /= Math.Pow(2d, minimumExp - exponent); mantissa /= Math.Pow(2d, MinimumExp - exponent);
} }
uint intMant = (uint)Math.Floor(mantissa * Math.Pow(2d, f)); uint intMant = (uint)Math.Floor(mantissa * Math.Pow(2d, F));
double error = mantissa * Math.Pow(2d, f) - (double)intMant; double error = mantissa * Math.Pow(2d, F) - (double)intMant;
if (biasedExp == 0u && (error != 0d || (context.Fpcr & FPCR.Ufe) != 0)) if (biasedExp == 0u && (error != 0d || (context.Fpcr & FPCR.Ufe) != 0))
{ {
@@ -442,12 +442,12 @@ namespace ARMeilleure.Instructions
{ {
intMant++; intMant++;
if (intMant == 1u << f) if (intMant == 1u << F)
{ {
biasedExp = 1u; biasedExp = 1u;
} }
if (intMant == 1u << (f + 1)) if (intMant == 1u << (F + 1))
{ {
biasedExp++; biasedExp++;
intMant >>= 1; intMant >>= 1;
@@ -456,7 +456,7 @@ namespace ARMeilleure.Instructions
float result; float result;
if (biasedExp >= (1u << e) - 1u) if (biasedExp >= (1u << E) - 1u)
{ {
result = overflowToInf ? SoftFloat32.FPInfinity(sign) : SoftFloat32.FPMaxNormal(sign); result = overflowToInf ? SoftFloat32.FPInfinity(sign) : SoftFloat32.FPMaxNormal(sign);
@@ -529,10 +529,10 @@ namespace ARMeilleure.Instructions
private static double FPRoundCv(double real, ExecutionContext context) private static double FPRoundCv(double real, ExecutionContext context)
{ {
const int minimumExp = -1022; const int MinimumExp = -1022;
const int e = 11; const int E = 11;
const int f = 52; const int F = 52;
bool sign; bool sign;
double mantissa; double mantissa;
@@ -562,22 +562,22 @@ namespace ARMeilleure.Instructions
exponent++; exponent++;
} }
if ((context.Fpcr & FPCR.Fz) != 0 && exponent < minimumExp) if ((context.Fpcr & FPCR.Fz) != 0 && exponent < MinimumExp)
{ {
context.Fpsr |= FPSR.Ufc; context.Fpsr |= FPSR.Ufc;
return SoftFloat64.FPZero(sign); return SoftFloat64.FPZero(sign);
} }
uint biasedExp = (uint)Math.Max(exponent - minimumExp + 1, 0); uint biasedExp = (uint)Math.Max(exponent - MinimumExp + 1, 0);
if (biasedExp == 0u) if (biasedExp == 0u)
{ {
mantissa /= Math.Pow(2d, minimumExp - exponent); mantissa /= Math.Pow(2d, MinimumExp - exponent);
} }
ulong intMant = (ulong)Math.Floor(mantissa * Math.Pow(2d, f)); ulong intMant = (ulong)Math.Floor(mantissa * Math.Pow(2d, F));
double error = mantissa * Math.Pow(2d, f) - (double)intMant; double error = mantissa * Math.Pow(2d, F) - (double)intMant;
if (biasedExp == 0u && (error != 0d || (context.Fpcr & FPCR.Ufe) != 0)) if (biasedExp == 0u && (error != 0d || (context.Fpcr & FPCR.Ufe) != 0))
{ {
@@ -617,12 +617,12 @@ namespace ARMeilleure.Instructions
{ {
intMant++; intMant++;
if (intMant == 1ul << f) if (intMant == 1ul << F)
{ {
biasedExp = 1u; biasedExp = 1u;
} }
if (intMant == 1ul << (f + 1)) if (intMant == 1ul << (F + 1))
{ {
biasedExp++; biasedExp++;
intMant >>= 1; intMant >>= 1;
@@ -631,7 +631,7 @@ namespace ARMeilleure.Instructions
double result; double result;
if (biasedExp >= (1u << e) - 1u) if (biasedExp >= (1u << E) - 1u)
{ {
result = overflowToInf ? SoftFloat64.FPInfinity(sign) : SoftFloat64.FPMaxNormal(sign); result = overflowToInf ? SoftFloat64.FPInfinity(sign) : SoftFloat64.FPMaxNormal(sign);

View File

@@ -5,7 +5,6 @@ using ARMeilleure.Translation.Cache;
using System; using System;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory; using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
namespace ARMeilleure.Signal namespace ARMeilleure.Signal
@@ -261,20 +260,20 @@ namespace ARMeilleure.Signal
{ {
if (OperatingSystem.IsMacOS()) if (OperatingSystem.IsMacOS())
{ {
const ulong mcontextOffset = 48; // uc_mcontext const ulong McontextOffset = 48; // uc_mcontext
Operand ctxPtr = context.Load(OperandType.I64, context.Add(ucontextPtr, Const(mcontextOffset))); Operand ctxPtr = context.Load(OperandType.I64, context.Add(ucontextPtr, Const(McontextOffset)));
if (RuntimeInformation.ProcessArchitecture == Architecture.Arm64) if (RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
{ {
const ulong esrOffset = 8; // __es.__esr const ulong EsrOffset = 8; // __es.__esr
Operand esr = context.Load(OperandType.I64, context.Add(ctxPtr, Const(esrOffset))); Operand esr = context.Load(OperandType.I64, context.Add(ctxPtr, Const(EsrOffset)));
return context.BitwiseAnd(esr, Const(0x40ul)); return context.BitwiseAnd(esr, Const(0x40ul));
} }
if (RuntimeInformation.ProcessArchitecture == Architecture.X64) if (RuntimeInformation.ProcessArchitecture == Architecture.X64)
{ {
const ulong errOffset = 4; // __es.__err const ulong ErrOffset = 4; // __es.__err
Operand err = context.Load(OperandType.I64, context.Add(ctxPtr, Const(errOffset))); Operand err = context.Load(OperandType.I64, context.Add(ctxPtr, Const(ErrOffset)));
return context.BitwiseAnd(err, Const(2ul)); return context.BitwiseAnd(err, Const(2ul));
} }
} }
@@ -287,10 +286,10 @@ namespace ARMeilleure.Signal
Operand loopLabel = Label(); Operand loopLabel = Label();
Operand successLabel = Label(); Operand successLabel = Label();
const ulong auxOffset = 464; // uc_mcontext.__reserved const ulong AuxOffset = 464; // uc_mcontext.__reserved
const uint esrMagic = 0x45535201; const uint EsrMagic = 0x45535201;
context.Copy(auxPtr, context.Add(ucontextPtr, Const(auxOffset))); context.Copy(auxPtr, context.Add(ucontextPtr, Const(AuxOffset)));
context.MarkLabel(loopLabel); context.MarkLabel(loopLabel);
@@ -299,7 +298,7 @@ namespace ARMeilleure.Signal
// _aarch64_ctx::size // _aarch64_ctx::size
Operand size = context.Load(OperandType.I32, context.Add(auxPtr, Const(4ul))); Operand size = context.Load(OperandType.I32, context.Add(auxPtr, Const(4ul)));
context.BranchIf(successLabel, magic, Const(esrMagic), Comparison.Equal); context.BranchIf(successLabel, magic, Const(EsrMagic), Comparison.Equal);
context.Copy(auxPtr, context.Add(auxPtr, context.ZeroExtend32(OperandType.I64, size))); context.Copy(auxPtr, context.Add(auxPtr, context.ZeroExtend32(OperandType.I64, size)));
@@ -314,8 +313,8 @@ namespace ARMeilleure.Signal
if (RuntimeInformation.ProcessArchitecture == Architecture.X64) if (RuntimeInformation.ProcessArchitecture == Architecture.X64)
{ {
const int errOffset = 192; // uc_mcontext.gregs[REG_ERR] const int ErrOffset = 192; // uc_mcontext.gregs[REG_ERR]
Operand err = context.Load(OperandType.I64, context.Add(ucontextPtr, Const(errOffset))); Operand err = context.Load(OperandType.I64, context.Add(ucontextPtr, Const(ErrOffset)));
return context.BitwiseAnd(err, Const(2ul)); return context.BitwiseAnd(err, Const(2ul));
} }
} }

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";
@@ -880,7 +880,7 @@ namespace ARMeilleure.Translation.PTC
private void ReportProgress(object state) private void ReportProgress(object state)
{ {
const int refreshRate = 50; // ms. const int RefreshRate = 50; // ms.
AutoResetEvent endEvent = (AutoResetEvent)state; AutoResetEvent endEvent = (AutoResetEvent)state;
@@ -896,7 +896,7 @@ namespace ARMeilleure.Translation.PTC
count = newCount; count = newCount;
} }
} }
while (!endEvent.WaitOne(refreshRate)); while (!endEvent.WaitOne(RefreshRate));
} }
public static Hash128 ComputeHash(IMemoryManager memory, ulong address, ulong guestSize) public static Hash128 ComputeHash(IMemoryManager memory, ulong address, ulong guestSize)

View File

@@ -43,7 +43,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
public void Process(CommandList context) public void Process(CommandList context)
{ {
const int targetChannelCount = 2; const int TargetChannelCount = 2;
ulong currentOffset = CurrentOffset; ulong currentOffset = CurrentOffset;
@@ -59,10 +59,10 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
for (int y = 0; y < context.SampleCount; y++) for (int y = 0; y < context.SampleCount; y++)
{ {
context.MemoryManager.Write(targetOffset + (ulong)y * targetChannelCount, PcmHelper.Saturate(inputBuffer[y])); context.MemoryManager.Write(targetOffset + (ulong)y * TargetChannelCount, PcmHelper.Saturate(inputBuffer[y]));
} }
currentOffset += context.SampleCount * targetChannelCount; currentOffset += context.SampleCount * TargetChannelCount;
if (currentOffset >= CircularBufferSize) if (currentOffset >= CircularBufferSize)
{ {
@@ -73,4 +73,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
} }
} }
} }
} }

View File

@@ -56,7 +56,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private unsafe void ProcessDelayMono(ref DelayState state, float* outputBuffer, float* inputBuffer, uint sampleCount) private unsafe void ProcessDelayMono(ref DelayState state, float* outputBuffer, float* inputBuffer, uint sampleCount)
{ {
const ushort channelCount = 1; const ushort ChannelCount = 1;
float feedbackGain = FixedPointHelper.ToFloat(Parameter.FeedbackGain, FixedPointPrecision); float feedbackGain = FixedPointHelper.ToFloat(Parameter.FeedbackGain, FixedPointPrecision);
float inGain = FixedPointHelper.ToFloat(Parameter.InGain, FixedPointPrecision); float inGain = FixedPointHelper.ToFloat(Parameter.InGain, FixedPointPrecision);
@@ -70,7 +70,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
float temp = input * inGain + delayLineValue * feedbackGain; float temp = input * inGain + delayLineValue * feedbackGain;
state.UpdateLowPassFilter(ref temp, channelCount); state.UpdateLowPassFilter(ref temp, ChannelCount);
outputBuffer[i] = (input * dryGain + delayLineValue * outGain) / 64; outputBuffer[i] = (input * dryGain + delayLineValue * outGain) / 64;
} }
@@ -79,7 +79,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private unsafe void ProcessDelayStereo(ref DelayState state, Span<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount) private unsafe void ProcessDelayStereo(ref DelayState state, Span<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount)
{ {
const ushort channelCount = 2; const ushort ChannelCount = 2;
float delayFeedbackBaseGain = state.DelayFeedbackBaseGain; float delayFeedbackBaseGain = state.DelayFeedbackBaseGain;
float delayFeedbackCrossGain = state.DelayFeedbackCrossGain; float delayFeedbackCrossGain = state.DelayFeedbackCrossGain;
@@ -106,7 +106,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
Vector2 temp = MatrixHelper.Transform(ref delayLineValues, ref delayFeedback) + channelInput * inGain; Vector2 temp = MatrixHelper.Transform(ref delayLineValues, ref delayFeedback) + channelInput * inGain;
state.UpdateLowPassFilter(ref Unsafe.As<Vector2, float>(ref temp), channelCount); state.UpdateLowPassFilter(ref Unsafe.As<Vector2, float>(ref temp), ChannelCount);
*((float*)outputBuffers[0] + i) = (channelInput.X * dryGain + delayLineValues.X * outGain) / 64; *((float*)outputBuffers[0] + i) = (channelInput.X * dryGain + delayLineValues.X * outGain) / 64;
*((float*)outputBuffers[1] + i) = (channelInput.Y * dryGain + delayLineValues.Y * outGain) / 64; *((float*)outputBuffers[1] + i) = (channelInput.Y * dryGain + delayLineValues.Y * outGain) / 64;
@@ -116,7 +116,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private unsafe void ProcessDelayQuadraphonic(ref DelayState state, Span<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount) private unsafe void ProcessDelayQuadraphonic(ref DelayState state, Span<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount)
{ {
const ushort channelCount = 4; const ushort ChannelCount = 4;
float delayFeedbackBaseGain = state.DelayFeedbackBaseGain; float delayFeedbackBaseGain = state.DelayFeedbackBaseGain;
float delayFeedbackCrossGain = state.DelayFeedbackCrossGain; float delayFeedbackCrossGain = state.DelayFeedbackCrossGain;
@@ -150,7 +150,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
Vector4 temp = MatrixHelper.Transform(ref delayLineValues, ref delayFeedback) + channelInput * inGain; Vector4 temp = MatrixHelper.Transform(ref delayLineValues, ref delayFeedback) + channelInput * inGain;
state.UpdateLowPassFilter(ref Unsafe.As<Vector4, float>(ref temp), channelCount); state.UpdateLowPassFilter(ref Unsafe.As<Vector4, float>(ref temp), ChannelCount);
*((float*)outputBuffers[0] + i) = (channelInput.X * dryGain + delayLineValues.X * outGain) / 64; *((float*)outputBuffers[0] + i) = (channelInput.X * dryGain + delayLineValues.X * outGain) / 64;
*((float*)outputBuffers[1] + i) = (channelInput.Y * dryGain + delayLineValues.Y * outGain) / 64; *((float*)outputBuffers[1] + i) = (channelInput.Y * dryGain + delayLineValues.Y * outGain) / 64;
@@ -162,7 +162,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private unsafe void ProcessDelaySurround(ref DelayState state, Span<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount) private unsafe void ProcessDelaySurround(ref DelayState state, Span<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount)
{ {
const ushort channelCount = 6; const ushort ChannelCount = 6;
float feedbackGain = FixedPointHelper.ToFloat(Parameter.FeedbackGain, FixedPointPrecision); float feedbackGain = FixedPointHelper.ToFloat(Parameter.FeedbackGain, FixedPointPrecision);
float delayFeedbackBaseGain = state.DelayFeedbackBaseGain; float delayFeedbackBaseGain = state.DelayFeedbackBaseGain;
@@ -202,7 +202,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
Vector6 temp = MatrixHelper.Transform(ref delayLineValues, ref delayFeedback) + channelInput * inGain; Vector6 temp = MatrixHelper.Transform(ref delayLineValues, ref delayFeedback) + channelInput * inGain;
state.UpdateLowPassFilter(ref Unsafe.As<Vector6, float>(ref temp), channelCount); state.UpdateLowPassFilter(ref Unsafe.As<Vector6, float>(ref temp), ChannelCount);
*((float*)outputBuffers[0] + i) = (channelInput.X * dryGain + delayLineValues.X * outGain) / 64; *((float*)outputBuffers[0] + i) = (channelInput.X * dryGain + delayLineValues.X * outGain) / 64;
*((float*)outputBuffers[1] + i) = (channelInput.Y * dryGain + delayLineValues.Y * outGain) / 64; *((float*)outputBuffers[1] + i) = (channelInput.Y * dryGain + delayLineValues.Y * outGain) / 64;
@@ -277,4 +277,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
ProcessDelay(context, ref state); ProcessDelay(context, ref state);
} }
} }
} }

View File

@@ -65,7 +65,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
int channelCount = (int)device.GetChannelCount(); int channelCount = (int)device.GetChannelCount();
uint bufferCount = Math.Min(device.GetChannelCount(), InputCount); uint bufferCount = Math.Min(device.GetChannelCount(), InputCount);
const int sampleCount = Constants.TargetSampleCount; const int SampleCount = Constants.TargetSampleCount;
uint inputCount; uint inputCount;
@@ -79,13 +79,13 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
inputCount = bufferCount; inputCount = bufferCount;
} }
short[] outputBuffer = new short[inputCount * sampleCount]; short[] outputBuffer = new short[inputCount * SampleCount];
for (int i = 0; i < bufferCount; i++) for (int i = 0; i < bufferCount; i++)
{ {
ReadOnlySpan<float> inputBuffer = GetBuffer(InputBufferIndices[i], sampleCount); ReadOnlySpan<float> inputBuffer = GetBuffer(InputBufferIndices[i], SampleCount);
for (int j = 0; j < sampleCount; j++) for (int j = 0; j < SampleCount; j++)
{ {
outputBuffer[i + j * channelCount] = PcmHelper.Saturate(inputBuffer[j]); outputBuffer[i + j * channelCount] = PcmHelper.Saturate(inputBuffer[j]);
} }
@@ -100,4 +100,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
} }
} }
} }
} }

View File

@@ -96,7 +96,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
private unsafe void ProcessReverb3dGeneric(ref Reverb3dState state, ReadOnlySpan<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount, ReadOnlySpan<int> outputEarlyIndicesTable, ReadOnlySpan<int> targetEarlyDelayLineIndicesTable, ReadOnlySpan<int> targetOutputFeedbackIndicesTable) private unsafe void ProcessReverb3dGeneric(ref Reverb3dState state, ReadOnlySpan<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount, ReadOnlySpan<int> outputEarlyIndicesTable, ReadOnlySpan<int> targetEarlyDelayLineIndicesTable, ReadOnlySpan<int> targetOutputFeedbackIndicesTable)
{ {
const int delayLineSampleIndexOffset = 1; const int DelayLineSampleIndexOffset = 1;
bool isMono = Parameter.ChannelCount == 1; bool isMono = Parameter.ChannelCount == 1;
bool isSurround = Parameter.ChannelCount == 6; bool isSurround = Parameter.ChannelCount == 6;
@@ -111,14 +111,14 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
outputValues.Fill(0); outputValues.Fill(0);
float tapOut = state.PreDelayLine.TapUnsafe(state.ReflectionDelayTime, delayLineSampleIndexOffset); float tapOut = state.PreDelayLine.TapUnsafe(state.ReflectionDelayTime, DelayLineSampleIndexOffset);
for (int i = 0; i < targetEarlyDelayLineIndicesTable.Length; i++) for (int i = 0; i < targetEarlyDelayLineIndicesTable.Length; i++)
{ {
int earlyDelayIndex = targetEarlyDelayLineIndicesTable[i]; int earlyDelayIndex = targetEarlyDelayLineIndicesTable[i];
int outputIndex = outputEarlyIndicesTable[earlyDelayIndex]; int outputIndex = outputEarlyIndicesTable[earlyDelayIndex];
float tempTapOut = state.PreDelayLine.TapUnsafe(state.EarlyDelayTime[earlyDelayIndex], delayLineSampleIndexOffset); float tempTapOut = state.PreDelayLine.TapUnsafe(state.EarlyDelayTime[earlyDelayIndex], DelayLineSampleIndexOffset);
outputValues[outputIndex] += tempTapOut * state.EarlyGain[earlyDelayIndex]; outputValues[outputIndex] += tempTapOut * state.EarlyGain[earlyDelayIndex];
} }
@@ -251,4 +251,4 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
ProcessReverb3d(context, ref state); ProcessReverb3d(context, ref state);
} }
} }
} }

View File

@@ -44,9 +44,9 @@ namespace Ryujinx.Audio.Renderer.Dsp
public static void ProcessWaveBuffers(IVirtualMemoryManager memoryManager, Span<float> outputBuffer, ref WaveBufferInformation info, Span<WaveBuffer> wavebuffers, ref VoiceUpdateState voiceState, uint targetSampleRate, int sampleCount) public static void ProcessWaveBuffers(IVirtualMemoryManager memoryManager, Span<float> outputBuffer, ref WaveBufferInformation info, Span<WaveBuffer> wavebuffers, ref VoiceUpdateState voiceState, uint targetSampleRate, int sampleCount)
{ {
const int tempBufferSize = 0x3F00; const int TempBufferSize = 0x3F00;
Span<short> tempBuffer = stackalloc short[tempBufferSize]; Span<short> tempBuffer = stackalloc short[TempBufferSize];
float sampleRateRatio = (float)info.SourceSampleRate / targetSampleRate * info.Pitch; float sampleRateRatio = (float)info.SourceSampleRate / targetSampleRate * info.Pitch;
@@ -60,11 +60,11 @@ namespace Ryujinx.Audio.Renderer.Dsp
int totalNeededSize = (int)MathF.Truncate(fraction + sampleRateRatio * sampleCount); int totalNeededSize = (int)MathF.Truncate(fraction + sampleRateRatio * sampleCount);
if (totalNeededSize + pitchMaxLength <= tempBufferSize && totalNeededSize >= 0) if (totalNeededSize + pitchMaxLength <= TempBufferSize && totalNeededSize >= 0)
{ {
int sourceSampleCountToProcess = sampleCount; int sourceSampleCountToProcess = sampleCount;
int maxSampleCountPerIteration = Math.Min((int)MathF.Truncate((tempBufferSize - fraction) / sampleRateRatio), sampleCount); int maxSampleCountPerIteration = Math.Min((int)MathF.Truncate((TempBufferSize - fraction) / sampleRateRatio), sampleCount);
bool isStarving = false; bool isStarving = false;
@@ -463,4 +463,4 @@ namespace Ryujinx.Audio.Renderer.Dsp
} }
} }
} }
} }

View File

@@ -32,13 +32,13 @@ namespace Ryujinx.Audio.Renderer.Dsp
float BlackmanWindow(float x) float BlackmanWindow(float x)
{ {
const float a = 0.18f; const float A = 0.18f;
const float a0 = 0.5f - 0.5f * a; const float A0 = 0.5f - 0.5f * A;
const float a1 = -0.5f; const float A1 = -0.5f;
const float a2 = 0.5f * a; const float A2 = 0.5f * A;
return a0 + a1 * MathF.Cos(2 * MathF.PI * x) + a2 * MathF.Cos(4 * MathF.PI * x); return A0 + A1 * MathF.Cos(2 * MathF.PI * x) + A2 * MathF.Cos(4 * MathF.PI * x);
} }
Array20<float> result = new Array20<float>(); Array20<float> result = new Array20<float>();
for (int i = 0; i < FilterBankLength; i++) for (int i = 0; i < FilterBankLength; i++)
@@ -112,7 +112,7 @@ namespace Ryujinx.Audio.Renderer.Dsp
int inputBufferIndex = 0; int inputBufferIndex = 0;
switch (state.Scale) switch (state.Scale)
{ {
case 6.0f: case 6.0f:
for (int i = 0; i < outputSampleCount; i++) for (int i = 0; i < outputSampleCount; i++)
{ {
@@ -189,4 +189,4 @@ namespace Ryujinx.Audio.Renderer.Dsp
} }
} }
} }
} }

View File

@@ -60,7 +60,7 @@ namespace Ryujinx.Audio.Renderer.Server
public uint Estimate(MixRampGroupedCommand command) public uint Estimate(MixRampGroupedCommand command)
{ {
const float costPerSample = 7.245f; const float CostPerSample = 7.245f;
Debug.Assert(_sampleCount == 160 || _sampleCount == 240); Debug.Assert(_sampleCount == 160 || _sampleCount == 240);
@@ -74,7 +74,7 @@ namespace Ryujinx.Audio.Renderer.Server
} }
} }
return (uint)(_sampleCount * costPerSample * volumeCount); return (uint)(_sampleCount * CostPerSample * volumeCount);
} }
public uint Estimate(MixRampCommand command) public uint Estimate(MixRampCommand command)
@@ -549,4 +549,4 @@ namespace Ryujinx.Audio.Renderer.Server
return 0; return 0;
} }
} }
} }

View File

@@ -256,19 +256,19 @@ namespace Ryujinx.Audio.Renderer.Server.MemoryPool
MemoryPoolUserState outputState; MemoryPoolUserState outputState;
const uint pageSize = 0x1000; const uint PageSize = 0x1000;
if (inputState != MemoryPoolUserState.RequestAttach && inputState != MemoryPoolUserState.RequestDetach) if (inputState != MemoryPoolUserState.RequestAttach && inputState != MemoryPoolUserState.RequestDetach)
{ {
return UpdateResult.Success; return UpdateResult.Success;
} }
if (inParameter.CpuAddress == 0 || (inParameter.CpuAddress % pageSize) != 0) if (inParameter.CpuAddress == 0 || (inParameter.CpuAddress % PageSize) != 0)
{ {
return UpdateResult.InvalidParameter; return UpdateResult.InvalidParameter;
} }
if (inParameter.Size == 0 || (inParameter.Size % pageSize) != 0) if (inParameter.Size == 0 || (inParameter.Size % PageSize) != 0)
{ {
return UpdateResult.InvalidParameter; return UpdateResult.InvalidParameter;
} }
@@ -363,4 +363,4 @@ namespace Ryujinx.Audio.Renderer.Server.MemoryPool
} }
} }
} }
} }

View File

@@ -10,8 +10,8 @@ using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.UI.Windows;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Ui.App.Common;
using Ryujinx.HLE.HOS; using Ryujinx.HLE.HOS;
using Ryujinx.Ui.App.Common;
using Ryujinx.Ui.Common.Helper; using Ryujinx.Ui.Common.Helper;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;

View File

@@ -40,9 +40,9 @@ namespace Ryujinx.Ava.UI.Models
private string GetSizeString() private string GetSizeString()
{ {
const int scale = 1024; const int Scale = 1024;
string[] orders = { "GiB", "MiB", "KiB" }; string[] orders = { "GiB", "MiB", "KiB" };
long max = (long)Math.Pow(scale, orders.Length); long max = (long)Math.Pow(Scale, orders.Length);
foreach (string order in orders) foreach (string order in orders)
{ {
@@ -51,7 +51,7 @@ namespace Ryujinx.Ava.UI.Models
return $"{decimal.Divide(Size, max):##.##} {order}"; return $"{decimal.Divide(Size, max):##.##} {order}";
} }
max /= scale; max /= Scale;
} }
return "0 KiB"; return "0 KiB";
@@ -109,4 +109,4 @@ namespace Ryujinx.Ava.UI.Models
} }
} }
} }

View File

@@ -622,7 +622,7 @@ namespace Ryujinx.Ava.UI.ViewModels
OnPropertyChanged(); OnPropertyChanged();
} }
} }
public double WindowWidth public double WindowWidth
{ {
get => _windowWidth; get => _windowWidth;
@@ -1124,13 +1124,13 @@ namespace Ryujinx.Ava.UI.ViewModels
var dominantColor = IconColorPicker.GetFilteredColor(gameIconBmp).ToPixel<Bgra32>(); var dominantColor = IconColorPicker.GetFilteredColor(gameIconBmp).ToPixel<Bgra32>();
const float colorMultiple = 0.5f; const float ColorMultiple = 0.5f;
Color progressFgColor = Color.FromRgb(dominantColor.R, dominantColor.G, dominantColor.B); Color progressFgColor = Color.FromRgb(dominantColor.R, dominantColor.G, dominantColor.B);
Color progressBgColor = Color.FromRgb( Color progressBgColor = Color.FromRgb(
(byte)(dominantColor.R * colorMultiple), (byte)(dominantColor.R * ColorMultiple),
(byte)(dominantColor.G * colorMultiple), (byte)(dominantColor.G * ColorMultiple),
(byte)(dominantColor.B * colorMultiple)); (byte)(dominantColor.B * ColorMultiple));
ProgressBarForegroundColor = new SolidColorBrush(progressFgColor); ProgressBarForegroundColor = new SolidColorBrush(progressFgColor);
ProgressBarBackgroundColor = new SolidColorBrush(progressBgColor); ProgressBarBackgroundColor = new SolidColorBrush(progressBgColor);
@@ -1677,4 +1677,4 @@ namespace Ryujinx.Ava.UI.ViewModels
#endregion #endregion
} }
} }

View File

@@ -18,14 +18,14 @@ using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.HOS.Services.Time.TimeZone; using Ryujinx.HLE.HOS.Services.Time.TimeZone;
using Ryujinx.Ui.Common.Configuration; using Ryujinx.Ui.Common.Configuration;
using Ryujinx.Ui.Common.Configuration.System; using Ryujinx.Ui.Common.Configuration.System;
using Silk.NET.Vulkan;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices;
using System.Net.NetworkInformation; using System.Net.NetworkInformation;
using System.Runtime.InteropServices;
using TimeZone = Ryujinx.Ava.UI.Models.TimeZone; using TimeZone = Ryujinx.Ava.UI.Models.TimeZone;
using Silk.NET.Vulkan;
namespace Ryujinx.Ava.UI.ViewModels namespace Ryujinx.Ava.UI.ViewModels
{ {

View File

@@ -44,10 +44,10 @@ namespace Ryujinx.Common.SystemInfo
return 0; return 0;
} }
const int flavor = 4; // HOST_VM_INFO64 const int Flavor = 4; // HOST_VM_INFO64
uint count = (uint)(Marshal.SizeOf<VMStatistics64>() / sizeof(int)); // HOST_VM_INFO64_COUNT uint count = (uint)(Marshal.SizeOf<VMStatistics64>() / sizeof(int)); // HOST_VM_INFO64_COUNT
VMStatistics64 stats = new(); VMStatistics64 stats = new();
result = host_statistics64(port, flavor, ref stats, ref count); result = host_statistics64(port, Flavor, ref stats, ref count);
if (result != 0) if (result != 0)
{ {
@@ -154,4 +154,4 @@ 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 host_priv, int host_flavor, ref VMStatistics64 host_info64_out, ref uint host_info64_outCnt);
} }
} }

View File

@@ -29,10 +29,10 @@ namespace Ryujinx.Common.SystemInterop
[SupportedOSPlatform("macos")] [SupportedOSPlatform("macos")]
private void RegisterPosix() private void RegisterPosix()
{ {
const int stdErrFileno = 2; const int StdErrFileno = 2;
(int readFd, int writeFd) = MakePipe(); (int readFd, int writeFd) = MakePipe();
dup2(writeFd, stdErrFileno); dup2(writeFd, StdErrFileno);
_pipeReader = CreateFileDescriptorStream(readFd); _pipeReader = CreateFileDescriptorStream(readFd);
_pipeWriter = CreateFileDescriptorStream(writeFd); _pipeWriter = CreateFileDescriptorStream(writeFd);

View File

@@ -6,8 +6,8 @@ using Ryujinx.Memory.Range;
using Ryujinx.Memory.Tracking; using Ryujinx.Memory.Tracking;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
namespace Ryujinx.Graphics.Gpu.Memory namespace Ryujinx.Graphics.Gpu.Memory

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
{ {
@@ -91,4 +91,4 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Common
} }
} }
} }
} }

View File

@@ -14,13 +14,13 @@
public const int MaxRefFrames = 4; public const int MaxRefFrames = 4;
public const int MiSizeLog2 = 3; public const int MiSizeLog2 = 3;
public const int MiBlockSizeLog2 = 6 - MiSizeLog2; // 64 = 2^6 public const int MiBlockSizeLog2 = 6 - MiSizeLog2; // 64 = 2^6
public const int MiSize = 1 << MiSizeLog2; // pixels per mi-unit public const int MiSize = 1 << MiSizeLog2; // pixels per mi-unit
public const int MiBlockSize = 1 << MiBlockSizeLog2; // mi-units per max block public const int MiBlockSize = 1 << MiBlockSizeLog2; // mi-units per max block
public const int MiMask = MiBlockSize - 1; public const int MiMask = MiBlockSize - 1;
public const int PartitionPloffset = 4; // number of probability models per block size public const int PartitionPloffset = 4; // number of probability models per block size
/* Segment Feature Masks */ /* Segment Feature Masks */
public const int MaxMvRefCandidates = 2; public const int MaxMvRefCandidates = 2;
@@ -48,9 +48,9 @@
public const int MvLow = -(1 << MvInUseBits); public const int MvLow = -(1 << MvInUseBits);
// Coefficient token alphabet // Coefficient token alphabet
public const int ZeroToken = 0; // 0 Extra Bits 0+0 public const int ZeroToken = 0; // 0 Extra Bits 0+0
public const int OneToken = 1; // 1 Extra Bits 0+1 public const int OneToken = 1; // 1 Extra Bits 0+1
public const int TwoToken = 2; // 2 Extra Bits 0+1 public const int TwoToken = 2; // 2 Extra Bits 0+1
public const int PivotNode = 2; public const int PivotNode = 2;

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;
} }
@@ -893,7 +919,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
if (!less8x8 && eobtotal == 0) if (!less8x8 && eobtotal == 0)
{ {
mi.Skip = 1; // Skip loopfilter mi.Skip = 1; // Skip loopfilter
} }
} }
} }
@@ -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,10 +120,8 @@ 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;
} }
@@ -173,17 +182,19 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
if (!seg.Enabled) if (!seg.Enabled)
{ {
return 0; // Default for disabled segmentation return 0; // Default for disabled segmentation
} }
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;
} }
@@ -203,7 +214,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
if (!seg.Enabled) if (!seg.Enabled)
{ {
return 0; // Default for disabled segmentation return 0; // Default for disabled segmentation
} }
predictedSegmentId = !cm.LastFrameSegMap.IsNull predictedSegmentId = !cm.LastFrameSegMap.IsNull
@@ -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,17 +249,15 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
return 1; return 1;
} }
else
{
int ctx = xd.GetSkipContext();
int skip = r.Read(cm.Fc.Value.SkipProb[ctx]);
if (!xd.Counts.IsNull)
{
++xd.Counts.Value.Skip[ctx][skip];
}
return skip; int ctx = xd.GetSkipContext();
int skip = r.Read(cm.Fc.Value.SkipProb[ctx]);
if (!xd.Counts.IsNull)
{
++xd.Counts.Value.Skip[ctx][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)
@@ -265,7 +276,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
else else
{ {
int i; int i;
int n = (int)mvClass + Constants.Class0Bits - 1; // Number of bits int n = (int)mvClass + Constants.Class0Bits - 1; // Number of bits
d = 0; d = 0;
for (i = 0; i < n; ++i) for (i = 0; i < n; ++i)
@@ -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))
{ {
@@ -326,12 +338,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
++xd.Counts.Value.CompInter[ctx][(int)mode]; ++xd.Counts.Value.CompInter[ctx][(int)mode];
} }
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
@@ -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,17 +527,15 @@ 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();
bool isInter = r.Read(cm.Fc.Value.IntraInterProb[ctx]) != 0;
if (!xd.Counts.IsNull)
{
++xd.Counts.Value.IntraInter[ctx][isInter ? 1 : 0];
}
return isInter; int ctx = xd.GetIntraInterContext();
bool isInter = r.Read(cm.Fc.Value.IntraInterProb[ctx]) != 0;
if (!xd.Counts.IsNull)
{
++xd.Counts.Value.IntraInter[ctx][isInter ? 1 : 0];
} }
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,11 +1043,10 @@ 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,11 +1060,10 @@ 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(
@@ -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;
} }
@@ -776,7 +778,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Debug.Assert(yStepQ4 <= 32); Debug.Assert(yStepQ4 <= 32);
Debug.Assert(xStepQ4 <= 32); Debug.Assert(xStepQ4 <= 32);
HighbdConvolveHoriz(src - srcStride * (SubpelTaps / 2 - 1), srcStride, temp, 64, filter, x0Q4, xStepQ4, w, intermediateHeight, bd); HighbdConvolveHoriz(src - srcStride * (SubpelTaps / 2 - 1), srcStride, temp, 64, filter, x0Q4, xStepQ4, w, intermediateHeight, bd);
HighbdConvolveVert(temp + 64 * (SubpelTaps / 2 - 1), 64, dst, dstStride, filter, y0Q4, yStepQ4, w, h, bd); HighbdConvolveVert(temp + 64 * (SubpelTaps / 2 - 1), 64, dst, dstStride, filter, y0Q4, yStepQ4, w, h, bd);
} }
@@ -811,7 +813,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
int h, int h,
int bd) int bd)
{ {
HighbdConvolveAvgHoriz(src, srcStride, dst, dstStride, filter, x0Q4, xStepQ4, w, h, bd); HighbdConvolveAvgHoriz(src, srcStride, dst, dstStride, filter, x0Q4, xStepQ4, w, h, bd);
} }
public static unsafe void HighbdConvolve8Vert( public static unsafe void HighbdConvolve8Vert(

View File

@@ -227,7 +227,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
private static unsafe void D135Predictor(byte* dst, int stride, int bs, byte* above, byte* left) private static unsafe void D135Predictor(byte* dst, int stride, int bs, byte* above, byte* left)
{ {
int i; int i;
byte* border = stackalloc byte[32 + 32 - 1]; // outer border from bottom-left to top-right byte* border = stackalloc byte[32 + 32 - 1]; // outer border from bottom-left to top-right
// Dst(dst, stride, bs, bs - 2)[0], i.e., border starting at bottom-left // Dst(dst, stride, bs, bs - 2)[0], i.e., border starting at bottom-left
for (i = 0; i < bs - 2; ++i) for (i = 0; i < bs - 2; ++i)
@@ -607,13 +607,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Dst(dst, stride, 1, 0) = Dst(dst, stride, 0, 2) = Avg2(b, c); Dst(dst, stride, 1, 0) = Dst(dst, stride, 0, 2) = Avg2(b, c);
Dst(dst, stride, 2, 0) = Dst(dst, stride, 1, 2) = Avg2(c, d); Dst(dst, stride, 2, 0) = Dst(dst, stride, 1, 2) = Avg2(c, d);
Dst(dst, stride, 3, 0) = Dst(dst, stride, 2, 2) = Avg2(d, e); Dst(dst, stride, 3, 0) = Dst(dst, stride, 2, 2) = Avg2(d, e);
Dst(dst, stride, 3, 2) = Avg2(e, f); // Differs from vp8 Dst(dst, stride, 3, 2) = Avg2(e, f); // Differs from vp8
Dst(dst, stride, 0, 1) = Avg3(a, b, c); Dst(dst, stride, 0, 1) = Avg3(a, b, c);
Dst(dst, stride, 1, 1) = Dst(dst, stride, 0, 3) = Avg3(b, c, d); Dst(dst, stride, 1, 1) = Dst(dst, stride, 0, 3) = Avg3(b, c, d);
Dst(dst, stride, 2, 1) = Dst(dst, stride, 1, 3) = Avg3(c, d, e); Dst(dst, stride, 2, 1) = Dst(dst, stride, 1, 3) = Avg3(c, d, e);
Dst(dst, stride, 3, 1) = Dst(dst, stride, 2, 3) = Avg3(d, e, f); Dst(dst, stride, 3, 1) = Dst(dst, stride, 2, 3) = Avg3(d, e, f);
Dst(dst, stride, 3, 3) = Avg3(e, f, g); // Differs from vp8 Dst(dst, stride, 3, 3) = Avg3(e, f, g); // Differs from vp8
} }
public static unsafe void D63ePredictor4x4(byte* dst, int stride, byte* above, byte* left) public static unsafe void D63ePredictor4x4(byte* dst, int stride, byte* above, byte* left)
@@ -655,7 +655,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Dst(dst, stride, 3, 0) = Dst(dst, stride, 2, 1) = Dst(dst, stride, 1, 2) = Dst(dst, stride, 0, 3) = Avg3(d, e, f); Dst(dst, stride, 3, 0) = Dst(dst, stride, 2, 1) = Dst(dst, stride, 1, 2) = Dst(dst, stride, 0, 3) = Avg3(d, e, f);
Dst(dst, stride, 3, 1) = Dst(dst, stride, 2, 2) = Dst(dst, stride, 1, 3) = Avg3(e, f, g); Dst(dst, stride, 3, 1) = Dst(dst, stride, 2, 2) = Dst(dst, stride, 1, 3) = Avg3(e, f, g);
Dst(dst, stride, 3, 2) = Dst(dst, stride, 2, 3) = Avg3(f, g, h); Dst(dst, stride, 3, 2) = Dst(dst, stride, 2, 3) = Avg3(f, g, h);
Dst(dst, stride, 3, 3) = h; // differs from vp8 Dst(dst, stride, 3, 3) = h; // differs from vp8
} }
public static unsafe void D45ePredictor4x4(byte* dst, int stride, byte* above, byte* left) public static unsafe void D45ePredictor4x4(byte* dst, int stride, byte* above, byte* left)
@@ -935,7 +935,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
private static unsafe void HighbdD135Predictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, int bd) private static unsafe void HighbdD135Predictor(ushort* dst, int stride, int bs, ushort* above, ushort* left, int bd)
{ {
int i; int i;
ushort* border = stackalloc ushort[32 + 32 - 1]; // Outer border from bottom-left to top-right ushort* border = stackalloc ushort[32 + 32 - 1]; // Outer border from bottom-left to top-right
// Dst(dst, stride, bs, bs - 2)[0], i.e., border starting at bottom-left // Dst(dst, stride, bs, bs - 2)[0], i.e., border starting at bottom-left
for (i = 0; i < bs - 2; ++i) for (i = 0; i < bs - 2; ++i)
@@ -1281,13 +1281,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Dst(dst, stride, 1, 0) = Dst(dst, stride, 0, 2) = Avg2(b, c); Dst(dst, stride, 1, 0) = Dst(dst, stride, 0, 2) = Avg2(b, c);
Dst(dst, stride, 2, 0) = Dst(dst, stride, 1, 2) = Avg2(c, d); Dst(dst, stride, 2, 0) = Dst(dst, stride, 1, 2) = Avg2(c, d);
Dst(dst, stride, 3, 0) = Dst(dst, stride, 2, 2) = Avg2(d, e); Dst(dst, stride, 3, 0) = Dst(dst, stride, 2, 2) = Avg2(d, e);
Dst(dst, stride, 3, 2) = Avg2(e, f); // Differs from vp8 Dst(dst, stride, 3, 2) = Avg2(e, f); // Differs from vp8
Dst(dst, stride, 0, 1) = Avg3(a, b, c); Dst(dst, stride, 0, 1) = Avg3(a, b, c);
Dst(dst, stride, 1, 1) = Dst(dst, stride, 0, 3) = Avg3(b, c, d); Dst(dst, stride, 1, 1) = Dst(dst, stride, 0, 3) = Avg3(b, c, d);
Dst(dst, stride, 2, 1) = Dst(dst, stride, 1, 3) = Avg3(c, d, e); Dst(dst, stride, 2, 1) = Dst(dst, stride, 1, 3) = Avg3(c, d, e);
Dst(dst, stride, 3, 1) = Dst(dst, stride, 2, 3) = Avg3(d, e, f); Dst(dst, stride, 3, 1) = Dst(dst, stride, 2, 3) = Avg3(d, e, f);
Dst(dst, stride, 3, 3) = Avg3(e, f, g); // Differs from vp8 Dst(dst, stride, 3, 3) = Avg3(e, f, g); // Differs from vp8
} }
public static unsafe void HighbdD45Predictor4x4(ushort* dst, int stride, ushort* above, ushort* left, int bd) public static unsafe void HighbdD45Predictor4x4(ushort* dst, int stride, ushort* above, ushort* left, int bd)
@@ -1306,7 +1306,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
Dst(dst, stride, 3, 0) = Dst(dst, stride, 2, 1) = Dst(dst, stride, 1, 2) = Dst(dst, stride, 0, 3) = Avg3(d, e, f); Dst(dst, stride, 3, 0) = Dst(dst, stride, 2, 1) = Dst(dst, stride, 1, 2) = Dst(dst, stride, 0, 3) = Avg3(d, e, f);
Dst(dst, stride, 3, 1) = Dst(dst, stride, 2, 2) = Dst(dst, stride, 1, 3) = Avg3(e, f, g); Dst(dst, stride, 3, 1) = Dst(dst, stride, 2, 2) = Dst(dst, stride, 1, 3) = Avg3(e, f, g);
Dst(dst, stride, 3, 2) = Dst(dst, stride, 2, 3) = Avg3(f, g, h); Dst(dst, stride, 3, 2) = Dst(dst, stride, 2, 3) = Avg3(f, g, h);
Dst(dst, stride, 3, 3) = h; // Differs from vp8 Dst(dst, stride, 3, 3) = h; // Differs from vp8
} }
public static unsafe void HighbdD117Predictor4x4(ushort* dst, int stride, ushort* above, ushort* left, int bd) public static unsafe void HighbdD117Predictor4x4(ushort* dst, int stride, ushort* above, ushort* left, int bd)

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,7 +43,8 @@ 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;
@@ -160,7 +160,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
public int ReadBit() public int ReadBit()
{ {
return Read(128); // vpx_prob_half return Read(128); // vpx_prob_half
} }
public int ReadLiteral(int bits) public int ReadLiteral(int bits)
@@ -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

@@ -12,7 +12,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
private struct Transform2D private struct Transform2D
{ {
public Transform1D Cols, Rows; // Vertical and horizontal public Transform1D Cols, Rows; // Vertical and horizontal
public Transform2D(Transform1D cols, Transform1D rows) public Transform2D(Transform1D cols, Transform1D rows)
{ {
@@ -23,7 +23,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
private struct HighbdTransform2D private struct HighbdTransform2D
{ {
public HighbdTransform1D Cols, Rows; // Vertical and horizontal public HighbdTransform1D Cols, Rows; // Vertical and horizontal
public HighbdTransform2D(HighbdTransform1D cols, HighbdTransform1D rows) public HighbdTransform2D(HighbdTransform1D cols, HighbdTransform1D rows)
{ {
@@ -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,12 +30,11 @@ 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 0x1111111111111111UL, // TX_32x32
0x1111111111111111UL, // TX_32x32
}; };
// 64 bit masks for above transform size. Each 1 represents a position where // 64 bit masks for above transform size. Each 1 represents a position where
@@ -55,12 +54,11 @@ 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 0x000000ff000000ffUL, // TX_32x32
0x000000ff000000ffUL, // TX_32x32
}; };
// 64 bit masks for prediction sizes (left). Each 1 represents a position // 64 bit masks for prediction sizes (left). Each 1 represents a position
@@ -78,148 +76,143 @@ 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, 0x0000000000000001UL, // BLOCK_8X8,
0x0000000000000001UL, // BLOCK_8X8, 0x0000000000000101UL, // BLOCK_8X16,
0x0000000000000101UL, // BLOCK_8X16, 0x0000000000000001UL, // BLOCK_16X8,
0x0000000000000001UL, // BLOCK_16X8, 0x0000000000000101UL, // BLOCK_16X16,
0x0000000000000101UL, // BLOCK_16X16, 0x0000000001010101UL, // BLOCK_16X32,
0x0000000001010101UL, // BLOCK_16X32, 0x0000000000000101UL, // BLOCK_32X16,
0x0000000000000101UL, // BLOCK_32X16, 0x0000000001010101UL, // BLOCK_32X32,
0x0000000001010101UL, // BLOCK_32X32, 0x0101010101010101UL, // BLOCK_32X64,
0x0101010101010101UL, // BLOCK_32X64, 0x0000000001010101UL, // BLOCK_64X32,
0x0000000001010101UL, // BLOCK_64X32, 0x0101010101010101UL, // BLOCK_64X64
0x0101010101010101UL, // BLOCK_64X64
}; };
// 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 0x0000000000000001UL, // BLOCK_8X8
0x0000000000000001UL, // BLOCK_8X8 0x0000000000000001UL, // BLOCK_8X16,
0x0000000000000001UL, // BLOCK_8X16, 0x0000000000000003UL, // BLOCK_16X8
0x0000000000000003UL, // BLOCK_16X8 0x0000000000000003UL, // BLOCK_16X16
0x0000000000000003UL, // BLOCK_16X16 0x0000000000000003UL, // BLOCK_16X32,
0x0000000000000003UL, // BLOCK_16X32, 0x000000000000000fUL, // BLOCK_32X16,
0x000000000000000fUL, // BLOCK_32X16, 0x000000000000000fUL, // BLOCK_32X32,
0x000000000000000fUL, // BLOCK_32X32, 0x000000000000000fUL, // BLOCK_32X64,
0x000000000000000fUL, // BLOCK_32X64, 0x00000000000000ffUL, // BLOCK_64X32,
0x00000000000000ffUL, // BLOCK_64X32, 0x00000000000000ffUL, // BLOCK_64X64
0x00000000000000ffUL, // BLOCK_64X64
}; };
// 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 0x0000000000000001UL, // BLOCK_8X8
0x0000000000000001UL, // BLOCK_8X8 0x0000000000000101UL, // BLOCK_8X16,
0x0000000000000101UL, // BLOCK_8X16, 0x0000000000000003UL, // BLOCK_16X8
0x0000000000000003UL, // BLOCK_16X8 0x0000000000000303UL, // BLOCK_16X16
0x0000000000000303UL, // BLOCK_16X16 0x0000000003030303UL, // BLOCK_16X32,
0x0000000003030303UL, // BLOCK_16X32, 0x0000000000000f0fUL, // BLOCK_32X16,
0x0000000000000f0fUL, // BLOCK_32X16, 0x000000000f0f0f0fUL, // BLOCK_32X32,
0x000000000f0f0f0fUL, // BLOCK_32X32, 0x0f0f0f0f0f0f0f0fUL, // BLOCK_32X64,
0x0f0f0f0f0f0f0f0fUL, // BLOCK_32X64, 0x00000000ffffffffUL, // BLOCK_64X32,
0x00000000ffffffffUL, // BLOCK_64X32, 0xffffffffffffffffUL, // BLOCK_64X64
0xffffffffffffffffUL, // BLOCK_64X64
}; };
// 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 0x000f, // TX_32x32
0x000f, // TX_32x32
}; };
// 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, 0x0001, // BLOCK_8X8,
0x0001, // BLOCK_8X8, 0x0001, // BLOCK_8X16,
0x0001, // BLOCK_8X16, 0x0001, // BLOCK_16X8,
0x0001, // BLOCK_16X8, 0x0001, // BLOCK_16X16,
0x0001, // BLOCK_16X16, 0x0011, // BLOCK_16X32,
0x0011, // BLOCK_16X32, 0x0001, // BLOCK_32X16,
0x0001, // BLOCK_32X16, 0x0011, // BLOCK_32X32,
0x0011, // BLOCK_32X32, 0x1111, // BLOCK_32X64
0x1111, // BLOCK_32X64 0x0011, // BLOCK_64X32,
0x0011, // BLOCK_64X32, 0x1111, // BLOCK_64X64
0x1111, // BLOCK_64X64
}; };
// 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 0x0001, // BLOCK_8X8
0x0001, // BLOCK_8X8 0x0001, // BLOCK_8X16,
0x0001, // BLOCK_8X16, 0x0001, // BLOCK_16X8
0x0001, // BLOCK_16X8 0x0001, // BLOCK_16X16
0x0001, // BLOCK_16X16 0x0001, // BLOCK_16X32,
0x0001, // BLOCK_16X32, 0x0003, // BLOCK_32X16,
0x0003, // BLOCK_32X16, 0x0003, // BLOCK_32X32,
0x0003, // BLOCK_32X32, 0x0003, // BLOCK_32X64,
0x0003, // BLOCK_32X64, 0x000f, // BLOCK_64X32,
0x000f, // BLOCK_64X32, 0x000f, // BLOCK_64X64
0x000f, // BLOCK_64X64
}; };
// 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 0x0001, // BLOCK_8X8
0x0001, // BLOCK_8X8 0x0001, // BLOCK_8X16,
0x0001, // BLOCK_8X16, 0x0001, // BLOCK_16X8
0x0001, // BLOCK_16X8 0x0001, // BLOCK_16X16
0x0001, // BLOCK_16X16 0x0011, // BLOCK_16X32,
0x0011, // BLOCK_16X32, 0x0003, // BLOCK_32X16,
0x0003, // BLOCK_32X16, 0x0033, // BLOCK_32X32,
0x0033, // BLOCK_32X32, 0x3333, // BLOCK_32X64,
0x3333, // BLOCK_32X64, 0x00ff, // BLOCK_64X32,
0x00ff, // BLOCK_64X32, 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,21 +249,19 @@ 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 i;
for (i = 0; i < bh; i++)
{ {
int index = shiftY; MemoryMarshal.CreateSpan(ref lfm.LflY[index], 64 - index)[..bw].Fill((byte)filterLevel);
int i; index += 8;
for (i = 0; i < bh; i++)
{
MemoryMarshal.CreateSpan(ref lfm.LflY[index], 64 - index).Slice(0, bw).Fill((byte)filterLevel);
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.
@@ -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

@@ -13,7 +13,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// left of the entries corresponding to real macroblocks. // left of the entries corresponding to real macroblocks.
// The prediction flags in these dummy entries are initialized to 0. // The prediction flags in these dummy entries are initialized to 0.
if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull) if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
{ // both edges available { // both edges available
if (!xd.AboveMi.Value.HasSecondRef() && !xd.LeftMi.Value.HasSecondRef()) if (!xd.AboveMi.Value.HasSecondRef() && !xd.LeftMi.Value.HasSecondRef())
{ {
// Neither edge uses comp pred (0/1) // Neither edge uses comp pred (0/1)
@@ -30,13 +30,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// One of two edges uses comp pred (2/3) // One of two edges uses comp pred (2/3)
ctx = 2 + (xd.LeftMi.Value.RefFrame[0] == cm.CompFixedRef || !xd.LeftMi.Value.IsInterBlock() ? 1 : 0); ctx = 2 + (xd.LeftMi.Value.RefFrame[0] == cm.CompFixedRef || !xd.LeftMi.Value.IsInterBlock() ? 1 : 0);
} }
else // Both edges use comp pred (4) else // Both edges use comp pred (4)
{ {
ctx = 4; ctx = 4;
} }
} }
else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull) else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull)
{ // One edge available { // One edge available
ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value; ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value;
if (!edgeMi.HasSecondRef()) if (!edgeMi.HasSecondRef())
@@ -51,10 +51,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
} }
else else
{ // No edges available (1) { // No edges available (1)
ctx = 1; ctx = 1;
} }
Debug.Assert(ctx >= 0 && ctx < Constants.CompInterContexts); Debug.Assert(ctx >= 0 && ctx < Constants.CompInterContexts);
return ctx; return ctx;
} }
@@ -70,29 +71,29 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
int varRefIdx = fixRefIdx == 0 ? 1 : 0; int varRefIdx = fixRefIdx == 0 ? 1 : 0;
if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull) if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
{ // Both edges available { // Both edges available
bool aboveIntra = !xd.AboveMi.Value.IsInterBlock(); bool aboveIntra = !xd.AboveMi.Value.IsInterBlock();
bool leftIntra = !xd.LeftMi.Value.IsInterBlock(); bool leftIntra = !xd.LeftMi.Value.IsInterBlock();
if (aboveIntra && leftIntra) if (aboveIntra && leftIntra)
{ // Intra/Intra (2) { // Intra/Intra (2)
predContext = 2; predContext = 2;
} }
else if (aboveIntra || leftIntra) else if (aboveIntra || leftIntra)
{ // Intra/Inter { // Intra/Inter
ref ModeInfo edgeMi = ref aboveIntra ? ref xd.LeftMi.Value : ref xd.AboveMi.Value; ref ModeInfo edgeMi = ref aboveIntra ? ref xd.LeftMi.Value : ref xd.AboveMi.Value;
if (!edgeMi.HasSecondRef()) // single pred (1/3) if (!edgeMi.HasSecondRef()) // single pred (1/3)
{ {
predContext = 1 + 2 * (edgeMi.RefFrame[0] != cm.CompVarRef[1] ? 1 : 0); predContext = 1 + 2 * (edgeMi.RefFrame[0] != cm.CompVarRef[1] ? 1 : 0);
} }
else // Comp pred (1/3) else // Comp pred (1/3)
{ {
predContext = 1 + 2 * (edgeMi.RefFrame[varRefIdx] != cm.CompVarRef[1] ? 1 : 0); predContext = 1 + 2 * (edgeMi.RefFrame[varRefIdx] != cm.CompVarRef[1] ? 1 : 0);
} }
} }
else else
{ // Inter/Inter { // Inter/Inter
bool lSg = !xd.LeftMi.Value.HasSecondRef(); bool lSg = !xd.LeftMi.Value.HasSecondRef();
bool aSg = !xd.AboveMi.Value.HasSecondRef(); bool aSg = !xd.AboveMi.Value.HasSecondRef();
sbyte vrfa = aSg ? xd.AboveMi.Value.RefFrame[0] : xd.AboveMi.Value.RefFrame[varRefIdx]; sbyte vrfa = aSg ? xd.AboveMi.Value.RefFrame[0] : xd.AboveMi.Value.RefFrame[varRefIdx];
@@ -103,7 +104,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
predContext = 0; predContext = 0;
} }
else if (lSg && aSg) else if (lSg && aSg)
{ // Single/Single { // Single/Single
if ((vrfa == cm.CompFixedRef && vrfl == cm.CompVarRef[0]) || if ((vrfa == cm.CompFixedRef && vrfl == cm.CompVarRef[0]) ||
(vrfl == cm.CompFixedRef && vrfa == cm.CompVarRef[0])) (vrfl == cm.CompFixedRef && vrfa == cm.CompVarRef[0]))
{ {
@@ -119,7 +120,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
} }
else if (lSg || aSg) else if (lSg || aSg)
{ // Single/Comp { // Single/Comp
sbyte vrfc = lSg ? vrfa : vrfl; sbyte vrfc = lSg ? vrfa : vrfl;
sbyte rfs = aSg ? vrfa : vrfl; sbyte rfs = aSg ? vrfa : vrfl;
if (vrfc == cm.CompVarRef[1] && rfs != cm.CompVarRef[1]) if (vrfc == cm.CompVarRef[1] && rfs != cm.CompVarRef[1])
@@ -136,7 +137,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
} }
else if (vrfa == vrfl) else if (vrfa == vrfl)
{ // Comp/Comp { // Comp/Comp
predContext = 4; predContext = 4;
} }
else else
@@ -146,7 +147,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
} }
else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull) else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull)
{ // One edge available { // One edge available
ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value; ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value;
if (!edgeMi.IsInterBlock()) if (!edgeMi.IsInterBlock())
@@ -166,10 +167,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
} }
else else
{ // No edges available (2) { // No edges available (2)
predContext = 2; predContext = 2;
} }
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts); Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
return predContext; return predContext;
} }
@@ -181,16 +183,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// left of the entries corresponding to real macroblocks. // left of the entries corresponding to real macroblocks.
// The prediction flags in these dummy entries are initialized to 0. // The prediction flags in these dummy entries are initialized to 0.
if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull) if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
{ // Both edges available { // Both edges available
bool aboveIntra = !xd.AboveMi.Value.IsInterBlock(); bool aboveIntra = !xd.AboveMi.Value.IsInterBlock();
bool leftIntra = !xd.LeftMi.Value.IsInterBlock(); bool leftIntra = !xd.LeftMi.Value.IsInterBlock();
if (aboveIntra && leftIntra) if (aboveIntra && leftIntra)
{ // Intra/Intra { // Intra/Intra
predContext = 2; predContext = 2;
} }
else if (aboveIntra || leftIntra) else if (aboveIntra || leftIntra)
{ // Intra/Inter or Inter/Intra { // Intra/Inter or Inter/Intra
ref ModeInfo edgeMi = ref aboveIntra ? ref xd.LeftMi.Value : ref xd.AboveMi.Value; ref ModeInfo edgeMi = ref aboveIntra ? ref xd.LeftMi.Value : ref xd.AboveMi.Value;
if (!edgeMi.HasSecondRef()) if (!edgeMi.HasSecondRef())
{ {
@@ -203,7 +205,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
} }
else else
{ // Inter/Inter { // Inter/Inter
bool aboveHasSecond = xd.AboveMi.Value.HasSecondRef(); bool aboveHasSecond = xd.AboveMi.Value.HasSecondRef();
bool leftHasSecond = xd.LeftMi.Value.HasSecondRef(); bool leftHasSecond = xd.LeftMi.Value.HasSecondRef();
sbyte above0 = xd.AboveMi.Value.RefFrame[0]; sbyte above0 = xd.AboveMi.Value.RefFrame[0];
@@ -238,14 +240,14 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
} }
else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull) else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull)
{ // One edge available { // One edge available
ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value; ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value;
if (!edgeMi.IsInterBlock()) if (!edgeMi.IsInterBlock())
{ // Intra { // Intra
predContext = 2; predContext = 2;
} }
else else
{ // Inter { // Inter
if (!edgeMi.HasSecondRef()) if (!edgeMi.HasSecondRef())
{ {
predContext = 4 * (edgeMi.RefFrame[0] == Constants.LastFrame ? 1 : 0); predContext = 4 * (edgeMi.RefFrame[0] == Constants.LastFrame ? 1 : 0);
@@ -258,10 +260,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
} }
else else
{ // No edges available { // No edges available
predContext = 2; predContext = 2;
} }
Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts); Debug.Assert(predContext >= 0 && predContext < Constants.RefContexts);
return predContext; return predContext;
} }
@@ -274,16 +277,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
// left of the entries corresponding to real macroblocks. // left of the entries corresponding to real macroblocks.
// The prediction flags in these dummy entries are initialized to 0. // The prediction flags in these dummy entries are initialized to 0.
if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull) if (!xd.AboveMi.IsNull && !xd.LeftMi.IsNull)
{ // Both edges available { // Both edges available
bool aboveIntra = !xd.AboveMi.Value.IsInterBlock(); bool aboveIntra = !xd.AboveMi.Value.IsInterBlock();
bool leftIntra = !xd.LeftMi.Value.IsInterBlock(); bool leftIntra = !xd.LeftMi.Value.IsInterBlock();
if (aboveIntra && leftIntra) if (aboveIntra && leftIntra)
{ // Intra/Intra { // Intra/Intra
predContext = 2; predContext = 2;
} }
else if (aboveIntra || leftIntra) else if (aboveIntra || leftIntra)
{ // Intra/Inter or Inter/Intra { // Intra/Inter or Inter/Intra
ref ModeInfo edgeMi = ref aboveIntra ? ref xd.LeftMi.Value : ref xd.AboveMi.Value; ref ModeInfo edgeMi = ref aboveIntra ? ref xd.LeftMi.Value : ref xd.AboveMi.Value;
if (!edgeMi.HasSecondRef()) if (!edgeMi.HasSecondRef())
{ {
@@ -303,7 +306,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
} }
else else
{ // Inter/Inter { // Inter/Inter
bool aboveHasSecond = xd.AboveMi.Value.HasSecondRef(); bool aboveHasSecond = xd.AboveMi.Value.HasSecondRef();
bool leftHasSecond = xd.LeftMi.Value.HasSecondRef(); bool leftHasSecond = xd.LeftMi.Value.HasSecondRef();
sbyte above0 = xd.AboveMi.Value.RefFrame[0]; sbyte above0 = xd.AboveMi.Value.RefFrame[0];
@@ -361,7 +364,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
} }
else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull) else if (!xd.AboveMi.IsNull || !xd.LeftMi.IsNull)
{ // One edge available { // One edge available
ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value; ref ModeInfo edgeMi = ref !xd.AboveMi.IsNull ? ref xd.AboveMi.Value : ref xd.LeftMi.Value;
if (!edgeMi.IsInterBlock() || (edgeMi.RefFrame[0] == Constants.LastFrame && !edgeMi.HasSecondRef())) if (!edgeMi.IsInterBlock() || (edgeMi.RefFrame[0] == Constants.LastFrame && !edgeMi.HasSecondRef()))
@@ -379,10 +382,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
} }
else else
{ // No edges available (2) { // No edges available (2)
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,18 +7,17 @@ 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 TxType.DctDct, // D45
TxType.DctDct, // D45 TxType.AdstAdst, // D135
TxType.AdstAdst, // D135 TxType.AdstDct, // D117
TxType.AdstDct, // D117 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;
@@ -27,244 +26,240 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
private static ReadOnlySpan<byte> ExtendModes => new byte[] private static ReadOnlySpan<byte> ExtendModes => new byte[]
{ {
NeedAbove | NeedLeft, // DC NeedAbove | NeedLeft, // DC
NeedAbove, // V NeedAbove, // V
NeedLeft, // H NeedLeft, // H
NeedAboveRight, // D45 NeedAboveRight, // D45
NeedLeft | NeedAbove, // D135 NeedLeft | NeedAbove, // D135
NeedLeft | NeedAbove, // D117 NeedLeft | NeedAbove, // D117
NeedLeft | NeedAbove, // D153 NeedLeft | NeedAbove, // D153
NeedLeft, // D207 NeedLeft, // D207
NeedAboveRight, // D63 NeedAboveRight, // D63
NeedLeft | NeedAbove, // TM NeedLeft | NeedAbove, // TM
}; };
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

@@ -5,6 +5,6 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
internal struct BModeInfo internal struct BModeInfo
{ {
public PredictionMode Mode; public PredictionMode Mode;
public Array2<Mv> Mv; // First, second inter predictor motion vectors public Array2<Mv> Mv; // First, second inter predictor motion vectors
} }
} }

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,16 +104,18 @@ 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)
{ // One edge available if (!AboveMi.IsNull || !LeftMi.IsNull)
{ // 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);
} }
return 0; return 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

@@ -11,7 +11,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
public TxSize TxSize; public TxSize TxSize;
public sbyte Skip; public sbyte Skip;
public sbyte SegmentId; public sbyte SegmentId;
public sbyte SegIdPredicted; // Valid only when TemporalUpdate is enabled public sbyte SegIdPredicted; // Valid only when TemporalUpdate is enabled
// Only for Intra blocks // Only for Intra blocks
public PredictionMode UvMode; public PredictionMode UvMode;
@@ -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];
} }
} }

View File

@@ -9,6 +9,6 @@
BothNew = 4, BothNew = 4,
IntraPlusNonIntra = 5, IntraPlusNonIntra = 5,
BothIntra = 6, BothIntra = 6,
InvalidCase = 9 InvalidCase = 9,
} }
} }

View File

@@ -51,13 +51,13 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10,
}; };
public bool UseMvHp() public readonly bool UseMvHp()
{ {
const int kMvRefThresh = 64; // Threshold for use of high-precision 1/8 mv const int KMvRefThresh = 64; // Threshold for use of high-precision 1/8 mv
return Math.Abs(Row) < kMvRefThresh && Math.Abs(Col) < kMvRefThresh; return Math.Abs(Row) < KMvRefThresh && Math.Abs(Col) < KMvRefThresh;
} }
public static bool MvJointVertical(MvJointType type) public static bool MvJointVertical(MvJointType type)
@@ -110,7 +110,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
else else
{ {
int i; int i;
int b = c + Constants.Class0Bits - 1; // Number of bits int b = c + Constants.Class0Bits - 1; // Number of bits
for (i = 0; i < b; ++i) for (i = 0; i < b; ++i)
{ {
counts.Bits[comp][i][((d >> i) & 1)] += (uint)incr; counts.Bits[comp][i][((d >> i) & 1)] += (uint)incr;
@@ -121,19 +121,17 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
} }
} }
private MvJointType GetMvJoint() private readonly MvJointType GetMvJoint()
{ {
if (Row == 0) if (Row == 0)
{ {
return Col == 0 ? MvJointType.MvJointZero : MvJointType.MvJointHnzvz; return Col == 0 ? MvJointType.MvJointZero : MvJointType.MvJointHnzvz;
} }
else
{ return Col == 0 ? MvJointType.MvJointHzvnz : MvJointType.MvJointHnzvnz;
return Col == 0 ? MvJointType.MvJointHzvnz : MvJointType.MvJointHnzvnz;
}
} }
internal void IncMv(Ptr<Vp9BackwardUpdates> counts) internal readonly void IncMv(Ptr<Vp9BackwardUpdates> counts)
{ {
if (!counts.IsNull) if (!counts.IsNull)
{ {
@@ -158,7 +156,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
Row = (short)Math.Clamp(Row, minRow, maxRow); Row = (short)Math.Clamp(Row, minRow, maxRow);
} }
private const int MvBorder = (16 << 3); // Allow 16 pels in 1/8th pel units private const int MvBorder = (16 << 3); // Allow 16 pels in 1/8th pel units
public void ClampMvRef(ref MacroBlockD xd) public void ClampMvRef(ref MacroBlockD xd)
{ {

View File

@@ -7,6 +7,6 @@
PartitionVert, PartitionVert,
PartitionSplit, PartitionSplit,
PartitionTypes, PartitionTypes,
PartitionInvalid = PartitionTypes PartitionInvalid = PartitionTypes,
} }
} }

View File

@@ -4,6 +4,6 @@
{ {
Y = 0, Y = 0,
Uv = 1, Uv = 1,
PlaneTypes PlaneTypes,
} }
} }

View File

@@ -2,20 +2,20 @@
{ {
internal enum PredictionMode internal enum PredictionMode
{ {
DcPred = 0, // Average of above and left pixels DcPred = 0, // Average of above and left pixels
VPred = 1, // Vertical VPred = 1, // Vertical
HPred = 2, // Horizontal HPred = 2, // Horizontal
D45Pred = 3, // Directional 45 deg = round(arctan(1 / 1) * 180 / pi) D45Pred = 3, // Directional 45 deg = round(arctan(1 / 1) * 180 / pi)
D135Pred = 4, // Directional 135 deg = 180 - 45 D135Pred = 4, // Directional 135 deg = 180 - 45
D117Pred = 5, // Directional 117 deg = 180 - 63 D117Pred = 5, // Directional 117 deg = 180 - 63
D153Pred = 6, // Directional 153 deg = 180 - 27 D153Pred = 6, // Directional 153 deg = 180 - 27
D207Pred = 7, // Directional 207 deg = 180 + 27 D207Pred = 7, // Directional 207 deg = 180 + 27
D63Pred = 8, // Directional 63 deg = round(arctan(2 / 1) * 180 / pi) D63Pred = 8, // Directional 63 deg = round(arctan(2 / 1) * 180 / pi)
TmPred = 9, // True-motion TmPred = 9, // True-motion
NearestMv = 10, NearestMv = 10,
NearMv = 11, NearMv = 11,
ZeroMv = 12, ZeroMv = 12,
NewMv = 13, NewMv = 13,
MbModeCount = 14 MbModeCount = 14,
} }
} }

View File

@@ -5,6 +5,6 @@
SingleReference = 0, SingleReference = 0,
CompoundReference = 1, CompoundReference = 1,
ReferenceModeSelect = 2, ReferenceModeSelect = 2,
ReferenceModes = 3 ReferenceModes = 3,
} }
} }

View File

@@ -38,263 +38,255 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
int h, int h,
int bd); int bd);
private static readonly unsafe ConvolveFn[][][] PredictX16Y16 = new ConvolveFn[][][] private static readonly unsafe ConvolveFn[][][] _predictX16Y16 = {
{ new[]
new ConvolveFn[][]
{ {
new ConvolveFn[] new ConvolveFn[]
{ {
ConvolveCopy, ConvolveCopy,
ConvolveAvg ConvolveAvg,
}, },
new ConvolveFn[] new ConvolveFn[]
{ {
Convolve8Vert, Convolve8Vert,
Convolve8AvgVert Convolve8AvgVert,
} },
}, },
new ConvolveFn[][] new[]
{ {
new ConvolveFn[] new ConvolveFn[]
{ {
Convolve8Horiz, Convolve8Horiz,
Convolve8AvgHoriz Convolve8AvgHoriz,
}, },
new ConvolveFn[] new ConvolveFn[]
{ {
Convolve8, Convolve8,
Convolve8Avg Convolve8Avg,
} },
} },
}; };
private static readonly unsafe ConvolveFn[][][] PredictX16 = new ConvolveFn[][][] private static readonly unsafe ConvolveFn[][][] _predictX16 = {
{ new[]
new ConvolveFn[][]
{ {
new ConvolveFn[] new ConvolveFn[]
{ {
ScaledVert, ScaledVert,
ScaledAvgVert ScaledAvgVert,
}, },
new ConvolveFn[] new ConvolveFn[]
{ {
ScaledVert, ScaledVert,
ScaledAvgVert ScaledAvgVert,
} },
}, },
new ConvolveFn[][] new[]
{ {
new ConvolveFn[] new ConvolveFn[]
{ {
Scaled2D, Scaled2D,
ScaledAvg2D ScaledAvg2D,
}, },
new ConvolveFn[] new ConvolveFn[]
{ {
Scaled2D, Scaled2D,
ScaledAvg2D ScaledAvg2D,
} },
} },
}; };
private static readonly unsafe ConvolveFn[][][] PredictY16 = new ConvolveFn[][][] private static readonly unsafe ConvolveFn[][][] _predictY16 = {
{ new[]
new ConvolveFn[][]
{ {
new ConvolveFn[] new ConvolveFn[]
{ {
ScaledHoriz, ScaledHoriz,
ScaledAvgHoriz ScaledAvgHoriz,
}, },
new ConvolveFn[] new ConvolveFn[]
{ {
Scaled2D, Scaled2D,
ScaledAvg2D ScaledAvg2D,
} },
}, },
new ConvolveFn[][] new[]
{ {
new ConvolveFn[] new ConvolveFn[]
{ {
ScaledHoriz, ScaledHoriz,
ScaledAvgHoriz ScaledAvgHoriz,
}, },
new ConvolveFn[] new ConvolveFn[]
{ {
Scaled2D, Scaled2D,
ScaledAvg2D ScaledAvg2D,
}
}
};
private static readonly unsafe ConvolveFn[][][] Predict = new ConvolveFn[][][]
{
new ConvolveFn[][]
{
new ConvolveFn[]
{
Scaled2D,
ScaledAvg2D
}, },
new ConvolveFn[]
{
Scaled2D,
ScaledAvg2D
}
}, },
new ConvolveFn[][] };
private static readonly unsafe ConvolveFn[][][] _predict = {
new[]
{ {
new ConvolveFn[] new ConvolveFn[]
{ {
Scaled2D, Scaled2D,
ScaledAvg2D ScaledAvg2D,
}, },
new ConvolveFn[] new ConvolveFn[]
{ {
Scaled2D, Scaled2D,
ScaledAvg2D ScaledAvg2D,
} },
} },
new[]
{
new ConvolveFn[]
{
Scaled2D,
ScaledAvg2D,
},
new ConvolveFn[]
{
Scaled2D,
ScaledAvg2D,
},
},
}; };
private static readonly unsafe HighbdConvolveFn[][][] HighbdPredictX16Y16 = new HighbdConvolveFn[][][] private static readonly unsafe HighbdConvolveFn[][][] _highbdPredictX16Y16 = {
{ new[]
new HighbdConvolveFn[][]
{ {
new HighbdConvolveFn[] new HighbdConvolveFn[]
{ {
HighbdConvolveCopy, HighbdConvolveCopy,
HighbdConvolveAvg HighbdConvolveAvg,
}, },
new HighbdConvolveFn[] new HighbdConvolveFn[]
{ {
HighbdConvolve8Vert, HighbdConvolve8Vert,
HighbdConvolve8AvgVert HighbdConvolve8AvgVert,
} },
}, },
new HighbdConvolveFn[][] new[]
{ {
new HighbdConvolveFn[] new HighbdConvolveFn[]
{ {
HighbdConvolve8Horiz, HighbdConvolve8Horiz,
HighbdConvolve8AvgHoriz HighbdConvolve8AvgHoriz,
}, },
new HighbdConvolveFn[] new HighbdConvolveFn[]
{ {
HighbdConvolve8, HighbdConvolve8,
HighbdConvolve8Avg HighbdConvolve8Avg,
} },
} },
}; };
private static readonly unsafe HighbdConvolveFn[][][] HighbdPredictX16 = new HighbdConvolveFn[][][] private static readonly unsafe HighbdConvolveFn[][][] _highbdPredictX16 = {
{ new[]
new HighbdConvolveFn[][]
{ {
new HighbdConvolveFn[] new HighbdConvolveFn[]
{ {
HighbdConvolve8Vert, HighbdConvolve8Vert,
HighbdConvolve8AvgVert HighbdConvolve8AvgVert,
}, },
new HighbdConvolveFn[] new HighbdConvolveFn[]
{ {
HighbdConvolve8Vert, HighbdConvolve8Vert,
HighbdConvolve8AvgVert HighbdConvolve8AvgVert,
} },
}, },
new HighbdConvolveFn[][] new[]
{ {
new HighbdConvolveFn[] new HighbdConvolveFn[]
{ {
HighbdConvolve8, HighbdConvolve8,
HighbdConvolve8Avg HighbdConvolve8Avg,
}, },
new HighbdConvolveFn[] new HighbdConvolveFn[]
{ {
HighbdConvolve8, HighbdConvolve8,
HighbdConvolve8Avg HighbdConvolve8Avg,
} },
} },
}; };
private static readonly unsafe HighbdConvolveFn[][][] HighbdPredictY16 = new HighbdConvolveFn[][][] private static readonly unsafe HighbdConvolveFn[][][] _highbdPredictY16 = {
{ new[]
new HighbdConvolveFn[][]
{ {
new HighbdConvolveFn[] new HighbdConvolveFn[]
{ {
HighbdConvolve8Horiz, HighbdConvolve8Horiz,
HighbdConvolve8AvgHoriz HighbdConvolve8AvgHoriz,
}, },
new HighbdConvolveFn[] new HighbdConvolveFn[]
{ {
HighbdConvolve8, HighbdConvolve8,
HighbdConvolve8Avg HighbdConvolve8Avg,
} },
}, },
new HighbdConvolveFn[][] new[]
{ {
new HighbdConvolveFn[] new HighbdConvolveFn[]
{ {
HighbdConvolve8Horiz, HighbdConvolve8Horiz,
HighbdConvolve8AvgHoriz HighbdConvolve8AvgHoriz,
}, },
new HighbdConvolveFn[] new HighbdConvolveFn[]
{ {
HighbdConvolve8, HighbdConvolve8,
HighbdConvolve8Avg HighbdConvolve8Avg,
}
}
};
private static readonly unsafe HighbdConvolveFn[][][] HighbdPredict = new HighbdConvolveFn[][][]
{
new HighbdConvolveFn[][]
{
new HighbdConvolveFn[]
{
HighbdConvolve8,
HighbdConvolve8Avg
}, },
new HighbdConvolveFn[]
{
HighbdConvolve8,
HighbdConvolve8Avg
}
}, },
new HighbdConvolveFn[][] };
private static readonly unsafe HighbdConvolveFn[][][] _highbdPredict = {
new[]
{ {
new HighbdConvolveFn[] new HighbdConvolveFn[]
{ {
HighbdConvolve8, HighbdConvolve8,
HighbdConvolve8Avg HighbdConvolve8Avg,
}, },
new HighbdConvolveFn[] new HighbdConvolveFn[]
{ {
HighbdConvolve8, HighbdConvolve8,
HighbdConvolve8Avg HighbdConvolve8Avg,
} },
} },
new[]
{
new HighbdConvolveFn[]
{
HighbdConvolve8,
HighbdConvolve8Avg,
},
new HighbdConvolveFn[]
{
HighbdConvolve8,
HighbdConvolve8Avg,
},
},
}; };
public int XScaleFP; // Horizontal fixed point scale factor public int XScaleFP; // Horizontal fixed point scale factor
public int YScaleFP; // Vertical fixed point scale factor public int YScaleFP; // Vertical fixed point scale factor
public int XStepQ4; public int XStepQ4;
public int YStepQ4; public int YStepQ4;
public int ScaleValueX(int val) public readonly int ScaleValueX(int val)
{ {
return IsScaled() ? ScaledX(val) : val; return IsScaled() ? ScaledX(val) : val;
} }
public int ScaleValueY(int val) public readonly int ScaleValueY(int val)
{ {
return IsScaled() ? ScaledY(val) : val; return IsScaled() ? ScaledY(val) : val;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe void InterPredict( public readonly unsafe void InterPredict(
int horiz, int horiz,
int vert, int vert,
int avg, int avg,
@@ -315,12 +307,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
if (YStepQ4 == 16) if (YStepQ4 == 16)
{ {
// No scaling in either direction. // No scaling in either direction.
PredictX16Y16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h); _predictX16Y16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h);
} }
else else
{ {
// No scaling in x direction. Must always scale in the y direction. // No scaling in x direction. Must always scale in the y direction.
PredictX16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h); _predictX16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h);
} }
} }
else else
@@ -328,18 +320,18 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
if (YStepQ4 == 16) if (YStepQ4 == 16)
{ {
// No scaling in the y direction. Must always scale in the x direction. // No scaling in the y direction. Must always scale in the x direction.
PredictY16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h); _predictY16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h);
} }
else else
{ {
// Must always scale in both directions. // Must always scale in both directions.
Predict[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h); _predict[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h);
} }
} }
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe void HighbdInterPredict( public readonly unsafe void HighbdInterPredict(
int horiz, int horiz,
int vert, int vert,
int avg, int avg,
@@ -361,12 +353,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
if (YStepQ4 == 16) if (YStepQ4 == 16)
{ {
// No scaling in either direction. // No scaling in either direction.
HighbdPredictX16Y16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd); _highbdPredictX16Y16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd);
} }
else else
{ {
// No scaling in x direction. Must always scale in the y direction. // No scaling in x direction. Must always scale in the y direction.
HighbdPredictX16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd); _highbdPredictX16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd);
} }
} }
else else
@@ -374,22 +366,22 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
if (YStepQ4 == 16) if (YStepQ4 == 16)
{ {
// No scaling in the y direction. Must always scale in the x direction. // No scaling in the y direction. Must always scale in the x direction.
HighbdPredictY16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd); _highbdPredictY16[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd);
} }
else else
{ {
// Must always scale in both directions. // Must always scale in both directions.
HighbdPredict[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd); _highbdPredict[horiz][vert][avg](src, srcStride, dst, dstStride, kernel, subpelX, xs, subpelY, ys, w, h, bd);
} }
} }
} }
private int ScaledX(int val) private readonly int ScaledX(int val)
{ {
return (int)((long)val * XScaleFP >> RefScaleShift); return (int)((long)val * XScaleFP >> RefScaleShift);
} }
private int ScaledY(int val) private readonly int ScaledY(int val)
{ {
return (int)((long)val * YScaleFP >> RefScaleShift); return (int)((long)val * YScaleFP >> RefScaleShift);
} }
@@ -407,20 +399,21 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{ {
int xOffQ4 = ScaledX(x << SubpelBits) & SubpelMask; int xOffQ4 = ScaledX(x << SubpelBits) & SubpelMask;
int yOffQ4 = ScaledY(y << SubpelBits) & SubpelMask; int yOffQ4 = ScaledY(y << SubpelBits) & SubpelMask;
Mv32 res = new Mv32() Mv32 res = new()
{ {
Row = ScaledY(mv.Row) + yOffQ4, Row = ScaledY(mv.Row) + yOffQ4,
Col = ScaledX(mv.Col) + xOffQ4 Col = ScaledX(mv.Col) + xOffQ4,
}; };
return res; return res;
} }
public bool IsValidScale() public readonly bool IsValidScale()
{ {
return XScaleFP != RefInvalidScale && YScaleFP != RefInvalidScale; return XScaleFP != RefInvalidScale && YScaleFP != RefInvalidScale;
} }
public bool IsScaled() public readonly bool IsScaled()
{ {
return IsValidScale() && (XScaleFP != RefNoScale || YScaleFP != RefNoScale); return IsValidScale() && (XScaleFP != RefNoScale || YScaleFP != RefNoScale);
} }
@@ -439,6 +432,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{ {
XScaleFP = RefInvalidScale; XScaleFP = RefInvalidScale;
YScaleFP = RefInvalidScale; YScaleFP = RefInvalidScale;
return; return;
} }

View File

@@ -2,10 +2,10 @@
{ {
internal enum SegLvlFeatures internal enum SegLvlFeatures
{ {
SegLvlAltQ = 0, // Use alternate Quantizer .... SegLvlAltQ = 0, // Use alternate Quantizer ....
SegLvlAltLf = 1, // Use alternate loop filter value... SegLvlAltLf = 1, // Use alternate loop filter value...
SegLvlRefFrame = 2, // Optional Segment reference frame SegLvlRefFrame = 2, // Optional Segment reference frame
SegLvlSkip = 3, // Optional Segment (0,0) + skip mode SegLvlSkip = 3, // Optional Segment (0,0) + skip mode
SegLvlMax = 4 // Number of features supported SegLvlMax = 4, // Number of features supported
} }
} }

View File

@@ -6,8 +6,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{ {
internal struct Segmentation internal struct Segmentation
{ {
private static readonly int[] SegFeatureDataSigned = new int[] { 1, 1, 0, 0 }; private static readonly int[] _segFeatureDataSigned = { 1, 1, 0, 0 };
private static readonly int[] SegFeatureDataMax = new int[] { QuantCommon.MaxQ, Vp9.LoopFilter.MaxLoopFilter, 3, 0 }; private static readonly int[] _segFeatureDataMax = { QuantCommon.MaxQ, Vp9.LoopFilter.MaxLoopFilter, 3, 0 };
public bool Enabled; public bool Enabled;
public bool UpdateMap; public bool UpdateMap;
@@ -26,8 +26,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
public void ClearAllSegFeatures() public void ClearAllSegFeatures()
{ {
MemoryMarshal.CreateSpan(ref FeatureData[0][0], 8 * 4).Fill(0); MemoryMarshal.CreateSpan(ref FeatureData[0][0], 8 * 4).Clear();
MemoryMarshal.CreateSpan(ref FeatureMask[0], 8).Fill(0); MemoryMarshal.CreateSpan(ref FeatureMask[0], 8).Clear();
AqAvOffset = 0; AqAvOffset = 0;
} }
@@ -38,21 +38,21 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
internal static int FeatureDataMax(SegLvlFeatures featureId) internal static int FeatureDataMax(SegLvlFeatures featureId)
{ {
return SegFeatureDataMax[(int)featureId]; return _segFeatureDataMax[(int)featureId];
} }
internal static int IsSegFeatureSigned(SegLvlFeatures featureId) internal static int IsSegFeatureSigned(SegLvlFeatures featureId)
{ {
return SegFeatureDataSigned[(int)featureId]; return _segFeatureDataSigned[(int)featureId];
} }
internal void SetSegData(int segmentId, SegLvlFeatures featureId, int segData) internal void SetSegData(int segmentId, SegLvlFeatures featureId, int segData)
{ {
Debug.Assert(segData <= SegFeatureDataMax[(int)featureId]); Debug.Assert(segData <= _segFeatureDataMax[(int)featureId]);
if (segData < 0) if (segData < 0)
{ {
Debug.Assert(SegFeatureDataSigned[(int)featureId] != 0); Debug.Assert(_segFeatureDataSigned[(int)featureId] != 0);
Debug.Assert(-segData <= SegFeatureDataMax[(int)featureId]); Debug.Assert(-segData <= _segFeatureDataMax[(int)featureId]);
} }
FeatureData[segmentId][(int)featureId] = (short)segData; FeatureData[segmentId][(int)featureId] = (short)segData;

View File

@@ -11,11 +11,11 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
public ArrayPtr<byte> UBuffer; public ArrayPtr<byte> UBuffer;
public ArrayPtr<byte> VBuffer; public ArrayPtr<byte> VBuffer;
public unsafe Plane YPlane => new Plane((IntPtr)YBuffer.ToPointer(), YBuffer.Length); public readonly unsafe Plane YPlane => new((IntPtr)YBuffer.ToPointer(), YBuffer.Length);
public unsafe Plane UPlane => new Plane((IntPtr)UBuffer.ToPointer(), UBuffer.Length); public readonly unsafe Plane UPlane => new((IntPtr)UBuffer.ToPointer(), UBuffer.Length);
public unsafe Plane VPlane => new Plane((IntPtr)VBuffer.ToPointer(), VBuffer.Length); public readonly unsafe Plane VPlane => new((IntPtr)VBuffer.ToPointer(), VBuffer.Length);
public FrameField Field => FrameField.Progressive; public readonly FrameField Field => FrameField.Progressive;
public int Width { get; } public int Width { get; }
public int Height { get; } public int Height { get; }
@@ -27,29 +27,31 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
public int UvAlignedWidth { get; } public int UvAlignedWidth { get; }
public int UvAlignedHeight { get; } public int UvAlignedHeight { get; }
public int UvStride { get; } public int UvStride { get; }
public bool HighBd => false;
public bool HighBd { get; }
private readonly IntPtr _pointer; private readonly IntPtr _pointer;
public Surface(int width, int height) public Surface(int width, int height)
{ {
const int border = 32; HighBd = false;
const int ssX = 1;
const int ssY = 1; const int Border = 32;
const bool highbd = false; const int SsX = 1;
const int SsY = 1;
int alignedWidth = (width + 7) & ~7; int alignedWidth = (width + 7) & ~7;
int alignedHeight = (height + 7) & ~7; int alignedHeight = (height + 7) & ~7;
int yStride = ((alignedWidth + 2 * border) + 31) & ~31; int yStride = ((alignedWidth + 2 * Border) + 31) & ~31;
int yplaneSize = (alignedHeight + 2 * border) * yStride; int yplaneSize = (alignedHeight + 2 * Border) * yStride;
int uvWidth = alignedWidth >> ssX; int uvWidth = alignedWidth >> SsX;
int uvHeight = alignedHeight >> ssY; int uvHeight = alignedHeight >> SsY;
int uvStride = yStride >> ssX; int uvStride = yStride >> SsX;
int uvBorderW = border >> ssX; int uvBorderW = Border >> SsX;
int uvBorderH = border >> ssY; int uvBorderH = Border >> SsY;
int uvplaneSize = (uvHeight + 2 * uvBorderH) * uvStride; int uvplaneSize = (uvHeight + 2 * uvBorderH) * uvStride;
int frameSize = (highbd ? 2 : 1) * (yplaneSize + 2 * uvplaneSize); int frameSize = (HighBd ? 2 : 1) * (yplaneSize + 2 * uvplaneSize);
IntPtr pointer = Marshal.AllocHGlobal(frameSize); IntPtr pointer = Marshal.AllocHGlobal(frameSize);
_pointer = pointer; _pointer = pointer;
@@ -58,23 +60,23 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
AlignedWidth = alignedWidth; AlignedWidth = alignedWidth;
AlignedHeight = alignedHeight; AlignedHeight = alignedHeight;
Stride = yStride; Stride = yStride;
UvWidth = (width + ssX) >> ssX; UvWidth = (width + SsX) >> SsX;
UvHeight = (height + ssY) >> ssY; UvHeight = (height + SsY) >> SsY;
UvAlignedWidth = uvWidth; UvAlignedWidth = uvWidth;
UvAlignedHeight = uvHeight; UvAlignedHeight = uvHeight;
UvStride = uvStride; UvStride = uvStride;
ArrayPtr<byte> NewPlane(int start, int size, int border) ArrayPtr<byte> NewPlane(int start, int size, int planeBorder)
{ {
return new ArrayPtr<byte>(pointer + start + border, size - border); return new ArrayPtr<byte>(pointer + start + planeBorder, size - planeBorder);
} }
YBuffer = NewPlane(0, yplaneSize, (border * yStride) + border); YBuffer = NewPlane(0, yplaneSize, (Border * yStride) + Border);
UBuffer = NewPlane(yplaneSize, uvplaneSize, (uvBorderH * uvStride) + uvBorderW); UBuffer = NewPlane(yplaneSize, uvplaneSize, (uvBorderH * uvStride) + uvBorderW);
VBuffer = NewPlane(yplaneSize + uvplaneSize, uvplaneSize, (uvBorderH * uvStride) + uvBorderW); VBuffer = NewPlane(yplaneSize + uvplaneSize, uvplaneSize, (uvBorderH * uvStride) + uvBorderW);
} }
public void Dispose() public readonly void Dispose()
{ {
Marshal.FreeHGlobal(_pointer); Marshal.FreeHGlobal(_pointer);
} }

View File

@@ -21,6 +21,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
{ {
int sbCols = MiColsAlignedToSb(mis) >> Constants.MiBlockSizeLog2; int sbCols = MiColsAlignedToSb(mis) >> Constants.MiBlockSizeLog2;
int offset = ((idx * sbCols) >> log2) << Constants.MiBlockSizeLog2; int offset = ((idx * sbCols) >> log2) << Constants.MiBlockSizeLog2;
return Math.Min(offset, mis); return Math.Min(offset, mis);
} }
@@ -44,7 +45,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
// Checks that the given miRow, miCol and search point // Checks that the given miRow, miCol and search point
// are inside the borders of the tile. // are inside the borders of the tile.
public bool IsInside(int miCol, int miRow, int miRows, ref Position miPos) public readonly bool IsInside(int miCol, int miRow, int miRows, ref Position miPos)
{ {
return !(miRow + miPos.Row < 0 || return !(miRow + miPos.Row < 0 ||
miCol + miPos.Col < MiColStart || miCol + miPos.Col < MiColStart ||

View File

@@ -2,11 +2,11 @@
{ {
public enum TxMode public enum TxMode
{ {
Only4X4 = 0, // Only 4x4 transform used Only4X4 = 0, // Only 4x4 transform used
Allow8X8 = 1, // Allow block transform size up to 8x8 Allow8X8 = 1, // Allow block transform size up to 8x8
Allow16X16 = 2, // Allow block transform size up to 16x16 Allow16X16 = 2, // Allow block transform size up to 16x16
Allow32X32 = 3, // Allow block transform size up to 32x32 Allow32X32 = 3, // Allow block transform size up to 32x32
TxModeSelect = 4, // Transform specified for each block TxModeSelect = 4, // Transform specified for each block
TxModes = 5 TxModes = 5,
} }
} }

View File

@@ -2,10 +2,10 @@
{ {
public enum TxSize public enum TxSize
{ {
Tx4x4 = 0, // 4x4 transform Tx4x4 = 0, // 4x4 transform
Tx8x8 = 1, // 8x8 transform Tx8x8 = 1, // 8x8 transform
Tx16x16 = 2, // 16x16 transform Tx16x16 = 2, // 16x16 transform
Tx32x32 = 3, // 32x32 transform Tx32x32 = 3, // 32x32 transform
TxSizes = 4 TxSizes = 4,
} }
} }

View File

@@ -2,10 +2,10 @@
{ {
internal enum TxType internal enum TxType
{ {
DctDct = 0, // DCT in both horizontal and vertical DctDct = 0, // DCT in both horizontal and vertical
AdstDct = 1, // ADST in vertical, DCT in horizontal AdstDct = 1, // ADST in vertical, DCT in horizontal
DctAdst = 2, // DCT in vertical, ADST in horizontal DctAdst = 2, // DCT in vertical, ADST in horizontal
AdstAdst = 3, // ADST in both directions AdstAdst = 3, // ADST in both directions
TxTypes = 4 TxTypes = 4,
} }
} }

View File

@@ -88,7 +88,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
public ArrayPtr<sbyte> AboveSegContext; public ArrayPtr<sbyte> AboveSegContext;
public ArrayPtr<sbyte> AboveContext; public ArrayPtr<sbyte> AboveContext;
public bool FrameIsIntraOnly() public readonly bool FrameIsIntraOnly()
{ {
return FrameType == FrameType.KeyFrame || IntraOnly; return FrameType == FrameType.KeyFrame || IntraOnly;
} }
@@ -132,7 +132,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
TileWorkerData = allocator.Allocate<TileWorkerData>(tileCols * tileRows + (maxThreads > 1 ? maxThreads : 0)); TileWorkerData = allocator.Allocate<TileWorkerData>(tileCols * tileRows + (maxThreads > 1 ? maxThreads : 0));
} }
public void FreeTileWorkerData(MemoryAllocator allocator) public readonly void FreeTileWorkerData(MemoryAllocator allocator)
{ {
allocator.Free(TileWorkerData); allocator.Free(TileWorkerData);
} }
@@ -257,7 +257,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
} }
} }
private void SetPartitionProbs(ref MacroBlockD xd) private readonly void SetPartitionProbs(ref MacroBlockD xd)
{ {
xd.PartitionProbs = FrameIsIntraOnly() xd.PartitionProbs = FrameIsIntraOnly()
? new ArrayPtr<Array3<byte>>(ref Fc.Value.KfPartitionProb[0], 16) ? new ArrayPtr<Array3<byte>>(ref Fc.Value.KfPartitionProb[0], 16)
@@ -293,7 +293,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
public void SetupSegmentationDequant() public void SetupSegmentationDequant()
{ {
const BitDepth bitDepth = BitDepth.Bits8; // TODO: Configurable const BitDepth BitDepth = BitDepth.Bits8; // TODO: Configurable
// Build y/uv dequant values based on segmentation. // Build y/uv dequant values based on segmentation.
if (Seg.Enabled) if (Seg.Enabled)
{ {
@@ -301,10 +301,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
for (i = 0; i < Constants.MaxSegments; ++i) for (i = 0; i < Constants.MaxSegments; ++i)
{ {
int qIndex = QuantCommon.GetQIndex(ref Seg, i, BaseQindex); int qIndex = QuantCommon.GetQIndex(ref Seg, i, BaseQindex);
YDequant[i][0] = QuantCommon.DcQuant(qIndex, YDcDeltaQ, bitDepth); YDequant[i][0] = QuantCommon.DcQuant(qIndex, YDcDeltaQ, BitDepth);
YDequant[i][1] = QuantCommon.AcQuant(qIndex, 0, bitDepth); YDequant[i][1] = QuantCommon.AcQuant(qIndex, 0, BitDepth);
UvDequant[i][0] = QuantCommon.DcQuant(qIndex, UvDcDeltaQ, bitDepth); UvDequant[i][0] = QuantCommon.DcQuant(qIndex, UvDcDeltaQ, BitDepth);
UvDequant[i][1] = QuantCommon.AcQuant(qIndex, UvAcDeltaQ, bitDepth); UvDequant[i][1] = QuantCommon.AcQuant(qIndex, UvAcDeltaQ, BitDepth);
} }
} }
else else
@@ -312,10 +312,10 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Types
int qIndex = BaseQindex; int qIndex = BaseQindex;
// When segmentation is disabled, only the first value is used. The // When segmentation is disabled, only the first value is used. The
// remaining are don't cares. // remaining are don't cares.
YDequant[0][0] = QuantCommon.DcQuant(qIndex, YDcDeltaQ, bitDepth); YDequant[0][0] = QuantCommon.DcQuant(qIndex, YDcDeltaQ, BitDepth);
YDequant[0][1] = QuantCommon.AcQuant(qIndex, 0, bitDepth); YDequant[0][1] = QuantCommon.AcQuant(qIndex, 0, BitDepth);
UvDequant[0][0] = QuantCommon.DcQuant(qIndex, UvDcDeltaQ, bitDepth); UvDequant[0][0] = QuantCommon.DcQuant(qIndex, UvDcDeltaQ, BitDepth);
UvDequant[0][1] = QuantCommon.AcQuant(qIndex, UvAcDeltaQ, bitDepth); UvDequant[0][1] = QuantCommon.AcQuant(qIndex, UvAcDeltaQ, BitDepth);
} }
} }

View File

@@ -9,6 +9,6 @@ namespace Ryujinx.Graphics.Shader
Greater, Greater,
NotEqual, NotEqual,
GreaterOrEqual, GreaterOrEqual,
Always Always,
} }
} }

View File

@@ -8,7 +8,7 @@ namespace Ryujinx.Graphics.Shader
// Generic types. // Generic types.
Float, Float,
Sint, Sint,
Uint Uint,
} }
static class AttributeTypeExtensions static class AttributeTypeExtensions
@@ -20,7 +20,7 @@ namespace Ryujinx.Graphics.Shader
AttributeType.Float => "vec4", AttributeType.Float => "vec4",
AttributeType.Sint => "ivec4", AttributeType.Sint => "ivec4",
AttributeType.Uint => "uvec4", AttributeType.Uint => "uvec4",
_ => throw new ArgumentException($"Invalid attribute type \"{type}\".") _ => throw new ArgumentException($"Invalid attribute type \"{type}\"."),
}; };
} }
@@ -31,8 +31,8 @@ namespace Ryujinx.Graphics.Shader
AttributeType.Float => AggregateType.FP32, AttributeType.Float => AggregateType.FP32,
AttributeType.Sint => AggregateType.S32, AttributeType.Sint => AggregateType.S32,
AttributeType.Uint => AggregateType.U32, AttributeType.Uint => AggregateType.U32,
_ => throw new ArgumentException($"Invalid attribute type \"{type}\".") _ => throw new ArgumentException($"Invalid attribute type \"{type}\"."),
}; };
} }
} }
} }

View File

@@ -37,4 +37,4 @@ namespace Ryujinx.Graphics.Shader
return this; return this;
} }
} }
} }

View File

@@ -13,6 +13,6 @@ namespace Ryujinx.Graphics.Shader
/// <summary> /// <summary>
/// Buffer is written to. /// Buffer is written to.
/// </summary> /// </summary>
Write = 1 << 0 Write = 1 << 0,
} }
} }

View File

@@ -92,4 +92,4 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
return indentation; return indentation;
} }
} }
} }

View File

@@ -244,16 +244,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
} }
} }
private static string GetTfLayout(TransformFeedbackOutput tfOutput)
{
if (tfOutput.Valid)
{
return $"layout (xfb_buffer = {tfOutput.Buffer}, xfb_offset = {tfOutput.Offset}, xfb_stride = {tfOutput.Stride}) ";
}
return string.Empty;
}
public static void DeclareLocals(CodeGenContext context, StructuredFunction function) public static void DeclareLocals(CodeGenContext context, StructuredFunction function)
{ {
foreach (AstOperand decl in function.Locals) foreach (AstOperand decl in function.Locals)
@@ -294,7 +284,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
AggregateType.Vector4 | AggregateType.FP64 => "dvec4", AggregateType.Vector4 | AggregateType.FP64 => "dvec4",
AggregateType.Vector4 | AggregateType.S32 => "ivec4", AggregateType.Vector4 | AggregateType.S32 => "ivec4",
AggregateType.Vector4 | AggregateType.U32 => "uvec4", AggregateType.Vector4 | AggregateType.U32 => "uvec4",
_ => throw new ArgumentException($"Invalid variable type \"{type}\".") _ => throw new ArgumentException($"Invalid variable type \"{type}\"."),
}; };
} }
@@ -315,7 +305,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
string layout = buffer.Layout switch string layout = buffer.Layout switch
{ {
BufferLayout.Std140 => "std140", BufferLayout.Std140 => "std140",
_ => "std430" _ => "std430",
}; };
string set = string.Empty; string set = string.Empty;
@@ -507,7 +497,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
{ {
PixelImap.Constant => "flat ", PixelImap.Constant => "flat ",
PixelImap.ScreenLinear => "noperspective ", PixelImap.ScreenLinear => "noperspective ",
_ => string.Empty _ => string.Empty,
}; };
} }
@@ -524,7 +514,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
2 => "vec2", 2 => "vec2",
3 => "vec3", 3 => "vec3",
4 => "vec4", 4 => "vec4",
_ => "float" _ => "float",
}; };
context.AppendLine($"layout (location = {attr}) in {type} {name};"); context.AppendLine($"layout (location = {attr}) in {type} {name};");
@@ -611,7 +601,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
2 => "vec2", 2 => "vec2",
3 => "vec3", 3 => "vec3",
4 => "vec4", 4 => "vec4",
_ => "float" _ => "float",
}; };
string xfb = string.Empty; string xfb = string.Empty;
@@ -647,7 +637,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
{ {
AttributeType.Sint => "ivec4", AttributeType.Sint => "ivec4",
AttributeType.Uint => "uvec4", AttributeType.Uint => "uvec4",
_ => "vec4" _ => "vec4",
}; };
if (context.Config.GpuAccessor.QueryHostReducedPrecision() && context.Config.Stage == ShaderStage.Vertex && attr == 0) if (context.Config.GpuAccessor.QueryHostReducedPrecision() && context.Config.Stage == ShaderStage.Vertex && attr == 0)
@@ -721,4 +711,4 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
context.AppendLine(); context.AppendLine();
} }
} }
} }

View File

@@ -5,7 +5,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
public const string LocalNamePrefix = "temp"; public const string LocalNamePrefix = "temp";
public const string SamplerNamePrefix = "tex"; public const string SamplerNamePrefix = "tex";
public const string ImageNamePrefix = "img"; public const string ImageNamePrefix = "img";
public const string PerPatchAttributePrefix = "patch_attr_"; public const string PerPatchAttributePrefix = "patch_attr_";
public const string IAttributePrefix = "in_attr"; public const string IAttributePrefix = "in_attr";
@@ -15,4 +15,4 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
public const string UndefinedName = "undef"; public const string UndefinedName = "undef";
} }
} }

View File

@@ -13,7 +13,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
public static string Generate(StructuredProgramInfo info, ShaderConfig config) public static string Generate(StructuredProgramInfo info, ShaderConfig config)
{ {
CodeGenContext context = new CodeGenContext(info, config); CodeGenContext context = new(info, config);
Declarations.Declare(context, info); Declarations.Declare(context, info);
@@ -74,7 +74,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
private static void PrintBlock(CodeGenContext context, AstBlock block, bool isMainFunction) private static void PrintBlock(CodeGenContext context, AstBlock block, bool isMainFunction)
{ {
AstBlockVisitor visitor = new AstBlockVisitor(block); AstBlockVisitor visitor = new(block);
visitor.BlockEntered += (sender, e) => visitor.BlockEntered += (sender, e) =>
{ {
@@ -96,7 +96,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
context.AppendLine($"if ({GetCondExpr(context, e.Block.Condition)})"); context.AppendLine($"if ({GetCondExpr(context, e.Block.Condition)})");
break; break;
default: throw new InvalidOperationException($"Found unexpected block type \"{e.Block.Type}\"."); default:
throw new InvalidOperationException($"Found unexpected block type \"{e.Block.Type}\".");
} }
context.EnterScope(); context.EnterScope();
@@ -173,4 +174,4 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
return ReinterpretCast(context, cond, srcType, AggregateType.Bool); return ReinterpretCast(context, cond, srcType, AggregateType.Bool);
} }
} }
} }

View File

@@ -5,10 +5,10 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
public static string MultiplyHighS32 = "Helper_MultiplyHighS32"; public static string MultiplyHighS32 = "Helper_MultiplyHighS32";
public static string MultiplyHighU32 = "Helper_MultiplyHighU32"; public static string MultiplyHighU32 = "Helper_MultiplyHighU32";
public static string Shuffle = "Helper_Shuffle"; public static string Shuffle = "Helper_Shuffle";
public static string ShuffleDown = "Helper_ShuffleDown"; public static string ShuffleDown = "Helper_ShuffleDown";
public static string ShuffleUp = "Helper_ShuffleUp"; public static string ShuffleUp = "Helper_ShuffleUp";
public static string ShuffleXor = "Helper_ShuffleXor"; public static string ShuffleXor = "Helper_ShuffleXor";
public static string SwizzleAdd = "Helper_SwizzleAdd"; public static string SwizzleAdd = "Helper_SwizzleAdd";
} }
} }

View File

@@ -197,4 +197,4 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
throw new InvalidOperationException($"Unexpected instruction type \"{info.Type}\"."); throw new InvalidOperationException($"Unexpected instruction type \"{info.Type}\".");
} }
} }
} }

View File

@@ -24,4 +24,4 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
} }
} }
} }
} }

View File

@@ -26,4 +26,4 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
return $"{function.Name}({string.Join(", ", args)})"; return $"{function.Name}({string.Join(", ", args)})";
} }
} }
} }

View File

@@ -26,4 +26,4 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
return null; return null;
} }
} }
} }

View File

@@ -14,6 +14,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
{ {
_infoTable = new InstInfo[(int)Instruction.Count]; _infoTable = new InstInfo[(int)Instruction.Count];
#pragma warning disable IDE0055 // Disable formatting
Add(Instruction.AtomicAdd, InstType.AtomicBinary, "atomicAdd"); Add(Instruction.AtomicAdd, InstType.AtomicBinary, "atomicAdd");
Add(Instruction.AtomicAnd, InstType.AtomicBinary, "atomicAnd"); Add(Instruction.AtomicAnd, InstType.AtomicBinary, "atomicAnd");
Add(Instruction.AtomicCompareAndSwap, InstType.AtomicTernary, "atomicCompSwap"); Add(Instruction.AtomicCompareAndSwap, InstType.AtomicTernary, "atomicCompSwap");
@@ -125,6 +126,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
Add(Instruction.VoteAll, InstType.CallUnary, "allInvocationsARB"); Add(Instruction.VoteAll, InstType.CallUnary, "allInvocationsARB");
Add(Instruction.VoteAllEqual, InstType.CallUnary, "allInvocationsEqualARB"); Add(Instruction.VoteAllEqual, InstType.CallUnary, "allInvocationsEqualARB");
Add(Instruction.VoteAny, InstType.CallUnary, "anyInvocationARB"); Add(Instruction.VoteAny, InstType.CallUnary, "anyInvocationARB");
#pragma warning restore IDE0055
} }
private static void Add(Instruction inst, InstType flags, string opName = null, int precedence = 0) private static void Add(Instruction inst, InstType flags, string opName = null, int precedence = 0)
@@ -163,7 +165,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
{ {
// If the node isn't a operation, then it can only be a operand, // If the node isn't a operation, then it can only be a operand,
// and those never needs to be surrounded in parenthesis. // and those never needs to be surrounded in parenthesis.
if (!(node is AstOperation operation)) if (node is not AstOperation operation)
{ {
// This is sort of a special case, if this is a negative constant, // This is sort of a special case, if this is a negative constant,
// and it is consumed by a unary operation, we need to put on the parenthesis, // and it is consumed by a unary operation, we need to put on the parenthesis,
@@ -208,7 +210,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
private static bool IsNegativeConst(IAstNode node) private static bool IsNegativeConst(IAstNode node)
{ {
if (!(node is AstOperand operand)) if (node is not AstOperand operand)
{ {
return false; return false;
} }
@@ -216,4 +218,4 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
return operand.Type == OperandType.Constant && operand.Value < 0; return operand.Type == OperandType.Constant && operand.Value < 0;
} }
} }
} }

View File

@@ -3,7 +3,6 @@ using Ryujinx.Graphics.Shader.StructuredIr;
using Ryujinx.Graphics.Shader.Translation; using Ryujinx.Graphics.Shader.Translation;
using System; using System;
using System.Text; using System.Text;
using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenHelper; using static Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions.InstGenHelper;
using static Ryujinx.Graphics.Shader.StructuredIr.InstructionInfo; using static Ryujinx.Graphics.Shader.StructuredIr.InstructionInfo;
@@ -42,14 +41,16 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
} }
} }
bool isArray = (texOp.Type & SamplerType.Array) != 0; bool isArray = (texOp.Type & SamplerType.Array) != 0;
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0; bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
var texCallBuilder = new StringBuilder(); var texCallBuilder = new StringBuilder();
if (texOp.Inst == Instruction.ImageAtomic) if (texOp.Inst == Instruction.ImageAtomic)
{ {
texCallBuilder.Append((texOp.Flags & TextureFlags.AtomicMask) switch { texCallBuilder.Append((texOp.Flags & TextureFlags.AtomicMask) switch
{
#pragma warning disable IDE0055 // Disable formatting
TextureFlags.Add => "imageAtomicAdd", TextureFlags.Add => "imageAtomicAdd",
TextureFlags.Minimum => "imageAtomicMin", TextureFlags.Minimum => "imageAtomicMin",
TextureFlags.Maximum => "imageAtomicMax", TextureFlags.Maximum => "imageAtomicMax",
@@ -61,6 +62,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
TextureFlags.Swap => "imageAtomicExchange", TextureFlags.Swap => "imageAtomicExchange",
TextureFlags.CAS => "imageAtomicCompSwap", TextureFlags.CAS => "imageAtomicCompSwap",
_ => "imageAtomicAdd", _ => "imageAtomicAdd",
#pragma warning restore IDE0055
}); });
} }
else else
@@ -131,7 +133,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
{ {
AggregateType.S32 => NumberFormatter.FormatInt(0), AggregateType.S32 => NumberFormatter.FormatInt(0),
AggregateType.U32 => NumberFormatter.FormatUint(0), AggregateType.U32 => NumberFormatter.FormatUint(0),
_ => NumberFormatter.FormatFloat(0) _ => NumberFormatter.FormatFloat(0),
}; };
} }
} }
@@ -140,7 +142,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
{ {
AggregateType.S32 => "i", AggregateType.S32 => "i",
AggregateType.U32 => "u", AggregateType.U32 => "u",
_ => string.Empty _ => string.Empty,
}; };
Append($"{prefix}vec4({string.Join(", ", cElems)})"); Append($"{prefix}vec4({string.Join(", ", cElems)})");
@@ -159,7 +161,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
{ {
TextureFlags.Increment => NumberFormatter.FormatInt(1, type), // TODO: Clamp value TextureFlags.Increment => NumberFormatter.FormatInt(1, type), // TODO: Clamp value
TextureFlags.Decrement => NumberFormatter.FormatInt(-1, type), // TODO: Clamp value TextureFlags.Decrement => NumberFormatter.FormatInt(-1, type), // TODO: Clamp value
_ => Src(type) _ => Src(type),
}; };
Append(value); Append(value);
@@ -248,25 +250,25 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
{ {
AstTextureOperation texOp = (AstTextureOperation)operation; AstTextureOperation texOp = (AstTextureOperation)operation;
bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0; bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;
bool isGather = (texOp.Flags & TextureFlags.Gather) != 0; bool isGather = (texOp.Flags & TextureFlags.Gather) != 0;
bool hasDerivatives = (texOp.Flags & TextureFlags.Derivatives) != 0; bool hasDerivatives = (texOp.Flags & TextureFlags.Derivatives) != 0;
bool intCoords = (texOp.Flags & TextureFlags.IntCoords) != 0; bool intCoords = (texOp.Flags & TextureFlags.IntCoords) != 0;
bool hasLodBias = (texOp.Flags & TextureFlags.LodBias) != 0; bool hasLodBias = (texOp.Flags & TextureFlags.LodBias) != 0;
bool hasLodLevel = (texOp.Flags & TextureFlags.LodLevel) != 0; bool hasLodLevel = (texOp.Flags & TextureFlags.LodLevel) != 0;
bool hasOffset = (texOp.Flags & TextureFlags.Offset) != 0; bool hasOffset = (texOp.Flags & TextureFlags.Offset) != 0;
bool hasOffsets = (texOp.Flags & TextureFlags.Offsets) != 0; bool hasOffsets = (texOp.Flags & TextureFlags.Offsets) != 0;
bool isArray = (texOp.Type & SamplerType.Array) != 0; bool isArray = (texOp.Type & SamplerType.Array) != 0;
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0; bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
bool isMultisample = (texOp.Type & SamplerType.Multisample) != 0; bool isMultisample = (texOp.Type & SamplerType.Multisample) != 0;
bool isShadow = (texOp.Type & SamplerType.Shadow) != 0; bool isShadow = (texOp.Type & SamplerType.Shadow) != 0;
bool colorIsVector = isGather || !isShadow; bool colorIsVector = isGather || !isShadow;
SamplerType type = texOp.Type & SamplerType.Mask; SamplerType type = texOp.Type & SamplerType.Mask;
bool is2D = type == SamplerType.Texture2D; bool is2D = type == SamplerType.Texture2D;
bool isCube = type == SamplerType.TextureCube; bool isCube = type == SamplerType.TextureCube;
// 2D Array and Cube shadow samplers with LOD level or bias requires an extension. // 2D Array and Cube shadow samplers with LOD level or bias requires an extension.
@@ -500,14 +502,14 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
if (hasLodBias) if (hasLodBias)
{ {
Append(Src(AggregateType.FP32)); Append(Src(AggregateType.FP32));
} }
// textureGather* optional extra component index, // textureGather* optional extra component index,
// not needed for shadow samplers. // not needed for shadow samplers.
if (isGather && !isShadow) if (isGather && !isShadow)
{ {
Append(Src(AggregateType.S32)); Append(Src(AggregateType.S32));
} }
texCall += ")" + (colorIsVector ? GetMaskMultiDest(texOp.Index) : ""); texCall += ")" + (colorIsVector ? GetMaskMultiDest(texOp.Index) : "");
@@ -584,7 +586,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
{ {
case StorageKind.ConstantBuffer: case StorageKind.ConstantBuffer:
case StorageKind.StorageBuffer: case StorageKind.StorageBuffer:
if (!(operation.GetSource(srcIndex++) is AstOperand bindingIndex) || bindingIndex.Type != OperandType.Constant) if (operation.GetSource(srcIndex++) is not AstOperand bindingIndex || bindingIndex.Type != OperandType.Constant)
{ {
throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand."); throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand.");
} }
@@ -594,7 +596,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
? context.Config.Properties.ConstantBuffers[binding] ? context.Config.Properties.ConstantBuffers[binding]
: context.Config.Properties.StorageBuffers[binding]; : context.Config.Properties.StorageBuffers[binding];
if (!(operation.GetSource(srcIndex++) is AstOperand fieldIndex) || fieldIndex.Type != OperandType.Constant) if (operation.GetSource(srcIndex++) is not AstOperand fieldIndex || fieldIndex.Type != OperandType.Constant)
{ {
throw new InvalidOperationException($"Second input of {operation.Inst} with {storageKind} storage must be a constant operand."); throw new InvalidOperationException($"Second input of {operation.Inst} with {storageKind} storage must be a constant operand.");
} }
@@ -606,7 +608,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
case StorageKind.LocalMemory: case StorageKind.LocalMemory:
case StorageKind.SharedMemory: case StorageKind.SharedMemory:
if (!(operation.GetSource(srcIndex++) is AstOperand bindingId) || bindingId.Type != OperandType.Constant) if (operation.GetSource(srcIndex++) is not AstOperand { Type: OperandType.Constant } bindingId)
{ {
throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand."); throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand.");
} }
@@ -623,7 +625,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
case StorageKind.InputPerPatch: case StorageKind.InputPerPatch:
case StorageKind.Output: case StorageKind.Output:
case StorageKind.OutputPerPatch: case StorageKind.OutputPerPatch:
if (!(operation.GetSource(srcIndex++) is AstOperand varId) || varId.Type != OperandType.Constant) if (operation.GetSource(srcIndex++) is not AstOperand varId || varId.Type != OperandType.Constant)
{ {
throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand."); throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand.");
} }
@@ -636,7 +638,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
if (context.Config.HasPerLocationInputOrOutput(ioVariable, isOutput)) if (context.Config.HasPerLocationInputOrOutput(ioVariable, isOutput))
{ {
if (!(operation.GetSource(srcIndex++) is AstOperand vecIndex) || vecIndex.Type != OperandType.Constant) if (operation.GetSource(srcIndex++) is not AstOperand vecIndex || vecIndex.Type != OperandType.Constant)
{ {
throw new InvalidOperationException($"Second input of {operation.Inst} with {storageKind} storage must be a constant operand."); throw new InvalidOperationException($"Second input of {operation.Inst} with {storageKind} storage must be a constant operand.");
} }
@@ -733,4 +735,4 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
return swizzle; return swizzle;
} }
} }
} }

View File

@@ -53,4 +53,4 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
return $".{"xy".AsSpan(index, 1)}"; return $".{"xy".AsSpan(index, 1)}";
} }
} }
} }

View File

@@ -29,4 +29,4 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
} }
} }
} }
} }

View File

@@ -10,9 +10,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
public InstInfo(InstType type, string opName, int precedence) public InstInfo(InstType type, string opName, int precedence)
{ {
Type = type; Type = type;
OpName = opName; OpName = opName;
Precedence = precedence; Precedence = precedence;
} }
} }
} }

View File

@@ -1,33 +1,35 @@
using System; using System;
using System.Diagnostics.CodeAnalysis;
namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
{ {
[Flags] [Flags]
[SuppressMessage("Design", "CA1069: Enums values should not be duplicated")]
enum InstType enum InstType
{ {
OpNullary = Op | 0, OpNullary = Op | 0,
OpUnary = Op | 1, OpUnary = Op | 1,
OpBinary = Op | 2, OpBinary = Op | 2,
OpBinaryCom = Op | 2 | Commutative, OpBinaryCom = Op | 2 | Commutative,
OpTernary = Op | 3, OpTernary = Op | 3,
CallNullary = Call | 0, CallNullary = Call | 0,
CallUnary = Call | 1, CallUnary = Call | 1,
CallBinary = Call | 2, CallBinary = Call | 2,
CallTernary = Call | 3, CallTernary = Call | 3,
CallQuaternary = Call | 4, CallQuaternary = Call | 4,
// The atomic instructions have one extra operand, // The atomic instructions have one extra operand,
// for the storage slot and offset pair. // for the storage slot and offset pair.
AtomicBinary = Call | Atomic | 3, AtomicBinary = Call | Atomic | 3,
AtomicTernary = Call | Atomic | 4, AtomicTernary = Call | Atomic | 4,
Commutative = 1 << 8, Commutative = 1 << 8,
Op = 1 << 9, Op = 1 << 9,
Call = 1 << 10, Call = 1 << 10,
Atomic = 1 << 11, Atomic = 1 << 11,
Special = 1 << 12, Special = 1 << 12,
ArityMask = 0xff ArityMask = 0xff,
} }
} }

View File

@@ -28,7 +28,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
IoVariable.FragmentOutputColor => GetFragmentOutputColorVariableName(config, location), IoVariable.FragmentOutputColor => GetFragmentOutputColorVariableName(config, location),
IoVariable.FragmentOutputDepth => ("gl_FragDepth", AggregateType.FP32), IoVariable.FragmentOutputDepth => ("gl_FragDepth", AggregateType.FP32),
IoVariable.FrontColorDiffuse => ("gl_FrontColor", AggregateType.Vector4 | AggregateType.FP32), // Deprecated. IoVariable.FrontColorDiffuse => ("gl_FrontColor", AggregateType.Vector4 | AggregateType.FP32), // Deprecated.
IoVariable.FrontColorSpecular => ("gl_FrontSecondaryColor", AggregateType.Vector4 | AggregateType.FP32), // Deprecated. IoVariable.FrontColorSpecular => ("gl_FrontSecondaryColor", AggregateType.Vector4 | AggregateType.FP32), // Deprecated.
IoVariable.FrontFacing => ("gl_FrontFacing", AggregateType.Bool), IoVariable.FrontFacing => ("gl_FrontFacing", AggregateType.Bool),
IoVariable.InstanceId => ("gl_InstanceID", AggregateType.S32), IoVariable.InstanceId => ("gl_InstanceID", AggregateType.S32),
IoVariable.InstanceIndex => ("gl_InstanceIndex", AggregateType.S32), IoVariable.InstanceIndex => ("gl_InstanceIndex", AggregateType.S32),
@@ -56,7 +56,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
IoVariable.VertexIndex => ("gl_VertexIndex", AggregateType.S32), IoVariable.VertexIndex => ("gl_VertexIndex", AggregateType.S32),
IoVariable.ViewportIndex => ("gl_ViewportIndex", AggregateType.S32), IoVariable.ViewportIndex => ("gl_ViewportIndex", AggregateType.S32),
IoVariable.ViewportMask => ("gl_ViewportMask", AggregateType.Array | AggregateType.S32), IoVariable.ViewportMask => ("gl_ViewportMask", AggregateType.Array | AggregateType.S32),
_ => (null, AggregateType.Invalid) _ => (null, AggregateType.Invalid),
}; };
} }
@@ -139,4 +139,4 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
return (name, config.GetUserDefinedType(location, isOutput)); return (name, config.GetUserDefinedType(location, isOutput));
} }
} }
} }

View File

@@ -101,4 +101,4 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
return "0x" + value.ToString("X", CultureInfo.InvariantCulture) + "u"; return "0x" + value.ToString("X", CultureInfo.InvariantCulture) + "u";
} }
} }
} }

View File

@@ -5,7 +5,6 @@ using Ryujinx.Graphics.Shader.Translation;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using static Ryujinx.Graphics.Shader.StructuredIr.InstructionInfo; using static Ryujinx.Graphics.Shader.StructuredIr.InstructionInfo;
namespace Ryujinx.Graphics.Shader.CodeGen.Glsl namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
@@ -14,7 +13,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
{ {
private static readonly string[] _stagePrefixes = new string[] { "cp", "vp", "tcp", "tep", "gp", "fp" }; private static readonly string[] _stagePrefixes = new string[] { "cp", "vp", "tcp", "tep", "gp", "fp" };
private Dictionary<AstOperand, string> _locals; private readonly Dictionary<AstOperand, string> _locals;
public OperandManager() public OperandManager()
{ {
@@ -38,7 +37,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
OperandType.Constant => NumberFormatter.FormatInt(operand.Value), OperandType.Constant => NumberFormatter.FormatInt(operand.Value),
OperandType.LocalVariable => _locals[operand], OperandType.LocalVariable => _locals[operand],
OperandType.Undefined => DefaultNames.UndefinedName, OperandType.Undefined => DefaultNames.UndefinedName,
_ => throw new ArgumentException($"Invalid operand type \"{operand.Type}\".") _ => throw new ArgumentException($"Invalid operand type \"{operand.Type}\"."),
}; };
} }
@@ -96,11 +95,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
return _stagePrefixes[index]; return _stagePrefixes[index];
} }
private static char GetSwizzleMask(int value)
{
return "xyzw"[value];
}
public static string GetArgumentName(int argIndex) public static string GetArgumentName(int argIndex)
{ {
return $"{DefaultNames.ArgumentNamePrefix}{argIndex}"; return $"{DefaultNames.ArgumentNamePrefix}{argIndex}";
@@ -119,12 +113,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
{ {
case StorageKind.ConstantBuffer: case StorageKind.ConstantBuffer:
case StorageKind.StorageBuffer: case StorageKind.StorageBuffer:
if (!(operation.GetSource(0) is AstOperand bindingIndex) || bindingIndex.Type != OperandType.Constant) if (operation.GetSource(0) is not AstOperand bindingIndex || bindingIndex.Type != OperandType.Constant)
{ {
throw new InvalidOperationException($"First input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand."); throw new InvalidOperationException($"First input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand.");
} }
if (!(operation.GetSource(1) is AstOperand fieldIndex) || fieldIndex.Type != OperandType.Constant) if (operation.GetSource(1) is not AstOperand fieldIndex || fieldIndex.Type != OperandType.Constant)
{ {
throw new InvalidOperationException($"Second input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand."); throw new InvalidOperationException($"Second input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand.");
} }
@@ -138,7 +132,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
case StorageKind.LocalMemory: case StorageKind.LocalMemory:
case StorageKind.SharedMemory: case StorageKind.SharedMemory:
if (!(operation.GetSource(0) is AstOperand bindingId) || bindingId.Type != OperandType.Constant) if (operation.GetSource(0) is not AstOperand { Type: OperandType.Constant } bindingId)
{ {
throw new InvalidOperationException($"First input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand."); throw new InvalidOperationException($"First input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand.");
} }
@@ -153,7 +147,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
case StorageKind.InputPerPatch: case StorageKind.InputPerPatch:
case StorageKind.Output: case StorageKind.Output:
case StorageKind.OutputPerPatch: case StorageKind.OutputPerPatch:
if (!(operation.GetSource(0) is AstOperand varId) || varId.Type != OperandType.Constant) if (operation.GetSource(0) is not AstOperand varId || varId.Type != OperandType.Constant)
{ {
throw new InvalidOperationException($"First input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand."); throw new InvalidOperationException($"First input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand.");
} }
@@ -166,7 +160,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
if (context.Config.HasPerLocationInputOrOutput(ioVariable, isOutput)) if (context.Config.HasPerLocationInputOrOutput(ioVariable, isOutput))
{ {
if (!(operation.GetSource(1) is AstOperand vecIndex) || vecIndex.Type != OperandType.Constant) if (operation.GetSource(1) is not AstOperand vecIndex || vecIndex.Type != OperandType.Constant)
{ {
throw new InvalidOperationException($"Second input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand."); throw new InvalidOperationException($"Second input of {operation.Inst} with {operation.StorageKind} storage must be a constant operand.");
} }
@@ -232,4 +226,4 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
} }
} }
} }
} }

View File

@@ -10,9 +10,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
{ {
public static string ReinterpretCast( public static string ReinterpretCast(
CodeGenContext context, CodeGenContext context,
IAstNode node, IAstNode node,
AggregateType srcType, AggregateType srcType,
AggregateType dstType) AggregateType dstType)
{ {
if (node is AstOperand operand && operand.Type == OperandType.Constant) if (node is AstOperand operand && operand.Type == OperandType.Constant)
{ {
@@ -38,18 +38,24 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
{ {
switch (dstType) switch (dstType)
{ {
case AggregateType.Bool: return $"(floatBitsToInt({expr}) != 0)"; case AggregateType.Bool:
case AggregateType.S32: return $"floatBitsToInt({expr})"; return $"(floatBitsToInt({expr}) != 0)";
case AggregateType.U32: return $"floatBitsToUint({expr})"; case AggregateType.S32:
return $"floatBitsToInt({expr})";
case AggregateType.U32:
return $"floatBitsToUint({expr})";
} }
} }
else if (dstType == AggregateType.FP32) else if (dstType == AggregateType.FP32)
{ {
switch (srcType) switch (srcType)
{ {
case AggregateType.Bool: return $"intBitsToFloat({ReinterpretBoolToInt(expr, node, AggregateType.S32)})"; case AggregateType.Bool:
case AggregateType.S32: return $"intBitsToFloat({expr})"; return $"intBitsToFloat({ReinterpretBoolToInt(expr, node, AggregateType.S32)})";
case AggregateType.U32: return $"uintBitsToFloat({expr})"; case AggregateType.S32:
return $"intBitsToFloat({expr})";
case AggregateType.U32:
return $"uintBitsToFloat({expr})";
} }
} }
else if (srcType == AggregateType.Bool) else if (srcType == AggregateType.Bool)
@@ -76,7 +82,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
private static string ReinterpretBoolToInt(string expr, IAstNode node, AggregateType dstType) private static string ReinterpretBoolToInt(string expr, IAstNode node, AggregateType dstType)
{ {
string trueExpr = NumberFormatter.FormatInt(IrConsts.True, dstType); string trueExpr = NumberFormatter.FormatInt(IrConsts.True, dstType);
string falseExpr = NumberFormatter.FormatInt(IrConsts.False, dstType); string falseExpr = NumberFormatter.FormatInt(IrConsts.False, dstType);
expr = InstGenHelper.Enclose(expr, node, Instruction.ConditionalSelect, isLhs: false); expr = InstGenHelper.Enclose(expr, node, Instruction.ConditionalSelect, isLhs: false);
@@ -84,4 +90,4 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
return $"({expr} ? {trueExpr} : {falseExpr})"; return $"({expr} ? {trueExpr} : {falseExpr})";
} }
} }
} }

View File

@@ -1,13 +1,14 @@
using Ryujinx.Graphics.Shader.StructuredIr; using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using Ryujinx.Graphics.Shader.StructuredIr;
using Ryujinx.Graphics.Shader.Translation; using Ryujinx.Graphics.Shader.Translation;
using Spv.Generator; using Spv.Generator;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using static Spv.Specification; using static Spv.Specification;
using Instruction = Spv.Generator.Instruction;
namespace Ryujinx.Graphics.Shader.CodeGen.Spirv namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
{ {
using IrConsts = IntermediateRepresentation.IrConsts;
using IrOperandType = IntermediateRepresentation.OperandType; using IrOperandType = IntermediateRepresentation.OperandType;
partial class CodeGenContext : Module partial class CodeGenContext : Module
@@ -36,15 +37,15 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
public Dictionary<IoDefinition, Instruction> OutputsPerPatch { get; } = new Dictionary<IoDefinition, Instruction>(); public Dictionary<IoDefinition, Instruction> OutputsPerPatch { get; } = new Dictionary<IoDefinition, Instruction>();
public StructuredFunction CurrentFunction { get; set; } public StructuredFunction CurrentFunction { get; set; }
private readonly Dictionary<AstOperand, Instruction> _locals = new Dictionary<AstOperand, Instruction>(); private readonly Dictionary<AstOperand, Instruction> _locals = new();
private readonly Dictionary<int, Instruction[]> _localForArgs = new Dictionary<int, Instruction[]>(); private readonly Dictionary<int, Instruction[]> _localForArgs = new();
private readonly Dictionary<int, Instruction> _funcArgs = new Dictionary<int, Instruction>(); private readonly Dictionary<int, Instruction> _funcArgs = new();
private readonly Dictionary<int, (StructuredFunction, Instruction)> _functions = new Dictionary<int, (StructuredFunction, Instruction)>(); private readonly Dictionary<int, (StructuredFunction, Instruction)> _functions = new();
private class BlockState private class BlockState
{ {
private int _entryCount; private int _entryCount;
private readonly List<Instruction> _labels = new List<Instruction>(); private readonly List<Instruction> _labels = new();
public Instruction GetNextLabel(CodeGenContext context) public Instruction GetNextLabel(CodeGenContext context)
{ {
@@ -67,7 +68,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
} }
} }
private readonly Dictionary<AstBlock, BlockState> _labels = new Dictionary<AstBlock, BlockState>(); private readonly Dictionary<AstBlock, BlockState> _labels = new();
public Dictionary<AstBlock, (Instruction, Instruction)> LoopTargets { get; set; } public Dictionary<AstBlock, (Instruction, Instruction)> LoopTargets { get; set; }
@@ -98,7 +99,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
InputTopology.LinesAdjacency => 2, InputTopology.LinesAdjacency => 2,
InputTopology.Triangles => 3, InputTopology.Triangles => 3,
InputTopology.TrianglesAdjacency => 3, InputTopology.TrianglesAdjacency => 3,
_ => throw new InvalidOperationException($"Invalid input topology \"{inPrimitive}\".") _ => throw new InvalidOperationException($"Invalid input topology \"{inPrimitive}\"."),
}; };
} }
@@ -222,7 +223,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
IrOperandType.Constant => GetConstant(type, operand), IrOperandType.Constant => GetConstant(type, operand),
IrOperandType.LocalVariable => GetLocal(type, operand), IrOperandType.LocalVariable => GetLocal(type, operand),
IrOperandType.Undefined => GetUndefined(type), IrOperandType.Undefined => GetUndefined(type),
_ => throw new ArgumentException($"Invalid operand type \"{operand.Type}\".") _ => throw new ArgumentException($"Invalid operand type \"{operand.Type}\"."),
}; };
} }
@@ -259,7 +260,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
AggregateType.Bool => ConstantFalse(TypeBool()), AggregateType.Bool => ConstantFalse(TypeBool()),
AggregateType.FP32 => Constant(TypeFP32(), 0f), AggregateType.FP32 => Constant(TypeFP32(), 0f),
AggregateType.FP64 => Constant(TypeFP64(), 0d), AggregateType.FP64 => Constant(TypeFP64(), 0d),
_ => Constant(GetType(type), 0) _ => Constant(GetType(type), 0),
}; };
} }
@@ -272,7 +273,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
AggregateType.FP64 => Constant(TypeFP64(), (double)BitConverter.Int32BitsToSingle(operand.Value)), AggregateType.FP64 => Constant(TypeFP64(), (double)BitConverter.Int32BitsToSingle(operand.Value)),
AggregateType.S32 => Constant(TypeS32(), operand.Value), AggregateType.S32 => Constant(TypeS32(), operand.Value),
AggregateType.U32 => Constant(TypeU32(), (uint)operand.Value), AggregateType.U32 => Constant(TypeU32(), (uint)operand.Value),
_ => throw new ArgumentException($"Invalid type \"{type}\".") _ => throw new ArgumentException($"Invalid type \"{type}\"."),
}; };
} }
@@ -328,7 +329,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
AggregateType.Vector2 => 2, AggregateType.Vector2 => 2,
AggregateType.Vector3 => 3, AggregateType.Vector3 => 3,
AggregateType.Vector4 => 4, AggregateType.Vector4 => 4,
_ => 1 _ => 1,
}; };
return TypeVector(GetType(type & ~AggregateType.ElementCountMask), vectorLength); return TypeVector(GetType(type & ~AggregateType.ElementCountMask), vectorLength);
@@ -342,7 +343,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
AggregateType.FP64 => TypeFP64(), AggregateType.FP64 => TypeFP64(),
AggregateType.S32 => TypeS32(), AggregateType.S32 => TypeS32(),
AggregateType.U32 => TypeU32(), AggregateType.U32 => TypeU32(),
_ => throw new ArgumentException($"Invalid attribute type \"{type}\".") _ => throw new ArgumentException($"Invalid attribute type \"{type}\"."),
}; };
} }
@@ -359,7 +360,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
} }
else if (srcType == AggregateType.Bool) else if (srcType == AggregateType.Bool)
{ {
var intTrue = Constant(TypeS32(), IrConsts.True); var intTrue = Constant(TypeS32(), IrConsts.True);
var intFalse = Constant(TypeS32(), IrConsts.False); var intFalse = Constant(TypeS32(), IrConsts.False);
return BitcastIfNeeded(dstType, AggregateType.S32, Select(TypeS32(), value, intTrue, intFalse)); return BitcastIfNeeded(dstType, AggregateType.S32, Select(TypeS32(), value, intTrue, intFalse));

View File

@@ -1,5 +1,4 @@
using Ryujinx.Common; using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using Ryujinx.Graphics.Shader.StructuredIr; using Ryujinx.Graphics.Shader.StructuredIr;
using Ryujinx.Graphics.Shader.Translation; using Ryujinx.Graphics.Shader.Translation;
using Spv.Generator; using Spv.Generator;
@@ -14,7 +13,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
{ {
static class Declarations static class Declarations
{ {
private static readonly string[] StagePrefixes = new string[] { "cp", "vp", "tcp", "tep", "gp", "fp" }; private static readonly string[] _stagePrefixes = { "cp", "vp", "tcp", "tep", "gp", "fp" };
public static void DeclareParameters(CodeGenContext context, StructuredFunction function) public static void DeclareParameters(CodeGenContext context, StructuredFunction function)
{ {
@@ -107,7 +106,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
private static void DeclareBuffers(CodeGenContext context, IEnumerable<BufferDefinition> buffers, bool isBuffer) private static void DeclareBuffers(CodeGenContext context, IEnumerable<BufferDefinition> buffers, bool isBuffer)
{ {
HashSet<SpvInstruction> decoratedTypes = new HashSet<SpvInstruction>(); HashSet<SpvInstruction> decoratedTypes = new();
foreach (BufferDefinition buffer in buffers) foreach (BufferDefinition buffer in buffers)
{ {
@@ -199,7 +198,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
SamplerType.Texture3D => Dim.Dim3D, SamplerType.Texture3D => Dim.Dim3D,
SamplerType.TextureCube => Dim.Cube, SamplerType.TextureCube => Dim.Cube,
SamplerType.TextureBuffer => Dim.Buffer, SamplerType.TextureBuffer => Dim.Buffer,
_ => throw new InvalidOperationException($"Invalid sampler type \"{descriptor.Type & SamplerType.Mask}\".") _ => throw new InvalidOperationException($"Invalid sampler type \"{descriptor.Type & SamplerType.Mask}\"."),
}; };
var imageType = context.TypeImage( var imageType = context.TypeImage(
@@ -282,7 +281,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
SamplerType.Texture3D => Dim.Dim3D, SamplerType.Texture3D => Dim.Dim3D,
SamplerType.TextureCube => Dim.Cube, SamplerType.TextureCube => Dim.Cube,
SamplerType.TextureBuffer => Dim.Buffer, SamplerType.TextureBuffer => Dim.Buffer,
_ => throw new ArgumentException($"Invalid sampler type \"{type & SamplerType.Mask}\".") _ => throw new ArgumentException($"Invalid sampler type \"{type & SamplerType.Mask}\"."),
}; };
} }
@@ -330,7 +329,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
TextureFormat.R10G10B10A2Unorm => ImageFormat.Rgb10A2, TextureFormat.R10G10B10A2Unorm => ImageFormat.Rgb10A2,
TextureFormat.R10G10B10A2Uint => ImageFormat.Rgb10a2ui, TextureFormat.R10G10B10A2Uint => ImageFormat.Rgb10a2ui,
TextureFormat.R11G11B10Float => ImageFormat.R11fG11fB10f, TextureFormat.R11G11B10Float => ImageFormat.R11fG11fB10f,
_ => throw new ArgumentException($"Invalid texture format \"{format}\".") _ => throw new ArgumentException($"Invalid texture format \"{format}\"."),
}; };
} }
@@ -352,7 +351,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
(_, AggregateType varType) = IoMap.GetSpirvBuiltIn(ioVariable); (_, AggregateType varType) = IoMap.GetSpirvBuiltIn(ioVariable);
AggregateType elemType = varType & AggregateType.ElementTypeMask; AggregateType elemType = varType & AggregateType.ElementTypeMask;
if (elemType == AggregateType.S32 || elemType == AggregateType.U32) if (elemType is AggregateType.S32 or AggregateType.U32)
{ {
iq = PixelImap.Constant; iq = PixelImap.Constant;
} }
@@ -410,7 +409,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
2 => AggregateType.Vector2, 2 => AggregateType.Vector2,
3 => AggregateType.Vector3, 3 => AggregateType.Vector3,
4 => AggregateType.Vector4, 4 => AggregateType.Vector4,
_ => AggregateType.Invalid _ => AggregateType.Invalid,
}; };
} }
@@ -420,7 +419,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
if (!isPerPatch && IoMap.IsPerVertex(ioVariable, context.Config.Stage, isOutput)) if (!isPerPatch && IoMap.IsPerVertex(ioVariable, context.Config.Stage, isOutput))
{ {
int arraySize = context.Config.Stage == ShaderStage.Geometry ? context.InputVertices : 32; int arraySize = context.Config.Stage == ShaderStage.Geometry ? context.InputVertices : 32;
spvType = context.TypeArray(spvType, context.Constant(context.TypeU32(), (LiteralInteger)arraySize)); spvType = context.TypeArray(spvType, context.Constant(context.TypeU32(), arraySize));
if (context.Config.GpPassthrough && context.Config.GpuAccessor.QueryHostSupportsGeometryShaderPassthrough()) if (context.Config.GpPassthrough && context.Config.GpuAccessor.QueryHostSupportsGeometryShaderPassthrough())
{ {
@@ -542,7 +541,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
private static string GetStagePrefix(ShaderStage stage) private static string GetStagePrefix(ShaderStage stage)
{ {
return StagePrefixes[(int)stage]; return _stagePrefixes[(int)stage];
} }
} }
} }

View File

@@ -15,7 +15,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
ShaderStage.TessellationEvaluation => ExecutionModel.TessellationEvaluation, ShaderStage.TessellationEvaluation => ExecutionModel.TessellationEvaluation,
ShaderStage.Geometry => ExecutionModel.Geometry, ShaderStage.Geometry => ExecutionModel.Geometry,
ShaderStage.Fragment => ExecutionModel.Fragment, ShaderStage.Fragment => ExecutionModel.Fragment,
_ => throw new ArgumentException($"Invalid shader stage \"{stage}\".") _ => throw new ArgumentException($"Invalid shader stage \"{stage}\"."),
}; };
} }
} }

View File

@@ -14,19 +14,20 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
static class Instructions static class Instructions
{ {
private const MemorySemanticsMask DefaultMemorySemantics = private const MemorySemanticsMask DefaultMemorySemantics =
MemorySemanticsMask.ImageMemory | MemorySemanticsMask.ImageMemory |
MemorySemanticsMask.AtomicCounterMemory | MemorySemanticsMask.AtomicCounterMemory |
MemorySemanticsMask.WorkgroupMemory | MemorySemanticsMask.WorkgroupMemory |
MemorySemanticsMask.UniformMemory | MemorySemanticsMask.UniformMemory |
MemorySemanticsMask.AcquireRelease; MemorySemanticsMask.AcquireRelease;
private static readonly Func<CodeGenContext, AstOperation, OperationResult>[] InstTable; private static readonly Func<CodeGenContext, AstOperation, OperationResult>[] _instTable;
static Instructions() static Instructions()
{ {
InstTable = new Func<CodeGenContext, AstOperation, OperationResult>[(int)Instruction.Count]; _instTable = new Func<CodeGenContext, AstOperation, OperationResult>[(int)Instruction.Count];
#pragma warning disable IDE0055 // Disable formatting
Add(Instruction.Absolute, GenerateAbsolute); Add(Instruction.Absolute, GenerateAbsolute);
Add(Instruction.Add, GenerateAdd); Add(Instruction.Add, GenerateAdd);
Add(Instruction.AtomicAdd, GenerateAtomicAdd); Add(Instruction.AtomicAdd, GenerateAtomicAdd);
@@ -141,16 +142,17 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
Add(Instruction.VoteAll, GenerateVoteAll); Add(Instruction.VoteAll, GenerateVoteAll);
Add(Instruction.VoteAllEqual, GenerateVoteAllEqual); Add(Instruction.VoteAllEqual, GenerateVoteAllEqual);
Add(Instruction.VoteAny, GenerateVoteAny); Add(Instruction.VoteAny, GenerateVoteAny);
#pragma warning restore IDE0055
} }
private static void Add(Instruction inst, Func<CodeGenContext, AstOperation, OperationResult> handler) private static void Add(Instruction inst, Func<CodeGenContext, AstOperation, OperationResult> handler)
{ {
InstTable[(int)(inst & Instruction.Mask)] = handler; _instTable[(int)(inst & Instruction.Mask)] = handler;
} }
public static OperationResult Generate(CodeGenContext context, AstOperation operation) public static OperationResult Generate(CodeGenContext context, AstOperation operation)
{ {
var handler = InstTable[(int)(operation.Inst & Instruction.Mask)]; var handler = _instTable[(int)(operation.Inst & Instruction.Mask)];
if (handler != null) if (handler != null)
{ {
return handler(context, operation); return handler(context, operation);
@@ -305,7 +307,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
Debug.Assert(funcId.Type == OperandType.Constant); Debug.Assert(funcId.Type == OperandType.Constant);
(var function, var spvFunc) = context.GetFunction(funcId.Value); var (function, spvFunc) = context.GetFunction(funcId.Value);
var args = new SpvInstruction[operation.SourcesCount - 1]; var args = new SpvInstruction[operation.SourcesCount - 1];
var spvLocals = context.GetLocalForArgsPointers(funcId.Value); var spvLocals = context.GetLocalForArgsPointers(funcId.Value);
@@ -615,7 +617,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
}); });
} }
bool isArray = (texOp.Type & SamplerType.Array) != 0; bool isArray = (texOp.Type & SamplerType.Array) != 0;
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0; bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
int srcIndex = isBindless ? 1 : 0; int srcIndex = isBindless ? 1 : 0;
@@ -625,11 +627,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
return context.Get(type, texOp.GetSource(srcIndex++)); return context.Get(type, texOp.GetSource(srcIndex++));
} }
SpvInstruction index = null;
if (isIndexed) if (isIndexed)
{ {
index = Src(AggregateType.S32); Src(AggregateType.S32);
} }
int coordsCount = texOp.Type.GetDimensions(); int coordsCount = texOp.Type.GetDimensions();
@@ -657,9 +657,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
SpvInstruction value = Src(componentType); SpvInstruction value = Src(componentType);
(var imageType, var imageVariable) = context.Images[new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format)]; (SpvInstruction imageType, SpvInstruction imageVariable) = context.Images[new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format)];
var image = context.Load(imageType, imageVariable); context.Load(imageType, imageVariable);
SpvInstruction resultType = context.GetType(componentType); SpvInstruction resultType = context.GetType(componentType);
SpvInstruction imagePointerType = context.TypePointer(StorageClass.Image, resultType); SpvInstruction imagePointerType = context.TypePointer(StorageClass.Image, resultType);
@@ -670,21 +670,21 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
var result = (texOp.Flags & TextureFlags.AtomicMask) switch var result = (texOp.Flags & TextureFlags.AtomicMask) switch
{ {
TextureFlags.Add => context.AtomicIAdd(resultType, pointer, one, zero, value), TextureFlags.Add => context.AtomicIAdd(resultType, pointer, one, zero, value),
TextureFlags.Minimum => componentType == AggregateType.S32 TextureFlags.Minimum => componentType == AggregateType.S32
? context.AtomicSMin(resultType, pointer, one, zero, value) ? context.AtomicSMin(resultType, pointer, one, zero, value)
: context.AtomicUMin(resultType, pointer, one, zero, value), : context.AtomicUMin(resultType, pointer, one, zero, value),
TextureFlags.Maximum => componentType == AggregateType.S32 TextureFlags.Maximum => componentType == AggregateType.S32
? context.AtomicSMax(resultType, pointer, one, zero, value) ? context.AtomicSMax(resultType, pointer, one, zero, value)
: context.AtomicUMax(resultType, pointer, one, zero, value), : context.AtomicUMax(resultType, pointer, one, zero, value),
TextureFlags.Increment => context.AtomicIIncrement(resultType, pointer, one, zero), TextureFlags.Increment => context.AtomicIIncrement(resultType, pointer, one, zero),
TextureFlags.Decrement => context.AtomicIDecrement(resultType, pointer, one, zero), TextureFlags.Decrement => context.AtomicIDecrement(resultType, pointer, one, zero),
TextureFlags.BitwiseAnd => context.AtomicAnd(resultType, pointer, one, zero, value), TextureFlags.BitwiseAnd => context.AtomicAnd(resultType, pointer, one, zero, value),
TextureFlags.BitwiseOr => context.AtomicOr(resultType, pointer, one, zero, value), TextureFlags.BitwiseOr => context.AtomicOr(resultType, pointer, one, zero, value),
TextureFlags.BitwiseXor => context.AtomicXor(resultType, pointer, one, zero, value), TextureFlags.BitwiseXor => context.AtomicXor(resultType, pointer, one, zero, value),
TextureFlags.Swap => context.AtomicExchange(resultType, pointer, one, zero, value), TextureFlags.Swap => context.AtomicExchange(resultType, pointer, one, zero, value),
TextureFlags.CAS => context.AtomicCompareExchange(resultType, pointer, one, zero, zero, Src(componentType), value), TextureFlags.CAS => context.AtomicCompareExchange(resultType, pointer, one, zero, zero, Src(componentType), value),
_ => context.AtomicIAdd(resultType, pointer, one, zero, value), _ => context.AtomicIAdd(resultType, pointer, one, zero, value),
}; };
return new OperationResult(componentType, result); return new OperationResult(componentType, result);
@@ -704,7 +704,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
return GetZeroOperationResult(context, texOp, componentType, isVector: true); return GetZeroOperationResult(context, texOp, componentType, isVector: true);
} }
bool isArray = (texOp.Type & SamplerType.Array) != 0; bool isArray = (texOp.Type & SamplerType.Array) != 0;
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0; bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
int srcIndex = isBindless ? 1 : 0; int srcIndex = isBindless ? 1 : 0;
@@ -714,11 +714,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
return context.Get(type, texOp.GetSource(srcIndex++)); return context.Get(type, texOp.GetSource(srcIndex++));
} }
SpvInstruction index = null;
if (isIndexed) if (isIndexed)
{ {
index = Src(AggregateType.S32); Src(AggregateType.S32);
} }
int coordsCount = texOp.Type.GetDimensions(); int coordsCount = texOp.Type.GetDimensions();
@@ -744,7 +742,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
pCoords = Src(AggregateType.S32); pCoords = Src(AggregateType.S32);
} }
(var imageType, var imageVariable) = context.Images[new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format)]; var (imageType, imageVariable) = context.Images[new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format)];
var image = context.Load(imageType, imageVariable); var image = context.Load(imageType, imageVariable);
var imageComponentType = context.GetType(componentType); var imageComponentType = context.GetType(componentType);
@@ -768,7 +766,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
return OperationResult.Invalid; return OperationResult.Invalid;
} }
bool isArray = (texOp.Type & SamplerType.Array) != 0; bool isArray = (texOp.Type & SamplerType.Array) != 0;
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0; bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
int srcIndex = isBindless ? 1 : 0; int srcIndex = isBindless ? 1 : 0;
@@ -778,11 +776,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
return context.Get(type, texOp.GetSource(srcIndex++)); return context.Get(type, texOp.GetSource(srcIndex++));
} }
SpvInstruction index = null;
if (isIndexed) if (isIndexed)
{ {
index = Src(AggregateType.S32); Src(AggregateType.S32);
} }
int coordsCount = texOp.Type.GetDimensions(); int coordsCount = texOp.Type.GetDimensions();
@@ -833,7 +829,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
var texel = context.CompositeConstruct(context.TypeVector(context.GetType(componentType), ComponentsCount), cElems); var texel = context.CompositeConstruct(context.TypeVector(context.GetType(componentType), ComponentsCount), cElems);
(var imageType, var imageVariable) = context.Images[new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format)]; var (imageType, imageVariable) = context.Images[new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format)];
var image = context.Load(imageType, imageVariable); var image = context.Load(imageType, imageVariable);
@@ -886,11 +882,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
return context.Get(type, texOp.GetSource(srcIndex++)); return context.Get(type, texOp.GetSource(srcIndex++));
} }
SpvInstruction index = null;
if (isIndexed) if (isIndexed)
{ {
index = Src(AggregateType.S32); Src(AggregateType.S32);
} }
int pCount = texOp.Type.GetDimensions(); int pCount = texOp.Type.GetDimensions();
@@ -916,7 +910,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
var meta = new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format); var meta = new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format);
(_, var sampledImageType, var sampledImageVariable) = context.Samplers[meta]; var (_, sampledImageType, sampledImageVariable) = context.Samplers[meta];
var image = context.Load(sampledImageType, sampledImageVariable); var image = context.Load(sampledImageType, sampledImageVariable);
@@ -973,7 +967,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
loopBlock = loopBlock.Parent; loopBlock = loopBlock.Parent;
} }
(var loopTarget, var continueTarget) = context.LoopTargets[loopBlock]; (_, SpvInstruction continueTarget) = context.LoopTargets[loopBlock];
context.Branch(continueTarget); context.Branch(continueTarget);
@@ -1278,19 +1272,19 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
{ {
AstTextureOperation texOp = (AstTextureOperation)operation; AstTextureOperation texOp = (AstTextureOperation)operation;
bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0; bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;
bool isGather = (texOp.Flags & TextureFlags.Gather) != 0; bool isGather = (texOp.Flags & TextureFlags.Gather) != 0;
bool hasDerivatives = (texOp.Flags & TextureFlags.Derivatives) != 0; bool hasDerivatives = (texOp.Flags & TextureFlags.Derivatives) != 0;
bool intCoords = (texOp.Flags & TextureFlags.IntCoords) != 0; bool intCoords = (texOp.Flags & TextureFlags.IntCoords) != 0;
bool hasLodBias = (texOp.Flags & TextureFlags.LodBias) != 0; bool hasLodBias = (texOp.Flags & TextureFlags.LodBias) != 0;
bool hasLodLevel = (texOp.Flags & TextureFlags.LodLevel) != 0; bool hasLodLevel = (texOp.Flags & TextureFlags.LodLevel) != 0;
bool hasOffset = (texOp.Flags & TextureFlags.Offset) != 0; bool hasOffset = (texOp.Flags & TextureFlags.Offset) != 0;
bool hasOffsets = (texOp.Flags & TextureFlags.Offsets) != 0; bool hasOffsets = (texOp.Flags & TextureFlags.Offsets) != 0;
bool isArray = (texOp.Type & SamplerType.Array) != 0; bool isArray = (texOp.Type & SamplerType.Array) != 0;
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0; bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
bool isMultisample = (texOp.Type & SamplerType.Multisample) != 0; bool isMultisample = (texOp.Type & SamplerType.Multisample) != 0;
bool isShadow = (texOp.Type & SamplerType.Shadow) != 0; bool isShadow = (texOp.Type & SamplerType.Shadow) != 0;
bool colorIsVector = isGather || !isShadow; bool colorIsVector = isGather || !isShadow;
@@ -1307,11 +1301,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
return context.Get(type, texOp.GetSource(srcIndex++)); return context.Get(type, texOp.GetSource(srcIndex++));
} }
SpvInstruction index = null;
if (isIndexed) if (isIndexed)
{ {
index = Src(AggregateType.S32); Src(AggregateType.S32);
} }
int coordsCount = texOp.Type.GetDimensions(); int coordsCount = texOp.Type.GetDimensions();
@@ -1395,7 +1387,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
derivatives = new[] derivatives = new[]
{ {
AssembleDerivativesVector(coordsCount), // dPdx AssembleDerivativesVector(coordsCount), // dPdx
AssembleDerivativesVector(coordsCount) // dPdy AssembleDerivativesVector(coordsCount), // dPdy
}; };
} }
@@ -1445,7 +1437,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
AssembleOffsetVector(coordsCount), AssembleOffsetVector(coordsCount),
AssembleOffsetVector(coordsCount), AssembleOffsetVector(coordsCount),
AssembleOffsetVector(coordsCount), AssembleOffsetVector(coordsCount),
AssembleOffsetVector(coordsCount) AssembleOffsetVector(coordsCount),
}; };
} }
@@ -1474,7 +1466,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
// not needed for shadow samplers. // not needed for shadow samplers.
if (isGather && !isShadow) if (isGather && !isShadow)
{ {
compIdx = Src(AggregateType.S32); compIdx = Src(AggregateType.S32);
} }
var operandsList = new List<SpvInstruction>(); var operandsList = new List<SpvInstruction>();
@@ -1521,7 +1513,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
var meta = new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format); var meta = new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format);
(var imageType, var sampledImageType, var sampledImageVariable) = context.Samplers[meta]; var (imageType, sampledImageType, sampledImageVariable) = context.Samplers[meta];
var image = context.Load(sampledImageType, sampledImageVariable); var image = context.Load(sampledImageType, sampledImageVariable);
@@ -1595,16 +1587,14 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0; bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
SpvInstruction index = null;
if (isIndexed) if (isIndexed)
{ {
index = context.GetS32(texOp.GetSource(0)); context.GetS32(texOp.GetSource(0));
} }
var meta = new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format); var meta = new TextureMeta(texOp.CbufSlot, texOp.Handle, texOp.Format);
(var imageType, var sampledImageType, var sampledImageVariable) = context.Samplers[meta]; (SpvInstruction imageType, SpvInstruction sampledImageType, SpvInstruction sampledImageVariable) = context.Samplers[meta];
var image = context.Load(sampledImageType, sampledImageVariable); var image = context.Load(sampledImageType, sampledImageVariable);
image = context.Image(imageType, image); image = context.Image(imageType, image);
@@ -1809,12 +1799,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
{ {
case StorageKind.ConstantBuffer: case StorageKind.ConstantBuffer:
case StorageKind.StorageBuffer: case StorageKind.StorageBuffer:
if (!(operation.GetSource(srcIndex++) is AstOperand bindingIndex) || bindingIndex.Type != OperandType.Constant) if (operation.GetSource(srcIndex++) is not AstOperand bindingIndex || bindingIndex.Type != OperandType.Constant)
{ {
throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand."); throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand.");
} }
if (!(operation.GetSource(srcIndex) is AstOperand fieldIndex) || fieldIndex.Type != OperandType.Constant) if (operation.GetSource(srcIndex) is not AstOperand fieldIndex || fieldIndex.Type != OperandType.Constant)
{ {
throw new InvalidOperationException($"Second input of {operation.Inst} with {storageKind} storage must be a constant operand."); throw new InvalidOperationException($"Second input of {operation.Inst} with {storageKind} storage must be a constant operand.");
} }
@@ -1833,7 +1823,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
case StorageKind.LocalMemory: case StorageKind.LocalMemory:
case StorageKind.SharedMemory: case StorageKind.SharedMemory:
if (!(operation.GetSource(srcIndex++) is AstOperand bindingId) || bindingId.Type != OperandType.Constant) if (operation.GetSource(srcIndex++) is not AstOperand { Type: OperandType.Constant } bindingId)
{ {
throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand."); throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand.");
} }
@@ -1856,7 +1846,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
case StorageKind.InputPerPatch: case StorageKind.InputPerPatch:
case StorageKind.Output: case StorageKind.Output:
case StorageKind.OutputPerPatch: case StorageKind.OutputPerPatch:
if (!(operation.GetSource(srcIndex++) is AstOperand varId) || varId.Type != OperandType.Constant) if (operation.GetSource(srcIndex++) is not AstOperand varId || varId.Type != OperandType.Constant)
{ {
throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand."); throw new InvalidOperationException($"First input of {operation.Inst} with {storageKind} storage must be a constant operand.");
} }
@@ -1869,7 +1859,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
if (context.Config.HasPerLocationInputOrOutput(ioVariable, isOutput)) if (context.Config.HasPerLocationInputOrOutput(ioVariable, isOutput))
{ {
if (!(operation.GetSource(srcIndex++) is AstOperand vecIndex) || vecIndex.Type != OperandType.Constant) if (operation.GetSource(srcIndex++) is not AstOperand vecIndex || vecIndex.Type != OperandType.Constant)
{ {
throw new InvalidOperationException($"Second input of {operation.Inst} with {storageKind} storage must be a constant operand."); throw new InvalidOperationException($"Second input of {operation.Inst} with {storageKind} storage must be a constant operand.");
} }
@@ -1964,7 +1954,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
private static SpvInstruction GetScalarInput(CodeGenContext context, IoVariable ioVariable) private static SpvInstruction GetScalarInput(CodeGenContext context, IoVariable ioVariable)
{ {
(_, var varType) = IoMap.GetSpirvBuiltIn(ioVariable); var (_, varType) = IoMap.GetSpirvBuiltIn(ioVariable);
varType &= AggregateType.ElementTypeMask; varType &= AggregateType.ElementTypeMask;
var ioDefinition = new IoDefinition(StorageKind.Input, ioVariable); var ioDefinition = new IoDefinition(StorageKind.Input, ioVariable);
@@ -2061,10 +2051,10 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
return new OperationResult(AggregateType.Bool, emitB(context.TypeBool(), context.Get(AggregateType.Bool, source))); return new OperationResult(AggregateType.Bool, emitB(context.TypeBool(), context.Get(AggregateType.Bool, source)));
} }
private static OperationResult GenerateUnaryFP32( private static OperationResult GenerateUnaryFP32(
CodeGenContext context, CodeGenContext context,
AstOperation operation, AstOperation operation,
Func<SpvInstruction, SpvInstruction, SpvInstruction> emit) Func<SpvInstruction, SpvInstruction, SpvInstruction> emit)
{ {
var source = operation.GetSource(0); var source = operation.GetSource(0);
return new OperationResult(AggregateType.FP32, emit(context.TypeFP32(), context.GetFP32(source))); return new OperationResult(AggregateType.FP32, emit(context.TypeFP32(), context.GetFP32(source)));

View File

@@ -45,7 +45,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
IoVariable.VertexIndex => (BuiltIn.VertexIndex, AggregateType.S32), IoVariable.VertexIndex => (BuiltIn.VertexIndex, AggregateType.S32),
IoVariable.ViewportIndex => (BuiltIn.ViewportIndex, AggregateType.S32), IoVariable.ViewportIndex => (BuiltIn.ViewportIndex, AggregateType.S32),
IoVariable.ViewportMask => (BuiltIn.ViewportMaskNV, AggregateType.Array | AggregateType.S32), IoVariable.ViewportMask => (BuiltIn.ViewportMaskNV, AggregateType.Array | AggregateType.S32),
_ => (default, AggregateType.Invalid) _ => (default, AggregateType.Invalid),
}; };
} }
@@ -58,7 +58,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
IoVariable.TessellationLevelOuter => 4, IoVariable.TessellationLevelOuter => 4,
IoVariable.ViewportMask => 1, IoVariable.ViewportMask => 1,
IoVariable.UserDefined => MaxAttributes, IoVariable.UserDefined => MaxAttributes,
_ => 1 _ => 1,
}; };
} }
@@ -74,13 +74,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
case IoVariable.ClipDistance: case IoVariable.ClipDistance:
case IoVariable.PointCoord: case IoVariable.PointCoord:
case IoVariable.ViewportMask: case IoVariable.ViewportMask:
return !isOutput && return !isOutput &&
(stage == ShaderStage.TessellationControl || stage is ShaderStage.TessellationControl or ShaderStage.TessellationEvaluation or ShaderStage.Geometry;
stage == ShaderStage.TessellationEvaluation ||
stage == ShaderStage.Geometry);
} }
return false; return false;
} }
} }
} }

View File

@@ -5,7 +5,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
{ {
readonly struct OperationResult readonly struct OperationResult
{ {
public static OperationResult Invalid => new OperationResult(AggregateType.Invalid, null); public static OperationResult Invalid => new(AggregateType.Invalid, null);
public AggregateType Type { get; } public AggregateType Type { get; }
public Instruction Value { get; } public Instruction Value { get; }

View File

@@ -17,15 +17,15 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
{ {
// Resource pools for Spirv generation. Note: Increase count when more threads are being used. // Resource pools for Spirv generation. Note: Increase count when more threads are being used.
private const int GeneratorPoolCount = 1; private const int GeneratorPoolCount = 1;
private static ObjectPool<SpvInstructionPool> InstructionPool; private static readonly ObjectPool<SpvInstructionPool> _instructionPool;
private static ObjectPool<SpvLiteralIntegerPool> IntegerPool; private static readonly ObjectPool<SpvLiteralIntegerPool> _integerPool;
private static object PoolLock; private static readonly object _poolLock;
static SpirvGenerator() static SpirvGenerator()
{ {
InstructionPool = new (() => new SpvInstructionPool(), GeneratorPoolCount); _instructionPool = new(() => new SpvInstructionPool(), GeneratorPoolCount);
IntegerPool = new (() => new SpvLiteralIntegerPool(), GeneratorPoolCount); _integerPool = new(() => new SpvLiteralIntegerPool(), GeneratorPoolCount);
PoolLock = new object(); _poolLock = new object();
} }
private const HelperFunctionsMask NeedsInvocationIdMask = private const HelperFunctionsMask NeedsInvocationIdMask =
@@ -40,13 +40,13 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
SpvInstructionPool instPool; SpvInstructionPool instPool;
SpvLiteralIntegerPool integerPool; SpvLiteralIntegerPool integerPool;
lock (PoolLock) lock (_poolLock)
{ {
instPool = InstructionPool.Allocate(); instPool = _instructionPool.Allocate();
integerPool = IntegerPool.Allocate(); integerPool = _integerPool.Allocate();
} }
CodeGenContext context = new CodeGenContext(info, config, instPool, integerPool); CodeGenContext context = new(info, config, instPool, integerPool);
context.AddCapability(Capability.GroupNonUniformBallot); context.AddCapability(Capability.GroupNonUniformBallot);
context.AddCapability(Capability.GroupNonUniformShuffle); context.AddCapability(Capability.GroupNonUniformShuffle);
@@ -133,10 +133,10 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
byte[] result = context.Generate(); byte[] result = context.Generate();
lock (PoolLock) lock (_poolLock)
{ {
InstructionPool.Release(instPool); _instructionPool.Release(instPool);
IntegerPool.Release(integerPool); _integerPool.Release(integerPool);
} }
return result; return result;
@@ -144,7 +144,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
private static void Generate(CodeGenContext context, StructuredProgramInfo info, int funcIndex) private static void Generate(CodeGenContext context, StructuredProgramInfo info, int funcIndex)
{ {
(var function, var spvFunc) = context.GetFunction(funcIndex); var (function, spvFunc) = context.GetFunction(funcIndex);
context.CurrentFunction = function; context.CurrentFunction = function;
context.AddFunction(spvFunc); context.AddFunction(spvFunc);
@@ -160,7 +160,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
Generate(context, function.MainBlock); Generate(context, function.MainBlock);
// Functions must always end with a return. // Functions must always end with a return.
if (!(function.MainBlock.Last is AstOperation operation) || if (function.MainBlock.Last is not AstOperation operation ||
(operation.Inst != Instruction.Return && operation.Inst != Instruction.Discard)) (operation.Inst != Instruction.Return && operation.Inst != Instruction.Discard))
{ {
context.Return(); context.Return();
@@ -232,7 +232,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
InputTopology.LinesAdjacency => ExecutionMode.InputLinesAdjacency, InputTopology.LinesAdjacency => ExecutionMode.InputLinesAdjacency,
InputTopology.Triangles => ExecutionMode.Triangles, InputTopology.Triangles => ExecutionMode.Triangles,
InputTopology.TrianglesAdjacency => ExecutionMode.InputTrianglesAdjacency, InputTopology.TrianglesAdjacency => ExecutionMode.InputTrianglesAdjacency,
_ => throw new InvalidOperationException($"Invalid input topology \"{inputTopology}\".") _ => throw new InvalidOperationException($"Invalid input topology \"{inputTopology}\"."),
}); });
context.AddExecutionMode(spvFunc, ExecutionMode.Invocations, (SpvLiteralInteger)context.Config.ThreadsPerInputPrimitive); context.AddExecutionMode(spvFunc, ExecutionMode.Invocations, (SpvLiteralInteger)context.Config.ThreadsPerInputPrimitive);
@@ -242,7 +242,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
OutputTopology.PointList => ExecutionMode.OutputPoints, OutputTopology.PointList => ExecutionMode.OutputPoints,
OutputTopology.LineStrip => ExecutionMode.OutputLineStrip, OutputTopology.LineStrip => ExecutionMode.OutputLineStrip,
OutputTopology.TriangleStrip => ExecutionMode.OutputTriangleStrip, OutputTopology.TriangleStrip => ExecutionMode.OutputTriangleStrip,
_ => throw new InvalidOperationException($"Invalid output topology \"{context.Config.OutputTopology}\".") _ => throw new InvalidOperationException($"Invalid output topology \"{context.Config.OutputTopology}\"."),
}); });
int maxOutputVertices = context.Config.GpPassthrough ? context.InputVertices : context.Config.MaxOutputVertices; int maxOutputVertices = context.Config.GpPassthrough ? context.InputVertices : context.Config.MaxOutputVertices;
@@ -294,7 +294,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
private static void Generate(CodeGenContext context, AstBlock block) private static void Generate(CodeGenContext context, AstBlock block)
{ {
AstBlockVisitor visitor = new AstBlockVisitor(block); AstBlockVisitor visitor = new(block);
var loopTargets = new Dictionary<AstBlock, (SpvInstruction, SpvInstruction)>(); var loopTargets = new Dictionary<AstBlock, (SpvInstruction, SpvInstruction)>();
@@ -346,7 +346,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
// if the condition is true. // if the condition is true.
AstBlock mergeBlock = e.Block.Parent; AstBlock mergeBlock = e.Block.Parent;
(var loopTarget, var continueTarget) = loopTargets[e.Block]; var (loopTarget, continueTarget) = loopTargets[e.Block];
context.Branch(continueTarget); context.Branch(continueTarget);
context.AddLabel(continueTarget); context.AddLabel(continueTarget);

View File

@@ -1,4 +1,4 @@
namespace Ryujinx.Graphics.Shader.CodeGen.Spirv namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
{ {
readonly record struct TextureMeta(int CbufSlot, int Handle, TextureFormat Format); readonly record struct TextureMeta(int CbufSlot, int Handle, TextureFormat Format);
} }

View File

@@ -17,4 +17,4 @@ namespace Ryujinx.Graphics.Shader
public const int TfeBufferBaseBinding = 1; public const int TfeBufferBaseBinding = 1;
public const int TfeBuffersCount = 4; public const int TfeBuffersCount = 4;
} }
} }

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