diff --git a/gpu/TODO-webgpu.h b/gpu/TODO-webgpu.h index c378f283..a8364209 100644 --- a/gpu/TODO-webgpu.h +++ b/gpu/TODO-webgpu.h @@ -10,7 +10,6 @@ typedef void (*WGPUQueueWorkDoneCallback)(WGPUQueueWorkDoneStatus status, void * typedef void (*WGPURequestAdapterCallback)(WGPURequestAdapterStatus status, WGPUAdapter adapter, char const * message, void * userdata); typedef void (*WGPURequestDeviceCallback)(WGPURequestDeviceStatus status, WGPUDevice device, char const * message, void * userdata); -WGPU_EXPORT WGPUInstance wgpuCreateInstance(WGPUInstanceDescriptor const * descriptor); WGPU_EXPORT WGPUProc wgpuGetProcAddress(WGPUDevice device, char const * procName); // Methods of Adapter diff --git a/gpu/src/interface.zig b/gpu/src/interface.zig new file mode 100644 index 00000000..fbdf8544 --- /dev/null +++ b/gpu/src/interface.zig @@ -0,0 +1,36 @@ +const Instance = @import("instance.zig").Instance; + +/// Verifies that a gpu.Interface implementation exposes the expected function declarations. +pub fn Interface(comptime Impl: type) type { + assertDecl(Impl, "createInstance", fn (descriptor: *const Instance.Descriptor) callconv(.Inline) Instance); + return Impl; +} + +fn assertDecl(comptime Impl: anytype, comptime name: []const u8, comptime T: type) void { + if (!@hasDecl(Impl, name)) @compileError("gpu.Interface missing declaration: " ++ @typeName(T)); + const Decl = @TypeOf(@field(Impl, name)); + if (Decl != T) @compileError("gpu.Interface field '" ++ name ++ "'\n\texpected type: " ++ @typeName(T) ++ "\n\t found type: " ++ @typeName(Decl)); +} + +/// Exports C ABI function declarations for the given gpu.Interface implementation. +pub fn Export(comptime Impl: type) type { + _ = Interface(Impl); // verify implementation is a valid interface + return struct { + // WGPU_EXPORT WGPUInstance wgpuCreateInstance(WGPUInstanceDescriptor const * descriptor); + export fn wgpuCreateInstance(descriptor: *const Instance.Descriptor) Instance { + return Impl.createInstance(descriptor); + } + }; +} + +/// A no-operation gpu.Interface implementation. +pub const NullInterface = Interface(struct { + pub inline fn createInstance(descriptor: *const Instance.Descriptor) Instance { + _ = descriptor; + return Instance.none; + } +}); + +test "null" { + _ = Export(NullInterface); +} diff --git a/gpu/src/main.zig b/gpu/src/main.zig index 0bf5de64..35ed0350 100644 --- a/gpu/src/main.zig +++ b/gpu/src/main.zig @@ -46,6 +46,10 @@ pub const RenderPassTimestampLocation = @import("types.zig").RenderPassTimestamp pub const PowerPreference = @import("types.zig").PowerPreference; pub const RenderPassColorAttachment = @import("types.zig").RenderPassColorAttachment; +pub const Interface = @import("interface.zig").Interface; +pub const Export = @import("interface.zig").Export; +pub const NullInterface = @import("interface.zig").NullInterface; + pub const ComputePassTimestampWrite = extern struct { query_set: QuerySet, query_index: u32,