From 50e69995b6bbd3bcb7edea0aef9153c41dda2929 Mon Sep 17 00:00:00 2001 From: iris <2+iris@noreply.localhost> Date: Mon, 7 Sep 2026 21:50:06 -0400 Subject: [PATCH] docs/RUST.md: the emulator crash loop was the missing GLES fallback, with the panic-hook note Co-Authored-By: Claude Fable 5.1 --- docs/RUST.md | 65 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 60 insertions(+), 5 deletions(-) diff --git a/docs/RUST.md b/docs/RUST.md index a7ba04c..bb5c933 100644 --- a/docs/RUST.md +++ b/docs/RUST.md @@ -716,11 +716,66 @@ closes it. devlog agent shrank the label type 18 -> 13 to make room (UI_RULES: never shrink text to fit). Put the controls in two rows or make the header wrap; restore the size. Sonnet. -- [ ] Bench app crash-loops on this checkout's emulator once - backgrounded (seen by the devlog agent, pre-existing; the phone's - resume works since ba2afba). Reproduce on the emulator's GLES path, - read the crash from the devlog/`adb logcat`, fix. Opus if it is in - the surface lifecycle. +- [x] **Bench app crash-loops on this checkout's emulator (done + 2026-09-07).** Not the surface lifecycle at all, and not "once + backgrounded" -- a build with the **default features** (no + `force-gles`) never got a first frame. `AndroidRenderer::new` + (`iris/src/android/render.rs`) asked wgpu for `Backends::PRIMARY`, + which does not contain `GL`, and this emulator advertises a Vulkan ICD + with no adapter behind it: `RequestAdapterError::NotFound { + active_backends: VULKAN, no_adapter_backends: VULKAN, + supported_backends: VULKAN | GL }`, `.expect`ed, so SIGABRT, so the + launcher restarts it -- the loop. A `force-gles` build was never + affected, which is why the crash looked like it belonged to whatever + else was going on. **Root cause: iris refused a device whose only + usable adapter is a GLES one.** + + **Fix, two halves.** (1) `AndroidRenderer::new` now probes for a + `PRIMARY` adapter with an instance that never touches the window and + rebuilds the instance on `Backends::GL` when there is none. The probe + is surface-free deliberately: **an Android window can be connected to + one graphics API only**, so a single instance carrying both backends + fails differently and worse -- Vulkan's + `vkCreateAndroidSurfaceKHR` claims the window in `create_surface` and + the GLES surface built from the same window then reports `In + Surface::configure / Invalid surface`, aborting one frame later in + `Surface::get_current_texture_view` ("Surface is not configured for + presentation"). That was measured here on the way to the fix, not + reasoned about. Vulkan still wins wherever it has an adapter, so + nothing changes on the phone. (2) The surface, adapter and device + requests all report through the `Result` this function + already returns, instead of two of the three panicking -- one rule for + the set, and `surface_changed` already puts that string on screen and + in the log ring. + + **Evidence**, this checkout's emulator (API 36, x86_64, debug): + before, default features aborted on first launch with `Abort message: + 'Could not get adapter!: NotFound {...}'`; after, `iris renderer: no + Backends(VULKAN | METAL | DX12 | BROWSER_WEBGPU) adapter on this + device, falling back to GLES` then `new renderer built (Gl)` and + frames. Then the cases the fix had no reason to touch, clean on both + the default build and a `force-gles` one: two background/return + cycles, rotate to landscape and back (`already_live=true`, the reuse + branch), a background/return after the rotation, and cold starts. + **Vulkan could not be exercised here** -- the probe's own answer is + that this emulator has no Vulkan adapter, which is the whole defect; + Vulkan remains only testable on Iris's phone. + + **Also landed with it, and worth more than the fix**: a panic hook in + `iris/android-app/src/app_log.rs`. Checked first, rather than assumed: + under `panic = "abort"` a panic's message reaches the tombstone's + `Abort message` and **nothing else** -- not `log`, so not the ring, so + not Dev Updater's Runtime tab, which is the only surface Iris has on a + phone with no `adb`. The hook writes the message and its location at + `error` level, and -- because the ring is memory only and the process + is about to die -- also to `last-panic.txt` in the app's private + directory, which `set_crash_dir` (called from `nativeSetFilesDir`) + replays into the ring at `error` level on the next start and deletes. + So a crash loop now explains itself in the Runtime tab of the run + that is still up. Verified on the emulator by building the *unfixed* + renderer with the hook: `iris panic at .../render.rs:140:14: Could not + get adapter!: NotFound {...}` in the ring on the run that died, and + `iris app log: the previous run died -- ...` on the next one. - [ ] Masks with a shape -- docs/LAYOUT.md "Masks with a shape (decided 2026-09-07)". A mask references a primitive already drawn (rect SDF, texture or glyph alpha), chained and multiplied; `.masked()`