a73x

a49da033

Add instance upload planning helpers

a73x   2026-04-08 18:44


diff --git a/src/renderer.zig b/src/renderer.zig
index 21603db..864b195 100644
--- a/src/renderer.zig
+++ b/src/renderer.zig
@@ -313,6 +313,28 @@ fn nextInstanceCapacity(current: u32, needed: u32) u32 {
    return capacity;
}

const InstanceUploadRequest = struct {
    current_capacity: u32,
    offset_instances: u32,
    write_len: u32,
};

const InstanceUploadDecision = struct {
    needed_capacity: u32,
    needs_growth: bool,
    force_full_upload: bool,
};

fn planInstanceUpload(req: InstanceUploadRequest) InstanceUploadDecision {
    const needed_capacity = std.math.add(u32, req.offset_instances, req.write_len) catch std.math.maxInt(u32);
    const needs_growth = needed_capacity > req.current_capacity;
    return .{
        .needed_capacity = needed_capacity,
        .needs_growth = needs_growth,
        .force_full_upload = needs_growth,
    };
}

fn swapchainNeedsRebuild(result: vk.Result) bool {
    return result == .suboptimal_khr;
}
@@ -1345,3 +1367,25 @@ test "swapchainNeedsRebuild flags suboptimal result" {
    try std.testing.expect(swapchainNeedsRebuild(.suboptimal_khr));
    try std.testing.expect(!swapchainNeedsRebuild(.success));
}

test "range upload falls back to full upload when capacity must grow" {
    const decision = planInstanceUpload(.{
        .current_capacity = 8,
        .offset_instances = 6,
        .write_len = 4,
    });

    try std.testing.expect(decision.needs_growth);
    try std.testing.expect(decision.force_full_upload);
}

test "range upload stays partial when capacity is sufficient" {
    const decision = planInstanceUpload(.{
        .current_capacity = 16,
        .offset_instances = 4,
        .write_len = 3,
    });

    try std.testing.expect(!decision.needs_growth);
    try std.testing.expect(!decision.force_full_upload);
}