//! A native webgpu.h implementation of the gpu.Interface const c = @import("c.zig").c; const Interface = @import("Interface.zig"); const Surface = @import("Surface.zig"); const NativeInstance = @This(); /// The WGPUInstance that is wrapped by this native instance. instance: c.WGPUInstance, /// Wraps a native WGPUInstance to provide an implementation of the gpu.Interface. pub fn wrap(instance: *anyopaque) NativeInstance { return .{ .instance = @ptrCast(c.WGPUInstance, instance) }; } const interface_vtable = Interface.VTable{ .reference = (struct { pub fn reference(ptr: *anyopaque) void { const native = @ptrCast(*NativeInstance, @alignCast(@alignOf(*NativeInstance), ptr)); c.wgpuInstanceReference(native.instance); } }).reference, .release = (struct { pub fn release(ptr: *anyopaque) void { const native = @ptrCast(*NativeInstance, @alignCast(@alignOf(*NativeInstance), ptr)); c.wgpuInstanceRelease(native.instance); } }).release, }; /// Returns the gpu.Interface for interacting with this native instance. pub fn interface(native: *NativeInstance) Interface { return .{ .ptr = native, .vtable = &interface_vtable, }; // TODO: implement Device interface // TODO: implement Adapter interface: // typedef struct WGPUAdapterImpl* WGPUAdapter; // // Methods of Adapter // WGPU_EXPORT size_t wgpuAdapterEnumerateFeatures(WGPUAdapter adapter, WGPUFeatureName * features); // WGPU_EXPORT bool wgpuAdapterHasFeature(WGPUAdapter adapter, WGPUFeatureName feature); // WGPU_EXPORT bool wgpuAdapterGetLimits(WGPUAdapter adapter, WGPUSupportedLimits * limits); // WGPU_EXPORT void wgpuAdapterGetProperties(WGPUAdapter adapter, WGPUAdapterProperties * properties); } pub fn createSurface(native: *const NativeInstance, descriptor: *const Surface.Descriptor) Surface { const surface = switch (descriptor.*) { .metal_layer => |src| blk: { var desc: c.WGPUSurfaceDescriptorFromMetalLayer = undefined; desc.chain.next = null; desc.chain.sType = c.WGPUSType_SurfaceDescriptorFromMetalLayer; desc.layer = src.layer; break :blk c.wgpuInstanceCreateSurface(native.instance, &c.WGPUSurfaceDescriptor{ .nextInChain = @ptrCast(*c.WGPUChainedStruct, &desc), .label = if (src.label) |l| @ptrCast([*c]const u8, l) else null, }); }, .windows_hwnd => |src| blk: { var desc: c.WGPUSurfaceDescriptorFromWindowsHWND = undefined; desc.chain.next = null; desc.chain.sType = c.WGPUSType_SurfaceDescriptorFromWindowsHWND; desc.hinstance = src.hinstance; desc.hwnd = src.hwnd; break :blk c.wgpuInstanceCreateSurface(native.instance, &c.WGPUSurfaceDescriptor{ .nextInChain = @ptrCast(*c.WGPUChainedStruct, &desc), .label = if (src.label) |l| @ptrCast([*c]const u8, l) else null, }); }, .windows_core_window => |src| blk: { var desc: c.WGPUSurfaceDescriptorFromWindowsCoreWindow = undefined; desc.chain.next = null; desc.chain.sType = c.WGPUSType_SurfaceDescriptorFromWindowsCoreWindow; desc.coreWindow = src.core_window; break :blk c.wgpuInstanceCreateSurface(native.instance, &c.WGPUSurfaceDescriptor{ .nextInChain = @ptrCast(*c.WGPUChainedStruct, &desc), .label = if (src.label) |l| @ptrCast([*c]const u8, l) else null, }); }, .windows_swap_chain_panel => |src| blk: { var desc: c.WGPUSurfaceDescriptorFromWindowsSwapChainPanel = undefined; desc.chain.next = null; desc.chain.sType = c.WGPUSType_SurfaceDescriptorFromWindowsSwapChainPanel; desc.swapChainPanel = src.swap_chain_panel; break :blk c.wgpuInstanceCreateSurface(native.instance, &c.WGPUSurfaceDescriptor{ .nextInChain = @ptrCast(*c.WGPUChainedStruct, &desc), .label = if (src.label) |l| @ptrCast([*c]const u8, l) else null, }); }, .xlib_window => |src| blk: { var desc: c.WGPUSurfaceDescriptorFromXlibWindow = undefined; desc.chain.next = null; desc.chain.sType = c.WGPUSType_SurfaceDescriptorFromXlibWindow; desc.display = src.display; desc.window = src.window; break :blk c.wgpuInstanceCreateSurface(native.instance, &c.WGPUSurfaceDescriptor{ .nextInChain = @ptrCast(*c.WGPUChainedStruct, &desc), .label = if (src.label) |l| @ptrCast([*c]const u8, l) else null, }); }, .canvas_html_selector => |src| blk: { var desc: c.WGPUSurfaceDescriptorFromCanvasHTMLSelector = undefined; desc.chain.next = null; desc.chain.sType = c.WGPUSType_SurfaceDescriptorFromCanvasHTMLSelector; desc.selector = @ptrCast([*c]const u8, src.selector); break :blk c.wgpuInstanceCreateSurface(native.instance, &c.WGPUSurfaceDescriptor{ .nextInChain = @ptrCast(*c.WGPUChainedStruct, &desc), .label = if (src.label) |l| @ptrCast([*c]const u8, l) else null, }); }, }; return Surface{ .ptr = surface.?, .vtable = &surface_vtable, }; } const surface_vtable = Surface.VTable{ .reference = (struct { pub fn reference(ptr: *anyopaque) void { c.wgpuSurfaceReference(@ptrCast(c.WGPUSurface, ptr)); } }).reference, .release = (struct { pub fn release(ptr: *anyopaque) void { c.wgpuSurfaceRelease(@ptrCast(c.WGPUSurface, ptr)); } }).release, }; test "syntax" { _ = wrap; _ = interface; _ = createSurface; }