fix(engine): disable GPU compositing on SwiftShader for all capture modes - #3062
fix(engine): disable GPU compositing on SwiftShader for all capture modes#3062miga-heygen wants to merge 1 commit into
Conversation
…odes (#3049) SwiftShader's GPU compositor retains stale transformed layers across frames, producing phantom duplicate content at renderHeight/4 offsets in transparent renders. The --disable-gpu-compositing workaround was previously gated to BeginFrame capture mode only, but the same artefact affects Page.captureScreenshot on SwiftShader — and software-GPU renders are clamped to screenshot mode by the forceScreenshot invariant. Move --disable-gpu-compositing outside the BeginFrame-only block so it applies to all capture modes when browserGpuMode is "software". Also adds PRODUCER_EXTRA_CHROME_ARGS env var: a space-separated escape hatch for passing additional Chrome flags during debugging, so future compositor investigations do not require wrapping the chrome binary. Closes #3049
7b6e31e to
484d19b
Compare
|
Closing this. The premise does not hold, and the change measurably degrades software renders. The one true part
Why the fix is wrongThe stated root cause is falsified. This PR claims SwiftShader retains stale layers in screenshot mode too. I rendered The existing comment does not say what the PR body says it does. It says both readback methods see the stale surface, which was measured inside a BeginFrame session. #2521's evidence was BeginFrame only. The flag makes software output worse, not better. Same transparent composition (1280x1144, static SVG line primitives, alpha), rendered software vs a hardware-GPU render of the same file as ground truth. Frame 30:
CI caught the same thing. No reproduction. The validation section lists unit tests over What #3049 actually looks likeThe reporter's own evidence points away from the compositor: compositor flags had no effect, static elements duplicate, it survives Chrome 131 through Chrome 152, and merging the SVG I built a matching composition (240 static SVG lines, transparent background, yoyo timeline) and could not reproduce the banding on either build. Follow-up is on the issue: we need the reporter's composition before guessing again. Salvageable
|
Summary
--disable-gpu-compositingfrom the BeginFrame-only block to all capture modes whenbrowserGpuMode === "software"PRODUCER_EXTRA_CHROME_ARGSenv var for passing additional Chrome flags during debuggingProblem
SwiftShader's GPU compositor retains stale transformed layers across frames, producing phantom duplicate content at exactly
renderHeight/4vertical offsets. The artefact appears in both BeginFrame andPage.captureScreenshotcapture modes — the existing comment documents this ("both BeginFrame and Page.captureScreenshot read the stale surface"), but the--disable-gpu-compositingworkaround was gated to BeginFrame mode only.Software-GPU renders are clamped to screenshot mode by the
forceScreenshotinvariant (applyConcreteGpuScreenshotClamp), so the workaround never applied to the most common SwiftShader capture path.Root cause
buildChromeArgsplaced--disable-gpu-compositinginside theif (options.captureMode !== "screenshot")block (line 914–926). This was originally scoped to BeginFrame because BeginFrame drives the compositor step-by-step (where stale retention is deterministic), while screenshot mode was considered "good enough" because the compositor runs freely. Issue #3049 proves that SwiftShader's compositor also retains stale layers in screenshot mode, with a different pattern: band duplication atrenderHeight/4rather than sequential-frame yoyo persistence.Fix
Hoist
--disable-gpu-compositingout of the BeginFrame block so it fires for anybrowserGpuMode === "software"session, regardless of capture mode. Hardware-GPU captures are unaffected.The
PRODUCER_EXTRA_CHROME_ARGSescape hatch (space-separated env var) lets users inject Chrome flags without wrapping the binary — the original issue reporter specifically called this out as needed for debugging.Validation
npx vitest run packages/engine/src/services/browserManager.test.ts— 42/42 passing (8resolveHeadlessShellPathtests requirebun, pre-existing skip in this env)--disable-gpu-compositingpresent for BOTHsoftwareBeginFrameandsoftwareScreenshotbunx oxlint packages/engine/src/services/browserManager.ts— 0 warnings, 0 errorsbunx oxfmt --check— cleanCloses #3049