gpu: initial pass at requestAdapter
Signed-off-by: Stephen Gutekanst <stephen@hexops.com>
This commit is contained in:
parent
3f19563354
commit
3a0b0fd83c
5 changed files with 189 additions and 29 deletions
|
|
@ -36,6 +36,8 @@ limits: SupportedLimits,
|
||||||
/// An adapter may be considered a fallback adapter if it has significant performance caveats in
|
/// An adapter may be considered a fallback adapter if it has significant performance caveats in
|
||||||
/// exchange for some combination of wider compatibility, more predictable behavior, or improved
|
/// exchange for some combination of wider compatibility, more predictable behavior, or improved
|
||||||
/// privacy. It is not guaranteed that a fallback adapter is available on every system.
|
/// privacy. It is not guaranteed that a fallback adapter is available on every system.
|
||||||
|
///
|
||||||
|
/// Always false on native implementations of WebGPU (TODO: why is this not queryable in Dawn?)
|
||||||
fallback: bool,
|
fallback: bool,
|
||||||
|
|
||||||
// The type erased pointer to the Adapter implementation
|
// The type erased pointer to the Adapter implementation
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
//! A standard interface to a WebGPU implementation.
|
//! A standard interface to a WebGPU implementation.
|
||||||
//!
|
//!
|
||||||
//! Like std.mem.Allocator, but representing 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 Interface = @This();
|
const Interface = @This();
|
||||||
|
|
||||||
|
|
@ -8,9 +12,13 @@ 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,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub inline fn reference(interface: Interface) void {
|
pub inline fn reference(interface: Interface) void {
|
||||||
|
|
@ -21,5 +29,79 @@ pub inline fn release(interface: Interface) void {
|
||||||
interface.vtable.release(interface.ptr);
|
interface.vtable.release(interface.ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO:
|
// TODO: docs
|
||||||
// WGPU_EXPORT void wgpuInstanceRequestAdapter(WGPUInstance instance, WGPURequestAdapterOptions const * options, WGPURequestAdapterCallback callback, void * userdata);
|
pub const RequestAdapterOptions = struct {
|
||||||
|
// TODO:
|
||||||
|
//power_preference: PowerPreference,
|
||||||
|
force_fallback_adapter: bool = false,
|
||||||
|
|
||||||
|
/// Only respected by native WebGPU implementations.
|
||||||
|
compatible_surface: ?Surface,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const RequestAdapterErrorCode = error{
|
||||||
|
Unavailable,
|
||||||
|
Error,
|
||||||
|
Unknown,
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: docs
|
||||||
|
pub const RequestAdapterError = struct {
|
||||||
|
message: []const u8,
|
||||||
|
code: RequestAdapterErrorCode,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const RequestAdapterResponseTag = enum {
|
||||||
|
adapter,
|
||||||
|
err,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const RequestAdapterResponse = union(RequestAdapterResponseTag) {
|
||||||
|
// TODO: docs
|
||||||
|
adapter: Adapter,
|
||||||
|
err: RequestAdapterError,
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: docs
|
||||||
|
pub fn requestAdapter(interface: Interface, options: *const RequestAdapterOptions) callconv(.Async) RequestAdapterResponse {
|
||||||
|
var frame_buffer = std.heap.page_allocator.allocAdvanced(
|
||||||
|
u8,
|
||||||
|
16,
|
||||||
|
interface.request_adapter_frame_size,
|
||||||
|
std.mem.Allocator.Exact.at_least,
|
||||||
|
) catch {
|
||||||
|
return .{ .err = .{
|
||||||
|
.message = "Out of memory",
|
||||||
|
.code = RequestAdapterErrorCode.Error,
|
||||||
|
} };
|
||||||
|
};
|
||||||
|
defer std.heap.page_allocator.free(frame_buffer);
|
||||||
|
|
||||||
|
var result: RequestAdapterResponse = undefined;
|
||||||
|
const f = @asyncCall(frame_buffer, &result, interface.vtable.requestAdapter, .{ interface.ptr, options });
|
||||||
|
resume f;
|
||||||
|
return result;
|
||||||
|
|
||||||
|
// @asyncCall(frame_buffer: []align(@alignOf(@Frame(anyAsyncFunction))) u8, result_ptr, function_ptr, args: anytype) anyframe->T
|
||||||
|
|
||||||
|
// var data: i32 = 1;
|
||||||
|
// const Foo = struct {
|
||||||
|
// bar: fn (*i32) callconv(.Async) void,
|
||||||
|
// };
|
||||||
|
// var foo = Foo{ .bar = func };
|
||||||
|
// var bytes: [64]u8 align(@alignOf(@Frame(func))) = undefined;
|
||||||
|
// const f = @asyncCall(&bytes, {}, foo.bar, .{&data});
|
||||||
|
|
||||||
|
// return async interface.vtable.requestAdapter(interface.ptr, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "syntax" {
|
||||||
|
_ = VTable;
|
||||||
|
_ = reference;
|
||||||
|
_ = release;
|
||||||
|
_ = RequestAdapterOptions;
|
||||||
|
_ = RequestAdapterErrorCode;
|
||||||
|
_ = RequestAdapterError;
|
||||||
|
_ = RequestAdapterResponse;
|
||||||
|
_ = requestAdapter;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,14 @@
|
||||||
//! A native webgpu.h implementation of the gpu.Interface
|
//! A native webgpu.h implementation of the gpu.Interface
|
||||||
|
const std = @import("std");
|
||||||
const c = @import("c.zig").c;
|
const c = @import("c.zig").c;
|
||||||
const Interface = @import("Interface.zig");
|
|
||||||
|
pub const Interface = @import("Interface.zig");
|
||||||
|
pub const RequestAdapterOptions = Interface.RequestAdapterOptions;
|
||||||
|
pub const RequestAdapterErrorCode = Interface.RequestAdapterErrorCode;
|
||||||
|
pub const RequestAdapterError = Interface.RequestAdapterError;
|
||||||
|
pub const RequestAdapterResponse = Interface.RequestAdapterResponse;
|
||||||
|
|
||||||
|
pub const Adapter = @import("Adapter.zig");
|
||||||
const Surface = @import("Surface.zig");
|
const Surface = @import("Surface.zig");
|
||||||
|
|
||||||
const NativeInstance = @This();
|
const NativeInstance = @This();
|
||||||
|
|
@ -8,6 +16,8 @@ const NativeInstance = @This();
|
||||||
/// The WGPUInstance that is wrapped by this native instance.
|
/// The WGPUInstance that is wrapped by this native instance.
|
||||||
instance: c.WGPUInstance,
|
instance: c.WGPUInstance,
|
||||||
|
|
||||||
|
request_adapter_response: ?Interface.RequestAdapterResponse = null,
|
||||||
|
|
||||||
/// Wraps a native WGPUInstance to provide an implementation of the gpu.Interface.
|
/// Wraps a native WGPUInstance to provide an implementation of the gpu.Interface.
|
||||||
pub fn wrap(instance: *anyopaque) NativeInstance {
|
pub fn wrap(instance: *anyopaque) NativeInstance {
|
||||||
return .{ .instance = @ptrCast(c.WGPUInstance, instance) };
|
return .{ .instance = @ptrCast(c.WGPUInstance, instance) };
|
||||||
|
|
@ -26,23 +36,73 @@ const interface_vtable = Interface.VTable{
|
||||||
c.wgpuInstanceRelease(native.instance);
|
c.wgpuInstanceRelease(native.instance);
|
||||||
}
|
}
|
||||||
}).release,
|
}).release,
|
||||||
|
.requestAdapter = (struct {
|
||||||
|
pub fn requestAdapter(ptr: *anyopaque, options: *const RequestAdapterOptions) callconv(.Async) RequestAdapterResponse {
|
||||||
|
const native = @ptrCast(*NativeInstance, @alignCast(@alignOf(*NativeInstance), ptr));
|
||||||
|
|
||||||
|
const opt = c.WGPURequestAdapterOptions{
|
||||||
|
.nextInChain = null,
|
||||||
|
.compatibleSurface = if (options.compatible_surface) |surface| @ptrCast(c.WGPUSurface, surface.ptr) else null,
|
||||||
|
// TODO:
|
||||||
|
//.powerPreference = power_preference,
|
||||||
|
.powerPreference = c.WGPUPowerPreference_Undefined,
|
||||||
|
.forceFallbackAdapter = options.force_fallback_adapter,
|
||||||
|
};
|
||||||
|
|
||||||
|
const callback = (struct {
|
||||||
|
pub fn callback(status: c.WGPURequestAdapterStatus, adapter: c.WGPUAdapter, message: [*c]const u8, userdata: ?*anyopaque) callconv(.C) void {
|
||||||
|
const _native = @ptrCast(*NativeInstance, @alignCast(@alignOf(*NativeInstance), userdata));
|
||||||
|
|
||||||
|
// Store the response into a field on the native instance for later reading.
|
||||||
|
_native.request_adapter_response = if (status == c.WGPURequestAdapterStatus_Success) .{
|
||||||
|
.adapter = wrapAdapter(adapter.?),
|
||||||
|
} else .{
|
||||||
|
.err = Interface.RequestAdapterError{
|
||||||
|
.message = std.mem.span(message),
|
||||||
|
.code = switch (status) {
|
||||||
|
c.WGPURequestAdapterStatus_Unavailable => RequestAdapterErrorCode.Unavailable,
|
||||||
|
c.WGPURequestAdapterStatus_Error => RequestAdapterErrorCode.Error,
|
||||||
|
c.WGPURequestAdapterStatus_Unknown => RequestAdapterErrorCode.Unknown,
|
||||||
|
else => unreachable,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}).callback;
|
||||||
|
|
||||||
|
c.wgpuInstanceRequestAdapter(native.instance, &opt, callback, native);
|
||||||
|
// TODO: Once crbug.com/dawn/1122 is fixed, we should process events here otherwise our
|
||||||
|
// callback will not be invoked.
|
||||||
|
// c.wgpuInstanceProcessEvents(native.instance)
|
||||||
|
|
||||||
|
// Return the response, asserting the callback has executed at this point.
|
||||||
|
const resp = native.request_adapter_response.?;
|
||||||
|
native.request_adapter_response = null;
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
}).requestAdapter,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
// typedef void (*WGPURequestAdapterCallback)(WGPURequestAdapterStatus status, WGPUAdapter adapter, char const * message, void * userdata);
|
||||||
|
// WGPU_EXPORT void wgpuInstanceRequestAdapter(WGPUInstance instance, WGPURequestAdapterOptions const * options, WGPURequestAdapterCallback callback, void * userdata);
|
||||||
|
|
||||||
|
// typedef enum WGPURequestAdapterStatus {
|
||||||
|
// WGPURequestAdapterStatus_Success = 0x00000000,
|
||||||
|
// WGPURequestAdapterStatus_Unavailable = 0x00000001,
|
||||||
|
// WGPURequestAdapterStatus_Error = 0x00000002,
|
||||||
|
// WGPURequestAdapterStatus_Unknown = 0x00000003,
|
||||||
|
// WGPURequestAdapterStatus_Force32 = 0x7FFFFFFF
|
||||||
|
// } WGPURequestAdapterStatus;
|
||||||
|
|
||||||
/// Returns the gpu.Interface for interacting with this native instance.
|
/// Returns the gpu.Interface for interacting with this native instance.
|
||||||
pub fn interface(native: *NativeInstance) Interface {
|
pub fn interface(native: *NativeInstance) Interface {
|
||||||
|
std.debug.assert(@alignOf(@Frame(interface_vtable.requestAdapter)) == 16);
|
||||||
return .{
|
return .{
|
||||||
.ptr = native,
|
.ptr = native,
|
||||||
.vtable = &interface_vtable,
|
.vtable = &interface_vtable,
|
||||||
|
.request_adapter_frame_size = @frameSize(interface_vtable.requestAdapter),
|
||||||
};
|
};
|
||||||
// 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 {
|
pub fn createSurface(native: *const NativeInstance, descriptor: *const Surface.Descriptor) Surface {
|
||||||
|
|
@ -130,8 +190,36 @@ const surface_vtable = Surface.VTable{
|
||||||
}).release,
|
}).release,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
fn wrapAdapter(adapter: c.WGPUAdapter) Adapter {
|
||||||
|
// TODO: implement Adapter interface:
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
return .{
|
||||||
|
// TODO:
|
||||||
|
.features = undefined,
|
||||||
|
// TODO:
|
||||||
|
.limits = undefined,
|
||||||
|
|
||||||
|
// TODO: why is fallback not queryable on Dawn?
|
||||||
|
.fallback = false,
|
||||||
|
|
||||||
|
.ptr = adapter.?,
|
||||||
|
.vtable = &adapter_vtable,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const adapter_vtable = Adapter.VTable{};
|
||||||
|
|
||||||
|
// TODO: implement Device interface
|
||||||
|
|
||||||
test "syntax" {
|
test "syntax" {
|
||||||
_ = wrap;
|
_ = wrap;
|
||||||
|
_ = interface_vtable;
|
||||||
_ = interface;
|
_ = interface;
|
||||||
_ = createSurface;
|
_ = createSurface;
|
||||||
|
_ = surface_vtable;
|
||||||
|
_ = adapter_vtable;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
16
gpu/src/TODO
16
gpu/src/TODO
|
|
@ -281,14 +281,6 @@ typedef enum WGPURenderPassTimestampLocation {
|
||||||
WGPURenderPassTimestampLocation_Force32 = 0x7FFFFFFF
|
WGPURenderPassTimestampLocation_Force32 = 0x7FFFFFFF
|
||||||
} WGPURenderPassTimestampLocation;
|
} WGPURenderPassTimestampLocation;
|
||||||
|
|
||||||
typedef enum WGPURequestAdapterStatus {
|
|
||||||
WGPURequestAdapterStatus_Success = 0x00000000,
|
|
||||||
WGPURequestAdapterStatus_Unavailable = 0x00000001,
|
|
||||||
WGPURequestAdapterStatus_Error = 0x00000002,
|
|
||||||
WGPURequestAdapterStatus_Unknown = 0x00000003,
|
|
||||||
WGPURequestAdapterStatus_Force32 = 0x7FFFFFFF
|
|
||||||
} WGPURequestAdapterStatus;
|
|
||||||
|
|
||||||
typedef enum WGPURequestDeviceStatus {
|
typedef enum WGPURequestDeviceStatus {
|
||||||
WGPURequestDeviceStatus_Success = 0x00000000,
|
WGPURequestDeviceStatus_Success = 0x00000000,
|
||||||
WGPURequestDeviceStatus_Error = 0x00000001,
|
WGPURequestDeviceStatus_Error = 0x00000001,
|
||||||
|
|
@ -808,13 +800,6 @@ typedef struct WGPURenderPassTimestampWrite {
|
||||||
WGPURenderPassTimestampLocation location;
|
WGPURenderPassTimestampLocation location;
|
||||||
} WGPURenderPassTimestampWrite;
|
} WGPURenderPassTimestampWrite;
|
||||||
|
|
||||||
typedef struct WGPURequestAdapterOptions {
|
|
||||||
WGPUChainedStruct const * nextInChain;
|
|
||||||
WGPUSurface compatibleSurface;
|
|
||||||
WGPUPowerPreference powerPreference;
|
|
||||||
bool forceFallbackAdapter;
|
|
||||||
} WGPURequestAdapterOptions;
|
|
||||||
|
|
||||||
typedef struct WGPUSamplerBindingLayout {
|
typedef struct WGPUSamplerBindingLayout {
|
||||||
WGPUChainedStruct const * nextInChain;
|
WGPUChainedStruct const * nextInChain;
|
||||||
WGPUSamplerBindingType type;
|
WGPUSamplerBindingType type;
|
||||||
|
|
@ -1112,7 +1097,6 @@ typedef void (*WGPUErrorCallback)(WGPUErrorType type, char const * message, void
|
||||||
typedef void (*WGPULoggingCallback)(WGPULoggingType type, char const * message, void * userdata);
|
typedef void (*WGPULoggingCallback)(WGPULoggingType type, char const * message, void * userdata);
|
||||||
typedef void (*WGPUProc)();
|
typedef void (*WGPUProc)();
|
||||||
typedef void (*WGPUQueueWorkDoneCallback)(WGPUQueueWorkDoneStatus status, void * userdata);
|
typedef void (*WGPUQueueWorkDoneCallback)(WGPUQueueWorkDoneStatus status, void * userdata);
|
||||||
typedef void (*WGPURequestAdapterCallback)(WGPURequestAdapterStatus status, WGPUAdapter adapter, char const * message, void * userdata);
|
|
||||||
typedef void (*WGPURequestDeviceCallback)(WGPURequestDeviceStatus status, WGPUDevice device, char const * message, void * userdata);
|
typedef void (*WGPURequestDeviceCallback)(WGPURequestDeviceStatus status, WGPUDevice device, char const * message, void * userdata);
|
||||||
|
|
||||||
WGPU_EXPORT WGPUProc wgpuGetProcAddress(WGPUDevice device, char const * procName);
|
WGPU_EXPORT WGPUProc wgpuGetProcAddress(WGPUDevice device, char const * procName);
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,11 @@
|
||||||
//!
|
//!
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
pub const Interface = @import("Interface.zig");
|
pub const Interface = @import("Interface.zig");
|
||||||
|
pub const RequestAdapterOptions = Interface.RequestAdapterOptions;
|
||||||
|
pub const RequestAdapterErrorCode = Interface.RequestAdapterErrorCode;
|
||||||
|
pub const RequestAdapterError = Interface.RequestAdapterError;
|
||||||
|
pub const RequestAdapterResponse = Interface.RequestAdapterResponse;
|
||||||
|
|
||||||
pub const NativeInstance = @import("NativeInstance.zig");
|
pub const NativeInstance = @import("NativeInstance.zig");
|
||||||
|
|
||||||
pub const Adapter = @import("Adapter.zig");
|
pub const Adapter = @import("Adapter.zig");
|
||||||
|
|
@ -33,7 +38,6 @@ test "syntax" {
|
||||||
_ = Adapter;
|
_ = Adapter;
|
||||||
_ = Device;
|
_ = Device;
|
||||||
_ = Surface;
|
_ = Surface;
|
||||||
_ = Surface.Descriptor;
|
|
||||||
|
|
||||||
_ = FeatureName;
|
_ = FeatureName;
|
||||||
_ = SupportedLimits;
|
_ = SupportedLimits;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue