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
199 changes: 199 additions & 0 deletions .github/workflows/artifacts.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
name: Target artifacts

on:
workflow_dispatch:
push:
tags:
- "v*"

permissions:
contents: read

jobs:
linux:
name: Linux ${{ matrix.arch }}
strategy:
fail-fast: false
matrix:
include:
- arch: x86_64
runner: ubuntu-latest
zig_target: x86_64-linux-gnu
rust_target: x86_64-unknown-linux-gnu
- arch: aarch64
runner: ubuntu-24.04-arm
zig_target: aarch64-linux-gnu
rust_target: aarch64-unknown-linux-gnu
runs-on: ${{ matrix.runner }}
steps:
- uses: actions/checkout@v4
- uses: mlugg/setup-zig@v2
with:
version: 0.16.0
- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.rust_target }}
- name: Build static and dynamic libraries
run: zig build -Dtarget=${{ matrix.zig_target }} -Doptimize=ReleaseFast -p dist/wgpu-linux-${{ matrix.arch }}
- uses: actions/upload-artifact@v4
with:
name: wgpu-linux-${{ matrix.arch }}
path: dist/wgpu-linux-${{ matrix.arch }}

apple:
name: ${{ matrix.artifact }}
strategy:
fail-fast: false
matrix:
include:
- artifact: wgpu-macos-aarch64
runner: macos-latest
zig_target: aarch64-macos
rust_target: aarch64-apple-darwin
- artifact: wgpu-macos-x86_64
runner: macos-15-intel
zig_target: x86_64-macos
rust_target: x86_64-apple-darwin
- artifact: wgpu-ios-aarch64
runner: macos-latest
zig_target: aarch64-ios
rust_target: aarch64-apple-ios
- artifact: wgpu-ios-aarch64-simulator
runner: macos-latest
zig_target: aarch64-ios-simulator
rust_target: aarch64-apple-ios-sim
- artifact: wgpu-ios-x86_64-simulator
runner: macos-15-intel
zig_target: x86_64-ios-simulator
rust_target: x86_64-apple-ios
runs-on: ${{ matrix.runner }}
steps:
- uses: actions/checkout@v4
- uses: mlugg/setup-zig@v2
with:
version: 0.16.0
- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.rust_target }}
- name: Build static and dynamic libraries
run: zig build -Dtarget=${{ matrix.zig_target }} -Doptimize=ReleaseFast -p dist/${{ matrix.artifact }}
- uses: actions/upload-artifact@v4
with:
name: ${{ matrix.artifact }}
path: dist/${{ matrix.artifact }}

windows:
name: ${{ matrix.artifact }}
strategy:
fail-fast: false
matrix:
include:
- artifact: wgpu-windows-aarch64-msvc
zig_target: aarch64-windows-msvc
rust_target: aarch64-pc-windows-msvc
rust_toolchain: stable-msvc
- artifact: wgpu-windows-x86-msvc
zig_target: x86-windows-msvc
rust_target: i686-pc-windows-msvc
rust_toolchain: stable-msvc
- artifact: wgpu-windows-x86_64-msvc
zig_target: x86_64-windows-msvc
rust_target: x86_64-pc-windows-msvc
rust_toolchain: stable-msvc
- artifact: wgpu-windows-x86_64-gnu
zig_target: x86_64-windows-gnu
rust_target: x86_64-pc-windows-gnu
rust_toolchain: stable-gnu
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: mlugg/setup-zig@v2
with:
version: 0.16.0
- uses: dtolnay/rust-toolchain@stable
with:
toolchain: ${{ matrix.rust_toolchain }}
targets: ${{ matrix.rust_target }}
- name: Build static and dynamic libraries
run: zig build -Dtarget=${{ matrix.zig_target }} -Doptimize=ReleaseFast -p dist/${{ matrix.artifact }}
- uses: actions/upload-artifact@v4
with:
name: ${{ matrix.artifact }}
path: dist/${{ matrix.artifact }}

