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

Unused GPU contexts

Implementation links are pinned to develop at c20464a5 (2026-10-09). The mixer has changed since; this page was checked against develop at 8fa15c92 on 2026-10-13. Measurements retain their original workload and scope. Watch the current 192-input L4 demo.

Current scope. Unused context removal remains in place. The custom v210 uploader was replaced by FFmpeg; it is no longer a CUDAState flag reader. Memory figures below are historical estimates, not a new VRAM measurement.

Two GPU contexts held device memory but drew nothing: an OpenGL context in every browser importer, and a CUDA context created at process start. The mixer image removes both and runs live on the test host. A code audit of the other apps that use avplumber found nothing that relied on either context.

Status: Implemented

1. The GL context in each browser importer

Each browser page has its own drm_prime_to_cuda node. The setup allows up to 40 browser pages at every frame rate (five browser workers of eight windows); the memory figures on this page were estimated for 32. Importing a page frame needs only an EGL display: eglCreateImage already takes EGL_NO_CONTEXT, and CUDA registers the EGL image directly. The node still created an OpenGL context and a 2×2 pbuffer, and made it current before every import. Nothing drew with it. Both importers, drm_prime_to_cuda and drm_prime_to_egl_image, now share one display-only setup, EglDmabufDisplay.

Before: each of 32 importers holds an EGL display, an unused OpenGL context and pbuffer, and re-binds that context per import. After: the same import chain with only the display. Before × 32 importers, one per browser page Browser page DMA-BUF eglCreateImage EGL_NO_CONTEXT cuGraphicsEGL RegisterImage CUDA frame to the compositor EGL display OpenGL 3.3 context + 2×2 pbuffer never drawn with · ~150 MB for all 32 eglMakeCurrent before every import After display only, as in drm_prime_to_egl_image Browser page DMA-BUF eglCreateImage EGL_NO_CONTEXT cuGraphicsEGL RegisterImage CUDA frame to the compositor EGL display
Teal boxes are the work every import does. The hatched red box is the context that nothing used. The ~150 MB is an estimate for all 32 importers (range 100–250 MB), not a measurement.

2. The global CUDA context

A constructor in src/cuda.cpp ran at process start and created a CUDA context on device 0. Every CUDA node runs in the context of its hwaccel device instead. The only thing other code read was the has_errors flag, which does not need a context. A later cleanup also dropped CUDAState::device, which nothing read once the context was gone: start-up now only counts devices, and CUDAState holds just has_errors.

Process start: cuInit, cuDeviceGet, then a cuCtxCreate that is now removed. Only the has_errors flag is read: by two nodes now, since the third, the legacy uploader, is removed. Nodes draw in their hwaccel device's context. Process start (init_global_cuda) cuInit cuDeviceGet(0) cuCtxCreate removed · 60–100 MB has_errors read by legacy uploader removed cuda_to_egl_image nvof_fruc hwaccel device context made by hwaccel.init; decode, import, compositors and NVENC all run here. Unchanged.
The removed step (red) only allocated. The flag (amber) is still set when the driver or device is missing, and the two nodes that still check it are unchanged; the third, the legacy uploader, has been removed. The 60–100 MB is an estimate. The diagram shows the first change; the cuDeviceGet(0) step has since gone too.

At a glance

Where in the code

Historical deployment note. Compatibility audit (2026-10-01): two downstream applications pin avplumber as a submodule, their CUDA nodes make their own hwaccel context current before any CUDA call, none reads the removed global_cuda fields, and their runtime Python runs no CUDA of its own. Whether a smoke run of both was made after they took the change is not recorded. Source links above identify the reviewed revision.