Skip to content

Fix headless RenderPlay not tracking frames for TakeSnapshot#685

Open
habibrehmansg wants to merge 4 commits intoSuRGeoNix:masterfrom
habibrehmansg:fix/headless-renderer-frame
Open

Fix headless RenderPlay not tracking frames for TakeSnapshot#685
habibrehmansg wants to merge 4 commits intoSuRGeoNix:masterfrom
habibrehmansg:fix/headless-renderer-frame

Conversation

@habibrehmansg
Copy link

In v3.10.2, RenderPlay returns early without calling Frames.SetRendererFrame when SwapChain.CanPresent is false. This breaks TakeSnapshot for headless/offscreen consumers that extract frames without a visible window.

In v3.9.7, RenderPlay always set LastFrame regardless of canRenderPresent. Restore that behavior so TakeSnapshot can access the current frame even without a SwapChain.

In v3.10.2, RenderPlay returns early without calling
Frames.SetRendererFrame when SwapChain.CanPresent is false.
This breaks TakeSnapshot for headless/offscreen consumers
that extract frames without a visible window.

In v3.9.7, RenderPlay always set LastFrame regardless of
canRenderPresent. Restore that behavior so TakeSnapshot
can access the current frame even without a SwapChain.

The SetRendererFrame call is wrapped in lockRenderLoops to
synchronize with TakeSnapshot, preventing use-after-dispose
of GPU frame resources.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@habibrehmansg habibrehmansg force-pushed the fix/headless-renderer-frame branch from 61f9ea4 to a58449d Compare March 13, 2026 14:28
@habibrehmansg
Copy link
Author

Also checking if there exists a different way to grab frames without a visible window?

When the swap chain cannot present (headless), apply VP requests immediately instead of queuing them: set vpRequestsIn, clear Resize, and call D3ProcessRequests() or FLProcessRequests() depending on the VideoProcessor. Also move VP request processing into the lockRenderLoops section of Present so queued requests are handled under the same lock before calling Frames.SetRendererFrame(frame), preserving synchronization with TakeSnapshot and matching prior behavior.
Clear the VPRequestType.Resize flag before processing video-processor requests and add a lock around headless (CanPresent == false) VP request processing. This prevents resize requests from being handled in these paths and serializes access to vpRequestsIn to avoid race conditions when processing D3D11 or FL video processor requests.
@SuRGeoNix
Copy link
Owner

I will need to revisit this as I don't feel confident for the approach. My understanding is that for example when the window is minimized you still want to be able to take the snapshot of the latest/current frame. That will be disabled by Resize (in SwapChain.cs) with this:

CanPresent = controlWidth > 0 && controlHeight > 0;

Your current solution creates a performance issue when you don't care for snapshots and your window is minimized.

@habibrehmansg
Copy link
Author

Ok. If it helps, the use case that led me here was headless playback and grabbing frames for USB panel displays.

@habibrehmansg
Copy link
Author

Would having a config like player.Config.Video.SnapshotAlways (default false) help alleviate your concern?

SuRGeoNix added a commit that referenced this pull request Mar 18, 2026
- Config.Player: Introduces SnapshotAlways to allow off-screen snapshots

- Renderer: Adds support for off-screen snapshots
@SuRGeoNix
Copy link
Owner

@habibrehmansg can you check my commit and let me know if that satisfies your requirement?

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