Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
40f2bd37e3 | ||
|
9288ffd26d | ||
|
2cdc82cb91 | ||
|
6aa8d71588 | ||
|
9becbd7d72 |
@@ -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" />
|
||||||
|
23
src/ARMeilleure/Decoders/OpCode32SimdCvtFFixed.cs
Normal file
23
src/ARMeilleure/Decoders/OpCode32SimdCvtFFixed.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -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);
|
||||||
|
@@ -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;
|
||||||
|
@@ -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";
|
||||||
|
@@ -51,6 +51,6 @@
|
|||||||
/*!\brief An iterator reached the end of list.
|
/*!\brief An iterator reached the end of list.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
CodecListEnd
|
CodecListEnd,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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
|
||||||
{
|
{
|
||||||
|
@@ -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;
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
|
@@ -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;
|
||||||
|
@@ -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(
|
||||||
|
@@ -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)
|
||||||
|
@@ -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..];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
|
@@ -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)
|
||||||
{
|
{
|
||||||
|
@@ -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
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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(
|
||||||
|
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -16,6 +16,6 @@
|
|||||||
Block64x32 = 11,
|
Block64x32 = 11,
|
||||||
Block64x64 = 12,
|
Block64x64 = 12,
|
||||||
BlockSizes = 13,
|
BlockSizes = 13,
|
||||||
BlockInvalid = BlockSizes
|
BlockInvalid = BlockSizes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,6 +3,6 @@
|
|||||||
internal enum FrameType
|
internal enum FrameType
|
||||||
{
|
{
|
||||||
KeyFrame = 0,
|
KeyFrame = 0,
|
||||||
InterFrame = 1
|
InterFrame = 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
||||||
|
@@ -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;
|
||||||
|
@@ -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];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -9,6 +9,6 @@
|
|||||||
BothNew = 4,
|
BothNew = 4,
|
||||||
IntraPlusNonIntra = 5,
|
IntraPlusNonIntra = 5,
|
||||||
BothIntra = 6,
|
BothIntra = 6,
|
||||||
InvalidCase = 9
|
InvalidCase = 9,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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)
|
||||||
{
|
{
|
||||||
|
@@ -7,6 +7,6 @@
|
|||||||
PartitionVert,
|
PartitionVert,
|
||||||
PartitionSplit,
|
PartitionSplit,
|
||||||
PartitionTypes,
|
PartitionTypes,
|
||||||
PartitionInvalid = PartitionTypes
|
PartitionInvalid = PartitionTypes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,6 +4,6 @@
|
|||||||
{
|
{
|
||||||
Y = 0,
|
Y = 0,
|
||||||
Uv = 1,
|
Uv = 1,
|
||||||
PlaneTypes
|
PlaneTypes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -5,6 +5,6 @@
|
|||||||
SingleReference = 0,
|
SingleReference = 0,
|
||||||
CompoundReference = 1,
|
CompoundReference = 1,
|
||||||
ReferenceModeSelect = 2,
|
ReferenceModeSelect = 2,
|
||||||
ReferenceModes = 3
|
ReferenceModes = 3,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
|
@@ -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 ||
|
||||||
|
@@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -9,12 +9,12 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
{
|
{
|
||||||
[ThreadStatic]
|
[ThreadStatic]
|
||||||
public static bool InBackground;
|
public static bool InBackground;
|
||||||
private Thread _thread;
|
private readonly Thread _thread;
|
||||||
private bool _running;
|
private bool _running;
|
||||||
|
|
||||||
private AutoResetEvent _signal;
|
private readonly AutoResetEvent _signal;
|
||||||
private Queue<Action> _work;
|
private readonly Queue<Action> _work;
|
||||||
private ObjectPool<ManualResetEventSlim> _invokePool;
|
private readonly ObjectPool<ManualResetEventSlim> _invokePool;
|
||||||
private readonly IOpenGLContext _backgroundContext;
|
private readonly IOpenGLContext _backgroundContext;
|
||||||
|
|
||||||
public BackgroundContextWorker(IOpenGLContext backgroundContext)
|
public BackgroundContextWorker(IOpenGLContext backgroundContext)
|
||||||
|
@@ -63,10 +63,18 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case DebugType.DebugTypeError : Logger.Error?.Print(LogClass.Gpu, $"{severity}: {msg}\nCallStack={Environment.StackTrace}", "GLERROR"); break;
|
case DebugType.DebugTypeError:
|
||||||
case DebugType.DebugTypePerformance: Logger.Warning?.Print(LogClass.Gpu, $"{severity}: {msg}", "GLPERF"); break;
|
Logger.Error?.Print(LogClass.Gpu, $"{severity}: {msg}\nCallStack={Environment.StackTrace}", "GLERROR");
|
||||||
case DebugType.DebugTypePushGroup : Logger.Info?.Print(LogClass.Gpu, $"{{ ({id}) {severity}: {msg}", "GLINFO"); break;
|
break;
|
||||||
case DebugType.DebugTypePopGroup : Logger.Info?.Print(LogClass.Gpu, $"}} ({id}) {severity}: {msg}", "GLINFO"); break;
|
case DebugType.DebugTypePerformance:
|
||||||
|
Logger.Warning?.Print(LogClass.Gpu, $"{severity}: {msg}", "GLPERF");
|
||||||
|
break;
|
||||||
|
case DebugType.DebugTypePushGroup:
|
||||||
|
Logger.Info?.Print(LogClass.Gpu, $"{{ ({id}) {severity}: {msg}", "GLINFO");
|
||||||
|
break;
|
||||||
|
case DebugType.DebugTypePopGroup:
|
||||||
|
Logger.Info?.Print(LogClass.Gpu, $"}} ({id}) {severity}: {msg}", "GLINFO");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if (source == DebugSource.DebugSourceApplication)
|
if (source == DebugSource.DebugSourceApplication)
|
||||||
{
|
{
|
||||||
|
@@ -65,16 +65,12 @@ void main()
|
|||||||
|
|
||||||
if (x0 > x1)
|
if (x0 > x1)
|
||||||
{
|
{
|
||||||
float temp = s0;
|
(s1, s0) = (s0, s1);
|
||||||
s0 = s1;
|
|
||||||
s1 = temp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (y0 > y1)
|
if (y0 > y1)
|
||||||
{
|
{
|
||||||
float temp = t0;
|
(t1, t0) = (t0, t1);
|
||||||
t0 = t1;
|
|
||||||
t1 = temp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GL.Uniform1(_uniformSrcX0Location, s0);
|
GL.Uniform1(_uniformSrcX0Location, s0);
|
||||||
|
@@ -37,7 +37,7 @@ namespace Ryujinx.Graphics.OpenGL.Effects
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public FsrScalingFilter(OpenGLRenderer renderer, IPostProcessingEffect filter)
|
public FsrScalingFilter(OpenGLRenderer renderer)
|
||||||
{
|
{
|
||||||
Initialize();
|
Initialize();
|
||||||
|
|
||||||
|
@@ -3,7 +3,7 @@ using System;
|
|||||||
|
|
||||||
namespace Ryujinx.Graphics.OpenGL.Effects
|
namespace Ryujinx.Graphics.OpenGL.Effects
|
||||||
{
|
{
|
||||||
internal interface IPostProcessingEffect : IDisposable
|
internal interface IPostProcessingEffect : IDisposable
|
||||||
{
|
{
|
||||||
const int LocalGroupSize = 64;
|
const int LocalGroupSize = 64;
|
||||||
TextureView Run(TextureView view, int width, int height);
|
TextureView Run(TextureView view, int width, int height);
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
using OpenTK.Graphics.OpenGL;
|
using OpenTK.Graphics.OpenGL;
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.OpenGL.Effects
|
namespace Ryujinx.Graphics.OpenGL.Effects
|
||||||
{
|
{
|
||||||
|
@@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.OpenGL.Effects.Smaa
|
|||||||
private int[] _neighbourShaderPrograms;
|
private int[] _neighbourShaderPrograms;
|
||||||
private TextureStorage _edgeOutputTexture;
|
private TextureStorage _edgeOutputTexture;
|
||||||
private TextureStorage _blendOutputTexture;
|
private TextureStorage _blendOutputTexture;
|
||||||
private string[] _qualities;
|
private readonly string[] _qualities;
|
||||||
private int _inputUniform;
|
private int _inputUniform;
|
||||||
private int _outputUniform;
|
private int _outputUniform;
|
||||||
private int _samplerAreaUniform;
|
private int _samplerAreaUniform;
|
||||||
|
@@ -4,42 +4,42 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
{
|
{
|
||||||
readonly struct FormatInfo
|
readonly struct FormatInfo
|
||||||
{
|
{
|
||||||
public int Components { get; }
|
public int Components { get; }
|
||||||
public bool Normalized { get; }
|
public bool Normalized { get; }
|
||||||
public bool Scaled { get; }
|
public bool Scaled { get; }
|
||||||
|
|
||||||
public PixelInternalFormat PixelInternalFormat { get; }
|
public PixelInternalFormat PixelInternalFormat { get; }
|
||||||
public PixelFormat PixelFormat { get; }
|
public PixelFormat PixelFormat { get; }
|
||||||
public PixelType PixelType { get; }
|
public PixelType PixelType { get; }
|
||||||
|
|
||||||
public bool IsCompressed { get; }
|
public bool IsCompressed { get; }
|
||||||
|
|
||||||
public FormatInfo(
|
public FormatInfo(
|
||||||
int components,
|
int components,
|
||||||
bool normalized,
|
bool normalized,
|
||||||
bool scaled,
|
bool scaled,
|
||||||
All pixelInternalFormat,
|
All pixelInternalFormat,
|
||||||
PixelFormat pixelFormat,
|
PixelFormat pixelFormat,
|
||||||
PixelType pixelType)
|
PixelType pixelType)
|
||||||
{
|
{
|
||||||
Components = components;
|
Components = components;
|
||||||
Normalized = normalized;
|
Normalized = normalized;
|
||||||
Scaled = scaled;
|
Scaled = scaled;
|
||||||
PixelInternalFormat = (PixelInternalFormat)pixelInternalFormat;
|
PixelInternalFormat = (PixelInternalFormat)pixelInternalFormat;
|
||||||
PixelFormat = pixelFormat;
|
PixelFormat = pixelFormat;
|
||||||
PixelType = pixelType;
|
PixelType = pixelType;
|
||||||
IsCompressed = false;
|
IsCompressed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public FormatInfo(int components, bool normalized, bool scaled, All pixelFormat)
|
public FormatInfo(int components, bool normalized, bool scaled, All pixelFormat)
|
||||||
{
|
{
|
||||||
Components = components;
|
Components = components;
|
||||||
Normalized = normalized;
|
Normalized = normalized;
|
||||||
Scaled = scaled;
|
Scaled = scaled;
|
||||||
PixelInternalFormat = 0;
|
PixelInternalFormat = 0;
|
||||||
PixelFormat = (PixelFormat)pixelFormat;
|
PixelFormat = (PixelFormat)pixelFormat;
|
||||||
PixelType = 0;
|
PixelType = 0;
|
||||||
IsCompressed = true;
|
IsCompressed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,10 +4,10 @@ using System;
|
|||||||
|
|
||||||
namespace Ryujinx.Graphics.OpenGL
|
namespace Ryujinx.Graphics.OpenGL
|
||||||
{
|
{
|
||||||
struct FormatTable
|
readonly struct FormatTable
|
||||||
{
|
{
|
||||||
private static FormatInfo[] _table;
|
private static readonly FormatInfo[] _table;
|
||||||
private static SizedInternalFormat[] _tableImage;
|
private static readonly SizedInternalFormat[] _tableImage;
|
||||||
|
|
||||||
static FormatTable()
|
static FormatTable()
|
||||||
{
|
{
|
||||||
@@ -16,6 +16,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
_table = new FormatInfo[tableSize];
|
_table = new FormatInfo[tableSize];
|
||||||
_tableImage = new SizedInternalFormat[tableSize];
|
_tableImage = new SizedInternalFormat[tableSize];
|
||||||
|
|
||||||
|
#pragma warning disable IDE0055 // Disable formatting
|
||||||
Add(Format.R8Unorm, new FormatInfo(1, true, false, All.R8, PixelFormat.Red, PixelType.UnsignedByte));
|
Add(Format.R8Unorm, new FormatInfo(1, true, false, All.R8, PixelFormat.Red, PixelType.UnsignedByte));
|
||||||
Add(Format.R8Snorm, new FormatInfo(1, true, false, All.R8Snorm, PixelFormat.Red, PixelType.Byte));
|
Add(Format.R8Snorm, new FormatInfo(1, true, false, All.R8Snorm, PixelFormat.Red, PixelType.Byte));
|
||||||
Add(Format.R8Uint, new FormatInfo(1, false, false, All.R8ui, PixelFormat.RedInteger, PixelType.UnsignedByte));
|
Add(Format.R8Uint, new FormatInfo(1, false, false, All.R8ui, PixelFormat.RedInteger, PixelType.UnsignedByte));
|
||||||
@@ -200,6 +201,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
Add(Format.R10G10B10A2Unorm, (SizedInternalFormat)All.Rgb10A2);
|
Add(Format.R10G10B10A2Unorm, (SizedInternalFormat)All.Rgb10A2);
|
||||||
Add(Format.R10G10B10A2Uint, (SizedInternalFormat)All.Rgb10A2ui);
|
Add(Format.R10G10B10A2Uint, (SizedInternalFormat)All.Rgb10A2ui);
|
||||||
Add(Format.R11G11B10Float, (SizedInternalFormat)All.R11fG11fB10f);
|
Add(Format.R11G11B10Float, (SizedInternalFormat)All.R11fG11fB10f);
|
||||||
|
#pragma warning restore IDE0055
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Add(Format format, FormatInfo info)
|
private static void Add(Format format, FormatInfo info)
|
||||||
|
@@ -105,7 +105,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
_colorsCount = colorsCount;
|
_colorsCount = colorsCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetDrawBuffersImpl(int colorsCount)
|
private static void SetDrawBuffersImpl(int colorsCount)
|
||||||
{
|
{
|
||||||
DrawBuffersEnum[] drawBuffers = new DrawBuffersEnum[colorsCount];
|
DrawBuffersEnum[] drawBuffers = new DrawBuffersEnum[colorsCount];
|
||||||
|
|
||||||
|
@@ -5,30 +5,30 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
{
|
{
|
||||||
static class HwCapabilities
|
static class HwCapabilities
|
||||||
{
|
{
|
||||||
private static readonly Lazy<bool> _supportsAlphaToCoverageDitherControl = new Lazy<bool>(() => HasExtension("GL_NV_alpha_to_coverage_dither_control"));
|
private static readonly Lazy<bool> _supportsAlphaToCoverageDitherControl = new(() => HasExtension("GL_NV_alpha_to_coverage_dither_control"));
|
||||||
private static readonly Lazy<bool> _supportsAstcCompression = new Lazy<bool>(() => HasExtension("GL_KHR_texture_compression_astc_ldr"));
|
private static readonly Lazy<bool> _supportsAstcCompression = new(() => HasExtension("GL_KHR_texture_compression_astc_ldr"));
|
||||||
private static readonly Lazy<bool> _supportsBlendEquationAdvanced = new Lazy<bool>(() => HasExtension("GL_NV_blend_equation_advanced"));
|
private static readonly Lazy<bool> _supportsBlendEquationAdvanced = new(() => HasExtension("GL_NV_blend_equation_advanced"));
|
||||||
private static readonly Lazy<bool> _supportsDrawTexture = new Lazy<bool>(() => HasExtension("GL_NV_draw_texture"));
|
private static readonly Lazy<bool> _supportsDrawTexture = new(() => HasExtension("GL_NV_draw_texture"));
|
||||||
private static readonly Lazy<bool> _supportsFragmentShaderInterlock = new Lazy<bool>(() => HasExtension("GL_ARB_fragment_shader_interlock"));
|
private static readonly Lazy<bool> _supportsFragmentShaderInterlock = new(() => HasExtension("GL_ARB_fragment_shader_interlock"));
|
||||||
private static readonly Lazy<bool> _supportsFragmentShaderOrdering = new Lazy<bool>(() => HasExtension("GL_INTEL_fragment_shader_ordering"));
|
private static readonly Lazy<bool> _supportsFragmentShaderOrdering = new(() => HasExtension("GL_INTEL_fragment_shader_ordering"));
|
||||||
private static readonly Lazy<bool> _supportsGeometryShaderPassthrough = new Lazy<bool>(() => HasExtension("GL_NV_geometry_shader_passthrough"));
|
private static readonly Lazy<bool> _supportsGeometryShaderPassthrough = new(() => HasExtension("GL_NV_geometry_shader_passthrough"));
|
||||||
private static readonly Lazy<bool> _supportsImageLoadFormatted = new Lazy<bool>(() => HasExtension("GL_EXT_shader_image_load_formatted"));
|
private static readonly Lazy<bool> _supportsImageLoadFormatted = new(() => HasExtension("GL_EXT_shader_image_load_formatted"));
|
||||||
private static readonly Lazy<bool> _supportsIndirectParameters = new Lazy<bool>(() => HasExtension("GL_ARB_indirect_parameters"));
|
private static readonly Lazy<bool> _supportsIndirectParameters = new(() => HasExtension("GL_ARB_indirect_parameters"));
|
||||||
private static readonly Lazy<bool> _supportsParallelShaderCompile = new Lazy<bool>(() => HasExtension("GL_ARB_parallel_shader_compile"));
|
private static readonly Lazy<bool> _supportsParallelShaderCompile = new(() => HasExtension("GL_ARB_parallel_shader_compile"));
|
||||||
private static readonly Lazy<bool> _supportsPolygonOffsetClamp = new Lazy<bool>(() => HasExtension("GL_EXT_polygon_offset_clamp"));
|
private static readonly Lazy<bool> _supportsPolygonOffsetClamp = new(() => HasExtension("GL_EXT_polygon_offset_clamp"));
|
||||||
private static readonly Lazy<bool> _supportsQuads = new Lazy<bool>(SupportsQuadsCheck);
|
private static readonly Lazy<bool> _supportsQuads = new(SupportsQuadsCheck);
|
||||||
private static readonly Lazy<bool> _supportsSeamlessCubemapPerTexture = new Lazy<bool>(() => HasExtension("GL_ARB_seamless_cubemap_per_texture"));
|
private static readonly Lazy<bool> _supportsSeamlessCubemapPerTexture = new(() => HasExtension("GL_ARB_seamless_cubemap_per_texture"));
|
||||||
private static readonly Lazy<bool> _supportsShaderBallot = new Lazy<bool>(() => HasExtension("GL_ARB_shader_ballot"));
|
private static readonly Lazy<bool> _supportsShaderBallot = new(() => HasExtension("GL_ARB_shader_ballot"));
|
||||||
private static readonly Lazy<bool> _supportsShaderViewportLayerArray = new Lazy<bool>(() => HasExtension("GL_ARB_shader_viewport_layer_array"));
|
private static readonly Lazy<bool> _supportsShaderViewportLayerArray = new(() => HasExtension("GL_ARB_shader_viewport_layer_array"));
|
||||||
private static readonly Lazy<bool> _supportsViewportArray2 = new Lazy<bool>(() => HasExtension("GL_NV_viewport_array2"));
|
private static readonly Lazy<bool> _supportsViewportArray2 = new(() => HasExtension("GL_NV_viewport_array2"));
|
||||||
private static readonly Lazy<bool> _supportsTextureCompressionBptc = new Lazy<bool>(() => HasExtension("GL_EXT_texture_compression_bptc"));
|
private static readonly Lazy<bool> _supportsTextureCompressionBptc = new(() => HasExtension("GL_EXT_texture_compression_bptc"));
|
||||||
private static readonly Lazy<bool> _supportsTextureCompressionRgtc = new Lazy<bool>(() => HasExtension("GL_EXT_texture_compression_rgtc"));
|
private static readonly Lazy<bool> _supportsTextureCompressionRgtc = new(() => HasExtension("GL_EXT_texture_compression_rgtc"));
|
||||||
private static readonly Lazy<bool> _supportsTextureCompressionS3tc = new Lazy<bool>(() => HasExtension("GL_EXT_texture_compression_s3tc"));
|
private static readonly Lazy<bool> _supportsTextureCompressionS3tc = new(() => HasExtension("GL_EXT_texture_compression_s3tc"));
|
||||||
private static readonly Lazy<bool> _supportsTextureShadowLod = new Lazy<bool>(() => HasExtension("GL_EXT_texture_shadow_lod"));
|
private static readonly Lazy<bool> _supportsTextureShadowLod = new(() => HasExtension("GL_EXT_texture_shadow_lod"));
|
||||||
private static readonly Lazy<bool> _supportsViewportSwizzle = new Lazy<bool>(() => HasExtension("GL_NV_viewport_swizzle"));
|
private static readonly Lazy<bool> _supportsViewportSwizzle = new(() => HasExtension("GL_NV_viewport_swizzle"));
|
||||||
|
|
||||||
private static readonly Lazy<int> _maximumComputeSharedMemorySize = new Lazy<int>(() => GetLimit(All.MaxComputeSharedMemorySize));
|
private static readonly Lazy<int> _maximumComputeSharedMemorySize = new(() => GetLimit(All.MaxComputeSharedMemorySize));
|
||||||
private static readonly Lazy<int> _storageBufferOffsetAlignment = new Lazy<int>(() => GetLimit(All.ShaderStorageBufferOffsetAlignment));
|
private static readonly Lazy<int> _storageBufferOffsetAlignment = new(() => GetLimit(All.ShaderStorageBufferOffsetAlignment));
|
||||||
|
|
||||||
public enum GpuVendor
|
public enum GpuVendor
|
||||||
{
|
{
|
||||||
@@ -40,45 +40,44 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
Nvidia
|
Nvidia
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly Lazy<GpuVendor> _gpuVendor = new Lazy<GpuVendor>(GetGpuVendor);
|
private static readonly Lazy<GpuVendor> _gpuVendor = new(GetGpuVendor);
|
||||||
|
|
||||||
private static bool _isAMD => _gpuVendor.Value == GpuVendor.AmdWindows || _gpuVendor.Value == GpuVendor.AmdUnix;
|
private static bool IsIntel => _gpuVendor.Value == GpuVendor.IntelWindows || _gpuVendor.Value == GpuVendor.IntelUnix;
|
||||||
private static bool _isIntel => _gpuVendor.Value == GpuVendor.IntelWindows || _gpuVendor.Value == GpuVendor.IntelUnix;
|
|
||||||
|
|
||||||
public static GpuVendor Vendor => _gpuVendor.Value;
|
public static GpuVendor Vendor => _gpuVendor.Value;
|
||||||
|
|
||||||
private static Lazy<float> _maxSupportedAnisotropy = new Lazy<float>(GL.GetFloat((GetPName)All.MaxTextureMaxAnisotropy));
|
private static readonly Lazy<float> _maxSupportedAnisotropy = new(GL.GetFloat((GetPName)All.MaxTextureMaxAnisotropy));
|
||||||
|
|
||||||
public static bool UsePersistentBufferForFlush => _gpuVendor.Value == GpuVendor.AmdWindows || _gpuVendor.Value == GpuVendor.Nvidia;
|
public static bool UsePersistentBufferForFlush => _gpuVendor.Value == GpuVendor.AmdWindows || _gpuVendor.Value == GpuVendor.Nvidia;
|
||||||
|
|
||||||
public static bool SupportsAlphaToCoverageDitherControl => _supportsAlphaToCoverageDitherControl.Value;
|
public static bool SupportsAlphaToCoverageDitherControl => _supportsAlphaToCoverageDitherControl.Value;
|
||||||
public static bool SupportsAstcCompression => _supportsAstcCompression.Value;
|
public static bool SupportsAstcCompression => _supportsAstcCompression.Value;
|
||||||
public static bool SupportsBlendEquationAdvanced => _supportsBlendEquationAdvanced.Value;
|
public static bool SupportsBlendEquationAdvanced => _supportsBlendEquationAdvanced.Value;
|
||||||
public static bool SupportsDrawTexture => _supportsDrawTexture.Value;
|
public static bool SupportsDrawTexture => _supportsDrawTexture.Value;
|
||||||
public static bool SupportsFragmentShaderInterlock => _supportsFragmentShaderInterlock.Value;
|
public static bool SupportsFragmentShaderInterlock => _supportsFragmentShaderInterlock.Value;
|
||||||
public static bool SupportsFragmentShaderOrdering => _supportsFragmentShaderOrdering.Value;
|
public static bool SupportsFragmentShaderOrdering => _supportsFragmentShaderOrdering.Value;
|
||||||
public static bool SupportsGeometryShaderPassthrough => _supportsGeometryShaderPassthrough.Value;
|
public static bool SupportsGeometryShaderPassthrough => _supportsGeometryShaderPassthrough.Value;
|
||||||
public static bool SupportsImageLoadFormatted => _supportsImageLoadFormatted.Value;
|
public static bool SupportsImageLoadFormatted => _supportsImageLoadFormatted.Value;
|
||||||
public static bool SupportsIndirectParameters => _supportsIndirectParameters.Value;
|
public static bool SupportsIndirectParameters => _supportsIndirectParameters.Value;
|
||||||
public static bool SupportsParallelShaderCompile => _supportsParallelShaderCompile.Value;
|
public static bool SupportsParallelShaderCompile => _supportsParallelShaderCompile.Value;
|
||||||
public static bool SupportsPolygonOffsetClamp => _supportsPolygonOffsetClamp.Value;
|
public static bool SupportsPolygonOffsetClamp => _supportsPolygonOffsetClamp.Value;
|
||||||
public static bool SupportsQuads => _supportsQuads.Value;
|
public static bool SupportsQuads => _supportsQuads.Value;
|
||||||
public static bool SupportsSeamlessCubemapPerTexture => _supportsSeamlessCubemapPerTexture.Value;
|
public static bool SupportsSeamlessCubemapPerTexture => _supportsSeamlessCubemapPerTexture.Value;
|
||||||
public static bool SupportsShaderBallot => _supportsShaderBallot.Value;
|
public static bool SupportsShaderBallot => _supportsShaderBallot.Value;
|
||||||
public static bool SupportsShaderViewportLayerArray => _supportsShaderViewportLayerArray.Value;
|
public static bool SupportsShaderViewportLayerArray => _supportsShaderViewportLayerArray.Value;
|
||||||
public static bool SupportsViewportArray2 => _supportsViewportArray2.Value;
|
public static bool SupportsViewportArray2 => _supportsViewportArray2.Value;
|
||||||
public static bool SupportsTextureCompressionBptc => _supportsTextureCompressionBptc.Value;
|
public static bool SupportsTextureCompressionBptc => _supportsTextureCompressionBptc.Value;
|
||||||
public static bool SupportsTextureCompressionRgtc => _supportsTextureCompressionRgtc.Value;
|
public static bool SupportsTextureCompressionRgtc => _supportsTextureCompressionRgtc.Value;
|
||||||
public static bool SupportsTextureCompressionS3tc => _supportsTextureCompressionS3tc.Value;
|
public static bool SupportsTextureCompressionS3tc => _supportsTextureCompressionS3tc.Value;
|
||||||
public static bool SupportsTextureShadowLod => _supportsTextureShadowLod.Value;
|
public static bool SupportsTextureShadowLod => _supportsTextureShadowLod.Value;
|
||||||
public static bool SupportsViewportSwizzle => _supportsViewportSwizzle.Value;
|
public static bool SupportsViewportSwizzle => _supportsViewportSwizzle.Value;
|
||||||
|
|
||||||
public static bool SupportsMismatchingViewFormat => _gpuVendor.Value != GpuVendor.AmdWindows && _gpuVendor.Value != GpuVendor.IntelWindows;
|
public static bool SupportsMismatchingViewFormat => _gpuVendor.Value != GpuVendor.AmdWindows && _gpuVendor.Value != GpuVendor.IntelWindows;
|
||||||
public static bool SupportsNonConstantTextureOffset => _gpuVendor.Value == GpuVendor.Nvidia;
|
public static bool SupportsNonConstantTextureOffset => _gpuVendor.Value == GpuVendor.Nvidia;
|
||||||
public static bool RequiresSyncFlush => _gpuVendor.Value == GpuVendor.AmdWindows || _isIntel;
|
public static bool RequiresSyncFlush => _gpuVendor.Value == GpuVendor.AmdWindows || IsIntel;
|
||||||
|
|
||||||
public static int MaximumComputeSharedMemorySize => _maximumComputeSharedMemorySize.Value;
|
public static int MaximumComputeSharedMemorySize => _maximumComputeSharedMemorySize.Value;
|
||||||
public static int StorageBufferOffsetAlignment => _storageBufferOffsetAlignment.Value;
|
public static int StorageBufferOffsetAlignment => _storageBufferOffsetAlignment.Value;
|
||||||
|
|
||||||
public static float MaximumSupportedAnisotropy => _maxSupportedAnisotropy.Value;
|
public static float MaximumSupportedAnisotropy => _maxSupportedAnisotropy.Value;
|
||||||
|
|
||||||
|
@@ -39,8 +39,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||||||
GL.SamplerParameter(Handle, SamplerParameterName.TextureBorderColor, borderColor);
|
GL.SamplerParameter(Handle, SamplerParameterName.TextureBorderColor, borderColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
GL.SamplerParameter(Handle, SamplerParameterName.TextureMinLod, info.MinLod);
|
GL.SamplerParameter(Handle, SamplerParameterName.TextureMinLod, info.MinLod);
|
||||||
GL.SamplerParameter(Handle, SamplerParameterName.TextureMaxLod, info.MaxLod);
|
GL.SamplerParameter(Handle, SamplerParameterName.TextureMaxLod, info.MaxLod);
|
||||||
GL.SamplerParameter(Handle, SamplerParameterName.TextureLodBias, info.MipLodBias);
|
GL.SamplerParameter(Handle, SamplerParameterName.TextureLodBias, info.MipLodBias);
|
||||||
|
|
||||||
GL.SamplerParameter(Handle, SamplerParameterName.TextureMaxAnisotropyExt, info.MaxAnisotropy);
|
GL.SamplerParameter(Handle, SamplerParameterName.TextureMaxAnisotropyExt, info.MaxAnisotropy);
|
||||||
|
@@ -7,7 +7,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||||||
{
|
{
|
||||||
class TextureBuffer : TextureBase, ITexture
|
class TextureBuffer : TextureBase, ITexture
|
||||||
{
|
{
|
||||||
private OpenGLRenderer _renderer;
|
private readonly OpenGLRenderer _renderer;
|
||||||
private int _bufferOffset;
|
private int _bufferOffset;
|
||||||
private int _bufferSize;
|
private int _bufferSize;
|
||||||
private int _bufferCount;
|
private int _bufferCount;
|
||||||
@@ -58,7 +58,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||||||
{
|
{
|
||||||
var dataSpan = data.AsSpan();
|
var dataSpan = data.AsSpan();
|
||||||
|
|
||||||
Buffer.SetData(_buffer, _bufferOffset, dataSpan.Slice(0, Math.Min(dataSpan.Length, _bufferSize)));
|
Buffer.SetData(_buffer, _bufferOffset, dataSpan[..Math.Min(dataSpan.Length, _bufferSize)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetData(SpanOrArray<byte> data, int layer, int level)
|
public void SetData(SpanOrArray<byte> data, int layer, int level)
|
||||||
|
@@ -26,13 +26,13 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||||||
public void Copy(
|
public void Copy(
|
||||||
TextureView src,
|
TextureView src,
|
||||||
TextureView dst,
|
TextureView dst,
|
||||||
Extents2D srcRegion,
|
Extents2D srcRegion,
|
||||||
Extents2D dstRegion,
|
Extents2D dstRegion,
|
||||||
bool linearFilter,
|
bool linearFilter,
|
||||||
int srcLayer = 0,
|
int srcLayer = 0,
|
||||||
int dstLayer = 0,
|
int dstLayer = 0,
|
||||||
int srcLevel = 0,
|
int srcLevel = 0,
|
||||||
int dstLevel = 0)
|
int dstLevel = 0)
|
||||||
{
|
{
|
||||||
int levels = Math.Min(src.Info.Levels - srcLevel, dst.Info.Levels - dstLevel);
|
int levels = Math.Min(src.Info.Levels - srcLevel, dst.Info.Levels - dstLevel);
|
||||||
int layers = Math.Min(src.Info.GetLayers() - srcLayer, dst.Info.GetLayers() - dstLayer);
|
int layers = Math.Min(src.Info.GetLayers() - srcLayer, dst.Info.GetLayers() - dstLayer);
|
||||||
@@ -43,15 +43,15 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||||||
public void Copy(
|
public void Copy(
|
||||||
TextureView src,
|
TextureView src,
|
||||||
TextureView dst,
|
TextureView dst,
|
||||||
Extents2D srcRegion,
|
Extents2D srcRegion,
|
||||||
Extents2D dstRegion,
|
Extents2D dstRegion,
|
||||||
bool linearFilter,
|
bool linearFilter,
|
||||||
int srcLayer,
|
int srcLayer,
|
||||||
int dstLayer,
|
int dstLayer,
|
||||||
int srcLevel,
|
int srcLevel,
|
||||||
int dstLevel,
|
int dstLevel,
|
||||||
int layers,
|
int layers,
|
||||||
int levels)
|
int levels)
|
||||||
{
|
{
|
||||||
TextureView srcConverted = src.Format.IsBgr() != dst.Format.IsBgr() ? BgraSwap(src) : src;
|
TextureView srcConverted = src.Format.IsBgr() != dst.Format.IsBgr() ? BgraSwap(src) : src;
|
||||||
|
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
using OpenTK.Graphics.OpenGL;
|
using OpenTK.Graphics.OpenGL;
|
||||||
using Ryujinx.Graphics.GAL;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
@@ -81,9 +80,6 @@ void main()
|
|||||||
|
|
||||||
public void CopyIncompatibleFormats(ITextureInfo src, ITextureInfo dst, int srcLayer, int dstLayer, int srcLevel, int dstLevel, int depth, int levels)
|
public void CopyIncompatibleFormats(ITextureInfo src, ITextureInfo dst, int srcLayer, int dstLayer, int srcLevel, int dstLevel, int depth, int levels)
|
||||||
{
|
{
|
||||||
TextureCreateInfo srcInfo = src.Info;
|
|
||||||
TextureCreateInfo dstInfo = dst.Info;
|
|
||||||
|
|
||||||
int srcBpp = src.Info.BytesPerPixel;
|
int srcBpp = src.Info.BytesPerPixel;
|
||||||
int dstBpp = dst.Info.BytesPerPixel;
|
int dstBpp = dst.Info.BytesPerPixel;
|
||||||
|
|
||||||
@@ -176,7 +172,7 @@ void main()
|
|||||||
return GetShader(ComputeShaderWidening, _wideningProgramHandles, componentSize, srcComponentsCount, dstComponentsCount);
|
return GetShader(ComputeShaderWidening, _wideningProgramHandles, componentSize, srcComponentsCount, dstComponentsCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int GetShader(
|
private static int GetShader(
|
||||||
string code,
|
string code,
|
||||||
Dictionary<int, int> programHandles,
|
Dictionary<int, int> programHandles,
|
||||||
int componentSize,
|
int componentSize,
|
||||||
|
@@ -94,8 +94,8 @@ void main()
|
|||||||
}";
|
}";
|
||||||
|
|
||||||
private readonly OpenGLRenderer _renderer;
|
private readonly OpenGLRenderer _renderer;
|
||||||
private int[] _msToNonMSProgramHandles;
|
private readonly int[] _msToNonMSProgramHandles;
|
||||||
private int[] _nonMSToMSProgramHandles;
|
private readonly int[] _nonMSToMSProgramHandles;
|
||||||
|
|
||||||
public TextureCopyMS(OpenGLRenderer renderer)
|
public TextureCopyMS(OpenGLRenderer renderer)
|
||||||
{
|
{
|
||||||
@@ -219,7 +219,7 @@ void main()
|
|||||||
return GetShader(ComputeShaderNonMSToMS, _nonMSToMSProgramHandles, bytesPerPixel);
|
return GetShader(ComputeShaderNonMSToMS, _nonMSToMSProgramHandles, bytesPerPixel);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int GetShader(string code, int[] programHandles, int bytesPerPixel)
|
private static int GetShader(string code, int[] programHandles, int bytesPerPixel)
|
||||||
{
|
{
|
||||||
int index = BitOperations.Log2((uint)bytesPerPixel);
|
int index = BitOperations.Log2((uint)bytesPerPixel);
|
||||||
|
|
||||||
|
@@ -21,7 +21,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||||||
public TextureStorage(OpenGLRenderer renderer, TextureCreateInfo info, float scaleFactor)
|
public TextureStorage(OpenGLRenderer renderer, TextureCreateInfo info, float scaleFactor)
|
||||||
{
|
{
|
||||||
_renderer = renderer;
|
_renderer = renderer;
|
||||||
Info = info;
|
Info = info;
|
||||||
|
|
||||||
Handle = GL.GenTexture();
|
Handle = GL.GenTexture();
|
||||||
ScaleFactor = scaleFactor;
|
ScaleFactor = scaleFactor;
|
||||||
|
@@ -88,9 +88,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||||||
{
|
{
|
||||||
// Swap B <-> R for BGRA formats, as OpenGL has no support for them
|
// Swap B <-> R for BGRA formats, as OpenGL has no support for them
|
||||||
// and we need to manually swap the components on read/write on the GPU.
|
// and we need to manually swap the components on read/write on the GPU.
|
||||||
int temp = swizzleRgba[0];
|
(swizzleRgba[2], swizzleRgba[0]) = (swizzleRgba[0], swizzleRgba[2]);
|
||||||
swizzleRgba[0] = swizzleRgba[2];
|
|
||||||
swizzleRgba[2] = temp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GL.TexParameter(target, TextureParameterName.TextureSwizzleRgba, swizzleRgba);
|
GL.TexParameter(target, TextureParameterName.TextureSwizzleRgba, swizzleRgba);
|
||||||
@@ -186,8 +184,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||||||
// This approach uses blit, which causes a resolution loss since some samples will be lost
|
// This approach uses blit, which causes a resolution loss since some samples will be lost
|
||||||
// in the process.
|
// in the process.
|
||||||
|
|
||||||
Extents2D srcRegion = new Extents2D(0, 0, Width, Height);
|
Extents2D srcRegion = new(0, 0, Width, Height);
|
||||||
Extents2D dstRegion = new Extents2D(0, 0, destinationView.Width, destinationView.Height);
|
Extents2D dstRegion = new(0, 0, destinationView.Width, destinationView.Height);
|
||||||
|
|
||||||
if (destinationView.Target.IsMultisample())
|
if (destinationView.Target.IsMultisample())
|
||||||
{
|
{
|
||||||
|
@@ -21,13 +21,13 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
|
|
||||||
public IWindow Window => _window;
|
public IWindow Window => _window;
|
||||||
|
|
||||||
private TextureCopy _textureCopy;
|
private readonly TextureCopy _textureCopy;
|
||||||
private TextureCopy _backgroundTextureCopy;
|
private readonly TextureCopy _backgroundTextureCopy;
|
||||||
internal TextureCopy TextureCopy => BackgroundContextWorker.InBackground ? _backgroundTextureCopy : _textureCopy;
|
internal TextureCopy TextureCopy => BackgroundContextWorker.InBackground ? _backgroundTextureCopy : _textureCopy;
|
||||||
internal TextureCopyIncompatible TextureCopyIncompatible { get; }
|
internal TextureCopyIncompatible TextureCopyIncompatible { get; }
|
||||||
internal TextureCopyMS TextureCopyMS { get; }
|
internal TextureCopyMS TextureCopyMS { get; }
|
||||||
|
|
||||||
private Sync _sync;
|
private readonly Sync _sync;
|
||||||
|
|
||||||
public event EventHandler<ScreenCaptureImageInfo> ScreenCaptured;
|
public event EventHandler<ScreenCaptureImageInfo> ScreenCaptured;
|
||||||
|
|
||||||
@@ -222,9 +222,9 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
|
|
||||||
private void PrintGpuInformation()
|
private void PrintGpuInformation()
|
||||||
{
|
{
|
||||||
GpuVendor = GL.GetString(StringName.Vendor);
|
GpuVendor = GL.GetString(StringName.Vendor);
|
||||||
GpuRenderer = GL.GetString(StringName.Renderer);
|
GpuRenderer = GL.GetString(StringName.Renderer);
|
||||||
GpuVersion = GL.GetString(StringName.Version);
|
GpuVersion = GL.GetString(StringName.Version);
|
||||||
|
|
||||||
Logger.Notice.Print(LogClass.Gpu, $"{GpuVendor} {GpuRenderer} ({GpuVersion})");
|
Logger.Notice.Print(LogClass.Gpu, $"{GpuVendor} {GpuRenderer} ({GpuVersion})");
|
||||||
}
|
}
|
||||||
|
@@ -11,10 +11,10 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
{
|
{
|
||||||
class PersistentBuffers : IDisposable
|
class PersistentBuffers : IDisposable
|
||||||
{
|
{
|
||||||
private PersistentBuffer _main = new PersistentBuffer();
|
private readonly PersistentBuffer _main = new();
|
||||||
private PersistentBuffer _background = new PersistentBuffer();
|
private readonly PersistentBuffer _background = new();
|
||||||
|
|
||||||
private Dictionary<BufferHandle, IntPtr> _maps = new Dictionary<BufferHandle, IntPtr>();
|
private readonly Dictionary<BufferHandle, IntPtr> _maps = new();
|
||||||
|
|
||||||
public PersistentBuffer Default => BackgroundContextWorker.InBackground ? _background : _main;
|
public PersistentBuffer Default => BackgroundContextWorker.InBackground ? _background : _main;
|
||||||
|
|
||||||
@@ -91,7 +91,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
return _dataMap;
|
return _dataMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Sync()
|
private static void Sync()
|
||||||
{
|
{
|
||||||
GL.MemoryBarrier(MemoryBarrierFlags.ClientMappedBufferBarrierBit);
|
GL.MemoryBarrier(MemoryBarrierFlags.ClientMappedBufferBarrierBit);
|
||||||
|
|
||||||
@@ -133,7 +133,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
|
|
||||||
Sync();
|
Sync();
|
||||||
|
|
||||||
return new ReadOnlySpan<byte>(_bufferMap.ToPointer(), size).Slice(offset);
|
return new ReadOnlySpan<byte>(_bufferMap.ToPointer(), size)[offset..];
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe ReadOnlySpan<byte> GetBufferData(BufferHandle buffer, int offset, int size)
|
public unsafe ReadOnlySpan<byte> GetBufferData(BufferHandle buffer, int offset, int size)
|
||||||
|
@@ -44,11 +44,11 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
|
|
||||||
private CounterQueueEvent _activeConditionalRender;
|
private CounterQueueEvent _activeConditionalRender;
|
||||||
|
|
||||||
private Vector4<int>[] _fpIsBgra = new Vector4<int>[SupportBuffer.FragmentIsBgraCount];
|
private readonly Vector4<int>[] _fpIsBgra = new Vector4<int>[SupportBuffer.FragmentIsBgraCount];
|
||||||
private Vector4<float>[] _renderScale = new Vector4<float>[73];
|
private readonly Vector4<float>[] _renderScale = new Vector4<float>[73];
|
||||||
private int _fragmentScaleCount;
|
private int _fragmentScaleCount;
|
||||||
|
|
||||||
private (TextureBase, Format)[] _images;
|
private readonly (TextureBase, Format)[] _images;
|
||||||
private TextureBase _unit0Texture;
|
private TextureBase _unit0Texture;
|
||||||
private Sampler _unit0Sampler;
|
private Sampler _unit0Sampler;
|
||||||
|
|
||||||
@@ -260,7 +260,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
PostDraw();
|
PostDraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawQuadsImpl(
|
private static void DrawQuadsImpl(
|
||||||
int vertexCount,
|
int vertexCount,
|
||||||
int instanceCount,
|
int instanceCount,
|
||||||
int firstVertex,
|
int firstVertex,
|
||||||
@@ -285,7 +285,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
quadsCount);
|
quadsCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawQuadStripImpl(
|
private static void DrawQuadStripImpl(
|
||||||
int vertexCount,
|
int vertexCount,
|
||||||
int instanceCount,
|
int instanceCount,
|
||||||
int firstVertex,
|
int firstVertex,
|
||||||
@@ -366,8 +366,12 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
|
|
||||||
switch (_elementsType)
|
switch (_elementsType)
|
||||||
{
|
{
|
||||||
case DrawElementsType.UnsignedShort: indexElemSize = 2; break;
|
case DrawElementsType.UnsignedShort:
|
||||||
case DrawElementsType.UnsignedInt: indexElemSize = 4; break;
|
indexElemSize = 2;
|
||||||
|
break;
|
||||||
|
case DrawElementsType.UnsignedInt:
|
||||||
|
indexElemSize = 4;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
IntPtr indexBaseOffset = _indexBaseOffset + firstIndex * indexElemSize;
|
IntPtr indexBaseOffset = _indexBaseOffset + firstIndex * indexElemSize;
|
||||||
@@ -1471,7 +1475,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
GL.MemoryBarrier(MemoryBarrierFlags.TextureFetchBarrierBit);
|
GL.MemoryBarrier(MemoryBarrierFlags.TextureFetchBarrierBit);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetBuffers(ReadOnlySpan<BufferAssignment> buffers, bool isStorage)
|
private static void SetBuffers(ReadOnlySpan<BufferAssignment> buffers, bool isStorage)
|
||||||
{
|
{
|
||||||
BufferRangeTarget target = isStorage ? BufferRangeTarget.ShaderStorageBuffer : BufferRangeTarget.UniformBuffer;
|
BufferRangeTarget target = isStorage ? BufferRangeTarget.ShaderStorageBuffer : BufferRangeTarget.UniformBuffer;
|
||||||
|
|
||||||
@@ -1701,11 +1705,9 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
|
|
||||||
public bool TryHostConditionalRendering(ICounterEvent value, ulong compare, bool isEqual)
|
public bool TryHostConditionalRendering(ICounterEvent value, ulong compare, bool isEqual)
|
||||||
{
|
{
|
||||||
if (value is CounterQueueEvent)
|
// Compare an event and a constant value.
|
||||||
|
if (value is CounterQueueEvent evt)
|
||||||
{
|
{
|
||||||
// Compare an event and a constant value.
|
|
||||||
CounterQueueEvent evt = (CounterQueueEvent)value;
|
|
||||||
|
|
||||||
// Easy host conditional rendering when the check matches what GL can do:
|
// Easy host conditional rendering when the check matches what GL can do:
|
||||||
// - Event is of type samples passed.
|
// - Event is of type samples passed.
|
||||||
// - Result is not a combination of multiple queries.
|
// - Result is not a combination of multiple queries.
|
||||||
|
@@ -123,7 +123,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
|
|
||||||
if (log.Length > MaxShaderLogLength)
|
if (log.Length > MaxShaderLogLength)
|
||||||
{
|
{
|
||||||
log = log.Substring(0, MaxShaderLogLength) + "...";
|
log = log[..MaxShaderLogLength] + "...";
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.Warning?.Print(LogClass.Gpu, $"Shader linking failed: \n{log}");
|
Logger.Warning?.Print(LogClass.Gpu, $"Shader linking failed: \n{log}");
|
||||||
|
@@ -14,9 +14,9 @@ namespace Ryujinx.Graphics.OpenGL.Queries
|
|||||||
|
|
||||||
public int Query { get; }
|
public int Query { get; }
|
||||||
|
|
||||||
private int _buffer;
|
private readonly int _buffer;
|
||||||
private IntPtr _bufferMap;
|
private readonly IntPtr _bufferMap;
|
||||||
private QueryTarget _type;
|
private readonly QueryTarget _type;
|
||||||
|
|
||||||
public BufferedQuery(QueryTarget type)
|
public BufferedQuery(QueryTarget type)
|
||||||
{
|
{
|
||||||
@@ -64,7 +64,7 @@ namespace Ryujinx.Graphics.OpenGL.Queries
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool WaitingForValue(long data)
|
private static bool WaitingForValue(long data)
|
||||||
{
|
{
|
||||||
return data == DefaultValue ||
|
return data == DefaultValue ||
|
||||||
((ulong)data & HighMask) == (unchecked((ulong)DefaultValue) & HighMask);
|
((ulong)data & HighMask) == (unchecked((ulong)DefaultValue) & HighMask);
|
||||||
|
@@ -15,7 +15,7 @@ namespace Ryujinx.Graphics.OpenGL.Queries
|
|||||||
|
|
||||||
private readonly Pipeline _pipeline;
|
private readonly Pipeline _pipeline;
|
||||||
|
|
||||||
private Queue<CounterQueueEvent> _events = new Queue<CounterQueueEvent>();
|
private readonly Queue<CounterQueueEvent> _events = new();
|
||||||
private CounterQueueEvent _current;
|
private CounterQueueEvent _current;
|
||||||
|
|
||||||
private ulong _accumulatedCounter;
|
private ulong _accumulatedCounter;
|
||||||
@@ -23,12 +23,12 @@ namespace Ryujinx.Graphics.OpenGL.Queries
|
|||||||
|
|
||||||
private readonly object _lock = new();
|
private readonly object _lock = new();
|
||||||
|
|
||||||
private Queue<BufferedQuery> _queryPool;
|
private readonly Queue<BufferedQuery> _queryPool;
|
||||||
private AutoResetEvent _queuedEvent = new AutoResetEvent(false);
|
private readonly AutoResetEvent _queuedEvent = new(false);
|
||||||
private AutoResetEvent _wakeSignal = new AutoResetEvent(false);
|
private readonly AutoResetEvent _wakeSignal = new(false);
|
||||||
private AutoResetEvent _eventConsumed = new AutoResetEvent(false);
|
private readonly AutoResetEvent _eventConsumed = new(false);
|
||||||
|
|
||||||
private Thread _consumerThread;
|
private readonly Thread _consumerThread;
|
||||||
|
|
||||||
internal CounterQueue(Pipeline pipeline, CounterType type)
|
internal CounterQueue(Pipeline pipeline, CounterType type)
|
||||||
{
|
{
|
||||||
@@ -148,14 +148,13 @@ namespace Ryujinx.Graphics.OpenGL.Queries
|
|||||||
|
|
||||||
private static QueryTarget GetTarget(CounterType type)
|
private static QueryTarget GetTarget(CounterType type)
|
||||||
{
|
{
|
||||||
switch (type)
|
return type switch
|
||||||
{
|
{
|
||||||
case CounterType.SamplesPassed: return QueryTarget.SamplesPassed;
|
CounterType.SamplesPassed => QueryTarget.SamplesPassed,
|
||||||
case CounterType.PrimitivesGenerated: return QueryTarget.PrimitivesGenerated;
|
CounterType.PrimitivesGenerated => QueryTarget.PrimitivesGenerated,
|
||||||
case CounterType.TransformFeedbackPrimitivesWritten: return QueryTarget.TransformFeedbackPrimitivesWritten;
|
CounterType.TransformFeedbackPrimitivesWritten => QueryTarget.TransformFeedbackPrimitivesWritten,
|
||||||
}
|
_ => QueryTarget.SamplesPassed,
|
||||||
|
};
|
||||||
return QueryTarget.SamplesPassed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Flush(bool blocking)
|
public void Flush(bool blocking)
|
||||||
|
@@ -18,8 +18,8 @@ namespace Ryujinx.Graphics.OpenGL.Queries
|
|||||||
|
|
||||||
public ulong DrawIndex { get; }
|
public ulong DrawIndex { get; }
|
||||||
|
|
||||||
private CounterQueue _queue;
|
private readonly CounterQueue _queue;
|
||||||
private BufferedQuery _counter;
|
private readonly BufferedQuery _counter;
|
||||||
|
|
||||||
private bool _hostAccessReserved = false;
|
private bool _hostAccessReserved = false;
|
||||||
private int _refCount = 1; // Starts with a reference from the counter queue.
|
private int _refCount = 1; // Starts with a reference from the counter queue.
|
||||||
|
@@ -5,7 +5,7 @@ namespace Ryujinx.Graphics.OpenGL.Queries
|
|||||||
{
|
{
|
||||||
class Counters : IDisposable
|
class Counters : IDisposable
|
||||||
{
|
{
|
||||||
private CounterQueue[] _counterQueues;
|
private readonly CounterQueue[] _counterQueues;
|
||||||
|
|
||||||
public Counters()
|
public Counters()
|
||||||
{
|
{
|
||||||
|
@@ -21,7 +21,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
private const int DisposedLiveFrames = 2;
|
private const int DisposedLiveFrames = 2;
|
||||||
|
|
||||||
private readonly object _lock = new();
|
private readonly object _lock = new();
|
||||||
private readonly Dictionary<TextureCreateInfo, List<DisposedTexture>> _textures = new Dictionary<TextureCreateInfo, List<DisposedTexture>>();
|
private readonly Dictionary<TextureCreateInfo, List<DisposedTexture>> _textures = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Add a texture that is not being used anymore to the resource pool to be used later.
|
/// Add a texture that is not being used anymore to the resource pool to be used later.
|
||||||
@@ -32,8 +32,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
{
|
{
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
List<DisposedTexture> list;
|
if (!_textures.TryGetValue(view.Info, out List<DisposedTexture> list))
|
||||||
if (!_textures.TryGetValue(view.Info, out list))
|
|
||||||
{
|
{
|
||||||
list = new List<DisposedTexture>();
|
list = new List<DisposedTexture>();
|
||||||
_textures.Add(view.Info, list);
|
_textures.Add(view.Info, list);
|
||||||
@@ -59,8 +58,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
{
|
{
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
List<DisposedTexture> list;
|
if (!_textures.TryGetValue(info, out List<DisposedTexture> list))
|
||||||
if (!_textures.TryGetValue(info, out list))
|
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@@ -15,13 +15,13 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ulong _firstHandle = 0;
|
private ulong _firstHandle = 0;
|
||||||
private ClientWaitSyncFlags _syncFlags => HwCapabilities.RequiresSyncFlush ? ClientWaitSyncFlags.None : ClientWaitSyncFlags.SyncFlushCommandsBit;
|
private static ClientWaitSyncFlags SyncFlags => HwCapabilities.RequiresSyncFlush ? ClientWaitSyncFlags.None : ClientWaitSyncFlags.SyncFlushCommandsBit;
|
||||||
|
|
||||||
private List<SyncHandle> _handles = new List<SyncHandle>();
|
private readonly List<SyncHandle> _handles = new();
|
||||||
|
|
||||||
public void Create(ulong id)
|
public void Create(ulong id)
|
||||||
{
|
{
|
||||||
SyncHandle handle = new SyncHandle
|
SyncHandle handle = new()
|
||||||
{
|
{
|
||||||
ID = id,
|
ID = id,
|
||||||
Handle = GL.FenceSync(SyncCondition.SyncGpuCommandsComplete, WaitSyncFlags.None)
|
Handle = GL.FenceSync(SyncCondition.SyncGpuCommandsComplete, WaitSyncFlags.None)
|
||||||
@@ -57,7 +57,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
|
|
||||||
if (handle.ID > lastHandle)
|
if (handle.ID > lastHandle)
|
||||||
{
|
{
|
||||||
WaitSyncStatus syncResult = GL.ClientWaitSync(handle.Handle, _syncFlags, 0);
|
WaitSyncStatus syncResult = GL.ClientWaitSync(handle.Handle, SyncFlags, 0);
|
||||||
|
|
||||||
if (syncResult == WaitSyncStatus.AlreadySignaled)
|
if (syncResult == WaitSyncStatus.AlreadySignaled)
|
||||||
{
|
{
|
||||||
@@ -101,7 +101,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
WaitSyncStatus syncResult = GL.ClientWaitSync(result.Handle, _syncFlags, 1000000000);
|
WaitSyncStatus syncResult = GL.ClientWaitSync(result.Handle, SyncFlags, 1000000000);
|
||||||
|
|
||||||
if (syncResult == WaitSyncStatus.TimeoutExpired)
|
if (syncResult == WaitSyncStatus.TimeoutExpired)
|
||||||
{
|
{
|
||||||
@@ -123,9 +123,12 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
first = _handles.FirstOrDefault();
|
first = _handles.FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (first == null) break;
|
if (first == null)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
WaitSyncStatus syncResult = GL.ClientWaitSync(first.Handle, _syncFlags, 0);
|
WaitSyncStatus syncResult = GL.ClientWaitSync(first.Handle, SyncFlags, 0);
|
||||||
|
|
||||||
if (syncResult == WaitSyncStatus.AlreadySignaled)
|
if (syncResult == WaitSyncStatus.AlreadySignaled)
|
||||||
{
|
{
|
||||||
@@ -140,7 +143,8 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
first.Handle = IntPtr.Zero;
|
first.Handle = IntPtr.Zero;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// This sync handle and any following have not been reached yet.
|
// This sync handle and any following have not been reached yet.
|
||||||
break;
|
break;
|
||||||
|
@@ -20,7 +20,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
private uint _vertexBuffersLimited;
|
private uint _vertexBuffersLimited;
|
||||||
|
|
||||||
private BufferRange _indexBuffer;
|
private BufferRange _indexBuffer;
|
||||||
private BufferHandle _tempIndexBuffer;
|
private readonly BufferHandle _tempIndexBuffer;
|
||||||
private BufferHandle _tempVertexBuffer;
|
private BufferHandle _tempVertexBuffer;
|
||||||
private int _tempVertexBufferSize;
|
private int _tempVertexBufferSize;
|
||||||
|
|
||||||
@@ -102,7 +102,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
}
|
}
|
||||||
|
|
||||||
int offset = attrib.Offset;
|
int offset = attrib.Offset;
|
||||||
int size = fmtInfo.Components;
|
int size = fmtInfo.Components;
|
||||||
|
|
||||||
bool isFloat = fmtInfo.PixelType == PixelType.Float ||
|
bool isFloat = fmtInfo.PixelType == PixelType.Float ||
|
||||||
fmtInfo.PixelType == PixelType.HalfFloat;
|
fmtInfo.PixelType == PixelType.HalfFloat;
|
||||||
|
@@ -375,7 +375,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
if (_scalingFilter is not FsrScalingFilter)
|
if (_scalingFilter is not FsrScalingFilter)
|
||||||
{
|
{
|
||||||
_scalingFilter?.Dispose();
|
_scalingFilter?.Dispose();
|
||||||
_scalingFilter = new FsrScalingFilter(_renderer, _antiAliasing);
|
_scalingFilter = new FsrScalingFilter(_renderer);
|
||||||
}
|
}
|
||||||
_isLinear = false;
|
_isLinear = false;
|
||||||
_scalingFilter.Level = _scalingFilterLevel;
|
_scalingFilter.Level = _scalingFilterLevel;
|
||||||
|
@@ -9,6 +9,6 @@ namespace Ryujinx.Graphics.Shader
|
|||||||
Greater,
|
Greater,
|
||||||
NotEqual,
|
NotEqual,
|
||||||
GreaterOrEqual,
|
GreaterOrEqual,
|
||||||
Always
|
Always,
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -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,7 +31,7 @@ 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}\"."),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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)
|
||||||
|
@@ -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";
|
||||||
|
@@ -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();
|
||||||
|
@@ -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";
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
@@ -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.");
|
||||||
}
|
}
|
||||||
|
@@ -10,8 +10,8 @@ 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -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),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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.");
|
||||||
}
|
}
|
||||||
|
@@ -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);
|
||||||
|
@@ -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));
|
||||||
|
@@ -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];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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}\"."),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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)));
|
||||||
|
@@ -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,10 +74,8 @@ 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;
|
||||||
|
@@ -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; }
|
||||||
|
@@ -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);
|
||||||
|
@@ -92,7 +92,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||||||
pushOpInfo.Consumers.Add(rightBlock, local);
|
pushOpInfo.Consumers.Add(rightBlock, local);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ((ulong key, SyncTarget value) in SyncTargets)
|
foreach ((ulong key, SyncTarget value) in SyncTargets)
|
||||||
{
|
{
|
||||||
rightBlock.SyncTargets.Add(key, value);
|
rightBlock.SyncTargets.Add(key, value);
|
||||||
}
|
}
|
||||||
@@ -148,7 +148,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||||||
{
|
{
|
||||||
if (OpCodes.Count != 0)
|
if (OpCodes.Count != 0)
|
||||||
{
|
{
|
||||||
return OpCodes[OpCodes.Count - 1];
|
return OpCodes[^1];
|
||||||
}
|
}
|
||||||
|
|
||||||
return default;
|
return default;
|
||||||
|
@@ -3,7 +3,6 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Shader.Decoders
|
namespace Ryujinx.Graphics.Shader.Decoders
|
||||||
@@ -12,8 +11,8 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||||||
{
|
{
|
||||||
public static DecodedProgram Decode(ShaderConfig config, ulong startAddress)
|
public static DecodedProgram Decode(ShaderConfig config, ulong startAddress)
|
||||||
{
|
{
|
||||||
Queue<DecodedFunction> functionsQueue = new Queue<DecodedFunction>();
|
Queue<DecodedFunction> functionsQueue = new();
|
||||||
Dictionary<ulong, DecodedFunction> functionsVisited = new Dictionary<ulong, DecodedFunction>();
|
Dictionary<ulong, DecodedFunction> functionsVisited = new();
|
||||||
|
|
||||||
DecodedFunction EnqueueFunction(ulong address)
|
DecodedFunction EnqueueFunction(ulong address)
|
||||||
{
|
{
|
||||||
@@ -30,9 +29,9 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||||||
|
|
||||||
while (functionsQueue.TryDequeue(out DecodedFunction currentFunction))
|
while (functionsQueue.TryDequeue(out DecodedFunction currentFunction))
|
||||||
{
|
{
|
||||||
List<Block> blocks = new List<Block>();
|
List<Block> blocks = new();
|
||||||
Queue<Block> workQueue = new Queue<Block>();
|
Queue<Block> workQueue = new();
|
||||||
Dictionary<ulong, Block> visited = new Dictionary<ulong, Block>();
|
Dictionary<ulong, Block> visited = new();
|
||||||
|
|
||||||
Block GetBlock(ulong blkAddress)
|
Block GetBlock(ulong blkAddress)
|
||||||
{
|
{
|
||||||
@@ -168,7 +167,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||||||
{
|
{
|
||||||
index = 0;
|
index = 0;
|
||||||
|
|
||||||
int left = 0;
|
int left = 0;
|
||||||
int right = blocks.Count - 1;
|
int right = blocks.Count - 1;
|
||||||
|
|
||||||
while (left <= right)
|
while (left <= right)
|
||||||
@@ -273,12 +272,12 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||||||
int offset;
|
int offset;
|
||||||
int count = 1;
|
int count = 1;
|
||||||
bool isStore = false;
|
bool isStore = false;
|
||||||
bool indexed = false;
|
bool indexed;
|
||||||
bool perPatch = false;
|
bool perPatch = false;
|
||||||
|
|
||||||
if (name == InstName.Ast)
|
if (name == InstName.Ast)
|
||||||
{
|
{
|
||||||
InstAst opAst = new InstAst(opCode);
|
InstAst opAst = new(opCode);
|
||||||
count = (int)opAst.AlSize + 1;
|
count = (int)opAst.AlSize + 1;
|
||||||
offset = opAst.Imm11;
|
offset = opAst.Imm11;
|
||||||
indexed = opAst.Phys;
|
indexed = opAst.Phys;
|
||||||
@@ -287,7 +286,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||||||
}
|
}
|
||||||
else if (name == InstName.Ald)
|
else if (name == InstName.Ald)
|
||||||
{
|
{
|
||||||
InstAld opAld = new InstAld(opCode);
|
InstAld opAld = new(opCode);
|
||||||
count = (int)opAld.AlSize + 1;
|
count = (int)opAld.AlSize + 1;
|
||||||
offset = opAld.Imm11;
|
offset = opAld.Imm11;
|
||||||
indexed = opAld.Phys;
|
indexed = opAld.Phys;
|
||||||
@@ -296,7 +295,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||||||
}
|
}
|
||||||
else /* if (name == InstName.Ipa) */
|
else /* if (name == InstName.Ipa) */
|
||||||
{
|
{
|
||||||
InstIpa opIpa = new InstIpa(opCode);
|
InstIpa opIpa = new(opCode);
|
||||||
offset = opIpa.Imm10;
|
offset = opIpa.Imm10;
|
||||||
indexed = opIpa.Idx;
|
indexed = opIpa.Idx;
|
||||||
}
|
}
|
||||||
@@ -370,7 +369,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||||||
|
|
||||||
private static bool IsUnconditional(ref InstOp op)
|
private static bool IsUnconditional(ref InstOp op)
|
||||||
{
|
{
|
||||||
InstConditional condOp = new InstConditional(op.RawOpCode);
|
InstConditional condOp = new(op.RawOpCode);
|
||||||
|
|
||||||
if ((op.Name == InstName.Bra || op.Name == InstName.Exit) && condOp.Ccc != Ccc.T)
|
if ((op.Name == InstName.Bra || op.Name == InstName.Exit) && condOp.Ccc != Ccc.T)
|
||||||
{
|
{
|
||||||
@@ -391,9 +390,9 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||||||
|
|
||||||
if (lastOp.Name == InstName.Brx && block.Successors.Count == (hasNext ? 1 : 0))
|
if (lastOp.Name == InstName.Brx && block.Successors.Count == (hasNext ? 1 : 0))
|
||||||
{
|
{
|
||||||
HashSet<ulong> visited = new HashSet<ulong>();
|
HashSet<ulong> visited = new();
|
||||||
|
|
||||||
InstBrx opBrx = new InstBrx(lastOp.RawOpCode);
|
InstBrx opBrx = new(lastOp.RawOpCode);
|
||||||
ulong baseOffset = lastOp.GetAbsoluteAddress();
|
ulong baseOffset = lastOp.GetAbsoluteAddress();
|
||||||
|
|
||||||
// An indirect branch could go anywhere,
|
// An indirect branch could go anywhere,
|
||||||
@@ -437,7 +436,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||||||
// On a successful match, "BaseOffset" is the offset in bytes where the jump offsets are
|
// On a successful match, "BaseOffset" is the offset in bytes where the jump offsets are
|
||||||
// located on the constant buffer, and "UpperBound" is the total number of offsets for the BRX, minus 1.
|
// located on the constant buffer, and "UpperBound" is the total number of offsets for the BRX, minus 1.
|
||||||
|
|
||||||
HashSet<Block> visited = new HashSet<Block>();
|
HashSet<Block> visited = new();
|
||||||
|
|
||||||
var ldcLocation = FindFirstRegWrite(visited, new BlockLocation(block, block.OpCodes.Count - 1), brxReg);
|
var ldcLocation = FindFirstRegWrite(visited, new BlockLocation(block, block.OpCodes.Count - 1), brxReg);
|
||||||
if (ldcLocation.Block == null || ldcLocation.Block.OpCodes[ldcLocation.Index].Name != InstName.Ldc)
|
if (ldcLocation.Block == null || ldcLocation.Block.OpCodes[ldcLocation.Index].Name != InstName.Ldc)
|
||||||
@@ -507,7 +506,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||||||
|
|
||||||
private static BlockLocation FindFirstRegWrite(HashSet<Block> visited, BlockLocation location, int regIndex)
|
private static BlockLocation FindFirstRegWrite(HashSet<Block> visited, BlockLocation location, int regIndex)
|
||||||
{
|
{
|
||||||
Queue<BlockLocation> toVisit = new Queue<BlockLocation>();
|
Queue<BlockLocation> toVisit = new();
|
||||||
toVisit.Enqueue(location);
|
toVisit.Enqueue(location);
|
||||||
visited.Add(location.Block);
|
visited.Add(location.Block);
|
||||||
|
|
||||||
@@ -554,10 +553,10 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||||||
{
|
{
|
||||||
Brk,
|
Brk,
|
||||||
Cont,
|
Cont,
|
||||||
Sync
|
Sync,
|
||||||
}
|
}
|
||||||
|
|
||||||
private struct PathBlockState
|
private readonly struct PathBlockState
|
||||||
{
|
{
|
||||||
public Block Block { get; }
|
public Block Block { get; }
|
||||||
|
|
||||||
@@ -565,37 +564,37 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||||||
{
|
{
|
||||||
None,
|
None,
|
||||||
PopPushOp,
|
PopPushOp,
|
||||||
PushBranchOp
|
PushBranchOp,
|
||||||
}
|
}
|
||||||
|
|
||||||
private RestoreType _restoreType;
|
private readonly RestoreType _restoreType;
|
||||||
|
|
||||||
private ulong _restoreValue;
|
private readonly ulong _restoreValue;
|
||||||
private MergeType _restoreMergeType;
|
private readonly MergeType _restoreMergeType;
|
||||||
|
|
||||||
public bool ReturningFromVisit => _restoreType != RestoreType.None;
|
public bool ReturningFromVisit => _restoreType != RestoreType.None;
|
||||||
|
|
||||||
public PathBlockState(Block block)
|
public PathBlockState(Block block)
|
||||||
{
|
{
|
||||||
Block = block;
|
Block = block;
|
||||||
_restoreType = RestoreType.None;
|
_restoreType = RestoreType.None;
|
||||||
_restoreValue = 0;
|
_restoreValue = 0;
|
||||||
_restoreMergeType = default;
|
_restoreMergeType = default;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PathBlockState(int oldStackSize)
|
public PathBlockState(int oldStackSize)
|
||||||
{
|
{
|
||||||
Block = null;
|
Block = null;
|
||||||
_restoreType = RestoreType.PopPushOp;
|
_restoreType = RestoreType.PopPushOp;
|
||||||
_restoreValue = (ulong)oldStackSize;
|
_restoreValue = (ulong)oldStackSize;
|
||||||
_restoreMergeType = default;
|
_restoreMergeType = default;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PathBlockState(ulong syncAddress, MergeType mergeType)
|
public PathBlockState(ulong syncAddress, MergeType mergeType)
|
||||||
{
|
{
|
||||||
Block = null;
|
Block = null;
|
||||||
_restoreType = RestoreType.PushBranchOp;
|
_restoreType = RestoreType.PushBranchOp;
|
||||||
_restoreValue = syncAddress;
|
_restoreValue = syncAddress;
|
||||||
_restoreMergeType = mergeType;
|
_restoreMergeType = mergeType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -622,9 +621,9 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||||||
|
|
||||||
Block target = blocks[pushOp.GetAbsoluteAddress()];
|
Block target = blocks[pushOp.GetAbsoluteAddress()];
|
||||||
|
|
||||||
Stack<PathBlockState> workQueue = new Stack<PathBlockState>();
|
Stack<PathBlockState> workQueue = new();
|
||||||
HashSet<Block> visited = new HashSet<Block>();
|
HashSet<Block> visited = new();
|
||||||
Stack<(ulong, MergeType)> branchStack = new Stack<(ulong, MergeType)>();
|
Stack<(ulong, MergeType)> branchStack = new();
|
||||||
|
|
||||||
void Push(PathBlockState pbs)
|
void Push(PathBlockState pbs)
|
||||||
{
|
{
|
||||||
@@ -759,7 +758,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||||||
{
|
{
|
||||||
InstName.Pbk => MergeType.Brk,
|
InstName.Pbk => MergeType.Brk,
|
||||||
InstName.Pcnt => MergeType.Cont,
|
InstName.Pcnt => MergeType.Cont,
|
||||||
_ => MergeType.Sync
|
_ => MergeType.Sync,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -769,7 +768,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||||||
{
|
{
|
||||||
InstName.Brk => MergeType.Brk,
|
InstName.Brk => MergeType.Brk,
|
||||||
InstName.Cont => MergeType.Cont,
|
InstName.Cont => MergeType.Cont,
|
||||||
_ => MergeType.Sync
|
_ => MergeType.Sync,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user