138 lines
6.6 KiB
Text
138 lines
6.6 KiB
Text
# infra/config/chromium-flags.vgl — pushed to /etc/fly/chromium-flags.vgl,
|
|
# selected by FLY_CHROMIUM_PROFILE=vgl in infra/bin/flystage-launch, which also
|
|
# wraps Chromium in `vglrun -d egl0`. This is docs/design/gpu.md section 3
|
|
# option (d), VirtualGL's EGL back end, and unlike the `gpu` profile it is
|
|
# MEASURED AND PASSING — see infra/docs/virtualgl-spike.md for the run.
|
|
#
|
|
# What it is for, in one paragraph: NVIDIA's GL/EGL *X11* paths need a real X
|
|
# server running the NVIDIA X driver, and we capture from Xvfb, so the `gpu`
|
|
# profile on its own gets no GL at all. VirtualGL 3.x's EGL back end renders on
|
|
# the card through the EGL *device* platform (no X server involved, no
|
|
# /dev/nvidia-modeset needed) and blits the result into the 2D X server, which
|
|
# may be Xvfb. x11grab, the pulse clock and the whole A/V timing are therefore
|
|
# untouched: from ffmpeg's side nothing about the capture changed.
|
|
#
|
|
# Measured on the dev container fly-spike, 2026-09-16, against the `default` profile's
|
|
# paper fly: WebGL "enabled" and GL_RENDERER
|
|
# "ANGLE (NVIDIA Corporation, Quadro RTX 4000/PCIe/SSE2, OpenGL ES 3.2 NVIDIA
|
|
# 580.76.05)", `__stage.fly()` mode webgl at 35-37 fps, rAF 59.99, and total
|
|
# Chromium CPU 1.057 core against 1.379 on the paper fly — 0.322 core cheaper,
|
|
# which is the bar gpu.md section 3 set ("at least 0.3 core BELOW").
|
|
#
|
|
# Requires, all three:
|
|
# 1. GPU=1 passthrough plus the NVIDIA userspace in the container (02-base.sh).
|
|
# /dev/nvidia-modeset is NOT required and stays unbound — measured, and it
|
|
# corrects gpu.md section 1's note that an "EGL display" needs it. The EGL
|
|
# *device* platform needs only nvidia0/nvidiactl/uvm.
|
|
# 2. VirtualGL 3.1+ installed in the container (02-base.sh, VIRTUALGL_VERSION).
|
|
# 3. Xvfb with `-extension GLX`, which xvfb.service already passes. VirtualGL
|
|
# wants exactly that: the 2D X server must NOT serve GLX, the faker answers
|
|
# the app's GLX calls itself and blits pixels with XPutImage/XShm. The
|
|
# `Xlib: extension "GLX" missing on display ":99"` lines in the journal are
|
|
# that arrangement working as designed, not a fault.
|
|
#
|
|
# Everything below the marker is identical to config/chromium-flags.gpu, which
|
|
# is in turn config/chromium-flags plus the GPU delta. The one difference from
|
|
# .gpu is --disable-gpu-sandbox, and it is not optional — see its comment.
|
|
|
|
# --- the GPU delta (gpu.md section 3) ---------------------------------------
|
|
--use-gl=angle
|
|
--use-angle=gl-egl
|
|
--use-cmd-decoder=passthrough
|
|
# ANGLE over EGL, passthrough command decoder: the EGL variant from Chromium's
|
|
# own server-side-headless docs, and the combination measured working under
|
|
# vglrun. Chromium reports back `(gl=egl-angle,angle=opengl)`, i.e. ANGLE's
|
|
# OpenGL backend on an EGL surface, which is the path VirtualGL interposes.
|
|
|
|
--disable-gpu-sandbox
|
|
# REQUIRED, and the whole reason this file exists separately from
|
|
# chromium-flags.gpu. VirtualGL's faker opens its own second X11 connection
|
|
# from inside the process it is loaded into; Chromium's GPU-process sandbox
|
|
# forbids that, and the measured failure is a crash loop, not a fallback:
|
|
# Xlib: extension "GLX" missing on display ":99".
|
|
# [VGL] ERROR: in VirtualWin-- 77: Could not clone X display connection
|
|
# ERROR:...gpu_process_host.cc:1035] GPU process exited unexpectedly: exit_code=256
|
|
# repeating about twice a second until Chromium gives up and reports
|
|
# `(gl=disabled,angle=none)`.
|
|
#
|
|
# The security cost, stated plainly rather than buried: the GPU process loses
|
|
# its namespace/layer-one sandbox while holding an ioctl handle on the host's
|
|
# NVIDIA kernel module — a module with a history of privilege-escalation CVEs —
|
|
# on a card that is shared with the GPU workload in the neighbouring container. What it does NOT lose,
|
|
# measured on the running container: NoNewPrivs stays 1 and a seccomp-bpf
|
|
# filter is still attached (Seccomp: 2), and the *renderer* sandbox, the one
|
|
# that actually contains the page and anything a viewer can influence, is
|
|
# completely untouched (two filters, unchanged from the default profile).
|
|
# That trade is acceptable on a dev box. It is a deliberate decision for a 24/7
|
|
# public stream and this file does not make it: the release envs keep
|
|
# CHROMIUM_PROFILE unset, i.e. `default`.
|
|
|
|
--ignore-gpu-blocklist
|
|
# the Quadro on a software X server is blocklisted; this is the flag that makes
|
|
# the configuration possible at all, and is also why a "success" here has to be
|
|
# confirmed against chrome://gpu rather than assumed. Confirmed over CDP
|
|
# (SystemInfo.getInfo — Page.navigate to chrome://gpu is not available in
|
|
# kiosk): webgl/2d_canvas/gpu_compositing all "enabled", rasterization
|
|
# "enabled_force", 9 driver bug workarounds active.
|
|
|
|
--enable-gpu-rasterization
|
|
--canvas-oop-rasterization
|
|
--enable-zero-copy
|
|
# raster and canvas on the GPU, out-of-process, without a CPU round trip.
|
|
# These are what actually paid for the GPU: the page renderer went from 0.913
|
|
# core to 0.629 while the GPU process stayed flat at 0.411 (0.449 before) even
|
|
# though it now does real GL plus VirtualGL's 1920x1080 readback and blit.
|
|
|
|
# --- identical to config/chromium-flags below this line ---------------------
|
|
|
|
--kiosk
|
|
--window-position=0,0
|
|
--window-size=1920,1080
|
|
# one window filling the root, no browser chrome in frame
|
|
|
|
--user-data-dir=/var/lib/fly/chrome
|
|
# writable profile outside a nologin home, survives restarts
|
|
|
|
--no-first-run
|
|
--no-default-browser-check
|
|
--disable-search-engine-choice-screen
|
|
# no first-run UI on stream
|
|
|
|
--noerrdialogs
|
|
--disable-session-crashed-bubble
|
|
--disable-infobars
|
|
--hide-scrollbars
|
|
# nothing modal can appear over the broadcast
|
|
|
|
--autoplay-policy=no-user-gesture-required
|
|
# page-played audio has no click to wait for (decision 8: page plays audio, no --mute-audio)
|
|
|
|
--disable-background-timer-throttling
|
|
# Chromium throttles background timers to ~1 Hz
|
|
|
|
--disable-backgrounding-occluded-windows
|
|
# an occluded window must not be treated as background
|
|
|
|
--disable-renderer-backgrounding
|
|
# keep renderer priority
|
|
|
|
--disable-ipc-flooding-protection
|
|
# a 30 Hz feed plus canvas draws exceeds the default 10/s/frame cap
|
|
|
|
--force-device-scale-factor=1
|
|
--force-color-profile=srgb
|
|
# deterministic pixels into the encoder
|
|
|
|
--disable-lcd-text
|
|
# subpixel antialiasing becomes colour fringing after 4:2:0 subsampling
|
|
|
|
--password-store=basic
|
|
--use-mock-keychain
|
|
# no gnome-keyring in the container
|
|
|
|
--disable-features=Translate,MediaRouter,OptimizationHints,CalculateNativeWinOcclusion
|
|
# fewer background subsystems; occlusion calculation is meaningless on Xvfb
|
|
|
|
--remote-debugging-port=9222
|
|
# loopback by default; needed for the P0 measurements and the CDP fallback
|
|
# watchdog — and for the chrome://gpu dump this profile's measurement requires
|