Skip to content

Python: headless viewer, vsync control, pipelined frame capture#11

Merged
sebcrozet merged 3 commits into
dimforge:mainfrom
haixuanTao:feat/python-headless-capture
Jul 16, 2026
Merged

Python: headless viewer, vsync control, pipelined frame capture#11
sebcrozet merged 3 commits into
dimforge:mainfrom
haixuanTao:feat/python-headless-capture

Conversation

@haixuanTao

@haixuanTao haixuanTao commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Stacked on #8 (which stacks on #7) — merge order: #7#8 → this. After those merge, this PR reduces to its single commit (feat: headless viewer, vsync control, and pipelined frame capture (Python)); until then the diff below includes their changes.

New capture API in the nexus3d Python bindings:

  • NexusViewer(..., headless=True) — no OS window, no swapchain: frames render into an off-screen texture, never throttled by display vsync, and it works without a display server.
  • set_vsync(enabled) / vsync() — uncap a windowed viewer instead.
  • snap_rgb_async() / snap_rgb_flush() — pipelined capture: returns the previous frame while the current frame's GPU→CPU copy runs in the background (one frame of latency; flush collects the last frame).

Why: the windowed capture loop was vsync-locked at ~30 fps — the swapchain defaults to Fifo and the blocking per-frame snap_rgb() readback defeats frame pipelining, so each iteration ate ~2 vblanks regardless of GPU load. Headless + pipelined readback reaches 92 gen-fps at 640×480 (GPU physics; 37.5 with the Rapier CPU backend) on an RTX 5080, up from 33.

⚠️ Builds against the kiss3d headless-capture branch: dimforge/kiss3d#398.

🤖 Generated with Claude Code

@haixuanTao
haixuanTao force-pushed the feat/python-headless-capture branch from e000dc5 to 5bd7f21 Compare July 8, 2026 19:56
@haixuanTao haixuanTao changed the title Python frame capture: render export, path tracing, headless viewer, pipelined readback Python: headless viewer, vsync control, pipelined frame capture Jul 8, 2026
@haixuanTao
haixuanTao force-pushed the feat/python-headless-capture branch from 5bd7f21 to 6a3c7e1 Compare July 9, 2026 07:05
haixuanTao and others added 2 commits July 16, 2026 13:58
…thon)

The windowed capture loop was vsync-locked: kiss3d's swapchain defaults to
AutoVsync and the blocking per-frame snap_rgb() readback defeats frame
pipelining, so each render_frame+render iteration ate ~2 vblanks (~30 fps
at 60 Hz) no matter how fast the GPU was. Fixes, exposed through nexus3d:

- NexusViewer(width, height, headless=True): no OS window, no swapchain —
  frames render into an off-screen texture (kiss3d headless Window), never
  throttled by the display and usable without a display server.
- NexusViewer.set_vsync(enabled)/vsync(): uncap a windowed viewer instead.
- NexusViewer.render_async()/render_flush(): pipelined capture — returns
  the previous frame while this frame's GPU->CPU copy runs in the
  background (one frame of latency; flush collects the last frame).

Cube-drop capture at 640x480: 33.1 -> 92.1 gen-fps (GPU physics),
26.5 -> 37.5 (Rapier CPU backend).

Requires kiss3d feat/headless-capture-pipeline (new_headless_with_setup +
snap_begin/snap_finish).
@sebcrozet
sebcrozet force-pushed the feat/python-headless-capture branch from 6a3c7e1 to 2185c94 Compare July 16, 2026 12:01
@sebcrozet
sebcrozet merged commit 73edeb2 into dimforge:main Jul 16, 2026
5 checks passed
@sebcrozet

Copy link
Copy Markdown
Member

Thanks!

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.

2 participants