mach/gpu/src/NativeInstance.zig
Stephen Gutekanst 3f19563354 gpu: implement Interface.reference, Interface.release
Signed-off-by: Stephen Gutekanst <stephen@hexops.com>
2022-03-19 00:51:48 -07:00

137 lines
5.8 KiB
Zig

//! 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;
}