MSAA beat SMAA on a tile GPU, and KTX2 cut texture memory
· 1 min read · webgpu, performance, ktx2, anti-aliasing, game-dev
Two decisions in Graveyard Pinball came from measuring, not from habit.
MSAA against SMAA #
The scene pass at the top quality levels is drawn with 4x MSAA, and the canvas itself is created with antialias: false: the chains draw offscreen and the canvas only gets a full-screen quad.
Measured on an Apple GPU at 1.5x pixel ratio, the frame was 2.3 ms with MSAA and 6.5 ms with SMAA (7.3 ms with three's stock RGBA16F SMAA targets). SMAA's three full-screen passes were about 5 ms alone, and the edges looked as clean or cleaner with MSAA. A query parameter brings SMAA back, with 8-bit targets, to compare on another GPU.
The lesson is the usual one for tile-based GPUs: multisampling is cheap there, and full-screen passes are not. There is no temporal AA, because it was for the screen-space reflections and their history.
Textures in KTX2 #
Every large texture is KTX2 / Basis Universal. It stays compressed in VRAM at about 1 byte per pixel, mipmaps included, and the browser transcodes it to ASTC or BC7 on load, in workers, with no JPEG or PNG decode on the main thread.
The estimated texture memory went from about 230 MB to 45 MB: the 2674x5276 playfield art alone was about 75 MB as RGBA8 with mips.
The price is download size: the table model went from 7.8 to 12 MB, because the near-lossless format is bigger than JPEG. That is a trade I would take again, since memory is what kills phones.
The pipeline #
- inside the GLB, the images are re-encoded in place by a script,
- loose files go through the same encoder,
- one KTX2 loader, with the transcoder in
public, is handed the renderer once.
The display is in the DMD post. The project is on its project page.
Related projects
- Graveyard Pinball — Free Halloween game