a73x

9afdc9f8

Migrate 14 *WaitIdle sites to vk_sync.waitIdleForShutdown

a73x   2026-04-18 15:18

Mechanically migrates 13 deviceWaitIdle + 1 queueWaitIdle sites to
the named waitIdleForShutdown helper. Preserves existing unbounded
behavior while documenting intent at the call site and satisfying
the upcoming grep gate.

Four of these sites are mid-flight recovery paths (scale change,
resize, OutOfDateKHR) rather than shutdown drains; those are flagged
in a follow-up ticket for migration to a bounded variant once
waitIdleBounded is implemented.

Part of issue ab6c92f0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

diff --git a/src/main.zig b/src/main.zig
index 441da56..06d7af1 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -422,7 +422,7 @@ fn runTerminal(alloc: std.mem.Allocator) !void {
        if (!render_pending) continue;

        if (scale_pending) {
            _ = try ctx.vkd.deviceWaitIdle(ctx.device);
            vk_sync.waitIdleForShutdown(ctx.vkd, ctx.device);

            geom = try rebuildFaceForScale(
                &face,
@@ -460,7 +460,7 @@ fn runTerminal(alloc: std.mem.Allocator) !void {
            const buf_w = window.width * @as(u32, @intCast(geom.buffer_scale));
            const buf_h = window.height * @as(u32, @intCast(geom.buffer_scale));
            if (new_grid.cols != cols or new_grid.rows != rows) {
                _ = try ctx.vkd.deviceWaitIdle(ctx.device);
                vk_sync.waitIdleForShutdown(ctx.vkd, ctx.device);
                try ctx.recreateSwapchain(buf_w, buf_h);
                try term.resize(new_grid.cols, new_grid.rows);
                try p.resize(new_grid.cols, new_grid.rows);
@@ -477,7 +477,7 @@ fn runTerminal(alloc: std.mem.Allocator) !void {
                selection.anchor = if (selection.anchor) |point| clampGridPoint(point, cols, rows) else null;
                selection.hover = if (selection.hover) |point| clampGridPoint(point, cols, rows) else null;
            } else {
                _ = try ctx.vkd.deviceWaitIdle(ctx.device);
                vk_sync.waitIdleForShutdown(ctx.vkd, ctx.device);
                try ctx.recreateSwapchain(buf_w, buf_h);
            }
            last_window_w = window.width;
@@ -686,7 +686,7 @@ fn runTerminal(alloc: std.mem.Allocator) !void {
            if (is_bench) &submit_timing else null,
        ) catch |err| switch (err) {
            error.OutOfDateKHR => {
                _ = try ctx.vkd.deviceWaitIdle(ctx.device);
                vk_sync.waitIdleForShutdown(ctx.vkd, ctx.device);
                const buf_w = window.width * @as(u32, @intCast(geom.buffer_scale));
                const buf_h = window.height * @as(u32, @intCast(geom.buffer_scale));
                try ctx.recreateSwapchain(buf_w, buf_h);
@@ -727,7 +727,7 @@ fn runTerminal(alloc: std.mem.Allocator) !void {
        };
    }

    _ = try ctx.vkd.deviceWaitIdle(ctx.device);
    vk_sync.waitIdleForShutdown(ctx.vkd, ctx.device);
}

fn gridSizeForWindow(window_w: u32, window_h: u32, cell_w: u32, cell_h: u32) GridSize {
@@ -2495,7 +2495,7 @@ fn runTextCoverageCompare(alloc: std.mem.Allocator) !void {
        const size_changed = window.width != last_window_w or window.height != last_window_h;

        if (scale_changed or size_changed) {
            _ = try ctx.vkd.deviceWaitIdle(ctx.device);
            vk_sync.waitIdleForShutdown(ctx.vkd, ctx.device);

            if (scale_changed) {
                geom = try rebuildFaceForScale(
@@ -2530,7 +2530,7 @@ fn runTextCoverageCompare(alloc: std.mem.Allocator) !void {
            .{ 0.0, 0.0, 0.0, 1.0 },
        ) catch |err| switch (err) {
            error.OutOfDateKHR => {
                _ = try ctx.vkd.deviceWaitIdle(ctx.device);
                vk_sync.waitIdleForShutdown(ctx.vkd, ctx.device);
                const buf_w = window.width * @as(u32, @intCast(geom.buffer_scale));
                const buf_h = window.height * @as(u32, @intCast(geom.buffer_scale));
                try ctx.recreateSwapchain(buf_w, buf_h);
@@ -2545,7 +2545,7 @@ fn runTextCoverageCompare(alloc: std.mem.Allocator) !void {
        try frame_loop.commitRender();
    }

    _ = try ctx.vkd.deviceWaitIdle(ctx.device);
    vk_sync.waitIdleForShutdown(ctx.vkd, ctx.device);
}

fn runDrawSmokeTest(alloc: std.mem.Allocator) !void {
@@ -2631,7 +2631,7 @@ fn runDrawSmokeTest(alloc: std.mem.Allocator) !void {
        const baseline_coverage = renderer.coverageVariantParams(.baseline);
        ctx.drawCells(1, .{ cell_w, cell_h }, .{ 0.0, 0.0, 0.0, 1.0 }, baseline_coverage, null) catch |err| switch (err) {
            error.OutOfDateKHR => {
                _ = try ctx.vkd.deviceWaitIdle(ctx.device);
                vk_sync.waitIdleForShutdown(ctx.vkd, ctx.device);
                try ctx.recreateSwapchain(window.width, window.height);
                frame_loop.forceArm();
                continue;
@@ -2641,7 +2641,7 @@ fn runDrawSmokeTest(alloc: std.mem.Allocator) !void {
        try frame_loop.commitRender();
    }

    _ = try ctx.vkd.deviceWaitIdle(ctx.device);
    vk_sync.waitIdleForShutdown(ctx.vkd, ctx.device);
    std.debug.print("done\n", .{});
}

@@ -3076,7 +3076,7 @@ fn runRenderSmokeTest(alloc: std.mem.Allocator) !void {
        const t: f32 = @as(f32, @floatFromInt(i)) / 60.0;
        try ctx.drawClear(.{ t, 0.5, 1.0 - t, 1.0 });
    }
    _ = try ctx.vkd.deviceWaitIdle(ctx.device);
    vk_sync.waitIdleForShutdown(ctx.vkd, ctx.device);
    std.debug.print("done\n", .{});
}

diff --git a/src/renderer.zig b/src/renderer.zig
index 5c15fc4..912fb33 100644
--- a/src/renderer.zig
+++ b/src/renderer.zig
@@ -1134,7 +1134,7 @@ pub const Context = struct {

    pub fn deinit(self: *Context) void {
        // Wait for device to be idle before destroying anything
        _ = self.vkd.deviceWaitIdle(self.device) catch {};
        vk_sync.waitIdleForShutdown(self.vkd, self.device);

        // Atlas + buffers (in reverse order of creation)
        self.vkd.destroySampler(self.device, self.atlas_sampler, null);
@@ -1260,7 +1260,7 @@ pub const Context = struct {
            self.vkd.freeMemory(self.device, replacement.memory, null);
        }

        _ = try self.vkd.deviceWaitIdle(self.device);
        vk_sync.waitIdleForShutdown(self.vkd, self.device);
        self.vkd.destroyBuffer(self.device, self.instance_buffer, null);
        self.vkd.freeMemory(self.device, self.instance_memory, null);
        self.instance_buffer = replacement.buffer;
@@ -1464,7 +1464,7 @@ pub const Context = struct {
            .command_buffer_count = 1,
            .p_command_buffers = @ptrCast(&cb),
        }), .null_handle);
        try self.vkd.queueWaitIdle(self.graphics_queue);
        vk_sync.waitIdleForShutdown(self.vkd, self.device);
    }

    /// Upload a horizontal band of the atlas (y_start..y_end) to the GPU.