Skip to content

Recover from WebGL context loss on Safari and other browsers#225

Merged
ecto merged 1 commit into
mainfrom
claude/cool-davinci-QO98m
Jun 1, 2026
Merged

Recover from WebGL context loss on Safari and other browsers#225
ecto merged 1 commit into
mainfrom
claude/cool-davinci-QO98m

Conversation

@ecto
Copy link
Copy Markdown
Owner

@ecto ecto commented Jun 1, 2026

Summary

Fixed a viewport crash that occurs when the browser drops the WebGL context, which is especially common on Safari under GPU memory pressure, when too many live contexts exist, or when a tab is backgrounded and restored. The post-processing pipeline now gracefully tears down while the context is lost and remounts cleanly once the browser restores it.

Changes

  • New hook: useWebGLContextLost — Tracks whether the viewport's WebGL context is currently lost by listening to webglcontextlost and webglcontextrestored events. Calls preventDefault() on context loss to signal intent to recover, which triggers the matching restore event. Handles edge cases like contexts lost before listeners attach and getContext() throwing on half-torn-down renderers.

  • Updated ViewportContent — Conditionally unmounts the post-processing EffectComposer while the context is lost (it crashes reading renderer.getContext().getContextAttributes().alpha off a dead context). Triggers a repaint via invalidate() when the context is restored, since the viewport runs on demand frameloop and would otherwise sit blank until the next user interaction.

  • Changelog entry — Documents the fix for version 0.9.4.

Implementation Details

The hook seeds initial state by checking gl.isContextLost() in case the context was already lost before listeners attached (e.g., created on a backgrounded tab). The viewport's conditional rendering of post-processing ({engineReady && !xrPresenting && !contextLost && ...}) ensures fragile GPU-dependent subtrees are safely unmounted during context loss and remounted once Three.js's WebGLRenderer re-initializes its GL state on restore.

https://claude.ai/code/session_019HGPK77WwjeXuD7wFdNF1W

The postprocessing EffectComposer reads
`renderer.getContext().getContextAttributes().alpha` when its renderer or
passes are set. When the browser drops the WebGL context — common on
Safari/WebKit under GPU pressure, with many live contexts, or on tab
restore — `getContextAttributes()` returns null and the access throws
"null is not an object", crashing the viewport.

Add a useWebGLContextLost hook that tracks webglcontextlost/restored on the
R3F canvas (calling preventDefault so the browser attempts restoration), and
gate the EffectComposer on it so post-processing tears down while the context
is gone and remounts cleanly on restore. Nudge a repaint on restore since the
viewport uses a demand frameloop.

https://claude.ai/code/session_019HGPK77WwjeXuD7wFdNF1W
@vercel
Copy link
Copy Markdown

vercel Bot commented Jun 1, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

4 Skipped Deployments
Project Deployment Actions Updated (UTC)
mecheval Ignored Ignored Jun 1, 2026 9:05pm
vcad Ignored Ignored Jun 1, 2026 9:05pm
vcad-docs Ignored Ignored Jun 1, 2026 9:05pm
vcad-mcp Ignored Ignored Jun 1, 2026 9:05pm

Request Review

@ecto ecto merged commit 9cb10fd into main Jun 1, 2026
10 checks passed
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.

2 participants