Compare commits

...

15 Commits

Author SHA1 Message Date
Nicholas Rodine
eb6430f103 Skipped over the last "Count" key explicitly, instead of relying on an exception. (#3595) 2022-08-18 02:00:27 +02:00
Nicholas Rodine
80a879cb44 Fix SpirV parse failure (#3597)
* Added .ToString overrides, to help diagnose and debug SpirV generated code.

* Added Spirv to team shared dictionary, so the word will not show up as a warning.

* Fixed bug where we were creating invalid constants (bool 0i and float 0i)

* Update Ryujinx.Graphics.Shader/CodeGen/Spirv/CodeGenContext.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Update Spv.Generator/Instruction.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* Adjusted spacing to match style of the rest of the code.

* Added handler for FP64(double) as well, for undefined aggregate types.

* Made the operand labels a static dictionary, to avoid re-allocation on each call.
Replaced Contains/Get with a TryGetValue, to reduce the number of dictionary lookups.

* Added newline between AllOperands and ToString().

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2022-08-18 01:49:43 +02:00
Nicholas Rodine
2197f41506 Removed extra semicolons. (#3594) 2022-08-17 09:05:15 +02:00
Emmanuel Hansen
c8f9292bab Avalonia - Couple fixes and improvements to vulkan (#3483)
* drop split devices, rebase

* add fallback to opengl if vulkan is not available

* addressed review

* ensure present image references are incremented and decremented when necessary

* allow changing vsync for vulkan

* fix screenshot on avalonia vulkan

* save favorite when toggled

* improve sync between popups

* use separate devices for each new window

* fix crash when closing window

* addressed review

* don't create the main window with immediate mode

* change skia vk delegate to method

* update vulkan throwonerror

* addressed review
2022-08-16 16:32:37 +00:00
gdkchan
0ec933a615 Vulkan: Add ETC2 texture formats (#3576) 2022-08-16 15:42:42 +02:00
Ac_K
2135b6a51a am: Stub SetWirelessPriorityMode, SetWirelessPriorityMode and GetHdcpAuthenticationState (#3535)
This PR some calls in `am` service:
- ISelfController: SetWirelessPriorityMode, SaveCurrentScreenshot (Partially checked by RE).
- ICommonStateGetter: GetHdcpAuthenticationState

Close #1831 and close #3527
2022-08-15 11:12:08 +00:00
mageven
00e35d9bf6 ControllerApplet: Override player counts when SingleMode is set (#3571) 2022-08-15 09:46:08 +02:00
merry
6dfb6ccf8c PreAllocator: Check if instruction supports a Vex prefix in IsVexSameOperandDestSrc1 (#3587) 2022-08-14 17:35:08 -03:00
gdkchan
e87e8b012c Fix texture bindings using wrong sampler pool in some cases (#3583) 2022-08-14 14:00:30 -03:00
gdkchan
e8f1ca8427 OpenGL: Limit vertex buffer range for non-indexed draws (#3542)
* Limit vertex buffer range for non-indexed draws

* Fix typo
2022-08-11 20:21:56 -03:00
gdkchan
ad47bd2d4e Fix blend with RGBX color formats (#3553) 2022-08-11 18:23:25 -03:00
gdkchan
a5ff0024fb Rename ToSpan to AsSpan (#3556) 2022-08-11 18:07:37 -03:00
txorion
f9661a54d2 add Japanese translation to Avalonia UI (#3489)
* add Japanese translation to Avalonia UI

* translate language names

* fix raised in the review
2022-08-11 17:55:14 -03:00
gdkchan
66e7fdb871 OpenGL: Fix clears of unbound color targets (#3564) 2022-08-08 17:39:22 +00:00
gdkchan
2bb9b33da1 Implement Arm32 Sha256 and MRS Rd, CPSR instructions (#3544)
* Implement Arm32 Sha256 and MRS Rd, CPSR instructions

* Add tests using Arm64 outputs
2022-08-05 19:03:50 +02:00
107 changed files with 2275 additions and 902 deletions

View File

@@ -4,6 +4,11 @@ namespace ARMeilleure.CodeGen.X86
{ {
partial class Assembler partial class Assembler
{ {
public static bool SupportsVexPrefix(X86Instruction inst)
{
return _instTable[(int)inst].Flags.HasFlag(InstructionFlags.Vex);
}
private const int BadOp = 0; private const int BadOp = 0;
[Flags] [Flags]

View File

@@ -1297,11 +1297,15 @@ namespace ARMeilleure.CodeGen.X86
{ {
if (IsIntrinsic(operation.Instruction)) if (IsIntrinsic(operation.Instruction))
{ {
IntrinsicInfo info = IntrinsicTable.GetInfo(operation.Intrinsic);
bool hasVex = HardwareCapabilities.SupportsVexEncoding && Assembler.SupportsVexPrefix(info.Inst);
bool isUnary = operation.SourcesCount < 2; bool isUnary = operation.SourcesCount < 2;
bool hasVecDest = operation.Destination != default && operation.Destination.Type == OperandType.V128; bool hasVecDest = operation.Destination != default && operation.Destination.Type == OperandType.V128;
return !HardwareCapabilities.SupportsVexEncoding && !isUnary && hasVecDest; return !hasVex && !isUnary && hasVecDest;
} }
return false; return false;

View File

@@ -0,0 +1,16 @@
namespace ARMeilleure.Decoders
{
class OpCode32Mrs : OpCode32
{
public bool R { get; }
public int Rd { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32Mrs(inst, address, opCode);
public OpCode32Mrs(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
R = ((opCode >> 22) & 1) != 0;
Rd = (opCode >> 12) & 0xf;
}
}
}

View File

@@ -704,6 +704,7 @@ namespace ARMeilleure.Decoders
SetA32("<<<<00110100xxxxxxxxxxxxxxxxxxxx", InstName.Movt, InstEmit32.Movt, OpCode32AluImm16.Create); SetA32("<<<<00110100xxxxxxxxxxxxxxxxxxxx", InstName.Movt, InstEmit32.Movt, OpCode32AluImm16.Create);
SetA32("<<<<1110xxx1xxxxxxxx111xxxx1xxxx", InstName.Mrc, InstEmit32.Mrc, OpCode32System.Create); SetA32("<<<<1110xxx1xxxxxxxx111xxxx1xxxx", InstName.Mrc, InstEmit32.Mrc, OpCode32System.Create);
SetA32("<<<<11000101xxxxxxxx111xxxxxxxxx", InstName.Mrrc, InstEmit32.Mrrc, OpCode32System.Create); SetA32("<<<<11000101xxxxxxxx111xxxxxxxxx", InstName.Mrrc, InstEmit32.Mrrc, OpCode32System.Create);
SetA32("<<<<00010x001111xxxx000000000000", InstName.Mrs, InstEmit32.Mrs, OpCode32Mrs.Create);
SetA32("<<<<00010x10xxxx111100000000xxxx", InstName.Msr, InstEmit32.Msr, OpCode32MsrReg.Create); SetA32("<<<<00010x10xxxx111100000000xxxx", InstName.Msr, InstEmit32.Msr, OpCode32MsrReg.Create);
SetA32("<<<<0000000xxxxx0000xxxx1001xxxx", InstName.Mul, InstEmit32.Mul, OpCode32AluMla.Create); SetA32("<<<<0000000xxxxx0000xxxx1001xxxx", InstName.Mul, InstEmit32.Mul, OpCode32AluMla.Create);
SetA32("<<<<0011111x0000xxxxxxxxxxxxxxxx", InstName.Mvn, InstEmit32.Mvn, OpCode32AluImm.Create); SetA32("<<<<0011111x0000xxxxxxxxxxxxxxxx", InstName.Mvn, InstEmit32.Mvn, OpCode32AluImm.Create);
@@ -792,185 +793,189 @@ namespace ARMeilleure.Decoders
SetA32("<<<<01101111xxxxxxxxxx000111xxxx", InstName.Uxth, InstEmit32.Uxth, OpCode32AluUx.Create); SetA32("<<<<01101111xxxxxxxxxx000111xxxx", InstName.Uxth, InstEmit32.Uxth, OpCode32AluUx.Create);
// FP & SIMD // FP & SIMD
SetA32("111100111x110000xxx0001101x0xxx0", InstName.Aesd_V, InstEmit32.Aesd_V, OpCode32Simd.Create); SetA32("111100111x110000xxx0001101x0xxx0", InstName.Aesd_V, InstEmit32.Aesd_V, OpCode32Simd.Create);
SetA32("111100111x110000xxx0001100x0xxx0", InstName.Aese_V, InstEmit32.Aese_V, OpCode32Simd.Create); SetA32("111100111x110000xxx0001100x0xxx0", InstName.Aese_V, InstEmit32.Aese_V, OpCode32Simd.Create);
SetA32("111100111x110000xxx0001111x0xxx0", InstName.Aesimc_V, InstEmit32.Aesimc_V, OpCode32Simd.Create); SetA32("111100111x110000xxx0001111x0xxx0", InstName.Aesimc_V, InstEmit32.Aesimc_V, OpCode32Simd.Create);
SetA32("111100111x110000xxx0001110x0xxx0", InstName.Aesmc_V, InstEmit32.Aesmc_V, OpCode32Simd.Create); SetA32("111100111x110000xxx0001110x0xxx0", InstName.Aesmc_V, InstEmit32.Aesmc_V, OpCode32Simd.Create);
SetA32("1111001x0x<<xxxxxxxx0111xxx0xxxx", InstName.Vabd, InstEmit32.Vabd_I, OpCode32SimdReg.Create); SetA32("111100110x00xxx0xxx01100x1x0xxx0", InstName.Sha256h_V, InstEmit32.Sha256h_V, OpCode32SimdReg.Create);
SetA32("1111001x1x<<xxxxxxxx0111x0x0xxxx", InstName.Vabdl, InstEmit32.Vabdl_I, OpCode32SimdRegLong.Create); SetA32("111100110x01xxx0xxx01100x1x0xxx0", InstName.Sha256h2_V, InstEmit32.Sha256h2_V, OpCode32SimdReg.Create);
SetA32("<<<<11101x110000xxxx101x11x0xxxx", InstName.Vabs, InstEmit32.Vabs_S, OpCode32SimdS.Create); SetA32("111100111x111010xxx0001111x0xxx0", InstName.Sha256su0_V, InstEmit32.Sha256su0_V, OpCode32Simd.Create);
SetA32("111100111x11<<01xxxx00110xx0xxxx", InstName.Vabs, InstEmit32.Vabs_V, OpCode32SimdCmpZ.Create); SetA32("111100110x10xxx0xxx01100x1x0xxx0", InstName.Sha256su1_V, InstEmit32.Sha256su1_V, OpCode32SimdReg.Create);
SetA32("111100111x111001xxxx01110xx0xxxx", InstName.Vabs, InstEmit32.Vabs_V, OpCode32SimdCmpZ.Create); SetA32("1111001x0x<<xxxxxxxx0111xxx0xxxx", InstName.Vabd, InstEmit32.Vabd_I, OpCode32SimdReg.Create);
SetA32("111100100xxxxxxxxxxx1000xxx0xxxx", InstName.Vadd, InstEmit32.Vadd_I, OpCode32SimdReg.Create); SetA32("1111001x1x<<xxxxxxxx0111x0x0xxxx", InstName.Vabdl, InstEmit32.Vabdl_I, OpCode32SimdRegLong.Create);
SetA32("<<<<11100x11xxxxxxxx101xx0x0xxxx", InstName.Vadd, InstEmit32.Vadd_S, OpCode32SimdRegS.Create); SetA32("<<<<11101x110000xxxx101x11x0xxxx", InstName.Vabs, InstEmit32.Vabs_S, OpCode32SimdS.Create);
SetA32("111100100x00xxxxxxxx1101xxx0xxxx", InstName.Vadd, InstEmit32.Vadd_V, OpCode32SimdReg.Create); SetA32("111100111x11<<01xxxx00110xx0xxxx", InstName.Vabs, InstEmit32.Vabs_V, OpCode32SimdCmpZ.Create);
SetA32("1111001x1x<<xxxxxxxx0000x0x0xxxx", InstName.Vaddl, InstEmit32.Vaddl_I, OpCode32SimdRegLong.Create); SetA32("111100111x111001xxxx01110xx0xxxx", InstName.Vabs, InstEmit32.Vabs_V, OpCode32SimdCmpZ.Create);
SetA32("1111001x1x<<xxxxxxxx0001x0x0xxxx", InstName.Vaddw, InstEmit32.Vaddw_I, OpCode32SimdRegWide.Create); SetA32("111100100xxxxxxxxxxx1000xxx0xxxx", InstName.Vadd, InstEmit32.Vadd_I, OpCode32SimdReg.Create);
SetA32("111100100x00xxxxxxxx0001xxx1xxxx", InstName.Vand, InstEmit32.Vand_I, OpCode32SimdBinary.Create); SetA32("<<<<11100x11xxxxxxxx101xx0x0xxxx", InstName.Vadd, InstEmit32.Vadd_S, OpCode32SimdRegS.Create);
SetA32("111100100x01xxxxxxxx0001xxx1xxxx", InstName.Vbic, InstEmit32.Vbic_I, OpCode32SimdBinary.Create); SetA32("111100100x00xxxxxxxx1101xxx0xxxx", InstName.Vadd, InstEmit32.Vadd_V, OpCode32SimdReg.Create);
SetA32("1111001x1x000xxxxxxx<<x10x11xxxx", InstName.Vbic, InstEmit32.Vbic_II, OpCode32SimdImm.Create); SetA32("1111001x1x<<xxxxxxxx0000x0x0xxxx", InstName.Vaddl, InstEmit32.Vaddl_I, OpCode32SimdRegLong.Create);
SetA32("111100110x11xxxxxxxx0001xxx1xxxx", InstName.Vbif, InstEmit32.Vbif, OpCode32SimdBinary.Create); SetA32("1111001x1x<<xxxxxxxx0001x0x0xxxx", InstName.Vaddw, InstEmit32.Vaddw_I, OpCode32SimdRegWide.Create);
SetA32("111100110x10xxxxxxxx0001xxx1xxxx", InstName.Vbit, InstEmit32.Vbit, OpCode32SimdBinary.Create); SetA32("111100100x00xxxxxxxx0001xxx1xxxx", InstName.Vand, InstEmit32.Vand_I, OpCode32SimdBinary.Create);
SetA32("111100110x01xxxxxxxx0001xxx1xxxx", InstName.Vbsl, InstEmit32.Vbsl, OpCode32SimdBinary.Create); SetA32("111100100x01xxxxxxxx0001xxx1xxxx", InstName.Vbic, InstEmit32.Vbic_I, OpCode32SimdBinary.Create);
SetA32("111100110x<<xxxxxxxx1000xxx1xxxx", InstName.Vceq, InstEmit32.Vceq_I, OpCode32SimdReg.Create); SetA32("1111001x1x000xxxxxxx<<x10x11xxxx", InstName.Vbic, InstEmit32.Vbic_II, OpCode32SimdImm.Create);
SetA32("111100100x00xxxxxxxx1110xxx0xxxx", InstName.Vceq, InstEmit32.Vceq_V, OpCode32SimdReg.Create); SetA32("111100110x11xxxxxxxx0001xxx1xxxx", InstName.Vbif, InstEmit32.Vbif, OpCode32SimdBinary.Create);
SetA32("111100111x11xx01xxxx0x010xx0xxxx", InstName.Vceq, InstEmit32.Vceq_Z, OpCode32SimdCmpZ.Create); SetA32("111100110x10xxxxxxxx0001xxx1xxxx", InstName.Vbit, InstEmit32.Vbit, OpCode32SimdBinary.Create);
SetA32("1111001x0x<<xxxxxxxx0011xxx1xxxx", InstName.Vcge, InstEmit32.Vcge_I, OpCode32SimdReg.Create); SetA32("111100110x01xxxxxxxx0001xxx1xxxx", InstName.Vbsl, InstEmit32.Vbsl, OpCode32SimdBinary.Create);
SetA32("111100110x00xxxxxxxx1110xxx0xxxx", InstName.Vcge, InstEmit32.Vcge_V, OpCode32SimdReg.Create); SetA32("111100110x<<xxxxxxxx1000xxx1xxxx", InstName.Vceq, InstEmit32.Vceq_I, OpCode32SimdReg.Create);
SetA32("111100111x11xx01xxxx0x001xx0xxxx", InstName.Vcge, InstEmit32.Vcge_Z, OpCode32SimdCmpZ.Create); SetA32("111100100x00xxxxxxxx1110xxx0xxxx", InstName.Vceq, InstEmit32.Vceq_V, OpCode32SimdReg.Create);
SetA32("1111001x0x<<xxxxxxxx0011xxx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_I, OpCode32SimdReg.Create); SetA32("111100111x11xx01xxxx0x010xx0xxxx", InstName.Vceq, InstEmit32.Vceq_Z, OpCode32SimdCmpZ.Create);
SetA32("111100110x10xxxxxxxx1110xxx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_V, OpCode32SimdReg.Create); SetA32("1111001x0x<<xxxxxxxx0011xxx1xxxx", InstName.Vcge, InstEmit32.Vcge_I, OpCode32SimdReg.Create);
SetA32("111100111x11xx01xxxx0x000xx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_Z, OpCode32SimdCmpZ.Create); SetA32("111100110x00xxxxxxxx1110xxx0xxxx", InstName.Vcge, InstEmit32.Vcge_V, OpCode32SimdReg.Create);
SetA32("111100111x11xx01xxxx0x011xx0xxxx", InstName.Vcle, InstEmit32.Vcle_Z, OpCode32SimdCmpZ.Create); SetA32("111100111x11xx01xxxx0x001xx0xxxx", InstName.Vcge, InstEmit32.Vcge_Z, OpCode32SimdCmpZ.Create);
SetA32("111100111x11xx01xxxx0x100xx0xxxx", InstName.Vclt, InstEmit32.Vclt_Z, OpCode32SimdCmpZ.Create); SetA32("1111001x0x<<xxxxxxxx0011xxx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_I, OpCode32SimdReg.Create);
SetA32("<<<<11101x11010xxxxx101x01x0xxxx", InstName.Vcmp, InstEmit32.Vcmp, OpCode32SimdS.Create); SetA32("111100110x10xxxxxxxx1110xxx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_V, OpCode32SimdReg.Create);
SetA32("<<<<11101x11010xxxxx101x11x0xxxx", InstName.Vcmpe, InstEmit32.Vcmpe, OpCode32SimdS.Create); SetA32("111100111x11xx01xxxx0x000xx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_Z, OpCode32SimdCmpZ.Create);
SetA32("111100111x110000xxxx01010xx0xxxx", InstName.Vcnt, InstEmit32.Vcnt, OpCode32SimdCmpZ.Create); SetA32("111100111x11xx01xxxx0x011xx0xxxx", InstName.Vcle, InstEmit32.Vcle_Z, OpCode32SimdCmpZ.Create);
SetA32("<<<<11101x110111xxxx101x11x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FD, OpCode32SimdS.Create); // FP 32 and 64, scalar. SetA32("111100111x11xx01xxxx0x100xx0xxxx", InstName.Vclt, InstEmit32.Vclt_Z, OpCode32SimdCmpZ.Create);
SetA32("<<<<11101x11110xxxxx101x11x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FI, OpCode32SimdCvtFI.Create); // FP32 to int. SetA32("<<<<11101x11010xxxxx101x01x0xxxx", InstName.Vcmp, InstEmit32.Vcmp, OpCode32SimdS.Create);
SetA32("<<<<11101x111000xxxx101xx1x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FI, OpCode32SimdCvtFI.Create); // Int to FP32. SetA32("<<<<11101x11010xxxxx101x11x0xxxx", InstName.Vcmpe, InstEmit32.Vcmpe, OpCode32SimdS.Create);
SetA32("111111101x1111xxxxxx101xx1x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_RM, OpCode32SimdCvtFI.Create); // The many FP32 to int encodings (fp). SetA32("111100111x110000xxxx01010xx0xxxx", InstName.Vcnt, InstEmit32.Vcnt, OpCode32SimdCmpZ.Create);
SetA32("111100111x111011xxxx011xxxx0xxxx", InstName.Vcvt, InstEmit32.Vcvt_V, OpCode32SimdCmpZ.Create); // FP and integer, vector. SetA32("<<<<11101x110111xxxx101x11x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FD, OpCode32SimdS.Create); // FP 32 and 64, scalar.
SetA32("<<<<11101x00xxxxxxxx101xx0x0xxxx", InstName.Vdiv, InstEmit32.Vdiv_S, OpCode32SimdRegS.Create); SetA32("<<<<11101x11110xxxxx101x11x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FI, OpCode32SimdCvtFI.Create); // FP32 to int.
SetA32("<<<<11101xx0xxxxxxxx1011x0x10000", InstName.Vdup, InstEmit32.Vdup, OpCode32SimdDupGP.Create); SetA32("<<<<11101x111000xxxx101xx1x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FI, OpCode32SimdCvtFI.Create); // Int to FP32.
SetA32("111100111x11xxxxxxxx11000xx0xxxx", InstName.Vdup, InstEmit32.Vdup_1, OpCode32SimdDupElem.Create); SetA32("111111101x1111xxxxxx101xx1x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_RM, OpCode32SimdCvtFI.Create); // The many FP32 to int encodings (fp).
SetA32("111100110x00xxxxxxxx0001xxx1xxxx", InstName.Veor, InstEmit32.Veor_I, OpCode32SimdBinary.Create); SetA32("111100111x111011xxxx011xxxx0xxxx", InstName.Vcvt, InstEmit32.Vcvt_V, OpCode32SimdCmpZ.Create); // FP and integer, vector.
SetA32("111100101x11xxxxxxxxxxxxxxx0xxxx", InstName.Vext, InstEmit32.Vext, OpCode32SimdExt.Create); SetA32("<<<<11101x00xxxxxxxx101xx0x0xxxx", InstName.Vdiv, InstEmit32.Vdiv_S, OpCode32SimdRegS.Create);
SetA32("<<<<11101x10xxxxxxxx101xx0x0xxxx", InstName.Vfma, InstEmit32.Vfma_S, OpCode32SimdRegS.Create); SetA32("<<<<11101xx0xxxxxxxx1011x0x10000", InstName.Vdup, InstEmit32.Vdup, OpCode32SimdDupGP.Create);
SetA32("111100100x00xxxxxxxx1100xxx1xxxx", InstName.Vfma, InstEmit32.Vfma_V, OpCode32SimdReg.Create); SetA32("111100111x11xxxxxxxx11000xx0xxxx", InstName.Vdup, InstEmit32.Vdup_1, OpCode32SimdDupElem.Create);
SetA32("<<<<11101x10xxxxxxxx101xx1x0xxxx", InstName.Vfms, InstEmit32.Vfms_S, OpCode32SimdRegS.Create); SetA32("111100110x00xxxxxxxx0001xxx1xxxx", InstName.Veor, InstEmit32.Veor_I, OpCode32SimdBinary.Create);
SetA32("111100100x10xxxxxxxx1100xxx1xxxx", InstName.Vfms, InstEmit32.Vfms_V, OpCode32SimdReg.Create); SetA32("111100101x11xxxxxxxxxxxxxxx0xxxx", InstName.Vext, InstEmit32.Vext, OpCode32SimdExt.Create);
SetA32("<<<<11101x01xxxxxxxx101xx1x0xxxx", InstName.Vfnma, InstEmit32.Vfnma_S, OpCode32SimdRegS.Create); SetA32("<<<<11101x10xxxxxxxx101xx0x0xxxx", InstName.Vfma, InstEmit32.Vfma_S, OpCode32SimdRegS.Create);
SetA32("<<<<11101x01xxxxxxxx101xx0x0xxxx", InstName.Vfnms, InstEmit32.Vfnms_S, OpCode32SimdRegS.Create); SetA32("111100100x00xxxxxxxx1100xxx1xxxx", InstName.Vfma, InstEmit32.Vfma_V, OpCode32SimdReg.Create);
SetA32("1111001x0x<<xxxxxxxx0000xxx0xxxx", InstName.Vhadd, InstEmit32.Vhadd, OpCode32SimdReg.Create); SetA32("<<<<11101x10xxxxxxxx101xx1x0xxxx", InstName.Vfms, InstEmit32.Vfms_S, OpCode32SimdRegS.Create);
SetA32("111101001x10xxxxxxxxxx00xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemSingle.Create); SetA32("111100100x10xxxxxxxx1100xxx1xxxx", InstName.Vfms, InstEmit32.Vfms_V, OpCode32SimdReg.Create);
SetA32("111101000x10xxxxxxxx0111xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create); // Regs = 1. SetA32("<<<<11101x01xxxxxxxx101xx1x0xxxx", InstName.Vfnma, InstEmit32.Vfnma_S, OpCode32SimdRegS.Create);
SetA32("111101000x10xxxxxxxx1010xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create); // Regs = 2. SetA32("<<<<11101x01xxxxxxxx101xx0x0xxxx", InstName.Vfnms, InstEmit32.Vfnms_S, OpCode32SimdRegS.Create);
SetA32("111101000x10xxxxxxxx0110xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create); // Regs = 3. SetA32("1111001x0x<<xxxxxxxx0000xxx0xxxx", InstName.Vhadd, InstEmit32.Vhadd, OpCode32SimdReg.Create);
SetA32("111101000x10xxxxxxxx0010xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create); // Regs = 4. SetA32("111101001x10xxxxxxxxxx00xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemSingle.Create);
SetA32("111101001x10xxxxxxxxxx01xxxxxxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemSingle.Create); SetA32("111101000x10xxxxxxxx0111xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create); // Regs = 1.
SetA32("111101000x10xxxxxxxx100xxxxxxxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemPair.Create); // Regs = 1, inc = 1/2 (itype). SetA32("111101000x10xxxxxxxx1010xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create); // Regs = 2.
SetA32("111101000x10xxxxxxxx0011xxxxxxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemPair.Create); // Regs = 2, inc = 2. SetA32("111101000x10xxxxxxxx0110xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create); // Regs = 3.
SetA32("111101001x10xxxxxxxxxx10xxxxxxxx", InstName.Vld3, InstEmit32.Vld3, OpCode32SimdMemSingle.Create); SetA32("111101000x10xxxxxxxx0010xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create); // Regs = 4.
SetA32("111101000x10xxxxxxxx010xxxxxxxxx", InstName.Vld3, InstEmit32.Vld3, OpCode32SimdMemPair.Create); // Inc = 1/2 (itype). SetA32("111101001x10xxxxxxxxxx01xxxxxxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemSingle.Create);
SetA32("111101001x10xxxxxxxxxx11xxxxxxxx", InstName.Vld4, InstEmit32.Vld4, OpCode32SimdMemSingle.Create); SetA32("111101000x10xxxxxxxx100xxxxxxxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemPair.Create); // Regs = 1, inc = 1/2 (itype).
SetA32("111101000x10xxxxxxxx000xxxxxxxxx", InstName.Vld4, InstEmit32.Vld4, OpCode32SimdMemPair.Create); // Inc = 1/2 (itype). SetA32("111101000x10xxxxxxxx0011xxxxxxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemPair.Create); // Regs = 2, inc = 2.
SetA32("<<<<11001x01xxxxxxxx1011xxxxxxx0", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create); SetA32("111101001x10xxxxxxxxxx10xxxxxxxx", InstName.Vld3, InstEmit32.Vld3, OpCode32SimdMemSingle.Create);
SetA32("<<<<11001x11xxxxxxxx1011xxxxxxx0", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create); SetA32("111101000x10xxxxxxxx010xxxxxxxxx", InstName.Vld3, InstEmit32.Vld3, OpCode32SimdMemPair.Create); // Inc = 1/2 (itype).
SetA32("<<<<11010x11xxxxxxxx1011xxxxxxx0", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create); SetA32("111101001x10xxxxxxxxxx11xxxxxxxx", InstName.Vld4, InstEmit32.Vld4, OpCode32SimdMemSingle.Create);
SetA32("<<<<11001x01xxxxxxxx1010xxxxxxxx", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create); SetA32("111101000x10xxxxxxxx000xxxxxxxxx", InstName.Vld4, InstEmit32.Vld4, OpCode32SimdMemPair.Create); // Inc = 1/2 (itype).
SetA32("<<<<11001x11xxxxxxxx1010xxxxxxxx", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create); SetA32("<<<<11001x01xxxxxxxx1011xxxxxxx0", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create);
SetA32("<<<<11010x11xxxxxxxx1010xxxxxxxx", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create); SetA32("<<<<11001x11xxxxxxxx1011xxxxxxx0", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create);
SetA32("<<<<1101xx01xxxxxxxx101xxxxxxxxx", InstName.Vldr, InstEmit32.Vldr, OpCode32SimdMemImm.Create); SetA32("<<<<11010x11xxxxxxxx1011xxxxxxx0", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create);
SetA32("1111001x0x<<xxxxxxxx0110xxx0xxxx", InstName.Vmax, InstEmit32.Vmax_I, OpCode32SimdReg.Create); SetA32("<<<<11001x01xxxxxxxx1010xxxxxxxx", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create);
SetA32("111100100x00xxxxxxxx1111xxx0xxxx", InstName.Vmax, InstEmit32.Vmax_V, OpCode32SimdReg.Create); SetA32("<<<<11001x11xxxxxxxx1010xxxxxxxx", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create);
SetA32("1111001x0x<<xxxxxxxx0110xxx1xxxx", InstName.Vmin, InstEmit32.Vmin_I, OpCode32SimdReg.Create); SetA32("<<<<11010x11xxxxxxxx1010xxxxxxxx", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create);
SetA32("111100100x10xxxxxxxx1111xxx0xxxx", InstName.Vmin, InstEmit32.Vmin_V, OpCode32SimdReg.Create); SetA32("<<<<1101xx01xxxxxxxx101xxxxxxxxx", InstName.Vldr, InstEmit32.Vldr, OpCode32SimdMemImm.Create);
SetA32("111111101x00xxxxxxxx10>>x0x0xxxx", InstName.Vmaxnm, InstEmit32.Vmaxnm_S, OpCode32SimdRegS.Create); SetA32("1111001x0x<<xxxxxxxx0110xxx0xxxx", InstName.Vmax, InstEmit32.Vmax_I, OpCode32SimdReg.Create);
SetA32("111100110x0xxxxxxxxx1111xxx1xxxx", InstName.Vmaxnm, InstEmit32.Vmaxnm_V, OpCode32SimdReg.Create); SetA32("111100100x00xxxxxxxx1111xxx0xxxx", InstName.Vmax, InstEmit32.Vmax_V, OpCode32SimdReg.Create);
SetA32("111111101x00xxxxxxxx10>>x1x0xxxx", InstName.Vminnm, InstEmit32.Vminnm_S, OpCode32SimdRegS.Create); SetA32("1111001x0x<<xxxxxxxx0110xxx1xxxx", InstName.Vmin, InstEmit32.Vmin_I, OpCode32SimdReg.Create);
SetA32("111100110x1xxxxxxxxx1111xxx1xxxx", InstName.Vminnm, InstEmit32.Vminnm_V, OpCode32SimdReg.Create); SetA32("111100100x10xxxxxxxx1111xxx0xxxx", InstName.Vmin, InstEmit32.Vmin_V, OpCode32SimdReg.Create);
SetA32("1111001x1x<<xxxxxxxx000xx1x0xxxx", InstName.Vmla, InstEmit32.Vmla_1, OpCode32SimdRegElem.Create); SetA32("111111101x00xxxxxxxx10>>x0x0xxxx", InstName.Vmaxnm, InstEmit32.Vmaxnm_S, OpCode32SimdRegS.Create);
SetA32("111100100xxxxxxxxxxx1001xxx0xxxx", InstName.Vmla, InstEmit32.Vmla_I, OpCode32SimdReg.Create); SetA32("111100110x0xxxxxxxxx1111xxx1xxxx", InstName.Vmaxnm, InstEmit32.Vmaxnm_V, OpCode32SimdReg.Create);
SetA32("<<<<11100x00xxxxxxxx101xx0x0xxxx", InstName.Vmla, InstEmit32.Vmla_S, OpCode32SimdRegS.Create); SetA32("111111101x00xxxxxxxx10>>x1x0xxxx", InstName.Vminnm, InstEmit32.Vminnm_S, OpCode32SimdRegS.Create);
SetA32("111100100x00xxxxxxxx1101xxx1xxxx", InstName.Vmla, InstEmit32.Vmla_V, OpCode32SimdReg.Create); SetA32("111100110x1xxxxxxxxx1111xxx1xxxx", InstName.Vminnm, InstEmit32.Vminnm_V, OpCode32SimdReg.Create);
SetA32("1111001x1x<<xxxxxxxx010xx1x0xxxx", InstName.Vmls, InstEmit32.Vmls_1, OpCode32SimdRegElem.Create); SetA32("1111001x1x<<xxxxxxxx000xx1x0xxxx", InstName.Vmla, InstEmit32.Vmla_1, OpCode32SimdRegElem.Create);
SetA32("<<<<11100x00xxxxxxxx101xx1x0xxxx", InstName.Vmls, InstEmit32.Vmls_S, OpCode32SimdRegS.Create); SetA32("111100100xxxxxxxxxxx1001xxx0xxxx", InstName.Vmla, InstEmit32.Vmla_I, OpCode32SimdReg.Create);
SetA32("111100100x10xxxxxxxx1101xxx1xxxx", InstName.Vmls, InstEmit32.Vmls_V, OpCode32SimdReg.Create); SetA32("<<<<11100x00xxxxxxxx101xx0x0xxxx", InstName.Vmla, InstEmit32.Vmla_S, OpCode32SimdRegS.Create);
SetA32("111100110xxxxxxxxxxx1001xxx0xxxx", InstName.Vmls, InstEmit32.Vmls_I, OpCode32SimdReg.Create); SetA32("111100100x00xxxxxxxx1101xxx1xxxx", InstName.Vmla, InstEmit32.Vmla_V, OpCode32SimdReg.Create);
SetA32("1111001x1x<<xxxxxxx01010x0x0xxxx", InstName.Vmlsl, InstEmit32.Vmlsl_I, OpCode32SimdRegLong.Create); SetA32("1111001x1x<<xxxxxxxx010xx1x0xxxx", InstName.Vmls, InstEmit32.Vmls_1, OpCode32SimdRegElem.Create);
SetA32("<<<<11100xx0xxxxxxxx1011xxx10000", InstName.Vmov, InstEmit32.Vmov_G1, OpCode32SimdMovGpElem.Create); // From gen purpose. SetA32("<<<<11100x00xxxxxxxx101xx1x0xxxx", InstName.Vmls, InstEmit32.Vmls_S, OpCode32SimdRegS.Create);
SetA32("<<<<1110xxx1xxxxxxxx1011xxx10000", InstName.Vmov, InstEmit32.Vmov_G1, OpCode32SimdMovGpElem.Create); // To gen purpose. SetA32("111100100x10xxxxxxxx1101xxx1xxxx", InstName.Vmls, InstEmit32.Vmls_V, OpCode32SimdReg.Create);
SetA32("<<<<1100010xxxxxxxxx101000x1xxxx", InstName.Vmov, InstEmit32.Vmov_G2, OpCode32SimdMovGpDouble.Create); // To/from gen purpose x2 and single precision x2. SetA32("111100110xxxxxxxxxxx1001xxx0xxxx", InstName.Vmls, InstEmit32.Vmls_I, OpCode32SimdReg.Create);
SetA32("<<<<1100010xxxxxxxxx101100x1xxxx", InstName.Vmov, InstEmit32.Vmov_GD, OpCode32SimdMovGpDouble.Create); // To/from gen purpose x2 and double precision. SetA32("1111001x1x<<xxxxxxx01010x0x0xxxx", InstName.Vmlsl, InstEmit32.Vmlsl_I, OpCode32SimdRegLong.Create);
SetA32("<<<<1110000xxxxxxxxx1010x0010000", InstName.Vmov, InstEmit32.Vmov_GS, OpCode32SimdMovGp.Create); // To/from gen purpose and single precision. SetA32("<<<<11100xx0xxxxxxxx1011xxx10000", InstName.Vmov, InstEmit32.Vmov_G1, OpCode32SimdMovGpElem.Create); // From gen purpose.
SetA32("1111001x1x000xxxxxxx0xx00x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create); // D/Q vector I32. SetA32("<<<<1110xxx1xxxxxxxx1011xxx10000", InstName.Vmov, InstEmit32.Vmov_G1, OpCode32SimdMovGpElem.Create); // To gen purpose.
SetA32("<<<<11101x11xxxxxxxx101x0000xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm44.Create); // Scalar f16/32/64 based on size 01 10 11. SetA32("<<<<1100010xxxxxxxxx101000x1xxxx", InstName.Vmov, InstEmit32.Vmov_G2, OpCode32SimdMovGpDouble.Create); // To/from gen purpose x2 and single precision x2.
SetA32("1111001x1x000xxxxxxx10x00x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create); // D/Q I16. SetA32("<<<<1100010xxxxxxxxx101100x1xxxx", InstName.Vmov, InstEmit32.Vmov_GD, OpCode32SimdMovGpDouble.Create); // To/from gen purpose x2 and double precision.
SetA32("1111001x1x000xxxxxxx11xx0x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create); // D/Q (dt - from cmode). SetA32("<<<<1110000xxxxxxxxx1010x0010000", InstName.Vmov, InstEmit32.Vmov_GS, OpCode32SimdMovGp.Create); // To/from gen purpose and single precision.
SetA32("1111001x1x000xxxxxxx11100x11xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create); // D/Q I64. SetA32("1111001x1x000xxxxxxx0xx00x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create); // D/Q vector I32.
SetA32("<<<<11101x110000xxxx101x01x0xxxx", InstName.Vmov, InstEmit32.Vmov_S, OpCode32SimdS.Create); SetA32("<<<<11101x11xxxxxxxx101x0000xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm44.Create); // Scalar f16/32/64 based on size 01 10 11.
SetA32("1111001x1x001000xxx0101000x1xxxx", InstName.Vmovl, InstEmit32.Vmovl, OpCode32SimdLong.Create); SetA32("1111001x1x000xxxxxxx10x00x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create); // D/Q I16.
SetA32("1111001x1x010000xxx0101000x1xxxx", InstName.Vmovl, InstEmit32.Vmovl, OpCode32SimdLong.Create); SetA32("1111001x1x000xxxxxxx11xx0x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create); // D/Q (dt - from cmode).
SetA32("1111001x1x100000xxx0101000x1xxxx", InstName.Vmovl, InstEmit32.Vmovl, OpCode32SimdLong.Create); SetA32("1111001x1x000xxxxxxx11100x11xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create); // D/Q I64.
SetA32("111100111x11xx10xxxx001000x0xxx0", InstName.Vmovn, InstEmit32.Vmovn, OpCode32SimdCmpZ.Create); SetA32("<<<<11101x110000xxxx101x01x0xxxx", InstName.Vmov, InstEmit32.Vmov_S, OpCode32SimdS.Create);
SetA32("<<<<11101111xxxxxxxx101000010000", InstName.Vmrs, InstEmit32.Vmrs, OpCode32SimdSpecial.Create); SetA32("1111001x1x001000xxx0101000x1xxxx", InstName.Vmovl, InstEmit32.Vmovl, OpCode32SimdLong.Create);
SetA32("<<<<11101110xxxxxxxx101000010000", InstName.Vmsr, InstEmit32.Vmsr, OpCode32SimdSpecial.Create); SetA32("1111001x1x010000xxx0101000x1xxxx", InstName.Vmovl, InstEmit32.Vmovl, OpCode32SimdLong.Create);
SetA32("1111001x1x<<xxxxxxxx100xx1x0xxxx", InstName.Vmul, InstEmit32.Vmul_1, OpCode32SimdRegElem.Create); SetA32("1111001x1x100000xxx0101000x1xxxx", InstName.Vmovl, InstEmit32.Vmovl, OpCode32SimdLong.Create);
SetA32("111100100x<<xxxxxxxx1001xxx1xxxx", InstName.Vmul, InstEmit32.Vmul_I, OpCode32SimdReg.Create); SetA32("111100111x11xx10xxxx001000x0xxx0", InstName.Vmovn, InstEmit32.Vmovn, OpCode32SimdCmpZ.Create);
SetA32("111100110x00xxxxxxxx1001xxx1xxxx", InstName.Vmul, InstEmit32.Vmul_I, OpCode32SimdReg.Create); SetA32("<<<<11101111xxxxxxxx101000010000", InstName.Vmrs, InstEmit32.Vmrs, OpCode32SimdSpecial.Create);
SetA32("<<<<11100x10xxxxxxxx101xx0x0xxxx", InstName.Vmul, InstEmit32.Vmul_S, OpCode32SimdRegS.Create); SetA32("<<<<11101110xxxxxxxx101000010000", InstName.Vmsr, InstEmit32.Vmsr, OpCode32SimdSpecial.Create);
SetA32("111100110x00xxxxxxxx1101xxx1xxxx", InstName.Vmul, InstEmit32.Vmul_V, OpCode32SimdReg.Create); SetA32("1111001x1x<<xxxxxxxx100xx1x0xxxx", InstName.Vmul, InstEmit32.Vmul_1, OpCode32SimdRegElem.Create);
SetA32("1111001x1x<<xxxxxxx01010x1x0xxxx", InstName.Vmull, InstEmit32.Vmull_1, OpCode32SimdRegElemLong.Create); SetA32("111100100x<<xxxxxxxx1001xxx1xxxx", InstName.Vmul, InstEmit32.Vmul_I, OpCode32SimdReg.Create);
SetA32("1111001x1x<<xxxxxxx01100x0x0xxxx", InstName.Vmull, InstEmit32.Vmull_I, OpCode32SimdRegLong.Create); SetA32("111100110x00xxxxxxxx1001xxx1xxxx", InstName.Vmul, InstEmit32.Vmul_I, OpCode32SimdReg.Create);
SetA32("111100101xx0xxxxxxx01110x0x0xxxx", InstName.Vmull, InstEmit32.Vmull_I, OpCode32SimdRegLong.Create); // P8/P64 SetA32("<<<<11100x10xxxxxxxx101xx0x0xxxx", InstName.Vmul, InstEmit32.Vmul_S, OpCode32SimdRegS.Create);
SetA32("111100111x110000xxxx01011xx0xxxx", InstName.Vmvn, InstEmit32.Vmvn_I, OpCode32SimdBinary.Create); SetA32("111100110x00xxxxxxxx1101xxx1xxxx", InstName.Vmul, InstEmit32.Vmul_V, OpCode32SimdReg.Create);
SetA32("1111001x1x000xxxxxxx0xx00x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_II, OpCode32SimdImm.Create); // D/Q vector I32. SetA32("1111001x1x<<xxxxxxx01010x1x0xxxx", InstName.Vmull, InstEmit32.Vmull_1, OpCode32SimdRegElemLong.Create);
SetA32("1111001x1x000xxxxxxx10x00x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_II, OpCode32SimdImm.Create); SetA32("1111001x1x<<xxxxxxx01100x0x0xxxx", InstName.Vmull, InstEmit32.Vmull_I, OpCode32SimdRegLong.Create);
SetA32("1111001x1x000xxxxxxx110x0x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_II, OpCode32SimdImm.Create); SetA32("111100101xx0xxxxxxx01110x0x0xxxx", InstName.Vmull, InstEmit32.Vmull_I, OpCode32SimdRegLong.Create); // P8/P64
SetA32("<<<<11101x110001xxxx101x01x0xxxx", InstName.Vneg, InstEmit32.Vneg_S, OpCode32SimdS.Create); SetA32("111100111x110000xxxx01011xx0xxxx", InstName.Vmvn, InstEmit32.Vmvn_I, OpCode32SimdBinary.Create);
SetA32("111100111x11<<01xxxx00111xx0xxxx", InstName.Vneg, InstEmit32.Vneg_V, OpCode32SimdCmpZ.Create); SetA32("1111001x1x000xxxxxxx0xx00x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_II, OpCode32SimdImm.Create); // D/Q vector I32.
SetA32("111100111x111001xxxx01111xx0xxxx", InstName.Vneg, InstEmit32.Vneg_V, OpCode32SimdCmpZ.Create); SetA32("1111001x1x000xxxxxxx10x00x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_II, OpCode32SimdImm.Create);
SetA32("<<<<11100x01xxxxxxxx101xx1x0xxxx", InstName.Vnmla, InstEmit32.Vnmla_S, OpCode32SimdRegS.Create); SetA32("1111001x1x000xxxxxxx110x0x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_II, OpCode32SimdImm.Create);
SetA32("<<<<11100x01xxxxxxxx101xx0x0xxxx", InstName.Vnmls, InstEmit32.Vnmls_S, OpCode32SimdRegS.Create); SetA32("<<<<11101x110001xxxx101x01x0xxxx", InstName.Vneg, InstEmit32.Vneg_S, OpCode32SimdS.Create);
SetA32("<<<<11100x10xxxxxxxx101xx1x0xxxx", InstName.Vnmul, InstEmit32.Vnmul_S, OpCode32SimdRegS.Create); SetA32("111100111x11<<01xxxx00111xx0xxxx", InstName.Vneg, InstEmit32.Vneg_V, OpCode32SimdCmpZ.Create);
SetA32("111100100x11xxxxxxxx0001xxx1xxxx", InstName.Vorn, InstEmit32.Vorn_I, OpCode32SimdBinary.Create); SetA32("111100111x111001xxxx01111xx0xxxx", InstName.Vneg, InstEmit32.Vneg_V, OpCode32SimdCmpZ.Create);
SetA32("111100100x10xxxxxxxx0001xxx1xxxx", InstName.Vorr, InstEmit32.Vorr_I, OpCode32SimdBinary.Create); SetA32("<<<<11100x01xxxxxxxx101xx1x0xxxx", InstName.Vnmla, InstEmit32.Vnmla_S, OpCode32SimdRegS.Create);
SetA32("1111001x1x000xxxxxxx<<x10x01xxxx", InstName.Vorr, InstEmit32.Vorr_II, OpCode32SimdImm.Create); SetA32("<<<<11100x01xxxxxxxx101xx0x0xxxx", InstName.Vnmls, InstEmit32.Vnmls_S, OpCode32SimdRegS.Create);
SetA32("111100100x<<xxxxxxxx1011x0x1xxxx", InstName.Vpadd, InstEmit32.Vpadd_I, OpCode32SimdReg.Create); SetA32("<<<<11100x10xxxxxxxx101xx1x0xxxx", InstName.Vnmul, InstEmit32.Vnmul_S, OpCode32SimdRegS.Create);
SetA32("111100110x00xxxxxxxx1101x0x0xxxx", InstName.Vpadd, InstEmit32.Vpadd_V, OpCode32SimdReg.Create); SetA32("111100100x11xxxxxxxx0001xxx1xxxx", InstName.Vorn, InstEmit32.Vorn_I, OpCode32SimdBinary.Create);
SetA32("1111001x0x<<xxxxxxxx1010x0x0xxxx", InstName.Vpmax, InstEmit32.Vpmax_I, OpCode32SimdReg.Create); SetA32("111100100x10xxxxxxxx0001xxx1xxxx", InstName.Vorr, InstEmit32.Vorr_I, OpCode32SimdBinary.Create);
SetA32("111100110x00xxxxxxxx1111x0x0xxxx", InstName.Vpmax, InstEmit32.Vpmax_V, OpCode32SimdReg.Create); SetA32("1111001x1x000xxxxxxx<<x10x01xxxx", InstName.Vorr, InstEmit32.Vorr_II, OpCode32SimdImm.Create);
SetA32("1111001x0x<<xxxxxxxx1010x0x1xxxx", InstName.Vpmin, InstEmit32.Vpmin_I, OpCode32SimdReg.Create); SetA32("111100100x<<xxxxxxxx1011x0x1xxxx", InstName.Vpadd, InstEmit32.Vpadd_I, OpCode32SimdReg.Create);
SetA32("111100110x10xxxxxxxx1111x0x0xxxx", InstName.Vpmin, InstEmit32.Vpmin_V, OpCode32SimdReg.Create); SetA32("111100110x00xxxxxxxx1101x0x0xxxx", InstName.Vpadd, InstEmit32.Vpadd_V, OpCode32SimdReg.Create);
SetA32("1111001x1x>>>xxxxxxx100101x1xxx0", InstName.Vqrshrn, InstEmit32.Vqrshrn, OpCode32SimdShImmNarrow.Create); SetA32("1111001x0x<<xxxxxxxx1010x0x0xxxx", InstName.Vpmax, InstEmit32.Vpmax_I, OpCode32SimdReg.Create);
SetA32("111100111x>>>xxxxxxx100001x1xxx0", InstName.Vqrshrun, InstEmit32.Vqrshrun, OpCode32SimdShImmNarrow.Create); SetA32("111100110x00xxxxxxxx1111x0x0xxxx", InstName.Vpmax, InstEmit32.Vpmax_V, OpCode32SimdReg.Create);
SetA32("1111001x1x>>>xxxxxxx100100x1xxx0", InstName.Vqshrn, InstEmit32.Vqshrn, OpCode32SimdShImmNarrow.Create); SetA32("1111001x0x<<xxxxxxxx1010x0x1xxxx", InstName.Vpmin, InstEmit32.Vpmin_I, OpCode32SimdReg.Create);
SetA32("111100111x111011xxxx010x0xx0xxxx", InstName.Vrecpe, InstEmit32.Vrecpe, OpCode32SimdSqrte.Create); SetA32("111100110x10xxxxxxxx1111x0x0xxxx", InstName.Vpmin, InstEmit32.Vpmin_V, OpCode32SimdReg.Create);
SetA32("111100100x00xxxxxxxx1111xxx1xxxx", InstName.Vrecps, InstEmit32.Vrecps, OpCode32SimdReg.Create); SetA32("1111001x1x>>>xxxxxxx100101x1xxx0", InstName.Vqrshrn, InstEmit32.Vqrshrn, OpCode32SimdShImmNarrow.Create);
SetA32("111100111x11xx00xxxx000<<xx0xxxx", InstName.Vrev, InstEmit32.Vrev, OpCode32SimdRev.Create); SetA32("111100111x>>>xxxxxxx100001x1xxx0", InstName.Vqrshrun, InstEmit32.Vqrshrun, OpCode32SimdShImmNarrow.Create);
SetA32("111111101x1110xxxxxx101x01x0xxxx", InstName.Vrint, InstEmit32.Vrint_RM, OpCode32SimdS.Create); SetA32("1111001x1x>>>xxxxxxx100100x1xxx0", InstName.Vqshrn, InstEmit32.Vqshrn, OpCode32SimdShImmNarrow.Create);
SetA32("<<<<11101x110110xxxx101x11x0xxxx", InstName.Vrint, InstEmit32.Vrint_Z, OpCode32SimdS.Create); SetA32("111100111x111011xxxx010x0xx0xxxx", InstName.Vrecpe, InstEmit32.Vrecpe, OpCode32SimdSqrte.Create);
SetA32("<<<<11101x110111xxxx101x01x0xxxx", InstName.Vrintx, InstEmit32.Vrintx_S, OpCode32SimdS.Create); SetA32("111100100x00xxxxxxxx1111xxx1xxxx", InstName.Vrecps, InstEmit32.Vrecps, OpCode32SimdReg.Create);
SetA32("1111001x1x>>>xxxxxxx0010>xx1xxxx", InstName.Vrshr, InstEmit32.Vrshr, OpCode32SimdShImm.Create); SetA32("111100111x11xx00xxxx000<<xx0xxxx", InstName.Vrev, InstEmit32.Vrev, OpCode32SimdRev.Create);
SetA32("111100111x111011xxxx010x1xx0xxxx", InstName.Vrsqrte, InstEmit32.Vrsqrte, OpCode32SimdSqrte.Create); SetA32("111111101x1110xxxxxx101x01x0xxxx", InstName.Vrint, InstEmit32.Vrint_RM, OpCode32SimdS.Create);
SetA32("111100100x10xxxxxxxx1111xxx1xxxx", InstName.Vrsqrts, InstEmit32.Vrsqrts, OpCode32SimdReg.Create); SetA32("<<<<11101x110110xxxx101x11x0xxxx", InstName.Vrint, InstEmit32.Vrint_Z, OpCode32SimdS.Create);
SetA32("111111100xxxxxxxxxxx101xx0x0xxxx", InstName.Vsel, InstEmit32.Vsel, OpCode32SimdSel.Create); SetA32("<<<<11101x110111xxxx101x01x0xxxx", InstName.Vrintx, InstEmit32.Vrintx_S, OpCode32SimdS.Create);
SetA32("111100101x>>>xxxxxxx0101>xx1xxxx", InstName.Vshl, InstEmit32.Vshl, OpCode32SimdShImm.Create); SetA32("1111001x1x>>>xxxxxxx0010>xx1xxxx", InstName.Vrshr, InstEmit32.Vrshr, OpCode32SimdShImm.Create);
SetA32("1111001x0xxxxxxxxxxx0100xxx0xxxx", InstName.Vshl, InstEmit32.Vshl_I, OpCode32SimdReg.Create); SetA32("111100111x111011xxxx010x1xx0xxxx", InstName.Vrsqrte, InstEmit32.Vrsqrte, OpCode32SimdSqrte.Create);
SetA32("1111001x1x>>>xxxxxxx101000x1xxxx", InstName.Vshll, InstEmit32.Vshll, OpCode32SimdShImmLong.Create); // A1 encoding. SetA32("111100100x10xxxxxxxx1111xxx1xxxx", InstName.Vrsqrts, InstEmit32.Vrsqrts, OpCode32SimdReg.Create);
SetA32("1111001x1x>>>xxxxxxx0000>xx1xxxx", InstName.Vshr, InstEmit32.Vshr, OpCode32SimdShImm.Create); SetA32("111111100xxxxxxxxxxx101xx0x0xxxx", InstName.Vsel, InstEmit32.Vsel, OpCode32SimdSel.Create);
SetA32("111100101x>>>xxxxxxx100000x1xxx0", InstName.Vshrn, InstEmit32.Vshrn, OpCode32SimdShImmNarrow.Create); SetA32("111100101x>>>xxxxxxx0101>xx1xxxx", InstName.Vshl, InstEmit32.Vshl, OpCode32SimdShImm.Create);
SetA32("<<<<11101x110001xxxx101x11x0xxxx", InstName.Vsqrt, InstEmit32.Vsqrt_S, OpCode32SimdS.Create); SetA32("1111001x0xxxxxxxxxxx0100xxx0xxxx", InstName.Vshl, InstEmit32.Vshl_I, OpCode32SimdReg.Create);
SetA32("1111001x1x>>>xxxxxxx0001>xx1xxxx", InstName.Vsra, InstEmit32.Vsra, OpCode32SimdShImm.Create); SetA32("1111001x1x>>>xxxxxxx101000x1xxxx", InstName.Vshll, InstEmit32.Vshll, OpCode32SimdShImmLong.Create); // A1 encoding.
SetA32("111101001x00xxxxxxxx<<00xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemSingle.Create); SetA32("1111001x1x>>>xxxxxxx0000>xx1xxxx", InstName.Vshr, InstEmit32.Vshr, OpCode32SimdShImm.Create);
SetA32("111101000x00xxxxxxxx0111xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create); // Regs = 1. SetA32("111100101x>>>xxxxxxx100000x1xxx0", InstName.Vshrn, InstEmit32.Vshrn, OpCode32SimdShImmNarrow.Create);
SetA32("111101000x00xxxxxxxx1010xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create); // Regs = 2. SetA32("<<<<11101x110001xxxx101x11x0xxxx", InstName.Vsqrt, InstEmit32.Vsqrt_S, OpCode32SimdS.Create);
SetA32("111101000x00xxxxxxxx0110xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create); // Regs = 3. SetA32("1111001x1x>>>xxxxxxx0001>xx1xxxx", InstName.Vsra, InstEmit32.Vsra, OpCode32SimdShImm.Create);
SetA32("111101000x00xxxxxxxx0010xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create); // Regs = 4. SetA32("111101001x00xxxxxxxx<<00xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemSingle.Create);
SetA32("111101001x00xxxxxxxx<<01xxxxxxxx", InstName.Vst2, InstEmit32.Vst2, OpCode32SimdMemSingle.Create); SetA32("111101000x00xxxxxxxx0111xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create); // Regs = 1.
SetA32("111101000x00xxxxxxxx100xxxxxxxxx", InstName.Vst2, InstEmit32.Vst2, OpCode32SimdMemPair.Create); // Regs = 1, inc = 1/2 (itype). SetA32("111101000x00xxxxxxxx1010xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create); // Regs = 2.
SetA32("111101000x00xxxxxxxx0011xxxxxxxx", InstName.Vst2, InstEmit32.Vst2, OpCode32SimdMemPair.Create); // Regs = 2, inc = 2. SetA32("111101000x00xxxxxxxx0110xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create); // Regs = 3.
SetA32("111101001x00xxxxxxxx<<10xxxxxxxx", InstName.Vst3, InstEmit32.Vst3, OpCode32SimdMemSingle.Create); SetA32("111101000x00xxxxxxxx0010xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create); // Regs = 4.
SetA32("111101000x00xxxxxxxx010xxxxxxxxx", InstName.Vst3, InstEmit32.Vst3, OpCode32SimdMemPair.Create); // Inc = 1/2 (itype). SetA32("111101001x00xxxxxxxx<<01xxxxxxxx", InstName.Vst2, InstEmit32.Vst2, OpCode32SimdMemSingle.Create);
SetA32("111101001x00xxxxxxxx<<11xxxxxxxx", InstName.Vst4, InstEmit32.Vst4, OpCode32SimdMemSingle.Create); SetA32("111101000x00xxxxxxxx100xxxxxxxxx", InstName.Vst2, InstEmit32.Vst2, OpCode32SimdMemPair.Create); // Regs = 1, inc = 1/2 (itype).
SetA32("111101000x00xxxxxxxx000xxxxxxxxx", InstName.Vst4, InstEmit32.Vst4, OpCode32SimdMemPair.Create); // Inc = 1/2 (itype). SetA32("111101000x00xxxxxxxx0011xxxxxxxx", InstName.Vst2, InstEmit32.Vst2, OpCode32SimdMemPair.Create); // Regs = 2, inc = 2.
SetA32("<<<<11001x00xxxxxxxx1011xxxxxxx0", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create); SetA32("111101001x00xxxxxxxx<<10xxxxxxxx", InstName.Vst3, InstEmit32.Vst3, OpCode32SimdMemSingle.Create);
SetA32("<<<<11001x10xxxxxxxx1011xxxxxxx0", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create); SetA32("111101000x00xxxxxxxx010xxxxxxxxx", InstName.Vst3, InstEmit32.Vst3, OpCode32SimdMemPair.Create); // Inc = 1/2 (itype).
SetA32("<<<<11010x10xxxxxxxx1011xxxxxxx0", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create); SetA32("111101001x00xxxxxxxx<<11xxxxxxxx", InstName.Vst4, InstEmit32.Vst4, OpCode32SimdMemSingle.Create);
SetA32("<<<<11001x00xxxxxxxx1010xxxxxxxx", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create); SetA32("111101000x00xxxxxxxx000xxxxxxxxx", InstName.Vst4, InstEmit32.Vst4, OpCode32SimdMemPair.Create); // Inc = 1/2 (itype).
SetA32("<<<<11001x10xxxxxxxx1010xxxxxxxx", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create); SetA32("<<<<11001x00xxxxxxxx1011xxxxxxx0", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create);
SetA32("<<<<11010x10xxxxxxxx1010xxxxxxxx", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create); SetA32("<<<<11001x10xxxxxxxx1011xxxxxxx0", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create);
SetA32("<<<<1101xx00xxxxxxxx101xxxxxxxxx", InstName.Vstr, InstEmit32.Vstr, OpCode32SimdMemImm.Create); SetA32("<<<<11010x10xxxxxxxx1011xxxxxxx0", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create);
SetA32("111100110xxxxxxxxxxx1000xxx0xxxx", InstName.Vsub, InstEmit32.Vsub_I, OpCode32SimdReg.Create); SetA32("<<<<11001x00xxxxxxxx1010xxxxxxxx", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create);
SetA32("<<<<11100x11xxxxxxxx101xx1x0xxxx", InstName.Vsub, InstEmit32.Vsub_S, OpCode32SimdRegS.Create); SetA32("<<<<11001x10xxxxxxxx1010xxxxxxxx", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create);
SetA32("111100100x10xxxxxxxx1101xxx0xxxx", InstName.Vsub, InstEmit32.Vsub_V, OpCode32SimdReg.Create); SetA32("<<<<11010x10xxxxxxxx1010xxxxxxxx", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create);
SetA32("1111001x1x<<xxxxxxxx0011x0x0xxxx", InstName.Vsubw, InstEmit32.Vsubw_I, OpCode32SimdRegWide.Create); SetA32("<<<<1101xx00xxxxxxxx101xxxxxxxxx", InstName.Vstr, InstEmit32.Vstr, OpCode32SimdMemImm.Create);
SetA32("111100111x11xxxxxxxx10xxxxx0xxxx", InstName.Vtbl, InstEmit32.Vtbl, OpCode32SimdTbl.Create); SetA32("111100110xxxxxxxxxxx1000xxx0xxxx", InstName.Vsub, InstEmit32.Vsub_I, OpCode32SimdReg.Create);
SetA32("111100111x11<<10xxxx00001xx0xxxx", InstName.Vtrn, InstEmit32.Vtrn, OpCode32SimdCmpZ.Create); SetA32("<<<<11100x11xxxxxxxx101xx1x0xxxx", InstName.Vsub, InstEmit32.Vsub_S, OpCode32SimdRegS.Create);
SetA32("111100100x<<xxxxxxxx1000xxx1xxxx", InstName.Vtst, InstEmit32.Vtst, OpCode32SimdReg.Create); SetA32("111100100x10xxxxxxxx1101xxx0xxxx", InstName.Vsub, InstEmit32.Vsub_V, OpCode32SimdReg.Create);
SetA32("111100111x11<<10xxxx00010xx0xxxx", InstName.Vuzp, InstEmit32.Vuzp, OpCode32SimdCmpZ.Create); SetA32("1111001x1x<<xxxxxxxx0011x0x0xxxx", InstName.Vsubw, InstEmit32.Vsubw_I, OpCode32SimdRegWide.Create);
SetA32("111100111x11<<10xxxx00011xx0xxxx", InstName.Vzip, InstEmit32.Vzip, OpCode32SimdCmpZ.Create); SetA32("111100111x11xxxxxxxx10xxxxx0xxxx", InstName.Vtbl, InstEmit32.Vtbl, OpCode32SimdTbl.Create);
SetA32("111100111x11<<10xxxx00001xx0xxxx", InstName.Vtrn, InstEmit32.Vtrn, OpCode32SimdCmpZ.Create);
SetA32("111100100x<<xxxxxxxx1000xxx1xxxx", InstName.Vtst, InstEmit32.Vtst, OpCode32SimdReg.Create);
SetA32("111100111x11<<10xxxx00010xx0xxxx", InstName.Vuzp, InstEmit32.Vuzp, OpCode32SimdCmpZ.Create);
SetA32("111100111x11<<10xxxx00011xx0xxxx", InstName.Vzip, InstEmit32.Vzip, OpCode32SimdCmpZ.Create);
#endregion #endregion
#region "OpCode Table (AArch32, T16)" #region "OpCode Table (AArch32, T16)"

View File

@@ -0,0 +1,64 @@
using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation;
using static ARMeilleure.Instructions.InstEmitHelper;
namespace ARMeilleure.Instructions
{
static partial class InstEmit32
{
#region "Sha256"
public static void Sha256h_V(ArmEmitterContext context)
{
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
Operand d = GetVecA32(op.Qd);
Operand n = GetVecA32(op.Qn);
Operand m = GetVecA32(op.Qm);
Operand res = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashLower)), d, n, m);
context.Copy(GetVecA32(op.Qd), res);
}
public static void Sha256h2_V(ArmEmitterContext context)
{
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
Operand d = GetVecA32(op.Qd);
Operand n = GetVecA32(op.Qn);
Operand m = GetVecA32(op.Qm);
Operand res = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashUpper)), d, n, m);
context.Copy(GetVecA32(op.Qd), res);
}
public static void Sha256su0_V(ArmEmitterContext context)
{
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
Operand d = GetVecA32(op.Qd);
Operand m = GetVecA32(op.Qm);
Operand res = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart1)), d, m);
context.Copy(GetVecA32(op.Qd), res);
}
public static void Sha256su1_V(ArmEmitterContext context)
{
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
Operand d = GetVecA32(op.Qd);
Operand n = GetVecA32(op.Qn);
Operand m = GetVecA32(op.Qm);
Operand res = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart2)), d, n, m);
context.Copy(GetVecA32(op.Qd), res);
}
#endregion
}
}

View File

@@ -169,6 +169,31 @@ namespace ARMeilleure.Instructions
SetIntA32(context, op.CRn, context.ConvertI64ToI32(context.ShiftRightUI(result, Const(32)))); SetIntA32(context, op.CRn, context.ConvertI64ToI32(context.ShiftRightUI(result, Const(32))));
} }
public static void Mrs(ArmEmitterContext context)
{
OpCode32Mrs op = (OpCode32Mrs)context.CurrOp;
if (op.R)
{
throw new NotImplementedException("SPSR");
}
else
{
Operand vSh = context.ShiftLeft(GetFlag(PState.VFlag), Const((int)PState.VFlag));
Operand cSh = context.ShiftLeft(GetFlag(PState.CFlag), Const((int)PState.CFlag));
Operand zSh = context.ShiftLeft(GetFlag(PState.ZFlag), Const((int)PState.ZFlag));
Operand nSh = context.ShiftLeft(GetFlag(PState.NFlag), Const((int)PState.NFlag));
Operand qSh = context.ShiftLeft(GetFlag(PState.QFlag), Const((int)PState.QFlag));
Operand spsr = context.BitwiseOr(context.BitwiseOr(nSh, zSh), context.BitwiseOr(cSh, vSh));
spsr = context.BitwiseOr(spsr, qSh);
// TODO: Remaining flags.
SetIntA32(context, op.Rd, spsr);
}
}
public static void Msr(ArmEmitterContext context) public static void Msr(ArmEmitterContext context)
{ {
OpCode32MsrReg op = (OpCode32MsrReg)context.CurrOp; OpCode32MsrReg op = (OpCode32MsrReg)context.CurrOp;

View File

@@ -76,7 +76,7 @@ namespace Ryujinx.Audio.Renderer.Dsp
if (!info.DecodingBehaviour.HasFlag(DecodingBehaviour.SkipPitchAndSampleRateConversion)) if (!info.DecodingBehaviour.HasFlag(DecodingBehaviour.SkipPitchAndSampleRateConversion))
{ {
voiceState.Pitch.ToSpan().Slice(0, pitchMaxLength).CopyTo(tempBuffer); voiceState.Pitch.AsSpan().Slice(0, pitchMaxLength).CopyTo(tempBuffer);
tempBufferIndex += pitchMaxLength; tempBufferIndex += pitchMaxLength;
} }
@@ -239,7 +239,7 @@ namespace Ryujinx.Audio.Renderer.Dsp
ResamplerHelper.Resample(outputBuffer, tempBuffer, sampleRateRatio, ref fraction, sampleCountToProcess, info.SrcQuality, y != sourceSampleCountToProcess || info.Pitch != 1.0f); ResamplerHelper.Resample(outputBuffer, tempBuffer, sampleRateRatio, ref fraction, sampleCountToProcess, info.SrcQuality, y != sourceSampleCountToProcess || info.Pitch != 1.0f);
tempBuffer.Slice(sampleCountToDecode, pitchMaxLength).CopyTo(voiceState.Pitch.ToSpan()); tempBuffer.Slice(sampleCountToDecode, pitchMaxLength).CopyTo(voiceState.Pitch.AsSpan());
} }
i += sampleCountToProcess; i += sampleCountToProcess;

View File

@@ -24,8 +24,8 @@ namespace Ryujinx.Audio.Renderer.Parameter.Effect
/// </summary> /// </summary>
public void Reset() public void Reset()
{ {
InputMax.ToSpan().Fill(0.0f); InputMax.AsSpan().Fill(0.0f);
CompressionGainMin.ToSpan().Fill(1.0f); CompressionGainMin.AsSpan().Fill(1.0f);
} }
} }
} }

View File

@@ -141,7 +141,7 @@ namespace Ryujinx.Audio.Renderer.Server
Memory<byte> biquadStateRawMemory = SpanMemoryManager<byte>.Cast(state).Slice(VoiceUpdateState.BiquadStateOffset, VoiceUpdateState.BiquadStateSize * Constants.VoiceBiquadFilterCount); Memory<byte> biquadStateRawMemory = SpanMemoryManager<byte>.Cast(state).Slice(VoiceUpdateState.BiquadStateOffset, VoiceUpdateState.BiquadStateSize * Constants.VoiceBiquadFilterCount);
Memory<BiquadFilterState> stateMemory = SpanMemoryManager<BiquadFilterState>.Cast(biquadStateRawMemory); Memory<BiquadFilterState> stateMemory = SpanMemoryManager<BiquadFilterState>.Cast(biquadStateRawMemory);
_commandBuffer.GenerateGroupedBiquadFilter(baseIndex, voiceState.BiquadFilters.ToSpan(), stateMemory, bufferOffset, bufferOffset, voiceState.BiquadFilterNeedInitialization, nodeId); _commandBuffer.GenerateGroupedBiquadFilter(baseIndex, voiceState.BiquadFilters.AsSpan(), stateMemory, bufferOffset, bufferOffset, voiceState.BiquadFilterNeedInitialization, nodeId);
} }
else else
{ {
@@ -337,8 +337,8 @@ namespace Ryujinx.Audio.Renderer.Server
GeneratePerformance(ref performanceEntry, PerformanceCommand.Type.Start, nodeId); GeneratePerformance(ref performanceEntry, PerformanceCommand.Type.Start, nodeId);
} }
GenerateVoiceMix(channelResource.Mix.ToSpan(), GenerateVoiceMix(channelResource.Mix.AsSpan(),
channelResource.PreviousMix.ToSpan(), channelResource.PreviousMix.AsSpan(),
dspStateMemory, dspStateMemory,
mix.BufferOffset, mix.BufferOffset,
mix.BufferCount, mix.BufferCount,
@@ -505,8 +505,8 @@ namespace Ryujinx.Audio.Renderer.Server
BiquadFilterParameter parameter = new BiquadFilterParameter(); BiquadFilterParameter parameter = new BiquadFilterParameter();
parameter.Enable = true; parameter.Enable = true;
effect.Parameter.Denominator.ToSpan().CopyTo(parameter.Denominator.ToSpan()); effect.Parameter.Denominator.AsSpan().CopyTo(parameter.Denominator.AsSpan());
effect.Parameter.Numerator.ToSpan().CopyTo(parameter.Numerator.ToSpan()); effect.Parameter.Numerator.AsSpan().CopyTo(parameter.Numerator.AsSpan());
for (int i = 0; i < effect.Parameter.ChannelCount; i++) for (int i = 0; i < effect.Parameter.ChannelCount; i++)
{ {
@@ -923,8 +923,8 @@ namespace Ryujinx.Audio.Renderer.Server
if (useCustomDownMixingCommand) if (useCustomDownMixingCommand)
{ {
_commandBuffer.GenerateDownMixSurroundToStereo(finalMix.BufferOffset, _commandBuffer.GenerateDownMixSurroundToStereo(finalMix.BufferOffset,
sink.Parameter.Input.ToSpan(), sink.Parameter.Input.AsSpan(),
sink.Parameter.Input.ToSpan(), sink.Parameter.Input.AsSpan(),
sink.DownMixCoefficients, sink.DownMixCoefficients,
Constants.InvalidNodeId); Constants.InvalidNodeId);
} }
@@ -932,8 +932,8 @@ namespace Ryujinx.Audio.Renderer.Server
else if (_rendererContext.ChannelCount == 2 && sink.Parameter.InputCount == 6) else if (_rendererContext.ChannelCount == 2 && sink.Parameter.InputCount == 6)
{ {
_commandBuffer.GenerateDownMixSurroundToStereo(finalMix.BufferOffset, _commandBuffer.GenerateDownMixSurroundToStereo(finalMix.BufferOffset,
sink.Parameter.Input.ToSpan(), sink.Parameter.Input.AsSpan(),
sink.Parameter.Input.ToSpan(), sink.Parameter.Input.AsSpan(),
Constants.DefaultSurroundToStereoCoefficients, Constants.DefaultSurroundToStereoCoefficients,
Constants.InvalidNodeId); Constants.InvalidNodeId);
} }
@@ -945,7 +945,7 @@ namespace Ryujinx.Audio.Renderer.Server
_commandBuffer.GenerateUpsample(finalMix.BufferOffset, _commandBuffer.GenerateUpsample(finalMix.BufferOffset,
sink.UpsamplerState, sink.UpsamplerState,
sink.Parameter.InputCount, sink.Parameter.InputCount,
sink.Parameter.Input.ToSpan(), sink.Parameter.Input.AsSpan(),
commandList.BufferCount, commandList.BufferCount,
commandList.SampleCount, commandList.SampleCount,
commandList.SampleRate, commandList.SampleRate,

View File

@@ -63,10 +63,10 @@ namespace Ryujinx.Audio.Renderer.Server.Sink
else else
{ {
Parameter.DownMixParameterEnabled = inputDeviceParameter.DownMixParameterEnabled; Parameter.DownMixParameterEnabled = inputDeviceParameter.DownMixParameterEnabled;
inputDeviceParameter.DownMixParameter.ToSpan().CopyTo(Parameter.DownMixParameter.ToSpan()); inputDeviceParameter.DownMixParameter.AsSpan().CopyTo(Parameter.DownMixParameter.AsSpan());
} }
Parameter.DownMixParameter.ToSpan().CopyTo(DownMixCoefficients.AsSpan()); Parameter.DownMixParameter.AsSpan().CopyTo(DownMixCoefficients.AsSpan());
errorInfo = new BehaviourParameter.ErrorInfo(); errorInfo = new BehaviourParameter.ErrorInfo();
outStatus = new SinkOutStatus(); outStatus = new SinkOutStatus();

View File

@@ -119,7 +119,7 @@ namespace Ryujinx.Audio.Renderer.Server
ref VoiceChannelResource resource = ref context.GetChannelResource(i); ref VoiceChannelResource resource = ref context.GetChannelResource(i);
resource.Id = parameter.Id; resource.Id = parameter.Id;
parameter.Mix.ToSpan().CopyTo(resource.Mix.ToSpan()); parameter.Mix.AsSpan().CopyTo(resource.Mix.AsSpan());
resource.IsUsed = parameter.IsUsed; resource.IsUsed = parameter.IsUsed;
} }
@@ -587,7 +587,7 @@ namespace Ryujinx.Audio.Renderer.Server
{ {
ref BehaviourErrorInfoOutStatus outStatus = ref SpanIOHelper.GetWriteRef<BehaviourErrorInfoOutStatus>(ref _output)[0]; ref BehaviourErrorInfoOutStatus outStatus = ref SpanIOHelper.GetWriteRef<BehaviourErrorInfoOutStatus>(ref _output)[0];
_behaviourContext.CopyErrorInfo(outStatus.ErrorInfos.ToSpan(), out outStatus.ErrorInfosCount); _behaviourContext.CopyErrorInfo(outStatus.ErrorInfos.AsSpan(), out outStatus.ErrorInfosCount);
OutputHeader.BehaviourSize = (uint)Unsafe.SizeOf<BehaviourErrorInfoOutStatus>(); OutputHeader.BehaviourSize = (uint)Unsafe.SizeOf<BehaviourErrorInfoOutStatus>();
OutputHeader.TotalSize += OutputHeader.BehaviourSize; OutputHeader.TotalSize += OutputHeader.BehaviourSize;

View File

@@ -34,7 +34,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
public void UpdateState() public void UpdateState()
{ {
Mix.ToSpan().CopyTo(PreviousMix.ToSpan()); Mix.AsSpan().CopyTo(PreviousMix.AsSpan());
} }
} }
} }

View File

@@ -202,7 +202,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
Pitch = 0.0f; Pitch = 0.0f;
Volume = 0.0f; Volume = 0.0f;
PreviousVolume = 0.0f; PreviousVolume = 0.0f;
BiquadFilters.ToSpan().Fill(new BiquadFilterParameter()); BiquadFilters.AsSpan().Fill(new BiquadFilterParameter());
WaveBuffersCount = 0; WaveBuffersCount = 0;
WaveBuffersIndex = 0; WaveBuffersIndex = 0;
MixId = Constants.UnusedMixId; MixId = Constants.UnusedMixId;
@@ -288,7 +288,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
ChannelsCount = parameter.ChannelCount; ChannelsCount = parameter.ChannelCount;
Pitch = parameter.Pitch; Pitch = parameter.Pitch;
Volume = parameter.Volume; Volume = parameter.Volume;
parameter.BiquadFilters.ToSpan().CopyTo(BiquadFilters.ToSpan()); parameter.BiquadFilters.AsSpan().CopyTo(BiquadFilters.AsSpan());
WaveBuffersCount = parameter.WaveBuffersCount; WaveBuffersCount = parameter.WaveBuffersCount;
WaveBuffersIndex = parameter.WaveBuffersIndex; WaveBuffersIndex = parameter.WaveBuffersIndex;
@@ -308,7 +308,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
SplitterId = Constants.UnusedSplitterId; SplitterId = Constants.UnusedSplitterId;
} }
parameter.ChannelResourceIds.ToSpan().CopyTo(ChannelResourceIds.ToSpan()); parameter.ChannelResourceIds.AsSpan().CopyTo(ChannelResourceIds.AsSpan());
DecodingBehaviour behaviour = DecodingBehaviour.Default; DecodingBehaviour behaviour = DecodingBehaviour.Default;
@@ -638,7 +638,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
voiceUpdateState.Offset = 0; voiceUpdateState.Offset = 0;
voiceUpdateState.PlayedSampleCount = 0; voiceUpdateState.PlayedSampleCount = 0;
voiceUpdateState.Pitch.ToSpan().Fill(0); voiceUpdateState.Pitch.AsSpan().Fill(0);
voiceUpdateState.Fraction = 0; voiceUpdateState.Fraction = 0;
voiceUpdateState.LoopContext = new Dsp.State.AdpcmLoopContext(); voiceUpdateState.LoopContext = new Dsp.State.AdpcmLoopContext();
} }
@@ -650,7 +650,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
case Types.PlayState.Stopped: case Types.PlayState.Stopped:
case Types.PlayState.Paused: case Types.PlayState.Paused:
foreach (ref WaveBuffer wavebuffer in WaveBuffers.ToSpan()) foreach (ref WaveBuffer wavebuffer in WaveBuffers.AsSpan())
{ {
wavebuffer.BufferAddressInfo.GetReference(true); wavebuffer.BufferAddressInfo.GetReference(true);
wavebuffer.ContextAddressInfo.GetReference(true); wavebuffer.ContextAddressInfo.GetReference(true);

View File

@@ -12,6 +12,7 @@ using Ryujinx.Audio.Integration;
using Ryujinx.Ava.Common; using Ryujinx.Ava.Common;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Input; using Ryujinx.Ava.Input;
using Ryujinx.Ava.Ui.Backend.Vulkan;
using Ryujinx.Ava.Ui.Controls; using Ryujinx.Ava.Ui.Controls;
using Ryujinx.Ava.Ui.Models; using Ryujinx.Ava.Ui.Models;
using Ryujinx.Ava.Ui.Vulkan; using Ryujinx.Ava.Ui.Vulkan;
@@ -334,6 +335,8 @@ namespace Ryujinx.Ava
return; return;
} }
AvaloniaLocator.Current.GetService<VulkanPlatformInterface>()?.MainSurface.Display.ChangeVSyncMode(true);
_isStopped = true; _isStopped = true;
_isActive = false; _isActive = false;
} }
@@ -596,12 +599,13 @@ namespace Ryujinx.Ava
if (Program.UseVulkan) if (Program.UseVulkan)
{ {
var vulkan = AvaloniaLocator.Current.GetService<VulkanPlatformInterface>(); var vulkan = AvaloniaLocator.Current.GetService<VulkanPlatformInterface>();
renderer = new VulkanRenderer(vulkan.Instance.InternalHandle, renderer = new VulkanRenderer(vulkan.Instance.InternalHandle,
vulkan.Device.InternalHandle, vulkan.MainSurface.Device.InternalHandle,
vulkan.PhysicalDevice.InternalHandle, vulkan.PhysicalDevice.InternalHandle,
vulkan.Device.Queue.InternalHandle, vulkan.MainSurface.Device.Queue.InternalHandle,
vulkan.PhysicalDevice.QueueFamilyIndex, vulkan.PhysicalDevice.QueueFamilyIndex,
vulkan.Device.Lock); vulkan.MainSurface.Device.Lock);
} }
else else
{ {
@@ -775,7 +779,10 @@ namespace Ryujinx.Ava
Width = (int)e.Width; Width = (int)e.Width;
Height = (int)e.Height; Height = (int)e.Height;
SetRendererWindowSize(e); if (!Program.UseVulkan)
{
SetRendererWindowSize(e);
}
} }
private void MainLoop() private void MainLoop()
@@ -815,12 +822,11 @@ namespace Ryujinx.Ava
_renderer.ScreenCaptured += Renderer_ScreenCaptured; _renderer.ScreenCaptured += Renderer_ScreenCaptured;
if (!Program.UseVulkan) (_renderer as OpenGLRenderer)?.InitializeBackgroundContext(SPBOpenGLContext.CreateBackgroundContext((Renderer as OpenGLRendererControl).GameContext));
{
(_renderer as OpenGLRenderer).InitializeBackgroundContext(SPBOpenGLContext.CreateBackgroundContext((Renderer as OpenGLRendererControl).GameContext));
Renderer.MakeCurrent(); Renderer.MakeCurrent();
}
AvaloniaLocator.Current.GetService<VulkanPlatformInterface>()?.MainSurface?.Display?.ChangeVSyncMode(Device.EnableDeviceVsync);
Device.Gpu.Renderer.Initialize(_glLogLevel); Device.Gpu.Renderer.Initialize(_glLogLevel);
@@ -837,8 +843,6 @@ namespace Ryujinx.Ava
Renderer.Start(); Renderer.Start();
Renderer.QueueRender();
while (_isActive) while (_isActive)
{ {
if (Device.WaitFifo()) if (Device.WaitFifo())
@@ -889,6 +893,16 @@ namespace Ryujinx.Ava
$"FIFO: {Device.Statistics.GetFifoPercent():00.00} %", $"FIFO: {Device.Statistics.GetFifoPercent():00.00} %",
$"GPU: {_renderer.GetHardwareInfo().GpuVendor}")); $"GPU: {_renderer.GetHardwareInfo().GpuVendor}"));
if (Program.UseVulkan)
{
var platformInterface = AvaloniaLocator.Current.GetService<VulkanPlatformInterface>();
if (platformInterface.MainSurface.Display.IsSurfaceChanged())
{
SetRendererWindowSize(new Size(Width, Height));
return;
}
}
Renderer.Present(image); Renderer.Present(image);
} }
@@ -970,6 +984,9 @@ namespace Ryujinx.Ava
{ {
case KeyboardHotkeyState.ToggleVSync: case KeyboardHotkeyState.ToggleVSync:
Device.EnableDeviceVsync = !Device.EnableDeviceVsync; Device.EnableDeviceVsync = !Device.EnableDeviceVsync;
AvaloniaLocator.Current.GetService<VulkanPlatformInterface>()?.MainSurface?.Display?.ChangeVSyncMode(Device.EnableDeviceVsync);
break; break;
case KeyboardHotkeyState.Screenshot: case KeyboardHotkeyState.Screenshot:
ScreenshotRequested = true; ScreenshotRequested = true;

View File

@@ -0,0 +1,581 @@
{
"MenuBarFileOpenApplet": "アプレットを開く",
"MenuBarFileOpenAppletOpenMiiAppletToolTip": "スタンドアロンモードで Mii エディタアプレットを開きます",
"SettingsTabInputDirectMouseAccess": "マウス直接アクセス",
"SettingsTabSystemMemoryManagerMode": "メモリ管理モード:",
"SettingsTabSystemMemoryManagerModeSoftware": "ソフトウェア",
"SettingsTabSystemMemoryManagerModeHost": "ホスト (高速)",
"SettingsTabSystemMemoryManagerModeHostUnchecked": "ホスト, チェックなし (最高速, 安全でない)",
"MenuBarFile": "ファイル(_F)",
"MenuBarFileOpenFromFile": "ファイルからアプリケーションをロード(_L)",
"MenuBarFileOpenUnpacked": "展開されたゲームをロード",
"MenuBarFileOpenEmuFolder": "Ryujinx フォルダを開く",
"MenuBarFileOpenLogsFolder": "ログフォルダを開く",
"MenuBarFileExit": "終了(_E)",
"MenuBarOptions": "オプション",
"MenuBarOptionsToggleFullscreen": "全画面切り替え",
"MenuBarOptionsStartGamesInFullscreen": "全画面モードでゲームを開始",
"MenuBarOptionsStopEmulation": "エミュレーションを停止",
"MenuBarOptionsSettings": "設定(_S)",
"MenuBarOptionsManageUserProfiles": "ユーザプロファイルを管理(_M)",
"MenuBarActions": "アクション(_A)",
"MenuBarOptionsSimulateWakeUpMessage": "スリープ復帰メッセージをシミュレート",
"MenuBarActionsScanAmiibo": "Amiibo をスキャン",
"MenuBarTools": "ツール(_T)",
"MenuBarToolsInstallFirmware": "ファームウェアをインストール",
"MenuBarFileToolsInstallFirmwareFromFile": "XCI または ZIP からファームウェアをインストール",
"MenuBarFileToolsInstallFirmwareFromDirectory": "ディレクトリからファームウェアをインストール",
"MenuBarHelp": "ヘルプ",
"MenuBarHelpCheckForUpdates": "アップデートを確認",
"MenuBarHelpAbout": "Ryujinx について",
"MenuSearch": "検索...",
"GameListHeaderFavorite": "お気に入り",
"GameListHeaderIcon": "アイコン",
"GameListHeaderApplication": "名称",
"GameListHeaderDeveloper": "開発元",
"GameListHeaderVersion": "バージョン",
"GameListHeaderTimePlayed": "プレイ時間",
"GameListHeaderLastPlayed": "最終プレイ日時",
"GameListHeaderFileExtension": "ファイル拡張子",
"GameListHeaderFileSize": "ファイルサイズ",
"GameListHeaderPath": "パス",
"GameListContextMenuOpenUserSaveDirectory": "セーブディレクトリを開く",
"GameListContextMenuOpenUserSaveDirectoryToolTip": "アプリケーションのユーザセーブデータを格納するディレクトリを開きます",
"GameListContextMenuOpenUserDeviceDirectory": "デバイスディレクトリを開く",
"GameListContextMenuOpenUserDeviceDirectoryToolTip": "アプリケーションのデバイスセーブデータを格納するディレクトリを開きます",
"GameListContextMenuOpenUserBcatDirectory": "BCATディレクトリを開く",
"GameListContextMenuOpenUserBcatDirectoryToolTip": "アプリケーションの BCAT セーブデータを格納するディレクトリを開きます",
"GameListContextMenuManageTitleUpdates": "アップデートを管理",
"GameListContextMenuManageTitleUpdatesToolTip": "タイトルのアップデート管理ウインドウを開きます",
"GameListContextMenuManageDlc": "DLCを管理",
"GameListContextMenuManageDlcToolTip": "DLC管理ウインドウを開きます",
"GameListContextMenuOpenModsDirectory": "Modディレクトリを開く",
"GameListContextMenuOpenModsDirectoryToolTip": "アプリケーションの Mod データを格納するディレクトリを開きます",
"GameListContextMenuCacheManagement": "キャッシュ管理",
"GameListContextMenuCacheManagementPurgePptc": "PPTC キャッシュを破棄",
"GameListContextMenuCacheManagementPurgePptcToolTip": "アプリケーションの PPTC キャッシュを破棄します",
"GameListContextMenuCacheManagementPurgeShaderCache": "シェーダキャッシュを破棄",
"GameListContextMenuCacheManagementPurgeShaderCacheToolTip": "アプリケーションのシェーダキャッシュを破棄します",
"GameListContextMenuCacheManagementOpenPptcDirectory": "PPTC ディレクトリを開く",
"GameListContextMenuCacheManagementOpenPptcDirectoryToolTip": "アプリケーションの PPTC キャッシュを格納するディレクトリを開きます",
"GameListContextMenuCacheManagementOpenShaderCacheDirectory": "シェーダキャッシュディレクトリを開く",
"GameListContextMenuCacheManagementOpenShaderCacheDirectoryToolTip": "アプリケーションのシェーダキャッシュを格納するディレクトリを開きます",
"GameListContextMenuExtractData": "データを展開",
"GameListContextMenuExtractDataExeFS": "ExeFS",
"GameListContextMenuExtractDataExeFSToolTip": "現在のアプリケーション設定(アップデート含む)から ExeFS セクションを展開します",
"GameListContextMenuExtractDataRomFS": "RomFS",
"GameListContextMenuExtractDataRomFSToolTip": "現在のアプリケーション設定(アップデート含む)から RomFS セクションを展開します",
"GameListContextMenuExtractDataLogo": "ロゴ",
"GameListContextMenuExtractDataLogoToolTip": "現在のアプリケーション設定(アップデート含む)からロゴセクションを展開します",
"StatusBarGamesLoaded": "{0}/{1} ゲーム",
"StatusBarSystemVersion": "システムバージョン: {0}",
"Settings": "設定",
"SettingsTabGeneral": "ユーザインタフェース",
"SettingsTabGeneralGeneral": "一般",
"SettingsTabGeneralEnableDiscordRichPresence": "Discord リッチプレゼンスを有効",
"SettingsTabGeneralCheckUpdatesOnLaunch": "起動時にアップデートを確認",
"SettingsTabGeneralShowConfirmExitDialog": "\"終了を確認\" ダイアログを表示",
"SettingsTabGeneralHideCursorOnIdle": "アイドル時にカーソルを隠す",
"SettingsTabGeneralGameDirectories": "ゲームディレクトリ",
"SettingsTabGeneralAdd": "追加",
"SettingsTabGeneralRemove": "削除",
"SettingsTabSystem": "システム",
"SettingsTabSystemCore": "コア",
"SettingsTabSystemSystemRegion": "地域:",
"SettingsTabSystemSystemRegionJapan": "日本",
"SettingsTabSystemSystemRegionUSA": "アメリカ",
"SettingsTabSystemSystemRegionEurope": "ヨーロッパ",
"SettingsTabSystemSystemRegionAustralia": "オーストラリア",
"SettingsTabSystemSystemRegionChina": "中国",
"SettingsTabSystemSystemRegionKorea": "韓国",
"SettingsTabSystemSystemRegionTaiwan": "台湾",
"SettingsTabSystemSystemLanguage": "言語:",
"SettingsTabSystemSystemLanguageJapanese": "日本語",
"SettingsTabSystemSystemLanguageAmericanEnglish": "英語(アメリカ)",
"SettingsTabSystemSystemLanguageFrench": "フランス語",
"SettingsTabSystemSystemLanguageGerman": "ドイツ語",
"SettingsTabSystemSystemLanguageItalian": "イタリア語",
"SettingsTabSystemSystemLanguageSpanish": "スペイン語",
"SettingsTabSystemSystemLanguageChinese": "中国語",
"SettingsTabSystemSystemLanguageKorean": "韓国語",
"SettingsTabSystemSystemLanguageDutch": "オランダ語",
"SettingsTabSystemSystemLanguagePortuguese": "ポルトガル語",
"SettingsTabSystemSystemLanguageRussian": "ロシア語",
"SettingsTabSystemSystemLanguageTaiwanese": "台湾語",
"SettingsTabSystemSystemLanguageBritishEnglish": "英語(イギリス)",
"SettingsTabSystemSystemLanguageCanadianFrench": "フランス語(カナダ)",
"SettingsTabSystemSystemLanguageLatinAmericanSpanish": "スペイン語(ラテンアメリカ)",
"SettingsTabSystemSystemLanguageSimplifiedChinese": "中国語",
"SettingsTabSystemSystemLanguageTraditionalChinese": "台湾語",
"SettingsTabSystemSystemTimeZone": "タイムゾーン:",
"SettingsTabSystemSystemTime": "時刻:",
"SettingsTabSystemEnableVsync": "VSync",
"SettingsTabSystemEnablePptc": "PPTC (Profiled Persistent Translation Cache)",
"SettingsTabSystemEnableFsIntegrityChecks": "ファイルシステム整合性チェック",
"SettingsTabSystemAudioBackend": "音声バックエンド:",
"SettingsTabSystemAudioBackendDummy": "ダミー",
"SettingsTabSystemAudioBackendOpenAL": "OpenAL",
"SettingsTabSystemAudioBackendSoundIO": "SoundIO",
"SettingsTabSystemAudioBackendSDL2": "SDL2",
"SettingsTabSystemHacks": "ハック",
"SettingsTabSystemHacksNote": " (挙動が不安定になる可能性があります)",
"SettingsTabSystemExpandDramSize": "DRAMサイズを6GBに拡大",
"SettingsTabSystemIgnoreMissingServices": "未実装サービスを無視",
"SettingsTabGraphics": "グラフィクス",
"SettingsTabGraphicsEnhancements": "拡張",
"SettingsTabGraphicsEnableShaderCache": "シェーダキャッシュ",
"SettingsTabGraphicsAnisotropicFiltering": "異方性フィルタリング:",
"SettingsTabGraphicsAnisotropicFilteringAuto": "自動",
"SettingsTabGraphicsAnisotropicFiltering2x": "2x",
"SettingsTabGraphicsAnisotropicFiltering4x": "4x",
"SettingsTabGraphicsAnisotropicFiltering8x": "8x",
"SettingsTabGraphicsAnisotropicFiltering16x": "16x",
"SettingsTabGraphicsResolutionScale": "解像度:",
"SettingsTabGraphicsResolutionScaleCustom": "カスタム (非推奨)",
"SettingsTabGraphicsResolutionScaleNative": "ネイティブ (720p/1080p)",
"SettingsTabGraphicsResolutionScale2x": "2x (1440p/2160p)",
"SettingsTabGraphicsResolutionScale3x": "3x (2160p/3240p)",
"SettingsTabGraphicsResolutionScale4x": "4x (2880p/4320p)",
"SettingsTabGraphicsAspectRatio": "アスペクト比:",
"SettingsTabGraphicsAspectRatio4x3": "4:3",
"SettingsTabGraphicsAspectRatio16x9": "16:9",
"SettingsTabGraphicsAspectRatio16x10": "16:10",
"SettingsTabGraphicsAspectRatio21x9": "21:9",
"SettingsTabGraphicsAspectRatio32x9": "32:9",
"SettingsTabGraphicsAspectRatioStretch": "ウインドウサイズに合わせる",
"SettingsTabGraphicsDeveloperOptions": "開発者向けオプション",
"SettingsTabGraphicsShaderDumpPath": "グラフィクス シェーダダンプパス:",
"SettingsTabLogging": "ロギング",
"SettingsTabLoggingLogging": "ロギング",
"SettingsTabLoggingEnableLoggingToFile": "ファイルへのロギングを有効",
"SettingsTabLoggingEnableStubLogs": "Stub ログを有効",
"SettingsTabLoggingEnableInfoLogs": "Info ログを有効",
"SettingsTabLoggingEnableWarningLogs": "Warning ログを有効",
"SettingsTabLoggingEnableErrorLogs": "Error ログを有効",
"SettingsTabLoggingEnableTraceLogs": "Trace ログを有効",
"SettingsTabLoggingEnableGuestLogs": "Guest ログを有効",
"SettingsTabLoggingEnableFsAccessLogs": "Fs アクセスログを有効",
"SettingsTabLoggingFsGlobalAccessLogMode": "Fs グローバルアクセスログモード:",
"SettingsTabLoggingDeveloperOptions": "開発者オプション (警告: パフォーマンスが低下します)",
"SettingsTabLoggingOpenglLogLevel": "OpenGL ログレベル:",
"SettingsTabLoggingOpenglLogLevelNone": "なし",
"SettingsTabLoggingOpenglLogLevelError": "エラー",
"SettingsTabLoggingOpenglLogLevelPerformance": "パフォーマンス低下",
"SettingsTabLoggingOpenglLogLevelAll": "すべて",
"SettingsTabLoggingEnableDebugLogs": "デバッグログを有効",
"SettingsTabInput": "入力",
"SettingsTabInputEnableDockedMode": "ドッキングモード",
"SettingsTabInputDirectKeyboardAccess": "キーボード直接アクセス",
"SettingsButtonSave": "セーブ",
"SettingsButtonClose": "閉じる",
"SettingsButtonApply": "適用",
"ControllerSettingsPlayer": "プレイヤー",
"ControllerSettingsPlayer1": "プレイヤー 1",
"ControllerSettingsPlayer2": "プレイヤー 2",
"ControllerSettingsPlayer3": "プレイヤー 3",
"ControllerSettingsPlayer4": "プレイヤー 4",
"ControllerSettingsPlayer5": "プレイヤー 5",
"ControllerSettingsPlayer6": "プレイヤー 6",
"ControllerSettingsPlayer7": "プレイヤー 7",
"ControllerSettingsPlayer8": "プレイヤー 8",
"ControllerSettingsHandheld": "携帯",
"ControllerSettingsInputDevice": "入力デバイス",
"ControllerSettingsRefresh": "更新",
"ControllerSettingsDeviceDisabled": "無効",
"ControllerSettingsControllerType": "コントローラ種別",
"ControllerSettingsControllerTypeHandheld": "携帯",
"ControllerSettingsControllerTypeProController": "Pro コントローラ",
"ControllerSettingsControllerTypeJoyConPair": "JoyCon ペア",
"ControllerSettingsControllerTypeJoyConLeft": "JoyCon 左",
"ControllerSettingsControllerTypeJoyConRight": "JoyCon 右",
"ControllerSettingsProfile": "プロファイル",
"ControllerSettingsProfileDefault": "デフォルト",
"ControllerSettingsLoad": "ロード",
"ControllerSettingsAdd": "追加",
"ControllerSettingsRemove": "削除",
"ControllerSettingsButtons": "ボタン",
"ControllerSettingsButtonA": "A",
"ControllerSettingsButtonB": "B",
"ControllerSettingsButtonX": "X",
"ControllerSettingsButtonY": "Y",
"ControllerSettingsButtonPlus": "+",
"ControllerSettingsButtonMinus": "-",
"ControllerSettingsDPad": "十字キー",
"ControllerSettingsDPadUp": "上",
"ControllerSettingsDPadDown": "下",
"ControllerSettingsDPadLeft": "左",
"ControllerSettingsDPadRight": "右",
"ControllerSettingsLStick": "左スティック",
"ControllerSettingsLStickButton": "ボタン",
"ControllerSettingsLStickUp": "上",
"ControllerSettingsLStickDown": "下",
"ControllerSettingsLStickLeft": "左",
"ControllerSettingsLStickRight": "右",
"ControllerSettingsLStickStick": "スティック",
"ControllerSettingsLStickInvertXAxis": "X軸を反転",
"ControllerSettingsLStickInvertYAxis": "Y軸を反転",
"ControllerSettingsLStickDeadzone": "遊び:",
"ControllerSettingsRStick": "右スティック",
"ControllerSettingsRStickButton": "ボタン",
"ControllerSettingsRStickUp": "上",
"ControllerSettingsRStickDown": "下",
"ControllerSettingsRStickLeft": "左",
"ControllerSettingsRStickRight": "右",
"ControllerSettingsRStickStick": "スティック",
"ControllerSettingsRStickInvertXAxis": "X軸を反転",
"ControllerSettingsRStickInvertYAxis": "Y軸を反転",
"ControllerSettingsRStickDeadzone": "遊び:",
"ControllerSettingsTriggersLeft": "左トリガー",
"ControllerSettingsTriggersRight": "右トリガー",
"ControllerSettingsTriggersButtonsLeft": "左トリガーボタン",
"ControllerSettingsTriggersButtonsRight": "右トリガーボタン",
"ControllerSettingsTriggers": "トリガー",
"ControllerSettingsTriggerL": "L",
"ControllerSettingsTriggerR": "R",
"ControllerSettingsTriggerZL": "ZL",
"ControllerSettingsTriggerZR": "ZR",
"ControllerSettingsLeftSL": "SL",
"ControllerSettingsLeftSR": "SR",
"ControllerSettingsRightSL": "SL",
"ControllerSettingsRightSR": "SR",
"ControllerSettingsExtraButtonsLeft": "左ボタン",
"ControllerSettingsExtraButtonsRight": "右ボタン",
"ControllerSettingsMisc": "その他",
"ControllerSettingsTriggerThreshold": "トリガーしきい値:",
"ControllerSettingsMotion": "モーション",
"ControllerSettingsMotionUseCemuhookCompatibleMotion": "CemuHook 互換モーションを使用",
"ControllerSettingsMotionControllerSlot": "コントローラ スロット:",
"ControllerSettingsMotionMirrorInput": "入力反転",
"ControllerSettingsMotionRightJoyConSlot": "JoyCon 右 スロット:",
"ControllerSettingsMotionServerHost": "サーバ:",
"ControllerSettingsMotionGyroSensitivity": "ジャイロ感度:",
"ControllerSettingsMotionGyroDeadzone": "ジャイロ遊び:",
"ControllerSettingsSave": "セーブ",
"ControllerSettingsClose": "閉じる",
"UserProfilesSelectedUserProfile": "選択されたユーザプロファイル:",
"UserProfilesSaveProfileName": "プロファイル名をセーブ",
"UserProfilesChangeProfileImage": "プロファイル画像を変更",
"UserProfilesAvailableUserProfiles": "利用可能なユーザプロファイル:",
"UserProfilesAddNewProfile": "プロファイルを作成",
"UserProfilesDeleteSelectedProfile": "削除",
"UserProfilesClose": "閉じる",
"ProfileImageSelectionTitle": "プロファイル画像選択",
"ProfileImageSelectionHeader": "プロファイル画像を選択",
"ProfileImageSelectionNote": "カスタム画像をインポート, またはファームウェア内のアバターを選択できます",
"ProfileImageSelectionImportImage": "画像ファイルをインポート",
"ProfileImageSelectionSelectAvatar": "ファームウェア内のアバターを選択",
"InputDialogTitle": "入力ダイアログ",
"InputDialogOk": "OK",
"InputDialogCancel": "キャンセル",
"InputDialogAddNewProfileTitle": "プロファイル名を選択",
"InputDialogAddNewProfileHeader": "プロファイル名を入力してください",
"InputDialogAddNewProfileSubtext": "(最大長: {0})",
"AvatarChoose": "選択",
"AvatarSetBackgroundColor": "背景色を指定",
"AvatarClose": "閉じる",
"ControllerSettingsLoadProfileToolTip": "プロファイルをロード",
"ControllerSettingsAddProfileToolTip": "プロファイルを追加",
"ControllerSettingsRemoveProfileToolTip": "プロファイルを削除",
"ControllerSettingsSaveProfileToolTip": "プロファイルをセーブ",
"MenuBarFileToolsTakeScreenshot": "スクリーンショットを撮影",
"MenuBarFileToolsHideUi": "UIを隠す",
"GameListContextMenuToggleFavorite": "お気に入りを切り替え",
"GameListContextMenuToggleFavoriteToolTip": "ゲームをお気に入りに含めるかどうかを切り替えます",
"SettingsTabGeneralTheme": "テーマ",
"SettingsTabGeneralThemeCustomTheme": "カスタムテーマパス",
"SettingsTabGeneralThemeBaseStyle": "基本スタイル",
"SettingsTabGeneralThemeBaseStyleDark": "ダーク",
"SettingsTabGeneralThemeBaseStyleLight": "ライト",
"SettingsTabGeneralThemeEnableCustomTheme": "カスタムテーマを有効",
"ButtonBrowse": "参照",
"ControllerSettingsConfigureGeneral": "設定",
"ControllerSettingsRumble": "振動",
"ControllerSettingsRumbleStrongMultiplier": "強振動の補正値",
"ControllerSettingsRumbleWeakMultiplier": "弱振動の補正値",
"DialogMessageSaveNotAvailableMessage": "{0} [{1:x16}] のセーブデータはありません",
"DialogMessageSaveNotAvailableCreateSaveMessage": "このゲームのセーブデータを作成してよろしいですか?",
"DialogConfirmationTitle": "Ryujinx - 確認",
"DialogUpdaterTitle": "Ryujinx - アップデータ",
"DialogErrorTitle": "Ryujinx - エラー",
"DialogWarningTitle": "Ryujinx - 警告",
"DialogExitTitle": "Ryujinx - 終了",
"DialogErrorMessage": "エラーが発生しました",
"DialogExitMessage": "Ryujinx を閉じてよろしいですか?",
"DialogExitSubMessage": "セーブされていないのデータはすべて失われます!",
"DialogMessageCreateSaveErrorMessage": "セーブデータ: {0} の作成中にエラーが発生しました",
"DialogMessageFindSaveErrorMessage": "セーブデータ: {0} の検索中にエラーが発生しました",
"FolderDialogExtractTitle": "展開フォルダを選択",
"DialogNcaExtractionMessage": "{1} から {0} セクションを展開中...",
"DialogNcaExtractionTitle": "Ryujinx - NCA セクション展開",
"DialogNcaExtractionMainNcaNotFoundErrorMessage": "展開に失敗しました. 選択されたファイルにはメイン NCA が存在しません.",
"DialogNcaExtractionCheckLogErrorMessage": "展開に失敗しました. 詳細はログを確認してください.",
"DialogNcaExtractionSuccessMessage": "展開が正常終了しました",
"DialogUpdaterConvertFailedMessage": "現在の Ryujinx バージョンの変換に失敗しました.",
"DialogUpdaterCancelUpdateMessage": "アップデータをキャンセル中!",
"DialogUpdaterAlreadyOnLatestVersionMessage": "最新バージョンの Ryujinx を使用中です!",
"DialogUpdaterFailedToGetVersionMessage": "Github からのリリース情報取得時にエラーが発生しました. Github Actions でリリースファイルを作成中かもしれません. 後ほどもう一度試してみてください.",
"DialogUpdaterConvertFailedGithubMessage": "Github から取得した Ryujinx バージョンの変換に失敗しました.",
"DialogUpdaterDownloadingMessage": "アップデートをダウンロード中...",
"DialogUpdaterExtractionMessage": "アップデートを展開中...",
"DialogUpdaterRenamingMessage": "アップデートをリネーム中...",
"DialogUpdaterAddingFilesMessage": "新規アップデートを追加中...",
"DialogUpdaterCompleteMessage": "アップデート完了!",
"DialogUpdaterRestartMessage": "すぐに Ryujinx を再起動しますか?",
"DialogUpdaterArchNotSupportedMessage": "サポート外のアーキテクチャです!",
"DialogUpdaterArchNotSupportedSubMessage": "(x64 システムのみサポートしています!)",
"DialogUpdaterNoInternetMessage": "インターネットに接続されていません!",
"DialogUpdaterNoInternetSubMessage": "インターネット接続が正常動作しているか確認してください!",
"DialogUpdaterDirtyBuildMessage": "Dirty ビルドの Ryujinx はアップデートできません!",
"DialogUpdaterDirtyBuildSubMessage": "サポートされているバージョンをお探しなら, https://ryujinx.org/ で Ryujinx をダウンロードしてください.",
"DialogRestartRequiredMessage": "再起動が必要",
"DialogThemeRestartMessage": "テーマがセーブされました. テーマを適用するには再起動が必要です.",
"DialogThemeRestartSubMessage": "再起動しますか",
"DialogFirmwareInstallEmbeddedMessage": "このゲームに含まれるファームウェアをインストールしてよろしいですか? (ファームウェア {0})",
"DialogFirmwareInstallEmbeddedSuccessMessage": "ファームウェアがインストールされていませんが, ゲームに含まれるファームウェア {0} をインストールできます.\\nエミュレータが開始します.",
"DialogFirmwareNoFirmwareInstalledMessage": "ファームウェアがインストールされていません",
"DialogFirmwareInstalledMessage": "ファームウェア {0} がインストールされました",
"DialogOpenSettingsWindowLabel": "設定ウインドウを開く",
"DialogControllerAppletTitle": "コントローラアプレット",
"DialogMessageDialogErrorExceptionMessage": "メッセージダイアログ表示エラー: {0}",
"DialogSoftwareKeyboardErrorExceptionMessage": "ソフトウェアキーボード表示エラー: {0}",
"DialogErrorAppletErrorExceptionMessage": "エラーアプレットダイアログ表示エラー: {0}",
"DialogUserErrorDialogMessage": "{0}: {1}",
"DialogUserErrorDialogInfoMessage": "\nこのエラーへの対処方法については, セットアップガイドを参照してください.",
"DialogUserErrorDialogTitle": "Ryujinx エラー ({0})",
"DialogAmiiboApiTitle": "Amiibo API",
"DialogAmiiboApiFailFetchMessage": "API からの情報取得中にエラーが発生しました.",
"DialogAmiiboApiConnectErrorMessage": "Amiibo API サーバに接続できませんでした. サーバがダウンしているか, インターネット接続に問題があるかもしれません.",
"DialogProfileInvalidProfileErrorMessage": "プロファイル {0} は現在の入力設定システムと互換性がありません.",
"DialogProfileDefaultProfileOverwriteErrorMessage": "デフォルトのプロファイルは上書きできません",
"DialogProfileDeleteProfileTitle": "プロファイルを削除中",
"DialogProfileDeleteProfileMessage": "このアクションは元に戻せません. 本当に続けてよろしいですか?",
"DialogWarning": "警告",
"DialogPPTCDeletionMessage": "PPTC キャッシュを破棄しようとしています:\n\n{0}\n\n実行してよろしいですか?",
"DialogPPTCDeletionErrorMessage": "PPTC キャッシュ破棄エラー {0}: {1}",
"DialogShaderDeletionMessage": "シェーダキャッシュを破棄しようとしています:\n\n{0}\n\n実行してよろしいですか?",
"DialogShaderDeletionErrorMessage": "シェーダキャッシュ破棄エラー {0}: {1}",
"DialogRyujinxErrorMessage": "エラーが発生しました",
"DialogInvalidTitleIdErrorMessage": "UI エラー: 選択されたゲームは有効なタイトル ID を保持していません",
"DialogFirmwareInstallerFirmwareNotFoundErrorMessage": "{0} には有効なシステムファームウェアがありません.",
"DialogFirmwareInstallerFirmwareInstallTitle": "ファームウェア {0} をインストール",
"DialogFirmwareInstallerFirmwareInstallMessage": "システムバージョン {0} がインストールされます.",
"DialogFirmwareInstallerFirmwareInstallSubMessage": "\n\n現在のシステムバージョン {0} を置き換えます.",
"DialogFirmwareInstallerFirmwareInstallConfirmMessage": "\n\n続けてよろしいですか?",
"DialogFirmwareInstallerFirmwareInstallWaitMessage": "ファームウェアをインストール中...",
"DialogFirmwareInstallerFirmwareInstallSuccessMessage": "システムバージョン {0} が正常にインストールされました.",
"DialogUserProfileDeletionWarningMessage": "選択されたプロファイルを削除すると,プロファイルがひとつも存在しなくなります",
"DialogUserProfileDeletionConfirmMessage": "選択されたプロファイルを削除しますか",
"DialogControllerSettingsModifiedConfirmMessage": "現在のコントローラ設定が更新されました.",
"DialogControllerSettingsModifiedConfirmSubMessage": "セーブしますか?",
"DialogDlcLoadNcaErrorMessage": "{0}. エラー発生ファイル: {1}",
"DialogDlcNoDlcErrorMessage": "選択されたファイルはこのタイトル用の DLC ではありません!",
"DialogPerformanceCheckLoggingEnabledMessage": "トレースロギングを有効にします. これは開発者のみに有用な機能です.",
"DialogPerformanceCheckLoggingEnabledConfirmMessage": "パフォーマンス最適化のためには,トレースロギングを無効にすることを推奨します. トレースロギングを無効にしてよろしいですか?",
"DialogPerformanceCheckShaderDumpEnabledMessage": "シェーダダンプを有効にします. これは開発者のみに有用な機能です.",
"DialogPerformanceCheckShaderDumpEnabledConfirmMessage": "パフォーマンス最適化のためには, シェーダダンプを無効にすることを推奨します. シェーダダンプを無効にしてよろしいですか?",
"DialogLoadAppGameAlreadyLoadedMessage": "ゲームはすでにロード済みです",
"DialogLoadAppGameAlreadyLoadedSubMessage": "別のゲームを起動する前に, エミュレーションを停止またはエミュレータを閉じてください.",
"DialogUpdateAddUpdateErrorMessage": "選択されたファイルはこのタイトル用のアップデートではありません!",
"DialogSettingsBackendThreadingWarningTitle": "警告 - バックエンドスレッディング",
"DialogSettingsBackendThreadingWarningMessage": "このオプションの変更を完全に適用するには Ryujinx の再起動が必要です. プラットフォームによっては, Ryujinx のものを使用する前に手動でドライバ自身のマルチスレッディングを無効にする必要があるかもしれません.",
"SettingsTabGraphicsFeaturesOptions": "機能",
"SettingsTabGraphicsBackendMultithreading": "グラフィクスバックエンドのマルチスレッド実行:",
"CommonAuto": "自動",
"CommonOff": "オフ",
"CommonOn": "オン",
"InputDialogYes": "はい",
"InputDialogNo": "いいえ",
"DialogProfileInvalidProfileNameErrorMessage": "プロファイル名に無効な文字が含まれています. 再度試してみてください.",
"MenuBarOptionsPauseEmulation": "中断",
"MenuBarOptionsResumeEmulation": "再開",
"AboutUrlTooltipMessage": "クリックするとデフォルトのブラウザで Ryujinx のウェブサイトを開きます.",
"AboutDisclaimerMessage": "Ryujinx は Nintendo™ および\nそのパートナー企業とは一切関係ありません.",
"AboutAmiiboDisclaimerMessage": "AmiiboAPI (www.amiiboapi.com) は\nAmiibo エミュレーションに使用されています.",
"AboutPatreonUrlTooltipMessage": "クリックするとデフォルトのブラウザで Ryujinx の Patreon ページを開きます.",
"AboutGithubUrlTooltipMessage": "クリックするとデフォルトのブラウザで Ryujinx の Github ページを開きます.",
"AboutDiscordUrlTooltipMessage": "クリックするとデフォルトのブラウザで Ryujinx の Discord サーバを開きます.",
"AboutTwitterUrlTooltipMessage": "クリックするとデフォルトのブラウザで Ryujinx の Twitter ページを開きます.",
"AboutRyujinxAboutTitle": "Ryujinx について:",
"AboutRyujinxAboutContent": "Ryujinx は Nintendo Switch™ のエミュレータです.\nPatreon で私達の活動を支援してください.\n最新の情報は Twitter または Discord から取得できます.\n貢献したい開発者の方は GitHub または Discord で詳細をご確認ください.",
"AboutRyujinxMaintainersTitle": "開発者:",
"AboutRyujinxMaintainersContentTooltipMessage": "クリックするとデフォルトのブラウザで 貢献者のページを開きます.",
"AboutRyujinxSupprtersTitle": "Patreon での支援者:",
"AmiiboSeriesLabel": "Amiibo シリーズ",
"AmiiboCharacterLabel": "キャラクタ",
"AmiiboScanButtonLabel": "スキャン",
"AmiiboOptionsShowAllLabel": "すべての Amiibo を表示",
"AmiiboOptionsUsRandomTagLabel": "ハック: ランダムな Uuid を使用",
"DlcManagerTableHeadingEnabledLabel": "有効",
"DlcManagerTableHeadingTitleIdLabel": "タイトルID",
"DlcManagerTableHeadingContainerPathLabel": "コンテナパス",
"DlcManagerTableHeadingFullPathLabel": "フルパス",
"DlcManagerRemoveAllButton": "すべて削除",
"MenuBarOptionsChangeLanguage": "言語を変更",
"CommonSort": "並べ替え",
"CommonShowNames": "名称を表示",
"CommonFavorite": "お気に入り",
"OrderAscending": "昇順",
"OrderDescending": "降順",
"SettingsTabGraphicsFeatures": "機能",
"ErrorWindowTitle": "エラーウインドウ",
"ToggleDiscordTooltip": "Discord の \"現在プレイ中\" アクティビティに Ryujinx を表示するかどうかを選択します",
"AddGameDirBoxTooltip": "リストに追加するゲームディレクトリを入力します",
"AddGameDirTooltip": "リストにゲームディレクトリを追加します",
"RemoveGameDirTooltip": "選択したゲームディレクトリを削除します",
"CustomThemeCheckTooltip": "エミュレータのメニュー外観を変更するためカスタム Avalonia テーマを使用します",
"CustomThemePathTooltip": "カスタム GUI テーマのパスです",
"CustomThemeBrowseTooltip": "カスタム GUI テーマを参照します",
"DockModeToggleTooltip": "有効にすると,ドッキングされた Nintendo Switch をエミュレートします.多くのゲームではグラフィクス品質が向上します.\n無効にすると,携帯モードの Nintendo Switch をエミュレートします.グラフィクスの品質は低下します.\n\nドッキングモード有効ならプレイヤー1の,無効なら携帯の入力を設定してください.\n\nよくわからない場合はオンのままにしてください.",
"DirectKeyboardTooltip": "キーボード直接アクセス (HID) に対応します. キーボードをテキスト入力デバイスとして使用できます.",
"DirectMouseTooltip": "マウス直接アクセス (HID) に対応します. マウスをポインティングデバイスとして使用できます.",
"RegionTooltip": "システムの地域を変更します",
"LanguageTooltip": "システムの言語を変更します",
"TimezoneTooltip": "システムのタイムゾーンを変更します",
"TimeTooltip": "システムの時刻を変更します",
"VSyncToggleTooltip": "エミュレートされたゲーム機の垂直同期です. 多くのゲームにおいて, フレームリミッタとして機能します. 無効にすると, ゲームが高速で実行されたり, ロード中に時間がかかったり, 止まったりすることがあります.\n\n設定したホットキーで, ゲーム内で切り替え可能です. 無効にする場合は, この操作を行うことをおすすめします.\n\nよくわからない場合はオンのままにしてください.",
"PptcToggleTooltip": "翻訳されたJIT関数をセーブすることで, ゲームをロードするたびに毎回翻訳する処理を不要とします.\n\n一度ゲームを起動すれば,二度目以降の起動時遅延を大きく軽減できます.\n\nよくわからない場合はオンのままにしてください.",
"FsIntegrityToggleTooltip": "ゲーム起動時にファイル破損をチェックし,破損が検出されたらログにハッシュエラーを表示します..\n\nパフォーマンスには影響なく, トラブルシューティングに役立ちます.\n\nよくわからない場合はオンのままにしてください.",
"AudioBackendTooltip": "音声レンダリングに使用するバックエンドを変更します.\n\nSDL2 が優先され, OpenAL と SoundIO はフォールバックとして使用されます. ダミーは音声出力しません.\n\nよくわからない場合は SDL2 を設定してください.",
"MemoryManagerTooltip": "ゲストメモリのマップ/アクセス方式を変更します. エミュレートされるCPUのパフォーマンスに大きな影響を与えます.\n\nよくわからない場合は「ホスト,チェックなし」を設定してください.",
"MemoryManagerSoftwareTooltip": "アドレス変換にソフトウェアページテーブルを使用します. 非常に正確ですがパフォーマンスが大きく低下します.",
"MemoryManagerHostTooltip": "ホストのアドレス空間にメモリを直接マップします.JITのコンパイルと実行速度が大きく向上します.",
"MemoryManagerUnsafeTooltip": "メモリを直接マップしますが, アクセス前にゲストのアドレス空間内のアドレスをマスクしません. より高速になりますが, 安全性が犠牲になります. ゲストアプリケーションは Ryujinx のどこからでもメモリにアクセスできるので,このモードでは信頼できるプログラムだけを実行するようにしてください.",
"DRamTooltip": "エミュレートされたシステムのメモリ容量を 4GB から 6GB に増加します.\n\n高解像度のテクスチャパックや 4K解像度の mod を使用する場合に有用です. パフォーマンスを改善するものではありません.\n\nよくわからない場合はオフのままにしてください.",
"IgnoreMissingServicesTooltip": "未実装の Horizon OS サービスを無視します. 特定のゲームにおいて起動時のクラッシュを回避できる場合があります.\n\nよくわからない場合はオフのままにしてください.",
"GraphicsBackendThreadingTooltip": "グラフィクスバックエンドのコマンドを別スレッドで実行します.\n\nシェーダのコンパイルを高速化し, 遅延を軽減し, マルチスレッド非対応の GPU ドライバにおいてパフォーマンスを改善します. マルチスレッド対応のドライバでも若干パフォーマンス改善が見られます.\n\nよくわからない場合は自動に設定してください.",
"GalThreadingTooltip": "グラフィクスバックエンドのコマンドを別スレッドで実行します.\n\nシェーダのコンパイルを高速化し, 遅延を軽減し, マルチスレッド非対応の GPU ドライバにおいてパフォーマンスを改善します. マルチスレッド対応のドライバでも若干パフォーマンス改善が見られます.\n\nよくわからない場合は自動に設定してください.",
"ShaderCacheToggleTooltip": "ディスクシェーダキャッシュをセーブし,次回以降の実行時遅延を軽減します.\n\nよくわからない場合はオンのままにしてください.",
"ResolutionScaleTooltip": "レンダリングに適用される解像度の倍率です",
"ResolutionScaleEntryTooltip": "1.5 のような整数でない倍率を指定すると,問題が発生したりクラッシュしたりする場合があります.",
"AnisotropyTooltip": "異方性フィルタリングのレベルです (ゲームが要求する値を使用する場合は「自動」を設定してください)",
"AspectRatioTooltip": "レンダリングに適用されるアスペクト比です.",
"ShaderDumpPathTooltip": "グラフィクス シェーダダンプのパスです",
"FileLogTooltip": "コンソール出力されるログをディスク上のログファイルにセーブします. パフォーマンスには影響を与えません.",
"StubLogTooltip": "stub ログメッセージをコンソールに出力します. パフォーマンスには影響を与えません.",
"InfoLogTooltip": "info ログメッセージをコンソールに出力します. パフォーマンスには影響を与えません.",
"WarnLogTooltip": "warning ログメッセージをコンソールに出力します. パフォーマンスには影響を与えません.",
"ErrorLogTooltip": "error ログメッセージをコンソールに出力します. パフォーマンスには影響を与えません.",
"TraceLogTooltip": "trace ログメッセージをコンソールに出力します. パフォーマンスには影響を与えません.",
"GuestLogTooltip": "guest ログメッセージをコンソールに出力します. パフォーマンスには影響を与えません.",
"FileAccessLogTooltip": "ファイルアクセスログメッセージをコンソールに出力します.",
"FSAccessLogModeTooltip": "コンソールへのファイルシステムアクセスログ出力を有効にします.0-3 のモードが有効です",
"DeveloperOptionTooltip": "使用上の注意",
"OpenGlLogLevel": "適切なログレベルを有効にする必要があります",
"DebugLogTooltip": "デバッグログメッセージをコンソールに出力します.\n\nログが読みづらくなり,エミュレータのパフォーマンスが低下するため,開発者から特別な指示がある場合のみ使用してください.",
"LoadApplicationFileTooltip": "ロードする Switch 互換のファイルを選択するためファイルエクスプローラを開きます",
"LoadApplicationFolderTooltip": "ロードする Switch 互換の展開済みアプリケーションを選択するためファイルエクスプローラを開きます",
"OpenRyujinxFolderTooltip": "Ryujinx ファイルシステムフォルダを開きます",
"OpenRyujinxLogsTooltip": "ログが格納されるフォルダを開きます",
"ExitTooltip": "Ryujinx を終了します",
"OpenSettingsTooltip": "設定ウインドウを開きます",
"OpenProfileManagerTooltip": "ユーザプロファイル管理ウインドウを開きます",
"StopEmulationTooltip": "ゲームのエミュレーションを停止してゲーム選択画面に戻ります",
"CheckUpdatesTooltip": "Ryujinx のアップデートを確認します",
"OpenAboutTooltip": "Ryujinx についてのウインドウを開きます",
"GridSize": "グリッドサイズ",
"GridSizeTooltip": "グリッドサイズを変更します",
"SettingsTabSystemSystemLanguageBrazilianPortuguese": "ポルトガル語(ブラジル)",
"AboutRyujinxContributorsButtonHeader": "すべての貢献者を確認",
"SettingsTabSystemAudioVolume": "音量: ",
"AudioVolumeTooltip": "音量を変更します",
"SettingsTabSystemEnableInternetAccess": "ゲストインターネットアクセス / LAN モード",
"EnableInternetAccessTooltip": "エミュレートしたアプリケーションをインターネットに接続できるようにします.\n\nLAN モードを持つゲーム同士は,この機能を有効にして同じアクセスポイントに接続すると接続できます. 実機も含まれます.\n\n任天堂のサーバーには接続できません. インターネットに接続しようとすると,特定のゲームでクラッシュすることがあります.\n\nよくわからない場合はオフのままにしてください.",
"GameListContextMenuManageCheatToolTip": "チートを管理します",
"GameListContextMenuManageCheat": "チートを管理",
"ControllerSettingsStickRange": "範囲:",
"DialogStopEmulationTitle": "Ryujinx - エミュレーションを停止",
"DialogStopEmulationMessage": "エミュレーションを停止してよろしいですか?",
"SettingsTabCpu": "CPU",
"SettingsTabAudio": "音声",
"SettingsTabNetwork": "ネットワーク",
"SettingsTabNetworkConnection": "ネットワーク接続",
"SettingsTabCpuCache": "CPU キャッシュ",
"SettingsTabCpuMemory": "CPU メモリ",
"DialogUpdaterFlatpakNotSupportedMessage": "FlatHub を使用して Ryujinx をアップデートしてください.",
"UpdaterDisabledWarningTitle": "アップデータは無効です!",
"GameListContextMenuOpenSdModsDirectory": "Atmosphere Mods ディレクトリを開く",
"GameListContextMenuOpenSdModsDirectoryToolTip": "アプリケーションの Mod データを格納する SD カードの Atmosphere ディレクトリを開きます. 実際のハードウェア用にパッケージされた Mod データに有用です.",
"ControllerSettingsRotate90": "時計回りに 90° 回転",
"IconSize": "アイコンサイズ",
"IconSizeTooltip": "ゲームアイコンのサイズを変更します",
"MenuBarOptionsShowConsole": "コンソールを表示",
"ShaderCachePurgeError": "シェーダキャッシュの破棄エラー {0}: {1}",
"UserErrorNoKeys": "Keys がありません",
"UserErrorNoFirmware": "ファームウェアがありません",
"UserErrorFirmwareParsingFailed": "ファームウェアのパーズエラー",
"UserErrorApplicationNotFound": "アプリケーションがありません",
"UserErrorUnknown": "不明なエラー",
"UserErrorUndefined": "未定義エラー",
"UserErrorNoKeysDescription": "'prod.keys' が見つかりませんでした",
"UserErrorNoFirmwareDescription": "インストールされたファームウェアが見つかりませんでした",
"UserErrorFirmwareParsingFailedDescription": "ファームウェアをパーズできませんでした.通常,古いキーが原因です.",
"UserErrorApplicationNotFoundDescription": "指定されたパスに有効なアプリケーションがありませんでした.",
"UserErrorUnknownDescription": "不明なエラーが発生しました!",
"UserErrorUndefinedDescription": "未定義のエラーが発生しました! 発生すべきものではないので,開発者にご連絡ください!",
"OpenSetupGuideMessage": "セットアップガイドを開く",
"NoUpdate": "アップデートなし",
"TitleUpdateVersionLabel": "バージョン {0} - {1}",
"RyujinxInfo": "Ryujinx - 情報",
"RyujinxConfirm": "Ryujinx - 確認",
"FileDialogAllTypes": "すべての種別",
"Never": "Never",
"SwkbdMinCharacters": "最低 {0} 文字必要です",
"SwkbdMinRangeCharacters": "{0}-{1} 文字にしてください",
"SoftwareKeyboard": "ソフトウェアキーボード",
"DialogControllerAppletMessagePlayerRange": "アプリケーションは {0} 名のプレイヤーを要求しています:\n\n種別: {1}\n\nプレイヤー: {2}\n\n{3}設定を開き各プレイヤーの入力設定を行ってから閉じるを押してください.",
"DialogControllerAppletMessage": "アプリケーションは {0} 名のプレイヤーを要求しています:\n\n種別: {1}\n\nプレイヤー: {2}\n\n{3}設定を開き各プレイヤーの入力設定を行ってから閉じるを押してください.",
"DialogControllerAppletDockModeSet": "ドッキングモードに設定されました. 携帯モードは無効になります.\n\n",
"UpdaterRenaming": "古いファイルをリネーム中...",
"UpdaterRenameFailed": "ファイルをリネームできませんでした: {0}",
"UpdaterAddingFiles": "新規ファイルを追加中...",
"UpdaterExtracting": "アップデートを展開中...",
"UpdaterDownloading": "アップデートをダウンロード中...",
"Game": "ゲーム",
"Docked": "ドッキング",
"Handheld": "携帯",
"ConnectionError": "接続エラー.",
"AboutPageDeveloperListMore": "{0}, その他大勢...",
"ApiError": "API エラー.",
"LoadingHeading": "ロード中: {0}",
"CompilingPPTC": "PTC をコンパイル中",
"CompilingShaders": "シェーダをコンパイル中",
"AllKeyboards": "すべてキーボード",
"OpenFileDialogTitle": "開くファイルを選択",
"OpenFolderDialogTitle": "展開されたゲームフォルダを選択",
"AllSupportedFormats": "すべての対応フォーマット",
"RyujinxUpdater": "Ryujinx アップデータ",
"SettingsTabHotkeys": "キーボード ホットキー",
"SettingsTabHotkeysHotkeys": "キーボード ホットキー",
"SettingsTabHotkeysToggleVsyncHotkey": "VSync 切り替え:",
"SettingsTabHotkeysScreenshotHotkey": "スクリーンショット:",
"SettingsTabHotkeysShowUiHotkey": "UI表示:",
"SettingsTabHotkeysPauseHotkey": "中断:",
"SettingsTabHotkeysToggleMuteHotkey": "ミュート:",
"ControllerMotionTitle": "モーションコントロール設定",
"ControllerRumbleTitle": "振動設定",
"SettingsSelectThemeFileDialogTitle": "テーマファイルを選択",
"SettingsXamlThemeFile": "Xaml テーマファイル",
"AvatarWindowTitle": "アカウント - アバター管理",
"Amiibo": "Amiibo",
"Unknown": "不明",
"Usage": "使用法",
"Writable": "書き込み可能",
"SelectDlcDialogTitle": "DLC ファイルを選択",
"SelectUpdateDialogTitle": "アップデートファイルを選択",
"UserProfileWindowTitle": "ユーザプロファイルを管理",
"CheatWindowTitle": "チート管理",
"DlcWindowTitle": "DLC 管理",
"UpdateWindowTitle": "アップデート管理",
"CheatWindowHeading": "利用可能なチート {0} [{1}]",
"DlcWindowHeading": "利用可能な DLC {0} [{1}]",
"UserProfilesEditProfile": "編集",
"Cancel": "キャンセル",
"Save": "セーブ",
"Discard": "破棄",
"UserProfilesSetProfileImage": "プロファイル画像を設定",
"UserProfileEmptyNameError": "名前が必要です",
"UserProfileNoImageError": "プロファイル画像が必要です",
"GameUpdateWindowHeading": "利用可能なアップデート {0} [{1}]",
"SettingsTabHotkeysResScaleUpHotkey": "解像度を上げる:",
"SettingsTabHotkeysResScaleDownHotkey": "解像度を下げる:"
}

View File

@@ -94,7 +94,6 @@ namespace Ryujinx.Ava
.With(new Ui.Vulkan.VulkanOptions() .With(new Ui.Vulkan.VulkanOptions()
{ {
ApplicationName = "Ryujinx.Graphics.Vulkan", ApplicationName = "Ryujinx.Graphics.Vulkan",
VulkanVersion = new Version(1, 2),
MaxQueueCount = 2, MaxQueueCount = 2,
PreferDiscreteGpu = true, PreferDiscreteGpu = true,
PreferredDevice = !PreviewerDetached ? "" : ConfigurationState.Instance.Graphics.PreferredGpu.Value, PreferredDevice = !PreviewerDetached ? "" : ConfigurationState.Instance.Graphics.PreferredGpu.Value,
@@ -181,6 +180,18 @@ namespace Ryujinx.Ava
UseVulkan = PreviewerDetached ? ConfigurationState.Instance.Graphics.GraphicsBackend.Value == GraphicsBackend.Vulkan : false; UseVulkan = PreviewerDetached ? ConfigurationState.Instance.Graphics.GraphicsBackend.Value == GraphicsBackend.Vulkan : false;
if (UseVulkan)
{
if (VulkanRenderer.GetPhysicalDevices().Length == 0)
{
UseVulkan = false;
ConfigurationState.Instance.Graphics.GraphicsBackend.Value = GraphicsBackend.OpenGl;
Logger.Warning?.PrintMsg(LogClass.Application, "A suitable Vulkan physical device is not available. Falling back to OpenGL");
}
}
if (UseVulkan) if (UseVulkan)
{ {
// With a custom gpu backend, avalonia doesn't enable dpi awareness, so the backend must handle it. This isn't so for the opengl backed, // With a custom gpu backend, avalonia doesn't enable dpi awareness, so the backend must handle it. This isn't so for the opengl backed,

View File

@@ -118,6 +118,7 @@
<None Remove="Assets\Locales\fr_FR.json" /> <None Remove="Assets\Locales\fr_FR.json" />
<None Remove="Assets\Locales\de_DE.json" /> <None Remove="Assets\Locales\de_DE.json" />
<None Remove="Assets\Locales\it_IT.json" /> <None Remove="Assets\Locales\it_IT.json" />
<None Remove="Assets\Locales\ja_JP.json" />
<None Remove="Assets\Locales\ko_KR.json" /> <None Remove="Assets\Locales\ko_KR.json" />
<None Remove="Assets\Locales\pt_BR.json" /> <None Remove="Assets\Locales\pt_BR.json" />
<None Remove="Assets\Locales\ru_RU.json" /> <None Remove="Assets\Locales\ru_RU.json" />
@@ -136,6 +137,7 @@
<EmbeddedResource Include="Assets\Locales\fr_FR.json" /> <EmbeddedResource Include="Assets\Locales\fr_FR.json" />
<EmbeddedResource Include="Assets\Locales\de_DE.json" /> <EmbeddedResource Include="Assets\Locales\de_DE.json" />
<EmbeddedResource Include="Assets\Locales\it_IT.json" /> <EmbeddedResource Include="Assets\Locales\it_IT.json" />
<EmbeddedResource Include="Assets\Locales\ja_JP.json" />
<EmbeddedResource Include="Assets\Locales\ko_KR.json" /> <EmbeddedResource Include="Assets\Locales\ko_KR.json" />
<EmbeddedResource Include="Assets\Locales\pt_BR.json" /> <EmbeddedResource Include="Assets\Locales\pt_BR.json" />
<EmbeddedResource Include="Assets\Locales\ru_RU.json" /> <EmbeddedResource Include="Assets\Locales\ru_RU.json" />

View File

@@ -7,7 +7,8 @@ namespace Ryujinx.Ava.Ui.Vulkan
{ {
public static void ThrowOnError(this Result result) public static void ThrowOnError(this Result result)
{ {
if (result != Result.Success) // Only negative result codes are errors.
if ((int)result < (int)Result.Success)
{ {
throw new Exception($"Unexpected API error \"{result}\"."); throw new Exception($"Unexpected API error \"{result}\".");
} }

View File

@@ -1,26 +1,90 @@
using System; using System;
using Avalonia;
using Avalonia.Skia; using Avalonia.Skia;
using Ryujinx.Ava.Ui.Vulkan; using Ryujinx.Ava.Ui.Vulkan;
using Ryujinx.Ava.Ui.Vulkan.Surfaces; using Ryujinx.Ava.Ui.Vulkan.Surfaces;
using Silk.NET.Vulkan;
using SkiaSharp; using SkiaSharp;
namespace Ryujinx.Ava.Ui.Backend.Vulkan namespace Ryujinx.Ava.Ui.Backend.Vulkan
{ {
internal class VulkanRenderTarget : ISkiaGpuRenderTarget internal class VulkanRenderTarget : ISkiaGpuRenderTarget
{ {
public GRContext GrContext { get; set; } public GRContext GrContext { get; private set; }
private readonly VulkanSurfaceRenderTarget _surface; private readonly VulkanSurfaceRenderTarget _surface;
private readonly VulkanPlatformInterface _vulkanPlatformInterface;
private readonly IVulkanPlatformSurface _vulkanPlatformSurface; private readonly IVulkanPlatformSurface _vulkanPlatformSurface;
private GRVkBackendContext _grVkBackend;
public VulkanRenderTarget(VulkanPlatformInterface vulkanPlatformInterface, IVulkanPlatformSurface vulkanPlatformSurface) public VulkanRenderTarget(VulkanPlatformInterface vulkanPlatformInterface, IVulkanPlatformSurface vulkanPlatformSurface)
{ {
_surface = vulkanPlatformInterface.CreateRenderTarget(vulkanPlatformSurface); _surface = vulkanPlatformInterface.CreateRenderTarget(vulkanPlatformSurface);
_vulkanPlatformInterface = vulkanPlatformInterface;
_vulkanPlatformSurface = vulkanPlatformSurface; _vulkanPlatformSurface = vulkanPlatformSurface;
Initialize();
}
private void Initialize()
{
GRVkGetProcedureAddressDelegate getProc = GetVulkanProcAddress;
_grVkBackend = new GRVkBackendContext()
{
VkInstance = _surface.Device.Handle,
VkPhysicalDevice = _vulkanPlatformInterface.PhysicalDevice.Handle,
VkDevice = _surface.Device.Handle,
VkQueue = _surface.Device.Queue.Handle,
GraphicsQueueIndex = _vulkanPlatformInterface.PhysicalDevice.QueueFamilyIndex,
GetProcedureAddress = getProc
};
GrContext = GRContext.CreateVulkan(_grVkBackend);
var gpu = AvaloniaLocator.Current.GetService<VulkanSkiaGpu>();
if (gpu.MaxResourceBytes.HasValue)
{
GrContext.SetResourceCacheLimit(gpu.MaxResourceBytes.Value);
}
}
private IntPtr GetVulkanProcAddress(string name, IntPtr instanceHandle, IntPtr deviceHandle)
{
IntPtr addr;
if (deviceHandle != IntPtr.Zero)
{
addr = _vulkanPlatformInterface.Api.GetDeviceProcAddr(new Device(deviceHandle), name);
if (addr != IntPtr.Zero)
{
return addr;
}
addr = _vulkanPlatformInterface.Api.GetDeviceProcAddr(new Device(_surface.Device.Handle), name);
if (addr != IntPtr.Zero)
{
return addr;
}
}
addr = _vulkanPlatformInterface.Api.GetInstanceProcAddr(new Instance(_vulkanPlatformInterface.Instance.Handle), name);
if (addr == IntPtr.Zero)
{
addr = _vulkanPlatformInterface.Api.GetInstanceProcAddr(new Instance(instanceHandle), name);
}
return addr;
} }
public void Dispose() public void Dispose()
{ {
_grVkBackend.Dispose();
GrContext.Dispose();
_surface.Dispose(); _surface.Dispose();
} }
@@ -45,20 +109,22 @@ namespace Ryujinx.Ava.Ui.Backend.Vulkan
{ {
GrContext.ResetContext(); GrContext.ResetContext();
var image = _surface.GetImage();
var imageInfo = new GRVkImageInfo() var imageInfo = new GRVkImageInfo()
{ {
CurrentQueueFamily = disp.QueueFamilyIndex, CurrentQueueFamily = disp.QueueFamilyIndex,
Format = _surface.ImageFormat, Format = (uint)image.Format,
Image = _surface.Image.Handle, Image = image.Handle,
ImageLayout = (uint)_surface.Image.CurrentLayout, ImageLayout = (uint)image.CurrentLayout,
ImageTiling = (uint)_surface.Image.Tiling, ImageTiling = (uint)image.Tiling,
ImageUsageFlags = _surface.UsageFlags, ImageUsageFlags = _surface.UsageFlags,
LevelCount = _surface.MipLevels, LevelCount = _surface.MipLevels,
SampleCount = 1, SampleCount = 1,
Protected = false, Protected = false,
Alloc = new GRVkAlloc() Alloc = new GRVkAlloc()
{ {
Memory = _surface.Image.MemoryHandle, Memory = image.MemoryHandle,
Flags = 0, Flags = 0,
Offset = 0, Offset = 0,
Size = _surface.MemorySize Size = _surface.MemorySize

View File

@@ -13,71 +13,12 @@ namespace Ryujinx.Ava.Ui.Backend.Vulkan
public class VulkanSkiaGpu : ISkiaGpu public class VulkanSkiaGpu : ISkiaGpu
{ {
private readonly VulkanPlatformInterface _vulkan; private readonly VulkanPlatformInterface _vulkan;
private readonly long? _maxResourceBytes; public long? MaxResourceBytes { get; }
private GRVkBackendContext _grVkBackend;
private bool _initialized;
public GRContext GrContext { get; private set; }
public VulkanSkiaGpu(long? maxResourceBytes) public VulkanSkiaGpu(long? maxResourceBytes)
{ {
_vulkan = AvaloniaLocator.Current.GetService<VulkanPlatformInterface>(); _vulkan = AvaloniaLocator.Current.GetService<VulkanPlatformInterface>();
_maxResourceBytes = maxResourceBytes; MaxResourceBytes = maxResourceBytes;
}
private void Initialize()
{
if (_initialized)
{
return;
}
_initialized = true;
GRVkGetProcedureAddressDelegate getProc = (string name, IntPtr instanceHandle, IntPtr deviceHandle) =>
{
IntPtr addr = IntPtr.Zero;
if (deviceHandle != IntPtr.Zero)
{
addr = _vulkan.Device.Api.GetDeviceProcAddr(new Device(deviceHandle), name);
if (addr != IntPtr.Zero)
{
return addr;
}
addr = _vulkan.Device.Api.GetDeviceProcAddr(new Device(_vulkan.Device.Handle), name);
if (addr != IntPtr.Zero)
{
return addr;
}
}
addr = _vulkan.Device.Api.GetInstanceProcAddr(new Instance(_vulkan.Instance.Handle), name);
if (addr == IntPtr.Zero)
{
addr = _vulkan.Device.Api.GetInstanceProcAddr(new Instance(instanceHandle), name);
}
return addr;
};
_grVkBackend = new GRVkBackendContext()
{
VkInstance = _vulkan.Device.Handle,
VkPhysicalDevice = _vulkan.PhysicalDevice.Handle,
VkDevice = _vulkan.Device.Handle,
VkQueue = _vulkan.Device.Queue.Handle,
GraphicsQueueIndex = _vulkan.PhysicalDevice.QueueFamilyIndex,
GetProcedureAddress = getProc
};
GrContext = GRContext.CreateVulkan(_grVkBackend);
if (_maxResourceBytes.HasValue)
{
GrContext.SetResourceCacheLimit(_maxResourceBytes.Value);
}
} }
public ISkiaGpuRenderTarget TryCreateRenderTarget(IEnumerable<object> surfaces) public ISkiaGpuRenderTarget TryCreateRenderTarget(IEnumerable<object> surfaces)
@@ -106,10 +47,6 @@ namespace Ryujinx.Ava.Ui.Backend.Vulkan
VulkanRenderTarget vulkanRenderTarget = new VulkanRenderTarget(_vulkan, window); VulkanRenderTarget vulkanRenderTarget = new VulkanRenderTarget(_vulkan, window);
Initialize();
vulkanRenderTarget.GrContext = GrContext;
return vulkanRenderTarget; return vulkanRenderTarget;
} }

View File

@@ -1,5 +1,6 @@
using System; using System;
using Avalonia; using Avalonia;
using Ryujinx.Graphics.Vulkan;
using Silk.NET.Vulkan; using Silk.NET.Vulkan;
namespace Ryujinx.Ava.Ui.Vulkan.Surfaces namespace Ryujinx.Ava.Ui.Vulkan.Surfaces
@@ -7,24 +8,35 @@ namespace Ryujinx.Ava.Ui.Vulkan.Surfaces
internal class VulkanSurfaceRenderTarget : IDisposable internal class VulkanSurfaceRenderTarget : IDisposable
{ {
private readonly VulkanPlatformInterface _platformInterface; private readonly VulkanPlatformInterface _platformInterface;
private readonly Format _format; private readonly Format _format;
public VulkanImage Image { get; private set; } private VulkanCommandBufferPool.VulkanCommandBuffer _commandBuffer;
public bool IsCorrupted { get; private set; } = true; private VulkanImage Image { get; set; }
private object _lock = new object();
public uint MipLevels => Image.MipLevels; public uint MipLevels => Image.MipLevels;
public VulkanDevice Device { get; }
public VulkanSurfaceRenderTarget(VulkanPlatformInterface platformInterface, VulkanSurface surface) public VulkanSurfaceRenderTarget(VulkanPlatformInterface platformInterface, VulkanSurface surface)
{ {
_platformInterface = platformInterface; _platformInterface = platformInterface;
Display = VulkanDisplay.CreateDisplay(platformInterface.Instance, platformInterface.Device, var device = VulkanInitialization.CreateDevice(platformInterface.Api,
platformInterface.PhysicalDevice, surface); platformInterface.PhysicalDevice.InternalHandle,
platformInterface.PhysicalDevice.QueueFamilyIndex,
VulkanInitialization.GetSupportedExtensions(platformInterface.Api, platformInterface.PhysicalDevice.InternalHandle),
platformInterface.PhysicalDevice.QueueCount);
Device = new VulkanDevice(device, platformInterface.PhysicalDevice, platformInterface.Api);
Display = VulkanDisplay.CreateDisplay(
platformInterface.Instance,
Device,
platformInterface.PhysicalDevice,
surface);
Surface = surface; Surface = surface;
// Skia seems to only create surfaces from images with unorm format // Skia seems to only create surfaces from images with unorm format
IsRgba = Display.SurfaceFormat.Format >= Format.R8G8B8A8Unorm && IsRgba = Display.SurfaceFormat.Format >= Format.R8G8B8A8Unorm &&
Display.SurfaceFormat.Format <= Format.R8G8B8A8Srgb; Display.SurfaceFormat.Format <= Format.R8G8B8A8Srgb;
@@ -33,13 +45,13 @@ namespace Ryujinx.Ava.Ui.Vulkan.Surfaces
public bool IsRgba { get; } public bool IsRgba { get; }
public uint ImageFormat => (uint) _format; public uint ImageFormat => (uint)_format;
public ulong MemorySize => Image.MemorySize; public ulong MemorySize => Image.MemorySize;
public VulkanDisplay Display { get; } public VulkanDisplay Display { get; private set; }
public VulkanSurface Surface { get; } public VulkanSurface Surface { get; private set; }
public uint UsageFlags => Image.UsageFlags; public uint UsageFlags => Image.UsageFlags;
@@ -47,46 +59,76 @@ namespace Ryujinx.Ava.Ui.Vulkan.Surfaces
public void Dispose() public void Dispose()
{ {
_platformInterface.Device.WaitIdle(); lock (_lock)
DestroyImage(); {
Display?.Dispose(); DestroyImage();
Surface?.Dispose(); Display?.Dispose();
Surface?.Dispose();
Device?.Dispose();
Display = null;
Surface = null;
}
} }
public VulkanSurfaceRenderingSession BeginDraw(float scaling) public VulkanSurfaceRenderingSession BeginDraw(float scaling)
{ {
var session = new VulkanSurfaceRenderingSession(Display, _platformInterface.Device, this, scaling); if (Image == null)
{
RecreateImage();
}
if (IsCorrupted) _commandBuffer?.WaitForFence();
{ _commandBuffer = null;
IsCorrupted = false;
DestroyImage(); var session = new VulkanSurfaceRenderingSession(Display, Device, this, scaling);
CreateImage();
} Image.TransitionLayout(ImageLayout.ColorAttachmentOptimal, AccessFlags.AccessNoneKhr);
else
{
Image.TransitionLayout(ImageLayout.ColorAttachmentOptimal, AccessFlags.AccessNoneKhr);
}
return session; return session;
} }
public void Invalidate() public void RecreateImage()
{ {
IsCorrupted = true; DestroyImage();
CreateImage();
} }
private void CreateImage() private void CreateImage()
{ {
Size = Display.Size; Size = Display.Size;
Image = new VulkanImage(_platformInterface.Device, _platformInterface.PhysicalDevice, _platformInterface.Device.CommandBufferPool, ImageFormat, Size); Image = new VulkanImage(Device, _platformInterface.PhysicalDevice, Display.CommandBufferPool, ImageFormat, Size);
} }
private void DestroyImage() private void DestroyImage()
{ {
_platformInterface.Device.WaitIdle(); _commandBuffer?.WaitForFence();
_commandBuffer = null;
Image?.Dispose(); Image?.Dispose();
Image = null;
}
public VulkanImage GetImage()
{
return Image;
}
public void EndDraw()
{
lock (_lock)
{
if (Display == null)
{
return;
}
_commandBuffer = Display.StartPresentation();
Display.BlitImageToCurrentImage(this, _commandBuffer.InternalHandle);
Display.EndPresentation(_commandBuffer);
}
} }
} }
} }

View File

@@ -10,6 +10,7 @@ namespace Ryujinx.Ava.Ui.Vulkan
private readonly CommandPool _commandPool; private readonly CommandPool _commandPool;
private readonly List<VulkanCommandBuffer> _usedCommandBuffers = new(); private readonly List<VulkanCommandBuffer> _usedCommandBuffers = new();
private readonly object _lock = new object();
public unsafe VulkanCommandBufferPool(VulkanDevice device, VulkanPhysicalDevice physicalDevice) public unsafe VulkanCommandBufferPool(VulkanDevice device, VulkanPhysicalDevice physicalDevice)
{ {
@@ -36,9 +37,12 @@ namespace Ryujinx.Ava.Ui.Vulkan
Level = CommandBufferLevel.Primary Level = CommandBufferLevel.Primary
}; };
_device.Api.AllocateCommandBuffers(_device.InternalHandle, commandBufferAllocateInfo, out var commandBuffer); lock (_lock)
{
_device.Api.AllocateCommandBuffers(_device.InternalHandle, commandBufferAllocateInfo, out var commandBuffer);
return commandBuffer; return commandBuffer;
}
} }
public VulkanCommandBuffer CreateCommandBuffer() public VulkanCommandBuffer CreateCommandBuffer()
@@ -48,7 +52,7 @@ namespace Ryujinx.Ava.Ui.Vulkan
public void FreeUsedCommandBuffers() public void FreeUsedCommandBuffers()
{ {
lock (_usedCommandBuffers) lock (_lock)
{ {
foreach (var usedCommandBuffer in _usedCommandBuffers) foreach (var usedCommandBuffer in _usedCommandBuffers)
{ {
@@ -61,7 +65,7 @@ namespace Ryujinx.Ava.Ui.Vulkan
private void DisposeCommandBuffer(VulkanCommandBuffer commandBuffer) private void DisposeCommandBuffer(VulkanCommandBuffer commandBuffer)
{ {
lock (_usedCommandBuffers) lock (_lock)
{ {
_usedCommandBuffers.Add(commandBuffer); _usedCommandBuffers.Add(commandBuffer);
} }
@@ -69,8 +73,11 @@ namespace Ryujinx.Ava.Ui.Vulkan
public void Dispose() public void Dispose()
{ {
FreeUsedCommandBuffers(); lock (_lock)
_device.Api.DestroyCommandPool(_device.InternalHandle, _commandPool, Span<AllocationCallbacks>.Empty); {
FreeUsedCommandBuffers();
_device.Api.DestroyCommandPool(_device.InternalHandle, _commandPool, Span<AllocationCallbacks>.Empty);
}
} }
public class VulkanCommandBuffer : IDisposable public class VulkanCommandBuffer : IDisposable
@@ -80,6 +87,8 @@ namespace Ryujinx.Ava.Ui.Vulkan
private readonly Fence _fence; private readonly Fence _fence;
private bool _hasEnded; private bool _hasEnded;
private bool _hasStarted; private bool _hasStarted;
private bool _isDisposed;
private object _lock = new object();
public IntPtr Handle => InternalHandle.Handle; public IntPtr Handle => InternalHandle.Handle;
@@ -101,6 +110,22 @@ namespace Ryujinx.Ava.Ui.Vulkan
device.Api.CreateFence(device.InternalHandle, fenceCreateInfo, null, out _fence); device.Api.CreateFence(device.InternalHandle, fenceCreateInfo, null, out _fence);
} }
public void WaitForFence()
{
if (_isDisposed)
{
return;
}
lock (_lock)
{
if (!_isDisposed)
{
_device.Api.WaitForFences(_device.InternalHandle, 1, _fence, true, ulong.MaxValue);
}
}
}
public void BeginRecording() public void BeginRecording()
{ {
if (!_hasStarted) if (!_hasStarted)
@@ -173,9 +198,17 @@ namespace Ryujinx.Ava.Ui.Vulkan
public void Dispose() public void Dispose()
{ {
_device.Api.WaitForFences(_device.InternalHandle, 1, _fence, true, ulong.MaxValue); lock (_lock)
_device.Api.FreeCommandBuffers(_device.InternalHandle, _commandBufferPool._commandPool, 1, InternalHandle); {
_device.Api.DestroyFence(_device.InternalHandle, _fence, Span<AllocationCallbacks>.Empty); if (!_isDisposed)
{
_isDisposed = true;
_device.Api.WaitForFences(_device.InternalHandle, 1, _fence, true, ulong.MaxValue);
_device.Api.FreeCommandBuffers(_device.InternalHandle, _commandBufferPool._commandPool, 1, InternalHandle);
_device.Api.DestroyFence(_device.InternalHandle, _fence, Span<AllocationCallbacks>.Empty);
}
}
} }
} }
} }

View File

@@ -14,12 +14,9 @@ namespace Ryujinx.Ava.Ui.Vulkan
api.GetDeviceQueue(apiHandle, physicalDevice.QueueFamilyIndex, 0, out var queue); api.GetDeviceQueue(apiHandle, physicalDevice.QueueFamilyIndex, 0, out var queue);
var vulkanQueue = new VulkanQueue(this, queue); Queue = new VulkanQueue(this, queue);
Queue = vulkanQueue;
PresentQueue = vulkanQueue; PresentQueue = Queue;
CommandBufferPool = new VulkanCommandBufferPool(this, physicalDevice);
} }
public IntPtr Handle => InternalHandle.Handle; public IntPtr Handle => InternalHandle.Handle;
@@ -29,13 +26,12 @@ namespace Ryujinx.Ava.Ui.Vulkan
public VulkanQueue Queue { get; private set; } public VulkanQueue Queue { get; private set; }
public VulkanQueue PresentQueue { get; } public VulkanQueue PresentQueue { get; }
public VulkanCommandBufferPool CommandBufferPool { get; }
public void Dispose() public void Dispose()
{ {
WaitIdle(); WaitIdle();
CommandBufferPool?.Dispose();
Queue = null; Queue = null;
Api.DestroyDevice(InternalHandle, Span<AllocationCallbacks>.Empty);
} }
internal void Submit(SubmitInfo submitInfo, Fence fence = default) internal void Submit(SubmitInfo submitInfo, Fence fence = default)

View File

@@ -3,7 +3,6 @@ using System.Linq;
using System.Threading; using System.Threading;
using Avalonia; using Avalonia;
using Ryujinx.Ava.Ui.Vulkan.Surfaces; using Ryujinx.Ava.Ui.Vulkan.Surfaces;
using Ryujinx.Ui.Common.Configuration;
using Silk.NET.Vulkan; using Silk.NET.Vulkan;
using Silk.NET.Vulkan.Extensions.KHR; using Silk.NET.Vulkan.Extensions.KHR;
@@ -15,16 +14,19 @@ namespace Ryujinx.Ava.Ui.Vulkan
private readonly VulkanInstance _instance; private readonly VulkanInstance _instance;
private readonly VulkanPhysicalDevice _physicalDevice; private readonly VulkanPhysicalDevice _physicalDevice;
private readonly VulkanSemaphorePair _semaphorePair; private readonly VulkanSemaphorePair _semaphorePair;
private readonly VulkanDevice _device;
private uint _nextImage; private uint _nextImage;
private readonly VulkanSurface _surface; private readonly VulkanSurface _surface;
private SurfaceFormatKHR _surfaceFormat; private SurfaceFormatKHR _surfaceFormat;
private SwapchainKHR _swapchain; private SwapchainKHR _swapchain;
private Extent2D _swapchainExtent; private Extent2D _swapchainExtent;
private Image[] _swapchainImages; private Image[] _swapchainImages;
private VulkanDevice _device { get; } private ImageView[] _swapchainImageViews = Array.Empty<ImageView>();
private ImageView[] _swapchainImageViews = new ImageView[0];
private bool _vsyncStateChanged; private bool _vsyncStateChanged;
private bool _vsyncEnabled; private bool _vsyncEnabled;
private bool _surfaceChanged;
public event EventHandler Presented;
public VulkanCommandBufferPool CommandBufferPool { get; set; } public VulkanCommandBufferPool CommandBufferPool { get; set; }
@@ -73,6 +75,14 @@ namespace Ryujinx.Ava.Ui.Vulkan
CommandBufferPool.Dispose(); CommandBufferPool.Dispose();
} }
public bool IsSurfaceChanged()
{
var changed = _surfaceChanged;
_surfaceChanged = false;
return changed;
}
private static unsafe SwapchainKHR CreateSwapchain(VulkanInstance instance, VulkanDevice device, private static unsafe SwapchainKHR CreateSwapchain(VulkanInstance instance, VulkanDevice device,
VulkanPhysicalDevice physicalDevice, VulkanSurface surface, out Extent2D swapchainExtent, VulkanPhysicalDevice physicalDevice, VulkanSurface surface, out Extent2D swapchainExtent,
SwapchainKHR? oldswapchain = null, bool vsyncEnabled = true) SwapchainKHR? oldswapchain = null, bool vsyncEnabled = true)
@@ -193,22 +203,23 @@ namespace Ryujinx.Ava.Ui.Vulkan
} }
var modes = presentModes.ToList(); var modes = presentModes.ToList();
var presentMode = PresentModeKHR.PresentModeFifoKhr;
if (!vsyncEnabled && modes.Contains(PresentModeKHR.PresentModeImmediateKhr)) if (!vsyncEnabled && modes.Contains(PresentModeKHR.PresentModeImmediateKhr))
{ {
presentMode = PresentModeKHR.PresentModeImmediateKhr; return PresentModeKHR.PresentModeImmediateKhr;
} }
else if (modes.Contains(PresentModeKHR.PresentModeMailboxKhr)) else if (modes.Contains(PresentModeKHR.PresentModeMailboxKhr))
{ {
presentMode = PresentModeKHR.PresentModeMailboxKhr; return PresentModeKHR.PresentModeMailboxKhr;
} }
else if (modes.Contains(PresentModeKHR.PresentModeImmediateKhr)) else if (modes.Contains(PresentModeKHR.PresentModeFifoKhr))
{ {
presentMode = PresentModeKHR.PresentModeImmediateKhr; return PresentModeKHR.PresentModeFifoKhr;
}
else
{
return PresentModeKHR.PresentModeImmediateKhr;
} }
return presentMode;
} }
internal static VulkanDisplay CreateDisplay(VulkanInstance instance, VulkanDevice device, internal static VulkanDisplay CreateDisplay(VulkanInstance instance, VulkanDevice device,
@@ -266,6 +277,8 @@ namespace Ryujinx.Ava.Ui.Vulkan
_swapchain = CreateSwapchain(_instance, _device, _physicalDevice, _surface, out _swapchainExtent, _swapchain, _vsyncEnabled); _swapchain = CreateSwapchain(_instance, _device, _physicalDevice, _surface, out _swapchainExtent, _swapchain, _vsyncEnabled);
CreateSwapchainImages(); CreateSwapchainImages();
_surfaceChanged = true;
} }
private unsafe ImageView CreateSwapchainImageView(Image swapchainImage, Format format) private unsafe ImageView CreateSwapchainImageView(Image swapchainImage, Format format)
@@ -306,7 +319,7 @@ namespace Ryujinx.Ava.Ui.Vulkan
return true; return true;
} }
internal VulkanCommandBufferPool.VulkanCommandBuffer StartPresentation(VulkanSurfaceRenderTarget renderTarget) internal VulkanCommandBufferPool.VulkanCommandBuffer StartPresentation()
{ {
_nextImage = 0; _nextImage = 0;
while (true) while (true)
@@ -346,8 +359,10 @@ namespace Ryujinx.Ava.Ui.Vulkan
internal void BlitImageToCurrentImage(VulkanSurfaceRenderTarget renderTarget, CommandBuffer commandBuffer) internal void BlitImageToCurrentImage(VulkanSurfaceRenderTarget renderTarget, CommandBuffer commandBuffer)
{ {
var image = renderTarget.GetImage();
VulkanMemoryHelper.TransitionLayout(_device, commandBuffer, VulkanMemoryHelper.TransitionLayout(_device, commandBuffer,
renderTarget.Image.InternalHandle.Value, (ImageLayout)renderTarget.Image.CurrentLayout, image.InternalHandle.Value, (ImageLayout)image.CurrentLayout,
AccessFlags.AccessNoneKhr, AccessFlags.AccessNoneKhr,
ImageLayout.TransferSrcOptimal, ImageLayout.TransferSrcOptimal,
AccessFlags.AccessTransferReadBit, AccessFlags.AccessTransferReadBit,
@@ -381,7 +396,7 @@ namespace Ryujinx.Ava.Ui.Vulkan
} }
}; };
_device.Api.CmdBlitImage(commandBuffer, renderTarget.Image.InternalHandle.Value, _device.Api.CmdBlitImage(commandBuffer, image.InternalHandle.Value,
ImageLayout.TransferSrcOptimal, ImageLayout.TransferSrcOptimal,
_swapchainImages[_nextImage], _swapchainImages[_nextImage],
ImageLayout.TransferDstOptimal, ImageLayout.TransferDstOptimal,
@@ -390,9 +405,9 @@ namespace Ryujinx.Ava.Ui.Vulkan
Filter.Linear); Filter.Linear);
VulkanMemoryHelper.TransitionLayout(_device, commandBuffer, VulkanMemoryHelper.TransitionLayout(_device, commandBuffer,
renderTarget.Image.InternalHandle.Value, ImageLayout.TransferSrcOptimal, image.InternalHandle.Value, ImageLayout.TransferSrcOptimal,
AccessFlags.AccessTransferReadBit, AccessFlags.AccessTransferReadBit,
(ImageLayout)renderTarget.Image.CurrentLayout, (ImageLayout)image.CurrentLayout,
AccessFlags.AccessNoneKhr, AccessFlags.AccessNoneKhr,
renderTarget.MipLevels); renderTarget.MipLevels);
} }
@@ -434,6 +449,8 @@ namespace Ryujinx.Ava.Ui.Vulkan
} }
CommandBufferPool.FreeUsedCommandBuffers(); CommandBufferPool.FreeUsedCommandBuffers();
Presented?.Invoke(this, null);
} }
} }
} }

View File

@@ -148,20 +148,18 @@ namespace Ryujinx.Ava.Ui.Vulkan
_currentAccessFlags = destinationAccessFlags; _currentAccessFlags = destinationAccessFlags;
} }
public void TransitionLayout(uint destinationLayout, uint destinationAccessFlags) public void Dispose()
{ {
TransitionLayout((ImageLayout)destinationLayout, (AccessFlags)destinationAccessFlags); if (InternalHandle != null)
} {
_device.Api.DestroyImageView(_device.InternalHandle, _imageView.Value, Span<AllocationCallbacks>.Empty);
_device.Api.DestroyImage(_device.InternalHandle, InternalHandle.Value, Span<AllocationCallbacks>.Empty);
_device.Api.FreeMemory(_device.InternalHandle, _imageMemory, Span<AllocationCallbacks>.Empty);
public unsafe void Dispose() _imageView = default;
{ InternalHandle = null;
_device.Api.DestroyImageView(_device.InternalHandle, _imageView.Value, null); _imageMemory = default;
_device.Api.DestroyImage(_device.InternalHandle, InternalHandle.Value, null); }
_device.Api.FreeMemory(_device.InternalHandle, _imageMemory, null);
_imageView = default;
InternalHandle = default;
_imageMemory = default;
} }
} }
} }

View File

@@ -57,8 +57,7 @@ namespace Ryujinx.Ava.Ui.Vulkan
var applicationInfo = new ApplicationInfo var applicationInfo = new ApplicationInfo
{ {
PApplicationName = (byte*)applicationName, PApplicationName = (byte*)applicationName,
ApiVersion = new Version32((uint)options.VulkanVersion.Major, (uint)options.VulkanVersion.Minor, ApiVersion = Vk.Version12.Value,
(uint)options.VulkanVersion.Build),
PEngineName = (byte*)engineName, PEngineName = (byte*)engineName,
EngineVersion = new Version32(1, 0, 0), EngineVersion = new Version32(1, 0, 0),
ApplicationVersion = new Version32(1, 0, 0) ApplicationVersion = new Version32(1, 0, 0)

View File

@@ -11,11 +11,6 @@ namespace Ryujinx.Ava.Ui.Vulkan
/// </summary> /// </summary>
public string ApplicationName { get; set; } public string ApplicationName { get; set; }
/// <summary>
/// Specifies the Vulkan API version to use
/// </summary>
public Version VulkanVersion { get; set; } = new Version(1, 1, 0);
/// <summary> /// <summary>
/// Specifies additional extensions to enable if available on the instance /// Specifies additional extensions to enable if available on the instance
/// </summary> /// </summary>

View File

@@ -18,13 +18,11 @@ namespace Ryujinx.Ava.Ui.Vulkan
public VulkanPhysicalDevice PhysicalDevice { get; private set; } public VulkanPhysicalDevice PhysicalDevice { get; private set; }
public VulkanInstance Instance { get; } public VulkanInstance Instance { get; }
public VulkanDevice Device { get; set; }
public Vk Api { get; private set; } public Vk Api { get; private set; }
public VulkanSurfaceRenderTarget MainSurface { get; set; } public VulkanSurfaceRenderTarget MainSurface { get; set; }
public void Dispose() public void Dispose()
{ {
Device?.Dispose();
Instance?.Dispose(); Instance?.Dispose();
Api?.Dispose(); Api?.Dispose();
} }
@@ -54,16 +52,9 @@ namespace Ryujinx.Ava.Ui.Vulkan
{ {
var surface = VulkanSurface.CreateSurface(Instance, platformSurface); var surface = VulkanSurface.CreateSurface(Instance, platformSurface);
if (Device == null) if (PhysicalDevice == null)
{ {
PhysicalDevice = VulkanPhysicalDevice.FindSuitablePhysicalDevice(Instance, surface, _options.PreferDiscreteGpu, _options.PreferredDevice); PhysicalDevice = VulkanPhysicalDevice.FindSuitablePhysicalDevice(Instance, surface, _options.PreferDiscreteGpu, _options.PreferredDevice);
var device = VulkanInitialization.CreateDevice(Instance.Api,
PhysicalDevice.InternalHandle,
PhysicalDevice.QueueFamilyIndex,
VulkanInitialization.GetSupportedExtensions(Instance.Api, PhysicalDevice.InternalHandle),
PhysicalDevice.QueueCount);
Device = new VulkanDevice(device, PhysicalDevice, Instance.Api);
} }
var renderTarget = new VulkanSurfaceRenderTarget(this, surface); var renderTarget = new VulkanSurfaceRenderTarget(this, surface);
@@ -71,7 +62,6 @@ namespace Ryujinx.Ava.Ui.Vulkan
if (MainSurface == null && surface != null) if (MainSurface == null && surface != null)
{ {
MainSurface = renderTarget; MainSurface = renderTarget;
MainSurface.Display.ChangeVSyncMode(false);
} }
return renderTarget; return renderTarget;

View File

@@ -9,7 +9,6 @@ namespace Ryujinx.Ava.Ui.Vulkan
{ {
private readonly VulkanDevice _device; private readonly VulkanDevice _device;
private readonly VulkanSurfaceRenderTarget _renderTarget; private readonly VulkanSurfaceRenderTarget _renderTarget;
private VulkanCommandBufferPool.VulkanCommandBuffer _commandBuffer;
public VulkanSurfaceRenderingSession(VulkanDisplay display, VulkanDevice device, public VulkanSurfaceRenderingSession(VulkanDisplay display, VulkanDevice device,
VulkanSurfaceRenderTarget renderTarget, float scaling) VulkanSurfaceRenderTarget renderTarget, float scaling)
@@ -32,17 +31,13 @@ namespace Ryujinx.Ava.Ui.Vulkan
{ {
if (!Display.EnsureSwapchainAvailable()) if (!Display.EnsureSwapchainAvailable())
{ {
_renderTarget.Invalidate(); _renderTarget.RecreateImage();
} }
} }
public void Dispose() public void Dispose()
{ {
_commandBuffer = Display.StartPresentation(_renderTarget); _renderTarget.EndDraw();
Display.BlitImageToCurrentImage(_renderTarget, _commandBuffer.InternalHandle);
Display.EndPresentation(_commandBuffer);
} }
} }
} }

View File

@@ -37,7 +37,7 @@ namespace Ryujinx.Ava.Ui.Controls
public override void DestroyBackgroundContext() public override void DestroyBackgroundContext()
{ {
_image = null; Image = null;
if (_fence != IntPtr.Zero) if (_fence != IntPtr.Zero)
{ {
@@ -57,6 +57,8 @@ namespace Ryujinx.Ava.Ui.Controls
Dispatcher.UIThread.InvokeAsync(() => Dispatcher.UIThread.InvokeAsync(() =>
{ {
Image = (int)image; Image = (int)image;
InvalidateVisual();
}).Wait(); }).Wait();
if (_fence != IntPtr.Zero) if (_fence != IntPtr.Zero)
@@ -66,7 +68,7 @@ namespace Ryujinx.Ava.Ui.Controls
_fence = GL.FenceSync(SyncCondition.SyncGpuCommandsComplete, WaitSyncFlags.None); _fence = GL.FenceSync(SyncCondition.SyncGpuCommandsComplete, WaitSyncFlags.None);
QueueRender(); InvalidateVisual();
_gameBackgroundWindow.SwapBuffers(); _gameBackgroundWindow.SwapBuffers();
} }

View File

@@ -11,25 +11,7 @@ namespace Ryujinx.Ava.Ui.Controls
{ {
internal abstract class RendererControl : Control internal abstract class RendererControl : Control
{ {
protected object _image; protected object Image { get; set; }
static RendererControl()
{
AffectsRender<RendererControl>(ImageProperty);
}
public readonly static StyledProperty<object> ImageProperty =
AvaloniaProperty.Register<RendererControl, object>(
nameof(Image),
0,
inherits: true,
defaultBindingMode: BindingMode.TwoWay);
protected object Image
{
get => _image;
set => SetAndRaise(ImageProperty, ref _image, value);
}
public event EventHandler<EventArgs> RendererInitialized; public event EventHandler<EventArgs> RendererInitialized;
public event EventHandler<Size> SizeChanged; public event EventHandler<Size> SizeChanged;
@@ -60,8 +42,6 @@ namespace Ryujinx.Ava.Ui.Controls
if (!rect.IsEmpty) if (!rect.IsEmpty)
{ {
RenderSize = rect.Size * VisualRoot.RenderScaling; RenderSize = rect.Size * VisualRoot.RenderScaling;
DrawOperation?.Dispose();
DrawOperation = CreateDrawOperation(); DrawOperation = CreateDrawOperation();
} }
} }
@@ -97,17 +77,11 @@ namespace Ryujinx.Ava.Ui.Controls
RendererInitialized?.Invoke(this, EventArgs.Empty); RendererInitialized?.Invoke(this, EventArgs.Empty);
} }
public void QueueRender()
{
Program.RenderTimer.TickNow();
}
internal abstract void Present(object image); internal abstract void Present(object image);
internal void Start() internal void Start()
{ {
IsStarted = true; IsStarted = true;
QueueRender();
} }
internal void Stop() internal void Stop()

View File

@@ -1,4 +1,5 @@
using Avalonia; using Avalonia;
using Avalonia.Media;
using Avalonia.Platform; using Avalonia.Platform;
using Avalonia.Rendering.SceneGraph; using Avalonia.Rendering.SceneGraph;
using Avalonia.Skia; using Avalonia.Skia;
@@ -11,20 +12,23 @@ using Silk.NET.Vulkan;
using SkiaSharp; using SkiaSharp;
using SPB.Windowing; using SPB.Windowing;
using System; using System;
using System.Collections.Generic; using System.Collections.Concurrent;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Ryujinx.Ava.Ui.Controls namespace Ryujinx.Ava.Ui.Controls
{ {
internal class VulkanRendererControl : RendererControl internal class VulkanRendererControl : RendererControl
{ {
private const int MaxImagesInFlight = 3;
private VulkanPlatformInterface _platformInterface; private VulkanPlatformInterface _platformInterface;
private ConcurrentQueue<PresentImageInfo> _imagesInFlight;
private PresentImageInfo _currentImage;
public VulkanRendererControl(GraphicsDebugLevel graphicsDebugLevel) : base(graphicsDebugLevel) public VulkanRendererControl(GraphicsDebugLevel graphicsDebugLevel) : base(graphicsDebugLevel)
{ {
_platformInterface = AvaloniaLocator.Current.GetService<VulkanPlatformInterface>(); _platformInterface = AvaloniaLocator.Current.GetService<VulkanPlatformInterface>();
_imagesInFlight = new ConcurrentQueue<PresentImageInfo>();
} }
public override void DestroyBackgroundContext() public override void DestroyBackgroundContext()
@@ -37,6 +41,40 @@ namespace Ryujinx.Ava.Ui.Controls
return new VulkanDrawOperation(this); return new VulkanDrawOperation(this);
} }
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnDetachedFromVisualTree(e);
_imagesInFlight.Clear();
if (_platformInterface.MainSurface.Display != null)
{
_platformInterface.MainSurface.Display.Presented -= Window_Presented;
}
_currentImage?.Put();
_currentImage = null;
}
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnAttachedToVisualTree(e);
_platformInterface.MainSurface.Display.Presented += Window_Presented;
}
private void Window_Presented(object sender, EventArgs e)
{
_platformInterface.MainSurface.Device.QueueWaitIdle();
_currentImage?.Put();
_currentImage = null;
}
public override void Render(DrawingContext context)
{
base.Render(context);
}
protected override void CreateWindow() protected override void CreateWindow()
{ {
} }
@@ -51,12 +89,29 @@ namespace Ryujinx.Ava.Ui.Controls
internal override void Present(object image) internal override void Present(object image)
{ {
Dispatcher.UIThread.InvokeAsync(() => Image = image;
{
Image = image;
}).Wait();
QueueRender(); _imagesInFlight.Enqueue((PresentImageInfo)image);
if (_imagesInFlight.Count > MaxImagesInFlight)
{
_imagesInFlight.TryDequeue(out _);
}
Dispatcher.UIThread.Post(InvalidateVisual);
}
private PresentImageInfo GetImage()
{
lock (_imagesInFlight)
{
if (!_imagesInFlight.TryDequeue(out _currentImage))
{
_currentImage = (PresentImageInfo)Image;
}
return _currentImage;
}
} }
private class VulkanDrawOperation : ICustomDrawOperation private class VulkanDrawOperation : ICustomDrawOperation
@@ -64,6 +119,7 @@ namespace Ryujinx.Ava.Ui.Controls
public Rect Bounds { get; } public Rect Bounds { get; }
private readonly VulkanRendererControl _control; private readonly VulkanRendererControl _control;
private bool _isDestroyed;
public VulkanDrawOperation(VulkanRendererControl control) public VulkanDrawOperation(VulkanRendererControl control)
{ {
@@ -73,7 +129,12 @@ namespace Ryujinx.Ava.Ui.Controls
public void Dispose() public void Dispose()
{ {
if (_isDestroyed)
{
return;
}
_isDestroyed = true;
} }
public bool Equals(ICustomDrawOperation other) public bool Equals(ICustomDrawOperation other)
@@ -86,30 +147,33 @@ namespace Ryujinx.Ava.Ui.Controls
return Bounds.Contains(p); return Bounds.Contains(p);
} }
public void Render(IDrawingContextImpl context) public unsafe void Render(IDrawingContextImpl context)
{ {
if (_control.Image == null || _control.RenderSize.Width == 0 || _control.RenderSize.Height == 0) if (_isDestroyed || _control.Image == null || _control.RenderSize.Width == 0 || _control.RenderSize.Height == 0 ||
context is not ISkiaDrawingContextImpl skiaDrawingContextImpl)
{ {
return; return;
} }
var image = (PresentImageInfo)_control.Image; var image = _control.GetImage();
if (context is not ISkiaDrawingContextImpl skiaDrawingContextImpl) if (!image.State.IsValid)
{ {
_control._currentImage = null;
return; return;
} }
_control._platformInterface.Device.QueueWaitIdle();
var gpu = AvaloniaLocator.Current.GetService<VulkanSkiaGpu>(); var gpu = AvaloniaLocator.Current.GetService<VulkanSkiaGpu>();
image.Get();
var imageInfo = new GRVkImageInfo() var imageInfo = new GRVkImageInfo()
{ {
CurrentQueueFamily = _control._platformInterface.PhysicalDevice.QueueFamilyIndex, CurrentQueueFamily = _control._platformInterface.PhysicalDevice.QueueFamilyIndex,
Format = (uint)Format.R8G8B8A8Unorm, Format = (uint)Format.R8G8B8A8Unorm,
Image = image.Image.Handle, Image = image.Image.Handle,
ImageLayout = (uint)ImageLayout.ColorAttachmentOptimal, ImageLayout = (uint)ImageLayout.TransferSrcOptimal,
ImageTiling = (uint)ImageTiling.Optimal, ImageTiling = (uint)ImageTiling.Optimal,
ImageUsageFlags = (uint)(ImageUsageFlags.ImageUsageColorAttachmentBit ImageUsageFlags = (uint)(ImageUsageFlags.ImageUsageColorAttachmentBit
| ImageUsageFlags.ImageUsageTransferSrcBit | ImageUsageFlags.ImageUsageTransferSrcBit
@@ -127,13 +191,15 @@ namespace Ryujinx.Ava.Ui.Controls
}; };
using var backendTexture = new GRBackendRenderTarget( using var backendTexture = new GRBackendRenderTarget(
(int)_control.RenderSize.Width, (int)image.Extent.Width,
(int)_control.RenderSize.Height, (int)image.Extent.Height,
1, 1,
imageInfo); imageInfo);
var vulkan = AvaloniaLocator.Current.GetService<VulkanPlatformInterface>();
using var surface = SKSurface.Create( using var surface = SKSurface.Create(
gpu.GrContext, skiaDrawingContextImpl.GrContext,
backendTexture, backendTexture,
GRSurfaceOrigin.TopLeft, GRSurfaceOrigin.TopLeft,
SKColorType.Rgba8888); SKColorType.Rgba8888);
@@ -143,10 +209,11 @@ namespace Ryujinx.Ava.Ui.Controls
return; return;
} }
var rect = new Rect(new Point(), _control.RenderSize); var rect = new Rect(new Point(), new Size(image.Extent.Width, image.Extent.Height));
using var snapshot = surface.Snapshot(); using var snapshot = surface.Snapshot();
skiaDrawingContextImpl.SkCanvas.DrawImage(snapshot, rect.ToSKRect(), _control.Bounds.ToSKRect(), new SKPaint()); skiaDrawingContextImpl.SkCanvas.DrawImage(snapshot, rect.ToSKRect(), _control.Bounds.ToSKRect(),
new SKPaint());
} }
} }
} }

View File

@@ -38,6 +38,8 @@ namespace Ryujinx.Ava.Ui.ViewModels
{ {
internal class MainWindowViewModel : BaseModel internal class MainWindowViewModel : BaseModel
{ {
private const int HotKeyPressDelayMs = 500;
private readonly MainWindow _owner; private readonly MainWindow _owner;
private ObservableCollection<ApplicationData> _applications; private ObservableCollection<ApplicationData> _applications;
private string _aspectStatusText; private string _aspectStatusText;
@@ -54,6 +56,7 @@ namespace Ryujinx.Ava.Ui.ViewModels
private bool _isLoading; private bool _isLoading;
private int _progressMaximum; private int _progressMaximum;
private int _progressValue; private int _progressValue;
private long _lastFullscreenToggle = Environment.TickCount64;
private bool _showLoadProgress; private bool _showLoadProgress;
private bool _showMenuAndStatusBar = true; private bool _showMenuAndStatusBar = true;
private bool _showStatusSeparator; private bool _showStatusSeparator;
@@ -929,6 +932,13 @@ namespace Ryujinx.Ava.Ui.ViewModels
public void ToggleFullscreen() public void ToggleFullscreen()
{ {
if (Environment.TickCount64 - _lastFullscreenToggle < HotKeyPressDelayMs)
{
return;
}
_lastFullscreenToggle = Environment.TickCount64;
WindowState state = _owner.WindowState; WindowState state = _owner.WindowState;
if (state == WindowState.FullScreen) if (state == WindowState.FullScreen)
@@ -1085,6 +1095,11 @@ namespace Ryujinx.Ava.Ui.ViewModels
{ {
selection.Favorite = !selection.Favorite; selection.Favorite = !selection.Favorite;
_owner.ApplicationLibrary.LoadAndSaveMetaData(selection.TitleId, appMetadata =>
{
appMetadata.Favorite = selection.Favorite;
});
RefreshView(); RefreshView();
} }
} }

View File

@@ -48,6 +48,10 @@ namespace Ryujinx.Ava.Ui.ViewModels
private int _graphicsBackendMultithreadingIndex; private int _graphicsBackendMultithreadingIndex;
private float _previousVolumeLevel; private float _previousVolumeLevel;
private float _volume; private float _volume;
private bool _isVulkanAvailable = true;
private List<string> _gpuIds = new List<string>();
private KeyboardHotkeys _keyboardHotkeys;
private int _graphicsBackendIndex;
public int ResolutionScale public int ResolutionScale
{ {
@@ -97,6 +101,17 @@ namespace Ryujinx.Ava.Ui.ViewModels
} }
} }
public bool IsVulkanAvailable
{
get => _isVulkanAvailable;
set
{
_isVulkanAvailable = value;
OnPropertyChanged();
}
}
public bool EnableDiscordIntegration { get; set; } public bool EnableDiscordIntegration { get; set; }
public bool CheckUpdatesOnStart { get; set; } public bool CheckUpdatesOnStart { get; set; }
public bool ShowConfirmExit { get; set; } public bool ShowConfirmExit { get; set; }
@@ -143,10 +158,10 @@ namespace Ryujinx.Ava.Ui.ViewModels
public int BaseStyleIndex { get; set; } public int BaseStyleIndex { get; set; }
public int GraphicsBackendIndex public int GraphicsBackendIndex
{ {
get => graphicsBackendIndex; get => _graphicsBackendIndex;
set set
{ {
graphicsBackendIndex = value; _graphicsBackendIndex = value;
OnPropertyChanged(); OnPropertyChanged();
OnPropertyChanged(nameof(IsVulkanSelected)); OnPropertyChanged(nameof(IsVulkanSelected));
} }
@@ -170,14 +185,9 @@ namespace Ryujinx.Ava.Ui.ViewModels
public DateTimeOffset DateOffset { get; set; } public DateTimeOffset DateOffset { get; set; }
public TimeSpan TimeOffset { get; set; } public TimeSpan TimeOffset { get; set; }
public AvaloniaList<TimeZone> TimeZones { get; set; } public AvaloniaList<TimeZone> TimeZones { get; set; }
public AvaloniaList<string> GameDirectories { get; set; } public AvaloniaList<string> GameDirectories { get; set; }
public ObservableCollection<ComboBoxItem> AvailableGpus { get; set; } public ObservableCollection<ComboBoxItem> AvailableGpus { get; set; }
private KeyboardHotkeys _keyboardHotkeys;
private int graphicsBackendIndex;
private List<string> _gpuIds = new List<string>();
public KeyboardHotkeys KeyboardHotkeys public KeyboardHotkeys KeyboardHotkeys
{ {
get => _keyboardHotkeys; get => _keyboardHotkeys;
@@ -233,20 +243,31 @@ namespace Ryujinx.Ava.Ui.ViewModels
if (!Program.UseVulkan) if (!Program.UseVulkan)
{ {
var devices = VulkanRenderer.GetPhysicalDevices(); var devices = VulkanRenderer.GetPhysicalDevices();
foreach (var device in devices)
if (devices.Length == 0)
{ {
_gpuIds.Add(device.Id); IsVulkanAvailable = false;
names.Add($"{device.Name} {(device.IsDiscrete ? "(dGpu)" : "")}"); GraphicsBackendIndex = 1;
}
else
{
foreach (var device in devices)
{
_gpuIds.Add(device.Id);
names.Add($"{device.Name} {(device.IsDiscrete ? "(dGPU)" : "")}");
}
} }
} }
else else
{ {
foreach (var device in VulkanPhysicalDevice.SuitableDevices) foreach (var device in VulkanPhysicalDevice.SuitableDevices)
{ {
_gpuIds.Add(VulkanInitialization.StringFromIdPair(device.Value.VendorID, device.Value.DeviceID)); _gpuIds.Add(
VulkanInitialization.StringFromIdPair(device.Value.VendorID, device.Value.DeviceID));
var value = device.Value; var value = device.Value;
var name = value.DeviceName; var name = value.DeviceName;
names.Add($"{Marshal.PtrToStringAnsi((IntPtr)name)} {(device.Value.DeviceType == PhysicalDeviceType.DiscreteGpu ? "(dGpu)" : "")}"); names.Add(
$"{Marshal.PtrToStringAnsi((IntPtr)name)} {(device.Value.DeviceType == PhysicalDeviceType.DiscreteGpu ? "(dGPU)" : "")}");
} }
} }

View File

@@ -157,6 +157,10 @@
Command="{ReflectionBinding ChangeLanguage}" Command="{ReflectionBinding ChangeLanguage}"
CommandParameter="it_IT" CommandParameter="it_IT"
Header="Italian" /> Header="Italian" />
<MenuItem
Command="{ReflectionBinding ChangeLanguage}"
CommandParameter="ja_JP"
Header="Japanese" />
<MenuItem <MenuItem
Command="{ReflectionBinding ChangeLanguage}" Command="{ReflectionBinding ChangeLanguage}"
CommandParameter="ko_KR" CommandParameter="ko_KR"

View File

@@ -656,7 +656,12 @@ namespace Ryujinx.Ava.Ui.Windows
{ {
AppHost = null; AppHost = null;
Dispatcher.UIThread.Post(Close); Dispatcher.UIThread.Post(() =>
{
MainContent = null;
Close();
});
}; };
AppHost?.Stop(); AppHost?.Stop();

View File

@@ -519,7 +519,7 @@
HorizontalContentAlignment="Left" HorizontalContentAlignment="Left"
ToolTip.Tip="{locale:Locale SettingsTabGraphicsBackendTooltip}" ToolTip.Tip="{locale:Locale SettingsTabGraphicsBackendTooltip}"
SelectedIndex="{Binding GraphicsBackendIndex}"> SelectedIndex="{Binding GraphicsBackendIndex}">
<ComboBoxItem> <ComboBoxItem IsVisible="{Binding IsVulkanAvailable}">
<TextBlock Text="Vulkan" /> <TextBlock Text="Vulkan" />
</ComboBoxItem> </ComboBoxItem>
<ComboBoxItem> <ComboBoxItem>

View File

@@ -87,7 +87,7 @@ namespace Ryujinx.Common.Memory
/// Gets a span from the array. /// Gets a span from the array.
/// </summary> /// </summary>
/// <returns>Span of the array</returns> /// <returns>Span of the array</returns>
public Span<T> ToSpan() => Length == 0 ? Span<T>.Empty : MemoryMarshal.CreateSpan(ref this[0], Length); public Span<T> AsSpan() => Length == 0 ? Span<T>.Empty : MemoryMarshal.CreateSpan(ref this[0], Length);
/// <summary> /// <summary>
/// Gets the array base pointer. /// Gets the array base pointer.

View File

@@ -83,7 +83,7 @@ namespace Ryujinx.Common.Memory.PartialUnmaps
/// memory might be accessed but is unmapped. Users of the API must compensate for that by catching the /// memory might be accessed but is unmapped. Users of the API must compensate for that by catching the
/// access violation and retrying if it happened between the unmap and remap operation. /// access violation and retrying if it happened between the unmap and remap operation.
/// This method can be used to decide if retrying in such cases is necessary or not. /// This method can be used to decide if retrying in such cases is necessary or not.
/// ///
/// This version of the function is not used, but serves as a reference for the native /// This version of the function is not used, but serves as a reference for the native
/// implementation in ARMeilleure. /// implementation in ARMeilleure.
/// </remarks> /// </remarks>
@@ -128,12 +128,12 @@ namespace Ryujinx.Common.Memory.PartialUnmaps
const uint ExitCodeStillActive = 259; const uint ExitCodeStillActive = 259;
const int ThreadQueryInformation = 0x40; const int ThreadQueryInformation = 0x40;
Span<int> ids = LocalCounts.ThreadIds.ToSpan(); Span<int> ids = LocalCounts.ThreadIds.AsSpan();
for (int i = 0; i < ids.Length; i++) for (int i = 0; i < ids.Length; i++)
{ {
int id = ids[i]; int id = ids[i];
if (id != 0) if (id != 0)
{ {
IntPtr handle = OpenThread(ThreadQueryInformation, false, (uint)id); IntPtr handle = OpenThread(ThreadQueryInformation, false, (uint)id);

View File

@@ -7,8 +7,8 @@ namespace Ryujinx.Common.Memory
{ {
T _e0; T _e0;
public int Length => 1; public int Length => 1;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 1); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 1);
} }
public struct Array2<T> : IArray<T> where T : unmanaged public struct Array2<T> : IArray<T> where T : unmanaged
{ {
@@ -17,8 +17,8 @@ namespace Ryujinx.Common.Memory
Array1<T> _other; Array1<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 2; public int Length => 2;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 2); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 2);
} }
public struct Array3<T> : IArray<T> where T : unmanaged public struct Array3<T> : IArray<T> where T : unmanaged
{ {
@@ -27,8 +27,8 @@ namespace Ryujinx.Common.Memory
Array2<T> _other; Array2<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 3; public int Length => 3;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 3); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 3);
} }
public struct Array4<T> : IArray<T> where T : unmanaged public struct Array4<T> : IArray<T> where T : unmanaged
{ {
@@ -37,8 +37,8 @@ namespace Ryujinx.Common.Memory
Array3<T> _other; Array3<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 4; public int Length => 4;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 4); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 4);
} }
public struct Array5<T> : IArray<T> where T : unmanaged public struct Array5<T> : IArray<T> where T : unmanaged
{ {
@@ -47,8 +47,8 @@ namespace Ryujinx.Common.Memory
Array4<T> _other; Array4<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 5; public int Length => 5;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 5); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 5);
} }
public struct Array6<T> : IArray<T> where T : unmanaged public struct Array6<T> : IArray<T> where T : unmanaged
{ {
@@ -57,8 +57,8 @@ namespace Ryujinx.Common.Memory
Array5<T> _other; Array5<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 6; public int Length => 6;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 6); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 6);
} }
public struct Array7<T> : IArray<T> where T : unmanaged public struct Array7<T> : IArray<T> where T : unmanaged
{ {
@@ -67,8 +67,8 @@ namespace Ryujinx.Common.Memory
Array6<T> _other; Array6<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 7; public int Length => 7;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 7); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 7);
} }
public struct Array8<T> : IArray<T> where T : unmanaged public struct Array8<T> : IArray<T> where T : unmanaged
{ {
@@ -77,8 +77,8 @@ namespace Ryujinx.Common.Memory
Array7<T> _other; Array7<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 8; public int Length => 8;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 8); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 8);
} }
public struct Array9<T> : IArray<T> where T : unmanaged public struct Array9<T> : IArray<T> where T : unmanaged
{ {
@@ -87,8 +87,8 @@ namespace Ryujinx.Common.Memory
Array8<T> _other; Array8<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 9; public int Length => 9;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 9); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 9);
} }
public struct Array10<T> : IArray<T> where T : unmanaged public struct Array10<T> : IArray<T> where T : unmanaged
{ {
@@ -97,8 +97,8 @@ namespace Ryujinx.Common.Memory
Array9<T> _other; Array9<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 10; public int Length => 10;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 10); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 10);
} }
public struct Array11<T> : IArray<T> where T : unmanaged public struct Array11<T> : IArray<T> where T : unmanaged
{ {
@@ -107,8 +107,8 @@ namespace Ryujinx.Common.Memory
Array10<T> _other; Array10<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 11; public int Length => 11;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 11); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 11);
} }
public struct Array12<T> : IArray<T> where T : unmanaged public struct Array12<T> : IArray<T> where T : unmanaged
{ {
@@ -117,8 +117,8 @@ namespace Ryujinx.Common.Memory
Array11<T> _other; Array11<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 12; public int Length => 12;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 12); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 12);
} }
public struct Array13<T> : IArray<T> where T : unmanaged public struct Array13<T> : IArray<T> where T : unmanaged
{ {
@@ -127,8 +127,8 @@ namespace Ryujinx.Common.Memory
Array12<T> _other; Array12<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 13; public int Length => 13;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 13); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 13);
} }
public struct Array14<T> : IArray<T> where T : unmanaged public struct Array14<T> : IArray<T> where T : unmanaged
{ {
@@ -137,8 +137,8 @@ namespace Ryujinx.Common.Memory
Array13<T> _other; Array13<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 14; public int Length => 14;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 14); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 14);
} }
public struct Array15<T> : IArray<T> where T : unmanaged public struct Array15<T> : IArray<T> where T : unmanaged
{ {
@@ -147,8 +147,8 @@ namespace Ryujinx.Common.Memory
Array14<T> _other; Array14<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 15; public int Length => 15;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 15); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 15);
} }
public struct Array16<T> : IArray<T> where T : unmanaged public struct Array16<T> : IArray<T> where T : unmanaged
{ {
@@ -157,8 +157,8 @@ namespace Ryujinx.Common.Memory
Array15<T> _other; Array15<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 16; public int Length => 16;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 16); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 16);
} }
public struct Array17<T> : IArray<T> where T : unmanaged public struct Array17<T> : IArray<T> where T : unmanaged
{ {
@@ -167,8 +167,8 @@ namespace Ryujinx.Common.Memory
Array16<T> _other; Array16<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 17; public int Length => 17;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 17); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 17);
} }
public struct Array18<T> : IArray<T> where T : unmanaged public struct Array18<T> : IArray<T> where T : unmanaged
{ {
@@ -177,8 +177,8 @@ namespace Ryujinx.Common.Memory
Array17<T> _other; Array17<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 18; public int Length => 18;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 18); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 18);
} }
public struct Array19<T> : IArray<T> where T : unmanaged public struct Array19<T> : IArray<T> where T : unmanaged
{ {
@@ -187,8 +187,8 @@ namespace Ryujinx.Common.Memory
Array18<T> _other; Array18<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 19; public int Length => 19;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 19); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 19);
} }
public struct Array20<T> : IArray<T> where T : unmanaged public struct Array20<T> : IArray<T> where T : unmanaged
{ {
@@ -197,8 +197,8 @@ namespace Ryujinx.Common.Memory
Array19<T> _other; Array19<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 20; public int Length => 20;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 20); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 20);
} }
public struct Array21<T> : IArray<T> where T : unmanaged public struct Array21<T> : IArray<T> where T : unmanaged
{ {
@@ -207,8 +207,8 @@ namespace Ryujinx.Common.Memory
Array20<T> _other; Array20<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 21; public int Length => 21;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 21); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 21);
} }
public struct Array22<T> : IArray<T> where T : unmanaged public struct Array22<T> : IArray<T> where T : unmanaged
{ {
@@ -217,8 +217,8 @@ namespace Ryujinx.Common.Memory
Array21<T> _other; Array21<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 22; public int Length => 22;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 22); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 22);
} }
public struct Array23<T> : IArray<T> where T : unmanaged public struct Array23<T> : IArray<T> where T : unmanaged
{ {
@@ -227,8 +227,8 @@ namespace Ryujinx.Common.Memory
Array22<T> _other; Array22<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 23; public int Length => 23;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 23); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 23);
} }
public struct Array24<T> : IArray<T> where T : unmanaged public struct Array24<T> : IArray<T> where T : unmanaged
{ {
@@ -237,8 +237,8 @@ namespace Ryujinx.Common.Memory
Array23<T> _other; Array23<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 24; public int Length => 24;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 24); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 24);
} }
public struct Array25<T> : IArray<T> where T : unmanaged public struct Array25<T> : IArray<T> where T : unmanaged
{ {
@@ -247,8 +247,8 @@ namespace Ryujinx.Common.Memory
Array24<T> _other; Array24<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 25; public int Length => 25;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 25); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 25);
} }
public struct Array26<T> : IArray<T> where T : unmanaged public struct Array26<T> : IArray<T> where T : unmanaged
{ {
@@ -257,8 +257,8 @@ namespace Ryujinx.Common.Memory
Array25<T> _other; Array25<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 26; public int Length => 26;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 26); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 26);
} }
public struct Array27<T> : IArray<T> where T : unmanaged public struct Array27<T> : IArray<T> where T : unmanaged
{ {
@@ -267,8 +267,8 @@ namespace Ryujinx.Common.Memory
Array26<T> _other; Array26<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 27; public int Length => 27;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 27); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 27);
} }
public struct Array28<T> : IArray<T> where T : unmanaged public struct Array28<T> : IArray<T> where T : unmanaged
{ {
@@ -277,8 +277,8 @@ namespace Ryujinx.Common.Memory
Array27<T> _other; Array27<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 28; public int Length => 28;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 28); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 28);
} }
public struct Array29<T> : IArray<T> where T : unmanaged public struct Array29<T> : IArray<T> where T : unmanaged
{ {
@@ -287,8 +287,8 @@ namespace Ryujinx.Common.Memory
Array28<T> _other; Array28<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 29; public int Length => 29;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 29); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 29);
} }
public struct Array30<T> : IArray<T> where T : unmanaged public struct Array30<T> : IArray<T> where T : unmanaged
{ {
@@ -297,8 +297,8 @@ namespace Ryujinx.Common.Memory
Array29<T> _other; Array29<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 30; public int Length => 30;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 30); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 30);
} }
public struct Array31<T> : IArray<T> where T : unmanaged public struct Array31<T> : IArray<T> where T : unmanaged
{ {
@@ -307,8 +307,8 @@ namespace Ryujinx.Common.Memory
Array30<T> _other; Array30<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 31; public int Length => 31;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 31); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 31);
} }
public struct Array32<T> : IArray<T> where T : unmanaged public struct Array32<T> : IArray<T> where T : unmanaged
{ {
@@ -317,8 +317,8 @@ namespace Ryujinx.Common.Memory
Array31<T> _other; Array31<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 32; public int Length => 32;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 32); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 32);
} }
public struct Array33<T> : IArray<T> where T : unmanaged public struct Array33<T> : IArray<T> where T : unmanaged
{ {
@@ -327,8 +327,8 @@ namespace Ryujinx.Common.Memory
Array32<T> _other; Array32<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 33; public int Length => 33;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 33); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 33);
} }
public struct Array34<T> : IArray<T> where T : unmanaged public struct Array34<T> : IArray<T> where T : unmanaged
{ {
@@ -337,8 +337,8 @@ namespace Ryujinx.Common.Memory
Array33<T> _other; Array33<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 34; public int Length => 34;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 34); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 34);
} }
public struct Array35<T> : IArray<T> where T : unmanaged public struct Array35<T> : IArray<T> where T : unmanaged
{ {
@@ -347,8 +347,8 @@ namespace Ryujinx.Common.Memory
Array34<T> _other; Array34<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 35; public int Length => 35;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 35); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 35);
} }
public struct Array36<T> : IArray<T> where T : unmanaged public struct Array36<T> : IArray<T> where T : unmanaged
{ {
@@ -357,8 +357,8 @@ namespace Ryujinx.Common.Memory
Array35<T> _other; Array35<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 36; public int Length => 36;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 36); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 36);
} }
public struct Array37<T> : IArray<T> where T : unmanaged public struct Array37<T> : IArray<T> where T : unmanaged
{ {
@@ -367,8 +367,8 @@ namespace Ryujinx.Common.Memory
Array36<T> _other; Array36<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 37; public int Length => 37;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 37); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 37);
} }
public struct Array38<T> : IArray<T> where T : unmanaged public struct Array38<T> : IArray<T> where T : unmanaged
{ {
@@ -377,8 +377,8 @@ namespace Ryujinx.Common.Memory
Array37<T> _other; Array37<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 38; public int Length => 38;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 38); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 38);
} }
public struct Array39<T> : IArray<T> where T : unmanaged public struct Array39<T> : IArray<T> where T : unmanaged
{ {
@@ -387,8 +387,8 @@ namespace Ryujinx.Common.Memory
Array38<T> _other; Array38<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 39; public int Length => 39;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 39); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 39);
} }
public struct Array40<T> : IArray<T> where T : unmanaged public struct Array40<T> : IArray<T> where T : unmanaged
{ {
@@ -397,8 +397,8 @@ namespace Ryujinx.Common.Memory
Array39<T> _other; Array39<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 40; public int Length => 40;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 40); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 40);
} }
public struct Array41<T> : IArray<T> where T : unmanaged public struct Array41<T> : IArray<T> where T : unmanaged
{ {
@@ -407,8 +407,8 @@ namespace Ryujinx.Common.Memory
Array40<T> _other; Array40<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 41; public int Length => 41;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 41); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 41);
} }
public struct Array42<T> : IArray<T> where T : unmanaged public struct Array42<T> : IArray<T> where T : unmanaged
{ {
@@ -417,8 +417,8 @@ namespace Ryujinx.Common.Memory
Array41<T> _other; Array41<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 42; public int Length => 42;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 42); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 42);
} }
public struct Array43<T> : IArray<T> where T : unmanaged public struct Array43<T> : IArray<T> where T : unmanaged
{ {
@@ -427,8 +427,8 @@ namespace Ryujinx.Common.Memory
Array42<T> _other; Array42<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 43; public int Length => 43;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 43); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 43);
} }
public struct Array44<T> : IArray<T> where T : unmanaged public struct Array44<T> : IArray<T> where T : unmanaged
{ {
@@ -437,8 +437,8 @@ namespace Ryujinx.Common.Memory
Array43<T> _other; Array43<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 44; public int Length => 44;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 44); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 44);
} }
public struct Array45<T> : IArray<T> where T : unmanaged public struct Array45<T> : IArray<T> where T : unmanaged
{ {
@@ -447,8 +447,8 @@ namespace Ryujinx.Common.Memory
Array44<T> _other; Array44<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 45; public int Length => 45;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 45); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 45);
} }
public struct Array46<T> : IArray<T> where T : unmanaged public struct Array46<T> : IArray<T> where T : unmanaged
{ {
@@ -457,8 +457,8 @@ namespace Ryujinx.Common.Memory
Array45<T> _other; Array45<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 46; public int Length => 46;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 46); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 46);
} }
public struct Array47<T> : IArray<T> where T : unmanaged public struct Array47<T> : IArray<T> where T : unmanaged
{ {
@@ -467,8 +467,8 @@ namespace Ryujinx.Common.Memory
Array46<T> _other; Array46<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 47; public int Length => 47;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 47); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 47);
} }
public struct Array48<T> : IArray<T> where T : unmanaged public struct Array48<T> : IArray<T> where T : unmanaged
{ {
@@ -477,8 +477,8 @@ namespace Ryujinx.Common.Memory
Array47<T> _other; Array47<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 48; public int Length => 48;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 48); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 48);
} }
public struct Array49<T> : IArray<T> where T : unmanaged public struct Array49<T> : IArray<T> where T : unmanaged
{ {
@@ -487,8 +487,8 @@ namespace Ryujinx.Common.Memory
Array48<T> _other; Array48<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 49; public int Length => 49;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 49); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 49);
} }
public struct Array50<T> : IArray<T> where T : unmanaged public struct Array50<T> : IArray<T> where T : unmanaged
{ {
@@ -497,8 +497,8 @@ namespace Ryujinx.Common.Memory
Array49<T> _other; Array49<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 50; public int Length => 50;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 50); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 50);
} }
public struct Array51<T> : IArray<T> where T : unmanaged public struct Array51<T> : IArray<T> where T : unmanaged
{ {
@@ -507,8 +507,8 @@ namespace Ryujinx.Common.Memory
Array50<T> _other; Array50<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 51; public int Length => 51;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 51); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 51);
} }
public struct Array52<T> : IArray<T> where T : unmanaged public struct Array52<T> : IArray<T> where T : unmanaged
{ {
@@ -517,8 +517,8 @@ namespace Ryujinx.Common.Memory
Array51<T> _other; Array51<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 52; public int Length => 52;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 52); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 52);
} }
public struct Array53<T> : IArray<T> where T : unmanaged public struct Array53<T> : IArray<T> where T : unmanaged
{ {
@@ -527,8 +527,8 @@ namespace Ryujinx.Common.Memory
Array52<T> _other; Array52<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 53; public int Length => 53;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 53); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 53);
} }
public struct Array54<T> : IArray<T> where T : unmanaged public struct Array54<T> : IArray<T> where T : unmanaged
{ {
@@ -537,8 +537,8 @@ namespace Ryujinx.Common.Memory
Array53<T> _other; Array53<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 54; public int Length => 54;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 54); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 54);
} }
public struct Array55<T> : IArray<T> where T : unmanaged public struct Array55<T> : IArray<T> where T : unmanaged
{ {
@@ -547,8 +547,8 @@ namespace Ryujinx.Common.Memory
Array54<T> _other; Array54<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 55; public int Length => 55;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 55); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 55);
} }
public struct Array56<T> : IArray<T> where T : unmanaged public struct Array56<T> : IArray<T> where T : unmanaged
{ {
@@ -557,8 +557,8 @@ namespace Ryujinx.Common.Memory
Array55<T> _other; Array55<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 56; public int Length => 56;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 56); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 56);
} }
public struct Array57<T> : IArray<T> where T : unmanaged public struct Array57<T> : IArray<T> where T : unmanaged
{ {
@@ -567,8 +567,8 @@ namespace Ryujinx.Common.Memory
Array56<T> _other; Array56<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 57; public int Length => 57;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 57); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 57);
} }
public struct Array58<T> : IArray<T> where T : unmanaged public struct Array58<T> : IArray<T> where T : unmanaged
{ {
@@ -577,8 +577,8 @@ namespace Ryujinx.Common.Memory
Array57<T> _other; Array57<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 58; public int Length => 58;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 58); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 58);
} }
public struct Array59<T> : IArray<T> where T : unmanaged public struct Array59<T> : IArray<T> where T : unmanaged
{ {
@@ -587,8 +587,8 @@ namespace Ryujinx.Common.Memory
Array58<T> _other; Array58<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 59; public int Length => 59;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 59); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 59);
} }
public struct Array60<T> : IArray<T> where T : unmanaged public struct Array60<T> : IArray<T> where T : unmanaged
{ {
@@ -597,8 +597,8 @@ namespace Ryujinx.Common.Memory
Array59<T> _other; Array59<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 60; public int Length => 60;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 60); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 60);
} }
public struct Array61<T> : IArray<T> where T : unmanaged public struct Array61<T> : IArray<T> where T : unmanaged
{ {
@@ -607,8 +607,8 @@ namespace Ryujinx.Common.Memory
Array60<T> _other; Array60<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 61; public int Length => 61;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 61); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 61);
} }
public struct Array62<T> : IArray<T> where T : unmanaged public struct Array62<T> : IArray<T> where T : unmanaged
{ {
@@ -617,8 +617,8 @@ namespace Ryujinx.Common.Memory
Array61<T> _other; Array61<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 62; public int Length => 62;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 62); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 62);
} }
public struct Array63<T> : IArray<T> where T : unmanaged public struct Array63<T> : IArray<T> where T : unmanaged
{ {
@@ -627,8 +627,8 @@ namespace Ryujinx.Common.Memory
Array62<T> _other; Array62<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 63; public int Length => 63;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 63); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 63);
} }
public struct Array64<T> : IArray<T> where T : unmanaged public struct Array64<T> : IArray<T> where T : unmanaged
{ {
@@ -637,8 +637,8 @@ namespace Ryujinx.Common.Memory
Array63<T> _other; Array63<T> _other;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 64; public int Length => 64;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 64); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 64);
} }
public struct Array73<T> : IArray<T> where T : unmanaged public struct Array73<T> : IArray<T> where T : unmanaged
{ {
@@ -648,7 +648,7 @@ namespace Ryujinx.Common.Memory
Array8<T> _other2; Array8<T> _other2;
#pragma warning restore CS0169 #pragma warning restore CS0169
public int Length => 73; public int Length => 73;
public ref T this[int index] => ref ToSpan()[index]; public ref T this[int index] => ref AsSpan()[index];
public Span<T> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 73); public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 73);
} }
} }

View File

@@ -11,8 +11,8 @@ namespace Ryujinx.Common.Memory
byte _element; byte _element;
public int Length => Size; public int Length => Size;
public ref byte this[int index] => ref ToSpan()[index]; public ref byte this[int index] => ref AsSpan()[index];
public Span<byte> ToSpan() => MemoryMarshal.CreateSpan(ref _element, Size); public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
} }
[StructLayout(LayoutKind.Sequential, Size = Size, Pack = 1)] [StructLayout(LayoutKind.Sequential, Size = Size, Pack = 1)]
@@ -23,8 +23,8 @@ namespace Ryujinx.Common.Memory
byte _element; byte _element;
public int Length => Size; public int Length => Size;
public ref byte this[int index] => ref ToSpan()[index]; public ref byte this[int index] => ref AsSpan()[index];
public Span<byte> ToSpan() => MemoryMarshal.CreateSpan(ref _element, Size); public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
} }
[StructLayout(LayoutKind.Sequential, Size = Size, Pack = 1)] [StructLayout(LayoutKind.Sequential, Size = Size, Pack = 1)]
@@ -35,8 +35,8 @@ namespace Ryujinx.Common.Memory
byte _element; byte _element;
public int Length => Size; public int Length => Size;
public ref byte this[int index] => ref ToSpan()[index]; public ref byte this[int index] => ref AsSpan()[index];
public Span<byte> ToSpan() => MemoryMarshal.CreateSpan(ref _element, Size); public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
} }
[StructLayout(LayoutKind.Sequential, Size = Size, Pack = 1)] [StructLayout(LayoutKind.Sequential, Size = Size, Pack = 1)]
@@ -47,8 +47,8 @@ namespace Ryujinx.Common.Memory
byte _element; byte _element;
public int Length => Size; public int Length => Size;
public ref byte this[int index] => ref ToSpan()[index]; public ref byte this[int index] => ref AsSpan()[index];
public Span<byte> ToSpan() => MemoryMarshal.CreateSpan(ref _element, Size); public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
} }
[StructLayout(LayoutKind.Sequential, Size = Size, Pack = 1)] [StructLayout(LayoutKind.Sequential, Size = Size, Pack = 1)]
@@ -59,8 +59,8 @@ namespace Ryujinx.Common.Memory
byte _element; byte _element;
public int Length => Size; public int Length => Size;
public ref byte this[int index] => ref ToSpan()[index]; public ref byte this[int index] => ref AsSpan()[index];
public Span<byte> ToSpan() => MemoryMarshal.CreateSpan(ref _element, Size); public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
} }
[StructLayout(LayoutKind.Sequential, Size = Size, Pack = 1)] [StructLayout(LayoutKind.Sequential, Size = Size, Pack = 1)]
@@ -71,7 +71,7 @@ namespace Ryujinx.Common.Memory
byte _element; byte _element;
public int Length => Size; public int Length => Size;
public ref byte this[int index] => ref ToSpan()[index]; public ref byte this[int index] => ref AsSpan()[index];
public Span<byte> ToSpan() => MemoryMarshal.CreateSpan(ref _element, Size); public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
} }
} }

View File

@@ -24,7 +24,7 @@ namespace Ryujinx.Common.SystemInfo
if (sysctlbyname("hw.memsize", ref totalRAM) != 0) // Bytes if (sysctlbyname("hw.memsize", ref totalRAM) != 0) // Bytes
{ {
totalRAM = 0; totalRAM = 0;
}; }
CpuName = $"{cpuName} ; {LogicalCoreCount} logical"; CpuName = $"{cpuName} ; {LogicalCoreCount} logical";
RamTotal = totalRAM; RamTotal = totalRAM;

View File

@@ -56,7 +56,6 @@ namespace Ryujinx.Graphics.GAL
D32Float, D32Float,
D24UnormS8Uint, D24UnormS8Uint,
D32FloatS8Uint, D32FloatS8Uint,
R8G8B8X8Srgb,
R8G8B8A8Srgb, R8G8B8A8Srgb,
R4G4Unorm, R4G4Unorm,
R4G4B4A4Unorm, R4G4B4A4Unorm,
@@ -83,8 +82,10 @@ namespace Ryujinx.Graphics.GAL
Bc6HUfloat, Bc6HUfloat,
Etc2RgbUnorm, Etc2RgbUnorm,
Etc2RgbaUnorm, Etc2RgbaUnorm,
Etc2RgbPtaUnorm,
Etc2RgbSrgb, Etc2RgbSrgb,
Etc2RgbaSrgb, Etc2RgbaSrgb,
Etc2RgbPtaSrgb,
R8Uscaled, R8Uscaled,
R8Sscaled, R8Sscaled,
R16Uscaled, R16Uscaled,
@@ -113,18 +114,6 @@ namespace Ryujinx.Graphics.GAL
R10G10B10A2Sint, R10G10B10A2Sint,
R10G10B10A2Uscaled, R10G10B10A2Uscaled,
R10G10B10A2Sscaled, R10G10B10A2Sscaled,
R8G8B8X8Unorm,
R8G8B8X8Snorm,
R8G8B8X8Uint,
R8G8B8X8Sint,
R16G16B16X16Float,
R16G16B16X16Unorm,
R16G16B16X16Snorm,
R16G16B16X16Uint,
R16G16B16X16Sint,
R32G32B32X32Float,
R32G32B32X32Uint,
R32G32B32X32Sint,
Astc4x4Unorm, Astc4x4Unorm,
Astc5x4Unorm, Astc5x4Unorm,
Astc5x5Unorm, Astc5x5Unorm,
@@ -154,12 +143,9 @@ namespace Ryujinx.Graphics.GAL
Astc12x10Srgb, Astc12x10Srgb,
Astc12x12Srgb, Astc12x12Srgb,
B5G6R5Unorm, B5G6R5Unorm,
B5G5R5X1Unorm,
B5G5R5A1Unorm, B5G5R5A1Unorm,
A1B5G5R5Unorm, A1B5G5R5Unorm,
B8G8R8X8Unorm,
B8G8R8A8Unorm, B8G8R8A8Unorm,
B8G8R8X8Srgb,
B8G8R8A8Srgb B8G8R8A8Srgb
} }
@@ -272,7 +258,6 @@ namespace Ryujinx.Graphics.GAL
case Format.R8Snorm: case Format.R8Snorm:
case Format.R8Sint: case Format.R8Sint:
case Format.R8Uint: case Format.R8Uint:
case Format.B5G5R5X1Unorm:
return true; return true;
} }
@@ -357,11 +342,8 @@ namespace Ryujinx.Graphics.GAL
switch (format) switch (format)
{ {
case Format.B5G6R5Unorm: case Format.B5G6R5Unorm:
case Format.B5G5R5X1Unorm:
case Format.B5G5R5A1Unorm: case Format.B5G5R5A1Unorm:
case Format.B8G8R8X8Unorm:
case Format.B8G8R8A8Unorm: case Format.B8G8R8A8Unorm:
case Format.B8G8R8X8Srgb:
case Format.B8G8R8A8Srgb: case Format.B8G8R8A8Srgb:
return true; return true;
} }
@@ -412,9 +394,6 @@ namespace Ryujinx.Graphics.GAL
case Format.R16G16B16A16Uint: case Format.R16G16B16A16Uint:
case Format.R32G32B32A32Uint: case Format.R32G32B32A32Uint:
case Format.R10G10B10A2Uint: case Format.R10G10B10A2Uint:
case Format.R8G8B8X8Uint:
case Format.R16G16B16X16Uint:
case Format.R32G32B32X32Uint:
return true; return true;
} }
@@ -443,9 +422,6 @@ namespace Ryujinx.Graphics.GAL
case Format.R16G16B16A16Sint: case Format.R16G16B16A16Sint:
case Format.R32G32B32A32Sint: case Format.R32G32B32A32Sint:
case Format.R10G10B10A2Sint: case Format.R10G10B10A2Sint:
case Format.R8G8B8X8Sint:
case Format.R16G16B16X16Sint:
case Format.R32G32B32X32Sint:
return true; return true;
} }

View File

@@ -7,5 +7,7 @@ namespace Ryujinx.Graphics.GAL
void Present(ITexture texture, ImageCrop crop, Action<object> swapBuffersCallback); void Present(ITexture texture, ImageCrop crop, Action<object> swapBuffersCallback);
void SetSize(int width, int height); void SetSize(int width, int height);
void ChangeVSyncMode(bool vsyncEnabled);
} }
} }

View File

@@ -13,13 +13,13 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Commands
public void Set(int vertices, ReadOnlySpan<float> defaultOuterLevel, ReadOnlySpan<float> defaultInnerLevel) public void Set(int vertices, ReadOnlySpan<float> defaultOuterLevel, ReadOnlySpan<float> defaultInnerLevel)
{ {
_vertices = vertices; _vertices = vertices;
defaultOuterLevel.CopyTo(_defaultOuterLevel.ToSpan()); defaultOuterLevel.CopyTo(_defaultOuterLevel.AsSpan());
defaultInnerLevel.CopyTo(_defaultInnerLevel.ToSpan()); defaultInnerLevel.CopyTo(_defaultInnerLevel.AsSpan());
} }
public static void Run(ref SetPatchParametersCommand command, ThreadedRenderer threaded, IRenderer renderer) public static void Run(ref SetPatchParametersCommand command, ThreadedRenderer threaded, IRenderer renderer)
{ {
renderer.Pipeline.SetPatchParameters(command._vertices, command._defaultOuterLevel.ToSpan(), command._defaultInnerLevel.ToSpan()); renderer.Pipeline.SetPatchParameters(command._vertices, command._defaultOuterLevel.AsSpan(), command._defaultInnerLevel.AsSpan());
} }
} }
} }

View File

@@ -30,5 +30,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
{ {
_impl.Window.SetSize(width, height); _impl.Window.SetSize(width, height);
} }
public void ChangeVSyncMode(bool vsyncEnabled) { }
} }
} }

View File

@@ -66,7 +66,7 @@ namespace Ryujinx.Graphics.GAL
public void SetVertexAttribs(ReadOnlySpan<VertexAttribDescriptor> vertexAttribs) public void SetVertexAttribs(ReadOnlySpan<VertexAttribDescriptor> vertexAttribs)
{ {
VertexAttribCount = vertexAttribs.Length; VertexAttribCount = vertexAttribs.Length;
vertexAttribs.CopyTo(VertexAttribs.ToSpan()); vertexAttribs.CopyTo(VertexAttribs.AsSpan());
} }
public void SetLogicOpState(bool enable, LogicalOp op) public void SetLogicOpState(bool enable, LogicalOp op)

View File

@@ -65,12 +65,12 @@ namespace Ryujinx.Graphics.GAL
public void UpdateRenderScale(ReadOnlySpan<Vector4<float>> data, int offset, int count) public void UpdateRenderScale(ReadOnlySpan<Vector4<float>> data, int offset, int count)
{ {
UpdateGenericField(SupportBuffer.GraphicsRenderScaleOffset, data, Data.RenderScale.ToSpan(), offset, count); UpdateGenericField(SupportBuffer.GraphicsRenderScaleOffset, data, Data.RenderScale.AsSpan(), offset, count);
} }
public void UpdateFragmentIsBgra(ReadOnlySpan<Vector4<int>> data, int offset, int count) public void UpdateFragmentIsBgra(ReadOnlySpan<Vector4<int>> data, int offset, int count)
{ {
UpdateGenericField(SupportBuffer.FragmentIsBgraOffset, data, Data.FragmentIsBgra.ToSpan(), offset, count); UpdateGenericField(SupportBuffer.FragmentIsBgraOffset, data, Data.FragmentIsBgra.AsSpan(), offset, count);
} }
public void UpdateViewportInverse(Vector4<float> data) public void UpdateViewportInverse(Vector4<float> data)

View File

@@ -12,7 +12,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
#pragma warning disable CS0169 #pragma warning disable CS0169
private uint _e0; private uint _e0;
#pragma warning restore CS0169 #pragma warning restore CS0169
public ref uint this[int index] => ref ToSpan()[index]; public ref uint this[int index] => ref AsSpan()[index];
public Span<uint> ToSpan() => MemoryMarshal.CreateSpan(ref _e0, 256); public Span<uint> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, 256);
} }
} }

View File

@@ -42,6 +42,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
private uint _prevFirstVertex; private uint _prevFirstVertex;
private bool _prevTfEnable; private bool _prevTfEnable;
private uint _prevRtNoAlphaMask;
/// <summary> /// <summary>
/// Creates a new instance of the state updater. /// Creates a new instance of the state updater.
/// </summary> /// </summary>
@@ -331,8 +333,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
_context.Renderer.Pipeline.SetPatchParameters( _context.Renderer.Pipeline.SetPatchParameters(
_state.State.PatchVertices, _state.State.PatchVertices,
_state.State.TessOuterLevel.ToSpan(), _state.State.TessOuterLevel.AsSpan(),
_state.State.TessInnerLevel.ToSpan()); _state.State.TessInnerLevel.AsSpan());
} }
/// <summary> /// <summary>
@@ -398,6 +400,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
int clipRegionHeight = int.MaxValue; int clipRegionHeight = int.MaxValue;
bool changedScale = false; bool changedScale = false;
uint rtNoAlphaMask = 0;
for (int index = 0; index < Constants.TotalRenderTargets; index++) for (int index = 0; index < Constants.TotalRenderTargets; index++)
{ {
@@ -412,6 +415,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
continue; continue;
} }
if (colorState.Format.NoAlpha())
{
rtNoAlphaMask |= 1u << index;
}
Image.Texture color = memoryManager.Physical.TextureCache.FindOrCreateTexture( Image.Texture color = memoryManager.Physical.TextureCache.FindOrCreateTexture(
memoryManager, memoryManager,
colorState, colorState,
@@ -485,6 +493,13 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
} }
_channel.TextureManager.SetClipRegion(clipRegionWidth, clipRegionHeight); _channel.TextureManager.SetClipRegion(clipRegionWidth, clipRegionHeight);
if (useControl && _prevRtNoAlphaMask != rtNoAlphaMask)
{
_prevRtNoAlphaMask = rtNoAlphaMask;
UpdateBlendState();
}
} }
/// <summary> /// <summary>
@@ -1056,44 +1071,80 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
bool blendIndependent = _state.State.BlendIndependent; bool blendIndependent = _state.State.BlendIndependent;
ColorF blendConstant = _state.State.BlendConstant; ColorF blendConstant = _state.State.BlendConstant;
for (int index = 0; index < Constants.TotalRenderTargets; index++) if (blendIndependent)
{ {
BlendDescriptor descriptor; for (int index = 0; index < Constants.TotalRenderTargets; index++)
if (blendIndependent)
{ {
bool enable = _state.State.BlendEnable[index]; bool enable = _state.State.BlendEnable[index];
var blend = _state.State.BlendState[index]; var blend = _state.State.BlendState[index];
descriptor = new BlendDescriptor( var descriptor = new BlendDescriptor(
enable, enable,
blendConstant, blendConstant,
blend.ColorOp, blend.ColorOp,
blend.ColorSrcFactor, FilterBlendFactor(blend.ColorSrcFactor, index),
blend.ColorDstFactor, FilterBlendFactor(blend.ColorDstFactor, index),
blend.AlphaOp, blend.AlphaOp,
blend.AlphaSrcFactor, FilterBlendFactor(blend.AlphaSrcFactor, index),
blend.AlphaDstFactor); FilterBlendFactor(blend.AlphaDstFactor, index));
}
else
{
bool enable = _state.State.BlendEnable[0];
var blend = _state.State.BlendStateCommon;
descriptor = new BlendDescriptor( _pipeline.BlendDescriptors[index] = descriptor;
enable, _context.Renderer.Pipeline.SetBlendState(index, descriptor);
blendConstant,
blend.ColorOp,
blend.ColorSrcFactor,
blend.ColorDstFactor,
blend.AlphaOp,
blend.AlphaSrcFactor,
blend.AlphaDstFactor);
} }
_pipeline.BlendDescriptors[index] = descriptor;
_context.Renderer.Pipeline.SetBlendState(index, descriptor);
} }
else
{
bool enable = _state.State.BlendEnable[0];
var blend = _state.State.BlendStateCommon;
var descriptor = new BlendDescriptor(
enable,
blendConstant,
blend.ColorOp,
FilterBlendFactor(blend.ColorSrcFactor, 0),
FilterBlendFactor(blend.ColorDstFactor, 0),
blend.AlphaOp,
FilterBlendFactor(blend.AlphaSrcFactor, 0),
FilterBlendFactor(blend.AlphaDstFactor, 0));
for (int index = 0; index < Constants.TotalRenderTargets; index++)
{
_pipeline.BlendDescriptors[index] = descriptor;
_context.Renderer.Pipeline.SetBlendState(index, descriptor);
}
}
}
/// <summary>
/// Gets a blend factor for the color target currently.
/// This will return <paramref name="factor"/> unless the target format has no alpha component,
/// in which case it will replace destination alpha factor with a constant factor of one or zero.
/// </summary>
/// <param name="factor">Input factor</param>
/// <param name="index">Color target index</param>
/// <returns>New blend factor</returns>
private BlendFactor FilterBlendFactor(BlendFactor factor, int index)
{
// If any color target format without alpha is being used, we need to make sure that
// if blend is active, it will not use destination alpha as a factor.
// That is required because RGBX formats are emulated using host RGBA formats.
if (_state.State.RtColorState[index].Format.NoAlpha())
{
switch (factor)
{
case BlendFactor.DstAlpha:
case BlendFactor.DstAlphaGl:
factor = BlendFactor.One;
break;
case BlendFactor.OneMinusDstAlpha:
case BlendFactor.OneMinusDstAlphaGl:
factor = BlendFactor.Zero;
break;
}
}
return factor;
} }
/// <summary> /// <summary>
@@ -1242,6 +1293,10 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
_channel.BufferManager.SetGraphicsUniformBufferBindings(stage, info.CBuffers); _channel.BufferManager.SetGraphicsUniformBufferBindings(stage, info.CBuffers);
} }
/// <summary>
/// Gets the current texture pool state.
/// </summary>
/// <returns>Texture pool state</returns>
private GpuChannelPoolState GetPoolState() private GpuChannelPoolState GetPoolState()
{ {
return new GpuChannelPoolState( return new GpuChannelPoolState(
@@ -1286,6 +1341,10 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
ref attributeTypes); ref attributeTypes);
} }
/// <summary>
/// Gets the depth mode that is currently being used (zero to one or minus one to one).
/// </summary>
/// <returns>Current depth mode</returns>
private DepthMode GetDepthMode() private DepthMode GetDepthMode()
{ {
ref var transform = ref _state.State.ViewportTransform[0]; ref var transform = ref _state.State.ViewportTransform[0];

View File

@@ -124,11 +124,42 @@ namespace Ryujinx.Graphics.Gpu.Engine.Types
ColorFormat.R8Snorm => new FormatInfo(Format.R8Snorm, 1, 1, 1, 1), ColorFormat.R8Snorm => new FormatInfo(Format.R8Snorm, 1, 1, 1, 1),
ColorFormat.R8Sint => new FormatInfo(Format.R8Sint, 1, 1, 1, 1), ColorFormat.R8Sint => new FormatInfo(Format.R8Sint, 1, 1, 1, 1),
ColorFormat.R8Uint => new FormatInfo(Format.R8Uint, 1, 1, 1, 1), ColorFormat.R8Uint => new FormatInfo(Format.R8Uint, 1, 1, 1, 1),
ColorFormat.B5G5R5X1Unorm => new FormatInfo(Format.B5G5R5X1Unorm, 1, 1, 2, 4), ColorFormat.B5G5R5X1Unorm => new FormatInfo(Format.B5G5R5A1Unorm, 1, 1, 2, 4),
ColorFormat.R8G8B8X8Unorm => new FormatInfo(Format.R8G8B8A8Unorm, 1, 1, 4, 4), ColorFormat.R8G8B8X8Unorm => new FormatInfo(Format.R8G8B8A8Unorm, 1, 1, 4, 4),
ColorFormat.R8G8B8X8Srgb => new FormatInfo(Format.R8G8B8A8Srgb, 1, 1, 4, 4), ColorFormat.R8G8B8X8Srgb => new FormatInfo(Format.R8G8B8A8Srgb, 1, 1, 4, 4),
_ => FormatInfo.Default _ => FormatInfo.Default
}; };
} }
/// <summary>
/// Checks if a format has an alpha component.
/// </summary>
/// <param name="format">Format to be checked</param>
/// <returns>True if the format has no alpha component (RGBX), false if it does (RGBA)</returns>
public static bool NoAlpha(this ColorFormat format)
{
switch (format)
{
case ColorFormat.R32G32B32X32Float:
case ColorFormat.R32G32B32X32Sint:
case ColorFormat.R32G32B32X32Uint:
case ColorFormat.R16G16B16X16Unorm:
case ColorFormat.R16G16B16X16Snorm:
case ColorFormat.R16G16B16X16Sint:
case ColorFormat.R16G16B16X16Uint:
case ColorFormat.R16G16B16X16Float:
case ColorFormat.R8G8B8X8Snorm:
case ColorFormat.R8G8B8X8Sint:
case ColorFormat.R8G8B8X8Uint:
case ColorFormat.B8G8R8X8Unorm:
case ColorFormat.B8G8R8X8Srgb:
case ColorFormat.B5G5R5X1Unorm:
case ColorFormat.R8G8B8X8Unorm:
case ColorFormat.R8G8B8X8Srgb:
return true;
}
return false;
}
} }
} }

View File

@@ -553,7 +553,7 @@ namespace Ryujinx.Graphics.Gpu.Image
specStateMatches &= specState.MatchesTexture(stage, index, descriptor); specStateMatches &= specState.MatchesTexture(stage, index, descriptor);
Sampler sampler = _samplerPool?.Get(samplerId); Sampler sampler = samplerPool?.Get(samplerId);
ITexture hostTexture = texture?.GetTargetTexture(bindingInfo.Target); ITexture hostTexture = texture?.GetTargetTexture(bindingInfo.Target);
ISampler hostSampler = sampler?.GetHostSampler(texture); ISampler hostSampler = sampler?.GetHostSampler(texture);

View File

@@ -515,7 +515,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
return false; return false;
} }
if (!graphicsState.AttributeTypes.ToSpan().SequenceEqual(GraphicsState.AttributeTypes.ToSpan())) if (!graphicsState.AttributeTypes.AsSpan().SequenceEqual(GraphicsState.AttributeTypes.AsSpan()))
{ {
return false; return false;
} }

View File

@@ -52,7 +52,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// <returns>Span of varying locations</returns> /// <returns>Span of varying locations</returns>
public ReadOnlySpan<byte> AsSpan() public ReadOnlySpan<byte> AsSpan()
{ {
return MemoryMarshal.Cast<uint, byte>(VaryingLocations.ToSpan()).Slice(0, Math.Min(128, VaryingCount)); return MemoryMarshal.Cast<uint, byte>(VaryingLocations.AsSpan()).Slice(0, Math.Min(128, VaryingCount));
} }
} }
} }

View File

@@ -30,23 +30,23 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
Span<ushort> dst16 = MemoryMarshal.Cast<byte, ushort>(dst); Span<ushort> dst16 = MemoryMarshal.Cast<byte, ushort>(dst);
if (xd.Lossless) if (xd.Lossless)
{ {
Idct.HighbdIwht4x4Add(dqcoeff.ToSpan(), dst16, stride, eob, xd.Bd); Idct.HighbdIwht4x4Add(dqcoeff.AsSpan(), dst16, stride, eob, xd.Bd);
} }
else else
{ {
switch (txSize) switch (txSize)
{ {
case TxSize.Tx4x4: case TxSize.Tx4x4:
Idct.HighbdIdct4x4Add(dqcoeff.ToSpan(), dst16, stride, eob, xd.Bd); Idct.HighbdIdct4x4Add(dqcoeff.AsSpan(), dst16, stride, eob, xd.Bd);
break; break;
case TxSize.Tx8x8: case TxSize.Tx8x8:
Idct.HighbdIdct8x8Add(dqcoeff.ToSpan(), dst16, stride, eob, xd.Bd); Idct.HighbdIdct8x8Add(dqcoeff.AsSpan(), dst16, stride, eob, xd.Bd);
break; break;
case TxSize.Tx16x16: case TxSize.Tx16x16:
Idct.HighbdIdct16x16Add(dqcoeff.ToSpan(), dst16, stride, eob, xd.Bd); Idct.HighbdIdct16x16Add(dqcoeff.AsSpan(), dst16, stride, eob, xd.Bd);
break; break;
case TxSize.Tx32x32: case TxSize.Tx32x32:
Idct.HighbdIdct32x32Add(dqcoeff.ToSpan(), 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;
} }
@@ -56,16 +56,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
if (xd.Lossless) if (xd.Lossless)
{ {
Idct.Iwht4x4Add(dqcoeff.ToSpan(), dst, stride, eob); Idct.Iwht4x4Add(dqcoeff.AsSpan(), dst, stride, eob);
} }
else else
{ {
switch (txSize) switch (txSize)
{ {
case TxSize.Tx4x4: Idct.Idct4x4Add(dqcoeff.ToSpan(), dst, stride, eob); break; case TxSize.Tx4x4: Idct.Idct4x4Add(dqcoeff.AsSpan(), dst, stride, eob); break;
case TxSize.Tx8x8: Idct.Idct8x8Add(dqcoeff.ToSpan(), dst, stride, eob); break; case TxSize.Tx8x8: Idct.Idct8x8Add(dqcoeff.AsSpan(), dst, stride, eob); break;
case TxSize.Tx16x16: Idct.Idct16x16Add(dqcoeff.ToSpan(), dst, stride, eob); break; case TxSize.Tx16x16: Idct.Idct16x16Add(dqcoeff.AsSpan(), dst, stride, eob); break;
case TxSize.Tx32x32: Idct.Idct32x32Add(dqcoeff.ToSpan(), dst, stride, eob); break; case TxSize.Tx32x32: Idct.Idct32x32Add(dqcoeff.AsSpan(), dst, stride, eob); break;
default: Debug.Assert(false, "Invalid transform size"); return; default: Debug.Assert(false, "Invalid transform size"); return;
} }
} }
@@ -73,21 +73,21 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
if (eob == 1) if (eob == 1)
{ {
dqcoeff.ToSpan()[0] = 0; dqcoeff.AsSpan()[0] = 0;
} }
else else
{ {
if (txSize <= TxSize.Tx16x16 && eob <= 10) if (txSize <= TxSize.Tx16x16 && eob <= 10)
{ {
dqcoeff.ToSpan().Slice(0, 4 * (4 << (int)txSize)).Fill(0); dqcoeff.AsSpan().Slice(0, 4 * (4 << (int)txSize)).Fill(0);
} }
else if (txSize == TxSize.Tx32x32 && eob <= 34) else if (txSize == TxSize.Tx32x32 && eob <= 34)
{ {
dqcoeff.ToSpan().Slice(0, 256).Fill(0); dqcoeff.AsSpan().Slice(0, 256).Fill(0);
} }
else else
{ {
dqcoeff.ToSpan().Slice(0, 16 << ((int)txSize << 1)).Fill(0); dqcoeff.AsSpan().Slice(0, 16 << ((int)txSize << 1)).Fill(0);
} }
} }
} }
@@ -109,23 +109,23 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
Span<ushort> dst16 = MemoryMarshal.Cast<byte, ushort>(dst); Span<ushort> dst16 = MemoryMarshal.Cast<byte, ushort>(dst);
if (xd.Lossless) if (xd.Lossless)
{ {
Idct.HighbdIwht4x4Add(dqcoeff.ToSpan(), dst16, stride, eob, xd.Bd); Idct.HighbdIwht4x4Add(dqcoeff.AsSpan(), dst16, stride, eob, xd.Bd);
} }
else else
{ {
switch (txSize) switch (txSize)
{ {
case TxSize.Tx4x4: case TxSize.Tx4x4:
Idct.HighbdIht4x4Add(txType, dqcoeff.ToSpan(), dst16, stride, eob, xd.Bd); Idct.HighbdIht4x4Add(txType, dqcoeff.AsSpan(), dst16, stride, eob, xd.Bd);
break; break;
case TxSize.Tx8x8: case TxSize.Tx8x8:
Idct.HighbdIht8x8Add(txType, dqcoeff.ToSpan(), dst16, stride, eob, xd.Bd); Idct.HighbdIht8x8Add(txType, dqcoeff.AsSpan(), dst16, stride, eob, xd.Bd);
break; break;
case TxSize.Tx16x16: case TxSize.Tx16x16:
Idct.HighbdIht16x16Add(txType, dqcoeff.ToSpan(), dst16, stride, eob, xd.Bd); Idct.HighbdIht16x16Add(txType, dqcoeff.AsSpan(), dst16, stride, eob, xd.Bd);
break; break;
case TxSize.Tx32x32: case TxSize.Tx32x32:
Idct.HighbdIdct32x32Add(dqcoeff.ToSpan(), 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;
} }
@@ -135,16 +135,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
if (xd.Lossless) if (xd.Lossless)
{ {
Idct.Iwht4x4Add(dqcoeff.ToSpan(), dst, stride, eob); Idct.Iwht4x4Add(dqcoeff.AsSpan(), dst, stride, eob);
} }
else else
{ {
switch (txSize) switch (txSize)
{ {
case TxSize.Tx4x4: Idct.Iht4x4Add(txType, dqcoeff.ToSpan(), dst, stride, eob); break; case TxSize.Tx4x4: Idct.Iht4x4Add(txType, dqcoeff.AsSpan(), dst, stride, eob); break;
case TxSize.Tx8x8: Idct.Iht8x8Add(txType, dqcoeff.ToSpan(), dst, stride, eob); break; case TxSize.Tx8x8: Idct.Iht8x8Add(txType, dqcoeff.AsSpan(), dst, stride, eob); break;
case TxSize.Tx16x16: Idct.Iht16x16Add(txType, dqcoeff.ToSpan(), dst, stride, eob); break; case TxSize.Tx16x16: Idct.Iht16x16Add(txType, dqcoeff.AsSpan(), dst, stride, eob); break;
case TxSize.Tx32x32: Idct.Idct32x32Add(dqcoeff.ToSpan(), dst, stride, eob); break; case TxSize.Tx32x32: Idct.Idct32x32Add(dqcoeff.AsSpan(), dst, stride, eob); break;
default: Debug.Assert(false, "Invalid transform size"); return; default: Debug.Assert(false, "Invalid transform size"); return;
} }
} }
@@ -152,21 +152,21 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
if (eob == 1) if (eob == 1)
{ {
dqcoeff.ToSpan()[0] = 0; dqcoeff.AsSpan()[0] = 0;
} }
else else
{ {
if (txType == TxType.DctDct && txSize <= TxSize.Tx16x16 && eob <= 10) if (txType == TxType.DctDct && txSize <= TxSize.Tx16x16 && eob <= 10)
{ {
dqcoeff.ToSpan().Slice(0, 4 * (4 << (int)txSize)).Fill(0); dqcoeff.AsSpan().Slice(0, 4 * (4 << (int)txSize)).Fill(0);
} }
else if (txSize == TxSize.Tx32x32 && eob <= 34) else if (txSize == TxSize.Tx32x32 && eob <= 34)
{ {
dqcoeff.ToSpan().Slice(0, 256).Fill(0); dqcoeff.AsSpan().Slice(0, 256).Fill(0);
} }
else else
{ {
dqcoeff.ToSpan().Slice(0, 16 << ((int)txSize << 1)).Fill(0); dqcoeff.AsSpan().Slice(0, 16 << ((int)txSize << 1)).Fill(0);
} }
} }
} }
@@ -184,7 +184,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.ToSpan().Slice(dstOffset); Span<byte> dstSpan = pd.Dst.Buf.AsSpan().Slice(dstOffset);
if (mi.SbType < BlockSize.Block8x8) if (mi.SbType < BlockSize.Block8x8)
{ {
@@ -223,7 +223,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.ToSpan().Slice(4 * row * pd.Dst.Stride + 4 * col); Span<byte> dst = pd.Dst.Buf.AsSpan().Slice(4 * row * pd.Dst.Stride + 4 * col);
if (eob > 0) if (eob > 0)
{ {
@@ -922,7 +922,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
BlockSize subsize, BlockSize subsize,
int bw) int bw)
{ {
Span<sbyte> aboveCtx = twd.Xd.AboveSegContext.Slice(miCol).ToSpan(); Span<sbyte> aboveCtx = twd.Xd.AboveSegContext.Slice(miCol).AsSpan();
Span<sbyte> leftCtx = MemoryMarshal.CreateSpan(ref twd.Xd.LeftSegContext[miRow & Constants.MiMask], 8 - (miRow & Constants.MiMask)); Span<sbyte> leftCtx = MemoryMarshal.CreateSpan(ref twd.Xd.LeftSegContext[miRow & Constants.MiMask], 8 - (miRow & Constants.MiMask));
// Update the partition context at the end notes. Set partition bits // Update the partition context at the end notes. Set partition bits
@@ -1077,7 +1077,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
errorInfo.InternalError(CodecErr.CodecCorruptFrame, "Truncated packet or corrupt tile length"); errorInfo.InternalError(CodecErr.CodecCorruptFrame, "Truncated packet or corrupt tile length");
} }
size = BinaryPrimitives.ReadInt32BigEndian(data.ToSpan()); size = BinaryPrimitives.ReadInt32BigEndian(data.AsSpan());
data = data.Slice(4); data = data.Slice(4);
if (size > data.Length) if (size > data.Length)
@@ -1187,7 +1187,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
if (cm.Mb.Corrupted) if (cm.Mb.Corrupted)
{ {
cm.Error.InternalError(CodecErr.CodecCorruptFrame, "Failed to decode tile data"); cm.Error.InternalError(CodecErr.CodecCorruptFrame, "Failed to decode tile data");
}; }
} }
} }
} }
@@ -1250,8 +1250,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.ToSpan().Fill(0); cm.AboveContext.AsSpan().Fill(0);
cm.AboveSegContext.ToSpan().Fill(0); cm.AboveSegContext.AsSpan().Fill(0);
for (n = 0; n < numWorkers; ++n) for (n = 0; n < numWorkers; ++n)
{ {
@@ -1266,12 +1266,12 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
GetTileBuffers(ref cm, data, tileCols, ref tileBuffers); GetTileBuffers(ref cm, data, tileCols, ref tileBuffers);
tileBuffers.ToSpan().Slice(0, tileCols).Sort(CompareTileBuffers); tileBuffers.AsSpan().Slice(0, tileCols).Sort(CompareTileBuffers);
if (numWorkers == tileCols) if (numWorkers == tileCols)
{ {
TileBuffer largest = tileBuffers[0]; TileBuffer largest = tileBuffers[0];
Span<TileBuffer> buffers = tileBuffers.ToSpan(); Span<TileBuffer> buffers = tileBuffers.AsSpan();
buffers.Slice(1).CopyTo(buffers.Slice(0, tileBuffers.Length - 1)); buffers.Slice(1).CopyTo(buffers.Slice(0, tileBuffers.Length - 1));
tileBuffers[tileCols - 1] = largest; tileBuffers[tileCols - 1] = largest;
} }

View File

@@ -21,7 +21,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
private static PredictionMode ReadIntraModeY(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r, int sizeGroup) private static PredictionMode ReadIntraModeY(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r, int sizeGroup)
{ {
PredictionMode yMode = ReadIntraMode(ref r, cm.Fc.Value.YModeProb[sizeGroup].ToSpan()); PredictionMode yMode = ReadIntraMode(ref r, cm.Fc.Value.YModeProb[sizeGroup].AsSpan());
if (!xd.Counts.IsNull) if (!xd.Counts.IsNull)
{ {
++xd.Counts.Value.YMode[sizeGroup][(int)yMode]; ++xd.Counts.Value.YMode[sizeGroup][(int)yMode];
@@ -32,7 +32,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
private static PredictionMode ReadIntraModeUv(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r, byte yMode) private static PredictionMode ReadIntraModeUv(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r, byte yMode)
{ {
PredictionMode uvMode = ReadIntraMode(ref r, cm.Fc.Value.UvModeProb[yMode].ToSpan()); PredictionMode uvMode = ReadIntraMode(ref r, cm.Fc.Value.UvModeProb[yMode].AsSpan());
if (!xd.Counts.IsNull) if (!xd.Counts.IsNull)
{ {
++xd.Counts.Value.UvMode[yMode][(int)uvMode]; ++xd.Counts.Value.UvMode[yMode][(int)uvMode];
@@ -43,7 +43,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
private static PredictionMode ReadInterMode(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r, int ctx) private static PredictionMode ReadInterMode(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r, int ctx)
{ {
int mode = r.ReadTree(Luts.Vp9InterModeTree, cm.Fc.Value.InterModeProb[ctx].ToSpan()); int mode = r.ReadTree(Luts.Vp9InterModeTree, cm.Fc.Value.InterModeProb[ctx].AsSpan());
if (!xd.Counts.IsNull) if (!xd.Counts.IsNull)
{ {
++xd.Counts.Value.InterMode[ctx][mode]; ++xd.Counts.Value.InterMode[ctx][mode];
@@ -54,16 +54,16 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
private static int ReadSegmentId(ref Reader r, ref Array7<byte> segTreeProbs) private static int ReadSegmentId(ref Reader r, ref Array7<byte> segTreeProbs)
{ {
return r.ReadTree(Luts.Vp9SegmentTree, segTreeProbs.ToSpan()); return r.ReadTree(Luts.Vp9SegmentTree, segTreeProbs.AsSpan());
} }
private static ReadOnlySpan<byte> GetTxProbs(ref Vp9EntropyProbs fc, TxSize maxTxSize, int ctx) private static ReadOnlySpan<byte> GetTxProbs(ref Vp9EntropyProbs fc, TxSize maxTxSize, int ctx)
{ {
switch (maxTxSize) switch (maxTxSize)
{ {
case TxSize.Tx8x8: return fc.Tx8x8Prob[ctx].ToSpan(); case TxSize.Tx8x8: return fc.Tx8x8Prob[ctx].AsSpan();
case TxSize.Tx16x16: return fc.Tx16x16Prob[ctx].ToSpan(); case TxSize.Tx16x16: return fc.Tx16x16Prob[ctx].AsSpan();
case TxSize.Tx32x32: return fc.Tx32x32Prob[ctx].ToSpan(); case TxSize.Tx32x32: return fc.Tx32x32Prob[ctx].AsSpan();
default: Debug.Assert(false, "Invalid maxTxSize."); return ReadOnlySpan<byte>.Empty; default: Debug.Assert(false, "Invalid maxTxSize."); return ReadOnlySpan<byte>.Empty;
} }
} }
@@ -72,9 +72,9 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
switch (maxTxSize) switch (maxTxSize)
{ {
case TxSize.Tx8x8: return counts.Tx8x8[ctx].ToSpan(); case TxSize.Tx8x8: return counts.Tx8x8[ctx].AsSpan();
case TxSize.Tx16x16: return counts.Tx16x16[ctx].ToSpan(); case TxSize.Tx16x16: return counts.Tx16x16[ctx].AsSpan();
case TxSize.Tx32x32: return counts.Tx32x32[ctx].ToSpan(); case TxSize.Tx32x32: return counts.Tx32x32[ctx].AsSpan();
default: Debug.Assert(false, "Invalid maxTxSize."); return Span<uint>.Empty; default: Debug.Assert(false, "Invalid maxTxSize."); return Span<uint>.Empty;
} }
} }
@@ -253,7 +253,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
int mag, d, fr, hp; int mag, d, fr, hp;
bool sign = r.Read(fc.Sign[mvcomp]) != 0; bool sign = r.Read(fc.Sign[mvcomp]) != 0;
MvClassType mvClass = (MvClassType)r.ReadTree(Luts.Vp9MvClassTree, fc.Classes[mvcomp].ToSpan()); MvClassType mvClass = (MvClassType)r.ReadTree(Luts.Vp9MvClassTree, fc.Classes[mvcomp].AsSpan());
bool class0 = mvClass == MvClassType.MvClass0; bool class0 = mvClass == MvClassType.MvClass0;
// Integer part // Integer part
@@ -277,7 +277,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
} }
// Fractional part // Fractional part
fr = r.ReadTree(Luts.Vp9MvFPTree, class0 ? fc.Class0Fp[mvcomp][d].ToSpan() : fc.Fp[mvcomp].ToSpan()); fr = r.ReadTree(Luts.Vp9MvFPTree, class0 ? fc.Class0Fp[mvcomp][d].AsSpan() : fc.Fp[mvcomp].AsSpan());
// High precision part (if hp is not used, the default value of the hp is 1) // High precision part (if hp is not used, the default value of the hp is 1)
hp = usehp ? r.Read(class0 ? fc.Class0Hp[mvcomp] : fc.Hp[mvcomp]) : 1; hp = usehp ? r.Read(class0 ? fc.Class0Hp[mvcomp] : fc.Hp[mvcomp]) : 1;
@@ -295,7 +295,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
Ptr<Vp9BackwardUpdates> counts, Ptr<Vp9BackwardUpdates> counts,
bool allowHP) bool allowHP)
{ {
MvJointType jointType = (MvJointType)r.ReadTree(Luts.Vp9MvJointTree, fc.Joints.ToSpan()); 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 Mv();
@@ -402,7 +402,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
private static byte ReadSwitchableInterpFilter(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r) private static byte ReadSwitchableInterpFilter(ref Vp9Common cm, ref MacroBlockD xd, ref Reader r)
{ {
int ctx = xd.GetPredContextSwitchableInterp(); int ctx = xd.GetPredContextSwitchableInterp();
byte type = (byte)r.ReadTree(Luts.Vp9SwitchableInterpTree, cm.Fc.Value.SwitchableInterpProb[ctx].ToSpan()); byte type = (byte)r.ReadTree(Luts.Vp9SwitchableInterpTree, cm.Fc.Value.SwitchableInterpProb[ctx].AsSpan());
if (!xd.Counts.IsNull) if (!xd.Counts.IsNull)
{ {
++xd.Counts.Value.SwitchableInterp[ctx][type]; ++xd.Counts.Value.SwitchableInterp[ctx][type];
@@ -1060,7 +1060,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].ToSpan(); return fc.KfYModeProb[(int)above][(int)left].AsSpan();
} }
private static void ReadIntraFrameModeInfo( private static void ReadIntraFrameModeInfo(
@@ -1113,7 +1113,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
break; break;
} }
mi.Value.UvMode = ReadIntraMode(ref r, cm.Fc.Value.KfUvModeProb[(int)mi.Value.Mode].ToSpan()); mi.Value.UvMode = ReadIntraMode(ref r, cm.Fc.Value.KfUvModeProb[(int)mi.Value.Mode].AsSpan());
} }
private static void CopyRefFramePair(ref Array2<sbyte> dst, ref Array2<sbyte> src) private static void CopyRefFramePair(ref Array2<sbyte> dst, ref Array2<sbyte> src)

View File

@@ -236,8 +236,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.ToSpan().Slice(x); Span<sbyte> a = pd.AboveContext.AsSpan().Slice(x);
Span<sbyte> l = pd.LeftContext.ToSpan().Slice(y); Span<sbyte> l = pd.LeftContext.AsSpan().Slice(y);
int ctx; int ctx;
int ctxShiftA = 0; int ctxShiftA = 0;
int ctxShiftL = 0; int ctxShiftL = 0;
@@ -250,7 +250,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
eob = DecodeCoefs( eob = DecodeCoefs(
ref xd, ref xd,
GetPlaneType(plane), GetPlaneType(plane),
pd.DqCoeff.ToSpan(), pd.DqCoeff.AsSpan(),
txSize, txSize,
ref dequant, ref dequant,
ctx, ctx,
@@ -266,7 +266,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
eob = DecodeCoefs( eob = DecodeCoefs(
ref xd, ref xd,
GetPlaneType(plane), GetPlaneType(plane),
pd.DqCoeff.ToSpan(), pd.DqCoeff.AsSpan(),
txSize, txSize,
ref dequant, ref dequant,
ctx, ctx,
@@ -283,7 +283,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
eob = DecodeCoefs( eob = DecodeCoefs(
ref xd, ref xd,
GetPlaneType(plane), GetPlaneType(plane),
pd.DqCoeff.ToSpan(), pd.DqCoeff.AsSpan(),
txSize, txSize,
ref dequant, ref dequant,
ctx, ctx,
@@ -303,7 +303,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
eob = DecodeCoefs( eob = DecodeCoefs(
ref xd, ref xd,
GetPlaneType(plane), GetPlaneType(plane),
pd.DqCoeff.ToSpan(), pd.DqCoeff.AsSpan(),
txSize, txSize,
ref dequant, ref dequant,
ctx, ctx,

View File

@@ -50,7 +50,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9.Dsp
private void Fill() private void Fill()
{ {
ReadOnlySpan<byte> buffer = _buffer.ToSpan(); ReadOnlySpan<byte> buffer = _buffer.AsSpan();
ReadOnlySpan<byte> bufferStart = buffer; ReadOnlySpan<byte> bufferStart = buffer;
ulong value = Value; ulong value = Value;
int count = Count; int count = Count;

View File

@@ -359,8 +359,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
blockInsideLimit = 1; blockInsideLimit = 1;
} }
lfi.Lfthr[lvl].Lim.ToSpan().Fill((byte)blockInsideLimit); lfi.Lfthr[lvl].Lim.AsSpan().Fill((byte)blockInsideLimit);
lfi.Lfthr[lvl].Mblim.ToSpan().Fill((byte)(2 * (lvl + 2) + blockInsideLimit)); lfi.Lfthr[lvl].Mblim.AsSpan().Fill((byte)(2 * (lvl + 2) + blockInsideLimit));
} }
} }
@@ -395,7 +395,7 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
// We could get rid of this if we assume that deltas are set to // We could get rid of this if we assume that deltas are set to
// zero when not in use; encoder always uses deltas // zero when not in use; encoder always uses deltas
MemoryMarshal.Cast<Array2<byte>, byte>(lfi.Lvl[segId].ToSpan()).Fill((byte)lvlSeg); MemoryMarshal.Cast<Array2<byte>, byte>(lfi.Lvl[segId].AsSpan()).Fill((byte)lvlSeg);
} }
else else
{ {

View File

@@ -70,7 +70,6 @@ namespace Ryujinx.Graphics.OpenGL
Add(Format.D32Float, new FormatInfo(1, false, false, All.DepthComponent32f, PixelFormat.DepthComponent, PixelType.Float)); Add(Format.D32Float, new FormatInfo(1, false, false, All.DepthComponent32f, PixelFormat.DepthComponent, PixelType.Float));
Add(Format.D24UnormS8Uint, new FormatInfo(1, false, false, All.Depth24Stencil8, PixelFormat.DepthStencil, PixelType.UnsignedInt248)); Add(Format.D24UnormS8Uint, new FormatInfo(1, false, false, All.Depth24Stencil8, PixelFormat.DepthStencil, PixelType.UnsignedInt248));
Add(Format.D32FloatS8Uint, new FormatInfo(1, false, false, All.Depth32fStencil8, PixelFormat.DepthStencil, PixelType.Float32UnsignedInt248Rev)); Add(Format.D32FloatS8Uint, new FormatInfo(1, false, false, All.Depth32fStencil8, PixelFormat.DepthStencil, PixelType.Float32UnsignedInt248Rev));
Add(Format.R8G8B8X8Srgb, new FormatInfo(4, false, false, All.Srgb8, PixelFormat.Rgba, PixelType.UnsignedByte));
Add(Format.R8G8B8A8Srgb, new FormatInfo(4, false, false, All.Srgb8Alpha8, PixelFormat.Rgba, PixelType.UnsignedByte)); Add(Format.R8G8B8A8Srgb, new FormatInfo(4, false, false, All.Srgb8Alpha8, PixelFormat.Rgba, PixelType.UnsignedByte));
Add(Format.R4G4B4A4Unorm, new FormatInfo(4, true, false, All.Rgba4, PixelFormat.Rgba, PixelType.UnsignedShort4444Reversed)); Add(Format.R4G4B4A4Unorm, new FormatInfo(4, true, false, All.Rgba4, PixelFormat.Rgba, PixelType.UnsignedShort4444Reversed));
Add(Format.R5G5B5X1Unorm, new FormatInfo(4, true, false, All.Rgb5, PixelFormat.Rgb, PixelType.UnsignedShort1555Reversed)); Add(Format.R5G5B5X1Unorm, new FormatInfo(4, true, false, All.Rgb5, PixelFormat.Rgb, PixelType.UnsignedShort1555Reversed));
@@ -94,8 +93,12 @@ namespace Ryujinx.Graphics.OpenGL
Add(Format.Bc7Srgb, new FormatInfo(4, false, false, All.CompressedSrgbAlphaBptcUnorm)); Add(Format.Bc7Srgb, new FormatInfo(4, false, false, All.CompressedSrgbAlphaBptcUnorm));
Add(Format.Bc6HSfloat, new FormatInfo(4, false, false, All.CompressedRgbBptcSignedFloat)); Add(Format.Bc6HSfloat, new FormatInfo(4, false, false, All.CompressedRgbBptcSignedFloat));
Add(Format.Bc6HUfloat, new FormatInfo(4, false, false, All.CompressedRgbBptcUnsignedFloat)); Add(Format.Bc6HUfloat, new FormatInfo(4, false, false, All.CompressedRgbBptcUnsignedFloat));
Add(Format.Etc2RgbUnorm, new FormatInfo(4, false, false, All.CompressedRgb8Etc2));
Add(Format.Etc2RgbaUnorm, new FormatInfo(4, false, false, All.CompressedRgba8Etc2Eac)); Add(Format.Etc2RgbaUnorm, new FormatInfo(4, false, false, All.CompressedRgba8Etc2Eac));
Add(Format.Etc2RgbPtaUnorm, new FormatInfo(4, false, false, All.CompressedRgb8PunchthroughAlpha1Etc2));
Add(Format.Etc2RgbSrgb, new FormatInfo(4, false, false, All.CompressedSrgb8Etc2));
Add(Format.Etc2RgbaSrgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Etc2Eac)); Add(Format.Etc2RgbaSrgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Etc2Eac));
Add(Format.Etc2RgbPtaSrgb, new FormatInfo(4, false, false, All.CompressedSrgb8PunchthroughAlpha1Etc2));
Add(Format.R8Uscaled, new FormatInfo(1, false, true, All.R8ui, PixelFormat.RedInteger, PixelType.UnsignedByte)); Add(Format.R8Uscaled, new FormatInfo(1, false, true, All.R8ui, PixelFormat.RedInteger, PixelType.UnsignedByte));
Add(Format.R8Sscaled, new FormatInfo(1, false, true, All.R8i, PixelFormat.RedInteger, PixelType.Byte)); Add(Format.R8Sscaled, new FormatInfo(1, false, true, All.R8i, PixelFormat.RedInteger, PixelType.Byte));
Add(Format.R16Uscaled, new FormatInfo(1, false, true, All.R16ui, PixelFormat.RedInteger, PixelType.UnsignedShort)); Add(Format.R16Uscaled, new FormatInfo(1, false, true, All.R16ui, PixelFormat.RedInteger, PixelType.UnsignedShort));
@@ -124,18 +127,6 @@ namespace Ryujinx.Graphics.OpenGL
Add(Format.R10G10B10A2Sint, new FormatInfo(4, false, false, All.Rgb10A2, PixelFormat.RgbaInteger, (PixelType)All.Int2101010Rev)); Add(Format.R10G10B10A2Sint, new FormatInfo(4, false, false, All.Rgb10A2, PixelFormat.RgbaInteger, (PixelType)All.Int2101010Rev));
Add(Format.R10G10B10A2Uscaled, new FormatInfo(4, false, true, All.Rgb10A2ui, PixelFormat.RgbaInteger, PixelType.UnsignedInt2101010Reversed)); Add(Format.R10G10B10A2Uscaled, new FormatInfo(4, false, true, All.Rgb10A2ui, PixelFormat.RgbaInteger, PixelType.UnsignedInt2101010Reversed));
Add(Format.R10G10B10A2Sscaled, new FormatInfo(4, false, true, All.Rgb10A2, PixelFormat.RgbaInteger, PixelType.UnsignedInt2101010Reversed)); Add(Format.R10G10B10A2Sscaled, new FormatInfo(4, false, true, All.Rgb10A2, PixelFormat.RgbaInteger, PixelType.UnsignedInt2101010Reversed));
Add(Format.R8G8B8X8Unorm, new FormatInfo(4, true, false, All.Rgb8, PixelFormat.Rgba, PixelType.UnsignedByte));
Add(Format.R8G8B8X8Snorm, new FormatInfo(4, true, false, All.Rgb8Snorm, PixelFormat.Rgba, PixelType.Byte));
Add(Format.R8G8B8X8Uint, new FormatInfo(4, false, false, All.Rgb8ui, PixelFormat.RgbaInteger, PixelType.UnsignedByte));
Add(Format.R8G8B8X8Sint, new FormatInfo(4, false, false, All.Rgb8i, PixelFormat.RgbaInteger, PixelType.Byte));
Add(Format.R16G16B16X16Float, new FormatInfo(4, false, false, All.Rgb16f, PixelFormat.Rgba, PixelType.HalfFloat));
Add(Format.R16G16B16X16Unorm, new FormatInfo(4, true, false, All.Rgb16, PixelFormat.Rgba, PixelType.UnsignedShort));
Add(Format.R16G16B16X16Snorm, new FormatInfo(4, true, false, All.Rgb16Snorm, PixelFormat.Rgba, PixelType.Short));
Add(Format.R16G16B16X16Uint, new FormatInfo(4, false, false, All.Rgb16ui, PixelFormat.RgbaInteger, PixelType.UnsignedShort));
Add(Format.R16G16B16X16Sint, new FormatInfo(4, false, false, All.Rgb16i, PixelFormat.RgbaInteger, PixelType.Short));
Add(Format.R32G32B32X32Float, new FormatInfo(4, false, false, All.Rgb32f, PixelFormat.Rgba, PixelType.Float));
Add(Format.R32G32B32X32Uint, new FormatInfo(4, false, false, All.Rgb32ui, PixelFormat.RgbaInteger, PixelType.UnsignedInt));
Add(Format.R32G32B32X32Sint, new FormatInfo(4, false, false, All.Rgb32i, PixelFormat.RgbaInteger, PixelType.Int));
Add(Format.Astc4x4Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc4X4Khr)); Add(Format.Astc4x4Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc4X4Khr));
Add(Format.Astc5x4Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc5X4Khr)); Add(Format.Astc5x4Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc5X4Khr));
Add(Format.Astc5x5Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc5X5Khr)); Add(Format.Astc5x5Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc5X5Khr));
@@ -165,12 +156,9 @@ namespace Ryujinx.Graphics.OpenGL
Add(Format.Astc12x10Srgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Astc12X10Khr)); Add(Format.Astc12x10Srgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Astc12X10Khr));
Add(Format.Astc12x12Srgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Astc12X12Khr)); Add(Format.Astc12x12Srgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Astc12X12Khr));
Add(Format.B5G6R5Unorm, new FormatInfo(3, true, false, All.Rgb565, PixelFormat.Rgb, PixelType.UnsignedShort565Reversed)); Add(Format.B5G6R5Unorm, new FormatInfo(3, true, false, All.Rgb565, PixelFormat.Rgb, PixelType.UnsignedShort565Reversed));
Add(Format.B5G5R5X1Unorm, new FormatInfo(4, true, false, All.Rgb5, PixelFormat.Rgba, PixelType.UnsignedShort1555Reversed));
Add(Format.B5G5R5A1Unorm, new FormatInfo(4, true, false, All.Rgb5A1, PixelFormat.Rgba, PixelType.UnsignedShort1555Reversed)); Add(Format.B5G5R5A1Unorm, new FormatInfo(4, true, false, All.Rgb5A1, PixelFormat.Rgba, PixelType.UnsignedShort1555Reversed));
Add(Format.A1B5G5R5Unorm, new FormatInfo(4, true, false, All.Rgb5A1, PixelFormat.Rgba, PixelType.UnsignedShort5551)); Add(Format.A1B5G5R5Unorm, new FormatInfo(4, true, false, All.Rgb5A1, PixelFormat.Rgba, PixelType.UnsignedShort5551));
Add(Format.B8G8R8X8Unorm, new FormatInfo(4, true, false, All.Rgba8, PixelFormat.Rgba, PixelType.UnsignedByte));
Add(Format.B8G8R8A8Unorm, new FormatInfo(4, true, false, All.Rgba8, PixelFormat.Rgba, PixelType.UnsignedByte)); Add(Format.B8G8R8A8Unorm, new FormatInfo(4, true, false, All.Rgba8, PixelFormat.Rgba, PixelType.UnsignedByte));
Add(Format.B8G8R8X8Srgb, new FormatInfo(4, false, false, All.Srgb8, PixelFormat.Rgba, PixelType.UnsignedByte));
Add(Format.B8G8R8A8Srgb, new FormatInfo(4, false, false, All.Srgb8Alpha8, PixelFormat.Rgba, PixelType.UnsignedByte)); Add(Format.B8G8R8A8Srgb, new FormatInfo(4, false, false, All.Srgb8Alpha8, PixelFormat.Rgba, PixelType.UnsignedByte));
Add(Format.R8Unorm, SizedInternalFormat.R8); Add(Format.R8Unorm, SizedInternalFormat.R8);

View File

@@ -147,7 +147,7 @@ namespace Ryujinx.Graphics.OpenGL
public int GetColorLayerCount(int index) public int GetColorLayerCount(int index)
{ {
return _colors[index].Info.GetDepthOrLayers(); return _colors[index]?.Info.GetDepthOrLayers() ?? 0;
} }
public int GetDepthStencilLayerCount() public int GetDepthStencilLayerCount()

View File

@@ -112,6 +112,8 @@ namespace Ryujinx.Graphics.OpenGL
public void ClearRenderTargetColor(int index, int layer, int layerCount, uint componentMask, ColorF color) public void ClearRenderTargetColor(int index, int layer, int layerCount, uint componentMask, ColorF color)
{ {
EnsureFramebuffer();
GL.ColorMask( GL.ColorMask(
index, index,
(componentMask & 1) != 0, (componentMask & 1) != 0,
@@ -142,6 +144,8 @@ namespace Ryujinx.Graphics.OpenGL
public void ClearRenderTargetDepthStencil(int layer, int layerCount, float depthValue, bool depthMask, int stencilValue, int stencilMask) public void ClearRenderTargetDepthStencil(int layer, int layerCount, float depthValue, bool depthMask, int stencilValue, int stencilMask)
{ {
EnsureFramebuffer();
bool stencilMaskChanged = bool stencilMaskChanged =
stencilMask != 0 && stencilMask != 0 &&
stencilMask != _stencilFrontMask; stencilMask != _stencilFrontMask;
@@ -232,7 +236,7 @@ namespace Ryujinx.Graphics.OpenGL
return; return;
} }
PreDraw(); PreDraw(vertexCount);
if (_primitiveType == PrimitiveType.Quads && !HwCapabilities.SupportsQuads) if (_primitiveType == PrimitiveType.Quads && !HwCapabilities.SupportsQuads)
{ {
@@ -350,7 +354,7 @@ namespace Ryujinx.Graphics.OpenGL
return; return;
} }
PreDraw(); PreDrawVbUnbounded();
int indexElemSize = 1; int indexElemSize = 1;
@@ -682,7 +686,7 @@ namespace Ryujinx.Graphics.OpenGL
return; return;
} }
PreDraw(); PreDrawVbUnbounded();
GL.BindBuffer((BufferTarget)All.DrawIndirectBuffer, indirectBuffer.Handle.ToInt32()); GL.BindBuffer((BufferTarget)All.DrawIndirectBuffer, indirectBuffer.Handle.ToInt32());
GL.BindBuffer((BufferTarget)All.ParameterBuffer, parameterBuffer.Handle.ToInt32()); GL.BindBuffer((BufferTarget)All.ParameterBuffer, parameterBuffer.Handle.ToInt32());
@@ -705,7 +709,7 @@ namespace Ryujinx.Graphics.OpenGL
return; return;
} }
PreDraw(); PreDrawVbUnbounded();
_vertexArray.SetRangeOfIndexBuffer(); _vertexArray.SetRangeOfIndexBuffer();
@@ -1511,11 +1515,22 @@ namespace Ryujinx.Graphics.OpenGL
_supportBuffer.Commit(); _supportBuffer.Commit();
} }
private void PreDraw(int vertexCount)
{
_vertexArray.PreDraw(vertexCount);
PreDraw();
}
private void PreDrawVbUnbounded()
{
_vertexArray.PreDrawVbUnbounded();
PreDraw();
}
private void PreDraw() private void PreDraw()
{ {
DrawCount++; DrawCount++;
_vertexArray.Validate();
_unit0Texture?.Bind(0); _unit0Texture?.Bind(0);
_supportBuffer.Commit(); _supportBuffer.Commit();
} }

View File

@@ -1,6 +1,7 @@
using OpenTK.Graphics.OpenGL; using OpenTK.Graphics.OpenGL;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using System; using System;
using System.Numerics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
namespace Ryujinx.Graphics.OpenGL namespace Ryujinx.Graphics.OpenGL
@@ -16,12 +17,16 @@ namespace Ryujinx.Graphics.OpenGL
private int _vertexAttribsCount; private int _vertexAttribsCount;
private int _vertexBuffersCount; private int _vertexBuffersCount;
private int _minVertexCount;
private uint _vertexAttribsInUse; private uint _vertexAttribsInUse;
private uint _vertexBuffersInUse; private uint _vertexBuffersInUse;
private uint _vertexBuffersLimited;
private BufferRange _indexBuffer; private BufferRange _indexBuffer;
private BufferHandle _tempIndexBuffer; private BufferHandle _tempIndexBuffer;
private BufferHandle _tempVertexBuffer;
private int _tempVertexBufferSize;
public VertexArray() public VertexArray()
{ {
@@ -40,6 +45,8 @@ namespace Ryujinx.Graphics.OpenGL
public void SetVertexBuffers(ReadOnlySpan<VertexBufferDescriptor> vertexBuffers) public void SetVertexBuffers(ReadOnlySpan<VertexBufferDescriptor> vertexBuffers)
{ {
int minVertexCount = int.MaxValue;
int bindingIndex; int bindingIndex;
for (bindingIndex = 0; bindingIndex < vertexBuffers.Length; bindingIndex++) for (bindingIndex = 0; bindingIndex < vertexBuffers.Length; bindingIndex++)
{ {
@@ -47,6 +54,12 @@ namespace Ryujinx.Graphics.OpenGL
if (vb.Buffer.Handle != BufferHandle.Null) if (vb.Buffer.Handle != BufferHandle.Null)
{ {
int vertexCount = vb.Stride <= 0 ? 0 : vb.Buffer.Size / vb.Stride;
if (minVertexCount > vertexCount)
{
minVertexCount = vertexCount;
}
GL.BindVertexBuffer(bindingIndex, vb.Buffer.Handle.ToInt32(), (IntPtr)vb.Buffer.Offset, vb.Stride); GL.BindVertexBuffer(bindingIndex, vb.Buffer.Handle.ToInt32(), (IntPtr)vb.Buffer.Offset, vb.Stride);
GL.VertexBindingDivisor(bindingIndex, vb.Divisor); GL.VertexBindingDivisor(bindingIndex, vb.Divisor);
_vertexBuffersInUse |= 1u << bindingIndex; _vertexBuffersInUse |= 1u << bindingIndex;
@@ -64,6 +77,7 @@ namespace Ryujinx.Graphics.OpenGL
} }
_vertexBuffersCount = bindingIndex; _vertexBuffersCount = bindingIndex;
_minVertexCount = minVertexCount;
_needsAttribsUpdate = true; _needsAttribsUpdate = true;
} }
@@ -143,6 +157,101 @@ namespace Ryujinx.Graphics.OpenGL
GL.BindBuffer(BufferTarget.ElementArrayBuffer, _indexBuffer.Handle.ToInt32()); GL.BindBuffer(BufferTarget.ElementArrayBuffer, _indexBuffer.Handle.ToInt32());
} }
public void PreDraw(int vertexCount)
{
LimitVertexBuffers(vertexCount);
Validate();
}
public void PreDrawVbUnbounded()
{
UnlimitVertexBuffers();
Validate();
}
public void LimitVertexBuffers(int vertexCount)
{
// Is it possible for the draw to fetch outside the bounds of any vertex buffer currently bound?
if (vertexCount <= _minVertexCount)
{
return;
}
// If the draw can fetch out of bounds, let's ensure that it will only fetch zeros rather than memory garbage.
int currentTempVbOffset = 0;
uint buffersInUse = _vertexBuffersInUse;
while (buffersInUse != 0)
{
int vbIndex = BitOperations.TrailingZeroCount(buffersInUse);
ref var vb = ref _vertexBuffers[vbIndex];
int requiredSize = vertexCount * vb.Stride;
if (vb.Buffer.Size < requiredSize)
{
BufferHandle tempVertexBuffer = EnsureTempVertexBufferSize(currentTempVbOffset + requiredSize);
Buffer.Copy(vb.Buffer.Handle, tempVertexBuffer, vb.Buffer.Offset, currentTempVbOffset, vb.Buffer.Size);
Buffer.Clear(tempVertexBuffer, currentTempVbOffset + vb.Buffer.Size, requiredSize - vb.Buffer.Size, 0);
GL.BindVertexBuffer(vbIndex, tempVertexBuffer.ToInt32(), (IntPtr)currentTempVbOffset, vb.Stride);
currentTempVbOffset += requiredSize;
_vertexBuffersLimited |= 1u << vbIndex;
}
buffersInUse &= ~(1u << vbIndex);
}
}
private BufferHandle EnsureTempVertexBufferSize(int size)
{
BufferHandle tempVertexBuffer = _tempVertexBuffer;
if (_tempVertexBufferSize < size)
{
_tempVertexBufferSize = size;
if (tempVertexBuffer == BufferHandle.Null)
{
tempVertexBuffer = Buffer.Create(size);
_tempVertexBuffer = tempVertexBuffer;
return tempVertexBuffer;
}
Buffer.Resize(_tempVertexBuffer, size);
}
return tempVertexBuffer;
}
public void UnlimitVertexBuffers()
{
uint buffersLimited = _vertexBuffersLimited;
if (buffersLimited == 0)
{
return;
}
while (buffersLimited != 0)
{
int vbIndex = BitOperations.TrailingZeroCount(buffersLimited);
ref var vb = ref _vertexBuffers[vbIndex];
GL.BindVertexBuffer(vbIndex, vb.Buffer.Handle.ToInt32(), (IntPtr)vb.Buffer.Offset, vb.Stride);
buffersLimited &= ~(1u << vbIndex);
}
_vertexBuffersLimited = 0;
}
public void Validate() public void Validate()
{ {
for (int attribIndex = 0; attribIndex < _vertexAttribsCount; attribIndex++) for (int attribIndex = 0; attribIndex < _vertexAttribsCount; attribIndex++)

View File

@@ -1,19 +0,0 @@
using Ryujinx.Graphics.GAL;
namespace Ryujinx.Graphics.OpenGL
{
struct VertexBuffer
{
public BufferRange Range { get; }
public int Divisor { get; }
public int Stride { get; }
public VertexBuffer(BufferRange range, int divisor, int stride)
{
Range = range;
Divisor = divisor;
Stride = stride;
}
}
}

View File

@@ -58,6 +58,8 @@ namespace Ryujinx.Graphics.OpenGL
GL.PixelStore(PixelStoreParameter.UnpackAlignment, 4); GL.PixelStore(PixelStoreParameter.UnpackAlignment, 4);
} }
public void ChangeVSyncMode(bool vsyncEnabled) { }
private void CreateStagingFramebuffer() private void CreateStagingFramebuffer()
{ {
_stagingFrameBuffer = GL.GenFramebuffer(); _stagingFrameBuffer = GL.GenFramebuffer();

View File

@@ -234,7 +234,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
IrOperandType.Constant => GetConstant(type, operand), IrOperandType.Constant => GetConstant(type, operand),
IrOperandType.ConstantBuffer => GetConstantBuffer(type, operand), IrOperandType.ConstantBuffer => GetConstantBuffer(type, operand),
IrOperandType.LocalVariable => GetLocal(type, operand), IrOperandType.LocalVariable => GetLocal(type, operand),
IrOperandType.Undefined => Constant(GetType(type), 0), IrOperandType.Undefined => GetUndefined(type),
_ => throw new ArgumentException($"Invalid operand type \"{operand.Type}\".") _ => throw new ArgumentException($"Invalid operand type \"{operand.Type}\".")
}; };
} }
@@ -242,6 +242,17 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
throw new NotImplementedException(node.GetType().Name); throw new NotImplementedException(node.GetType().Name);
} }
private Instruction GetUndefined(AggregateType type)
{
return type switch
{
AggregateType.Bool => ConstantFalse(TypeBool()),
AggregateType.FP32 => Constant(TypeFP32(), 0f),
AggregateType.FP64 => Constant(TypeFP64(), 0d),
_ => Constant(GetType(type), 0)
};
}
public Instruction GetAttributeElemPointer(int attr, bool isOutAttr, Instruction index, out AggregateType elemType) public Instruction GetAttributeElemPointer(int attr, bool isOutAttr, Instruction index, out AggregateType elemType)
{ {
var storageClass = isOutAttr ? StorageClass.Output : StorageClass.Input; var storageClass = isOutAttr ? StorageClass.Output : StorageClass.Input;

View File

@@ -120,7 +120,7 @@ namespace Ryujinx.Graphics.Shader
case TextureFormat.R16G16B16A16Sint: case TextureFormat.R16G16B16A16Sint:
case TextureFormat.R32G32B32A32Sint: case TextureFormat.R32G32B32A32Sint:
return VariableType.S32; return VariableType.S32;
}; }
return VariableType.F32; return VariableType.F32;
} }

View File

@@ -66,7 +66,6 @@ namespace Ryujinx.Graphics.Vulkan
Add(Format.D32Float, VkFormat.D32Sfloat); Add(Format.D32Float, VkFormat.D32Sfloat);
Add(Format.D24UnormS8Uint, VkFormat.D24UnormS8Uint); Add(Format.D24UnormS8Uint, VkFormat.D24UnormS8Uint);
Add(Format.D32FloatS8Uint, VkFormat.D32SfloatS8Uint); Add(Format.D32FloatS8Uint, VkFormat.D32SfloatS8Uint);
Add(Format.R8G8B8X8Srgb, VkFormat.R8G8B8Srgb);
Add(Format.R8G8B8A8Srgb, VkFormat.R8G8B8A8Srgb); Add(Format.R8G8B8A8Srgb, VkFormat.R8G8B8A8Srgb);
Add(Format.R4G4Unorm, VkFormat.R4G4UnormPack8); Add(Format.R4G4Unorm, VkFormat.R4G4UnormPack8);
Add(Format.R4G4B4A4Unorm, VkFormat.R4G4B4A4UnormPack16); Add(Format.R4G4B4A4Unorm, VkFormat.R4G4B4A4UnormPack16);
@@ -91,6 +90,12 @@ namespace Ryujinx.Graphics.Vulkan
Add(Format.Bc7Srgb, VkFormat.BC7SrgbBlock); Add(Format.Bc7Srgb, VkFormat.BC7SrgbBlock);
Add(Format.Bc6HSfloat, VkFormat.BC6HSfloatBlock); Add(Format.Bc6HSfloat, VkFormat.BC6HSfloatBlock);
Add(Format.Bc6HUfloat, VkFormat.BC6HUfloatBlock); Add(Format.Bc6HUfloat, VkFormat.BC6HUfloatBlock);
Add(Format.Etc2RgbUnorm, VkFormat.Etc2R8G8B8UnormBlock);
Add(Format.Etc2RgbaUnorm, VkFormat.Etc2R8G8B8A8UnormBlock);
Add(Format.Etc2RgbPtaUnorm, VkFormat.Etc2R8G8B8A1UnormBlock);
Add(Format.Etc2RgbSrgb, VkFormat.Etc2R8G8B8SrgbBlock);
Add(Format.Etc2RgbaSrgb, VkFormat.Etc2R8G8B8A8SrgbBlock);
Add(Format.Etc2RgbPtaSrgb, VkFormat.Etc2R8G8B8A1SrgbBlock);
Add(Format.R8Uscaled, VkFormat.R8Uscaled); Add(Format.R8Uscaled, VkFormat.R8Uscaled);
Add(Format.R8Sscaled, VkFormat.R8Sscaled); Add(Format.R8Sscaled, VkFormat.R8Sscaled);
Add(Format.R16Uscaled, VkFormat.R16Uscaled); Add(Format.R16Uscaled, VkFormat.R16Uscaled);
@@ -119,18 +124,6 @@ namespace Ryujinx.Graphics.Vulkan
Add(Format.R10G10B10A2Sint, VkFormat.A2B10G10R10SintPack32); Add(Format.R10G10B10A2Sint, VkFormat.A2B10G10R10SintPack32);
Add(Format.R10G10B10A2Uscaled, VkFormat.A2B10G10R10UscaledPack32); Add(Format.R10G10B10A2Uscaled, VkFormat.A2B10G10R10UscaledPack32);
Add(Format.R10G10B10A2Sscaled, VkFormat.A2B10G10R10SscaledPack32); Add(Format.R10G10B10A2Sscaled, VkFormat.A2B10G10R10SscaledPack32);
Add(Format.R8G8B8X8Unorm, VkFormat.R8G8B8Unorm);
Add(Format.R8G8B8X8Snorm, VkFormat.R8G8B8SNorm);
Add(Format.R8G8B8X8Uint, VkFormat.R8G8B8Uint);
Add(Format.R8G8B8X8Sint, VkFormat.R8G8B8Sint);
Add(Format.R16G16B16X16Float, VkFormat.R16G16B16Sfloat);
Add(Format.R16G16B16X16Unorm, VkFormat.R16G16B16Unorm);
Add(Format.R16G16B16X16Snorm, VkFormat.R16G16B16SNorm);
Add(Format.R16G16B16X16Uint, VkFormat.R16G16B16Uint);
Add(Format.R16G16B16X16Sint, VkFormat.R16G16B16Sint);
Add(Format.R32G32B32X32Float, VkFormat.R32G32B32Sfloat);
Add(Format.R32G32B32X32Uint, VkFormat.R32G32B32Uint);
Add(Format.R32G32B32X32Sint, VkFormat.R32G32B32Sint);
Add(Format.Astc4x4Unorm, VkFormat.Astc4x4UnormBlock); Add(Format.Astc4x4Unorm, VkFormat.Astc4x4UnormBlock);
Add(Format.Astc5x4Unorm, VkFormat.Astc5x4UnormBlock); Add(Format.Astc5x4Unorm, VkFormat.Astc5x4UnormBlock);
Add(Format.Astc5x5Unorm, VkFormat.Astc5x5UnormBlock); Add(Format.Astc5x5Unorm, VkFormat.Astc5x5UnormBlock);
@@ -160,12 +153,9 @@ namespace Ryujinx.Graphics.Vulkan
Add(Format.Astc12x10Srgb, VkFormat.Astc12x10SrgbBlock); Add(Format.Astc12x10Srgb, VkFormat.Astc12x10SrgbBlock);
Add(Format.Astc12x12Srgb, VkFormat.Astc12x12SrgbBlock); Add(Format.Astc12x12Srgb, VkFormat.Astc12x12SrgbBlock);
Add(Format.B5G6R5Unorm, VkFormat.R5G6B5UnormPack16); Add(Format.B5G6R5Unorm, VkFormat.R5G6B5UnormPack16);
Add(Format.B5G5R5X1Unorm, VkFormat.A1R5G5B5UnormPack16);
Add(Format.B5G5R5A1Unorm, VkFormat.A1R5G5B5UnormPack16); Add(Format.B5G5R5A1Unorm, VkFormat.A1R5G5B5UnormPack16);
Add(Format.A1B5G5R5Unorm, VkFormat.R5G5B5A1UnormPack16); Add(Format.A1B5G5R5Unorm, VkFormat.R5G5B5A1UnormPack16);
Add(Format.B8G8R8X8Unorm, VkFormat.B8G8R8Unorm);
Add(Format.B8G8R8A8Unorm, VkFormat.B8G8R8A8Unorm); Add(Format.B8G8R8A8Unorm, VkFormat.B8G8R8A8Unorm);
Add(Format.B8G8R8X8Srgb, VkFormat.B8G8R8Srgb);
Add(Format.B8G8R8A8Srgb, VkFormat.B8G8R8A8Srgb); Add(Format.B8G8R8A8Srgb, VkFormat.B8G8R8A8Srgb);
} }

View File

@@ -7,7 +7,9 @@ namespace Ryujinx.Graphics.Vulkan
{ {
class ImageWindow : WindowBase, IWindow, IDisposable class ImageWindow : WindowBase, IWindow, IDisposable
{ {
private const int ImageCount = 5; internal const VkFormat Format = VkFormat.R8G8B8A8Unorm;
private const int ImageCount = 3;
private const int SurfaceWidth = 1280; private const int SurfaceWidth = 1280;
private const int SurfaceHeight = 720; private const int SurfaceHeight = 720;
@@ -18,52 +20,49 @@ namespace Ryujinx.Graphics.Vulkan
private Auto<DisposableImage>[] _images; private Auto<DisposableImage>[] _images;
private Auto<DisposableImageView>[] _imageViews; private Auto<DisposableImageView>[] _imageViews;
private Auto<MemoryAllocation>[] _imageAllocationAuto; private Auto<MemoryAllocation>[] _imageAllocationAuto;
private ImageState[] _states;
private PresentImageInfo[] _presentedImages;
private FenceHolder[] _fences;
private ulong[] _imageSizes; private ulong[] _imageSizes;
private ulong[] _imageOffsets; private ulong[] _imageOffsets;
private Semaphore _imageAvailableSemaphore;
private Semaphore _renderFinishedSemaphore;
private int _width = SurfaceWidth; private int _width = SurfaceWidth;
private int _height = SurfaceHeight; private int _height = SurfaceHeight;
private VkFormat _format;
private bool _recreateImages; private bool _recreateImages;
private int _nextImage; private int _nextImage;
internal new bool ScreenCaptureRequested { get; set; }
public unsafe ImageWindow(VulkanRenderer gd, PhysicalDevice physicalDevice, Device device) public unsafe ImageWindow(VulkanRenderer gd, PhysicalDevice physicalDevice, Device device)
{ {
_gd = gd; _gd = gd;
_physicalDevice = physicalDevice; _physicalDevice = physicalDevice;
_device = device; _device = device;
_format = VkFormat.R8G8B8A8Unorm;
_images = new Auto<DisposableImage>[ImageCount]; _images = new Auto<DisposableImage>[ImageCount];
_imageAllocationAuto = new Auto<MemoryAllocation>[ImageCount]; _imageAllocationAuto = new Auto<MemoryAllocation>[ImageCount];
_imageSizes = new ulong[ImageCount]; _imageSizes = new ulong[ImageCount];
_imageOffsets = new ulong[ImageCount]; _imageOffsets = new ulong[ImageCount];
_states = new ImageState[ImageCount];
_presentedImages = new PresentImageInfo[ImageCount];
CreateImages(); CreateImages();
var semaphoreCreateInfo = new SemaphoreCreateInfo()
{
SType = StructureType.SemaphoreCreateInfo
};
gd.Api.CreateSemaphore(device, semaphoreCreateInfo, null, out _imageAvailableSemaphore).ThrowOnError();
gd.Api.CreateSemaphore(device, semaphoreCreateInfo, null, out _renderFinishedSemaphore).ThrowOnError();
} }
private void RecreateImages() private void RecreateImages()
{ {
for (int i = 0; i < ImageCount; i++) for (int i = 0; i < ImageCount; i++)
{ {
_imageViews[i]?.Dispose(); lock (_states[i])
_imageAllocationAuto[i]?.Dispose(); {
_images[i]?.Dispose(); _states[i].IsValid = false;
_fences[i]?.Wait();
_fences[i]?.Put();
_imageViews[i]?.Dispose();
_imageAllocationAuto[i]?.Dispose();
_images[i]?.Dispose();
}
} }
_presentedImages = null;
CreateImages(); CreateImages();
} }
@@ -71,34 +70,35 @@ namespace Ryujinx.Graphics.Vulkan
private unsafe void CreateImages() private unsafe void CreateImages()
{ {
_imageViews = new Auto<DisposableImageView>[ImageCount]; _imageViews = new Auto<DisposableImageView>[ImageCount];
_fences = new FenceHolder[ImageCount];
_presentedImages = new PresentImageInfo[ImageCount];
_nextImage = 0;
var cbs = _gd.CommandBufferPool.Rent(); var cbs = _gd.CommandBufferPool.Rent();
var imageCreateInfo = new ImageCreateInfo
{
SType = StructureType.ImageCreateInfo,
ImageType = ImageType.ImageType2D,
Format = Format,
Extent = new Extent3D((uint?)_width, (uint?)_height, 1),
MipLevels = 1,
ArrayLayers = 1,
Samples = SampleCountFlags.SampleCount1Bit,
Tiling = ImageTiling.Optimal,
Usage = ImageUsageFlags.ImageUsageColorAttachmentBit | ImageUsageFlags.ImageUsageTransferSrcBit | ImageUsageFlags.ImageUsageTransferDstBit,
SharingMode = SharingMode.Exclusive,
InitialLayout = ImageLayout.Undefined,
Flags = ImageCreateFlags.ImageCreateMutableFormatBit
};
for (int i = 0; i < _images.Length; i++) for (int i = 0; i < _images.Length; i++)
{ {
var imageCreateInfo = new ImageCreateInfo
{
SType = StructureType.ImageCreateInfo,
ImageType = ImageType.ImageType2D,
Format = _format,
Extent =
new Extent3D((uint?)_width,
(uint?)_height, 1),
MipLevels = 1,
ArrayLayers = 1,
Samples = SampleCountFlags.SampleCount1Bit,
Tiling = ImageTiling.Optimal,
Usage = ImageUsageFlags.ImageUsageColorAttachmentBit | ImageUsageFlags.ImageUsageTransferSrcBit | ImageUsageFlags.ImageUsageTransferDstBit,
SharingMode = SharingMode.Exclusive,
InitialLayout = ImageLayout.Undefined,
Flags = ImageCreateFlags.ImageCreateMutableFormatBit
};
_gd.Api.CreateImage(_device, imageCreateInfo, null, out var image).ThrowOnError(); _gd.Api.CreateImage(_device, imageCreateInfo, null, out var image).ThrowOnError();
_images[i] = new Auto<DisposableImage>(new DisposableImage(_gd.Api, _device, image)); _images[i] = new Auto<DisposableImage>(new DisposableImage(_gd.Api, _device, image));
_gd.Api.GetImageMemoryRequirements(_device, image, _gd.Api.GetImageMemoryRequirements(_device, image,
out var memoryRequirements); out var memoryRequirements);
var allocation = _gd.MemoryAllocator.AllocateDeviceMemory(_physicalDevice, memoryRequirements, MemoryPropertyFlags.MemoryPropertyDeviceLocalBit); var allocation = _gd.MemoryAllocator.AllocateDeviceMemory(_physicalDevice, memoryRequirements, MemoryPropertyFlags.MemoryPropertyDeviceLocalBit);
_imageSizes[i] = allocation.Size; _imageSizes[i] = allocation.Size;
@@ -108,7 +108,7 @@ namespace Ryujinx.Graphics.Vulkan
_gd.Api.BindImageMemory(_device, image, allocation.Memory, allocation.Offset); _gd.Api.BindImageMemory(_device, image, allocation.Memory, allocation.Offset);
_imageViews[i] = CreateImageView(image, _format); _imageViews[i] = CreateImageView(image, Format);
Transition( Transition(
cbs.CommandBuffer, cbs.CommandBuffer,
@@ -116,7 +116,9 @@ namespace Ryujinx.Graphics.Vulkan
0, 0,
0, 0,
ImageLayout.Undefined, ImageLayout.Undefined,
ImageLayout.ColorAttachmentOptimal); ImageLayout.TransferSrcOptimal);
_states[i] = new ImageState();
} }
_gd.CommandBufferPool.Return(cbs); _gd.CommandBufferPool.Return(cbs);
@@ -165,7 +167,7 @@ namespace Ryujinx.Graphics.Vulkan
image.GetUnsafe().Value, image.GetUnsafe().Value,
0, 0,
AccessFlags.AccessTransferWriteBit, AccessFlags.AccessTransferWriteBit,
ImageLayout.ColorAttachmentOptimal, ImageLayout.TransferSrcOptimal,
ImageLayout.General); ImageLayout.General);
var view = (TextureView)texture; var view = (TextureView)texture;
@@ -232,7 +234,7 @@ namespace Ryujinx.Graphics.Vulkan
_imageViews[_nextImage], _imageViews[_nextImage],
_width, _width,
_height, _height,
_format, Format,
new Extents2D(srcX0, srcY0, srcX1, srcY1), new Extents2D(srcX0, srcY0, srcX1, srcY1),
new Extents2D(dstX0, dstY1, dstX1, dstY0), new Extents2D(dstX0, dstY1, dstX1, dstY0),
true, true,
@@ -244,7 +246,7 @@ namespace Ryujinx.Graphics.Vulkan
0, 0,
0, 0,
ImageLayout.General, ImageLayout.General,
ImageLayout.ColorAttachmentOptimal); ImageLayout.TransferSrcOptimal);
_gd.CommandBufferPool.Return( _gd.CommandBufferPool.Return(
cbs, cbs,
@@ -252,12 +254,30 @@ namespace Ryujinx.Graphics.Vulkan
stackalloc[] { PipelineStageFlags.PipelineStageColorAttachmentOutputBit }, stackalloc[] { PipelineStageFlags.PipelineStageColorAttachmentOutputBit },
null); null);
var memory = _imageAllocationAuto[_nextImage].GetUnsafe().Memory; _fences[_nextImage]?.Put();
var presentInfo = new PresentImageInfo(image.GetUnsafe().Value, memory, _imageSizes[_nextImage], _imageOffsets[_nextImage], _renderFinishedSemaphore, _imageAvailableSemaphore); _fences[_nextImage] = cbs.GetFence();
cbs.GetFence().Get();
swapBuffersCallback(presentInfo); PresentImageInfo info = _presentedImages[_nextImage];
_nextImage %= ImageCount; if (info == null)
{
info = new PresentImageInfo(
image,
_imageAllocationAuto[_nextImage],
_device,
_physicalDevice,
_imageSizes[_nextImage],
_imageOffsets[_nextImage],
new Extent2D((uint)_width, (uint)_height),
_states[_nextImage]);
_presentedImages[_nextImage] = info;
}
swapBuffersCallback(info);
_nextImage = (_nextImage + 1) % ImageCount;
} }
private unsafe void Transition( private unsafe void Transition(
@@ -320,11 +340,11 @@ namespace Ryujinx.Graphics.Vulkan
{ {
unsafe unsafe
{ {
_gd.Api.DestroySemaphore(_device, _renderFinishedSemaphore, null);
_gd.Api.DestroySemaphore(_device, _imageAvailableSemaphore, null);
for (int i = 0; i < ImageCount; i++) for (int i = 0; i < ImageCount; i++)
{ {
_states[i].IsValid = false;
_fences[i]?.Wait();
_fences[i]?.Put();
_imageViews[i]?.Dispose(); _imageViews[i]?.Dispose();
_imageAllocationAuto[i]?.Dispose(); _imageAllocationAuto[i]?.Dispose();
_images[i]?.Dispose(); _images[i]?.Dispose();
@@ -337,25 +357,73 @@ namespace Ryujinx.Graphics.Vulkan
{ {
Dispose(true); Dispose(true);
} }
public override void ChangeVSyncMode(bool vsyncEnabled) { }
}
public class ImageState
{
private bool _isValid = true;
public bool IsValid
{
get => _isValid;
internal set
{
_isValid = value;
StateChanged?.Invoke(this, _isValid);
}
}
public event EventHandler<bool> StateChanged;
} }
public class PresentImageInfo public class PresentImageInfo
{ {
public Image Image { get; } private readonly Auto<DisposableImage> _image;
public DeviceMemory Memory { get; } private readonly Auto<MemoryAllocation> _memory;
public ulong MemorySize { get; set; }
public ulong MemoryOffset { get; set; }
public Semaphore ReadySemaphore { get; }
public Semaphore AvailableSemaphore { get; }
public PresentImageInfo(Image image, DeviceMemory memory, ulong memorySize, ulong memoryOffset, Semaphore readySemaphore, Semaphore availableSemaphore) public Image Image => _image.GetUnsafe().Value;
public DeviceMemory Memory => _memory.GetUnsafe().Memory;
public Device Device { get; }
public PhysicalDevice PhysicalDevice { get; }
public ulong MemorySize { get; }
public ulong MemoryOffset { get; }
public Extent2D Extent { get; }
public ImageState State { get; internal set; }
internal PresentImageInfo(
Auto<DisposableImage> image,
Auto<MemoryAllocation> memory,
Device device,
PhysicalDevice physicalDevice,
ulong memorySize,
ulong memoryOffset,
Extent2D extent2D,
ImageState state)
{ {
this.Image = image; _image = image;
this.Memory = memory; _memory = memory;
this.MemorySize = memorySize; Device = device;
this.MemoryOffset = memoryOffset; PhysicalDevice = physicalDevice;
this.ReadySemaphore = readySemaphore; MemorySize = memorySize;
this.AvailableSemaphore = availableSemaphore; MemoryOffset = memoryOffset;
Extent = extent2D;
State = state;
}
public void Get()
{
_memory.IncrementReferenceCount();
_image.IncrementReferenceCount();
}
public void Put()
{
_memory.DecrementReferenceCount();
_image.DecrementReferenceCount();
} }
} }
} }

View File

@@ -31,7 +31,7 @@ namespace Ryujinx.Graphics.Vulkan
Length = length; Length = length;
} }
public Span<T> ToSpan() public Span<T> AsSpan()
{ {
return new Span<T>(Pointer, Length); return new Span<T>(Pointer, Length);
} }

View File

@@ -582,7 +582,7 @@ namespace Ryujinx.Graphics.Vulkan
_newState.PipelineLayout = internalProgram.PipelineLayout; _newState.PipelineLayout = internalProgram.PipelineLayout;
_newState.StagesCount = (uint)stages.Length; _newState.StagesCount = (uint)stages.Length;
stages.CopyTo(_newState.Stages.ToSpan().Slice(0, stages.Length)); stages.CopyTo(_newState.Stages.AsSpan().Slice(0, stages.Length));
SignalStateChange(); SignalStateChange();
} }
@@ -921,7 +921,7 @@ namespace Ryujinx.Graphics.Vulkan
protected void UpdatePipelineAttachmentFormats() protected void UpdatePipelineAttachmentFormats()
{ {
var dstAttachmentFormats = _newState.Internal.AttachmentFormats.ToSpan(); var dstAttachmentFormats = _newState.Internal.AttachmentFormats.AsSpan();
FramebufferParams.AttachmentFormats.CopyTo(dstAttachmentFormats); FramebufferParams.AttachmentFormats.CopyTo(dstAttachmentFormats);
int maxAttachmentIndex = FramebufferParams.MaxColorAttachmentIndex + (FramebufferParams.HasDepthStencil ? 1 : 0); int maxAttachmentIndex = FramebufferParams.MaxColorAttachmentIndex + (FramebufferParams.HasDepthStencil ? 1 : 0);

View File

@@ -117,7 +117,7 @@ namespace Ryujinx.Graphics.Vulkan
private void RecordScissor(Vk api, CommandBuffer commandBuffer) private void RecordScissor(Vk api, CommandBuffer commandBuffer)
{ {
api.CmdSetScissor(commandBuffer, 0, (uint)ScissorsCount, _scissors.ToSpan()); api.CmdSetScissor(commandBuffer, 0, (uint)ScissorsCount, _scissors.AsSpan());
} }
private void RecordStencilMasks(Vk api, CommandBuffer commandBuffer) private void RecordStencilMasks(Vk api, CommandBuffer commandBuffer)
@@ -132,7 +132,7 @@ namespace Ryujinx.Graphics.Vulkan
private void RecordViewport(Vk api, CommandBuffer commandBuffer) private void RecordViewport(Vk api, CommandBuffer commandBuffer)
{ {
api.CmdSetViewport(commandBuffer, 0, (uint)ViewportsCount, Viewports.ToSpan()); api.CmdSetViewport(commandBuffer, 0, (uint)ViewportsCount, Viewports.AsSpan());
} }
} }
} }

View File

@@ -52,22 +52,22 @@ namespace Ryujinx.Graphics.Vulkan
return false; return false;
} }
if (!SequenceEqual<VertexInputAttributeDescription>(VertexAttributeDescriptions.ToSpan(), other.VertexAttributeDescriptions.ToSpan(), VertexAttributeDescriptionsCount)) if (!SequenceEqual<VertexInputAttributeDescription>(VertexAttributeDescriptions.AsSpan(), other.VertexAttributeDescriptions.AsSpan(), VertexAttributeDescriptionsCount))
{ {
return false; return false;
} }
if (!SequenceEqual<VertexInputBindingDescription>(VertexBindingDescriptions.ToSpan(), other.VertexBindingDescriptions.ToSpan(), VertexBindingDescriptionsCount)) if (!SequenceEqual<VertexInputBindingDescription>(VertexBindingDescriptions.AsSpan(), other.VertexBindingDescriptions.AsSpan(), VertexBindingDescriptionsCount))
{ {
return false; return false;
} }
if (!SequenceEqual<PipelineColorBlendAttachmentState>(ColorBlendAttachmentState.ToSpan(), other.ColorBlendAttachmentState.ToSpan(), ColorBlendAttachmentStateCount)) if (!SequenceEqual<PipelineColorBlendAttachmentState>(ColorBlendAttachmentState.AsSpan(), other.ColorBlendAttachmentState.AsSpan(), ColorBlendAttachmentStateCount))
{ {
return false; return false;
} }
if (!SequenceEqual<Format>(AttachmentFormats.ToSpan(), other.AttachmentFormats.ToSpan(), ColorBlendAttachmentStateCount + (HasDepthStencil ? 1u : 0u))) if (!SequenceEqual<Format>(AttachmentFormats.AsSpan(), other.AttachmentFormats.AsSpan(), ColorBlendAttachmentStateCount + (HasDepthStencil ? 1u : 0u)))
{ {
return false; return false;
} }

View File

@@ -131,7 +131,7 @@ namespace Ryujinx.Graphics.Vulkan
return ShaderKind.GlslFragmentShader; return ShaderKind.GlslFragmentShader;
case ShaderStage.Compute: case ShaderStage.Compute:
return ShaderKind.GlslComputeShader; return ShaderKind.GlslComputeShader;
}; }
Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(ShaderStage)} enum value: {stage}."); Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(ShaderStage)} enum value: {stage}.");

View File

@@ -245,7 +245,7 @@ namespace Ryujinx.Graphics.Vulkan
PipelineState pipeline = _state.ToVulkanPipelineState(_gd); PipelineState pipeline = _state.ToVulkanPipelineState(_gd);
// Copy the shader stage info to the pipeline. // Copy the shader stage info to the pipeline.
var stages = pipeline.Stages.ToSpan(); var stages = pipeline.Stages.AsSpan();
for (int i = 0; i < _shaders.Length; i++) for (int i = 0; i < _shaders.Length; i++)
{ {

View File

@@ -111,7 +111,7 @@ namespace Ryujinx.Graphics.Vulkan
_offset = buffer.Offset; _offset = buffer.Offset;
_size = buffer.Size; _size = buffer.Size;
ReleaseImpl();; ReleaseImpl();
} }
public BufferView GetBufferView(CommandBufferScoped cbs) public BufferView GetBufferView(CommandBufferScoped cbs)

View File

@@ -25,6 +25,8 @@ namespace Ryujinx.Graphics.Vulkan
private int _width; private int _width;
private int _height; private int _height;
private bool _vsyncEnabled;
private bool _vsyncModeChanged;
private VkFormat _format; private VkFormat _format;
public unsafe Window(VulkanRenderer gd, SurfaceKHR surface, PhysicalDevice physicalDevice, Device device) public unsafe Window(VulkanRenderer gd, SurfaceKHR surface, PhysicalDevice physicalDevice, Device device)
@@ -47,6 +49,8 @@ namespace Ryujinx.Graphics.Vulkan
private void RecreateSwapchain() private void RecreateSwapchain()
{ {
_vsyncModeChanged = false;
for (int i = 0; i < _swapchainImageViews.Length; i++) for (int i = 0; i < _swapchainImageViews.Length; i++)
{ {
_swapchainImageViews[i].Dispose(); _swapchainImageViews[i].Dispose();
@@ -110,7 +114,7 @@ namespace Ryujinx.Graphics.Vulkan
ImageArrayLayers = 1, ImageArrayLayers = 1,
PreTransform = capabilities.CurrentTransform, PreTransform = capabilities.CurrentTransform,
CompositeAlpha = CompositeAlphaFlagsKHR.CompositeAlphaOpaqueBitKhr, CompositeAlpha = CompositeAlphaFlagsKHR.CompositeAlphaOpaqueBitKhr,
PresentMode = ChooseSwapPresentMode(presentModes), PresentMode = ChooseSwapPresentMode(presentModes, _vsyncEnabled),
Clipped = true, Clipped = true,
OldSwapchain = oldSwapchain OldSwapchain = oldSwapchain
}; };
@@ -178,9 +182,9 @@ namespace Ryujinx.Graphics.Vulkan
return availableFormats[0]; return availableFormats[0];
} }
private static PresentModeKHR ChooseSwapPresentMode(PresentModeKHR[] availablePresentModes) private static PresentModeKHR ChooseSwapPresentMode(PresentModeKHR[] availablePresentModes, bool vsyncEnabled)
{ {
if (availablePresentModes.Contains(PresentModeKHR.PresentModeImmediateKhr)) if (!vsyncEnabled && availablePresentModes.Contains(PresentModeKHR.PresentModeImmediateKhr))
{ {
return PresentModeKHR.PresentModeImmediateKhr; return PresentModeKHR.PresentModeImmediateKhr;
} }
@@ -188,6 +192,10 @@ namespace Ryujinx.Graphics.Vulkan
{ {
return PresentModeKHR.PresentModeMailboxKhr; return PresentModeKHR.PresentModeMailboxKhr;
} }
else if (availablePresentModes.Contains(PresentModeKHR.PresentModeFifoKhr))
{
return PresentModeKHR.PresentModeFifoKhr;
}
else else
{ {
return PresentModeKHR.PresentModeFifoKhr; return PresentModeKHR.PresentModeFifoKhr;
@@ -224,7 +232,8 @@ namespace Ryujinx.Graphics.Vulkan
ref nextImage); ref nextImage);
if (acquireResult == Result.ErrorOutOfDateKhr || if (acquireResult == Result.ErrorOutOfDateKhr ||
acquireResult == Result.SuboptimalKhr) acquireResult == Result.SuboptimalKhr ||
_vsyncModeChanged)
{ {
RecreateSwapchain(); RecreateSwapchain();
} }
@@ -404,6 +413,12 @@ namespace Ryujinx.Graphics.Vulkan
// Not needed as we can get the size from the surface. // Not needed as we can get the size from the surface.
} }
public override void ChangeVSyncMode(bool vsyncEnabled)
{
_vsyncEnabled = vsyncEnabled;
_vsyncModeChanged = true;
}
protected virtual void Dispose(bool disposing) protected virtual void Dispose(bool disposing)
{ {
if (disposing) if (disposing)

View File

@@ -10,5 +10,6 @@ namespace Ryujinx.Graphics.Vulkan
public abstract void Dispose(); public abstract void Dispose();
public abstract void Present(ITexture texture, ImageCrop crop, Action<object> swapBuffersCallback); public abstract void Present(ITexture texture, ImageCrop crop, Action<object> swapBuffersCallback);
public abstract void SetSize(int width, int height); public abstract void SetSize(int width, int height);
public abstract void ChangeVSyncMode(bool vsyncEnabled);
} }
} }

View File

@@ -766,7 +766,7 @@ namespace Ryujinx.HLE.FileSystem
metaEntries = meta.MetaEntries; metaEntries = meta.MetaEntries;
updateNcas.Remove(SystemUpdateTitleId); updateNcas.Remove(SystemUpdateTitleId);
}; }
} }
} }
@@ -905,7 +905,7 @@ namespace Ryujinx.HLE.FileSystem
{ {
metaEntries = meta.MetaEntries; metaEntries = meta.MetaEntries;
} }
}; }
continue; continue;
} }

View File

@@ -72,9 +72,16 @@ namespace Ryujinx.HLE.HOS.Applets
int playerMin = argHeader.PlayerCountMin; int playerMin = argHeader.PlayerCountMin;
int playerMax = argHeader.PlayerCountMax; int playerMax = argHeader.PlayerCountMax;
bool singleMode = argHeader.EnableSingleMode != 0;
Logger.Stub?.PrintStub(LogClass.ServiceHid, $"ControllerApplet Arg {playerMin} {playerMax} {argHeader.EnableTakeOverConnection} {argHeader.EnableSingleMode}"); Logger.Stub?.PrintStub(LogClass.ServiceHid, $"ControllerApplet Arg {playerMin} {playerMax} {argHeader.EnableTakeOverConnection} {argHeader.EnableSingleMode}");
if (singleMode)
{
// Applications can set an arbitrary player range even with SingleMode, so clamp it
playerMin = playerMax = 1;
}
int configuredCount = 0; int configuredCount = 0;
PlayerIndex primaryIndex = PlayerIndex.Unknown; PlayerIndex primaryIndex = PlayerIndex.Unknown;
while (!_system.Device.Hid.Npads.Validate(playerMin, playerMax, (ControllerType)privateArg.NpadStyleSet, out configuredCount, out primaryIndex)) while (!_system.Device.Hid.Npads.Validate(playerMin, playerMax, (ControllerType)privateArg.NpadStyleSet, out configuredCount, out primaryIndex))

View File

@@ -19,7 +19,7 @@ namespace Ryujinx.HLE.HOS.Applets
{ {
private byte element; private byte element;
public Span<byte> ToSpan() => MemoryMarshal.CreateSpan(ref element, 8 * 0x81); public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref element, 8 * 0x81);
} }
} }
#pragma warning restore CS0649 #pragma warning restore CS0649

View File

@@ -19,7 +19,7 @@ namespace Ryujinx.HLE.HOS.Applets
{ {
private byte element; private byte element;
public Span<byte> ToSpan() => MemoryMarshal.CreateSpan(ref element, 4 * 0x81); public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref element, 4 * 0x81);
} }
} }
#pragma warning restore CS0649 #pragma warning restore CS0649

View File

@@ -179,8 +179,8 @@ namespace Ryujinx.HLE.HOS.Applets.Error
byte[] messageTextBuffer = new byte[0x800]; byte[] messageTextBuffer = new byte[0x800];
byte[] detailsTextBuffer = new byte[0x800]; byte[] detailsTextBuffer = new byte[0x800];
applicationErrorArg.MessageText.ToSpan().CopyTo(messageTextBuffer); applicationErrorArg.MessageText.AsSpan().CopyTo(messageTextBuffer);
applicationErrorArg.DetailsText.ToSpan().CopyTo(detailsTextBuffer); applicationErrorArg.DetailsText.AsSpan().CopyTo(detailsTextBuffer);
string messageText = Encoding.ASCII.GetString(messageTextBuffer.TakeWhile(b => !b.Equals(0)).ToArray()); string messageText = Encoding.ASCII.GetString(messageTextBuffer.TakeWhile(b => !b.Equals(0)).ToArray());
string detailsText = Encoding.ASCII.GetString(detailsTextBuffer.TakeWhile(b => !b.Equals(0)).ToArray()); string detailsText = Encoding.ASCII.GetString(detailsTextBuffer.TakeWhile(b => !b.Equals(0)).ToArray());

View File

@@ -224,6 +224,17 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
return ResultCode.Success; return ResultCode.Success;
} }
[CommandHipc(62)] // 4.0.0+
// GetHdcpAuthenticationState() -> s32 state
public ResultCode GetHdcpAuthenticationState(ServiceCtx context)
{
context.ResponseData.Write(0);
Logger.Stub?.PrintStub(LogClass.ServiceAm);
return ResultCode.Success;
}
[CommandHipc(66)] // 6.0.0+ [CommandHipc(66)] // 6.0.0+
// SetCpuBoostMode(u32 cpu_boost_mode) // SetCpuBoostMode(u32 cpu_boost_mode)
public ResultCode SetCpuBoostMode(ServiceCtx context) public ResultCode SetCpuBoostMode(ServiceCtx context)

View File

@@ -2,6 +2,7 @@ using Ryujinx.Common.Logging;
using Ryujinx.HLE.HOS.Ipc; using Ryujinx.HLE.HOS.Ipc;
using Ryujinx.HLE.HOS.Kernel.Common; using Ryujinx.HLE.HOS.Kernel.Common;
using Ryujinx.HLE.HOS.Kernel.Threading; using Ryujinx.HLE.HOS.Kernel.Threading;
using Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy.Types;
using System; using System;
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
@@ -316,6 +317,22 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
return ResultCode.Success; return ResultCode.Success;
} }
[CommandHipc(80)] // 4.0.0+
// SetWirelessPriorityMode(s32 wireless_priority_mode)
public ResultCode SetWirelessPriorityMode(ServiceCtx context)
{
WirelessPriorityMode wirelessPriorityMode = (WirelessPriorityMode)context.RequestData.ReadInt32();
if (wirelessPriorityMode > WirelessPriorityMode.Unknown2)
{
return ResultCode.InvalidParameters;
}
Logger.Stub?.PrintStub(LogClass.ServiceAm, new { wirelessPriorityMode });
return ResultCode.Success;
}
[CommandHipc(90)] // 6.0.0+ [CommandHipc(90)] // 6.0.0+
// GetAccumulatedSuspendedTickValue() -> u64 // GetAccumulatedSuspendedTickValue() -> u64
public ResultCode GetAccumulatedSuspendedTickValue(ServiceCtx context) public ResultCode GetAccumulatedSuspendedTickValue(ServiceCtx context)
@@ -356,5 +373,21 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
return ResultCode.Success; return ResultCode.Success;
} }
[CommandHipc(120)] // 11.0.0+
// SaveCurrentScreenshot(s32 album_report_option)
public ResultCode SaveCurrentScreenshot(ServiceCtx context)
{
AlbumReportOption albumReportOption = (AlbumReportOption)context.RequestData.ReadInt32();
if (albumReportOption > AlbumReportOption.Unknown3)
{
return ResultCode.InvalidParameters;
}
Logger.Stub?.PrintStub(LogClass.ServiceAm, new { albumReportOption });
return ResultCode.Success;
}
} }
} }

View File

@@ -0,0 +1,10 @@
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy.Types
{
enum AlbumReportOption
{
OverlayNotDisplayed,
OverlayDisplayed,
Unknown2,
Unknown3
}
}

View File

@@ -0,0 +1,9 @@
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy.Types
{
enum WirelessPriorityMode
{
Default,
OptimizedForWlan,
Unknown2
}
}

View File

@@ -117,7 +117,7 @@ namespace Ryujinx.HLE.HOS.Services.Audio
OpusMultiStreamParametersEx parameters = context.Memory.Read<OpusMultiStreamParametersEx>(parametersAddress); OpusMultiStreamParametersEx parameters = context.Memory.Read<OpusMultiStreamParametersEx>(parametersAddress);
byte[] mappings = MemoryMarshal.Cast<uint, byte>(parameters.ChannelMappings.ToSpan()).ToArray(); byte[] mappings = MemoryMarshal.Cast<uint, byte>(parameters.ChannelMappings.AsSpan()).ToArray();
// UseLargeFrameSize can be ignored due to not relying on fixed size buffers for storing the decoded result. // UseLargeFrameSize can be ignored due to not relying on fixed size buffers for storing the decoded result.
MakeObject(context, new IHardwareOpusDecoder( MakeObject(context, new IHardwareOpusDecoder(

View File

@@ -131,7 +131,7 @@ namespace Ryujinx.HLE.HOS.Services.Friend.ServiceCreator
return ResultCode.InvalidArgument; return ResultCode.InvalidArgument;
} }
// TODO: Service mount the friends:/ system savedata and try to load friend.cache file, returns true if exists, false otherwise. // TODO: Service mount the friends:/ system savedata and try to load friend.cache file, returns true if exists, false otherwise.
// NOTE: If no cache is available, guest then calls nn::friends::EnsureFriendListAvailable, we can avoid that by faking the cache check. // NOTE: If no cache is available, guest then calls nn::friends::EnsureFriendListAvailable, we can avoid that by faking the cache check.
context.ResponseData.Write(true); context.ResponseData.Write(true);
@@ -190,7 +190,7 @@ namespace Ryujinx.HLE.HOS.Services.Friend.ServiceCreator
} }
context.Device.System.AccountManager.OpenUserOnlinePlay(userId); context.Device.System.AccountManager.OpenUserOnlinePlay(userId);
Logger.Stub?.PrintStub(LogClass.ServiceFriend, new { UserId = userId.ToString() }); Logger.Stub?.PrintStub(LogClass.ServiceFriend, new { UserId = userId.ToString() });
return ResultCode.Success; return ResultCode.Success;
@@ -277,7 +277,7 @@ namespace Ryujinx.HLE.HOS.Services.Friend.ServiceCreator
Array16<byte> randomGuid = new Array16<byte>(); Array16<byte> randomGuid = new Array16<byte>();
Guid.NewGuid().ToByteArray().AsSpan().CopyTo(randomGuid.ToSpan()); Guid.NewGuid().ToByteArray().AsSpan().CopyTo(randomGuid.AsSpan());
PlayHistoryRegistrationKey playHistoryRegistrationKey = new PlayHistoryRegistrationKey PlayHistoryRegistrationKey playHistoryRegistrationKey = new PlayHistoryRegistrationKey
{ {

View File

@@ -26,7 +26,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
SamplingNumber = previousEntry.SamplingNumber + 1, SamplingNumber = previousEntry.SamplingNumber + 1,
}; };
keyState.Keys.AsSpan().CopyTo(newState.Keys.RawData.ToSpan()); keyState.Keys.AsSpan().CopyTo(newState.Keys.RawData.AsSpan());
newState.Modifiers = (KeyboardModifier)keyState.Modifier; newState.Modifiers = (KeyboardModifier)keyState.Modifier;
lifo.Write(ref newState); lifo.Write(ref newState);

View File

@@ -543,7 +543,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
Attributes = SixAxisSensorAttribute.IsConnected Attributes = SixAxisSensorAttribute.IsConnected
}; };
state.Orientation.AsSpan().CopyTo(newState.Direction.ToSpan()); state.Orientation.AsSpan().CopyTo(newState.Direction.AsSpan());
ref RingLifo<SixAxisSensorState> lifo = ref GetSixAxisSensorLifo(ref currentNpad, isRightPair); ref RingLifo<SixAxisSensorState> lifo = ref GetSixAxisSensorLifo(ref currentNpad, isRightPair);

View File

@@ -628,7 +628,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp
Reserved2 = new Array6<byte>() Reserved2 = new Array6<byte>()
}; };
Uuid.CopyTo(tagInfo.Uuid.ToSpan()); Uuid.CopyTo(tagInfo.Uuid.AsSpan());
context.Memory.Write(outputPosition, tagInfo); context.Memory.Write(outputPosition, tagInfo);

View File

@@ -85,7 +85,7 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp
Reserved1 = new Array64<byte>(), Reserved1 = new Array64<byte>(),
Reserved2 = new Array58<byte>() Reserved2 = new Array58<byte>()
}; };
Encoding.ASCII.GetBytes("Ryujinx").CopyTo(registerInfo.Nickname.ToSpan()); Encoding.ASCII.GetBytes("Ryujinx").CopyTo(registerInfo.Nickname.AsSpan());
return registerInfo; return registerInfo;
} }

View File

@@ -84,7 +84,7 @@ namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService
networkProfile.IpSettingData.IpAddressSetting = new IpAddressSetting(interfaceProperties, unicastAddress); networkProfile.IpSettingData.IpAddressSetting = new IpAddressSetting(interfaceProperties, unicastAddress);
networkProfile.IpSettingData.DnsSetting = new DnsSetting(interfaceProperties); networkProfile.IpSettingData.DnsSetting = new DnsSetting(interfaceProperties);
Encoding.ASCII.GetBytes("RyujinxNetwork").CopyTo(networkProfile.Name.ToSpan()); Encoding.ASCII.GetBytes("RyujinxNetwork").CopyTo(networkProfile.Name.AsSpan());
context.Memory.Write(networkProfileDataPosition, networkProfile); context.Memory.Write(networkProfileDataPosition, networkProfile);

View File

@@ -16,7 +16,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
public IPEndPoint ToIPEndPoint() public IPEndPoint ToIPEndPoint()
{ {
IPAddress address = new IPAddress(Address.ToSpan()); IPAddress address = new IPAddress(Address.AsSpan());
int port = (ushort)IPAddress.NetworkToHostOrder((short)Port); int port = (ushort)IPAddress.NetworkToHostOrder((short)Port);
return new IPEndPoint(address, port); return new IPEndPoint(address, port);
@@ -31,7 +31,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
Port = (ushort)IPAddress.HostToNetworkOrder((short)endpoint.Port) Port = (ushort)IPAddress.HostToNetworkOrder((short)endpoint.Port)
}; };
endpoint.Address.GetAddressBytes().AsSpan().CopyTo(result.Address.ToSpan()); endpoint.Address.GetAddressBytes().AsSpan().CopyTo(result.Address.AsSpan());
return result; return result;
} }

View File

@@ -22,7 +22,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Sfdnsres.Types
Port = port; Port = port;
Address = new Array4<byte>(); Address = new Array4<byte>();
address.TryWriteBytes(Address.ToSpan(), out _); address.TryWriteBytes(Address.AsSpan(), out _);
} }
public void ToNetworkOrder() public void ToNetworkOrder()
@@ -43,7 +43,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Sfdnsres.Types
{ {
if (BitConverter.IsLittleEndian) if (BitConverter.IsLittleEndian)
{ {
address.ToSpan().Reverse(); address.AsSpan().Reverse();
} }
} }
} }

View File

@@ -1440,7 +1440,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
int timeZoneSize = Math.Min(StringUtils.LengthCstr(timeZoneAbbreviation), 8); int timeZoneSize = Math.Min(StringUtils.LengthCstr(timeZoneAbbreviation), 8);
timeZoneAbbreviation[..timeZoneSize].CopyTo(calendarAdditionalInfo.TimezoneName.ToSpan()); timeZoneAbbreviation[..timeZoneSize].CopyTo(calendarAdditionalInfo.TimezoneName.AsSpan());
} }
return result; return result;

View File

@@ -49,7 +49,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService
Height = height Height = height
}; };
Encoding.ASCII.GetBytes(name).AsSpan().CopyTo(displayInfo.Name.ToSpan()); Encoding.ASCII.GetBytes(name).AsSpan().CopyTo(displayInfo.Name.AsSpan());
_displayInfo.Add(displayInfo); _displayInfo.Add(displayInfo);
} }
@@ -171,7 +171,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi.RootService
return ResultCode.InvalidValue; return ResultCode.InvalidValue;
} }
int displayId = _displayInfo.FindIndex(display => Encoding.ASCII.GetString(display.Name.ToSpan()).Trim('\0') == name); int displayId = _displayInfo.FindIndex(display => Encoding.ASCII.GetString(display.Name.AsSpan()).Trim('\0') == name);
if (displayId == -1) if (displayId == -1)
{ {

View File

@@ -171,6 +171,35 @@ namespace Ryujinx.Tests.Cpu
private static readonly bool NoInfs = false; private static readonly bool NoInfs = false;
private static readonly bool NoNaNs = false; private static readonly bool NoNaNs = false;
[Test, Pairwise, Description("SHA256SU0.32 <Qd>, <Qm>")]
public void Sha256su0_V([Values(0xF3BA03C0u)] uint opcode,
[Values(0u)] uint rd,
[Values(2u)] uint rm,
[Values(0x9BCBBF7443FB4F91ul)] ulong z0,
[Values(0x482C58A58CBCBD59ul)] ulong z1,
[Values(0xA0099B803625F82Aul)] ulong a0,
[Values(0x1AA3B0B4E1AB4C8Cul)] ulong a1,
[Values(0x29A44D72598F15F3ul)] ulong resultL,
[Values(0x74CED221E2793F07ul)] ulong resultH)
{
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
V128 v0 = MakeVectorE0E1(z0, z1);
V128 v1 = MakeVectorE0E1(a0, a1);
ExecutionContext context = SingleOpcode(opcode, v0: v0, v1: v1, runUnicorn: false);
Assert.Multiple(() =>
{
Assert.That(GetVectorE0(context.GetV(0)), Is.EqualTo(resultL));
Assert.That(GetVectorE1(context.GetV(0)), Is.EqualTo(resultH));
});
// Unicorn does not yet support hash instructions in A32.
// CompareAgainstUnicorn();
}
[Test, Pairwise] [Test, Pairwise]
public void Vabs_Vneg_V_S8_S16_S32([ValueSource("_Vabs_Vneg_V_")] uint opcode, public void Vabs_Vneg_V_S8_S16_S32([ValueSource("_Vabs_Vneg_V_")] uint opcode,
[Range(0u, 3u)] uint rd, [Range(0u, 3u)] uint rd,

View File

@@ -247,6 +247,108 @@ namespace Ryujinx.Tests.Cpu
private static readonly bool NoInfs = false; private static readonly bool NoInfs = false;
private static readonly bool NoNaNs = false; private static readonly bool NoNaNs = false;
[Test, Pairwise, Description("SHA256H.32 <Qd>, <Qn>, <Qm>")]
public void Sha256h_V([Values(0xF3000C40u)] uint opcode,
[Values(0u)] uint rd,
[Values(2u)] uint rn,
[Values(4u)] uint rm,
[Values(0xAEE65C11943FB939ul)] ulong z0,
[Values(0xA89A87F110291DA3ul)] ulong z1,
[Values(0xE9F766DB7A49EA7Dul)] ulong a0,
[Values(0x3053F46B0C2F3507ul)] ulong a1,
[Values(0x6E86A473B9D4A778ul)] ulong b0,
[Values(0x7BE4F9E638156BB1ul)] ulong b1,
[Values(0x1F1DC4A98DA9C132ul)] ulong resultL,
[Values(0xDB9A2A7B47031A0Dul)] ulong resultH)
{
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3);
opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
V128 v0 = MakeVectorE0E1(z0, z1);
V128 v1 = MakeVectorE0E1(a0, a1);
V128 v2 = MakeVectorE0E1(b0, b1);
ExecutionContext context = SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, runUnicorn: false);
Assert.Multiple(() =>
{
Assert.That(GetVectorE0(context.GetV(0)), Is.EqualTo(resultL));
Assert.That(GetVectorE1(context.GetV(0)), Is.EqualTo(resultH));
});
// Unicorn does not yet support hash instructions in A32.
// CompareAgainstUnicorn();
}
[Test, Pairwise, Description("SHA256H2.32 <Qd>, <Qn>, <Qm>")]
public void Sha256h2_V([Values(0xF3100C40u)] uint opcode,
[Values(0u)] uint rd,
[Values(2u)] uint rn,
[Values(4u)] uint rm,
[Values(0xAEE65C11943FB939ul)] ulong z0,
[Values(0xA89A87F110291DA3ul)] ulong z1,
[Values(0xE9F766DB7A49EA7Dul)] ulong a0,
[Values(0x3053F46B0C2F3507ul)] ulong a1,
[Values(0x6E86A473B9D4A778ul)] ulong b0,
[Values(0x7BE4F9E638156BB1ul)] ulong b1,
[Values(0x0A1177E9D9C9B611ul)] ulong resultL,
[Values(0xF5A826404928A515ul)] ulong resultH)
{
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3);
opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
V128 v0 = MakeVectorE0E1(z0, z1);
V128 v1 = MakeVectorE0E1(a0, a1);
V128 v2 = MakeVectorE0E1(b0, b1);
ExecutionContext context = SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, runUnicorn: false);
Assert.Multiple(() =>
{
Assert.That(GetVectorE0(context.GetV(0)), Is.EqualTo(resultL));
Assert.That(GetVectorE1(context.GetV(0)), Is.EqualTo(resultH));
});
// Unicorn does not yet support hash instructions in A32.
// CompareAgainstUnicorn();
}
[Test, Pairwise, Description("SHA256SU1.32 <Qd>, <Qn>, <Qm>")]
public void Sha256su1_V([Values(0xF3200C40u)] uint opcode,
[Values(0u)] uint rd,
[Values(2u)] uint rn,
[Values(4u)] uint rm,
[Values(0xAEE65C11943FB939ul)] ulong z0,
[Values(0xA89A87F110291DA3ul)] ulong z1,
[Values(0xE9F766DB7A49EA7Dul)] ulong a0,
[Values(0x3053F46B0C2F3507ul)] ulong a1,
[Values(0x6E86A473B9D4A778ul)] ulong b0,
[Values(0x7BE4F9E638156BB1ul)] ulong b1,
[Values(0x9EE69CC896D7DE66ul)] ulong resultL,
[Values(0x004A147155573E54ul)] ulong resultH)
{
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
opcode |= ((rn & 0xf) << 16) | ((rn & 0x10) << 3);
opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
V128 v0 = MakeVectorE0E1(z0, z1);
V128 v1 = MakeVectorE0E1(a0, a1);
V128 v2 = MakeVectorE0E1(b0, b1);
ExecutionContext context = SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, runUnicorn: false);
Assert.Multiple(() =>
{
Assert.That(GetVectorE0(context.GetV(0)), Is.EqualTo(resultL));
Assert.That(GetVectorE1(context.GetV(0)), Is.EqualTo(resultH));
});
// Unicorn does not yet support hash instructions in A32.
// CompareAgainstUnicorn();
}
[Explicit] [Explicit]
[Test, Pairwise, Description("VADD.f32 V0, V0, V0")] [Test, Pairwise, Description("VADD.f32 V0, V0, V0")]
public void Vadd_f32([Values(0u)] uint rd, public void Vadd_f32([Values(0u)] uint rd,

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