From 0be5cae3287440b8fd9ee7ff250600be94edc5d3 Mon Sep 17 00:00:00 2001 From: Stephen Gutekanst Date: Tue, 8 Mar 2022 11:50:21 -0700 Subject: [PATCH] gpu: implement Queue.on_submitted_work_done callback Signed-off-by: Stephen Gutekanst --- gpu/src/NativeInstance.zig | 26 ++++++++++++++++++++-- gpu/src/Queue.zig | 45 +++++++++++++++++++++++++------------- 2 files changed, 54 insertions(+), 17 deletions(-) diff --git a/gpu/src/NativeInstance.zig b/gpu/src/NativeInstance.zig index 6f4ee26c..c3190863 100644 --- a/gpu/src/NativeInstance.zig +++ b/gpu/src/NativeInstance.zig @@ -354,9 +354,31 @@ const queue_vtable = Queue.VTable{ } }).release, .submit = (struct { - pub fn submit(ptr: *anyopaque, command_count: u32, commands: *const CommandBuffer) void { + pub fn submit(queue: Queue, command_count: u32, commands: *const CommandBuffer) void { + const wgpu_queue = @ptrCast(c.WGPUQueue, queue.ptr); + + if (queue.on_submitted_work_done) |on_submitted_work_done| { + // Note: signalValue is not available in the web API, and it's usage is undocumented + // kainino says "It's basically reserved for future use, though it's been suggested + // to remove it instead" + const signal_value: u64 = 0; + + const callback = (struct { + pub fn callback(status: c.WGPUQueueWorkDoneStatus, userdata: ?*anyopaque) callconv(.C) void { + const _on_submitted_work_done = @ptrCast(*Queue.OnSubmittedWorkDone, @alignCast(@alignOf(*Queue.OnSubmittedWorkDone), userdata)); + _on_submitted_work_done.callback( + @intToEnum(Queue.WorkDoneStatus, status), + _on_submitted_work_done.userdata, + ); + } + }).callback; + + var mut_on_submitted_work_done = on_submitted_work_done; + c.wgpuQueueOnSubmittedWorkDone(wgpu_queue, signal_value, callback, &mut_on_submitted_work_done); + } + c.wgpuQueueSubmit( - @ptrCast(c.WGPUQueue, ptr), + wgpu_queue, command_count, @ptrCast(*c.WGPUCommandBuffer, @alignCast(@alignOf(*c.WGPUCommandBuffer), commands.ptr)), ); diff --git a/gpu/src/Queue.zig b/gpu/src/Queue.zig index bd058f46..19845c30 100644 --- a/gpu/src/Queue.zig +++ b/gpu/src/Queue.zig @@ -2,6 +2,8 @@ const CommandBuffer = @import("CommandBuffer.zig"); const Queue = @This(); +on_submitted_work_done: ?OnSubmittedWorkDone = null, + /// The type erased pointer to the Queue implementation /// Equal to c.WGPUQueue for NativeInstance. ptr: *anyopaque, @@ -12,11 +14,10 @@ pub const VTable = struct { release: fn (ptr: *anyopaque) void, // TODO: // copyTextureForBrowser: fn (ptr: *anyopaque, source: *const ImageCopyTexture, destination: *const ImageCopyTexture, copy_size: *const Extent3D, options: *const CopyTextureForBrowserOptions) void, - // WGPU_EXPORT void wgpuQueueOnSubmittedWorkDone(WGPUQueue queue, uint64_t signalValue, WGPUQueueWorkDoneCallback callback, void * userdata); - submit: fn (ptr: *anyopaque, command_count: u32, commands: *const CommandBuffer) void, + submit: fn (queue: Queue, command_count: u32, commands: *const CommandBuffer) void, // TODO: - // queueWriteBuffer: fn (ptr: *anyopaque, buffer: Buffer, buffer_offset: u64, data: *const anyopaque, size: usize); - // queueWriteTexture: fn (ptr: *anyopaque, destination: *const ImageCopyTexture, data: *const anyopaque, data_size: usize, data_layout: *const TextureDataLayout, write_size: *const Extent3D); + // writeBuffer: fn (ptr: *anyopaque, buffer: Buffer, buffer_offset: u64, data: *const anyopaque, size: usize); + // writeTexture: fn (ptr: *anyopaque, destination: *const ImageCopyTexture, data: *const anyopaque, data_size: usize, data_layout: *const TextureDataLayout, write_size: *const Extent3D); }; pub inline fn reference(queue: Queue) void { @@ -28,24 +29,38 @@ pub inline fn release(queue: Queue) void { } pub inline fn submit(queue: Queue, command_count: u32, commands: *const CommandBuffer) void { - queue.vtable.submit(queue.ptr, command_count, commands); + queue.vtable.submit(queue, command_count, commands); } -// TODO: -// typedef void (*WGPUQueueWorkDoneCallback)(WGPUQueueWorkDoneStatus status, void * userdata); +pub const OnSubmittedWorkDone = struct { + userdata: *anyopaque, + callback: fn (status: WorkDoneStatus, userdata: *anyopaque) void, -// TODO: -// typedef enum WGPUQueueWorkDoneStatus { -// WGPUQueueWorkDoneStatus_Success = 0x00000000, -// WGPUQueueWorkDoneStatus_Error = 0x00000001, -// WGPUQueueWorkDoneStatus_Unknown = 0x00000002, -// WGPUQueueWorkDoneStatus_DeviceLost = 0x00000003, -// WGPUQueueWorkDoneStatus_Force32 = 0x7FFFFFFF -// } WGPUQueueWorkDoneStatus; + fn init(comptime Context: type, userdata: *Context, comptime callback: fn (status: WorkDoneStatus, userdata: *Context) void) OnSubmittedWorkDone { + return .{ + .userdata = userdata, + .callback = (struct { + pub inline fn untyped(status: WorkDoneStatus, _userdata: *anyopaque) void { + callback(status, @ptrCast(*Context, @alignCast(@alignOf(*Context), _userdata))); + } + }).untyped, + }; + } +}; + +pub const WorkDoneStatus = enum(u32) { + Success = 0x00000000, + Error = 0x00000001, + Unknown = 0x00000002, + DeviceLost = 0x00000003, + Force32 = 0x7FFFFFFF, +}; test "syntax" { _ = VTable; _ = reference; _ = release; _ = submit; + _ = OnSubmittedWorkDone; + _ = WorkDoneStatus; }