Tile-Based Rendering

Every lesson in this module so far described the desktop GPU's dataflow, which architects call immediate-mode rendering: a triangle enters the pipeline and flows straight through — transformed, rasterized, shaded, blended — with its fragments landing wherever on the screen they land. The ROPs soften the blow with caches and compression, but the framebuffer fundamentally lives in DRAM, and every overdrawn, blended, depth-tested pixel hammers it. On a desktop card with a 300-watt budget and a dedicated memory system, that's a fine trade.

Now design a GPU for a phone. Your power budget is two or three watts — for the whole chip — and the single most expensive thing you can do, by an order of magnitude, is move a byte to DRAM: external memory access costs hundreds of times the energy of on-chip SRAM access. The framebuffer traffic that desktop architecture shrugs off is now your biggest power line-item. So mobile GPU architects (PowerVR first, then ARM, Qualcomm, Apple) redesigned the dataflow itself around one goal: make the framebuffer stop touching DRAM. The result — tile-based rendering — is the best case study in this whole course of the same logical pipeline rebuilt in the opposite direction because the physics changed.

Two phases: bin everything, then render tile by tile

A tile-based GPU splits the frame into two phases separated by a full pass over the scene:

Count what DRAM sees per frame: the geometry (written and read once for binning) and each framebuffer pixel exactly once, at the end. Overdraw never reaches memory. Blending never reads memory. And the depth buffer — consulted per fragment, needed by no one after the frame — can live and die entirely on-chip, never written to DRAM at all. On a phone screen at 60 fps, that is the difference between a warm pocket and a dead battery.

The two dataflows, drawn

Same logical pipeline, opposite plumbing. Watch where the fat arrows point.

TBDR: since we have the whole tile's geometry anyway…

Binning creates a luxury immediate mode never has: before shading a single fragment, the hardware holds the complete list of every triangle touching this tile. PowerVR's tile-based deferred rendering (TBDR — the architecture in every iPhone) spends that luxury on perfect occlusion: rasterize the whole tile's geometry depth-only first, keeping for each pixel just the identity of the winning fragment — then shade only the winners. Opaque overdraw costs zero shading, in any draw order — no front-to-back sorting, no depth pre-pass, none of the early-Z choreography from three lessons ago. Hidden-surface removal stops being the app's optimisation problem and becomes a property of the machine.

The bill: nothing is free

Tiling buys its bandwidth win with real costs, and they all trace back to the same clause: the whole scene must be binned before any pixel can finish.

The design points meet in the middle, too: since the mid-2010s desktop GPUs quietly bin small batches of geometry and rasterize them tile-by-tile while the tile's pixels sit in L2 ("tiled caching") — not full two-phase tiling, but the same bandwidth instinct. Meanwhile mobile chips grow ever better at the geometry-heavy cases. The poles remain, but both camps have stolen each other's tricks.

Be the bandwidth accountant

Put numbers on the whole argument: one frame, both architectures, DRAM bytes counted. Play with overdraw and tris and find the crossover where binning stops paying.

// One frame's DRAM traffic, immediate vs tiled (a deliberately simple model). const W = 2560, H = 1600; // a tablet screen const overdraw = 3; // fragments per pixel, on average const tris = 300_000; // triangles in the frame const bppColour = 4, bppDepth = 4; // bytes per pixel const bytesPerBinnedTri = 32; // position + references in the bin lists const MB = (b: number) => (b / 1e6).toFixed(1).padStart(8) + " MB"; const pixels = W * H; const frags = pixels * overdraw; // Immediate mode: every fragment depth-tests (read + write) and writes colour, in DRAM. const immDepth = frags * bppDepth * 2; const immColour = frags * bppColour; const immTotal = immDepth + immColour; // Tiled: bin lists written then read; colour written once per pixel; depth stays on-chip. const binTraffic = tris * bytesPerBinnedTri * 2; const tiledColour = pixels * bppColour; const tiledTotal = binTraffic + tiledColour; console.log(`frame: ${W}×${H}, overdraw ${overdraw}, ${tris} triangles\n`); console.log(`IMMEDIATE depth RMW ${MB(immDepth)}`); console.log(` colour ${MB(immColour)}`); console.log(` total ${MB(immTotal)}\n`); console.log(`TILED bin lists ${MB(binTraffic)}`); console.log(` colour (×1) ${MB(tiledColour)}`); console.log(` depth ${MB(0)} (never leaves the chip)`); console.log(` total ${MB(tiledTotal)}\n`); console.log(`tiled uses ${(immTotal / tiledTotal).toFixed(1)}× less DRAM traffic`); console.log(`at 60 fps that saves ${((immTotal - tiledTotal) * 60 / 1e9).toFixed(1)} GB/s of DRAM bandwidth`);

Now set tris = 20_000_000 (a tessellation storm): the bin lists alone dwarf the framebuffer, and the tiled "total" loses. Architecture is a bet about workloads, and this slider is the bet.

Mobile-graphics guides are full of commandments like "never read the framebuffer mid-frame" or "avoid switching render targets". These are not general truths — they are consequences of tiling. A mid-frame read of pixels that only exist in half-finished tile memory forces the GPU to flush every tile to DRAM and reload it — the exact round-trip the whole architecture exists to avoid; the same operation on an immediate-mode desktop card is a cheap L2 hit. The reverse bites too: desktop wisdom like "sort opaque objects front-to-back for early-Z" buys almost nothing on a TBDR chip that removes hidden surfaces perfectly anyway — effort spent optimising for the wrong machine. Performance advice is architecture-specific: before you obey a rule, ask which dataflow it was written for. (And profile on the device, not the dev workstation — it is running a different machine.)

Immediate-mode and tile-based GPUs implement the same API — same shaders, same triangles, same pixels out — yet their silicon moves data in opposite directions. Nothing in graphics theory decides between them; joules do. A desktop card ships with GDDR memory burning tens of watts as a line-item nobody reads; a phone SoC shares one LPDDR bus with the CPU, modem and camera, inside a glass slab with no fan, where DRAM traffic is measured against battery-hours. Same maths, different physics, different optimal machine — evolution on separate islands. It is the cleanest instance of this course's oldest theme: architecture follows physics. Wherever computing goes next — datacentre accelerators rebuilt around interconnect power, or whatever replaces DRAM — expect the same play: when the cost model flips, the dataflow flips with it, and the "obvious" design was only ever obvious for one set of numbers.