a73x

1b76e08f

Test partial upload API contract

a73x   2026-04-08 19:40

Commit message
Test partial upload API contract

src/renderer.zig
Old New
@@ -335,6 +335,13 @@ const InstanceRangeWrite = struct {
335 byte_len: vk.DeviceSize, 335 byte_len: vk.DeviceSize,
336 }; 336 };
337 337
338 const InstanceRangeUploadAction = enum {
339 no_op,
340 partial,
341 full,
342 invalid_range,
343 };
344
338 fn planInstanceUpload(req: InstanceUploadRequest) InstanceUploadDecision { 345 fn planInstanceUpload(req: InstanceUploadRequest) InstanceUploadDecision {
339 const needed_capacity = std.math.add(u32, req.offset_instances, req.write_len) catch { 346 const needed_capacity = std.math.add(u32, req.offset_instances, req.write_len) catch {
340 return .{ 347 return .{
@@ -355,6 +362,24 @@ fn planInstanceRangeWrite(offset_instances: u32, len_instances: u32) InstanceRan
355 }; 362 };
356 } 363 }
357 364
365 fn planUploadInstanceRangeAction(
366 current_capacity: u32,
367 offset_instances: u32,
368 len_instances: u32,
369 ) InstanceRangeUploadAction {
370 if (len_instances == 0) return .no_op;
371
372 return switch (planInstanceUpload(.{
373 .current_capacity = current_capacity,
374 .offset_instances = offset_instances,
375 .write_len = len_instances,
376 }).upload_mode) {
377 .partial => .partial,
378 .full => .full,
379 .invalid_range => .invalid_range,
380 };
381 }
382
358 fn writeInstanceRange( 383 fn writeInstanceRange(
359 target: []Instance, 384 target: []Instance,
360 offset_instances: u32, 385 offset_instances: u32,
@@ -1265,16 +1290,15 @@ pub const Context = struct {
1265 offset_instances: u32, 1290 offset_instances: u32,
1266 instances: []const Instance, 1291 instances: []const Instance,
1267 ) !bool { 1292 ) !bool {
1268 if (instances.len == 0) return false; 1293 const action = planUploadInstanceRangeAction(
1269 1294 self.instance_capacity,
1270 const decision = planInstanceUpload(.{ 1295 offset_instances,
1271 .current_capacity = self.instance_capacity, 1296 std.math.cast(u32, instances.len) orelse return error.InvalidInstanceRange,
1272 .offset_instances = offset_instances, 1297 );
1273 .write_len = std.math.cast(u32, instances.len) orelse return error.InvalidInstanceRange, 1298 switch (action) {
1274 }); 1299 .no_op => return false,
1275 switch (decision.upload_mode) {
1276 .invalid_range => return error.InvalidInstanceRange,
1277 .full => return true, 1300 .full => return true,
1301 .invalid_range => return error.InvalidInstanceRange,
1278 .partial => {}, 1302 .partial => {},
1279 } 1303 }
1280 1304
@@ -1575,3 +1599,23 @@ test "writeInstanceRange rejects overflowing ranges" {
1575 writeInstanceRange(target[0..], std.math.maxInt(u32), replacement[0..]), 1599 writeInstanceRange(target[0..], std.math.maxInt(u32), replacement[0..]),
1576 ); 1600 );
1577 } 1601 }
1602
1603 test "uploadInstanceRange contract treats zero-length writes as a no-op" {
1604 const action = planUploadInstanceRangeAction(4, 99, 0);
1605 try std.testing.expectEqual(InstanceRangeUploadAction.no_op, action);
1606 }
1607
1608 test "uploadInstanceRange contract reports partial writes when capacity fits" {
1609 const action = planUploadInstanceRangeAction(8, 3, 2);
1610 try std.testing.expectEqual(InstanceRangeUploadAction.partial, action);
1611 }
1612
1613 test "uploadInstanceRange contract reports full-upload fallback on growth" {
1614 const action = planUploadInstanceRangeAction(4, 3, 2);
1615 try std.testing.expectEqual(InstanceRangeUploadAction.full, action);
1616 }
1617
1618 test "uploadInstanceRange contract reports invalid ranges explicitly" {
1619 const action = planUploadInstanceRangeAction(std.math.maxInt(u32), std.math.maxInt(u32), 1);
1620 try std.testing.expectEqual(InstanceRangeUploadAction.invalid_range, action);
1621 }