经纬志
首页 / luma.gl / API 文档

Buffer

先看结论

GPU 上的线性内存块,存放顶点、索引、uniform 或存储数据。

最后验证 2026-11-03 · luma.gl 9.4 · 更新 2026-10-27 · 引用本文
device.createBuffer(props) → Buffer

创建方式

缓冲区由设备创建,不直接 new。最简单的方式是直接传一个类型化数组, 设备会按数组长度分配并以 VERTEX 用途初始化:

const positions = device.createBuffer(new Float32Array([
  -0.5, -0.5, 0,
   0.5, -0.5, 0,
   0.0,  0.5, 0
]));

需要索引、写入或作为 uniform 使用时,用对象形式显式声明用途:

const vertexBuffer = device.createBuffer({
  data: new Float32Array(vertexData),
  usage: Buffer.VERTEX | Buffer.COPY_DST
});

const indexBuffer = device.createBuffer({
  data: new Uint32Array([0, 1, 2]),
  usage: Buffer.INDEX,
  indexType: 'uint32'
});

const uniformBuffer = device.createBuffer({
  byteLength: 64,
  usage: Buffer.UNIFORM | Buffer.COPY_DST
});

构造参数

参数说明
data初始数据,ArrayBuffer 或类型化数组视图
byteLength字节长度,未提供时由 data 推算
byteOffset写入起始偏移
usage用途位掩码,见下表
indexType索引类型:uint8、uint16、uint32
onMapped映射写入回调,用来避免一次额外拷贝
id调试用标识

用途标志

常量含义
Buffer.VERTEX顶点属性缓冲
Buffer.INDEX索引缓冲
Buffer.UNIFORMuniform 缓冲
Buffer.STORAGE存储缓冲,可用于计算着色器
Buffer.COPY_DST允许作为写入目标,更新数据时需要
Buffer.COPY_SRC允许作为读取来源

WebGL2 对这些用途的约束相对宽松,但同一份代码要跑在 WebGPU 上时, 用途声明必须齐全。养成把 VERTEX | COPY_DST 写全的习惯, 迁移时能省掉一轮排查。

属性与方法

成员说明
byteLength缓冲区字节长度
usage创建时的用途掩码
updateTimestamp最后一次写入的时间戳,可用于判断是否需要重绘
write(data, byteOffset)覆盖写入数据
readAsync(offset, length)异步读回,返回 Uint8Array
mapAndWriteAsync(cb, offset, length)映射后写入,避免中间拷贝
mapAndReadAsync(cb, offset, length)映射后读取,回调结束后解除映射
readSyncWebGL(offset, length)同步读回,仅 WebGL 可用,会阻塞
destroy()释放 GPU 内存

逐帧更新

// 创建时声明可写
const positions = device.createBuffer({
  data: new Float32Array(count * 3),
  usage: Buffer.VERTEX | Buffer.COPY_DST
});

function update(time) {
  const data = new Float32Array(count * 3);
  for (let i = 0; i < count; i++) {
    data[i * 3] = xAt(i);
    data[i * 3 + 1] = Math.sin(i * 0.1 + time) * 0.4;
    data[i * 3 + 2] = 0;
  }

  positions.write(data);
}

每帧新建数组会产生垃圾回收压力。点数固定时,应当复用一个 Float32Array,原地改值后再写入。

DynamicBuffer

频繁部分更新的场景,DynamicBuffer 封装了环形缓冲与分段写入, 减少整体覆盖带来的带宽浪费。如果每帧只有一个 uniform 变化, 用它比每次重写整个缓冲区更合适。

读回数据

GPU 到 CPU 的读回是同步点,代价较高。readAsync 会等待 GPU 完成当前工作, 不能在每帧调用。需要做回读校验、截图或拾取结果分析时, 放在交互结束或调试流程里。

缓冲区不负责布局。Buffer 只是内存,怎么解释这段内存 由 bufferLayout 决定。同一个缓冲区可以按不同格式读取, 但格式必须与着色器声明一致。

引用本文

经纬志(2026)。《Buffer》。https://www.jingweizhi.com/lumagl/api/buffer.html(访问日期 2026-11-03)。