Skip to content

gfx: scene render pipeline rework + GPU video I/O interop layer#2109

Draft
jcelerier wants to merge 21 commits into
masterfrom
clean/gpu-interop
Draft

gfx: scene render pipeline rework + GPU video I/O interop layer#2109
jcelerier wants to merge 21 commits into
masterfrom
clean/gpu-interop

Conversation

@jcelerier

Copy link
Copy Markdown
Member

Overview

This branch bundles two stacked features (merge as one), 22 commits on top of master:

1. Scene-aware GPU render pipeline (6 commits)

Reworks the gfx render graph around a flat, incrementally-rebuilt scene model:

  • OffsetAllocator-backed GPU resource arenas, a shared decoded-asset cache, scene math / pipeline-state helpers and a flat scene state + packer
  • ISF parser and nodes gain 3D samplers, uniform inputs and geometry/vertex stages; the compute and raster pipelines become scene-aware (MRT, auxiliary outputs); the render graph updates edges / render targets / passes in place instead of rebuilding wholesale
  • scene preprocessor and scene-filter / geometry-merge nodes
  • avnd, js and threedim node lifecycles adapted to the new pipeline

2. GPU video I/O interop layer (16 commits)

Adds a vendor-neutral layer for capture-card and PipeWire video I/O without a CPU round-trip:

  • high-bit-depth / planar / packed GPU video encoders and wire-format (v210, r210) + hardware decoders
  • Vulkan external-memory + texture sharing, a CUDA layer (functions / VMM allocator / capability probing), Vulkan↔CUDA semaphores and fences, host-pinned / imported / RDMA GPU-buffer rings, dma-buf / DRM-PRIME import-export, and CPU-staged / RDMA output strategies with a runtime selector
  • direct video output and DMA capture graph nodes, an external-genlock render clock, and a NVIDIA GPUDirect-for-Video bridge (dlopen'd at runtime, driver-only)
  • native PipeWire video input/output (shm + zero-copy dma-buf)
  • a few core robustness fixes (panel-delegate null tolerance, minimal-app teardown order, Vulkan-instance guard) surfaced by the harnesses

Validation

Every commit builds independently on Linux (clang/ninja; score_plugin_gfx at each commit, consumer plugins from their adaptation commit, full tree at the tip). The interop paths were hardware-validated end-to-end (AJA Kona 5 SDI/HDMI, DeckLink, Magewell, PipeWire) and are ASan/UBSan-clean.

🤖 Generated with Claude Code

jcelerier and others added 21 commits July 12, 2026 22:50
Bring in OffsetAllocator to back the slab-allocated GPU arenas.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014rZgzE8JjWvHDtaVUhxpLE
…ebuilt

The core scene-GPU rework. Adds the supporting infrastructure — OffsetAllocator-backed
GPU arenas (GpuResourceRegistry), a shared decoded-asset cache (AssetTable +
TextureLoader), scene math and pipeline-state helpers, the flat scene state and packer
(SceneGPUState), an offscreen RHI device and preview widget — then reworks the pipeline
on top of it: the ISF parser and nodes gain 3D samplers, uniform inputs and
geometry/vertex stages; the compute and raster pipelines become scene-aware with multiple
render targets and auxiliary outputs; the render graph updates edges, render targets and
passes in place instead of rebuilding wholesale; and the filter, texture-port, window,
capture and video-output paths follow the new node and renderer interfaces.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014rZgzE8JjWvHDtaVUhxpLE
ScenePreprocessorNode turns a scene spec into flat draw commands and arena uploads;
SceneFilterNode, FlattenedSceneFilterNode and MergeGeometriesNode operate on flattened
scenes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014rZgzE8JjWvHDtaVUhxpLE
Split the CPU filter/analysis and GPU node lifecycles into init / initState / release
and add the scene-port concept with its storage helpers.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014rZgzE8JjWvHDtaVUhxpLE
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014rZgzE8JjWvHDtaVUhxpLE
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014rZgzE8JjWvHDtaVUhxpLE
Request the xcb EGL integration on X11 so that dma-buf import can stay
zero-copy, and pin a desktop-GL (not GLES) core-profile context with a
stencil buffer on the desktop code path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014rZgzE8JjWvHDtaVUhxpLE
A PanelDelegateFactory may now legitimately return no widget. Don't store
a null panel, guard the plugin-load instantiation path against it, and make
the device-explorer panel lookup null-tolerant instead of dereferencing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014rZgzE8JjWvHDtaVUhxpLE
Drain the event queue before deleting the presenter: deferred slots queued
during plugin load read the presenter-owned application context, so running
them after the presenter is gone is a use-after-free. Also take the settings
models down while the QApplication is still alive, which Qt >= 6.11 requires.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014rZgzE8JjWvHDtaVUhxpLE
staticVulkanInstance() could hand back an instance whose create() had failed;
return null instead so callers fall back cleanly rather than crashing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014rZgzE8JjWvHDtaVUhxpLE
…tizer builds

Honor SCORE_SANITIZE_SKIP_CHECKS in firstTimeLibraryDownload so that ASan and
UBSan runs don't reach out to the network at startup.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014rZgzE8JjWvHDtaVUhxpLE
A small static bridge that dlopens libdvp at runtime (the driver ships it; no
CUDA toolkit install is required) and exposes its buffer/texture transfer API
to the gfx plugin.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014rZgzE8JjWvHDtaVUhxpLE
A backend-neutral pixel-format description plus conversions to and from
ffmpeg's AVPixelFormat, shared by the video encoders, decoders and the
GPU interop strategies.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014rZgzE8JjWvHDtaVUhxpLE
P010, packed high-bit-depth RGB, and planar/packed YCbCr (YUY2, yuv422p10)
GPU encoders; parameterize the packed-RGBA encoder for the RGBA, ABGR and
ARGB byte orders; and add a factory that selects the encoder for a given
wire format.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014rZgzE8JjWvHDtaVUhxpLE
Vendor-neutral primitives for moving frames between the GPU and capture cards
without a CPU round-trip:

  - Vulkan external memory and cross-API texture sharing
  - a CUDA layer (function loader, VMM allocator, capability probing)
  - Vulkan<->CUDA binary semaphores and an interop fence
  - host-pinned, imported and RDMA GPU-buffer rings (NVIDIA and AMD)
  - dma-buf / DRM-PRIME import and export helpers
  - a paced frame pump and a stage profiler
  - CPU-staged and RDMA output strategies with a runtime selector

Everything is compiled unconditionally but only activates when the matching
driver and hardware are present at runtime.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014rZgzE8JjWvHDtaVUhxpLE
v210 and r210 wire decoders, with correct padded strides at widths that are
not a multiple of six, plus a decoder factory and the DRM-PRIME, VAAPI, CUDA
and Vulkan hardware-decode paths. Video inputs can now report a dynamic
format change and carry the hardware surface's underlying software pixel
format.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014rZgzE8JjWvHDtaVUhxpLE
DirectVideoOutputNode drives a capture card's SDI/HDMI output through a shader
encode plus the selected interop strategy, and DMACaptureInputNode ingests a
card's input straight into GPU textures.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014rZgzE8JjWvHDtaVUhxpLE
Extract a RenderClock abstraction behind which the display-vsync and timer
render clocks sit, and add an opt-in external clock so the render loop can be
paced by a capture card's vertical interval. Off by default.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014rZgzE8JjWvHDtaVUhxpLE
Native PipeWire video input and output, with shared-memory and zero-copy
dma-buf transport negotiated per pixel format.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014rZgzE8JjWvHDtaVUhxpLE
…kends

Wire the high-bit-depth encoders into the Libav and GStreamer video outputs
and the dma-buf import into the window-capture, shmdata and sh4lt inputs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014rZgzE8JjWvHDtaVUhxpLE
An offscreen self-test for the GPU video encoders and a PipeWire
producer/consumer round-trip harness covering every pixel format and
transport.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014rZgzE8JjWvHDtaVUhxpLE
@jcelerier jcelerier force-pushed the clean/gpu-interop branch from dae2a5b to ef992e4 Compare July 13, 2026 02:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant