GpuBuffer now hold its def and not values directly

This commit is contained in:
adrien 2026-05-22 00:30:29 +02:00
parent e03cb3f285
commit 4901dc654d
2 changed files with 15 additions and 17 deletions

View File

@ -4,11 +4,10 @@ const GpuAllocator = @import("GpuAllocator.zig");
const svOpt = @import("utils.zig").svOpt; const svOpt = @import("utils.zig").svOpt;
raw: c.WGPUBuffer, raw: c.WGPUBuffer,
size: u64,
usage: c.WGPUBufferUsage,
gloc: GpuAllocator, gloc: GpuAllocator,
def: GpuBufferDef,
const BufferUsage = enum(u64) { pub const GpuBufferUsage = enum(u64) {
None = 0x0000000000000000, None = 0x0000000000000000,
MapRead = 0x0000000000000001, MapRead = 0x0000000000000001,
MapWrite = 0x0000000000000002, MapWrite = 0x0000000000000002,
@ -22,10 +21,10 @@ const BufferUsage = enum(u64) {
QueryResolve = 0x0000000000000200, QueryResolve = 0x0000000000000200,
}; };
const GpuBufferDef = struct { pub const GpuBufferDef = struct {
label: ?[]const u8 = null, label: ?[]const u8 = null,
size: u64, size: u64,
usage: std.EnumSet(BufferUsage), usage: std.EnumSet(GpuBufferUsage),
}; };
pub fn init(gloc: GpuAllocator, def: GpuBufferDef) !@This() { pub fn init(gloc: GpuAllocator, def: GpuBufferDef) !@This() {
@ -43,8 +42,7 @@ pub fn init(gloc: GpuAllocator, def: GpuBufferDef) !@This() {
}); });
return .{ return .{
.raw = raw_handle, .raw = raw_handle,
.size = aligned_size, .def = def,
.usage = use,
.gloc = gloc, .gloc = gloc,
}; };
} }
@ -79,9 +77,9 @@ pub fn load(
) !void { ) !void {
const bytes = data.len * @sizeOf(T); const bytes = data.len * @sizeOf(T);
if (bytes == self.size) { if (bytes == self.def.size) {
// Aligned path: direct download // Aligned path: direct download
c.wgpuQueueWriteBuffer(self.gloc.device.queue, self.raw, 0, data.ptr, self.size); c.wgpuQueueWriteBuffer(self.gloc.device.queue, self.raw, 0, data.ptr, self.def.size);
} else { } else {
// Unaligned path: Split the write into an aligned chunk and a padded remainder // Unaligned path: Split the write into an aligned chunk and a padded remainder
// to support arbitrary lengths without any allocations or large stack arrays. // to support arbitrary lengths without any allocations or large stack arrays.
@ -100,17 +98,17 @@ pub fn load(
/// GPU to CPU /// GPU to CPU
pub fn read(self: @This(), alloc: std.mem.Allocator, T: type) ![]T { pub fn read(self: @This(), alloc: std.mem.Allocator, T: type) ![]T {
const out = try alloc.alloc(T, @divExact(self.size, @sizeOf(T))); const out = try alloc.alloc(T, @divExact(self.def.size, @sizeOf(T)));
const staging = try init(self.gloc, .{ const staging = try init(self.gloc, .{
.size = self.size, .size = self.def.size,
.usage = .initMany(&.{ .MapRead, .CopyDst }), .usage = .initMany(&.{ .MapRead, .CopyDst }),
.label = "staging_read_buffer", .label = "staging_read_buffer",
}); });
defer staging.deinit(); defer staging.deinit();
const enc = c.wgpuDeviceCreateCommandEncoder(self.gloc.device.device, null) orelse return error.Encoder; const enc = c.wgpuDeviceCreateCommandEncoder(self.gloc.device.device, null) orelse return error.Encoder;
c.wgpuCommandEncoderCopyBufferToBuffer(enc, self.raw, 0, staging.raw, 0, self.size); c.wgpuCommandEncoderCopyBufferToBuffer(enc, self.raw, 0, staging.raw, 0, self.def.size);
const cmd = c.wgpuCommandEncoderFinish(enc, null); const cmd = c.wgpuCommandEncoderFinish(enc, null);
defer c.wgpuCommandEncoderRelease(enc); defer c.wgpuCommandEncoderRelease(enc);
defer c.wgpuCommandBufferRelease(cmd); defer c.wgpuCommandBufferRelease(cmd);
@ -120,13 +118,13 @@ pub fn read(self: @This(), alloc: std.mem.Allocator, T: type) ![]T {
staging.mapAsync( staging.mapAsync(
c.WGPUMapMode_Read, c.WGPUMapMode_Read,
0, 0,
self.size, self.def.size,
.{ .callback = onMapped, .userdata1 = &mapped }, .{ .callback = onMapped, .userdata1 = &mapped },
); );
while (!mapped) self.gloc.device.poll(); while (!mapped) self.gloc.device.poll();
const ptr: [*]const T = @ptrCast(@alignCast( const ptr: [*]const T = @ptrCast(@alignCast(
staging.getConstMappedRange(0, self.size), staging.getConstMappedRange(0, self.def.size),
)); ));
@memcpy(out[0..out.len], ptr[0..out.len]); @memcpy(out[0..out.len], ptr[0..out.len]);
staging.unmap(); staging.unmap();

View File

@ -74,7 +74,7 @@ pub fn run(
const buf = @field(args, field.name); const buf = @field(args, field.name);
const el_size = self.def.bindings[i].element_size; const el_size = self.def.bindings[i].element_size;
if (el_size > 0) { if (el_size > 0) {
elements_count = @intCast(buf.size / el_size); elements_count = @intCast(buf.def.size / el_size);
} }
} }
} }
@ -85,7 +85,7 @@ pub fn run(
const el_size = self.def.bindings[i].element_size; const el_size = self.def.bindings[i].element_size;
if (el_size > 0) { if (el_size > 0) {
const expected_min_bytes = @as(u64, elements_count) * el_size; const expected_min_bytes = @as(u64, elements_count) * el_size;
if (buf.size < expected_min_bytes) if (buf.def.size < expected_min_bytes)
return error.BufferTooSmall; return error.BufferTooSmall;
} }
} }
@ -103,7 +103,7 @@ pub fn run(
.binding = @intCast(i), .binding = @intCast(i),
.buffer = buf.raw, .buffer = buf.raw,
.offset = 0, .offset = 0,
.size = buf.size, // Size exposes the fully allocated length .size = buf.def.size, // Size exposes the fully allocated length
}; };
entry_count += 1; entry_count += 1;
} }