android:
name: Android ${{ matrix.abi }}
strategy:
fail-fast: false
matrix:
include:
- abi: arm64-v8a
zig_target: aarch64-linux-android
rust_target: aarch64-linux-android
- abi: armeabi-v7a
zig_target: arm-linux-androideabi
rust_target: armv7-linux-androideabi
- abi: x86
zig_target: x86-linux-android
rust_target: i686-linux-android
- abi: x86_64
zig_target: x86_64-linux-android
rust_target: x86_64-linux-android
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: mlugg/setup-zig@v2
with:
version: 0.16.0
- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.rust_target }}
- name: Select Android NDK
shell: bash
run: |
"$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager" --install "ndk;27.0.12077973"
echo "ANDROID_NDK_HOME=$ANDROID_SDK_ROOT/ndk/27.0.12077973" >> "$GITHUB_ENV"
- name: Build static and dynamic libraries
run: zig build -Dtarget=${{ matrix.zig_target }} -Doptimize=ReleaseFast -p dist/wgpu-android-${{ matrix.abi }}
- uses: actions/upload-artifact@v4
with:
name: wgpu-android-${{ matrix.abi }}
path: dist/wgpu-android-${{ matrix.abi }}

ohos:
name: OpenHarmony ${{ matrix.abi }}
strategy:
fail-fast: false
matrix:
include:
- abi: arm64-v8a
zig_target: aarch64-linux-ohos
rust_target: aarch64-unknown-linux-ohos
- abi: armeabi-v7a
zig_target: arm-linux-ohoseabi
rust_target: armv7-unknown-linux-ohos
- abi: x86_64
zig_target: x86_64-linux-ohos
rust_target: x86_64-unknown-linux-ohos
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup OpenHarmony SDK
uses: openharmony-rs/setup-ohos-sdk@v1.0.0
with:
version: "5.0.0"
- name: Setup Zig with OpenHarmony targets
uses: openharmony-zig/setup-zig-ohos@v0.1.1
with:
tag: "0.16.0"
- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.rust_target }}
- name: Compile and link the Zig binding probe
run: zig build --build-file build.tests.zig check -Dtarget=${{ matrix.zig_target }} -Doptimize=ReleaseFast --summary all
- name: Build static and dynamic libraries
run: zig build -Dtarget=${{ matrix.zig_target }} -Doptimize=ReleaseFast -p dist/wgpu-ohos-${{ matrix.abi }}
- uses: actions/upload-artifact@v4
with:
name: wgpu-ohos-${{ matrix.abi }}
path: dist/wgpu-ohos-${{ matrix.abi }}
73 changes: 73 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:

permissions:
contents: read

concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true

jobs:
formatting:
name: Zig 0.16 formatting
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: mlugg/setup-zig@v2
with:
version: 0.16.0
- name: Check formatting
shell: bash
run: |
git ls-files -z '*.zig' '*.zon' | xargs -0 zig fmt --check

