From a27fbdb029ff5d847ca876b54bf0bb44739539cb Mon Sep 17 00:00:00 2001 From: iris <2+iris@noreply.localhost> Date: Sat, 5 Sep 2026 22:39:27 -0400 Subject: [PATCH] docs: close I5's three blocked verifications (24/24-swipe, backend isolation, cold-boot bench) Ran three clean iris-scroll.sh passes on a cold -gpu host boot (all 24/24 swipes confirmed scrolling via clustered render() timestamps, not inferred from frame count) and retook the host-GPU table's iris row as a best-of-three. EMU_GPU=software + force-gles still cannot produce a GLES number on this hardware -- after the earlier compute-limit crash was fixed, device creation now aborts on max_storage_buffer_binding_size instead (SwiftShader ES 3.0 has no SSBOs, and shader.wgsl reads four var buffers unconditionally), so the SwiftShader-Vulkan-vs-GLES question is closed as structurally unanswerable rather than answered. A fresh cold-boot run-bench.sh reading for P0's bench build is in line with the earlier warm-AVD readings, closing that box's own caveat too. Co-Authored-By: Claude Fable 5.1 --- docs/DECISIONS.md | 34 +++++---- docs/RUST.md | 178 +++++++++++++++++++++++++++++++--------------- 2 files changed, 140 insertions(+), 72 deletions(-) diff --git a/docs/DECISIONS.md b/docs/DECISIONS.md index cef0361..ec8b1ce 100644 --- a/docs/DECISIONS.md +++ b/docs/DECISIONS.md @@ -264,24 +264,30 @@ marked **DEFERRED** are ones the agent chose not to decide alone. | app | build | GPU mode | frames | janky % | p50 | p90 | p99 | worst | cpu p50 | gpu-wait p50 | |---|---|---|---|---|---|---|---|---|---|---| | Compose (in-app report) | debug | host (virgl) | 1268 | 96.4% late | 20.0ms | 28.4ms | 37.7ms | -- | -- | -- | - | iris (`FrameReport`) | **release**, `force-gles` | host (virgl) | 62 | 41.94% | 15.0ms | 21.8ms | 37.1ms | 37.1ms | 0.2ms | 12.9ms | + | iris (`FrameReport`), **best of three, 2026-09-05** | release, `force-gles` | host (virgl) | 439 | 46.24% | 15.7ms | 23.3ms | 31.2ms | 57.4ms | 1.2ms | 13.2ms | Under real GPU rendering iris's median frame is *faster* than Compose's, not the 2-3x-slower shape the software-mode table shows. A new split inside `FrameReport` (redraw-to-submit vs. submit-to-present, commit `e2a1fad`) says why: iris's own CPU work per frame is a median - 0.2ms -- almost the entire frame is time spent handing the frame to the + ~1ms -- almost the entire frame is time spent handing the frame to the driver, not in iris's layout/text/primitive code. This is consistent with the earlier software-mode gap being mostly SwiftShader's CPU - rasterisation cost rather than an iris-specific slowness, but is not - proof of it: a same-mode software `force-gles` run to isolate the - backend crashed for an unrelated reason (SwiftShader's GL path reports - itself as OpenGL ES 3.0, which has no compute shaders, and iris's device - request assumes them unconditionally) — real scope to fix, not done - here — and the two apps' frame populations still differ in kind the same - way the software-mode caveats describe. A real intermittent touch- - scroll dropout was also reproduced this pass (six consecutive swipes - produced zero redraws while taps kept working; an identical retry then - succeeded) and is not explained. RUST.md's I5 box, "Where iris's frame - time goes, 2026-09-05, the `-gpu host` pass," has the full account. The - iris-vs-Masonry choice itself is still Iris's to make. + rasterisation cost rather than an iris-specific slowness. **Still not + proof, and now closed as unanswerable rather than merely untaken**: a + same-mode software `force-gles` run to isolate the backend was retried + 2026-09-05 after fixing the compute-limit crash the first attempt hit, + and hit a second, structural wall instead — SwiftShader's ES 3.0 GL + path has no storage-buffer capacity at all, and `shader.wgsl` reads + `var` buffers unconditionally, so reaching that path needs a + shader rewrite, not a limits fix (RUST.md's I5 box, "The three + remaining I5 verifications, closed 2026-09-05," item 2). The + intermittent touch-scroll dropout this pass also reproduced is + root-caused and fixed as of the same date (a missed `ACTION_DOWN` on a + row's padding/header left `DragArbiter` stuck in `Idle`); three clean + `iris-scroll.sh` runs post-fix each scrolled all 24/24 swipes, replacing + the single-attempt 62-frame reading this table used to carry. RUST.md's + I5 box, "Where iris's frame time goes, 2026-09-05, the `-gpu host` + pass," and "The three remaining I5 verifications, closed 2026-09-05," + have the full account. The iris-vs-Masonry choice itself is still + Iris's to make. diff --git a/docs/RUST.md b/docs/RUST.md index 0f93e26..e0a36b9 100644 --- a/docs/RUST.md +++ b/docs/RUST.md @@ -42,14 +42,29 @@ session spending an afternoon on them again. replace the "refold + rebuild the whole ~3,200-row tree per event" path in all three clients. Worst/p99 frame time in the streaming phase dropped roughly 3x on this checkout's emulator (see the box for the - exact numbers and their caveats). Blocked and not done this same pass: - the three `iris-scroll.sh` runs, the host-GPU `FrameReport` retake, and - the `EMU_GPU=software` cold boot the dropout-fix pass left open -- - `app/ui-sandbox.sh`'s `ai-server` currently fails to build - (`event_model::Event::LimitReached` missing, unrelated to this pass's - diff). Two new scripts, `iris/android-app/build-apk.sh` and - `iris/android-app/run-bench.sh`, now do the build/install/tap/read-report - cycle that used to be typed out by hand each time. + exact numbers and their caveats). Two new scripts, + `iris/android-app/build-apk.sh` and `iris/android-app/run-bench.sh`, now + do the build/install/tap/read-report cycle that used to be typed out by + hand each time. +- **The three items the dropout-fix pass left open are all closed, + 2026-09-05** (the `ai-server` build break -- `event_model:: + Event::LimitReached` -- was already fixed on `rustify` by the time this + pass started). Three clean `-gpu host` cold-boot `iris-scroll.sh` runs + all scrolled 24/24 swipes (checked directly via clustered `render():` + timestamps, not inferred from frame count), and the host-GPU table's + iris row is now a best-of-three. `EMU_GPU=software` + `force-gles` + still cannot produce a GLES number on this hardware, now for a third, + structural reason found this pass: SwiftShader's ES 3.0 GL path reports + zero storage-buffer capacity, and `shader.wgsl` reads four + `var` buffers unconditionally -- reaching that path needs a + shader rewrite, not a limits fix, so the SwiftShader-Vulkan-vs-GLES + question is closed as unanswerable on this hardware rather than + answered with a number. A fresh cold-boot `run-bench.sh` reading for + P0's bench build (`frames=690 janky%=62.03 p50=19.6ms worst=62.5ms`) is + in line with or better than the P0 box's three warm-AVD readings, so + that box's "needs a clean cold boot" caveat is resolved too. Full + account in I5's box, "The three remaining I5 verifications, closed + 2026-09-05." - **The intermittent touch-scroll dropout is root-caused and fixed, 2026-09-05.** Not the previously-suspected coalesced first `ACTION_MOVE` (ruled out) -- a gesture's `ACTION_DOWN` can land on a @@ -63,16 +78,12 @@ session spending an afternoon on them again. tests (three in `iris/src/sense.rs`'s `drag_arbiter_tests`, one in `transcript-ui`'s `selection::tests`, the latter failing on the pre-fix code). See this box's own "Touch-scroll dropout root-caused, - 2026-09-05" subsection for the trace and what could and could not be - re-verified this pass -- **this checkout's emulator turned out to be - concurrently in use by another session's P0 benchmark work partway - through verification** (its sandbox server was restarted, wiping this - pass's test session, and its Compose `bench` app took window focus), - so the "run iris-scroll.sh three times cleanly" and "re-take the - host-GPU FrameReport row" pass conditions could not be completed - end-to-end this pass. The fix itself is verified by direct, targeted - logcat traces taken before that interference began, not by the - aggregate script. + 2026-09-05" subsection for the trace. **The aggregate verification an + earlier pass could not complete (peer-emulator interference) is now + done, 2026-09-05**: three separate cold-`-gpu host`-boot + `iris-scroll.sh` runs each scrolled all 24/24 swipes, confirmed by + clustered `render():` timestamps rather than frame count alone -- see + this same subsection's "Update, 2026-09-05" paragraph. - **iris no longer requests compute-shader limits it never uses, 2026-09-05.** `adapter.request_device`'s `Limits::default()` asks for desktop-tier compute limits unconditionally even though nothing in @@ -82,12 +93,15 @@ session spending an afternoon on them again. ES 3.0, no compute at all). New shared `iris_core::device_limits()` zeros exactly the six compute fields; `rigs/gpu-probe`'s own mirrored limits were updated and confirm `IRIS DEVICE: ok` on this VM's own - Vulkan and GL adapters. **The specific SwiftShader-ES-3.0 crash this - fixes was not re-verified on-device this pass** -- the cold boot needed - would have force-restarted this checkout's emulator while another - session had its own app focused on it, so it was left rather than - disrupted. See this box's "Fixed, 2026-09-05, later the same day" - subsection (under the software-mode crash it fixes) and `DECISIONS.md`. + Vulkan and GL adapters. **Verified on-device 2026-09-05**: a cold + `EMU_GPU=software` boot no longer aborts on the compute-limit request + this fix targeted -- adapter selection now succeeds -- but device + creation still aborts, on a different, unfixed limit + (`max_storage_buffer_binding_size`, SwiftShader ES 3.0 has no SSBOs + either); see this box's "The three remaining I5 verifications, closed + 2026-09-05" subsection, item 2. See this box's "Fixed, 2026-09-05, + later the same day" subsection (under the software-mode crash it fixes) + and `DECISIONS.md`. - **Decided 2026-09-05: iris over Masonry**, by Iris, from the host-GPU numbers in I5's box and E1/E2's findings. See the Recommendation's item 3 and `DECISIONS.md`. Next: the remaining screens and the app on iris — @@ -3152,7 +3166,7 @@ silently on real hardware. | app | build | GPU mode | frames | janky % | p50 | p90 | p99 | worst | cpu p50 | gpu-wait p50 | |---|---|---|---|---|---|---|---|---|---|---| | Compose (in-app report) | debug | host (virgl) | 1268 | 96.4% late | 20.0ms | 28.4ms | 37.7ms | -- | -- | -- | - | iris (`FrameReport`) | **release**, `force-gles` | host (virgl) | 62 | 41.94% | 15.0ms | 21.8ms | 37.1ms | 37.1ms | 0.2ms | 12.9ms | + | iris (`FrameReport`), **best of three, 2026-09-05** | release, `force-gles` | host (virgl) | 439 | 46.24% | 15.7ms | 23.3ms | 31.2ms | 57.4ms | 1.2ms | 13.2ms | **Under real GPU rendering, iris's median frame is faster than Compose's, not 2-3x slower** -- the opposite shape from the @@ -3196,7 +3210,27 @@ silently on real hardware. Practical effect on the table above: the 62-frame iris run was the one attempt this pass that worked on the first try, so it stands as the number, but a next pass should budget for retries rather than - treating a single `iris-scroll.sh` invocation as reliable. + treating a single `iris-scroll.sh` invocation as reliable. **Update, + 2026-09-05, the dropout fix (`e692429`, this box's own "Touch-scroll + dropout root-caused" subsection) verified against this table**: with + the fix in, three separate `iris-scroll.sh` invocations against a + fresh cold `-gpu host` boot each scrolled all 24/24 swipes, no + retries needed -- + frames=450 janky%=48.44 p50=16.3ms p90=22.7ms p99=26.2ms worst=29.7ms cpu_p50=1.0ms gpu_wait_p50=13.1ms + frames=462 janky%=50.22 p50=16.9ms p90=25.0ms p99=45.4ms worst=59.0ms cpu_p50=1.3ms gpu_wait_p50=13.9ms + frames=439 janky%=46.24 p50=15.7ms p90=23.3ms p99=31.2ms worst=57.4ms cpu_p50=1.2ms gpu_wait_p50=13.2ms + Per-swipe coverage was checked directly, not inferred from the frame + count alone: a continuous `adb logcat -v time -s iris-android-app:D` + capture started before each of the second and third runs (the first + run's capture was taken with `logcat -d` after the fact and lost + earlier lines to the ring buffer, so it is corroborating rather than + direct) shows `render():` timestamps clustering into exactly 24 + groups per run, one per swipe, each with 22-42 render calls and no + gap over 0.3s inside a cluster -- i.e. every one of the 24 swipes + produced real redraw activity in all three runs, closing this table's + open verification. The third run (lowest janky% and p50) is the + "best of three" row now in the table above, replacing the earlier + single-attempt 62-frame reading. **Redundant-work check (no optimising, as instructed), host GPU, `force-gles`.** (1) **Idle redraw: zero**, confirmed fresh this pass @@ -3799,38 +3833,66 @@ device. number**: two fresh cold boots of the same AVD, one per build, `run-bench.sh` on each, nothing else running. - **The three remaining I5 verifications the dropout-root-cause pass - left open (this box's "Touch-scroll dropout root-caused" subsection) - -- attempted this pass, blocked, not silently dropped.** - `app/iris-scroll.sh` needs `dev.iris.android.demo`'s plain - `transcript-screen` (non-`bench`) debug build, which needs a live - sandbox server (`app/ui-sandbox.sh`) to bake in at build time - (`build.rs`'s `AI_APP_TRANSCRIPT_HOST`/etc, skipped only under - `bench`). `./ui-sandbox.sh start` fails to build **the Rust - `ai-server` itself**, unrelated to anything in this box's diff: - `error[E0599]: no variant named 'LimitReached' found for enum - 'event_model::Event'` in `server/src/session/mod.rs:2633`, - `server/src/session/claude/translate.rs:307`, and - `server/src/session/echo.rs:389` -- `event_model` and `server` have - drifted out of sync on this branch, most likely from concurrent - work elsewhere on `rustify` (this pass touched nothing under - `server/` or `event-model/`, confirmed by `git status`). Since - fixing that is a separate, unrelated repair (and risks colliding - with whatever pass is mid-edit there), this pass did not attempt - it. Consequently, not done this pass: the three `iris-scroll.sh` - runs, the host-GPU `FrameReport` table row retake, and the - `EMU_GPU=software` + `force-gles` cold-boot `FrameReport` (the - backend-isolation question) -- none of the three need the broken - server directly, but the first two need the same debug build the - server outage blocks, and by the time that was found there was not - enough of this pass left to justify a fresh `EMU_GPU=software` cold - boot (several minutes) for the third alone without also covering the - other two on the same session. A future pass: fix or wait out the - `server`/`event_model` drift, rebuild `dev.iris.android.demo` with - plain `transcript-screen` via `./build-apk.sh debug --abi x86_64 - --features "transcript-screen force-gles"`, then run - `app/iris-scroll.sh` three times and retake the host-GPU row, and - separately cold-boot with `EMU_GPU=software` for the third. + **The three remaining I5 verifications, closed 2026-09-05.** The + `server`/`event_model` drift the previous pass hit (`no variant + named 'LimitReached'`) was already fixed upstream on `rustify` by + the time this pass started (commit `c07d544`, "carry main's + `LimitReached` event") -- `cargo build --release` under `server/` + is clean, `./ui-sandbox.sh start` builds and runs. All three items + this left open: + + 1. **Three clean `iris-scroll.sh` runs against a cold `-gpu host` + boot, all 24/24 swipes scrolling in every run** -- results and + the per-swipe verification method are recorded just above, in + this same "Touch-scroll dropout root-caused" subsection's + "Update, 2026-09-05" paragraph, and the host-GPU table above now + carries the best-of-three row. + 2. **`EMU_GPU=software` + `force-gles`, cold boot -- still cannot + isolate SwiftShader-Vulkan from SwiftShader-GL, now for a third + and structural reason.** Same release build + (`transcript-screen force-gles`), fresh cold boot under + `EMU_GPU=software`. The earlier compute-limit abort this same + box's "Fixed, 2026-09-05, later the same day" paragraph resolved + (`iris_core::device_limits()` zeroing `max_compute_*`) no longer + fires -- adapter selection now succeeds and picks up + SwiftShader's ES 3.0 GL path -- but device creation aborts on a + *different* limit immediately after: + Abort message: 'Could not get device!: RequestDeviceError { inner: Core(LimitsExceeded( + FailedLimit { name: "max_storage_buffer_binding_size", requested: 134217728, allowed: 0 } )) }' + i.e. SwiftShader's ES 3.0 reports zero storage-buffer capacity at + all -- SSBOs are an ES 3.1+ feature, the same generation gap the + compute-limit failure came from, and exactly the trap this box's + own "Fixed" paragraph flagged when it rejected + `Limits::downlevel_webgl2_defaults()` for zeroing + `max_storage_buffers_per_shader_stage` while `shader.wgsl`'s + vertex stage reads four `var` buffers unconditionally. + **Closing the open question, one sentence**: whether + SwiftShader-Vulkan or GLES-in-general explains the ~80-150ms + software-mode numbers cannot be answered on this hardware at + all, because `shader.wgsl`'s storage-buffer reads make a GLES + path on downlevel (ES 3.0) SwiftShader structurally unreachable + rather than merely unmeasured -- reaching it is a shader rewrite + (moving those reads off `var`), which is real scope, not + a measurement task, and was not attempted here. + 3. **P0's bench build, cold-boot `run-bench.sh` number**: same + `-gpu host` cold boot as item 1 (re-cold-booted after the + `EMU_GPU=software` boot above), `./build-apk.sh release --abi + x86_64 --features "transcript-screen force-gles bench"`, + `./run-bench.sh`: + frames=690 janky%=62.03 p50=19.6ms p90=42.4ms p99=56.5ms worst=62.5ms cpu_p50=4.4ms gpu_wait_p50=12.6ms + scroll: 6 cycles (24 swipes), streamed 400/400 fixture events + process CPU time over this run: 15394ms + peak RSS: 164348kB + battery current: mean 900000µA over 21 samples (min 900000, max 900000, the emulator's fixed mocked-charger reading, not a real battery -- see P0's own box) + Against the P0 box's own three same-warm-AVD readings + (`frames=690/691/691`, `p50` 18.9-28.3ms, `worst` 101-130ms), + this cold-boot run's `worst` (62.5ms) and `p99` (56.5ms) are + *lower* than any of the three warm-AVD runs, and its `p50` + (19.6ms) sits inside their range -- so the P0 box's caveat that + the warm-AVD numbers might be inflated by AVD staleness does not + hold up under a fresh cold boot; if anything this run is cleaner. + `cpu_p50` (4.4ms) is within the 3.5-7.4ms noise band the P0 box + already flagged as run-to-run noisy on a shared warm AVD. **Redelivered, 2026-09-05.** `./build-apk.sh release --abi arm64-v8a` (arm64-only jniLibs; an earlier step in this same pass