eskiuv0.14.1
Package · eskiu-lang/gpu · v0.3.0

Compute, graphics and machine learning on the GPU

Kernels, PBR models, LLM inference and training over WebGPU. One API for Metal, Vulkan and DirectX 12, on desktops and phones, with shaders in WGSL.

The DamagedHelmet glTF model, drawn by Eskiu's gpu package with physically based shading
45 tok/sLlama 2 7B Q4_0 on an Apple M4 Pro
97%MNIST test accuracy in three epochs
5 platformsmacOS, Linux, Windows, iOS and Android
MITOpen source

A kernel is a string of WGSL

Storage buffers, kernels and dispatches, with the results read back into Eskiu memory. Every call that can fail returns a Result with the message from WebGPU's validation layer, and a WGSL error comes with its line and column.

Underneath, <gpu/raw> is all of webgpu.h and wgpu.h, generated, with every struct's layout checked against the C compiler.

import <io>;
import <gpu>;

string twice = "@group(0) @binding(0) var<storage, read_write> v: array<f32>;\n"
    "@compute @workgroup_size(64)\n"
    "fn main(@builtin(global_invocation_id) id: vec3<u32>) {\n"
    "    v[id.x] = v[id.x] * 2.0;\n"
    "}\n";

Result<int, string> run() {
    float[256] data;
    for (i in 0..256) data[i] = (float)i;
    Gpu gpu = gpu_open()?;
    defer gpu.release();
    GpuBuffer v = gpu.storage(&data, sizeof(data))?;
    defer v.release();
    GpuKernel k = gpu.kernel(twice, "main")?;
    defer k.release();
    k.bind(0, &v);
    k.dispatch(4, 1, 1)?;
    v.read(&data, sizeof(data))?;
    printf("%.1f\n", (double)data[255]);   // 510.0
    return Ok<int, string>(0);
}

3D models, the format of AR and VR

<gpu/gltf> loads glTF 2.0 (.gltf and .glb) and <gpu/obj> Wavefront OBJ with its MTL materials, and <gpu/model> draws either with physically based shading, normal maps, alpha modes, skinning and animation.

PNG and JPEG (baseline and progressive) decode in pure Eskiu, and textures can be sRGB and mipmapped. <gpu/window> opens a window over SDL3 with its keyboard and mouse.

Gltf data = model_load("helmet.glb")?;   // or a .gltf, or an .obj
defer data.free();
GpuModel model = gpu.model(&data, surface.format)?;
defer model.release();

// every frame
data.animate(0, seconds);
model.update(mat4_identity());
GpuCamera cam = model.camera(aspect);
GpuPass pass = gpu.pass(frame.view, GpuColor{0.1, 0.1, 0.1, 1.0}, &depth);
model.draw(&pass, &cam);
pass.end()?;
The DamagedHelmet model from the front, with its emissive visor
DamagedHelmet by theblueturtle_ (CC BY 4.0), from the Khronos glTF sample assets.

Machine learning on the GPU

<gpu/nn> runs transformer inference from GGUF, safetensors and llama2.c files. The Llama 2 example records the forward pass once and replays it as one compute pass per token, in f32, f16, Q8_0 and Q4_0.

ModelEskiuReference
stories110M (llama2.c, f16)350 tokens/sllama2.c on the CPU: 22
TinyLlama 1.1B Q4_0178 tokens/sllama.cpp (Metal): 260
Llama 2 7B Q4_045 tokens/sllama.cpp (Metal): 58

Apple M4 Pro, greedy decoding. The outputs match llama2.c byte for byte, and llama.cpp and Hugging Face transformers token for token, on the prompts tested.

Training with automatic differentiation

<gpu/train> builds a graph of operations and records the gradients of each one. The MNIST example reaches 97% test accuracy in three epochs of about 0.4 seconds, and saves the weights as safetensors that PyTorch loads with the same accuracy.

NnGraph g = gpu.nn_graph(100)?;
NnVar x = g.input(784);
NnVar labels = g.labels();
NnVar h = g.relu(g.bias(g.matmul(x, g.param(784, 128, 0.05)), g.param(1, 128, 0.0)));
NnVar logits = g.bias(g.matmul(h, g.param(128, 10, 0.125)), g.param(1, 10, 0.0));
NnVar loss = g.cross_entropy(logits, labels);
g.backward(loss)?;   // the gradients of every operation
g.adam(0.001);       // and the optimizer step

Where it runs

The GPU modules go through wgpu-native, on desktops and phones. In an eskiu-lang/ui app, <gpu/ui> mounts a GpuView to draw into (a CAMetalLayer on iOS, a SurfaceView on Android). In a browser WebGPU is the browser's own, which cannot block on the GPU, so the GPU modules are planned there. The rest is plain Eskiu and runs on every target.

PlatformBackend
macOS arm64Metal
Linux x86-64Vulkan
Windows x86-64DirectX 12, Vulkan
iOS (arm64, simulator)Metal
Android (arm64, x86-64)Vulkan
WebAssemblyThe pure Eskiu modules (glTF, OBJ, images, GGUF, safetensors, math) today; the GPU modules are planned

Get started

The package names wgpu-native's release archives in its manifest: the first build downloads the one for your machine, checks its SHA-256 and links it. A desktop window also needs SDL3 (brew install sdl3 on macOS). It needs Eskiu 0.14 or newer.

eskiuc new myapp && cd myapp
eskiuc add gpu --git https://github.com/eskiu-lang/gpu --rev v0.3.0
eskiuc build

Put the GPU to work.

The README has every module, with the platforms and what is not supported yet.