docs: §4 outdoor full-world flap — onset pinned to building-flood merge (handoff)
Evidence-chain handoff for the outdoor flap investigation: frame-exact onset (pv-input flood 1->5 + the gl-state doorway-box fingerprint, same frame), the full probe exoneration chain (camera matrix NaN-free at 6 dp, eye above terrain, cross-frame GL leak refuted, full-screen quad planes can't cull, MergeNearbyBuildingFloods doesn't touch OutsideView, ClipFrame capacity clean), the two surviving kill-mechanism suspects (per-instance clip-slot routing under outdoor roots / terrain UBO content at draw time), the decisive [clip-route] probe spec, the user-validated repro protocol, and the probe-semantics gotchas. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
fafe5d66e8
commit
d877e4329a
1 changed files with 105 additions and 0 deletions
|
|
@ -0,0 +1,105 @@
|
|||
# HANDOFF — §4 outdoor FULL-WORLD flap: onset pinned to the building-flood merge
|
||||
|
||||
**Date:** 2026-06-09 (late evening). **Branch:** `claude/thirsty-goldberg-51bb9b`, HEAD `fafe5d6`.
|
||||
**Status:** trigger pinned frame-exact; kill mechanism NOT yet pinned — one purpose-built
|
||||
probe (or RenderDoc) decides it. Read this top-to-bottom before touching code.
|
||||
|
||||
---
|
||||
|
||||
## 0. TL;DR
|
||||
|
||||
1. **The user-visible bug:** standing/running OUTDOORS at specific spots, the WHOLE world
|
||||
(terrain + buildings + entities + the player model + sky) drops to the fog-tinted clear
|
||||
color. It strobes at onset then HOLDS; rotating the camera pops it back; walking
|
||||
forward through the trigger zone reproduces it; sidestep/backwards through the same
|
||||
zone does not. Confirmed distinct from #106 (membership healthy throughout).
|
||||
2. **Frame-exact onset (the day's key result):** the flap begins at EXACTLY the frame the
|
||||
nearby cottage's per-building flood merges into the outdoor root —
|
||||
`[pv-input] flood=1 → flood=5` with player/yaw frozen and only the camera boom settling
|
||||
(~3 cm/frame). Same frame, the `[gl-state]` tripwire shows the leftover scissor box
|
||||
flip from full-screen to a **drifting 9×21 px doorway footprint** (the cottage doorway
|
||||
projected to screen, moving with the eye's micro-settle). Onset evidence:
|
||||
`flap-glstate-capture.log` (gl-state frame 4977 = log line 5006); the same transition
|
||||
with full render-sig fields: `flap-residual-capture.log` (38 such transitions, e.g.
|
||||
frame 1745→1746: ONLY `ids=`/`draw=` gain a cell — every other field identical,
|
||||
`out=10529` instances submitted in BOTH frames).
|
||||
3. **Massive exoneration chain (all probe-verified, do not re-tread):** membership/root/
|
||||
viewer cell stable; `res=None`; camera view-projection matrix sane and NaN-free
|
||||
(11,767 frames, 6 dp); eye 1.6–2.1 m ABOVE terrain (buried-eye refuted); flood/
|
||||
outPolys/outSlices/outMode constant; full-screen quad clip planes mathematically
|
||||
cannot cull; `MergeNearbyBuildingFloods` does NOT touch OutsideView; cross-frame GL
|
||||
state leak refuted (`[gl-state]` shows scissor test OFF + sane depth/blend/cull/vp/fbo
|
||||
entering every frame, `err=0x0`); `ClipFrameAssembler` slices carry their own plane
|
||||
arrays (slot repacking can't swap planes per se); `ClipFrame.AppendSlot/UploadShared`
|
||||
have dynamic capacity + full re-upload (no overflow).
|
||||
4. **What remains (the kill mechanism, one of):**
|
||||
a. **Per-instance clip-slot routing** (`WbDrawDispatcher.SetClipRouting` +
|
||||
`ResolveEntitySlot`, binding=3 slot SSBO): the landscape slice installs routing
|
||||
UNCONDITIONALLY (`RetailPViewRenderer.cs:215`) even for OUTDOOR roots, while the
|
||||
U.4 contract (`WbDrawDispatcher.cs:309-331`) says outdoor frames should
|
||||
`ClearClipRouting`. When the flood merges, `CellIdToSlot` gains cells and slot
|
||||
indices REPACK (cells pack before the outside view in the assembler) — if any
|
||||
instance's slot resolution or the slot SSBO content goes stale/wrong, the world's
|
||||
instances clip against the cottage's doorway planes (or CULL).
|
||||
b. **Terrain/sky UBO content at draw time** — `SetTerrainClip(slice.Planes)` should
|
||||
hold the full-screen planes; if the merge path overwrites it with doorway planes
|
||||
(or count) before terrain samples it, terrain + sky die together.
|
||||
c. Something in the per-slice draw orchestration (`DrawLandscapeThroughOutsideView`,
|
||||
`RetailPViewRenderer.cs:208-230`) that behaves differently when cell slices exist.
|
||||
5. **Why this matters beyond the spot:** the same merge boundary is crossed every time
|
||||
you run past cottages (the original "parts of the screen flash while running") and at
|
||||
cottage enter/exit — this is very likely THE remaining §4 visible flap, with the
|
||||
edge-on doorway grey (2a) and corner seal (2b) as siblings in the same family.
|
||||
|
||||
## 1. The decisive next probe (do this first)
|
||||
|
||||
Add a `[clip-route]` print-on-change probe (gate: reuse `ACDREAM_PROBE_GLSTATE` or a new
|
||||
var) emitting, per frame:
|
||||
- In `RetailPViewRenderer.DrawLandscapeThroughOutsideView`: `slice.Slot`, `slice.Planes`
|
||||
values (all 4–8 vec4s), `clipAssembly.CellIdToSlot` contents, and the first 16 bytes of
|
||||
`_clipFrame`'s terrain bytes (the count + first plane) as uploaded.
|
||||
- In `WbDrawDispatcher.Draw` (when routing active): a histogram of `ResolveEntitySlot`
|
||||
outcomes — instances per slot index + CULL count.
|
||||
|
||||
One repro run (the user triggers the flap, holds 3 s, rotates, closes) then diff the
|
||||
held-flap frames vs healthy frames. Whichever of (a)/(b) shows wrong values is the bug.
|
||||
If BOTH look correct → RenderDoc frame capture during the flap (the GPU truth).
|
||||
|
||||
## 2. Repro protocol (user-validated, fast)
|
||||
|
||||
Spot: Holtburg south slope, player ≈ (167–169, −31..−37) world frame (A9B4 anchor), the
|
||||
slope SE of town with the A9B3 cottage. Walk FORWARD downhill through the zone → strobe →
|
||||
hold. Rotate camera → recovers. `eyeAbove` stays ~+2 m (do not chase buried-eye).
|
||||
Launch with `ACDREAM_PROBE_PVINPUT=1` + `ACDREAM_PROBE_GLSTATE=1` (+ the new probe);
|
||||
AVOID `ACDREAM_PROBE_FLAP` for visual judgment runs (timing skew — render digest landmine).
|
||||
|
||||
## 3. Evidence inventory (this session's captures, worktree root, untracked)
|
||||
|
||||
| File | What it holds |
|
||||
|---|---|
|
||||
| `flap-residual-capture.log` | Full flap probes; 38 flood-merge transitions w/ render-sig field diffs; the held-flap [flap-cam]/[flap] stability blocks |
|
||||
| `flap-pvinput-capture2.log` | 11,767 pv-input frames; NaN-free matrix proof; held blocks at 6 dp |
|
||||
| `flap-eyeterr-capture.log` | eyeAbove (terrain-burial refutation) |
|
||||
| `flap-glstate-capture.log` | GL-state tripwire; frame-exact onset marker (frame 4977) + doorway-box fingerprint |
|
||||
|
||||
## 4. DO-NOT-RETRY additions from this session (full chain in §0.3)
|
||||
|
||||
- Camera matrix NaN / degenerate orientation — REFUTED (6 dp capture).
|
||||
- Eye buried in terrain — REFUTED (`eyeAbove` +1.6..2.1 m).
|
||||
- Cross-frame GL scissor/depth/blend leak — REFUTED (`[gl-state]` stable + scis=0 entering frames).
|
||||
- Full-screen outdoor quad plane collapse / winding — impossible (static CCW NDC quad).
|
||||
- `MergeNearbyBuildingFloods` contaminating OutsideView — code-verified NOT (explicitly skipped).
|
||||
- `ClipFrame` slot-capacity overflow — dynamic capacity, full re-upload, code-verified.
|
||||
- The earlier "stale render anchor explains the running distortion" attribution — PARTIAL
|
||||
only; #106 fixed the anchor, this flap persists (correction noted in the #105/#106 docs).
|
||||
|
||||
## 5. Probe-semantics gotchas (cost an hour today)
|
||||
|
||||
- `[render-sig]`'s `terrain=` prints a STALE pre-DrawInside local (always `Skip` when a
|
||||
clipRoot exists); the REAL assembler mode is `[flap-cam]`'s `terrain=` and render-sig's
|
||||
`outMode=`. Don't diff the wrong field.
|
||||
- `[render-sig]` prints on signature change only; the EYE coords are part of the
|
||||
signature → a settling boom spams lines with nothing else changing.
|
||||
- `Tee-Object` writes UTF-16LE; Python analyzers must BOM-detect (`b'\xff\xfe'`).
|
||||
- The first pv-input run produced 0 lines because the client was closed pre-entry —
|
||||
check `auto-entered player mode` exists before analyzing.
|
||||
Loading…
Add table
Add a link
Reference in a new issue