perf(rendering): retain synchronous frame scratch
Reuse the PView frame input, publish mutation-invalidated landblock views, and avoid constructing optional shadow iterators while preserving title and lifecycle visibility facts.
This commit is contained in:
parent
b9cbf5e040
commit
b3427554c3
10 changed files with 397 additions and 129 deletions
|
|
@ -80,21 +80,26 @@ subtree-withdrawal suites preserve exact event and resource counts.
|
|||
Landed evidence:
|
||||
[`../research/2026-07-25-slice-h-a3-attached-pose-reconcile.md`](../research/2026-07-25-slice-h-a3-attached-pose-reconcile.md).
|
||||
|
||||
### H-a4 — diagnostics and frame scratch
|
||||
### H-a4 — diagnostics and frame scratch — COMPLETE
|
||||
|
||||
1. Reuse one synchronous `RetailPViewFrameInput` owned by
|
||||
`WorldSceneRenderer`; reset every field before each draw.
|
||||
2. Expose stable borrowed landblock entry/bounds views instead of creating
|
||||
iterator state in each frame.
|
||||
3. Consumer-gate diagnostic landblock visibility counting and shadow
|
||||
enumeration. When no DebugVM/collision/probe consumer exists, publish a
|
||||
neutral diagnostic outcome without scanning resident landblocks.
|
||||
3. Consumer-gate optional shadow enumeration. Preserve landblock visibility
|
||||
counting because the normal title and lifecycle checkpoints are active
|
||||
consumers of `lb V/T`; neutralizing it would be a visible/automation
|
||||
behavior change.
|
||||
4. Do not rework `InteriorEntityPartition` while the G4 referee remains.
|
||||
Issue #241 closes with G5 old-route deletion, not by editing the fallback.
|
||||
5. Profile capped and uncapped production paths and retain evidence.
|
||||
|
||||
Gate: identical framebuffer/scene digest, no per-frame PView input allocation,
|
||||
and no diagnostic world traversal with all consumers disabled.
|
||||
no iterator allocation for stable landblock views, and no shadow traversal
|
||||
with all optional consumers disabled.
|
||||
|
||||
Landed evidence:
|
||||
[`../research/2026-07-25-slice-h-a4-frame-scratch.md`](../research/2026-07-25-slice-h-a4-frame-scratch.md).
|
||||
|
||||
## 3. H-b — exact light top-k
|
||||
|
||||
|
|
|
|||
69
docs/research/2026-07-25-slice-h-a4-frame-scratch.md
Normal file
69
docs/research/2026-07-25-slice-h-a4-frame-scratch.md
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
# Slice H-a4 — retained frame scratch and diagnostic traversal
|
||||
|
||||
## Scope
|
||||
|
||||
This is a behavior-preserving ownership/allocation correction. It does not
|
||||
change retail visibility, PView construction, spatial ordering, collision
|
||||
debug drawing, title facts, or lifecycle checkpoint facts.
|
||||
|
||||
## Findings
|
||||
|
||||
Three independent steady-frame allocation sources remained:
|
||||
|
||||
1. `WorldSceneRenderer` constructed one `RetailPViewFrameInput` reference
|
||||
object for every PView frame even though `DrawInside` consumes it
|
||||
synchronously.
|
||||
2. `GpuWorldState.LandblockEntries` and `LandblockBounds` were C# iterator
|
||||
methods, so merely obtaining each sequence constructed fresh iterator
|
||||
state. The underlying spatial membership changed only at update-thread
|
||||
publication boundaries.
|
||||
3. `WorldSceneDiagnosticsController` passed
|
||||
`ShadowObjectRegistry.AllEntriesForDebug()` to the DebugVM publisher even
|
||||
when no developer UI consumer existed. The publisher correctly avoided
|
||||
enumeration, but the yield sequence itself had already been constructed.
|
||||
|
||||
The execution plan initially described landblock visibility counting as an
|
||||
unconsumed diagnostic. That was incorrect in the current application:
|
||||
`WorldRenderFrameOutcome` feeds the always-visible FPS/title `lb V/T` values
|
||||
and connected lifecycle snapshots. Returning a neutral count would therefore
|
||||
change observable behavior and invalidate lifecycle evidence. The count is
|
||||
retained; only its iterator allocation is removed.
|
||||
|
||||
## Implementation
|
||||
|
||||
- `WorldSceneRenderer` owns one `RetailPViewFrameInput` and resets every field
|
||||
before the synchronous `DrawInside` call. The input is publicly read-only
|
||||
and internally mutable so downstream render owners cannot change borrowed
|
||||
frame facts.
|
||||
- `GpuWorldState` exposes retained entry, no-animated-index entry, and bounds
|
||||
lists. They rebuild only after landblock membership, resident entity-list,
|
||||
animated-index, or AABB changes. Existing render-traversal slot order is
|
||||
preserved exactly.
|
||||
- Landblock diagnostic counting uses indexed access over the retained bounds
|
||||
view.
|
||||
- Shadow enumeration is constructed only when the DebugVM is mounted. The
|
||||
independent collision-wireframe switch keeps its existing enumeration.
|
||||
- `InteriorEntityPartition` remains untouched while the G4 referee is still
|
||||
retained. Its removal and issue #241 close remain G5 work after the user
|
||||
accepts the G4 visual gate.
|
||||
|
||||
## Conformance
|
||||
|
||||
- Stable retained render-view getters allocate zero bytes over 1,000 polls.
|
||||
- A spatial mutation refreshes the same borrowed list identity and publishes
|
||||
the new count.
|
||||
- Two successive PView frames receive the same input object, reset with the
|
||||
current frame values.
|
||||
- Existing quiescence, render traversal, animated-index, PView executor,
|
||||
abort/recovery, and DebugVM tests remain unchanged in behavior.
|
||||
|
||||
## Rollback boundary
|
||||
|
||||
This work is independent of the G4 production-source cutover. If tomorrow's
|
||||
visual gate rejects G4, use:
|
||||
|
||||
```text
|
||||
git revert ef1d263337997bb030eadb7b8e71d73dc659907a
|
||||
```
|
||||
|
||||
Do not revert this Slice H-a4 commit, G3, or the portal-warmup corrections.
|
||||
Loading…
Add table
Add a link
Reference in a new issue