Skip to content

Vulkan - Fix display surface lost error #16887

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 24 additions & 9 deletions src/Avalonia.Vulkan/Interop/VulkanDisplay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<VkImage>();
private VkImageView[] _swapchainImageViews = Array.Empty<VkImageView>();
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();
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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;
Expand All @@ -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");
Expand Down Expand Up @@ -323,6 +336,8 @@ public void Dispose()
DestroySwapchain();
CommandBufferPool?.Dispose();
CommandBufferPool = null!;
_surface?.Dispose();
_surface = null!;
}

}
8 changes: 2 additions & 6 deletions src/Avalonia.Vulkan/VulkanKhrSurfaceRenderTarget.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ namespace Avalonia.Vulkan;

internal class VulkanKhrRenderTarget : IVulkanRenderTarget
{
private VulkanKhrSurface _khrSurface;
private readonly IVulkanPlatformGraphicsContext _context;
private VulkanDisplay _display;
private VulkanImage? _image;
Expand All @@ -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;
Expand All @@ -46,8 +44,6 @@ public void Dispose()
DestroyImage();
_display?.Dispose();
_display = null!;
_khrSurface?.Dispose();
_khrSurface = null!;
}


Expand Down Expand Up @@ -104,4 +100,4 @@ public void Dispose()
}
}
}
}
}
Loading