[GH-ISSUE #478] AMD/VAAPI: framerates above 60 fail to negotiate ("could not transform ... framerate=120/1") #289

Closed
opened 2026-10-15 12:59:23 +00:00 by bsakaguchi · 2 comments
Owner

Originally created by @sturq on GitHub (Aug 16, 2026).
Original GitHub issue: https://github.com/games-on-whales/wolf/issues/478

On an AMD RX 7900 XT (gfx1100, Mesa/VAAPI), any client request above 60fps fails to negotiate and falls back to 60. Requesting 1920x1080@120 produces:

transform could not transform video/x-raw, format=(string)RGBx, width=(int)1920, height=(int)1080, framerate=(fraction)120/1 in anything we support
warning: not negotiated

The stream still works, but always at 60fps.

Context

At startup Wolf reports it cannot use the zero-copy path on this GPU:

Unable to find any compatible DMA formats for vapostproc, disabling zero copy pipeline.
Using legacy pipeline on AMD (/dev/dri/renderD129)
Detected multiple VAAPI capable devices, using varenderD129h264enc encoder

So the failing negotiation happens in the legacy pipeline, where vapostproc has to convert RGBx to NV12 in system memory.

The compositor side does not appear to be the limit: wayland-display-core derives the mode from the client (base_info.fps()), and the GStreamer source advertises framerate_range(1/1 .. i32::MAX/1). The failure is downstream of that, at the vapostproc + capsfilter stage.

What I tried (all still fail with the same error)

  1. videoconvert ! vapostproc … in [gstreamer.video.defaults.va] video_params
  2. videorate ! videoconvert ! vapostproc … in both video_params and video_params_zero_copy — this made it worse: instead of falling back to 60fps the stream froze completely
  3. Replacing vapostproc with videoconvertscale (plus vaupload for the zero-copy variant) — negotiation still fails at 120

60fps works reliably in all of the above.

The elements themselves handle 120fps fine

Running the same conversion manually inside the Wolf container succeeds at both 60 and 120fps, including with the exact caps from config.toml:

gst-launch-1.0 videotestsrc num-buffers=20 \
  ! "video/x-raw,format=RGBx,width=1920,height=1080,framerate=120/1" \
  ! varenderD129postproc add-borders=true \
  ! "video/x-raw,chroma-site=mpeg2,width=1920,height=1080,format=NV12,colorimetry=bt709,pixel-aspect-ratio=1/1" \
  ! varenderD129h264enc ! fakesink

No errors, only the usual "VPP does not support alpha blending" / "Driver does not support trellis" warnings. So vapostproc and the VA encoder are not the limit on this GPU. Whatever caps Wolf negotiates at runtime differ from this.

Questions

  • Is >60fps expected to work on AMD/VAAPI, or is the legacy pipeline limited to 60 by design?
  • The root cause looks like the missing DMA format support that disables zero copy. Is there a known Mesa/driver version or container image where vapostproc reports usable DMA formats on RDNA3? If zero copy worked here, the RGBx conversion (and presumably the 120fps negotiation) would be avoided entirely.

Possibly related to #103 (VAAPI and AMD issues).

Environment

  • AlmaLinux 10.2, kernel 6.12.0-211.el10_2, SELinux enforcing
  • Podman 5.8.2, rootful Quadlet
  • Wolf stable (revision 7f416ec0f2); also tested feat-comprehensive-display-modes, same DMA/legacy fallback
  • AMD RX 7900 XT (gfx1100) as WOLF_RENDER_NODE=/dev/dri/renderD129; a second AMD GPU (RX 550, Polaris) is present as renderD128
  • Client: Moonlight, 1920x1080, 120fps requested
Originally created by @sturq on GitHub (Aug 16, 2026). Original GitHub issue: https://github.com/games-on-whales/wolf/issues/478 On an AMD RX 7900 XT (gfx1100, Mesa/VAAPI), any client request above 60fps fails to negotiate and falls back to 60. Requesting 1920x1080@120 produces: ``` transform could not transform video/x-raw, format=(string)RGBx, width=(int)1920, height=(int)1080, framerate=(fraction)120/1 in anything we support warning: not negotiated ``` The stream still works, but always at 60fps. ## Context At startup Wolf reports it cannot use the zero-copy path on this GPU: ``` Unable to find any compatible DMA formats for vapostproc, disabling zero copy pipeline. Using legacy pipeline on AMD (/dev/dri/renderD129) Detected multiple VAAPI capable devices, using varenderD129h264enc encoder ``` So the failing negotiation happens in the legacy pipeline, where `vapostproc` has to convert RGBx to NV12 in system memory. The compositor side does not appear to be the limit: `wayland-display-core` derives the mode from the client (`base_info.fps()`), and the GStreamer source advertises `framerate_range(1/1 .. i32::MAX/1)`. The failure is downstream of that, at the `vapostproc` + capsfilter stage. ## What I tried (all still fail with the same error) 1. `videoconvert ! vapostproc …` in `[gstreamer.video.defaults.va] video_params` 2. `videorate ! videoconvert ! vapostproc …` in both `video_params` and `video_params_zero_copy` — this made it worse: instead of falling back to 60fps the stream froze completely 3. Replacing `vapostproc` with `videoconvertscale` (plus `vaupload` for the zero-copy variant) — negotiation still fails at 120 60fps works reliably in all of the above. ## The elements themselves handle 120fps fine Running the same conversion manually inside the Wolf container succeeds at both 60 and 120fps, including with the exact caps from `config.toml`: ``` gst-launch-1.0 videotestsrc num-buffers=20 \ ! "video/x-raw,format=RGBx,width=1920,height=1080,framerate=120/1" \ ! varenderD129postproc add-borders=true \ ! "video/x-raw,chroma-site=mpeg2,width=1920,height=1080,format=NV12,colorimetry=bt709,pixel-aspect-ratio=1/1" \ ! varenderD129h264enc ! fakesink ``` No errors, only the usual "VPP does not support alpha blending" / "Driver does not support trellis" warnings. So `vapostproc` and the VA encoder are not the limit on this GPU. Whatever caps Wolf negotiates at runtime differ from this. ## Questions - Is >60fps expected to work on AMD/VAAPI, or is the legacy pipeline limited to 60 by design? - The root cause looks like the missing DMA format support that disables zero copy. Is there a known Mesa/driver version or container image where `vapostproc` reports usable DMA formats on RDNA3? If zero copy worked here, the RGBx conversion (and presumably the 120fps negotiation) would be avoided entirely. Possibly related to #103 (VAAPI and AMD issues). ## Environment - AlmaLinux 10.2, kernel 6.12.0-211.el10_2, SELinux enforcing - Podman 5.8.2, rootful Quadlet - Wolf `stable` (revision 7f416ec0f26bb4d95218af806cd1181fe5434598); also tested `feat-comprehensive-display-modes`, same DMA/legacy fallback - AMD RX 7900 XT (gfx1100) as `WOLF_RENDER_NODE=/dev/dri/renderD129`; a second AMD GPU (RX 550, Polaris) is present as renderD128 - Client: Moonlight, 1920x1080, 120fps requested
Author
Owner

@ABeltramo commented on GitHub (Aug 16, 2026):

This is most likely because you have multiple VAAPI compatible GPUs available; see if this helps: https://github.com/games-on-whales/wolf/issues/225#issuecomment-3585056921

<!-- gh-comment-id:5309820357 --> @ABeltramo commented on GitHub (Aug 16, 2026): This is most likely because you have multiple VAAPI compatible GPUs available; see if this helps: https://github.com/games-on-whales/wolf/issues/225#issuecomment-3585056921
Author
Owner

@sturq commented on GitHub (Aug 17, 2026):

That was it, thank you. Passing only the second GPU instead of the whole /dev/dri fixed it completely.

Before (whole /dev/dri mounted):

Detected multiple VAAPI capable devices, using varenderD129h264enc encoder
Unable to find any compatible DMA formats for vapostproc, disabling zero copy pipeline.
Using legacy pipeline on AMD (/dev/dri/renderD129)

After (/dev/dri/renderD129 only, /dev/input instead of all of /dev):

Using h264 encoder: va
Using h265 encoder: va
Using av1 encoder: va
Using zero copy pipeline on AMD (/dev/dri/renderD129)

With the zero copy pipeline active, 120fps negotiates fine. Verified with moonlight-embedded, same result at both rates:

60fps:   Received first video packet after 0 ms
120fps:  Received first video packet after 0 ms

No more could not transform ... framerate=(fraction)120/1 and no not negotiated. AV1 also moved from the software encoder to hardware.

So on this setup the >60fps failure was a side effect of the legacy pipeline being selected, which in turn came from exposing both GPUs. Might be worth calling this out in the docs: multi-GPU hosts should pass a single render node rather than all of /dev/dri.

For reference, the working Quadlet bits (rootful Podman, AlmaLinux 10, RX 7900 XT + RX 550):

AddDevice=/dev/dri/renderD129
AddDevice=/dev/uinput
AddDevice=/dev/uhid
PodmanArgs=--device-cgroup-rule="c 13:* rmw"
Volume=/dev/input:/dev/input:rw
Volume=/run/udev:/run/udev:rw
Environment=WOLF_RENDER_NODE=/dev/dri/renderD129
<!-- gh-comment-id:5316813572 --> @sturq commented on GitHub (Aug 17, 2026): That was it, thank you. Passing only the second GPU instead of the whole `/dev/dri` fixed it completely. Before (whole `/dev/dri` mounted): ``` Detected multiple VAAPI capable devices, using varenderD129h264enc encoder Unable to find any compatible DMA formats for vapostproc, disabling zero copy pipeline. Using legacy pipeline on AMD (/dev/dri/renderD129) ``` After (`/dev/dri/renderD129` only, `/dev/input` instead of all of `/dev`): ``` Using h264 encoder: va Using h265 encoder: va Using av1 encoder: va Using zero copy pipeline on AMD (/dev/dri/renderD129) ``` With the zero copy pipeline active, 120fps negotiates fine. Verified with moonlight-embedded, same result at both rates: ``` 60fps: Received first video packet after 0 ms 120fps: Received first video packet after 0 ms ``` No more `could not transform ... framerate=(fraction)120/1` and no `not negotiated`. AV1 also moved from the software encoder to hardware. So on this setup the >60fps failure was a side effect of the legacy pipeline being selected, which in turn came from exposing both GPUs. Might be worth calling this out in the docs: multi-GPU hosts should pass a single render node rather than all of `/dev/dri`. For reference, the working Quadlet bits (rootful Podman, AlmaLinux 10, RX 7900 XT + RX 550): ```ini AddDevice=/dev/dri/renderD129 AddDevice=/dev/uinput AddDevice=/dev/uhid PodmanArgs=--device-cgroup-rule="c 13:* rmw" Volume=/dev/input:/dev/input:rw Volume=/run/udev:/run/udev:rw Environment=WOLF_RENDER_NODE=/dev/dri/renderD129 ```
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
games-on-whales/wolf#289
No description provided.