gpu: implement Adapter.requestDevice
Signed-off-by: Stephen Gutekanst <stephen@hexops.com>
This commit is contained in:
parent
93d6e5dedf
commit
4bc5411a14
3 changed files with 128 additions and 19 deletions
|
|
@ -17,9 +17,11 @@
|
||||||
//!
|
//!
|
||||||
//! https://gpuweb.github.io/gpuweb/#adapters
|
//! https://gpuweb.github.io/gpuweb/#adapters
|
||||||
//! https://gpuweb.github.io/gpuweb/#gpuadapter
|
//! https://gpuweb.github.io/gpuweb/#gpuadapter
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
const FeatureName = @import("feature_name.zig").FeatureName;
|
const FeatureName = @import("feature_name.zig").FeatureName;
|
||||||
const SupportedLimits = @import("supported_limits.zig").SupportedLimits;
|
const SupportedLimits = @import("supported_limits.zig").SupportedLimits;
|
||||||
|
const Device = @import("Device.zig");
|
||||||
|
|
||||||
const Adapter = @This();
|
const Adapter = @This();
|
||||||
|
|
||||||
|
|
@ -43,16 +45,20 @@ fallback: bool,
|
||||||
// TODO: docs
|
// TODO: docs
|
||||||
properties: Properties,
|
properties: Properties,
|
||||||
|
|
||||||
// The type erased pointer to the Adapter implementation
|
/// The type erased pointer to the Adapter implementation
|
||||||
|
/// Equal to c.WGPUAdapter for NativeInstance.
|
||||||
ptr: *anyopaque,
|
ptr: *anyopaque,
|
||||||
vtable: *const VTable,
|
vtable: *const VTable,
|
||||||
|
|
||||||
|
// The @frameSize(func) of the implementations requestDevice async function
|
||||||
|
request_device_frame_size: usize,
|
||||||
|
|
||||||
pub const VTable = struct {
|
pub const VTable = struct {
|
||||||
// TODO:
|
// TODO:
|
||||||
// WGPU_EXPORT void wgpuAdapterRequestDevice(WGPUAdapter adapter, WGPUDeviceDescriptor const * descriptor, WGPURequestDeviceCallback callback, void * userdata);
|
|
||||||
// WGPU_EXPORT WGPUDevice wgpuAdapterCreateDevice(WGPUAdapter adapter, WGPUDeviceDescriptor const * descriptor);
|
// WGPU_EXPORT WGPUDevice wgpuAdapterCreateDevice(WGPUAdapter adapter, WGPUDeviceDescriptor const * descriptor);
|
||||||
reference: fn (ptr: *anyopaque) void,
|
reference: fn (ptr: *anyopaque) void,
|
||||||
release: fn (ptr: *anyopaque) void,
|
release: fn (ptr: *anyopaque) void,
|
||||||
|
requestDevice: fn requestDevice(ptr: *anyopaque, descriptor: *const Device.Descriptor) callconv(.Async) RequestDeviceResponse,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub inline fn reference(adapter: Adapter) void {
|
pub inline fn reference(adapter: Adapter) void {
|
||||||
|
|
@ -123,10 +129,57 @@ pub fn backendTypeName(t: BackendType) []const u8 {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const RequestDeviceErrorCode = error{
|
||||||
|
Error,
|
||||||
|
Unknown,
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: docs
|
||||||
|
pub const RequestDeviceError = struct {
|
||||||
|
message: []const u8,
|
||||||
|
code: RequestDeviceErrorCode,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const RequestDeviceResponseTag = enum {
|
||||||
|
device,
|
||||||
|
err,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const RequestDeviceResponse = union(RequestDeviceResponseTag) {
|
||||||
|
// TODO: docs
|
||||||
|
device: Device,
|
||||||
|
err: RequestDeviceError,
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: docs
|
||||||
|
pub fn requestDevice(adapter: Adapter, descriptor: *const Device.Descriptor) callconv(.Async) RequestDeviceResponse {
|
||||||
|
var frame_buffer = std.heap.page_allocator.allocAdvanced(
|
||||||
|
u8,
|
||||||
|
16,
|
||||||
|
adapter.request_device_frame_size,
|
||||||
|
std.mem.Allocator.Exact.at_least,
|
||||||
|
) catch {
|
||||||
|
return .{ .err = .{
|
||||||
|
.message = "Out of memory",
|
||||||
|
.code = RequestDeviceErrorCode.Error,
|
||||||
|
} };
|
||||||
|
};
|
||||||
|
defer std.heap.page_allocator.free(frame_buffer);
|
||||||
|
|
||||||
|
var result: RequestDeviceResponse = undefined;
|
||||||
|
const f = @asyncCall(frame_buffer, &result, adapter.vtable.requestDevice, .{ adapter.ptr, descriptor });
|
||||||
|
resume f;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
test "syntax" {
|
test "syntax" {
|
||||||
_ = VTable;
|
_ = VTable;
|
||||||
_ = hasFeature;
|
_ = hasFeature;
|
||||||
_ = Properties;
|
_ = Properties;
|
||||||
_ = Type;
|
_ = Type;
|
||||||
_ = BackendType;
|
_ = BackendType;
|
||||||
|
_ = RequestDeviceErrorCode;
|
||||||
|
_ = RequestDeviceError;
|
||||||
|
_ = RequestDeviceResponse;
|
||||||
|
_ = requestDevice;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,12 @@ pub const RequestAdapterError = Interface.RequestAdapterError;
|
||||||
pub const RequestAdapterResponse = Interface.RequestAdapterResponse;
|
pub const RequestAdapterResponse = Interface.RequestAdapterResponse;
|
||||||
|
|
||||||
pub const Adapter = @import("Adapter.zig");
|
pub const Adapter = @import("Adapter.zig");
|
||||||
|
pub const RequestDeviceErrorCode = Adapter.RequestDeviceErrorCode;
|
||||||
|
pub const RequestDeviceError = Adapter.RequestDeviceError;
|
||||||
|
pub const RequestDeviceResponse = Adapter.RequestDeviceResponse;
|
||||||
|
|
||||||
|
pub const Device = @import("Device.zig");
|
||||||
|
|
||||||
const Surface = @import("Surface.zig");
|
const Surface = @import("Surface.zig");
|
||||||
|
|
||||||
const NativeInstance = @This();
|
const NativeInstance = @This();
|
||||||
|
|
@ -16,6 +22,7 @@ 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,
|
||||||
|
|
||||||
|
// TODO: use CallbackResponse approach instead of storing here
|
||||||
request_adapter_response: ?Interface.RequestAdapterResponse = null,
|
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.
|
||||||
|
|
@ -207,6 +214,7 @@ fn wrapAdapter(adapter: c.WGPUAdapter) Adapter {
|
||||||
|
|
||||||
.ptr = adapter.?,
|
.ptr = adapter.?,
|
||||||
.vtable = &adapter_vtable,
|
.vtable = &adapter_vtable,
|
||||||
|
.request_device_frame_size = @frameSize(adapter_vtable.requestDevice),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -221,9 +229,71 @@ const adapter_vtable = Adapter.VTable{
|
||||||
c.wgpuAdapterRelease(@ptrCast(c.WGPUAdapter, ptr));
|
c.wgpuAdapterRelease(@ptrCast(c.WGPUAdapter, ptr));
|
||||||
}
|
}
|
||||||
}).release,
|
}).release,
|
||||||
|
.requestDevice = (struct {
|
||||||
|
pub fn requestDevice(ptr: *anyopaque, descriptor: *const Device.Descriptor) callconv(.Async) RequestDeviceResponse {
|
||||||
|
const adapter = @ptrCast(c.WGPUAdapter, @alignCast(@alignOf(c.WGPUAdapter), ptr));
|
||||||
|
|
||||||
|
const desc = c.WGPUDeviceDescriptor{
|
||||||
|
.nextInChain = null,
|
||||||
|
.label = if (descriptor.label) |l| @ptrCast([*c]const u8, l) else null,
|
||||||
|
.requiredFeaturesCount = if (descriptor.required_features) |f| @intCast(u32, f.len) else 0,
|
||||||
|
.requiredFeatures = if (descriptor.required_features) |f| @ptrCast([*c]const c_uint, &f[0]) else null,
|
||||||
|
.requiredLimits = null, // TODO
|
||||||
|
};
|
||||||
|
|
||||||
|
const callback = (struct {
|
||||||
|
pub fn callback(status: c.WGPURequestDeviceStatus, device: c.WGPUDevice, message: [*c]const u8, userdata: ?*anyopaque) callconv(.C) void {
|
||||||
|
const _callback_response = @ptrCast(*Adapter.RequestDeviceResponse, @alignCast(@alignOf(*Adapter.RequestDeviceResponse), userdata));
|
||||||
|
|
||||||
|
// Store the response into a field on the native instance for later reading.
|
||||||
|
_callback_response.* = if (status == c.WGPURequestDeviceStatus_Success) .{
|
||||||
|
.device = wrapDevice(device.?),
|
||||||
|
} else .{
|
||||||
|
.err = Adapter.RequestDeviceError{
|
||||||
|
.message = std.mem.span(message),
|
||||||
|
.code = switch (status) {
|
||||||
|
c.WGPURequestDeviceStatus_Error => RequestDeviceErrorCode.Error,
|
||||||
|
c.WGPURequestDeviceStatus_Unknown => RequestDeviceErrorCode.Unknown,
|
||||||
|
else => unreachable,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}).callback;
|
||||||
|
|
||||||
|
var callback_response: Adapter.RequestDeviceResponse = undefined;
|
||||||
|
c.wgpuAdapterRequestDevice(adapter, &desc, 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;
|
||||||
|
}
|
||||||
|
}).requestDevice,
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: implement Device interface
|
fn wrapDevice(device: c.WGPUDevice) Device {
|
||||||
|
// TODO: implement Device interface
|
||||||
|
return .{
|
||||||
|
.ptr = device.?,
|
||||||
|
.vtable = &device_vtable,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const device_vtable = Device.VTable{
|
||||||
|
.reference = (struct {
|
||||||
|
pub fn reference(ptr: *anyopaque) void {
|
||||||
|
c.wgpuDeviceReference(@ptrCast(c.WGPUDevice, ptr));
|
||||||
|
}
|
||||||
|
}).reference,
|
||||||
|
.release = (struct {
|
||||||
|
pub fn release(ptr: *anyopaque) void {
|
||||||
|
c.wgpuDeviceRelease(@ptrCast(c.WGPUDevice, ptr));
|
||||||
|
}
|
||||||
|
}).release,
|
||||||
|
};
|
||||||
|
|
||||||
test "syntax" {
|
test "syntax" {
|
||||||
_ = wrap;
|
_ = wrap;
|
||||||
|
|
@ -232,4 +302,6 @@ test "syntax" {
|
||||||
_ = createSurface;
|
_ = createSurface;
|
||||||
_ = surface_vtable;
|
_ = surface_vtable;
|
||||||
_ = adapter_vtable;
|
_ = adapter_vtable;
|
||||||
|
_ = wrapDevice;
|
||||||
|
_ = device_vtable;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
16
gpu/src/TODO
16
gpu/src/TODO
|
|
@ -269,13 +269,6 @@ typedef enum WGPURenderPassTimestampLocation {
|
||||||
WGPURenderPassTimestampLocation_Force32 = 0x7FFFFFFF
|
WGPURenderPassTimestampLocation_Force32 = 0x7FFFFFFF
|
||||||
} WGPURenderPassTimestampLocation;
|
} WGPURenderPassTimestampLocation;
|
||||||
|
|
||||||
typedef enum WGPURequestDeviceStatus {
|
|
||||||
WGPURequestDeviceStatus_Success = 0x00000000,
|
|
||||||
WGPURequestDeviceStatus_Error = 0x00000001,
|
|
||||||
WGPURequestDeviceStatus_Unknown = 0x00000002,
|
|
||||||
WGPURequestDeviceStatus_Force32 = 0x7FFFFFFF
|
|
||||||
} WGPURequestDeviceStatus;
|
|
||||||
|
|
||||||
typedef enum WGPUSType {
|
typedef enum WGPUSType {
|
||||||
WGPUSType_Invalid = 0x00000000,
|
WGPUSType_Invalid = 0x00000000,
|
||||||
WGPUSType_ShaderModuleSPIRVDescriptor = 0x00000005,
|
WGPUSType_ShaderModuleSPIRVDescriptor = 0x00000005,
|
||||||
|
|
@ -1006,14 +999,6 @@ typedef struct WGPUComputePipelineDescriptor {
|
||||||
WGPUProgrammableStageDescriptor compute;
|
WGPUProgrammableStageDescriptor compute;
|
||||||
} WGPUComputePipelineDescriptor;
|
} WGPUComputePipelineDescriptor;
|
||||||
|
|
||||||
typedef struct WGPUDeviceDescriptor {
|
|
||||||
WGPUChainedStruct const * nextInChain;
|
|
||||||
char const * label;
|
|
||||||
uint32_t requiredFeaturesCount;
|
|
||||||
WGPUFeatureName const * requiredFeatures;
|
|
||||||
WGPURequiredLimits const * requiredLimits;
|
|
||||||
} WGPUDeviceDescriptor;
|
|
||||||
|
|
||||||
typedef struct WGPUDeviceProperties {
|
typedef struct WGPUDeviceProperties {
|
||||||
uint32_t deviceID;
|
uint32_t deviceID;
|
||||||
uint32_t vendorID;
|
uint32_t vendorID;
|
||||||
|
|
@ -1085,7 +1070,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 (*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);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue