Skip to content

Fix #369: restart the web build's graphics after a lost device or context - #403

Merged
bflatastic merged 1 commit into
mainfrom
fix/issue-369
Oct 8, 2026
Merged

bflatastic merged 1 commit into
mainfrom
fix/issue-369

Conversation

@bflatastic

@bflatastic bflatastic commented Oct 7, 2026 •

Copy link
Copy Markdown
Member

When the browser drops the page's WebGPU device or WebGL context, the web build now starts its graphics again with the same documents. Before, it froze on a stale canvas (Chrome, WebKit) or went blank (Firefox) while edits and Save went on.

  • Detection: wgpu's device-lost callback (WebGPU) and the canvas's webglcontextlost event (WebGL2) report to a new graphics::GraphicsLoss (ui-egui), which WebShell::logic handles on the next frame.
  • Recovery (web): VectorcraftApp::graphics_lost writes Data Recovery copies first. Then the shell swaps in a fresh <canvas> and starts the same WebRunner again with new graphics, handing over the same VectorcraftApp (documents, undo, panels). Its services are made for the new context, and the status bar says the graphics were restarted.
  • Re-uploading textures: the app notices a new egui context (adopt_context) and uploads everything again: fonts and theme, the canvas, and the place cursor thumbnails. Every per-thread texture cache (thumbnails, previews, font samples, Navigator, Flattener Preview) is now a TexCache that empties for a new context. Without this, the moved app showed stale or wrong textures, and egui panicked on missing font families.
  • Fallback: if there are no new graphics, or after 3 losses, the shell removes the stale canvas and gives up the recovery copies with the new recovery::leave (engine). The reloaded page then offers the copies at once, not after the heartbeat goes stale. The page tells the user to reload.
  • Web Locks (Fix #367: keep a paused browser tab's recovery copies #399): started once before the first frame and kept in the shell's Host, so a graphics restart reuses them and the tab stays the owner of its recovery area. recovery::leave also drops the area's lock or announcement, so a reloaded page takes the copies at once.
  • Desktop: eframe can't give a window a new device. On a lost device (driver reset) the app logs it, writes the copies and says in the status bar to save and restart. Closing the window then skips the Save Changes dialog, which it can't show.
  • Docs: docs/development.md (web section, with how to trigger a loss by hand) and the ROADMAP.

Checks

  • Rebased on 72fc1ac0e18dbf241429c87302ba9af71b1df6bc (with #399 Web Locks).
  • cargo fmt --all --check.
  • cargo clippy -D warnings:
    • ui-egui, engine and vectorcraft with --all-targets;
    • vectorcraft-web and ui-egui on wasm32-unknown-unknown;
    • vectorcraft on aarch64-apple-darwin and x86_64-unknown-linux-gnu;
    • vectorcraft with --features windows7 on linux.
  • cargo test: ui-egui 625 passed, engine 1296 + integration passed, vectorcraft 18 passed.
  • New tests: graphics::tests::* (4) and an_app_that_leaves_has_its_copies_offered_at_once. the_app_uploads_everything_again_in_a_new_context fails without the fix: wrong canvas texture, and egui panics on the missing fonts.
  • cargo xtask wasm (19/19 ok), cargo xtask layers, cargo xtask brands.
  • Not done: a live browser run with loseContext() / device.destroy(). trunk isn't installed on this machine. Please check with ?webgl plus WEBGL_lose_context, and on WebGPU with device.destroy().

🤖 Generated with Claude Code

…text

When the browser dropped the page's WebGPU device or WebGL context, the
editor kept running but nothing it drew reached the screen: Chrome and
WebKit showed a frozen, stale canvas and Firefox a blank page, while
edits and Save went on.

- ui-egui: new `graphics` module. `GraphicsLoss` carries a loss report
  from any thread (wgpu's device-lost callback, the canvas's
  `webglcontextlost` event) to the UI thread. `VectorcraftApp::
  graphics_lost` writes Data Recovery copies of the modified documents at
  once. The app now notices when the host hands it a new egui context and
  uploads everything again (fonts and theme, the canvas, place cursor
  thumbnails); every per-thread texture cache (layer, symbol, swatch,
  style, asset and glyph thumbnails, previews, font samples, Navigator,
  Flattener Preview) is a `TexCache` that empties for a new context.
  Without this, the moved app drew stale or wrong textures and egui
  panicked on its missing font families.
- web: the shell watches both loss signals; on a loss it puts a fresh
  canvas in place of the dead one and starts the same `WebRunner` again,
  handing over the same app (documents, undo, panels), with services made
  for the new context and a status-bar note. If no new graphics can be had
  (or after three losses) it removes the stale canvas, lets go of the
  recovery copies and says to reload.
- engine: `recovery::leave` lets go of a session's area but keeps its
  copies, so the reloaded page offers them at once instead of after the
  heartbeat goes stale.
- desktop: eframe can't give a window a new device, so a lost device
  (driver reset) is logged, the copies are written and the status bar says
  to save and restart; closing then skips the Save Changes question it
  can't show.
- Tests: loss reporting across threads, `TexCache` emptying, the app
  uploading the canvas, a cached preview, theme and fonts again in a new
  context (fails without the fix), copies written on loss, and
  `recovery::leave` offering copies at once with both lock and heartbeat
  stores. docs/development.md (web section) and ROADMAP updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@bflatastic
bflatastic merged commit d036a6d into main Oct 8, 2026
@bflatastic

Copy link
Copy Markdown
Member Author

Full cargo xtask ci passed on the integrated stack; merging.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant