Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

POC: vulkan-gaming with HDR using latest gamescope and linux-hdr #215343

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions nixos/modules/module-list.nix
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@
./programs/fuse.nix
./programs/fzf.nix
./programs/gamemode.nix
./programs/gamescope.nix
./programs/geary.nix
./programs/git.nix
./programs/gnome-disks.nix
Expand Down
93 changes: 93 additions & 0 deletions nixos/modules/programs/gamescope.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
{ config
, lib
, pkgs
, ...
}:
with lib; let
cfg = config.programs.gamescope;

# wrapper that adds the default env, the default args.
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}
'';

# package with only the vulkan implicit layer
gamescope-vulkan-layers =
pkgs.runCommand "gamescope-vulkan-layers" { } ''
mkdir -p $out
ln -s ${cfg.package}/share $out/share
'';
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 = [ gamescope-vulkan-layers ]
++ lib.lists.optional (!cfg.capSysNice) gamescope;
};

meta.maintainers = with maintainers; [ nrdxp ];
}
88 changes: 80 additions & 8 deletions nixos/modules/programs/steam.nix
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,43 @@ with lib;

let
cfg = config.programs.steam;
in {
gamescopeCfg = config.programs.gamescope;

steam = pkgs.steam.override ({
extraLibraries = pkgs: with config.hardware.opengl;
if pkgs.stdenv.hostPlatform.is64bit
then [ package ] ++ extraPackages
else [ package32 ] ++ extraPackages32;
} // optionalAttrs
(cfg.gamescopeSession.enable && gamescopeCfg.capSysNice)
{
buildFHSUserEnv = pkgs.buildFHSUserEnvBubblewrap.override {
# use the setuid wrapped bubblewrap
bubblewrap = "/run/wrappers";
};
}
);

gamescopeSessionStarter =
pkgs.writeShellScriptBin "steam-gamescope" ''
${let
exports = builtins.attrValues (builtins.mapAttrs (n: v: "export ${n}=${v}") cfg.gamescopeSession.env);
in
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=${gamescopeSessionStarter}/bin/steam-gamescope
Type=Application
'').overrideAttrs (_: { passthru.providedSessions = [ "steam" ]; });
in
{
options.programs.steam = {
enable = mkEnableOption (lib.mdDoc "steam");
enable = mkEnableOption (mdDoc "steam");

package = mkOption {
type = types.package;
Expand Down Expand Up @@ -45,27 +79,65 @@ in {
remotePlay.openFirewall = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc ''
description = mdDoc ''
Open ports in the firewall for Steam Remote Play.
'';
};

dedicatedServer.openFirewall = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc ''
description = mdDoc ''
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 {
hardware.opengl = { # this fixes the "glXChooseVisual failed" bug, context: https://github.com/NixOS/nixpkgs/issues/47932
hardware.opengl = {
# this fixes the "glXChooseVisual failed" bug, context: https://github.com/NixOS/nixpkgs/issues/47932
enable = true;
driSupport = true;
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;

Expand All @@ -74,12 +146,12 @@ in {
environment.systemPackages = [
cfg.package
cfg.package.run
];
] ++ lib.optional cfg.gamescopeSession.enable gamescopeSessionStarter;

networking.firewall = lib.mkMerge [
networking.firewall = mkMerge [
(mkIf cfg.remotePlay.openFirewall {
allowedTCPPorts = [ 27036 ];
allowedUDPPortRanges = [ { from = 27031; to = 27036; } ];
allowedUDPPortRanges = [{ from = 27031; to = 27036; }];
})

(mkIf cfg.dedicatedServer.openFirewall {
Expand Down
33 changes: 4 additions & 29 deletions pkgs/applications/window-managers/gamescope/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
}:
let
pname = "gamescope";
version = "3.11.52-beta6";
version = "3.11.52-unstable-2023-03-22";

vkroots = fetchFromGitHub {
owner = "Joshua-Ashton";
Expand All @@ -44,39 +44,14 @@ stdenv.mkDerivation {
inherit pname version;

src = fetchFromGitHub {
owner = "Plagman";
owner = "ValveSoftware";
repo = "gamescope";
rev = "refs/tags/${version}";
hash = "sha256-2gn6VQfmwwl86mmnRh+J1uxSIpA5x/Papq578seJ3n8=";
rev = "5d9ecd462e6d5939fc2697509f53bcb6aba7eb92";
hash = "sha256-1Ya59k60YmrJ1AWQ3eoWYBFjiz+RENBNc4FxK3GcgIQ=";
};

patches = [
./use-pkgconfig.patch

# https://github.com/Plagman/gamescope/pull/811
(fetchpatch {
name = "fix-openvr-dependency-name.patch";
url = "https://github.com/Plagman/gamescope/commit/557e56badec7d4c56263d3463ca9cdb195e368d7.patch";
sha256 = "sha256-9Y1tJ24EsdtZEOCEA30+FJBrdzXX+Nj3nTb5kgcPfBE=";
})
# https://github.com/Plagman/gamescope/pull/813
(fetchpatch {
name = "fix-openvr-include.patch";
url = "https://github.com/Plagman/gamescope/commit/1331b9f81ea4b3ae692a832ed85a464c3fd4c5e9.patch";
sha256 = "sha256-wDtFpM/nMcqSbIpR7K5Tyf0845r3l4kQHfwll1VL4Mc=";
})
# https://github.com/Plagman/gamescope/pull/812
(fetchpatch {
name = "bump-libdisplay-info-maximum-version.patch";
url = "https://github.com/Plagman/gamescope/commit/b430c5b9a05951755051fd4e41ce20496705fbbc.patch";
sha256 = "sha256-YHtwudMUHiE8i3ZbiC9gkSjrlS0/7ydjmJsY1a8ZI2E=";
})
# https://github.com/Plagman/gamescope/pull/824
(fetchpatch {
name = "update-libdisplay-info-pkgconfig-filename.patch";
url = "https://github.com/Plagman/gamescope/commit/5a672f09aa07c7c5d674789f3c685c8173e7a2cf.patch";
sha256 = "sha256-7NX54WIsJDvZT3C58N2FQasV9PJyKkJrLGYS1r4f+kc=";
})
];

nativeBuildInputs = [
Expand Down
31 changes: 31 additions & 0 deletions pkgs/os-specific/linux/kernel/linux-testing-hdr.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{ lib, fetchFromGitLab, buildLinux, ... } @ args:

# NOTE: This patched kernel is based upon amd-staging-drm-next
buildLinux (args // rec {
version = "6.0-unstable-2023-01-17";
extraMeta.branch = lib.versions.majorMinor version;

# modDirVersion needs to be x.y.z, will always add .0
modDirVersion = "6.0.0";

src = fetchFromGitLab {
domain = "gitlab.freedesktop.org";
owner = "JoshuaAshton";
repo = "linux-hdr";
rev = "ff57328e57842bb2e0475449fc598ff84e88d55c";
hash = "sha256-RS2AMybUw2tqxY3wDs1bWrNsaGeEsiXYLKEoqmgPMu0=";
};

# Never build it on Hydra
extraMeta.hydraPlatforms = [];

# Some unavailable options
structuredExtraConfig = with lib.kernel; {
ANDROID = lib.mkOverride 60 (option no);
DRM_AMD_DC_DCN = lib.mkOverride 60 (option no);
DRM_AMD_DC_HDCP = lib.mkOverride 60 (option no);
LRU_GEN = lib.mkOverride 60 (option no);
LRU_GEN_ENABLED = lib.mkOverride 60 (option no);
};

} // (args.argsOverride or {}))
3 changes: 3 additions & 0 deletions pkgs/top-level/all-packages.nix
Original file line number Diff line number Diff line change
Expand Up @@ -26492,6 +26492,9 @@ with pkgs;
linuxPackages_testing_bcachefs = linuxKernel.packages.linux_testing_bcachefs;
linux_testing_bcachefs = linuxKernel.kernels.linux_testing_bcachefs;

linuxPackages_testing_hdr = linuxKernel.packages.linux_testing_hdr;
linux_testing_hdr = linuxKernel.kernels.linux_testing_hdr;

# Realtime kernel
linuxPackages-rt = linuxKernel.packageAliases.linux_rt_default;
linuxPackages-rt_latest = linuxKernel.packageAliases.linux_rt_latest;
Expand Down
8 changes: 8 additions & 0 deletions pkgs/top-level/linux-kernels.nix
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,13 @@ in {
kernelPatches = linux_6_1.kernelPatches;
};

linux_testing_hdr = callPackage ../os-specific/linux/kernel/linux-testing-hdr.nix {
kernelPatches = [
kernelPatches.bridge_stp_helper
kernelPatches.request_key_helper
];
};

linux_hardkernel_4_14 = callPackage ../os-specific/linux/kernel/linux-hardkernel-4.14.nix {
kernelPatches = [
kernelPatches.bridge_stp_helper
Expand Down Expand Up @@ -592,6 +599,7 @@ in {
# Intentionally lacks recurseIntoAttrs, as -rc kernels will quite likely break out-of-tree modules and cause failed Hydra builds.
linux_testing = packagesFor kernels.linux_testing;
linux_testing_bcachefs = recurseIntoAttrs (packagesFor kernels.linux_testing_bcachefs);
linux_testing_hdr = recurseIntoAttrs (packagesFor kernels.linux_testing_hdr);

linux_hardened = recurseIntoAttrs (hardenedPackagesFor packageAliases.linux_default.kernel { });

Expand Down