fix(diagnostics): keep UI scripts on game-loop time

Preserve sub-millisecond frame deltas with a command-local compensated clock so uncapped diagnostic routes do not outrun materialization and settling. Keep sleep boundaries inclusive, wait timeouts strict, and handle long-duration and invalid-delta cases deterministically.

Record the aligned seven-destination connected route with a full turn at every stop. Release build succeeds and all 6,308 tests pass with five intentional skips.

Co-authored-by: OpenAI Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-19 16:38:49 +02:00
parent 3718e341be
commit b95bb3e21c
4 changed files with 336 additions and 15 deletions

View file

@ -126,18 +126,51 @@ stable radix, avoiding a second immediate-buffer pack for deferred transparent
instances, packing per-instance light sets, caching static picking descriptors,
and using checked direct group handles. Historical material groups now retire
after one complete unused frame (not after one `Draw`, because landscape slices
and paperdoll share the dispatcher) and release their list capacity. That dense
sample reached roughly 5.36.2 ms CPU / 7.18.3 ms p95 and 3.23.6 ms GPU before
the final group-retirement review correction.
and paperdoll share the dispatcher) and release their list capacity. Before the
final group-retirement review correction, that fixed dense sample reached
5.36.2 ms CPU p50, 7.18.3 ms CPU p95, and 3.23.6 ms GPU p50.
The earlier software limiter also used coarse `Thread.Sleep`, whose nominal
one-millisecond waits measured about 15.98 ms on this host. A reusable Windows
high-resolution waitable timer now paces to the monitor deadline and is reported
as `pace` by the frame profiler. Scripted UI automation no longer enables the
allocation-heavy GPU-stream dump implicitly, and graceful shutdown now wakes
all persistent mesh workers without resetting their shared wake signal. The
post-review connected stress rerun remains pending because local ACE was not
listening; sparse-scene 239 FPS samples are not substituted for that gate.
all persistent mesh workers without resetting their shared wake signal. The UI
automation clock now uses command-local compensated accumulation, retaining
sub-millisecond frame deltas instead of rounding every uncapped frame up to one
millisecond. Exact sleep and strict timeout boundaries therefore remain stable
across high-refresh frames and long scripts.
The post-review connected rerun passed on 2026-07-19. It used the complete
Caul → Sawato → Rynthid → Aerlinthe → Sawato → Holtburg → Caul route, waited for
each actual materialization, allowed at least five seconds of destination
streaming, synchronized to the next profiler boundary, and then held the retail
turn-right action through one dedicated interval (4.935.07 seconds, more than
one full visibility sweep) at every stop. Each
turn window and its following stationary window were captured on separate
profiler boundaries. The uncapped Release client completed all seven portals
and seven turns and shut down gracefully, with no exception, WER report, or AMD
driver reset observed in the process logs, Windows event logs, or crash-dump
directory. Returned dense Caul contained about 21,024 visible entities and
measured 3.8 ms median / 5.0 ms p95 CPU and 2.6 ms median / 3.2 ms p95 GPU while
stationary (241 FPS in the title sample). Its complete turning window measured
3.0 ms median / 4.9 ms p95 CPU and 2.0 ms median / 3.4 ms p95 GPU.
Across all stationary destinations, CPU p50/p95 ranged from 1.14.0 /
1.65.1 ms and GPU p50/p95 from 0.72.8 / 1.03.4 ms. Across the turn
windows, those ranges were 1.03.1 / 1.84.9 ms CPU and
0.72.0 / 1.23.4 ms GPU. Working/private memory was 939.8/1,438.3 MiB on the
first Caul dwell; the highest stationary sample was 1,065.0/1,660.6 MiB in
Holtburg, followed by 1,034.8/1,630.5 MiB on the Caul return. The samples were
non-monotonic, but one circuit is not claimed as a new lifetime plateau proof.
Startup reached a transient 240.2 ms maximum, and the largest later
destination-load window reached 81.9 ms CPU; all isolated turn and stationary
windows recovered to low-millisecond frame times, so this run is not described
as stall-free.
The run was performed over RDP, but software pacing was explicitly disabled and
`pace` remained zero, so these are engine-throughput measurements rather than
remote-display refresh measurements. The lifestone/particle visual gate remains.
**Files:** `src/AcDream.App/Rendering/RetailAlphaQueue.cs`;
`src/AcDream.App/Rendering/Wb/WbDrawDispatcher.cs`;
@ -153,7 +186,13 @@ listening; sparse-scene 239 FPS samples are not substituted for that gate.
`src/AcDream.Content/BoundedDatObjectCache.cs`;
`src/AcDream.Content/DecodedTextureCache.cs`;
`src/AcDream.App/Rendering/FramePacingController.cs`;
`src/AcDream.App/Rendering/WindowsHighResolutionFramePacingWaiter.cs`.
`src/AcDream.App/Rendering/WindowsHighResolutionFramePacingWaiter.cs`;
`src/AcDream.App/Diagnostics/FrameProfiler.cs`;
`src/AcDream.App/Rendering/GameWindow.cs`;
`src/AcDream.App/Rendering/Wb/ObjectMeshManager.cs`;
`src/AcDream.App/Rendering/Wb/CachedBatch.cs`;
`src/AcDream.App/Rendering/Wb/EntityClassificationCache.cs`;
`src/AcDream.App/UI/Testing/RetailUiAutomationScriptRunner.cs`.
**Research:**
`docs/research/2026-07-18-retail-shared-alpha-list-pseudocode.md`;

