aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Ava/Ui/Backend/Vulkan/Skia/VulkanSkiaGpu.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Ava/Ui/Backend/Vulkan/Skia/VulkanSkiaGpu.cs')
-rw-r--r--Ryujinx.Ava/Ui/Backend/Vulkan/Skia/VulkanSkiaGpu.cs124
1 files changed, 124 insertions, 0 deletions
diff --git a/Ryujinx.Ava/Ui/Backend/Vulkan/Skia/VulkanSkiaGpu.cs b/Ryujinx.Ava/Ui/Backend/Vulkan/Skia/VulkanSkiaGpu.cs
new file mode 100644
index 00000000..4fc6b929
--- /dev/null
+++ b/Ryujinx.Ava/Ui/Backend/Vulkan/Skia/VulkanSkiaGpu.cs
@@ -0,0 +1,124 @@
+using System;
+using System.Collections.Generic;
+using Avalonia;
+using Avalonia.Platform;
+using Avalonia.Skia;
+using Avalonia.X11;
+using Ryujinx.Ava.Ui.Vulkan;
+using Silk.NET.Vulkan;
+using SkiaSharp;
+
+namespace Ryujinx.Ava.Ui.Backend.Vulkan
+{
+ public class VulkanSkiaGpu : ISkiaGpu
+ {
+ private readonly VulkanPlatformInterface _vulkan;
+ private readonly long? _maxResourceBytes;
+ private GRVkBackendContext _grVkBackend;
+ private bool _initialized;
+
+ public GRContext GrContext { get; private set; }
+
+ public VulkanSkiaGpu(long? maxResourceBytes)
+ {
+ _vulkan = AvaloniaLocator.Current.GetService<VulkanPlatformInterface>();
+ _maxResourceBytes = maxResourceBytes;
+ }
+
+ private void Initialize()
+ {
+ if (_initialized)
+ {
+ return;
+ }
+
+ _initialized = true;
+ GRVkGetProcedureAddressDelegate getProc = (string name, IntPtr instanceHandle, IntPtr deviceHandle) =>
+ {
+ IntPtr addr = IntPtr.Zero;
+
+ if (deviceHandle != IntPtr.Zero)
+ {
+ addr = _vulkan.Device.Api.GetDeviceProcAddr(new Device(deviceHandle), name);
+
+ if (addr != IntPtr.Zero)
+ {
+ return addr;
+ }
+
+ addr = _vulkan.Device.Api.GetDeviceProcAddr(new Device(_vulkan.Device.Handle), name);
+
+ if (addr != IntPtr.Zero)
+ {
+ return addr;
+ }
+ }
+
+ addr = _vulkan.Device.Api.GetInstanceProcAddr(new Instance(_vulkan.Instance.Handle), name);
+
+ if (addr == IntPtr.Zero)
+ {
+ addr = _vulkan.Device.Api.GetInstanceProcAddr(new Instance(instanceHandle), name);
+ }
+
+ return addr;
+ };
+
+ _grVkBackend = new GRVkBackendContext()
+ {
+ VkInstance = _vulkan.Device.Handle,
+ VkPhysicalDevice = _vulkan.PhysicalDevice.Handle,
+ VkDevice = _vulkan.Device.Handle,
+ VkQueue = _vulkan.Device.Queue.Handle,
+ GraphicsQueueIndex = _vulkan.PhysicalDevice.QueueFamilyIndex,
+ GetProcedureAddress = getProc
+ };
+ GrContext = GRContext.CreateVulkan(_grVkBackend);
+ if (_maxResourceBytes.HasValue)
+ {
+ GrContext.SetResourceCacheLimit(_maxResourceBytes.Value);
+ }
+ }
+
+ public ISkiaGpuRenderTarget TryCreateRenderTarget(IEnumerable<object> surfaces)
+ {
+ foreach (var surface in surfaces)
+ {
+ VulkanWindowSurface window;
+
+ if (surface is IPlatformHandle handle)
+ {
+ window = new VulkanWindowSurface(handle.Handle);
+ }
+ else if (surface is X11FramebufferSurface x11FramebufferSurface)
+ {
+ // As of Avalonia 0.10.13, an IPlatformHandle isn't passed for linux, so use reflection to otherwise get the window id
+ var xId = (IntPtr)x11FramebufferSurface.GetType().GetField(
+ "_xid",
+ System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetValue(x11FramebufferSurface);
+
+ window = new VulkanWindowSurface(xId);
+ }
+ else
+ {
+ continue;
+ }
+
+ VulkanRenderTarget vulkanRenderTarget = new VulkanRenderTarget(_vulkan, window);
+
+ Initialize();
+
+ vulkanRenderTarget.GrContext = GrContext;
+
+ return vulkanRenderTarget;
+ }
+
+ return null;
+ }
+
+ public ISkiaSurface TryCreateSurface(PixelSize size, ISkiaGpuRenderSession session)
+ {
+ return null;
+ }
+ }
+}