Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
cd74ae1bbd | |||
62216782ca | |||
2f36a6665c | |||
ca59c3f499 | |||
fdd7ee791c | |||
398fa1c238 | |||
2c5c0392f9 | |||
e0acde04bb | |||
3c61d560c3 | |||
b45a81458a | |||
460f9faf4e | |||
552c15739c | |||
0137c9e635 |
@ -13,7 +13,7 @@
|
|||||||
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
|
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
|
||||||
<PackageVersion Include="Concentus" Version="2.2.0" />
|
<PackageVersion Include="Concentus" Version="2.2.0" />
|
||||||
<PackageVersion Include="DiscordRichPresence" Version="1.2.1.24" />
|
<PackageVersion Include="DiscordRichPresence" Version="1.2.1.24" />
|
||||||
<PackageVersion Include="DynamicData" Version="9.0.1" />
|
<PackageVersion Include="DynamicData" Version="9.0.4" />
|
||||||
<PackageVersion Include="FluentAvaloniaUI" Version="2.0.5" />
|
<PackageVersion Include="FluentAvaloniaUI" Version="2.0.5" />
|
||||||
<PackageVersion Include="GtkSharp.Dependencies" Version="1.1.1" />
|
<PackageVersion Include="GtkSharp.Dependencies" Version="1.1.1" />
|
||||||
<PackageVersion Include="GtkSharp.Dependencies.osx" Version="0.0.5" />
|
<PackageVersion Include="GtkSharp.Dependencies.osx" Version="0.0.5" />
|
||||||
@ -39,11 +39,11 @@
|
|||||||
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
|
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
|
||||||
<PackageVersion Include="shaderc.net" Version="0.1.0" />
|
<PackageVersion Include="shaderc.net" Version="0.1.0" />
|
||||||
<PackageVersion Include="SharpZipLib" Version="1.4.2" />
|
<PackageVersion Include="SharpZipLib" Version="1.4.2" />
|
||||||
<PackageVersion Include="Silk.NET.Vulkan" Version="2.16.0" />
|
<PackageVersion Include="Silk.NET.Vulkan" Version="2.21.0" />
|
||||||
<PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.16.0" />
|
<PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.21.0" />
|
||||||
<PackageVersion Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.16.0" />
|
<PackageVersion Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.21.0" />
|
||||||
<PackageVersion Include="SixLabors.ImageSharp" Version="2.1.8" />
|
<PackageVersion Include="SkiaSharp" Version="2.88.7" />
|
||||||
<PackageVersion Include="SixLabors.ImageSharp.Drawing" Version="1.0.0" />
|
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.7" />
|
||||||
<PackageVersion Include="SPB" Version="0.0.4-build32" />
|
<PackageVersion Include="SPB" Version="0.0.4-build32" />
|
||||||
<PackageVersion Include="System.IO.Hashing" Version="8.0.0" />
|
<PackageVersion Include="System.IO.Hashing" Version="8.0.0" />
|
||||||
<PackageVersion Include="System.Management" Version="8.0.0" />
|
<PackageVersion Include="System.Management" Version="8.0.0" />
|
||||||
|
@ -87,6 +87,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon", "src\Ryuj
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Kernel.Generators", "src\Ryujinx.Horizon.Kernel.Generators\Ryujinx.Horizon.Kernel.Generators.csproj", "{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Kernel.Generators", "src\Ryujinx.Horizon.Kernel.Generators\Ryujinx.Horizon.Kernel.Generators.csproj", "{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.HLE.Generators", "src\Ryujinx.HLE.Generators\Ryujinx.HLE.Generators.csproj", "{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@ -249,6 +251,10 @@ Global
|
|||||||
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Release|Any CPU.Build.0 = Release|Any CPU
|
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
@ -746,6 +746,7 @@ namespace ARMeilleure.Decoders
|
|||||||
SetA32("<<<<01101000xxxxxxxxxxxxxx01xxxx", InstName.Pkh, InstEmit32.Pkh, OpCode32AluRsImm.Create);
|
SetA32("<<<<01101000xxxxxxxxxxxxxx01xxxx", InstName.Pkh, InstEmit32.Pkh, OpCode32AluRsImm.Create);
|
||||||
SetA32("11110101xx01xxxx1111xxxxxxxxxxxx", InstName.Pld, InstEmit32.Nop, OpCode32.Create);
|
SetA32("11110101xx01xxxx1111xxxxxxxxxxxx", InstName.Pld, InstEmit32.Nop, OpCode32.Create);
|
||||||
SetA32("11110111xx01xxxx1111xxxxxxx0xxxx", InstName.Pld, InstEmit32.Nop, OpCode32.Create);
|
SetA32("11110111xx01xxxx1111xxxxxxx0xxxx", InstName.Pld, InstEmit32.Nop, OpCode32.Create);
|
||||||
|
SetA32("<<<<01100010xxxxxxxx11110001xxxx", InstName.Qadd16, InstEmit32.Qadd16, OpCode32AluReg.Create);
|
||||||
SetA32("<<<<011011111111xxxx11110011xxxx", InstName.Rbit, InstEmit32.Rbit, OpCode32AluReg.Create);
|
SetA32("<<<<011011111111xxxx11110011xxxx", InstName.Rbit, InstEmit32.Rbit, OpCode32AluReg.Create);
|
||||||
SetA32("<<<<011010111111xxxx11110011xxxx", InstName.Rev, InstEmit32.Rev, OpCode32AluReg.Create);
|
SetA32("<<<<011010111111xxxx11110011xxxx", InstName.Rev, InstEmit32.Rev, OpCode32AluReg.Create);
|
||||||
SetA32("<<<<011010111111xxxx11111011xxxx", InstName.Rev16, InstEmit32.Rev16, OpCode32AluReg.Create);
|
SetA32("<<<<011010111111xxxx11111011xxxx", InstName.Rev16, InstEmit32.Rev16, OpCode32AluReg.Create);
|
||||||
@ -1034,6 +1035,7 @@ namespace ARMeilleure.Decoders
|
|||||||
SetAsimd("111100101x>>>xxxxxxx0101>xx1xxxx", InstName.Vshl, InstEmit32.Vshl, OpCode32SimdShImm.Create, OpCode32SimdShImm.CreateT32);
|
SetAsimd("111100101x>>>xxxxxxx0101>xx1xxxx", InstName.Vshl, InstEmit32.Vshl, OpCode32SimdShImm.Create, OpCode32SimdShImm.CreateT32);
|
||||||
SetAsimd("1111001x0xxxxxxxxxxx0100xxx0xxxx", InstName.Vshl, InstEmit32.Vshl_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
SetAsimd("1111001x0xxxxxxxxxxx0100xxx0xxxx", InstName.Vshl, InstEmit32.Vshl_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetAsimd("1111001x1x>>>xxxxxxx101000x1xxxx", InstName.Vshll, InstEmit32.Vshll, OpCode32SimdShImmLong.Create, OpCode32SimdShImmLong.CreateT32); // A1 encoding.
|
SetAsimd("1111001x1x>>>xxxxxxx101000x1xxxx", InstName.Vshll, InstEmit32.Vshll, OpCode32SimdShImmLong.Create, OpCode32SimdShImmLong.CreateT32); // A1 encoding.
|
||||||
|
SetAsimd("111100111x11<<10xxxx001100x0xxxx", InstName.Vshll, InstEmit32.Vshll2, OpCode32SimdMovn.Create, OpCode32SimdMovn.CreateT32); // A2 encoding.
|
||||||
SetAsimd("1111001x1x>>>xxxxxxx0000>xx1xxxx", InstName.Vshr, InstEmit32.Vshr, OpCode32SimdShImm.Create, OpCode32SimdShImm.CreateT32);
|
SetAsimd("1111001x1x>>>xxxxxxx0000>xx1xxxx", InstName.Vshr, InstEmit32.Vshr, OpCode32SimdShImm.Create, OpCode32SimdShImm.CreateT32);
|
||||||
SetAsimd("111100101x>>>xxxxxxx100000x1xxx0", InstName.Vshrn, InstEmit32.Vshrn, OpCode32SimdShImmNarrow.Create, OpCode32SimdShImmNarrow.CreateT32);
|
SetAsimd("111100101x>>>xxxxxxx100000x1xxx0", InstName.Vshrn, InstEmit32.Vshrn, OpCode32SimdShImmNarrow.Create, OpCode32SimdShImmNarrow.CreateT32);
|
||||||
SetAsimd("111100111x>>>xxxxxxx0101>xx1xxxx", InstName.Vsli, InstEmit32.Vsli_I, OpCode32SimdShImm.Create, OpCode32SimdShImm.CreateT32);
|
SetAsimd("111100111x>>>xxxxxxx0101>xx1xxxx", InstName.Vsli, InstEmit32.Vsli_I, OpCode32SimdShImm.Create, OpCode32SimdShImm.CreateT32);
|
||||||
|
@ -292,6 +292,16 @@ namespace ARMeilleure.Instructions
|
|||||||
EmitAluStore(context, res);
|
EmitAluStore(context, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Qadd16(ArmEmitterContext context)
|
||||||
|
{
|
||||||
|
OpCode32AluReg op = (OpCode32AluReg)context.CurrOp;
|
||||||
|
|
||||||
|
SetIntA32(context, op.Rd, EmitSigned16BitPair(context, GetIntA32(context, op.Rn), GetIntA32(context, op.Rm), (d, n, m) =>
|
||||||
|
{
|
||||||
|
EmitSaturateRange(context, d, context.Add(n, m), 16, unsigned: false, setQ: false);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
public static void Rbit(ArmEmitterContext context)
|
public static void Rbit(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
Operand m = GetAluM(context);
|
Operand m = GetAluM(context);
|
||||||
@ -976,6 +986,94 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void EmitSaturateRange(ArmEmitterContext context, Operand result, Operand value, uint saturateTo, bool unsigned, bool setQ = true)
|
||||||
|
{
|
||||||
|
Debug.Assert(saturateTo <= 32);
|
||||||
|
Debug.Assert(!unsigned || saturateTo < 32);
|
||||||
|
|
||||||
|
if (!unsigned && saturateTo == 32)
|
||||||
|
{
|
||||||
|
// No saturation possible for this case.
|
||||||
|
|
||||||
|
context.Copy(result, value);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (saturateTo == 0)
|
||||||
|
{
|
||||||
|
// Result is always zero if we saturate 0 bits.
|
||||||
|
|
||||||
|
context.Copy(result, Const(0));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Operand satValue;
|
||||||
|
|
||||||
|
if (unsigned)
|
||||||
|
{
|
||||||
|
// Negative values always saturate (to zero).
|
||||||
|
// So we must always ignore the sign bit when masking, so that the truncated value will differ from the original one.
|
||||||
|
|
||||||
|
satValue = context.BitwiseAnd(value, Const((int)(uint.MaxValue >> (32 - (int)saturateTo))));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
satValue = context.ShiftLeft(value, Const(32 - (int)saturateTo));
|
||||||
|
satValue = context.ShiftRightSI(satValue, Const(32 - (int)saturateTo));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the result is 0, the values are equal and we don't need saturation.
|
||||||
|
Operand lblNoSat = Label();
|
||||||
|
context.BranchIfFalse(lblNoSat, context.Subtract(value, satValue));
|
||||||
|
|
||||||
|
// Saturate and set Q flag.
|
||||||
|
if (unsigned)
|
||||||
|
{
|
||||||
|
if (saturateTo == 31)
|
||||||
|
{
|
||||||
|
// Only saturation case possible when going from 32 bits signed to 32 or 31 bits unsigned
|
||||||
|
// is when the signed input is negative, as all positive values are representable on a 31 bits range.
|
||||||
|
|
||||||
|
satValue = Const(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
satValue = context.ShiftRightSI(value, Const(31));
|
||||||
|
satValue = context.BitwiseNot(satValue);
|
||||||
|
satValue = context.ShiftRightUI(satValue, Const(32 - (int)saturateTo));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (saturateTo == 1)
|
||||||
|
{
|
||||||
|
satValue = context.ShiftRightSI(value, Const(31));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
satValue = Const(uint.MaxValue >> (33 - (int)saturateTo));
|
||||||
|
satValue = context.BitwiseExclusiveOr(satValue, context.ShiftRightSI(value, Const(31)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setQ)
|
||||||
|
{
|
||||||
|
SetFlag(context, PState.QFlag, Const(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
context.Copy(result, satValue);
|
||||||
|
|
||||||
|
Operand lblExit = Label();
|
||||||
|
context.Branch(lblExit);
|
||||||
|
|
||||||
|
context.MarkLabel(lblNoSat);
|
||||||
|
|
||||||
|
context.Copy(result, value);
|
||||||
|
|
||||||
|
context.MarkLabel(lblExit);
|
||||||
|
}
|
||||||
|
|
||||||
private static void EmitSaturateUqadd(ArmEmitterContext context, Operand result, Operand value, uint saturateTo)
|
private static void EmitSaturateUqadd(ArmEmitterContext context, Operand result, Operand value, uint saturateTo)
|
||||||
{
|
{
|
||||||
Debug.Assert(saturateTo <= 32);
|
Debug.Assert(saturateTo <= 32);
|
||||||
@ -1053,6 +1151,21 @@ namespace ARMeilleure.Instructions
|
|||||||
context.MarkLabel(lblExit);
|
context.MarkLabel(lblExit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Operand EmitSigned16BitPair(ArmEmitterContext context, Operand rn, Operand rm, Action<Operand, Operand, Operand> elementAction)
|
||||||
|
{
|
||||||
|
Operand tempD = context.AllocateLocal(OperandType.I32);
|
||||||
|
|
||||||
|
Operand tempN = context.SignExtend16(OperandType.I32, rn);
|
||||||
|
Operand tempM = context.SignExtend16(OperandType.I32, rm);
|
||||||
|
elementAction(tempD, tempN, tempM);
|
||||||
|
Operand tempD2 = context.ZeroExtend16(OperandType.I32, tempD);
|
||||||
|
|
||||||
|
tempN = context.ShiftRightSI(rn, Const(16));
|
||||||
|
tempM = context.ShiftRightSI(rm, Const(16));
|
||||||
|
elementAction(tempD, tempN, tempM);
|
||||||
|
return context.BitwiseOr(tempD2, context.ShiftLeft(tempD, Const(16)));
|
||||||
|
}
|
||||||
|
|
||||||
private static Operand EmitUnsigned16BitPair(ArmEmitterContext context, Operand rn, Operand rm, Action<Operand, Operand, Operand> elementAction)
|
private static Operand EmitUnsigned16BitPair(ArmEmitterContext context, Operand rn, Operand rm, Action<Operand, Operand, Operand> elementAction)
|
||||||
{
|
{
|
||||||
Operand tempD = context.AllocateLocal(OperandType.I32);
|
Operand tempD = context.AllocateLocal(OperandType.I32);
|
||||||
|
@ -106,6 +106,38 @@ namespace ARMeilleure.Instructions
|
|||||||
context.Copy(GetVecA32(op.Qd), res);
|
context.Copy(GetVecA32(op.Qd), res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Vshll2(ArmEmitterContext context)
|
||||||
|
{
|
||||||
|
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
|
||||||
|
|
||||||
|
Operand res = context.VectorZero();
|
||||||
|
|
||||||
|
int elems = op.GetBytesCount() >> op.Size;
|
||||||
|
|
||||||
|
for (int index = 0; index < elems; index++)
|
||||||
|
{
|
||||||
|
Operand me = EmitVectorExtract32(context, op.Qm, op.Im + index, op.Size, !op.U);
|
||||||
|
|
||||||
|
if (op.Size == 2)
|
||||||
|
{
|
||||||
|
if (op.U)
|
||||||
|
{
|
||||||
|
me = context.ZeroExtend32(OperandType.I64, me);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
me = context.SignExtend32(OperandType.I64, me);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
me = context.ShiftLeft(me, Const(8 << op.Size));
|
||||||
|
|
||||||
|
res = EmitVectorInsert(context, res, me, index, op.Size + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
context.Copy(GetVecA32(op.Qd), res);
|
||||||
|
}
|
||||||
|
|
||||||
public static void Vshr(ArmEmitterContext context)
|
public static void Vshr(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
OpCode32SimdShImm op = (OpCode32SimdShImm)context.CurrOp;
|
OpCode32SimdShImm op = (OpCode32SimdShImm)context.CurrOp;
|
||||||
|
@ -527,6 +527,7 @@ namespace ARMeilleure.Instructions
|
|||||||
Pld,
|
Pld,
|
||||||
Pop,
|
Pop,
|
||||||
Push,
|
Push,
|
||||||
|
Qadd16,
|
||||||
Rev,
|
Rev,
|
||||||
Revsh,
|
Revsh,
|
||||||
Rsb,
|
Rsb,
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace ARMeilleure.Translation
|
namespace ARMeilleure.Translation
|
||||||
{
|
{
|
||||||
@ -11,11 +10,10 @@ namespace ARMeilleure.Translation
|
|||||||
|
|
||||||
public IntPtr FuncPtr { get; }
|
public IntPtr FuncPtr { get; }
|
||||||
|
|
||||||
public DelegateInfo(Delegate dlg)
|
public DelegateInfo(Delegate dlg, IntPtr funcPtr)
|
||||||
{
|
{
|
||||||
_dlg = dlg;
|
_dlg = dlg;
|
||||||
|
FuncPtr = funcPtr;
|
||||||
FuncPtr = Marshal.GetFunctionPointerForDelegate<Delegate>(dlg);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ using ARMeilleure.State;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace ARMeilleure.Translation
|
namespace ARMeilleure.Translation
|
||||||
{
|
{
|
||||||
@ -64,11 +65,11 @@ namespace ARMeilleure.Translation
|
|||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SetDelegateInfo(Delegate dlg)
|
private static void SetDelegateInfo(Delegate dlg, IntPtr funcPtr)
|
||||||
{
|
{
|
||||||
string key = GetKey(dlg.Method);
|
string key = GetKey(dlg.Method);
|
||||||
|
|
||||||
_delegates.Add(key, new DelegateInfo(dlg)); // ArgumentException (key).
|
_delegates.Add(key, new DelegateInfo(dlg, funcPtr)); // ArgumentException (key).
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetKey(MethodInfo info)
|
private static string GetKey(MethodInfo info)
|
||||||
@ -82,179 +83,353 @@ namespace ARMeilleure.Translation
|
|||||||
{
|
{
|
||||||
_delegates = new SortedList<string, DelegateInfo>();
|
_delegates = new SortedList<string, DelegateInfo>();
|
||||||
|
|
||||||
SetDelegateInfo(new MathAbs(Math.Abs));
|
var dlgMathAbs = new MathAbs(Math.Abs);
|
||||||
SetDelegateInfo(new MathCeiling(Math.Ceiling));
|
var dlgMathCeiling = new MathCeiling(Math.Ceiling);
|
||||||
SetDelegateInfo(new MathFloor(Math.Floor));
|
var dlgMathFloor = new MathFloor(Math.Floor);
|
||||||
SetDelegateInfo(new MathRound(Math.Round));
|
var dlgMathRound = new MathRound(Math.Round);
|
||||||
SetDelegateInfo(new MathTruncate(Math.Truncate));
|
var dlgMathTruncate = new MathTruncate(Math.Truncate);
|
||||||
|
|
||||||
SetDelegateInfo(new MathFAbs(MathF.Abs));
|
var dlgMathFAbs = new MathFAbs(MathF.Abs);
|
||||||
SetDelegateInfo(new MathFCeiling(MathF.Ceiling));
|
var dlgMathFCeiling = new MathFCeiling(MathF.Ceiling);
|
||||||
SetDelegateInfo(new MathFFloor(MathF.Floor));
|
var dlgMathFFloor = new MathFFloor(MathF.Floor);
|
||||||
SetDelegateInfo(new MathFRound(MathF.Round));
|
var dlgMathFRound = new MathFRound(MathF.Round);
|
||||||
SetDelegateInfo(new MathFTruncate(MathF.Truncate));
|
var dlgMathFTruncate = new MathFTruncate(MathF.Truncate);
|
||||||
|
|
||||||
SetDelegateInfo(new NativeInterfaceBreak(NativeInterface.Break));
|
var dlgNativeInterfaceBreak = new NativeInterfaceBreak(NativeInterface.Break);
|
||||||
SetDelegateInfo(new NativeInterfaceCheckSynchronization(NativeInterface.CheckSynchronization));
|
var dlgNativeInterfaceCheckSynchronization = new NativeInterfaceCheckSynchronization(NativeInterface.CheckSynchronization);
|
||||||
SetDelegateInfo(new NativeInterfaceEnqueueForRejit(NativeInterface.EnqueueForRejit));
|
var dlgNativeInterfaceEnqueueForRejit = new NativeInterfaceEnqueueForRejit(NativeInterface.EnqueueForRejit);
|
||||||
SetDelegateInfo(new NativeInterfaceGetCntfrqEl0(NativeInterface.GetCntfrqEl0));
|
var dlgNativeInterfaceGetCntfrqEl0 = new NativeInterfaceGetCntfrqEl0(NativeInterface.GetCntfrqEl0);
|
||||||
SetDelegateInfo(new NativeInterfaceGetCntpctEl0(NativeInterface.GetCntpctEl0));
|
var dlgNativeInterfaceGetCntpctEl0 = new NativeInterfaceGetCntpctEl0(NativeInterface.GetCntpctEl0);
|
||||||
SetDelegateInfo(new NativeInterfaceGetCntvctEl0(NativeInterface.GetCntvctEl0));
|
var dlgNativeInterfaceGetCntvctEl0 = new NativeInterfaceGetCntvctEl0(NativeInterface.GetCntvctEl0);
|
||||||
SetDelegateInfo(new NativeInterfaceGetCtrEl0(NativeInterface.GetCtrEl0));
|
var dlgNativeInterfaceGetCtrEl0 = new NativeInterfaceGetCtrEl0(NativeInterface.GetCtrEl0);
|
||||||
SetDelegateInfo(new NativeInterfaceGetDczidEl0(NativeInterface.GetDczidEl0));
|
var dlgNativeInterfaceGetDczidEl0 = new NativeInterfaceGetDczidEl0(NativeInterface.GetDczidEl0);
|
||||||
SetDelegateInfo(new NativeInterfaceGetFunctionAddress(NativeInterface.GetFunctionAddress));
|
var dlgNativeInterfaceGetFunctionAddress = new NativeInterfaceGetFunctionAddress(NativeInterface.GetFunctionAddress);
|
||||||
SetDelegateInfo(new NativeInterfaceInvalidateCacheLine(NativeInterface.InvalidateCacheLine));
|
var dlgNativeInterfaceInvalidateCacheLine = new NativeInterfaceInvalidateCacheLine(NativeInterface.InvalidateCacheLine);
|
||||||
SetDelegateInfo(new NativeInterfaceReadByte(NativeInterface.ReadByte));
|
var dlgNativeInterfaceReadByte = new NativeInterfaceReadByte(NativeInterface.ReadByte);
|
||||||
SetDelegateInfo(new NativeInterfaceReadUInt16(NativeInterface.ReadUInt16));
|
var dlgNativeInterfaceReadUInt16 = new NativeInterfaceReadUInt16(NativeInterface.ReadUInt16);
|
||||||
SetDelegateInfo(new NativeInterfaceReadUInt32(NativeInterface.ReadUInt32));
|
var dlgNativeInterfaceReadUInt32 = new NativeInterfaceReadUInt32(NativeInterface.ReadUInt32);
|
||||||
SetDelegateInfo(new NativeInterfaceReadUInt64(NativeInterface.ReadUInt64));
|
var dlgNativeInterfaceReadUInt64 = new NativeInterfaceReadUInt64(NativeInterface.ReadUInt64);
|
||||||
SetDelegateInfo(new NativeInterfaceReadVector128(NativeInterface.ReadVector128));
|
var dlgNativeInterfaceReadVector128 = new NativeInterfaceReadVector128(NativeInterface.ReadVector128);
|
||||||
SetDelegateInfo(new NativeInterfaceSignalMemoryTracking(NativeInterface.SignalMemoryTracking));
|
var dlgNativeInterfaceSignalMemoryTracking = new NativeInterfaceSignalMemoryTracking(NativeInterface.SignalMemoryTracking);
|
||||||
SetDelegateInfo(new NativeInterfaceSupervisorCall(NativeInterface.SupervisorCall));
|
var dlgNativeInterfaceSupervisorCall = new NativeInterfaceSupervisorCall(NativeInterface.SupervisorCall);
|
||||||
SetDelegateInfo(new NativeInterfaceThrowInvalidMemoryAccess(NativeInterface.ThrowInvalidMemoryAccess));
|
var dlgNativeInterfaceThrowInvalidMemoryAccess = new NativeInterfaceThrowInvalidMemoryAccess(NativeInterface.ThrowInvalidMemoryAccess);
|
||||||
SetDelegateInfo(new NativeInterfaceUndefined(NativeInterface.Undefined));
|
var dlgNativeInterfaceUndefined = new NativeInterfaceUndefined(NativeInterface.Undefined);
|
||||||
SetDelegateInfo(new NativeInterfaceWriteByte(NativeInterface.WriteByte));
|
var dlgNativeInterfaceWriteByte = new NativeInterfaceWriteByte(NativeInterface.WriteByte);
|
||||||
SetDelegateInfo(new NativeInterfaceWriteUInt16(NativeInterface.WriteUInt16));
|
var dlgNativeInterfaceWriteUInt16 = new NativeInterfaceWriteUInt16(NativeInterface.WriteUInt16);
|
||||||
SetDelegateInfo(new NativeInterfaceWriteUInt32(NativeInterface.WriteUInt32));
|
var dlgNativeInterfaceWriteUInt32 = new NativeInterfaceWriteUInt32(NativeInterface.WriteUInt32);
|
||||||
SetDelegateInfo(new NativeInterfaceWriteUInt64(NativeInterface.WriteUInt64));
|
var dlgNativeInterfaceWriteUInt64 = new NativeInterfaceWriteUInt64(NativeInterface.WriteUInt64);
|
||||||
SetDelegateInfo(new NativeInterfaceWriteVector128(NativeInterface.WriteVector128));
|
var dlgNativeInterfaceWriteVector128 = new NativeInterfaceWriteVector128(NativeInterface.WriteVector128);
|
||||||
|
|
||||||
SetDelegateInfo(new SoftFallbackCountLeadingSigns(SoftFallback.CountLeadingSigns));
|
var dlgSoftFallbackCountLeadingSigns = new SoftFallbackCountLeadingSigns(SoftFallback.CountLeadingSigns);
|
||||||
SetDelegateInfo(new SoftFallbackCountLeadingZeros(SoftFallback.CountLeadingZeros));
|
var dlgSoftFallbackCountLeadingZeros = new SoftFallbackCountLeadingZeros(SoftFallback.CountLeadingZeros);
|
||||||
SetDelegateInfo(new SoftFallbackCrc32b(SoftFallback.Crc32b));
|
var dlgSoftFallbackCrc32b = new SoftFallbackCrc32b(SoftFallback.Crc32b);
|
||||||
SetDelegateInfo(new SoftFallbackCrc32cb(SoftFallback.Crc32cb));
|
var dlgSoftFallbackCrc32cb = new SoftFallbackCrc32cb(SoftFallback.Crc32cb);
|
||||||
SetDelegateInfo(new SoftFallbackCrc32ch(SoftFallback.Crc32ch));
|
var dlgSoftFallbackCrc32ch = new SoftFallbackCrc32ch(SoftFallback.Crc32ch);
|
||||||
SetDelegateInfo(new SoftFallbackCrc32cw(SoftFallback.Crc32cw));
|
var dlgSoftFallbackCrc32cw = new SoftFallbackCrc32cw(SoftFallback.Crc32cw);
|
||||||
SetDelegateInfo(new SoftFallbackCrc32cx(SoftFallback.Crc32cx));
|
var dlgSoftFallbackCrc32cx = new SoftFallbackCrc32cx(SoftFallback.Crc32cx);
|
||||||
SetDelegateInfo(new SoftFallbackCrc32h(SoftFallback.Crc32h));
|
var dlgSoftFallbackCrc32h = new SoftFallbackCrc32h(SoftFallback.Crc32h);
|
||||||
SetDelegateInfo(new SoftFallbackCrc32w(SoftFallback.Crc32w));
|
var dlgSoftFallbackCrc32w = new SoftFallbackCrc32w(SoftFallback.Crc32w);
|
||||||
SetDelegateInfo(new SoftFallbackCrc32x(SoftFallback.Crc32x));
|
var dlgSoftFallbackCrc32x = new SoftFallbackCrc32x(SoftFallback.Crc32x);
|
||||||
SetDelegateInfo(new SoftFallbackDecrypt(SoftFallback.Decrypt));
|
var dlgSoftFallbackDecrypt = new SoftFallbackDecrypt(SoftFallback.Decrypt);
|
||||||
SetDelegateInfo(new SoftFallbackEncrypt(SoftFallback.Encrypt));
|
var dlgSoftFallbackEncrypt = new SoftFallbackEncrypt(SoftFallback.Encrypt);
|
||||||
SetDelegateInfo(new SoftFallbackFixedRotate(SoftFallback.FixedRotate));
|
var dlgSoftFallbackFixedRotate = new SoftFallbackFixedRotate(SoftFallback.FixedRotate);
|
||||||
SetDelegateInfo(new SoftFallbackHashChoose(SoftFallback.HashChoose));
|
var dlgSoftFallbackHashChoose = new SoftFallbackHashChoose(SoftFallback.HashChoose);
|
||||||
SetDelegateInfo(new SoftFallbackHashLower(SoftFallback.HashLower));
|
var dlgSoftFallbackHashLower = new SoftFallbackHashLower(SoftFallback.HashLower);
|
||||||
SetDelegateInfo(new SoftFallbackHashMajority(SoftFallback.HashMajority));
|
var dlgSoftFallbackHashMajority = new SoftFallbackHashMajority(SoftFallback.HashMajority);
|
||||||
SetDelegateInfo(new SoftFallbackHashParity(SoftFallback.HashParity));
|
var dlgSoftFallbackHashParity = new SoftFallbackHashParity(SoftFallback.HashParity);
|
||||||
SetDelegateInfo(new SoftFallbackHashUpper(SoftFallback.HashUpper));
|
var dlgSoftFallbackHashUpper = new SoftFallbackHashUpper(SoftFallback.HashUpper);
|
||||||
SetDelegateInfo(new SoftFallbackInverseMixColumns(SoftFallback.InverseMixColumns));
|
var dlgSoftFallbackInverseMixColumns = new SoftFallbackInverseMixColumns(SoftFallback.InverseMixColumns);
|
||||||
SetDelegateInfo(new SoftFallbackMixColumns(SoftFallback.MixColumns));
|
var dlgSoftFallbackMixColumns = new SoftFallbackMixColumns(SoftFallback.MixColumns);
|
||||||
SetDelegateInfo(new SoftFallbackPolynomialMult64_128(SoftFallback.PolynomialMult64_128));
|
var dlgSoftFallbackPolynomialMult64_128 = new SoftFallbackPolynomialMult64_128(SoftFallback.PolynomialMult64_128);
|
||||||
SetDelegateInfo(new SoftFallbackSatF32ToS32(SoftFallback.SatF32ToS32));
|
var dlgSoftFallbackSatF32ToS32 = new SoftFallbackSatF32ToS32(SoftFallback.SatF32ToS32);
|
||||||
SetDelegateInfo(new SoftFallbackSatF32ToS64(SoftFallback.SatF32ToS64));
|
var dlgSoftFallbackSatF32ToS64 = new SoftFallbackSatF32ToS64(SoftFallback.SatF32ToS64);
|
||||||
SetDelegateInfo(new SoftFallbackSatF32ToU32(SoftFallback.SatF32ToU32));
|
var dlgSoftFallbackSatF32ToU32 = new SoftFallbackSatF32ToU32(SoftFallback.SatF32ToU32);
|
||||||
SetDelegateInfo(new SoftFallbackSatF32ToU64(SoftFallback.SatF32ToU64));
|
var dlgSoftFallbackSatF32ToU64 = new SoftFallbackSatF32ToU64(SoftFallback.SatF32ToU64);
|
||||||
SetDelegateInfo(new SoftFallbackSatF64ToS32(SoftFallback.SatF64ToS32));
|
var dlgSoftFallbackSatF64ToS32 = new SoftFallbackSatF64ToS32(SoftFallback.SatF64ToS32);
|
||||||
SetDelegateInfo(new SoftFallbackSatF64ToS64(SoftFallback.SatF64ToS64));
|
var dlgSoftFallbackSatF64ToS64 = new SoftFallbackSatF64ToS64(SoftFallback.SatF64ToS64);
|
||||||
SetDelegateInfo(new SoftFallbackSatF64ToU32(SoftFallback.SatF64ToU32));
|
var dlgSoftFallbackSatF64ToU32 = new SoftFallbackSatF64ToU32(SoftFallback.SatF64ToU32);
|
||||||
SetDelegateInfo(new SoftFallbackSatF64ToU64(SoftFallback.SatF64ToU64));
|
var dlgSoftFallbackSatF64ToU64 = new SoftFallbackSatF64ToU64(SoftFallback.SatF64ToU64);
|
||||||
SetDelegateInfo(new SoftFallbackSha1SchedulePart1(SoftFallback.Sha1SchedulePart1));
|
var dlgSoftFallbackSha1SchedulePart1 = new SoftFallbackSha1SchedulePart1(SoftFallback.Sha1SchedulePart1);
|
||||||
SetDelegateInfo(new SoftFallbackSha1SchedulePart2(SoftFallback.Sha1SchedulePart2));
|
var dlgSoftFallbackSha1SchedulePart2 = new SoftFallbackSha1SchedulePart2(SoftFallback.Sha1SchedulePart2);
|
||||||
SetDelegateInfo(new SoftFallbackSha256SchedulePart1(SoftFallback.Sha256SchedulePart1));
|
var dlgSoftFallbackSha256SchedulePart1 = new SoftFallbackSha256SchedulePart1(SoftFallback.Sha256SchedulePart1);
|
||||||
SetDelegateInfo(new SoftFallbackSha256SchedulePart2(SoftFallback.Sha256SchedulePart2));
|
var dlgSoftFallbackSha256SchedulePart2 = new SoftFallbackSha256SchedulePart2(SoftFallback.Sha256SchedulePart2);
|
||||||
SetDelegateInfo(new SoftFallbackSignedShrImm64(SoftFallback.SignedShrImm64));
|
var dlgSoftFallbackSignedShrImm64 = new SoftFallbackSignedShrImm64(SoftFallback.SignedShrImm64);
|
||||||
SetDelegateInfo(new SoftFallbackTbl1(SoftFallback.Tbl1));
|
var dlgSoftFallbackTbl1 = new SoftFallbackTbl1(SoftFallback.Tbl1);
|
||||||
SetDelegateInfo(new SoftFallbackTbl2(SoftFallback.Tbl2));
|
var dlgSoftFallbackTbl2 = new SoftFallbackTbl2(SoftFallback.Tbl2);
|
||||||
SetDelegateInfo(new SoftFallbackTbl3(SoftFallback.Tbl3));
|
var dlgSoftFallbackTbl3 = new SoftFallbackTbl3(SoftFallback.Tbl3);
|
||||||
SetDelegateInfo(new SoftFallbackTbl4(SoftFallback.Tbl4));
|
var dlgSoftFallbackTbl4 = new SoftFallbackTbl4(SoftFallback.Tbl4);
|
||||||
SetDelegateInfo(new SoftFallbackTbx1(SoftFallback.Tbx1));
|
var dlgSoftFallbackTbx1 = new SoftFallbackTbx1(SoftFallback.Tbx1);
|
||||||
SetDelegateInfo(new SoftFallbackTbx2(SoftFallback.Tbx2));
|
var dlgSoftFallbackTbx2 = new SoftFallbackTbx2(SoftFallback.Tbx2);
|
||||||
SetDelegateInfo(new SoftFallbackTbx3(SoftFallback.Tbx3));
|
var dlgSoftFallbackTbx3 = new SoftFallbackTbx3(SoftFallback.Tbx3);
|
||||||
SetDelegateInfo(new SoftFallbackTbx4(SoftFallback.Tbx4));
|
var dlgSoftFallbackTbx4 = new SoftFallbackTbx4(SoftFallback.Tbx4);
|
||||||
SetDelegateInfo(new SoftFallbackUnsignedShrImm64(SoftFallback.UnsignedShrImm64));
|
var dlgSoftFallbackUnsignedShrImm64 = new SoftFallbackUnsignedShrImm64(SoftFallback.UnsignedShrImm64);
|
||||||
|
|
||||||
SetDelegateInfo(new SoftFloat16_32FPConvert(SoftFloat16_32.FPConvert));
|
var dlgSoftFloat16_32FPConvert = new SoftFloat16_32FPConvert(SoftFloat16_32.FPConvert);
|
||||||
SetDelegateInfo(new SoftFloat16_64FPConvert(SoftFloat16_64.FPConvert));
|
var dlgSoftFloat16_64FPConvert = new SoftFloat16_64FPConvert(SoftFloat16_64.FPConvert);
|
||||||
|
|
||||||
SetDelegateInfo(new SoftFloat32FPAdd(SoftFloat32.FPAdd));
|
var dlgSoftFloat32FPAdd = new SoftFloat32FPAdd(SoftFloat32.FPAdd);
|
||||||
SetDelegateInfo(new SoftFloat32FPAddFpscr(SoftFloat32.FPAddFpscr)); // A32 only.
|
var dlgSoftFloat32FPAddFpscr = new SoftFloat32FPAddFpscr(SoftFloat32.FPAddFpscr); // A32 only.
|
||||||
SetDelegateInfo(new SoftFloat32FPCompare(SoftFloat32.FPCompare));
|
var dlgSoftFloat32FPCompare = new SoftFloat32FPCompare(SoftFloat32.FPCompare);
|
||||||
SetDelegateInfo(new SoftFloat32FPCompareEQ(SoftFloat32.FPCompareEQ));
|
var dlgSoftFloat32FPCompareEQ = new SoftFloat32FPCompareEQ(SoftFloat32.FPCompareEQ);
|
||||||
SetDelegateInfo(new SoftFloat32FPCompareEQFpscr(SoftFloat32.FPCompareEQFpscr)); // A32 only.
|
var dlgSoftFloat32FPCompareEQFpscr = new SoftFloat32FPCompareEQFpscr(SoftFloat32.FPCompareEQFpscr); // A32 only.
|
||||||
SetDelegateInfo(new SoftFloat32FPCompareGE(SoftFloat32.FPCompareGE));
|
var dlgSoftFloat32FPCompareGE = new SoftFloat32FPCompareGE(SoftFloat32.FPCompareGE);
|
||||||
SetDelegateInfo(new SoftFloat32FPCompareGEFpscr(SoftFloat32.FPCompareGEFpscr)); // A32 only.
|
var dlgSoftFloat32FPCompareGEFpscr = new SoftFloat32FPCompareGEFpscr(SoftFloat32.FPCompareGEFpscr); // A32 only.
|
||||||
SetDelegateInfo(new SoftFloat32FPCompareGT(SoftFloat32.FPCompareGT));
|
var dlgSoftFloat32FPCompareGT = new SoftFloat32FPCompareGT(SoftFloat32.FPCompareGT);
|
||||||
SetDelegateInfo(new SoftFloat32FPCompareGTFpscr(SoftFloat32.FPCompareGTFpscr)); // A32 only.
|
var dlgSoftFloat32FPCompareGTFpscr = new SoftFloat32FPCompareGTFpscr(SoftFloat32.FPCompareGTFpscr); // A32 only.
|
||||||
SetDelegateInfo(new SoftFloat32FPCompareLE(SoftFloat32.FPCompareLE));
|
var dlgSoftFloat32FPCompareLE = new SoftFloat32FPCompareLE(SoftFloat32.FPCompareLE);
|
||||||
SetDelegateInfo(new SoftFloat32FPCompareLEFpscr(SoftFloat32.FPCompareLEFpscr)); // A32 only.
|
var dlgSoftFloat32FPCompareLEFpscr = new SoftFloat32FPCompareLEFpscr(SoftFloat32.FPCompareLEFpscr); // A32 only.
|
||||||
SetDelegateInfo(new SoftFloat32FPCompareLT(SoftFloat32.FPCompareLT));
|
var dlgSoftFloat32FPCompareLT = new SoftFloat32FPCompareLT(SoftFloat32.FPCompareLT);
|
||||||
SetDelegateInfo(new SoftFloat32FPCompareLTFpscr(SoftFloat32.FPCompareLTFpscr)); // A32 only.
|
var dlgSoftFloat32FPCompareLTFpscr = new SoftFloat32FPCompareLTFpscr(SoftFloat32.FPCompareLTFpscr); // A32 only.
|
||||||
SetDelegateInfo(new SoftFloat32FPDiv(SoftFloat32.FPDiv));
|
var dlgSoftFloat32FPDiv = new SoftFloat32FPDiv(SoftFloat32.FPDiv);
|
||||||
SetDelegateInfo(new SoftFloat32FPMax(SoftFloat32.FPMax));
|
var dlgSoftFloat32FPMax = new SoftFloat32FPMax(SoftFloat32.FPMax);
|
||||||
SetDelegateInfo(new SoftFloat32FPMaxFpscr(SoftFloat32.FPMaxFpscr)); // A32 only.
|
var dlgSoftFloat32FPMaxFpscr = new SoftFloat32FPMaxFpscr(SoftFloat32.FPMaxFpscr); // A32 only.
|
||||||
SetDelegateInfo(new SoftFloat32FPMaxNum(SoftFloat32.FPMaxNum));
|
var dlgSoftFloat32FPMaxNum = new SoftFloat32FPMaxNum(SoftFloat32.FPMaxNum);
|
||||||
SetDelegateInfo(new SoftFloat32FPMaxNumFpscr(SoftFloat32.FPMaxNumFpscr)); // A32 only.
|
var dlgSoftFloat32FPMaxNumFpscr = new SoftFloat32FPMaxNumFpscr(SoftFloat32.FPMaxNumFpscr); // A32 only.
|
||||||
SetDelegateInfo(new SoftFloat32FPMin(SoftFloat32.FPMin));
|
var dlgSoftFloat32FPMin = new SoftFloat32FPMin(SoftFloat32.FPMin);
|
||||||
SetDelegateInfo(new SoftFloat32FPMinFpscr(SoftFloat32.FPMinFpscr)); // A32 only.
|
var dlgSoftFloat32FPMinFpscr = new SoftFloat32FPMinFpscr(SoftFloat32.FPMinFpscr); // A32 only.
|
||||||
SetDelegateInfo(new SoftFloat32FPMinNum(SoftFloat32.FPMinNum));
|
var dlgSoftFloat32FPMinNum = new SoftFloat32FPMinNum(SoftFloat32.FPMinNum);
|
||||||
SetDelegateInfo(new SoftFloat32FPMinNumFpscr(SoftFloat32.FPMinNumFpscr)); // A32 only.
|
var dlgSoftFloat32FPMinNumFpscr = new SoftFloat32FPMinNumFpscr(SoftFloat32.FPMinNumFpscr); // A32 only.
|
||||||
SetDelegateInfo(new SoftFloat32FPMul(SoftFloat32.FPMul));
|
var dlgSoftFloat32FPMul = new SoftFloat32FPMul(SoftFloat32.FPMul);
|
||||||
SetDelegateInfo(new SoftFloat32FPMulFpscr(SoftFloat32.FPMulFpscr)); // A32 only.
|
var dlgSoftFloat32FPMulFpscr = new SoftFloat32FPMulFpscr(SoftFloat32.FPMulFpscr); // A32 only.
|
||||||
SetDelegateInfo(new SoftFloat32FPMulAdd(SoftFloat32.FPMulAdd));
|
var dlgSoftFloat32FPMulAdd = new SoftFloat32FPMulAdd(SoftFloat32.FPMulAdd);
|
||||||
SetDelegateInfo(new SoftFloat32FPMulAddFpscr(SoftFloat32.FPMulAddFpscr)); // A32 only.
|
var dlgSoftFloat32FPMulAddFpscr = new SoftFloat32FPMulAddFpscr(SoftFloat32.FPMulAddFpscr); // A32 only.
|
||||||
SetDelegateInfo(new SoftFloat32FPMulSub(SoftFloat32.FPMulSub));
|
var dlgSoftFloat32FPMulSub = new SoftFloat32FPMulSub(SoftFloat32.FPMulSub);
|
||||||
SetDelegateInfo(new SoftFloat32FPMulSubFpscr(SoftFloat32.FPMulSubFpscr)); // A32 only.
|
var dlgSoftFloat32FPMulSubFpscr = new SoftFloat32FPMulSubFpscr(SoftFloat32.FPMulSubFpscr); // A32 only.
|
||||||
SetDelegateInfo(new SoftFloat32FPMulX(SoftFloat32.FPMulX));
|
var dlgSoftFloat32FPMulX = new SoftFloat32FPMulX(SoftFloat32.FPMulX);
|
||||||
SetDelegateInfo(new SoftFloat32FPNegMulAdd(SoftFloat32.FPNegMulAdd));
|
var dlgSoftFloat32FPNegMulAdd = new SoftFloat32FPNegMulAdd(SoftFloat32.FPNegMulAdd);
|
||||||
SetDelegateInfo(new SoftFloat32FPNegMulSub(SoftFloat32.FPNegMulSub));
|
var dlgSoftFloat32FPNegMulSub = new SoftFloat32FPNegMulSub(SoftFloat32.FPNegMulSub);
|
||||||
SetDelegateInfo(new SoftFloat32FPRecipEstimate(SoftFloat32.FPRecipEstimate));
|
var dlgSoftFloat32FPRecipEstimate = new SoftFloat32FPRecipEstimate(SoftFloat32.FPRecipEstimate);
|
||||||
SetDelegateInfo(new SoftFloat32FPRecipEstimateFpscr(SoftFloat32.FPRecipEstimateFpscr)); // A32 only.
|
var dlgSoftFloat32FPRecipEstimateFpscr = new SoftFloat32FPRecipEstimateFpscr(SoftFloat32.FPRecipEstimateFpscr); // A32 only.
|
||||||
SetDelegateInfo(new SoftFloat32FPRecipStep(SoftFloat32.FPRecipStep)); // A32 only.
|
var dlgSoftFloat32FPRecipStep = new SoftFloat32FPRecipStep(SoftFloat32.FPRecipStep); // A32 only.
|
||||||
SetDelegateInfo(new SoftFloat32FPRecipStepFused(SoftFloat32.FPRecipStepFused));
|
var dlgSoftFloat32FPRecipStepFused = new SoftFloat32FPRecipStepFused(SoftFloat32.FPRecipStepFused);
|
||||||
SetDelegateInfo(new SoftFloat32FPRecpX(SoftFloat32.FPRecpX));
|
var dlgSoftFloat32FPRecpX = new SoftFloat32FPRecpX(SoftFloat32.FPRecpX);
|
||||||
SetDelegateInfo(new SoftFloat32FPRSqrtEstimate(SoftFloat32.FPRSqrtEstimate));
|
var dlgSoftFloat32FPRSqrtEstimate = new SoftFloat32FPRSqrtEstimate(SoftFloat32.FPRSqrtEstimate);
|
||||||
SetDelegateInfo(new SoftFloat32FPRSqrtEstimateFpscr(SoftFloat32.FPRSqrtEstimateFpscr)); // A32 only.
|
var dlgSoftFloat32FPRSqrtEstimateFpscr = new SoftFloat32FPRSqrtEstimateFpscr(SoftFloat32.FPRSqrtEstimateFpscr); // A32 only.
|
||||||
SetDelegateInfo(new SoftFloat32FPRSqrtStep(SoftFloat32.FPRSqrtStep)); // A32 only.
|
var dlgSoftFloat32FPRSqrtStep = new SoftFloat32FPRSqrtStep(SoftFloat32.FPRSqrtStep); // A32 only.
|
||||||
SetDelegateInfo(new SoftFloat32FPRSqrtStepFused(SoftFloat32.FPRSqrtStepFused));
|
var dlgSoftFloat32FPRSqrtStepFused = new SoftFloat32FPRSqrtStepFused(SoftFloat32.FPRSqrtStepFused);
|
||||||
SetDelegateInfo(new SoftFloat32FPSqrt(SoftFloat32.FPSqrt));
|
var dlgSoftFloat32FPSqrt = new SoftFloat32FPSqrt(SoftFloat32.FPSqrt);
|
||||||
SetDelegateInfo(new SoftFloat32FPSub(SoftFloat32.FPSub));
|
var dlgSoftFloat32FPSub = new SoftFloat32FPSub(SoftFloat32.FPSub);
|
||||||
|
|
||||||
SetDelegateInfo(new SoftFloat32_16FPConvert(SoftFloat32_16.FPConvert));
|
var dlgSoftFloat32_16FPConvert = new SoftFloat32_16FPConvert(SoftFloat32_16.FPConvert);
|
||||||
|
|
||||||
SetDelegateInfo(new SoftFloat64FPAdd(SoftFloat64.FPAdd));
|
var dlgSoftFloat64FPAdd = new SoftFloat64FPAdd(SoftFloat64.FPAdd);
|
||||||
SetDelegateInfo(new SoftFloat64FPAddFpscr(SoftFloat64.FPAddFpscr)); // A32 only.
|
var dlgSoftFloat64FPAddFpscr = new SoftFloat64FPAddFpscr(SoftFloat64.FPAddFpscr); // A32 only.
|
||||||
SetDelegateInfo(new SoftFloat64FPCompare(SoftFloat64.FPCompare));
|
var dlgSoftFloat64FPCompare = new SoftFloat64FPCompare(SoftFloat64.FPCompare);
|
||||||
SetDelegateInfo(new SoftFloat64FPCompareEQ(SoftFloat64.FPCompareEQ));
|
var dlgSoftFloat64FPCompareEQ = new SoftFloat64FPCompareEQ(SoftFloat64.FPCompareEQ);
|
||||||
SetDelegateInfo(new SoftFloat64FPCompareEQFpscr(SoftFloat64.FPCompareEQFpscr)); // A32 only.
|
var dlgSoftFloat64FPCompareEQFpscr = new SoftFloat64FPCompareEQFpscr(SoftFloat64.FPCompareEQFpscr); // A32 only.
|
||||||
SetDelegateInfo(new SoftFloat64FPCompareGE(SoftFloat64.FPCompareGE));
|
var dlgSoftFloat64FPCompareGE = new SoftFloat64FPCompareGE(SoftFloat64.FPCompareGE);
|
||||||
SetDelegateInfo(new SoftFloat64FPCompareGEFpscr(SoftFloat64.FPCompareGEFpscr)); // A32 only.
|
var dlgSoftFloat64FPCompareGEFpscr = new SoftFloat64FPCompareGEFpscr(SoftFloat64.FPCompareGEFpscr); // A32 only.
|
||||||
SetDelegateInfo(new SoftFloat64FPCompareGT(SoftFloat64.FPCompareGT));
|
var dlgSoftFloat64FPCompareGT = new SoftFloat64FPCompareGT(SoftFloat64.FPCompareGT);
|
||||||
SetDelegateInfo(new SoftFloat64FPCompareGTFpscr(SoftFloat64.FPCompareGTFpscr)); // A32 only.
|
var dlgSoftFloat64FPCompareGTFpscr = new SoftFloat64FPCompareGTFpscr(SoftFloat64.FPCompareGTFpscr); // A32 only.
|
||||||
SetDelegateInfo(new SoftFloat64FPCompareLE(SoftFloat64.FPCompareLE));
|
var dlgSoftFloat64FPCompareLE = new SoftFloat64FPCompareLE(SoftFloat64.FPCompareLE);
|
||||||
SetDelegateInfo(new SoftFloat64FPCompareLEFpscr(SoftFloat64.FPCompareLEFpscr)); // A32 only.
|
var dlgSoftFloat64FPCompareLEFpscr = new SoftFloat64FPCompareLEFpscr(SoftFloat64.FPCompareLEFpscr); // A32 only.
|
||||||
SetDelegateInfo(new SoftFloat64FPCompareLT(SoftFloat64.FPCompareLT));
|
var dlgSoftFloat64FPCompareLT = new SoftFloat64FPCompareLT(SoftFloat64.FPCompareLT);
|
||||||
SetDelegateInfo(new SoftFloat64FPCompareLTFpscr(SoftFloat64.FPCompareLTFpscr)); // A32 only.
|
var dlgSoftFloat64FPCompareLTFpscr = new SoftFloat64FPCompareLTFpscr(SoftFloat64.FPCompareLTFpscr); // A32 only.
|
||||||
SetDelegateInfo(new SoftFloat64FPDiv(SoftFloat64.FPDiv));
|
var dlgSoftFloat64FPDiv = new SoftFloat64FPDiv(SoftFloat64.FPDiv);
|
||||||
SetDelegateInfo(new SoftFloat64FPMax(SoftFloat64.FPMax));
|
var dlgSoftFloat64FPMax = new SoftFloat64FPMax(SoftFloat64.FPMax);
|
||||||
SetDelegateInfo(new SoftFloat64FPMaxFpscr(SoftFloat64.FPMaxFpscr)); // A32 only.
|
var dlgSoftFloat64FPMaxFpscr = new SoftFloat64FPMaxFpscr(SoftFloat64.FPMaxFpscr); // A32 only.
|
||||||
SetDelegateInfo(new SoftFloat64FPMaxNum(SoftFloat64.FPMaxNum));
|
var dlgSoftFloat64FPMaxNum = new SoftFloat64FPMaxNum(SoftFloat64.FPMaxNum);
|
||||||
SetDelegateInfo(new SoftFloat64FPMaxNumFpscr(SoftFloat64.FPMaxNumFpscr)); // A32 only.
|
var dlgSoftFloat64FPMaxNumFpscr = new SoftFloat64FPMaxNumFpscr(SoftFloat64.FPMaxNumFpscr); // A32 only.
|
||||||
SetDelegateInfo(new SoftFloat64FPMin(SoftFloat64.FPMin));
|
var dlgSoftFloat64FPMin = new SoftFloat64FPMin(SoftFloat64.FPMin);
|
||||||
SetDelegateInfo(new SoftFloat64FPMinFpscr(SoftFloat64.FPMinFpscr)); // A32 only.
|
var dlgSoftFloat64FPMinFpscr = new SoftFloat64FPMinFpscr(SoftFloat64.FPMinFpscr); // A32 only.
|
||||||
SetDelegateInfo(new SoftFloat64FPMinNum(SoftFloat64.FPMinNum));
|
var dlgSoftFloat64FPMinNum = new SoftFloat64FPMinNum(SoftFloat64.FPMinNum);
|
||||||
SetDelegateInfo(new SoftFloat64FPMinNumFpscr(SoftFloat64.FPMinNumFpscr)); // A32 only.
|
var dlgSoftFloat64FPMinNumFpscr = new SoftFloat64FPMinNumFpscr(SoftFloat64.FPMinNumFpscr); // A32 only.
|
||||||
SetDelegateInfo(new SoftFloat64FPMul(SoftFloat64.FPMul));
|
var dlgSoftFloat64FPMul = new SoftFloat64FPMul(SoftFloat64.FPMul);
|
||||||
SetDelegateInfo(new SoftFloat64FPMulFpscr(SoftFloat64.FPMulFpscr)); // A32 only.
|
var dlgSoftFloat64FPMulFpscr = new SoftFloat64FPMulFpscr(SoftFloat64.FPMulFpscr); // A32 only.
|
||||||
SetDelegateInfo(new SoftFloat64FPMulAdd(SoftFloat64.FPMulAdd));
|
var dlgSoftFloat64FPMulAdd = new SoftFloat64FPMulAdd(SoftFloat64.FPMulAdd);
|
||||||
SetDelegateInfo(new SoftFloat64FPMulAddFpscr(SoftFloat64.FPMulAddFpscr)); // A32 only.
|
var dlgSoftFloat64FPMulAddFpscr = new SoftFloat64FPMulAddFpscr(SoftFloat64.FPMulAddFpscr); // A32 only.
|
||||||
SetDelegateInfo(new SoftFloat64FPMulSub(SoftFloat64.FPMulSub));
|
var dlgSoftFloat64FPMulSub = new SoftFloat64FPMulSub(SoftFloat64.FPMulSub);
|
||||||
SetDelegateInfo(new SoftFloat64FPMulSubFpscr(SoftFloat64.FPMulSubFpscr)); // A32 only.
|
var dlgSoftFloat64FPMulSubFpscr = new SoftFloat64FPMulSubFpscr(SoftFloat64.FPMulSubFpscr); // A32 only.
|
||||||
SetDelegateInfo(new SoftFloat64FPMulX(SoftFloat64.FPMulX));
|
var dlgSoftFloat64FPMulX = new SoftFloat64FPMulX(SoftFloat64.FPMulX);
|
||||||
SetDelegateInfo(new SoftFloat64FPNegMulAdd(SoftFloat64.FPNegMulAdd));
|
var dlgSoftFloat64FPNegMulAdd = new SoftFloat64FPNegMulAdd(SoftFloat64.FPNegMulAdd);
|
||||||
SetDelegateInfo(new SoftFloat64FPNegMulSub(SoftFloat64.FPNegMulSub));
|
var dlgSoftFloat64FPNegMulSub = new SoftFloat64FPNegMulSub(SoftFloat64.FPNegMulSub);
|
||||||
SetDelegateInfo(new SoftFloat64FPRecipEstimate(SoftFloat64.FPRecipEstimate));
|
var dlgSoftFloat64FPRecipEstimate = new SoftFloat64FPRecipEstimate(SoftFloat64.FPRecipEstimate);
|
||||||
SetDelegateInfo(new SoftFloat64FPRecipEstimateFpscr(SoftFloat64.FPRecipEstimateFpscr)); // A32 only.
|
var dlgSoftFloat64FPRecipEstimateFpscr = new SoftFloat64FPRecipEstimateFpscr(SoftFloat64.FPRecipEstimateFpscr); // A32 only.
|
||||||
SetDelegateInfo(new SoftFloat64FPRecipStep(SoftFloat64.FPRecipStep)); // A32 only.
|
var dlgSoftFloat64FPRecipStep = new SoftFloat64FPRecipStep(SoftFloat64.FPRecipStep); // A32 only.
|
||||||
SetDelegateInfo(new SoftFloat64FPRecipStepFused(SoftFloat64.FPRecipStepFused));
|
var dlgSoftFloat64FPRecipStepFused = new SoftFloat64FPRecipStepFused(SoftFloat64.FPRecipStepFused);
|
||||||
SetDelegateInfo(new SoftFloat64FPRecpX(SoftFloat64.FPRecpX));
|
var dlgSoftFloat64FPRecpX = new SoftFloat64FPRecpX(SoftFloat64.FPRecpX);
|
||||||
SetDelegateInfo(new SoftFloat64FPRSqrtEstimate(SoftFloat64.FPRSqrtEstimate));
|
var dlgSoftFloat64FPRSqrtEstimate = new SoftFloat64FPRSqrtEstimate(SoftFloat64.FPRSqrtEstimate);
|
||||||
SetDelegateInfo(new SoftFloat64FPRSqrtEstimateFpscr(SoftFloat64.FPRSqrtEstimateFpscr)); // A32 only.
|
var dlgSoftFloat64FPRSqrtEstimateFpscr = new SoftFloat64FPRSqrtEstimateFpscr(SoftFloat64.FPRSqrtEstimateFpscr); // A32 only.
|
||||||
SetDelegateInfo(new SoftFloat64FPRSqrtStep(SoftFloat64.FPRSqrtStep)); // A32 only.
|
var dlgSoftFloat64FPRSqrtStep = new SoftFloat64FPRSqrtStep(SoftFloat64.FPRSqrtStep); // A32 only.
|
||||||
SetDelegateInfo(new SoftFloat64FPRSqrtStepFused(SoftFloat64.FPRSqrtStepFused));
|
var dlgSoftFloat64FPRSqrtStepFused = new SoftFloat64FPRSqrtStepFused(SoftFloat64.FPRSqrtStepFused);
|
||||||
SetDelegateInfo(new SoftFloat64FPSqrt(SoftFloat64.FPSqrt));
|
var dlgSoftFloat64FPSqrt = new SoftFloat64FPSqrt(SoftFloat64.FPSqrt);
|
||||||
SetDelegateInfo(new SoftFloat64FPSub(SoftFloat64.FPSub));
|
var dlgSoftFloat64FPSub = new SoftFloat64FPSub(SoftFloat64.FPSub);
|
||||||
|
|
||||||
SetDelegateInfo(new SoftFloat64_16FPConvert(SoftFloat64_16.FPConvert));
|
var dlgSoftFloat64_16FPConvert = new SoftFloat64_16FPConvert(SoftFloat64_16.FPConvert);
|
||||||
|
|
||||||
|
SetDelegateInfo(dlgMathAbs, Marshal.GetFunctionPointerForDelegate<MathAbs>(dlgMathAbs));
|
||||||
|
SetDelegateInfo(dlgMathCeiling, Marshal.GetFunctionPointerForDelegate<MathCeiling>(dlgMathCeiling));
|
||||||
|
SetDelegateInfo(dlgMathFloor, Marshal.GetFunctionPointerForDelegate<MathFloor>(dlgMathFloor));
|
||||||
|
SetDelegateInfo(dlgMathRound, Marshal.GetFunctionPointerForDelegate<MathRound>(dlgMathRound));
|
||||||
|
SetDelegateInfo(dlgMathTruncate, Marshal.GetFunctionPointerForDelegate<MathTruncate>(dlgMathTruncate));
|
||||||
|
|
||||||
|
SetDelegateInfo(dlgMathFAbs, Marshal.GetFunctionPointerForDelegate<MathFAbs>(dlgMathFAbs));
|
||||||
|
SetDelegateInfo(dlgMathFCeiling, Marshal.GetFunctionPointerForDelegate<MathFCeiling>(dlgMathFCeiling));
|
||||||
|
SetDelegateInfo(dlgMathFFloor, Marshal.GetFunctionPointerForDelegate<MathFFloor>(dlgMathFFloor));
|
||||||
|
SetDelegateInfo(dlgMathFRound, Marshal.GetFunctionPointerForDelegate<MathFRound>(dlgMathFRound));
|
||||||
|
SetDelegateInfo(dlgMathFTruncate, Marshal.GetFunctionPointerForDelegate<MathFTruncate>(dlgMathFTruncate));
|
||||||
|
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceBreak, Marshal.GetFunctionPointerForDelegate<NativeInterfaceBreak>(dlgNativeInterfaceBreak));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceCheckSynchronization, Marshal.GetFunctionPointerForDelegate<NativeInterfaceCheckSynchronization>(dlgNativeInterfaceCheckSynchronization));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceEnqueueForRejit, Marshal.GetFunctionPointerForDelegate<NativeInterfaceEnqueueForRejit>(dlgNativeInterfaceEnqueueForRejit));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceGetCntfrqEl0, Marshal.GetFunctionPointerForDelegate<NativeInterfaceGetCntfrqEl0>(dlgNativeInterfaceGetCntfrqEl0));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceGetCntpctEl0, Marshal.GetFunctionPointerForDelegate<NativeInterfaceGetCntpctEl0>(dlgNativeInterfaceGetCntpctEl0));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceGetCntvctEl0, Marshal.GetFunctionPointerForDelegate<NativeInterfaceGetCntvctEl0>(dlgNativeInterfaceGetCntvctEl0));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceGetCtrEl0, Marshal.GetFunctionPointerForDelegate<NativeInterfaceGetCtrEl0>(dlgNativeInterfaceGetCtrEl0));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceGetDczidEl0, Marshal.GetFunctionPointerForDelegate<NativeInterfaceGetDczidEl0>(dlgNativeInterfaceGetDczidEl0));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceGetFunctionAddress, Marshal.GetFunctionPointerForDelegate<NativeInterfaceGetFunctionAddress>(dlgNativeInterfaceGetFunctionAddress));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceInvalidateCacheLine, Marshal.GetFunctionPointerForDelegate<NativeInterfaceInvalidateCacheLine>(dlgNativeInterfaceInvalidateCacheLine));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceReadByte, Marshal.GetFunctionPointerForDelegate<NativeInterfaceReadByte>(dlgNativeInterfaceReadByte));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceReadUInt16, Marshal.GetFunctionPointerForDelegate<NativeInterfaceReadUInt16>(dlgNativeInterfaceReadUInt16));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceReadUInt32, Marshal.GetFunctionPointerForDelegate<NativeInterfaceReadUInt32>(dlgNativeInterfaceReadUInt32));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceReadUInt64, Marshal.GetFunctionPointerForDelegate<NativeInterfaceReadUInt64>(dlgNativeInterfaceReadUInt64));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceReadVector128, Marshal.GetFunctionPointerForDelegate<NativeInterfaceReadVector128>(dlgNativeInterfaceReadVector128));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceSignalMemoryTracking, Marshal.GetFunctionPointerForDelegate<NativeInterfaceSignalMemoryTracking>(dlgNativeInterfaceSignalMemoryTracking));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceSupervisorCall, Marshal.GetFunctionPointerForDelegate<NativeInterfaceSupervisorCall>(dlgNativeInterfaceSupervisorCall));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceThrowInvalidMemoryAccess, Marshal.GetFunctionPointerForDelegate<NativeInterfaceThrowInvalidMemoryAccess>(dlgNativeInterfaceThrowInvalidMemoryAccess));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceUndefined, Marshal.GetFunctionPointerForDelegate<NativeInterfaceUndefined>(dlgNativeInterfaceUndefined));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceWriteByte, Marshal.GetFunctionPointerForDelegate<NativeInterfaceWriteByte>(dlgNativeInterfaceWriteByte));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceWriteUInt16, Marshal.GetFunctionPointerForDelegate<NativeInterfaceWriteUInt16>(dlgNativeInterfaceWriteUInt16));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceWriteUInt32, Marshal.GetFunctionPointerForDelegate<NativeInterfaceWriteUInt32>(dlgNativeInterfaceWriteUInt32));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceWriteUInt64, Marshal.GetFunctionPointerForDelegate<NativeInterfaceWriteUInt64>(dlgNativeInterfaceWriteUInt64));
|
||||||
|
SetDelegateInfo(dlgNativeInterfaceWriteVector128, Marshal.GetFunctionPointerForDelegate<NativeInterfaceWriteVector128>(dlgNativeInterfaceWriteVector128));
|
||||||
|
|
||||||
|
SetDelegateInfo(dlgSoftFallbackCountLeadingSigns, Marshal.GetFunctionPointerForDelegate<SoftFallbackCountLeadingSigns>(dlgSoftFallbackCountLeadingSigns));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackCountLeadingZeros, Marshal.GetFunctionPointerForDelegate<SoftFallbackCountLeadingZeros>(dlgSoftFallbackCountLeadingZeros));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackCrc32b, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32b>(dlgSoftFallbackCrc32b));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackCrc32cb, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32cb>(dlgSoftFallbackCrc32cb));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackCrc32ch, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32ch>(dlgSoftFallbackCrc32ch));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackCrc32cw, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32cw>(dlgSoftFallbackCrc32cw));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackCrc32cx, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32cx>(dlgSoftFallbackCrc32cx));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackCrc32h, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32h>(dlgSoftFallbackCrc32h));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackCrc32w, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32w>(dlgSoftFallbackCrc32w));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackCrc32x, Marshal.GetFunctionPointerForDelegate<SoftFallbackCrc32x>(dlgSoftFallbackCrc32x));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackDecrypt, Marshal.GetFunctionPointerForDelegate<SoftFallbackDecrypt>(dlgSoftFallbackDecrypt));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackEncrypt, Marshal.GetFunctionPointerForDelegate<SoftFallbackEncrypt>(dlgSoftFallbackEncrypt));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackFixedRotate, Marshal.GetFunctionPointerForDelegate<SoftFallbackFixedRotate>(dlgSoftFallbackFixedRotate));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackHashChoose, Marshal.GetFunctionPointerForDelegate<SoftFallbackHashChoose>(dlgSoftFallbackHashChoose));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackHashLower, Marshal.GetFunctionPointerForDelegate<SoftFallbackHashLower>(dlgSoftFallbackHashLower));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackHashMajority, Marshal.GetFunctionPointerForDelegate<SoftFallbackHashMajority>(dlgSoftFallbackHashMajority));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackHashParity, Marshal.GetFunctionPointerForDelegate<SoftFallbackHashParity>(dlgSoftFallbackHashParity));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackHashUpper, Marshal.GetFunctionPointerForDelegate<SoftFallbackHashUpper>(dlgSoftFallbackHashUpper));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackInverseMixColumns, Marshal.GetFunctionPointerForDelegate<SoftFallbackInverseMixColumns>(dlgSoftFallbackInverseMixColumns));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackMixColumns, Marshal.GetFunctionPointerForDelegate<SoftFallbackMixColumns>(dlgSoftFallbackMixColumns));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackPolynomialMult64_128, Marshal.GetFunctionPointerForDelegate<SoftFallbackPolynomialMult64_128>(dlgSoftFallbackPolynomialMult64_128));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackSatF32ToS32, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF32ToS32>(dlgSoftFallbackSatF32ToS32));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackSatF32ToS64, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF32ToS64>(dlgSoftFallbackSatF32ToS64));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackSatF32ToU32, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF32ToU32>(dlgSoftFallbackSatF32ToU32));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackSatF32ToU64, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF32ToU64>(dlgSoftFallbackSatF32ToU64));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackSatF64ToS32, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF64ToS32>(dlgSoftFallbackSatF64ToS32));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackSatF64ToS64, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF64ToS64>(dlgSoftFallbackSatF64ToS64));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackSatF64ToU32, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF64ToU32>(dlgSoftFallbackSatF64ToU32));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackSatF64ToU64, Marshal.GetFunctionPointerForDelegate<SoftFallbackSatF64ToU64>(dlgSoftFallbackSatF64ToU64));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackSha1SchedulePart1, Marshal.GetFunctionPointerForDelegate<SoftFallbackSha1SchedulePart1>(dlgSoftFallbackSha1SchedulePart1));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackSha1SchedulePart2, Marshal.GetFunctionPointerForDelegate<SoftFallbackSha1SchedulePart2>(dlgSoftFallbackSha1SchedulePart2));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackSha256SchedulePart1, Marshal.GetFunctionPointerForDelegate<SoftFallbackSha256SchedulePart1>(dlgSoftFallbackSha256SchedulePart1));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackSha256SchedulePart2, Marshal.GetFunctionPointerForDelegate<SoftFallbackSha256SchedulePart2>(dlgSoftFallbackSha256SchedulePart2));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackSignedShrImm64, Marshal.GetFunctionPointerForDelegate<SoftFallbackSignedShrImm64>(dlgSoftFallbackSignedShrImm64));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackTbl1, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbl1>(dlgSoftFallbackTbl1));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackTbl2, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbl2>(dlgSoftFallbackTbl2));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackTbl3, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbl3>(dlgSoftFallbackTbl3));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackTbl4, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbl4>(dlgSoftFallbackTbl4));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackTbx1, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbx1>(dlgSoftFallbackTbx1));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackTbx2, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbx2>(dlgSoftFallbackTbx2));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackTbx3, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbx3>(dlgSoftFallbackTbx3));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackTbx4, Marshal.GetFunctionPointerForDelegate<SoftFallbackTbx4>(dlgSoftFallbackTbx4));
|
||||||
|
SetDelegateInfo(dlgSoftFallbackUnsignedShrImm64, Marshal.GetFunctionPointerForDelegate<SoftFallbackUnsignedShrImm64>(dlgSoftFallbackUnsignedShrImm64));
|
||||||
|
|
||||||
|
SetDelegateInfo(dlgSoftFloat16_32FPConvert, Marshal.GetFunctionPointerForDelegate<SoftFloat16_32FPConvert>(dlgSoftFloat16_32FPConvert));
|
||||||
|
SetDelegateInfo(dlgSoftFloat16_64FPConvert, Marshal.GetFunctionPointerForDelegate<SoftFloat16_64FPConvert>(dlgSoftFloat16_64FPConvert));
|
||||||
|
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPAdd, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPAdd>(dlgSoftFloat32FPAdd));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPAddFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPAddFpscr>(dlgSoftFloat32FPAddFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPCompare, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompare>(dlgSoftFloat32FPCompare));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPCompareEQ, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareEQ>(dlgSoftFloat32FPCompareEQ));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPCompareEQFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareEQFpscr>(dlgSoftFloat32FPCompareEQFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPCompareGE, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareGE>(dlgSoftFloat32FPCompareGE));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPCompareGEFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareGEFpscr>(dlgSoftFloat32FPCompareGEFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPCompareGT, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareGT>(dlgSoftFloat32FPCompareGT));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPCompareGTFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareGTFpscr>(dlgSoftFloat32FPCompareGTFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPCompareLE, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareLE>(dlgSoftFloat32FPCompareLE));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPCompareLEFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareLEFpscr>(dlgSoftFloat32FPCompareLEFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPCompareLT, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareLT>(dlgSoftFloat32FPCompareLT));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPCompareLTFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPCompareLTFpscr>(dlgSoftFloat32FPCompareLTFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPDiv, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPDiv>(dlgSoftFloat32FPDiv));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPMax, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMax>(dlgSoftFloat32FPMax));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPMaxFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMaxFpscr>(dlgSoftFloat32FPMaxFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPMaxNum, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMaxNum>(dlgSoftFloat32FPMaxNum));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPMaxNumFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMaxNumFpscr>(dlgSoftFloat32FPMaxNumFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPMin, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMin>(dlgSoftFloat32FPMin));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPMinFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMinFpscr>(dlgSoftFloat32FPMinFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPMinNum, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMinNum>(dlgSoftFloat32FPMinNum));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPMinNumFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMinNumFpscr>(dlgSoftFloat32FPMinNumFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPMul, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMul>(dlgSoftFloat32FPMul));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPMulFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMulFpscr>(dlgSoftFloat32FPMulFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPMulAdd, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMulAdd>(dlgSoftFloat32FPMulAdd));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPMulAddFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMulAddFpscr>(dlgSoftFloat32FPMulAddFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPMulSub, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMulSub>(dlgSoftFloat32FPMulSub));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPMulSubFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMulSubFpscr>(dlgSoftFloat32FPMulSubFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPMulX, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPMulX>(dlgSoftFloat32FPMulX));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPNegMulAdd, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPNegMulAdd>(dlgSoftFloat32FPNegMulAdd));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPNegMulSub, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPNegMulSub>(dlgSoftFloat32FPNegMulSub));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPRecipEstimate, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRecipEstimate>(dlgSoftFloat32FPRecipEstimate));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPRecipEstimateFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRecipEstimateFpscr>(dlgSoftFloat32FPRecipEstimateFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPRecipStep, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRecipStep>(dlgSoftFloat32FPRecipStep)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPRecipStepFused, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRecipStepFused>(dlgSoftFloat32FPRecipStepFused));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPRecpX, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRecpX>(dlgSoftFloat32FPRecpX));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPRSqrtEstimate, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRSqrtEstimate>(dlgSoftFloat32FPRSqrtEstimate));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPRSqrtEstimateFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRSqrtEstimateFpscr>(dlgSoftFloat32FPRSqrtEstimateFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPRSqrtStep, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRSqrtStep>(dlgSoftFloat32FPRSqrtStep)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPRSqrtStepFused, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPRSqrtStepFused>(dlgSoftFloat32FPRSqrtStepFused));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPSqrt, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPSqrt>(dlgSoftFloat32FPSqrt));
|
||||||
|
SetDelegateInfo(dlgSoftFloat32FPSub, Marshal.GetFunctionPointerForDelegate<SoftFloat32FPSub>(dlgSoftFloat32FPSub));
|
||||||
|
|
||||||
|
SetDelegateInfo(dlgSoftFloat32_16FPConvert, Marshal.GetFunctionPointerForDelegate<SoftFloat32_16FPConvert>(dlgSoftFloat32_16FPConvert));
|
||||||
|
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPAdd, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPAdd>(dlgSoftFloat64FPAdd));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPAddFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPAddFpscr>(dlgSoftFloat64FPAddFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPCompare, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompare>(dlgSoftFloat64FPCompare));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPCompareEQ, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareEQ>(dlgSoftFloat64FPCompareEQ));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPCompareEQFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareEQFpscr>(dlgSoftFloat64FPCompareEQFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPCompareGE, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareGE>(dlgSoftFloat64FPCompareGE));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPCompareGEFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareGEFpscr>(dlgSoftFloat64FPCompareGEFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPCompareGT, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareGT>(dlgSoftFloat64FPCompareGT));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPCompareGTFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareGTFpscr>(dlgSoftFloat64FPCompareGTFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPCompareLE, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareLE>(dlgSoftFloat64FPCompareLE));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPCompareLEFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareLEFpscr>(dlgSoftFloat64FPCompareLEFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPCompareLT, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareLT>(dlgSoftFloat64FPCompareLT));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPCompareLTFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPCompareLTFpscr>(dlgSoftFloat64FPCompareLTFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPDiv, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPDiv>(dlgSoftFloat64FPDiv));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPMax, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMax>(dlgSoftFloat64FPMax));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPMaxFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMaxFpscr>(dlgSoftFloat64FPMaxFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPMaxNum, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMaxNum>(dlgSoftFloat64FPMaxNum));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPMaxNumFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMaxNumFpscr>(dlgSoftFloat64FPMaxNumFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPMin, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMin>(dlgSoftFloat64FPMin));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPMinFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMinFpscr>(dlgSoftFloat64FPMinFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPMinNum, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMinNum>(dlgSoftFloat64FPMinNum));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPMinNumFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMinNumFpscr>(dlgSoftFloat64FPMinNumFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPMul, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMul>(dlgSoftFloat64FPMul));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPMulFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMulFpscr>(dlgSoftFloat64FPMulFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPMulAdd, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMulAdd>(dlgSoftFloat64FPMulAdd));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPMulAddFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMulAddFpscr>(dlgSoftFloat64FPMulAddFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPMulSub, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMulSub>(dlgSoftFloat64FPMulSub));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPMulSubFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMulSubFpscr>(dlgSoftFloat64FPMulSubFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPMulX, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPMulX>(dlgSoftFloat64FPMulX));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPNegMulAdd, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPNegMulAdd>(dlgSoftFloat64FPNegMulAdd));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPNegMulSub, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPNegMulSub>(dlgSoftFloat64FPNegMulSub));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPRecipEstimate, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRecipEstimate>(dlgSoftFloat64FPRecipEstimate));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPRecipEstimateFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRecipEstimateFpscr>(dlgSoftFloat64FPRecipEstimateFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPRecipStep, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRecipStep>(dlgSoftFloat64FPRecipStep)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPRecipStepFused, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRecipStepFused>(dlgSoftFloat64FPRecipStepFused));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPRecpX, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRecpX>(dlgSoftFloat64FPRecpX));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPRSqrtEstimate, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRSqrtEstimate>(dlgSoftFloat64FPRSqrtEstimate));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPRSqrtEstimateFpscr, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRSqrtEstimateFpscr>(dlgSoftFloat64FPRSqrtEstimateFpscr)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPRSqrtStep, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRSqrtStep>(dlgSoftFloat64FPRSqrtStep)); // A32 only.
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPRSqrtStepFused, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPRSqrtStepFused>(dlgSoftFloat64FPRSqrtStepFused));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPSqrt, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPSqrt>(dlgSoftFloat64FPSqrt));
|
||||||
|
SetDelegateInfo(dlgSoftFloat64FPSub, Marshal.GetFunctionPointerForDelegate<SoftFloat64FPSub>(dlgSoftFloat64FPSub));
|
||||||
|
|
||||||
|
SetDelegateInfo(dlgSoftFloat64_16FPConvert, Marshal.GetFunctionPointerForDelegate<SoftFloat64_16FPConvert>(dlgSoftFloat64_16FPConvert));
|
||||||
}
|
}
|
||||||
|
|
||||||
private delegate double MathAbs(double value);
|
private delegate double MathAbs(double value);
|
||||||
|
@ -80,7 +80,10 @@ namespace ARMeilleure.Translation
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Monitor.Wait(Sync);
|
if (!_disposed)
|
||||||
|
{
|
||||||
|
Monitor.Wait(Sync);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,13 +1,33 @@
|
|||||||
|
using Ryujinx.Common.Utilities;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Common.GraphicsDriver
|
namespace Ryujinx.Common.GraphicsDriver
|
||||||
{
|
{
|
||||||
public static class DriverUtilities
|
public static class DriverUtilities
|
||||||
{
|
{
|
||||||
|
private static void AddMesaFlags(string envVar, string newFlags)
|
||||||
|
{
|
||||||
|
string existingFlags = Environment.GetEnvironmentVariable(envVar);
|
||||||
|
|
||||||
|
string flags = existingFlags == null ? newFlags : $"{existingFlags},{newFlags}";
|
||||||
|
|
||||||
|
OsUtils.SetEnvironmentVariableNoCaching(envVar, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void InitDriverConfig(bool oglThreading)
|
||||||
|
{
|
||||||
|
if (OperatingSystem.IsLinux())
|
||||||
|
{
|
||||||
|
AddMesaFlags("RADV_DEBUG", "nodcc");
|
||||||
|
}
|
||||||
|
|
||||||
|
ToggleOGLThreading(oglThreading);
|
||||||
|
}
|
||||||
|
|
||||||
public static void ToggleOGLThreading(bool enabled)
|
public static void ToggleOGLThreading(bool enabled)
|
||||||
{
|
{
|
||||||
Environment.SetEnvironmentVariable("mesa_glthread", enabled.ToString().ToLower());
|
OsUtils.SetEnvironmentVariableNoCaching("mesa_glthread", enabled.ToString().ToLower());
|
||||||
Environment.SetEnvironmentVariable("__GL_THREADED_OPTIMIZATIONS", enabled ? "1" : "0");
|
OsUtils.SetEnvironmentVariableNoCaching("__GL_THREADED_OPTIMIZATIONS", enabled ? "1" : "0");
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
24
src/Ryujinx.Common/Utilities/OsUtils.cs
Normal file
24
src/Ryujinx.Common/Utilities/OsUtils.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace Ryujinx.Common.Utilities
|
||||||
|
{
|
||||||
|
public partial class OsUtils
|
||||||
|
{
|
||||||
|
[LibraryImport("libc", SetLastError = true)]
|
||||||
|
private static partial int setenv([MarshalAs(UnmanagedType.LPStr)] string name, [MarshalAs(UnmanagedType.LPStr)] string value, int overwrite);
|
||||||
|
|
||||||
|
public static void SetEnvironmentVariableNoCaching(string key, string value)
|
||||||
|
{
|
||||||
|
// Set the value in the cached environment variables, too.
|
||||||
|
Environment.SetEnvironmentVariable(key, value);
|
||||||
|
|
||||||
|
if (!OperatingSystem.IsWindows())
|
||||||
|
{
|
||||||
|
int res = setenv(key, value, 1);
|
||||||
|
Debug.Assert(res != -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -39,7 +39,10 @@ namespace Ryujinx.Graphics.Device
|
|||||||
{
|
{
|
||||||
var field = fields[fieldIndex];
|
var field = fields[fieldIndex];
|
||||||
|
|
||||||
int sizeOfField = SizeCalculator.SizeOf(field.FieldType);
|
var currentFieldOffset = (int)Marshal.OffsetOf<TState>(field.Name);
|
||||||
|
var nextFieldOffset = fieldIndex + 1 == fields.Length ? Unsafe.SizeOf<TState>() : (int)Marshal.OffsetOf<TState>(fields[fieldIndex + 1].Name);
|
||||||
|
|
||||||
|
int sizeOfField = nextFieldOffset - currentFieldOffset;
|
||||||
|
|
||||||
for (int i = 0; i < ((sizeOfField + 3) & ~3); i += 4)
|
for (int i = 0; i < ((sizeOfField + 3) & ~3); i += 4)
|
||||||
{
|
{
|
||||||
|
@ -1,63 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Device
|
|
||||||
{
|
|
||||||
public static class SizeCalculator
|
|
||||||
{
|
|
||||||
public static int SizeOf(Type type)
|
|
||||||
{
|
|
||||||
// Is type a enum type?
|
|
||||||
if (type.IsEnum)
|
|
||||||
{
|
|
||||||
type = type.GetEnumUnderlyingType();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is type a pointer type?
|
|
||||||
if (type.IsPointer || type == typeof(IntPtr) || type == typeof(UIntPtr))
|
|
||||||
{
|
|
||||||
return IntPtr.Size;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is type a struct type?
|
|
||||||
if (type.IsValueType && !type.IsPrimitive)
|
|
||||||
{
|
|
||||||
// Check if the struct has a explicit size, if so, return that.
|
|
||||||
if (type.StructLayoutAttribute.Size != 0)
|
|
||||||
{
|
|
||||||
return type.StructLayoutAttribute.Size;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise we calculate the sum of the sizes of all fields.
|
|
||||||
int size = 0;
|
|
||||||
var fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
|
||||||
|
|
||||||
for (int fieldIndex = 0; fieldIndex < fields.Length; fieldIndex++)
|
|
||||||
{
|
|
||||||
size += SizeOf(fields[fieldIndex].FieldType);
|
|
||||||
}
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Primitive types.
|
|
||||||
return (Type.GetTypeCode(type)) switch
|
|
||||||
{
|
|
||||||
TypeCode.SByte => sizeof(sbyte),
|
|
||||||
TypeCode.Byte => sizeof(byte),
|
|
||||||
TypeCode.Int16 => sizeof(short),
|
|
||||||
TypeCode.UInt16 => sizeof(ushort),
|
|
||||||
TypeCode.Int32 => sizeof(int),
|
|
||||||
TypeCode.UInt32 => sizeof(uint),
|
|
||||||
TypeCode.Int64 => sizeof(long),
|
|
||||||
TypeCode.UInt64 => sizeof(ulong),
|
|
||||||
TypeCode.Char => sizeof(char),
|
|
||||||
TypeCode.Single => sizeof(float),
|
|
||||||
TypeCode.Double => sizeof(double),
|
|
||||||
TypeCode.Decimal => sizeof(decimal),
|
|
||||||
TypeCode.Boolean => sizeof(bool),
|
|
||||||
_ => throw new ArgumentException($"Length for type \"{type.Name}\" is unknown."),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -276,8 +276,6 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
|
|||||||
dstBaseOffset += dstStride * (yCount - 1);
|
dstBaseOffset += dstStride * (yCount - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadOnlySpan<byte> srcSpan = memoryManager.GetSpan(srcGpuVa + (ulong)srcBaseOffset, srcSize, true);
|
|
||||||
|
|
||||||
// If remapping is disabled, we always copy the components directly, in order.
|
// If remapping is disabled, we always copy the components directly, in order.
|
||||||
// If it's enabled, but the mapping is just XYZW, we also copy them in order.
|
// If it's enabled, but the mapping is just XYZW, we also copy them in order.
|
||||||
bool isIdentityRemap = !remap ||
|
bool isIdentityRemap = !remap ||
|
||||||
@ -289,6 +287,52 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
|
|||||||
bool completeSource = IsTextureCopyComplete(src, srcLinear, srcBpp, srcStride, xCount, yCount);
|
bool completeSource = IsTextureCopyComplete(src, srcLinear, srcBpp, srcStride, xCount, yCount);
|
||||||
bool completeDest = IsTextureCopyComplete(dst, dstLinear, dstBpp, dstStride, xCount, yCount);
|
bool completeDest = IsTextureCopyComplete(dst, dstLinear, dstBpp, dstStride, xCount, yCount);
|
||||||
|
|
||||||
|
// Check if the source texture exists on the GPU, if it does, do a GPU side copy.
|
||||||
|
// Otherwise, we would need to flush the source texture which is costly.
|
||||||
|
// We don't expect the source to be linear in such cases, as linear source usually indicates buffer or CPU written data.
|
||||||
|
|
||||||
|
if (completeSource && completeDest && !srcLinear && isIdentityRemap)
|
||||||
|
{
|
||||||
|
var source = memoryManager.Physical.TextureCache.FindTexture(
|
||||||
|
memoryManager,
|
||||||
|
srcGpuVa,
|
||||||
|
srcBpp,
|
||||||
|
srcStride,
|
||||||
|
src.Height,
|
||||||
|
xCount,
|
||||||
|
yCount,
|
||||||
|
srcLinear,
|
||||||
|
src.MemoryLayout.UnpackGobBlocksInY(),
|
||||||
|
src.MemoryLayout.UnpackGobBlocksInZ());
|
||||||
|
|
||||||
|
if (source != null && source.Height == yCount)
|
||||||
|
{
|
||||||
|
source.SynchronizeMemory();
|
||||||
|
|
||||||
|
var target = memoryManager.Physical.TextureCache.FindOrCreateTexture(
|
||||||
|
memoryManager,
|
||||||
|
source.Info.FormatInfo,
|
||||||
|
dstGpuVa,
|
||||||
|
xCount,
|
||||||
|
yCount,
|
||||||
|
dstStride,
|
||||||
|
dstLinear,
|
||||||
|
dst.MemoryLayout.UnpackGobBlocksInY(),
|
||||||
|
dst.MemoryLayout.UnpackGobBlocksInZ());
|
||||||
|
|
||||||
|
if (source.ScaleFactor != target.ScaleFactor)
|
||||||
|
{
|
||||||
|
target.PropagateScale(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
source.HostTexture.CopyTo(target.HostTexture, 0, 0);
|
||||||
|
target.SignalModified();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadOnlySpan<byte> srcSpan = memoryManager.GetSpan(srcGpuVa + (ulong)srcBaseOffset, srcSize, true);
|
||||||
|
|
||||||
// Try to set the texture data directly,
|
// Try to set the texture data directly,
|
||||||
// but only if we are doing a complete copy,
|
// but only if we are doing a complete copy,
|
||||||
// and not for block linear to linear copies, since those are typically accessed from the CPU.
|
// and not for block linear to linear copies, since those are typically accessed from the CPU.
|
||||||
|
@ -79,7 +79,10 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
{
|
{
|
||||||
var field = fields[fieldIndex];
|
var field = fields[fieldIndex];
|
||||||
|
|
||||||
int sizeOfField = SizeCalculator.SizeOf(field.FieldType);
|
var currentFieldOffset = (int)Marshal.OffsetOf<TState>(field.Name);
|
||||||
|
var nextFieldOffset = fieldIndex + 1 == fields.Length ? Unsafe.SizeOf<TState>() : (int)Marshal.OffsetOf<TState>(fields[fieldIndex + 1].Name);
|
||||||
|
|
||||||
|
int sizeOfField = nextFieldOffset - currentFieldOffset;
|
||||||
|
|
||||||
if (fieldToDelegate.TryGetValue(field.Name, out int entryIndex))
|
if (fieldToDelegate.TryGetValue(field.Name, out int entryIndex))
|
||||||
{
|
{
|
||||||
|
@ -415,7 +415,13 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
#pragma warning disable CS0649 // Field is never assigned to
|
#pragma warning disable CS0649 // Field is never assigned to
|
||||||
public int Width;
|
public int Width;
|
||||||
public int Height;
|
public int Height;
|
||||||
public int Depth;
|
public ushort Depth;
|
||||||
|
public ushort Flags;
|
||||||
|
|
||||||
|
public readonly bool UnpackIsLayered()
|
||||||
|
{
|
||||||
|
return (Flags & 1) == 0;
|
||||||
|
}
|
||||||
#pragma warning restore CS0649
|
#pragma warning restore CS0649
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,7 +340,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
/// <returns>True if any used entries of the pool might have been modified, false otherwise</returns>
|
/// <returns>True if any used entries of the pool might have been modified, false otherwise</returns>
|
||||||
public bool SamplerPoolModified()
|
public bool SamplerPoolModified()
|
||||||
{
|
{
|
||||||
return SamplerPool.WasModified(ref _samplerPoolSequence);
|
return SamplerPool != null && SamplerPool.WasModified(ref _samplerPoolSequence);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -516,12 +516,15 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if any of our cached samplers changed on the pool.
|
// Check if any of our cached samplers changed on the pool.
|
||||||
foreach ((int samplerId, (Sampler sampler, SamplerDescriptor descriptor)) in SamplerIds)
|
if (SamplerPool != null)
|
||||||
{
|
{
|
||||||
if (SamplerPool.GetCachedItem(samplerId) != sampler ||
|
foreach ((int samplerId, (Sampler sampler, SamplerDescriptor descriptor)) in SamplerIds)
|
||||||
(sampler == null && SamplerPool.IsValidId(samplerId) && !SamplerPool.GetDescriptorRef(samplerId).Equals(descriptor)))
|
|
||||||
{
|
{
|
||||||
return true;
|
if (SamplerPool.GetCachedItem(samplerId) != sampler ||
|
||||||
|
(sampler == null && SamplerPool.IsValidId(samplerId) && !SamplerPool.GetDescriptorRef(samplerId).Equals(descriptor)))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -899,13 +902,19 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Sampler sampler = samplerPool?.Get(samplerId);
|
|
||||||
|
|
||||||
entry.TextureIds[textureId] = (texture, descriptor);
|
entry.TextureIds[textureId] = (texture, descriptor);
|
||||||
entry.SamplerIds[samplerId] = (sampler, samplerPool?.GetDescriptorRef(samplerId) ?? default);
|
|
||||||
|
|
||||||
ITexture hostTexture = texture?.GetTargetTexture(bindingInfo.Target);
|
ITexture hostTexture = texture?.GetTargetTexture(bindingInfo.Target);
|
||||||
ISampler hostSampler = sampler?.GetHostSampler(texture);
|
ISampler hostSampler = null;
|
||||||
|
|
||||||
|
if (!isImage && bindingInfo.Target != Target.TextureBuffer)
|
||||||
|
{
|
||||||
|
Sampler sampler = samplerPool?.Get(samplerId);
|
||||||
|
|
||||||
|
entry.SamplerIds[samplerId] = (sampler, samplerPool?.GetDescriptorRef(samplerId) ?? default);
|
||||||
|
|
||||||
|
hostSampler = sampler?.GetHostSampler(texture);
|
||||||
|
}
|
||||||
|
|
||||||
Format format = bindingInfo.Format;
|
Format format = bindingInfo.Format;
|
||||||
|
|
||||||
|
@ -347,6 +347,53 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to find an existing texture, or create a new one if not found.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="memoryManager">GPU memory manager where the texture is mapped</param>
|
||||||
|
/// <param name="formatInfo">Format of the texture</param>
|
||||||
|
/// <param name="gpuAddress">GPU virtual address of the texture</param>
|
||||||
|
/// <param name="xCount">Texture width in bytes</param>
|
||||||
|
/// <param name="yCount">Texture height</param>
|
||||||
|
/// <param name="stride">Texture stride if linear, otherwise ignored</param>
|
||||||
|
/// <param name="isLinear">Indicates if the texture is linear or block linear</param>
|
||||||
|
/// <param name="gobBlocksInY">GOB blocks in Y for block linear textures</param>
|
||||||
|
/// <param name="gobBlocksInZ">GOB blocks in Z for 3D block linear textures</param>
|
||||||
|
/// <returns>The texture</returns>
|
||||||
|
public Texture FindOrCreateTexture(
|
||||||
|
MemoryManager memoryManager,
|
||||||
|
FormatInfo formatInfo,
|
||||||
|
ulong gpuAddress,
|
||||||
|
int xCount,
|
||||||
|
int yCount,
|
||||||
|
int stride,
|
||||||
|
bool isLinear,
|
||||||
|
int gobBlocksInY,
|
||||||
|
int gobBlocksInZ)
|
||||||
|
{
|
||||||
|
TextureInfo info = new(
|
||||||
|
gpuAddress,
|
||||||
|
xCount / formatInfo.BytesPerPixel,
|
||||||
|
yCount,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
stride,
|
||||||
|
isLinear,
|
||||||
|
gobBlocksInY,
|
||||||
|
gobBlocksInZ,
|
||||||
|
1,
|
||||||
|
Target.Texture2D,
|
||||||
|
formatInfo);
|
||||||
|
|
||||||
|
Texture texture = FindOrCreateTexture(memoryManager, TextureSearchFlags.ForCopy, info, 0, sizeHint: new Size(xCount, yCount, 1));
|
||||||
|
|
||||||
|
texture?.SynchronizeMemory();
|
||||||
|
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tries to find an existing texture, or create a new one if not found.
|
/// Tries to find an existing texture, or create a new one if not found.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -468,13 +515,11 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
int gobBlocksInY = dsState.MemoryLayout.UnpackGobBlocksInY();
|
int gobBlocksInY = dsState.MemoryLayout.UnpackGobBlocksInY();
|
||||||
int gobBlocksInZ = dsState.MemoryLayout.UnpackGobBlocksInZ();
|
int gobBlocksInZ = dsState.MemoryLayout.UnpackGobBlocksInZ();
|
||||||
|
|
||||||
|
layered &= size.UnpackIsLayered();
|
||||||
|
|
||||||
Target target;
|
Target target;
|
||||||
|
|
||||||
if (dsState.MemoryLayout.UnpackIsTarget3D())
|
if ((samplesInX | samplesInY) != 1)
|
||||||
{
|
|
||||||
target = Target.Texture3D;
|
|
||||||
}
|
|
||||||
else if ((samplesInX | samplesInY) != 1)
|
|
||||||
{
|
{
|
||||||
target = size.Depth > 1 && layered
|
target = size.Depth > 1 && layered
|
||||||
? Target.Texture2DMultisampleArray
|
? Target.Texture2DMultisampleArray
|
||||||
|
@ -32,10 +32,12 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
CommandBuffer
|
CommandBuffer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool _feedbackLoopActive;
|
||||||
private PipelineStageFlags _incoherentBufferWriteStages;
|
private PipelineStageFlags _incoherentBufferWriteStages;
|
||||||
private PipelineStageFlags _incoherentTextureWriteStages;
|
private PipelineStageFlags _incoherentTextureWriteStages;
|
||||||
private PipelineStageFlags _extraStages;
|
private PipelineStageFlags _extraStages;
|
||||||
private IncoherentBarrierType _queuedIncoherentBarrier;
|
private IncoherentBarrierType _queuedIncoherentBarrier;
|
||||||
|
private bool _queuedFeedbackLoopBarrier;
|
||||||
|
|
||||||
public BarrierBatch(VulkanRenderer gd)
|
public BarrierBatch(VulkanRenderer gd)
|
||||||
{
|
{
|
||||||
@ -53,17 +55,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
stages |= PipelineStageFlags.TransformFeedbackBitExt;
|
stages |= PipelineStageFlags.TransformFeedbackBitExt;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gd.IsTBDR)
|
|
||||||
{
|
|
||||||
// Desktop GPUs can transform image barriers into memory barriers.
|
|
||||||
|
|
||||||
access |= AccessFlags.DepthStencilAttachmentWriteBit | AccessFlags.ColorAttachmentWriteBit;
|
|
||||||
access |= AccessFlags.DepthStencilAttachmentReadBit | AccessFlags.ColorAttachmentReadBit;
|
|
||||||
|
|
||||||
stages |= PipelineStageFlags.EarlyFragmentTestsBit | PipelineStageFlags.LateFragmentTestsBit;
|
|
||||||
stages |= PipelineStageFlags.ColorAttachmentOutputBit;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (access, stages);
|
return (access, stages);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,16 +169,34 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
}
|
}
|
||||||
|
|
||||||
_queuedIncoherentBarrier = IncoherentBarrierType.None;
|
_queuedIncoherentBarrier = IncoherentBarrierType.None;
|
||||||
|
_queuedFeedbackLoopBarrier = false;
|
||||||
}
|
}
|
||||||
|
else if (_feedbackLoopActive && _queuedFeedbackLoopBarrier)
|
||||||
|
{
|
||||||
|
// Feedback loop barrier.
|
||||||
|
|
||||||
|
MemoryBarrier barrier = new MemoryBarrier()
|
||||||
|
{
|
||||||
|
SType = StructureType.MemoryBarrier,
|
||||||
|
SrcAccessMask = AccessFlags.ShaderWriteBit,
|
||||||
|
DstAccessMask = AccessFlags.ShaderReadBit
|
||||||
|
};
|
||||||
|
|
||||||
|
QueueBarrier(barrier, PipelineStageFlags.FragmentShaderBit, PipelineStageFlags.AllGraphicsBit);
|
||||||
|
|
||||||
|
_queuedFeedbackLoopBarrier = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_feedbackLoopActive = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe void Flush(CommandBufferScoped cbs, bool inRenderPass, RenderPassHolder rpHolder, Action endRenderPass)
|
public unsafe void Flush(CommandBufferScoped cbs, bool inRenderPass, RenderPassHolder rpHolder, Action endRenderPass)
|
||||||
{
|
{
|
||||||
Flush(cbs, null, inRenderPass, rpHolder, endRenderPass);
|
Flush(cbs, null, false, inRenderPass, rpHolder, endRenderPass);
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe void Flush(CommandBufferScoped cbs, ShaderCollection program, bool inRenderPass, RenderPassHolder rpHolder, Action endRenderPass)
|
public unsafe void Flush(CommandBufferScoped cbs, ShaderCollection program, bool feedbackLoopActive, bool inRenderPass, RenderPassHolder rpHolder, Action endRenderPass)
|
||||||
{
|
{
|
||||||
if (program != null)
|
if (program != null)
|
||||||
{
|
{
|
||||||
@ -195,6 +204,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
_incoherentTextureWriteStages |= program.IncoherentTextureWriteStages;
|
_incoherentTextureWriteStages |= program.IncoherentTextureWriteStages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_feedbackLoopActive |= feedbackLoopActive;
|
||||||
|
|
||||||
FlushMemoryBarrier(program, inRenderPass);
|
FlushMemoryBarrier(program, inRenderPass);
|
||||||
|
|
||||||
if (!inRenderPass && rpHolder != null)
|
if (!inRenderPass && rpHolder != null)
|
||||||
@ -406,6 +417,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
{
|
{
|
||||||
_queuedIncoherentBarrier = type;
|
_queuedIncoherentBarrier = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_queuedFeedbackLoopBarrier = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void QueueTextureBarrier()
|
public void QueueTextureBarrier()
|
||||||
|
@ -122,7 +122,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
Range = (uint)size,
|
Range = (uint)size,
|
||||||
};
|
};
|
||||||
|
|
||||||
_gd.Api.CreateBufferView(_device, bufferViewCreateInfo, null, out var bufferView).ThrowOnError();
|
_gd.Api.CreateBufferView(_device, in bufferViewCreateInfo, null, out var bufferView).ThrowOnError();
|
||||||
|
|
||||||
return new Auto<DisposableBufferView>(new DisposableBufferView(_gd.Api, _device, bufferView), this, _waitable, _buffer);
|
return new Auto<DisposableBufferView>(new DisposableBufferView(_gd.Api, _device, bufferView), this, _waitable, _buffer);
|
||||||
}
|
}
|
||||||
@ -153,7 +153,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
PipelineStageFlags.AllCommandsBit,
|
PipelineStageFlags.AllCommandsBit,
|
||||||
DependencyFlags.DeviceGroupBit,
|
DependencyFlags.DeviceGroupBit,
|
||||||
1,
|
1,
|
||||||
memoryBarrier,
|
in memoryBarrier,
|
||||||
0,
|
0,
|
||||||
null,
|
null,
|
||||||
0,
|
0,
|
||||||
@ -770,7 +770,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
0,
|
0,
|
||||||
null,
|
null,
|
||||||
1,
|
1,
|
||||||
memoryBarrier,
|
in memoryBarrier,
|
||||||
0,
|
0,
|
||||||
null);
|
null);
|
||||||
}
|
}
|
||||||
|
@ -221,7 +221,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
PBufferBinds = &bufferBind
|
PBufferBinds = &bufferBind
|
||||||
};
|
};
|
||||||
|
|
||||||
gd.Api.QueueBindSparse(gd.Queue, 1, bindSparseInfo, default).ThrowOnError();
|
gd.Api.QueueBindSparse(gd.Queue, 1, in bindSparseInfo, default).ThrowOnError();
|
||||||
}
|
}
|
||||||
|
|
||||||
var holder = new BufferHolder(gd, _device, buffer, (int)size, storageAllocations);
|
var holder = new BufferHolder(gd, _device, buffer, (int)size, storageAllocations);
|
||||||
|
@ -25,7 +25,10 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
{
|
{
|
||||||
var buffer = _buffer.Get(cbs, _offset, _size, true).Value;
|
var buffer = _buffer.Get(cbs, _offset, _size, true).Value;
|
||||||
|
|
||||||
gd.TransformFeedbackApi.CmdBindTransformFeedbackBuffers(cbs.CommandBuffer, binding, 1, buffer, (ulong)_offset, (ulong)_size);
|
ulong offset = (ulong)_offset;
|
||||||
|
ulong size = (ulong)_size;
|
||||||
|
|
||||||
|
gd.TransformFeedbackApi.CmdBindTransformFeedbackBuffers(cbs.CommandBuffer, binding, 1, in buffer, in offset, in size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
Level = CommandBufferLevel.Primary,
|
Level = CommandBufferLevel.Primary,
|
||||||
};
|
};
|
||||||
|
|
||||||
api.AllocateCommandBuffers(device, allocateInfo, out CommandBuffer);
|
api.AllocateCommandBuffers(device, in allocateInfo, out CommandBuffer);
|
||||||
|
|
||||||
Dependants = new List<IAuto>();
|
Dependants = new List<IAuto>();
|
||||||
Waitables = new List<MultiFenceHolder>();
|
Waitables = new List<MultiFenceHolder>();
|
||||||
@ -83,7 +83,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
CommandPoolCreateFlags.ResetCommandBufferBit,
|
CommandPoolCreateFlags.ResetCommandBufferBit,
|
||||||
};
|
};
|
||||||
|
|
||||||
api.CreateCommandPool(device, commandPoolCreateInfo, null, out _pool).ThrowOnError();
|
api.CreateCommandPool(device, in commandPoolCreateInfo, null, out _pool).ThrowOnError();
|
||||||
|
|
||||||
// We need at least 2 command buffers to get texture data in some cases.
|
// We need at least 2 command buffers to get texture data in some cases.
|
||||||
_totalCommandBuffers = isLight ? 2 : MaxCommandBuffers;
|
_totalCommandBuffers = isLight ? 2 : MaxCommandBuffers;
|
||||||
@ -253,7 +253,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
SType = StructureType.CommandBufferBeginInfo,
|
SType = StructureType.CommandBufferBeginInfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
_api.BeginCommandBuffer(entry.CommandBuffer, commandBufferBeginInfo).ThrowOnError();
|
_api.BeginCommandBuffer(entry.CommandBuffer, in commandBufferBeginInfo).ThrowOnError();
|
||||||
|
|
||||||
return new CommandBufferScoped(this, entry.CommandBuffer, cursor);
|
return new CommandBufferScoped(this, entry.CommandBuffer, cursor);
|
||||||
}
|
}
|
||||||
@ -311,7 +311,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
lock (_queueLock)
|
lock (_queueLock)
|
||||||
{
|
{
|
||||||
_api.QueueSubmit(_queue, 1, sInfo, entry.Fence.GetUnsafe()).ThrowOnError();
|
_api.QueueSubmit(_queue, 1, in sInfo, entry.Fence.GetUnsafe()).ThrowOnError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
PBufferInfo = &bufferInfo,
|
PBufferInfo = &bufferInfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
_holder.Api.UpdateDescriptorSets(_holder.Device, 1, writeDescriptorSet, 0, null);
|
_holder.Api.UpdateDescriptorSets(_holder.Device, 1, in writeDescriptorSet, 0, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,7 +66,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
PBufferInfo = pBufferInfo,
|
PBufferInfo = pBufferInfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
_holder.Api.UpdateDescriptorSets(_holder.Device, 1, writeDescriptorSet, 0, null);
|
_holder.Api.UpdateDescriptorSets(_holder.Device, 1, in writeDescriptorSet, 0, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +84,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
PImageInfo = &imageInfo,
|
PImageInfo = &imageInfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
_holder.Api.UpdateDescriptorSets(_holder.Device, 1, writeDescriptorSet, 0, null);
|
_holder.Api.UpdateDescriptorSets(_holder.Device, 1, in writeDescriptorSet, 0, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,7 +107,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
PImageInfo = pImageInfo,
|
PImageInfo = pImageInfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
_holder.Api.UpdateDescriptorSets(_holder.Device, 1, writeDescriptorSet, 0, null);
|
_holder.Api.UpdateDescriptorSets(_holder.Device, 1, in writeDescriptorSet, 0, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,7 +144,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
PImageInfo = pImageInfo,
|
PImageInfo = pImageInfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
_holder.Api.UpdateDescriptorSets(_holder.Device, 1, writeDescriptorSet, 0, null);
|
_holder.Api.UpdateDescriptorSets(_holder.Device, 1, in writeDescriptorSet, 0, null);
|
||||||
|
|
||||||
i += count - 1;
|
i += count - 1;
|
||||||
}
|
}
|
||||||
@ -166,7 +166,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
PTexelBufferView = &texelBufferView,
|
PTexelBufferView = &texelBufferView,
|
||||||
};
|
};
|
||||||
|
|
||||||
_holder.Api.UpdateDescriptorSets(_holder.Device, 1, writeDescriptorSet, 0, null);
|
_holder.Api.UpdateDescriptorSets(_holder.Device, 1, in writeDescriptorSet, 0, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,7 +200,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
PTexelBufferView = pTexelBufferView + i,
|
PTexelBufferView = pTexelBufferView + i,
|
||||||
};
|
};
|
||||||
|
|
||||||
_holder.Api.UpdateDescriptorSets(_holder.Device, 1, writeDescriptorSet, 0, null);
|
_holder.Api.UpdateDescriptorSets(_holder.Device, 1, in writeDescriptorSet, 0, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
i += count;
|
i += count;
|
||||||
|
@ -40,7 +40,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
PPoolSizes = pPoolsSize,
|
PPoolSizes = pPoolsSize,
|
||||||
};
|
};
|
||||||
|
|
||||||
Api.CreateDescriptorPool(device, descriptorPoolCreateInfo, null, out _pool).ThrowOnError();
|
Api.CreateDescriptorPool(device, in descriptorPoolCreateInfo, null, out _pool).ThrowOnError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ using Ryujinx.Graphics.Shader;
|
|||||||
using Silk.NET.Vulkan;
|
using Silk.NET.Vulkan;
|
||||||
using System;
|
using System;
|
||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using CompareOp = Ryujinx.Graphics.GAL.CompareOp;
|
using CompareOp = Ryujinx.Graphics.GAL.CompareOp;
|
||||||
@ -42,15 +43,15 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
private record struct TextureRef
|
private record struct TextureRef
|
||||||
{
|
{
|
||||||
public ShaderStage Stage;
|
public ShaderStage Stage;
|
||||||
public TextureStorage Storage;
|
public TextureView View;
|
||||||
public Auto<DisposableImageView> View;
|
public Auto<DisposableImageView> ImageView;
|
||||||
public Auto<DisposableSampler> Sampler;
|
public Auto<DisposableSampler> Sampler;
|
||||||
|
|
||||||
public TextureRef(ShaderStage stage, TextureStorage storage, Auto<DisposableImageView> view, Auto<DisposableSampler> sampler)
|
public TextureRef(ShaderStage stage, TextureView view, Auto<DisposableImageView> imageView, Auto<DisposableSampler> sampler)
|
||||||
{
|
{
|
||||||
Stage = stage;
|
Stage = stage;
|
||||||
Storage = storage;
|
|
||||||
View = view;
|
View = view;
|
||||||
|
ImageView = imageView;
|
||||||
Sampler = sampler;
|
Sampler = sampler;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -58,14 +59,14 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
private record struct ImageRef
|
private record struct ImageRef
|
||||||
{
|
{
|
||||||
public ShaderStage Stage;
|
public ShaderStage Stage;
|
||||||
public TextureStorage Storage;
|
public TextureView View;
|
||||||
public Auto<DisposableImageView> View;
|
public Auto<DisposableImageView> ImageView;
|
||||||
|
|
||||||
public ImageRef(ShaderStage stage, TextureStorage storage, Auto<DisposableImageView> view)
|
public ImageRef(ShaderStage stage, TextureView view, Auto<DisposableImageView> imageView)
|
||||||
{
|
{
|
||||||
Stage = stage;
|
Stage = stage;
|
||||||
Storage = storage;
|
|
||||||
View = view;
|
View = view;
|
||||||
|
ImageView = imageView;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,6 +125,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
private readonly TextureView _dummyTexture;
|
private readonly TextureView _dummyTexture;
|
||||||
private readonly SamplerHolder _dummySampler;
|
private readonly SamplerHolder _dummySampler;
|
||||||
|
|
||||||
|
public List<TextureView> FeedbackLoopHazards { get; private set; }
|
||||||
|
|
||||||
public DescriptorSetUpdater(VulkanRenderer gd, Device device)
|
public DescriptorSetUpdater(VulkanRenderer gd, Device device)
|
||||||
{
|
{
|
||||||
_gd = gd;
|
_gd = gd;
|
||||||
@ -209,10 +212,15 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
_templateUpdater = new();
|
_templateUpdater = new();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Initialize()
|
public void Initialize(bool isMainPipeline)
|
||||||
{
|
{
|
||||||
MemoryOwner<byte> dummyTextureData = MemoryOwner<byte>.RentCleared(4);
|
MemoryOwner<byte> dummyTextureData = MemoryOwner<byte>.RentCleared(4);
|
||||||
_dummyTexture.SetData(dummyTextureData);
|
_dummyTexture.SetData(dummyTextureData);
|
||||||
|
|
||||||
|
if (isMainPipeline)
|
||||||
|
{
|
||||||
|
FeedbackLoopHazards = new();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool BindingOverlaps(ref DescriptorBufferInfo info, int bindingOffset, int offset, int size)
|
private static bool BindingOverlaps(ref DescriptorBufferInfo info, int bindingOffset, int offset, int size)
|
||||||
@ -275,6 +283,18 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
public void InsertBindingBarriers(CommandBufferScoped cbs)
|
public void InsertBindingBarriers(CommandBufferScoped cbs)
|
||||||
{
|
{
|
||||||
|
if ((FeedbackLoopHazards?.Count ?? 0) > 0)
|
||||||
|
{
|
||||||
|
// Clear existing hazards - they will be rebuilt.
|
||||||
|
|
||||||
|
foreach (TextureView hazard in FeedbackLoopHazards)
|
||||||
|
{
|
||||||
|
hazard.DecrementHazardUses();
|
||||||
|
}
|
||||||
|
|
||||||
|
FeedbackLoopHazards.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
foreach (ResourceBindingSegment segment in _program.BindingSegments[PipelineBase.TextureSetIndex])
|
foreach (ResourceBindingSegment segment in _program.BindingSegments[PipelineBase.TextureSetIndex])
|
||||||
{
|
{
|
||||||
if (segment.Type == ResourceType.TextureAndSampler)
|
if (segment.Type == ResourceType.TextureAndSampler)
|
||||||
@ -284,7 +304,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
for (int i = 0; i < segment.Count; i++)
|
for (int i = 0; i < segment.Count; i++)
|
||||||
{
|
{
|
||||||
ref var texture = ref _textureRefs[segment.Binding + i];
|
ref var texture = ref _textureRefs[segment.Binding + i];
|
||||||
texture.Storage?.QueueWriteToReadBarrier(cbs, AccessFlags.ShaderReadBit, texture.Stage.ConvertToPipelineStageFlags());
|
texture.View?.PrepareForUsage(cbs, texture.Stage.ConvertToPipelineStageFlags(), FeedbackLoopHazards);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -305,7 +325,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
for (int i = 0; i < segment.Count; i++)
|
for (int i = 0; i < segment.Count; i++)
|
||||||
{
|
{
|
||||||
ref var image = ref _imageRefs[segment.Binding + i];
|
ref var image = ref _imageRefs[segment.Binding + i];
|
||||||
image.Storage?.QueueWriteToReadBarrier(cbs, AccessFlags.ShaderReadBit, image.Stage.ConvertToPipelineStageFlags());
|
image.View?.PrepareForUsage(cbs, image.Stage.ConvertToPipelineStageFlags(), FeedbackLoopHazards);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -385,9 +405,12 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
}
|
}
|
||||||
else if (image is TextureView view)
|
else if (image is TextureView view)
|
||||||
{
|
{
|
||||||
view.Storage.QueueWriteToReadBarrier(cbs, AccessFlags.ShaderReadBit, stage.ConvertToPipelineStageFlags());
|
ref ImageRef iRef = ref _imageRefs[binding];
|
||||||
|
|
||||||
_imageRefs[binding] = new(stage, view.Storage, view.GetView(imageFormat).GetIdentityImageView());
|
iRef.View?.ClearUsage(FeedbackLoopHazards);
|
||||||
|
view?.PrepareForUsage(cbs, stage.ConvertToPipelineStageFlags(), FeedbackLoopHazards);
|
||||||
|
|
||||||
|
iRef = new(stage, view, view.GetView(imageFormat).GetIdentityImageView());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -486,9 +509,12 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
}
|
}
|
||||||
else if (texture is TextureView view)
|
else if (texture is TextureView view)
|
||||||
{
|
{
|
||||||
view.Storage.QueueWriteToReadBarrier(cbs, AccessFlags.ShaderReadBit, stage.ConvertToPipelineStageFlags());
|
ref TextureRef iRef = ref _textureRefs[binding];
|
||||||
|
|
||||||
_textureRefs[binding] = new(stage, view.Storage, view.GetImageView(), ((SamplerHolder)sampler)?.GetSampler());
|
iRef.View?.ClearUsage(FeedbackLoopHazards);
|
||||||
|
view?.PrepareForUsage(cbs, stage.ConvertToPipelineStageFlags(), FeedbackLoopHazards);
|
||||||
|
|
||||||
|
iRef = new(stage, view, view.GetImageView(), ((SamplerHolder)sampler)?.GetSampler());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -510,7 +536,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
{
|
{
|
||||||
view.Storage.QueueWriteToReadBarrier(cbs, AccessFlags.ShaderReadBit, stage.ConvertToPipelineStageFlags());
|
view.Storage.QueueWriteToReadBarrier(cbs, AccessFlags.ShaderReadBit, stage.ConvertToPipelineStageFlags());
|
||||||
|
|
||||||
_textureRefs[binding] = new(stage, view.Storage, view.GetIdentityImageView(), ((SamplerHolder)sampler)?.GetSampler());
|
_textureRefs[binding] = new(stage, view, view.GetIdentityImageView(), ((SamplerHolder)sampler)?.GetSampler());
|
||||||
|
|
||||||
SignalDirty(DirtyFlags.Texture);
|
SignalDirty(DirtyFlags.Texture);
|
||||||
}
|
}
|
||||||
@ -836,7 +862,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
ref var texture = ref textures[i];
|
ref var texture = ref textures[i];
|
||||||
ref var refs = ref _textureRefs[binding + i];
|
ref var refs = ref _textureRefs[binding + i];
|
||||||
|
|
||||||
texture.ImageView = refs.View?.Get(cbs).Value ?? default;
|
texture.ImageView = refs.ImageView?.Get(cbs).Value ?? default;
|
||||||
texture.Sampler = refs.Sampler?.Get(cbs).Value ?? default;
|
texture.Sampler = refs.Sampler?.Get(cbs).Value ?? default;
|
||||||
|
|
||||||
if (texture.ImageView.Handle == 0)
|
if (texture.ImageView.Handle == 0)
|
||||||
@ -886,7 +912,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
images[i].ImageView = _imageRefs[binding + i].View?.Get(cbs).Value ?? default;
|
images[i].ImageView = _imageRefs[binding + i].ImageView?.Get(cbs).Value ?? default;
|
||||||
}
|
}
|
||||||
|
|
||||||
tu.Push<DescriptorImageInfo>(images[..count]);
|
tu.Push<DescriptorImageInfo>(images[..count]);
|
||||||
@ -957,7 +983,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
ref var texture = ref textures[i];
|
ref var texture = ref textures[i];
|
||||||
ref var refs = ref _textureRefs[binding + i];
|
ref var refs = ref _textureRefs[binding + i];
|
||||||
|
|
||||||
texture.ImageView = refs.View?.Get(cbs).Value ?? default;
|
texture.ImageView = refs.ImageView?.Get(cbs).Value ?? default;
|
||||||
texture.Sampler = refs.Sampler?.Get(cbs).Value ?? default;
|
texture.Sampler = refs.Sampler?.Get(cbs).Value ?? default;
|
||||||
|
|
||||||
if (texture.ImageView.Handle == 0)
|
if (texture.ImageView.Handle == 0)
|
||||||
|
12
src/Ryujinx.Graphics.Vulkan/FeedbackLoopAspects.cs
Normal file
12
src/Ryujinx.Graphics.Vulkan/FeedbackLoopAspects.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Vulkan
|
||||||
|
{
|
||||||
|
[Flags]
|
||||||
|
internal enum FeedbackLoopAspects
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Color = 1 << 0,
|
||||||
|
Depth = 1 << 1,
|
||||||
|
}
|
||||||
|
}
|
@ -250,7 +250,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
Layers = Layers,
|
Layers = Layers,
|
||||||
};
|
};
|
||||||
|
|
||||||
api.CreateFramebuffer(_device, framebufferCreateInfo, null, out var framebuffer).ThrowOnError();
|
api.CreateFramebuffer(_device, in framebufferCreateInfo, null, out var framebuffer).ThrowOnError();
|
||||||
return new Auto<DisposableFramebuffer>(new DisposableFramebuffer(api, _device, framebuffer), null, _attachments);
|
return new Auto<DisposableFramebuffer>(new DisposableFramebuffer(api, _device, framebuffer), null, _attachments);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,6 +302,27 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
_depthStencil?.Storage?.AddStoreOpUsage(true);
|
_depthStencil?.Storage?.AddStoreOpUsage(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ClearBindings()
|
||||||
|
{
|
||||||
|
_depthStencil?.Storage.ClearBindings();
|
||||||
|
|
||||||
|
for (int i = 0; i < _colorsCanonical.Length; i++)
|
||||||
|
{
|
||||||
|
_colorsCanonical[i]?.Storage.ClearBindings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddBindings()
|
||||||
|
{
|
||||||
|
_depthStencil?.Storage.AddBinding(_depthStencil);
|
||||||
|
|
||||||
|
for (int i = 0; i < _colorsCanonical.Length; i++)
|
||||||
|
{
|
||||||
|
TextureView color = _colorsCanonical[i];
|
||||||
|
color?.Storage.AddBinding(color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public (RenderPassHolder rpHolder, Auto<DisposableFramebuffer> framebuffer) GetPassAndFramebuffer(
|
public (RenderPassHolder rpHolder, Auto<DisposableFramebuffer> framebuffer) GetPassAndFramebuffer(
|
||||||
VulkanRenderer gd,
|
VulkanRenderer gd,
|
||||||
Device device,
|
Device device,
|
||||||
|
@ -46,6 +46,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
public readonly bool SupportsViewportArray2;
|
public readonly bool SupportsViewportArray2;
|
||||||
public readonly bool SupportsHostImportedMemory;
|
public readonly bool SupportsHostImportedMemory;
|
||||||
public readonly bool SupportsDepthClipControl;
|
public readonly bool SupportsDepthClipControl;
|
||||||
|
public readonly bool SupportsAttachmentFeedbackLoop;
|
||||||
|
public readonly bool SupportsDynamicAttachmentFeedbackLoop;
|
||||||
public readonly uint SubgroupSize;
|
public readonly uint SubgroupSize;
|
||||||
public readonly SampleCountFlags SupportedSampleCounts;
|
public readonly SampleCountFlags SupportedSampleCounts;
|
||||||
public readonly PortabilitySubsetFlags PortabilitySubset;
|
public readonly PortabilitySubsetFlags PortabilitySubset;
|
||||||
@ -84,6 +86,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
bool supportsViewportArray2,
|
bool supportsViewportArray2,
|
||||||
bool supportsHostImportedMemory,
|
bool supportsHostImportedMemory,
|
||||||
bool supportsDepthClipControl,
|
bool supportsDepthClipControl,
|
||||||
|
bool supportsAttachmentFeedbackLoop,
|
||||||
|
bool supportsDynamicAttachmentFeedbackLoop,
|
||||||
uint subgroupSize,
|
uint subgroupSize,
|
||||||
SampleCountFlags supportedSampleCounts,
|
SampleCountFlags supportedSampleCounts,
|
||||||
PortabilitySubsetFlags portabilitySubset,
|
PortabilitySubsetFlags portabilitySubset,
|
||||||
@ -121,6 +125,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
SupportsViewportArray2 = supportsViewportArray2;
|
SupportsViewportArray2 = supportsViewportArray2;
|
||||||
SupportsHostImportedMemory = supportsHostImportedMemory;
|
SupportsHostImportedMemory = supportsHostImportedMemory;
|
||||||
SupportsDepthClipControl = supportsDepthClipControl;
|
SupportsDepthClipControl = supportsDepthClipControl;
|
||||||
|
SupportsAttachmentFeedbackLoop = supportsAttachmentFeedbackLoop;
|
||||||
|
SupportsDynamicAttachmentFeedbackLoop = supportsDynamicAttachmentFeedbackLoop;
|
||||||
SubgroupSize = subgroupSize;
|
SubgroupSize = subgroupSize;
|
||||||
SupportedSampleCounts = supportedSampleCounts;
|
SupportedSampleCounts = supportedSampleCounts;
|
||||||
PortabilitySubset = portabilitySubset;
|
PortabilitySubset = portabilitySubset;
|
||||||
|
@ -115,7 +115,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
PNext = &importInfo,
|
PNext = &importInfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
Result result = _api.AllocateMemory(_device, memoryAllocateInfo, null, out var deviceMemory);
|
Result result = _api.AllocateMemory(_device, in memoryAllocateInfo, null, out var deviceMemory);
|
||||||
|
|
||||||
if (result < Result.Success)
|
if (result < Result.Success)
|
||||||
{
|
{
|
||||||
|
@ -95,7 +95,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
{
|
{
|
||||||
_cachedCommandBufferIndex = -1;
|
_cachedCommandBufferIndex = -1;
|
||||||
_storages = null;
|
_storages = null;
|
||||||
SetDirty(_gd);
|
SetDirty(_gd, isImage: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void QueueWriteToReadBarriers(CommandBufferScoped cbs, PipelineStageFlags stageFlags)
|
public void QueueWriteToReadBarriers(CommandBufferScoped cbs, PipelineStageFlags stageFlags)
|
||||||
|
@ -220,7 +220,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
MemoryTypeIndex = (uint)MemoryTypeIndex,
|
MemoryTypeIndex = (uint)MemoryTypeIndex,
|
||||||
};
|
};
|
||||||
|
|
||||||
_api.AllocateMemory(_device, memoryAllocateInfo, null, out var deviceMemory).ThrowOnError();
|
_api.AllocateMemory(_device, in memoryAllocateInfo, null, out var deviceMemory).ThrowOnError();
|
||||||
|
|
||||||
IntPtr hostPointer = IntPtr.Zero;
|
IntPtr hostPointer = IntPtr.Zero;
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
using Silk.NET.Core.Loader;
|
||||||
using Silk.NET.Vulkan;
|
using Silk.NET.Vulkan;
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
@ -8,6 +9,8 @@ namespace Ryujinx.Graphics.Vulkan.MoltenVK
|
|||||||
[SupportedOSPlatform("macos")]
|
[SupportedOSPlatform("macos")]
|
||||||
public static partial class MVKInitialization
|
public static partial class MVKInitialization
|
||||||
{
|
{
|
||||||
|
private const string VulkanLib = "libvulkan.dylib";
|
||||||
|
|
||||||
[LibraryImport("libMoltenVK.dylib")]
|
[LibraryImport("libMoltenVK.dylib")]
|
||||||
private static partial Result vkGetMoltenVKConfigurationMVK(IntPtr unusedInstance, out MVKConfiguration config, in IntPtr configSize);
|
private static partial Result vkGetMoltenVKConfigurationMVK(IntPtr unusedInstance, out MVKConfiguration config, in IntPtr configSize);
|
||||||
|
|
||||||
@ -29,5 +32,20 @@ namespace Ryujinx.Graphics.Vulkan.MoltenVK
|
|||||||
|
|
||||||
vkSetMoltenVKConfigurationMVK(IntPtr.Zero, config, configSize);
|
vkSetMoltenVKConfigurationMVK(IntPtr.Zero, config, configSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string[] Resolver(string path)
|
||||||
|
{
|
||||||
|
if (path.EndsWith(VulkanLib))
|
||||||
|
{
|
||||||
|
path = path[..^VulkanLib.Length] + "libMoltenVK.dylib";
|
||||||
|
return [path];
|
||||||
|
}
|
||||||
|
return Array.Empty<string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void InitializeResolver()
|
||||||
|
{
|
||||||
|
((DefaultPathResolver)PathResolver.Default).Resolvers.Insert(0, Resolver);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ using Ryujinx.Graphics.GAL;
|
|||||||
using Ryujinx.Graphics.Shader;
|
using Ryujinx.Graphics.Shader;
|
||||||
using Silk.NET.Vulkan;
|
using Silk.NET.Vulkan;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
@ -33,6 +34,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
public readonly Action EndRenderPassDelegate;
|
public readonly Action EndRenderPassDelegate;
|
||||||
|
|
||||||
protected PipelineDynamicState DynamicState;
|
protected PipelineDynamicState DynamicState;
|
||||||
|
protected bool IsMainPipeline;
|
||||||
private PipelineState _newState;
|
private PipelineState _newState;
|
||||||
private bool _graphicsStateDirty;
|
private bool _graphicsStateDirty;
|
||||||
private bool _computeStateDirty;
|
private bool _computeStateDirty;
|
||||||
@ -85,6 +87,9 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
private bool _tfEnabled;
|
private bool _tfEnabled;
|
||||||
private bool _tfActive;
|
private bool _tfActive;
|
||||||
|
|
||||||
|
private FeedbackLoopAspects _feedbackLoop;
|
||||||
|
private bool _passWritesDepthStencil;
|
||||||
|
|
||||||
private readonly PipelineColorBlendAttachmentState[] _storedBlend;
|
private readonly PipelineColorBlendAttachmentState[] _storedBlend;
|
||||||
public ulong DrawCount { get; private set; }
|
public ulong DrawCount { get; private set; }
|
||||||
public bool RenderPassActive { get; private set; }
|
public bool RenderPassActive { get; private set; }
|
||||||
@ -102,7 +107,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
SType = StructureType.PipelineCacheCreateInfo,
|
SType = StructureType.PipelineCacheCreateInfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
gd.Api.CreatePipelineCache(device, pipelineCacheCreateInfo, null, out PipelineCache).ThrowOnError();
|
gd.Api.CreatePipelineCache(device, in pipelineCacheCreateInfo, null, out PipelineCache).ThrowOnError();
|
||||||
|
|
||||||
_descriptorSetUpdater = new DescriptorSetUpdater(gd, device);
|
_descriptorSetUpdater = new DescriptorSetUpdater(gd, device);
|
||||||
_vertexBufferUpdater = new VertexBufferUpdater(gd);
|
_vertexBufferUpdater = new VertexBufferUpdater(gd);
|
||||||
@ -126,7 +131,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
public void Initialize()
|
public void Initialize()
|
||||||
{
|
{
|
||||||
_descriptorSetUpdater.Initialize();
|
_descriptorSetUpdater.Initialize(IsMainPipeline);
|
||||||
|
|
||||||
QuadsToTrisPattern = new IndexBufferPattern(Gd, 4, 6, 0, new[] { 0, 1, 2, 0, 2, 3 }, 4, false);
|
QuadsToTrisPattern = new IndexBufferPattern(Gd, 4, 6, 0, new[] { 0, 1, 2, 0, 2, 3 }, 4, false);
|
||||||
TriFanToTrisPattern = new IndexBufferPattern(Gd, 3, 3, 2, new[] { int.MinValue, -1, 0 }, 1, true);
|
TriFanToTrisPattern = new IndexBufferPattern(Gd, 3, 3, 2, new[] { int.MinValue, -1, 0 }, 1, true);
|
||||||
@ -814,6 +819,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
_newState.DepthTestEnable = depthTest.TestEnable;
|
_newState.DepthTestEnable = depthTest.TestEnable;
|
||||||
_newState.DepthWriteEnable = depthTest.WriteEnable;
|
_newState.DepthWriteEnable = depthTest.WriteEnable;
|
||||||
_newState.DepthCompareOp = depthTest.Func.Convert();
|
_newState.DepthCompareOp = depthTest.Func.Convert();
|
||||||
|
|
||||||
|
UpdatePassDepthStencil();
|
||||||
SignalStateChange();
|
SignalStateChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1079,6 +1086,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
_newState.StencilFrontPassOp = stencilTest.FrontDpPass.Convert();
|
_newState.StencilFrontPassOp = stencilTest.FrontDpPass.Convert();
|
||||||
_newState.StencilFrontDepthFailOp = stencilTest.FrontDpFail.Convert();
|
_newState.StencilFrontDepthFailOp = stencilTest.FrontDpFail.Convert();
|
||||||
_newState.StencilFrontCompareOp = stencilTest.FrontFunc.Convert();
|
_newState.StencilFrontCompareOp = stencilTest.FrontFunc.Convert();
|
||||||
|
|
||||||
|
UpdatePassDepthStencil();
|
||||||
SignalStateChange();
|
SignalStateChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1426,7 +1435,23 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IsMainPipeline)
|
||||||
|
{
|
||||||
|
FramebufferParams?.ClearBindings();
|
||||||
|
}
|
||||||
|
|
||||||
FramebufferParams = new FramebufferParams(Device, colors, depthStencil);
|
FramebufferParams = new FramebufferParams(Device, colors, depthStencil);
|
||||||
|
|
||||||
|
if (IsMainPipeline)
|
||||||
|
{
|
||||||
|
FramebufferParams.AddBindings();
|
||||||
|
|
||||||
|
_newState.FeedbackLoopAspects = FeedbackLoopAspects.None;
|
||||||
|
_bindingBarriersDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_passWritesDepthStencil = false;
|
||||||
|
UpdatePassDepthStencil();
|
||||||
UpdatePipelineAttachmentFormats();
|
UpdatePipelineAttachmentFormats();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1493,11 +1518,82 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Gd.Barriers.Flush(Cbs, _program, RenderPassActive, _rpHolder, EndRenderPassDelegate);
|
Gd.Barriers.Flush(Cbs, _program, _feedbackLoop != 0, RenderPassActive, _rpHolder, EndRenderPassDelegate);
|
||||||
|
|
||||||
_descriptorSetUpdater.UpdateAndBindDescriptorSets(Cbs, PipelineBindPoint.Compute);
|
_descriptorSetUpdater.UpdateAndBindDescriptorSets(Cbs, PipelineBindPoint.Compute);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool ChangeFeedbackLoop(FeedbackLoopAspects aspects)
|
||||||
|
{
|
||||||
|
if (_feedbackLoop != aspects)
|
||||||
|
{
|
||||||
|
if (Gd.Capabilities.SupportsDynamicAttachmentFeedbackLoop)
|
||||||
|
{
|
||||||
|
DynamicState.SetFeedbackLoop(aspects);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_newState.FeedbackLoopAspects = aspects;
|
||||||
|
}
|
||||||
|
|
||||||
|
_feedbackLoop = aspects;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private bool UpdateFeedbackLoop()
|
||||||
|
{
|
||||||
|
List<TextureView> hazards = _descriptorSetUpdater.FeedbackLoopHazards;
|
||||||
|
|
||||||
|
if ((hazards?.Count ?? 0) > 0)
|
||||||
|
{
|
||||||
|
FeedbackLoopAspects aspects = 0;
|
||||||
|
|
||||||
|
foreach (TextureView view in hazards)
|
||||||
|
{
|
||||||
|
// May need to enforce feedback loop layout here in the future.
|
||||||
|
// Though technically, it should always work with the general layout.
|
||||||
|
|
||||||
|
if (view.Info.Format.IsDepthOrStencil())
|
||||||
|
{
|
||||||
|
if (_passWritesDepthStencil)
|
||||||
|
{
|
||||||
|
// If depth/stencil isn't written in the pass, it doesn't count as a feedback loop.
|
||||||
|
|
||||||
|
aspects |= FeedbackLoopAspects.Depth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aspects |= FeedbackLoopAspects.Color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ChangeFeedbackLoop(aspects);
|
||||||
|
}
|
||||||
|
else if (_feedbackLoop != 0)
|
||||||
|
{
|
||||||
|
return ChangeFeedbackLoop(FeedbackLoopAspects.None);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdatePassDepthStencil()
|
||||||
|
{
|
||||||
|
if (!RenderPassActive)
|
||||||
|
{
|
||||||
|
_passWritesDepthStencil = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stencil test being enabled doesn't necessarily mean a write, but it's not critical to check.
|
||||||
|
_passWritesDepthStencil |= (_newState.DepthTestEnable && _newState.DepthWriteEnable) || _newState.StencilTestEnable;
|
||||||
|
}
|
||||||
|
|
||||||
private bool RecreateGraphicsPipelineIfNeeded()
|
private bool RecreateGraphicsPipelineIfNeeded()
|
||||||
{
|
{
|
||||||
if (AutoFlush.ShouldFlushDraw(DrawCount))
|
if (AutoFlush.ShouldFlushDraw(DrawCount))
|
||||||
@ -1505,7 +1601,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
Gd.FlushAllCommands();
|
Gd.FlushAllCommands();
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicState.ReplayIfDirty(Gd.Api, CommandBuffer);
|
DynamicState.ReplayIfDirty(Gd, CommandBuffer);
|
||||||
|
|
||||||
if (_needsIndexBufferRebind && _indexBufferPattern == null)
|
if (_needsIndexBufferRebind && _indexBufferPattern == null)
|
||||||
{
|
{
|
||||||
@ -1539,7 +1635,15 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
_vertexBufferUpdater.Commit(Cbs);
|
_vertexBufferUpdater.Commit(Cbs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_graphicsStateDirty || Pbp != PipelineBindPoint.Graphics)
|
if (_bindingBarriersDirty)
|
||||||
|
{
|
||||||
|
// Stale barriers may have been activated by switching program. Emit any that are relevant.
|
||||||
|
_descriptorSetUpdater.InsertBindingBarriers(Cbs);
|
||||||
|
|
||||||
|
_bindingBarriersDirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UpdateFeedbackLoop() || _graphicsStateDirty || Pbp != PipelineBindPoint.Graphics)
|
||||||
{
|
{
|
||||||
if (!CreatePipeline(PipelineBindPoint.Graphics))
|
if (!CreatePipeline(PipelineBindPoint.Graphics))
|
||||||
{
|
{
|
||||||
@ -1548,17 +1652,9 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
_graphicsStateDirty = false;
|
_graphicsStateDirty = false;
|
||||||
Pbp = PipelineBindPoint.Graphics;
|
Pbp = PipelineBindPoint.Graphics;
|
||||||
|
|
||||||
if (_bindingBarriersDirty)
|
|
||||||
{
|
|
||||||
// Stale barriers may have been activated by switching program. Emit any that are relevant.
|
|
||||||
_descriptorSetUpdater.InsertBindingBarriers(Cbs);
|
|
||||||
|
|
||||||
_bindingBarriersDirty = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Gd.Barriers.Flush(Cbs, _program, RenderPassActive, _rpHolder, EndRenderPassDelegate);
|
Gd.Barriers.Flush(Cbs, _program, _feedbackLoop != 0, RenderPassActive, _rpHolder, EndRenderPassDelegate);
|
||||||
|
|
||||||
_descriptorSetUpdater.UpdateAndBindDescriptorSets(Cbs, PipelineBindPoint.Graphics);
|
_descriptorSetUpdater.UpdateAndBindDescriptorSets(Cbs, PipelineBindPoint.Graphics);
|
||||||
|
|
||||||
@ -1628,7 +1724,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
ClearValueCount = 1,
|
ClearValueCount = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
Gd.Api.CmdBeginRenderPass(CommandBuffer, renderPassBeginInfo, SubpassContents.Inline);
|
Gd.Api.CmdBeginRenderPass(CommandBuffer, in renderPassBeginInfo, SubpassContents.Inline);
|
||||||
RenderPassActive = true;
|
RenderPassActive = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
DependencyCount = 1,
|
DependencyCount = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
gd.Api.CreateRenderPass(device, renderPassCreateInfo, null, out var renderPass).ThrowOnError();
|
gd.Api.CreateRenderPass(device, in renderPassCreateInfo, null, out var renderPass).ThrowOnError();
|
||||||
|
|
||||||
return new DisposableRenderPass(gd.Api, device, renderPass);
|
return new DisposableRenderPass(gd.Api, device, renderPass);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using Ryujinx.Common.Memory;
|
using Ryujinx.Common.Memory;
|
||||||
using Silk.NET.Vulkan;
|
using Silk.NET.Vulkan;
|
||||||
|
using Silk.NET.Vulkan.Extensions.EXT;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Vulkan
|
namespace Ryujinx.Graphics.Vulkan
|
||||||
{
|
{
|
||||||
@ -21,6 +22,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
private Array4<float> _blendConstants;
|
private Array4<float> _blendConstants;
|
||||||
|
|
||||||
|
private FeedbackLoopAspects _feedbackLoopAspects;
|
||||||
|
|
||||||
public uint ViewportsCount;
|
public uint ViewportsCount;
|
||||||
public Array16<Viewport> Viewports;
|
public Array16<Viewport> Viewports;
|
||||||
|
|
||||||
@ -32,7 +35,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
Scissor = 1 << 2,
|
Scissor = 1 << 2,
|
||||||
Stencil = 1 << 3,
|
Stencil = 1 << 3,
|
||||||
Viewport = 1 << 4,
|
Viewport = 1 << 4,
|
||||||
All = Blend | DepthBias | Scissor | Stencil | Viewport,
|
FeedbackLoop = 1 << 5,
|
||||||
|
All = Blend | DepthBias | Scissor | Stencil | Viewport | FeedbackLoop,
|
||||||
}
|
}
|
||||||
|
|
||||||
private DirtyFlags _dirty;
|
private DirtyFlags _dirty;
|
||||||
@ -99,13 +103,22 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetFeedbackLoop(FeedbackLoopAspects aspects)
|
||||||
|
{
|
||||||
|
_feedbackLoopAspects = aspects;
|
||||||
|
|
||||||
|
_dirty |= DirtyFlags.FeedbackLoop;
|
||||||
|
}
|
||||||
|
|
||||||
public void ForceAllDirty()
|
public void ForceAllDirty()
|
||||||
{
|
{
|
||||||
_dirty = DirtyFlags.All;
|
_dirty = DirtyFlags.All;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ReplayIfDirty(Vk api, CommandBuffer commandBuffer)
|
public void ReplayIfDirty(VulkanRenderer gd, CommandBuffer commandBuffer)
|
||||||
{
|
{
|
||||||
|
Vk api = gd.Api;
|
||||||
|
|
||||||
if (_dirty.HasFlag(DirtyFlags.Blend))
|
if (_dirty.HasFlag(DirtyFlags.Blend))
|
||||||
{
|
{
|
||||||
RecordBlend(api, commandBuffer);
|
RecordBlend(api, commandBuffer);
|
||||||
@ -131,6 +144,11 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
RecordViewport(api, commandBuffer);
|
RecordViewport(api, commandBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_dirty.HasFlag(DirtyFlags.FeedbackLoop) && gd.Capabilities.SupportsDynamicAttachmentFeedbackLoop)
|
||||||
|
{
|
||||||
|
RecordFeedbackLoop(gd.DynamicFeedbackLoopApi, commandBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
_dirty = DirtyFlags.None;
|
_dirty = DirtyFlags.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,5 +187,17 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
api.CmdSetViewport(commandBuffer, 0, ViewportsCount, Viewports.AsSpan());
|
api.CmdSetViewport(commandBuffer, 0, ViewportsCount, Viewports.AsSpan());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private readonly void RecordFeedbackLoop(ExtAttachmentFeedbackLoopDynamicState api, CommandBuffer commandBuffer)
|
||||||
|
{
|
||||||
|
ImageAspectFlags aspects = (_feedbackLoopAspects & FeedbackLoopAspects.Color) != 0 ? ImageAspectFlags.ColorBit : 0;
|
||||||
|
|
||||||
|
if ((_feedbackLoopAspects & FeedbackLoopAspects.Depth) != 0)
|
||||||
|
{
|
||||||
|
aspects |= ImageAspectFlags.DepthBit | ImageAspectFlags.StencilBit;
|
||||||
|
}
|
||||||
|
|
||||||
|
api.CmdSetAttachmentFeedbackLoopEnable(commandBuffer, aspects);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
_activeBufferMirrors = new();
|
_activeBufferMirrors = new();
|
||||||
|
|
||||||
CommandBuffer = (Cbs = gd.CommandBufferPool.Rent()).CommandBuffer;
|
CommandBuffer = (Cbs = gd.CommandBufferPool.Rent()).CommandBuffer;
|
||||||
|
|
||||||
|
IsMainPipeline = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CopyPendingQuery()
|
private void CopyPendingQuery()
|
||||||
@ -235,7 +237,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
if (Pipeline != null && Pbp == PipelineBindPoint.Graphics)
|
if (Pipeline != null && Pbp == PipelineBindPoint.Graphics)
|
||||||
{
|
{
|
||||||
DynamicState.ReplayIfDirty(Gd.Api, CommandBuffer);
|
DynamicState.ReplayIfDirty(Gd, CommandBuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
Flags = flags,
|
Flags = flags,
|
||||||
};
|
};
|
||||||
|
|
||||||
gd.Api.CreateDescriptorSetLayout(device, descriptorSetLayoutCreateInfo, null, out layouts[setIndex]).ThrowOnError();
|
gd.Api.CreateDescriptorSetLayout(device, in descriptorSetLayoutCreateInfo, null, out layouts[setIndex]).ThrowOnError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
struct PipelineState : IDisposable
|
struct PipelineState : IDisposable
|
||||||
{
|
{
|
||||||
private const int RequiredSubgroupSize = 32;
|
private const int RequiredSubgroupSize = 32;
|
||||||
|
private const int MaxDynamicStatesCount = 9;
|
||||||
|
|
||||||
public PipelineUid Internal;
|
public PipelineUid Internal;
|
||||||
|
|
||||||
@ -299,6 +300,12 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFFFFFFFFBF) | ((value ? 1UL : 0UL) << 6);
|
set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFFFFFFFFBF) | ((value ? 1UL : 0UL) << 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public FeedbackLoopAspects FeedbackLoopAspects
|
||||||
|
{
|
||||||
|
readonly get => (FeedbackLoopAspects)((Internal.Id8 >> 7) & 0x3);
|
||||||
|
set => Internal.Id8 = (Internal.Id8 & 0xFFFFFFFFFFFFFE7F) | (((ulong)value) << 7);
|
||||||
|
}
|
||||||
|
|
||||||
public bool HasTessellationControlShader;
|
public bool HasTessellationControlShader;
|
||||||
public NativeArray<PipelineShaderStageCreateInfo> Stages;
|
public NativeArray<PipelineShaderStageCreateInfo> Stages;
|
||||||
public PipelineLayout PipelineLayout;
|
public PipelineLayout PipelineLayout;
|
||||||
@ -564,9 +571,11 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool supportsExtDynamicState = gd.Capabilities.SupportsExtendedDynamicState;
|
bool supportsExtDynamicState = gd.Capabilities.SupportsExtendedDynamicState;
|
||||||
int dynamicStatesCount = supportsExtDynamicState ? 8 : 7;
|
bool supportsFeedbackLoopDynamicState = gd.Capabilities.SupportsDynamicAttachmentFeedbackLoop;
|
||||||
|
|
||||||
DynamicState* dynamicStates = stackalloc DynamicState[dynamicStatesCount];
|
DynamicState* dynamicStates = stackalloc DynamicState[MaxDynamicStatesCount];
|
||||||
|
|
||||||
|
int dynamicStatesCount = 7;
|
||||||
|
|
||||||
dynamicStates[0] = DynamicState.Viewport;
|
dynamicStates[0] = DynamicState.Viewport;
|
||||||
dynamicStates[1] = DynamicState.Scissor;
|
dynamicStates[1] = DynamicState.Scissor;
|
||||||
@ -578,7 +587,12 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
if (supportsExtDynamicState)
|
if (supportsExtDynamicState)
|
||||||
{
|
{
|
||||||
dynamicStates[7] = DynamicState.VertexInputBindingStrideExt;
|
dynamicStates[dynamicStatesCount++] = DynamicState.VertexInputBindingStrideExt;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (supportsFeedbackLoopDynamicState)
|
||||||
|
{
|
||||||
|
dynamicStates[dynamicStatesCount++] = DynamicState.AttachmentFeedbackLoopEnableExt;
|
||||||
}
|
}
|
||||||
|
|
||||||
var pipelineDynamicStateCreateInfo = new PipelineDynamicStateCreateInfo
|
var pipelineDynamicStateCreateInfo = new PipelineDynamicStateCreateInfo
|
||||||
@ -588,9 +602,27 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
PDynamicStates = dynamicStates,
|
PDynamicStates = dynamicStates,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
PipelineCreateFlags flags = 0;
|
||||||
|
|
||||||
|
if (gd.Capabilities.SupportsAttachmentFeedbackLoop)
|
||||||
|
{
|
||||||
|
FeedbackLoopAspects aspects = FeedbackLoopAspects;
|
||||||
|
|
||||||
|
if ((aspects & FeedbackLoopAspects.Color) != 0)
|
||||||
|
{
|
||||||
|
flags |= PipelineCreateFlags.CreateColorAttachmentFeedbackLoopBitExt;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((aspects & FeedbackLoopAspects.Depth) != 0)
|
||||||
|
{
|
||||||
|
flags |= PipelineCreateFlags.CreateDepthStencilAttachmentFeedbackLoopBitExt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var pipelineCreateInfo = new GraphicsPipelineCreateInfo
|
var pipelineCreateInfo = new GraphicsPipelineCreateInfo
|
||||||
{
|
{
|
||||||
SType = StructureType.GraphicsPipelineCreateInfo,
|
SType = StructureType.GraphicsPipelineCreateInfo,
|
||||||
|
Flags = flags,
|
||||||
StageCount = StagesCount,
|
StageCount = StagesCount,
|
||||||
PStages = Stages.Pointer,
|
PStages = Stages.Pointer,
|
||||||
PVertexInputState = &vertexInputState,
|
PVertexInputState = &vertexInputState,
|
||||||
|
@ -52,7 +52,7 @@ namespace Ryujinx.Graphics.Vulkan.Queries
|
|||||||
PipelineStatistics = flags,
|
PipelineStatistics = flags,
|
||||||
};
|
};
|
||||||
|
|
||||||
gd.Api.CreateQueryPool(device, queryPoolCreateInfo, null, out _queryPool).ThrowOnError();
|
gd.Api.CreateQueryPool(device, in queryPoolCreateInfo, null, out _queryPool).ThrowOnError();
|
||||||
}
|
}
|
||||||
|
|
||||||
var buffer = gd.BufferManager.Create(gd, sizeof(long), forConditionalRendering: true);
|
var buffer = gd.BufferManager.Create(gd, sizeof(long), forConditionalRendering: true);
|
||||||
|
@ -125,7 +125,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
DependencyCount = 1,
|
DependencyCount = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
gd.Api.CreateRenderPass(device, renderPassCreateInfo, null, out var renderPass).ThrowOnError();
|
gd.Api.CreateRenderPass(device, in renderPassCreateInfo, null, out var renderPass).ThrowOnError();
|
||||||
|
|
||||||
_renderPass = new Auto<DisposableRenderPass>(new DisposableRenderPass(gd.Api, device, renderPass));
|
_renderPass = new Auto<DisposableRenderPass>(new DisposableRenderPass(gd.Api, device, renderPass));
|
||||||
}
|
}
|
||||||
|
@ -14,13 +14,20 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
private int _bindCount;
|
private int _bindCount;
|
||||||
|
|
||||||
protected void SetDirty(VulkanRenderer gd)
|
protected void SetDirty(VulkanRenderer gd, bool isImage)
|
||||||
{
|
{
|
||||||
ReleaseDescriptorSet();
|
ReleaseDescriptorSet();
|
||||||
|
|
||||||
if (_bindCount != 0)
|
if (_bindCount != 0)
|
||||||
{
|
{
|
||||||
gd.PipelineInternal.ForceTextureDirty();
|
if (isImage)
|
||||||
|
{
|
||||||
|
gd.PipelineInternal.ForceImageDirty();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gd.PipelineInternal.ForceTextureDirty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
samplerCreateInfo.BorderColor = BorderColor.FloatCustomExt;
|
samplerCreateInfo.BorderColor = BorderColor.FloatCustomExt;
|
||||||
}
|
}
|
||||||
|
|
||||||
gd.Api.CreateSampler(device, samplerCreateInfo, null, out var sampler).ThrowOnError();
|
gd.Api.CreateSampler(device, in samplerCreateInfo, null, out var sampler).ThrowOnError();
|
||||||
|
|
||||||
_sampler = new Auto<DisposableSampler>(new DisposableSampler(gd.Api, device, sampler));
|
_sampler = new Auto<DisposableSampler>(new DisposableSampler(gd.Api, device, sampler));
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
PCode = (uint*)pCode,
|
PCode = (uint*)pCode,
|
||||||
};
|
};
|
||||||
|
|
||||||
api.CreateShaderModule(device, shaderModuleCreateInfo, null, out _module).ThrowOnError();
|
api.CreateShaderModule(device, in shaderModuleCreateInfo, null, out _module).ThrowOnError();
|
||||||
}
|
}
|
||||||
|
|
||||||
CompileStatus = ProgramLinkStatus.Success;
|
CompileStatus = ProgramLinkStatus.Success;
|
||||||
|
@ -104,7 +104,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
{
|
{
|
||||||
_cachedCommandBufferIndex = -1;
|
_cachedCommandBufferIndex = -1;
|
||||||
_storages = null;
|
_storages = null;
|
||||||
SetDirty(_gd);
|
SetDirty(_gd, isImage: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void QueueWriteToReadBarriers(CommandBufferScoped cbs, PipelineStageFlags stageFlags)
|
public void QueueWriteToReadBarriers(CommandBufferScoped cbs, PipelineStageFlags stageFlags)
|
||||||
|
@ -88,7 +88,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
DstOffsets = dstOffsets,
|
DstOffsets = dstOffsets,
|
||||||
};
|
};
|
||||||
|
|
||||||
api.CmdBlitImage(commandBuffer, srcImage, ImageLayout.General, dstImage, ImageLayout.General, 1, region, filter);
|
api.CmdBlitImage(commandBuffer, srcImage, ImageLayout.General, dstImage, ImageLayout.General, 1, in region, filter);
|
||||||
|
|
||||||
copySrcLevel++;
|
copySrcLevel++;
|
||||||
copyDstLevel++;
|
copyDstLevel++;
|
||||||
@ -320,13 +320,13 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
{
|
{
|
||||||
var region = new ImageResolve(srcSl, new Offset3D(0, 0, srcZ), dstSl, new Offset3D(0, 0, dstZ), extent);
|
var region = new ImageResolve(srcSl, new Offset3D(0, 0, srcZ), dstSl, new Offset3D(0, 0, dstZ), extent);
|
||||||
|
|
||||||
api.CmdResolveImage(commandBuffer, srcImage, ImageLayout.General, dstImage, ImageLayout.General, 1, region);
|
api.CmdResolveImage(commandBuffer, srcImage, ImageLayout.General, dstImage, ImageLayout.General, 1, in region);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var region = new ImageCopy(srcSl, new Offset3D(0, 0, srcZ), dstSl, new Offset3D(0, 0, dstZ), extent);
|
var region = new ImageCopy(srcSl, new Offset3D(0, 0, srcZ), dstSl, new Offset3D(0, 0, dstZ), extent);
|
||||||
|
|
||||||
api.CmdCopyImage(commandBuffer, srcImage, ImageLayout.General, dstImage, ImageLayout.General, 1, region);
|
api.CmdCopyImage(commandBuffer, srcImage, ImageLayout.General, dstImage, ImageLayout.General, 1, in region);
|
||||||
}
|
}
|
||||||
|
|
||||||
width = Math.Max(1, width >> 1);
|
width = Math.Max(1, width >> 1);
|
||||||
@ -422,7 +422,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
DependencyCount = 1,
|
DependencyCount = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
gd.Api.CreateRenderPass2(device, renderPassCreateInfo, null, out var renderPass).ThrowOnError();
|
gd.Api.CreateRenderPass2(device, in renderPassCreateInfo, null, out var renderPass).ThrowOnError();
|
||||||
|
|
||||||
using var rp = new Auto<DisposableRenderPass>(new DisposableRenderPass(gd.Api, device, renderPass));
|
using var rp = new Auto<DisposableRenderPass>(new DisposableRenderPass(gd.Api, device, renderPass));
|
||||||
|
|
||||||
@ -445,7 +445,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
Layers = (uint)src.Layers,
|
Layers = (uint)src.Layers,
|
||||||
};
|
};
|
||||||
|
|
||||||
gd.Api.CreateFramebuffer(device, framebufferCreateInfo, null, out var framebuffer).ThrowOnError();
|
gd.Api.CreateFramebuffer(device, in framebufferCreateInfo, null, out var framebuffer).ThrowOnError();
|
||||||
using var fb = new Auto<DisposableFramebuffer>(new DisposableFramebuffer(gd.Api, device, framebuffer), null, srcView, dstView);
|
using var fb = new Auto<DisposableFramebuffer>(new DisposableFramebuffer(gd.Api, device, framebuffer), null, srcView, dstView);
|
||||||
|
|
||||||
var renderArea = new Rect2D(null, new Extent2D((uint)src.Info.Width, (uint)src.Info.Height));
|
var renderArea = new Rect2D(null, new Extent2D((uint)src.Info.Width, (uint)src.Info.Height));
|
||||||
@ -465,7 +465,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
// to resolve the depth-stencil texture.
|
// to resolve the depth-stencil texture.
|
||||||
// TODO: Do speculative resolve and part of the same render pass as the draw to avoid
|
// TODO: Do speculative resolve and part of the same render pass as the draw to avoid
|
||||||
// ending the current render pass?
|
// ending the current render pass?
|
||||||
gd.Api.CmdBeginRenderPass(cbs.CommandBuffer, renderPassBeginInfo, SubpassContents.Inline);
|
gd.Api.CmdBeginRenderPass(cbs.CommandBuffer, in renderPassBeginInfo, SubpassContents.Inline);
|
||||||
gd.Api.CmdEndRenderPass(cbs.CommandBuffer);
|
gd.Api.CmdEndRenderPass(cbs.CommandBuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ using Silk.NET.Vulkan;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using Format = Ryujinx.Graphics.GAL.Format;
|
using Format = Ryujinx.Graphics.GAL.Format;
|
||||||
using VkBuffer = Silk.NET.Vulkan.Buffer;
|
using VkBuffer = Silk.NET.Vulkan.Buffer;
|
||||||
using VkFormat = Silk.NET.Vulkan.Format;
|
using VkFormat = Silk.NET.Vulkan.Format;
|
||||||
@ -12,6 +13,11 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
{
|
{
|
||||||
class TextureStorage : IDisposable
|
class TextureStorage : IDisposable
|
||||||
{
|
{
|
||||||
|
private struct TextureSliceInfo
|
||||||
|
{
|
||||||
|
public int BindCount;
|
||||||
|
}
|
||||||
|
|
||||||
private const MemoryPropertyFlags DefaultImageMemoryFlags =
|
private const MemoryPropertyFlags DefaultImageMemoryFlags =
|
||||||
MemoryPropertyFlags.DeviceLocalBit;
|
MemoryPropertyFlags.DeviceLocalBit;
|
||||||
|
|
||||||
@ -43,6 +49,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
private readonly Image _image;
|
private readonly Image _image;
|
||||||
private readonly Auto<DisposableImage> _imageAuto;
|
private readonly Auto<DisposableImage> _imageAuto;
|
||||||
private readonly Auto<MemoryAllocation> _allocationAuto;
|
private readonly Auto<MemoryAllocation> _allocationAuto;
|
||||||
|
private readonly int _depthOrLayers;
|
||||||
private Auto<MemoryAllocation> _foreignAllocationAuto;
|
private Auto<MemoryAllocation> _foreignAllocationAuto;
|
||||||
|
|
||||||
private Dictionary<Format, TextureStorage> _aliasedStorages;
|
private Dictionary<Format, TextureStorage> _aliasedStorages;
|
||||||
@ -55,6 +62,9 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
private int _viewsCount;
|
private int _viewsCount;
|
||||||
private readonly ulong _size;
|
private readonly ulong _size;
|
||||||
|
|
||||||
|
private int _bindCount;
|
||||||
|
private readonly TextureSliceInfo[] _slices;
|
||||||
|
|
||||||
public VkFormat VkFormat { get; }
|
public VkFormat VkFormat { get; }
|
||||||
|
|
||||||
public unsafe TextureStorage(
|
public unsafe TextureStorage(
|
||||||
@ -73,6 +83,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
var depth = (uint)(info.Target == Target.Texture3D ? info.Depth : 1);
|
var depth = (uint)(info.Target == Target.Texture3D ? info.Depth : 1);
|
||||||
|
|
||||||
VkFormat = format;
|
VkFormat = format;
|
||||||
|
_depthOrLayers = info.GetDepthOrLayers();
|
||||||
|
|
||||||
var type = info.Target.Convert();
|
var type = info.Target.Convert();
|
||||||
|
|
||||||
@ -80,7 +91,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
var sampleCountFlags = ConvertToSampleCountFlags(gd.Capabilities.SupportedSampleCounts, (uint)info.Samples);
|
var sampleCountFlags = ConvertToSampleCountFlags(gd.Capabilities.SupportedSampleCounts, (uint)info.Samples);
|
||||||
|
|
||||||
var usage = GetImageUsage(info.Format, info.Target, gd.Capabilities.SupportsShaderStorageImageMultisample);
|
var usage = GetImageUsage(info.Format, info.Target, gd.Capabilities);
|
||||||
|
|
||||||
var flags = ImageCreateFlags.CreateMutableFormatBit | ImageCreateFlags.CreateExtendedUsageBit;
|
var flags = ImageCreateFlags.CreateMutableFormatBit | ImageCreateFlags.CreateExtendedUsageBit;
|
||||||
|
|
||||||
@ -114,7 +125,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
Flags = flags,
|
Flags = flags,
|
||||||
};
|
};
|
||||||
|
|
||||||
gd.Api.CreateImage(device, imageCreateInfo, null, out _image).ThrowOnError();
|
gd.Api.CreateImage(device, in imageCreateInfo, null, out _image).ThrowOnError();
|
||||||
|
|
||||||
if (foreignAllocation == null)
|
if (foreignAllocation == null)
|
||||||
{
|
{
|
||||||
@ -148,6 +159,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
InitialTransition(ImageLayout.Preinitialized, ImageLayout.General);
|
InitialTransition(ImageLayout.Preinitialized, ImageLayout.General);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_slices = new TextureSliceInfo[levels * _depthOrLayers];
|
||||||
}
|
}
|
||||||
|
|
||||||
public TextureStorage CreateAliasedColorForDepthStorageUnsafe(Format format)
|
public TextureStorage CreateAliasedColorForDepthStorageUnsafe(Format format)
|
||||||
@ -284,7 +297,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
0,
|
0,
|
||||||
null,
|
null,
|
||||||
1,
|
1,
|
||||||
barrier);
|
in barrier);
|
||||||
|
|
||||||
if (useTempCbs)
|
if (useTempCbs)
|
||||||
{
|
{
|
||||||
@ -292,7 +305,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ImageUsageFlags GetImageUsage(Format format, Target target, bool supportsMsStorage)
|
public static ImageUsageFlags GetImageUsage(Format format, Target target, in HardwareCapabilities capabilities)
|
||||||
{
|
{
|
||||||
var usage = DefaultUsageFlags;
|
var usage = DefaultUsageFlags;
|
||||||
|
|
||||||
@ -305,11 +318,19 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
usage |= ImageUsageFlags.ColorAttachmentBit;
|
usage |= ImageUsageFlags.ColorAttachmentBit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool supportsMsStorage = capabilities.SupportsShaderStorageImageMultisample;
|
||||||
|
|
||||||
if (format.IsImageCompatible() && (supportsMsStorage || !target.IsMultisample()))
|
if (format.IsImageCompatible() && (supportsMsStorage || !target.IsMultisample()))
|
||||||
{
|
{
|
||||||
usage |= ImageUsageFlags.StorageBit;
|
usage |= ImageUsageFlags.StorageBit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (capabilities.SupportsAttachmentFeedbackLoop &&
|
||||||
|
(usage & (ImageUsageFlags.DepthStencilAttachmentBit | ImageUsageFlags.ColorAttachmentBit)) != 0)
|
||||||
|
{
|
||||||
|
usage |= ImageUsageFlags.AttachmentFeedbackLoopBitExt;
|
||||||
|
}
|
||||||
|
|
||||||
return usage;
|
return usage;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -401,11 +422,11 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
if (to)
|
if (to)
|
||||||
{
|
{
|
||||||
_gd.Api.CmdCopyImageToBuffer(commandBuffer, image, ImageLayout.General, buffer, 1, region);
|
_gd.Api.CmdCopyImageToBuffer(commandBuffer, image, ImageLayout.General, buffer, 1, in region);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_gd.Api.CmdCopyBufferToImage(commandBuffer, buffer, image, ImageLayout.General, 1, region);
|
_gd.Api.CmdCopyBufferToImage(commandBuffer, buffer, image, ImageLayout.General, 1, in region);
|
||||||
}
|
}
|
||||||
|
|
||||||
offset += mipSize;
|
offset += mipSize;
|
||||||
@ -510,6 +531,55 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void AddBinding(TextureView view)
|
||||||
|
{
|
||||||
|
// Assumes a view only has a first level.
|
||||||
|
|
||||||
|
int index = view.FirstLevel * _depthOrLayers + view.FirstLayer;
|
||||||
|
int layers = view.Layers;
|
||||||
|
|
||||||
|
for (int i = 0; i < layers; i++)
|
||||||
|
{
|
||||||
|
ref TextureSliceInfo info = ref _slices[index++];
|
||||||
|
|
||||||
|
info.BindCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
_bindCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearBindings()
|
||||||
|
{
|
||||||
|
if (_bindCount != 0)
|
||||||
|
{
|
||||||
|
Array.Clear(_slices, 0, _slices.Length);
|
||||||
|
|
||||||
|
_bindCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public bool IsBound(TextureView view)
|
||||||
|
{
|
||||||
|
if (_bindCount != 0)
|
||||||
|
{
|
||||||
|
int index = view.FirstLevel * _depthOrLayers + view.FirstLayer;
|
||||||
|
int layers = view.Layers;
|
||||||
|
|
||||||
|
for (int i = 0; i < layers; i++)
|
||||||
|
{
|
||||||
|
ref TextureSliceInfo info = ref _slices[index++];
|
||||||
|
|
||||||
|
if (info.BindCount != 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public void IncrementViewsCount()
|
public void IncrementViewsCount()
|
||||||
{
|
{
|
||||||
_viewsCount++;
|
_viewsCount++;
|
||||||
|
@ -23,6 +23,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
private readonly Auto<DisposableImageView> _imageView2dArray;
|
private readonly Auto<DisposableImageView> _imageView2dArray;
|
||||||
private Dictionary<Format, TextureView> _selfManagedViews;
|
private Dictionary<Format, TextureView> _selfManagedViews;
|
||||||
|
|
||||||
|
private int _hazardUses;
|
||||||
|
|
||||||
private readonly TextureCreateInfo _info;
|
private readonly TextureCreateInfo _info;
|
||||||
|
|
||||||
private HashTableSlim<RenderPassCacheKey, RenderPassHolder> _renderPasses;
|
private HashTableSlim<RenderPassCacheKey, RenderPassHolder> _renderPasses;
|
||||||
@ -60,7 +62,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
gd.Textures.Add(this);
|
gd.Textures.Add(this);
|
||||||
|
|
||||||
var format = _gd.FormatCapabilities.ConvertToVkFormat(info.Format);
|
var format = _gd.FormatCapabilities.ConvertToVkFormat(info.Format);
|
||||||
var usage = TextureStorage.GetImageUsage(info.Format, info.Target, gd.Capabilities.SupportsShaderStorageImageMultisample);
|
var usage = TextureStorage.GetImageUsage(info.Format, info.Target, gd.Capabilities);
|
||||||
var levels = (uint)info.Levels;
|
var levels = (uint)info.Levels;
|
||||||
var layers = (uint)info.GetLayers();
|
var layers = (uint)info.GetLayers();
|
||||||
|
|
||||||
@ -117,7 +119,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
PNext = &imageViewUsage,
|
PNext = &imageViewUsage,
|
||||||
};
|
};
|
||||||
|
|
||||||
gd.Api.CreateImageView(device, imageCreateInfo, null, out var imageView).ThrowOnError();
|
gd.Api.CreateImageView(device, in imageCreateInfo, null, out var imageView).ThrowOnError();
|
||||||
return new Auto<DisposableImageView>(new DisposableImageView(gd.Api, device, imageView), null, storage.GetImage());
|
return new Auto<DisposableImageView>(new DisposableImageView(gd.Api, device, imageView), null, storage.GetImage());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -492,7 +494,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
dstStageMask,
|
dstStageMask,
|
||||||
DependencyFlags.None,
|
DependencyFlags.None,
|
||||||
1,
|
1,
|
||||||
memoryBarrier,
|
in memoryBarrier,
|
||||||
0,
|
0,
|
||||||
null,
|
null,
|
||||||
0,
|
0,
|
||||||
@ -557,7 +559,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
0,
|
0,
|
||||||
null,
|
null,
|
||||||
1,
|
1,
|
||||||
memoryBarrier);
|
in memoryBarrier);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TextureView GetView(Format format)
|
public TextureView GetView(Format format)
|
||||||
@ -949,11 +951,11 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
if (to)
|
if (to)
|
||||||
{
|
{
|
||||||
_gd.Api.CmdCopyImageToBuffer(commandBuffer, image, ImageLayout.General, buffer, 1, region);
|
_gd.Api.CmdCopyImageToBuffer(commandBuffer, image, ImageLayout.General, buffer, 1, in region);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_gd.Api.CmdCopyBufferToImage(commandBuffer, buffer, image, ImageLayout.General, 1, region);
|
_gd.Api.CmdCopyBufferToImage(commandBuffer, buffer, image, ImageLayout.General, 1, in region);
|
||||||
}
|
}
|
||||||
|
|
||||||
offset += mipSize;
|
offset += mipSize;
|
||||||
@ -1010,11 +1012,11 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
if (to)
|
if (to)
|
||||||
{
|
{
|
||||||
_gd.Api.CmdCopyImageToBuffer(commandBuffer, image, ImageLayout.General, buffer, 1, region);
|
_gd.Api.CmdCopyImageToBuffer(commandBuffer, image, ImageLayout.General, buffer, 1, in region);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_gd.Api.CmdCopyBufferToImage(commandBuffer, buffer, image, ImageLayout.General, 1, region);
|
_gd.Api.CmdCopyBufferToImage(commandBuffer, buffer, image, ImageLayout.General, 1, in region);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1034,6 +1036,34 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void PrepareForUsage(CommandBufferScoped cbs, PipelineStageFlags flags, List<TextureView> feedbackLoopHazards)
|
||||||
|
{
|
||||||
|
Storage.QueueWriteToReadBarrier(cbs, AccessFlags.ShaderReadBit, flags);
|
||||||
|
|
||||||
|
if (feedbackLoopHazards != null && Storage.IsBound(this))
|
||||||
|
{
|
||||||
|
feedbackLoopHazards.Add(this);
|
||||||
|
_hazardUses++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearUsage(List<TextureView> feedbackLoopHazards)
|
||||||
|
{
|
||||||
|
if (_hazardUses != 0 && feedbackLoopHazards != null)
|
||||||
|
{
|
||||||
|
feedbackLoopHazards.Remove(this);
|
||||||
|
_hazardUses--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DecrementHazardUses()
|
||||||
|
{
|
||||||
|
if (_hazardUses != 0)
|
||||||
|
{
|
||||||
|
_hazardUses--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public (RenderPassHolder rpHolder, Auto<DisposableFramebuffer> framebuffer) GetPassAndFramebuffer(
|
public (RenderPassHolder rpHolder, Auto<DisposableFramebuffer> framebuffer) GetPassAndFramebuffer(
|
||||||
VulkanRenderer gd,
|
VulkanRenderer gd,
|
||||||
Device device,
|
Device device,
|
||||||
|
@ -90,11 +90,9 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
DriverId.SamsungProprietary => "Samsung",
|
DriverId.SamsungProprietary => "Samsung",
|
||||||
DriverId.MesaVenus => "Venus",
|
DriverId.MesaVenus => "Venus",
|
||||||
DriverId.MesaDozen => "Dozen",
|
DriverId.MesaDozen => "Dozen",
|
||||||
|
DriverId.MesaNvk => "NVK",
|
||||||
// TODO: Use real enum when we have an up to date Silk.NET.
|
DriverId.ImaginationOpenSourceMesa => "Imagination (Open)",
|
||||||
(DriverId)24 => "NVK",
|
DriverId.MesaAgxv => "Honeykrisp",
|
||||||
(DriverId)25 => "Imagination (Open)",
|
|
||||||
(DriverId)26 => "Honeykrisp",
|
|
||||||
_ => id.ToString(),
|
_ => id.ToString(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
"VK_EXT_4444_formats",
|
"VK_EXT_4444_formats",
|
||||||
"VK_KHR_8bit_storage",
|
"VK_KHR_8bit_storage",
|
||||||
"VK_KHR_maintenance2",
|
"VK_KHR_maintenance2",
|
||||||
|
"VK_EXT_attachment_feedback_loop_layout",
|
||||||
|
"VK_EXT_attachment_feedback_loop_dynamic_state",
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly string[] _requiredExtensions = {
|
private static readonly string[] _requiredExtensions = {
|
||||||
@ -357,6 +359,28 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
features2.PNext = &supportedFeaturesDepthClipControl;
|
features2.PNext = &supportedFeaturesDepthClipControl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesEXT supportedFeaturesAttachmentFeedbackLoopLayout = new()
|
||||||
|
{
|
||||||
|
SType = StructureType.PhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesExt,
|
||||||
|
PNext = features2.PNext,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (physicalDevice.IsDeviceExtensionPresent("VK_EXT_attachment_feedback_loop_layout"))
|
||||||
|
{
|
||||||
|
features2.PNext = &supportedFeaturesAttachmentFeedbackLoopLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT supportedFeaturesDynamicAttachmentFeedbackLoopLayout = new()
|
||||||
|
{
|
||||||
|
SType = StructureType.PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesExt,
|
||||||
|
PNext = features2.PNext,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (physicalDevice.IsDeviceExtensionPresent("VK_EXT_attachment_feedback_loop_dynamic_state"))
|
||||||
|
{
|
||||||
|
features2.PNext = &supportedFeaturesDynamicAttachmentFeedbackLoopLayout;
|
||||||
|
}
|
||||||
|
|
||||||
PhysicalDeviceVulkan12Features supportedPhysicalDeviceVulkan12Features = new()
|
PhysicalDeviceVulkan12Features supportedPhysicalDeviceVulkan12Features = new()
|
||||||
{
|
{
|
||||||
SType = StructureType.PhysicalDeviceVulkan12Features,
|
SType = StructureType.PhysicalDeviceVulkan12Features,
|
||||||
@ -531,6 +555,36 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
pExtendedFeatures = &featuresDepthClipControl;
|
pExtendedFeatures = &featuresDepthClipControl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesEXT featuresAttachmentFeedbackLoopLayout;
|
||||||
|
|
||||||
|
if (physicalDevice.IsDeviceExtensionPresent("VK_EXT_attachment_feedback_loop_layout") &&
|
||||||
|
supportedFeaturesAttachmentFeedbackLoopLayout.AttachmentFeedbackLoopLayout)
|
||||||
|
{
|
||||||
|
featuresAttachmentFeedbackLoopLayout = new()
|
||||||
|
{
|
||||||
|
SType = StructureType.PhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesExt,
|
||||||
|
PNext = pExtendedFeatures,
|
||||||
|
AttachmentFeedbackLoopLayout = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
pExtendedFeatures = &featuresAttachmentFeedbackLoopLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT featuresDynamicAttachmentFeedbackLoopLayout;
|
||||||
|
|
||||||
|
if (physicalDevice.IsDeviceExtensionPresent("VK_EXT_attachment_feedback_loop_dynamic_state") &&
|
||||||
|
supportedFeaturesDynamicAttachmentFeedbackLoopLayout.AttachmentFeedbackLoopDynamicState)
|
||||||
|
{
|
||||||
|
featuresDynamicAttachmentFeedbackLoopLayout = new()
|
||||||
|
{
|
||||||
|
SType = StructureType.PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesExt,
|
||||||
|
PNext = pExtendedFeatures,
|
||||||
|
AttachmentFeedbackLoopDynamicState = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
pExtendedFeatures = &featuresDynamicAttachmentFeedbackLoopLayout;
|
||||||
|
}
|
||||||
|
|
||||||
var enabledExtensions = _requiredExtensions.Union(_desirableExtensions.Intersect(physicalDevice.DeviceExtensions)).ToArray();
|
var enabledExtensions = _requiredExtensions.Union(_desirableExtensions.Intersect(physicalDevice.DeviceExtensions)).ToArray();
|
||||||
|
|
||||||
IntPtr* ppEnabledExtensions = stackalloc IntPtr[enabledExtensions.Length];
|
IntPtr* ppEnabledExtensions = stackalloc IntPtr[enabledExtensions.Length];
|
||||||
|
@ -38,6 +38,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
internal KhrPushDescriptor PushDescriptorApi { get; private set; }
|
internal KhrPushDescriptor PushDescriptorApi { get; private set; }
|
||||||
internal ExtTransformFeedback TransformFeedbackApi { get; private set; }
|
internal ExtTransformFeedback TransformFeedbackApi { get; private set; }
|
||||||
internal KhrDrawIndirectCount DrawIndirectCountApi { get; private set; }
|
internal KhrDrawIndirectCount DrawIndirectCountApi { get; private set; }
|
||||||
|
internal ExtAttachmentFeedbackLoopDynamicState DynamicFeedbackLoopApi { get; private set; }
|
||||||
|
|
||||||
internal uint QueueFamilyIndex { get; private set; }
|
internal uint QueueFamilyIndex { get; private set; }
|
||||||
internal Queue Queue { get; private set; }
|
internal Queue Queue { get; private set; }
|
||||||
@ -149,6 +150,11 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
DrawIndirectCountApi = drawIndirectCountApi;
|
DrawIndirectCountApi = drawIndirectCountApi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Api.TryGetDeviceExtension(_instance.Instance, _device, out ExtAttachmentFeedbackLoopDynamicState dynamicFeedbackLoopApi))
|
||||||
|
{
|
||||||
|
DynamicFeedbackLoopApi = dynamicFeedbackLoopApi;
|
||||||
|
}
|
||||||
|
|
||||||
if (maxQueueCount >= 2)
|
if (maxQueueCount >= 2)
|
||||||
{
|
{
|
||||||
Api.GetDeviceQueue(_device, queueFamilyIndex, 1, out var backgroundQueue);
|
Api.GetDeviceQueue(_device, queueFamilyIndex, 1, out var backgroundQueue);
|
||||||
@ -243,6 +249,16 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
SType = StructureType.PhysicalDeviceDepthClipControlFeaturesExt,
|
SType = StructureType.PhysicalDeviceDepthClipControlFeaturesExt,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
PhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesEXT featuresAttachmentFeedbackLoop = new()
|
||||||
|
{
|
||||||
|
SType = StructureType.PhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesExt,
|
||||||
|
};
|
||||||
|
|
||||||
|
PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT featuresDynamicAttachmentFeedbackLoop = new()
|
||||||
|
{
|
||||||
|
SType = StructureType.PhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesExt,
|
||||||
|
};
|
||||||
|
|
||||||
PhysicalDevicePortabilitySubsetFeaturesKHR featuresPortabilitySubset = new()
|
PhysicalDevicePortabilitySubsetFeaturesKHR featuresPortabilitySubset = new()
|
||||||
{
|
{
|
||||||
SType = StructureType.PhysicalDevicePortabilitySubsetFeaturesKhr,
|
SType = StructureType.PhysicalDevicePortabilitySubsetFeaturesKhr,
|
||||||
@ -279,6 +295,22 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
features2.PNext = &featuresDepthClipControl;
|
features2.PNext = &featuresDepthClipControl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool supportsAttachmentFeedbackLoop = _physicalDevice.IsDeviceExtensionPresent("VK_EXT_attachment_feedback_loop_layout");
|
||||||
|
|
||||||
|
if (supportsAttachmentFeedbackLoop)
|
||||||
|
{
|
||||||
|
featuresAttachmentFeedbackLoop.PNext = features2.PNext;
|
||||||
|
features2.PNext = &featuresAttachmentFeedbackLoop;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool supportsDynamicAttachmentFeedbackLoop = _physicalDevice.IsDeviceExtensionPresent("VK_EXT_attachment_feedback_loop_dynamic_state");
|
||||||
|
|
||||||
|
if (supportsDynamicAttachmentFeedbackLoop)
|
||||||
|
{
|
||||||
|
featuresDynamicAttachmentFeedbackLoop.PNext = features2.PNext;
|
||||||
|
features2.PNext = &featuresDynamicAttachmentFeedbackLoop;
|
||||||
|
}
|
||||||
|
|
||||||
bool usePortability = _physicalDevice.IsDeviceExtensionPresent("VK_KHR_portability_subset");
|
bool usePortability = _physicalDevice.IsDeviceExtensionPresent("VK_KHR_portability_subset");
|
||||||
|
|
||||||
if (usePortability)
|
if (usePortability)
|
||||||
@ -401,6 +433,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
_physicalDevice.IsDeviceExtensionPresent("VK_NV_viewport_array2"),
|
_physicalDevice.IsDeviceExtensionPresent("VK_NV_viewport_array2"),
|
||||||
_physicalDevice.IsDeviceExtensionPresent(ExtExternalMemoryHost.ExtensionName),
|
_physicalDevice.IsDeviceExtensionPresent(ExtExternalMemoryHost.ExtensionName),
|
||||||
supportsDepthClipControl && featuresDepthClipControl.DepthClipControl,
|
supportsDepthClipControl && featuresDepthClipControl.DepthClipControl,
|
||||||
|
supportsAttachmentFeedbackLoop && featuresAttachmentFeedbackLoop.AttachmentFeedbackLoopLayout,
|
||||||
|
supportsDynamicAttachmentFeedbackLoop && featuresDynamicAttachmentFeedbackLoop.AttachmentFeedbackLoopDynamicState,
|
||||||
propertiesSubgroup.SubgroupSize,
|
propertiesSubgroup.SubgroupSize,
|
||||||
supportedSampleCounts,
|
supportedSampleCounts,
|
||||||
portabilityFlags,
|
portabilityFlags,
|
||||||
|
@ -160,7 +160,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
SwizzleComponent.Blue,
|
SwizzleComponent.Blue,
|
||||||
SwizzleComponent.Alpha);
|
SwizzleComponent.Alpha);
|
||||||
|
|
||||||
_gd.SwapchainApi.CreateSwapchain(_device, swapchainCreateInfo, null, out _swapchain).ThrowOnError();
|
_gd.SwapchainApi.CreateSwapchain(_device, in swapchainCreateInfo, null, out _swapchain).ThrowOnError();
|
||||||
|
|
||||||
_gd.SwapchainApi.GetSwapchainImages(_device, _swapchain, &imageCount, null);
|
_gd.SwapchainApi.GetSwapchainImages(_device, _swapchain, &imageCount, null);
|
||||||
|
|
||||||
@ -187,14 +187,14 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
for (int i = 0; i < _imageAvailableSemaphores.Length; i++)
|
for (int i = 0; i < _imageAvailableSemaphores.Length; i++)
|
||||||
{
|
{
|
||||||
_gd.Api.CreateSemaphore(_device, semaphoreCreateInfo, null, out _imageAvailableSemaphores[i]).ThrowOnError();
|
_gd.Api.CreateSemaphore(_device, in semaphoreCreateInfo, null, out _imageAvailableSemaphores[i]).ThrowOnError();
|
||||||
}
|
}
|
||||||
|
|
||||||
_renderFinishedSemaphores = new Semaphore[imageCount];
|
_renderFinishedSemaphores = new Semaphore[imageCount];
|
||||||
|
|
||||||
for (int i = 0; i < _renderFinishedSemaphores.Length; i++)
|
for (int i = 0; i < _renderFinishedSemaphores.Length; i++)
|
||||||
{
|
{
|
||||||
_gd.Api.CreateSemaphore(_device, semaphoreCreateInfo, null, out _renderFinishedSemaphores[i]).ThrowOnError();
|
_gd.Api.CreateSemaphore(_device, in semaphoreCreateInfo, null, out _renderFinishedSemaphores[i]).ThrowOnError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,7 +220,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
SubresourceRange = subresourceRange,
|
SubresourceRange = subresourceRange,
|
||||||
};
|
};
|
||||||
|
|
||||||
_gd.Api.CreateImageView(_device, imageCreateInfo, null, out var imageView).ThrowOnError();
|
_gd.Api.CreateImageView(_device, in imageCreateInfo, null, out var imageView).ThrowOnError();
|
||||||
|
|
||||||
return new TextureView(_gd, _device, new DisposableImageView(_gd.Api, _device, imageView), info, format);
|
return new TextureView(_gd, _device, new DisposableImageView(_gd.Api, _device, imageView), info, format);
|
||||||
}
|
}
|
||||||
@ -479,7 +479,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
lock (_gd.QueueLock)
|
lock (_gd.QueueLock)
|
||||||
{
|
{
|
||||||
_gd.SwapchainApi.QueuePresent(_gd.Queue, presentInfo);
|
_gd.SwapchainApi.QueuePresent(_gd.Queue, in presentInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -611,7 +611,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
0,
|
0,
|
||||||
null,
|
null,
|
||||||
1,
|
1,
|
||||||
barrier);
|
in barrier);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CaptureFrame(TextureView texture, int x, int y, int width, int height, bool isBgra, bool flipX, bool flipY)
|
private void CaptureFrame(TextureView texture, int x, int y, int width, int height, bool isBgra, bool flipX, bool flipY)
|
||||||
|
@ -4,6 +4,8 @@ using Ryujinx.Common.Configuration;
|
|||||||
using Ryujinx.Common.GraphicsDriver;
|
using Ryujinx.Common.GraphicsDriver;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Common.SystemInterop;
|
using Ryujinx.Common.SystemInterop;
|
||||||
|
using Ryujinx.Common.Utilities;
|
||||||
|
using Ryujinx.Graphics.Vulkan.MoltenVK;
|
||||||
using Ryujinx.Modules;
|
using Ryujinx.Modules;
|
||||||
using Ryujinx.SDL2.Common;
|
using Ryujinx.SDL2.Common;
|
||||||
using Ryujinx.UI;
|
using Ryujinx.UI;
|
||||||
@ -13,7 +15,6 @@ using Ryujinx.UI.Common.Configuration;
|
|||||||
using Ryujinx.UI.Common.Helper;
|
using Ryujinx.UI.Common.Helper;
|
||||||
using Ryujinx.UI.Common.SystemInfo;
|
using Ryujinx.UI.Common.SystemInfo;
|
||||||
using Ryujinx.UI.Widgets;
|
using Ryujinx.UI.Widgets;
|
||||||
using SixLabors.ImageSharp.Formats.Jpeg;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
@ -41,9 +42,6 @@ namespace Ryujinx
|
|||||||
[LibraryImport("user32.dll", SetLastError = true)]
|
[LibraryImport("user32.dll", SetLastError = true)]
|
||||||
public static partial int MessageBoxA(IntPtr hWnd, [MarshalAs(UnmanagedType.LPStr)] string text, [MarshalAs(UnmanagedType.LPStr)] string caption, uint type);
|
public static partial int MessageBoxA(IntPtr hWnd, [MarshalAs(UnmanagedType.LPStr)] string text, [MarshalAs(UnmanagedType.LPStr)] string caption, uint type);
|
||||||
|
|
||||||
[LibraryImport("libc", SetLastError = true)]
|
|
||||||
private static partial int setenv([MarshalAs(UnmanagedType.LPStr)] string name, [MarshalAs(UnmanagedType.LPStr)] string value, int overwrite);
|
|
||||||
|
|
||||||
private const uint MbIconWarning = 0x30;
|
private const uint MbIconWarning = 0x30;
|
||||||
|
|
||||||
static Program()
|
static Program()
|
||||||
@ -105,12 +103,13 @@ namespace Ryujinx
|
|||||||
throw new NotSupportedException("Failed to initialize multi-threading support.");
|
throw new NotSupportedException("Failed to initialize multi-threading support.");
|
||||||
}
|
}
|
||||||
|
|
||||||
Environment.SetEnvironmentVariable("GDK_BACKEND", "x11");
|
OsUtils.SetEnvironmentVariableNoCaching("GDK_BACKEND", "x11");
|
||||||
setenv("GDK_BACKEND", "x11", 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OperatingSystem.IsMacOS())
|
if (OperatingSystem.IsMacOS())
|
||||||
{
|
{
|
||||||
|
MVKInitialization.InitializeResolver();
|
||||||
|
|
||||||
string baseDirectory = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory);
|
string baseDirectory = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory);
|
||||||
string resourcesDataDir;
|
string resourcesDataDir;
|
||||||
|
|
||||||
@ -123,19 +122,13 @@ namespace Ryujinx
|
|||||||
resourcesDataDir = baseDirectory;
|
resourcesDataDir = baseDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SetEnvironmentVariableNoCaching(string key, string value)
|
|
||||||
{
|
|
||||||
int res = setenv(key, value, 1);
|
|
||||||
Debug.Assert(res != -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// On macOS, GTK3 needs XDG_DATA_DIRS to be set, otherwise it will try searching for "gschemas.compiled" in system directories.
|
// On macOS, GTK3 needs XDG_DATA_DIRS to be set, otherwise it will try searching for "gschemas.compiled" in system directories.
|
||||||
SetEnvironmentVariableNoCaching("XDG_DATA_DIRS", Path.Combine(resourcesDataDir, "share"));
|
OsUtils.SetEnvironmentVariableNoCaching("XDG_DATA_DIRS", Path.Combine(resourcesDataDir, "share"));
|
||||||
|
|
||||||
// On macOS, GTK3 needs GDK_PIXBUF_MODULE_FILE to be set, otherwise it will try searching for "loaders.cache" in system directories.
|
// On macOS, GTK3 needs GDK_PIXBUF_MODULE_FILE to be set, otherwise it will try searching for "loaders.cache" in system directories.
|
||||||
SetEnvironmentVariableNoCaching("GDK_PIXBUF_MODULE_FILE", Path.Combine(resourcesDataDir, "lib", "gdk-pixbuf-2.0", "2.10.0", "loaders.cache"));
|
OsUtils.SetEnvironmentVariableNoCaching("GDK_PIXBUF_MODULE_FILE", Path.Combine(resourcesDataDir, "lib", "gdk-pixbuf-2.0", "2.10.0", "loaders.cache"));
|
||||||
|
|
||||||
SetEnvironmentVariableNoCaching("GTK_IM_MODULE_FILE", Path.Combine(resourcesDataDir, "lib", "gtk-3.0", "3.0.0", "immodules.cache"));
|
OsUtils.SetEnvironmentVariableNoCaching("GTK_IM_MODULE_FILE", Path.Combine(resourcesDataDir, "lib", "gtk-3.0", "3.0.0", "immodules.cache"));
|
||||||
}
|
}
|
||||||
|
|
||||||
string systemPath = Environment.GetEnvironmentVariable("Path", EnvironmentVariableTarget.Machine);
|
string systemPath = Environment.GetEnvironmentVariable("Path", EnvironmentVariableTarget.Machine);
|
||||||
@ -162,12 +155,6 @@ namespace Ryujinx
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Sets ImageSharp Jpeg Encoder Quality.
|
|
||||||
SixLabors.ImageSharp.Configuration.Default.ImageFormatsManager.SetEncoder(JpegFormat.Instance, new JpegEncoder()
|
|
||||||
{
|
|
||||||
Quality = 100,
|
|
||||||
});
|
|
||||||
|
|
||||||
string localConfigurationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ReleaseInformation.ConfigName);
|
string localConfigurationPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ReleaseInformation.ConfigName);
|
||||||
string appDataConfigurationPath = Path.Combine(AppDataManager.BaseDirPath, ReleaseInformation.ConfigName);
|
string appDataConfigurationPath = Path.Combine(AppDataManager.BaseDirPath, ReleaseInformation.ConfigName);
|
||||||
|
|
||||||
@ -237,9 +224,9 @@ namespace Ryujinx
|
|||||||
// Logging system information.
|
// Logging system information.
|
||||||
PrintSystemInfo();
|
PrintSystemInfo();
|
||||||
|
|
||||||
// Enable OGL multithreading on the driver, when available.
|
// Enable OGL multithreading on the driver, and some other flags.
|
||||||
BackendThreading threadingMode = ConfigurationState.Instance.Graphics.BackendThreading;
|
BackendThreading threadingMode = ConfigurationState.Instance.Graphics.BackendThreading;
|
||||||
DriverUtilities.ToggleOGLThreading(threadingMode == BackendThreading.Off);
|
DriverUtilities.InitDriverConfig(threadingMode == BackendThreading.Off);
|
||||||
|
|
||||||
// Initialize Gtk.
|
// Initialize Gtk.
|
||||||
Application.Init();
|
Application.Init();
|
||||||
|
@ -30,7 +30,6 @@
|
|||||||
<PackageReference Include="OpenTK.Graphics" />
|
<PackageReference Include="OpenTK.Graphics" />
|
||||||
<PackageReference Include="SPB" />
|
<PackageReference Include="SPB" />
|
||||||
<PackageReference Include="SharpZipLib" />
|
<PackageReference Include="SharpZipLib" />
|
||||||
<PackageReference Include="SixLabors.ImageSharp" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -13,16 +13,13 @@ using Ryujinx.Input.HLE;
|
|||||||
using Ryujinx.UI.Common.Configuration;
|
using Ryujinx.UI.Common.Configuration;
|
||||||
using Ryujinx.UI.Common.Helper;
|
using Ryujinx.UI.Common.Helper;
|
||||||
using Ryujinx.UI.Widgets;
|
using Ryujinx.UI.Widgets;
|
||||||
using SixLabors.ImageSharp;
|
using SkiaSharp;
|
||||||
using SixLabors.ImageSharp.Formats.Png;
|
|
||||||
using SixLabors.ImageSharp.PixelFormats;
|
|
||||||
using SixLabors.ImageSharp.Processing;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Image = SixLabors.ImageSharp.Image;
|
|
||||||
using Key = Ryujinx.Input.Key;
|
using Key = Ryujinx.Input.Key;
|
||||||
using ScalingFilter = Ryujinx.Graphics.GAL.ScalingFilter;
|
using ScalingFilter = Ryujinx.Graphics.GAL.ScalingFilter;
|
||||||
using Switch = Ryujinx.HLE.Switch;
|
using Switch = Ryujinx.HLE.Switch;
|
||||||
@ -404,23 +401,31 @@ namespace Ryujinx.UI
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Image image = e.IsBgra ? Image.LoadPixelData<Bgra32>(e.Data, e.Width, e.Height)
|
var colorType = e.IsBgra ? SKColorType.Bgra8888 : SKColorType.Rgba8888;
|
||||||
: Image.LoadPixelData<Rgba32>(e.Data, e.Width, e.Height);
|
using var image = new SKBitmap(new SKImageInfo(e.Width, e.Height, colorType, SKAlphaType.Premul));
|
||||||
|
|
||||||
if (e.FlipX)
|
Marshal.Copy(e.Data, 0, image.GetPixels(), e.Data.Length);
|
||||||
|
using var surface = SKSurface.Create(image.Info);
|
||||||
|
var canvas = surface.Canvas;
|
||||||
|
|
||||||
|
if (e.FlipX || e.FlipY)
|
||||||
{
|
{
|
||||||
image.Mutate(x => x.Flip(FlipMode.Horizontal));
|
canvas.Clear(SKColors.Transparent);
|
||||||
|
|
||||||
|
float scaleX = e.FlipX ? -1 : 1;
|
||||||
|
float scaleY = e.FlipY ? -1 : 1;
|
||||||
|
|
||||||
|
var matrix = SKMatrix.CreateScale(scaleX, scaleY, image.Width / 2f, image.Height / 2f);
|
||||||
|
|
||||||
|
canvas.SetMatrix(matrix);
|
||||||
}
|
}
|
||||||
|
canvas.DrawBitmap(image, new SKPoint());
|
||||||
|
|
||||||
if (e.FlipY)
|
surface.Flush();
|
||||||
{
|
using var snapshot = surface.Snapshot();
|
||||||
image.Mutate(x => x.Flip(FlipMode.Vertical));
|
using var encoded = snapshot.Encode(SKEncodedImageFormat.Png, 80);
|
||||||
}
|
using var file = File.OpenWrite(path);
|
||||||
|
encoded.SaveTo(file);
|
||||||
image.SaveAsPng(path, new PngEncoder()
|
|
||||||
{
|
|
||||||
ColorType = PngColorType.Rgb,
|
|
||||||
});
|
|
||||||
|
|
||||||
image.Dispose();
|
image.Dispose();
|
||||||
|
|
||||||
|
@ -9,16 +9,13 @@ using LibHac.Tools.FsSystem.NcaUtils;
|
|||||||
using Ryujinx.Common.Memory;
|
using Ryujinx.Common.Memory;
|
||||||
using Ryujinx.HLE.FileSystem;
|
using Ryujinx.HLE.FileSystem;
|
||||||
using Ryujinx.UI.Common.Configuration;
|
using Ryujinx.UI.Common.Configuration;
|
||||||
using SixLabors.ImageSharp;
|
using SkiaSharp;
|
||||||
using SixLabors.ImageSharp.Formats.Png;
|
|
||||||
using SixLabors.ImageSharp.PixelFormats;
|
|
||||||
using SixLabors.ImageSharp.Processing;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Buffers.Binary;
|
using System.Buffers.Binary;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Image = SixLabors.ImageSharp.Image;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Ryujinx.UI.Windows
|
namespace Ryujinx.UI.Windows
|
||||||
{
|
{
|
||||||
@ -144,9 +141,11 @@ namespace Ryujinx.UI.Windows
|
|||||||
|
|
||||||
stream.Position = 0;
|
stream.Position = 0;
|
||||||
|
|
||||||
Image avatarImage = Image.LoadPixelData<Rgba32>(DecompressYaz0(stream), 256, 256);
|
using var avatarImage = new SKBitmap(new SKImageInfo(256, 256, SKColorType.Rgba8888));
|
||||||
|
var data = DecompressYaz0(stream);
|
||||||
|
Marshal.Copy(data, 0, avatarImage.GetPixels(), data.Length);
|
||||||
|
|
||||||
avatarImage.SaveAsPng(streamPng);
|
avatarImage.Encode(streamPng, SKEncodedImageFormat.Png, 80);
|
||||||
|
|
||||||
_avatarDict.Add(item.FullPath, streamPng.ToArray());
|
_avatarDict.Add(item.FullPath, streamPng.ToArray());
|
||||||
}
|
}
|
||||||
@ -170,15 +169,23 @@ namespace Ryujinx.UI.Windows
|
|||||||
{
|
{
|
||||||
using MemoryStream streamJpg = MemoryStreamManager.Shared.GetStream();
|
using MemoryStream streamJpg = MemoryStreamManager.Shared.GetStream();
|
||||||
|
|
||||||
Image avatarImage = Image.Load(data, new PngDecoder());
|
using var avatarImage = SKBitmap.Decode(data);
|
||||||
|
using var surface = SKSurface.Create(avatarImage.Info);
|
||||||
|
|
||||||
avatarImage.Mutate(x => x.BackgroundColor(new Rgba32(
|
var background = new SKColor(
|
||||||
(byte)(_backgroundColor.Red * 255),
|
(byte)(_backgroundColor.Red * 255),
|
||||||
(byte)(_backgroundColor.Green * 255),
|
(byte)(_backgroundColor.Green * 255),
|
||||||
(byte)(_backgroundColor.Blue * 255),
|
(byte)(_backgroundColor.Blue * 255),
|
||||||
(byte)(_backgroundColor.Alpha * 255)
|
(byte)(_backgroundColor.Alpha * 255)
|
||||||
)));
|
);
|
||||||
avatarImage.SaveAsJpeg(streamJpg);
|
var canvas = surface.Canvas;
|
||||||
|
canvas.Clear(background);
|
||||||
|
canvas.DrawBitmap(avatarImage, new SKPoint());
|
||||||
|
|
||||||
|
surface.Flush();
|
||||||
|
using var snapshot = surface.Snapshot();
|
||||||
|
using var encoded = snapshot.Encode(SKEncodedImageFormat.Jpeg, 80);
|
||||||
|
encoded.SaveTo(streamJpg);
|
||||||
|
|
||||||
return streamJpg.ToArray();
|
return streamJpg.ToArray();
|
||||||
}
|
}
|
||||||
|
@ -4,15 +4,13 @@ using Ryujinx.HLE.FileSystem;
|
|||||||
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
||||||
using Ryujinx.UI.Common.Configuration;
|
using Ryujinx.UI.Common.Configuration;
|
||||||
using Ryujinx.UI.Widgets;
|
using Ryujinx.UI.Widgets;
|
||||||
using SixLabors.ImageSharp;
|
using SkiaSharp;
|
||||||
using SixLabors.ImageSharp.Processing;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Image = SixLabors.ImageSharp.Image;
|
|
||||||
|
|
||||||
namespace Ryujinx.UI.Windows
|
namespace Ryujinx.UI.Windows
|
||||||
{
|
{
|
||||||
@ -177,13 +175,13 @@ namespace Ryujinx.UI.Windows
|
|||||||
|
|
||||||
private void ProcessProfileImage(byte[] buffer)
|
private void ProcessProfileImage(byte[] buffer)
|
||||||
{
|
{
|
||||||
using Image image = Image.Load(buffer);
|
using var image = SKBitmap.Decode(buffer);
|
||||||
|
|
||||||
image.Mutate(x => x.Resize(256, 256));
|
image.Resize(new SKImageInfo(256, 256), SKFilterQuality.High);
|
||||||
|
|
||||||
using MemoryStream streamJpg = MemoryStreamManager.Shared.GetStream();
|
using MemoryStream streamJpg = MemoryStreamManager.Shared.GetStream();
|
||||||
|
|
||||||
image.SaveAsJpeg(streamJpg);
|
image.Encode(streamJpg, SKEncodedImageFormat.Jpeg, 80);
|
||||||
|
|
||||||
_bufferImageProfile = streamJpg.ToArray();
|
_bufferImageProfile = streamJpg.ToArray();
|
||||||
}
|
}
|
||||||
|
63
src/Ryujinx.HLE.Generators/CodeGenerator.cs
Normal file
63
src/Ryujinx.HLE.Generators/CodeGenerator.cs
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Ryujinx.HLE.Generators
|
||||||
|
{
|
||||||
|
class CodeGenerator
|
||||||
|
{
|
||||||
|
private const int IndentLength = 4;
|
||||||
|
|
||||||
|
private readonly StringBuilder _sb;
|
||||||
|
private int _currentIndentCount;
|
||||||
|
|
||||||
|
public CodeGenerator()
|
||||||
|
{
|
||||||
|
_sb = new StringBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void EnterScope(string header = null)
|
||||||
|
{
|
||||||
|
if (header != null)
|
||||||
|
{
|
||||||
|
AppendLine(header);
|
||||||
|
}
|
||||||
|
|
||||||
|
AppendLine("{");
|
||||||
|
IncreaseIndentation();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LeaveScope(string suffix = "")
|
||||||
|
{
|
||||||
|
DecreaseIndentation();
|
||||||
|
AppendLine($"}}{suffix}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void IncreaseIndentation()
|
||||||
|
{
|
||||||
|
_currentIndentCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DecreaseIndentation()
|
||||||
|
{
|
||||||
|
if (_currentIndentCount - 1 >= 0)
|
||||||
|
{
|
||||||
|
_currentIndentCount--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AppendLine()
|
||||||
|
{
|
||||||
|
_sb.AppendLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AppendLine(string text)
|
||||||
|
{
|
||||||
|
_sb.Append(' ', IndentLength * _currentIndentCount);
|
||||||
|
_sb.AppendLine(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return _sb.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
76
src/Ryujinx.HLE.Generators/IpcServiceGenerator.cs
Normal file
76
src/Ryujinx.HLE.Generators/IpcServiceGenerator.cs
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Ryujinx.HLE.Generators
|
||||||
|
{
|
||||||
|
[Generator]
|
||||||
|
public class IpcServiceGenerator : ISourceGenerator
|
||||||
|
{
|
||||||
|
public void Execute(GeneratorExecutionContext context)
|
||||||
|
{
|
||||||
|
var syntaxReceiver = (ServiceSyntaxReceiver)context.SyntaxReceiver;
|
||||||
|
CodeGenerator generator = new CodeGenerator();
|
||||||
|
|
||||||
|
generator.AppendLine("using System;");
|
||||||
|
generator.EnterScope($"namespace Ryujinx.HLE.HOS.Services.Sm");
|
||||||
|
generator.EnterScope($"partial class IUserInterface");
|
||||||
|
|
||||||
|
generator.EnterScope($"public IpcService? GetServiceInstance(Type type, ServiceCtx context, object? parameter = null)");
|
||||||
|
foreach (var className in syntaxReceiver.Types)
|
||||||
|
{
|
||||||
|
if (className.Modifiers.Any(SyntaxKind.AbstractKeyword) || className.Modifiers.Any(SyntaxKind.PrivateKeyword) || !className.AttributeLists.Any(x => x.Attributes.Any(y => y.ToString().StartsWith("Service"))))
|
||||||
|
continue;
|
||||||
|
var name = GetFullName(className, context).Replace("global::", "");
|
||||||
|
if (!name.StartsWith("Ryujinx.HLE.HOS.Services"))
|
||||||
|
continue;
|
||||||
|
var constructors = className.ChildNodes().Where(x => x.IsKind(SyntaxKind.ConstructorDeclaration)).Select(y => y as ConstructorDeclarationSyntax);
|
||||||
|
|
||||||
|
if (!constructors.Any(x => x.ParameterList.Parameters.Count >= 1))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (constructors.Where(x => x.ParameterList.Parameters.Count >= 1).FirstOrDefault().ParameterList.Parameters[0].Type.ToString() == "ServiceCtx")
|
||||||
|
{
|
||||||
|
generator.EnterScope($"if (type == typeof({GetFullName(className, context)}))");
|
||||||
|
if (constructors.Any(x => x.ParameterList.Parameters.Count == 2))
|
||||||
|
{
|
||||||
|
var type = constructors.Where(x => x.ParameterList.Parameters.Count == 2).FirstOrDefault().ParameterList.Parameters[1].Type;
|
||||||
|
var model = context.Compilation.GetSemanticModel(type.SyntaxTree);
|
||||||
|
var typeSymbol = model.GetSymbolInfo(type).Symbol as INamedTypeSymbol;
|
||||||
|
var fullName = typeSymbol.ToString();
|
||||||
|
generator.EnterScope("if (parameter != null)");
|
||||||
|
generator.AppendLine($"return new {GetFullName(className, context)}(context, ({fullName})parameter);");
|
||||||
|
generator.LeaveScope();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (constructors.Any(x => x.ParameterList.Parameters.Count == 1))
|
||||||
|
{
|
||||||
|
generator.AppendLine($"return new {GetFullName(className, context)}(context);");
|
||||||
|
}
|
||||||
|
|
||||||
|
generator.LeaveScope();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
generator.AppendLine("return null;");
|
||||||
|
generator.LeaveScope();
|
||||||
|
|
||||||
|
generator.LeaveScope();
|
||||||
|
generator.LeaveScope();
|
||||||
|
context.AddSource($"IUserInterface.g.cs", generator.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetFullName(ClassDeclarationSyntax syntaxNode, GeneratorExecutionContext context)
|
||||||
|
{
|
||||||
|
var typeSymbol = context.Compilation.GetSemanticModel(syntaxNode.SyntaxTree).GetDeclaredSymbol(syntaxNode);
|
||||||
|
|
||||||
|
return typeSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Initialize(GeneratorInitializationContext context)
|
||||||
|
{
|
||||||
|
context.RegisterForSyntaxNotifications(() => new ServiceSyntaxReceiver());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
19
src/Ryujinx.HLE.Generators/Ryujinx.HLE.Generators.csproj
Normal file
19
src/Ryujinx.HLE.Generators/Ryujinx.HLE.Generators.csproj
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
|
||||||
|
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
|
||||||
|
<CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath>
|
||||||
|
<IsRoslynComponent>true</IsRoslynComponent>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
24
src/Ryujinx.HLE.Generators/ServiceSyntaxReceiver.cs
Normal file
24
src/Ryujinx.HLE.Generators/ServiceSyntaxReceiver.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Ryujinx.HLE.Generators
|
||||||
|
{
|
||||||
|
internal class ServiceSyntaxReceiver : ISyntaxReceiver
|
||||||
|
{
|
||||||
|
public HashSet<ClassDeclarationSyntax> Types = new HashSet<ClassDeclarationSyntax>();
|
||||||
|
|
||||||
|
public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
|
||||||
|
{
|
||||||
|
if (syntaxNode is ClassDeclarationSyntax classDeclaration)
|
||||||
|
{
|
||||||
|
if (classDeclaration.BaseList == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Types.Add(classDeclaration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -8,27 +8,24 @@ namespace Ryujinx.HLE.HOS.Applets
|
|||||||
{
|
{
|
||||||
static class AppletManager
|
static class AppletManager
|
||||||
{
|
{
|
||||||
private static readonly Dictionary<AppletId, Type> _appletMapping;
|
|
||||||
|
|
||||||
static AppletManager()
|
|
||||||
{
|
|
||||||
_appletMapping = new Dictionary<AppletId, Type>
|
|
||||||
{
|
|
||||||
{ AppletId.Error, typeof(ErrorApplet) },
|
|
||||||
{ AppletId.PlayerSelect, typeof(PlayerSelectApplet) },
|
|
||||||
{ AppletId.Controller, typeof(ControllerApplet) },
|
|
||||||
{ AppletId.SoftwareKeyboard, typeof(SoftwareKeyboardApplet) },
|
|
||||||
{ AppletId.LibAppletWeb, typeof(BrowserApplet) },
|
|
||||||
{ AppletId.LibAppletShop, typeof(BrowserApplet) },
|
|
||||||
{ AppletId.LibAppletOff, typeof(BrowserApplet) },
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IApplet Create(AppletId applet, Horizon system)
|
public static IApplet Create(AppletId applet, Horizon system)
|
||||||
{
|
{
|
||||||
if (_appletMapping.TryGetValue(applet, out Type appletClass))
|
switch (applet)
|
||||||
{
|
{
|
||||||
return (IApplet)Activator.CreateInstance(appletClass, system);
|
case AppletId.Controller:
|
||||||
|
return new ControllerApplet(system);
|
||||||
|
case AppletId.Error:
|
||||||
|
return new ErrorApplet(system);
|
||||||
|
case AppletId.PlayerSelect:
|
||||||
|
return new PlayerSelectApplet(system);
|
||||||
|
case AppletId.SoftwareKeyboard:
|
||||||
|
return new SoftwareKeyboardApplet(system);
|
||||||
|
case AppletId.LibAppletWeb:
|
||||||
|
return new BrowserApplet(system);
|
||||||
|
case AppletId.LibAppletShop:
|
||||||
|
return new BrowserApplet(system);
|
||||||
|
case AppletId.LibAppletOff:
|
||||||
|
return new BrowserApplet(system);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new NotImplementedException($"{applet} applet is not implemented.");
|
throw new NotImplementedException($"{applet} applet is not implemented.");
|
||||||
|
@ -112,11 +112,16 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
|
|||||||
{
|
{
|
||||||
// Update the parameters that were provided.
|
// Update the parameters that were provided.
|
||||||
_state.InputText = inputText ?? _state.InputText;
|
_state.InputText = inputText ?? _state.InputText;
|
||||||
_state.CursorBegin = cursorBegin.GetValueOrDefault(_state.CursorBegin);
|
_state.CursorBegin = Math.Max(0, cursorBegin.GetValueOrDefault(_state.CursorBegin));
|
||||||
_state.CursorEnd = cursorEnd.GetValueOrDefault(_state.CursorEnd);
|
_state.CursorEnd = Math.Min(cursorEnd.GetValueOrDefault(_state.CursorEnd), _state.InputText.Length);
|
||||||
_state.OverwriteMode = overwriteMode.GetValueOrDefault(_state.OverwriteMode);
|
_state.OverwriteMode = overwriteMode.GetValueOrDefault(_state.OverwriteMode);
|
||||||
_state.TypingEnabled = typingEnabled.GetValueOrDefault(_state.TypingEnabled);
|
_state.TypingEnabled = typingEnabled.GetValueOrDefault(_state.TypingEnabled);
|
||||||
|
|
||||||
|
var begin = _state.CursorBegin;
|
||||||
|
var end = _state.CursorEnd;
|
||||||
|
_state.CursorBegin = Math.Min(begin, end);
|
||||||
|
_state.CursorEnd = Math.Max(begin, end);
|
||||||
|
|
||||||
// Reset the cursor blink.
|
// Reset the cursor blink.
|
||||||
_state.TextBoxBlinkCounter = 0;
|
_state.TextBoxBlinkCounter = 0;
|
||||||
|
|
||||||
|
@ -1,14 +1,9 @@
|
|||||||
using Ryujinx.HLE.UI;
|
using Ryujinx.HLE.UI;
|
||||||
using Ryujinx.Memory;
|
using Ryujinx.Memory;
|
||||||
using SixLabors.Fonts;
|
using SkiaSharp;
|
||||||
using SixLabors.ImageSharp;
|
|
||||||
using SixLabors.ImageSharp.Drawing.Processing;
|
|
||||||
using SixLabors.ImageSharp.PixelFormats;
|
|
||||||
using SixLabors.ImageSharp.Processing;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Numerics;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
@ -29,38 +24,39 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
|
|||||||
private readonly object _bufferLock = new();
|
private readonly object _bufferLock = new();
|
||||||
|
|
||||||
private RenderingSurfaceInfo _surfaceInfo = null;
|
private RenderingSurfaceInfo _surfaceInfo = null;
|
||||||
private Image<Argb32> _surface = null;
|
private SKImageInfo _imageInfo;
|
||||||
|
private SKSurface _surface = null;
|
||||||
private byte[] _bufferData = null;
|
private byte[] _bufferData = null;
|
||||||
|
|
||||||
private readonly Image _ryujinxLogo = null;
|
private readonly SKBitmap _ryujinxLogo = null;
|
||||||
private readonly Image _padAcceptIcon = null;
|
private readonly SKBitmap _padAcceptIcon = null;
|
||||||
private readonly Image _padCancelIcon = null;
|
private readonly SKBitmap _padCancelIcon = null;
|
||||||
private readonly Image _keyModeIcon = null;
|
private readonly SKBitmap _keyModeIcon = null;
|
||||||
|
|
||||||
private readonly float _textBoxOutlineWidth;
|
private readonly float _textBoxOutlineWidth;
|
||||||
private readonly float _padPressedPenWidth;
|
private readonly float _padPressedPenWidth;
|
||||||
|
|
||||||
private readonly Color _textNormalColor;
|
private readonly SKColor _textNormalColor;
|
||||||
private readonly Color _textSelectedColor;
|
private readonly SKColor _textSelectedColor;
|
||||||
private readonly Color _textOverCursorColor;
|
private readonly SKColor _textOverCursorColor;
|
||||||
|
|
||||||
private readonly Brush _panelBrush;
|
private readonly SKPaint _panelBrush;
|
||||||
private readonly Brush _disabledBrush;
|
private readonly SKPaint _disabledBrush;
|
||||||
private readonly Brush _cursorBrush;
|
private readonly SKPaint _cursorBrush;
|
||||||
private readonly Brush _selectionBoxBrush;
|
private readonly SKPaint _selectionBoxBrush;
|
||||||
|
|
||||||
private readonly Pen _textBoxOutlinePen;
|
private readonly SKPaint _textBoxOutlinePen;
|
||||||
private readonly Pen _cursorPen;
|
private readonly SKPaint _cursorPen;
|
||||||
private readonly Pen _selectionBoxPen;
|
private readonly SKPaint _selectionBoxPen;
|
||||||
private readonly Pen _padPressedPen;
|
private readonly SKPaint _padPressedPen;
|
||||||
|
|
||||||
private readonly int _inputTextFontSize;
|
private readonly int _inputTextFontSize;
|
||||||
private Font _messageFont;
|
private SKFont _messageFont;
|
||||||
private Font _inputTextFont;
|
private SKFont _inputTextFont;
|
||||||
private Font _labelsTextFont;
|
private SKFont _labelsTextFont;
|
||||||
|
|
||||||
private RectangleF _panelRectangle;
|
private SKRect _panelRectangle;
|
||||||
private Point _logoPosition;
|
private SKPoint _logoPosition;
|
||||||
private float _messagePositionY;
|
private float _messagePositionY;
|
||||||
|
|
||||||
public SoftwareKeyboardRendererBase(IHostUITheme uiTheme)
|
public SoftwareKeyboardRendererBase(IHostUITheme uiTheme)
|
||||||
@ -78,10 +74,10 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
|
|||||||
_padCancelIcon = LoadResource(typeof(SoftwareKeyboardRendererBase).Assembly, padCancelIconPath, 0, 0);
|
_padCancelIcon = LoadResource(typeof(SoftwareKeyboardRendererBase).Assembly, padCancelIconPath, 0, 0);
|
||||||
_keyModeIcon = LoadResource(typeof(SoftwareKeyboardRendererBase).Assembly, keyModeIconPath, 0, 0);
|
_keyModeIcon = LoadResource(typeof(SoftwareKeyboardRendererBase).Assembly, keyModeIconPath, 0, 0);
|
||||||
|
|
||||||
Color panelColor = ToColor(uiTheme.DefaultBackgroundColor, 255);
|
var panelColor = ToColor(uiTheme.DefaultBackgroundColor, 255);
|
||||||
Color panelTransparentColor = ToColor(uiTheme.DefaultBackgroundColor, 150);
|
var panelTransparentColor = ToColor(uiTheme.DefaultBackgroundColor, 150);
|
||||||
Color borderColor = ToColor(uiTheme.DefaultBorderColor);
|
var borderColor = ToColor(uiTheme.DefaultBorderColor);
|
||||||
Color selectionBackgroundColor = ToColor(uiTheme.SelectionBackgroundColor);
|
var selectionBackgroundColor = ToColor(uiTheme.SelectionBackgroundColor);
|
||||||
|
|
||||||
_textNormalColor = ToColor(uiTheme.DefaultForegroundColor);
|
_textNormalColor = ToColor(uiTheme.DefaultForegroundColor);
|
||||||
_textSelectedColor = ToColor(uiTheme.SelectionForegroundColor);
|
_textSelectedColor = ToColor(uiTheme.SelectionForegroundColor);
|
||||||
@ -92,15 +88,29 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
|
|||||||
_textBoxOutlineWidth = 2;
|
_textBoxOutlineWidth = 2;
|
||||||
_padPressedPenWidth = 2;
|
_padPressedPenWidth = 2;
|
||||||
|
|
||||||
_panelBrush = new SolidBrush(panelColor);
|
_panelBrush = new SKPaint()
|
||||||
_disabledBrush = new SolidBrush(panelTransparentColor);
|
{
|
||||||
_cursorBrush = new SolidBrush(_textNormalColor);
|
Color = panelColor,
|
||||||
_selectionBoxBrush = new SolidBrush(selectionBackgroundColor);
|
IsAntialias = true
|
||||||
|
};
|
||||||
|
_disabledBrush = new SKPaint()
|
||||||
|
{
|
||||||
|
Color = panelTransparentColor,
|
||||||
|
IsAntialias = true
|
||||||
|
};
|
||||||
|
_cursorBrush = new SKPaint() { Color = _textNormalColor, IsAntialias = true };
|
||||||
|
_selectionBoxBrush = new SKPaint() { Color = selectionBackgroundColor, IsAntialias = true };
|
||||||
|
|
||||||
_textBoxOutlinePen = Pens.Solid(borderColor, _textBoxOutlineWidth);
|
_textBoxOutlinePen = new SKPaint()
|
||||||
_cursorPen = Pens.Solid(_textNormalColor, cursorWidth);
|
{
|
||||||
_selectionBoxPen = Pens.Solid(selectionBackgroundColor, cursorWidth);
|
Color = borderColor,
|
||||||
_padPressedPen = Pens.Solid(borderColor, _padPressedPenWidth);
|
StrokeWidth = _textBoxOutlineWidth,
|
||||||
|
IsStroke = true,
|
||||||
|
IsAntialias = true
|
||||||
|
};
|
||||||
|
_cursorPen = new SKPaint() { Color = _textNormalColor, StrokeWidth = cursorWidth, IsStroke = true, IsAntialias = true };
|
||||||
|
_selectionBoxPen = new SKPaint() { Color = selectionBackgroundColor, StrokeWidth = cursorWidth, IsStroke = true, IsAntialias = true };
|
||||||
|
_padPressedPen = new SKPaint() { Color = borderColor, StrokeWidth = _padPressedPenWidth, IsStroke = true, IsAntialias = true };
|
||||||
|
|
||||||
_inputTextFontSize = 20;
|
_inputTextFontSize = 20;
|
||||||
|
|
||||||
@ -123,9 +133,10 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_messageFont = SystemFonts.CreateFont(fontFamily, 26, FontStyle.Regular);
|
using var typeface = SKTypeface.FromFamilyName(fontFamily, SKFontStyle.Normal);
|
||||||
_inputTextFont = SystemFonts.CreateFont(fontFamily, _inputTextFontSize, FontStyle.Regular);
|
_messageFont = new SKFont(typeface, 26);
|
||||||
_labelsTextFont = SystemFonts.CreateFont(fontFamily, 24, FontStyle.Regular);
|
_inputTextFont = new SKFont(typeface, _inputTextFontSize);
|
||||||
|
_labelsTextFont = new SKFont(typeface, 24);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -137,7 +148,7 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
|
|||||||
throw new Exception($"None of these fonts were found in the system: {String.Join(", ", availableFonts)}!");
|
throw new Exception($"None of these fonts were found in the system: {String.Join(", ", availableFonts)}!");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Color ToColor(ThemeColor color, byte? overrideAlpha = null, bool flipRgb = false)
|
private static SKColor ToColor(ThemeColor color, byte? overrideAlpha = null, bool flipRgb = false)
|
||||||
{
|
{
|
||||||
var a = (byte)(color.A * 255);
|
var a = (byte)(color.A * 255);
|
||||||
var r = (byte)(color.R * 255);
|
var r = (byte)(color.R * 255);
|
||||||
@ -151,34 +162,33 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
|
|||||||
b = (byte)(255 - b);
|
b = (byte)(255 - b);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Color.FromRgba(r, g, b, overrideAlpha.GetValueOrDefault(a));
|
return new SKColor(r, g, b, overrideAlpha.GetValueOrDefault(a));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Image LoadResource(Assembly assembly, string resourcePath, int newWidth, int newHeight)
|
private static SKBitmap LoadResource(Assembly assembly, string resourcePath, int newWidth, int newHeight)
|
||||||
{
|
{
|
||||||
Stream resourceStream = assembly.GetManifestResourceStream(resourcePath);
|
Stream resourceStream = assembly.GetManifestResourceStream(resourcePath);
|
||||||
|
|
||||||
return LoadResource(resourceStream, newWidth, newHeight);
|
return LoadResource(resourceStream, newWidth, newHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Image LoadResource(Stream resourceStream, int newWidth, int newHeight)
|
private static SKBitmap LoadResource(Stream resourceStream, int newWidth, int newHeight)
|
||||||
{
|
{
|
||||||
Debug.Assert(resourceStream != null);
|
Debug.Assert(resourceStream != null);
|
||||||
|
|
||||||
var image = Image.Load(resourceStream);
|
var bitmap = SKBitmap.Decode(resourceStream);
|
||||||
|
|
||||||
if (newHeight != 0 && newWidth != 0)
|
if (newHeight != 0 && newWidth != 0)
|
||||||
{
|
{
|
||||||
image.Mutate(x => x.Resize(newWidth, newHeight, KnownResamplers.Lanczos3));
|
var resized = bitmap.Resize(new SKImageInfo(newWidth, newHeight), SKFilterQuality.High);
|
||||||
|
if (resized != null)
|
||||||
|
{
|
||||||
|
bitmap.Dispose();
|
||||||
|
bitmap = resized;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return image;
|
return bitmap;
|
||||||
}
|
|
||||||
|
|
||||||
private static void SetGraphicsOptions(IImageProcessingContext context)
|
|
||||||
{
|
|
||||||
context.GetGraphicsOptions().Antialias = true;
|
|
||||||
context.GetDrawingOptions().GraphicsOptions.Antialias = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawImmutableElements()
|
private void DrawImmutableElements()
|
||||||
@ -187,22 +197,18 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
var canvas = _surface.Canvas;
|
||||||
|
|
||||||
_surface.Mutate(context =>
|
canvas.Clear(SKColors.Transparent);
|
||||||
{
|
canvas.DrawRect(_panelRectangle, _panelBrush);
|
||||||
SetGraphicsOptions(context);
|
canvas.DrawBitmap(_ryujinxLogo, _logoPosition);
|
||||||
|
|
||||||
context.Clear(Color.Transparent);
|
float halfWidth = _panelRectangle.Width / 2;
|
||||||
context.Fill(_panelBrush, _panelRectangle);
|
float buttonsY = _panelRectangle.Top + 185;
|
||||||
context.DrawImage(_ryujinxLogo, _logoPosition, 1);
|
|
||||||
|
|
||||||
float halfWidth = _panelRectangle.Width / 2;
|
SKPoint disableButtonPosition = new(halfWidth + 180, buttonsY);
|
||||||
float buttonsY = _panelRectangle.Y + 185;
|
|
||||||
|
|
||||||
PointF disableButtonPosition = new(halfWidth + 180, buttonsY);
|
DrawControllerToggle(canvas, disableButtonPosition);
|
||||||
|
|
||||||
DrawControllerToggle(context, disableButtonPosition);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DrawMutableElements(SoftwareKeyboardUIState state)
|
public void DrawMutableElements(SoftwareKeyboardUIState state)
|
||||||
@ -212,40 +218,43 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_surface.Mutate(context =>
|
using var paint = new SKPaint(_messageFont)
|
||||||
{
|
{
|
||||||
var messageRectangle = MeasureString(MessageText, _messageFont);
|
Color = _textNormalColor,
|
||||||
float messagePositionX = (_panelRectangle.Width - messageRectangle.Width) / 2 - messageRectangle.X;
|
IsAntialias = true
|
||||||
float messagePositionY = _messagePositionY - messageRectangle.Y;
|
};
|
||||||
var messagePosition = new PointF(messagePositionX, messagePositionY);
|
|
||||||
var messageBoundRectangle = new RectangleF(messagePositionX, messagePositionY, messageRectangle.Width, messageRectangle.Height);
|
|
||||||
|
|
||||||
SetGraphicsOptions(context);
|
var canvas = _surface.Canvas;
|
||||||
|
var messageRectangle = MeasureString(MessageText, paint);
|
||||||
|
float messagePositionX = (_panelRectangle.Width - messageRectangle.Width) / 2 - messageRectangle.Left;
|
||||||
|
float messagePositionY = _messagePositionY - messageRectangle.Top;
|
||||||
|
var messagePosition = new SKPoint(messagePositionX, messagePositionY);
|
||||||
|
var messageBoundRectangle = SKRect.Create(messagePositionX, messagePositionY, messageRectangle.Width, messageRectangle.Height);
|
||||||
|
|
||||||
context.Fill(_panelBrush, messageBoundRectangle);
|
canvas.DrawRect(messageBoundRectangle, _panelBrush);
|
||||||
|
|
||||||
context.DrawText(MessageText, _messageFont, _textNormalColor, messagePosition);
|
canvas.DrawText(MessageText, messagePosition.X, messagePosition.Y + _messageFont.Metrics.XHeight + _messageFont.Metrics.Descent, paint);
|
||||||
|
|
||||||
if (!state.TypingEnabled)
|
if (!state.TypingEnabled)
|
||||||
{
|
{
|
||||||
// Just draw a semi-transparent rectangle on top to fade the component with the background.
|
// Just draw a semi-transparent rectangle on top to fade the component with the background.
|
||||||
// TODO (caian): This will not work if one decides to add make background semi-transparent as well.
|
// TODO (caian): This will not work if one decides to add make background semi-transparent as well.
|
||||||
|
|
||||||
context.Fill(_disabledBrush, messageBoundRectangle);
|
canvas.DrawRect(messageBoundRectangle, _disabledBrush);
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawTextBox(context, state);
|
DrawTextBox(canvas, state);
|
||||||
|
|
||||||
float halfWidth = _panelRectangle.Width / 2;
|
float halfWidth = _panelRectangle.Width / 2;
|
||||||
float buttonsY = _panelRectangle.Y + 185;
|
float buttonsY = _panelRectangle.Top + 185;
|
||||||
|
|
||||||
PointF acceptButtonPosition = new(halfWidth - 180, buttonsY);
|
SKPoint acceptButtonPosition = new(halfWidth - 180, buttonsY);
|
||||||
PointF cancelButtonPosition = new(halfWidth, buttonsY);
|
SKPoint cancelButtonPosition = new(halfWidth, buttonsY);
|
||||||
PointF disableButtonPosition = new(halfWidth + 180, buttonsY);
|
SKPoint disableButtonPosition = new(halfWidth + 180, buttonsY);
|
||||||
|
|
||||||
|
DrawPadButton(canvas, acceptButtonPosition, _padAcceptIcon, AcceptText, state.AcceptPressed, state.ControllerEnabled);
|
||||||
|
DrawPadButton(canvas, cancelButtonPosition, _padCancelIcon, CancelText, state.CancelPressed, state.ControllerEnabled);
|
||||||
|
|
||||||
DrawPadButton(context, acceptButtonPosition, _padAcceptIcon, AcceptText, state.AcceptPressed, state.ControllerEnabled);
|
|
||||||
DrawPadButton(context, cancelButtonPosition, _padCancelIcon, CancelText, state.CancelPressed, state.ControllerEnabled);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CreateSurface(RenderingSurfaceInfo surfaceInfo)
|
public void CreateSurface(RenderingSurfaceInfo surfaceInfo)
|
||||||
@ -268,7 +277,8 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
|
|||||||
Debug.Assert(_surfaceInfo.Height <= totalHeight);
|
Debug.Assert(_surfaceInfo.Height <= totalHeight);
|
||||||
Debug.Assert(_surfaceInfo.Pitch * _surfaceInfo.Height <= _surfaceInfo.Size);
|
Debug.Assert(_surfaceInfo.Pitch * _surfaceInfo.Height <= _surfaceInfo.Size);
|
||||||
|
|
||||||
_surface = new Image<Argb32>((int)totalWidth, (int)totalHeight);
|
_imageInfo = new SKImageInfo((int)totalWidth, (int)totalHeight, SKColorType.Rgba8888);
|
||||||
|
_surface = SKSurface.Create(_imageInfo);
|
||||||
|
|
||||||
ComputeConstants();
|
ComputeConstants();
|
||||||
DrawImmutableElements();
|
DrawImmutableElements();
|
||||||
@ -282,76 +292,81 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
|
|||||||
int panelHeight = 240;
|
int panelHeight = 240;
|
||||||
int panelPositionY = totalHeight - panelHeight;
|
int panelPositionY = totalHeight - panelHeight;
|
||||||
|
|
||||||
_panelRectangle = new RectangleF(0, panelPositionY, totalWidth, panelHeight);
|
_panelRectangle = SKRect.Create(0, panelPositionY, totalWidth, panelHeight);
|
||||||
|
|
||||||
_messagePositionY = panelPositionY + 60;
|
_messagePositionY = panelPositionY + 60;
|
||||||
|
|
||||||
int logoPositionX = (totalWidth - _ryujinxLogo.Width) / 2;
|
int logoPositionX = (totalWidth - _ryujinxLogo.Width) / 2;
|
||||||
int logoPositionY = panelPositionY + 18;
|
int logoPositionY = panelPositionY + 18;
|
||||||
|
|
||||||
_logoPosition = new Point(logoPositionX, logoPositionY);
|
_logoPosition = new SKPoint(logoPositionX, logoPositionY);
|
||||||
}
|
}
|
||||||
private static RectangleF MeasureString(string text, Font font)
|
private static SKRect MeasureString(string text, SKPaint paint)
|
||||||
{
|
{
|
||||||
TextOptions options = new(font);
|
SKRect bounds = SKRect.Empty;
|
||||||
|
|
||||||
if (text == "")
|
if (text == "")
|
||||||
{
|
{
|
||||||
FontRectangle emptyRectangle = TextMeasurer.MeasureSize(" ", options);
|
paint.MeasureText(" ", ref bounds);
|
||||||
|
}
|
||||||
return new RectangleF(0, emptyRectangle.Y, 0, emptyRectangle.Height);
|
else
|
||||||
|
{
|
||||||
|
paint.MeasureText(text, ref bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
FontRectangle rectangle = TextMeasurer.MeasureSize(text, options);
|
return bounds;
|
||||||
|
|
||||||
return new RectangleF(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static RectangleF MeasureString(ReadOnlySpan<char> text, Font font)
|
private static SKRect MeasureString(ReadOnlySpan<char> text, SKPaint paint)
|
||||||
{
|
{
|
||||||
TextOptions options = new(font);
|
SKRect bounds = SKRect.Empty;
|
||||||
|
|
||||||
if (text == "")
|
if (text == "")
|
||||||
{
|
{
|
||||||
FontRectangle emptyRectangle = TextMeasurer.MeasureSize(" ", options);
|
paint.MeasureText(" ", ref bounds);
|
||||||
return new RectangleF(0, emptyRectangle.Y, 0, emptyRectangle.Height);
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
paint.MeasureText(text, ref bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
FontRectangle rectangle = TextMeasurer.MeasureSize(text, options);
|
return bounds;
|
||||||
|
|
||||||
return new RectangleF(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawTextBox(IImageProcessingContext context, SoftwareKeyboardUIState state)
|
private void DrawTextBox(SKCanvas canvas, SoftwareKeyboardUIState state)
|
||||||
{
|
{
|
||||||
var inputTextRectangle = MeasureString(state.InputText, _inputTextFont);
|
using var textPaint = new SKPaint(_labelsTextFont)
|
||||||
|
{
|
||||||
|
IsAntialias = true,
|
||||||
|
Color = _textNormalColor
|
||||||
|
};
|
||||||
|
var inputTextRectangle = MeasureString(state.InputText, textPaint);
|
||||||
|
|
||||||
float boxWidth = (int)(Math.Max(300, inputTextRectangle.Width + inputTextRectangle.X + 8));
|
float boxWidth = (int)(Math.Max(300, inputTextRectangle.Width + inputTextRectangle.Left + 8));
|
||||||
float boxHeight = 32;
|
float boxHeight = 32;
|
||||||
float boxY = _panelRectangle.Y + 110;
|
float boxY = _panelRectangle.Top + 110;
|
||||||
float boxX = (int)((_panelRectangle.Width - boxWidth) / 2);
|
float boxX = (int)((_panelRectangle.Width - boxWidth) / 2);
|
||||||
|
|
||||||
RectangleF boxRectangle = new(boxX, boxY, boxWidth, boxHeight);
|
SKRect boxRectangle = SKRect.Create(boxX, boxY, boxWidth, boxHeight);
|
||||||
|
|
||||||
RectangleF boundRectangle = new(_panelRectangle.X, boxY - _textBoxOutlineWidth,
|
SKRect boundRectangle = SKRect.Create(_panelRectangle.Left, boxY - _textBoxOutlineWidth,
|
||||||
_panelRectangle.Width, boxHeight + 2 * _textBoxOutlineWidth);
|
_panelRectangle.Width, boxHeight + 2 * _textBoxOutlineWidth);
|
||||||
|
|
||||||
context.Fill(_panelBrush, boundRectangle);
|
canvas.DrawRect(boundRectangle, _panelBrush);
|
||||||
|
|
||||||
context.Draw(_textBoxOutlinePen, boxRectangle);
|
canvas.DrawRect(boxRectangle, _textBoxOutlinePen);
|
||||||
|
|
||||||
float inputTextX = (_panelRectangle.Width - inputTextRectangle.Width) / 2 - inputTextRectangle.X;
|
float inputTextX = (_panelRectangle.Width - inputTextRectangle.Width) / 2 - inputTextRectangle.Left;
|
||||||
float inputTextY = boxY + 5;
|
float inputTextY = boxY + 5;
|
||||||
|
|
||||||
var inputTextPosition = new PointF(inputTextX, inputTextY);
|
var inputTextPosition = new SKPoint(inputTextX, inputTextY);
|
||||||
|
canvas.DrawText(state.InputText, inputTextPosition.X, inputTextPosition.Y + (_labelsTextFont.Metrics.XHeight + _labelsTextFont.Metrics.Descent), textPaint);
|
||||||
context.DrawText(state.InputText, _inputTextFont, _textNormalColor, inputTextPosition);
|
|
||||||
|
|
||||||
// Draw the cursor on top of the text and redraw the text with a different color if necessary.
|
// Draw the cursor on top of the text and redraw the text with a different color if necessary.
|
||||||
|
|
||||||
Color cursorTextColor;
|
SKColor cursorTextColor;
|
||||||
Brush cursorBrush;
|
SKPaint cursorBrush;
|
||||||
Pen cursorPen;
|
SKPaint cursorPen;
|
||||||
|
|
||||||
float cursorPositionYTop = inputTextY + 1;
|
float cursorPositionYTop = inputTextY + 1;
|
||||||
float cursorPositionYBottom = cursorPositionYTop + _inputTextFontSize + 1;
|
float cursorPositionYBottom = cursorPositionYTop + _inputTextFontSize + 1;
|
||||||
@ -371,12 +386,12 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
|
|||||||
ReadOnlySpan<char> textUntilBegin = state.InputText.AsSpan(0, state.CursorBegin);
|
ReadOnlySpan<char> textUntilBegin = state.InputText.AsSpan(0, state.CursorBegin);
|
||||||
ReadOnlySpan<char> textUntilEnd = state.InputText.AsSpan(0, state.CursorEnd);
|
ReadOnlySpan<char> textUntilEnd = state.InputText.AsSpan(0, state.CursorEnd);
|
||||||
|
|
||||||
var selectionBeginRectangle = MeasureString(textUntilBegin, _inputTextFont);
|
var selectionBeginRectangle = MeasureString(textUntilBegin, textPaint);
|
||||||
var selectionEndRectangle = MeasureString(textUntilEnd, _inputTextFont);
|
var selectionEndRectangle = MeasureString(textUntilEnd, textPaint);
|
||||||
|
|
||||||
cursorVisible = true;
|
cursorVisible = true;
|
||||||
cursorPositionXLeft = inputTextX + selectionBeginRectangle.Width + selectionBeginRectangle.X;
|
cursorPositionXLeft = inputTextX + selectionBeginRectangle.Width + selectionBeginRectangle.Left;
|
||||||
cursorPositionXRight = inputTextX + selectionEndRectangle.Width + selectionEndRectangle.X;
|
cursorPositionXRight = inputTextX + selectionEndRectangle.Width + selectionEndRectangle.Left;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -390,10 +405,10 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
|
|||||||
|
|
||||||
int cursorBegin = Math.Min(state.InputText.Length, state.CursorBegin);
|
int cursorBegin = Math.Min(state.InputText.Length, state.CursorBegin);
|
||||||
ReadOnlySpan<char> textUntilCursor = state.InputText.AsSpan(0, cursorBegin);
|
ReadOnlySpan<char> textUntilCursor = state.InputText.AsSpan(0, cursorBegin);
|
||||||
var cursorTextRectangle = MeasureString(textUntilCursor, _inputTextFont);
|
var cursorTextRectangle = MeasureString(textUntilCursor, textPaint);
|
||||||
|
|
||||||
cursorVisible = true;
|
cursorVisible = true;
|
||||||
cursorPositionXLeft = inputTextX + cursorTextRectangle.Width + cursorTextRectangle.X;
|
cursorPositionXLeft = inputTextX + cursorTextRectangle.Width + cursorTextRectangle.Left;
|
||||||
|
|
||||||
if (state.OverwriteMode)
|
if (state.OverwriteMode)
|
||||||
{
|
{
|
||||||
@ -402,8 +417,8 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
|
|||||||
if (state.CursorBegin < state.InputText.Length)
|
if (state.CursorBegin < state.InputText.Length)
|
||||||
{
|
{
|
||||||
textUntilCursor = state.InputText.AsSpan(0, cursorBegin + 1);
|
textUntilCursor = state.InputText.AsSpan(0, cursorBegin + 1);
|
||||||
cursorTextRectangle = MeasureString(textUntilCursor, _inputTextFont);
|
cursorTextRectangle = MeasureString(textUntilCursor, textPaint);
|
||||||
cursorPositionXRight = inputTextX + cursorTextRectangle.Width + cursorTextRectangle.X;
|
cursorPositionXRight = inputTextX + cursorTextRectangle.Width + cursorTextRectangle.Left;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -430,29 +445,32 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
|
|||||||
|
|
||||||
if (cursorWidth == 0)
|
if (cursorWidth == 0)
|
||||||
{
|
{
|
||||||
PointF[] points = {
|
canvas.DrawLine(new SKPoint(cursorPositionXLeft, cursorPositionYTop),
|
||||||
new PointF(cursorPositionXLeft, cursorPositionYTop),
|
new SKPoint(cursorPositionXLeft, cursorPositionYBottom),
|
||||||
new PointF(cursorPositionXLeft, cursorPositionYBottom),
|
cursorPen);
|
||||||
};
|
|
||||||
|
|
||||||
context.DrawLine(cursorPen, points);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var cursorRectangle = new RectangleF(cursorPositionXLeft, cursorPositionYTop, cursorWidth, cursorHeight);
|
var cursorRectangle = SKRect.Create(cursorPositionXLeft, cursorPositionYTop, cursorWidth, cursorHeight);
|
||||||
|
|
||||||
context.Draw(cursorPen, cursorRectangle);
|
canvas.DrawRect(cursorRectangle, cursorPen);
|
||||||
context.Fill(cursorBrush, cursorRectangle);
|
canvas.DrawRect(cursorRectangle, cursorBrush);
|
||||||
|
|
||||||
Image<Argb32> textOverCursor = new((int)cursorRectangle.Width, (int)cursorRectangle.Height);
|
using var textOverCursor = SKSurface.Create(new SKImageInfo((int)cursorRectangle.Width, (int)cursorRectangle.Height, SKColorType.Rgba8888));
|
||||||
textOverCursor.Mutate(context =>
|
var textOverCanvas = textOverCursor.Canvas;
|
||||||
|
var textRelativePosition = new SKPoint(inputTextPosition.X - cursorRectangle.Left, inputTextPosition.Y - cursorRectangle.Top);
|
||||||
|
|
||||||
|
using var cursorPaint = new SKPaint(_inputTextFont)
|
||||||
{
|
{
|
||||||
var textRelativePosition = new PointF(inputTextPosition.X - cursorRectangle.X, inputTextPosition.Y - cursorRectangle.Y);
|
Color = cursorTextColor,
|
||||||
context.DrawText(state.InputText, _inputTextFont, cursorTextColor, textRelativePosition);
|
IsAntialias = true
|
||||||
});
|
};
|
||||||
|
|
||||||
var cursorPosition = new Point((int)cursorRectangle.X, (int)cursorRectangle.Y);
|
textOverCanvas.DrawText(state.InputText, textRelativePosition.X, textRelativePosition.Y + _inputTextFont.Metrics.XHeight + _inputTextFont.Metrics.Descent, cursorPaint);
|
||||||
context.DrawImage(textOverCursor, cursorPosition, 1);
|
|
||||||
|
var cursorPosition = new SKPoint((int)cursorRectangle.Left, (int)cursorRectangle.Top);
|
||||||
|
textOverCursor.Flush();
|
||||||
|
canvas.DrawSurface(textOverCursor, cursorPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!state.TypingEnabled)
|
else if (!state.TypingEnabled)
|
||||||
@ -460,11 +478,11 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
|
|||||||
// Just draw a semi-transparent rectangle on top to fade the component with the background.
|
// Just draw a semi-transparent rectangle on top to fade the component with the background.
|
||||||
// TODO (caian): This will not work if one decides to add make background semi-transparent as well.
|
// TODO (caian): This will not work if one decides to add make background semi-transparent as well.
|
||||||
|
|
||||||
context.Fill(_disabledBrush, boundRectangle);
|
canvas.DrawRect(boundRectangle, _disabledBrush);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawPadButton(IImageProcessingContext context, PointF point, Image icon, string label, bool pressed, bool enabled)
|
private void DrawPadButton(SKCanvas canvas, SKPoint point, SKBitmap icon, string label, bool pressed, bool enabled)
|
||||||
{
|
{
|
||||||
// Use relative positions so we can center the entire drawing later.
|
// Use relative positions so we can center the entire drawing later.
|
||||||
|
|
||||||
@ -473,12 +491,18 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
|
|||||||
float iconWidth = icon.Width;
|
float iconWidth = icon.Width;
|
||||||
float iconHeight = icon.Height;
|
float iconHeight = icon.Height;
|
||||||
|
|
||||||
var labelRectangle = MeasureString(label, _labelsTextFont);
|
using var paint = new SKPaint(_labelsTextFont)
|
||||||
|
{
|
||||||
|
Color = _textNormalColor,
|
||||||
|
IsAntialias = true
|
||||||
|
};
|
||||||
|
|
||||||
float labelPositionX = iconWidth + 8 - labelRectangle.X;
|
var labelRectangle = MeasureString(label, paint);
|
||||||
|
|
||||||
|
float labelPositionX = iconWidth + 8 - labelRectangle.Left;
|
||||||
float labelPositionY = 3;
|
float labelPositionY = 3;
|
||||||
|
|
||||||
float fullWidth = labelPositionX + labelRectangle.Width + labelRectangle.X;
|
float fullWidth = labelPositionX + labelRectangle.Width + labelRectangle.Left;
|
||||||
float fullHeight = iconHeight;
|
float fullHeight = iconHeight;
|
||||||
|
|
||||||
// Convert all relative positions into absolute.
|
// Convert all relative positions into absolute.
|
||||||
@ -489,24 +513,24 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
|
|||||||
iconX += originX;
|
iconX += originX;
|
||||||
iconY += originY;
|
iconY += originY;
|
||||||
|
|
||||||
var iconPosition = new Point((int)iconX, (int)iconY);
|
var iconPosition = new SKPoint((int)iconX, (int)iconY);
|
||||||
var labelPosition = new PointF(labelPositionX + originX, labelPositionY + originY);
|
var labelPosition = new SKPoint(labelPositionX + originX, labelPositionY + originY);
|
||||||
|
|
||||||
var selectedRectangle = new RectangleF(originX - 2 * _padPressedPenWidth, originY - 2 * _padPressedPenWidth,
|
var selectedRectangle = SKRect.Create(originX - 2 * _padPressedPenWidth, originY - 2 * _padPressedPenWidth,
|
||||||
fullWidth + 4 * _padPressedPenWidth, fullHeight + 4 * _padPressedPenWidth);
|
fullWidth + 4 * _padPressedPenWidth, fullHeight + 4 * _padPressedPenWidth);
|
||||||
|
|
||||||
var boundRectangle = new RectangleF(originX, originY, fullWidth, fullHeight);
|
var boundRectangle = SKRect.Create(originX, originY, fullWidth, fullHeight);
|
||||||
boundRectangle.Inflate(4 * _padPressedPenWidth, 4 * _padPressedPenWidth);
|
boundRectangle.Inflate(4 * _padPressedPenWidth, 4 * _padPressedPenWidth);
|
||||||
|
|
||||||
context.Fill(_panelBrush, boundRectangle);
|
canvas.DrawRect(boundRectangle, _panelBrush);
|
||||||
context.DrawImage(icon, iconPosition, 1);
|
canvas.DrawBitmap(icon, iconPosition);
|
||||||
context.DrawText(label, _labelsTextFont, _textNormalColor, labelPosition);
|
canvas.DrawText(label, labelPosition.X, labelPosition.Y + _labelsTextFont.Metrics.XHeight + _labelsTextFont.Metrics.Descent, paint);
|
||||||
|
|
||||||
if (enabled)
|
if (enabled)
|
||||||
{
|
{
|
||||||
if (pressed)
|
if (pressed)
|
||||||
{
|
{
|
||||||
context.Draw(_padPressedPen, selectedRectangle);
|
canvas.DrawRect(selectedRectangle, _padPressedPen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -514,21 +538,26 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
|
|||||||
// Just draw a semi-transparent rectangle on top to fade the component with the background.
|
// Just draw a semi-transparent rectangle on top to fade the component with the background.
|
||||||
// TODO (caian): This will not work if one decides to add make background semi-transparent as well.
|
// TODO (caian): This will not work if one decides to add make background semi-transparent as well.
|
||||||
|
|
||||||
context.Fill(_disabledBrush, boundRectangle);
|
canvas.DrawRect(boundRectangle, _disabledBrush);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawControllerToggle(IImageProcessingContext context, PointF point)
|
private void DrawControllerToggle(SKCanvas canvas, SKPoint point)
|
||||||
{
|
{
|
||||||
var labelRectangle = MeasureString(ControllerToggleText, _labelsTextFont);
|
using var paint = new SKPaint(_labelsTextFont)
|
||||||
|
{
|
||||||
|
IsAntialias = true,
|
||||||
|
Color = _textNormalColor
|
||||||
|
};
|
||||||
|
var labelRectangle = MeasureString(ControllerToggleText, paint);
|
||||||
|
|
||||||
// Use relative positions so we can center the entire drawing later.
|
// Use relative positions so we can center the entire drawing later.
|
||||||
|
|
||||||
float keyWidth = _keyModeIcon.Width;
|
float keyWidth = _keyModeIcon.Width;
|
||||||
float keyHeight = _keyModeIcon.Height;
|
float keyHeight = _keyModeIcon.Height;
|
||||||
|
|
||||||
float labelPositionX = keyWidth + 8 - labelRectangle.X;
|
float labelPositionX = keyWidth + 8 - labelRectangle.Left;
|
||||||
float labelPositionY = -labelRectangle.Y - 1;
|
float labelPositionY = -labelRectangle.Top - 1;
|
||||||
|
|
||||||
float keyX = 0;
|
float keyX = 0;
|
||||||
float keyY = (int)((labelPositionY + labelRectangle.Height - keyHeight) / 2);
|
float keyY = (int)((labelPositionY + labelRectangle.Height - keyHeight) / 2);
|
||||||
@ -544,14 +573,14 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
|
|||||||
keyX += originX;
|
keyX += originX;
|
||||||
keyY += originY;
|
keyY += originY;
|
||||||
|
|
||||||
var labelPosition = new PointF(labelPositionX + originX, labelPositionY + originY);
|
var labelPosition = new SKPoint(labelPositionX + originX, labelPositionY + originY);
|
||||||
var overlayPosition = new Point((int)keyX, (int)keyY);
|
var overlayPosition = new SKPoint((int)keyX, (int)keyY);
|
||||||
|
|
||||||
context.DrawImage(_keyModeIcon, overlayPosition, 1);
|
canvas.DrawBitmap(_keyModeIcon, overlayPosition);
|
||||||
context.DrawText(ControllerToggleText, _labelsTextFont, _textNormalColor, labelPosition);
|
canvas.DrawText(ControllerToggleText, labelPosition.X, labelPosition.Y + _labelsTextFont.Metrics.XHeight, paint);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CopyImageToBuffer()
|
public unsafe void CopyImageToBuffer()
|
||||||
{
|
{
|
||||||
lock (_bufferLock)
|
lock (_bufferLock)
|
||||||
{
|
{
|
||||||
@ -561,21 +590,20 @@ namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Convert the pixel format used in the image to the one used in the Switch surface.
|
// Convert the pixel format used in the image to the one used in the Switch surface.
|
||||||
|
_surface.Flush();
|
||||||
|
|
||||||
if (!_surface.DangerousTryGetSinglePixelMemory(out Memory<Argb32> pixels))
|
var buffer = new byte[_imageInfo.BytesSize];
|
||||||
|
fixed (byte* bufferPtr = buffer)
|
||||||
{
|
{
|
||||||
return;
|
if (!_surface.ReadPixels(_imageInfo, (nint)bufferPtr, _imageInfo.RowBytes, 0, 0))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_bufferData = MemoryMarshal.AsBytes(pixels.Span).ToArray();
|
_bufferData = buffer;
|
||||||
Span<uint> dataConvert = MemoryMarshal.Cast<byte, uint>(_bufferData);
|
|
||||||
|
|
||||||
Debug.Assert(_bufferData.Length == _surfaceInfo.Size);
|
Debug.Assert(buffer.Length == _surfaceInfo.Size);
|
||||||
|
|
||||||
for (int i = 0; i < dataConvert.Length; i++)
|
|
||||||
{
|
|
||||||
dataConvert[i] = BitOperations.RotateRight(dataConvert[i], 8);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
using Ryujinx.Common.Memory;
|
using Ryujinx.Common.Memory;
|
||||||
using Ryujinx.HLE.HOS.Services.Caps.Types;
|
using Ryujinx.HLE.HOS.Services.Caps.Types;
|
||||||
using SixLabors.ImageSharp;
|
using SkiaSharp;
|
||||||
using SixLabors.ImageSharp.PixelFormats;
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Caps
|
namespace Ryujinx.HLE.HOS.Services.Caps
|
||||||
@ -118,7 +118,11 @@ namespace Ryujinx.HLE.HOS.Services.Caps
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: The saved JPEG file doesn't have the limitation in the extra EXIF data.
|
// NOTE: The saved JPEG file doesn't have the limitation in the extra EXIF data.
|
||||||
Image.LoadPixelData<Rgba32>(screenshotData, 1280, 720).SaveAsJpegAsync(filePath);
|
using var bitmap = new SKBitmap(new SKImageInfo(1280, 720, SKColorType.Rgba8888));
|
||||||
|
Marshal.Copy(screenshotData, 0, bitmap.GetPixels(), screenshotData.Length);
|
||||||
|
using var data = bitmap.Encode(SKEncodedImageFormat.Jpeg, 80);
|
||||||
|
using var file = File.OpenWrite(filePath);
|
||||||
|
data.SaveTo(file);
|
||||||
|
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
@ -40,5 +40,12 @@ namespace Ryujinx.HLE.HOS.Services.Nim
|
|||||||
|
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[CommandCmif(5)] // 17.0.0+
|
||||||
|
// CreateServerInterface2(pid, handle<unknown>, u64) -> object<nn::ec::IshopServiceAccessServer>
|
||||||
|
public ResultCode CreateServerInterface2(ServiceCtx context)
|
||||||
|
{
|
||||||
|
return CreateServerInterface(context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ using Ryujinx.Common.Logging;
|
|||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel;
|
using Ryujinx.HLE.HOS.Kernel;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Ipc;
|
using Ryujinx.HLE.HOS.Kernel.Ipc;
|
||||||
|
using Ryujinx.HLE.HOS.Services.Apm;
|
||||||
using Ryujinx.Horizon.Common;
|
using Ryujinx.Horizon.Common;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@ -12,7 +13,7 @@ using System.Text;
|
|||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Sm
|
namespace Ryujinx.HLE.HOS.Services.Sm
|
||||||
{
|
{
|
||||||
class IUserInterface : IpcService
|
partial class IUserInterface : IpcService
|
||||||
{
|
{
|
||||||
private static readonly Dictionary<string, Type> _services;
|
private static readonly Dictionary<string, Type> _services;
|
||||||
|
|
||||||
@ -95,9 +96,7 @@ namespace Ryujinx.HLE.HOS.Services.Sm
|
|||||||
{
|
{
|
||||||
ServiceAttribute serviceAttribute = (ServiceAttribute)type.GetCustomAttributes(typeof(ServiceAttribute)).First(service => ((ServiceAttribute)service).Name == name);
|
ServiceAttribute serviceAttribute = (ServiceAttribute)type.GetCustomAttributes(typeof(ServiceAttribute)).First(service => ((ServiceAttribute)service).Name == name);
|
||||||
|
|
||||||
IpcService service = serviceAttribute.Parameter != null
|
IpcService service = GetServiceInstance(type, context, serviceAttribute.Parameter);
|
||||||
? (IpcService)Activator.CreateInstance(type, context, serviceAttribute.Parameter)
|
|
||||||
: (IpcService)Activator.CreateInstance(type, context);
|
|
||||||
|
|
||||||
service.TrySetServer(_commonServer);
|
service.TrySetServer(_commonServer);
|
||||||
service.Server.AddSessionObj(session.ServerSession, service);
|
service.Server.AddSessionObj(session.ServerSession, service);
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -11,6 +12,7 @@
|
|||||||
<ProjectReference Include="..\Ryujinx.Graphics.Host1x\Ryujinx.Graphics.Host1x.csproj" />
|
<ProjectReference Include="..\Ryujinx.Graphics.Host1x\Ryujinx.Graphics.Host1x.csproj" />
|
||||||
<ProjectReference Include="..\Ryujinx.Graphics.Nvdec\Ryujinx.Graphics.Nvdec.csproj" />
|
<ProjectReference Include="..\Ryujinx.Graphics.Nvdec\Ryujinx.Graphics.Nvdec.csproj" />
|
||||||
<ProjectReference Include="..\Ryujinx.Graphics.Vic\Ryujinx.Graphics.Vic.csproj" />
|
<ProjectReference Include="..\Ryujinx.Graphics.Vic\Ryujinx.Graphics.Vic.csproj" />
|
||||||
|
<ProjectReference Include="..\Ryujinx.HLE.Generators\Ryujinx.HLE.Generators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false"/>
|
||||||
<ProjectReference Include="..\Ryujinx.Horizon.Common\Ryujinx.Horizon.Common.csproj" />
|
<ProjectReference Include="..\Ryujinx.Horizon.Common\Ryujinx.Horizon.Common.csproj" />
|
||||||
<ProjectReference Include="..\Ryujinx.Horizon.Kernel.Generators\Ryujinx.Horizon.Kernel.Generators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
|
<ProjectReference Include="..\Ryujinx.Horizon.Kernel.Generators\Ryujinx.Horizon.Kernel.Generators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
|
||||||
<ProjectReference Include="..\Ryujinx.Horizon\Ryujinx.Horizon.csproj" />
|
<ProjectReference Include="..\Ryujinx.Horizon\Ryujinx.Horizon.csproj" />
|
||||||
@ -24,8 +26,8 @@
|
|||||||
<PackageReference Include="LibHac" />
|
<PackageReference Include="LibHac" />
|
||||||
<PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" />
|
<PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" />
|
||||||
<PackageReference Include="MsgPack.Cli" />
|
<PackageReference Include="MsgPack.Cli" />
|
||||||
<PackageReference Include="SixLabors.ImageSharp" />
|
<PackageReference Include="SkiaSharp" />
|
||||||
<PackageReference Include="SixLabors.ImageSharp.Drawing" />
|
<PackageReference Include="SkiaSharp.NativeAssets.Linux" />
|
||||||
<PackageReference Include="NetCoreServer" />
|
<PackageReference Include="NetCoreServer" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ using Ryujinx.Common.Configuration.Hid;
|
|||||||
using Ryujinx.Common.Configuration.Hid.Controller;
|
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||||
using Ryujinx.Common.Configuration.Hid.Controller.Motion;
|
using Ryujinx.Common.Configuration.Hid.Controller.Motion;
|
||||||
using Ryujinx.Common.Configuration.Hid.Keyboard;
|
using Ryujinx.Common.Configuration.Hid.Keyboard;
|
||||||
|
using Ryujinx.Common.GraphicsDriver;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Common.Logging.Targets;
|
using Ryujinx.Common.Logging.Targets;
|
||||||
using Ryujinx.Common.SystemInterop;
|
using Ryujinx.Common.SystemInterop;
|
||||||
@ -18,6 +19,7 @@ using Ryujinx.Graphics.Gpu;
|
|||||||
using Ryujinx.Graphics.Gpu.Shader;
|
using Ryujinx.Graphics.Gpu.Shader;
|
||||||
using Ryujinx.Graphics.OpenGL;
|
using Ryujinx.Graphics.OpenGL;
|
||||||
using Ryujinx.Graphics.Vulkan;
|
using Ryujinx.Graphics.Vulkan;
|
||||||
|
using Ryujinx.Graphics.Vulkan.MoltenVK;
|
||||||
using Ryujinx.Headless.SDL2.OpenGL;
|
using Ryujinx.Headless.SDL2.OpenGL;
|
||||||
using Ryujinx.Headless.SDL2.Vulkan;
|
using Ryujinx.Headless.SDL2.Vulkan;
|
||||||
using Ryujinx.HLE;
|
using Ryujinx.HLE;
|
||||||
@ -88,6 +90,11 @@ namespace Ryujinx.Headless.SDL2
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (OperatingSystem.IsMacOS())
|
||||||
|
{
|
||||||
|
MVKInitialization.InitializeResolver();
|
||||||
|
}
|
||||||
|
|
||||||
Parser.Default.ParseArguments<Options>(args)
|
Parser.Default.ParseArguments<Options>(args)
|
||||||
.WithParsed(Load)
|
.WithParsed(Load)
|
||||||
.WithNotParsed(errors => errors.Output());
|
.WithNotParsed(errors => errors.Output());
|
||||||
@ -457,6 +464,8 @@ namespace Ryujinx.Headless.SDL2
|
|||||||
GraphicsConfig.ShadersDumpPath = option.GraphicsShadersDumpPath;
|
GraphicsConfig.ShadersDumpPath = option.GraphicsShadersDumpPath;
|
||||||
GraphicsConfig.EnableMacroHLE = !option.DisableMacroHLE;
|
GraphicsConfig.EnableMacroHLE = !option.DisableMacroHLE;
|
||||||
|
|
||||||
|
DriverUtilities.InitDriverConfig(option.BackendThreading == BackendThreading.Off);
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
LoadApplication(option);
|
LoadApplication(option);
|
||||||
|
@ -29,6 +29,7 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
{
|
{
|
||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
|
0xe6200f10u, // QADD16 R0, R0, R0
|
||||||
0xe6600f10u, // UQADD16 R0, R0, R0
|
0xe6600f10u, // UQADD16 R0, R0, R0
|
||||||
0xe6600f70u, // UQSUB16 R0, R0, R0
|
0xe6600f70u, // UQSUB16 R0, R0, R0
|
||||||
};
|
};
|
||||||
|
@ -328,6 +328,29 @@ namespace Ryujinx.Tests.Cpu
|
|||||||
CompareAgainstUnicorn();
|
CompareAgainstUnicorn();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test, Pairwise, Description("VSHLL.<size> {<Vd>}, <Vm>, #<imm>")]
|
||||||
|
public void Vshll([Values(0u, 2u)] uint rd,
|
||||||
|
[Values(1u, 0u)] uint rm,
|
||||||
|
[Values(0u, 1u, 2u)] uint size,
|
||||||
|
[Random(RndCnt)] ulong z,
|
||||||
|
[Random(RndCnt)] ulong a,
|
||||||
|
[Random(RndCnt)] ulong b)
|
||||||
|
{
|
||||||
|
uint opcode = 0xf3b20300u; // VSHLL.I8 Q0, D0, #8
|
||||||
|
|
||||||
|
opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
|
||||||
|
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
|
||||||
|
opcode |= size << 18;
|
||||||
|
|
||||||
|
V128 v0 = MakeVectorE0E1(z, z);
|
||||||
|
V128 v1 = MakeVectorE0E1(a, z);
|
||||||
|
V128 v2 = MakeVectorE0E1(b, z);
|
||||||
|
|
||||||
|
SingleOpcode(opcode, v0: v0, v1: v1, v2: v2);
|
||||||
|
|
||||||
|
CompareAgainstUnicorn();
|
||||||
|
}
|
||||||
|
|
||||||
[Test, Pairwise, Description("VSWP D0, D0")]
|
[Test, Pairwise, Description("VSWP D0, D0")]
|
||||||
public void Vswp([Values(0u, 1u)] uint rd,
|
public void Vswp([Values(0u, 1u)] uint rd,
|
||||||
[Values(0u, 1u)] uint rm,
|
[Values(0u, 1u)] uint rm,
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using ShellLink;
|
using ShellLink;
|
||||||
using SixLabors.ImageSharp;
|
using SkiaSharp;
|
||||||
using SixLabors.ImageSharp.Formats.Png;
|
|
||||||
using SixLabors.ImageSharp.PixelFormats;
|
|
||||||
using SixLabors.ImageSharp.Processing;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@ -21,8 +18,8 @@ namespace Ryujinx.UI.Common.Helper
|
|||||||
iconPath += ".ico";
|
iconPath += ".ico";
|
||||||
|
|
||||||
MemoryStream iconDataStream = new(iconData);
|
MemoryStream iconDataStream = new(iconData);
|
||||||
var image = Image.Load(iconDataStream);
|
using var image = SKBitmap.Decode(iconDataStream);
|
||||||
image.Mutate(x => x.Resize(128, 128));
|
image.Resize(new SKImageInfo(128, 128), SKFilterQuality.High);
|
||||||
SaveBitmapAsIcon(image, iconPath);
|
SaveBitmapAsIcon(image, iconPath);
|
||||||
|
|
||||||
var shortcut = Shortcut.CreateShortcut(basePath, GetArgsString(applicationFilePath, applicationId), iconPath, 0);
|
var shortcut = Shortcut.CreateShortcut(basePath, GetArgsString(applicationFilePath, applicationId), iconPath, 0);
|
||||||
@ -37,8 +34,10 @@ namespace Ryujinx.UI.Common.Helper
|
|||||||
var desktopFile = EmbeddedResources.ReadAllText("Ryujinx.UI.Common/shortcut-template.desktop");
|
var desktopFile = EmbeddedResources.ReadAllText("Ryujinx.UI.Common/shortcut-template.desktop");
|
||||||
iconPath += ".png";
|
iconPath += ".png";
|
||||||
|
|
||||||
var image = Image.Load<Rgba32>(iconData);
|
var image = SKBitmap.Decode(iconData);
|
||||||
image.SaveAsPng(iconPath);
|
using var data = image.Encode(SKEncodedImageFormat.Png, 100);
|
||||||
|
using var file = File.OpenWrite(iconPath);
|
||||||
|
data.SaveTo(file);
|
||||||
|
|
||||||
using StreamWriter outputFile = new(Path.Combine(desktopPath, cleanedAppName + ".desktop"));
|
using StreamWriter outputFile = new(Path.Combine(desktopPath, cleanedAppName + ".desktop"));
|
||||||
outputFile.Write(desktopFile, cleanedAppName, iconPath, $"{basePath} {GetArgsString(applicationFilePath, applicationId)}");
|
outputFile.Write(desktopFile, cleanedAppName, iconPath, $"{basePath} {GetArgsString(applicationFilePath, applicationId)}");
|
||||||
@ -78,8 +77,10 @@ namespace Ryujinx.UI.Common.Helper
|
|||||||
}
|
}
|
||||||
|
|
||||||
const string IconName = "icon.png";
|
const string IconName = "icon.png";
|
||||||
var image = Image.Load<Rgba32>(iconData);
|
var image = SKBitmap.Decode(iconData);
|
||||||
image.SaveAsPng(Path.Combine(resourceFolderPath, IconName));
|
using var data = image.Encode(SKEncodedImageFormat.Png, 100);
|
||||||
|
using var file = File.OpenWrite(Path.Combine(resourceFolderPath, IconName));
|
||||||
|
data.SaveTo(file);
|
||||||
|
|
||||||
// plist file
|
// plist file
|
||||||
using StreamWriter outputFile = new(Path.Combine(contentFolderPath, "Info.plist"));
|
using StreamWriter outputFile = new(Path.Combine(contentFolderPath, "Info.plist"));
|
||||||
@ -148,7 +149,7 @@ namespace Ryujinx.UI.Common.Helper
|
|||||||
/// <param name="source">The source bitmap image that will be saved as an .ico file</param>
|
/// <param name="source">The source bitmap image that will be saved as an .ico file</param>
|
||||||
/// <param name="filePath">The location that the new .ico file will be saved too (Make sure to include '.ico' in the path).</param>
|
/// <param name="filePath">The location that the new .ico file will be saved too (Make sure to include '.ico' in the path).</param>
|
||||||
[SupportedOSPlatform("windows")]
|
[SupportedOSPlatform("windows")]
|
||||||
private static void SaveBitmapAsIcon(Image source, string filePath)
|
private static void SaveBitmapAsIcon(SKBitmap source, string filePath)
|
||||||
{
|
{
|
||||||
// Code Modified From https://stackoverflow.com/a/11448060/368354 by Benlitz
|
// Code Modified From https://stackoverflow.com/a/11448060/368354 by Benlitz
|
||||||
byte[] header = { 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 32, 0, 0, 0, 0, 0, 22, 0, 0, 0 };
|
byte[] header = { 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 32, 0, 0, 0, 0, 0, 22, 0, 0, 0 };
|
||||||
@ -156,13 +157,16 @@ namespace Ryujinx.UI.Common.Helper
|
|||||||
|
|
||||||
fs.Write(header);
|
fs.Write(header);
|
||||||
// Writing actual data
|
// Writing actual data
|
||||||
source.Save(fs, PngFormat.Instance);
|
using var data = source.Encode(SKEncodedImageFormat.Png, 100);
|
||||||
|
data.SaveTo(fs);
|
||||||
// Getting data length (file length minus header)
|
// Getting data length (file length minus header)
|
||||||
long dataLength = fs.Length - header.Length;
|
long dataLength = fs.Length - header.Length;
|
||||||
// Write it in the correct place
|
// Write it in the correct place
|
||||||
fs.Seek(14, SeekOrigin.Begin);
|
fs.Seek(14, SeekOrigin.Begin);
|
||||||
fs.WriteByte((byte)dataLength);
|
fs.WriteByte((byte)dataLength);
|
||||||
fs.WriteByte((byte)(dataLength >> 8));
|
fs.WriteByte((byte)(dataLength >> 8));
|
||||||
|
fs.WriteByte((byte)(dataLength >> 16));
|
||||||
|
fs.WriteByte((byte)(dataLength >> 24));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ using Ryujinx.Common.Configuration;
|
|||||||
using Ryujinx.Common.GraphicsDriver;
|
using Ryujinx.Common.GraphicsDriver;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Common.SystemInterop;
|
using Ryujinx.Common.SystemInterop;
|
||||||
|
using Ryujinx.Graphics.Vulkan.MoltenVK;
|
||||||
using Ryujinx.Modules;
|
using Ryujinx.Modules;
|
||||||
using Ryujinx.SDL2.Common;
|
using Ryujinx.SDL2.Common;
|
||||||
using Ryujinx.UI.Common;
|
using Ryujinx.UI.Common;
|
||||||
@ -80,6 +81,11 @@ namespace Ryujinx.Ava
|
|||||||
// Parse arguments
|
// Parse arguments
|
||||||
CommandLineState.ParseArguments(args);
|
CommandLineState.ParseArguments(args);
|
||||||
|
|
||||||
|
if (OperatingSystem.IsMacOS())
|
||||||
|
{
|
||||||
|
MVKInitialization.InitializeResolver();
|
||||||
|
}
|
||||||
|
|
||||||
// Delete backup files after updating.
|
// Delete backup files after updating.
|
||||||
Task.Run(Updater.CleanupUpdate);
|
Task.Run(Updater.CleanupUpdate);
|
||||||
|
|
||||||
@ -111,8 +117,8 @@ namespace Ryujinx.Ava
|
|||||||
// Logging system information.
|
// Logging system information.
|
||||||
PrintSystemInfo();
|
PrintSystemInfo();
|
||||||
|
|
||||||
// Enable OGL multithreading on the driver, when available.
|
// Enable OGL multithreading on the driver, and some other flags.
|
||||||
DriverUtilities.ToggleOGLThreading(ConfigurationState.Instance.Graphics.BackendThreading == BackendThreading.Off);
|
DriverUtilities.InitDriverConfig(ConfigurationState.Instance.Graphics.BackendThreading == BackendThreading.Off);
|
||||||
|
|
||||||
// Check if keys exists.
|
// Check if keys exists.
|
||||||
if (!File.Exists(Path.Combine(AppDataManager.KeysDirPath, "prod.keys")))
|
if (!File.Exists(Path.Combine(AppDataManager.KeysDirPath, "prod.keys")))
|
||||||
|
@ -41,17 +41,12 @@ namespace Ryujinx.Ava.UI.Applet
|
|||||||
|
|
||||||
private void TextChanged(string text)
|
private void TextChanged(string text)
|
||||||
{
|
{
|
||||||
TextChangedEvent?.Invoke(text ?? string.Empty, _hiddenTextBox.SelectionStart, _hiddenTextBox.SelectionEnd, true);
|
TextChangedEvent?.Invoke(text ?? string.Empty, _hiddenTextBox.SelectionStart, _hiddenTextBox.SelectionEnd, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SelectionChanged(int selection)
|
private void SelectionChanged(int selection)
|
||||||
{
|
{
|
||||||
if (_hiddenTextBox.SelectionEnd < _hiddenTextBox.SelectionStart)
|
TextChangedEvent?.Invoke(_hiddenTextBox.Text ?? string.Empty, _hiddenTextBox.SelectionStart, _hiddenTextBox.SelectionEnd, false);
|
||||||
{
|
|
||||||
_hiddenTextBox.SelectionStart = _hiddenTextBox.SelectionEnd;
|
|
||||||
}
|
|
||||||
|
|
||||||
TextChangedEvent?.Invoke(_hiddenTextBox.Text ?? string.Empty, _hiddenTextBox.SelectionStart, _hiddenTextBox.SelectionEnd, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AvaloniaDynamicTextInputHandler_TextInput(object sender, string text)
|
private void AvaloniaDynamicTextInputHandler_TextInput(object sender, string text)
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Helpers
|
namespace Ryujinx.Ava.UI.Helpers
|
||||||
{
|
{
|
||||||
public class OffscreenTextBox : TextBox
|
public class OffscreenTextBox : TextBox
|
||||||
{
|
{
|
||||||
|
protected override Type StyleKeyOverride => typeof(TextBox);
|
||||||
|
|
||||||
public static RoutedEvent<KeyEventArgs> GetKeyDownRoutedEvent()
|
public static RoutedEvent<KeyEventArgs> GetKeyDownRoutedEvent()
|
||||||
{
|
{
|
||||||
return KeyDownEvent;
|
return KeyDownEvent;
|
||||||
|
@ -42,12 +42,10 @@
|
|||||||
</Window.KeyBindings>
|
</Window.KeyBindings>
|
||||||
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
|
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="Auto" />
|
|
||||||
<RowDefinition Height="*" />
|
<RowDefinition Height="*" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<helpers:OffscreenTextBox Name="HiddenTextBox" Grid.Row="0" />
|
<helpers:OffscreenTextBox IsEnabled="False" Opacity="0" Name="HiddenTextBox" IsHitTestVisible="False" IsTabStop="False" />
|
||||||
<Grid
|
<Grid
|
||||||
Grid.Row="1"
|
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
VerticalAlignment="Stretch">
|
VerticalAlignment="Stretch">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
|
Reference in New Issue
Block a user