View file

@ -562,7 +562,7 @@ behavior. Estimated 1726 days focused work, 35 weeks calendar.
- **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/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.
- **Render-thread CPU and high-refresh pacing correction 2026-07-19; automated/review gates passed, connected rerun pending.** Software pacing now uses one reusable Windows high-resolution waitable timer instead of scheduler-quantized `Thread.Sleep`; the permanent profiler attributes that wait as `pace`. Wb keeps exact stable far-to-near alpha order while using a radix key, avoids immediate SSBO packing for deferred transparent objects, packs each eight-light set, caches immutable selection descriptors, and retires historical material groups only after one complete unused frame across every landscape/dynamics/paperdoll draw scope. A fixed dense-Caul sample improved from roughly 912 ms CPU to 5.36.2 ms without reducing view distance, particles, textures, streaming radius, or other quality. The prior 141.8 FPS result remains scene-specific; local ACE was offline for the post-review connected rerun.
- **Render-thread CPU and high-refresh pacing correction 2026-07-19; automated/review/connected gates passed, final translucency visual gate pending.** Software pacing now uses one reusable Windows high-resolution waitable timer instead of scheduler-quantized `Thread.Sleep`; the permanent profiler attributes that wait as `pace`. Wb keeps exact stable far-to-near alpha order while using a radix key, avoids immediate SSBO packing for deferred transparent objects, packs each eight-light set, caches immutable selection descriptors, and retires historical material groups only after one complete unused frame across every landscape/dynamics/paperdoll draw scope. A fixed dense-Caul sample improved from roughly 912 ms CPU to 5.36.2 ms without reducing view distance, particles, textures, streaming radius, or other quality. The corrected post-review uncapped route waited for every materialization and held a full visibility sweep through one dedicated profiler window at all seven destinations. Returned dense Caul (about 21,024 visible entities) measured 3.0/4.9 ms CPU p50/p95 and 2.0/3.4 ms GPU while turning, then 3.8/5.0 ms CPU and 2.6/3.2 ms GPU stationary (241 FPS title sample). First/return Caul memory was 939.8/1,438.3 and 1,034.8/1,630.5 MiB working/private; the highest stationary sample was 1,065.0/1,660.6 MiB in Holtburg, and the client exited gracefully. With pacing disabled (`pace=0`) and title samples reaching 844 FPS, RDP did not refresh-cap engine throughput. UI automation now uses a command-local compensated clock, preserving sub-millisecond frame deltas and exact long-duration sleep/timeout boundaries.
**Reference docs:** `docs/research/retail-ui/00-master-synthesis.md` + slices 01-06. Every AC-specific behavior has a decompiled FUN_ / DAT_ citation.