Skip to content
Merged
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
2 changes: 1 addition & 1 deletion nixos/modules/hardware/video/amdgpu-pro.nix
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ in
nixpkgs.config.xorg.abiCompat = "1.19";

services.xserver.drivers = singleton
{ name = "amdgpu"; modules = [ package ]; };
{ name = "amdgpu"; modules = [ package ]; display = true; };

hardware.opengl.package = package;
hardware.opengl.package32 = package32;
Expand Down
2 changes: 1 addition & 1 deletion nixos/modules/hardware/video/ati.nix
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ in
nixpkgs.config.xorg.abiCompat = "1.17";

services.xserver.drivers = singleton
{ name = "fglrx"; modules = [ ati_x11 ]; };
{ name = "fglrx"; modules = [ ati_x11 ]; display = true; };

hardware.opengl.package = ati_x11;
hardware.opengl.package32 = pkgs.pkgsi686Linux.linuxPackages.ati_drivers_x11.override { libsOnly = true; kernel = null; };
Expand Down
138 changes: 86 additions & 52 deletions nixos/modules/hardware/video/nvidia.nix
Original file line number Diff line number Diff line change
Expand Up @@ -34,26 +34,57 @@ let
enabled = nvidia_x11 != null;

cfg = config.hardware.nvidia;
optimusCfg = cfg.optimus_prime;
pCfg = cfg.prime;
syncCfg = pCfg.sync;
offloadCfg = pCfg.offload;
primeEnabled = syncCfg.enable || offloadCfg.enable;
in

