npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

webgpu-forge

v1.1.0

Published

WGSL-aware WebGPU binding memory layout and ArrayBuffer writing utilities.

Readme

webgpu-forge

一个面向 WebGPU 的工具库,当前重点是 WGSL 兼容的 binding memory layout 解析ArrayBuffer 数据写入

当前状态

BufferBindingMemory 是目前正在持续完善的核心 API 之一,已经覆盖以下基础流程:

  • 解析 WGSL 中的 @group(...) @binding(...) var<uniform|storage> 资源声明
  • 计算正确的布局、对齐、偏移和 padding
  • 创建大小正确的 ArrayBuffer
  • 把普通 JavaScript 对象 / 数组 / TypedArray 写入 buffer

下面的示例重点展示当前 API 的作用和使用方式。后续随着功能继续增加,公开 API 和文档内容还会继续扩展。

安装

npm install webgpu-forge

BufferBindingMemory

源码位置:lib/bindingMemory/BufferBindingMemory.ts

这个 API 是做什么的

BufferBindingMemory 的作用是:把一段 WGSL buffer 声明当成“可写入的内存模板”
你只需要提供 WGSL 源码,再传入普通 JavaScript 数据,就可以得到一个已经按 WGSL 布局规则正确写好的 ArrayBuffer,不需要手动计算 offset、stride 和 padding。

主要能力

  • 解析 WGSL 中的 uniform / storage buffer 声明
  • 创建大小正确的 ArrayBuffer
  • 支持定长布局和 runtime-sized array
  • 支持 scalar / vector / matrix / struct / array 写入
  • 支持普通数组和 TypedArray 作为输入
  • 支持在 Node 终端或浏览器 canvas 中可视化 binding memory 布局

API 总览

new BufferBindingMemory(shaderCode)

用一段 WGSL 源码创建内存辅助对象。
构造函数会解析其中的 @group/@binding buffer 声明,并建立后续调用 set 时需要使用的 layout 信息。


set(groupBindingName, data, options?)

set() 是主要的写入 API。
它会根据解析出的 WGSL binding layout 创建大小正确的 ArrayBuffer,再按照布局规则把你传入的 JavaScript 数据写进去,最后返回这个已经写好的 buffer。

如果你希望直接通过 WGSL + JS 数据拿到一个可用的 ArrayBuffer,优先使用 set()

对于 runtime-sized array,需要在 options 中提供以下之一:

  • runtimeArrayCount
  • byteLength

createLayoutSnapshot(groupBindingName)

createLayoutSnapshot() 是查看 / 调试 binding memory 布局的可视化 API。 它会先构建一份结构化的 layout snapshot,然后根据当前运行环境自动选择渲染方式:

  • Node.js:自动输出带颜色、会根据终端宽度裁剪的终端可视化
  • Web / 浏览器:生成 canvas 版 memory board,并放到 snapshot.image
  • 未知环境:只返回结构化 snapshot,不做渲染

返回的 snapshot 里会包含这些信息:

  • binding 名称
  • address space
  • 总大小和对齐
  • validation 结果与 issues
  • 递归布局树(snapshot.root
  • 当前识别到的环境(snapshot.environment
  • Web 环境下可选的 canvas 图像(snapshot.image

当你想检查 offset、padding、stride、数组展开结果,或者快速定位 validation 错误时,优先使用这个 API。

示例 1:定长 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,
// ]

这个例子说明了什么

你只需要传普通 JS 数据,API 会自动处理 WGSL 要求的 padding。

示例 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); // 80

重要说明

对于 runtime-sized array,BufferBindingMemory 无法自动推断最终尾部长度。
你必须通过 runtimeArrayCountbyteLength 告诉它目标大小。

示例 3:Node 端终端可视化

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"
// 创建 snapshot 时会自动把终端可视化打印出来。

这个场景适合 CLI 工具、Node 脚本、服务端调试,能直接看出字节范围、padding 和 validation 问题。

下面是一个终端输出片段示例:

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.projection

示例 4:Web 端 canvas 可视化

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);
}

在浏览器里,snapshot.image 会是一张 memory-board 风格的 canvas,可用来直观看字段色带、offset、padding,以及数组 / 矩阵展开后的布局。

下面是一张 Web 端 canvas 可视化截图:

典型用法

const memory = new BufferBindingMemory(shaderCode);
const arrayBuffer = memory.set(groupBindingName, data, options);

在大多数场景里,这就是最主要的使用方式。

当前支持的数据输入形式

当前支持的输入大致包括:

  • WGSL struct -> 普通对象
  • WGSL array -> 数组 / TypedArray
  • vector / matrix -> 数组 / TypedArray
  • 标量类型,如 i32u32f32f16
  • 原子标量写入,如 atomic<u32>

Vec

源码位置:lib/vector.ts

Vec 是一组基于 Float32Array 的轻量向量工具,主要面向 2D / 3D / 4D 向量计算,不引入额外封装类。

导入方式

import {Vec} from "webgpu-forge";

约定

  • 向量底层都是普通 Float32Array
  • 只支持 vec2vec3vec4
  • 输出参数 out 可选;不传时会分配新向量
  • 大多数二元运算要求两边维度一致
  • normalize() 会把非常小的向量当作零向量处理

主要 API

  • 构造:vec2vec3vec4
  • 按分量运算:copyaddsubmuldivscalenegateminmaxclamplerp
  • 标量 / 几何运算:dotlengthSqlengthdistanceSqdistancenormalizeequals
  • 仅 3D:cross

示例

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

源码位置:lib/mat.ts

Mat 提供基于 Float32Array 的轻量矩阵工具,采用列主序存储,当前重点支持 3x34x4 变换相关矩阵。

导入方式

import {Mat} from "webgpu-forge";

约定

  • 矩阵底层都是普通 Float32Array
  • 存储顺序是列主序(column-major)
  • mat3x3() 生成长度为 9 的矩阵,mat4x4() 生成长度为 16 的矩阵
  • identity() 不传 out 时默认返回 4x4
  • translation() 只生成 4x4
  • scaling()rotationX()rotationY()rotationZ()rotation() 会根据 out 的长度写入 3x34x4

主要 API

  • 创建:mat3x3mat4x4identity
  • 变换:translationscalingrotationXrotationYrotationZrotation
  • 矩阵运算:copyaddsubscaletransposemultiply
  • 矩阵乘向量:multiplyVector

rotation() 的输入对象

rotation() 现在只接收下面两种对象之一:

  • 欧拉角对象:{ x, y, z, order? }
  • 四元数对象:{ x, y, z, w }

说明:

  • 欧拉角单位是弧度
  • order 支持:xyzxzyyxzyzxzxyzyx
  • 四元数会在内部先归一化,再转换成矩阵

示例

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);

开发

npm install
npm run dev
npm run typecheck
npm run test:run
npm run build

发布检查清单

  1. 更新 package.json 中的 name / version
  2. 运行 npm run build,并确认 dist/ 中包含 .js.cjs.d.ts
  3. 发布包