Merge pull request #66601 from eadwu/nvidia/prime-render-offload

nvidia: prime render offload
This commit is contained in:
José Romildo Malaquias 2020-03-01 14:28:57 -03:00 committed by GitHub
commit 74f5358f13
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 131 additions and 88 deletions

View File

@ -30,7 +30,7 @@ in
nixpkgs.config.xorg.abiCompat = "1.19"; nixpkgs.config.xorg.abiCompat = "1.19";
services.xserver.drivers = singleton services.xserver.drivers = singleton
{ name = "amdgpu"; modules = [ package ]; }; { name = "amdgpu"; modules = [ package ]; display = true; };
hardware.opengl.package = package; hardware.opengl.package = package;
hardware.opengl.package32 = package32; hardware.opengl.package32 = package32;

View File

@ -21,7 +21,7 @@ in
nixpkgs.config.xorg.abiCompat = "1.17"; nixpkgs.config.xorg.abiCompat = "1.17";
services.xserver.drivers = singleton services.xserver.drivers = singleton
{ name = "fglrx"; modules = [ ati_x11 ]; }; { name = "fglrx"; modules = [ ati_x11 ]; display = true; };
hardware.opengl.package = ati_x11; hardware.opengl.package = ati_x11;
hardware.opengl.package32 = pkgs.pkgsi686Linux.linuxPackages.ati_drivers_x11.override { libsOnly = true; kernel = null; }; hardware.opengl.package32 = pkgs.pkgsi686Linux.linuxPackages.ati_drivers_x11.override { libsOnly = true; kernel = null; };

View File

