Keep WebGPU alive when toggling 3D; single adapter/device owner - #445
Merged
Merged
Conversation
Problem B: rendererSelection.ts and deviceCapabilities.ts each called navigator.gpu.requestAdapter() directly (default and low-power preference respectively), racing the real device request in webgpuDevice.ts and risking binding a different GPU on dual-GPU hardware. webgpuDevice.ts is now the sole requestAdapter/requestDevice call site: it tracks the latest device request so other modules can peek/reuse it (peekInFlightWebGPUDeviceRequest, peekAdapterInfoForCapabilityHint) instead of requesting their own adapter. The renderer-selection probe degrades to a cheap navigator.gpu surface check when no real request is in flight yet. Problem C: the boot probe configured its throwaway canvas with alphaMode: 'opaque' while the real swapchain defaults to 'premultiplied', so bloom/screenshot/createImageBitmap paths could disagree with what the probe validated. The probe now configures through the same configureCanvasContext() helper the runtime uses, so alphaMode/usage/format can never drift apart. Premultiplied stays the default — the pattern canvas composites over dark HTML chrome. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
App.tsx used to early-return a completely different tree for 3D mode
(App3DModeShell instead of MainLayout), which unmounted MainLayout /
PerformanceStage / PatternDisplay — destroying the WebGPU device,
swapchain, bloom post-processor and compute pipeline. App3DView then
mounted a *second* PatternDisplay (key={shader3D}) embedded in the R3F
scene via Drei's <Html>, requesting a second device. Toggling 3D was
therefore a full GPU teardown/rebuild: black canvas, possible audio
glitch, and a device-lifecycle race.
3D is a React-Three-Fiber "studio" that embeds the 2D visualiser as
HTML — it never needed a different WebGPU device. This treats it like
stage mode (see MainLayout/ChromeLayout/PerformanceStage's existing
invariant-tree pattern): MainLayout stays mounted unconditionally;
App3DModeShell renders as a sibling, fixed-position overlay instead of
replacing it.
The one PatternDisplay instance is shared between 2D and 3D rather
than duplicated. PerformanceStage now portals it into a stable,
never-recreated container (`canvasHost`, created once via lazy
useState) — createPortal's target identity never changes, so the
portal is never remounted. Only that container's *real DOM parent*
moves: normally PerformanceStage's own on-page slot, or — while 3D is
open — the DOM node Studio3D's R3F <Html> pattern-display panel
exposes via a ref callback threaded down through App.tsx → MainLayout
→ ChromeLayout → PerformanceStage (App3DModeShell → App3DView →
Studio3D on the other side). App3DView no longer constructs its own
PatternDisplay or picks a 3D-only shader (shader3D /
patternv0.21|patternv0.38 is gone — 3D always shows whatever 2D is
currently showing, per the "embeds the 2D visualiser" framing).
Added tests/threeDModeLayout.test.ts (modeled on the existing
stageModeLayout.test.ts) to pin the invariant tree shape, and
tests/webgpuDeviceOwnership.test.ts to pin Problem B/C's single-owner
invariants (only webgpuDevice.ts calls requestAdapter/requestDevice;
the presentation probe shares configureCanvasContext).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Note Currently processing new changes in this PR. This may take a few minutes, please wait... ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (12)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Toggling 3D mode used to unmount
MainLayout/PatternDisplay, destroying the WebGPU device, swapchain, bloom, and compute pipeline, then remount a secondPatternDisplayinside the R3F scene. 3D is now a sibling overlay (same invariant-tree pattern as stage mode): the one visualiser stays mounted and is portaled into Studio3D's HTML panel. Adapter/device requests and canvasconfigure()also go through a single owner so probes cannot race a second GPU or disagree onalphaMode.Changes
MainLayoutstays mounted;App3DModeShellis a fixed overlay.PerformanceStageportals the onePatternDisplayinto a stablecanvasHostwhose DOM parent moves into Studio3D while 3D is open. 3D no longer constructs its own visualiser or picks a 3D-only shader — it shows whatever 2D is showing.webgpuDevice.tsis the onlyrequestAdapter/requestDevicecall site. Renderer-selection and capability probes peek/reuse the in-flight request instead of requesting their own adapter.configureCanvasContext()helper as the runtime (premultiplieddefault), so bloom/screenshot/createImageBitmapcannot disagree with what the probe validated.tests/threeDModeLayout.test.ts(invariant tree) andtests/webgpuDeviceOwnership.test.ts(single owner + shared configure).Commits
db8a3e9webgpu: unify adapter requests and canvas config into one owner41683353d: stop tearing down the WebGPU canvas when toggling 3D modeSummary by CodeRabbit
New Features
Bug Fixes
Tests