v146 · Web APIs · WebGPU
WebGPU transient attachments
Chrome 146 adds support for WebGPU transient attachments — render pass attachments that only exist for the duration of the render pass and don't need to be read back or stored after it completes. On tile-based GPU architectures (most mobile GPUs), this eliminates the memory bandwidth cost of writing these textures to main memory.
concepts
-
Transient Demo
Shows a WebGPU render pass using a depth buffer as a transient attachment — flagged with
GPUTextureUsage.TRANSIENT_ATTACHMENTso the browser knows it doesn't need to be stored after the pass. -
Memory Benefit
Explains why transient attachments save memory bandwidth on tile-based GPUs, what architectures benefit most, and the usage flag that enables the optimization.
-
Bandwidth budget meter
Compute the memory-bandwidth savings transient attachments deliver for your specific viewport, MSAA, attachment count and usage profile. Projects monthly savings.
-
Render Pass Inspector
Step through a 3-pass rendering pipeline — depth pre-pass, geometry/lighting, and post-processing. Each pass shows its attachment table, which attachments are marked transient, and the memory bandwidth saved per pass.
why it shipped
Tile-based GPUs (used in most mobile devices and Apple Silicon) process rendering in tiles that fit in fast on-chip memory. If a render target is never read after the pass, there's no need to flush it from the tile buffer to main DRAM — an expensive operation. The WebGPU spec allows textures to be created with TRANSIENT_ATTACHMENT usage, signalling to the driver that the content can be discarded at the end of the pass. Chrome 146 exposes this flag, enabling mobile-friendly GPU memory optimization for depth, stencil, and intermediate render targets.
the change
// Chrome 146: TRANSIENT_ATTACHMENT usage flag available
const depthTexture = device.createTexture({
size: [canvas.width, canvas.height],
format: 'depth24plus',
usage: GPUTextureUsage.RENDER_ATTACHMENT |
GPUTextureUsage.TRANSIENT_ATTACHMENT, // new in Chrome 146
});
const renderPassDescriptor = {
colorAttachments: [{ /* ... */ }],
depthStencilAttachment: {
view: depthTexture.createView(),
depthLoadOp: 'clear',
depthClearValue: 1.0,
// storeOp: 'discard' — content not needed after pass
depthStoreOp: 'discard',
},
};
// On tile-based GPUs: the depth buffer stays in tile memory
// and is never written to main memory — zero bandwidth cost