@ -34,26 +34,57 @@ let
enabled = nvidia_x11 != null; enabled = nvidia_x11 != null;
cfg = config.hardware.nvidia; cfg = config.hardware.nvidia;
optimusCfg = cfg.optimus_prime; pCfg = cfg.prime;
syncCfg = pCfg.sync;
offloadCfg = pCfg.offload;
primeEnabled = syncCfg.enable || offloadCfg.enable;
in 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 = { options = {
hardware.nvidia.modesetting.enable = lib.mkOption { hardware.nvidia.modesetting.enable = mkOption {
type = lib.types.bool; type = types.bool;
default = false; default = false;
description = '' description = ''
Enable kernel modesetting when using the NVIDIA proprietary driver. Enable kernel modesetting when using the NVIDIA proprietary driver.
Enabling this fixes screen tearing when using Optimus via PRIME (see 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 by default because it is not officially supported by NVIDIA and would not
work with SLI. work with SLI.
''; '';
}; };
hardware.nvidia.optimus_prime.enable = lib.mkOption { hardware.nvidia.prime.nvidiaBusId = mkOption {
type = lib.types.bool; 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 {
type = types.bool;
default = false; default = false;
description = '' description = ''
Enable NVIDIA Optimus support using the NVIDIA proprietary driver via PRIME. Enable NVIDIA Optimus support using the NVIDIA proprietary driver via PRIME.
@ -66,8 +97,8 @@ in
be the only driver there. be the only driver there.
If this is enabled, then the bus IDs of the NVIDIA and Intel GPUs have to be 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 specified (<option>hardware.nvidia.prime.nvidiaBusId</option> and
<option>hardware.nvidia.optimus_prime.intelBusId</option>). <option>hardware.nvidia.prime.intelBusId</option>).
If you enable this, you may want to also enable kernel modesetting for the If you enable this, you may want to also enable kernel modesetting for the
NVIDIA driver (<option>hardware.nvidia.modesetting.enable</option>) in order NVIDIA driver (<option>hardware.nvidia.modesetting.enable</option>) in order
@ -79,31 +110,23 @@ in
''; '';
}; };
hardware.nvidia.optimus_prime.allowExternalGpu = lib.mkOption { hardware.nvidia.prime.sync.allowExternalGpu = mkOption {
type = lib.types.bool; type = types.bool;
default = false; default = false;
description = '' description = ''
Configure X to allow external NVIDIA GPUs when using optimus. Configure X to allow external NVIDIA GPUs when using optimus.
''; '';
}; };
hardware.nvidia.optimus_prime.nvidiaBusId = lib.mkOption { hardware.nvidia.prime.offload.enable = mkOption {
type = lib.types.str; type = types.bool;
default = ""; default = false;
example = "PCI:1:0:0";
description = '' description = ''
Bus ID of the NVIDIA GPU. You can find it using lspci; for example if lspci Enable render offload support using the NVIDIA proprietary driver via PRIME.
shows the NVIDIA GPU at "01:00.0", set this option to "PCI:1:0:0".
'';
};
hardware.nvidia.optimus_prime.intelBusId = lib.mkOption { If this is enabled, then the bus IDs of the NVIDIA and Intel GPUs have to be
type = lib.types.str; specified (<option>hardware.nvidia.prime.nvidiaBusId</option> and
default = ""; <option>hardware.nvidia.prime.intelBusId</option>).
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".
''; '';
}; };
}; };
@ -116,12 +139,19 @@ in
} }
{ {
assertion = !optimusCfg.enable || assertion = primeEnabled -> pCfg.nvidiaBusId != "" && pCfg.intelBusId != "";
(optimusCfg.nvidiaBusId != "" && optimusCfg.intelBusId != "");
message = '' 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: # If Optimus/PRIME is enabled, we:
@ -136,36 +166,38 @@ in
# - Configure the display manager to run specific `xrandr` commands which will # - Configure the display manager to run specific `xrandr` commands which will
# configure/enable displays connected to the Intel GPU. # 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"; name = "nvidia";
modules = [ nvidia_x11.bin ]; modules = [ nvidia_x11.bin ];
deviceSection = optionalString optimusCfg.enable display = !offloadCfg.enable;
deviceSection = optionalString primeEnabled
'' ''
BusID "${optimusCfg.nvidiaBusId}" BusID "${pCfg.nvidiaBusId}"
${optionalString optimusCfg.allowExternalGpu "Option \"AllowExternalGpus\""} ${optionalString syncCfg.allowExternalGpu "Option \"AllowExternalGpus\""}
''; '';
screenSection = screenSection =
'' ''
Option "RandRRotation" "on" Option "RandRRotation" "on"
${optionalString optimusCfg.enable "Option \"AllowEmptyInitialConfiguration\""} ${optionalString syncCfg.enable "Option \"AllowEmptyInitialConfiguration\""}
''; '';
}; };
services.xserver.extraConfig = optionalString optimusCfg.enable services.xserver.serverLayoutSection = optionalString syncCfg.enable ''
'' Inactive "Device-modesetting[0]"
Section "Device" '' + optionalString offloadCfg.enable ''
Identifier "nvidia-optimus-intel" Option "AllowNVIDIAGPUScreens"
Driver "modesetting" '';
BusID "${optimusCfg.intelBusId}"
Option "AccelMethod" "none"
EndSection
'';
services.xserver.serverLayoutSection = optionalString optimusCfg.enable
''
Inactive "nvidia-optimus-intel"
'';
services.xserver.displayManager.setupCommands = optionalString optimusCfg.enable '' services.xserver.displayManager.setupCommands = optionalString syncCfg.enable ''
# Added by nvidia configuration module for Optimus/PRIME. # Added by nvidia configuration module for Optimus/PRIME.
${pkgs.xorg.xrandr}/bin/xrandr --setprovideroutputsource modesetting NVIDIA-0 ${pkgs.xorg.xrandr}/bin/xrandr --setprovideroutputsource modesetting NVIDIA-0
${pkgs.xorg.xrandr}/bin/xrandr --auto ${pkgs.xorg.xrandr}/bin/xrandr --auto
@ -175,11 +207,13 @@ in
source = "${nvidia_x11.bin}/share/nvidia/nvidia-application-profiles-rc"; source = "${nvidia_x11.bin}/share/nvidia/nvidia-application-profiles-rc";
}; };
hardware.opengl.package = nvidia_x11.out; hardware.opengl.package = mkIf (!offloadCfg.enable) nvidia_x11.out;
hardware.opengl.package32 = nvidia_libs32; 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 ] 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 systemd.tmpfiles.rules = optional config.virtualisation.docker.enableNvidia
"L+ /run/nvidia-docker/bin - - - - ${nvidia_x11.bin}/origBin" "L+ /run/nvidia-docker/bin - - - - ${nvidia_x11.bin}/origBin"
@ -190,10 +224,10 @@ in
# nvidia-uvm is required by CUDA applications. # nvidia-uvm is required by CUDA applications.
boot.kernelModules = [ "nvidia-uvm" ] ++ 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. # 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. # Create /dev/nvidia-uvm when the nvidia-uvm module is loaded.
services.udev.extraRules = services.udev.extraRules =

