From 92ac2abbcb9de9eb35a30c7a177898de1c4b2b7f Mon Sep 17 00:00:00 2001 From: Emmanuel Hansen Date: Mon, 2 Sep 2024 12:20:48 +0000 Subject: [PATCH] vulkan - fix display out of date error --- src/Avalonia.Vulkan/Interop/VulkanDisplay.cs | 33 ++++++++++++++----- .../VulkanKhrSurfaceRenderTarget.cs | 8 ++--- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/Avalonia.Vulkan/Interop/VulkanDisplay.cs b/src/Avalonia.Vulkan/Interop/VulkanDisplay.cs index cda28ecff7e..8f4da16afc2 100644 --- a/src/Avalonia.Vulkan/Interop/VulkanDisplay.cs +++ b/src/Avalonia.Vulkan/Interop/VulkanDisplay.cs @@ -13,22 +13,24 @@ internal class VulkanDisplay : IDisposable private IVulkanPlatformGraphicsContext _context; private VulkanSemaphorePair _semaphorePair; private uint _nextImage; - private readonly VulkanKhrSurface _surface; + private VulkanKhrSurface _surface; private VkSurfaceFormatKHR _surfaceFormat; private VkSwapchainKHR _swapchain; private VkExtent2D _swapchainExtent; + private readonly IVulkanKhrSurfacePlatformSurface _platformSurface; private VkImage[] _swapchainImages = Array.Empty(); private VkImageView[] _swapchainImageViews = Array.Empty(); public VulkanCommandBufferPool CommandBufferPool { get; private set; } public PixelSize Size { get; private set; } - + private VulkanDisplay(IVulkanPlatformGraphicsContext context, VulkanKhrSurface surface, VkSwapchainKHR swapchain, - VkExtent2D swapchainExtent) + VkExtent2D swapchainExtent, IVulkanKhrSurfacePlatformSurface platformSurface) { _context = context; _surface = surface; _swapchain = swapchain; _swapchainExtent = swapchainExtent; + _platformSurface = platformSurface; _semaphorePair = new VulkanSemaphorePair(_context); CommandBufferPool = new VulkanCommandBufferPool(_context); CreateSwapchainImages(); @@ -135,10 +137,11 @@ private void DestroySwapchain() _swapchain = default; } - internal static VulkanDisplay CreateDisplay(IVulkanPlatformGraphicsContext context, VulkanKhrSurface surface) + internal static VulkanDisplay CreateDisplay(IVulkanPlatformGraphicsContext context, IVulkanKhrSurfacePlatformSurface surface) { - var swapchain = CreateSwapchain(context, surface, out var extent); - return new VulkanDisplay(context, surface, swapchain, extent); + var khrSurface = new VulkanKhrSurface(context, surface); + var swapchain = CreateSwapchain(context, khrSurface, out var extent); + return new VulkanDisplay(context, khrSurface, swapchain, extent, surface); } private void DestroyCurrentImageViews() @@ -188,19 +191,27 @@ private VkImageView CreateSwapchainImageView(VkImage swapchainImage, VkFormat fo return imageView; } - private void Recreate() + private void RecreateSwapchain() { _context.DeviceApi.DeviceWaitIdle(_context.DeviceHandle); _swapchain = CreateSwapchain(_context, _surface, out var extent, this); _swapchainExtent = extent; CreateSwapchainImages(); } + + private void RecreateSurface() + { + _surface?.Dispose(); + _surface = new VulkanKhrSurface(_context, _platformSurface); + DestroySwapchain(); + RecreateSwapchain(); + } public bool EnsureSwapchainAvailable() { if (Size != _surface.Size) { - Recreate(); + RecreateSwapchain(); return true; } return false; @@ -218,7 +229,9 @@ public VulkanCommandBuffer StartPresentation() _semaphorePair.ImageAvailableSemaphore.Handle, default, out _nextImage); if (acquireResult is VkResult.VK_ERROR_OUT_OF_DATE_KHR or VkResult.VK_SUBOPTIMAL_KHR) - Recreate(); + RecreateSwapchain(); + else if (acquireResult is VkResult.VK_ERROR_SURFACE_LOST_KHR) + RecreateSurface(); else { acquireResult.ThrowOnError("vkAcquireNextImageKHR"); @@ -323,6 +336,8 @@ public void Dispose() DestroySwapchain(); CommandBufferPool?.Dispose(); CommandBufferPool = null!; + _surface?.Dispose(); + _surface = null!; } } diff --git a/src/Avalonia.Vulkan/VulkanKhrSurfaceRenderTarget.cs b/src/Avalonia.Vulkan/VulkanKhrSurfaceRenderTarget.cs index 7a83c85eeb2..a24b9eea7a4 100644 --- a/src/Avalonia.Vulkan/VulkanKhrSurfaceRenderTarget.cs +++ b/src/Avalonia.Vulkan/VulkanKhrSurfaceRenderTarget.cs @@ -7,7 +7,6 @@ namespace Avalonia.Vulkan; internal class VulkanKhrRenderTarget : IVulkanRenderTarget { - private VulkanKhrSurface _khrSurface; private readonly IVulkanPlatformGraphicsContext _context; private VulkanDisplay _display; private VulkanImage? _image; @@ -18,8 +17,7 @@ internal class VulkanKhrRenderTarget : IVulkanRenderTarget public VulkanKhrRenderTarget(IVulkanKhrSurfacePlatformSurface surface, IVulkanPlatformGraphicsContext context) { _platformSurface = surface; - _khrSurface = new(context, surface); - _display = VulkanDisplay.CreateDisplay(context, _khrSurface); + _display = VulkanDisplay.CreateDisplay(context, surface); _context = context; IsRgba = _display.SurfaceFormat.format >= VkFormat.VK_FORMAT_R8G8B8A8_UNORM && _display.SurfaceFormat.format <= VkFormat.VK_FORMAT_R8G8B8A8_SRGB; @@ -46,8 +44,6 @@ public void Dispose() DestroyImage(); _display?.Dispose(); _display = null!; - _khrSurface?.Dispose(); - _khrSurface = null!; } @@ -104,4 +100,4 @@ public void Dispose() } } } -} \ No newline at end of file +}