写过 WebGPU 的人都踩过这个坑——每次 render pass 结尾那次显存写入从来不是必须的,今天 Firefox 157 把这件事彻底原生化了
写过 WebGPU 的人都踩过这个坑——每次 render pass 结尾那次显存写入从来不是必须的,今天 Firefox 157 把这件事彻底原生化了。
写过 WebGPU 的人都踩过这个坑——每次做渲染管线,color attachment 的内容总要在 pass 结束后写回主显存,下一帧再读回来。这个看似理所当然的操作,在移动端 GPU 上其实多了一次完全可以避免的 VRAM 读写。今天 Firefox 157 把这件事彻底原生化了。
问题出在哪
GPU 有两种渲染架构:立即模式(IMR)和分块模式(TBDR)。桌面独显多用 IMR,渲染整个画面后再写回显存;移动端 GPU(苹果全系、高通 Adreno、ARM Mali)多用 TBDR,把画面分成 16×16 或 32×32 的小 tile,每个 tile 在片上高速内存(tile memory)里完成所有渲染操作,最后一次性写回 DRAM。
问题是,WebGPU 的 color attachment 默认总要被写入主显存。哪怕你这个 pass 的结果只用来做屏幕显示,下一帧就被覆盖,GPU 仍然要执行一次写回操作。移动端一次 VRAM 写入大约是 50~200ns,而访问 tile memory 只有 1~5ns——差了整整一百倍。
Firefox 157 支持的 TRANSIENT_ATTACHMENT 是 WebGPU 规范 2024 年 1 月新增的纹理用法类型(GPUTextureUsage.transient_attachment)。加上这个标记后,GPU 知道这个纹理的内容只在当前 render pass 内有用,pass 结束后可以直接丢弃(storeOp: 'discard'),不需要写回 DRAM。
const texture = device.createTexture({
size: [canvas.width, canvas.height],
format: 'bgra8unorm',
usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TRANSIENT_ATTACHMENT,
});
// 创建出来的纹理内容只在当前 pass 需要
// pass 结束后 GPU 自动 discard,不写回 VRAM
对应的 render pass descriptor:
const passDesc = {
colorAttachments: [{
view: texture.createView(),
loadOp: 'clear', // 首次加载需要读初始值
storeOp: 'discard', // pass 结束后不写回,直接丢弃
}]
};
注意:如果你在后续 pass 的 colorAttachments 里用 loadOp: 'load' 引用同一个 transient attachment,那是 spec 违规——因为上一个 pass 已经 discard 了它,内容是未定义的。
实际收益
PixiJS v8(WebGL/WebGPU 双引擎 2D 渲染库)在其 WebGPU 后端已将 canvas 根节点的 MSAA resolve buffer 标记为 transient。根据其代码注释,使用 TRANSIENT_ATTACHMENT 后:
- MSAA 4x 场景每帧减少 1 次全屏 VRAM 写入(1920×1080 × 4 samples × 4 bytes ≈ 33MB)
- tile memory 带宽下降约 40%(Mali G710 实测)
- 移动端视频通话 + WebGPU 滤镜同时跑时,电池续航提升约 8%
哪些场景适用
TRANSIENT_ATTACHMENT 只适合「当前 pass 结果不会被后续 pass 读取」的情况,最典型的场景:
- 屏幕最终输出(没有后续 pass 需要读回)
- MSAA resolve buffer(resolve 完成后原始 buffer 不再需要)
- 深度/模板 attachment(只在当前 pass 做深度测试)
- 多 pass 渲染中中间 pass 的 color output(但需确认后续 pass 不需要 load 其内容)
不适合:需要 loadOp: 'load' 读取上一帧内容的场景,比如 Temporal Anti-Aliasing(TAA)或任何反馈类渲染管线。
浏览器支持
Firefox 157(2026-09-29 稳定版)是第二个支持 TRANSIENT_ATTACHMENT 的主流浏览器。Chrome 已于 2026 年 1 月 Intent to Ship(预计 Chrome 156+ 稳定版)。Safari/WebKit 尚未实现(截至 2026 年 9 月)。
feature detection 写法:
const supportsTransient = 'TRANSIENT_ATTACHMENT' in GPUTextureUsage;
下一步
如果你在用 PixiJS v8 或 Three.js WebGPU renderer,升级到最新版后 WebGPU 后端会自动使用 transient attachment,不需要改代码。如果你自己的 WebGPU 渲染管线里有多 pass 中间结果现在每次都写回 VRAM,可以尝试将那些「不需要后续 pass 读取」的 attachment 加上 TRANSIENT_ATTACHMENT 标记,实测移动端帧率和续航的提升。
评论区
登录后可评论。