feat: NVIDIA fix for gaming mode (kernel parameters and early modules)

Untested on hardware; .no-release-yet keeps it out of the release.
This commit is contained in:
theupriser committed 2026-10-01 10:54:27 +02:00
1 parent ca027cb607
commit ce8c3b9109
8 files changed
+130 -2

No files matched your search

+3
View File
@@ -0,0 +1,3 @@
This branch is not ready to be released: do not merge it into the release branch.
When the feature is complete and tested, ask the user whether it may be released;
on a yes, delete this file, then open the pull request into the release branch.
+5
View File
@@ -127,6 +127,11 @@ gamescope and the Plasma desktop. Primary target: the Valve Steam Machine
it. Only the
release branch's pull request into `main` is the user's: never commit
or merge to `main`, the user merges that one.
A `.no-release-yet` file at the root of a feature/bugfix branch means
it must not be merged into the release branch yet (work in progress,
untested on hardware). When the feature is complete, ask the user
whether it may be released; on a yes, delete the file, then open the
pull request and merge it.
Keep a feature/bugfix branch up to date by merging (or rebasing on)
its release branch, the release branch by merging `main` when that
moved.
+2
View File
@@ -7,6 +7,8 @@ one per merged pull request.
## 2.9.7 - 2026-10-01
- **feat: the SteamOS conversion fixes a corrupted gaming mode screen with an NVIDIA GPU: nvidia-drm.modeset=1 and fbdev=1 on the kernel command line, NVIDIA modules in the initramfs (lib/nvidia.sh)**
## 2.9.6 - 2026-09-30
- **fix(ci): a dev ISO from a release branch is built with that branch's own Steamify (input steamify_ref of the ISO workflow), not the newest published release: release/2.9.6 kept producing 2.9.5 ISOs**
+14
View File
@@ -206,6 +206,19 @@ or upgraded. A newly added kernel doesn't come with its headers, so
`ensure-kernel-headers.service` checks at every boot and installs any
missing `-headers` package, which makes DKMS build the driver for it.
## NVIDIA fix for gaming mode
gamescope drives the display itself through DRM/KMS, which with NVIDIA needs
kernel modesetting and the framebuffer driver, and the driver loaded early;
without them gaming mode can show a corrupted image. With an NVIDIA GPU and
its driver installed (`lib/nvidia.sh`), the SteamOS conversion adds
`nvidia-drm.modeset=1 nvidia-drm.fbdev=1` to the kernel command line (Limine,
systemd-boot or GRUB; the file is backed up first) and
`/etc/mkinitcpio.conf.d/90-steamify-nvidia.conf` (`MODULES+=(nvidia
nvidia_modeset nvidia_uvm nvidia_drm)`), then rebuilds the initramfs and boot
entries. Only what's missing is changed; it applies after a reboot. Turning
the conversion off removes both. Untested on hardware so far.
## HDMI-CEC
The **HDMI-CEC** item (on every PC; ticked by default only on a Steam
@@ -510,6 +523,7 @@ immediately, which can turn into a loop - see
| `lib/steam-game.sh` | Add as non-Steam game: Steamify in the Steam library (`patches/steam-shortcuts.py`) |
| `lib/update-notifier.sh` | Update notifications: the notifier from `patches/` and its user timer |
| `lib/first-login.sh` | `--defaults` without a session (the Steam Machine ISO's installer): the one-time first-login step that sets up single user's launcher on Plasma's new layout and opens the app |
| `lib/nvidia.sh` | NVIDIA fix for gaming mode: kernel parameters and early modules (part of the SteamOS conversion) |
| `lib/vram-booster.sh` | VRAM booster (`dmemcg-booster`, `plasma-foreground-booster`) |
| `services/` | The systemd units the scripts install (`service_file`, `@KEY@` placeholders); see its README |
| `patches/` | Module sources and patches the scripts build or apply (`patch_file`); see its README |
+2
View File
@@ -109,6 +109,7 @@ gaming_enable() {
esac
create_desktop_shortcut
steam_enable
nvidia_enable || return 1
os_name_enable || return 1
}
@@ -124,6 +125,7 @@ gaming_disable() {
steam_disable
krevert gaming
os_name_disable
nvidia_disable
ok "The PC boots to the normal login screen again (from the next boot)."
}
+1 -1
View File
@@ -25,7 +25,7 @@ NO_PRESELECT=(boot cec kpin hdmi)
# FEATURE_BASELINE.
FEATURE_BASELINE=2.1.0
declare -A FEATURE_VERSION=(
[gaming]=2.9.0 [boot]=2.1.0 [theme]=2.1.0 [glyphs]=2.1.0 [single]=2.1.0
[gaming]=2.9.7 [boot]=2.1.0 [theme]=2.1.0 [glyphs]=2.1.0 [single]=2.1.0
[launcher]=2.1.0 [cec]=2.7.0 [machine]=2.9.0 [poweroff]=2.2.0 [vram]=2.3.0 [notify]=2.5.0 [steamgame]=2.5.1
[kpin]=2.1.0 [hdmi]=2.1.0
)
+102
View File
@@ -0,0 +1,102 @@
#!/bin/bash
# NVIDIA fix for gaming mode, part of the SteamOS conversion
# (gaming_enable/gaming_disable). gamescope drives the display itself
# through DRM/KMS; with NVIDIA that needs kernel modesetting and the
# framebuffer driver (nvidia-drm.modeset=1 nvidia-drm.fbdev=1) and the
# driver in the initramfs, or the screen shows a corrupted image.
# Does nothing without an NVIDIA GPU that has its driver installed.
# Sourced by steamify.sh; not meant to be run on its own.
NVIDIA_PARAMS="nvidia-drm.modeset=1 nvidia-drm.fbdev=1"
NVIDIA_INITRAMFS_CONF=/etc/mkinitcpio.conf.d/90-steamify-nvidia.conf
NVIDIA_MARK="# steamify-nvidia"
nvidia_present() {
# An NVIDIA GPU (PCI vendor 0x10de, display class) and its kernel driver.
local d
for d in /sys/class/drm/card[0-9]*/device; do
[[ "$(cat "$d/vendor" 2>/dev/null)" == 0x10de ]] || continue
[[ "$(cat "$d/class" 2>/dev/null)" == 0x03* ]] && modinfo nvidia_drm >/dev/null 2>&1 && return 0
done
return 1
}
nvidia_boot_file() {
# Same boot loaders as the kernel command line elsewhere (lib/hdmi-refresh.sh).
hdmi_boot_file
}
nvidia_param_set() {
# 0 when $1 (e.g. nvidia-drm.modeset=1) is on the kernel command line or
# already in the boot loader's file (not booted yet).
local f; f="$(nvidia_boot_file)"
grep -qw -- "$1" /proc/cmdline 2>/dev/null ||
{ [[ -n "$f" ]] && grep -qw -- "$1" "$f" 2>/dev/null; }
}
nvidia_params_missing() {
local p
for p in $NVIDIA_PARAMS; do nvidia_param_set "$p" || return 0; done
return 1
}
nvidia_initramfs_ok() {
[[ -f "$NVIDIA_INITRAMFS_CONF" ]] || grep -qE '^MODULES=.*nvidia_drm' /etc/mkinitcpio.conf 2>/dev/null
}
nvidia_rebuild_boot() {
local f; f="$(nvidia_boot_file)"
info "Rebuilding the initramfs and boot entries..."
case "$f" in
/etc/default/limine) sudo limine-mkinitcpio ;;
/etc/sdboot-manage.conf) sudo /usr/bin/mkinitcpio -P && sudo sdboot-manage gen ;;
/etc/default/grub) sudo /usr/bin/mkinitcpio -P && sudo grub-mkconfig -o /boot/grub/grub.cfg ;;
*) sudo /usr/bin/mkinitcpio -P ;;
esac
}
nvidia_enable() {
nvidia_present || return 0
local f changed=0 p; f="$(nvidia_boot_file)"
if nvidia_params_missing; then
if [[ -z "$f" ]]; then
warn "NVIDIA GPU found, but no supported boot loader: add '$NVIDIA_PARAMS' to the kernel command line yourself."
else
info "NVIDIA GPU found: adding $NVIDIA_PARAMS to the kernel command line (fixes a corrupted screen in gaming mode)..."
backup_file "$f"
case "$f" in
/etc/default/limine)
printf 'KERNEL_CMDLINE[default]+=" %s" %s\n' "$NVIDIA_PARAMS" "$NVIDIA_MARK" | sudo tee -a "$f" >/dev/null ;;
/etc/sdboot-manage.conf)
sudo sed -i -E "s/^(LINUX_OPTIONS=\"[^\"]*)\"/\1 $NVIDIA_PARAMS\"/" "$f" ;;
/etc/default/grub)
sudo sed -i -E "s/^(GRUB_CMDLINE_LINUX_DEFAULT=\"[^\"]*)\"/\1 $NVIDIA_PARAMS\"/" "$f" ;;
esac
changed=1
fi
fi
if ! nvidia_initramfs_ok; then
info "Loading the NVIDIA modules early (initramfs)..."
printf 'MODULES+=(nvidia nvidia_modeset nvidia_uvm nvidia_drm)\n' |
sudo install -Dm644 /dev/stdin "$NVIDIA_INITRAMFS_CONF" && changed=1
fi
if [[ $changed == 1 ]]; then
nvidia_rebuild_boot || { err "Rebuilding the boot entries failed."; return 1; }
ok "NVIDIA gaming mode fix applied; it takes effect after a reboot."
fi
return 0
}
nvidia_disable() {
local f changed=0; f="$(nvidia_boot_file)"
if [[ -n "$f" ]] && grep -q "$NVIDIA_PARAMS" "$f" 2>/dev/null; then
case "$f" in
/etc/default/limine) sudo sed -i "/$NVIDIA_MARK\$/d" "$f" ;;
*) sudo sed -i "s/ \?$NVIDIA_PARAMS//" "$f" ;;
esac
changed=1
fi
[[ -f "$NVIDIA_INITRAMFS_CONF" ]] && { sudo rm -f "$NVIDIA_INITRAMFS_CONF"; changed=1; }
[[ $changed == 1 ]] && nvidia_rebuild_boot
return 0
}
+1 -1
View File
@@ -19,7 +19,7 @@ VERSION=2.9.7
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
for lib in common state packages login-manager single-user steam-desktop steam-machine fremont-poweroff vram-booster hdmi-refresh cec boot-session vapor-theme steamos-extras bios desktop-shortcut wizard-shortcut steam-game update-notifier first-login menu backend; do
for lib in common state packages login-manager single-user steam-desktop steam-machine fremont-poweroff vram-booster hdmi-refresh nvidia cec boot-session vapor-theme steamos-extras bios desktop-shortcut wizard-shortcut steam-game update-notifier first-login menu backend; do
# shellcheck source=/dev/null
source "$SCRIPT_DIR/lib/$lib.sh"
done