{
imports =
[
(mkRenamedOptionModule [ "hardware" "nvidia" "optimus_prime" "enable" ] [ "hardware" "nvidia" "prime" "sync" "enable" ])
(mkRenamedOptionModule [ "hardware" "nvidia" "optimus_prime" "allowExternalGpu" ] [ "hardware" "nvidia" "prime" "sync" "allowExternalGpu" ])
(mkRenamedOptionModule [ "hardware" "nvidia" "optimus_prime" "nvidiaBusId" ] [ "hardware" "nvidia" "prime" "nvidiaBusId" ])
(mkRenamedOptionModule [ "hardware" "nvidia" "optimus_prime" "intelBusId" ] [ "hardware" "nvidia" "prime" "intelBusId" ])
];

options = {
hardware.nvidia.modesetting.enable = lib.mkOption {
type = lib.types.bool;
hardware.nvidia.modesetting.enable = mkOption {
type = types.bool;
default = false;
description = ''
Enable kernel modesetting when using the NVIDIA proprietary driver.

Enabling this fixes screen tearing when using Optimus via PRIME (see
<option>hardware.nvidia.optimus_prime.enable</option>. This is not enabled
<option>hardware.nvidia.prime.sync.enable</option>. This is not enabled
by default because it is not officially supported by NVIDIA and would not
work with SLI.
'';
};

hardware.nvidia.optimus_prime.enable = lib.mkOption {
type = lib.types.bool;
hardware.nvidia.prime.nvidiaBusId = mkOption {
type = types.str;
default = "";
example = "PCI:1:0:0";
description = ''
Bus ID of the NVIDIA GPU. You can find it using lspci; for example if lspci
shows the NVIDIA GPU at "01:00.0", set this option to "PCI:1:0:0".
'';
};

hardware.nvidia.prime.intelBusId = mkOption {
type = types.str;
default = "";
example = "PCI:0:2:0";
description = ''
Bus ID of the Intel GPU. You can find it using lspci; for example if lspci
shows the Intel GPU at "00:02.0", set this option to "PCI:0:2:0".
'';
};

hardware.nvidia.prime.sync.enable = mkOption {
Copy link
Contributor

@nh2 nh2 Jun 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@eadwu and others:

Soes prime.sync have anything to do with PRIME Synchronization? (Arch wiki link and NVIDIA link)

Or is it just the old name for "Optimus Prime's sync mode" as described in https://nixos.wiki/wiki/Nvidia#sync_mode ?

If the former, we should probably rename it, or at write this in the docs here and into the NixOS wiki.

Do you know?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes prime.sync refers to PRIME Synchronization. It was previously put as optimus_prime https://github.com/NixOS/nixpkgs/pull/66601/files#diff-28ea4da3a9a595f8bd1a37a555c229f998f3a11b0715ebc5842ba266384eba73L55 as why the section has two different versions.

type = types.bool;
default = false;
description = ''
Enable NVIDIA Optimus support using the NVIDIA proprietary driver via PRIME.
Expand All @@ -66,8 +97,8 @@ in
be the only driver there.

If this is enabled, then the bus IDs of the NVIDIA and Intel GPUs have to be
specified (<option>hardware.nvidia.optimus_prime.nvidiaBusId</option> and
<option>hardware.nvidia.optimus_prime.intelBusId</option>).
specified (<option>hardware.nvidia.prime.nvidiaBusId</option> and
<option>hardware.nvidia.prime.intelBusId</option>).

If you enable this, you may want to also enable kernel modesetting for the
NVIDIA driver (<option>hardware.nvidia.modesetting.enable</option>) in order
Expand All @@ -79,31 +110,23 @@ in
'';
};

hardware.nvidia.optimus_prime.allowExternalGpu = lib.mkOption {
type = lib.types.bool;
hardware.nvidia.prime.sync.allowExternalGpu = mkOption {
type = types.bool;
default = false;
description = ''
Configure X to allow external NVIDIA GPUs when using optimus.
'';
};

hardware.nvidia.optimus_prime.nvidiaBusId = lib.mkOption {
type = lib.types.str;
default = "";
example = "PCI:1:0:0";
hardware.nvidia.prime.offload.enable = mkOption {
type = types.bool;
default = false;
description = ''
Bus ID of the NVIDIA GPU. You can find it using lspci; for example if lspci
shows the NVIDIA GPU at "01:00.0", set this option to "PCI:1:0:0".
'';
};
Enable render offload support using the NVIDIA proprietary driver via PRIME.

hardware.nvidia.optimus_prime.intelBusId = lib.mkOption {
type = lib.types.str;
default = "";
example = "PCI:0:2:0";
description = ''
Bus ID of the Intel GPU. You can find it using lspci; for example if lspci
shows the Intel GPU at "00:02.0", set this option to "PCI:0:2:0".
If this is enabled, then the bus IDs of the NVIDIA and Intel GPUs have to be
specified (<option>hardware.nvidia.prime.nvidiaBusId</option> and
<option>hardware.nvidia.prime.intelBusId</option>).
'';
};
};
Expand All @@ -116,12 +139,19 @@ in
}

{
assertion = !optimusCfg.enable ||
(optimusCfg.nvidiaBusId != "" && optimusCfg.intelBusId != "");
assertion = primeEnabled -> pCfg.nvidiaBusId != "" && pCfg.intelBusId != "";
message = ''
When NVIDIA Optimus via PRIME is enabled, the GPU bus IDs must configured.
When NVIDIA PRIME is enabled, the GPU bus IDs must configured.
'';
}
{
assertion = offloadCfg.enable -> versionAtLeast nvidia_x11.version "435.21";
message = "NVIDIA PRIME render offload is currently only supported on versions >= 435.21.";
}
{
assertion = !(syncCfg.enable && offloadCfg.enable);
message = "Only one NVIDIA PRIME solution may be used at a time.";
}
];

# If Optimus/PRIME is enabled, we:
Expand All @@ -136,36 +166,38 @@ in
# - Configure the display manager to run specific `xrandr` commands which will
# configure/enable displays connected to the Intel GPU.

services.xserver.drivers = singleton {
services.xserver.useGlamor = mkDefault offloadCfg.enable;

services.xserver.drivers = optional primeEnabled {
name = "modesetting";
display = offloadCfg.enable;
deviceSection = ''
BusID "${pCfg.intelBusId}"
${optionalString syncCfg.enable ''Option "AccelMethod" "none"''}
'';
} ++ singleton {
name = "nvidia";
modules = [ nvidia_x11.bin ];
deviceSection = optionalString optimusCfg.enable
display = !offloadCfg.enable;
deviceSection = optionalString primeEnabled
''
BusID "${optimusCfg.nvidiaBusId}"
${optionalString optimusCfg.allowExternalGpu "Option \"AllowExternalGpus\""}
BusID "${pCfg.nvidiaBusId}"
${optionalString syncCfg.allowExternalGpu "Option \"AllowExternalGpus\""}
'';
screenSection =
''
Option "RandRRotation" "on"
${optionalString optimusCfg.enable "Option \"AllowEmptyInitialConfiguration\""}
${optionalString syncCfg.enable "Option \"AllowEmptyInitialConfiguration\""}
'';
};

services.xserver.extraConfig = optionalString optimusCfg.enable
''
Section "Device"
Identifier "nvidia-optimus-intel"
Driver "modesetting"
BusID "${optimusCfg.intelBusId}"
Option "AccelMethod" "none"
EndSection
'';
services.xserver.serverLayoutSection = optionalString optimusCfg.enable
''
Inactive "nvidia-optimus-intel"
'';
services.xserver.serverLayoutSection = optionalString syncCfg.enable ''
Inactive "Device-modesetting[0]"
'' + optionalString offloadCfg.enable ''
Option "AllowNVIDIAGPUScreens"
'';

services.xserver.displayManager.setupCommands = optionalString optimusCfg.enable ''
services.xserver.displayManager.setupCommands = optionalString syncCfg.enable ''
# Added by nvidia configuration module for Optimus/PRIME.
${pkgs.xorg.xrandr}/bin/xrandr --setprovideroutputsource modesetting NVIDIA-0
${pkgs.xorg.xrandr}/bin/xrandr --auto
Expand All @@ -175,11 +207,13 @@ in
source = "${nvidia_x11.bin}/share/nvidia/nvidia-application-profiles-rc";
};

hardware.opengl.package = nvidia_x11.out;
hardware.opengl.package32 = nvidia_libs32;
hardware.opengl.package = mkIf (!offloadCfg.enable) nvidia_x11.out;
hardware.opengl.package32 = mkIf (!offloadCfg.enable) nvidia_libs32;
hardware.opengl.extraPackages = optional offloadCfg.enable nvidia_x11.out;
hardware.opengl.extraPackages32 = optional offloadCfg.enable nvidia_libs32;

environment.systemPackages = [ nvidia_x11.bin nvidia_x11.settings ]
++ lib.filter (p: p != null) [ nvidia_x11.persistenced ];
++ filter (p: p != null) [ nvidia_x11.persistenced ];

systemd.tmpfiles.rules = optional config.virtualisation.docker.enableNvidia
"L+ /run/nvidia-docker/bin - - - - ${nvidia_x11.bin}/origBin"
Expand All @@ -190,10 +224,10 @@ in

# nvidia-uvm is required by CUDA applications.
boot.kernelModules = [ "nvidia-uvm" ] ++
lib.optionals config.services.xserver.enable [ "nvidia" "nvidia_modeset" "nvidia_drm" ];
optionals config.services.xserver.enable [ "nvidia" "nvidia_modeset" "nvidia_drm" ];

# If requested enable modesetting via kernel parameter.
boot.kernelParams = optional cfg.modesetting.enable "nvidia-drm.modeset=1";
boot.kernelParams = optional (offloadCfg.enable || cfg.modesetting.enable) "nvidia-drm.modeset=1";

# Create /dev/nvidia-uvm when the nvidia-uvm module is loaded.
services.udev.extraRules =
Expand Down
76 changes: 39 additions & 37 deletions nixos/modules/services/x11/xserver.nix
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@ in
then { modules = [xorg.${"xf86video" + name}]; }
else null)
knownVideoDrivers;
in optional (driver != null) ({ inherit name; modules = []; driverName = name; } // driver));
in optional (driver != null) ({ inherit name; modules = []; driverName = name; display = true; } // driver));

assertions = [
{ assertion = config.security.polkit.enable;
Expand Down Expand Up @@ -749,7 +749,7 @@ in
${cfg.serverLayoutSection}
# Reference the Screen sections for each driver. This will
# cause the X server to try each in turn.
${flip concatMapStrings cfg.drivers (d: ''
${flip concatMapStrings (filter (d: d.display) cfg.drivers) (d: ''
Screen "Screen-${d.name}[0]"
'')}
EndSection
Expand All @@ -773,42 +773,44 @@ in
${driver.deviceSection or ""}
${xrandrDeviceSection}
EndSection
${optionalString driver.display ''

Section "Screen"
Identifier "Screen-${driver.name}[0]"
Device "Device-${driver.name}[0]"
${optionalString (cfg.monitorSection != "") ''
Monitor "Monitor[0]"
''}

${cfg.screenSection}
${driver.screenSection or ""}

${optionalString (cfg.defaultDepth != 0) ''
DefaultDepth ${toString cfg.defaultDepth}
''}

${optionalString
(driver.name != "virtualbox" &&
(cfg.resolutions != [] ||
cfg.extraDisplaySettings != "" ||
cfg.virtualScreen != null))
(let
f = depth:
''
SubSection "Display"
Depth ${toString depth}
${optionalString (cfg.resolutions != [])
"Modes ${concatMapStrings (res: ''"${toString res.x}x${toString res.y}"'') cfg.resolutions}"}
${cfg.extraDisplaySettings}
${optionalString (cfg.virtualScreen != null)
"Virtual ${toString cfg.virtualScreen.x} ${toString cfg.virtualScreen.y}"}
EndSubSection
'';
in concatMapStrings f [8 16 24]
)}

Section "Screen"
Identifier "Screen-${driver.name}[0]"
Device "Device-${driver.name}[0]"
${optionalString (cfg.monitorSection != "") ''
Monitor "Monitor[0]"
''}

${cfg.screenSection}
${driver.screenSection or ""}

${optionalString (cfg.defaultDepth != 0) ''
DefaultDepth ${toString cfg.defaultDepth}
''}

${optionalString
(driver.name != "virtualbox" &&
(cfg.resolutions != [] ||
cfg.extraDisplaySettings != "" ||
cfg.virtualScreen != null))
(let
f = depth:
''
SubSection "Display"
Depth ${toString depth}
${optionalString (cfg.resolutions != [])
"Modes ${concatMapStrings (res: ''"${toString res.x}x${toString res.y}"'') cfg.resolutions}"}
${cfg.extraDisplaySettings}
${optionalString (cfg.virtualScreen != null)
"Virtual ${toString cfg.virtualScreen.x} ${toString cfg.virtualScreen.y}"}
EndSubSection
'';
in concatMapStrings f [8 16 24]
)}

EndSection
EndSection
''}
'')}

${xrandrMonitorSections}
Expand Down
7 changes: 7 additions & 0 deletions pkgs/os-specific/linux/nvidia-x11/builder.sh
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,18 @@ installPhase() {
fi
install -Dm644 nvidia_icd.json.fixed $i/share/vulkan/icd.d/nvidia.json
fi
if [ -e nvidia_layers.json ]; then
sed -E "s#(libGLX_nvidia)#$i/lib/\\1#" nvidia_layers.json > nvidia_layers.json.fixed
install -Dm644 nvidia_layers.json.fixed $i/share/vulkan/implicit_layer.d/nvidia_layers.json
fi

# EGL
if [ "$useGLVND" = "1" ]; then
sed -E "s#(libEGL_nvidia)#$i/lib/\\1#" 10_nvidia.json > 10_nvidia.json.fixed
sed -E "s#(libnvidia-egl-wayland)#$i/lib/\\1#" 10_nvidia_wayland.json > 10_nvidia_wayland.json.fixed

install -Dm644 10_nvidia.json.fixed $i/share/glvnd/egl_vendor.d/nvidia.json
install -Dm644 10_nvidia_wayland.json.fixed $i/share/glvnd/egl_vendor.d/nvidia_wayland.json
fi

done
Expand Down
2 changes: 1 addition & 1 deletion pkgs/os-specific/linux/nvidia-x11/generic.nix
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ let
pkgSuffix = optionalString (versionOlder version "304") "-pkg0";
i686bundled = versionAtLeast version "391";

libPathFor = pkgs: pkgs.lib.makeLibraryPath [ pkgs.xorg.libXext pkgs.xorg.libX11
libPathFor = pkgs: pkgs.lib.makeLibraryPath [ pkgs.libdrm pkgs.xorg.libXext pkgs.xorg.libX11
pkgs.xorg.libXv pkgs.xorg.libXrandr pkgs.xorg.libxcb pkgs.zlib pkgs.stdenv.cc.cc ];

self = stdenv.mkDerivation {
Expand Down