| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- using System;
- using Avalonia;
- using Avalonia.Skia;
- using Ryujinx.Ava.Ui.Vulkan;
- using Ryujinx.Ava.Ui.Vulkan.Surfaces;
- using Silk.NET.Vulkan;
- using SkiaSharp;
- namespace Ryujinx.Ava.Ui.Backend.Vulkan
- {
- internal class VulkanRenderTarget : ISkiaGpuRenderTarget
- {
- public GRContext GrContext { get; private set; }
- private readonly VulkanSurfaceRenderTarget _surface;
- private readonly VulkanPlatformInterface _vulkanPlatformInterface;
- private readonly IVulkanPlatformSurface _vulkanPlatformSurface;
- private GRVkBackendContext _grVkBackend;
- public VulkanRenderTarget(VulkanPlatformInterface vulkanPlatformInterface, IVulkanPlatformSurface vulkanPlatformSurface)
- {
- _surface = vulkanPlatformInterface.CreateRenderTarget(vulkanPlatformSurface);
- _vulkanPlatformInterface = vulkanPlatformInterface;
- _vulkanPlatformSurface = vulkanPlatformSurface;
- Initialize();
- }
- private void Initialize()
- {
- GRVkGetProcedureAddressDelegate getProc = GetVulkanProcAddress;
- _grVkBackend = new GRVkBackendContext()
- {
- VkInstance = _surface.Device.Handle,
- VkPhysicalDevice = _vulkanPlatformInterface.PhysicalDevice.Handle,
- VkDevice = _surface.Device.Handle,
- VkQueue = _surface.Device.Queue.Handle,
- GraphicsQueueIndex = _vulkanPlatformInterface.PhysicalDevice.QueueFamilyIndex,
- GetProcedureAddress = getProc
- };
- GrContext = GRContext.CreateVulkan(_grVkBackend);
- var gpu = AvaloniaLocator.Current.GetService<VulkanSkiaGpu>();
- if (gpu.MaxResourceBytes.HasValue)
- {
- GrContext.SetResourceCacheLimit(gpu.MaxResourceBytes.Value);
- }
- }
- private IntPtr GetVulkanProcAddress(string name, IntPtr instanceHandle, IntPtr deviceHandle)
- {
- IntPtr addr;
- if (deviceHandle != IntPtr.Zero)
- {
- addr = _vulkanPlatformInterface.Api.GetDeviceProcAddr(new Device(deviceHandle), name);
- if (addr != IntPtr.Zero)
- {
- return addr;
- }
- addr = _vulkanPlatformInterface.Api.GetDeviceProcAddr(new Device(_surface.Device.Handle), name);
- if (addr != IntPtr.Zero)
- {
- return addr;
- }
- }
- addr = _vulkanPlatformInterface.Api.GetInstanceProcAddr(new Instance(_vulkanPlatformInterface.Instance.Handle), name);
- if (addr == IntPtr.Zero)
- {
- addr = _vulkanPlatformInterface.Api.GetInstanceProcAddr(new Instance(instanceHandle), name);
- }
- return addr;
- }
- public void Dispose()
- {
- _grVkBackend.Dispose();
- GrContext.Dispose();
- _surface.Dispose();
- }
- public ISkiaGpuRenderSession BeginRenderingSession()
- {
- var session = _surface.BeginDraw(_vulkanPlatformSurface.Scaling);
- bool success = false;
- try
- {
- var disp = session.Display;
- var api = session.Api;
- var size = session.Size;
- var scaling = session.Scaling;
- if (size.Width <= 0 || size.Height <= 0 || scaling < 0)
- {
- size = new Avalonia.PixelSize(1, 1);
- scaling = 1;
- }
- lock (GrContext)
- {
- GrContext.ResetContext();
- var image = _surface.GetImage();
- var imageInfo = new GRVkImageInfo()
- {
- CurrentQueueFamily = disp.QueueFamilyIndex,
- Format = (uint)image.Format,
- Image = image.Handle,
- ImageLayout = (uint)image.CurrentLayout,
- ImageTiling = (uint)image.Tiling,
- ImageUsageFlags = _surface.UsageFlags,
- LevelCount = _surface.MipLevels,
- SampleCount = 1,
- Protected = false,
- Alloc = new GRVkAlloc()
- {
- Memory = image.MemoryHandle,
- Flags = 0,
- Offset = 0,
- Size = _surface.MemorySize
- }
- };
- var renderTarget =
- new GRBackendRenderTarget((int)size.Width, (int)size.Height, 1,
- imageInfo);
- var surface = SKSurface.Create(GrContext, renderTarget,
- GRSurfaceOrigin.TopLeft,
- _surface.IsRgba ? SKColorType.Rgba8888 : SKColorType.Bgra8888, SKColorSpace.CreateSrgb());
- if (surface == null)
- {
- throw new InvalidOperationException(
- "Surface can't be created with the provided render target");
- }
- success = true;
- return new VulkanGpuSession(GrContext, renderTarget, surface, session);
- }
- }
- finally
- {
- if (!success)
- {
- session.Dispose();
- }
- }
- }
- public bool IsCorrupted { get; }
- internal class VulkanGpuSession : ISkiaGpuRenderSession
- {
- private readonly GRBackendRenderTarget _backendRenderTarget;
- private readonly VulkanSurfaceRenderingSession _vulkanSession;
- public VulkanGpuSession(GRContext grContext,
- GRBackendRenderTarget backendRenderTarget,
- SKSurface surface,
- VulkanSurfaceRenderingSession vulkanSession)
- {
- GrContext = grContext;
- _backendRenderTarget = backendRenderTarget;
- SkSurface = surface;
- _vulkanSession = vulkanSession;
- SurfaceOrigin = GRSurfaceOrigin.TopLeft;
- }
- public void Dispose()
- {
- lock (_vulkanSession.Display.Lock)
- {
- SkSurface.Canvas.Flush();
- SkSurface.Dispose();
- _backendRenderTarget.Dispose();
- GrContext.Flush();
- _vulkanSession.Dispose();
- }
- }
- public GRContext GrContext { get; }
- public SKSurface SkSurface { get; }
- public double ScaleFactor => _vulkanSession.Scaling;
- public GRSurfaceOrigin SurfaceOrigin { get; }
- }
- }
- }
|