Commit 32e7a008 by PLN (Algolia)

fix(slop): headless DOES reach the GPU — `--use-angle=gl-egl`, not `--use-gl=egl`

Correcting my own previous commit, which concluded hardware GL required headful
and made `--gl hw` open a real window per clip. PLN, mid-batch: "stop opening
chrome windows lol cant we do this headless". Yes — and the conclusion was wrong
because I tested three launch modes and stopped at the first that worked.

Five headless modes plus headful, each asked what WebGL actually resolved to:

    --use-angle=swiftshader                       -> SwiftShader (Subzero)
    --use-gl=egl                                  -> SwiftShader (Subzero)
    --use-angle=vulkan                            -> SwiftShader (Subzero)
    --ozone-platform=headless --use-angle=vulkan  -> SwiftShader (Subzero)
    --use-gl=angle --use-angle=gl-egl             -> Mesa Intel UHD (CML GT2)
    HEADFUL                                       -> Mesa Intel UHD (CML GT2)

`--use-gl=angle --use-angle=gl-egl` reaches the real GPU with no window at all.
It is ONE FLAG WORD from `--use-gl=egl`, which silently degrades to software —
which is exactly why the original code read as correct and was not, and why the
comment claiming the hw path "falls back by simply measuring worse" survived so
long. It never fell back: 3.5 fps and 3.2 fps were the same software backend
measured twice, and two numbers that looked like measurement noise were one wrong
assumption.

Measured, landscape 1920x1080, same 30 s window each time:

    swiftshader (headless)   3.5 fps captured
    headful + real GPU      11.4 fps captured, page rendered 17
    headless + gl-egl       17.8 fps captured, page rendered 542 of 542

Headless is FASTER than headful — no compositor in the path — and the capture
bottleneck disappears with it: captured frames now equal rendered frames, where
headful drained 346 of 516. So the earlier "the next lever is the capture path"
note was also an artefact of the wrong launch mode. 5x the software baseline,
comfortably past the under-5-fps guard, and no windows.

Lesson for the file: an early success is not a search. Two of the five modes
reach the GPU and three do not, and the three failures are indistinguishable
from each other by frame rate alone.
parent 1fdfb85f
...@@ -274,32 +274,32 @@ try { ...@@ -274,32 +274,32 @@ try {
console.log(` fx ${Object.keys(job.fx).join(", ")}`); console.log(` fx ${Object.keys(job.fx).join(", ")}`);
// --- 2. drive the page -------------------------------------------------- // --- 2. drive the page --------------------------------------------------
// MEASURED 2026-08-17, and it overturns the previous comment here. // MEASURED 2026-08-17 by asking WebGL what it actually resolved to, rather
// than inferring the backend from frame rate on a machine whose load varies.
// Five headless launch modes, one headful, same page:
// //
// `--gl hw` did not get hardware GL. Asked three launch modes what WebGL // --use-angle=swiftshader -> SwiftShader (Subzero)
// actually resolves to on this box: // --use-gl=egl -> SwiftShader (Subzero)
// --use-angle=vulkan -> SwiftShader (Subzero)
// --ozone-platform=headless --use-angle=vulkan -> SwiftShader (Subzero)
// --use-gl=angle --use-angle=gl-egl -> Mesa Intel UHD (CML GT2) <-- HW
// HEADFUL -> Mesa Intel UHD (CML GT2)
// //
// headless + --use-angle=swiftshader -> SwiftShader (Subzero) // So the old `--use-gl=egl` never left software, and the old comment claiming
// headless + --use-gl=egl -> SwiftShader (Subzero) <- same! // the hw path "falls back by simply measuring worse" was describing a path
// HEADFUL -> Mesa Intel UHD (CML GT2) // that was always the software path: 3.5 fps on swiftshader and 3.2 fps on
// "hw" were the same backend measured twice, both under the fps guard below.
// //
// So in headless the GPU is unreachable regardless of flags, and `--gl hw` // `--use-gl=angle --use-angle=gl-egl` reaches the real GPU while staying
// silently stayed on software while claiming otherwise — which is why a // HEADLESS — one flag word away from the version that does not. Headful also
// 1920x1080 landscape render captured 3.5 fps on swiftshader and 3.2 fps on // works but opens a window per clip, which is intolerable across a 19-clip
// "hw", tripping the under-5-fps guard both times. The old note said the hw // batch on the machine PLN is using.
// path "falls back by simply measuring worse"; it was not falling back, it
// never left software.
//
// Hardware GL therefore REQUIRES headful, on the real display. Same
// conclusion as the SoundCloud and YouTube transports: be a real browser.
// Costs a visible window for the duration of the capture.
const headful = A.gl === "hw";
browser = await chromium.launch({ browser = await chromium.launch({
headless: !headful, headless: true,
executablePath: chromeBinary(), executablePath: chromeBinary(),
args: [ args: [
...(headful ...(A.gl === "hw"
? ["--enable-gpu-rasterization"] ? ["--use-gl=angle", "--use-angle=gl-egl", "--enable-gpu-rasterization"]
: ["--use-gl=angle", "--use-angle=swiftshader"]), : ["--use-gl=angle", "--use-angle=swiftshader"]),
"--ignore-gpu-blocklist", "--ignore-gpu-blocklist",
"--autoplay-policy=no-user-gesture-required", "--autoplay-policy=no-user-gesture-required",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment