KO
|
EN
gitlite — search
Search
#javascript
#python
#hacktoberfest
#react
#ai
#typescript
#llm
#go
#golang
#android
#machine-learning
#rust
#deep-learning
#linux
wgpu-mojo
★ 9
Open GitHub ↗
No description available.
Download README (.md)
Explore Similar Repositories
math
:
Professional LaTeX notes, past paper solutions & midterm papers for BS Mathematics — Calculus, Linear Algebra, Fluid Dynamics, Biology, Numerical Analysis & more
beagleconnect-zepto
:
Mirror of https://openbeagle.org/beagleconnect/zepto
steer-like-the-llm
:
(ICML'26 spotlight): Steer Like the LLM: Activation Steering that Mimics Prompting
Hoc-han-tu
:
Vibe code 1 chiếc tool hỗ trợ học từ vựng Hán tự
mashq2_0407
:
No description available.
// repository documentation
Was this content helpful?
★ 0
(0 ratings)
Select Rating:
★
★
★
★
★
Submit Feedback
Recent Feedback
×
Download README
Do you want to download the
README.md
file for
wgpu-mojo
?
Download (.md)
<div align="center"> # wgpu-mojo **WebGPU for [Mojo](https://www.modular.com/mojo) — pure bindings to [wgpu-native](https://github.com/gfx-rs/wgpu-native), with RAII GPU objects and a 5-line compute facade.** [](https://github.com/Hundo1018/wgpu-mojo/actions/workflows/ci.yml) [](https://github.com/Hundo1018/wgpu-mojo/actions/workflows/consume.yml) [](https://raw.githubusercontent.com/Hundo1018/wgpu-mojo/main/LICENSE) [](https://raw.githubusercontent.com/Hundo1018/wgpu-mojo/main/) [](https://github.com/gfx-rs/wgpu-native) Compute *and* graphics on every backend Vulkan / Metal / DX12 supports — from a single Mojo program. </div> <table> <tr> <td width="33%"><img src="assets/plasma.gif" alt="animated plasma" width="100%"></td> <td width="33%"><img src="assets/metaballs.gif" alt="2D SDF metaballs" width="100%"></td> <td width="33%"><img src="assets/raymarch.gif" alt="raymarched 3D SDF" width="100%"></td> </tr> <tr> <td align="center"><code>example-plasma</code><br/>fullscreen fragment shader</td> <td align="center"><code>example-metaballs</code><br/>2D signed distance fields</td> <td align="center"><code>example-raymarch</code><br/>raymarched 3D SDF</td> </tr> </table> --- ## Why wgpu-mojo - **Pure Mojo** — no Python in the hot path. `from wgpu import …` resolves at compile time. - **RAII by default** — every GPU object frees its native handle when it goes out of scope. - **Two altitudes** — a [low-level API](#api-reference) that maps 1:1 to `webgpu.h`, and a [`GPU` facade](#your-first-program-gpu-compute) that does compile + dispatch + read-back in a handful of lines. - **Windows too** — [`RenderCanvas`](examples/triangle_window.mojo) wraps GLFW so the same device drives an interactive surface. - **Verified downstream** — CI installs the package into a fresh project on every push, so the [quickstart below](#quickstart) is exactly what runs in CI. --- ## Quickstart Use wgpu-mojo as a package in your own [pixi](https://pixi.sh) project — three steps. ### 1 · Point pixi at the right channels ```toml # pixi.toml [workspace] channels = ["https://conda.modular.com/max", "conda-forge"] preview = ["pixi-build"] ``` ### 2 · Add the package ```bash pixi add --git https://github.com/Hundo1018/wgpu-mojo wgpu-mojo ``` This builds `wgpu.mojopkg` and installs it into your environment. ### 3 · Install the native GPU library (once per machine) The package needs `libwgpu_native` + its callback bridge at runtime. Run this inside your activated pixi env: ```bash curl -fsSL https://raw.githubusercontent.com/Hundo1018/wgpu-mojo/main/scripts/setup-native.sh | bash ``` <details> <summary>What the script does</summary> - Downloads `libwgpu_native` **v29** from [wgpu-native releases](https://github.com/gfx-rs/wgpu-native/releases) - Compiles the Mojo callback bridge `libwgpu_mojo_cb` from source - Installs both into `$CONDA_PREFIX/lib/` - Compiles the GLFW window bridge `libglfw_input_cb` if GLFW is present - Requires `curl`, `unzip`, `gcc` — all standard in a conda environment </details> ### Check it works `mojo` has no `-c` flag, so write a one-file smoke test and run it: ```bash cat > wgpu_check.mojo <<'EOF' from wgpu import Instance def main() raises: _ = Instance() print("wgpu-mojo OK") EOF pixi run mojo run wgpu_check.mojo ``` --- ## Your first program: GPU compute Vector addition on the GPU, read back to the CPU — using the high-level `GPU` facade (no manual bind groups, pipeline layouts, or lifetime pins): ```mojo from wgpu.gpu import GPU from wgpu import WGPUBufferUsage comptime N = 1024 comptime ADD_WGSL = """ @group(0) @binding(0) var<storage, read> a : array<f32>; @group(0) @binding(1) var<storage, read> b : array<f32>; @group(0) @binding(2) var<storage, read_write> c : array<f32>; @compute @workgroup_size(64) fn main(@builtin(global_invocation_id) gid: vec3<u32>) { let i = gid.x; if i < arrayLength(&a) { c[i] = a[i] + b[i]; } } """ def main() raises: var gpu = GPU.wgpu() var a = gpu.buffer[Float32](N, WGPUBufferUsage.STORAGE | WGPUBufferUsage.COPY_DST) var b = gpu.buffer[Float32](N, WGPUBufferUsage.STORAGE | WGPUBufferUsage.COPY_DST) var c = gpu.buffer[Float32](N, WGPUBufferUsage.STORAGE | WGPUBufferUsage.COPY_SRC) var xs = List[Float32](capacity=N) var ys = List[Float32](capacity=N) for i in range(N): xs.append(Float32(i)) ys.append(Float32(i) * 2.0) gpu.write(a, xs) gpu.write(b, ys) var prog = gpu.compile_compute(ADD_WGSL, entry_point="main", n_storage_buffers=3) gpu.dispatch(prog^, [a.handle(), b.handle(), c.handle()], N // 64) var result = gpu.read[Float32](c) print(result[0], result[1], result[2]) # 0.0 3.0 6.0 ``` Full source: [`examples/compute_add_v2.mojo`](examples/compute_add_v2.mojo) · runs with `pixi run example-compute-v2`. --- ## Examples | Run | Window? | Shows | |-----|:------:|-------| | `pixi run example-compute-v2` | – | Vector add via the `GPU` facade (start here) | | `pixi run example-compute` | – | Same, spelled out with the low-level API | | `pixi run example-enumerate` | – | List every GPU adapter / backend | | `pixi run example-clear` | ✓ | Cornflower-blue window — minimal GPU smoke test | | `pixi run hello` · `example-triangle` | ✓ | The classic RGB "hello triangle" | | `pixi run example-plasma` | ✓ | **Fragment-shader host** — edit one WGSL `shade` function to make art | | `pixi run example-metaballs` | ✓ | 2D signed-distance fields (metaballs) | | `pixi run example-raymarch` | ✓ | Raymarched 3D SDF scene (camera orbit + lighting) | | `pixi run example-texture-sample` | ✓ | Texture + sampler on a fullscreen quad | | `pixi run example-fire-sim` | ✓ | Doom-style fire: compute + render ping-pong | | `pixi run example-input` | ✓ | GLFW keyboard / mouse polling | ### Make your own shader in 60 seconds [`examples/plasma.mojo`](examples/plasma.mojo) is a fullscreen fragment-shader host that hands your WGSL a small set of uniforms — `resolution`, `time`, `mouse`, `frame`. Copy it, edit only the `shade` function, and climb the ladder: **plasma → [2D SDF](examples/metaballs.mojo) → [raymarching](examples/raymarch.mojo)**. > The three GIFs above are rendered headlessly on the GPU and read back frame by > frame (`pixi run render-gifs`) — not screen-recorded, because the wgpu surface > presents via a GPU flip that screen grabbers can't capture. ```wgsl fn shade(frag_coord: vec2<f32>) -> vec3<f32> { let uv = frag_coord / U.resolution.xy; return vec3<f32>(uv, 0.5 + 0.5 * sin(U.time)); } ``` ### Hello triangle (windowed) ```mojo from wgpu.instance import Instance from wgpu._ffi.structs import WGPUColor from wgpu.rendercanvas import RenderCanvas def main() raises: var instance = Instance() var adapter = instance.request_adapter() var device = adapter.request_device() var canvas = RenderCanvas(adapter, device, 800, 600, "hello triangle") var shader = device.create_shader_module_wgsl(TRIANGLE_WGSL, "tri") var pl = device.create_pipeline_layout(List[OpaquePointer[MutUntrackedOrigin]](), "layout") var pipeline = device.create_render_pipeline( shader, "vs_main", "fs_main", canvas.surface_format(), pl, primitive_topology=UInt32(4), # TriangleStrip ) while canvas.is_open(): canvas.poll() var frame = canvas.next_frame() if not frame.is_renderable(): continue var enc = device.create_command_encoder("frame") var rpass = enc.begin_surface_clear_pass( frame.texture, WGPUColor(Float64(0), Float64(0), Float64(0), Float64(1)), "pass", ) rpass.set_pipeline(pipeline) rpass.draw(UInt32(3), UInt32(1), UInt32(0), UInt32(0)) rpass^.end() device.queue_submit(enc^.finish()) canvas.present() ``` Full source (with the WGSL): [`examples/triangle_window.mojo`](examples/triangle_window.mojo). --- ## API reference Every type is re-exported from `wgpu`, so `from wgpu import Instance` always works. | Module | Provides | |--------|----------| | `wgpu.gpu` | **`GPU`** — high-level facade: `buffer`, `write`, `compile_compute`, `dispatch`, `read` | | `wgpu.instance` | `Instance` — entry point, adapter selection | | `wgpu.adapter` | `Adapter` — device creation | | `wgpu.device` | `Device` — factory for every GPU object, submits work | | `wgpu.buffer` | `Buffer` — GPU memory, mapping, typed read-back | | `wgpu.texture` | `Texture`, `TextureView` | | `wgpu.shader` | `ShaderModule` — WGSL compilation | | `wgpu.pipeline` | `ComputePipeline`, `RenderPipeline` | | `wgpu.command` | `CommandEncoder`, `CommandBuffer` | | `wgpu.compute_pass` · `wgpu.render_pass` | `ComputePassEncoder`, `RenderPassEncoder` | | `wgpu.bind_group` | `BindGroup`, `BindGroupLayout` (+ `BGL` entry helpers) | | `wgpu.rendercanvas` | `RenderCanvas` — GLFW window + surface | | `wgpu.diagnostics` | `preflight()` — library load status + adapter list | ### Lifetimes & ownership Wrappers are RAII — GPU objects free themselves at end of scope. Two rules to remember (both handled for you by the `GPU` facade): ```mojo # 1 — encoders must be explicitly finished: var enc = device.create_command_encoder("enc") var cpass = enc.begin_compute_pass("pass") cpass^.end() # consume the pass device.queue_submit(enc^.finish()) # 2 — pin resources that must outlive an async GPU call: device.queue_submit(cmd) _ = pipeline^ # prevent ASAP-drop before the GPU finishes _ = bind_group^ device.poll(True) ``` --- ## Develop locally (clone the repo) ```bash git clone https://github.com/Hundo1018/wgpu-mojo cd wgpu-mojo pixi run build-callbacks # download wgpu-native + compile the C bridges pixi run test # non-GPU unit tests (no hardware needed) pixi run check-compile # compile-check every test & example pixi run hello # GPU smoke test — RGB triangle window ``` `build-callbacks` does the same job as `setup-native.sh`, but reads the native version from [`ffi/wgpu-native-meta/wgpu-native-git-tag`](ffi/wgpu-native-meta/wgpu-native-git-tag) and uses the bridge sources already in the repo. See [`docs/CI_CD.md`](docs/CI_CD.md) for the full CI/release pipeline. ### Drivers & platforms | Platform | GPU driver | |----------|-----------| | **Linux** (`linux-64`) | Vulkan: `mesa-vulkan-drivers` + `libvulkan1`, or NVIDIA proprietary | | **macOS** (`osx-arm64`) | Metal — built in, nothing to install | | **Windows** | D3D12 or Vulkan — usually present with vendor drivers | `linux-64` and `osx-arm64` are first-class via pixi. `osx-x86_64` / `win-x64` can be built manually — see [`conda.recipe/recipe.yaml`](conda.recipe/recipe.yaml). ### Diagnostics ```mojo from wgpu.diagnostics import preflight print(preflight()) # search paths, load status, wgpu-native version, adapters ``` --- ## License [Apache-2.0](LICENSE)