Context
While building the real-pointer popup-over-popup matrix for #16117, the ordinary headed E2E profile correctly retained --disable-frame-rate-limit (required for engine / OffscreenCanvas coverage) and the existing GL boot probe reported hardware acceleration:
[gl-probe] state=accelerated
renderer=ANGLE (Apple, ANGLE Metal Renderer: Apple M5 Max, Unspecified Version)
The first isolated matrix cell completed. Repeated native popup retirement / rebirth and then separately isolated Playwright contexts caused Chrome's GPU process to exit repeatedly until the whole browser terminated. Running the same large-over-small cell alone in a fresh Playwright process passed completely.
This is a successor to #15664 / #15813, not a reopening. Those tickets removed poison GL flags and guarded initial GL resolution; both remain correctly closed.
Live duplicate sweep on 2026-07-29:
- searched all issues for
GPU process isn't usable popup
- searched for
disable-frame-rate-limit Chrome GPU crash
- searched for
Playwright native window GPU exit_code 11
- inspected the latest 30 open issues
- no open equivalent found
Problem
The suite's effect-shaped boot probe proves GPU health only at browser birth. It cannot detect a later transition from healthy ANGLE/Metal to repeated GPU-process death during a headed multi-window run.
That creates two false signals:
- Product tests fail as if a page, App Worker, or popup lifecycle broke, although Chrome terminated the browser.
- A green boot probe can be read as run-wide GPU health even after the measured state has decayed.
The current workaround is process isolation per matrix cell. That is valid evidence isolation, but it is not yet an automated suite contract.
Evidence
Normal-profile command:
NEO_E2E_PORT=8158 npx playwright test workstation/WorkstationHumanPopupOverlapNL.spec.mjs -c test/playwright/playwright.config.e2e.mjs --headed --workers=1
Chrome stderr after the green GL probe:
ContextResult::kTransientFailure: Failed to send GpuControl.CreateCommandBuffer.
GPU process exited unexpectedly: exit_code=11
GPU process exited unexpectedly: exit_code=11
GPU process exited unexpectedly: exit_code=11
FATAL:content/browser/gpu/gpu_data_manager_impl_private.cc:416]
GPU process isn't usable. Goodbye.
Observed matrix boundary:
large-over-small alone in a fresh Playwright process: PASS (including early conversion, one target-local proxy, five target choices, two-frame pointer-follow, exact outer-size restoration, and clean retirement).
- four cells in one serial browser lifecycle: product assertions pass while the browser remains alive; later contexts fail during initial app boot because Chrome has crossed its GPU-crash threshold.
- each Playwright invocation still starts its own webpack server with
reuseExistingServer: false; cross-serving is not implicated.
- film capture is a separate profile and is not evidence for the ordinary engine-profile failure.
Architectural Reality
test/playwright/e2e/utils/gpuIntent.mjs is the launch-argument authority.
test/playwright/e2e/gl.setup.mjs is an initial-state gate, not a continuous liveness monitor.
test/playwright/playwright.config.e2e.mjs is intentionally serial (workers: 1) for benchmark/native-window stability.
--disable-frame-rate-limit must remain in the ordinary profile. Removing it would hide the required engine / OffscreenCanvas surface and is not an acceptable repair.
- Native windows and the GPU crash threshold are browser-process state. A fresh BrowserContext is insufficient isolation when the browser process survives across tests.
Acceptance Criteria
Out of Scope
- Dropping
--disable-frame-rate-limit from the ordinary profile.
- Treating film-mode pixel capture as a substitute for engine-profile coverage.
- Product-side docking changes from #16117.
- Reopening or rewriting the resolved truth of #15664 / #15813.
Related
- #16117 — the popup-over-popup witness that exposed this.
- #15664 — resolved predecessor: poison GL flags caused the former popup-birth browser kill.
- #15813 — resolved predecessor: initial GL effect probe.
test/playwright/e2e/utils/gpuIntent.mjs
test/playwright/e2e/gl.setup.mjs
test/playwright/playwright.config.e2e.mjs
Decision Record impact: none.
Origin Session ID: 5f3ec5da-f2a5-45e9-aa47-7c4f3866a06f
Retrieval Hint: "green ANGLE Metal boot probe then GPU exit_code 11 native popup churn disable-frame-rate-limit"
Context
While building the real-pointer popup-over-popup matrix for #16117, the ordinary headed E2E profile correctly retained
--disable-frame-rate-limit(required for engine / OffscreenCanvas coverage) and the existing GL boot probe reported hardware acceleration:The first isolated matrix cell completed. Repeated native popup retirement / rebirth and then separately isolated Playwright contexts caused Chrome's GPU process to exit repeatedly until the whole browser terminated. Running the same large-over-small cell alone in a fresh Playwright process passed completely.
This is a successor to #15664 / #15813, not a reopening. Those tickets removed poison GL flags and guarded initial GL resolution; both remain correctly closed.
Live duplicate sweep on 2026-07-29:
GPU process isn't usable popupdisable-frame-rate-limit Chrome GPU crashPlaywright native window GPU exit_code 11Problem
The suite's effect-shaped boot probe proves GPU health only at browser birth. It cannot detect a later transition from healthy ANGLE/Metal to repeated GPU-process death during a headed multi-window run.
That creates two false signals:
The current workaround is process isolation per matrix cell. That is valid evidence isolation, but it is not yet an automated suite contract.
Evidence
Normal-profile command:
NEO_E2E_PORT=8158 npx playwright test workstation/WorkstationHumanPopupOverlapNL.spec.mjs -c test/playwright/playwright.config.e2e.mjs --headed --workers=1Chrome stderr after the green GL probe:
Observed matrix boundary:
large-over-smallalone in a fresh Playwright process: PASS (including early conversion, one target-local proxy, five target choices, two-frame pointer-follow, exact outer-size restoration, and clean retirement).reuseExistingServer: false; cross-serving is not implicated.Architectural Reality
test/playwright/e2e/utils/gpuIntent.mjsis the launch-argument authority.test/playwright/e2e/gl.setup.mjsis an initial-state gate, not a continuous liveness monitor.test/playwright/playwright.config.e2e.mjsis intentionally serial (workers: 1) for benchmark/native-window stability.--disable-frame-rate-limitmust remain in the ordinary profile. Removing it would hide the required engine / OffscreenCanvas surface and is not an acceptable repair.Acceptance Criteria
dev, preserving--disable-frame-rate-limit.exit_code=11is caused by a current launch-flag interaction, Chrome/macOS runtime decay, native-window lifecycle, or another measurable browser-process condition.reuseExistingServer: false; every Playwright invocation continues to serve its own checkout.NEO_FILM_TAKE=1.Out of Scope
--disable-frame-rate-limitfrom the ordinary profile.Related
test/playwright/e2e/utils/gpuIntent.mjstest/playwright/e2e/gl.setup.mjstest/playwright/playwright.config.e2e.mjsDecision Record impact: none.
Origin Session ID: 5f3ec5da-f2a5-45e9-aa47-7c4f3866a06f Retrieval Hint: "green ANGLE Metal boot probe then GPU exit_code 11 native popup churn disable-frame-rate-limit"