Backends/DRM: add --prefer-drm to select the scanout device independently of the Vulkan device#2220
Open
relil wants to merge 1 commit into
Open
Backends/DRM: add --prefer-drm to select the scanout device independently of the Vulkan device#2220relil wants to merge 1 commit into
relil wants to merge 1 commit into
Conversation
Decouple the DRM/KMS scanout device from the Vulkan render device. Until now init_drm() always derived the KMS node from the chosen Vulkan physical device (vulkan_primary_dev_id -> DRM_NODE_PRIMARY), so on hybrid/eGPU/muxless setups selecting a headless render GPU via --prefer-vk-device also forced scanout onto that GPU, which has no connectors -> black screen. --prefer-drm lets the user pick the KMS device explicitly while --prefer-vk-device keeps choosing the render GPU and -O selects the connector within the chosen KMS device. Accepts /dev/dri/cardX, the short cardX form, and /dev/dri/by-path/...-card symlinks (resolved via realpath). The node is validated by inspecting its device number (primary minors are 0-63; render nodes 128+) rather than open()ing it, because under seatd/logind the compositor cannot open the primary node directly. The authoritative drmIsKMS() check still runs once the session opens the fd. When the flag is not given, the value is also read from the GAMESCOPE_PREFER_DRM environment variable, so a session manager can configure a split render/scanout setup without per-game launch options. Validation runs up-front in main() (DRMBackendCheckPreferredDevice) before Vulkan/session init, so invalid input fails fast with a clear message. Default behavior is unchanged when neither the flag nor the env var is set.
relil
added a commit
to relil/gamescope-bazzite
that referenced
this pull request
Jun 16, 2026
Decouple the DRM/KMS scanout device from the Vulkan render device. init_drm() derives the KMS node from the chosen Vulkan physical device (vulkan_primary_dev_id -> DRM_NODE_PRIMARY), so on hybrid/eGPU/muxless setups selecting a headless render GPU via --prefer-vk-device also forces scanout onto that GPU, which has no connectors -> black screen. --prefer-drm picks the KMS device explicitly while --prefer-vk-device keeps choosing the render GPU and -O selects the connector within it. Accepts /dev/dri/cardX, the short cardX form, and /dev/dri/by-path/...-card symlinks. Also read from $GAMESCOPE_PREFER_DRM when the flag is absent, so a session can configure a split setup without per-game options. The node is validated by device number (primary minors 0-63) up-front in main(), not by open() (which the compositor cannot do for a primary node under seatd/logind); drmIsKMS() still runs later. Default behavior is unchanged when neither is set. Also submitted upstream: ValveSoftware#2220.
relil
added a commit
to relil/gamescope-bazzite
that referenced
this pull request
Jun 16, 2026
Decouple the DRM/KMS scanout device from the Vulkan render device. init_drm() derives the KMS node from the chosen Vulkan physical device (vulkan_primary_dev_id -> DRM_NODE_PRIMARY), so on hybrid/eGPU/muxless setups selecting a headless render GPU via --prefer-vk-device also forces scanout onto that GPU, which has no connectors -> black screen. --prefer-drm picks the KMS device explicitly while --prefer-vk-device keeps choosing the render GPU and -O selects the connector within it. Accepts /dev/dri/cardX, the short cardX form, and /dev/dri/by-path/...-card symlinks. Also read from $GAMESCOPE_PREFER_DRM when the flag is absent, so a session can configure a split setup without per-game options. The node is validated by device number (primary minors 0-63) up-front in main(), not by open() (which the compositor cannot do for a primary node under seatd/logind); drmIsKMS() still runs later. Default behavior is unchanged when neither is set. Also submitted upstream: ValveSoftware#2220.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
init_drm()derives the KMS/scanout device from the selected Vulkan physical device (vulkan_primary_dev_id()→drmGetDeviceFromDevId()→DRM_NODE_PRIMARY). So choosing the render GPU with--prefer-vk-devicealso forces scanout onto that GPU. On hybrid / eGPU / muxless / split-SoC systems where the render GPU is headless (or is a different device from the display controller), gamescope picks a node with no connectors and fails:i.e. a black screen, with no way to say "render on GPU A, scan out on display GPU B". Requested in #1004; same root cause as #2070 (ARM rockchip + panthor) and #1324.
Change
Add
--prefer-drm <device>to choose the DRM/KMS scanout device independently of--prefer-vk-device.-O/--prefer-outputstill selects the connector within the chosen device. The value is also read from theGAMESCOPE_PREFER_DRMenvironment variable when the flag is absent, so a session manager can configure a split setup without per-game launch options./dev/dri/cardX, the shortcardX, and/dev/dri/by-path/…-cardsymlinks (resolved viarealpath).main()(before Vulkan/session init, so bad input fails fast) by inspecting the device number — DRM primary minors are 0–63, render nodes 128+ — rather thanopen()ing it, because under seatd/logind the compositor cannot open the primary node directly. The existingdrmIsKMS()check still runs once the session opens the fd.Testing
x86 hybrid: Intel UHD 630 (display) + AMD BC-160 (headless render), on CachyOS and Bazzite Game Mode. gamescope composites on the BC-160 and scans out through the Intel iGPU — Steam Big Picture and Cyberpunk 2077 run, no atomic/addfb2/dmabuf errors. Without the flag, gamescope still selects the BC-160 primary node and fails with
is not a KMS device(the bug this fixes). Invalid path / render-node input fails fast with a clear message.Orthogonal to #2197 (runtime connector selection within one device); this selects the scanout device.
Closes #1004.