From 9fae88755581ea085c3ea776cc1026a519ecdad7 Mon Sep 17 00:00:00 2001 From: Stephen Gutekanst Date: Tue, 15 Mar 2022 20:39:38 -0700 Subject: [PATCH] gpu: implement Device.createRenderPipelineAsync Signed-off-by: Stephen Gutekanst --- gpu/src/Device.zig | 18 +++++++++++-- gpu/src/NativeInstance.zig | 35 +++++++++++++++++++++++++ gpu/src/RenderPipeline.zig | 52 ++++++++++++++++++++++++++++++++++++++ gpu/src/TODO | 1 - 4 files changed, 103 insertions(+), 3 deletions(-) diff --git a/gpu/src/Device.zig b/gpu/src/Device.zig index 18124019..3aafefd0 100644 --- a/gpu/src/Device.zig +++ b/gpu/src/Device.zig @@ -41,8 +41,11 @@ pub const VTable = struct { // WGPU_EXPORT WGPUQuerySet wgpuDeviceCreateQuerySet(WGPUDevice device, WGPUQuerySetDescriptor const * descriptor); // WGPU_EXPORT WGPURenderBundleEncoder wgpuDeviceCreateRenderBundleEncoder(WGPUDevice device, WGPURenderBundleEncoderDescriptor const * descriptor); createRenderPipeline: fn (ptr: *anyopaque, descriptor: *const RenderPipeline.Descriptor) RenderPipeline, - // TODO: callback - // WGPU_EXPORT void wgpuDeviceCreateRenderPipelineAsync(WGPUDevice device, WGPURenderPipelineDescriptor const * descriptor, WGPUCreateRenderPipelineAsyncCallback callback, void * userdata); + createRenderPipelineAsync: fn ( + ptr: *anyopaque, + descriptor: *const RenderPipeline.Descriptor, + callback: *RenderPipeline.CreateCallback, + ) void, // WGPU_EXPORT WGPUSampler wgpuDeviceCreateSampler(WGPUDevice device, WGPUSamplerDescriptor const * descriptor); createShaderModule: fn (ptr: *anyopaque, descriptor: *const ShaderModule.Descriptor) ShaderModule, nativeCreateSwapChain: fn (ptr: *anyopaque, surface: ?Surface, descriptor: *const SwapChain.Descriptor) SwapChain, @@ -116,6 +119,14 @@ pub inline fn createRenderPipeline(device: Device, descriptor: *const RenderPipe return device.vtable.createRenderPipeline(device.ptr, descriptor); } +pub inline fn createRenderPipelineAsync( + device: Device, + descriptor: *const RenderPipeline.Descriptor, + callback: *RenderPipeline.CreateCallback, +) void { + device.vtable.createRenderPipelineAsync(device.ptr, descriptor, callback); +} + pub const Descriptor = struct { label: ?[*:0]const u8 = null, required_features: ?[]Feature = null, @@ -136,7 +147,10 @@ test "syntax" { _ = nativeCreateSwapChain; _ = destroy; _ = createCommandEncoder; + _ = createComputePipeline; + _ = createComputePipelineAsync; _ = createRenderPipeline; + _ = createRenderPipelineAsync; _ = Descriptor; _ = LostReason; } diff --git a/gpu/src/NativeInstance.zig b/gpu/src/NativeInstance.zig index e3a05d9e..bebfedb1 100644 --- a/gpu/src/NativeInstance.zig +++ b/gpu/src/NativeInstance.zig @@ -436,6 +436,41 @@ const device_vtable = Device.VTable{ return wrapRenderPipeline(c.wgpuDeviceCreateRenderPipeline(@ptrCast(c.WGPUDevice, ptr), &desc)); } }).createRenderPipeline, + .createRenderPipelineAsync = (struct { + pub fn createRenderPipelineAsync( + ptr: *anyopaque, + descriptor: *const RenderPipeline.Descriptor, + callback: *RenderPipeline.CreateCallback, + ) void { + var tmp_depth_stencil: c.WGPUDepthStencilState = undefined; + var tmp_fragment_state: c.WGPUFragmentState = undefined; + const desc = convertRenderPipelineDescriptor(descriptor, &tmp_depth_stencil, &tmp_fragment_state); + + const cCallback = (struct { + pub fn cCallback( + status: c.WGPUCreatePipelineAsyncStatus, + pipeline: c.WGPURenderPipeline, + message: [*c]const u8, + userdata: ?*anyopaque, + ) callconv(.C) void { + const callback_info = @ptrCast(*RenderPipeline.CreateCallback, @alignCast(@alignOf(*RenderPipeline.CreateCallback), userdata)); + callback_info.type_erased_callback( + callback_info.type_erased_ctx, + @intToEnum(RenderPipeline.CreateStatus, status), + wrapRenderPipeline(pipeline), + std.mem.span(message), + ); + } + }).cCallback; + + c.wgpuDeviceCreateRenderPipelineAsync( + @ptrCast(c.WGPUDevice, ptr), + &desc, + cCallback, + callback, + ); + } + }).createRenderPipelineAsync, }; inline fn convertComputePipelineDescriptor(descriptor: *const ComputePipeline.Descriptor) c.WGPUComputePipelineDescriptor { diff --git a/gpu/src/RenderPipeline.zig b/gpu/src/RenderPipeline.zig index 556c2e4c..9b7297ea 100644 --- a/gpu/src/RenderPipeline.zig +++ b/gpu/src/RenderPipeline.zig @@ -42,9 +42,61 @@ pub const Descriptor = struct { fragment: *const FragmentState, }; +pub const CreateStatus = enum(u32) { + success = 0x00000000, + err = 0x00000001, + device_lost = 0x00000002, + device_destroyed = 0x00000003, + unknown = 0x00000004, +}; + +pub const CreateCallback = struct { + type_erased_ctx: *anyopaque, + type_erased_callback: fn ( + ctx: *anyopaque, + status: CreateStatus, + pipeline: RenderPipeline, + message: [:0]const u8, + ) callconv(.Inline) void, + + pub fn init( + comptime Context: type, + ctx: *Context, + comptime callback: fn ( + ctx: *Context, + status: CreateStatus, + pipeline: RenderPipeline, + message: [:0]const u8, + ) void, + ) CreateCallback { + const erased = (struct { + pub inline fn erased( + type_erased_ctx: *anyopaque, + status: CreateStatus, + pipeline: RenderPipeline, + message: [:0]const u8, + ) void { + callback( + @ptrCast(*Context, @alignCast(@alignOf(*Context), type_erased_ctx)), + status, + pipeline, + message, + ); + } + }).erased; + + return .{ + .type_erased_ctx = ctx, + .type_erased_callback = erased, + }; + } +}; + test "syntax" { _ = VTable; _ = reference; _ = release; _ = Descriptor; + _ = CreateStatus; + _ = CreateCallback; } diff --git a/gpu/src/TODO b/gpu/src/TODO index dc99514c..e3e6b2c4 100644 --- a/gpu/src/TODO +++ b/gpu/src/TODO @@ -46,7 +46,6 @@ typedef struct WGPUCopyTextureForBrowserOptions { -typedef void (*WGPUCreateRenderPipelineAsyncCallback)(WGPUCreatePipelineAsyncStatus status, WGPURenderPipeline pipeline, char const * message, void * userdata); typedef void (*WGPUDeviceLostCallback)(WGPUDeviceLostReason reason, char const * message, void * userdata); typedef void (*WGPUErrorCallback)(WGPUErrorType type, char const * message, void * userdata); typedef void (*WGPULoggingCallback)(WGPULoggingType type, char const * message, void * userdata);