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.

Status: Implemented; historical test deployment
The crash path when all browser windows are recreated, before and after the two switches Before: a restart that changes the page closes 29 windows; a Vulkan cleanup task is left pending; a surviving window flushes its shared-texture copy; the CHECK in AddCleanupTaskForSkiaFlush trips and the GPU process crashes; a third crash within five minutes of the last makes the worker quit. Five restarts gave 6 crashes and 2 quit workers, and the show did not start. After: no Vulkan context exists, so closing windows leaves no cleanup task; the flush completes and the GPU process runs on; with the crash limit off, a crash would relaunch the GPU process instead of quitting the worker. Five restarts gave 0 crashes at 10.5 to 11 seconds each, with 0 missed deadlines. Before · WebGPU on Vulkan through GL interop: a Vulkan context in every GPU process Restart changes page29 windows closed Vulkan cleanup taskleft pending A surviving windowflushes its copy CHECK_EQ tripsGPU process crashes 3rd crash in 5 minworker quits 5 restarts: 6 GPU-process crashes, 2 workers quit, the show did not start. After · --use-webgpu-adapter=opengles and --disable-gpu-process-crash-limit Restart changes page29 windows closed No Vulkan contextno cleanup task A surviving windowflushes its copy Flush completesGPU process runs on Crash limit offa crash relaunches 5 restarts: 0 crashes, 10.5–11 s each, all windows painting, 0 missed deadlines.
Illustration of the crash path, not a measurement; the restart, crash and worker counts are measured. Before: with the GPU blocklist ignored, Chromium 144+ ran WebGPU on Vulkan through GL interop, so each GPU process held a Vulkan context although compositing ran on GL through ANGLE. Closing windows left a Vulkan cleanup task, and the next shared-texture copy flush from a window still painting met it in 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.

MetricElectron 41, no switchesElectron 44, both switches
Restarts recreating all 29 windows55
GPU-process crashes60
Workers quit (“GPU process isn't usable”)20
Show after the restartsfailed to startall 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

  1. 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.
  2. 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.
  3. Each switch behind an env flag, on by default. DMA_BROWSER_WEBGPU_OPENGLES and DMA_BROWSER_DISABLE_GPU_CRASH_LIMIT; 0 or false leaves 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

Where in the code

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.