View File

@ -573,7 +573,7 @@ in
then { modules = [xorg.${"xf86video" + name}]; } then { modules = [xorg.${"xf86video" + name}]; }
else null) else null)
knownVideoDrivers; knownVideoDrivers;
in optional (driver != null) ({ inherit name; modules = []; driverName = name; } // driver)); in optional (driver != null) ({ inherit name; modules = []; driverName = name; display = true; } // driver));
assertions = [ assertions = [
{ assertion = config.security.polkit.enable; { assertion = config.security.polkit.enable;
@ -740,7 +740,7 @@ in
${cfg.serverLayoutSection} ${cfg.serverLayoutSection}
# Reference the Screen sections for each driver. This will # Reference the Screen sections for each driver. This will
# cause the X server to try each in turn. # 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]" Screen "Screen-${d.name}[0]"
'')} '')}
EndSection EndSection
@ -764,42 +764,44 @@ in
${driver.deviceSection or ""} ${driver.deviceSection or ""}
${xrandrDeviceSection} ${xrandrDeviceSection}
EndSection EndSection
${optionalString driver.display ''
Section "Screen" Section "Screen"
Identifier "Screen-${driver.name}[0]" Identifier "Screen-${driver.name}[0]"
Device "Device-${driver.name}[0]" Device "Device-${driver.name}[0]"
${optionalString (cfg.monitorSection != "") '' ${optionalString (cfg.monitorSection != "") ''
Monitor "Monitor[0]" Monitor "Monitor[0]"
''} ''}
${cfg.screenSection} ${cfg.screenSection}
${driver.screenSection or ""} ${driver.screenSection or ""}
${optionalString (cfg.defaultDepth != 0) '' ${optionalString (cfg.defaultDepth != 0) ''
DefaultDepth ${toString cfg.defaultDepth} DefaultDepth ${toString cfg.defaultDepth}
''} ''}
${optionalString ${optionalString
(driver.name != "virtualbox" && (driver.name != "virtualbox" &&
(cfg.resolutions != [] || (cfg.resolutions != [] ||
cfg.extraDisplaySettings != "" || cfg.extraDisplaySettings != "" ||
cfg.virtualScreen != null)) cfg.virtualScreen != null))
(let (let
f = depth: f = depth:
'' ''
SubSection "Display" SubSection "Display"
Depth ${toString depth} Depth ${toString depth}
${optionalString (cfg.resolutions != []) ${optionalString (cfg.resolutions != [])
"Modes ${concatMapStrings (res: ''"${toString res.x}x${toString res.y}"'') cfg.resolutions}"} "Modes ${concatMapStrings (res: ''"${toString res.x}x${toString res.y}"'') cfg.resolutions}"}
${cfg.extraDisplaySettings} ${cfg.extraDisplaySettings}
${optionalString (cfg.virtualScreen != null) ${optionalString (cfg.virtualScreen != null)
"Virtual ${toString cfg.virtualScreen.x} ${toString cfg.virtualScreen.y}"} "Virtual ${toString cfg.virtualScreen.x} ${toString cfg.virtualScreen.y}"}
EndSubSection EndSubSection
''; '';
in concatMapStrings f [8 16 24] in concatMapStrings f [8 16 24]
)} )}
EndSection EndSection
''}
'')} '')}
${xrandrMonitorSections} ${xrandrMonitorSections}

View File

@ -75,11 +75,18 @@ installPhase() {
fi fi
install -Dm644 nvidia_icd.json.fixed $i/share/vulkan/icd.d/nvidia.json install -Dm644 nvidia_icd.json.fixed $i/share/vulkan/icd.d/nvidia.json
fi 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 # EGL
if [ "$useGLVND" = "1" ]; then if [ "$useGLVND" = "1" ]; then
sed -E "s#(libEGL_nvidia)#$i/lib/\\1#" 10_nvidia.json > 10_nvidia.json.fixed 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.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 fi
done done

View File

@ -32,7 +32,7 @@ let
pkgSuffix = optionalString (versionOlder version "304") "-pkg0"; pkgSuffix = optionalString (versionOlder version "304") "-pkg0";
i686bundled = versionAtLeast version "391"; 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 ]; pkgs.xorg.libXv pkgs.xorg.libXrandr pkgs.xorg.libxcb pkgs.zlib pkgs.stdenv.cc.cc ];
self = stdenv.mkDerivation { self = stdenv.mkDerivation {