ZenGPU is a pre-alpha GPU runtime for Rust. It provides a shared device model for graphics and general compute: buffers, textures, shaders, compute pipelines, render targets, surfaces, and command recording use the same backend foundation.
Version 0.0.1 is pre-alpha. APIs are expected to change before 0.1.0.
- A backend-independent HAL with typed generational handles, resource descriptors, structured errors, and object-safe compute traits.
- A split graphics contract for graphics-capable devices: surfaces, frames, render targets, graphics pipelines, and allocation-conscious command lists that record directly into backend command buffers.
- Vulkan 1.2 graphics and compute through
zengpu-vulkan. - Vulkan swapchains, offscreen targets, depth targets, and a lightweight frame graph with automatic image-layout barriers.
- Same-device zero-copy handoff from rendered targets to sampled-image slots.
- Compute-only backends for HIP/ROCm (
zengpu-hip) and CUDA (zengpu-cuda), plus a native Metal backend (zengpu-metal, graphics and compute, macOS/ iOS), all driven from the same ZSL source. A DirectX 12 backend (zengpu-dx12) exists as an inert skeleton. - A deterministic CPU backend used for conformance tests.
DeviceArray, pooled allocation,f32add/ReLU kernels, and portablef32GEMM.- Small SPIR-V tooling for disassembly and structural diagnostics during shader bring-up.
zengpu_spirv!, a shader macro that can compile GLSL throughinline-spirvor ZSL through the local Rust-flavored shader pipeline. ZSL compiles to SPIR-V, HIP C++, CUDA C++, and MSL from one source, with a unified type system (u32/i32/f32/bf16/f16buffer storage), typed bindless storage buffers, and subgroup/workgroup cooperative reductions (subgroup_reduce_*,subgroup_shuffle_*,workgroup_reduce_*) for cross-lane and cross-workgroup math.
ZenGPU does not include scene, ECS, asset, editor, tensor-graph, or application types. Consumer crates define planning and presentation policy; ZenGPU provides execution, resources, synchronization, and backend translation.
The default feature set enables Vulkan and compute helpers:
[dependencies]
zengpu = "0.0.1"Feature flags:
vulkan(default): Vulkan graphics and compute backend.compute(default):DeviceArray,BufferPool, and elementwise kernels.blas: portable GEMM; impliescompute.cpu: CPU reference backend for conformance tests.hip: HIP/ROCm compute backend.cuda: CUDA compute backend.metal: native Metal compute/graphics backend (macOS).dx12: DirectX 12 backend (currently an inert skeleton).
Foundation-only users can disable defaults:
zengpu = { version = "0.0.1", default-features = false }Vulkan runs on macOS through MoltenVK:
brew install vulkan-loader molten-vk
# Put the loader on macOS's default dylib search path (one-time, no sudo):
ln -sf /opt/homebrew/lib/libvulkan.dylib /usr/local/lib/libvulkan.dylib
ln -sf /opt/homebrew/lib/libvulkan.1.dylib /usr/local/lib/libvulkan.1.dylibAfter that, examples and tests run with no extra env (the Homebrew loader auto-discovers the MoltenVK ICD):
cargo run --release --example cubeThe native Apple Metal backend (metal feature) needs no setup.
This round-trips a host-visible buffer through the backend-independent device interface:
use zengpu::{
AdapterRequest, BufferDesc, BufferUsage, DeviceRequest, GpuAdapter, GpuInstance,
MemoryUsage, VulkanInstance,
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let instance = VulkanInstance::new()?;
let adapter = instance
.request_adapter(AdapterRequest::default())
.ok_or("no Vulkan adapter")?;
let device = adapter.open(DeviceRequest::default())?;
let buffer = device.create_buffer(BufferDesc {
size: 4,
usage: BufferUsage::STORAGE | BufferUsage::READBACK,
memory: MemoryUsage::Upload,
})?;
device.write_buffer(buffer, 0, &[1, 2, 3, 4])?;
assert_eq!(device.read_buffer(buffer, 0, 4)?, [1, 2, 3, 4]);
device.destroy_buffer(buffer);
Ok(())
}The zengpu_spirv! macro accepts either GLSL or ZSL.
use zengpu::zengpu_spirv;
const VERT: &[u32] = zengpu_spirv!(
r#"
#version 450
void main() { gl_Position = vec4(0.0); }
"#,
vert,
vulkan1_0
);ZSL is a Rust-flavored shader language compiled by zengpu-zsl — from one ZSL
source, zsl! produces SPIR-V (Vulkan), HIP C++ (ROCm), CUDA C++ (NVIDIA), and
MSL (Metal) simultaneously; pick the right compiled form for the active
backend at runtime with ZslShader::for_backend.
This ZSL compute kernel scales one buffer into another:
use zengpu_spirv::zsl;
const SCALE_ZSL: ZslShader = zsl!(
push Push { n: u32, scale: f32 }
@workgroup_size(64)
kernel scale(
p: Push,
src: device buffer<f32>,
dst: device mut buffer<f32>,
id: global_id,
) {
let i = id.x
if i < p.n {
dst[i] = src[i] * p.scale
}
}
);The equivalent GLSL uses ZenGPU's bindless storage-buffer table and push constants explicitly:
const SCALE_GLSL: &[u32] = zengpu_spirv!(
r#"
#version 450
layout(local_size_x = 64) in;
layout(set = 0, binding = 0) buffer Buf { float data[]; } g_bufs[];
layout(push_constant) uniform Push {
uint src;
uint dst;
uint len;
float scale;
} pc;
void main() {
uint i = gl_GlobalInvocationID.x;
if (i < pc.len) {
g_bufs[pc.dst].data[i] = g_bufs[pc.src].data[i] * pc.scale;
}
}
"#,
comp,
vulkan1_0
);ZSL supports compute, vertex, and fragment entry points; typed bindless
storage buffers (u32/i32/f32/bf16/f16); push constants; scalars,
vectors, and matrices; arithmetic and comparisons; if/for control flow;
workgroup-shared memory and barriers; atomics; and subgroup/workgroup
collectives (subgroup_reduce_add/min/max/and/or, subgroup_scan_inclusive/ exclusive_add, subgroup_shuffle*, subgroup_any/all/ballot,
workgroup_reduce_add/min/max) for cooperative cross-lane and
cross-workgroup reductions. It remains smaller than GLSL/HLSL in absolute
feature count (no user-defined structs, modules, or recursion yet) but covers
real compute and graphics workloads today, not just experimentation.
Run examples from the ZenGPU directory:
cargo run --example vec_add
cargo run --example op_graph_lower
cargo run --release --example heavy_compute
cargo run --example cubevec_add: upload buffers, dispatch a bindless compute shader, read results.op_graph_lower: shows how a consumer graph could lower toDeviceArray, elementwise kernels, and GEMM.heavy_compute: sustained GEMM workload for checking the compute path under heavier GPU use; tune withZENGPU_HEAVY_DIMandZENGPU_HEAVY_REPS.cube: create a Vulkan surface and render a windowed graphics workload.
| Crate | Purpose |
|---|---|
zengpu |
Main facade and recommended dependency |
zengpu-hal |
Backend-independent types, handles, traits, descriptors, and errors |
zengpu-vulkan |
Vulkan 1.2 graphics and compute backend |
zengpu-hip |
HIP/ROCm compute backend |
zengpu-cuda |
CUDA compute backend |
zengpu-metal |
Native Metal compute/graphics backend |
zengpu-dx12 |
DirectX 12 backend (inert skeleton) |
zengpu-cpu |
CPU reference backend |
zengpu-compute |
Resident arrays, pooling, and elementwise kernels |
zengpu-blas |
Portable GEMM kernel |
zengpu-conformance |
Cross-backend conformance harness |
zengpu-spirv |
Public shader macro and push-constant helpers |
zengpu-spv |
SPIR-V decoding, disassembly, and structural validation |
zengpu-zsl |
ZSL parsing and lowering to SPIR-V, HIP, CUDA, and MSL |
Most users should depend on zengpu. The subcrates are available for backend
work, conformance, or macro internals.
- ZenGPU executes work; higher layers decide what work should exist and in what application-level order.
- Graphics consumers bring their own windows, renderers, painters, scenes, text systems, and asset models.
- Compute consumers bring their own tensors, graphs, schedulers, and fusion policies.
- Public APIs stay backend-neutral. Vulkan is the first backend, not the shape every caller must copy.
- Vulkan and Metal are the only backends with graphics support; HIP and CUDA
are compute-only. DirectX 12 is an inert skeleton (no device creation yet).
ZSL's SPIR-V bf16/f16 typed storage is not yet implemented (HIP/CUDA/MSL
already have it);
dot_f32and workgroupany/all/scan are not yet implemented on any backend. - Dispatch and readback are synchronous.
- Built-in elementwise and GEMM kernels support
f32only (ZSL itself has wider type support:u32/i32/bf16/f16storage). - The CPU backend is intended for correctness testing rather than production fallback use.
- ZSL has no user-defined structs, modules, or recursion yet; GLSL remains
available through
inline-spirvfor anything outside ZSL's current scope. - Async readback, deferred destruction, and broader memory-pool policy are planned optimization areas.
- Resource synchronization and lifetime validation are still being expanded.
- Vulkan requires a Vulkan 1.2-capable driver with descriptor indexing.
Licensed under the Apache License, Version 2.0.