Refactor gaming config to use play flake

• Updates flake to use unstable nixpkgs for gaming packages
• Replaces custom gamescope setup with play flake integration
• Adds wrappers for Steam, Heroic, and Lutris desktop entries
• Simplifies host gaming configuration by delegating to play
• Remove proton-cachyos, handled by play now
This commit is contained in:
Chris Toph 2025-06-30 02:41:13 -04:00
parent 93dc3db7a5
commit 531897e287
6 changed files with 83 additions and 366 deletions

View file

@ -34,15 +34,20 @@
stylix.url = "github:danth/stylix";
## Misc Packages ##
## Gaming Packages ##
nix-gaming = {
url = "github:fufexan/nix-gaming";
inputs = {
nixpkgs.follows = "nixpkgs";
inputs.nixpkgs.follows = "nixpkgs-unstable";
};
play = {
url = "github:tophc7/play.nix";
inputs.nixpkgs.follows = "nixpkgs-unstable";
};
## Misc Packages ##
# nixcord.url = "github:kaylorben/nixcord";
# spicetify-nix = {
# url = "github:Gerg-L/spicetify-nix";
@ -57,7 +62,7 @@
snapraid-aio = {
# url = "git+https://git.ryot.foo/toph/snapraid-aio.nix.git";
url = "git+https://git.ryot.foo/toph/snapraid-aio.nix.git";
inputs.nixpkgs.follows = "nixpkgs";
inputs.nixpkgs.follows = "nixpkgs-unstable";
};
vscode-server = {
@ -67,7 +72,7 @@
yay = {
url = "git+https://git.ryot.foo/toph/yay.nix.git";
inputs.nixpkgs.follows = "nixpkgs";
inputs.nixpkgs.follows = "nixpkgs-unstable";
};
zen-browser = {

View file

@ -1,170 +1,69 @@
## NOTE:
## This is only configured for AMD GPUs; Nvidia might require additional configuration.
## For example host (PC) configuration using this module go to home/hosts/rune
{
config,
lib,
osConfig,
lib,
pkgs,
inputs,
...
}:
let
primaryMonitor = lib.custom.getPrimaryMonitor (config.monitors or [ ]);
WIDTH = primaryMonitor.width or 1980;
HEIGHT = primaryMonitor.height or 1080;
REFRESH_RATE = primaryMonitor.refreshRate or 60;
VRR = primaryMonitor.vrr or false;
HDR = primaryMonitor.hdr or false;
cursorTheme = config.home.pointerCursor.name or "Adwaita";
cursorPackage = config.home.pointerCursor.package or pkgs.gnome.adwaita-icon-theme;
# INFO: Example working commands for running games in steam-session
## Rivals ##
# SteamDeck=1 LD_PRELOAD="" PROTON_ENABLE_NVAPI=1 PROTON_ENABLE_WAYLAND=1 VKD3D_DISABLE_EXTENSIONS=VK_KHR_present_wait gamemoderun %command% -PSOCompileMode=1 -dx12
## Stats Overlay ##
# gamemoderun mangohud %command%
gamescope-env = ''
set -x DXVK_HDR 1
set -x ENABLE_GAMESCOPE_WSI 1
set -x ENABLE_HDR_WSI 1
set -x AMD_VULKAN_ICD RADV
set -x RADV_PERFTEST aco
set -x SDL_VIDEODRIVER wayland
set -x XCURSOR_THEME '${cursorTheme}'
set -x XCURSOR_PATH '${cursorPackage}/share/icons'
# Wayland specific environment variables
# set -x PROTON_USE_SDL 1
set -x PROTON_USE_WAYLAND 1
set -x PROTON_ENABLE_HDR 1
# Gamescope display identifier
set -x GAMESCOPE_WAYLAND_DISPLAY "gamescope-0"
# Steam specific environment variables
set -x STEAM_FORCE_DESKTOPUI_SCALING 1
set -x STEAM_GAMEPADUI 1
set -x STEAM_GAMESCOPE_CLIENT 1
# Lutris specific environment variables
set -x LUTRIS_SKIP_INIT 1
set -x DISABLE_LAYER_AMD_SWITCHABLE_GRAPHICS_1 1
set -x DISABLE_LAYER_NV_OPTIMUS_1 1
'';
# Base gamescope options
gamescope-base-opts =
[
"--fade-out-duration"
"200"
"-w"
"${toString WIDTH}"
"-h"
"${toString HEIGHT}"
"-r"
"${toString REFRESH_RATE}"
"-f"
"--backend"
"sdl"
"--rt"
"--immediate-flips"
]
++ lib.optionals HDR [
"--hdr-enabled"
"--hdr-debug-force-output"
"--hdr-itm-enable"
]
++ lib.optionals VRR [
"--adaptive-sync"
];
# Run gamescope with a set working environment
gamescope-run = pkgs.writeScriptBin "gamescope-run" ''
#!${lib.getExe pkgs.fish}
# Check if we're already inside a Gamescope session
if set -q GAMESCOPE_WAYLAND_DISPLAY
echo "Already inside Gamescope session ($GAMESCOPE_WAYLAND_DISPLAY), running command directly..."
# Skip gamescope and run the command directly
exec $argv
end
# Session Environment
${gamescope-env}
# Define and parse arguments using fish's built-in argparse
argparse -i 'x/extra-args=' -- $argv
if test $status -ne 0
exit 1
end
# The remaining arguments ($argv) are the command to be run
if test (count $argv) -eq 0
echo "Usage: gamescope-run [-x|--extra-args \"<options>\"] <command> [args...]"
echo ""
echo "Examples:"
echo " gamescope-run heroic"
echo " gamescope-run -x \"--fsr-upscaling-sharpness 5\" steam"
echo " GAMESCOPE_EXTRA_OPTS=\"--fsr\" gamescope-run steam (legacy)"
exit 1
end
# Combine base args, extra args from CLI, and extra args from env (for legacy)
set -l final_args ${lib.escapeShellArgs gamescope-base-opts}
# Add args from -x/--extra-args flag, splitting the string into a list
if set -q _flag_extra_args
set -a final_args (string split ' ' -- $_flag_extra_args)
end
# For legacy support, add args from GAMESCOPE_EXTRA_OPTS if it exists
if set -q GAMESCOPE_EXTRA_OPTS
set -a final_args (string split ' ' -- $GAMESCOPE_EXTRA_OPTS)
end
# Show the command being executed
echo -e "\033[1;36m[gamescope-run]\033[0m Running: \033[1;34m${lib.getExe pkgs.gamescope_git}\033[0m $final_args \033[1;32m--\033[0m $argv"
# Execute gamescope with the final arguments and the command
exec ${lib.getExe pkgs.gamescope_git} $final_args -- $argv
'';
## Effectively forces gamescope-run to be the default way to use Steam
## Why? Because , .desktops created by Steam would not run under gamescope-run otherwise
## !!! do not use 'pkgs.steam', it will not be configured correctly
steam-wrapper = pkgs.writeScriptBin "steam" ''
#!${lib.getExe pkgs.fish}
# This script wraps the original steam command to launch it
# with gamescope-run in a big picture mode.
# All arguments passed to this script are forwarded.
exec ${lib.getExe gamescope-run} -x "-e" ${lib.getExe osConfig.programs.steam.package} -tenfoot $argv
'';
## Ensures that all Lutris game launches go through Gamescope
## !!! This breaks the Lutris GUI, so use the overridden .desktop entry for opening Lutris itself
lutris-wrapper = pkgs.writeScriptBin "lutris" ''
#!${lib.getExe pkgs.fish}
# This script wraps the original lutris command to launch it
# with gamescope-run. All arguments passed to this script are forwarded.
exec ${lib.getExe gamescope-run} -x "--force-windows-fullscreen" ${lib.getExe pkgs.lutris} $argv
'';
in
{
home.packages = with pkgs; [
steam-run
steam-wrapper
gamescope-run
lutris-wrapper
imports = [
inputs.play.homeManagerModules.play
];
play = {
monitors = config.monitors; # I use the same module as in play.nix
gamescoperun = {
enable = true;
useGit = true;
# Extra environment variables
environment = {
XCURSOR_THEME = config.home.pointerCursor.name or "Adwaita";
XCURSOR_PATH = "${config.home.pointerCursor.package or pkgs.adwaita-icon-theme}/share/icons";
};
};
wrappers = {
steam = {
enable = true;
package = osConfig.programs.steam.package;
extraOptions = {
"steam" = true; # equivalent to --steam flag
};
environment = {
STEAM_FORCE_DESKTOPUI_SCALING = 1;
STEAM_GAMEPADUI = 1;
};
};
heroic = {
enable = true;
package = pkgs.heroic; # No special package configured by play.nix
extraOptions = {
"force-windows-fullscreen" = true;
};
};
lutris = {
enable = true;
package = osConfig.play.lutris.package;
extraOptions = {
"force-windows-fullscreen" = true;
};
environment = {
LUTRIS_SKIP_INIT = 1;
};
};
};
};
# Override default desktop entries to use gamescope wrappers
xdg.desktopEntries = {
steam = {
name = "Steam";
comment = "Steam Big Picture in Gamescope Session";
exec = "${lib.getExe steam-wrapper}";
exec = "${lib.getExe config.play.wrappers.steam.wrappedPackage} -bigpicture -tenfoot";
icon = "steam";
type = "Application";
terminal = false;
@ -183,7 +82,7 @@ in
actions = {
bigpicture = {
name = "Steam Client (No Gamescope)";
exec = "${lib.getExe pkgs.steam}";
exec = "${lib.getExe (config.play.steam.package or pkgs.steam)}";
};
};
};
@ -191,7 +90,7 @@ in
"com.heroicgameslauncher.hgl" = {
name = "Heroic Games Launcher";
comment = "Heroic in Gamescope Session";
exec = ''${lib.getExe gamescope-run} -x "--force-windows-fullscreen" ${lib.getExe pkgs.heroic}'';
exec = "${lib.getExe config.play.wrappers.heroic.wrappedPackage}";
icon = "com.heroicgameslauncher.hgl";
type = "Application";
terminal = false;
@ -207,7 +106,7 @@ in
"net.lutris.Lutris" = {
name = "Lutris";
comment = "Video Game Preservation Platform";
exec = "${lib.getExe pkgs.lutris} %U";
exec = "${lib.getExe (config.play.lutris.package or pkgs.lutris)} %U";
icon = "net.lutris.Lutris";
type = "Application";
terminal = false;
@ -222,12 +121,14 @@ in
actions = {
broken = {
name = "Lutris (Gamescope BROKEN)";
exec = ''${lib.getExe gamescope-run} -x "--force-windows-fullscreen" ${lib.getExe pkgs.lutris}'';
exec = "${lib.getExe config.play.wrappers.lutris.wrappedPackage}";
};
broken-exposed = {
name = "Lutris (Gamescope BROKEN; Exposed Wayland)";
exec = ''${lib.getExe gamescope-run} -x "--force-windows-fullscreen --expose-wayland" ${lib.getExe pkgs.lutris}'';
exec = ''${lib.getExe config.play.gamescoperun.package} -x "--force-windows-fullscreen --expose-wayland" ${
lib.getExe (config.play.lutris.package or pkgs.lutris)
}'';
};
};
};

View file

@ -1,6 +1,3 @@
## NOTE:
## This is only configured for AMD GPUs; Nvidia might require additional configuration.
## For example host (PC) configuration using this module go to hosts/x86/rune
{
pkgs,
lib,
@ -9,106 +6,27 @@
...
}:
{
hardware.graphics = {
enable = true;
enable32Bit = true;
};
environment.systemPackages = with pkgs; [
lact # AMDgpu tool
heroic
gamescope_git
gamescope-wsi_git
(pkgs.lutris.override {
extraPkgs = pkgs: [
pkgs.wineWowPackages.waylandFull
pkgs.winetricks
vulkan-tools
xterm
];
})
imports = [
inputs.play.nixosModules.play
];
systemd = {
packages = with pkgs; [ lact ];
services.lactd.wantedBy = [ "multi-user.target" ];
};
play = {
amd.enable = true;
ananicy.enable = true;
gamemode.enable = true;
# Instead of set -x CAP_SYS_NICE eip
services.ananicy = {
enable = true;
package = pkgs.ananicy-cpp;
rulesProvider = pkgs.ananicy-cpp;
extraRules = [
{
"name" = "gamescope";
"nice" = -20;
}
];
};
programs = {
steam = {
enable = true;
remotePlay.openFirewall = true;
dedicatedServer.openFirewall = true;
protontricks = {
enable = true;
package = pkgs.protontricks;
};
package = pkgs.steam.override {
extraPkgs =
pkgs:
(builtins.attrValues {
inherit (pkgs.xorg)
libXcursor
libXi
libXinerama
libXScrnSaver
;
inherit (pkgs.stdenv.cc.cc)
lib
;
inherit (pkgs)
gamemode
gperftools
keyutils
libkrb5
libpng
libpulseaudio
libvorbis
mangohud
;
});
};
extraCompatPackages = with pkgs; [
proton-ge-bin
proton-ge-custom
proton-cachyos
];
};
gamemode = {
enable = true;
settings = {
general = {
softrealtime = "auto";
inhibit_screensaver = 1;
renice = 15;
};
gpu = {
apply_gpu_optimisations = "accept-responsibility";
gpu_device = 1; # The DRM device number on the system (usually 0), ie. the number in /sys/class/drm/card0/
amd_performance_level = "high";
};
custom = {
start = "${pkgs.libnotify}/bin/notify-send 'GameMode started'";
end = "${pkgs.libnotify}/bin/notify-send 'GameMode ended'";
};
};
};
lutris.enable = true;
};
# Additional packages not covered by play.nix
environment.systemPackages = with pkgs; [
heroic
];
}

View file

@ -1,47 +0,0 @@
{
callPackage,
stdenv,
lib,
fetchurl,
}:
let
protonGeTitle = "Proton-CachyOS";
protonGeVersions = lib.importJSON ./versions.json;
in
stdenv.mkDerivation {
name = "proton-cachyos";
version = "${protonGeVersions.base}.${protonGeVersions.release}";
src =
let
tagName = "cachyos-${protonGeVersions.base}-${protonGeVersions.release}-slr";
fileName = "proton-cachyos-${protonGeVersions.base}-${protonGeVersions.release}-slr-x86_64.tar.xz";
in
fetchurl {
url = "https://github.com/CachyOS/proton-cachyos/releases/download/${tagName}/${fileName}";
inherit (protonGeVersions) hash;
};
buildCommand =
''
mkdir -p $out/bin
tar -C $out/bin --strip=1 -x -f $src
''
# Replace the internal name and display name
+ lib.strings.optionalString (protonGeTitle != null) ''
sed -i -r 's|"proton-cachyos-[^"]*"|"${protonGeTitle}"|g' $out/bin/compatibilitytool.vdf
sed -i -r 's|"display_name"[[:space:]]*"[^"]*"|"display_name" "${protonGeTitle}"|' $out/bin/compatibilitytool.vdf
'';
passthru.updateScript = callPackage ./update.nix { };
meta = with lib; {
description = "Compatibility tool for Steam Play based on Wine and additional components. CachyOS fork.";
homepage = "https://github.com/CachyOS/proton-cachyos";
license = licenses.bsd3;
platforms = [ "x86_64-linux" ];
maintainers = with maintainers; [
tophc7
];
};
}

View file

@ -1,55 +0,0 @@
{
writeShellScript,
lib,
coreutils,
findutils,
gnugrep,
curl,
jq,
git,
nix,
nix-prefetch-git,
moreutils,
yq,
}:
let
path = lib.makeBinPath [
coreutils
curl
findutils
gnugrep
jq
moreutils
git
nix-prefetch-git
nix
yq
];
in
writeShellScript "update-proton-cachyos" ''
set -euo pipefail
PATH=${path}
srcJson=pkgs/proton-cachyos/versions.json
localBase=$(jq -r .base < $srcJson)
localRelease=$(jq -r .release < $srcJson)
latestVer=$(curl 'https://github.com/GloriousEggroll/proton-cachyos/tags.atom' | xq -r '.feed.entry[0].link."@href"' | grep -Po '(?<=/)[^/]+$')
if [ "GE-Proton''${localBase}-''${localRelease}" == "$latestVer" ]; then
exit 0
fi
latestBase=$(echo $latestVer | grep -Po '(?<=GE-Proton)[^-]+')
latestRelease=$(echo $latestVer | grep -Po '(?<=-)[^-]+$')
latestSha256=$(nix-prefetch-url --type sha256 "https://github.com/CachyOS/proton-cachyos/releases/download/''${latestVer}/''${latestVer}.tar.gz")
latestHash=$(nix-hash --to-sri --type sha256 $latestSha256)
jq \
--arg latestBase "$latestBase" --arg latestRelease "$latestRelease" --arg latestHash "$latestHash" \
'.base = $latestBase | .release = $latestRelease | .hash = $latestHash' \
"$srcJson" | sponge "$srcJson"
git add $srcJson
git commit -m "proton-cachyos: ''${localBase}.''${localRelease} -> ''${latestBase}.''${latestRelease}"
''

View file

@ -1,5 +0,0 @@
{
"base": "10.0",
"release": "20250623",
"hash": "sha256-HLWWR2h+AdGfqt3Aay9Xyz7Q06NRoi3/Mp5vJtoqLlg="
}