a73x

94f2d7b5

vk_sync: fail closed on unknown acquire result + comments

a73x   2026-04-18 12:32

Fixes from code review of the prior vk_sync commit:
- acquireImageBounded returns error.VkAcquireTimeout on unknown
  VkResult values (fails closed instead of trusting image_index).
- Document benign TOCTOU in logVkTimeout rate-limit.
- Clarify why TimeoutKind.atlas exists (reserved for Task 3).

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

diff --git a/src/vk_sync.zig b/src/vk_sync.zig
index feea2a8..8be5c31 100644
--- a/src/vk_sync.zig
+++ b/src/vk_sync.zig
@@ -52,7 +52,10 @@ pub fn acquireImageBounded(
        .timeout, .not_ready => return error.VkAcquireTimeout,
        .suboptimal_khr => return error.OutOfDateKHR,
        .success => return acquire.image_index,
        else => return acquire.image_index, // unexpected but non-error; trust the image_index
        else => {
            std.log.warn("acquireImageBounded: unexpected VkResult {s}", .{@tagName(acquire.result)});
            return error.VkAcquireTimeout;
        },
    }
}

@@ -88,7 +91,11 @@ pub fn queueWaitIdleBounded(vkd: vk.DeviceWrapper, queue: vk.Queue, timeout_ns: 

// --- logging ---

const TimeoutKind = enum { fence, acquire, atlas };
const TimeoutKind = enum {
    fence, // waitFenceBounded timeouts
    acquire, // acquireImageBounded timeouts
    atlas, // uploadAtlasRegion fence timeouts (used by renderer.zig, Task 3)
};

var vk_timeout_count: std.atomic.Value(u64) = .init(0);
var last_log_ns: std.atomic.Value(i64) = .init(0);
@@ -100,6 +107,7 @@ pub fn logVkTimeout(src: std.builtin.SourceLocation, kind: TimeoutKind) void {
    const now: i64 = @truncate(std.time.nanoTimestamp());
    const last = last_log_ns.load(.monotonic);
    if (n == 1 or (now - last) > log_window_ns) {
        // Benign TOCTOU: two threads racing can fire twice in the same window.
        last_log_ns.store(now, .monotonic);
        std.log.warn(
            "vk timeout #{} ({s}) at {s}:{d} — driver may be wedged",