Record the span boundary landing and what the guard experiment showed
This commit is contained in:
1 parent
be895375ec
commit
0cdda1713f
1 file changed
+45
-15
+45
-15
@@ -10,7 +10,7 @@ stayed.
|
|||||||
|
|
||||||
Canonical Iris `main` is **`ca2b4b2`** (#17, the headless rig). **#18
|
Canonical Iris `main` is **`ca2b4b2`** (#17, the headless rig). **#18
|
||||||
`split/18-position-chain`** is open in `/home/bob/repos/iris-pr18`, head
|
`split/18-position-chain`** is open in `/home/bob/repos/iris-pr18`, head
|
||||||
**`a92c6ac`**, pushed. It holds LAYOUT.md §2's position chain, `leftover`,
|
**`25e456e`**, pushed. It holds LAYOUT.md §2's position chain, `leftover`,
|
||||||
the `Holds` retained-layout contract, region nodes, built-in alignment and
|
the `Holds` retained-layout contract, region nodes, built-in alignment and
|
||||||
size rules, fixed-point layout, a box in pixels threaded down the draw, and
|
size rules, fixed-point layout, a box in pixels threaded down the draw, and
|
||||||
a report read as a fraction of the containing widget. No PR review was
|
a report read as a fraction of the containing widget. No PR review was
|
||||||
@@ -207,15 +207,45 @@ loop {
|
|||||||
```
|
```
|
||||||
|
|
||||||
Bryan's, 2026-09-17, and the right answer where `0e0d4af` was a check:
|
Bryan's, 2026-09-17, and the right answer where `0e0d4af` was a check:
|
||||||
"then that entire category of issue can't even occur". `dirty_size_under`
|
"then that entire category of issue can't even occur".
|
||||||
stays in `draw_inner` anyway, because `update` draws the root for a resize
|
|
||||||
*before* `redraw_updates` runs at all and the ordering does not cover that
|
**No fuzzer can tell whether `0e0d4af`'s guard still does anything.**
|
||||||
entry. Whether it is still load-bearing is untested -- the experiment that
|
Dropping `dirty_size_under` from it passes the suite, the shrinker at 400
|
||||||
said it was not had a failed edit in it and measured nothing.
|
seeds of depth 5, the oracle at 1000 of depth 6 and 2000 seeds at depth 4.
|
||||||
|
It stays because `update` draws the root for a resize *before*
|
||||||
|
`redraw_updates` runs at all, which the ordering does not reach -- a hole
|
||||||
|
that is reasoned rather than measured, so either find the case or delete
|
||||||
|
the guard, but do not leave it on a hunch forever.
|
||||||
|
|
||||||
Drawn widgets, widget draws and primitive writes are unchanged on every rig
|
Drawn widgets, widget draws and primitive writes are unchanged on every rig
|
||||||
phase; `many` pays 51 queue pops for 27 and 1059 depth reads for 410.
|
phase; `many` pays 51 queue pops for 27 and 1059 depth reads for 410.
|
||||||
|
|
||||||
|
### A span's leftover boundary is its own inverse (landed, `53b00c6`)
|
||||||
|
|
||||||
|
The decision used a rounded division where the room the children get is a
|
||||||
|
floored multiply, so the boundary and the drawing it guarded were two
|
||||||
|
expressions for one length. `room` is that length as a `Len`, `room.to_px`
|
||||||
|
is the multiply, and `Holds::through` is its exact preimage:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
let room = Len::rel_max() - Len::from_parts(total.rel, total.px);
|
||||||
|
let mut shares = false;
|
||||||
|
if total.leftover > Weight::ZERO {
|
||||||
|
shares = room.to_px(painter.px_len(axis)) > Px::ZERO;
|
||||||
|
let holds = match shares {
|
||||||
|
true => Holds::from(Px::STEP..=Px::MAX),
|
||||||
|
false => Holds::from(Px::MIN..=Px::ZERO),
|
||||||
|
};
|
||||||
|
painter.holds(axis, holds.through(room));
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The three branches were the sign of `1 - rel`, which `through` reads
|
||||||
|
already. Forty lines became twelve and one `div` left layout. The general
|
||||||
|
rule stands and is now demonstrated: **derive a boundary through the
|
||||||
|
inverse of the expression that draws, never by a second expression for the
|
||||||
|
same length.**
|
||||||
|
|
||||||
### Two branches parked, both real, neither ready
|
### Two branches parked, both real, neither ready
|
||||||
|
|
||||||
**`wip/stack-fraction-twice`.** A stack sized by a child that reports a
|
**`wip/stack-fraction-twice`.** A stack sized by a child that reports a
|
||||||
@@ -561,7 +591,7 @@ above for what closing the rest would cost.
|
|||||||
|
|
||||||
## Verification at the current head
|
## Verification at the current head
|
||||||
|
|
||||||
At `a92c6ac`:
|
At `25e456e`:
|
||||||
|
|
||||||
- `cargo fmt --all --check`, `cargo clippy --workspace --all-targets --
|
- `cargo fmt --all --check`, `cargo clippy --workspace --all-targets --
|
||||||
-D warnings`, `cargo test --workspace`: green, 90 suite tests, 19 core
|
-D warnings`, `cargo test --workspace`: green, 90 suite tests, 19 core
|
||||||
@@ -571,7 +601,8 @@ At `a92c6ac`:
|
|||||||
59 s -- the debug run exercises the `Holds` assertion in `draw_at`.
|
59 s -- the debug run exercises the `Holds` assertion in `draw_at`.
|
||||||
- All fifteen shrinker cases at 400 seeds of depth 5 in 56 s, the oracle at
|
- All fifteen shrinker cases at 400 seeds of depth 5 in 56 s, the oracle at
|
||||||
1000 seeds of depth 6 in 142 s, and **2000 seeds at depth 4 over all
|
1000 seeds of depth 6 in 142 s, and **2000 seeds at depth 4 over all
|
||||||
fifteen cases** in 261 s.
|
fifteen cases** in 262 s. The last is not routine and should be: it is
|
||||||
|
the only run that has ever found anything past seed 400.
|
||||||
- `view`, `minimal`, `random` and `tabs` byte-identical at 1920x1200
|
- `view`, `minimal`, `random` and `tabs` byte-identical at 1920x1200
|
||||||
against `ea6dbae`. `random` live-resized from 1920x1200 to 1280x800 is
|
against `ea6dbae`. `random` live-resized from 1920x1200 to 1280x800 is
|
||||||
byte-identical to a cold 1280x800 render. **`text` is a new picture**:
|
byte-identical to a cold 1280x800 render. **`text` is a new picture**:
|
||||||
@@ -769,8 +800,7 @@ In order, from the review above and Bryan's steer (2026-09-17):
|
|||||||
4. Write `ActiveData::answer` in one place.
|
4. Write `ActiveData::answer` in one place.
|
||||||
5. Keep the `DrawInfo` on `ActiveData`; delete the copied fields and the
|
5. Keep the `DrawInfo` on `ActiveData`; delete the copied fields and the
|
||||||
reconstruction in `redraw`.
|
reconstruction in `redraw`.
|
||||||
6. `Span`'s leftover boundary through `Holds::through`.
|
6. **Round on the CPU and snap to the nearest pixel in the shader**, as
|
||||||
7. **Round on the CPU and snap to the nearest pixel in the shader**, as
|
|
||||||
one change with one verification. Bryan approved the snap on 2026-09-17
|
one change with one verification. Bryan approved the snap on 2026-09-17
|
||||||
(rendering may change wherever it brings the screen closer to what the
|
(rendering may change wherever it brings the screen closer to what the
|
||||||
user's code says: three equal sections of 1000 px need one of them
|
user's code says: three equal sections of 1000 px need one of them
|
||||||
@@ -786,20 +816,20 @@ In order, from the review above and Bryan's steer (2026-09-17):
|
|||||||
bounds move by half a `Rel` step); check with `nm` that `UiSpan::within`
|
bounds move by half a `Rel` step); check with `nm` that `UiSpan::within`
|
||||||
still inlines; expect a couple of percent of instructions and re-run the
|
still inlines; expect a couple of percent of instructions and re-run the
|
||||||
long fuzzers and the render set once for both.
|
long fuzzers and the render set once for both.
|
||||||
8. The smaller items: the stale `f32` comment, the gap of an undrawn child,
|
7. The smaller items: the stale `f32` comment, the gap of an undrawn child,
|
||||||
confirm nested `leftover` weights, one zero-divisor fallback. Add to
|
confirm nested `leftover` weights, one zero-divisor fallback. Add to
|
||||||
them: a span that overflows itself hands a child a box of negative
|
them: a span that overflows itself hands a child a box of negative
|
||||||
length, which is ordinary now rather than a corner, and nothing states
|
length, which is ordinary now rather than a corner, and nothing states
|
||||||
what a widget may assume about one.
|
what a widget may assume about one.
|
||||||
9. `LazySpan`, the next LAYOUT.md §2 item. Region nodes cover the movable
|
8. `LazySpan`, the next LAYOUT.md §2 item. Region nodes cover the movable
|
||||||
subtree case; do not restore a separate child-placement API.
|
subtree case; do not restore a separate child-placement API.
|
||||||
10. `SizeRule::{Min, Max, Clamp}`, restoring the `max_width`/`max_height`
|
9. `SizeRule::{Min, Max, Clamp}`, restoring the `max_width`/`max_height`
|
||||||
builders `8220a78` deleted. The clamp boundary is a hard layout decision
|
builders `8220a78` deleted. The clamp boundary is a hard layout decision
|
||||||
with an exact `Holds` split at the crossover, both sides in `Px`. Still
|
with an exact `Holds` split at the crossover, both sides in `Px`. Still
|
||||||
awaiting Bryan: whether a `Max` narrows the box the child draws in, or
|
awaiting Bryan: whether a `Max` narrows the box the child draws in, or
|
||||||
only what the parent reports for it.
|
only what the parent reports for it.
|
||||||
11. `Scroll` taking a direction rather than one axis.
|
10. `Scroll` taking a direction rather than one axis.
|
||||||
12. The measure/draw split, once the above is in. It deletes the two-ask
|
11. The measure/draw split, once the above is in. It deletes the two-ask
|
||||||
protocol, which is what `0e0d4af` had to put a guard around.
|
protocol, which is what `0e0d4af` had to put a guard around.
|
||||||
|
|
||||||
`docs/LAYOUT.md` §4, §5 and the density section are stale: they name
|
`docs/LAYOUT.md` §4, §5 and the density section are stale: they name
|
||||||
|
|||||||
Reference in new issue
Block a user