aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Ava/Ui/Backend/Vulkan/Surfaces/VulkanSurfaceRenderTarget.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Ava/Ui/Backend/Vulkan/Surfaces/VulkanSurfaceRenderTarget.cs')
-rw-r--r--Ryujinx.Ava/Ui/Backend/Vulkan/Surfaces/VulkanSurfaceRenderTarget.cs96
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);
+ }
}
}
}