fix(react): StrictMode-safe Sky disposal — defer one cancelable tick - #6
Open
DennisSmolek wants to merge 1 commit into
Open
fix(react): StrictMode-safe Sky disposal — defer one cancelable tick#6DennisSmolek wants to merge 1 commit into
DennisSmolek wants to merge 1 commit into
Conversation
StrictMode's dev mount→cleanup→mount cycle ran the attach effect's synchronous `sky.dispose()` against the useMemo'd instance, gutting its internals (dome mesh, LUT/cube targets) before re-attaching the husk. The sky then rendered its construction-time bake forever: every live setter re-baked an empty sky scene into a recreated texture nothing samples, with zero errors — while uniform-backed knobs (exposure, haze strength) kept working. Disposal is now scheduled on a 0ms timer and canceled if the same instance re-attaches within the tick; real unmounts and instance swaps still dispose. Diagnosed in the paris-mini-site hero demo by instrumenting renderer.render during a manual bake: all six cube-face renders executed against a skyScene with zero children. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
The bug
The react binding's attach effect ran
sky.detach(); sky.dispose()synchronously in its cleanup. React StrictMode runs every effect as mount → cleanup → mount in dev, so the cleanup disposed theuseMemo'd instance's internals — sky-scene dome mesh, LUT/cube render targets — and then re-attached the husk.Symptom (zero console errors): the sky renders its construction-time bake forever. Every live setter (
setTimeOfDay,setLatitude,setTurbidity, mirror…) updates instance state and clears the dirty flags — but the cube bake renders an empty sky scene into a lazily recreated texture that no long-lived pipeline samples, while the screen keeps showing the original bake through a cached GPU binding. Uniform-backed knobs (setExposure,setHazeStrength) keep working, which disguises it as "some sliders are dead".Diagnosed in a Next.js (StrictMode) R3F v10 WebGPU app by instrumenting
renderer.renderduring a manualbaker.update(): all six cube-face renders executed against a skyScene with zero children. The vanilla demos can never hit this (no React), and production builds without StrictMode don't either — it's a dev-only trap, but dev is where everyone lives.The fix
Disposal is deferred one tick on a cancelable timer (
scheduleDispose/cancelScheduledDispose, one pending timer per instance). The StrictMode remount re-runs the effect synchronously after cleanup, which cancels the pending disposal; a real unmount or a construction-time instance swap lets it fire. No API change.Also adds a CLAUDE.md gotcha entry so the pattern is mirrored for any future memoized GPU-resource owner in the react bindings.
Verified
In the consuming app (paris-mini-site hero demo): before — TOD slider inert at any value; after — TOD 20.5 → 12 flips dusk to full daylight instantly, and latitude/dayOfYear/turbidity/mirror all re-bake live.
🤖 Generated with Claude Code