From dfc5a3db4e9194ab5c33f9a730fae37df6a82b64 Mon Sep 17 00:00:00 2001 From: Sebastian Emanuel Dawid Date: Tue, 13 May 2025 11:27:22 +0200 Subject: [PATCH 1/2] Fix crash related to failure to acquire next swapchain image during resizing --- examples/swapchain.zig | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/examples/swapchain.zig b/examples/swapchain.zig index a8f1c06..db81de0 100644 --- a/examples/swapchain.zig +++ b/examples/swapchain.zig @@ -80,7 +80,11 @@ pub const Swapchain = struct { errdefer gc.dev.destroySemaphore(next_image_acquired, null); const result = try gc.dev.acquireNextImageKHR(handle, std.math.maxInt(u64), next_image_acquired, .null_handle); - if (result.result != .success) { + // event with a .suboptimal_khr we can still go on to present + // if we error even for .suboptimal_khr the example will crash and segfault + // on resize, since even the recreated swapchain can be suboptimal during a + // resize. + if (result.result == .not_ready or result.result == .timeout) { return error.ImageAcquireFailed; } From 783b70a12e47aaf286092a6fbea2eeff75b9b5cb Mon Sep 17 00:00:00 2001 From: Sebastian Emanuel Dawid Date: Tue, 13 May 2025 11:56:03 +0200 Subject: [PATCH 2/2] Make sure the example does not segfault if it crashes during swapchain recreation. --- examples/swapchain.zig | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/examples/swapchain.zig b/examples/swapchain.zig index db81de0..c4707aa 100644 --- a/examples/swapchain.zig +++ b/examples/swapchain.zig @@ -46,7 +46,7 @@ pub const Swapchain = struct { else .exclusive; - const handle = try gc.dev.createSwapchainKHR(&.{ + const handle = gc.dev.createSwapchainKHR(&.{ .surface = gc.surface, .min_image_count = image_count, .image_format = surface_format.format, @@ -62,7 +62,9 @@ pub const Swapchain = struct { .present_mode = present_mode, .clipped = vk.TRUE, .old_swapchain = old_handle, - }, null); + }, null) catch { + return error.SwapchainCreationFailed; + }; errdefer gc.dev.destroySwapchainKHR(handle, null); if (old_handle != .null_handle) { @@ -113,6 +115,8 @@ pub const Swapchain = struct { } pub fn deinit(self: Swapchain) void { + // if we have no swapchain none of these should exist and we can just return + if (self.handle == .null_handle) return; self.deinitExceptSwapchain(); self.gc.dev.destroySwapchainKHR(self.handle, null); } @@ -122,7 +126,18 @@ pub const Swapchain = struct { const allocator = self.allocator; const old_handle = self.handle; self.deinitExceptSwapchain(); - self.* = try initRecycle(gc, allocator, new_extent, old_handle); + // set current handle to NULL_HANDLE to signal that the current swapchain does no longer need to be + // de-initialized if we fail to recreate it. + self.handle = .null_handle; + self.* = initRecycle(gc, allocator, new_extent, old_handle) catch |err| switch (err) { + error.SwapchainCreationFailed => { + // we failed while recreating so our current handle still exists, + // but we won't destroy it in the deferred deinit of this object. + gc.dev.destroySwapchainKHR(old_handle, null); + return err; + }, + else => return err, + }; } pub fn currentImage(self: Swapchain) vk.Image {