Skip to content

TypeScript SDK

The wave-gpu npm package provides a TypeScript-first interface for compiling and launching GPU kernels through the WAVE toolchain. This guide covers installation, device detection, buffer management, kernel compilation, dispatch, and error handling.

Requires Node.js 18 or later.

Terminal window
npm install wave-gpu

Import the module:

import { array, zeros, ones, device, kernel } from "wave-gpu";

device() is async and returns a Promise<DeviceInfo>:

const dev = await device();
console.log(dev.vendor); // e.g. "Apple"
console.log(dev.name); // e.g. "Apple M2 Max"

The promise rejects if no GPU is found.

WaveArray is the buffer type used to transfer data between the host and the GPU. Create one with the factory functions:

// From existing data
const a = array([1.0, 2.0, 3.0, 4.0], "f32");
// Pre-filled buffers
const z = zeros(1024, "f32");
const o = ones(1024, "u32");

Supported DType values: "f16", "f32", "f64", "i32", "u32".

WaveArray exposes the following members:

MemberDescription
dataRaw underlying data
dtypeElement type string
lengthNumber of elements
toArray()Copy contents to a JavaScript array
toBuffer()Copy contents to a Node.js Buffer

Call kernel() with a source string and an optional language identifier. The default language is "typescript":

const src = `
import wave_gpu
@wave_gpu.kernel
def vector_add(a, b, out, n):
tid = wave_gpu.thread_id()
if tid < n:
out[tid] = a[tid] + b[tid]
`;
const vectorAdd = kernel(src, "python");

Supported language values: "python", "rust", "cpp", "typescript".

When the language argument is omitted the source is parsed as TypeScript:

const tsKernel = kernel(`
export function add(a: WaveArray, b: WaveArray, out: WaveArray, n: number) {
const tid = thread_id();
if (tid < n) {
out[tid] = a[tid] + b[tid];
}
}
`);

CompiledKernel.launch() is async. It takes the device, buffer and scalar arrays, and optional grid/workgroup dimensions:

const n = 1024;
const a = array(Float32Array.from({ length: n }, (_, i) => i), "f32");
const b = ones(n, "f32");
const out = zeros(n, "f32");
const dev = await device();
// Launch with explicit grid and workgroup
await vectorAdd.launch(dev, [a, b, out], [n], [n / 256, 1, 1], [256, 1, 1]);
// Grid and workgroup are optional - WAVE can infer defaults
await vectorAdd.launch(dev, [a, b, out], [n]);

The grid and workgroup parameters are 3-element arrays representing [x, y, z] dimensions.

After the launch promise resolves, read data back on the host:

const result = out.toArray();
console.log(result.slice(0, 4)); // [1, 2, 3, 4]

For interop with Node.js APIs you can also get a Buffer:

const buf = out.toBuffer();

All async operations (device(), launch()) signal failures through promise rejection. Use try/catch with async/await or .catch() on the promise:

try {
const dev = await device();
await vectorAdd.launch(dev, [a, b, out], [n]);
} catch (err) {
console.error("WAVE error:", err);
}

Synchronous errors (e.g. passing the wrong number of arguments to kernel()) throw immediately.

See the full TypeScript API Reference for detailed type definitions, interfaces, and advanced configuration.