A WebGL2 flicker fix (#1139) was render-parity-verified on exactly one scenario — the zoom-OUT hold-tiles case that reproduced the original flicker, retained-content 0.19 → 0.79 matching WebGPU — and never on zoom-in or per-frame cost. It shipped an unmemoized per-frame classifyTile run twice per tile plus synchronous uploads, and stuttered with progressively-black fills on a Seoul zoom-in. Reverted 36 minutes later (#1140). A hot-path fix must be verified in its worst regime, not the one that showed the original bug.
A draped landcover polygon rendered hundreds of kilometres offshore — but only on WebGPU. Every vector slice of one source shares one Material uniform pool, and each slice resets the pool cursor to 0, so a later slice's tile i overwrote an earlier slice's tile-i buffer. WebGPU's queue.writeBuffer defers to submit (last-writer-wins), so every draw read the final bytes; WebGL2's immediate bufferSubData never showed it — and the differential test was structurally blind, because both frames aliased identically.
Half the globe rendered as background again — same symptom as the drape-suppression bug, opposite root cause. This time the trans-antimeridian tiles were never selected: the overzoom fast-path unprojects the viewport corners to a lon/lat box, but on a small globe disc the corners miss the sphere, the box collapses to the sub-camera point, and it emits the single tile column under the camera — which a contiguous longitude range can never wrap across the dateline. Told apart from the draw bug by seam location and persistence.
A refactor rerouted the WebGPU frame shell through RHI wrappers and claimed byte-identical rendering. We did not diff pixels against a tolerance — we hashed three captures and got cd3097…9b0f three times. A same-code re-run proved the noise floor was zero, upgrading the gate from diff-below-tolerance to bit equality. Determinism is a property you engineer into the harness; once you have it, verification collapses from statistics to md5sum.
A building went missing from the 3D layer. Tile clipping had split its footprint into two pieces; the tiler flattened both outers into one rings array, and the extrusion consumer read everything after rings[0] as a hole — so piece #2 was earcut-punched out of piece #1's roof. Walls survived, roofs vanished, n pieces rendered n-1 roofs. The 2D fill was pixel-perfect the whole time, and zero tests had ever fed the consumer more than one polygon.
Half the globe rendered as pure background, cut exactly at the 0-meridian z1 tile boundary. The fallback ancestors for the missing half were computed, CPU-cached, and force-uploaded to the GPU — then drawn nowhere, because a drape suppression flag was scoped to the renderer instance instead of one dispatch. Verified by making the network slow on purpose, after the first pixel readback lied.
A row of country labels floated in the sky above the globe's horizon. Round 1 — an angular margin, provably safe at every zoom — died because floaters and healthy labels interleave in angular depth (Nigeria 0.332 floats, Kenya 0.329 doesn't). Round 2's screen-space limb fixed Chad and missed two-line Burkina Faso by exactly one line of text. The gate only held once it moved to where the quad height actually exists.
A displaced vector layer, a red/blue checkerboard ocean, a 16-gon planet, and intermittent flicker — four user-visible globe defects on WebGL2, and not one root cause in shared code. Every camera rendered correctly on WebGPU. On why a hand-maintained backend twin is scaffolding that must die, and the 20.7 km test witness that keeps its seam from drifting while it lives.
A headless session with no GPU had thirteen open issues and a hard rule against claiming a render is correct without a pixel diff. The split that worked sorted the backlog not by difficulty but by whether each fix's correctness reduces to something provable without a raster.
A concave country's label rendered offshore because the anchor was the bounding-box centre — a point the polygon does not contain. The fix is a guaranteed-interior point, but the harder call was shipping it from a session with no GPU to re-check the pixels.
Adjacent map tiles projected the same vertex 40,075 km apart — one full world circumference. A rotated projection's unavoidable branch cut, resolved per tile, scattered the seam across every tile join; the fix relocates it to the one edge geometry expects.
A fix for per-feature fill opacity came with a fail-before/pass-after test: 0.25 and 0.75 baked to alpha 64 and 191, two values where there had been one. It was green and I reverted the change — because the alpha it proved feeds the outline, not the fill.
A single-authority migration for on-screen scale left the globe branch returning the raw, uncapped value under a comment reading 'UNVERIFIED'. A sibling branch of identical shape was a non-bug — and only a probe of which value is read told them apart.
A bug report for one-way arrows drifting off the road came with a diagnosis and a one-line fix. The diagnosis was refuted by reading the anchor code, and the proposed fix was a revert of a change the repo had already tried and backed out. The real fix was neither.
Making the line outline's projection precise, but not its polygon fill, turned a shared invisible jitter into a ~3px fill≠outline seam at deep zoom. The fix isn't more f64 — it's the same camera-relative reframe, which the linear term needs no emulation for.
Two engines rendered the same style differently because one honoured a metadata field the other deliberately skipped. The comment defending the skip described a danger an existing clamp had already neutralized — and the "working" half of the cull turned out to be silently keyed past its own lookup.
A coordinate-space migration carried one assumption — "absolute geometry needs no per-copy shift" — that was true for the globe and false for flat maps. Applied per-renderer, it silently dropped world-copy fan-out path by path. The fix is one ten-line router.
Two overlapping map labels swapped survivors on pan because the collision pass's tie-break was tile-dispatch order — reversed. The fix is a stable identity fed to the greedy allocator, and the gate is a permutation test.
The GPU has no double. There are four ways to get one anyway — double-float error-free transforms, integer emulation, reference-point rendering, and perturbation — and they are not interchangeable. A decision guide, from a survey of Thall, QD/CAMPARY, Cesium, deck.gl, and fractal deep-zoom engines.
Three real bugs from making WebGL2 match WebGPU on a 117-layer basemap: a dedup map nobody cleared, a depth jitter that out-voted painter's order, and a vertically mirrored composite hidden by a symmetric test fixture.