This commit is contained in:
Emmanuel Hansen 2023-07-11 17:24:48 +00:00
parent 9b4d988d8c
commit 108fb2380a
14 changed files with 190 additions and 12 deletions

View file

@ -31,6 +31,8 @@ namespace LibRyujinx
private static ManualResetEvent _surfaceEvent;
private static long _surfacePtr;
public static VulkanLoader? VulkanLoader { get; private set; }
[DllImport("libryujinxjni")]
private extern static IntPtr getStringPointer(JEnvRef jEnv, JStringLocalRef s);
@ -213,7 +215,8 @@ namespace LibRyujinx
public unsafe static JBoolean JniInitializeGraphicsRendererNative(JEnvRef jEnv,
JObjectLocalRef jObj,
JArrayLocalRef extensionsArray,
JLong surfacePtr)
JLong surfacePtr,
JLong driverHandle)
{
if (Renderer != null)
{
@ -252,12 +255,17 @@ namespace LibRyujinx
_surfacePtr = surfacePtr;
if((long)driverHandle != 0)
{
VulkanLoader = new VulkanLoader((IntPtr)(long)driverHandle);
}
CreateSurface createSurfaceFunc = instance =>
{
_surfaceEvent.WaitOne();
_surfaceEvent.Reset();
var api = Vk.GetApi();
var api = VulkanLoader?.GetApi() ?? Vk.GetApi();
if (api.TryGetInstanceExtension(new Instance(instance), out KhrAndroidSurface surfaceExtension))
{
var createInfo = new AndroidSurfaceCreateInfoKHR

View file

@ -91,7 +91,7 @@ namespace LibRyujinx
}
else if (graphicsBackend == GraphicsBackend.Vulkan)
{
Renderer = new VulkanRenderer(Vk.GetApi(), (instance, vk) => new SurfaceKHR((ulong?)createSurfaceFunc(instance.Handle)),
Renderer = new VulkanRenderer(VulkanLoader?.GetApi() ?? Vk.GetApi(), (instance, vk) => new SurfaceKHR((ulong?)createSurfaceFunc(instance.Handle)),
() => requiredExtensions,
null);
}

View file

@ -0,0 +1,96 @@
using Ryujinx.Common.Logging;
using Silk.NET.Core.Contexts;
using Silk.NET.Vulkan;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace LibRyujinx
{
public class VulkanLoader : IDisposable
{
private delegate IntPtr GetInstanceProcAddress(IntPtr instance, IntPtr name);
private delegate IntPtr GetDeviceProcAddress(IntPtr device, IntPtr name);
private IntPtr _loadedLibrary = IntPtr.Zero;
private GetInstanceProcAddress _getInstanceProcAddr;
private GetDeviceProcAddress _getDeviceProcAddr;
public void Dispose()
{
if (_loadedLibrary != IntPtr.Zero)
{
NativeLibrary.Free(_loadedLibrary);
_loadedLibrary = IntPtr.Zero;
}
}
public VulkanLoader(IntPtr driver)
{
_loadedLibrary = driver;
if(_loadedLibrary != IntPtr.Zero)
{
var instanceGetProc = NativeLibrary.GetExport(_loadedLibrary, "vkGetInstanceProcAddr");
var deviceProc = NativeLibrary.GetExport(_loadedLibrary, "vkGetDeviceProcAddr");
_getInstanceProcAddr = Marshal.GetDelegateForFunctionPointer<GetInstanceProcAddress>(instanceGetProc);
_getDeviceProcAddr = Marshal.GetDelegateForFunctionPointer<GetDeviceProcAddress>(deviceProc);
}
}
public Vk GetApi()
{
if (_loadedLibrary == IntPtr.Zero)
{
return Vk.GetApi();
}
var ctx = new MultiNativeContext(new INativeContext[1]);
var ret = new Vk(ctx);
ctx.Contexts[0] = new LamdaNativeContext
(
x =>
{
var xPtr = Marshal.StringToHGlobalAnsi(x);
try
{
nint ptr = default;
ptr = _getInstanceProcAddr(ret.CurrentInstance.GetValueOrDefault().Handle, xPtr);
if (ptr == default)
{
ptr = _getInstanceProcAddr(IntPtr.Zero, xPtr);
if (ptr == default)
{
var currentDevice = ret.CurrentDevice.GetValueOrDefault().Handle;
if (currentDevice != IntPtr.Zero)
{
ptr = _getDeviceProcAddr(currentDevice, xPtr);
}
if (ptr == default)
{
Logger.Warning?.Print(LogClass.Gpu, $"Failed to get function pointer: {x}");
}
}
}
return ptr;
}
finally
{
Marshal.FreeHGlobal(xPtr);
}
}
);
return ret;
}
}
}