Skip to content

fix: stabilize explicit-sync and NVDEC lifecycles - #13

Merged
programmersd21 merged 5 commits into
programmersd21:mainfrom
Luquatic:fix/ffmpeg9-explicit-sync
Aug 9, 2026
Merged

fix: stabilize explicit-sync and NVDEC lifecycles#13
programmersd21 merged 5 commits into
programmersd21:mainfrom
Luquatic:fix/ffmpeg9-explicit-sync

Conversation

@Luquatic

@Luquatic Luquatic commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Summary

  • update ffmpeg-next to 9.0 and correctly transfer NVDEC hardware frames
  • avoid bufferless layer commits under explicit sync
  • defer startup and hotplug restoration until layer configure, with cancellation-safe output lifecycle handling
  • map native-resolution buffers to logical layer sizes through wp_viewporter
  • retain future video frames until their PTS is due instead of discarding them
  • stop active rendering and video playback before daemon exit or output teardown

Root causes

SCTK already acknowledges layer-shell configure events. Wallr's extra layer.commit() raced wgpu-owned presentation and produced a bufferless explicit-sync commit, which NVIDIA rejected with wp_linux_drm_syncobj_surface_v1: Missing buffer.

Cached startup and hotplug restoration could attach a buffer before configure or race output removal. Restoration is now configure-gated and lifecycle-cancelled.

Fractionally scaled outputs combined physical mode dimensions with Wayland's integer buffer scale. Native buffers now remain at scale 1 and are mapped to the compositor-provided logical size through wp_viewporter.

The playback scheduler discarded decoded frames whose PTS was slightly in the future. NVDEC could therefore advance while the displayed frame remained frozen. Wallr now retains the first future frame and presents it when due.

Verification

  • cargo fmt --all --check
  • cargo check --workspace
  • cargo clippy --workspace --all-targets -- -D warnings
  • cargo test --workspace (46 passed)
  • cargo build --release --bin wallr
  • static images, GIF playback, IPC pause/resume/seek/info/blank/restore
  • cached three-output startup with 3840x2160 H.264 at 60 FPS using NVDEC
  • Wayland trace: DP-1 uses set_buffer_scale(1) and wp_viewport.set_destination(3072, 1728)
  • scale-2 virtual output renders edge-to-edge without black bars
  • captures across normal playback and the 19.95-second loop boundary contain changing wallpaper pixels
  • configured hotplug removal and immediate pre-configure removal leave no stale IPC state
  • IPC stop during NVDEC playback exits with systemd status 0 and no core dump

Fixes #12

@sourcery-ai

sourcery-ai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Reviewer's Guide

This PR stabilizes explicit sync and NVDEC lifecycles by updating ffmpeg-next, correctly handling hardware frame detection and transfer, deferring cached/hotplug wallpaper restoration until layer surfaces are configured, avoiding premature/bufferless layer commits, and ensuring active video playback is stopped cleanly on daemon exit via IPC Stop.

Sequence diagram for deferred wallpaper restoration on layer configure

sequenceDiagram
    participant OutputHandler
    participant WaylandState
    participant LayerShellHandler
    participant WallpaperRestorer
    participant RenderState

    OutputHandler->>WaylandState: create_render_state_for_output_sync
    OutputHandler->>WaylandState: pending_restores.insert

    LayerShellHandler->>WaylandState: configure
    WaylandState->>WallpaperRestorer: tokio::spawn
    WallpaperRestorer->>RenderState: restore_cached_wallpaper
Loading

Sequence diagram for IPC Stop handling and video playback shutdown

sequenceDiagram
    actor IpcClient
    participant Daemon
    participant RenderState
    participant VideoPlayback
    participant Systemd

    IpcClient->>Daemon: IpcCommand::Stop
    Daemon->>RenderState: playback_gen.fetch_add
    Daemon->>RenderState: pacer.notify
    Daemon->>VideoPlayback: video_playback.stop
    Daemon->>Systemd: exit after delay
Loading

File-Level Changes

Change Details Files
Defer cached and hotplug wallpaper restoration until the compositor has configured each layer surface, avoiding bufferless commits and races with wgpu-owned buffers.
  • Add pending_restores map to WaylandState to queue per-output wallpaper restoration until configure callbacks fire.
  • Move hotplug render state insertion and wallpaper restoration into LayerShellHandler::configure using an async task and shared render_states map.
  • Queue initial startup render_states in pending_restores instead of restoring immediately in Daemon::run, relying on later configure events.
  • Extract wallpaper restoration logic into restore_cached_wallpaper helper and reuse it for both startup and hotplug cases.
wallr-core/src/daemon/mod.rs
Eliminate extra/bufferless layer commits and correct layer surface initialization ordering to cooperate with explicit sync.
  • Remove unconditional layer.commit() from LayerShellHandler::configure because SCTK already acknowledges configure and wgpu manages buffer commits.
  • Adjust layer surface setup to set input region and buffer scale before committing, and only destroy the empty region after commit in both async and sync render-state creation paths.
