Compute与GPGPU
通用计算(直方图、粒子积分、前缀和、剔除)应优先 WebGPU compute。WebGL 没有计算着色器;用浮点 FBO 或 transform feedback 硬做 GPGPU,是带光栅税的兼容路径,不是默认架构。
1. 为什么 WebGPU 是首选
Compute pass 随机读写 storage buffer、有 workgroup 共享内存、能写 indirect draw 参数。没有「必须画一个 fullscreen triangle 才能干活」。
export async function dispatchHistogram(
device: GPUDevice,
pipeline: GPUComputePipeline,
bindGroup: GPUBindGroup,
workgroups: number,
): Promise<void> {
const encoder = device.createCommandEncoder();
const pass = encoder.beginComputePass();
pass.setPipeline(pipeline);
pass.setBindGroup(0, bindGroup);
pass.dispatchWorkgroups(workgroups);
pass.end();
device.queue.submit([encoder.finish()]);
}
requestAdapter() 为 null 时这条路不存在,降级见 上下文生命周期。不要把 compute 写成「没有 GPU 就 throw」的唯一路径。
适用:每帧要对全体粒子 / 全图像素做同一公式、且结果留在 GPU 给下一趟渲染用。
不适用:几十个点的 CPU 循环、要回读成 JS 再决策的热路径(mapAsync 同样是同步点)。
2. WebGL 能做什么、边界在哪
| 手法 | 机制 | 边界 |
|---|---|---|
| 浮点 FBO | 全屏三角形,FS 读上一张纹理、写下一张 | 必须走光栅;无散写;要 EXT_color_buffer_float / EXT_color_buffer_half_float |
| Transform feedback | VS 写出 varyings 到 buffer | 适合粒子积分;不适合图像邻域卷积 |
| 整数 FBO 编码 | 把 float 拆进 RGBA8 | 精度差,调试痛苦 |
export function hasFloatColor(gl: WebGL2RenderingContext): boolean {
return gl.getExtension("EXT_color_buffer_float") !== null;
}
export function pingPong(
gl: WebGL2RenderingContext,
readTex: WebGLTexture,
writeFbo: WebGLFramebuffer,
drawQuad: (gl: WebGL2RenderingContext) => void,
): void {
gl.bindFramebuffer(gl.FRAMEBUFFER, writeFbo);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, readTex);
drawQuad(gl);
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
}
移动端 mediump 会把积分漂掉;浮点附件 incomplete 时不要假装算过。结果若 readPixels 回 CPU,GPGPU 的意义被一次同步吃掉——直方图展示用 WebGPU storage + 偶尔回读,或缩小后再读。
热路径不要:2D getImageData 做卷积再 texImage2D 回去。那是 Canvas 像素管线 的处理表面,不是 GPU 计算。
3. 数据所有权
场景图仍在 CPU。Compute 写的是 投影(粒子位置 buffer、直方图 bin)。业务删除一个发射器,要同时让 GPU buffer 失效或重打包,不要从 storage 反推「有哪些对象」。
4. 失败形态
| 症状 | 原因 |
|---|---|
| WebGL 「compute」结果阶梯状 | 没浮点附件,用 8bit FBO 积分 |
| ping-pong 花屏 | 读写同一张纹理(反馈回路未拆) |
| 粒子一帧后全 NaN | 移动端 mediump / 没夹速度 |
| 算完比 CPU 还慢 | 每帧 readPixels 整张 |
| WebGPU 示例局域网挂 | 非安全上下文,或 adapter 为 null 没降级 |
权威资料
- W3C — GPUComputePassEncoder
- Khronos — EXT_color_buffer_float
- Khronos — Transform Feedback (WebGL2)
- MDN — Transform Feedback
核对日期:2026-08-26