Record the two reuse defects the random trees found, their fixes, and the one-pixel tabs difference left for Iris to call
This commit is contained in:
1 parent
19b9ca7413
commit
e442481a30
1 file changed
+43
-25
@@ -9,7 +9,7 @@ Canonical `main` is **`ca2b4b2`** (#17, the headless rig). Sixteen slices are
|
||||
in; #16's size work and #17's rig both merged on 2026-09-14.
|
||||
|
||||
**#18 `split/18-position-chain`** is open, worktree `/home/bob/repos/iris-pr18`,
|
||||
head `86a7e8d`, eight commits. LAYOUT.md §2's O(1) subtree movement, the
|
||||
head `2272634`, ten commits. LAYOUT.md §2's O(1) subtree movement, the
|
||||
`Remap` retirement, and then the three changes the owner chose on 2026-09-14:
|
||||
the slot carries a box, slots are opt-in, and a widget's region is held in the
|
||||
coordinates of the slot it draws in.
|
||||
@@ -46,28 +46,50 @@ coordinates of the slot it draws in.
|
||||
2026-09-14: stretch has an opposite and scale does not, and the answer is
|
||||
per axis so the axis is already established where it is read.
|
||||
|
||||
**The open defect, and it is older than this branch.** `tests/generated.rs`
|
||||
grows a seeded random tree and checks that laying it out again lands where
|
||||
growing it cold does. It does not always. Every case seen is a **wrapping text
|
||||
on a span's own axis**: the span measures the child in the whole box, the
|
||||
child shapes to that width and reports the width it used, the span places it
|
||||
in exactly that width, which is a length change, so it shapes again and its
|
||||
longest line is shorter than the box it was just given. Where it settles
|
||||
depends on how many passes it has had, and a warm tree has had a different
|
||||
number from a cold one -- so layout is not a function of the state, which it
|
||||
has to be. A span whose axis is not the wrap axis is stable, which is every
|
||||
real column of text, and why nothing had run into it.
|
||||
**The divergence the random trees found, and what it was.** A warm tree did
|
||||
not always land where a cold build does -- 30 of 90 cases, against 7 on
|
||||
`db1751f`. Two causes, both fixed in `b0f9f04`, and both about deciding
|
||||
whether a drawing is still valid:
|
||||
|
||||
seeds 1-30, three checks each db1751f (before) 86a7e8d (now)
|
||||
diverging 7 of 90 30 of 90
|
||||
- **A region is a fraction of a slot's box, so an unchanged region is not an
|
||||
unchanged box.** `try_reuse` compared regions, and a child drawn at
|
||||
`UiRegion::FULL` of a slot whose box had just halved compared equal to
|
||||
itself and was reused without being descended into, leaving a wrapping text
|
||||
shaped for a width it no longer had. `ActiveData::px` now holds the pixel
|
||||
size of the box the widget drew against and the comparison is against that
|
||||
-- the question that was being asked all along, and right through a slot
|
||||
change and an output resize alike.
|
||||
- **A size the parent learnt by drawing the child is an answer for that box
|
||||
only.** The walk skipped a child whose own box was a fixed width, correctly
|
||||
-- but that width was what the child reported when the span drew it in the
|
||||
span's box, and the span's box had changed. A child whose size the widget
|
||||
read is now redrawn unless it declares an exact `size_hint` for the changed
|
||||
axis, which is the one case the parent did not draw it to find out.
|
||||
|
||||
The same defect either way: a placed child reaches the second shaping more
|
||||
often now. It wants fixing where the two draws meet, LAYOUT.md §4, rather than
|
||||
anywhere in the chain -- and **it should be fixed before #18 merges**, since
|
||||
tripling how often a tree lands somewhere unrepeatable is not something to
|
||||
land even on a defect that was already there.
|
||||
`a_wrapping_child_of_a_row_settles_somewhere_else_each_time` is the ignored
|
||||
reproduction; the six seeds the live tests use are ones that agree.
|
||||
90 of 90 now agree, and the ignored sweep agrees over 300 checks on 100
|
||||
seeds. The cost of the second one: a size-reading container gives up its reuse
|
||||
when its box changes length, which is every span, so `OnResize::Scale` earns
|
||||
its keep on moves and on subtrees whose sizes nobody read rather than on every
|
||||
stretch. `replace_cost` still measures the case the chain was built for.
|
||||
|
||||
**Render verification, done last as the owner asked.** `view`, `minimal` and
|
||||
`text` are byte-identical to `upstream/main` at 1920x1200. **`tabs` is not**:
|
||||
1,283 pixels of 2.3M (0.06%), two one-pixel-wide panel edges shifted by a
|
||||
pixel, at x=1056 and x=1337. Composing a position through the chain on the GPU
|
||||
associates the arithmetic differently from collapsing it on the CPU, so a
|
||||
value that used to land exactly on an integer now falls the other side of the
|
||||
shader's `floor`. The CPU and the GPU still agree with each other -- both walk
|
||||
the chain bottom-up -- so hit testing matches what is drawn; what changed is
|
||||
only the comparison against the old code. Matching it exactly would mean
|
||||
composing root-down in the shader, which needs the chain collected into an
|
||||
array first. **Worth the owner's call before merging**, since byte-identical
|
||||
against `upstream/main` has been the bar for every slice so far.
|
||||
|
||||
A live resize does land where a cold start does, byte for byte, on `tabs` and
|
||||
`text` -- the check that caught both of #16's defects. `run-headless.sh
|
||||
--resize WxH@Hz` is that check now. Run one at a time: the rig reuses a single
|
||||
compositor and a single output, so two at once resize each other's window and
|
||||
screenshot the wrong thing.
|
||||
|
||||
**Rigs added.** `iris::random` grows the tree (spans in every direction,
|
||||
stacks, rects with varying opacity, text wrapping and overflowing, a declared
|
||||
@@ -76,10 +98,6 @@ size over half of it, stopping at a depth), `examples/random.rs` draws one --
|
||||
against cold under a size change, a resize, and both. It found the
|
||||
non-terminating marking above immediately.
|
||||
|
||||
**Not verified yet:** the headless render shots and the live resize under
|
||||
sway. The owner asked for those last, after the CPU side is right, and the CPU
|
||||
side is not right until the divergence is.
|
||||
|
||||
### The plan after #18, agreed with the owner on 2026-09-14
|
||||
|
||||
Three changes, done together as one slice on top of #18, because each decides
|
||||
|
||||
Reference in new issue
Block a user