wallr-core/src/daemon/mod.rs
Ensure NVDEC hardware frames are detected via hw_frames_ctx and reusable software frames are unreffed before transfers to avoid stale data and lifecycle issues.
  • Change hardware frame detection to check AVFrame.hw_frames_ctx instead of data[0] pointer.
  • Call av_frame_unref on the reusable software frame before av_hwframe_transfer_data to reset its state for each transfer.
wallr-core/src/video/decoder.rs
Stop active video playback cleanly when handling IPC Stop, preventing playback from continuing across daemon shutdown and avoiding core dumps.
  • On IpcCommand::Stop, iterate over all render_states, bump playback_gen to invalidate current playback loops, notify pacer, and call video_playback.stop() before scheduling daemon shutdown.
wallr-core/src/daemon/mod.rs
Update ffmpeg-next dependency to the latest major version compatible with the new hardware frames handling.
  • Bump ffmpeg-next crate from version 8.1 to 9.0 with unchanged feature set for codec, format, software-resampling, and software-scaling.
Cargo.toml

Assessment against linked issues

Issue Objective Addressed Explanation
#12 Prevent the Wayland explicit-sync protocol error (wp_linux_drm_syncobj_surface_v1: Missing buffer) on first presentation so the daemon no longer loses its Wayland connection and exits when setting a wallpaper.
#12 Stabilize NVDEC hardware decoding and teardown so video playback and daemon exit no longer cause crashes or core dumps on NVIDIA/Vulkan.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've reviewed your changes and they look great!


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The daemon now waits for layer-surface configuration before registering render state and restoring cached wallpapers. It sets buffer scale before commits, improves playback shutdown, and updates FFmpeg dependency and hardware-frame handling.

Changes

Wallpaper playback lifecycle

Layer / File(s) Summary
Configure-time surface registration and restoration
wallr-core/src/daemon/mod.rs
Pending output restorations are registered when the layer surface configures. Cached wallpaper restoration uses a shared helper.
Surface commit and playback shutdown ordering
wallr-core/src/daemon/mod.rs
Both render-state creation paths set buffer scale before committing. Stop handling invalidates playback generations, wakes pacers, and stops decoders.
FFmpeg 9 hardware-frame compatibility
Cargo.toml, wallr-core/src/video/decoder.rs
The ffmpeg-next requirement changes to 9.0. Hardware-frame detection uses hw_frames_ctx, and the reusable software frame is cleared before transfer.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant DaemonStartup
  participant LayerSurface
  participant ConfigureHandler
  participant RenderStateMap
  participant WallpaperCache
  DaemonStartup->>LayerSurface: create and queue render state
  LayerSurface->>ConfigureHandler: send configure event
  ConfigureHandler->>RenderStateMap: register render state
  ConfigureHandler->>WallpaperCache: restore cached wallpaper
Loading

Suggested reviewers: programmersd21

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes address issue #12 by fixing configured-surface presentation, FFmpeg 9 support, NVDEC frame transfer, and decoder teardown.
Out of Scope Changes check ✅ Passed All changes are related to issue #12 and the stated objectives for explicit-sync presentation and NVDEC lifecycle stability.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the primary changes to explicit-sync and NVDEC lifecycle handling.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@wallr-core/src/daemon/mod.rs`:
- Around line 214-220: The per-output task around render state insertion and
restore_cached_wallpaper must serialize configuration with restoration and
removal. Add a per-output lifecycle generation or cancellation token, invalidate
it in output_destroyed, validate it before restoring and publishing, and move
the render_states insertion until after restoration completes so stale tasks
cannot reinsert destroyed outputs or overwrite newer IPC updates.
- Around line 1274-1276: Remove the initial render-state insertion into the
shared map immediately before the pending_restores insertion. Keep the state
only in wayland_state.pending_restores until the layer-surface configure path
registers it, preserving deferred registration and preventing IPC from targeting
unconfigured surfaces.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: bd6e1bb4-fa44-4e6d-b4dc-bf795868d769

📥 Commits

Reviewing files that changed from the base of the PR and between 391aa64 and 463d852.

📒 Files selected for processing (3)
  • Cargo.toml
  • wallr-core/src/daemon/mod.rs
  • wallr-core/src/video/decoder.rs

Comment thread wallr-core/src/daemon/mod.rs Outdated
Comment thread wallr-core/src/daemon/mod.rs Outdated
@programmersd21
programmersd21 merged commit 4eaa1bb into programmersd21:main Aug 9, 2026
2 checks passed
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.

Daemon loses Wayland connection on first present: wp_linux_drm_syncobj_surface_v1 "Missing buffer"

2 participants