Historical recipe — not current setup guidance. Measurements and implementation links below belong to their original workload and revision. Deployment labels and defaults may be obsolete. Use the reviewed performance recipes; browse historical evidence.
AVPlumber · Mixer optimization cookbook
Keeping Vulkan out of the GPU process
Implementation links are pinned to develop at c20464a5 (2026-10-09); read against develop at 8fa15c92 on 2026-10-13 and still current. Measurements retain their original workload and scope. Watch the current 192-input L4 demo.
Current scope. The restart result below applies to its recorded browser build and flags. It is not a new qualification of every later Chromium/Electron release.
A restart that changes the browser page closes and reopens all 29 browser windows. On Electron 41 that crashed Chromium's GPU process: closing windows left a Vulkan cleanup task pending, and a surviving window's shared-texture copy flush tripped a CHECK on it. Vulkan was in that GL-only process at all because, with the GPU blocklist ignored, Chromium runs WebGPU on Vulkan through GL interop. Two Chromium switches, both on by default in the browser sender, address it: WebGPU on the OpenGL ES adapter, so no Vulkan context exists, and no GPU-process crash limit, so a crash never quits the worker; five window-recreating restarts on Electron 44 then ran with 0 crashes.
- 6 → 0GPU-process crashes across 5 restarts that recreate all 29 browser windows
- 2 → 0workers quit with “GPU process isn't usable. Goodbye.”
- 10.5–11 sper window-recreating restart with the switches, all windows painting
- 0missed program deadlines after the 5 restarts on Electron 44
AddCleanupTaskForSkiaFlush. After: no Vulkan context, so nothing is left to clean up. The last box is the second switch, a safety net the measured run never exercised: 0 crashes.How the crash was traced
The kernel's trap line gave the offset inside the Electron binary; Electron's published breakpad symbols resolved it to CHECK_EQ(fFinishedProc, &CleanupAfterSkiaFlush) in gpu::AddCleanupTaskForSkiaFlush (skia_utils.cc), reached from SkiaOutputSurfaceImplOnGpu::FlushSurface under CopyOutputRGBAInTexture, the copy behind Electron's useSharedTexture capture. The CHECK fires when a Vulkan cleanup task is pending at flush time. That left the question of why a GL-only GPU process held a Vulkan context at all: the NVIDIA Vulkan ICD was mapped into every GPU process, and the --disable-vulkan the browser sender already passed is not a Chromium switch. The answer is the WebGPU interop: with --ignore-gpu-blocklist, Chromium 144+ enables WebGPU on Vulkan through GL interop and creates a Vulkan context in the GPU process even with Vulkan compositing off.
Measured: five restarts that recreate every browser window
Each restart changed the browser page, so the mixer closed and reopened all 29 browser windows. Same 68-input 60 fps show on both sides.
| Metric | Electron 41, no switches | Electron 44, both switches |
|---|---|---|
| Restarts recreating all 29 windows | 5 | 5 |
| GPU-process crashes | 6 | 0 |
| Workers quit (“GPU process isn't usable”) | 2 | 0 |
| Show after the restarts | failed to start | all windows painting |
| Time per restart | — | 10.5–11 s |
| Missed program deadlines | — | 0 |
Two runs in sequence, not a matrix: Electron 41 (Chromium 146) without the switches, then Electron 44.5.1 (Chromium 152) with both. “—”: not recorded; that sequence ended with two workers quit and the show failing to start. Neither switch was measured alone, and Electron 44 was not measured without them. The OpenGL ES adapter is verified to leave the Vulkan context off on Chromium 152 (Electron 44.5.1); it was not tried on Electron 41. Electron 42–44 do not change the code that crashes (electron/electron#54553 reports the same crash), so the version step alone is not the fix. With 0 crashes, the crash-limit switch had nothing to do.
What changed
- WebGPU runs on the OpenGL ES adapter.
--use-webgpu-adapter=opengles. On Chromium 152 that turns the WebGPU-on-Vulkan interop and its Vulkan context off, and the NVIDIA Vulkan ICD is no longer mapped into the GPU processes. Closing windows then leaves no Vulkan cleanup task for a later flush to meet. The mixer's pages use no WebGPU. - No GPU-process crash limit.
--disable-gpu-process-crash-limit. After three GPU-process crashes, each within five minutes of the last, Chromium quits the worker with “GPU process isn't usable. Goodbye.”; on Electron 41 that took two workers and the show could not start. Now the GPU process is relaunched every time, so a crash never cascades into quitting the worker. - Each switch behind an env flag, on by default.
DMA_BROWSER_WEBGPU_OPENGLESandDMA_BROWSER_DISABLE_GPU_CRASH_LIMIT;0orfalseleaves that switch out. Unit tests assert both defaults and both off. +13 lines in the configurator, +12 in its test, +11 in the README.
At a glance
- What
Two Chromium command-line switches added by the browser sender's
HwAccelConfigurator, each behind an env flag that defaults to on:--use-webgpu-adapter=openglesand--disable-gpu-process-crash-limit. Nothing changed in the mixer's Python or in the avplumber binary. - Why
A restart that changes the browser page recreates all 29 browser windows. On Electron 41 five such restarts produced 6 GPU-process crashes; the third crash within five minutes of the last made Chromium quit the worker, two workers went, and the show failed to start. The upgrade to Electron 44 would not have fixed it on its own: Electron 42–44 do not change the code that crashes.
- Latency
0 frames added to program and to command-to-screen: the switches change what the GPU process loads at start, not the frame path; no queue, buffer or node changed. Cut latency was not re-measured. A window-recreating restart ran in 10.5–11 s with the switches; without them, on Electron 41, the five restarts ended with two workers quit and the show unable to start.
- Side effects
A page that asked for WebGPU would get the OpenGL ES adapter instead of Vulkan; the mixer's pages ask for none.
With the crash limit off, a GPU process that keeps crashing is relaunched without limit instead of taking its worker down at a third crash within five minutes of the last: a persistent GPU fault shows as repeated relaunches, not a dead worker.
- Cost
- 0 nodes, 0 queues, 0 threads.
- Memory: the NVIDIA Vulkan ICD is no longer mapped into each GPU process; the saving was not measured.
- Code: +13 lines in
HwAccelConfigurator.ts, +12 in its test, +11 in the README.
- Risk
Low. Both are Chromium's own switches. The OpenGL ES adapter is verified to leave the Vulkan context off on Chromium 152 (Electron 44.5.1); it was not tried on older Chromium. Neither switch was measured alone; the measured fix is the pair on Electron 44. The crash-limit switch was never exercised in that run (0 crashes), so what a relaunch does to the windows in that worker is not measured.
- Switch it off
DMA_BROWSER_WEBGPU_OPENGLES=0drops--use-webgpu-adapter=opengles;DMA_BROWSER_DISABLE_GPU_CRASH_LIMIT=0drops--disable-gpu-process-crash-limit. Set either in the browser service's environment and restart it; the two are independent. No mixer or avplumber change.
Where in the code
- deps/dma-browser/src/main/HwAccelConfigurator.ts:
--ignore-gpu-blocklist, the comment stating the mechanism, and both switches behind their env flags; source the--disable-vulkanthat is not a Chromium switch. - deps/dma-browser/tests/unit/HwAccelConfigurator.test.ts: both switches present by default; source both flags off, and neither switch appears.
- Docs: dma-browser README · NVIDIA GPUs: the two switches and how to turn them off.
Source links are pinned to the reviewed revision.
Measured on the T4 test host (16 vCPU) with the 68-input 60 fps show: 18 NVDEC, 29 browser sources, 17 raw NV12 files and 4 browser key pages. Before: Electron 41 (Chromium 146) on Fedora 42. After: Electron 44.5.1 (Chromium 152) on Fedora 44, the image described in Browser CPU is per painted frame.