diff options
Diffstat (limited to 'Ryujinx.Ava/Ui/Backend/Vulkan/Surfaces/VulkanSurfaceRenderTarget.cs')
-rw-r--r-- | Ryujinx.Ava/Ui/Backend/Vulkan/Surfaces/VulkanSurfaceRenderTarget.cs | 96 |
1 files changed, 69 insertions, 27 deletions
diff --git a/Ryujinx.Ava/Ui/Backend/Vulkan/Surfaces/VulkanSurfaceRenderTarget.cs b/Ryujinx.Ava/Ui/Backend/Vulkan/Surfaces/VulkanSurfaceRenderTarget.cs index b2b8843d..510e6724 100644 --- a/Ryujinx.Ava/Ui/Backend/Vulkan/Surfaces/VulkanSurfaceRenderTarget.cs +++ b/Ryujinx.Ava/Ui/Backend/Vulkan/Surfaces/VulkanSurfaceRenderTarget.cs @@ -1,5 +1,6 @@ using System; using Avalonia; +using Ryujinx.Graphics.Vulkan; using Silk.NET.Vulkan; namespace Ryujinx.Ava.Ui.Vulkan.Surfaces @@ -7,24 +8,35 @@ namespace Ryujinx.Ava.Ui.Vulkan.Surfaces internal class VulkanSurfaceRenderTarget : IDisposable { private readonly VulkanPlatformInterface _platformInterface; - private readonly Format _format; - public VulkanImage Image { get; private set; } - public bool IsCorrupted { get; private set; } = true; + private VulkanCommandBufferPool.VulkanCommandBuffer _commandBuffer; + private VulkanImage Image { get; set; } + private object _lock = new object(); public uint MipLevels => Image.MipLevels; + public VulkanDevice Device { get; } public VulkanSurfaceRenderTarget(VulkanPlatformInterface platformInterface, VulkanSurface surface) { _platformInterface = platformInterface; - Display = VulkanDisplay.CreateDisplay(platformInterface.Instance, platformInterface.Device, - platformInterface.PhysicalDevice, surface); + var device = VulkanInitialization.CreateDevice(platformInterface.Api, + platformInterface.PhysicalDevice.InternalHandle, + platformInterface.PhysicalDevice.QueueFamilyIndex, + VulkanInitialization.GetSupportedExtensions(platformInterface.Api, platformInterface.PhysicalDevice.InternalHandle), + platformInterface.PhysicalDevice.QueueCount); + + Device = new VulkanDevice(device, platformInterface.PhysicalDevice, platformInterface.Api); + + Display = VulkanDisplay.CreateDisplay( + platformInterface.Instance, + Device, + platformInterface.PhysicalDevice, + surface); Surface = surface; // Skia seems to only create surfaces from images with unorm format - IsRgba = Display.SurfaceFormat.Format >= Format.R8G8B8A8Unorm && Display.SurfaceFormat.Format <= Format.R8G8B8A8Srgb; @@ -33,13 +45,13 @@ namespace Ryujinx.Ava.Ui.Vulkan.Surfaces public bool IsRgba { get; } - public uint ImageFormat => (uint) _format; + public uint ImageFormat => (uint)_format; public ulong MemorySize => Image.MemorySize; - public VulkanDisplay Display { get; } + public VulkanDisplay Display { get; private set; } - public VulkanSurface Surface { get; } + public VulkanSurface Surface { get; private set; } public uint UsageFlags => Image.UsageFlags; @@ -47,46 +59,76 @@ namespace Ryujinx.Ava.Ui.Vulkan.Surfaces public void Dispose() { - _platformInterface.Device.WaitIdle(); - DestroyImage(); - Display?.Dispose(); - Surface?.Dispose(); + lock (_lock) + { + DestroyImage(); + Display?.Dispose(); + Surface?.Dispose(); + Device?.Dispose(); + + Display = null; + Surface = null; + } } public VulkanSurfaceRenderingSession BeginDraw(float scaling) { - var session = new VulkanSurfaceRenderingSession(Display, _platformInterface.Device, this, scaling); - - if (IsCorrupted) + if (Image == null) { - IsCorrupted = false; - DestroyImage(); - CreateImage(); - } - else - { - Image.TransitionLayout(ImageLayout.ColorAttachmentOptimal, AccessFlags.AccessNoneKhr); + RecreateImage(); } + _commandBuffer?.WaitForFence(); + _commandBuffer = null; + + var session = new VulkanSurfaceRenderingSession(Display, Device, this, scaling); + + Image.TransitionLayout(ImageLayout.ColorAttachmentOptimal, AccessFlags.AccessNoneKhr); + return session; } - public void Invalidate() + public void RecreateImage() { - IsCorrupted = true; + DestroyImage(); + CreateImage(); } private void CreateImage() { Size = Display.Size; - Image = new VulkanImage(_platformInterface.Device, _platformInterface.PhysicalDevice, _platformInterface.Device.CommandBufferPool, ImageFormat, Size); + Image = new VulkanImage(Device, _platformInterface.PhysicalDevice, Display.CommandBufferPool, ImageFormat, Size); } private void DestroyImage() { - _platformInterface.Device.WaitIdle(); + _commandBuffer?.WaitForFence(); + _commandBuffer = null; Image?.Dispose(); + Image = null; + } + + public VulkanImage GetImage() + { + return Image; + } + + public void EndDraw() + { + lock (_lock) + { + if (Display == null) + { + return; + } + + _commandBuffer = Display.StartPresentation(); + + Display.BlitImageToCurrentImage(this, _commandBuffer.InternalHandle); + + Display.EndPresentation(_commandBuffer); + } } } } |