diff --git a/src/example.zig b/src/example.zig index 82be810..519c337 100644 --- a/src/example.zig +++ b/src/example.zig @@ -1,3 +1,5 @@ +/// This is a fully self contained example. +/// It set a simple f16 Vector and do a add operation on it const std = @import("std"); const GpuDevice = @import("GpuDevice.zig"); const GpuArena = @import("GpuArena.zig"); @@ -8,17 +10,20 @@ const GpuProcess = @import("GpuProcess.zig"); pub fn main(init: std.process.Init) !void { const allocator = init.gpa; + // Open GPU Device const device = try GpuDevice.init(.{}); defer device.deinit(); + // Create a GPU Arena to hold GPU memory var grena = GpuArena.init(allocator, device); defer grena.deinit(); - const gloc = grena.gpuAllocator(); + // Create a GPU process that load the pipeline/shader const add = try GpuProcess.init(device, @embedFile("shaders/add.wgsl")); defer add.deinit(); + // Allocate CPU memory const data_a = try allocator.alloc(f16, 16); defer allocator.free(data_a); const data_b = try allocator.alloc(f16, 16); @@ -29,16 +34,18 @@ pub fn main(init: std.process.Init) !void { data_b[i] = @floatFromInt(16 - 1 - i); } - const a = try Vec.initLoad(gloc, data_a); - defer a.deinit(); - const b = try Vec.initLoad(gloc, data_b); - defer b.deinit(); + // Allocate GPU memory (Vec.deinit isn't necessary because grena will do it when deinit) + const a = try Vec.initZero(gloc, 16); + const b = try Vec.initZero(gloc, 16); + // Load CPU -> GPU + try a.load(data_a); + try b.load(data_b); + + // Run GPU Pipeline const sum = try a.run(gloc, b, add); - // Don't need `sum.deinit()` because grena will deallocate everything when deinit - - std.debug.print("Bytes used: {d} (3 * {d})\n", .{ grena.allocated_vram_bytes, a.byteSize() }); + // Read GPU -> CPU const out = try sum.read(allocator); defer allocator.free(out); @@ -50,7 +57,6 @@ const Vec = struct { buf: GpuBuffer, len: usize, - // Changed: gloc is passed by value (const) pub fn initZero(gloc: GpuAllocator, len: usize) !Vec { return .{ .buf = try GpuBuffer.init( @@ -62,27 +68,18 @@ const Vec = struct { }; } - // Changed: gloc is passed by value - pub fn initLoad(gloc: GpuAllocator, data: []const f16) !Vec { - var self = try initZero(gloc, data.len); - try self.load(data); // Direct access via the interface copy - return self; - } - pub fn deinit(self: Vec) void { self.buf.deinit(); } - /// CPU to GPU. pub fn load(self: Vec, data: []const f16) !void { try self.buf.load(f16, data); } - pub fn byteSize(self: Vec) u64 { - return @as(u64, self.len) * @sizeOf(f16); + pub fn read(self: Vec, alloc: std.mem.Allocator) ![]f16 { + return self.buf.read(alloc, f16); } - // Changed: gloc is passed by value instead of *GpuAllocator pub fn run(self: Vec, gloc: GpuAllocator, other: Vec, process: GpuProcess) !Vec { std.debug.assert(self.len == other.len); @@ -92,9 +89,4 @@ const Vec = struct { try process.run(gloc, f16, self.buf, other.buf, result.buf); return result; } - - // Changed: gloc is passed by value instead of *GpuAllocator - pub fn read(self: Vec, alloc: std.mem.Allocator) ![]f16 { - return self.buf.read(alloc, f16); - } };