fix(ui-map): cut the visibility fog with an inverse stencil mask (Safari pan perf, stage 2)
Stage 1 (render-on-demand) removed the idle / whole-system freeze, but
panning a loaded map with "visible hyperspace" on stayed heavy in Safari:
the fog still cut its visibility holes by opaque overpaint — on KNNTS041
that is ~260 near-world-sized opaque circles blended over the fog every
rendered frame, a fill-rate cliff for Safari's WebGPU / Apple's tile-based
GPU.
Replace the overpaint with an INVERSE stencil mask: setVisibilityFog now
draws the FOG_COLOR rectangle(s) into fogLayer and collects the visibility
circles into one Graphics set as fogLayer.setMask({ mask, inverse: true }),
so the fog shows everywhere except the union of the circles. Per-frame cost
drops from dozens of blended opaque circle fills to one rect fill + a
stencil pass (no colour writes), which Apple's TBDR GPU handles cheaply,
and the fog stays fully vector — crisp at any zoom.
fogPaintOps and its unit tests are unchanged (the circle ops now feed the
mask instead of an overpaint). Verified with a high-contrast screenshot
during development (fog field with a correct circle-union hole) plus the
existing fog / render-on-demand e2e green on chromium + webkit.
Docs: renderer.md fog section + PLAN.md Phase 29 decision 9.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+20
-3
@@ -3293,9 +3293,26 @@ Decisions:
|
||||
is removed so a released drag stops instantly and the viewport
|
||||
goes idle immediately. `RendererHandle.getRenderCount()` (mirrored
|
||||
on `__galaxyDebug` as `getMapRenderCount`) backs the e2e
|
||||
assertions. If Safari pan is still heavy after this, stage 2 cuts
|
||||
the overpaint itself (an inverse stencil mask of the circle union,
|
||||
kept vector so the map stays crisp at any zoom).
|
||||
assertions. The owner confirmed this removed the idle / whole-system
|
||||
freeze, but panning a loaded map with the fog on stayed heavy in
|
||||
Safari (the overpaint fill-rate was untouched) — addressed in
|
||||
decision 9.
|
||||
9. **Inverse stencil mask for the fog (fog perf, stage 2).** The fog's
|
||||
visibility holes were previously cut by opaque background-coloured
|
||||
circle overpaint — on a large report dozens of near-world-sized
|
||||
opaque circles repainted every frame, the fill-rate cliff that kept
|
||||
Safari's WebGPU pan heavy after stage 1. Stage 2 replaces the
|
||||
overpaint with an INVERSE stencil mask: `setVisibilityFog` draws the
|
||||
`FOG_COLOR` rectangle(s) into `fogLayer` and collects the visibility
|
||||
circles into one `Graphics` set as
|
||||
`fogLayer.setMask({ mask, inverse: true })`, so the fog shows
|
||||
everywhere except the union of the circles. Per-frame cost drops to
|
||||
one rectangle fill plus a stencil pass (no blended colour writes,
|
||||
friendly to Apple's tile-based GPU), and the fog stays fully vector
|
||||
— crisp at any zoom. `fogPaintOps` and its unit tests are unchanged
|
||||
(the circle ops now feed the mask instead of an overpaint); the
|
||||
rendered result is verified by a high-contrast screenshot during
|
||||
development plus the existing fog / render-on-demand e2e.
|
||||
|
||||
## Phase 30. Calculator Tab
|
||||
|
||||
|
||||
Reference in New Issue
Block a user