docs(streaming): define cost-budgeted lifecycle
This commit is contained in:
parent
66690805c5
commit
2945896a6f
3 changed files with 479 additions and 0 deletions
|
|
@ -724,6 +724,8 @@ checkpoint retained staged or retiring bytes. Evidence:
|
||||||
|
|
||||||
### Slice E — Cost-budgeted streaming and retirement
|
### Slice E — Cost-budgeted streaming and retirement
|
||||||
|
|
||||||
|
**Active plan:** [`2026-07-24-modern-runtime-slice-e-cost-budgeted-streaming.md`](2026-07-24-modern-runtime-slice-e-cost-budgeted-streaming.md).
|
||||||
|
|
||||||
**Purpose:** Remove update-thread portal transactions.
|
**Purpose:** Remove update-thread portal transactions.
|
||||||
|
|
||||||
- Introduce explicit stage queues and `StreamingWorkBudget`.
|
- Introduce explicit stage queues and `StreamingWorkBudget`.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,300 @@
|
||||||
|
# Modern Runtime Slice E — Cost-budgeted streaming and retirement
|
||||||
|
|
||||||
|
**Status:** active — E0 contract/inventory complete
|
||||||
|
**Program:** `docs/plans/2026-07-24-modern-runtime-architecture.md`
|
||||||
|
**Baseline:** Slice D closeout commit `66690805`
|
||||||
|
**Behavior contract:** no visual-quality or retail-behavior reduction
|
||||||
|
|
||||||
|
## 1. Outcome
|
||||||
|
|
||||||
|
Slice E removes whole-window portal publication and retirement transactions
|
||||||
|
from a single update frame. It preserves the existing worker, canonical
|
||||||
|
`GpuWorldState`, presentation owners, retry receipts, world-reveal barrier,
|
||||||
|
and renderer resource owners.
|
||||||
|
|
||||||
|
The change is scheduling and lifecycle architecture:
|
||||||
|
|
||||||
|
- one immutable `StreamingWorkBudget` defines real per-frame limits;
|
||||||
|
- one single-writer scheduler admits and advances explicit work stages;
|
||||||
|
- destination-critical work receives reserved capacity across portal frames;
|
||||||
|
- old generations become unavailable and quiescent immediately;
|
||||||
|
- expensive owner/resource teardown resumes from exact cursors;
|
||||||
|
- publication advances through exact owner receipts under time, byte, entity,
|
||||||
|
upload, and retirement-operation limits;
|
||||||
|
- the existing `WorldRevealCoordinator` remains the only reveal predicate.
|
||||||
|
|
||||||
|
No distance, texture, particle, cell, collision, or presentation quality is
|
||||||
|
reduced.
|
||||||
|
|
||||||
|
## 2. Retail boundary
|
||||||
|
|
||||||
|
Retail teardown is synchronous:
|
||||||
|
|
||||||
|
- `CLandBlock::destroy_static_objects @ 0x0052FA50`;
|
||||||
|
- `CLandBlock::Destroy @ 0x0052FAA0`;
|
||||||
|
- `CObjectMaint::DestroyObjects @ 0x00508C30`.
|
||||||
|
|
||||||
|
Retail portal/cell blocking freezes object maintenance, physics, landscape,
|
||||||
|
game time, and ambient sound while continuing scene/UI/event work:
|
||||||
|
`SmartBox::UseTime @ 0x00455410`.
|
||||||
|
|
||||||
|
Acdream's async adaptation may defer physical cleanup, but may not leave a
|
||||||
|
retired owner active. Full translation:
|
||||||
|
[`../research/2026-07-24-retail-streaming-retirement-pseudocode.md`](../research/2026-07-24-retail-streaming-retirement-pseudocode.md).
|
||||||
|
|
||||||
|
## 3. Existing-owner inventory
|
||||||
|
|
||||||
|
| Concern | Current owner | Current behavior | Slice E action |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Worker inbox/outbox | `LandblockStreamer` | unbounded channels; near jobs prioritized | retain worker; expose bounded, allocation-free single-consumer drain and backlog facts |
|
||||||
|
| Completion apply | `StreamingController._deferredApply` | retained `List`; count-budgeted loads; unload and priority ring bypass | replace with explicit generation/priority FIFO stage queues and exact retained-byte accounting |
|
||||||
|
| Full reload | `BeginFullWindowRetirement` | snapshots and begins every resident retirement synchronously | retain stable snapshot/cursor and advance admissions under budget |
|
||||||
|
| Origin recenter | `OriginRecenterRetirement` | has a cursor but drains it to completion in one call | make the cursor the canonical budgeted admission receipt |
|
||||||
|
| Logical/spatial detach | `GpuWorldState.DetachLandblock/DetachNearLayer` | exact immediate bucket withdrawal; captures entity receipt | preserve; add destination-generation quiesce before cursored detaches |
|
||||||
|
| Retirement ledger | `LandblockRetirementCoordinator` | retryable per-stage/per-entity state, but advances a complete ticket on begin/advance | expose one bounded atomic step at a time; stable FIFO |
|
||||||
|
| Retirement effects | `LandblockPresentationRetirementOwner` | lights, translucency, plugin, terrain, physics, cells/buildings | preserve order; each entity/stage consumes measured budget |
|
||||||
|
| Publication ledger | `LandblockPresentationPipeline` | retryable stage booleans, but `Advance` runs the complete transaction | convert booleans/cursors into resumable atomic publication steps |
|
||||||
|
| Render publication | `LandblockRenderPublisher` | terrain/visibility/AABB/buildings/EnvCells whole stages | retain receipts; meter GPU bytes and split iterable registries where needed |
|
||||||
|
| Physics publication | `LandblockPhysicsPublisher` | rebuilds terrain/cells/buildings/statics/reflood in one call | cursor cell/building/static preparation and commit at safe mutation boundaries |
|
||||||
|
| Static presentation | `LandblockStaticPresentationPublisher` | allocates dictionaries/sorts arrays, then loops prior/plugin entities | prepare stable ordered arrays once; cursor cleanup/light/plugin work |
|
||||||
|
| Mesh upload | `ObjectMeshManager`/`WbMeshAdapter` | existing per-frame renderer owner/budgets | report exact upload bytes/operations to the streaming meter; never move GL ownership |
|
||||||
|
| Reveal | `WorldRevealCoordinator` + `WorldRevealReadinessBarrier` | one correct login/portal predicate | add destination generation/readiness stage facts; never duplicate predicate |
|
||||||
|
| Portal wait cue | `PortalTunnelPresentation` | authored tunnel and centered wait notice port exists | hold tunnel past five seconds and publish diagnostic; never early reveal |
|
||||||
|
| Audio | `OpenAlAudioEngine`/`AudioHookSink` | one-shot owner is not retained in source slot | tag 3-D voices by owner; stop old-generation owners at quiesce |
|
||||||
|
|
||||||
|
## 4. Work model
|
||||||
|
|
||||||
|
### 4.1 Immutable budget
|
||||||
|
|
||||||
|
The App-layer type is equivalent to:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public readonly record struct StreamingWorkBudget(
|
||||||
|
TimeSpan MaxUpdateTime,
|
||||||
|
int MaxCompletionAdmissions,
|
||||||
|
long MaxAdoptedCpuBytes,
|
||||||
|
int MaxEntityOperations,
|
||||||
|
long MaxGpuUploadBytes,
|
||||||
|
int MaxGlRetireOperations,
|
||||||
|
float DestinationReserveFraction);
|
||||||
|
```
|
||||||
|
|
||||||
|
All fields are positive and validated as one profile. The initial High/default
|
||||||
|
profile is evidence-tuned, not a reduction in quality:
|
||||||
|
|
||||||
|
- 2.0 ms update-thread streaming work;
|
||||||
|
- 64 completion admissions;
|
||||||
|
- 8 MiB retained CPU payload adoption;
|
||||||
|
- 256 entity operations;
|
||||||
|
- 8 MiB requested GPU upload;
|
||||||
|
- 64 logical GL-retirement admissions;
|
||||||
|
- 75% reserved for destination-critical work while a reveal is pending.
|
||||||
|
|
||||||
|
These are initial scheduling ceilings, not content ceilings. Work continues on
|
||||||
|
later frames until exact convergence. Connected E gates may retune the profile
|
||||||
|
as one atomic change.
|
||||||
|
|
||||||
|
The compatibility `MaxCompletionsPerFrame` setting maps to complete Low/Medium/
|
||||||
|
High/Ultra work profiles during migration. It does not remain an independent
|
||||||
|
hidden second throttle.
|
||||||
|
|
||||||
|
### 4.2 Meter
|
||||||
|
|
||||||
|
`StreamingWorkMeter` is stack/frame scoped and single-thread owned. It records:
|
||||||
|
|
||||||
|
- start/deadline timestamp;
|
||||||
|
- admitted results and retained CPU bytes;
|
||||||
|
- entity operations;
|
||||||
|
- GPU bytes requested;
|
||||||
|
- GL retirement operations;
|
||||||
|
- stage completions, yields, overruns, failures, and oldest-work age.
|
||||||
|
|
||||||
|
Reservation is checked before an atomic operation using its conservative known
|
||||||
|
cost. Elapsed time is checked after every atomic operation. A first operation
|
||||||
|
may run when a dimension is otherwise empty so progress cannot deadlock; any
|
||||||
|
single-operation overrun is named in diagnostics and becomes a required split
|
||||||
|
site.
|
||||||
|
|
||||||
|
### 4.3 Cost estimation
|
||||||
|
|
||||||
|
`LandblockStreamResultCost` is computed once from immutable payloads:
|
||||||
|
|
||||||
|
- terrain vertex/index bytes;
|
||||||
|
- entity count;
|
||||||
|
- mesh-reference count;
|
||||||
|
- EnvCell visibility/shell count;
|
||||||
|
- physics cell/building/GfxObj counts;
|
||||||
|
- prepared payload arrays retained by the completion.
|
||||||
|
|
||||||
|
It never uses process working set as a scheduling unit and never counts the
|
||||||
|
memory-mapped package's address space as adopted bytes.
|
||||||
|
|
||||||
|
## 5. Queue and ordering contract
|
||||||
|
|
||||||
|
One scheduler owns queues by `(generation, priority, stage)`.
|
||||||
|
|
||||||
|
Priorities:
|
||||||
|
|
||||||
|
1. destination collision/required Near scene;
|
||||||
|
2. visible Near;
|
||||||
|
3. ordinary Near;
|
||||||
|
4. Far/speculative;
|
||||||
|
5. retirement cleanup after immediate quiesce.
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
- FIFO is exact within one generation/priority.
|
||||||
|
- Generation supersession cancels stale unpublished work and releases its
|
||||||
|
retained-byte charge.
|
||||||
|
- Destination reserve applies only while the canonical reveal generation is
|
||||||
|
pending.
|
||||||
|
- Unreserved capacity is work-conserving: any queue may use it.
|
||||||
|
- At least one noncritical/retirement operation is admitted when capacity
|
||||||
|
remains, preventing starvation during a slow destination.
|
||||||
|
- Failed stages retain their exact receipt and queue position.
|
||||||
|
- Callback reentrancy appends work; it never mutates the active cursor.
|
||||||
|
- `_deferredApply`, `MaxDrainIterations`, the eager priority-radius bypass, and
|
||||||
|
count-only `MaxCompletionsPerFrame` execution disappear at cutover.
|
||||||
|
|
||||||
|
## 6. Immediate quiesce versus deferred release
|
||||||
|
|
||||||
|
At a hard destination-generation edge:
|
||||||
|
|
||||||
|
1. The old world generation is marked unavailable to normal world drawing,
|
||||||
|
picking, radar, status targeting, and collision queries.
|
||||||
|
2. Object/static animation, PhysicsScript, particle emission, and ambient/
|
||||||
|
owner-tagged audio for that generation are frozen or silenced.
|
||||||
|
3. The portal tunnel/UI/event path continues, matching retail's
|
||||||
|
`blocking_for_cells` branch.
|
||||||
|
4. Stable resident landblock IDs are captured once.
|
||||||
|
5. Per-landblock spatial detach and owner/resource release advance from cursors.
|
||||||
|
|
||||||
|
Quiesce is idempotent and generation-scoped. It does not destroy live server
|
||||||
|
identity, replay Hidden/UnHide, or clear the replacement generation.
|
||||||
|
|
||||||
|
For ordinary Near→Far demotion outside a hard portal edge, the exact landblock
|
||||||
|
detach remains the immediate visibility/collision boundary; only its expensive
|
||||||
|
owner cleanup is deferred.
|
||||||
|
|
||||||
|
## 7. Publication contract
|
||||||
|
|
||||||
|
One accepted completion progresses through:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Admitted
|
||||||
|
-> PreparedReceipt
|
||||||
|
-> RenderPrefix
|
||||||
|
-> PhysicsBase
|
||||||
|
-> RenderCellsBuildings
|
||||||
|
-> StaticEntityPresentationAndCollision
|
||||||
|
-> SpatialCommit
|
||||||
|
-> RenderPinsAndEnvCellReplay
|
||||||
|
-> LiveProjectionRecovery
|
||||||
|
-> Complete
|
||||||
|
```
|
||||||
|
|
||||||
|
Each transition owns a retry receipt and known cost. Mutation order remains the
|
||||||
|
existing retail-rooted order. A stage cannot publish partial externally visible
|
||||||
|
state unless its receipt describes and resumes that exact partial prefix.
|
||||||
|
|
||||||
|
Destination reveal consumes only `Complete`/renderer-upload facts belonging to
|
||||||
|
the active destination generation. Far-ring work may continue after reveal.
|
||||||
|
|
||||||
|
## 8. Threading
|
||||||
|
|
||||||
|
- Worker threads build immutable `LandblockBuild`/prepared payloads and enqueue
|
||||||
|
immutable completions only.
|
||||||
|
- The update/render thread is the sole scheduler, meter, world-state,
|
||||||
|
publication, and retirement writer.
|
||||||
|
- GL upload/non-residency/deletion remains with renderer resource owners.
|
||||||
|
- No update operation waits for the worker, a GPU fence, file I/O, or a lock
|
||||||
|
held by render work.
|
||||||
|
- Back-pressure never blocks the update thread. Worker-side bounded queues may
|
||||||
|
wait/cancel; update-side admission is non-blocking.
|
||||||
|
|
||||||
|
## 9. Delivery checkpoints
|
||||||
|
|
||||||
|
### E0 — Oracle, inventory, and contract
|
||||||
|
|
||||||
|
- Record named-retail teardown/blocking pseudocode.
|
||||||
|
- Inventory every current publication/retirement owner and bypass.
|
||||||
|
- Define budget dimensions, atomic work, queue ordering, quiesce, retries,
|
||||||
|
threading, diagnostics, and acceptance.
|
||||||
|
|
||||||
|
**Complete 2026-07-24.**
|
||||||
|
|
||||||
|
### E1 — Typed budgets, meter, cost model, and diagnostics
|
||||||
|
|
||||||
|
- Add validated `StreamingWorkBudgetOptions` to `RuntimeOptions`.
|
||||||
|
- Add pure `StreamingWorkMeter` and deterministic injected-clock tests.
|
||||||
|
- Add exact immutable completion-cost estimation.
|
||||||
|
- Publish per-stage backlog, bytes, oldest age, work/yield/overrun facts through
|
||||||
|
lifecycle artifacts.
|
||||||
|
- Preserve current execution while measuring the would-yield decisions.
|
||||||
|
|
||||||
|
### E2 — Explicit admission queues
|
||||||
|
|
||||||
|
- Replace `_deferredApply` with stable generation/priority queues.
|
||||||
|
- Bound result admission by count and CPU bytes.
|
||||||
|
- Remove `MaxDrainIterations`.
|
||||||
|
- Preserve exact retry position and stale-generation rejection.
|
||||||
|
- Keep current publication atomic until E4, but execute only work admitted by
|
||||||
|
the typed meter.
|
||||||
|
|
||||||
|
### E3 — Quiesce and budgeted retirement
|
||||||
|
|
||||||
|
- Add destination-generation world quiesce.
|
||||||
|
- Tag/stop owner audio at the immediate edge.
|
||||||
|
- Make full-window and recenter retirement admission cursor/time/entity bounded.
|
||||||
|
- Make each retirement ticket advance by bounded atomic entity/stage work.
|
||||||
|
- Prove no old generation ticks, emits, collides, targets, or renders while its
|
||||||
|
retained memory converges.
|
||||||
|
|
||||||
|
### E4 — Cursor-budgeted publication
|
||||||
|
|
||||||
|
- Move stable ordered arrays/cost facts into retained receipts.
|
||||||
|
- Cursor static cleanup, static light/collision/plugin publication, physics
|
||||||
|
cell/building work, and environment-cell publication at safe boundaries.
|
||||||
|
- Feed GPU requested-byte and retirement-operation facts from renderer owners.
|
||||||
|
- Prove every failure resumes the exact unfinished operation without replay.
|
||||||
|
|
||||||
|
### E5 — Destination reservation and reveal generation
|
||||||
|
|
||||||
|
- Replace eager `PriorityRadius` execution with destination reservations.
|
||||||
|
- Join scheduler destination generation to the existing reveal coordinator.
|
||||||
|
- Keep the tunnel animating and surface the retail wait cue/diagnostic beyond
|
||||||
|
five seconds.
|
||||||
|
- Remove the last count-only execution/bypass paths.
|
||||||
|
|
||||||
|
### E6 — Gates and closeout
|
||||||
|
|
||||||
|
- Deterministic pressure, reentrancy, failure, cancellation, stale-generation,
|
||||||
|
GUID reuse, dungeon, outdoor, and session-reset suites.
|
||||||
|
- Release build and full solution tests.
|
||||||
|
- Physical-local capped/uncapped nine-stop and pinned dense-Arwic routes.
|
||||||
|
- Compare portal p99 and maximum single-frame allocation to Slice A and Slice C.
|
||||||
|
- Require zero `viewport-before-ready`, zero stranded old generation, staged
|
||||||
|
upload, collision, effect, audio, or GPU owner.
|
||||||
|
- Fixed-camera screenshots and subjective visual gate only if pixels change.
|
||||||
|
- Update architecture, inventory, issues, roadmap, divergence register, and
|
||||||
|
durable memory.
|
||||||
|
|
||||||
|
## 10. Acceptance
|
||||||
|
|
||||||
|
Slice E closes only when:
|
||||||
|
|
||||||
|
1. No priority or unload path bypasses all work budgets.
|
||||||
|
2. No frame exceeds any configured count/byte/entity dimension.
|
||||||
|
3. Every time overrun names one indivisible operation; none remain above the
|
||||||
|
configured time ceiling at closeout.
|
||||||
|
4. Old generations become unavailable, tick-frozen, and audio-silent at the
|
||||||
|
hard transition edge.
|
||||||
|
5. Retirement/publication retries resume exact cursors without replay.
|
||||||
|
6. Deferred retained CPU bytes stay within their queue budget.
|
||||||
|
7. Reveal is possible only for the active destination generation and the
|
||||||
|
existing readiness predicate.
|
||||||
|
8. Portal-window p99 and largest frame allocation materially improve over the
|
||||||
|
post-Slice-A physical baseline.
|
||||||
|
9. Complete connected routes end with zero pending publication, retirement,
|
||||||
|
upload, effect, collision, audio, and stale-generation owners.
|
||||||
|
10. Visual output/range/quality and retail gameplay behavior are unchanged.
|
||||||
|
|
@ -0,0 +1,177 @@
|
||||||
|
# Retail landblock/object retirement and portal blocking — pseudocode
|
||||||
|
|
||||||
|
**Purpose:** Oracle boundary for Modern Runtime Slice E.
|
||||||
|
|
||||||
|
## Named-retail sources
|
||||||
|
|
||||||
|
- `CLandBlock::destroy_static_objects @ 0x0052FA50`
|
||||||
|
- `CLandBlock::Destroy @ 0x0052FAA0`
|
||||||
|
- `CObjectMaint::DestroyObjects @ 0x00508C30`
|
||||||
|
- `CObjectMaint::AddObjectToBeDestroyed @ 0x00508F70`
|
||||||
|
- `SmartBox::UseTime @ 0x00455410`
|
||||||
|
|
||||||
|
The Sept 2013 named pseudo-C is the behavioral oracle. WorldBuilder has no
|
||||||
|
equivalent live-client teardown scheduler; its extracted mesh/cache owners are
|
||||||
|
implementation references only.
|
||||||
|
|
||||||
|
## `CLandBlock::destroy_static_objects`
|
||||||
|
|
||||||
|
```text
|
||||||
|
for i = 0 .. num_static_objects - 1:
|
||||||
|
object = static_objects[i]
|
||||||
|
if object != null:
|
||||||
|
object.leave_world()
|
||||||
|
delete object
|
||||||
|
|
||||||
|
num_static_objects = 0
|
||||||
|
```
|
||||||
|
|
||||||
|
The operation is synchronous in retail. Each object leaves the world before
|
||||||
|
its memory is destroyed.
|
||||||
|
|
||||||
|
## `CLandBlock::Destroy`
|
||||||
|
|
||||||
|
```text
|
||||||
|
destroy_static_objects()
|
||||||
|
destroy_buildings()
|
||||||
|
|
||||||
|
if landblock_info != null:
|
||||||
|
landblock_info.Release()
|
||||||
|
landblock_info = null
|
||||||
|
|
||||||
|
closest = invalid
|
||||||
|
lbi_exists = false
|
||||||
|
direction = unknown
|
||||||
|
|
||||||
|
if draw_array != null:
|
||||||
|
delete[] draw_array
|
||||||
|
draw_array = null
|
||||||
|
|
||||||
|
draw_array_size = 0
|
||||||
|
```
|
||||||
|
|
||||||
|
Retail does not expose a partially active destroyed landblock. The visible,
|
||||||
|
spatial, ticking, and memory lifetimes end in one call.
|
||||||
|
|
||||||
|
## `CObjectMaint::DestroyObjects`
|
||||||
|
|
||||||
|
```text
|
||||||
|
for every physics object:
|
||||||
|
object.exit_world()
|
||||||
|
object.leave_world()
|
||||||
|
remove object from object_table
|
||||||
|
remove object from null_object_table
|
||||||
|
remove object from destruction schedule
|
||||||
|
object.unset_parent()
|
||||||
|
object.unparent_children()
|
||||||
|
delete object
|
||||||
|
|
||||||
|
for every weenie object:
|
||||||
|
remove from weenie tables
|
||||||
|
delete object
|
||||||
|
|
||||||
|
destroy all object/null/weenie/inventory tables
|
||||||
|
destroy lost-cell table
|
||||||
|
```
|
||||||
|
|
||||||
|
Again, execution is complete once begun. Parent/child and spatial withdrawal
|
||||||
|
precede physical deletion.
|
||||||
|
|
||||||
|
## `CObjectMaint::AddObjectToBeDestroyed`
|
||||||
|
|
||||||
|
```text
|
||||||
|
remove any prior destruction schedule for object_id
|
||||||
|
deadline = Timer.cur_time + 25 seconds
|
||||||
|
destruction_table[object_id] = deadline
|
||||||
|
destruction_priority_queue.Insert(deadline, object_id)
|
||||||
|
```
|
||||||
|
|
||||||
|
This queue delays *when* complete object destruction begins. It is not
|
||||||
|
precedent for leaving an object active while destroying it one field at a
|
||||||
|
time. Acdream's 25-second nonresident live-object lifetime already ports this
|
||||||
|
separate behavior.
|
||||||
|
|
||||||
|
## `SmartBox::UseTime`
|
||||||
|
|
||||||
|
```text
|
||||||
|
if cell_manager.blocking_for_cells == false:
|
||||||
|
if not all_cells_available and CheckPrefetchStatus():
|
||||||
|
CellManager.UpdateLoadPoint()
|
||||||
|
|
||||||
|
if player exists and player has a cell:
|
||||||
|
CellManager.ChangePosition(player.position)
|
||||||
|
|
||||||
|
if player exists and not waiting_for_teleport
|
||||||
|
and not position_update_complete:
|
||||||
|
position_update_complete = true
|
||||||
|
has_been_teleported = true
|
||||||
|
|
||||||
|
ObjectMaint.UseTime()
|
||||||
|
Physics.UseTime()
|
||||||
|
GameTime.UseTime()
|
||||||
|
LScape.UseTime()
|
||||||
|
Ambient.UseTime()
|
||||||
|
else:
|
||||||
|
CellManager.CheckPrefetchStatus()
|
||||||
|
|
||||||
|
SceneTool.Think()
|
||||||
|
drain inbound SmartBox event queue
|
||||||
|
CommandInterpreter.UseTime()
|
||||||
|
Render.CalcDegLevel()
|
||||||
|
```
|
||||||
|
|
||||||
|
While retail is blocked for destination cells, the old world does not advance
|
||||||
|
object maintenance, physics, landscape, game time, or ambient sound. UI/event
|
||||||
|
dispatch and the portal presentation continue. This is the retail basis for
|
||||||
|
Slice E's immediate old-generation quiesce.
|
||||||
|
|
||||||
|
## Acdream asynchronous adaptation
|
||||||
|
|
||||||
|
Retail performs each teardown synchronously and can synchronously block cell
|
||||||
|
loading. Acdream prepares content on a worker and must not spend an unbounded
|
||||||
|
render/update frame reproducing that transaction. The faithful observable
|
||||||
|
contract is therefore split at a different boundary:
|
||||||
|
|
||||||
|
```text
|
||||||
|
begin destination generation:
|
||||||
|
mark prior world generation unavailable
|
||||||
|
replace normal world viewport with portal presentation
|
||||||
|
freeze old-generation object/static/effect simulation
|
||||||
|
silence old-generation audio
|
||||||
|
reject old generation from collision, picking, radar, and targeting
|
||||||
|
|
||||||
|
over later update/resource-maintenance frames:
|
||||||
|
detach old landblocks through exact retry receipts
|
||||||
|
release scripts/effects/lights/plugin projections
|
||||||
|
release CPU owners
|
||||||
|
admit renderer retirement; physical GL release remains fence delayed
|
||||||
|
|
||||||
|
in parallel, under reserved destination budgets:
|
||||||
|
admit destination completions
|
||||||
|
publish collision and required Near render state
|
||||||
|
request/upload required assets
|
||||||
|
|
||||||
|
reveal only when the one destination-generation readiness state proves:
|
||||||
|
collision root ready
|
||||||
|
required Near scene ready
|
||||||
|
required composite textures ready
|
||||||
|
camera/player identity belongs to destination generation
|
||||||
|
```
|
||||||
|
|
||||||
|
Release-later never means run-later: an old owner may retain memory until its
|
||||||
|
cursor runs, but it cannot keep simulating, colliding, rendering, targeting, or
|
||||||
|
emitting audible work after the generation-quiesce edge.
|
||||||
|
|
||||||
|
## Port constraints
|
||||||
|
|
||||||
|
1. Preserve existing exact retry receipts; successful stages never replay.
|
||||||
|
2. FIFO is stable within priority and generation.
|
||||||
|
3. A time limit is checked between atomic owner operations. If one atomic
|
||||||
|
operation itself exceeds its ceiling, diagnostics name that operation; it
|
||||||
|
is then split at its natural cursor rather than interrupted mid-mutation.
|
||||||
|
4. No deferred callback may mutate GL from a worker.
|
||||||
|
5. Destination-critical work receives a reserved share of each frame; it does
|
||||||
|
not bypass all budgets.
|
||||||
|
6. A reveal delay beyond retail's five-second fade ceiling keeps the portal
|
||||||
|
tunnel active and displays the retail wait cue. It never reveals an
|
||||||
|
incomplete world.
|
||||||
Loading…
Add table
Add a link
Reference in a new issue