From e30dafc09bd4df9b27dac77c3655f4d5836915e9 Mon Sep 17 00:00:00 2001 From: Timothy DeHerrera Date: Fri, 19 Aug 2022 13:16:51 -0600 Subject: [PATCH 1/2] nixos: add module for GameScope --- nixos/modules/module-list.nix | 1 + nixos/modules/programs/gamescope.nix | 84 ++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 nixos/modules/programs/gamescope.nix diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index f1c459f75570..351da1d009a0 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -171,6 +171,7 @@ ./programs/fuse.nix ./programs/fzf.nix ./programs/gamemode.nix + ./programs/gamescope.nix ./programs/geary.nix ./programs/git.nix ./programs/gnome-disks.nix diff --git a/nixos/modules/programs/gamescope.nix b/nixos/modules/programs/gamescope.nix new file mode 100644 index 000000000000..ac2c7db0237d --- /dev/null +++ b/nixos/modules/programs/gamescope.nix @@ -0,0 +1,84 @@ +{ config +, lib +, pkgs +, ... +}: +with lib; let + cfg = config.programs.gamescope; + + gamescope = + let + wrapperArgs = + optional (cfg.args != [ ]) + ''--add-flags "${toString cfg.args}"'' + ++ builtins.attrValues (mapAttrs (var: val: "--set-default ${var} ${val}") cfg.env); + in + pkgs.runCommand "gamescope" { nativeBuildInputs = [ pkgs.makeBinaryWrapper ]; } '' + mkdir -p $out/bin + makeWrapper ${cfg.package}/bin/gamescope $out/bin/gamescope --inherit-argv0 \ + ${toString wrapperArgs} + ''; +in +{ + options.programs.gamescope = { + enable = mkEnableOption (mdDoc "gamescope"); + + package = mkOption { + type = types.package; + default = pkgs.gamescope; + defaultText = literalExpression "pkgs.gamescope"; + description = mdDoc '' + The GameScope package to use. + ''; + }; + + capSysNice = mkOption { + type = types.bool; + default = false; + description = mdDoc '' + Add cap_sys_nice capability to the GameScope binary. + ''; + }; + + args = mkOption { + type = types.listOf types.string; + default = [ ]; + example = [ "--rt" "--prefer-vk-device 8086:9bc4" ]; + description = mdDoc '' + Arguments passed to GameScope on startup. + ''; + }; + + env = mkOption { + type = types.attrsOf types.string; + default = { }; + example = literalExpression '' + # for Prime render offload on Nvidia laptops. + # Also requires `hardware.nvidia.prime.offload.enable`. + { + __NV_PRIME_RENDER_OFFLOAD = "1"; + __VK_LAYER_NV_optimus = "NVIDIA_only"; + __GLX_VENDOR_LIBRARY_NAME = "nvidia"; + } + ''; + description = mdDoc '' + Default environment variables available to the GameScope process, overridable at runtime. + ''; + }; + }; + + config = mkIf cfg.enable { + security.wrappers = mkIf cfg.capSysNice { + gamescope = { + owner = "root"; + group = "root"; + source = "${gamescope}/bin/gamescope"; + capabilities = "cap_sys_nice+pie"; + }; + }; + + environment.systemPackages = mkIf (!cfg.capSysNice) [ gamescope ]; + }; + + meta.maintainers = with maintainers; [ nrdxp ]; +} From 449fde8a09f336726f314a13e95e5951e444a2f4 Mon Sep 17 00:00:00 2001 From: Timothy DeHerrera Date: Tue, 25 Apr 2023 17:17:53 -0600 Subject: [PATCH 2/2] nixos(steam): add gamescope session option --- nixos/modules/programs/gamescope.nix | 3 +- nixos/modules/programs/steam.nix | 61 ++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/nixos/modules/programs/gamescope.nix b/nixos/modules/programs/gamescope.nix index ac2c7db0237d..c4424849a41e 100644 --- a/nixos/modules/programs/gamescope.nix +++ b/nixos/modules/programs/gamescope.nix @@ -36,7 +36,8 @@ in type = types.bool; default = false; description = mdDoc '' - Add cap_sys_nice capability to the GameScope binary. + Add cap_sys_nice capability to the GameScope + binary so that it may renice itself. ''; }; diff --git a/nixos/modules/programs/steam.nix b/nixos/modules/programs/steam.nix index fc63f0f187e8..28985b8db17c 100644 --- a/nixos/modules/programs/steam.nix +++ b/nixos/modules/programs/steam.nix @@ -4,6 +4,24 @@ with lib; let cfg = config.programs.steam; + gamescopeCfg = config.programs.gamescope; + + steam-gamescope = let + exports = builtins.attrValues (builtins.mapAttrs (n: v: "export ${n}=${v}") cfg.gamescopeSession.env); + in + pkgs.writeShellScriptBin "steam-gamescope" '' + ${builtins.concatStringsSep "\n" exports} + gamescope --steam ${toString cfg.gamescopeSession.args} -- steam -tenfoot -pipewire-dmabuf + ''; + + gamescopeSessionFile = + (pkgs.writeTextDir "share/wayland-sessions/steam.desktop" '' + [Desktop Entry] + Name=Steam + Comment=A digital distribution platform + Exec=${steam-gamescope}/bin/steam-gamescope + Type=Application + '').overrideAttrs (_: { passthru.providedSessions = [ "steam" ]; }); in { options.programs.steam = { enable = mkEnableOption (lib.mdDoc "steam"); @@ -32,6 +50,12 @@ in { then [ package ] ++ extraPackages else [ package32 ] ++ extraPackages32; in prevLibs ++ additionalLibs; + } // optionalAttrs (cfg.gamescopeSession.enable && gamescopeCfg.capSysNice) + { + buildFHSEnv = pkgs.buildFHSEnv.override { + # use the setuid wrapped bubblewrap + bubblewrap = "${config.security.wrapperDir}/.."; + }; }); description = lib.mdDoc '' The Steam package to use. Additional libraries are added from the system @@ -57,6 +81,30 @@ in { Open ports in the firewall for Source Dedicated Server. ''; }; + + gamescopeSession = mkOption { + description = mdDoc "Run a GameScope driven Steam session from your display-manager"; + type = types.submodule { + options = { + enable = mkEnableOption (mdDoc "GameScope Session"); + args = mkOption { + type = types.listOf types.string; + default = [ ]; + description = mdDoc '' + Arguments to be passed to GameScope for the session. + ''; + }; + + env = mkOption { + type = types.attrsOf types.string; + default = { }; + description = mdDoc '' + Environmental variables to be passed to GameScope for the session. + ''; + }; + }; + }; + }; }; config = mkIf cfg.enable { @@ -66,6 +114,19 @@ in { driSupport32Bit = true; }; + security.wrappers = mkIf (cfg.gamescopeSession.enable && gamescopeCfg.capSysNice) { + # needed or steam fails + bwrap = { + owner = "root"; + group = "root"; + source = "${pkgs.bubblewrap}/bin/bwrap"; + setuid = true; + }; + }; + + programs.gamescope.enable = mkDefault cfg.gamescopeSession.enable; + services.xserver.displayManager.sessionPackages = mkIf cfg.gamescopeSession.enable [ gamescopeSessionFile ]; + # optionally enable 32bit pulseaudio support if pulseaudio is enabled hardware.pulseaudio.support32Bit = config.hardware.pulseaudio.enable;