native:
name: ${{ matrix.name }}
strategy:
fail-fast: false
matrix:
include:
- name: Linux x86_64
runner: ubuntu-latest
zig_target: x86_64-linux-gnu
rust_target: x86_64-unknown-linux-gnu
- name: macOS arm64
runner: macos-latest
zig_target: aarch64-macos
rust_target: aarch64-apple-darwin
- name: Windows x86_64 MSVC
runner: windows-latest
zig_target: x86_64-windows-msvc
rust_target: x86_64-pc-windows-msvc
runs-on: ${{ matrix.runner }}
steps:
- uses: actions/checkout@v4
- uses: mlugg/setup-zig@v2
with:
version: 0.16.0
- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.rust_target }}
- name: Install Linux Vulkan software driver
if: runner.os == 'Linux'
shell: bash
run: |
sudo apt-get update
sudo apt-get install --yes mesa-vulkan-drivers
- name: Build wgpu-native from source
run: zig build -Dtarget=${{ matrix.zig_target }} -Doptimize=ReleaseFast --summary all
- name: Compile bindings and tests
run: zig build --build-file build.tests.zig check -Dtarget=${{ matrix.zig_target }} -Doptimize=ReleaseFast --summary all
- name: Run native unit tests
run: zig build --build-file build.tests.zig test -Dtarget=${{ matrix.zig_target }} -Doptimize=ReleaseFast -j1 --summary all
- name: Verify prebuilt fallback
env:
WGPU_NATIVE_USE_PREBUILT: "1"
run: zig build --build-file build.tests.zig check -Dtarget=${{ matrix.zig_target }} -Doptimize=ReleaseFast --summary all
99 changes: 96 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ const target = b.standardTargetOptions(.{
```
Or, specify it with your build command. For example, the triangle example in this repository can be run like so:
```sh
zig build run-triangle-example -Dtarget=x86_64-windows-msvc
zig build --build-file build.examples.zig run-triangle-example -Dtarget=x86_64-windows-msvc
```
Either way, pass the resolved target to the dependency like so:
```zig
Expand Down Expand Up @@ -95,6 +95,101 @@ const install_dll = b.addInstallBinFile(dll_path, "wgpu_native.dll");
b.getInstallStep().dependOn(&install_dll.step);
```

## Building `wgpu-native`

`wgpu-native` v25.0.2.1 is built from its pinned source commit by default. The matching
`webgpu-headers` commit is pinned separately, so the generated C ABI does not drift when
an upstream branch changes.

The source build requires Cargo, a Rust toolchain with the selected target installed,
and the platform SDK normally required by that target. For example:

```sh
# Native source build. Installs the static library, dynamic library, and C headers.
zig build -Doptimize=ReleaseFast

# Compile the bindings and link probes without running them.
zig build --build-file build.tests.zig check -Doptimize=ReleaseFast
```

Targets that cannot legally be built on every host still require their native toolchain:
iOS requires Xcode on macOS, MSVC requires Windows, and Android/OpenHarmony require their
respective NDKs.

The root `build.zig` only builds `wgpu-native` and exposes the `wgpu`/`wgpu-c` binding
modules. `build/Library.zig` is the shared library entry point, while
`build/platform/root.zig` dispatches to the Android, Apple, Linux, OpenHarmony, or
Windows build implementation. Tests and examples are isolated behind
`build.tests.zig` and `build.examples.zig`; their implementation stays in the
corresponding directory.

### Using published prebuilt libraries

Set `WGPU_NATIVE_USE_PREBUILT=1` to skip the Cargo source build and use the published
`wgpu-native` archive for the selected target:

```sh
WGPU_NATIVE_USE_PREBUILT=1 zig build --build-file build.tests.zig check \
-Dtarget=x86_64-linux-gnu
```

The equivalent Zig build option is `-Duse_prebuilt=true`. Downstream packages can pass it
while resolving this dependency:

```zig
const wgpu_native_dep = b.dependency("wgpu_native_zig", .{
.target = target,
.optimize = optimize,
.use_prebuilt = true,
});
```

`WGPU_NATIVE_PREBUILT_DIR=/path/to/prefix` uses a local artifact directory and also
implies prebuilt mode. The prefix must use the layout produced by this package:

```text
prefix/
├── include/webgpu/{webgpu.h,wgpu.h}
└── lib/
├── libwgpu_native.a
└── libwgpu_native.so
```

Use the platform-specific dynamic and import-library names on Apple and Windows.
OpenHarmony currently uses this local-directory mechanism when consuming CI artifacts,
because upstream `wgpu-native` does not publish OpenHarmony archives.

### Supported artifact targets

| Platform | Architectures / ABIs | Source build | Published prebuilt |
| --- | --- | --- | --- |
| Android | arm64-v8a, armeabi-v7a, x86, x86_64 | Yes, with `ANDROID_NDK_HOME` | Yes |
| iOS | arm64 device, arm64 simulator, x86_64 simulator | Yes, on macOS | Yes |
| Linux | aarch64, x86_64 (GNU); aarch64, x86_64 (musl) | Yes | GNU targets |
| macOS | aarch64, x86_64 | Yes, on macOS | Yes |
| Windows | aarch64/x86/x86_64 MSVC, x86/x86_64 GNU | Yes, on Windows | All except x86 GNU |
| OpenHarmony | arm64-v8a, armeabi-v7a, x86_64 | Yes, with `OHOS_NDK_HOME` | Local CI artifact |

The OpenHarmony commands are:

```sh
rustup target add \
aarch64-unknown-linux-ohos \
armv7-unknown-linux-ohos \
x86_64-unknown-linux-ohos

zig build --build-file build.tests.zig check \
-Dtarget=aarch64-linux-ohos -Doptimize=ReleaseFast
zig build --build-file build.tests.zig check \
-Dtarget=arm-linux-ohoseabi -Doptimize=ReleaseFast
zig build --build-file build.tests.zig check \
-Dtarget=x86_64-linux-ohos -Doptimize=ReleaseFast
```

The target-artifact workflow builds the complete matrix on Linux x86_64/aarch64, macOS
arm64/Intel, Windows, Android, and OpenHarmony runners. Every artifact prefix contains
both link modes and the matching headers.


## How the `wgpu` module differs from `wgpu-c`
* Names are shortened to remove redundancy.
Expand Down Expand Up @@ -202,14 +297,12 @@ b.getInstallStep().dependOn(&install_dll.step);
* 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`).

## TODO
* Test this on other machines with different OS/CPU. The package requires Zig 0.16.x.
* 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.
* Custom-build `wgpu-native`; provided all the necessary tools/dependencies are present.
* 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.
Loading
Loading