docs: record the phone-report fixes, follow-ups and the bundled-font API
RUST.md's P0 box gets Iris's first real-phone report (no crash) and the four defects it found (glyph-wipe-on-first-touch, missing bold glyphs, text far too small, status-bar inset not applied), what was fixed and how it was verified on the emulator, and what's still open (item 1's root cause, and the top-row height anomaly noted in the last commit). IRIS_TODO.md gets a new "From the phone, 2026-09-06" section for the two items explicitly deferred to a follow-up agent: no scroll momentum/fling, and occasional jitter scrolling down. IRIS.md gets the public-API entry for TextData's bundled fonts/ font_diagnostics, UiRenderNode::new/resize's new window_size parameter, AndroidUiState::content_scale, AndroidAppState::on_insets_changed, and iris_core::WgpuErrorLog. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
fd7e17523d
commit
560a74caf8
3 files changed
+184
No files matched your search
+123
@@ -4315,6 +4315,129 @@ device.
|
||||
confirming the phase marks partition the whole run rather than
|
||||
overlapping or dropping frames between them.
|
||||
|
||||
**Iris's first real phone report, 2026-09-06** (the redelivered,
|
||||
no-`force-gles` APK above): no crash. Two screenshots, before any
|
||||
touch: headings/links/code/table all render correctly. Four defects
|
||||
found and worked this pass:
|
||||
|
||||
1. **Every glyph disappears on the first tap or scroll; rectangles
|
||||
stay drawn** (the keyboard case is the same thing -- a tap on the
|
||||
composer). **Not root-caused this pass.** Audited `GpuTextures`'
|
||||
atlas-grow/patch path, `ArrBuf`'s resize-on-length-change
|
||||
contract, and the masks/move_offsets/rsc bind-group rebuild logic
|
||||
in `core/src/render/mod.rs` against wgpu's queue-ordering
|
||||
contract -- everything read as spec-correct (a `queue.write_texture`/
|
||||
`write_buffer` issued before a later `queue.submit` is guaranteed
|
||||
visible to it on the same queue, and a dropped `Buffer`/`Texture`/
|
||||
`BindGroup` still in flight is kept alive by wgpu's own tracker).
|
||||
No violation found by static reading; reproducing needs either
|
||||
the phone or a Mali driver trace, neither available this pass.
|
||||
Instrumented for the next report instead: `Device::
|
||||
on_uncaptured_error` is now installed on the Android device
|
||||
(`WgpuErrorLog`, `android::render::AndroidRenderer`), and
|
||||
`IrisViewPeer::render` logs masks/moves-resized, atlas
|
||||
pages-grown and image bind-group creates for the first 10 frames
|
||||
after every `surface_changed` -- exactly the window this bug
|
||||
lands in. The bench screen's new "Diagnostics" button (below)
|
||||
surfaces the error log and adapter identity on demand.
|
||||
2. **Bold words render as blank gaps of the correct advance width**
|
||||
(regular, links, inline code render fine). Fixed by bundling Noto
|
||||
Sans/Noto Sans Mono (regular/bold/italic/bold-italic, static
|
||||
cuts, OFL) into `iris-core` and registering them ahead of the
|
||||
platform's own fonts -- `core/src/primitive/text.rs`'s
|
||||
`TextData::register_bundled_fonts`. Named hypothesis, not
|
||||
confirmed on the phone: the system "Roboto" on a modern Android
|
||||
device is the variable "Roboto Flex," and this crate's glyph
|
||||
path (`TextData::place`) does not apply `Synthesis`/variable-axis
|
||||
correction at all -- a bundled *static* per-style face sidesteps
|
||||
the question rather than answering it. `TextData::font_diagnostics`
|
||||
reports what got resolved; logged once at startup and shown on
|
||||
the Diagnostics page.
|
||||
3. **Text far too small** -- iris had no device-pixel-ratio handling
|
||||
on *either* platform before this pass (grepped for `scale_factor`
|
||||
across the whole crate: zero hits). `DisplayMetrics.density`
|
||||
(Android) / `Window::scale_factor()` (desktop) now divides every
|
||||
physical-pixel number (window size, touch coordinates, the
|
||||
shader's window uniform) down to logical units before it reaches
|
||||
layout, so a `font_size: 16.0` is 16 dp rather than 16 raw device
|
||||
pixels on a ~3x-density phone. Cost a second, real bug found only
|
||||
by measuring on this checkout's emulator after the first fix
|
||||
landed: `android::view::IrisViewPeer::surface_changed`'s call
|
||||
into `UiRenderState::resize` (the layout engine's own notion of
|
||||
the canvas, which every widget's absolute `PixelRegion` is
|
||||
computed against) was still being handed raw physical
|
||||
`width`/`height`, while `AndroidRenderer`'s side of the same
|
||||
resize had already switched to logical -- splitting layout and
|
||||
the shader into two different units. A fixed-size widget (the
|
||||
bench screen's `.height(56)` button row) exposed it at ~40
|
||||
physical px against the ~147px `56 * content_scale` predicts;
|
||||
a proportional (`rest(n)`) size hid it by adapting to whichever
|
||||
total it was given. Both are logical now. **Not fully verified**:
|
||||
a fresh-install emulator screenshot after both fixes shows
|
||||
visibly larger, readable text (`docs/bench/` has neither
|
||||
screenshot committed -- see AGENTS.md on transcripts/screenshots
|
||||
not going in this repo -- but the before/after is described in
|
||||
the commit), and the button row's own height still isn't
|
||||
obviously matching `56 * content_scale` on this run -- worth a
|
||||
second look with `ui-trace show --field box` once there's time,
|
||||
but not a blocker for the magnitude of the original bug (3x too
|
||||
small).
|
||||
4. **Status-bar inset not applied** -- confirmed nothing in this
|
||||
app ever read `insets().top` at all (`android/insets.rs` has
|
||||
carried `Insets.top` since it was written; nothing consumed it).
|
||||
Fixed with a new, generic hook: `AndroidAppState::
|
||||
on_insets_changed(rsc, LogicalInsets)`, called from `render()`
|
||||
exactly when `AndroidUiState::insets()` changes, in logical units
|
||||
matching everything else `content_scale` now divides.
|
||||
`BenchClient::on_insets_changed` rebuilds the root tree with
|
||||
`Padding::top(insets.top)` on the button row -- rebuilding the
|
||||
whole tree rather than one `WidgetPtr` slot's content, because
|
||||
the first attempt (a `Pad` dropped into an unrelated `WidgetPtr`
|
||||
slot with no height override of its own) did not propagate the
|
||||
wrapped span's fixed height correctly, which is what surfaced
|
||||
finding 3's `UiRenderState::resize` bug in the first place.
|
||||
Verified via `ui-trace show --field box`: the button row's top
|
||||
(150 physical px) sits 8px below `statusBarBackground`'s bottom
|
||||
edge (142px) on this checkout's emulator.
|
||||
|
||||
**A named `Diagnostics` control now exists** (RUST.md's own earlier
|
||||
ask): a third button on the bench screen's top row, filling the
|
||||
existing benchmark-report `TextEdit` with adapter identity/backend/
|
||||
driver, font resolution, the atlas's live view count, every
|
||||
uncaptured wgpu error since surface creation, and the frame report
|
||||
-- `android::render::AndroidRenderer::diagnostics_report`. Uses the
|
||||
existing "Copy report" button/clipboard path rather than a second
|
||||
one.
|
||||
|
||||
**Verified this pass, this checkout's emulator** (`EMU_GPU` default,
|
||||
`--features force-gles` -- this cold `emu up` again enumerated zero
|
||||
Vulkan adapters, the same pre-existing flakiness earlier boxes
|
||||
documented, not something this pass's diff caused): `cargo fmt --all
|
||||
-- --check`, `cargo clippy --workspace --all-targets` (zero warnings
|
||||
beyond the pre-existing wgpu future-incompat notice), `cargo test
|
||||
--workspace` (all passing, unchanged pure-logic counts), `cargo ndk
|
||||
-t x86_64 -P 26 check` clean, `./run-bench.sh` end to end
|
||||
(`frames=691`, 24/24 swipes, 400/400 streamed events, no crash),
|
||||
fresh-install screenshots and `ui-trace` box readouts for the four
|
||||
items above. **Not verified this pass**: the actual phone (no
|
||||
access), and item 1's root cause (needs either the phone's next
|
||||
Diagnostics-page report or a Mali trace).
|
||||
|
||||
**Recorded but not fixed this pass** (a follow-up agent takes these,
|
||||
to avoid colliding with this pass's `bench_client.rs`/`view.rs`
|
||||
changes) -- see `IRIS_TODO.md`'s "From the phone, 2026-09-06":
|
||||
swiping has no momentum (stops exactly where the finger releases,
|
||||
unlike Compose's fling), and scrolling down sometimes jitters the
|
||||
text.
|
||||
|
||||
**Redelivered, 2026-09-06, later the same day.** New arm64 APK
|
||||
(Vulkan, no `force-gles`, bundled fonts, content-scale fix,
|
||||
Diagnostics control), same `dev.iris.android.demo.bench` id, same
|
||||
`CN=ai-app` signing cert, copied to `~/host/bench/
|
||||
iris-bench-arm64.apk` and `~/repos/ai-app-bench/iris/build/outputs/
|
||||
apk/release/iris-bench-arm64.apk`; that repo's own README gained a
|
||||
dated entry. Still not confirmed on Iris's actual phone.
|
||||
|
||||
- [ ] **P1 — session screen parity.** History paging backward (with the
|
||||
page-boundary healing `client-core` does not have yet, below),
|
||||
`TranscriptSource`-backed cache/server stitching, jump-to-latest,
|
||||
|
||||
Reference in new issue
Block a user