From a8950d6ac4c4d4e8b3884f799566603db2d9c406 Mon Sep 17 00:00:00 2001
From: Mary <mary@mary.zone>
Date: Mon, 8 May 2023 13:05:37 +0200
Subject: [PATCH] vulkan: Pass Vk instance to VulkanRenderer (#4859)

This will allow possible multiple driver selection without any need of
LD preload. (useful when testing custom version of mesa for example)
---
 src/Ryujinx.Ava/AppHost.cs                    |  2 ++
 .../UI/ViewModels/SettingsViewModel.cs        |  3 +-
 src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs | 29 +++++++++----------
 src/Ryujinx.Headless.SDL2/Program.cs          |  4 ++-
 src/Ryujinx/Ui/MainWindow.cs                  |  2 +-
 src/Ryujinx/Ui/Windows/SettingsWindow.cs      |  3 +-
 6 files changed, 23 insertions(+), 20 deletions(-)

diff --git a/src/Ryujinx.Ava/AppHost.cs b/src/Ryujinx.Ava/AppHost.cs
index e11a954d89..0955fb270f 100644
--- a/src/Ryujinx.Ava/AppHost.cs
+++ b/src/Ryujinx.Ava/AppHost.cs
@@ -35,6 +35,7 @@ using Ryujinx.Input.HLE;
 using Ryujinx.Ui.Common;
 using Ryujinx.Ui.Common.Configuration;
 using Ryujinx.Ui.Common.Helper;
+using Silk.NET.Vulkan;
 using SixLabors.ImageSharp;
 using SixLabors.ImageSharp.Formats.Png;
 using SixLabors.ImageSharp.PixelFormats;
@@ -701,6 +702,7 @@ namespace Ryujinx.Ava
             if (ConfigurationState.Instance.Graphics.GraphicsBackend.Value == GraphicsBackend.Vulkan)
             {
                 renderer = new VulkanRenderer(
+                    Vk.GetApi(),
                     (_rendererHost.EmbeddedWindow as EmbeddedWindowVulkan).CreateSurface,
                     VulkanHelper.GetRequiredInstanceExtensions,
                     ConfigurationState.Instance.Graphics.PreferredGpu.Value);
diff --git a/src/Ryujinx.Ava/UI/ViewModels/SettingsViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/SettingsViewModel.cs
index 75a5168fc4..89392f6b26 100644
--- a/src/Ryujinx.Ava/UI/ViewModels/SettingsViewModel.cs
+++ b/src/Ryujinx.Ava/UI/ViewModels/SettingsViewModel.cs
@@ -25,6 +25,7 @@ using System.Linq;
 using System.Runtime.InteropServices;
 using System.Net.NetworkInformation;
 using TimeZone = Ryujinx.Ava.UI.Models.TimeZone;
+using Silk.NET.Vulkan;
 
 namespace Ryujinx.Ava.UI.ViewModels
 {
@@ -310,7 +311,7 @@ namespace Ryujinx.Ava.UI.ViewModels
         {
             _gpuIds = new List<string>();
             List<string> names = new();
-            var devices = VulkanRenderer.GetPhysicalDevices();
+            var devices = VulkanRenderer.GetPhysicalDevices(Vk.GetApi());
 
             if (devices.Length == 0)
             {
diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs
index 06fec4f1b2..e4ce4904b0 100644
--- a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs
+++ b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs
@@ -89,11 +89,12 @@ namespace Ryujinx.Graphics.Vulkan
 
         public event EventHandler<ScreenCaptureImageInfo> ScreenCaptured;
 
-        public VulkanRenderer(Func<Instance, Vk, SurfaceKHR> surfaceFunc, Func<string[]> requiredExtensionsFunc, string preferredGpuId)
+        public VulkanRenderer(Vk api, Func<Instance, Vk, SurfaceKHR> surfaceFunc, Func<string[]> requiredExtensionsFunc, string preferredGpuId)
         {
             _getSurface = surfaceFunc;
             _getRequiredExtensions = requiredExtensionsFunc;
             _preferredGpuId = preferredGpuId;
+            Api = api;
             Shaders = new HashSet<ShaderCollection>();
             Textures = new HashSet<ITexture>();
             Samplers = new HashSet<SamplerHolder>();
@@ -345,31 +346,27 @@ namespace Ryujinx.Graphics.Vulkan
 
         private unsafe void SetupContext(GraphicsDebugLevel logLevel)
         {
-            var api = Vk.GetApi();
+            _instance = VulkanInitialization.CreateInstance(Api, logLevel, _getRequiredExtensions());
+            _debugMessenger = new VulkanDebugMessenger(Api, _instance.Instance, logLevel);
 
-            Api = api;
-
-            _instance = VulkanInitialization.CreateInstance(api, logLevel, _getRequiredExtensions());
-            _debugMessenger = new VulkanDebugMessenger(api, _instance.Instance, logLevel);
-
-            if (api.TryGetInstanceExtension(_instance.Instance, out KhrSurface surfaceApi))
+            if (Api.TryGetInstanceExtension(_instance.Instance, out KhrSurface surfaceApi))
             {
                 SurfaceApi = surfaceApi;
             }
 
-            _surface = _getSurface(_instance.Instance, api);
-            _physicalDevice = VulkanInitialization.FindSuitablePhysicalDevice(api, _instance, _surface, _preferredGpuId);
+            _surface = _getSurface(_instance.Instance, Api);
+            _physicalDevice = VulkanInitialization.FindSuitablePhysicalDevice(Api, _instance, _surface, _preferredGpuId);
 
-            var queueFamilyIndex = VulkanInitialization.FindSuitableQueueFamily(api, _physicalDevice, _surface, out uint maxQueueCount);
+            var queueFamilyIndex = VulkanInitialization.FindSuitableQueueFamily(Api, _physicalDevice, _surface, out uint maxQueueCount);
 
-            _device = VulkanInitialization.CreateDevice(api, _physicalDevice, queueFamilyIndex, maxQueueCount);
+            _device = VulkanInitialization.CreateDevice(Api, _physicalDevice, queueFamilyIndex, maxQueueCount);
 
-            if (api.TryGetDeviceExtension(_instance.Instance, _device, out KhrSwapchain swapchainApi))
+            if (Api.TryGetDeviceExtension(_instance.Instance, _device, out KhrSwapchain swapchainApi))
             {
                 SwapchainApi = swapchainApi;
             }
 
-            api.GetDeviceQueue(_device, queueFamilyIndex, 0, out var queue);
+            Api.GetDeviceQueue(_device, queueFamilyIndex, 0, out var queue);
             Queue = queue;
             QueueLock = new object();
 
@@ -603,11 +600,11 @@ namespace Ryujinx.Graphics.Vulkan
             return new HardwareInfo(GpuVendor, GpuRenderer);
         }
 
-        public static DeviceInfo[] GetPhysicalDevices()
+        public static DeviceInfo[] GetPhysicalDevices(Vk api)
         {
             try
             {
-                return VulkanInitialization.GetSuitablePhysicalDevices(Vk.GetApi());
+                return VulkanInitialization.GetSuitablePhysicalDevices(api);
             }
             catch (Exception)
             {
diff --git a/src/Ryujinx.Headless.SDL2/Program.cs b/src/Ryujinx.Headless.SDL2/Program.cs
index 453c470e73..643db845f4 100644
--- a/src/Ryujinx.Headless.SDL2/Program.cs
+++ b/src/Ryujinx.Headless.SDL2/Program.cs
@@ -487,11 +487,12 @@ namespace Ryujinx.Headless.SDL2
             if (options.GraphicsBackend == GraphicsBackend.Vulkan && window is VulkanWindow vulkanWindow)
             {
                 string preferredGpuId = string.Empty;
+                Vk api = Vk.GetApi();
 
                 if (!string.IsNullOrEmpty(options.PreferredGpuVendor))
                 {
                     string preferredGpuVendor = options.PreferredGpuVendor.ToLowerInvariant();
-                    var devices = VulkanRenderer.GetPhysicalDevices();
+                    var devices = VulkanRenderer.GetPhysicalDevices(api);
 
                     foreach (var device in devices)
                     {
@@ -504,6 +505,7 @@ namespace Ryujinx.Headless.SDL2
                 }
 
                 return new VulkanRenderer(
+                    api,
                     (instance, vk) => new SurfaceKHR((ulong)(vulkanWindow.CreateWindowSurface(instance.Handle))),
                     vulkanWindow.GetRequiredInstanceExtensions,
                     preferredGpuId);
diff --git a/src/Ryujinx/Ui/MainWindow.cs b/src/Ryujinx/Ui/MainWindow.cs
index b61855e4c9..f4cb3d0727 100644
--- a/src/Ryujinx/Ui/MainWindow.cs
+++ b/src/Ryujinx/Ui/MainWindow.cs
@@ -426,7 +426,7 @@ namespace Ryujinx.Ui
             if (ConfigurationState.Instance.Graphics.GraphicsBackend == GraphicsBackend.Vulkan)
             {
                 string preferredGpu = ConfigurationState.Instance.Graphics.PreferredGpu.Value;
-                renderer = new VulkanRenderer(CreateVulkanSurface, VulkanHelper.GetRequiredInstanceExtensions, preferredGpu);
+                renderer = new VulkanRenderer(Vk.GetApi(), CreateVulkanSurface, VulkanHelper.GetRequiredInstanceExtensions, preferredGpu);
             }
             else
             {
diff --git a/src/Ryujinx/Ui/Windows/SettingsWindow.cs b/src/Ryujinx/Ui/Windows/SettingsWindow.cs
index 7d39b9ea11..65175ff15d 100644
--- a/src/Ryujinx/Ui/Windows/SettingsWindow.cs
+++ b/src/Ryujinx/Ui/Windows/SettingsWindow.cs
@@ -13,6 +13,7 @@ using Ryujinx.Ui.Common.Configuration;
 using Ryujinx.Ui.Common.Configuration.System;
 using Ryujinx.Ui.Helper;
 using Ryujinx.Ui.Widgets;
+using Silk.NET.Vulkan;
 using System;
 using System.Collections.Generic;
 using System.Globalization;
@@ -477,7 +478,7 @@ namespace Ryujinx.Ui.Windows
 
             if (Enum.Parse<GraphicsBackend>(_graphicsBackend.ActiveId) == GraphicsBackend.Vulkan)
             {
-                var devices = VulkanRenderer.GetPhysicalDevices();
+                var devices = VulkanRenderer.GetPhysicalDevices(Vk.GetApi());
                 string preferredGpuIdFromConfig = ConfigurationState.Instance.Graphics.PreferredGpu.Value;
                 string preferredGpuId = preferredGpuIdFromConfig;
                 bool noGpuId = string.IsNullOrEmpty(preferredGpuIdFromConfig);