Repository navigation
fix(engine): a scene that has ended gives up its WebGL context so the next scene is not slowed - #6984
Conversation
Edit accuracy: accurate 271 (base branch 271), smooth 108 of thoseThe gate passes. Quarantined, measured but not gated (0) Unstable (2)
|
9dd2a12 to
41075d3
Compare
There was a problem hiding this comment.
Verdict: REQUEST CHANGES · 1 blocker · 0 important · 0 nits · head 30070ba0
1 blocker, posted as an inline comment: a 3D scene whose data-start is a reference (the documented data-start="intro" sequencing) can lose its WebGL context before it starts, so it renders with no 3D in the final video.
Scope
I read the whole diff and checked every path that captures frames out of order against the new per-frame release. The calibration sessions in captureCost.ts and planFrameCost.ts are closed rather than reused for the render. Probe discovery seeks without going through prepareFrameForCapture. Engine-mode shader transitions clone their scenes, so a WebGL canvas was already blank in those clones. The PR's own tests pass locally. I did not run a real render.
— genesis-v2 (Lane B)
| const hasEnded = (el: Element): boolean => { | ||
| let offset = 0; | ||
| return clipsAround(el).some((clip) => { | ||
| offset += Number(clip.getAttribute("data-start")) || 0; |
There was a problem hiding this comment.
blocker: Number(clip.getAttribute("data-start")) || 0 turns a reference start into 0. References are a documented way to set data-start ("intro", "intro + 0.5", "card-pro", per docs/concepts/data-attributes.mdx and compositions.mdx), and they are still unresolved on the render page. The runtime only resolves them through startResolver.
How it fails: intro runs 0–10 s and a three.js scene has data-start="intro" data-duration="3", so it plays 10–13 s. Before it starts, the runtime marks it data-hf-clip-hidden. This code puts its end at 0 + 3 = 3 s, so the frame at t=3 calls loseContext() on a scene that has not started yet. Frames 10–13 s then render with no 3D. A chain of scenes (A → B → C) hits the same thing whenever a reference-started clip is shorter than its real offset.
I ran this against the PR's own mock: releaseEndedWebglContexts(page, 5) returns 1 for that scene; it should return 0.
Fix: when any ancestor's data-start (or its length) is not a finite number, leave the context alone. Even better, read the start and duration the runtime has already resolved. Please also add a test for the reference case.
There was a problem hiding this comment.
✅ Fixed in 1d36408. The release now uses the runtime-resolved __hf.clipWindow.
… next scene is not slowed
… says its window ended
30070ba to
1d36408
Compare
There was a problem hiding this comment.
Verdict: APPROVE · 0 blocker · 0 important · 0 new · 1 resolved · 30070ba0 → 1d36408c
The reference-start blocker is resolved. The engine now asks the runtime for each clip window through __hf.clipWindow, which uses runtimeElementWindow and the start resolver, the same code the visibility pass uses, and it releases nothing when the runtime does not provide that. I checked locally that a child (data-start="1", data-duration="2") inside a sub-composition hosted at 10 s resolves to the absolute window {11, 13}, so a nested scene is not released early. The new engine tests and the core clipWindow test pass. The non-required Comments ratchet fails on packages/engine/src/types.ts (+1 comment line); this does not block approval.
There was a problem hiding this comment.
Verdict: APPROVE · 0 blocker · 0 important · 0 new · 1d36408c → 7f5cef34. Comment-only change: one comment in webglRelease.ts is reworded and one comment line is dropped from types.ts, the line that tripped the Comments ratchet. The code is the same as at 1d36408c.
A scene that has ended gives up its WebGL context, so the scene after it is not rendered at a crawl.
On software GL (the render workers), a three.js scene whose clip is over keeps its live WebGL context, and every later WebGL frame in the same page then costs several seconds. Measured on one project with a glass-refraction title (0 to 1 s) followed by a product turntable (1 to 3 s), one worker:
The engine records the WebGL contexts a page creates and, once per frame after the seek, calls
WEBGL_lose_contexton those inside a clip the runtime has hidden (data-hf-clip-hidden) whose window has ended. The window is the one the runtime resolves (window.__hf.clipWindow, a new read of the renderer's own start/end resolver), so a start written as a reference (data-start="intro + 1") is the resolved time and never the raw attribute; a scene whose window has not ended, or a runtime that does not report windows, keeps its context.Design: none (engine capture step)
fails without the fix:
releases a scene's context once the runtime's window for its hidden slot has ended,keeps the context of a scene whose start is a reference, until its resolved end has passed,reports a clip's window with its start reference resolvedWhat I measured
frameCapture*andwebglReleasetest files pass;tsc --noEmitclean inpackages/engine.What I did NOT exercise
webglcontextrestored, not tried here).Package size budget
The engine's packed budget goes from 456397 to 461788 bytes: the new module and its declarations ship in
dist(about 5 KB packed, over the 1% allowance).Size
6 files, about +180.