Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ This package exposes two modules: `wgpu-c` and `wgpu`.

`wgpu-c` is just `wgpu.h` (and by extension `webgpu.h`) run through `translate-c`, so as close to wgpu-native's original C API as is possible in Zig.

`wgpu` is a module full of pure Zig bindings for `libwgpu_native`, it does not import any C code and instead relies on `extern fn` declarations to hook up to `wgpu-native`.
`wgpu` is a Zig-friendly wrapper over the bindings generated directly from `wgpu.h` and
`webgpu.h`. The generated declarations are also available through `wgpu.raw`; wrapper
methods and raw calls therefore share the headers as their single ABI source of truth.

## Adding this package to your build
Add the package to your dependencies, either with:
Expand Down Expand Up @@ -294,15 +296,12 @@ both link modes and the matching headers.
}).withDesiredMaxFrameLatency(2);
```
* `WGPUBool` is replaced with `bool` whenever possible.
* This pretty much means, it is replaced with `bool` in the parameters and return values of methods, but not in structs or the parameters/return values of procs (which are supposed to be function pointers to things returned by `wgpuGetProcAddress`).
* This means it is replaced with `bool` in wrapper method parameters and return values, but not in structs that preserve the C ABI.

## TODO
* Cleanup/organization:
* If types are only tied to a specific opaque struct, they should be decls inside that struct.
* The associated Procs struct should probably be a decl of the opaque struct as well.
* There are many things that seem to be in the wrong file.
* For example a lot of what is in `pipeline.zig` is actually only used by `Device`, and should probably be in `device.zig` instead.
* Since pointers to opaque structs are made explicit, it would be more consistent if pointers to callback functions are explicit as well.
* Port [wgpu-native-examples](https://github.com/samdauwe/webgpu-native-examples) using wrapper code, as a basic form of documentation.
* Bindgen using [the webgpu-headers yaml](https://github.com/webgpu-native/webgpu-headers/blob/main/webgpu.yml)?
* The proc definitions are mainly there since they are also present in the webgpu headers and I didn't fully understand what they were for when I started working on this project. However, I know better now and they aren't really used for anything currently. They're supposed to be used with `wgpuGetProcAddress` but it's [unimplemented in `wgpu-native`](https://github.com/gfx-rs/wgpu-native/issues/223). They are a pain to update by hand, so maybe they should be removed for now and made optional once we have a working bindings generator? Like the bindgen could put them in a separate `wgpu-procs` module.
1 change: 1 addition & 0 deletions build/Library.zig
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ pub fn build(b: *std.Build, options: Options) ?Result {
Platform.configureTranslateC(platform, translate_step);
const wgpu_c_mod = translate_step.addModule("wgpu-c");
wgpu_c_mod.resolved_target = options.target;
wgpu_mod.addImport("wgpu-header", wgpu_c_mod);

var result: Result = .{
.target = options.target,
Expand Down
43 changes: 10 additions & 33 deletions src/adapter.zig
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const raw = @import("raw.zig");
const std = @import("std");

const _chained_struct = @import("chained_struct.zig");
Expand Down Expand Up @@ -125,12 +126,6 @@ pub const RequestAdapterResponse = struct {
adapter: ?*Adapter,
};

pub const AdapterInfoProcs = struct {
pub const FreeMembers = *const fn (AdapterInfo) callconv(.c) void;
};

extern fn wgpuAdapterInfoFreeMembers(adapter_info: AdapterInfo) void;

pub const AdapterInfo = extern struct {
next_in_chain: ?*ChainedStructOut = null,
vendor: StringView,
Expand All @@ -145,40 +140,22 @@ pub const AdapterInfo = extern struct {
subgroup_max_size: u32,

pub inline fn freeMembers(self: AdapterInfo) void {
wgpuAdapterInfoFreeMembers(self);
raw.call(void, "wgpuAdapterInfoFreeMembers", .{self});
}
};

pub const AdapterProcs = struct {
pub const GetFeatures = *const fn (*Adapter, *SupportedFeatures) callconv(.c) void;
pub const GetLimits = *const fn (*Adapter, *Limits) callconv(.c) Status;
pub const GetInfo = *const fn (*Adapter, *AdapterInfo) callconv(.c) Status;
pub const HasFeature = *const fn (*Adapter, FeatureName) callconv(.c) WGPUBool;
pub const RequestDevice = *const fn (*Adapter, ?*const DeviceDescriptor, RequestDeviceCallbackInfo) callconv(.c) Future;
pub const AddRef = *const fn (*Adapter) callconv(.c) void;
pub const Release = *const fn (*Adapter) callconv(.c) void;
};

extern fn wgpuAdapterGetFeatures(adapter: *Adapter, features: *SupportedFeatures) void;
extern fn wgpuAdapterGetLimits(adapter: *Adapter, limits: *Limits) Status;
extern fn wgpuAdapterGetInfo(adapter: *Adapter, info: *AdapterInfo) Status;
extern fn wgpuAdapterHasFeature(adapter: *Adapter, feature: FeatureName) WGPUBool;
extern fn wgpuAdapterRequestDevice(adapter: *Adapter, descriptor: ?*const DeviceDescriptor, callback_info: RequestDeviceCallbackInfo) Future;
extern fn wgpuAdapterAddRef(adapter: *Adapter) void;
extern fn wgpuAdapterRelease(adapter: *Adapter) void;

pub const Adapter = opaque {
pub inline fn getFeatures(self: *Adapter, features: *SupportedFeatures) void {
wgpuAdapterGetFeatures(self, features);
raw.call(void, "wgpuAdapterGetFeatures", .{ self, features });
}
pub inline fn getLimits(self: *Adapter, limits: *Limits) Status {
return wgpuAdapterGetLimits(self, limits);
return raw.call(Status, "wgpuAdapterGetLimits", .{ self, limits });
}
pub inline fn getInfo(self: *Adapter, info: *AdapterInfo) Status {
return wgpuAdapterGetInfo(self, info);
return raw.call(Status, "wgpuAdapterGetInfo", .{ self, info });
}
pub inline fn hasFeature(self: *Adapter, feature: FeatureName) bool {
return wgpuAdapterHasFeature(self, feature) != 0;
return raw.call(WGPUBool, "wgpuAdapterHasFeature", .{ self, feature }) != 0;
}

fn defaultDeviceCallback(status: RequestDeviceStatus, device: ?*Device, message: StringView, userdata1: ?*anyopaque, userdata2: ?*anyopaque) callconv(.c) void {
Expand Down Expand Up @@ -209,7 +186,7 @@ pub const Adapter = opaque {
.userdata1 = @ptrCast(&response),
.userdata2 = @ptrCast(&completed),
};
const device_future = wgpuAdapterRequestDevice(self, descriptor, callback_info);
const device_future = raw.call(Future, "wgpuAdapterRequestDevice", .{ self, descriptor, callback_info });

// TODO: Revisit once Instance.waitAny() is implemented in wgpu-native,
// it takes in futures and returns when one of them completes.
Expand All @@ -224,13 +201,13 @@ pub const Adapter = opaque {
}

pub inline fn requestDevice(self: *Adapter, descriptor: ?*const DeviceDescriptor, callback_info: RequestDeviceCallbackInfo) Future {
return wgpuAdapterRequestDevice(self, descriptor, callback_info);
return raw.call(Future, "wgpuAdapterRequestDevice", .{ self, descriptor, callback_info });
}
pub inline fn addRef(self: *Adapter) void {
wgpuAdapterAddRef(self);
raw.call(void, "wgpuAdapterAddRef", .{self});
}
pub inline fn release(self: *Adapter) void {
wgpuAdapterRelease(self);
raw.call(void, "wgpuAdapterRelease", .{self});
}
};

Expand Down
36 changes: 7 additions & 29 deletions src/bind_group.zig
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const raw = @import("raw.zig");
const _chained_struct = @import("chained_struct.zig");
const ChainedStruct = _chained_struct.ChainedStruct;
const SType = _chained_struct.SType;
Expand Down Expand Up @@ -27,17 +28,14 @@ const StringView = _misc.StringView;

pub const ExternalTexture = opaque {
pub inline fn addRef(self: *ExternalTexture) void {
wgpuExternalTextureAddRef(self);
raw.call(void, "wgpuExternalTextureAddRef", .{self});
}

pub inline fn release(self: *ExternalTexture) void {
wgpuExternalTextureRelease(self);
raw.call(void, "wgpuExternalTextureRelease", .{self});
}
};

extern fn wgpuExternalTextureAddRef(external_texture: *ExternalTexture) void;
extern fn wgpuExternalTextureRelease(external_texture: *ExternalTexture) void;

pub const ExternalTextureBindingLayout = extern struct {
chain: ChainedStruct = .{
.s_type = .external_texture_binding_layout,
Expand Down Expand Up @@ -94,16 +92,6 @@ pub const BindGroupLayoutDescriptor = extern struct {
entries: [*]const BindGroupLayoutEntry,
};

pub const BindGroupLayoutProcs = struct {
pub const SetLabel = *const fn (*BindGroupLayout, StringView) callconv(.c) void;
pub const AddRef = *const fn (*BindGroupLayout) callconv(.c) void;
pub const Release = *const fn (*BindGroupLayout) callconv(.c) void;
};

extern fn wgpuBindGroupLayoutSetLabel(bind_group_layout: *BindGroupLayout, label: StringView) void;
extern fn wgpuBindGroupLayoutAddRef(bind_group_layout: *BindGroupLayout) void;
extern fn wgpuBindGroupLayoutRelease(bind_group_layout: *BindGroupLayout) void;

pub const BindGroupLayout = opaque {
// Unimplemented as of wgpu-native v29.0.0.0,
// see https://github.com/gfx-rs/wgpu-native/blob/d2e3330ade4ae1bb238d76b485926f067e7ee64c/src/unimplemented.rs
Expand All @@ -112,10 +100,10 @@ pub const BindGroupLayout = opaque {
// }

pub inline fn addRef(self: *BindGroupLayout) void {
wgpuBindGroupLayoutAddRef(self);
raw.call(void, "wgpuBindGroupLayoutAddRef", .{self});
}
pub inline fn release(self: *BindGroupLayout) void {
wgpuBindGroupLayoutRelease(self);
raw.call(void, "wgpuBindGroupLayoutRelease", .{self});
}
};

Expand Down Expand Up @@ -155,16 +143,6 @@ pub const BindGroupDescriptor = extern struct {
entries: [*]const BindGroupEntry,
};

pub const BindGroupProcs = struct {
pub const SetLabel = *const fn (*BindGroup, StringView) callconv(.c) void;
pub const AddRef = *const fn (*BindGroup) callconv(.c) void;
pub const Release = *const fn (*BindGroup) callconv(.c) void;
};

extern fn wgpuBindGroupSetLabel(bind_group: *BindGroup, label: StringView) void;
extern fn wgpuBindGroupAddRef(bind_group: *BindGroup) void;
extern fn wgpuBindGroupRelease(bind_group: *BindGroup) void;

pub const BindGroup = opaque {
// Unimplemented as of wgpu-native v29.0.0.0,
// see https://github.com/gfx-rs/wgpu-native/blob/d2e3330ade4ae1bb238d76b485926f067e7ee64c/src/unimplemented.rs
Expand All @@ -173,9 +151,9 @@ pub const BindGroup = opaque {
// }

pub inline fn addRef(self: *BindGroup) void {
wgpuBindGroupAddRef(self);
raw.call(void, "wgpuBindGroupAddRef", .{self});
}
pub inline fn release(self: *BindGroup) void {
wgpuBindGroupRelease(self);
raw.call(void, "wgpuBindGroupRelease", .{self});
}
};
45 changes: 10 additions & 35 deletions src/buffer.zig
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const CallbackMode = _async.CallbackMode;
const Future = _async.Future;

const ChainedStruct = @import("chained_struct.zig").ChainedStruct;
const raw = @import("raw.zig");

pub const BufferBindingType = enum(u32) {
binding_not_used = 0x00000000, // Indicates that this BufferBindingLayout member of its parent BindGroupLayoutEntry is not used.
Expand Down Expand Up @@ -83,35 +84,9 @@ pub const BufferDescriptor = extern struct {
mapped_at_creation: WGPUBool = @intFromBool(false),
};

pub const BufferProcs = struct {
pub const Destroy = *const fn (*Buffer) callconv(.c) void;
pub const GetConstMappedRange = *const fn (*Buffer, usize, usize) callconv(.c) ?*const anyopaque;
pub const GetMapState = *const fn (*Buffer) callconv(.c) BufferMapState;
pub const GetMappedRange = *const fn (*Buffer, usize, usize) callconv(.c) ?*anyopaque;
pub const GetSize = *const fn (*Buffer) callconv(.c) u64;
pub const GetUsage = *const fn (*Buffer) callconv(.c) BufferUsage;
pub const MapAsync = *const fn (*Buffer, MapMode, usize, usize, BufferMapCallbackInfo) callconv(.c) Future;
pub const SetLabel = *const fn (*Buffer, StringView) callconv(.c) void;
pub const Unmap = *const fn (*Buffer) callconv(.c) void;
pub const AddRef = *const fn (*Buffer) callconv(.c) void;
pub const Release = *const fn (*Buffer) callconv(.c) void;
};

extern fn wgpuBufferDestroy(buffer: *Buffer) void;
extern fn wgpuBufferGetConstMappedRange(buffer: *Buffer, offset: usize, size: usize) ?*const anyopaque;
extern fn wgpuBufferGetMapState(buffer: *Buffer) BufferMapState;
extern fn wgpuBufferGetMappedRange(buffer: *Buffer, offset: usize, size: usize) ?*anyopaque;
extern fn wgpuBufferGetSize(buffer: *Buffer) u64;
extern fn wgpuBufferGetUsage(buffer: *Buffer) BufferUsage;
extern fn wgpuBufferMapAsync(buffer: *Buffer, mode: MapMode, offset: usize, size: usize, callback_info: BufferMapCallbackInfo) Future;
extern fn wgpuBufferSetLabel(buffer: *Buffer, label: StringView) void;
extern fn wgpuBufferUnmap(buffer: *Buffer) void;
extern fn wgpuBufferAddRef(buffer: *Buffer) void;
extern fn wgpuBufferRelease(buffer: *Buffer) void;

pub const Buffer = opaque {
pub inline fn destroy(self: *Buffer) void {
wgpuBufferDestroy(self);
raw.call(void, "wgpuBufferDestroy", .{self});
}

// offset
Expand All @@ -130,7 +105,7 @@ pub const Buffer = opaque {
//
// wgpu-native translates a size of WGPU_WHOLE_MAP_SIZE to "None" internally
pub inline fn getConstMappedRange(self: *Buffer, offset: usize, size: usize) ?*const anyopaque {
return wgpuBufferGetConstMappedRange(self, offset, size);
return raw.call(?*const anyopaque, "wgpuBufferGetConstMappedRange", .{ self, offset, size });
}

// Unimplemented as of wgpu-native v29.0.0.0,
Expand All @@ -153,18 +128,18 @@ pub const Buffer = opaque {
//
// wgpu-native translates a size of WGPU_WHOLE_MAP_SIZE to "None" internally
pub inline fn getMappedRange(self: *Buffer, offset: usize, size: usize) ?*anyopaque {
return wgpuBufferGetMappedRange(self, offset, size);
return raw.call(?*anyopaque, "wgpuBufferGetMappedRange", .{ self, offset, size });
}

pub inline fn getSize(self: *Buffer) u64 {
return wgpuBufferGetSize(self);
return raw.call(u64, "wgpuBufferGetSize", .{self});
}
pub inline fn getUsage(self: *Buffer) BufferUsage {
return wgpuBufferGetUsage(self);
return raw.call(BufferUsage, "wgpuBufferGetUsage", .{self});
}

pub inline fn mapAsync(self: *Buffer, mode: MapMode, offset: usize, size: usize, callback_info: BufferMapCallbackInfo) Future {
return wgpuBufferMapAsync(self, mode, offset, size, callback_info);
return raw.call(Future, "wgpuBufferMapAsync", .{ self, mode, offset, size, callback_info });
}

// Unimplemented as of wgpu-native v29.0.0.0,
Expand All @@ -174,12 +149,12 @@ pub const Buffer = opaque {
// }

pub inline fn unmap(self: *Buffer) void {
wgpuBufferUnmap(self);
raw.call(void, "wgpuBufferUnmap", .{self});
}
pub inline fn addRef(self: *Buffer) void {
wgpuBufferAddRef(self);
raw.call(void, "wgpuBufferAddRef", .{self});
}
pub inline fn release(self: *Buffer) void {
wgpuBufferRelease(self);
raw.call(void, "wgpuBufferRelease", .{self});
}
};
Loading
Loading