gpu: make requestAdapter callback-based, add waitForAdapter helper
Same rationale as 2c3e13ff4b90886d7f03adb3103abc9dee70b407 Signed-off-by: Stephen Gutekanst <stephen@hexops.com>
This commit is contained in:
parent
aab99b5474
commit
356e4102cd
5 changed files with 71 additions and 40 deletions
|
|
@ -73,7 +73,7 @@ pub fn setup(allocator: std.mem.Allocator) !Setup {
|
||||||
try discoverAdapters(instance, window, backend_type);
|
try discoverAdapters(instance, window, backend_type);
|
||||||
|
|
||||||
// Request an adapter.
|
// Request an adapter.
|
||||||
const backend_adapter = switch (nosuspend gpu_interface.requestAdapter(&.{
|
const backend_adapter = switch (gpu_interface.waitForAdapter(&.{
|
||||||
.power_preference = .high_performance,
|
.power_preference = .high_performance,
|
||||||
})) {
|
})) {
|
||||||
.adapter => |v| v,
|
.adapter => |v| v,
|
||||||
|
|
|
||||||
|
|
@ -204,4 +204,5 @@ test "syntax" {
|
||||||
_ = RequestDeviceResponse;
|
_ = RequestDeviceResponse;
|
||||||
_ = RequestDeviceCallback;
|
_ = RequestDeviceCallback;
|
||||||
_ = requestDevice;
|
_ = requestDevice;
|
||||||
|
_ = waitForDevice;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,13 +13,14 @@ const Interface = @This();
|
||||||
ptr: *anyopaque,
|
ptr: *anyopaque,
|
||||||
vtable: *const VTable,
|
vtable: *const VTable,
|
||||||
|
|
||||||
// The @frameSize(func) of the implementations requestAdapter async function
|
|
||||||
request_adapter_frame_size: usize,
|
|
||||||
|
|
||||||
pub const VTable = struct {
|
pub const VTable = struct {
|
||||||
reference: fn (ptr: *anyopaque) void,
|
reference: fn (ptr: *anyopaque) void,
|
||||||
release: fn (ptr: *anyopaque) void,
|
release: fn (ptr: *anyopaque) void,
|
||||||
requestAdapter: fn requestAdapter(ptr: *anyopaque, options: *const RequestAdapterOptions) callconv(.Async) RequestAdapterResponse,
|
requestAdapter: fn requestAdapter(
|
||||||
|
ptr: *anyopaque,
|
||||||
|
options: *const RequestAdapterOptions,
|
||||||
|
callback: *RequestAdapterCallback,
|
||||||
|
) void,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub inline fn reference(interface: Interface) void {
|
pub inline fn reference(interface: Interface) void {
|
||||||
|
|
@ -59,24 +60,53 @@ pub const RequestAdapterResponse = union(RequestAdapterResponseTag) {
|
||||||
err: RequestAdapterError,
|
err: RequestAdapterError,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn requestAdapter(interface: Interface, options: *const RequestAdapterOptions) callconv(.Async) RequestAdapterResponse {
|
pub fn requestAdapter(
|
||||||
var frame_buffer = std.heap.page_allocator.allocAdvanced(
|
interface: Interface,
|
||||||
u8,
|
options: *const RequestAdapterOptions,
|
||||||
16,
|
callback: *RequestAdapterCallback,
|
||||||
interface.request_adapter_frame_size,
|
) void {
|
||||||
std.mem.Allocator.Exact.at_least,
|
interface.vtable.requestAdapter(interface.ptr, options, callback);
|
||||||
) catch {
|
}
|
||||||
return .{ .err = .{
|
|
||||||
.message = "Out of memory",
|
|
||||||
.code = RequestAdapterErrorCode.Error,
|
|
||||||
} };
|
|
||||||
};
|
|
||||||
defer std.heap.page_allocator.free(frame_buffer);
|
|
||||||
|
|
||||||
var result: RequestAdapterResponse = undefined;
|
pub const RequestAdapterCallback = struct {
|
||||||
const f = @asyncCall(frame_buffer, &result, interface.vtable.requestAdapter, .{ interface.ptr, options });
|
type_erased_ctx: *anyopaque,
|
||||||
resume f;
|
type_erased_callback: fn (ctx: *anyopaque, response: RequestAdapterResponse) callconv(.Inline) void,
|
||||||
return result;
|
|
||||||
|
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(@ptrCast(*Context, @alignCast(@alignOf(*Context), type_erased_ctx)), response);
|
||||||
|
}
|
||||||
|
}).erased;
|
||||||
|
|
||||||
|
return .{
|
||||||
|
.type_erased_ctx = 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 {
|
||||||
|
const Context = RequestAdapterResponse;
|
||||||
|
var response: Context = undefined;
|
||||||
|
var callback = RequestAdapterCallback.init(Context, &response, (struct {
|
||||||
|
pub fn callback(ctx: *Context, 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 "syntax" {
|
test "syntax" {
|
||||||
|
|
@ -88,4 +118,5 @@ test "syntax" {
|
||||||
_ = RequestAdapterError;
|
_ = RequestAdapterError;
|
||||||
_ = RequestAdapterResponse;
|
_ = RequestAdapterResponse;
|
||||||
_ = requestAdapter;
|
_ = requestAdapter;
|
||||||
|
_ = waitForAdapter;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,14 @@ const Interface = @import("Interface.zig");
|
||||||
const RequestAdapterOptions = Interface.RequestAdapterOptions;
|
const RequestAdapterOptions = Interface.RequestAdapterOptions;
|
||||||
const RequestAdapterErrorCode = Interface.RequestAdapterErrorCode;
|
const RequestAdapterErrorCode = Interface.RequestAdapterErrorCode;
|
||||||
const RequestAdapterError = Interface.RequestAdapterError;
|
const RequestAdapterError = Interface.RequestAdapterError;
|
||||||
|
const RequestAdapterCallback = Interface.RequestAdapterCallback;
|
||||||
const RequestAdapterResponse = Interface.RequestAdapterResponse;
|
const RequestAdapterResponse = Interface.RequestAdapterResponse;
|
||||||
|
|
||||||
const Adapter = @import("Adapter.zig");
|
const Adapter = @import("Adapter.zig");
|
||||||
const RequestDeviceErrorCode = Adapter.RequestDeviceErrorCode;
|
const RequestDeviceErrorCode = Adapter.RequestDeviceErrorCode;
|
||||||
const RequestDeviceError = Adapter.RequestDeviceError;
|
const RequestDeviceError = Adapter.RequestDeviceError;
|
||||||
const RequestDeviceResponse = Adapter.RequestDeviceResponse;
|
|
||||||
const RequestDeviceCallback = Adapter.RequestDeviceCallback;
|
const RequestDeviceCallback = Adapter.RequestDeviceCallback;
|
||||||
|
const RequestDeviceResponse = Adapter.RequestDeviceResponse;
|
||||||
|
|
||||||
const Device = @import("Device.zig");
|
const Device = @import("Device.zig");
|
||||||
const Surface = @import("Surface.zig");
|
const Surface = @import("Surface.zig");
|
||||||
|
|
@ -64,7 +65,11 @@ const interface_vtable = Interface.VTable{
|
||||||
}
|
}
|
||||||
}).release,
|
}).release,
|
||||||
.requestAdapter = (struct {
|
.requestAdapter = (struct {
|
||||||
pub fn requestAdapter(ptr: *anyopaque, options: *const RequestAdapterOptions) callconv(.Async) RequestAdapterResponse {
|
pub fn requestAdapter(
|
||||||
|
ptr: *anyopaque,
|
||||||
|
options: *const RequestAdapterOptions,
|
||||||
|
callback: *RequestAdapterCallback,
|
||||||
|
) void {
|
||||||
const native = @ptrCast(*NativeInstance, @alignCast(@alignOf(*NativeInstance), ptr));
|
const native = @ptrCast(*NativeInstance, @alignCast(@alignOf(*NativeInstance), ptr));
|
||||||
|
|
||||||
const opt = c.WGPURequestAdapterOptions{
|
const opt = c.WGPURequestAdapterOptions{
|
||||||
|
|
@ -74,14 +79,14 @@ const interface_vtable = Interface.VTable{
|
||||||
.forceFallbackAdapter = options.force_fallback_adapter,
|
.forceFallbackAdapter = options.force_fallback_adapter,
|
||||||
};
|
};
|
||||||
|
|
||||||
const callback = (struct {
|
const cCallback = (struct {
|
||||||
pub fn callback(status: c.WGPURequestAdapterStatus, adapter: c.WGPUAdapter, message: [*c]const u8, userdata: ?*anyopaque) callconv(.C) void {
|
pub fn cCallback(status: c.WGPURequestAdapterStatus, adapter: c.WGPUAdapter, message: [*c]const u8, userdata: ?*anyopaque) callconv(.C) void {
|
||||||
const _callback_response = @ptrCast(*Interface.RequestAdapterResponse, @alignCast(@alignOf(*Interface.RequestAdapterResponse), userdata));
|
const callback_info = @ptrCast(*RequestAdapterCallback, @alignCast(@alignOf(*RequestAdapterCallback), userdata.?));
|
||||||
|
|
||||||
// Store the response into a field on the native instance for later reading.
|
// Store the response into a field on the native instance for later reading.
|
||||||
_callback_response.* = if (status == c.WGPURequestAdapterStatus_Success) .{
|
const response = if (status == c.WGPURequestAdapterStatus_Success) RequestAdapterResponse{
|
||||||
.adapter = wrapAdapter(adapter.?),
|
.adapter = wrapAdapter(adapter.?),
|
||||||
} else .{
|
} else RequestAdapterResponse{
|
||||||
.err = Interface.RequestAdapterError{
|
.err = Interface.RequestAdapterError{
|
||||||
.message = std.mem.span(message),
|
.message = std.mem.span(message),
|
||||||
.code = switch (status) {
|
.code = switch (status) {
|
||||||
|
|
@ -92,18 +97,12 @@ const interface_vtable = Interface.VTable{
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
callback_info.type_erased_callback(callback_info.type_erased_ctx, response);
|
||||||
}
|
}
|
||||||
}).callback;
|
}).cCallback;
|
||||||
|
|
||||||
var callback_response: Interface.RequestAdapterResponse = undefined;
|
c.wgpuInstanceRequestAdapter(native.instance, &opt, cCallback, callback);
|
||||||
c.wgpuInstanceRequestAdapter(native.instance, &opt, callback, &callback_response);
|
|
||||||
// TODO: Once crbug.com/dawn/1122 is fixed, we should process events here otherwise our
|
|
||||||
// callback will not be invoked.
|
|
||||||
// c.wgpuInstanceProcessEvents(native.instance)
|
|
||||||
suspend {} // must suspend so that async caller can resume
|
|
||||||
|
|
||||||
// Return the response, asserting the callback has executed at this point.
|
|
||||||
return callback_response;
|
|
||||||
}
|
}
|
||||||
}).requestAdapter,
|
}).requestAdapter,
|
||||||
};
|
};
|
||||||
|
|
@ -113,7 +112,6 @@ pub fn interface(native: *NativeInstance) Interface {
|
||||||
return .{
|
return .{
|
||||||
.ptr = native,
|
.ptr = native,
|
||||||
.vtable = &interface_vtable,
|
.vtable = &interface_vtable,
|
||||||
.request_adapter_frame_size = @frameSize(interface_vtable.requestAdapter),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@ pub const Interface = @import("Interface.zig");
|
||||||
pub const RequestAdapterOptions = Interface.RequestAdapterOptions;
|
pub const RequestAdapterOptions = Interface.RequestAdapterOptions;
|
||||||
pub const RequestAdapterErrorCode = Interface.RequestAdapterErrorCode;
|
pub const RequestAdapterErrorCode = Interface.RequestAdapterErrorCode;
|
||||||
pub const RequestAdapterError = Interface.RequestAdapterError;
|
pub const RequestAdapterError = Interface.RequestAdapterError;
|
||||||
|
pub const RequestAdapterCallback = Interface.RequestAdapterCallback;
|
||||||
pub const RequestAdapterResponse = Interface.RequestAdapterResponse;
|
pub const RequestAdapterResponse = Interface.RequestAdapterResponse;
|
||||||
|
|
||||||
pub const Adapter = @import("Adapter.zig");
|
pub const Adapter = @import("Adapter.zig");
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue