- Escape barrier: every checked store funnel tags stored objects REFFED
(stored => REFFED structural), ret==args guards at native completion,
fn-arg bind-time barrier (closure-captured scopes retained args untagged
-> latent use-after-free under eager release)
- vm.release_transient() for host per-call objects; *_unchecked pushes are
the releasable-container path; call_with_scope native branch no longer
leaks one scope object per Rust->native vm.call()
- pump_widget_async: dead-isolate reclaim every pump + needs_gc-gated
round-robin mark/sweep — isolate heaps were never collected before
- res.rs: resource path cache was Cx-global and cached handle VALUES across
VMs, so isolate heaps held main-heap handle indices (exposed by the first
isolate mark pass ever to run). Now: data shared globally, handles minted
per-heap, cache keyed (heap_key, path), per-heap detach on GC
- vm.gc() no longer shrink_to_fits every run; explicit gc_and_compact()
- script-test: GC campaign suite (flat-heap tick loops, retained-input
survival, escaped-scope capture, isolate churn collection)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
map_bake --recompress re-encodes EVERY tile (both pass-through sites) at
the target quality — compression parallelizes across the whole fleet and
the final dataset is uniformly q11. The slicer ships q2 intermediates
(fast, disk-lean). Bake mode also skips runtime-only work per tile:
building/tree vertex extrusion and POI point parsing never reach the
sink and no longer run on workers.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The dithered dissolve traded one artifact for another (user call): the
real fix is not fading at all in an already-3D scene — fades stay for 2D
and the single flat->3D mode reveal.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
5s mtime watch on the active archive (root.mkidx for mkmap); on change,
Failed placeholders clear and the visible loop re-requests. Workers
already reopen per batch, so an atomic shard-set swap appears live —
apps/route now points at world.mkmap and starts empty until cell-001
(NL) lands.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Alpha-multiplying opaque 3D through a depth-writing fade let the clear
color bleed through for 0.25s per arriving tile. Surviving fragments now
stay fully opaque; a 4x4 Bayer threshold ramps coverage instead.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Fresh/evicted/rebucketed tiles arriving into an already-3D scene were
replaying the pop-up (the zoom-crossing flash).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Tile ~22000 (Westland greenhouse belt) put thousands of identical-height
rings in one union and the memory spike got the bake SIGKILLed at the
same tile every run. Groups over 800 jobs / 120k ring points stay
per-building; the cap is computed identically at bake and runtime so
signatures agree.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Flattened ring lists turned disjoint outers into phantom earcut holes;
i_overlay orientation normalizes via the SAME shoelace form as
polygon_signed_area (outer > 0, holes < 0, y-down).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
BakedFacesBucket v4 carries pre-dissolved (height, tint) building groups
behind their own input signature; the bake sink unions eligible grounded
jobs per group (chunked i_overlay); on a runtime HIT the eligible jobs
swap for the dissolved groups (paint order re-sorted), on MISS the
per-building path runs unchanged. v3 streams parse with an empty section
so the current NL cut keeps working until the next bake.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
near = frustum half-diagonal (rotation-safe, full tilt stretch) plus a
tile diagonal of margin; the fixed viewport-height radii bit into
visible tile columns at some zooms (2D band with a hard seam). Rings now
only ever act beyond what the camera can see.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
simplify_wall_ring merges sub-2-degree collinear runs (digitization
noise) so adjacent wall quads fuse. fill_3d sub-splits by material:
MAT_WALL and MAT_CANOPY get their own bands; mid ring draws roofs +
two-quad crossed trees (geometric, no atlases), near ring full detail,
heights sink only toward the horizon.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
append_cached_road_icons appended logical 19-float records into the
GPU-packed icon buffer with the old stride's index base (fan-triangle
streaks after 2D/3D mode switches). Decals stay logical CPU-side and
pack on the way in. This closes the packed-format bring-up: 76B -> 48B
per vertex across all map buffers, packing on the builder thread, all
three DrawVector-family shaders (vector, map, svg) unpacking via the new
intrinsics.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The 3D suffix between the fills and buildings laps splits off; the draw
fades it from 0.75 to 1.5 viewport-heights around the view focus. Under
tilt the far (blurred) field skips the bulk of the fill vertex mass;
flat views are inside the near radius everywhere.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Post-build O(n) partition on the per-vertex zoom-floor slot; pass 4 draws
the band only at view >= 16.25. Kills millions of shader-collapsed icon
verts per frame at mid zooms.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Per command buffer: pass debug name, GPU start->end interval, draw calls,
vertices, instances, upload bytes — accumulated and printed as a 1Hz
table from the completion threads. Map frame stats gain gpu_ms/gpu_max
from the existing PERF_CHANNEL_GPU ring.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The cache-hit path re-emitted every glyph CPU-side with the pan shift
baked into vertices; under tilt that visibly trailed the tile geometry
(which pans purely by uniform). The pan/zoom delta now rides two new
uniforms applied before the existing camera-delta matrix, in the same
frame as map_offset — labels physically cannot lag the map. Pin-interior
text keeps constant px via a billboard instance flag.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Pinned carriers stretched the 1px AA band into a wide smear at corr>1 —
the dirty road edges across the morph band.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
At the keyframe corr==1 cancels offsets entirely, so ring-circular 1-2-1
smoothing (3 passes) costs zero keyframe fidelity; mid-morph the edge no
longer saw-tooths where junction wrap-arounds swing miter direction
per vertex.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The deck-shadow dissolve ran after the bake sink's early return, so no
cut ever contained it and every dz-covered street tile paid ~59ms at
runtime (found via emit-section fencing: ebuild=59). Extracted
dissolve_deck_shadows; the sink concatenates it into the baked shadow
shapes (concat == today's two separate emits exactly); a shadow HIT now
gates the runtime block off. Also: face-arm/stroke-arm/events laps, icon
template cache, batched expanded writer.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
subdivide_face_mesh_morph carries the offset channel (midpoints average
endpoints); decked bodies emit via the expanded layout with per-vertex
deck override. Fixes the magnified-wide roads across bridge-dz coverage
(all central Amsterdam) at deep zoom.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Street trees memcpy one origin-built mesh (anchor+zbias patch); icon
stalk clearance queries a building-ring cell grid instead of scanning
icons x groups x rings. Worst AMS 368 -> ~310ms serial.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The icon matchers read a finite key set; parsing micro-POI layers with
the whitelist off was ~140ms/tile at kf16. Worst AMS 504 -> 368ms serial.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Icon-horizon tiles run 50-85MB; a fixed 1.2GB budget sat below
visible+pan-ring at street zoom and pure LRU evicted the very neighbors
a circling pan re-enters — every loop around a center rebuilt its ring.
Budget now grows to hold 2x the visible set and eviction orders by
distance from the view center (LRU only as tiebreak): the ring survives,
the trail is what dies.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Morphable (flat, opaque, non-emissive) face bodies+fringes emit through
append_expanded_stroke_geometry (anchor = pos - miter*hw_key): the live
zoom re-widths them per frame via the existing width_correction path, and
the expanded branch already zeroes the fragment params faces with glow
would need — those stay pinned. render_bucket collapses to keyframes
{<=14 native, 15->14, >=16 -> 16}; icons include to a z18 horizon from
the high keyframe and reveal via the live icon_zoom uniform (mechanism
existed). Existing v3 streams serve both keyframes unchanged — the only
restyle event left on the zoom axis is the single 14<->16 crossover.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
build_paint_faces maps every outline vertex's exact f32 coords to its
miter normal and emits offsets (normal x keyframe half-width) parallel to
body and fringe verts; junction blends, clip cuts, carrier outer edges
and translucent groups pin at zero.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
BakedFacesBucket v3 carries the dissolved shadow shapes + grounded
footprints under their own input signature (job rings/heights, sun,
scale, min-edge); the runtime shadow block on a HIT skips
sweep/dissolve/diff/open wholesale and tessellates the baked shapes
(b-sh-baked 0.5ms vs 0.2-2.6s). bake_tile_paint_faces now builds 3D so
the shadow pass runs at bake time; faces signatures are road-only and
stay valid. Night/dynamic-sun themes gate at bake_shadows and simply
never submit the shapes. Theme-independence test passes on v3; NL smoke:
8418/5388 2.7s -> 97ms, 8417/5387 1.6s -> 134ms, worst AMS rz16 258ms
honest (was 611ms with runtime shadows).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The headless probe theme ran with bake_shadows OFF while every app theme
runs it ON, so all headless profiles silently skipped the shadow pass —
'155ms worst tile' excluded the 0.2-2.6s shadow dissolve the app pays
(user's 1.6-3.1s dockland tiles reproduce exactly now). Probe now bakes
shadows; b-jobs/b-sh-sweep/-dissolve/-diff/-open laps split the stage.
Buildings-buffer pre-reservation REVERTED (first-touch of ~240MB zero
pages per builder serialized 12 workers on the kernel fault path: 340ms
-> 3000ms in-app). Minkowski-sweep shadow silhouette tried and REVERTED
(epsilon-concave rings hand i_overlay self-crossing polygons, 10-15s;
also: f32-grid arithmetic in shadow geometry is load-bearing — f64-exact
translated points changed boolean coincidences and tripled dissolve
time). Real fix queued: bake dissolved shadow shapes per bucket.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
libs/mbtile_reader gains the .mkmap consumer: root.mkidx parse (Hilbert
tile ids, root ranges -> brotli leaf directories -> shard/offset/len),
positioned shard reads, same get_metadata/get_tile_decoded surface as
MbtilesReader; TileArchiveReader sniffs the path so mbtiles_path can
point at either. Index format v2 drops JSON: the metadata section is now
varint KV like the leaves (writer + reader; no serde in the container).
Loader, zoom-range probe and the headless harness go through the enum;
bridge-dz/overlay sidecars stay mbtiles. Harness parity via shards:
worst AMS rz16 164.7ms, z12 native 51.3ms — identical to mbtiles. App
repointed to local/maps/europe-base-br.mkmap (111 shards + root.mkidx,
the exact bytes a CDN would serve).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Road-surface tier identity (RoadSurfaceKey) now carries a theme-stable
class id (fnv of the styling rule's kind) plus geometric fields instead of
resolved colors; identically-styled rules alias to one canonical id at
theme compile so kinds a theme paints the same still union as one tier.
Plaza grouping keys on alpha alone (road-polygon fills are one theme
constant). The bake input signature contains no colors, so recolor-only
themes (night, circuit city — user contract: themes only recolor, shadows
fade via alpha) share one baked stream: proven by
baked_faces_theme_independent (5 keys, identical signatures + regions
under a full recolor via probe_compiled_theme_recolored). Light output:
fills byte-equal, casing within 0.3% (same-rank painter tiebreak moved
from color values to class ids — visual check pending).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The bake guard now hashes the ring-construction INPUT (tier order/styles,
smoothed way points+dz, plaza rings, joint/portal end sets, clip) with a
deterministic FNV std-Hasher instead of hashing the constructed rings, so
a HIT skips road_ribbon_rings + per-ring field classification wholesale:
rings+fields 35.7 -> 0.8ms, worst AMS rz16 3D 224 -> 155ms (NL v2 bake,
byte-equal buffers vs the runtime cascade kill switch). BAKED_FACES_VERSION
2 rejects v1 streams (old semantic) into the safe fallback. Also: part-
centroid cell grid for the building cover test (buildings 25.5 -> 13.6ms,
Paris was 56ms), lookup-only cell maps switch SipHash for a multiply-rotate
hasher (DzField::sample), VisibleRegions: Clone for the OOB-region guard.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replaces the remaining linear bbox scans in grade-through/flush-ends with
a 16-unit cell grid (candidates stay in ascending way order, so
first-match semantics survive); append helpers now extend_from_slice one
19-float record with reserved capacity. 7-tile rz16 sweep + z12 byte-equal.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The zoom-out pyramid was never baked: z11-13 city tiles ran the full
painter cascade at runtime (z12 AMS 340ms cascade, 661ms build). map_bake
gains --zooms (native bucket below z14) and the renderer accepts baked
buckets 10-16; NL smoke bake: 861 tiles/55MB/31s, z13 166->19ms,
z11 252->28ms. Remaining z12 cost was two quadratic endpoint passes over
4017 join ways: bbox+reach prefilters and an endpoint hash grid cut
grade-through 103->33ms and flush-ends 98->3ms, bit-identical (every gate
is half-width-bounded; buffer sizes byte-equal across the sweep). Also
sp-* sub-laps in stroke-prep.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>