* Fixed ErrorCallback.init() alignment * Fixed callbacks alignments * Fixed more of the callback alignment problems * Added checks for void Context in callback
121 lines
3.5 KiB
Zig
121 lines
3.5 KiB
Zig
//! A standard interface to a WebGPU implementation.
|
|
//!
|
|
//! Like std.mem.Allocator, but representing a WebGPU implementation.
|
|
const std = @import("std");
|
|
|
|
const Surface = @import("Surface.zig");
|
|
const Adapter = @import("Adapter.zig");
|
|
const PowerPreference = @import("enums.zig").PowerPreference;
|
|
|
|
const Interface = @This();
|
|
|
|
/// The type erased pointer to the Interface implementation
|
|
ptr: *anyopaque,
|
|
vtable: *const VTable,
|
|
|
|
pub const VTable = struct {
|
|
reference: fn (ptr: *anyopaque) void,
|
|
release: fn (ptr: *anyopaque) void,
|
|
requestAdapter: fn requestAdapter(
|
|
ptr: *anyopaque,
|
|
options: *const RequestAdapterOptions,
|
|
callback: *RequestAdapterCallback,
|
|
) void,
|
|
};
|
|
|
|
pub inline fn reference(interface: Interface) void {
|
|
interface.vtable.reference(interface.ptr);
|
|
}
|
|
|
|
pub inline fn release(interface: Interface) void {
|
|
interface.vtable.release(interface.ptr);
|
|
}
|
|
|
|
pub const RequestAdapterOptions = struct {
|
|
power_preference: PowerPreference,
|
|
force_fallback_adapter: bool = false,
|
|
|
|
/// Only respected by native WebGPU implementations.
|
|
compatible_surface: ?Surface = null,
|
|
};
|
|
|
|
pub const RequestAdapterErrorCode = error{
|
|
Unavailable,
|
|
Error,
|
|
Unknown,
|
|
};
|
|
|
|
pub const RequestAdapterError = struct {
|
|
message: []const u8,
|
|
code: RequestAdapterErrorCode,
|
|
};
|
|
|
|
pub const RequestAdapterResponseTag = enum {
|
|
adapter,
|
|
err,
|
|
};
|
|
|
|
pub const RequestAdapterResponse = union(RequestAdapterResponseTag) {
|
|
adapter: Adapter,
|
|
err: RequestAdapterError,
|
|
};
|
|
|
|
pub fn requestAdapter(
|
|
interface: Interface,
|
|
options: *const RequestAdapterOptions,
|
|
callback: *RequestAdapterCallback,
|
|
) void {
|
|
interface.vtable.requestAdapter(interface.ptr, options, callback);
|
|
}
|
|
|
|
pub const RequestAdapterCallback = struct {
|
|
type_erased_ctx: *anyopaque,
|
|
type_erased_callback: fn (ctx: *anyopaque, response: RequestAdapterResponse) callconv(.Inline) void,
|
|
|
|
pub fn init(
|
|
comptime Context: type,
|
|
ctx: Context,
|
|
comptime callback: fn (ctx: Context, response: RequestAdapterResponse) void,
|
|
) RequestAdapterCallback {
|
|
const erased = (struct {
|
|
pub inline fn erased(type_erased_ctx: *anyopaque, response: RequestAdapterResponse) void {
|
|
callback(if (Context == void) {} else @ptrCast(Context, @alignCast(std.meta.alignment(Context), type_erased_ctx)), response);
|
|
}
|
|
}).erased;
|
|
|
|
return .{
|
|
.type_erased_ctx = if (Context == void) undefined else ctx,
|
|
.type_erased_callback = erased,
|
|
};
|
|
}
|
|
};
|
|
|
|
/// A helper which invokes requestAdapter and blocks until the adapter is recieved.
|
|
pub fn waitForAdapter(interface: Interface, options: *const RequestAdapterOptions) RequestAdapterResponse {
|
|
var response: RequestAdapterResponse = undefined;
|
|
var callback = RequestAdapterCallback.init(*RequestAdapterResponse, &response, (struct {
|
|
pub fn callback(ctx: *RequestAdapterResponse, callback_response: RequestAdapterResponse) void {
|
|
ctx.* = callback_response;
|
|
}
|
|
}).callback);
|
|
|
|
interface.requestAdapter(options, &callback);
|
|
|
|
// TODO: FUTURE: Once crbug.com/dawn/1122 is fixed, we should process events here otherwise our
|
|
// callback would not be invoked:
|
|
//c.wgpuInstanceProcessEvents(interface.instance)
|
|
|
|
return response;
|
|
}
|
|
|
|
test {
|
|
_ = VTable;
|
|
_ = reference;
|
|
_ = release;
|
|
_ = RequestAdapterOptions;
|
|
_ = RequestAdapterErrorCode;
|
|
_ = RequestAdapterError;
|
|
_ = RequestAdapterResponse;
|
|
_ = requestAdapter;
|
|
_ = waitForAdapter;
|
|
}
|