UI: Add Metal surface creation for MoltenVK (#3980)

* Initial implementation of metal surface across UIs

* Fix SDL2 on windows

* Update Ryujinx/Ryujinx.csproj

Co-authored-by: Mary-nyan <thog@protonmail.com>

* Address Feedback

Co-authored-by: Mary-nyan <thog@protonmail.com>
This commit is contained in:
riperiperi 2022-12-06 22:00:25 +00:00 committed by GitHub
parent d3709a753f
commit e211c3f00a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 495 additions and 63 deletions

View file

@ -77,6 +77,26 @@ namespace Ryujinx.Headless.SDL2
_accountManager = new AccountManager(_libHacHorizonManager.RyujinxClient);
_userChannelPersistence = new UserChannelPersistence();
if (OperatingSystem.IsMacOS())
{
AutoResetEvent invoked = new AutoResetEvent(false);
// MacOS must perform SDL polls from the main thread.
Ryujinx.SDL2.Common.SDL2Driver.MainThreadDispatcher = (Action action) =>
{
invoked.Reset();
WindowBase.QueueMainThreadAction(() =>
{
action();
invoked.Set();
});
invoked.WaitOne();
};
}
_inputManager = new InputManager(new SDL2KeyboardDriver(), new SDL2GamepadDriver());
GraphicsConfig.EnableShaderCache = true;

View file

@ -12,7 +12,8 @@
<ItemGroup>
<PackageReference Include="OpenTK.Core" Version="4.7.5" />
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.1-build10" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'" />
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.1-build10" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64'" />
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies.osx" Version="5.0.1" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'win10-x64'" />
</ItemGroup>
<ItemGroup>

View file

@ -1,6 +1,7 @@
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging;
using Ryujinx.Input.HLE;
using Ryujinx.SDL2.Common;
using System;
using System.Runtime.InteropServices;
using static SDL2.SDL;
@ -26,15 +27,34 @@ namespace Ryujinx.Headless.SDL2.Vulkan
MouseDriver.SetClientSize(DefaultWidth, DefaultHeight);
}
private void BasicInvoke(Action action)
{
action();
}
public unsafe IntPtr CreateWindowSurface(IntPtr instance)
{
if (SDL_Vulkan_CreateSurface(WindowHandle, instance, out ulong surfaceHandle) == SDL_bool.SDL_FALSE)
ulong surfaceHandle = 0;
Action createSurface = () =>
{
string errorMessage = $"SDL_Vulkan_CreateSurface failed with error \"{SDL_GetError()}\"";
if (SDL_Vulkan_CreateSurface(WindowHandle, instance, out surfaceHandle) == SDL_bool.SDL_FALSE)
{
string errorMessage = $"SDL_Vulkan_CreateSurface failed with error \"{SDL_GetError()}\"";
Logger.Error?.Print(LogClass.Application, errorMessage);
Logger.Error?.Print(LogClass.Application, errorMessage);
throw new Exception(errorMessage);
throw new Exception(errorMessage);
}
};
if (SDL2Driver.MainThreadDispatcher != null)
{
SDL2Driver.MainThreadDispatcher(createSurface);
}
else
{
createSurface();
}
return (IntPtr)surfaceHandle;

View file

@ -11,6 +11,7 @@ using Ryujinx.Input;
using Ryujinx.Input.HLE;
using Ryujinx.SDL2.Common;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
@ -26,6 +27,13 @@ namespace Ryujinx.Headless.SDL2
private const SDL_WindowFlags DefaultFlags = SDL_WindowFlags.SDL_WINDOW_ALLOW_HIGHDPI | SDL_WindowFlags.SDL_WINDOW_RESIZABLE | SDL_WindowFlags.SDL_WINDOW_INPUT_FOCUS | SDL_WindowFlags.SDL_WINDOW_SHOWN;
private const int TargetFps = 60;
private static ConcurrentQueue<Action> MainThreadActions = new ConcurrentQueue<Action>();
public static void QueueMainThreadAction(Action action)
{
MainThreadActions.Enqueue(action);
}
public NpadManager NpadManager { get; }
public TouchScreenManager TouchScreenManager { get; }
public Switch Device { get; private set; }
@ -168,6 +176,14 @@ namespace Ryujinx.Headless.SDL2
public void Render()
{
InitializeWindowRenderer();
Device.Gpu.Renderer.Initialize(_glLogLevel);
InitializeRenderer();
_gpuVendorName = GetGpuVendorName();
Device.Gpu.Renderer.RunLoop(() =>
{
Device.Gpu.SetGpuThread();
@ -241,6 +257,14 @@ namespace Ryujinx.Headless.SDL2
_exitEvent.Dispose();
}
public void ProcessMainThreadQueue()
{
while (MainThreadActions.TryDequeue(out Action action))
{
action();
}
}
public void MainLoop()
{
while (_isActive)
@ -249,6 +273,8 @@ namespace Ryujinx.Headless.SDL2
SDL_PumpEvents();
ProcessMainThreadQueue();
// Polling becomes expensive if it's not slept
Thread.Sleep(1);
}
@ -315,14 +341,6 @@ namespace Ryujinx.Headless.SDL2
InitializeWindow();
InitializeWindowRenderer();
Device.Gpu.Renderer.Initialize(_glLogLevel);
InitializeRenderer();
_gpuVendorName = GetGpuVendorName();
Thread renderLoopThread = new Thread(Render)
{
Name = "GUI.RenderLoop"