Package Exports
- webgpu-forge
Readme
webgpu-forge
WGSL-aware buffer layout parsing and
ArrayBufferwriting for WebGPU.
Reusable WebGPU utilities with a current focus on WGSL-compatible binding memory layout and ArrayBuffer authoring.
Status
BufferBindingMemory is one of the main APIs currently under active development.
It already covers the core workflow of:
- parsing WGSL
@group(...) @binding(...) var<uniform|storage>declarations - computing the correct layout, alignment, offsets, and padding
- creating
ArrayBufferinstances with the correct byte length - writing plain JavaScript objects / arrays / typed arrays into the buffer
The examples below focus on current API behavior. As more features are added later, the public API surface and documentation will continue to grow.
Install
npm install webgpu-forgeBufferBindingMemory
Source: lib/bindingMemory/BufferBindingMemory.ts
What this API is for
BufferBindingMemory lets you treat a WGSL buffer declaration as a writable memory template.
You provide WGSL source code, then write normal JavaScript data into a correctly aligned ArrayBuffer without manually
calculating offsets, strides, or padding.
Main capabilities
- parse uniform/storage buffer declarations from WGSL
- create buffers with the correct size
- support both fixed-size layouts and runtime-sized arrays
- write scalar / vector / matrix / struct / array data
- accept plain arrays and typed arrays as input
- visualize binding memory layouts in the Node terminal or as a browser canvas
API Overview
new BufferBindingMemory(shaderCode)
Creates a memory helper from WGSL source.
The constructor parses @group/@binding buffer declarations and builds the layout information later used when you call
set.
set(groupBindingName, data, options?)
set() is the primary write API.
It takes a parsed WGSL binding, allocates an ArrayBuffer with the correct size, writes your JavaScript data into it
according to the computed layout, and returns the finished buffer.
Use set() when you want a ready-to-use ArrayBuffer directly from WGSL + JS data.
For runtime-sized arrays, provide one of the following in options:
runtimeArrayCountbyteLength
createLayoutSnapshot(groupBindingName)
createLayoutSnapshot() is the inspection / debugging API for binding memory visualization.
It builds a structured snapshot of the parsed binding layout and then renders it according to the current runtime:
- Node.js: prints a colorized, width-aware terminal visualization automatically
- Web / browser: creates a canvas-based memory board and stores it on
snapshot.image - Unknown runtime: returns the structured snapshot without rendering
The returned snapshot includes information such as:
- binding name
- address space
- total size and alignment
- validation result and issues
- the recursive layout tree (
snapshot.root) - the detected runtime (
snapshot.environment) - an optional canvas image (
snapshot.image) in web environments
Use this API when you want to inspect offsets, padding, stride, array expansion, or validation errors without manually reading the layout tree.
Example 1: fixed-size storage buffer
import {BufferBindingMemory} from "webgpu-forge";
const shaderCode = `
struct Material {
color: vec3f,
intensity: f32,
weights: array<f32, 2>,
transform: mat2x3f,
}
@group(0) @binding(0) var<storage> material: Material;
`;
const memory = new BufferBindingMemory(shaderCode);
const arrayBuffer = memory.set("material", {
color: [1, 2, 3],
intensity: 4,
weights: [5, 6],
transform: [7, 8, 9, 10, 11, 12],
});
const float32 = new Float32Array(arrayBuffer);
console.log(Array.from(float32));
// [
// 1, 2, 3, 4,
// 5, 6, 0, 0,
// 7, 8, 9, 0,
// 10, 11, 12, 0,
// ]Why this is useful
You write normal JS data, and the API inserts the required WGSL padding automatically.
Example 2: runtime-sized array
import {BufferBindingMemory} from "webgpu-forge";
const shaderCode = `
struct PointLight {
position: vec3f,
color: vec3f,
}
struct LightStorage {
pointCount: u32,
point: array<PointLight>,
}
@group(0) @binding(1) var<storage> lights: LightStorage;
`;
const memory = new BufferBindingMemory(shaderCode);
const arrayBuffer = memory.set(
"lights",
{
pointCount: 2,
point: [
{
position: [1, 2, 3],
color: [4, 5, 6],
},
{
position: [7, 8, 9],
color: [10, 11, 12],
},
],
},
{runtimeArrayCount: 2},
);
console.log(arrayBuffer.byteLength); // 80Important note
For runtime-sized arrays, BufferBindingMemory cannot guess the final tail size by itself.
You must tell it the target size using runtimeArrayCount or byteLength.
Example 3: Node terminal visualization
import {BufferBindingMemory} from "webgpu-forge";
const shaderCode = `
struct Camera {
scale: f32,
offset: vec3f,
projection: mat4x4f,
}
@group(0) @binding(0) var<uniform> camera: Camera;
`;
const memory = new BufferBindingMemory(shaderCode);
const snapshot = memory.createLayoutSnapshot("camera");
console.log(snapshot.environment); // "node"
// The terminal visualization is printed automatically when the snapshot is created.This is useful on the server side or in CLI tooling when you want to quickly inspect byte ranges, padding, and validation issues.
Example terminal output:
WGSL Binding Memory Snapshot
binding : camera
address-space : uniform
environment : node
size : 96B
align : 16
validation : ok
memory layout:
tree label kind offset end size align type details path
---- ---------- ------- ------ --- ---- ----- ------- ----------------- -----------------
root camera struct 0 96 96B 16 Camera — camera
├─ scale builtin 0 4 4B 4 f32 — camera.scale
├─ <padding> padding 4 16 12B — — reason=struct-gap —
├─ offset builtin 16 28 12B 16 vec3f — camera.offset
├─ <padding> padding 28 32 4B — — reason=struct-gap —
└─ projection builtin 32 96 64B 16 mat4x4f — camera.projectionExample 4: browser canvas visualization
import {BufferBindingMemory} from "webgpu-forge";
const shaderCode = `
struct Camera {
scale: f32,
offset: vec3f,
projection: mat4x4f,
}
@group(0) @binding(0) var<uniform> camera: Camera;
`;
const memory = new BufferBindingMemory(shaderCode);
const snapshot = memory.createLayoutSnapshot("camera");
if (snapshot.image instanceof HTMLCanvasElement) {
document.body.appendChild(snapshot.image);
}In the browser, snapshot.image contains a memory-board style canvas that helps visualize field bands, offsets,
padding, and expanded array/matrix layout.
Example canvas output:
Typical workflow
const memory = new BufferBindingMemory(shaderCode);
const arrayBuffer = memory.set(groupBindingName, data, options);In most cases, this is the main workflow you need.
Supported input shapes
Current input support includes:
- plain objects for WGSL structs
- arrays / typed arrays for WGSL arrays
- arrays / typed arrays for vectors and matrices
- scalars such as
i32,u32,f32,f16 - atomic scalar writes such as
atomic<u32>
Vec
Source: lib/vector.ts
Vec is a lightweight Float32Array vector helper module.
It focuses on direct 2D / 3D / 4D operations and avoids extra wrapper classes.
Import
import {Vec} from "webgpu-forge";Conventions
- vectors are plain
Float32Array - only
vec2,vec3, andvec4are supported - output parameters are optional; when omitted, a new vector is allocated
- most binary operations require both inputs to have the same dimension
normalize()treats very small vectors as zero vectors
Main APIs
- constructors:
vec2,vec3,vec4 - component-wise ops:
copy,add,sub,mul,div,scale,negate,min,max,clamp,lerp - scalar / geometric ops:
dot,lengthSq,length,distanceSq,distance,normalize,equals - 3D-only op:
cross
Example
import {Vec} from "webgpu-forge";
const a = Vec.vec3(1, 2, 3);
const b = Vec.vec3(4, 5, 6);
const added = Vec.add(a, b);
const unit = Vec.normalize(a);
const normal = Vec.cross(a, b);Mat
Source: lib/mat.ts
Mat provides lightweight column-major matrix helpers built on plain Float32Array.
It currently focuses on 3x3 and 4x4 matrices that work well with transform-style math.
Import
import {Mat} from "webgpu-forge";Conventions
- matrices are plain
Float32Array - storage order is column-major
mat3x3()creates length-9 matrices,mat4x4()creates length-16 matricesidentity()defaults to4x4whenoutis omittedtranslation()is4x4onlyscaling(),rotationX(),rotationY(),rotationZ(), androtation()can write either3x3or4x4depending on whetheroutis a length-9 or length-16 matrix
Main APIs
- creation:
mat3x3,mat4x4,identity - transforms:
translation,scaling,rotationX,rotationY,rotationZ,rotation - matrix ops:
copy,add,sub,scale,transpose,multiply - matrix-vector op:
multiplyVector
rotation() input shapes
rotation() accepts one of these objects:
- Euler rotation:
{ x, y, z, order? } - Quaternion rotation:
{ x, y, z, w }
Notes:
- Euler angles are in radians
- supported rotation orders are
xyz,xzy,yxz,yzx,zxy,zyx - quaternion input is normalized internally before conversion to a matrix
Example
import {Mat, Vec} from "webgpu-forge";
const model = Mat.rotation({x: 0, y: Math.PI / 2, z: 0});
const translated = Mat.translation(4, 5, 6);
const combined = Mat.multiply(translated, model);
const position = Vec.vec4(1, 2, 3, 1);
const worldPosition = Mat.multiplyVector(combined, position);Future expansion
This README intentionally treats BufferBindingMemory as a foundational API.
As the project grows, more capabilities may be added around it, for example:
- more binding-memory helpers
- more serialization / update utilities
- richer TypeScript typing for input data
- higher-level WebGPU integration examples
Chinese documentation
Development
npm install
npm run dev
npm run typecheck
npm run test:run
npm run buildPublish checklist
- Update
name/versioninpackage.json - Run
npm run buildand confirmdist/contains.js,.cjs, and.d.tsoutputs - Publish the package