From a77af4c5e9e74ada62bfdb7ef5672eeebb00c3ab Mon Sep 17 00:00:00 2001
From: TSRBerry <20988865+TSRBerry@users.noreply.github.com>
Date: Mon, 19 Sep 2022 14:06:00 +0200
Subject: [PATCH 1/8] Readme: Fix broken shell image (#3708)
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 83f56f66a..9a8581e06 100644
--- a/README.md
+++ b/README.md
@@ -27,7 +27,7 @@
-
+
From b9f1ff3c7748c6a2665e76d17e86c3b7228f44fe Mon Sep 17 00:00:00 2001
From: LDj3SNuD <35856442+LDj3SNuD@users.noreply.github.com>
Date: Mon, 19 Sep 2022 19:49:10 +0200
Subject: [PATCH 2/8] Implemented in IR the managed methods of the ShlReg
region of the SoftFallback class. (#3700)
* Implemented in IR the managed methods of the Saturating region ...
... of the SoftFallback class (the SatQ ones).
The need to natively manage the Fpcr and Fpsr system registers is still a fact.
Contributes to https://github.com/Ryujinx/Ryujinx/issues/2917 ; I will open another PR to implement in Intrinsics-branchless the methods of the Saturation region as well (the SatXXXToXXX ones).
All instructions involved have been tested locally in both release and debug modes, in both lowcq and highcq.
* Ptc.InternalVersion = 3665
* Addressed PR feedback.
* Implemented in IR the managed methods of the ShlReg region of the SoftFallback class.
It also includes the last two SatQ ones (following up on https://github.com/Ryujinx/Ryujinx/pull/3665).
All instructions involved have been tested locally in both release and debug modes, in both lowcq and highcq.
* Update InstEmitSimdHelper.cs
---
.../Instructions/InstEmitSimdHelper.cs | 156 +++++--
ARMeilleure/Instructions/InstEmitSimdShift.cs | 386 +++++++++++-------
ARMeilleure/Instructions/SoftFallback.cs | 330 ---------------
ARMeilleure/Translation/Delegates.cs | 4 -
ARMeilleure/Translation/PTC/Ptc.cs | 2 +-
5 files changed, 351 insertions(+), 527 deletions(-)
diff --git a/ARMeilleure/Instructions/InstEmitSimdHelper.cs b/ARMeilleure/Instructions/InstEmitSimdHelper.cs
index 27b5c1302..80dfc6889 100644
--- a/ARMeilleure/Instructions/InstEmitSimdHelper.cs
+++ b/ARMeilleure/Instructions/InstEmitSimdHelper.cs
@@ -1533,29 +1533,88 @@ namespace ARMeilleure.Instructions
context.Copy(d, res);
}
- // TSrc (16bit, 32bit, 64bit; signed) > TDst (8bit, 16bit, 32bit; signed, unsigned).
- // long SignedSrcSignedDstSatQ(long op, int size); ulong SignedSrcUnsignedDstSatQ(long op, int size);
- public static Operand EmitSignedSrcSatQ(ArmEmitterContext context, Operand op, int sizeDst, bool signedDst)
+ // long SignedSignSatQ(long op, int size);
+ public static Operand EmitSignedSignSatQ(ArmEmitterContext context, Operand op, int size)
{
- Debug.Assert(op.Type == OperandType.I64 && (uint)sizeDst <= 2u);
+ int eSize = 8 << size;
+
+ Debug.Assert(op.Type == OperandType.I64);
+ Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
Operand lbl1 = Label();
Operand lblEnd = Label();
- int eSize = 8 << sizeDst;
+ Operand zeroL = Const(0L);
+ Operand maxT = Const((1L << (eSize - 1)) - 1L);
+ Operand minT = Const(-(1L << (eSize - 1)));
- Operand maxT = signedDst ? Const((1L << (eSize - 1)) - 1L) : Const((1UL << eSize) - 1UL);
- Operand minT = signedDst ? Const(-(1L << (eSize - 1))) : Const(0UL);
+ Operand res = context.Copy(context.AllocateLocal(OperandType.I64), zeroL);
- Operand res = context.Copy(context.AllocateLocal(OperandType.I64), op);
-
- context.BranchIf(lbl1, res, maxT, Comparison.LessOrEqual);
+ context.BranchIf(lbl1, op, zeroL, Comparison.LessOrEqual);
context.Copy(res, maxT);
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
context.Branch(lblEnd);
context.MarkLabel(lbl1);
- context.BranchIf(lblEnd, res, minT, Comparison.GreaterOrEqual);
+ context.BranchIf(lblEnd, op, zeroL, Comparison.GreaterOrEqual);
+ context.Copy(res, minT);
+ context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
+ context.Branch(lblEnd);
+
+ context.MarkLabel(lblEnd);
+
+ return res;
+ }
+
+ // private static ulong UnsignedSignSatQ(ulong op, int size);
+ public static Operand EmitUnsignedSignSatQ(ArmEmitterContext context, Operand op, int size)
+ {
+ int eSize = 8 << size;
+
+ Debug.Assert(op.Type == OperandType.I64);
+ Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
+
+ Operand lblEnd = Label();
+
+ Operand zeroUL = Const(0UL);
+ Operand maxT = Const(ulong.MaxValue >> (64 - eSize));
+
+ Operand res = context.Copy(context.AllocateLocal(OperandType.I64), zeroUL);
+
+ context.BranchIf(lblEnd, op, zeroUL, Comparison.LessOrEqualUI);
+ context.Copy(res, maxT);
+ context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
+ context.Branch(lblEnd);
+
+ context.MarkLabel(lblEnd);
+
+ return res;
+ }
+
+ // TSrc (16bit, 32bit, 64bit; signed) > TDst (8bit, 16bit, 32bit; signed, unsigned).
+ // long SignedSrcSignedDstSatQ(long op, int size); ulong SignedSrcUnsignedDstSatQ(long op, int size);
+ public static Operand EmitSignedSrcSatQ(ArmEmitterContext context, Operand op, int sizeDst, bool signedDst)
+ {
+ int eSizeDst = 8 << sizeDst;
+
+ Debug.Assert(op.Type == OperandType.I64);
+ Debug.Assert(eSizeDst == 8 || eSizeDst == 16 || eSizeDst == 32);
+
+ Operand lbl1 = Label();
+ Operand lblEnd = Label();
+
+ Operand maxT = signedDst ? Const((1L << (eSizeDst - 1)) - 1L) : Const((1UL << eSizeDst) - 1UL);
+ Operand minT = signedDst ? Const(-(1L << (eSizeDst - 1))) : Const(0UL);
+
+ Operand res = context.Copy(context.AllocateLocal(OperandType.I64), op);
+
+ context.BranchIf(lbl1, op, maxT, Comparison.LessOrEqual);
+ context.Copy(res, maxT);
+ context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
+ context.Branch(lblEnd);
+
+ context.MarkLabel(lbl1);
+ context.BranchIf(lblEnd, op, minT, Comparison.GreaterOrEqual);
context.Copy(res, minT);
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
context.Branch(lblEnd);
@@ -1569,18 +1628,19 @@ namespace ARMeilleure.Instructions
// long UnsignedSrcSignedDstSatQ(ulong op, int size); ulong UnsignedSrcUnsignedDstSatQ(ulong op, int size);
public static Operand EmitUnsignedSrcSatQ(ArmEmitterContext context, Operand op, int sizeDst, bool signedDst)
{
- Debug.Assert(op.Type == OperandType.I64 && (uint)sizeDst <= 2u);
+ int eSizeDst = 8 << sizeDst;
+
+ Debug.Assert(op.Type == OperandType.I64);
+ Debug.Assert(eSizeDst == 8 || eSizeDst == 16 || eSizeDst == 32);
Operand lblEnd = Label();
- int eSize = 8 << sizeDst;
-
- Operand maxL = signedDst ? Const((1L << (eSize - 1)) - 1L) : Const((1UL << eSize) - 1UL);
+ Operand maxT = signedDst ? Const((1L << (eSizeDst - 1)) - 1L) : Const((1UL << eSizeDst) - 1UL);
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), op);
- context.BranchIf(lblEnd, res, maxL, Comparison.LessOrEqualUI);
- context.Copy(res, maxL);
+ context.BranchIf(lblEnd, op, maxT, Comparison.LessOrEqualUI);
+ context.Copy(res, maxT);
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
context.Branch(lblEnd);
@@ -1601,7 +1661,7 @@ namespace ARMeilleure.Instructions
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), op);
- context.BranchIf(lblEnd, res, minL, Comparison.NotEqual);
+ context.BranchIf(lblEnd, op, minL, Comparison.NotEqual);
context.Copy(res, maxL);
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
context.Branch(lblEnd);
@@ -1620,15 +1680,16 @@ namespace ARMeilleure.Instructions
Operand minL = Const(long.MinValue);
Operand maxL = Const(long.MaxValue);
- Operand zero = Const(0L);
+ Operand zeroL = Const(0L);
- Operand res = context.Copy(context.AllocateLocal(OperandType.I64), context.Add(op1, op2));
+ Operand add = context.Add(op1, op2);
+ Operand res = context.Copy(context.AllocateLocal(OperandType.I64), add);
Operand left = context.BitwiseNot(context.BitwiseExclusiveOr(op1, op2));
- Operand right = context.BitwiseExclusiveOr(op1, res);
- context.BranchIf(lblEnd, context.BitwiseAnd(left, right), zero, Comparison.GreaterOrEqual);
+ Operand right = context.BitwiseExclusiveOr(op1, add);
+ context.BranchIf(lblEnd, context.BitwiseAnd(left, right), zeroL, Comparison.GreaterOrEqual);
- Operand isPositive = context.ICompareGreaterOrEqual(op1, zero);
+ Operand isPositive = context.ICompareGreaterOrEqual(op1, zeroL);
context.Copy(res, context.ConditionalSelect(isPositive, maxL, minL));
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
context.Branch(lblEnd);
@@ -1647,9 +1708,10 @@ namespace ARMeilleure.Instructions
Operand maxUL = Const(ulong.MaxValue);
- Operand res = context.Copy(context.AllocateLocal(OperandType.I64), context.Add(op1, op2));
+ Operand add = context.Add(op1, op2);
+ Operand res = context.Copy(context.AllocateLocal(OperandType.I64), add);
- context.BranchIf(lblEnd, res, op1, Comparison.GreaterOrEqualUI);
+ context.BranchIf(lblEnd, add, op1, Comparison.GreaterOrEqualUI);
context.Copy(res, maxUL);
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
context.Branch(lblEnd);
@@ -1668,15 +1730,16 @@ namespace ARMeilleure.Instructions
Operand minL = Const(long.MinValue);
Operand maxL = Const(long.MaxValue);
- Operand zero = Const(0L);
+ Operand zeroL = Const(0L);
- Operand res = context.Copy(context.AllocateLocal(OperandType.I64), context.Subtract(op1, op2));
+ Operand sub = context.Subtract(op1, op2);
+ Operand res = context.Copy(context.AllocateLocal(OperandType.I64), sub);
Operand left = context.BitwiseExclusiveOr(op1, op2);
- Operand right = context.BitwiseExclusiveOr(op1, res);
- context.BranchIf(lblEnd, context.BitwiseAnd(left, right), zero, Comparison.GreaterOrEqual);
+ Operand right = context.BitwiseExclusiveOr(op1, sub);
+ context.BranchIf(lblEnd, context.BitwiseAnd(left, right), zeroL, Comparison.GreaterOrEqual);
- Operand isPositive = context.ICompareGreaterOrEqual(op1, zero);
+ Operand isPositive = context.ICompareGreaterOrEqual(op1, zeroL);
context.Copy(res, context.ConditionalSelect(isPositive, maxL, minL));
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
context.Branch(lblEnd);
@@ -1693,12 +1756,13 @@ namespace ARMeilleure.Instructions
Operand lblEnd = Label();
- Operand zero = Const(0L);
+ Operand zeroL = Const(0L);
- Operand res = context.Copy(context.AllocateLocal(OperandType.I64), context.Subtract(op1, op2));
+ Operand sub = context.Subtract(op1, op2);
+ Operand res = context.Copy(context.AllocateLocal(OperandType.I64), sub);
context.BranchIf(lblEnd, op1, op2, Comparison.GreaterOrEqualUI);
- context.Copy(res, zero);
+ context.Copy(res, zeroL);
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
context.Branch(lblEnd);
@@ -1717,25 +1781,26 @@ namespace ARMeilleure.Instructions
Operand lblEnd = Label();
Operand maxL = Const(long.MaxValue);
- Operand zero = Const(0L);
+ Operand zeroL = Const(0L);
- Operand res = context.Copy(context.AllocateLocal(OperandType.I64), context.Add(op1, op2));
+ Operand add = context.Add(op1, op2);
+ Operand res = context.Copy(context.AllocateLocal(OperandType.I64), add);
context.BranchIf(lbl1, op1, maxL, Comparison.GreaterUI);
- Operand notOp2AndRes = context.BitwiseAnd(context.BitwiseNot(op2), res);
- context.BranchIf(lblEnd, notOp2AndRes, zero, Comparison.GreaterOrEqual);
+ Operand notOp2AndRes = context.BitwiseAnd(context.BitwiseNot(op2), add);
+ context.BranchIf(lblEnd, notOp2AndRes, zeroL, Comparison.GreaterOrEqual);
context.Copy(res, maxL);
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
context.Branch(lblEnd);
context.MarkLabel(lbl1);
- context.BranchIf(lbl2, op2, zero, Comparison.Less);
+ context.BranchIf(lbl2, op2, zeroL, Comparison.Less);
context.Copy(res, maxL);
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
context.Branch(lblEnd);
context.MarkLabel(lbl2);
- context.BranchIf(lblEnd, res, maxL, Comparison.LessOrEqualUI);
+ context.BranchIf(lblEnd, add, maxL, Comparison.LessOrEqualUI);
context.Copy(res, maxL);
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
context.Branch(lblEnd);
@@ -1755,20 +1820,21 @@ namespace ARMeilleure.Instructions
Operand maxUL = Const(ulong.MaxValue);
Operand maxL = Const(long.MaxValue);
- Operand zero = Const(0L);
+ Operand zeroL = Const(0L);
- Operand res = context.Copy(context.AllocateLocal(OperandType.I64), context.Add(op1, op2));
+ Operand add = context.Add(op1, op2);
+ Operand res = context.Copy(context.AllocateLocal(OperandType.I64), add);
- context.BranchIf(lbl1, op1, zero, Comparison.Less);
- context.BranchIf(lblEnd, res, op1, Comparison.GreaterOrEqualUI);
+ context.BranchIf(lbl1, op1, zeroL, Comparison.Less);
+ context.BranchIf(lblEnd, add, op1, Comparison.GreaterOrEqualUI);
context.Copy(res, maxUL);
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
context.Branch(lblEnd);
context.MarkLabel(lbl1);
context.BranchIf(lblEnd, op2, maxL, Comparison.GreaterUI);
- context.BranchIf(lblEnd, res, zero, Comparison.GreaterOrEqual);
- context.Copy(res, zero);
+ context.BranchIf(lblEnd, add, zeroL, Comparison.GreaterOrEqual);
+ context.Copy(res, zeroL);
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
context.Branch(lblEnd);
diff --git a/ARMeilleure/Instructions/InstEmitSimdShift.cs b/ARMeilleure/Instructions/InstEmitSimdShift.cs
index 1a95200db..146aeafa7 100644
--- a/ARMeilleure/Instructions/InstEmitSimdShift.cs
+++ b/ARMeilleure/Instructions/InstEmitSimdShift.cs
@@ -188,23 +188,7 @@ namespace ARMeilleure.Instructions
public static void Sqrshl_V(ArmEmitterContext context)
{
- OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
-
- Operand res = context.VectorZero();
-
- int elems = op.GetBytesCount() >> op.Size;
-
- for (int index = 0; index < elems; index++)
- {
- Operand ne = EmitVectorExtractSx(context, op.Rn, index, op.Size);
- Operand me = EmitVectorExtractSx(context, op.Rm, index, op.Size);
-
- Operand e = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShlRegSatQ)), ne, me, Const(1), Const(op.Size));
-
- res = EmitVectorInsert(context, res, e, index, op.Size);
- }
-
- context.Copy(GetVec(op.Rd), res);
+ EmitShlRegOp(context, ShlRegFlags.Signed | ShlRegFlags.Round | ShlRegFlags.Saturating);
}
public static void Sqrshrn_S(ArmEmitterContext context)
@@ -229,23 +213,7 @@ namespace ARMeilleure.Instructions
public static void Sqshl_V(ArmEmitterContext context)
{
- OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
-
- Operand res = context.VectorZero();
-
- int elems = op.GetBytesCount() >> op.Size;
-
- for (int index = 0; index < elems; index++)
- {
- Operand ne = EmitVectorExtractSx(context, op.Rn, index, op.Size);
- Operand me = EmitVectorExtractSx(context, op.Rm, index, op.Size);
-
- Operand e = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShlRegSatQ)), ne, me, Const(0), Const(op.Size));
-
- res = EmitVectorInsert(context, res, e, index, op.Size);
- }
-
- context.Copy(GetVec(op.Rd), res);
+ EmitShlRegOp(context, ShlRegFlags.Signed | ShlRegFlags.Saturating);
}
public static void Sqshrn_S(ArmEmitterContext context)
@@ -280,23 +248,7 @@ namespace ARMeilleure.Instructions
public static void Srshl_V(ArmEmitterContext context)
{
- OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
-
- Operand res = context.VectorZero();
-
- int elems = op.GetBytesCount() >> op.Size;
-
- for (int index = 0; index < elems; index++)
- {
- Operand ne = EmitVectorExtractSx(context, op.Rn, index, op.Size);
- Operand me = EmitVectorExtractSx(context, op.Rm, index, op.Size);
-
- Operand e = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShlReg)), ne, me, Const(1), Const(op.Size));
-
- res = EmitVectorInsert(context, res, e, index, op.Size);
- }
-
- context.Copy(GetVec(op.Rd), res);
+ EmitShlRegOp(context, ShlRegFlags.Signed | ShlRegFlags.Round);
}
public static void Srshr_S(ArmEmitterContext context)
@@ -393,12 +345,12 @@ namespace ARMeilleure.Instructions
public static void Sshl_S(ArmEmitterContext context)
{
- EmitSshlOrUshl(context, signed: true, scalar: true);
+ EmitShlRegOp(context, ShlRegFlags.Scalar | ShlRegFlags.Signed);
}
public static void Sshl_V(ArmEmitterContext context)
{
- EmitSshlOrUshl(context, signed: true, scalar: false);
+ EmitShlRegOp(context, ShlRegFlags.Signed);
}
public static void Sshll_V(ArmEmitterContext context)
@@ -506,23 +458,7 @@ namespace ARMeilleure.Instructions
public static void Uqrshl_V(ArmEmitterContext context)
{
- OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
-
- Operand res = context.VectorZero();
-
- int elems = op.GetBytesCount() >> op.Size;
-
- for (int index = 0; index < elems; index++)
- {
- Operand ne = EmitVectorExtractZx(context, op.Rn, index, op.Size);
- Operand me = EmitVectorExtractZx(context, op.Rm, index, op.Size);
-
- Operand e = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShlRegSatQ)), ne, me, Const(1), Const(op.Size));
-
- res = EmitVectorInsert(context, res, e, index, op.Size);
- }
-
- context.Copy(GetVec(op.Rd), res);
+ EmitShlRegOp(context, ShlRegFlags.Round | ShlRegFlags.Saturating);
}
public static void Uqrshrn_S(ArmEmitterContext context)
@@ -537,23 +473,7 @@ namespace ARMeilleure.Instructions
public static void Uqshl_V(ArmEmitterContext context)
{
- OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
-
- Operand res = context.VectorZero();
-
- int elems = op.GetBytesCount() >> op.Size;
-
- for (int index = 0; index < elems; index++)
- {
- Operand ne = EmitVectorExtractZx(context, op.Rn, index, op.Size);
- Operand me = EmitVectorExtractZx(context, op.Rm, index, op.Size);
-
- Operand e = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShlRegSatQ)), ne, me, Const(0), Const(op.Size));
-
- res = EmitVectorInsert(context, res, e, index, op.Size);
- }
-
- context.Copy(GetVec(op.Rd), res);
+ EmitShlRegOp(context, ShlRegFlags.Saturating);
}
public static void Uqshrn_S(ArmEmitterContext context)
@@ -568,23 +488,7 @@ namespace ARMeilleure.Instructions
public static void Urshl_V(ArmEmitterContext context)
{
- OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
-
- Operand res = context.VectorZero();
-
- int elems = op.GetBytesCount() >> op.Size;
-
- for (int index = 0; index < elems; index++)
- {
- Operand ne = EmitVectorExtractZx(context, op.Rn, index, op.Size);
- Operand me = EmitVectorExtractZx(context, op.Rm, index, op.Size);
-
- Operand e = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShlReg)), ne, me, Const(1), Const(op.Size));
-
- res = EmitVectorInsert(context, res, e, index, op.Size);
- }
-
- context.Copy(GetVec(op.Rd), res);
+ EmitShlRegOp(context, ShlRegFlags.Round);
}
public static void Urshr_S(ArmEmitterContext context)
@@ -677,12 +581,12 @@ namespace ARMeilleure.Instructions
public static void Ushl_S(ArmEmitterContext context)
{
- EmitSshlOrUshl(context, signed: false, scalar: true);
+ EmitShlRegOp(context, ShlRegFlags.Scalar);
}
public static void Ushl_V(ArmEmitterContext context)
{
- EmitSshlOrUshl(context, signed: false, scalar: false);
+ EmitShlRegOp(context, ShlRegFlags.None);
}
public static void Ushll_V(ArmEmitterContext context)
@@ -872,43 +776,6 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), res);
}
- private static Operand EmitShlRegOp(ArmEmitterContext context, Operand op, Operand shiftLsB, int size, bool signed)
- {
- Debug.Assert(op.Type == OperandType.I64);
- Debug.Assert(shiftLsB.Type == OperandType.I32);
- Debug.Assert((uint)size < 4u);
-
- Operand negShiftLsB = context.Negate(shiftLsB);
-
- Operand isInRange = context.BitwiseAnd(
- context.ICompareLess(shiftLsB, Const(8 << size)),
- context.ICompareLess(negShiftLsB, Const(8 << size)));
-
- Operand isPositive = context.ICompareGreaterOrEqual(shiftLsB, Const(0));
-
- Operand shl = context.ShiftLeft(op, shiftLsB);
-
- Operand sarOrShr = signed
- ? context.ShiftRightSI(op, negShiftLsB)
- : context.ShiftRightUI(op, negShiftLsB);
-
- Operand res = context.ConditionalSelect(isPositive, shl, sarOrShr);
-
- if (signed)
- {
- Operand isPositive2 = context.ICompareGreaterOrEqual(op, Const(0L));
-
- Operand res2 = context.ConditionalSelect(isPositive2, Const(0L), Const(-1L));
- res2 = context.ConditionalSelect(isPositive, Const(0L), res2);
-
- return context.ConditionalSelect(isInRange, res, res2);
- }
- else
- {
- return context.ConditionalSelect(isInRange, res, Const(0UL));
- }
- }
-
private static void EmitVectorShrImmNarrowOpZx(ArmEmitterContext context, bool round)
{
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
@@ -1168,8 +1035,23 @@ namespace ARMeilleure.Instructions
}
}
- private static void EmitSshlOrUshl(ArmEmitterContext context, bool signed, bool scalar)
+ [Flags]
+ private enum ShlRegFlags
{
+ None = 0,
+ Scalar = 1 << 0,
+ Signed = 1 << 1,
+ Round = 1 << 2,
+ Saturating = 1 << 3
+ }
+
+ private static void EmitShlRegOp(ArmEmitterContext context, ShlRegFlags flags = ShlRegFlags.None)
+ {
+ bool scalar = flags.HasFlag(ShlRegFlags.Scalar);
+ bool signed = flags.HasFlag(ShlRegFlags.Signed);
+ bool round = flags.HasFlag(ShlRegFlags.Round);
+ bool saturating = flags.HasFlag(ShlRegFlags.Saturating);
+
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
Operand res = context.VectorZero();
@@ -1178,15 +1060,225 @@ namespace ARMeilleure.Instructions
for (int index = 0; index < elems; index++)
{
- Operand ne = EmitVectorExtract (context, op.Rn, index, op.Size, signed);
- Operand me = EmitVectorExtractSx(context, op.Rm, index << op.Size, 0);
+ Operand ne = EmitVectorExtract(context, op.Rn, index, op.Size, signed);
+ Operand me = EmitVectorExtractSx(context, op.Rm, index << op.Size, size: 0);
- Operand e = EmitShlRegOp(context, ne, context.ConvertI64ToI32(me), op.Size, signed);
+ Operand e = !saturating
+ ? EmitShlReg(context, ne, context.ConvertI64ToI32(me), round, op.Size, signed)
+ : EmitShlRegSatQ(context, ne, context.ConvertI64ToI32(me), round, op.Size, signed);
res = EmitVectorInsert(context, res, e, index, op.Size);
}
context.Copy(GetVec(op.Rd), res);
}
+
+ // long SignedShlReg(long op, int shiftLsB, bool round, int size);
+ // ulong UnsignedShlReg(ulong op, int shiftLsB, bool round, int size);
+ private static Operand EmitShlReg(ArmEmitterContext context, Operand op, Operand shiftLsB, bool round, int size, bool signed)
+ {
+ int eSize = 8 << size;
+
+ Debug.Assert(op.Type == OperandType.I64);
+ Debug.Assert(shiftLsB.Type == OperandType.I32);
+ Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
+
+ Operand lbl1 = Label();
+ Operand lblEnd = Label();
+
+ Operand eSizeOp = Const(eSize);
+ Operand zero = Const(0);
+ Operand zeroL = Const(0L);
+
+ Operand res = context.Copy(context.AllocateLocal(OperandType.I64), op);
+
+ context.BranchIf(lbl1, shiftLsB, zero, Comparison.GreaterOrEqual);
+ context.Copy(res, signed
+ ? EmitSignedShrReg(context, op, context.Negate(shiftLsB), round, eSize)
+ : EmitUnsignedShrReg(context, op, context.Negate(shiftLsB), round, eSize));
+ context.Branch(lblEnd);
+
+ context.MarkLabel(lbl1);
+ context.BranchIf(lblEnd, shiftLsB, zero, Comparison.LessOrEqual);
+ Operand shl = context.ShiftLeft(op, shiftLsB);
+ Operand isGreaterOrEqual = context.ICompareGreaterOrEqual(shiftLsB, eSizeOp);
+ context.Copy(res, context.ConditionalSelect(isGreaterOrEqual, zeroL, shl));
+ context.Branch(lblEnd);
+
+ context.MarkLabel(lblEnd);
+
+ return res;
+ }
+
+ // long SignedShlRegSatQ(long op, int shiftLsB, bool round, int size);
+ // ulong UnsignedShlRegSatQ(ulong op, int shiftLsB, bool round, int size);
+ private static Operand EmitShlRegSatQ(ArmEmitterContext context, Operand op, Operand shiftLsB, bool round, int size, bool signed)
+ {
+ int eSize = 8 << size;
+
+ Debug.Assert(op.Type == OperandType.I64);
+ Debug.Assert(shiftLsB.Type == OperandType.I32);
+ Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
+
+ Operand lbl1 = Label();
+ Operand lbl2 = Label();
+ Operand lblEnd = Label();
+
+ Operand eSizeOp = Const(eSize);
+ Operand zero = Const(0);
+
+ Operand res = context.Copy(context.AllocateLocal(OperandType.I64), op);
+
+ context.BranchIf(lbl1, shiftLsB, zero, Comparison.GreaterOrEqual);
+ context.Copy(res, signed
+ ? EmitSignedShrReg(context, op, context.Negate(shiftLsB), round, eSize)
+ : EmitUnsignedShrReg(context, op, context.Negate(shiftLsB), round, eSize));
+ context.Branch(lblEnd);
+
+ context.MarkLabel(lbl1);
+ context.BranchIf(lblEnd, shiftLsB, zero, Comparison.LessOrEqual);
+ context.BranchIf(lbl2, shiftLsB, eSizeOp, Comparison.Less);
+ context.Copy(res, signed
+ ? EmitSignedSignSatQ(context, op, size)
+ : EmitUnsignedSignSatQ(context, op, size));
+ context.Branch(lblEnd);
+
+ context.MarkLabel(lbl2);
+ Operand shl = context.ShiftLeft(op, shiftLsB);
+ if (eSize == 64)
+ {
+ Operand sarOrShr = signed
+ ? context.ShiftRightSI(shl, shiftLsB)
+ : context.ShiftRightUI(shl, shiftLsB);
+ context.Copy(res, shl);
+ context.BranchIf(lblEnd, sarOrShr, op, Comparison.Equal);
+ context.Copy(res, signed
+ ? EmitSignedSignSatQ(context, op, size)
+ : EmitUnsignedSignSatQ(context, op, size));
+ }
+ else
+ {
+ context.Copy(res, signed
+ ? EmitSignedSrcSatQ(context, shl, size, signedDst: true)
+ : EmitUnsignedSrcSatQ(context, shl, size, signedDst: false));
+ }
+ context.Branch(lblEnd);
+
+ context.MarkLabel(lblEnd);
+
+ return res;
+ }
+
+ // shift := [1, 128]; eSize := {8, 16, 32, 64}.
+ // long SignedShrReg(long op, int shift, bool round, int eSize);
+ private static Operand EmitSignedShrReg(ArmEmitterContext context, Operand op, Operand shift, bool round, int eSize)
+ {
+ if (round)
+ {
+ Operand lblEnd = Label();
+
+ Operand eSizeOp = Const(eSize);
+ Operand zeroL = Const(0L);
+ Operand one = Const(1);
+ Operand oneL = Const(1L);
+
+ Operand res = context.Copy(context.AllocateLocal(OperandType.I64), zeroL);
+
+ context.BranchIf(lblEnd, shift, eSizeOp, Comparison.GreaterOrEqual);
+ Operand roundConst = context.ShiftLeft(oneL, context.Subtract(shift, one));
+ Operand add = context.Add(op, roundConst);
+ Operand sar = context.ShiftRightSI(add, shift);
+ if (eSize == 64)
+ {
+ Operand shr = context.ShiftRightUI(add, shift);
+ Operand left = context.BitwiseAnd(context.Negate(op), context.BitwiseExclusiveOr(op, add));
+ Operand isLess = context.ICompareLess(left, zeroL);
+ context.Copy(res, context.ConditionalSelect(isLess, shr, sar));
+ }
+ else
+ {
+ context.Copy(res, sar);
+ }
+ context.Branch(lblEnd);
+
+ context.MarkLabel(lblEnd);
+
+ return res;
+ }
+ else
+ {
+ Operand lblEnd = Label();
+
+ Operand eSizeOp = Const(eSize);
+ Operand zeroL = Const(0L);
+ Operand negOneL = Const(-1L);
+
+ Operand sar = context.ShiftRightSI(op, shift);
+ Operand res = context.Copy(context.AllocateLocal(OperandType.I64), sar);
+
+ context.BranchIf(lblEnd, shift, eSizeOp, Comparison.Less);
+ Operand isLess = context.ICompareLess(op, zeroL);
+ context.Copy(res, context.ConditionalSelect(isLess, negOneL, zeroL));
+ context.Branch(lblEnd);
+
+ context.MarkLabel(lblEnd);
+
+ return res;
+ }
+ }
+
+ // shift := [1, 128]; eSize := {8, 16, 32, 64}.
+ // ulong UnsignedShrReg(ulong op, int shift, bool round, int eSize);
+ private static Operand EmitUnsignedShrReg(ArmEmitterContext context, Operand op, Operand shift, bool round, int eSize)
+ {
+ if (round)
+ {
+ Operand lblEnd = Label();
+
+ Operand zeroUL = Const(0UL);
+ Operand one = Const(1);
+ Operand oneUL = Const(1UL);
+ Operand eSizeMaxOp = Const(64);
+ Operand oneShl63UL = Const(1UL << 63);
+
+ Operand res = context.Copy(context.AllocateLocal(OperandType.I64), zeroUL);
+
+ context.BranchIf(lblEnd, shift, eSizeMaxOp, Comparison.Greater);
+ Operand roundConst = context.ShiftLeft(oneUL, context.Subtract(shift, one));
+ Operand add = context.Add(op, roundConst);
+ Operand shr = context.ShiftRightUI(add, shift);
+ Operand isEqual = context.ICompareEqual(shift, eSizeMaxOp);
+ context.Copy(res, context.ConditionalSelect(isEqual, zeroUL, shr));
+ if (eSize == 64)
+ {
+ context.BranchIf(lblEnd, add, op, Comparison.GreaterOrEqualUI);
+ Operand right = context.BitwiseOr(shr, context.ShiftRightUI(oneShl63UL, context.Subtract(shift, one)));
+ context.Copy(res, context.ConditionalSelect(isEqual, oneUL, right));
+ }
+ context.Branch(lblEnd);
+
+ context.MarkLabel(lblEnd);
+
+ return res;
+ }
+ else
+ {
+ Operand lblEnd = Label();
+
+ Operand eSizeOp = Const(eSize);
+ Operand zeroUL = Const(0UL);
+
+ Operand shr = context.ShiftRightUI(op, shift);
+ Operand res = context.Copy(context.AllocateLocal(OperandType.I64), shr);
+
+ context.BranchIf(lblEnd, shift, eSizeOp, Comparison.Less);
+ context.Copy(res, zeroUL);
+ context.Branch(lblEnd);
+
+ context.MarkLabel(lblEnd);
+
+ return res;
+ }
+ }
}
}
diff --git a/ARMeilleure/Instructions/SoftFallback.cs b/ARMeilleure/Instructions/SoftFallback.cs
index 829dd37a3..d5e1ab65d 100644
--- a/ARMeilleure/Instructions/SoftFallback.cs
+++ b/ARMeilleure/Instructions/SoftFallback.cs
@@ -5,287 +5,6 @@ namespace ARMeilleure.Instructions
{
static class SoftFallback
{
-#region "ShlReg"
- public static long SignedShlReg(long value, long shift, bool round, int size)
- {
- int eSize = 8 << size;
-
- int shiftLsB = (sbyte)shift;
-
- if (shiftLsB < 0)
- {
- return SignedShrReg(value, -shiftLsB, round, eSize);
- }
- else if (shiftLsB > 0)
- {
- if (shiftLsB >= eSize)
- {
- return 0L;
- }
-
- return value << shiftLsB;
- }
- else /* if (shiftLsB == 0) */
- {
- return value;
- }
- }
-
- public static ulong UnsignedShlReg(ulong value, ulong shift, bool round, int size)
- {
- int eSize = 8 << size;
-
- int shiftLsB = (sbyte)shift;
-
- if (shiftLsB < 0)
- {
- return UnsignedShrReg(value, -shiftLsB, round, eSize);
- }
- else if (shiftLsB > 0)
- {
- if (shiftLsB >= eSize)
- {
- return 0UL;
- }
-
- return value << shiftLsB;
- }
- else /* if (shiftLsB == 0) */
- {
- return value;
- }
- }
-
- public static long SignedShlRegSatQ(long value, long shift, bool round, int size)
- {
- ExecutionContext context = NativeInterface.GetContext();
-
- int eSize = 8 << size;
-
- int shiftLsB = (sbyte)shift;
-
- if (shiftLsB < 0)
- {
- return SignedShrReg(value, -shiftLsB, round, eSize);
- }
- else if (shiftLsB > 0)
- {
- if (shiftLsB >= eSize)
- {
- return SignedSignSatQ(value, eSize, context);
- }
-
- if (eSize == 64)
- {
- long shl = value << shiftLsB;
- long shr = shl >> shiftLsB;
-
- if (shr != value)
- {
- return SignedSignSatQ(value, eSize, context);
- }
- else /* if (shr == value) */
- {
- return shl;
- }
- }
- else /* if (eSize != 64) */
- {
- return SignedSrcSignedDstSatQ(value << shiftLsB, size); // InstEmitSimdHelper.EmitSignedSrcSatQ(signedDst: true).
- }
- }
- else /* if (shiftLsB == 0) */
- {
- return value;
- }
- }
-
- public static ulong UnsignedShlRegSatQ(ulong value, ulong shift, bool round, int size)
- {
- ExecutionContext context = NativeInterface.GetContext();
-
- int eSize = 8 << size;
-
- int shiftLsB = (sbyte)shift;
-
- if (shiftLsB < 0)
- {
- return UnsignedShrReg(value, -shiftLsB, round, eSize);
- }
- else if (shiftLsB > 0)
- {
- if (shiftLsB >= eSize)
- {
- return UnsignedSignSatQ(value, eSize, context);
- }
-
- if (eSize == 64)
- {
- ulong shl = value << shiftLsB;
- ulong shr = shl >> shiftLsB;
-
- if (shr != value)
- {
- return UnsignedSignSatQ(value, eSize, context);
- }
- else /* if (shr == value) */
- {
- return shl;
- }
- }
- else /* if (eSize != 64) */
- {
- return UnsignedSrcUnsignedDstSatQ(value << shiftLsB, size); // InstEmitSimdHelper.EmitUnsignedSrcSatQ(signedDst: false).
- }
- }
- else /* if (shiftLsB == 0) */
- {
- return value;
- }
- }
-
- private static long SignedShrReg(long value, int shift, bool round, int eSize) // shift := [1, 128]; eSize := {8, 16, 32, 64}.
- {
- if (round)
- {
- if (shift >= eSize)
- {
- return 0L;
- }
-
- long roundConst = 1L << (shift - 1);
-
- long add = value + roundConst;
-
- if (eSize == 64)
- {
- if ((~value & (value ^ add)) < 0L)
- {
- return (long)((ulong)add >> shift);
- }
- else
- {
- return add >> shift;
- }
- }
- else /* if (eSize != 64) */
- {
- return add >> shift;
- }
- }
- else /* if (!round) */
- {
- if (shift >= eSize)
- {
- if (value < 0L)
- {
- return -1L;
- }
- else /* if (value >= 0L) */
- {
- return 0L;
- }
- }
-
- return value >> shift;
- }
- }
-
- private static ulong UnsignedShrReg(ulong value, int shift, bool round, int eSize) // shift := [1, 128]; eSize := {8, 16, 32, 64}.
- {
- if (round)
- {
- if (shift > 64)
- {
- return 0UL;
- }
-
- ulong roundConst = 1UL << (shift - 1);
-
- ulong add = value + roundConst;
-
- if (eSize == 64)
- {
- if ((add < value) && (add < roundConst))
- {
- if (shift == 64)
- {
- return 1UL;
- }
-
- return (add >> shift) | (0x8000000000000000UL >> (shift - 1));
- }
- else
- {
- if (shift == 64)
- {
- return 0UL;
- }
-
- return add >> shift;
- }
- }
- else /* if (eSize != 64) */
- {
- if (shift == 64)
- {
- return 0UL;
- }
-
- return add >> shift;
- }
- }
- else /* if (!round) */
- {
- if (shift >= eSize)
- {
- return 0UL;
- }
-
- return value >> shift;
- }
- }
-
- private static long SignedSignSatQ(long op, int eSize, ExecutionContext context) // eSize := {8, 16, 32, 64}.
- {
- long tMaxValue = (1L << (eSize - 1)) - 1L;
- long tMinValue = -(1L << (eSize - 1));
-
- if (op > 0L)
- {
- context.Fpsr |= FPSR.Qc;
-
- return tMaxValue;
- }
- else if (op < 0L)
- {
- context.Fpsr |= FPSR.Qc;
-
- return tMinValue;
- }
- else
- {
- return 0L;
- }
- }
-
- private static ulong UnsignedSignSatQ(ulong op, int eSize, ExecutionContext context) // eSize := {8, 16, 32, 64}.
- {
- ulong tMaxValue = ulong.MaxValue >> (64 - eSize);
-
- if (op > 0UL)
- {
- context.Fpsr |= FPSR.Qc;
-
- return tMaxValue;
- }
- else
- {
- return 0UL;
- }
- }
-#endregion
-
#region "ShrImm64"
public static long SignedShrImm64(long value, long roundConst, int shift)
{
@@ -508,55 +227,6 @@ namespace ARMeilleure.Instructions
}
#endregion
-#region "Saturating"
- private static long SignedSrcSignedDstSatQ(long op, int size)
- {
- ExecutionContext context = NativeInterface.GetContext();
-
- int eSize = 8 << size;
-
- long tMaxValue = (1L << (eSize - 1)) - 1L;
- long tMinValue = -(1L << (eSize - 1));
-
- if (op > tMaxValue)
- {
- context.Fpsr |= FPSR.Qc;
-
- return tMaxValue;
- }
- else if (op < tMinValue)
- {
- context.Fpsr |= FPSR.Qc;
-
- return tMinValue;
- }
- else
- {
- return op;
- }
- }
-
- private static ulong UnsignedSrcUnsignedDstSatQ(ulong op, int size)
- {
- ExecutionContext context = NativeInterface.GetContext();
-
- int eSize = 8 << size;
-
- ulong tMaxValue = (1UL << eSize) - 1UL;
-
- if (op > tMaxValue)
- {
- context.Fpsr |= FPSR.Qc;
-
- return tMaxValue;
- }
- else
- {
- return op;
- }
- }
-#endregion
-
#region "Count"
public static ulong CountLeadingSigns(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
{
diff --git a/ARMeilleure/Translation/Delegates.cs b/ARMeilleure/Translation/Delegates.cs
index b36472b83..0da69ebc3 100644
--- a/ARMeilleure/Translation/Delegates.cs
+++ b/ARMeilleure/Translation/Delegates.cs
@@ -179,8 +179,6 @@ namespace ARMeilleure.Translation
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha1SchedulePart2)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart1)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart2)));
- SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShlReg)));
- SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShlRegSatQ)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShrImm64)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl1)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl2)));
@@ -190,8 +188,6 @@ namespace ARMeilleure.Translation
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx2)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx3)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx4)));
- SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShlReg)));
- SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShlRegSatQ)));
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShrImm64)));
SetDelegateInfo(typeof(SoftFloat16_32).GetMethod(nameof(SoftFloat16_32.FPConvert)));
diff --git a/ARMeilleure/Translation/PTC/Ptc.cs b/ARMeilleure/Translation/PTC/Ptc.cs
index 71f69ef7c..01f089882 100644
--- a/ARMeilleure/Translation/PTC/Ptc.cs
+++ b/ARMeilleure/Translation/PTC/Ptc.cs
@@ -27,7 +27,7 @@ namespace ARMeilleure.Translation.PTC
private const string OuterHeaderMagicString = "PTCohd\0\0";
private const string InnerHeaderMagicString = "PTCihd\0\0";
- private const uint InternalVersion = 3695; //! To be incremented manually for each change to the ARMeilleure project.
+ private const uint InternalVersion = 3700; //! To be incremented manually for each change to the ARMeilleure project.
private const string ActualDir = "0";
private const string BackupDir = "1";
From 6f0395538b8e8af3bba7536b44780d57e51e8697 Mon Sep 17 00:00:00 2001
From: Emmanuel Hansen
Date: Mon, 19 Sep 2022 18:05:26 +0000
Subject: [PATCH 3/8] Avalonia - Use embedded window for avalonia (#3674)
* wip
* use embedded window
* fix race condition on opengl Windows
* fix glx issues on prime nvidia
* fix mouse support win32
* clean up
* addressed review
* addressed review
* fix warnings
* fix sotware keyboard dialog
* Update Ryujinx.Ava/Ui/Applet/SwkbdAppletDialog.axaml.cs
Co-authored-by: gdkchan
* remove double semi
Co-authored-by: gdkchan
---
Ryujinx.Ava/AppHost.cs | 92 ++--
Ryujinx.Ava/Input/AvaloniaMouseDriver.cs | 15 +-
Ryujinx.Ava/Program.cs | 50 +-
.../Ui/Applet/SwkbdAppletDialog.axaml.cs | 69 ++-
Ryujinx.Ava/Ui/Backend/BackendSurface.cs | 76 ---
Ryujinx.Ava/Ui/Backend/Interop.cs | 49 --
Ryujinx.Ava/Ui/Backend/SkiaGpuFactory.cs | 26 -
.../Ui/Backend/Vulkan/ResultExtensions.cs | 17 -
.../Backend/Vulkan/Skia/VulkanRenderTarget.cs | 201 --------
.../Ui/Backend/Vulkan/Skia/VulkanSkiaGpu.cs | 61 ---
.../Ui/Backend/Vulkan/Skia/VulkanSurface.cs | 53 --
.../Vulkan/Surfaces/IVulkanPlatformSurface.cs | 13 -
.../Surfaces/VulkanSurfaceRenderTarget.cs | 134 -----
.../Backend/Vulkan/VulkanCommandBufferPool.cs | 215 ---------
Ryujinx.Ava/Ui/Backend/Vulkan/VulkanDevice.cs | 63 ---
.../Ui/Backend/Vulkan/VulkanDisplay.cs | 456 ------------------
Ryujinx.Ava/Ui/Backend/Vulkan/VulkanImage.cs | 165 -------
.../Ui/Backend/Vulkan/VulkanInstance.cs | 135 ------
.../Ui/Backend/Vulkan/VulkanMemoryHelper.cs | 59 ---
.../Ui/Backend/Vulkan/VulkanOptions.cs | 44 --
.../Ui/Backend/Vulkan/VulkanPhysicalDevice.cs | 219 ---------
.../Backend/Vulkan/VulkanPlatformInterface.cs | 70 ---
Ryujinx.Ava/Ui/Backend/Vulkan/VulkanQueue.cs | 18 -
.../Ui/Backend/Vulkan/VulkanSemaphorePair.cs | 32 --
.../Ui/Backend/Vulkan/VulkanSurface.cs | 75 ---
.../Vulkan/VulkanSurfaceRenderingSession.cs | 43 --
.../Ui/Controls/ContentDialogHelper.cs | 78 ++-
Ryujinx.Ava/Ui/Controls/EmbeddedWindow.cs | 204 ++++++++
.../Ui/Controls/OpenGLEmbeddedWindow.cs | 85 ++++
.../Ui/Controls/OpenGLRendererControl.cs | 192 --------
Ryujinx.Ava/Ui/Controls/RendererControl.cs | 96 ----
Ryujinx.Ava/Ui/Controls/RendererHost.axaml | 14 +
Ryujinx.Ava/Ui/Controls/RendererHost.axaml.cs | 126 +++++
.../Ui/Controls/VulkanEmbeddedWindow.cs | 33 ++
.../Ui/Controls/VulkanRendererControl.cs | 220 ---------
Ryujinx.Ava/Ui/Controls/Win32NativeInterop.cs | 113 +++++
.../Ui/ViewModels/SettingsViewModel.cs | 64 +--
.../Windows/ContentDialogOverlayWindow.axaml | 27 ++
.../ContentDialogOverlayWindow.axaml.cs | 25 +
Ryujinx.Ava/Ui/Windows/MainWindow.axaml | 1 +
Ryujinx.Ava/Ui/Windows/MainWindow.axaml.cs | 25 +-
.../Ui/Windows/SettingsWindow.axaml.cs | 12 +-
Ryujinx.Graphics.GAL/IWindow.cs | 2 +-
.../Commands/Window/WindowPresentCommand.cs | 4 +-
.../Multithreading/ThreadedWindow.cs | 4 +-
Ryujinx.Graphics.Gpu/Window.cs | 2 +-
Ryujinx.Graphics.OpenGL/Window.cs | 61 +--
Ryujinx.Graphics.Vulkan/ImageWindow.cs | 429 ----------------
Ryujinx.Graphics.Vulkan/VulkanRenderer.cs | 66 +--
Ryujinx.Graphics.Vulkan/Window.cs | 2 +-
Ryujinx.Graphics.Vulkan/WindowBase.cs | 2 +-
Ryujinx.HLE/Switch.cs | 2 +-
Ryujinx.Headless.SDL2/OpenGL/OpenGLWindow.cs | 24 +-
Ryujinx.Headless.SDL2/Vulkan/VulkanWindow.cs | 2 +-
Ryujinx.Headless.SDL2/WindowBase.cs | 4 +-
Ryujinx/Ui/GLRenderer.cs | 24 +-
Ryujinx/Ui/RendererWidgetBase.cs | 4 +-
Ryujinx/Ui/VKRenderer.cs | 2 +-
58 files changed, 868 insertions(+), 3531 deletions(-)
delete mode 100644 Ryujinx.Ava/Ui/Backend/BackendSurface.cs
delete mode 100644 Ryujinx.Ava/Ui/Backend/Interop.cs
delete mode 100644 Ryujinx.Ava/Ui/Backend/SkiaGpuFactory.cs
delete mode 100644 Ryujinx.Ava/Ui/Backend/Vulkan/ResultExtensions.cs
delete mode 100644 Ryujinx.Ava/Ui/Backend/Vulkan/Skia/VulkanRenderTarget.cs
delete mode 100644 Ryujinx.Ava/Ui/Backend/Vulkan/Skia/VulkanSkiaGpu.cs
delete mode 100644 Ryujinx.Ava/Ui/Backend/Vulkan/Skia/VulkanSurface.cs
delete mode 100644 Ryujinx.Ava/Ui/Backend/Vulkan/Surfaces/IVulkanPlatformSurface.cs
delete mode 100644 Ryujinx.Ava/Ui/Backend/Vulkan/Surfaces/VulkanSurfaceRenderTarget.cs
delete mode 100644 Ryujinx.Ava/Ui/Backend/Vulkan/VulkanCommandBufferPool.cs
delete mode 100644 Ryujinx.Ava/Ui/Backend/Vulkan/VulkanDevice.cs
delete mode 100644 Ryujinx.Ava/Ui/Backend/Vulkan/VulkanDisplay.cs
delete mode 100644 Ryujinx.Ava/Ui/Backend/Vulkan/VulkanImage.cs
delete mode 100644 Ryujinx.Ava/Ui/Backend/Vulkan/VulkanInstance.cs
delete mode 100644 Ryujinx.Ava/Ui/Backend/Vulkan/VulkanMemoryHelper.cs
delete mode 100644 Ryujinx.Ava/Ui/Backend/Vulkan/VulkanOptions.cs
delete mode 100644 Ryujinx.Ava/Ui/Backend/Vulkan/VulkanPhysicalDevice.cs
delete mode 100644 Ryujinx.Ava/Ui/Backend/Vulkan/VulkanPlatformInterface.cs
delete mode 100644 Ryujinx.Ava/Ui/Backend/Vulkan/VulkanQueue.cs
delete mode 100644 Ryujinx.Ava/Ui/Backend/Vulkan/VulkanSemaphorePair.cs
delete mode 100644 Ryujinx.Ava/Ui/Backend/Vulkan/VulkanSurface.cs
delete mode 100644 Ryujinx.Ava/Ui/Backend/Vulkan/VulkanSurfaceRenderingSession.cs
create mode 100644 Ryujinx.Ava/Ui/Controls/EmbeddedWindow.cs
create mode 100644 Ryujinx.Ava/Ui/Controls/OpenGLEmbeddedWindow.cs
delete mode 100644 Ryujinx.Ava/Ui/Controls/OpenGLRendererControl.cs
delete mode 100644 Ryujinx.Ava/Ui/Controls/RendererControl.cs
create mode 100644 Ryujinx.Ava/Ui/Controls/RendererHost.axaml
create mode 100644 Ryujinx.Ava/Ui/Controls/RendererHost.axaml.cs
create mode 100644 Ryujinx.Ava/Ui/Controls/VulkanEmbeddedWindow.cs
delete mode 100644 Ryujinx.Ava/Ui/Controls/VulkanRendererControl.cs
create mode 100644 Ryujinx.Ava/Ui/Controls/Win32NativeInterop.cs
create mode 100644 Ryujinx.Ava/Ui/Windows/ContentDialogOverlayWindow.axaml
create mode 100644 Ryujinx.Ava/Ui/Windows/ContentDialogOverlayWindow.axaml.cs
delete mode 100644 Ryujinx.Graphics.Vulkan/ImageWindow.cs
diff --git a/Ryujinx.Ava/AppHost.cs b/Ryujinx.Ava/AppHost.cs
index 7e3cddc88..7cf5934a6 100644
--- a/Ryujinx.Ava/AppHost.cs
+++ b/Ryujinx.Ava/AppHost.cs
@@ -1,6 +1,5 @@
using ARMeilleure.Translation;
using ARMeilleure.Translation.PTC;
-using Avalonia;
using Avalonia.Input;
using Avalonia.Threading;
using LibHac.Tools.FsSystem;
@@ -12,10 +11,8 @@ using Ryujinx.Audio.Integration;
using Ryujinx.Ava.Common;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Input;
-using Ryujinx.Ava.Ui.Backend.Vulkan;
using Ryujinx.Ava.Ui.Controls;
using Ryujinx.Ava.Ui.Models;
-using Ryujinx.Ava.Ui.Vulkan;
using Ryujinx.Ava.Ui.Windows;
using Ryujinx.Common;
using Ryujinx.Common.Configuration;
@@ -39,6 +36,7 @@ using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
+using SPB.Graphics.Vulkan;
using System;
using System.Diagnostics;
using System.IO;
@@ -58,24 +56,24 @@ namespace Ryujinx.Ava
{
private const int CursorHideIdleTime = 8; // Hide Cursor seconds
private const float MaxResolutionScale = 4.0f; // Max resolution hotkeys can scale to before wrapping.
+ private const int TargetFps = 60;
- private static readonly Cursor InvisibleCursor = new Cursor(StandardCursorType.None);
+ private static readonly Cursor InvisibleCursor = new Cursor(StandardCursorType.None);
+ private readonly long _ticksPerFrame;
+ private readonly Stopwatch _chrono;
private readonly AccountManager _accountManager;
private readonly UserChannelPersistence _userChannelPersistence;
-
private readonly InputManager _inputManager;
-
- private readonly IKeyboard _keyboardInterface;
-
private readonly MainWindow _parent;
-
+ private readonly IKeyboard _keyboardInterface;
private readonly GraphicsDebugLevel _glLogLevel;
private bool _hideCursorOnIdle;
private bool _isStopped;
private bool _isActive;
private long _lastCursorMoveTime;
+ private long _ticks = 0;
private KeyboardHotkeyState _prevHotkeyState;
@@ -93,7 +91,7 @@ namespace Ryujinx.Ava
public event EventHandler AppExit;
public event EventHandler StatusUpdatedEvent;
- public RendererControl Renderer { get; }
+ public RendererHost Renderer { get; }
public VirtualFileSystem VirtualFileSystem { get; }
public ContentManager ContentManager { get; }
public Switch Device { get; set; }
@@ -111,7 +109,7 @@ namespace Ryujinx.Ava
private object _lockObject = new();
public AppHost(
- RendererControl renderer,
+ RendererHost renderer,
InputManager inputManager,
string applicationPath,
VirtualFileSystem virtualFileSystem,
@@ -128,7 +126,7 @@ namespace Ryujinx.Ava
_hideCursorOnIdle = ConfigurationState.Instance.HideCursorOnIdle;
_lastCursorMoveTime = Stopwatch.GetTimestamp();
_glLogLevel = ConfigurationState.Instance.Logger.GraphicsDebugLevel;
- _inputManager.SetMouseDriver(new AvaloniaMouseDriver(renderer));
+ _inputManager.SetMouseDriver(new AvaloniaMouseDriver(_parent, renderer));
_keyboardInterface = (IKeyboard)_inputManager.KeyboardDriver.GetGamepad("0");
NpadManager = _inputManager.CreateNpadManager();
@@ -138,6 +136,9 @@ namespace Ryujinx.Ava
VirtualFileSystem = virtualFileSystem;
ContentManager = contentManager;
+ _chrono = new Stopwatch();
+ _ticksPerFrame = Stopwatch.Frequency / TargetFps;
+
if (ApplicationPath.StartsWith("@SystemContent"))
{
ApplicationPath = _parent.VirtualFileSystem.SwitchPathToSystemPath(ApplicationPath);
@@ -177,7 +178,7 @@ namespace Ryujinx.Ava
if (_renderer != null)
{
double scale = _parent.PlatformImpl.RenderScaling;
- _renderer.Window.SetSize((int)(size.Width * scale), (int)(size.Height * scale));
+ _renderer.Window?.SetSize((int)(size.Width * scale), (int)(size.Height * scale));
}
}
@@ -335,8 +336,6 @@ namespace Ryujinx.Ava
return;
}
- AvaloniaLocator.Current.GetService()?.MainSurface.Display.ChangeVSyncMode(true);
-
_isStopped = true;
_isActive = false;
}
@@ -376,6 +375,8 @@ namespace Ryujinx.Ava
_gpuCancellationTokenSource.Cancel();
_gpuCancellationTokenSource.Dispose();
+
+ _chrono.Stop();
}
public void DisposeGpu()
@@ -389,8 +390,7 @@ namespace Ryujinx.Ava
Renderer?.MakeCurrent();
Device.DisposeGpu();
-
- Renderer?.DestroyBackgroundContext();
+
Renderer?.MakeCurrent(null);
}
@@ -596,16 +596,11 @@ namespace Ryujinx.Ava
IRenderer renderer;
- if (Program.UseVulkan)
+ if (Renderer.IsVulkan)
{
- var vulkan = AvaloniaLocator.Current.GetService();
+ string preferredGpu = ConfigurationState.Instance.Graphics.PreferredGpu.Value;
- renderer = new VulkanRenderer(vulkan.Instance.InternalHandle,
- vulkan.MainSurface.Device.InternalHandle,
- vulkan.PhysicalDevice.InternalHandle,
- vulkan.MainSurface.Device.Queue.InternalHandle,
- vulkan.PhysicalDevice.QueueFamilyIndex,
- vulkan.MainSurface.Device.Lock);
+ renderer = new VulkanRenderer(Renderer.CreateVulkanSurface, VulkanHelper.GetRequiredInstanceExtensions, preferredGpu);
}
else
{
@@ -778,11 +773,7 @@ namespace Ryujinx.Ava
{
Width = (int)e.Width;
Height = (int)e.Height;
-
- if (!Program.UseVulkan)
- {
- SetRendererWindowSize(e);
- }
+ SetRendererWindowSize(e);
}
private void MainLoop()
@@ -822,12 +813,10 @@ namespace Ryujinx.Ava
_renderer.ScreenCaptured += Renderer_ScreenCaptured;
- (_renderer as OpenGLRenderer)?.InitializeBackgroundContext(SPBOpenGLContext.CreateBackgroundContext((Renderer as OpenGLRendererControl).GameContext));
+ (_renderer as OpenGLRenderer)?.InitializeBackgroundContext(SPBOpenGLContext.CreateBackgroundContext(Renderer.GetContext()));
Renderer.MakeCurrent();
- AvaloniaLocator.Current.GetService()?.MainSurface?.Display?.ChangeVSyncMode(Device.EnableDeviceVsync);
-
Device.Gpu.Renderer.Initialize(_glLogLevel);
Width = (int)Renderer.Bounds.Width;
@@ -835,16 +824,20 @@ namespace Ryujinx.Ava
_renderer.Window.SetSize((int)(Width * _parent.PlatformImpl.RenderScaling), (int)(Height * _parent.PlatformImpl.RenderScaling));
+ _chrono.Start();
+
Device.Gpu.Renderer.RunLoop(() =>
{
Device.Gpu.SetGpuThread();
Device.Gpu.InitializeShaderCache(_gpuCancellationTokenSource.Token);
Translator.IsReadyForTranslation.Set();
- Renderer.Start();
-
while (_isActive)
{
+ _ticks += _chrono.ElapsedTicks;
+
+ _chrono.Restart();
+
if (Device.WaitFifo())
{
Device.Statistics.RecordFifoStart();
@@ -860,19 +853,20 @@ namespace Ryujinx.Ava
_parent.SwitchToGameControl();
}
- Device.PresentFrame(Present);
+ Device.PresentFrame(() => Renderer?.SwapBuffers());
+ }
+
+ if (_ticks >= _ticksPerFrame)
+ {
+ UpdateStatus();
}
}
-
- Renderer.Stop();
});
Renderer?.MakeCurrent(null);
-
- Renderer.SizeChanged -= Window_SizeChanged;
}
- private void Present(object image)
+ public void UpdateStatus()
{
// Run a status update only when a frame is to be drawn. This prevents from updating the ui and wasting a render when no frame is queued
string dockedMode = ConfigurationState.Instance.System.EnableDockedMode ? LocaleManager.Instance["Docked"] : LocaleManager.Instance["Handheld"];
@@ -886,24 +880,12 @@ namespace Ryujinx.Ava
StatusUpdatedEvent?.Invoke(this, new StatusUpdatedEventArgs(
Device.EnableDeviceVsync,
Device.GetVolume(),
- Program.UseVulkan ? "Vulkan" : "OpenGL",
+ Renderer.IsVulkan ? "Vulkan" : "OpenGL",
dockedMode,
ConfigurationState.Instance.Graphics.AspectRatio.Value.ToText(),
LocaleManager.Instance["Game"] + $": {Device.Statistics.GetGameFrameRate():00.00} FPS ({Device.Statistics.GetGameFrameTime():00.00} ms)",
$"FIFO: {Device.Statistics.GetFifoPercent():00.00} %",
$"GPU: {_renderer.GetHardwareInfo().GpuVendor}"));
-
- if (Program.UseVulkan)
- {
- var platformInterface = AvaloniaLocator.Current.GetService();
- if (platformInterface.MainSurface.Display.IsSurfaceChanged())
- {
- SetRendererWindowSize(new Size(Width, Height));
- return;
- }
- }
-
- Renderer.Present(image);
}
public async Task ShowExitPrompt()
@@ -985,8 +967,6 @@ namespace Ryujinx.Ava
case KeyboardHotkeyState.ToggleVSync:
Device.EnableDeviceVsync = !Device.EnableDeviceVsync;
- AvaloniaLocator.Current.GetService()?.MainSurface?.Display?.ChangeVSyncMode(Device.EnableDeviceVsync);
-
break;
case KeyboardHotkeyState.Screenshot:
ScreenshotRequested = true;
diff --git a/Ryujinx.Ava/Input/AvaloniaMouseDriver.cs b/Ryujinx.Ava/Input/AvaloniaMouseDriver.cs
index 74c435b5c..9ad0310a5 100644
--- a/Ryujinx.Ava/Input/AvaloniaMouseDriver.cs
+++ b/Ryujinx.Ava/Input/AvaloniaMouseDriver.cs
@@ -14,20 +14,27 @@ namespace Ryujinx.Ava.Input
private Control _widget;
private bool _isDisposed;
private Size _size;
+ private readonly Window _window;
public bool[] PressedButtons { get; }
public Vector2 CurrentPosition { get; private set; }
public Vector2 Scroll { get; private set; }
- public AvaloniaMouseDriver(Control parent)
+ public AvaloniaMouseDriver(Window window, Control parent)
{
_widget = parent;
+ _window = window;
_widget.PointerMoved += Parent_PointerMovedEvent;
_widget.PointerPressed += Parent_PointerPressEvent;
_widget.PointerReleased += Parent_PointerReleaseEvent;
_widget.PointerWheelChanged += Parent_ScrollEvent;
+
+ _window.PointerMoved += Parent_PointerMovedEvent;
+ _window.PointerPressed += Parent_PointerPressEvent;
+ _window.PointerReleased += Parent_PointerReleaseEvent;
+ _window.PointerWheelChanged += Parent_ScrollEvent;
PressedButtons = new bool[(int)MouseButton.Count];
@@ -47,7 +54,6 @@ namespace Ryujinx.Ava.Input
private void Parent_PointerReleaseEvent(object o, PointerReleasedEventArgs args)
{
- var pointerProperties = args.GetCurrentPoint(_widget).Properties;
PressedButtons[(int)args.InitialPressMouseButton - 1] = false;
}
@@ -125,6 +131,11 @@ namespace Ryujinx.Ava.Input
_widget.PointerReleased -= Parent_PointerReleaseEvent;
_widget.PointerWheelChanged -= Parent_ScrollEvent;
+ _window.PointerMoved -= Parent_PointerMovedEvent;
+ _window.PointerPressed -= Parent_PointerPressEvent;
+ _window.PointerReleased -= Parent_PointerReleaseEvent;
+ _window.PointerWheelChanged -= Parent_ScrollEvent;
+
_widget = null;
}
}
diff --git a/Ryujinx.Ava/Program.cs b/Ryujinx.Ava/Program.cs
index 242246ebe..61b184c61 100644
--- a/Ryujinx.Ava/Program.cs
+++ b/Ryujinx.Ava/Program.cs
@@ -1,9 +1,7 @@
using ARMeilleure.Translation.PTC;
using Avalonia;
-using Avalonia.OpenGL;
using Avalonia.Rendering;
using Avalonia.Threading;
-using Ryujinx.Ava.Ui.Backend;
using Ryujinx.Ava.Ui.Controls;
using Ryujinx.Ava.Ui.Windows;
using Ryujinx.Common;
@@ -12,12 +10,10 @@ using Ryujinx.Common.GraphicsDriver;
using Ryujinx.Common.Logging;
using Ryujinx.Common.System;
using Ryujinx.Common.SystemInfo;
-using Ryujinx.Graphics.Vulkan;
using Ryujinx.Modules;
using Ryujinx.Ui.Common;
using Ryujinx.Ui.Common.Configuration;
using System;
-using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
@@ -34,7 +30,6 @@ namespace Ryujinx.Ava
public static bool PreviewerDetached { get; private set; }
public static RenderTimer RenderTimer { get; private set; }
- public static bool UseVulkan { get; private set; }
[DllImport("user32.dll", SetLastError = true)]
public static extern int MessageBoxA(IntPtr hWnd, string text, string caption, uint type);
@@ -71,36 +66,16 @@ namespace Ryujinx.Ava
EnableMultiTouch = true,
EnableIme = true,
UseEGL = false,
- UseGpu = !UseVulkan,
- GlProfiles = new List()
- {
- new GlVersion(GlProfileType.OpenGL, 4, 3)
- }
+ UseGpu = false
})
.With(new Win32PlatformOptions
{
EnableMultitouch = true,
- UseWgl = !UseVulkan,
- WglProfiles = new List()
- {
- new GlVersion(GlProfileType.OpenGL, 4, 3)
- },
+ UseWgl = false,
AllowEglInitialization = false,
CompositionBackdropCornerRadius = 8f,
})
.UseSkia()
- .With(new Ui.Vulkan.VulkanOptions()
- {
- ApplicationName = "Ryujinx.Graphics.Vulkan",
- MaxQueueCount = 2,
- PreferDiscreteGpu = true,
- PreferredDevice = !PreviewerDetached ? "" : ConfigurationState.Instance.Graphics.PreferredGpu.Value,
- UseDebug = !PreviewerDetached ? false : ConfigurationState.Instance.Logger.GraphicsDebugLevel.Value != GraphicsDebugLevel.None,
- })
- .With(new SkiaOptions()
- {
- CustomGpuFactory = UseVulkan ? SkiaGpuFactory.CreateVulkanGpu : null
- })
.AfterSetup(_ =>
{
AvaloniaLocator.CurrentMutable
@@ -176,26 +151,7 @@ namespace Ryujinx.Ava
ReloadConfig();
- 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)
- {
- // 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,
- // as that uses avalonia's gpu backend and it's enabled there.
- ForceDpiAware.Windows();
- }
+ ForceDpiAware.Windows();
WindowScaleFactor = ForceDpiAware.GetWindowScaleFactor();
ActualScaleFactor = ForceDpiAware.GetActualScaleFactor() / BaseDpi;
diff --git a/Ryujinx.Ava/Ui/Applet/SwkbdAppletDialog.axaml.cs b/Ryujinx.Ava/Ui/Applet/SwkbdAppletDialog.axaml.cs
index 564ee4b29..e4ddba966 100644
--- a/Ryujinx.Ava/Ui/Applet/SwkbdAppletDialog.axaml.cs
+++ b/Ryujinx.Ava/Ui/Applet/SwkbdAppletDialog.axaml.cs
@@ -1,3 +1,4 @@
+using Avalonia;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
@@ -59,29 +60,63 @@ namespace Ryujinx.Ava.Ui.Controls
string input = string.Empty;
+ var overlay = new ContentDialogOverlayWindow()
+ {
+ Height = window.Bounds.Height,
+ Width = window.Bounds.Width,
+ Position = window.PointToScreen(new Point())
+ };
+
+ window.PositionChanged += OverlayOnPositionChanged;
+
+ void OverlayOnPositionChanged(object sender, PixelPointEventArgs e)
+ {
+ overlay.Position = window.PointToScreen(new Point());
+ }
+
+ contentDialog = overlay.ContentDialog;
+
+ bool opened = false;
+
content.SetInputLengthValidation(args.StringLengthMin, args.StringLengthMax);
- if (contentDialog != null)
+ content._host = contentDialog;
+ contentDialog.Title = title;
+ contentDialog.PrimaryButtonText = args.SubmitText;
+ contentDialog.IsPrimaryButtonEnabled = content._checkLength(content.Message.Length);
+ contentDialog.SecondaryButtonText = "";
+ contentDialog.CloseButtonText = LocaleManager.Instance["InputDialogCancel"];
+ contentDialog.Content = content;
+
+ TypedEventHandler handler = (sender, eventArgs) =>
{
- content._host = contentDialog;
- contentDialog.Title = title;
- contentDialog.PrimaryButtonText = args.SubmitText;
- contentDialog.IsPrimaryButtonEnabled = content._checkLength(content.Message.Length);
- contentDialog.SecondaryButtonText = "";
- contentDialog.CloseButtonText = LocaleManager.Instance["InputDialogCancel"];
- contentDialog.Content = content;
- TypedEventHandler handler = (sender, eventArgs) =>
+ if (eventArgs.Result == ContentDialogResult.Primary)
{
- if (eventArgs.Result == ContentDialogResult.Primary)
- {
- result = UserResult.Ok;
- input = content.Input.Text;
- }
- };
- contentDialog.Closed += handler;
+ result = UserResult.Ok;
+ input = content.Input.Text;
+ }
+ };
+ contentDialog.Closed += handler;
+
+ overlay.Opened += OverlayOnActivated;
+
+ async void OverlayOnActivated(object sender, EventArgs e)
+ {
+ if (opened)
+ {
+ return;
+ }
+
+ opened = true;
+
+ overlay.Position = window.PointToScreen(new Point());
+
await contentDialog.ShowAsync();
contentDialog.Closed -= handler;
- }
+ overlay.Close();
+ };
+
+ await overlay.ShowDialog(window);
return (result, input);
}
diff --git a/Ryujinx.Ava/Ui/Backend/BackendSurface.cs b/Ryujinx.Ava/Ui/Backend/BackendSurface.cs
deleted file mode 100644
index 423fe038e..000000000
--- a/Ryujinx.Ava/Ui/Backend/BackendSurface.cs
+++ /dev/null
@@ -1,76 +0,0 @@
-using Avalonia;
-using System;
-using System.Runtime.InteropServices;
-using static Ryujinx.Ava.Ui.Backend.Interop;
-
-namespace Ryujinx.Ava.Ui.Backend
-{
- public abstract class BackendSurface : IDisposable
- {
- protected IntPtr Display => _display;
-
- private IntPtr _display = IntPtr.Zero;
-
- [DllImport("libX11.so.6")]
- public static extern IntPtr XOpenDisplay(IntPtr display);
-
- [DllImport("libX11.so.6")]
- public static extern int XCloseDisplay(IntPtr display);
-
- private PixelSize _currentSize;
- public IntPtr Handle { get; protected set; }
-
- public bool IsDisposed { get; private set; }
-
- public BackendSurface(IntPtr handle)
- {
- Handle = handle;
-
- if (OperatingSystem.IsLinux())
- {
- _display = XOpenDisplay(IntPtr.Zero);
- }
- }
-
- public PixelSize Size
- {
- get
- {
- PixelSize size = new PixelSize();
- if (OperatingSystem.IsWindows())
- {
- GetClientRect(Handle, out var rect);
- size = new PixelSize(rect.right, rect.bottom);
- }
- else if (OperatingSystem.IsLinux())
- {
- XWindowAttributes attributes = new XWindowAttributes();
- XGetWindowAttributes(Display, Handle, ref attributes);
-
- size = new PixelSize(attributes.width, attributes.height);
- }
-
- _currentSize = size;
-
- return size;
- }
- }
-
- public PixelSize CurrentSize => _currentSize;
-
- public virtual void Dispose()
- {
- if (IsDisposed)
- {
- throw new ObjectDisposedException(nameof(BackendSurface));
- }
-
- IsDisposed = true;
-
- if (_display != IntPtr.Zero)
- {
- XCloseDisplay(_display);
- }
- }
- }
-}
\ No newline at end of file
diff --git a/Ryujinx.Ava/Ui/Backend/Interop.cs b/Ryujinx.Ava/Ui/Backend/Interop.cs
deleted file mode 100644
index 617e97678..000000000
--- a/Ryujinx.Ava/Ui/Backend/Interop.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-using FluentAvalonia.Interop;
-using System;
-using System.Runtime.InteropServices;
-
-namespace Ryujinx.Ava.Ui.Backend
-{
- public static class Interop
- {
- [StructLayout(LayoutKind.Sequential)]
- public struct XWindowAttributes
- {
- public int x;
- public int y;
- public int width;
- public int height;
- public int border_width;
- public int depth;
- public IntPtr visual;
- public IntPtr root;
- public int c_class;
- public int bit_gravity;
- public int win_gravity;
- public int backing_store;
- public IntPtr backing_planes;
- public IntPtr backing_pixel;
- public int save_under;
- public IntPtr colormap;
- public int map_installed;
- public int map_state;
- public IntPtr all_event_masks;
- public IntPtr your_event_mask;
- public IntPtr do_not_propagate_mask;
- public int override_direct;
- public IntPtr screen;
- }
-
- [DllImport("user32.dll")]
- public static extern bool GetClientRect(IntPtr hwnd, out RECT lpRect);
-
- [DllImport("libX11.so.6")]
- public static extern int XCloseDisplay(IntPtr display);
-
- [DllImport("libX11.so.6")]
- public static extern int XGetWindowAttributes(IntPtr display, IntPtr window, ref XWindowAttributes attributes);
-
- [DllImport("libX11.so.6")]
- public static extern IntPtr XOpenDisplay(IntPtr display);
- }
-}
diff --git a/Ryujinx.Ava/Ui/Backend/SkiaGpuFactory.cs b/Ryujinx.Ava/Ui/Backend/SkiaGpuFactory.cs
deleted file mode 100644
index 335bc905f..000000000
--- a/Ryujinx.Ava/Ui/Backend/SkiaGpuFactory.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-using Avalonia;
-using Avalonia.Skia;
-using Ryujinx.Ava.Ui.Vulkan;
-using Ryujinx.Ava.Ui.Backend.Vulkan;
-
-namespace Ryujinx.Ava.Ui.Backend
-{
- public static class SkiaGpuFactory
- {
- public static ISkiaGpu CreateVulkanGpu()
- {
- var skiaOptions = AvaloniaLocator.Current.GetService() ?? new SkiaOptions();
- var platformInterface = AvaloniaLocator.Current.GetService();
-
- if (platformInterface == null)
- {
- VulkanPlatformInterface.TryInitialize();
- }
-
- var gpu = new VulkanSkiaGpu(skiaOptions.MaxGpuResourceSizeBytes);
- AvaloniaLocator.CurrentMutable.Bind().ToConstant(gpu);
-
- return gpu;
- }
- }
-}
\ No newline at end of file
diff --git a/Ryujinx.Ava/Ui/Backend/Vulkan/ResultExtensions.cs b/Ryujinx.Ava/Ui/Backend/Vulkan/ResultExtensions.cs
deleted file mode 100644
index 2a1cd2293..000000000
--- a/Ryujinx.Ava/Ui/Backend/Vulkan/ResultExtensions.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using System;
-using Silk.NET.Vulkan;
-
-namespace Ryujinx.Ava.Ui.Vulkan
-{
- public static class ResultExtensions
- {
- public static void ThrowOnError(this Result result)
- {
- // Only negative result codes are errors.
- if ((int)result < (int)Result.Success)
- {
- throw new Exception($"Unexpected API error \"{result}\".");
- }
- }
- }
-}
diff --git a/Ryujinx.Ava/Ui/Backend/Vulkan/Skia/VulkanRenderTarget.cs b/Ryujinx.Ava/Ui/Backend/Vulkan/Skia/VulkanRenderTarget.cs
deleted file mode 100644
index 70ec39c7c..000000000
--- a/Ryujinx.Ava/Ui/Backend/Vulkan/Skia/VulkanRenderTarget.cs
+++ /dev/null
@@ -1,201 +0,0 @@
-using System;
-using Avalonia;
-using Avalonia.Skia;
-using Ryujinx.Ava.Ui.Vulkan;
-using Ryujinx.Ava.Ui.Vulkan.Surfaces;
-using Silk.NET.Vulkan;
-using SkiaSharp;
-
-namespace Ryujinx.Ava.Ui.Backend.Vulkan
-{
- internal class VulkanRenderTarget : ISkiaGpuRenderTarget
- {
- public GRContext GrContext { get; private set; }
-
- private readonly VulkanSurfaceRenderTarget _surface;
- private readonly VulkanPlatformInterface _vulkanPlatformInterface;
- private readonly IVulkanPlatformSurface _vulkanPlatformSurface;
- private GRVkBackendContext _grVkBackend;
-
- public VulkanRenderTarget(VulkanPlatformInterface vulkanPlatformInterface, IVulkanPlatformSurface vulkanPlatformSurface)
- {
- _surface = vulkanPlatformInterface.CreateRenderTarget(vulkanPlatformSurface);
- _vulkanPlatformInterface = vulkanPlatformInterface;
- _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();
-
- 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()
- {
- _grVkBackend.Dispose();
- GrContext.Dispose();
- _surface.Dispose();
- }
-
- public ISkiaGpuRenderSession BeginRenderingSession()
- {
- var session = _surface.BeginDraw(_vulkanPlatformSurface.Scaling);
- bool success = false;
- try
- {
- var disp = session.Display;
- var api = session.Api;
-
- var size = session.Size;
- var scaling = session.Scaling;
- if (size.Width <= 0 || size.Height <= 0 || scaling < 0)
- {
- size = new Avalonia.PixelSize(1, 1);
- scaling = 1;
- }
-
- lock (GrContext)
- {
- GrContext.ResetContext();
-
- var image = _surface.GetImage();
-
- var imageInfo = new GRVkImageInfo()
- {
- CurrentQueueFamily = disp.QueueFamilyIndex,
- Format = (uint)image.Format,
- Image = image.Handle,
- ImageLayout = (uint)image.CurrentLayout,
- ImageTiling = (uint)image.Tiling,
- ImageUsageFlags = _surface.UsageFlags,
- LevelCount = _surface.MipLevels,
- SampleCount = 1,
- Protected = false,
- Alloc = new GRVkAlloc()
- {
- Memory = image.MemoryHandle,
- Flags = 0,
- Offset = 0,
- Size = _surface.MemorySize
- }
- };
-
- var renderTarget =
- new GRBackendRenderTarget((int)size.Width, (int)size.Height, 1,
- imageInfo);
- var surface = SKSurface.Create(GrContext, renderTarget,
- GRSurfaceOrigin.TopLeft,
- _surface.IsRgba ? SKColorType.Rgba8888 : SKColorType.Bgra8888, SKColorSpace.CreateSrgb());
-
- if (surface == null)
- {
- throw new InvalidOperationException(
- "Surface can't be created with the provided render target");
- }
-
- success = true;
-
- return new VulkanGpuSession(GrContext, renderTarget, surface, session);
- }
- }
- finally
- {
- if (!success)
- {
- session.Dispose();
- }
- }
- }
-
- public bool IsCorrupted { get; }
-
- internal class VulkanGpuSession : ISkiaGpuRenderSession
- {
- private readonly GRBackendRenderTarget _backendRenderTarget;
- private readonly VulkanSurfaceRenderingSession _vulkanSession;
-
- public VulkanGpuSession(GRContext grContext,
- GRBackendRenderTarget backendRenderTarget,
- SKSurface surface,
- VulkanSurfaceRenderingSession vulkanSession)
- {
- GrContext = grContext;
- _backendRenderTarget = backendRenderTarget;
- SkSurface = surface;
- _vulkanSession = vulkanSession;
-
- SurfaceOrigin = GRSurfaceOrigin.TopLeft;
- }
-
- public void Dispose()
- {
- lock (_vulkanSession.Display.Lock)
- {
- SkSurface.Canvas.Flush();
-
- SkSurface.Dispose();
- _backendRenderTarget.Dispose();
- GrContext.Flush();
-
- _vulkanSession.Dispose();
- }
- }
-
- public GRContext GrContext { get; }
- public SKSurface SkSurface { get; }
- public double ScaleFactor => _vulkanSession.Scaling;
- public GRSurfaceOrigin SurfaceOrigin { get; }
- }
- }
-}
diff --git a/Ryujinx.Ava/Ui/Backend/Vulkan/Skia/VulkanSkiaGpu.cs b/Ryujinx.Ava/Ui/Backend/Vulkan/Skia/VulkanSkiaGpu.cs
deleted file mode 100644
index a5c270863..000000000
--- a/Ryujinx.Ava/Ui/Backend/Vulkan/Skia/VulkanSkiaGpu.cs
+++ /dev/null
@@ -1,61 +0,0 @@
-using System;
-using System.Collections.Generic;
-using Avalonia;
-using Avalonia.Platform;
-using Avalonia.Skia;
-using Avalonia.X11;
-using Ryujinx.Ava.Ui.Vulkan;
-using Silk.NET.Vulkan;
-using SkiaSharp;
-
-namespace Ryujinx.Ava.Ui.Backend.Vulkan
-{
- public class VulkanSkiaGpu : ISkiaGpu
- {
- private readonly VulkanPlatformInterface _vulkan;
- public long? MaxResourceBytes { get; }
-
- public VulkanSkiaGpu(long? maxResourceBytes)
- {
- _vulkan = AvaloniaLocator.Current.GetService();
- MaxResourceBytes = maxResourceBytes;
- }
-
- public ISkiaGpuRenderTarget TryCreateRenderTarget(IEnumerable