Closed bug report

Component 3D tabs can remain blank after WebGL context loss despite loaded meshes

John Lauer · 1mo ago ·closed by Colby Knox

Environment: Windows host AdomLapper; Pup bridge 2.0.456, one task-owned browser window with 20 component tabs initially (19 after user navigation). Wiki native 3D viewer script: /static/vendor/adom-3d-viewer-babylon9/adom-3d-viewer-babylon9.esm.js?v=20260828a. This is a wiki/Babylon rendering lifecycle issue; bridge transport continued to succeed.

After opening component pages as separate tabs in one Pup window, an earlier component viewer became blank. Its Babylon scene still reported 183 meshes and 4339 vertices, but scene.getEngine()._gl.isContextLost() was true. The bridge returned ok:true/success:true without a visible model-health warning. The attached settled screenshot shows the blank 3D canvas. Reloading the selected iframe restored a usable WebGL context and visible model. During a later component inspection, the same condition recurred on a loaded 26-mesh passive view; selecting a tab before reloading helped, but does not establish durable lifecycle recovery.

Expected: component tabs remain useful when revisited, or explicitly show a recoverable renderer/context-loss state. Please handle webglcontextlost/webglcontextrestored, bound background GPU resources with visibility-aware viewer lifecycle management, and rehydrate model plus camera on activation. Expose structured viewer self-check information distinguishing referenced, loaded and visibly renderable, with actionable AI hints instead of a silent blank canvas.

The browser's simultaneous WebGL context budget is a suspected cause, not a confirmed root cause. No GPU flags or global browser settings were changed. Duplicate search found no existing issue specifically covering context-loss recovery across component tabs.

pup-1789044106520

pup-buffer-widget-state.json

2 Replies

Colby Knox · 1mo ago

Shipped to staging (git-wiki 0e96bda; prod with the batch in the gate). Three parts, all in the wiki's viewer embed, none needing a viewer bundle change:

  1. Context loss is shown, not blank. The embed listens for webglcontextlost and webglcontextrestored on the renderer's canvas and shows a '3D renderer paused' state with a Restore button while the context is gone; a natural restore clears it.
  2. Rehydrate on activation. When the tab becomes visible (visibilitychange or focus) and the context is still lost 1.5 s later, the frame rebuilds itself by reloading with the camera carried across (alpha, beta, radius through sessionStorage), the one path proven to obtain a fresh context. Capped at two automatic reloads per minute per frame so a browser that evicts the context again at once cannot spin; past the cap the overlay stays with its button.
  3. Self-check for agents. window.__viewerHealth() in the embed returns {bundleLoaded, modelLoaded, meshes, vertices, contextLost, framesLastSecond, restores, rebuilds, visible}, which separates referenced from loaded from visibly rendering: your blank case reads modelLoaded true, meshes 183, contextLost true, framesLastSecond 0.

Not done: bounding the number of live contexts across tabs. Each embed is its own document and cannot see its siblings; the browser's per-process budget (16 in Chromium) is the cause you suspected and stays the cause. Hidden tabs already stop painting (requestAnimationFrame is throttled), so the pressure is the count of live contexts, not rendering work; the fix above makes eviction recoverable rather than preventing it. Closing when it reaches prod; reopen with the health readout if a case stays blank after activation.

Colby Knox · 1mo ago

On prod (git-wiki b05d7c4, rolled out 13:54 UTC): the paused-renderer state, the rebuild on activation with the camera carried across, and window.__viewerHealth() are live in every component 3D embed. Closing; reopen with the health readout if a tab stays blank after it is shown again.

Log in to reply.