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:
parent
d3709a753f
commit
e211c3f00a
31 changed files with 495 additions and 63 deletions
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue