docs(render): S4 packet draft — what S3 already delivered, the alpha-list cutover, open questions

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-09-03 17:12:37 +02:00
parent e33fd24724
commit ac1b7afeb7

View file

@ -0,0 +1,137 @@
# S4 packet — depth and alpha: what S3 already delivered, what remains (lead draft, 2026-09-03 evening)
**Status:** DRAFT written while the S3 post-hoc lenses ran; NOT dispatchable
until the S3 review closes (plan §9 order: S3 review → G3 → S4). Every owner
named below is re-located at chunk time; names, not line numbers.
Specs: `oh1-depth-lifecycle.md`, `oh1-alpha-list-contract.md`; the plan's §9 S4
section; the §7 alpha/depth captures under `oh-capture/` (`*.alphadepth.log`,
line formats in `tools/walk-oracle/oh/oh-capture-alphadepth.cdb.template`).
## 1. What S3 already delivered of S4's chunk 1
S3 chunk 2 (§8 of the S3 packet, landed `be9b4c1f` + `434a7df2`) implemented
the S4 chunk-1 scope almost whole, because the walk could not be exact without
it:
| S4 chunk-1 item (plan §9) | State after S3 | Where |
|---|---|---|
| one frame-persistent latch owner for `portalsDrawnCount` | DONE — `WalkFrameDriver.PortalsDrawnCount`, retained across frames, never cleared by Begin/Abort/EndFrame | S3 §8.2 B2 |
| landscape → flush → stamp → clear → seal block gated exactly as retail (`outside_view.view_count > 0`) | DONE — `OnInteriorFloodDrawTurn(cells, outsideViewCount)`; `LandscapeFlush` leaf; stamp advance; clear ONLY IF count ≠ 0 (read-then-zero); seals | S3 §8.2 B1/B3 |
| `WalkFrameDriver`'s unconditional interior clear deleted | DONE | S3 §8.2 B1 |
| mid-frame stamp placed exactly (0x005a4886) | DONE (`AdvanceWalkPartPassStamp` at the flush leaf) | S3 §8.2 B1 |
| exit seals from the exact current views and cell order, counted by the seal leaf's return value | DONE — `DrawExitSeals` returns the submitted count; punch fans never count | S3 §8.2 B2 |
| look-ins cannot touch the root latch | DONE (look-in `DrawCells` never increments) | S3 §8.2 B2 |
| truth-table tests over root kind / draw_landscape / outside-view count / previous-current portal count | PARTIAL — the chunk-2 tests flipped the two wrong contracts (§8.3); the full truth table and the two-consecutive-frames latch test are NOT yet one theory | S4-c1 below |
The depth-lifecycle spec's "Current acdream correspondence" table (its rows
marked **missing** / **wrong** for the counter, the gate and the test
contracts) is therefore stale for those rows; the rows that still stand are
the three below.
## 2. What remains for S4 chunk 1 (S4-c1, small)
- **Far-punch depth constant.** Retail writes the far-Z punch at the exact
bits `0x3F7FFFEF`; `portal_depth.vert` uses the decimal `0.99999988`. The
chunk decides by TEST, not by eye: a pin that reinterprets `0.99999988f` and
asserts `BitConverter.SingleToInt32Bits == 0x3F7FFFEF`; if they differ, the
shader takes the hex literal (`uintBitsToFloat(0x3F7FFFEFu)`) and the
manifest hash is re-pinned. (1 2⁻²³ is the expected identity; prove it.)
- **The ±12 local-input reject.** Ghidra arbitration (S3 packet §2, the
"±12 test is an equality degenerate guard") says the check rejects a
whole polygon whose local x/y equals ±12 exactly — a degenerate-input
guard, not a clip rule. Port it at the punch-event producer as an
equality test on the LOCAL polygon before transform, with a test that
feeds one exact ±12 vertex polygon and one at ±11.999 (only the first is
rejected). If the arbitration table shows the branch can never fire for a
real DAT polygon, record that as the reason to skip and cite the table.
- **Seal/punch color state.** Retail's portal-depth draws keep color writes
ENABLED with `SRCALPHA/INVSRCALPHA` and source alpha 0 (a no-op blend);
acdream sets `ColorWrite=false`. Pixel-identical by construction; the
chunk adds the register row (AD-nnn: "portal-depth color path: write-mask
off instead of a zero-alpha blend — identical output, different state") OR
ports the exact state if the Vulkan pipeline already carries the blend
attachment; the reviewer decides which is cheaper to keep honest.
- **Truth table + two-frame latch test** (plan §9 S4 tests): one theory in
`WalkFrameDriverTests` over (root kind, draw_landscape, outside-view count,
previous count) → the exact event subsequence (`LFLUSH`, stamp, `CLEAR`?,
`SEALS`?), plus the consecutive-frames case proving the latch crosses
frames, plus "multiple look-ins isolated from the root".
## 3. S4 chunk 2 — the alpha lists (the slice's body)
**Current state (verified 2026-09-03 at `7df0b94c9`):** `RetailAlphaQueue` is
ONE scope-global list sorted by viewer distance at flush
(`SortRetailOrder` in `Flush` / `FlushFartherThan`); submitters:
`WbDrawDispatcher` (two `queue.Submit` sites: the packed path and the walk
classify path with `viewerDistance`) and `ParticleRenderer` (one site).
Barriers: `IWalkFrameLeafRenderer.AlphaBarrier``FlushLandscapeAlpha`
`_alpha.Flush()` at the building turn (retail `DrawBuilding`'s
`FlushAlphaList(0f)`), the `LandscapeFlush` leaf (retail `PView::DrawCells`'s
`FlushAlphaList(0f)` @0x005a4872), and two `RetailPViewRenderer` end-of-pass
calls (the top-level `SmartBox::RenderNormalMode` flush). `FlushFartherThan`
(the pre-punch "drain the farther content" approximation) is the AP-34 row.
**Retail (spec §5§7, verified against the decomp at chunk time):** two
independent FIFO lists (CLIP and ALPHA) of 3000 `AlphaListEntry` each;
`AddMeshToAlphaList` appends, never sorts; each `DrawMesh` invocation owns a
first-for-this-list flag that captures material + object matrix for the
list's replay; `FlushAlphaList(threshold)` is a no-op only when BOTH counts
are below `threshold × 3000`, otherwise drains CLIP then ALPHA in append
order, resets both, restores the object matrix, does NOT restore the
material; capacity overflow = append returns false and the delayed subset is
NOT drawn; `DrawBlock` calls `FlushAlphaList(0.75)` per land cell (the
pressure valve — inert below 2250 entries).
**Behavior change (chunk contract to be written after the S3 review):**
1. Replace the sorted single queue with two FIFO records mirroring the
retail entry (source token, first-for-list material/matrix capture,
`overrideClipmap`, list id) — no distance field, no sort.
2. Route every submitter to the exact list by the retail `DrawMesh` branch
table (spec §4): CLIP for the multipass clip-map delayed duplicate, ALPHA
for delayed subsets; sky/detail immediate gates; material `has_alpha`
fallback.
3. Flush sites exactly: `DrawBuilding` 0f (the existing `AlphaBarrier`),
`DrawBlock` 0.75 per land cell (NEW — a threshold flush at the `SC` turn;
inert at today's counts, pinned by a capacity test), `PView::DrawCells`
0f (the existing `LandscapeFlush`), top-level 0f (the existing pass-end
flush). Delete `FlushFartherThan` and retire AP-34.
4. Capacity 3000 per list with the exact overflow behavior (append false,
subset dropped) — pinned, not "expanded or recovered".
5. Transparent EnvCell subsets routed to their retail list (spec §6: the
environment detail surface makes eligible subsets immediate).
**Tests (plan §9 S4):** multiple translucent objects in one cell with
reversed distance vs insertion order (FIFO wins); equal-key stable tie; two
cells where a global sort disagrees with traversal; particle/object/
transparent-cell overlap; `DrawBuilding 0f` flush; pre-clear and final
flush; the 0.75 partial flush at exactly 2250; alternating blend modes across
Vulkan batches; capacity 3000 overflow drops the subset.
**Gate:** the alpha/depth transcripts exact against the §7 captures
(`*.alphadepth.log``AM` add-mesh, `FL` flush, `PM` portal mask lines), the
walk/depth/alpha suites, Release build; then the owner's G3 (S4's owner gate
per the plan) — the lead's S3-state G3 pre-run of 2026-09-03 (20/20 frames)
is the baseline to diff against.
## 4. S4 chunk 3 — deletions
Delete the obsolete stencil/bias/skip paths and the CYpt sort once chunk 2's
transcript is exact: `RetailAlphaOrdering.ComputeViewerDistance` and every
`viewerDistance` argument on the submit path; any remaining
`FlushFartherThan` consumer; the `#117`/`#129` bias remnants the S1 hygiene
already removed from `portal_depth.vert` (verify nothing else carries them).
Register: AP-34 retired; any row describing the distance sort retired; the
seal/punch color-state row from S4-c1 kept or retired per its decision.
## 5. Open questions to settle before dispatch
- Does the walk's `SC` turn (per land cell) have a leaf hook where the 0.75
valve belongs, or does `OnSortCellTurn` need a third leaf method? (Read
`WalkFrameDriver`'s land-cell turn after chunk 3's interleave.)
- Where does the particle submitter's list membership come from — the
particle draw is retail's own `AddMeshToAlphaList` consumer (billboards go
to ALPHA), or is it drawn through the emitter's cell turn immediately?
Check `ParticleRenderer.cs`'s submit site against the spec's §4 table.
- The `alphadepth` capture format: confirm the `AM`/`FL` lines carry the list
id so the transcript can be compared per list, not merged.