Record the renders and the counters for the frame-as-length step

Step 3 is done: against #18 the render set is byte-identical but for two
pixels of antialiasing in random and one padded block in text moving a
pixel, and a live resize of random matches a cold render at that size
exactly. The cost table is re-measured at adbedaf, where the fuzzer's own
Branch was found pinning the window and hiding what the change costs.
This commit is contained in:
iris-ai committed 2026-09-19 00:35:42 -04:00
1 parent 36ce66554b
commit 150245071f
2 files changed
+83 -35

No files matched your search

+54 -34
View File
@@ -14,12 +14,12 @@ detached comparison checkout is `/home/bob/repos/iris-layout-baseline`. It is
the reviewed baseline this work must preserve or improve.
The continuation is `/home/bob/repos/iris-layout-experiment`, now on branch
**`wip/one-ask`** at **`23523ee`**, four commits over `4328eac` (the head of
**`wip/one-ask`** at **`adbedaf`**, five commits over `4328eac` (the head of
`wip/transparent-frames`, which is unchanged). It replaces the old step 3
plan with the one-ask protocol below, and `1512d84` and `23523ee` make the
frame a length of the window. It passes every check:
| check at `23523ee` | result |
| check at `adbedaf` | result |
| --- | --- |
| `cargo fmt --all --check`, clippy `-D warnings`, with and without `layout-diagnostics` | clean |
| `cargo test --workspace` (debug) | 122 suite, 20 core, 11 generated, all green |
@@ -35,8 +35,14 @@ over two pads relocating the column under them instead of dividing it again,
and a resize leaving a short scroll's window-tall content where it was. Each
is pinned as a named test.
Not done: the renders and the `tabs` replay, the retained-cost work, the
renames, and a pre-submit review of the three commits as one diff.
The renders and the replay are done and recorded in `docs/LAYOUT_LOG.md`:
against #18, `minimal` and `tabs` are byte-identical (before and after the
reference gesture), `random` differs in two pixels of glyph antialiasing,
`text` moves one padded block one pixel, and a live resize of `random`
matches a cold render at that size byte for byte.
Not done: the retained-cost work, the renames, and a pre-submit review of
the five commits as one diff.
The worker's older step 3/4 experiment is preserved as branch
`wip/step3-experiment` (one commit over `4328eac`) and as
@@ -244,7 +250,7 @@ Unchanged; see `docs/LAYOUT.md`.
## Implementation plan
Work in `/home/bob/repos/iris-layout-experiment` on `wip/one-ask` from
`23523ee`. Make each step a warning-clean commit and run its named checks
`adbedaf`. Make each step a warning-clean commit and run its named checks
before the next. If a step exposes a different mechanism, stop and update
this handoff rather than papering over it.
@@ -254,30 +260,29 @@ frame, ask, box and size warm against cold), pinned as a named test in
`tests/cases/unsettled.rs`, then fixed under the two rules above. Do not add
a second draw back.
### 1. Review the four commits
### 1. Review the five commits
Run the pre-submit review over `3091fb8`, `0ef87eb`, `1512d84` and `23523ee`
as one diff against `4328eac`. `1512d84` rewrote much of what the first two did to
`painter.rs` and `render_state.rs` and was reviewed as it was written, but
the three have never been read as one change, and the parts of the one-ask
protocol it did not touch -- `place_at`, the twice-asked deferral, `Span`'s
two passes -- were written as a probe and reviewed only by their tests.
Run the pre-submit review over the five commits as one diff against
`4328eac`. `1512d84` rewrote much of what the first two did to `painter.rs`
and `render_state.rs` and was reviewed as it was written, but the five have
never been read as one change, and the parts of the one-ask protocol it did
not touch -- `place_at`, the twice-asked deferral, `Span`'s two passes --
were written as a probe and reviewed only by their tests.
### 2. Make the frame a length and the box a region
**Done at `1512d84` and `23523ee`.** The settled rule is in `docs/LAYOUT.md` under
"Frames, decided boxes and padding"; what implementing it corrected in the
plan -- three of them wrong layout that would have shipped -- is in
**Done at `1512d84` and `23523ee`.** The settled rule is in `docs/LAYOUT.md`
under "Frames, decided boxes and padding"; what implementing it corrected in
the plan -- four of them wrong layout that would have shipped -- is in
`docs/LAYOUT_LOG.md`.
### 3. Render and replay
Read the installed graphics skill and confirm the renderer. Render `view`,
`minimal`, `random`, `tabs` and `text` at 1920x1200 against `34cafb6` and
`e44dea3`, replay `tabs`, and compare a live resize of `random` with a cold
render at the same size (commands under **Full verification** below). A
text placed by re-expression rather than a second draw is the change most
likely to show here; inspect every intentional difference and record it.
**Done at `adbedaf`**, against `e44dea3` (#18); what each render showed is
in `docs/LAYOUT_LOG.md`. `view` has no counterpart in the baseline, so it
was rendered but not compared. Run the set again after any further change
here -- the commands are under **Full verification** below, and a text
placed by re-expression rather than by a second draw is what shows first.
### 4. Rename and delete
@@ -293,26 +298,36 @@ Suite, oracle.
### 5. Restore the expected retained cost
Work counters at `3091fb8`, seed 1 and 13, depth 8, widget draws / distinct
widgets, beside `e44dea3` (#18) and `49cec82` (the branch head before this):
Work counters, seed 1 and 13, depth 8, widget draws / distinct widgets,
beside `e44dea3` (#18) and `0ef87eb` (before the frame became a length):
| seed 1 | e44dea3 | 49cec82 | 0ef87eb |
| seed 1 | e44dea3 | 0ef87eb | adbedaf |
| --- | --- | --- | --- |
| cold | 369/261 | 516/288 | 331/288 |
| many | 157/95 | 187/119 | 110/92 |
| cold | 369/261 | 331/288 | 342/288 |
| many | 157/95 | 110/92 | 118/95 |
| size | 16/12 | 3/3 | 3/3 |
| scroll | 2 | 1 | 1 |
| resize | 13/13 | 24/76 | 40/15 |
| resize | 13/13 | 40/15 | 44/13 |
| seed 13 | e44dea3 | 49cec82 | 0ef87eb |
| seed 13 | e44dea3 | 0ef87eb | adbedaf |
| --- | --- | --- | --- |
| cold | 1330/707 | 2940/982 | 1179/982 |
| many | 524/159 | 1091/423 | 424/364 |
| resize | nothing | 2215/510 | nothing |
| cold | 1330/707 | 1179/982 | 1278/982 |
| many | 524/159 | 424/364 | 429/366 |
| resize | nothing | nothing | nothing |
`many` and `size` are better than #18 at seed 1 and `many` draws fewer times
at seed 13, but it touches twice as many distinct widgets there, and `resize`
at seed 1 draws 40 times where #18 drew 13. Two mechanisms, both understood:
`many`, `size` and `scroll` are better than #18 and within a few draws of
`0ef87eb`; `cold` is 3% and 8% more than `0ef87eb` for the same distinct
widgets, which is the frame pins making a widget answer again where it used
to be reused on a box that happened to match. `resize` at seed 1 still draws
44 times where #18 drew 13.
Measuring this is what found `adbedaf`: the fuzzer's own `Branch` pinned the
window rather than saying which side of its threshold it was on, which put
seed 1's resize at 131 and seed 13's at 828. A fixture that redraws
everything on a resize cannot tell a change that reuses well from one that
does not, so check the fixture before believing a regression.
Three mechanisms behind what is left, all understood:
- **A share child is asked twice per span draw** -- in the measuring room
with the frame forwarded, then in its slot with the frame narrowed. Each
@@ -331,6 +346,11 @@ at seed 1 draws 40 times where #18 drew 13. Two mechanisms, both understood:
so a resize redraws it. Read `extent_len` only where a slot depends on it
(shares, or `Sign::Neg`), and express the measuring room's far end without
the length. Measure `resize` at seed 1 before and after.
- **A rule that is a fraction of the frame pins the frame**, which is what
`cold` grew by. The answer for such an axis is a pure function of the rule
and the frame, so a reuse could resolve it again from the record instead
of redrawing -- `placed_extent` already takes `declared`. Worth trying
before anything subtler; the pin stays for the axes that read the frame.
Report every phase at both seeds, work counters first, medians only when the
work agrees.