forked from MeloNX/MeloNX
bunch of stuff don't push this monstrosity anywhere
actual stuff don't push this monstrosity anywhere
This commit is contained in:
parent
259f5da0fb
commit
59d6ceb9ee
src
ARMeilleure
CodeGen
Native
Signal
Translation
Ryujinx.Audio.Backends.SDL2
Ryujinx.Common
Ryujinx.Graphics.Gpu
Ryujinx.Graphics.Nvdec.FFmpeg/Native
Ryujinx.Graphics.Vulkan
Ryujinx.HLE/HOS/Services
Ryujinx.Headless.SDL2
Ryujinx.Memory
MachJitWorkaround.csMemoryBlock.csMemoryManagement.csMemoryManagementUnix.csMemoryManagerUnixHelper.cs
Ryujinx.Ui.Common
Ryujinx/Ui/Helper
@ -20,7 +20,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
LinuxFeatureInfoHwCap2 = (LinuxFeatureFlagsHwCap2)getauxval(AT_HWCAP2);
|
||||
}
|
||||
|
||||
if (OperatingSystem.IsMacOS())
|
||||
if (OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
|
||||
{
|
||||
for (int i = 0; i < _sysctlNames.Length; i++)
|
||||
{
|
||||
@ -130,6 +130,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
||||
private static unsafe partial int sysctlbyname([MarshalAs(UnmanagedType.LPStr)] string name, out int oldValue, ref ulong oldSize, IntPtr newValue, ulong newValueSize);
|
||||
|
||||
[SupportedOSPlatform("macos")]
|
||||
[SupportedOSPlatform("ios")]
|
||||
private static bool CheckSysctlName(string name)
|
||||
{
|
||||
ulong size = sizeof(int);
|
||||
|
@ -58,9 +58,9 @@ namespace ARMeilleure.CodeGen
|
||||
/// <typeparam name="T">Type of delegate</typeparam>
|
||||
/// <param name="codePointer">Pointer to the function code in memory</param>
|
||||
/// <returns>A delegate of type <typeparamref name="T"/> pointing to the mapped function</returns>
|
||||
public T MapWithPointer<T>(out IntPtr codePointer)
|
||||
public T MapWithPointer<T>(out IntPtr codePointer, bool deferProtect = false)
|
||||
{
|
||||
codePointer = JitCache.Map(this);
|
||||
codePointer = JitCache.Map(this, deferProtect);
|
||||
|
||||
return Marshal.GetDelegateForFunctionPointer<T>(codePointer);
|
||||
}
|
||||
|
@ -5,9 +5,41 @@ using System.Runtime.Versioning;
|
||||
namespace ARMeilleure.Native
|
||||
{
|
||||
[SupportedOSPlatform("macos")]
|
||||
[SupportedOSPlatform("ios")]
|
||||
internal static partial class JitSupportDarwin
|
||||
{
|
||||
[LibraryImport("libarmeilleure-jitsupport", EntryPoint = "armeilleure_jit_memcpy")]
|
||||
public static partial void Copy(IntPtr dst, IntPtr src, ulong n);
|
||||
}
|
||||
|
||||
[SupportedOSPlatform("ios")]
|
||||
internal static partial class JitSupportDarwinAot
|
||||
{
|
||||
[LibraryImport("pthread", EntryPoint = "pthread_jit_write_protect_np")]
|
||||
private static partial void pthread_jit_write_protect_np(int enabled);
|
||||
|
||||
[LibraryImport("libc", EntryPoint = "sys_icache_invalidate")]
|
||||
private static partial void sys_icache_invalidate(IntPtr start, IntPtr length);
|
||||
|
||||
public static unsafe void Copy(IntPtr dst, IntPtr src, ulong n) {
|
||||
// When NativeAOT is in use, we can toggle per-thread write protection without worrying about breaking .NET code.
|
||||
|
||||
//pthread_jit_write_protect_np(0);
|
||||
|
||||
var srcSpan = new Span<byte>(src.ToPointer(), (int)n);
|
||||
var dstSpan = new Span<byte>(dst.ToPointer(), (int)n);
|
||||
srcSpan.CopyTo(dstSpan);
|
||||
|
||||
//pthread_jit_write_protect_np(1);
|
||||
|
||||
// Ensure that the instruction cache for this range is invalidated.
|
||||
sys_icache_invalidate(dst, (IntPtr)n);
|
||||
}
|
||||
|
||||
public static unsafe void Invalidate(IntPtr dst, ulong n)
|
||||
{
|
||||
// Ensure that the instruction cache for this range is invalidated.
|
||||
sys_icache_invalidate(dst, (IntPtr)n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ namespace ARMeilleure.Signal
|
||||
|
||||
ref SignalHandlerConfig config = ref GetConfigRef();
|
||||
|
||||
if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
||||
if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
|
||||
{
|
||||
_signalHandlerPtr = Marshal.GetFunctionPointerForDelegate(GenerateUnixSignalHandler(_handlerConfig));
|
||||
|
||||
@ -252,13 +252,13 @@ namespace ARMeilleure.Signal
|
||||
|
||||
private static Operand GenerateUnixFaultAddress(EmitterContext context, Operand sigInfoPtr)
|
||||
{
|
||||
ulong structAddressOffset = OperatingSystem.IsMacOS() ? 24ul : 16ul; // si_addr
|
||||
ulong structAddressOffset = (OperatingSystem.IsMacOS() || OperatingSystem.IsIOS()) ? 24ul : 16ul; // si_addr
|
||||
return context.Load(OperandType.I64, context.Add(sigInfoPtr, Const(structAddressOffset)));
|
||||
}
|
||||
|
||||
private static Operand GenerateUnixWriteFlag(EmitterContext context, Operand ucontextPtr)
|
||||
{
|
||||
if (OperatingSystem.IsMacOS())
|
||||
if (OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
|
||||
{
|
||||
const ulong McontextOffset = 48; // uc_mcontext
|
||||
Operand ctxPtr = context.Load(OperandType.I64, context.Add(ucontextPtr, Const(McontextOffset)));
|
||||
|
@ -62,7 +62,7 @@ namespace ARMeilleure.Signal
|
||||
throw new InvalidOperationException($"Could not register SIGSEGV sigaction. Error: {result}");
|
||||
}
|
||||
|
||||
if (OperatingSystem.IsMacOS())
|
||||
if (OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
|
||||
{
|
||||
result = sigaction(SIGBUS, ref sig, out _);
|
||||
|
||||
@ -77,7 +77,7 @@ namespace ARMeilleure.Signal
|
||||
|
||||
public static bool RestoreExceptionHandler(SigAction oldAction)
|
||||
{
|
||||
return sigaction(SIGSEGV, ref oldAction, out SigAction _) == 0 && (!OperatingSystem.IsMacOS() || sigaction(SIGBUS, ref oldAction, out SigAction _) == 0);
|
||||
return sigaction(SIGSEGV, ref oldAction, out SigAction _) == 0 && (!OperatingSystem.IsMacOS() || OperatingSystem.IsIOS() || sigaction(SIGBUS, ref oldAction, out SigAction _) == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,21 +30,26 @@ namespace ARMeilleure.Translation.Cache
|
||||
_blocks.Add(new MemoryBlock(0, capacity));
|
||||
}
|
||||
|
||||
public int Allocate(int size)
|
||||
public int Allocate(ref int size, int alignment)
|
||||
{
|
||||
int alignM1 = alignment - 1;
|
||||
for (int i = 0; i < _blocks.Count; i++)
|
||||
{
|
||||
MemoryBlock block = _blocks[i];
|
||||
int misAlignment = ((block.Offset + alignM1) & (~alignM1)) - block.Offset;
|
||||
int alignedSize = size + misAlignment;
|
||||
|
||||
if (block.Size > size)
|
||||
if (block.Size > alignedSize)
|
||||
{
|
||||
_blocks[i] = new MemoryBlock(block.Offset + size, block.Size - size);
|
||||
return block.Offset;
|
||||
size = alignedSize;
|
||||
_blocks[i] = new MemoryBlock(block.Offset + alignedSize, block.Size - alignedSize);
|
||||
return block.Offset + misAlignment;
|
||||
}
|
||||
else if (block.Size == size)
|
||||
else if (block.Size == alignedSize)
|
||||
{
|
||||
size = alignedSize;
|
||||
_blocks.RemoveAt(i);
|
||||
return block.Offset;
|
||||
return block.Offset + misAlignment;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@ using ARMeilleure.Memory;
|
||||
using ARMeilleure.Native;
|
||||
using Ryujinx.Memory;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
@ -18,6 +19,7 @@ namespace ARMeilleure.Translation.Cache
|
||||
|
||||
private const int CodeAlignment = 4; // Bytes.
|
||||
private const int CacheSize = 2047 * 1024 * 1024;
|
||||
private const int CacheSizeIOS = 512 * 1024 * 1024;
|
||||
|
||||
private static ReservedRegion _jitRegion;
|
||||
private static JitCacheInvalidation _jitCacheInvalidator;
|
||||
@ -47,9 +49,9 @@ namespace ARMeilleure.Translation.Cache
|
||||
return;
|
||||
}
|
||||
|
||||
_jitRegion = new ReservedRegion(allocator, CacheSize);
|
||||
_jitRegion = new ReservedRegion(allocator, (ulong)(OperatingSystem.IsIOS() ? CacheSizeIOS : CacheSize));
|
||||
|
||||
if (!OperatingSystem.IsWindows() && !OperatingSystem.IsMacOS())
|
||||
if (!OperatingSystem.IsWindows() && !OperatingSystem.IsMacOS() && !OperatingSystem.IsIOS())
|
||||
{
|
||||
_jitCacheInvalidator = new JitCacheInvalidation(allocator);
|
||||
}
|
||||
@ -65,7 +67,17 @@ namespace ARMeilleure.Translation.Cache
|
||||
}
|
||||
}
|
||||
|
||||
public static IntPtr Map(CompiledFunction func)
|
||||
static ConcurrentQueue<(int funcOffset, int length)> _deferredRxProtect = new();
|
||||
|
||||
public static void RunDeferredRxProtects()
|
||||
{
|
||||
while (_deferredRxProtect.TryDequeue(out var result))
|
||||
{
|
||||
ReprotectAsExecutable(result.funcOffset, result.length);
|
||||
}
|
||||
}
|
||||
|
||||
public static IntPtr Map(CompiledFunction func, bool deferProtect)
|
||||
{
|
||||
byte[] code = func.Code;
|
||||
|
||||
@ -73,11 +85,25 @@ namespace ARMeilleure.Translation.Cache
|
||||
{
|
||||
Debug.Assert(_initialized);
|
||||
|
||||
int funcOffset = Allocate(code.Length);
|
||||
int funcOffset = Allocate(code.Length, deferProtect);
|
||||
|
||||
IntPtr funcPtr = _jitRegion.Pointer + funcOffset;
|
||||
|
||||
if (OperatingSystem.IsMacOS() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
|
||||
if (OperatingSystem.IsIOS())
|
||||
{
|
||||
Marshal.Copy(code, 0, funcPtr, code.Length);
|
||||
if (deferProtect)
|
||||
{
|
||||
_deferredRxProtect.Enqueue((funcOffset, code.Length));
|
||||
}
|
||||
else
|
||||
{
|
||||
ReprotectAsExecutable(funcOffset, code.Length);
|
||||
|
||||
JitSupportDarwinAot.Invalidate(funcPtr, (ulong)code.Length);
|
||||
}
|
||||
}
|
||||
else if (OperatingSystem.IsMacOS()&& RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
@ -111,6 +137,11 @@ namespace ARMeilleure.Translation.Cache
|
||||
|
||||
public static void Unmap(IntPtr pointer)
|
||||
{
|
||||
if (OperatingSystem.IsIOS())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
Debug.Assert(_initialized);
|
||||
@ -145,11 +176,20 @@ namespace ARMeilleure.Translation.Cache
|
||||
_jitRegion.Block.MapAsRx((ulong)regionStart, (ulong)(regionEnd - regionStart));
|
||||
}
|
||||
|
||||
private static int Allocate(int codeSize)
|
||||
private static int Allocate(int codeSize, bool deferProtect = false)
|
||||
{
|
||||
codeSize = AlignCodeSize(codeSize);
|
||||
codeSize = AlignCodeSize(codeSize, deferProtect);
|
||||
|
||||
int allocOffset = _cacheAllocator.Allocate(codeSize);
|
||||
int alignment = CodeAlignment;
|
||||
|
||||
if (OperatingSystem.IsIOS() && !deferProtect)
|
||||
{
|
||||
alignment = 0x4000;
|
||||
}
|
||||
|
||||
int allocOffset = _cacheAllocator.Allocate(ref codeSize, alignment);
|
||||
|
||||
Console.WriteLine($"{allocOffset:x8}: {codeSize:x8} {alignment:x8}");
|
||||
|
||||
if (allocOffset < 0)
|
||||
{
|
||||
@ -161,9 +201,16 @@ namespace ARMeilleure.Translation.Cache
|
||||
return allocOffset;
|
||||
}
|
||||
|
||||
private static int AlignCodeSize(int codeSize)
|
||||
private static int AlignCodeSize(int codeSize, bool deferProtect = false)
|
||||
{
|
||||
return checked(codeSize + (CodeAlignment - 1)) & ~(CodeAlignment - 1);
|
||||
int alignment = CodeAlignment;
|
||||
|
||||
if (OperatingSystem.IsIOS() && !deferProtect)
|
||||
{
|
||||
alignment = 0x4000;
|
||||
}
|
||||
|
||||
return checked(codeSize + (alignment - 1)) & ~(alignment - 1);
|
||||
}
|
||||
|
||||
private static void Add(int offset, int size, UnwindInfo unwindInfo)
|
||||
|
@ -3,6 +3,7 @@ using ARMeilleure.CodeGen.Linking;
|
||||
using ARMeilleure.CodeGen.Unwinding;
|
||||
using ARMeilleure.Common;
|
||||
using ARMeilleure.Memory;
|
||||
using ARMeilleure.Translation.Cache;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Logging;
|
||||
@ -744,7 +745,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
bool highCq)
|
||||
{
|
||||
var cFunc = new CompiledFunction(code, unwindInfo, RelocInfo.Empty);
|
||||
var gFunc = cFunc.MapWithPointer<GuestFunction>(out IntPtr gFuncPointer);
|
||||
var gFunc = cFunc.MapWithPointer<GuestFunction>(out IntPtr gFuncPointer, true);
|
||||
|
||||
return new TranslatedFunction(gFunc, gFuncPointer, callCounter, guestSize, highCq);
|
||||
}
|
||||
@ -826,7 +827,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
|
||||
Debug.Assert(Profiler.IsAddressInStaticCodeRange(address));
|
||||
|
||||
TranslatedFunction func = translator.Translate(address, item.funcProfile.Mode, item.funcProfile.HighCq);
|
||||
TranslatedFunction func = translator.Translate(address, item.funcProfile.Mode, item.funcProfile.HighCq, deferProtect: true);
|
||||
|
||||
bool isAddressUnique = translator.Functions.TryAdd(address, func.GuestSize, func);
|
||||
|
||||
@ -1004,6 +1005,7 @@ namespace ARMeilleure.Translation.PTC
|
||||
osPlatform |= (OperatingSystem.IsLinux() ? 1u : 0u) << 1;
|
||||
osPlatform |= (OperatingSystem.IsMacOS() ? 1u : 0u) << 2;
|
||||
osPlatform |= (OperatingSystem.IsWindows() ? 1u : 0u) << 3;
|
||||
osPlatform |= (OperatingSystem.IsIOS() ? 1u : 0u) << 4;
|
||||
#pragma warning restore IDE0055
|
||||
|
||||
return osPlatform;
|
||||
|
@ -112,6 +112,8 @@ namespace ARMeilleure.Translation
|
||||
Debug.Assert(Functions.Count == 0);
|
||||
_ptc.LoadTranslations(this);
|
||||
_ptc.MakeAndSaveTranslations(this);
|
||||
|
||||
JitCache.RunDeferredRxProtects();
|
||||
}
|
||||
|
||||
_ptc.Profiler.Start();
|
||||
@ -250,7 +252,7 @@ namespace ARMeilleure.Translation
|
||||
}
|
||||
}
|
||||
|
||||
internal TranslatedFunction Translate(ulong address, ExecutionMode mode, bool highCq, bool singleStep = false)
|
||||
internal TranslatedFunction Translate(ulong address, ExecutionMode mode, bool highCq, bool singleStep = false, bool deferProtect = false)
|
||||
{
|
||||
var context = new ArmEmitterContext(
|
||||
Memory,
|
||||
@ -308,7 +310,7 @@ namespace ARMeilleure.Translation
|
||||
_ptc.WriteCompiledFunction(address, funcSize, hash, highCq, compiledFunc);
|
||||
}
|
||||
|
||||
GuestFunction func = compiledFunc.MapWithPointer<GuestFunction>(out IntPtr funcPointer);
|
||||
GuestFunction func = compiledFunc.MapWithPointer<GuestFunction>(out IntPtr funcPointer, deferProtect);
|
||||
|
||||
Allocators.ResetAll();
|
||||
|
||||
|
@ -23,7 +23,7 @@ namespace Ryujinx.Audio.Backends.SDL2
|
||||
// TODO: Add this to SDL2-CS
|
||||
// NOTE: We use a DllImport here because of marshaling issue for spec.
|
||||
#pragma warning disable SYSLIB1054
|
||||
[DllImport("SDL2")]
|
||||
[DllImport("SDL2.framework/SDL2")]
|
||||
private static extern int SDL_GetDefaultAudioInfo(IntPtr name, out SDL_AudioSpec spec, int isCapture);
|
||||
#pragma warning restore SYSLIB1054
|
||||
|
||||
|
@ -50,6 +50,10 @@ namespace Ryujinx.Common.Configuration
|
||||
{
|
||||
appDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Library", "Application Support");
|
||||
}
|
||||
else if (OperatingSystem.IsIOS())
|
||||
{
|
||||
appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
|
||||
}
|
||||
else
|
||||
{
|
||||
appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
|
||||
|
@ -30,15 +30,26 @@ namespace Ryujinx.Common.Logging.Targets
|
||||
|
||||
public void Log(object sender, LogEventArgs args)
|
||||
{
|
||||
Console.ForegroundColor = GetLogColor(args.Level);
|
||||
Console.WriteLine(_formatter.Format(args));
|
||||
Console.ResetColor();
|
||||
if (OperatingSystem.IsIOS())
|
||||
{
|
||||
Console.WriteLine(_formatter.Format(args));
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.ForegroundColor = GetLogColor(args.Level);
|
||||
Console.WriteLine(_formatter.Format(args));
|
||||
Console.ResetColor();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
Console.ResetColor();
|
||||
|
||||
if (!OperatingSystem.IsIOS())
|
||||
{
|
||||
Console.ResetColor();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,6 +30,11 @@ namespace Ryujinx.Common
|
||||
|
||||
public static string GetVersion()
|
||||
{
|
||||
if (OperatingSystem.IsIOS())
|
||||
{
|
||||
return "ios";
|
||||
}
|
||||
|
||||
if (IsValid())
|
||||
{
|
||||
return BuildVersion;
|
||||
@ -46,7 +51,7 @@ namespace Ryujinx.Common
|
||||
#else
|
||||
public static string GetBaseApplicationDirectory()
|
||||
{
|
||||
if (IsFlatHubBuild() || OperatingSystem.IsMacOS())
|
||||
if (IsFlatHubBuild() || OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
|
||||
{
|
||||
return AppDataManager.BaseDirPath;
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ namespace Ryujinx.Common.SystemInterop
|
||||
|
||||
public StdErrAdapter()
|
||||
{
|
||||
if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
||||
if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS()) // TODO: iOS?
|
||||
{
|
||||
RegisterPosix();
|
||||
}
|
||||
@ -27,6 +27,7 @@ namespace Ryujinx.Common.SystemInterop
|
||||
|
||||
[SupportedOSPlatform("linux")]
|
||||
[SupportedOSPlatform("macos")]
|
||||
[SupportedOSPlatform("ios")]
|
||||
private void RegisterPosix()
|
||||
{
|
||||
const int StdErrFileno = 2;
|
||||
@ -44,6 +45,7 @@ namespace Ryujinx.Common.SystemInterop
|
||||
|
||||
[SupportedOSPlatform("linux")]
|
||||
[SupportedOSPlatform("macos")]
|
||||
[SupportedOSPlatform("ios")]
|
||||
private async Task EventWorkerAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
using TextReader reader = new StreamReader(_pipeReader, leaveOpen: true);
|
||||
@ -92,6 +94,7 @@ namespace Ryujinx.Common.SystemInterop
|
||||
|
||||
[SupportedOSPlatform("linux")]
|
||||
[SupportedOSPlatform("macos")]
|
||||
[SupportedOSPlatform("ios")]
|
||||
private static Stream CreateFileDescriptorStream(int fd)
|
||||
{
|
||||
return new FileStream(
|
||||
|
@ -40,7 +40,7 @@ namespace Ryujinx.Graphics.Gpu
|
||||
/// <summary>
|
||||
/// Enables or disables the Just-in-Time compiler for GPU Macro code.
|
||||
/// </summary>
|
||||
public static bool EnableMacroJit = true;
|
||||
public static bool EnableMacroJit = false;
|
||||
|
||||
/// <summary>
|
||||
/// Enables or disables high-level emulation of common GPU Macro code.
|
||||
|
@ -26,7 +26,7 @@ namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
|
||||
{
|
||||
return $"lib{libraryName}.so.{version}";
|
||||
}
|
||||
else if (OperatingSystem.IsMacOS())
|
||||
else if (OperatingSystem.IsMacOS() || OperatingSystem.IsIOS()) // TODO: ffmpeg on ios
|
||||
{
|
||||
return $"lib{libraryName}.{version}.dylib";
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ using System.Runtime.Versioning;
|
||||
namespace Ryujinx.Graphics.Vulkan.MoltenVK
|
||||
{
|
||||
[SupportedOSPlatform("macos")]
|
||||
[SupportedOSPlatform("ios")]
|
||||
public static partial class MVKInitialization
|
||||
{
|
||||
[LibraryImport("libMoltenVK.dylib")]
|
||||
|
@ -101,7 +101,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
Textures = new HashSet<ITexture>();
|
||||
Samplers = new HashSet<SamplerHolder>();
|
||||
|
||||
if (OperatingSystem.IsMacOS())
|
||||
if (OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
|
||||
{
|
||||
MVKInitialization.Initialize();
|
||||
|
||||
|
@ -15,7 +15,7 @@ namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService.Types
|
||||
|
||||
public IpAddressSetting(IPInterfaceProperties interfaceProperties, UnicastIPAddressInformation unicastIPAddressInformation)
|
||||
{
|
||||
IsDhcpEnabled = OperatingSystem.IsMacOS() || interfaceProperties.DhcpServerAddresses.Count != 0;
|
||||
IsDhcpEnabled = OperatingSystem.IsMacOS() || OperatingSystem.IsIOS() || interfaceProperties.DhcpServerAddresses.Count != 0;
|
||||
Address = new IpV4Address(unicastIPAddressInformation.Address);
|
||||
IPv4Mask = new IpV4Address(unicastIPAddressInformation.IPv4Mask);
|
||||
GatewayAddress = (interfaceProperties.GatewayAddresses.Count == 0) ? new IpV4Address() : new IpV4Address(interfaceProperties.GatewayAddresses[0].Address);
|
||||
|
@ -283,7 +283,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
|
||||
|
||||
public static LinuxError ConvertError(WsaError errorCode)
|
||||
{
|
||||
if (OperatingSystem.IsMacOS())
|
||||
if (OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
|
||||
{
|
||||
if (_errorMapMacOs.TryGetValue((int)errorCode, out LinuxError errno))
|
||||
{
|
||||
|
@ -33,6 +33,7 @@ using Silk.NET.Vulkan;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using ConfigGamepadInputId = Ryujinx.Common.Configuration.Hid.Controller.GamepadInputId;
|
||||
@ -60,16 +61,46 @@ namespace Ryujinx.Headless.SDL2
|
||||
|
||||
private static readonly InputConfigJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "main_ryujinx_sdl")]
|
||||
public static unsafe int MainExternal(int argCount, IntPtr* pArgs)
|
||||
{
|
||||
string[] args = new string[argCount];
|
||||
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < argCount; i++)
|
||||
{
|
||||
args[i] = Marshal.PtrToStringAnsi(pArgs[i]);
|
||||
|
||||
Console.WriteLine(args[i]);
|
||||
}
|
||||
|
||||
Main(args);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e.ToString());
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Version = ReleaseInformation.GetVersion();
|
||||
|
||||
// Make process DPI aware for proper window sizing on high-res screens.
|
||||
ForceDpiAware.Windows();
|
||||
|
||||
Console.Title = $"Ryujinx Console {Version} (Headless SDL2)";
|
||||
Silk.NET.Core.Loader.SearchPathContainer.Platform = Silk.NET.Core.Loader.UnderlyingPlatform.MacOS;
|
||||
|
||||
if (OperatingSystem.IsMacOS() || OperatingSystem.IsLinux())
|
||||
Version = ReleaseInformation.GetVersion();
|
||||
|
||||
if (!OperatingSystem.IsIOS())
|
||||
{
|
||||
Console.Title = $"Ryujinx Console {Version} (Headless SDL2)";
|
||||
}
|
||||
|
||||
if (OperatingSystem.IsMacOS() || OperatingSystem.IsIOS() || OperatingSystem.IsLinux())
|
||||
{
|
||||
AutoResetEvent invoked = new(false);
|
||||
|
||||
@ -344,12 +375,12 @@ namespace Ryujinx.Headless.SDL2
|
||||
|
||||
GraphicsConfig.EnableShaderCache = true;
|
||||
|
||||
if (OperatingSystem.IsMacOS())
|
||||
if (OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
|
||||
{
|
||||
if (option.GraphicsBackend == GraphicsBackend.OpenGl)
|
||||
{
|
||||
option.GraphicsBackend = GraphicsBackend.Vulkan;
|
||||
Logger.Warning?.Print(LogClass.Application, "OpenGL is not supported on macOS, switching to Vulkan!");
|
||||
Logger.Warning?.Print(LogClass.Application, "OpenGL is not supported on Apple platforms, switching to Vulkan!");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,21 +2,88 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<RuntimeIdentifiers>win-x64;osx-x64;linux-x64</RuntimeIdentifiers>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RuntimeIdentifiers>ios-arm64</RuntimeIdentifiers>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Version>1.0.0-dirty</Version>
|
||||
<DefineConstants Condition=" '$(ExtraDefineConstants)' != '' ">$(DefineConstants);$(ExtraDefineConstants)</DefineConstants>
|
||||
<SigningCertificate Condition=" '$(SigningCertificate)' == '' ">-</SigningCertificate>
|
||||
<TieredPGO>true</TieredPGO>
|
||||
|
||||
<PublishAot>true</PublishAot>
|
||||
<PublishAotUsingRuntimePack>true</PublishAotUsingRuntimePack>
|
||||
<UseNativeAOTRuntime>true</UseNativeAOTRuntime>
|
||||
<TrimmerSingleWarn>false</TrimmerSingleWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- iOS linking stuff from godot -->
|
||||
|
||||
<PropertyGroup>
|
||||
<InvariantGlobalization>true</InvariantGlobalization>
|
||||
<LinkStandardCPlusPlusLibrary>true</LinkStandardCPlusPlusLibrary>
|
||||
<FindXCode Condition=" '$(XCodePath)' == '' and '$([MSBuild]::IsOsPlatform(OSX))' ">true</FindXCode>
|
||||
<XCodePath Condition=" '$(XCodePath)' == '' ">/Applications/Xcode.app/Contents/Developer</XCodePath>
|
||||
<XCodePath>$([MSBuild]::EnsureTrailingSlash('$(XCodePath)'))</XCodePath>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="PrepareBeforeIlcCompile"
|
||||
BeforeTargets="IlcCompile">
|
||||
|
||||
<Copy SourceFiles="%(ResolvedRuntimePack.PackageDirectory)/runtimes/$(RuntimeIdentifier)/native/icudt.dat" DestinationFolder="$(PublishDir)"/>
|
||||
|
||||
<!-- We need to find the path to Xcode so we can set manual linker args to the correct SDKs
|
||||
Once https://github.com/dotnet/runtime/issues/88737 is released, we can take this out
|
||||
-->
|
||||
|
||||
<Exec Command="xcrun xcode-select -p" ConsoleToMSBuild="true" Condition=" '$(FindXCode)' == 'true' ">
|
||||
<Output TaskParameter="ConsoleOutput" PropertyName="XcodeSelect" />
|
||||
</Exec>
|
||||
|
||||
<PropertyGroup Condition=" '$(FindXCode)' == 'true' ">
|
||||
<XCodePath>$(XcodeSelect)</XCodePath>
|
||||
<XCodePath>$([MSBuild]::EnsureTrailingSlash('$(XCodePath)'))</XCodePath>
|
||||
</PropertyGroup>
|
||||
|
||||
<Message Importance="normal" Text="Found XCode at $(XcodeSelect)" Condition=" '$(FindXCode)' == 'true' "/>
|
||||
|
||||
<ItemGroup>
|
||||
<LinkerArg Include="-Wl,-ld_classic" />
|
||||
<LinkerArg Include="-isysroot %22$(XCodePath)Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk%22"
|
||||
Condition=" $(RuntimeIdentifier.Contains('simulator')) "/>
|
||||
<LinkerArg Include="-isysroot %22$(XCodePath)Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk%22"
|
||||
Condition=" !$(RuntimeIdentifier.Contains('simulator')) "/>
|
||||
</ItemGroup>
|
||||
|
||||
</Target>
|
||||
|
||||
<Target Name="FixDylib"
|
||||
AfterTargets="Publish">
|
||||
<!-- The dylib id needs to be changed to have @rpath -->
|
||||
|
||||
<Exec Command="install_name_tool -id @rpath/$(TargetName).dylib $(NativeBinary)" ConsoleToMSBuild="true" />
|
||||
</Target>
|
||||
|
||||
<Target Name="FixSymbols"
|
||||
AfterTargets="Publish">
|
||||
|
||||
<RemoveDir Directories="$(PublishDir)$(TargetName).framework.dSYM"/>
|
||||
|
||||
<!-- create-xcframework (called from the export plugin wants the symbol files in a directory
|
||||
with a slightly different name from the one created by dotnet publish, so we copy them over
|
||||
to the correctly-named directory -->
|
||||
<ItemGroup>
|
||||
<SymbolFiles Include="$(NativeBinary).dsym\**\*.*"/>
|
||||
</ItemGroup>
|
||||
<Copy SourceFiles="@(SymbolFiles)" DestinationFolder="$(PublishDir)$(TargetName).framework.dSYM"/>
|
||||
</Target>
|
||||
|
||||
<!-- end iOS linking stuff from godot -->
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="OpenTK.Core" />
|
||||
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="$([MSBuild]::IsOSPlatform('OSX'))">
|
||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="false">
|
||||
<Exec Command="codesign --entitlements '$(ProjectDir)..\..\distribution\macos\entitlements.xml' -f --deep -s $(SigningCertificate) '$(TargetDir)$(TargetName)'" />
|
||||
</Target>
|
||||
|
||||
@ -65,7 +132,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(RuntimeIdentifier)' != ''">
|
||||
<PublishSingleFile>true</PublishSingleFile>
|
||||
<PublishSingleFile>false</PublishSingleFile>
|
||||
<PublishTrimmed>true</PublishTrimmed>
|
||||
<TrimMode>partial</TrimMode>
|
||||
</PropertyGroup>
|
||||
|
@ -36,7 +36,7 @@ namespace Ryujinx.Headless.SDL2
|
||||
|
||||
private static readonly ConcurrentQueue<Action> _mainThreadActions = new();
|
||||
|
||||
[LibraryImport("SDL2")]
|
||||
[LibraryImport("SDL2.framework/SDL2")]
|
||||
// TODO: Remove this as soon as SDL2-CS was updated to expose this method publicly
|
||||
private static partial IntPtr SDL_LoadBMP_RW(IntPtr src, int freesrc);
|
||||
|
||||
|
168
src/Ryujinx.Memory/MachJitWorkaround.cs
Normal file
168
src/Ryujinx.Memory/MachJitWorkaround.cs
Normal file
@ -0,0 +1,168 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Versioning;
|
||||
|
||||
namespace Ryujinx.Memory
|
||||
{
|
||||
[SupportedOSPlatform("ios")]
|
||||
static unsafe partial class MachJitWorkaround
|
||||
{
|
||||
[LibraryImport("libc")]
|
||||
public static partial int mach_task_self();
|
||||
|
||||
[LibraryImport("libc")]
|
||||
public static partial int mach_make_memory_entry_64(IntPtr target_task, IntPtr* size, IntPtr offset, int permission, IntPtr* object_handle, IntPtr parent_entry);
|
||||
|
||||
[LibraryImport("libc")]
|
||||
public static partial int mach_memory_entry_ownership(IntPtr mem_entry, IntPtr owner, int ledger_tag, int ledger_flags);
|
||||
|
||||
[LibraryImport("libc")]
|
||||
public static partial int vm_map(IntPtr target_task, IntPtr* address, IntPtr size, IntPtr mask, int flags, IntPtr obj, IntPtr offset, int copy, int cur_protection, int max_protection, int inheritance);
|
||||
|
||||
[LibraryImport("libc")]
|
||||
public static partial int vm_allocate(IntPtr target_task, IntPtr* address, IntPtr size, int flags);
|
||||
|
||||
[LibraryImport("libc")]
|
||||
public static partial int vm_deallocate(IntPtr target_task, IntPtr address, IntPtr size);
|
||||
|
||||
[LibraryImport("libc")]
|
||||
public static partial int vm_remap(IntPtr target_task, IntPtr* target_address, IntPtr size, IntPtr mask, int flags, IntPtr src_task, IntPtr src_address, int copy, int* cur_protection, int* max_protection, int inheritance);
|
||||
|
||||
const int MAP_MEM_LEDGER_TAGGED = 0x002000;
|
||||
const int MAP_MEM_NAMED_CREATE = 0x020000;
|
||||
|
||||
const int VM_PROT_READ = 0x01;
|
||||
const int VM_PROT_WRITE = 0x02;
|
||||
const int VM_PROT_EXECUTE = 0x04;
|
||||
|
||||
const int VM_LEDGER_TAG_DEFAULT = 0x00000001;
|
||||
const int VM_LEDGER_FLAG_NO_FOOTPRINT = 0x00000001;
|
||||
|
||||
const int VM_INHERIT_COPY = 1;
|
||||
const int VM_INHERIT_DEFAULT = VM_INHERIT_COPY;
|
||||
|
||||
const int VM_FLAGS_FIXED = 0x0000;
|
||||
const int VM_FLAGS_ANYWHERE = 0x0001;
|
||||
const int VM_FLAGS_OVERWRITE = 0x4000;
|
||||
|
||||
const IntPtr TASK_NULL = 0;
|
||||
|
||||
public static void ReallocateBlock(IntPtr address, int size)
|
||||
{
|
||||
IntPtr selfTask = mach_task_self();
|
||||
IntPtr memorySize = (IntPtr)size;
|
||||
IntPtr memoryObjectPort = IntPtr.Zero;
|
||||
|
||||
int err = mach_make_memory_entry_64(selfTask, &memorySize, 0, MAP_MEM_NAMED_CREATE | MAP_MEM_LEDGER_TAGGED | VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE, &memoryObjectPort, 0);
|
||||
|
||||
if (err != 0)
|
||||
{
|
||||
throw new InvalidOperationException($"Make memory entry failed: {err}");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (memorySize != (IntPtr)size)
|
||||
{
|
||||
throw new InvalidOperationException($"Created with size {memorySize} instead of {size}.");
|
||||
}
|
||||
|
||||
err = mach_memory_entry_ownership(memoryObjectPort, TASK_NULL, VM_LEDGER_TAG_DEFAULT, VM_LEDGER_FLAG_NO_FOOTPRINT);
|
||||
|
||||
if (err != 0)
|
||||
{
|
||||
throw new InvalidOperationException($"Failed to set ownership: {err}");
|
||||
}
|
||||
|
||||
IntPtr mapAddress = address;
|
||||
|
||||
err = vm_map(
|
||||
selfTask,
|
||||
&mapAddress,
|
||||
memorySize,
|
||||
/*mask=*/ 0,
|
||||
/*flags=*/ VM_FLAGS_OVERWRITE,
|
||||
memoryObjectPort,
|
||||
/*offset=*/ 0,
|
||||
/*copy=*/ 0,
|
||||
VM_PROT_READ | VM_PROT_WRITE,
|
||||
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE,
|
||||
VM_INHERIT_COPY);
|
||||
|
||||
if (err != 0)
|
||||
{
|
||||
throw new InvalidOperationException($"Failed to map: {err}");
|
||||
}
|
||||
|
||||
if (address != mapAddress)
|
||||
{
|
||||
throw new InvalidOperationException($"Remap changed address");
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
//mach_port_deallocate(selfTask, memoryObjectPort);
|
||||
}
|
||||
|
||||
Console.WriteLine($"Reallocated an area... {address:x16}");
|
||||
}
|
||||
|
||||
public static void ReallocateAreaWithOwnership(IntPtr address, int size)
|
||||
{
|
||||
int mapChunkSize = 128 * 1024 * 1024;
|
||||
IntPtr endAddress = address + size;
|
||||
IntPtr blockAddress = address;
|
||||
while (blockAddress < endAddress)
|
||||
{
|
||||
int blockSize = Math.Min(mapChunkSize, (int)(endAddress - blockAddress));
|
||||
|
||||
ReallocateBlock(blockAddress, blockSize);
|
||||
|
||||
blockAddress += blockSize;
|
||||
}
|
||||
}
|
||||
|
||||
public static IntPtr AllocateSharedMemory(ulong size, bool reserve)
|
||||
{
|
||||
IntPtr address = 0;
|
||||
|
||||
int err = vm_allocate(mach_task_self(), &address, (IntPtr)size, VM_FLAGS_ANYWHERE);
|
||||
|
||||
if (err != 0)
|
||||
{
|
||||
throw new InvalidOperationException($"Failed to allocate shared memory: {err}");
|
||||
}
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
public static void DestroySharedMemory(IntPtr handle, ulong size)
|
||||
{
|
||||
vm_deallocate(mach_task_self(), handle, (IntPtr)size);
|
||||
}
|
||||
|
||||
public static IntPtr MapView(IntPtr sharedMemory, ulong srcOffset, IntPtr location, ulong size)
|
||||
{
|
||||
IntPtr taskSelf = mach_task_self();
|
||||
IntPtr srcAddress = (IntPtr)((ulong)sharedMemory + srcOffset);
|
||||
IntPtr dstAddress = location;
|
||||
|
||||
int cur_protection = 0;
|
||||
int max_protection = 0;
|
||||
|
||||
int err = vm_remap(taskSelf, &dstAddress, (IntPtr)size, 0, VM_FLAGS_OVERWRITE, taskSelf, srcAddress, 0, &cur_protection, &max_protection, VM_INHERIT_DEFAULT);
|
||||
|
||||
if (err != 0)
|
||||
{
|
||||
throw new InvalidOperationException($"Failed to allocate remap memory: {err}");
|
||||
}
|
||||
|
||||
return dstAddress;
|
||||
}
|
||||
|
||||
public static void UnmapView(IntPtr location, ulong size)
|
||||
{
|
||||
vm_deallocate(mach_task_self(), location, (IntPtr)size);
|
||||
}
|
||||
}
|
||||
}
|
@ -426,7 +426,7 @@ namespace Ryujinx.Memory
|
||||
return OperatingSystem.IsWindowsVersionAtLeast(10, 0, 17134);
|
||||
}
|
||||
|
||||
return OperatingSystem.IsLinux() || OperatingSystem.IsMacOS();
|
||||
return OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || OperatingSystem.IsIOS();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -10,7 +10,7 @@ namespace Ryujinx.Memory
|
||||
{
|
||||
return MemoryManagementWindows.Allocate((IntPtr)size);
|
||||
}
|
||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
|
||||
{
|
||||
return MemoryManagementUnix.Allocate(size, forJit);
|
||||
}
|
||||
@ -26,7 +26,7 @@ namespace Ryujinx.Memory
|
||||
{
|
||||
return MemoryManagementWindows.Reserve((IntPtr)size, viewCompatible);
|
||||
}
|
||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
|
||||
{
|
||||
return MemoryManagementUnix.Reserve(size, forJit);
|
||||
}
|
||||
@ -42,7 +42,7 @@ namespace Ryujinx.Memory
|
||||
{
|
||||
MemoryManagementWindows.Commit(address, (IntPtr)size);
|
||||
}
|
||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
|
||||
{
|
||||
MemoryManagementUnix.Commit(address, size, forJit);
|
||||
}
|
||||
@ -58,7 +58,7 @@ namespace Ryujinx.Memory
|
||||
{
|
||||
MemoryManagementWindows.Decommit(address, (IntPtr)size);
|
||||
}
|
||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
|
||||
{
|
||||
MemoryManagementUnix.Decommit(address, size);
|
||||
}
|
||||
@ -74,7 +74,7 @@ namespace Ryujinx.Memory
|
||||
{
|
||||
MemoryManagementWindows.MapView(sharedMemory, srcOffset, address, (IntPtr)size, owner);
|
||||
}
|
||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
|
||||
{
|
||||
MemoryManagementUnix.MapView(sharedMemory, srcOffset, address, size);
|
||||
}
|
||||
@ -90,7 +90,7 @@ namespace Ryujinx.Memory
|
||||
{
|
||||
MemoryManagementWindows.UnmapView(sharedMemory, address, (IntPtr)size, owner);
|
||||
}
|
||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
|
||||
{
|
||||
MemoryManagementUnix.UnmapView(address, size);
|
||||
}
|
||||
@ -108,7 +108,7 @@ namespace Ryujinx.Memory
|
||||
{
|
||||
result = MemoryManagementWindows.Reprotect(address, (IntPtr)size, permission, forView);
|
||||
}
|
||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
|
||||
{
|
||||
result = MemoryManagementUnix.Reprotect(address, size, permission);
|
||||
}
|
||||
@ -129,7 +129,7 @@ namespace Ryujinx.Memory
|
||||
{
|
||||
return MemoryManagementWindows.Free(address, (IntPtr)size);
|
||||
}
|
||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
|
||||
{
|
||||
return MemoryManagementUnix.Free(address);
|
||||
}
|
||||
@ -145,7 +145,7 @@ namespace Ryujinx.Memory
|
||||
{
|
||||
return MemoryManagementWindows.CreateSharedMemory((IntPtr)size, reserve);
|
||||
}
|
||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
|
||||
{
|
||||
return MemoryManagementUnix.CreateSharedMemory(size, reserve);
|
||||
}
|
||||
@ -161,7 +161,7 @@ namespace Ryujinx.Memory
|
||||
{
|
||||
MemoryManagementWindows.DestroySharedMemory(handle);
|
||||
}
|
||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
|
||||
{
|
||||
MemoryManagementUnix.DestroySharedMemory(handle);
|
||||
}
|
||||
@ -177,7 +177,7 @@ namespace Ryujinx.Memory
|
||||
{
|
||||
return MemoryManagementWindows.MapSharedMemory(handle);
|
||||
}
|
||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
|
||||
{
|
||||
return MemoryManagementUnix.MapSharedMemory(handle, size);
|
||||
}
|
||||
@ -193,7 +193,7 @@ namespace Ryujinx.Memory
|
||||
{
|
||||
MemoryManagementWindows.UnmapSharedMemory(address);
|
||||
}
|
||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
|
||||
else if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
|
||||
{
|
||||
MemoryManagementUnix.UnmapSharedMemory(address, size);
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Versioning;
|
||||
using static Ryujinx.Memory.MemoryManagerUnixHelper;
|
||||
@ -8,6 +9,7 @@ namespace Ryujinx.Memory
|
||||
{
|
||||
[SupportedOSPlatform("linux")]
|
||||
[SupportedOSPlatform("macos")]
|
||||
[SupportedOSPlatform("ios")]
|
||||
static class MemoryManagementUnix
|
||||
{
|
||||
private static readonly ConcurrentDictionary<IntPtr, ulong> _allocations = new();
|
||||
@ -40,7 +42,7 @@ namespace Ryujinx.Memory
|
||||
flags |= MmapFlags.MAP_NORESERVE;
|
||||
}
|
||||
|
||||
if (OperatingSystem.IsMacOSVersionAtLeast(10, 14) && forJit)
|
||||
if (OperatingSystem.IsMacOS() && OperatingSystem.IsMacOSVersionAtLeast(10, 14) && forJit)
|
||||
{
|
||||
flags |= MmapFlags.MAP_JIT_DARWIN;
|
||||
|
||||
@ -57,6 +59,11 @@ namespace Ryujinx.Memory
|
||||
throw new SystemException(Marshal.GetLastPInvokeErrorMessage());
|
||||
}
|
||||
|
||||
if (OperatingSystem.IsIOS() && forJit)
|
||||
{
|
||||
MachJitWorkaround.ReallocateAreaWithOwnership(ptr, (int)size);
|
||||
}
|
||||
|
||||
if (!_allocations.TryAdd(ptr, size))
|
||||
{
|
||||
// This should be impossible, kernel shouldn't return an already mapped address.
|
||||
@ -70,7 +77,7 @@ namespace Ryujinx.Memory
|
||||
{
|
||||
MmapProts prot = MmapProts.PROT_READ | MmapProts.PROT_WRITE;
|
||||
|
||||
if (OperatingSystem.IsMacOSVersionAtLeast(10, 14) && forJit)
|
||||
if ((OperatingSystem.IsIOS() || OperatingSystem.IsMacOSVersionAtLeast(10, 14)) && forJit)
|
||||
{
|
||||
prot |= MmapProts.PROT_EXEC;
|
||||
}
|
||||
@ -134,11 +141,21 @@ namespace Ryujinx.Memory
|
||||
return munmap(address, size) == 0;
|
||||
}
|
||||
|
||||
private static Dictionary<IntPtr, ulong> _sharedMemorySizes = new Dictionary<nint, ulong>();
|
||||
|
||||
public unsafe static IntPtr CreateSharedMemory(ulong size, bool reserve)
|
||||
{
|
||||
int fd;
|
||||
|
||||
if (OperatingSystem.IsMacOS())
|
||||
if (OperatingSystem.IsIOS())
|
||||
{
|
||||
IntPtr baseAddress = MachJitWorkaround.AllocateSharedMemory(size, reserve);
|
||||
|
||||
_sharedMemorySizes.Add(baseAddress, size);
|
||||
|
||||
return baseAddress;
|
||||
}
|
||||
else if (OperatingSystem.IsMacOS())
|
||||
{
|
||||
byte[] memName = "Ryujinx-XXXXXX"u8.ToArray();
|
||||
|
||||
@ -185,27 +202,64 @@ namespace Ryujinx.Memory
|
||||
|
||||
public static void DestroySharedMemory(IntPtr handle)
|
||||
{
|
||||
close(handle.ToInt32());
|
||||
if (OperatingSystem.IsIOS())
|
||||
{
|
||||
if (_sharedMemorySizes.TryGetValue(handle, out ulong size))
|
||||
{
|
||||
MachJitWorkaround.DestroySharedMemory(handle, size);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
close(handle.ToInt32());
|
||||
}
|
||||
}
|
||||
|
||||
public static IntPtr MapSharedMemory(IntPtr handle, ulong size)
|
||||
{
|
||||
return Mmap(IntPtr.Zero, size, MmapProts.PROT_READ | MmapProts.PROT_WRITE, MmapFlags.MAP_SHARED, handle.ToInt32(), 0);
|
||||
if (OperatingSystem.IsIOS())
|
||||
{
|
||||
// The base of the shared memory is already mapped - it's the handle.
|
||||
// Views are remapped from it.
|
||||
|
||||
return handle;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Mmap(IntPtr.Zero, size, MmapProts.PROT_READ | MmapProts.PROT_WRITE, MmapFlags.MAP_SHARED, handle.ToInt32(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
public static void UnmapSharedMemory(IntPtr address, ulong size)
|
||||
{
|
||||
munmap(address, size);
|
||||
if (!OperatingSystem.IsIOS())
|
||||
{
|
||||
munmap(address, size);
|
||||
}
|
||||
}
|
||||
|
||||
public static void MapView(IntPtr sharedMemory, ulong srcOffset, IntPtr location, ulong size)
|
||||
{
|
||||
Mmap(location, size, MmapProts.PROT_READ | MmapProts.PROT_WRITE, MmapFlags.MAP_FIXED | MmapFlags.MAP_SHARED, sharedMemory.ToInt32(), (long)srcOffset);
|
||||
if (OperatingSystem.IsIOS())
|
||||
{
|
||||
MachJitWorkaround.MapView(sharedMemory, srcOffset, location, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
Mmap(location, size, MmapProts.PROT_READ | MmapProts.PROT_WRITE, MmapFlags.MAP_FIXED | MmapFlags.MAP_SHARED, sharedMemory.ToInt32(), (long)srcOffset);
|
||||
}
|
||||
}
|
||||
|
||||
public static void UnmapView(IntPtr location, ulong size)
|
||||
{
|
||||
Mmap(location, size, MmapProts.PROT_NONE, MmapFlags.MAP_FIXED | MmapFlags.MAP_PRIVATE | MmapFlags.MAP_ANONYMOUS | MmapFlags.MAP_NORESERVE, -1, 0);
|
||||
if (OperatingSystem.IsIOS())
|
||||
{
|
||||
MachJitWorkaround.UnmapView(location, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
Mmap(location, size, MmapProts.PROT_NONE, MmapFlags.MAP_FIXED | MmapFlags.MAP_PRIVATE | MmapFlags.MAP_ANONYMOUS | MmapFlags.MAP_NORESERVE, -1, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ namespace Ryujinx.Memory
|
||||
{
|
||||
[SupportedOSPlatform("linux")]
|
||||
[SupportedOSPlatform("macos")]
|
||||
[SupportedOSPlatform("ios")]
|
||||
public static partial class MemoryManagerUnixHelper
|
||||
{
|
||||
[Flags]
|
||||
@ -114,7 +115,7 @@ namespace Ryujinx.Memory
|
||||
{
|
||||
result |= MAP_ANONYMOUS_LINUX_GENERIC;
|
||||
}
|
||||
else if (OperatingSystem.IsMacOS())
|
||||
else if (OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
|
||||
{
|
||||
result |= MAP_ANONYMOUS_DARWIN;
|
||||
}
|
||||
@ -130,7 +131,7 @@ namespace Ryujinx.Memory
|
||||
{
|
||||
result |= MAP_NORESERVE_LINUX_GENERIC;
|
||||
}
|
||||
else if (OperatingSystem.IsMacOS())
|
||||
else if (OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
|
||||
{
|
||||
result |= MAP_NORESERVE_DARWIN;
|
||||
}
|
||||
@ -146,7 +147,7 @@ namespace Ryujinx.Memory
|
||||
{
|
||||
result |= MAP_UNLOCKED_LINUX_GENERIC;
|
||||
}
|
||||
else if (OperatingSystem.IsMacOS())
|
||||
else if (OperatingSystem.IsMacOS() || OperatingSystem.IsIOS())
|
||||
{
|
||||
// FIXME: Doesn't exist on Darwin
|
||||
}
|
||||
@ -156,7 +157,7 @@ namespace Ryujinx.Memory
|
||||
}
|
||||
}
|
||||
|
||||
if (flags.HasFlag(MmapFlags.MAP_JIT_DARWIN) && OperatingSystem.IsMacOSVersionAtLeast(10, 14))
|
||||
if (flags.HasFlag(MmapFlags.MAP_JIT_DARWIN) && (OperatingSystem.IsIOS() || OperatingSystem.IsMacOSVersionAtLeast(10, 14)))
|
||||
{
|
||||
result |= (int)MmapFlags.MAP_JIT_DARWIN;
|
||||
}
|
||||
|
@ -1536,7 +1536,7 @@ namespace Ryujinx.Ui.Common.Configuration
|
||||
{
|
||||
// Any system running macOS or returning any amount of valid Vulkan devices should default to Vulkan.
|
||||
// Checks for if the Vulkan version and featureset is compatible should be performed within VulkanRenderer.
|
||||
if (OperatingSystem.IsMacOS() || VulkanRenderer.GetPhysicalDevices().Length > 0)
|
||||
if (OperatingSystem.IsMacOS() || OperatingSystem.IsIOS() || VulkanRenderer.GetPhysicalDevices().Length > 0)
|
||||
{
|
||||
return GraphicsBackend.Vulkan;
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ using System.Runtime.Versioning;
|
||||
namespace Ryujinx.Ui.Common.Helper
|
||||
{
|
||||
[SupportedOSPlatform("macos")]
|
||||
[SupportedOSPlatform("ios")]
|
||||
public static partial class ObjectiveC
|
||||
{
|
||||
private const string ObjCRuntime = "/usr/lib/libobjc.A.dylib";
|
||||
|
@ -8,6 +8,7 @@ namespace Ryujinx.Ui.Helper
|
||||
public delegate void UpdateBoundsCallbackDelegate(Window window);
|
||||
|
||||
[SupportedOSPlatform("macos")]
|
||||
[SupportedOSPlatform("ios")]
|
||||
static partial class MetalHelper
|
||||
{
|
||||
private const string LibObjCImport = "/usr/lib/libobjc.A.dylib";
|
||||
|
Loading…
x
Reference in New Issue
Block a user