iris: a one-layer glyph atlas is a GL_TEXTURE_2D, so every glyph drew as a box
The emulator was blamed for two days for what is iris's own defect on any GL adapter. `GpuTextures::new` created the atlas `texture_2d_array` with one layer; wgpu-hal picks the GL target from the descriptor alone (`gles::Texture::get_info_from_desc`, `(false, 1) => TEXTURE_2D`), so the shader's `sampler2DArray` was handed a `GL_TEXTURE_2D`, the unit was incomplete, every `textureSample` returned (0,0,0,1), and `draw_glyph`'s `color.a *= texel.a` painted the whole glyph quad. `MIN_ARRAY_LAYERS = 2`, with the account at `create_array_texture` and a `debug_assert!` there. Vulkan -- the phone's build and the desktop's default backend -- was never affected. `force-gles` now switches the desktop backend too, so the GLES path is reproducible on a machine with a real GPU in seconds rather than only through an APK: that is how this was found, with two shader probes showing the sample was exactly (0,0,0,1).
This commit is contained in:
1 parent
69525bd131
commit
3cb18ac5c2
5 files changed
+108
-14
No files matched your search
@@ -5600,6 +5600,61 @@ device.
|
||||
transcript-ui -p desktop-app -p tabs-ui --all-targets`
|
||||
warning-free; `cargo test` 85 (iris, +4) + 13 (iris-core) +
|
||||
31 (transcript-ui, +11) + 123 (client-core).
|
||||
**2026-09-06, after P1a: "the emulator cannot draw iris's glyphs"
|
||||
was iris's bug, not the emulator's.** The finding recorded in the
|
||||
box above -- that every glyph is a solid filled box under `-gpu
|
||||
host` GLES and that this is what an incomplete GL texture returns
|
||||
-- had the mechanism right and the attribution wrong. It is a real
|
||||
defect on **any** adapter that is GL rather than Vulkan.
|
||||
- **Reproduced off the emulator entirely**, which is what made it
|
||||
cheap: `default/render.rs` now honours the same `force-gles`
|
||||
feature `android/render.rs` did, so
|
||||
`./run-headless.sh transcript --shot /tmp/x.png -- -p
|
||||
transcript-ui --features iris/force-gles` draws the boxes on this
|
||||
machine's own GPU in seconds. Two shader probes then said what
|
||||
the sample was: `return vec4(texel.rgb, 1.0)` drew black boxes and
|
||||
`return vec4(texel.a, texel.a, texel.a, 1.0)` drew white ones, so
|
||||
the atlas sample was exactly (0, 0, 0, 1) -- GL's answer for an
|
||||
**incomplete texture unit**, and not the null texture (which is
|
||||
zeroed, alpha 0).
|
||||
- **Root cause: the glyph atlas array was created with one layer.**
|
||||
`GpuTextures::new` started `array_capacity` at 1 and `grow_array`
|
||||
only doubles once a page needs a layer past it, so the ordinary
|
||||
case -- one atlas page -- is a one-layer array. wgpu-hal picks the
|
||||
GL texture target from the descriptor alone
|
||||
(`gles::Texture::get_info_from_desc`: `(false, 1) => TEXTURE_2D`),
|
||||
so that array is created as a `GL_TEXTURE_2D` and then bound to
|
||||
the shader's `sampler2DArray`. wgpu has a name for this
|
||||
(`log_failing_target_heuristics`, its issues #1614/#1574); the
|
||||
result is an incomplete unit, `texel.a == 1`, and `draw_glyph`'s
|
||||
`color.a *= texel.a` paints the whole glyph quad.
|
||||
- **Fix**: `MIN_ARRAY_LAYERS = 2` in
|
||||
`iris/core/src/render/texture.rs` -- the array is never created
|
||||
with fewer, with the account at `create_array_texture` and a
|
||||
`debug_assert!` there so a future capacity arithmetic change fails
|
||||
at the mistake rather than as boxes on a screen. Cost: one page of
|
||||
texture memory, which the next atlas page uses anyway.
|
||||
- **Not a regression from `3e72a4e..20303e0`, and the bisect was not
|
||||
run.** The defect is a function of the layer count, not of any
|
||||
commit in that range: it has been there since the atlas became a
|
||||
`texture_2d_array` (TEXTURES.md, 2026-09-04) and it reproduces at
|
||||
HEAD and disappears at HEAD with the one-line capacity change. The
|
||||
claimed "visible text at `3e72a4e`" is a misreading of its own
|
||||
evidence -- `/tmp/final-typing.png`, the screenshot that entry
|
||||
cites, is boxes; what the agent read was the `iris text render:
|
||||
chars=5 glyphs=5` log line, which reports what **parley shaped**,
|
||||
not what reached the screen. The earlier genuinely-good emulator
|
||||
shots (`/tmp/after3.png`, 2026-09-05 19:56) predate the APK being
|
||||
built with `force-gles` at all, so they were the Vulkan path.
|
||||
- **The phone build is not affected and does not need withdrawing.**
|
||||
`android-app/build-apk.sh`'s default features are deliberately
|
||||
without `force-gles` (`d73db97`'s comment), so a phone build takes
|
||||
`Backends::PRIMARY` -> Vulkan, where a one-layer array is an
|
||||
ordinary one-layer array and glyphs draw correctly -- which is
|
||||
also what Iris's phone reports have shown all along. The fix
|
||||
matters for any device that falls back to GLES, which is why it is
|
||||
not just an emulator convenience.
|
||||
|
||||
- [ ] **P1b — tool-call cards and grouping.** `ToolRows.kt`/
|
||||
`ToolInput.kt`'s cards: a collapsed row per call with name
|
||||
and a one-line summary, expand to input and output, runs of
|
||||
|
||||
Reference in new issue
Block a user