perf(rendering): reconcile only changed attachments

This commit is contained in:
Erik 2026-07-25 05:18:33 +02:00
parent 6b56f4bef2
commit b9cbf5e040
8 changed files with 246 additions and 14 deletions

View file

@ -328,7 +328,7 @@ graph corrupts collision state, which is worse than the allocation.
## #238 — EquippedChildRenderController ticks twice per frame with six ToArray snapshots
**Status:** OPEN
**Status:** DONE — 2026-07-25, Modern Runtime Slice H-a3
**Severity:** MEDIUM
**Filed:** 2026-07-24
**Component:** render / live entities
@ -350,6 +350,14 @@ the ordering and skip the redundant recomposition instead. Plan Slice H-a.
**Files:** `src/AcDream.App/Rendering/EquippedChildRenderController.cs:265-310,1421-1429`;
`src/AcDream.App/Update/LiveObjectFrameController.cs:204,241`.
**Resolution:** Both required authority boundaries remain. The first is still a
complete parent-first pose pass; the post-network boundary now compares the
exact parent's pose version, identity, visibility, and cell and recomposes only
changed branches. Publishing a changed child dirties its descendants naturally
within the same parent-first walk. Per-heartbeat pending dictionaries use
retained typed snapshots instead of arrays. Evidence:
`docs/research/2026-07-25-slice-h-a3-attached-pose-reconcile.md`.
---
## #239 — Inbound net path allocates 3-4 arrays/objects per packet

View file

@ -62,7 +62,7 @@ cooldown step.
Landed evidence:
[`../research/2026-07-25-slice-h-a2-cooldown-scope.md`](../research/2026-07-25-slice-h-a2-cooldown-scope.md).
### H-a3 — equipped-child transition work
### H-a3 — equipped-child transition work — COMPLETE
1. Preserve both frame ordering points: pre-network presentation and
post-network spatial reconciliation have different authority boundaries.
@ -77,6 +77,9 @@ Landed evidence:
Gate: equip, unparent, reparent, pose loss, rollback, delete, GUID reuse, and
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
1. Reuse one synchronous `RetailPViewFrameInput` owned by

View file

@ -0,0 +1,45 @@
# Slice H-a3 — equipped-child post-network reconciliation
## Preserved ordering
Retail live-object presentation still has two authority boundaries:
1. the complete parent-first attachment update after animation;
2. post-network spatial reconciliation after accepted inbound mutations.
The second boundary was not deleted or delayed.
## Change
`EntityEffectPoseRegistry` now carries a monotonic change version for the
current pose-owner lifetime. It advances only when root, indexed parts, part
availability, or cell changes.
Each attached projection remembers the exact parent entity, pose version,
draw/ancestor visibility, and parent cell used for its last composition.
- The animation-order pass remains a complete parent-first walk.
- The post-network pass keeps transition retries but skips a child whose
remembered parent presentation is unchanged.
- A changed root recomposes its direct child; publishing that child's pose
advances its version, so descendants update later in the same parent-first
pass.
- Hidden/NoDraw ancestry and cell changes participate even when the geometric
pose itself is unchanged.
- Pose failure still withdraws the same complete subtree.
The per-frame transition retry path no longer allocates dictionary `ToArray`
snapshots. It copies key/value pairs into retained typed scratch lists, keeping
the old snapshot-before-callback semantics.
## Gate
- Existing equip/unparent/reparent/rollback/pose-loss/teardown tests pass.
- A root → child → grandchild test proves unchanged post-network reconcile
performs zero compositions and a changed root performs exactly two in
parent-first order.
- 1,000 stable post-network reconciles allocate zero managed bytes on the
calling thread.
Release gate: 3,783 App tests passed / 3 skipped; 8,267 complete-solution
tests passed / 5 skipped.