fix(rendering): bound portal resource lifetime

Separate logical ownership, render publication, and GPU retirement across live entities, landblocks, particles, textures, mesh arenas, portal/UI teardown, and per-frame scratch storage. Add bounded DAT/texture caches, upload budgets, three-frame fence retirement, exact-incarnation appearance reconciliation, frame pacing, and extensive lifetime conformance coverage.\n\nThe seven-destination connected route now cuts peak working/private memory roughly in half, returns Caul to 125-153 FPS locally, and produces no WER or AMD reset.\n\nCo-authored-by: OpenAI Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-18 21:35:16 +02:00
parent 3971997689
commit 749e8ceeb1
225 changed files with 29107 additions and 3914 deletions

View file

@ -561,7 +561,7 @@ behavior. Estimated 1726 days focused work, 35 weeks calendar.
- **Missile/portal VFX campaign Step 8 implemented and independently reviewed 2026-07-14.** `LiveEntityRuntime` now distinguishes raw server PhysicsState from retail's side-effect-derived final state, beginning from constructor state `0x00400C08` and applying `set_state` in Lighting → NoDraw → Hidden order. `LiveEntityPresentationController` keeps Hidden objects logically alive while suppressing root mesh, collision, picking, radar, status, and new target acquisition; typed `PS_Hidden`/`PS_UnHide` plays remain DAT-driven, direct equipped children inherit NoDraw, particles/lights survive, and repeated/stale state cannot replay a transition. A normal visible CreateObject never fabricates UnHide. Effect-owner preparation is separate from pending F754/F755 replay so construction-state effects always run first. Remote fresh-teleport/cell-less placement now executes the exact ordered `teleport_hook` action bundle and a full-cell hard placement before contact/airborne routing, preventing an airborne correction from restoring the old location. Projectile Hidden state pauses the retained body without consuming its active identity or accumulating a clock backlog. TS-43 is retired; AP-69 remains for exact ObjCell-PVS/preview-retention parity after the 2026-07-18 liveness port.
- **Missile/portal VFX campaign Step 9 automated hardening implemented and independently reviewed 2026-07-14; final two-client visual gate pending.** A deterministic 96-owner App fixture drives canonical missiles and effect owners through projectile updates, repeated DAT-effect scheduling, loaded↔pending↔loaded landblock churn, light/particle withdrawal and recovery, accepted deletes, same-GUID generation reuse, never-created F754 queues, and session reset. It asserts balanced logical render registration and zero residual records/bodies/projectiles, spatial buckets/rescues, shadows (including suspended registrations), effect profiles/packets, PhysicsScript FIFOs/anchors/delayed calls, particle bindings/logical IDs/render-pass owners, poses, light-controller/sink/manager owners, and stale record component references. A companion twelve-cycle gate drives exact recall motion `0x10000153` through AnimationSequencer/CallPES, Hidden, deferred remote placement, hydration, and UnHide; a second 96-owner `EntitySpawnAdapter` gate balances actual mesh-adapter reference counts without GL. The pass fixed undrained persistent rescue retention, delayed stale visibility edges, GUID-scoped teardown, create resurrection after a nested delete/reset, non-atomic resource registration, double teardown from a re-entrant session-clear callback, observer failure stranding later visibility edges, and stale outer projection transactions overwriting callback-created replacements. Teardown now removes exact projection references and generation/local-ID owners, uses per-GUID/session lifetime epochs plus per-record projection tokens, drains visibility fan-out before aggregating failures, and finishes or supersedes canonical commits before surfacing observer errors. Core remains GL/backend-free, panels remain on UI abstractions, and projectiles still draw through ordinary `WbDrawDispatcher` live-entity submission rather than a global projectile pass. AP-69 and TS-49 remain; AP-83/AP-91 now explicitly describe only a future mover that enables PerfectClip.
- **Portal lifetime/performance correction 2026-07-18; user visual gate pending.** `LiveEntityLivenessController` ports retail's 25-second leave-visibility destruction queue over canonical live records, cancels expiry for spatially resident or owned objects, and uses holtburger's conservative 384-unit envelope where ACE supplies no client-visible PVS leave event. Expiry reuses the exact generation-safe F747 teardown. The modern `GlobalMeshBuffer` now uploads vertices once per mesh and owns coalescing vertex/index ranges released by zero-reference LRU eviction. A connected five-region route returned animation ownership to baseline, reclaimed/reused GPU ranges, recreated the starting region on revisit, and prevented the prior persistent 312 FPS collapse. AP-69 is narrowed rather than retired because exact ObjCell PVS and explicit preview lifetimes remain.
- **Portal/resource lifetime correction 2026-07-18; connected stress gate passed, final visual gate pending.** `LiveEntityLivenessController` ports retail's 25-second leave-visibility destruction queue over canonical live records, cancels expiry for spatially resident or owned objects, and uses holtburger's conservative 384-unit envelope where ACE supplies no client-visible PVS leave event. The broader integration balances generation-scoped appearance/live/landblock/effect/UI/portal owners, bounds DAT/decoded/standalone/composite/atlas/mesh residency, performs incremental mesh-arena migration, and defers GL deletion or slot reuse through three frames of GPU fences. Render/UI scratch storage is reused with hysteretic trimming. No visual range or quality setting was reduced. The final seven-destination connected route cut peak working/private memory from 2,954.5/3,502.3 MiB to 1,493.4/1,969.5 MiB, returned Caul to 1,030.6/1,638.2 MiB, held 125153 FPS locally through the final dwell, and produced no WER/driver reset. AP-69 is narrowed rather than retired because exact ObjCell PVS and explicit preview lifetimes remain.
**Reference docs:** `docs/research/retail-ui/00-master-synthesis.md` + slices 01-06. Every AC-specific behavior has a decompiled FUN_ / DAT_ citation.
@ -1311,6 +1311,10 @@ port in any phase — no separate listing here.
> number and accepts the rewrite risk. Rust rejected. Parked (resume from the table
> below): MP1b pak/bake (needs the 865 GB EnvCell-dedup slice; loading-speed lever),
> MP-Alloc hard sites, MP1c, MP2. Full rationale: `project_mp_track_findings.md`.
> The 2026-07-18 portal/resource-lifetime repair does not resume MP's ECS, pak,
> or throughput redesign. It is corrective ownership/reclamation work for a
> reproduced crash-class regression in the mandatory renderer, using the current
> architecture and preserving pixels/ranges.
**Spec:** `docs/superpowers/specs/2026-07-05-modern-pipeline-design.md` (the
umbrella design — read it first). **Goal:** smoothness first (no frame over

View file

@ -5,9 +5,12 @@
**Currently working toward:** **M3 — "Cast a spell." M2 — "Kill a drudge"
LANDED 2026-07-15.** The complete connected melee/missile, death/loot,
inventory, and item-giving demo is user-gated. The shared projectile/effect
foundation is hardened through Step 9 and its single-client visual gate passes.
Next is the connected F.5 component-book/favorite-bar visual gate, followed by
cast/enchantment presentation and the two-client portal/observer VFX gate.
foundation is hardened through Step 9. Spellbook/component-book filtering,
favorite spell bar, connected casting/enchantment effects, and portal-space
presentation have passed their single-client visual gates. The corrective bounded
render/resource-lifetime integration passed its seven-destination connected
stress gate without a crash or cumulative collapse. The remaining M3 visual
requirement is the final two-client portal-out/materialize observer gate.
Carried:
#145-residual, #116 slide-response, R6/TS-42, and Track MP0.
@ -285,6 +288,11 @@ as ad-hoc rework. Rule 2's freeze still binds all NON-MP work. MP runs in
dedicated side-track sessions; the M1.5 critical path wins every conflict,
and MP4 is hard-queued behind #137.
The 2026-07-18 repeated-portal lifetime repair is a freeze-allowed corrective
change, not a resumption of Track MP. It keeps the current renderer and visual
ranges while balancing owners, bounding residency, and fence-delaying physical
GPU reuse; MP's pak/ECS/throughput redesign remains parked.
**Dungeon support (Phase G.3, issue #133) — SHIPPED.** The original
premise here (terrain-less dungeon landblocks unsupported anywhere in the
streaming/load/render/physics pipeline) was refuted at design time