fix(engine): Linux GPU path uses deprecated EGL + NVENC probe fails on data-center GPUs (#1504)

* fix(engine): use ANGLE-EGL for Linux GPU path, bump NVENC probe size

Chrome 131+ rejects --use-gl=egl in headless shell; the GPU process
exits and the renderer silently falls back to SwiftShader. Switch to
(gl=angle, angle=gl-egl) which is on the headless-shell allowlist,
and add --ignore-gpu-blocklist + --disable-software-rasterizer so
data-center GPUs (L4/T4/A10) are not blocked.

Also bump the NVENC probe frame from 16×16 to 320×240 — NVIDIA
data-center cards require ≥257 on each dimension and reject the
smaller size with "Frame Dimension less than the minimum supported
value", causing the encoder probe to silently fall back to libx264.

Closes #1493

* fix(engine): address review feedback — probe test, observability, comments

- Export getProbeArgs and add test pinning 320×240 probe dimensions
  across all 5 GPU encoder backends (nvenc/videotoolbox/vaapi/qsv/amf)
- Add driver/SKU rationale comment on the probe size constant with
  context about NVIDIA data-center card behavior vs documented minimums
- Add rationale comment on --ignore-gpu-blocklist (operator opted into
  hardware mode explicitly)
- Log resolved GL flags at browser launch for GPU fallback observability
This commit is contained in:
Miguel Ángel
2026-06-16 12:07:04 -04:00
committed by GitHub
parent 479184ecf0
commit e5346afdd8
4 changed files with 43 additions and 7 deletions
@@ -45,11 +45,13 @@ describe("buildChromeArgs browser GPU mode", () => {
expect(args).not.toContain("--use-angle=swiftshader");
});
it("uses EGL for hardware browser GPU mode on Linux", () => {
it("uses ANGLE-EGL for hardware browser GPU mode on Linux", () => {
const args = buildChromeArgs({ ...base, platform: "linux" }, { browserGpuMode: "hardware" });
expect(args).toContain("--use-gl=egl");
expect(args).toContain("--use-gl=angle");
expect(args).toContain("--use-angle=gl-egl");
expect(args).toContain("--enable-gpu-rasterization");
expect(args).not.toContain("--use-gl=angle");
expect(args).toContain("--ignore-gpu-blocklist");
expect(args).toContain("--disable-software-rasterizer");
expect(args).not.toContain("--use-angle=swiftshader");
});
+15 -2
View File
@@ -378,8 +378,11 @@ async function launchBrowser(
});
const browserVersion = await browser.version().catch(() => "unknown");
const gpuFlags = chromeArgs.filter(
(a) => a.startsWith("--use-gl=") || a.startsWith("--use-angle="),
);
console.log(
`[BrowserManager] Browser launched (${browserVersion}, ${captureMode}, headlessShell=${!!headlessShell}, platform=${process.platform})`,
`[BrowserManager] Browser launched (${browserVersion}, ${captureMode}, gl=${gpuFlags.join(" ") || "default"}, headlessShell=${!!headlessShell}, platform=${process.platform})`,
);
if (captureMode === "beginframe") {
@@ -650,7 +653,17 @@ function getBrowserGpuArgs(
case "win32":
return ["--use-gl=angle", "--use-angle=d3d11", "--enable-gpu-rasterization"];
case "linux":
return ["--use-gl=egl", "--enable-gpu-rasterization"];
// Chrome 131+ headless shell only accepts (gl=angle, angle=gl-egl);
// the old --use-gl=egl causes the GPU process to exit silently.
// --ignore-gpu-blocklist: the operator explicitly opted into
// browserGpuMode="hardware", so trust their driver/GPU choice.
return [
"--use-gl=angle",
"--use-angle=gl-egl",
"--enable-gpu-rasterization",
"--ignore-gpu-blocklist",
"--disable-software-rasterizer",
];
default:
return ["--enable-gpu-rasterization"];
}