From 2a7130d13a032093f5394ef0961842d1e1928789 Mon Sep 17 00:00:00 2001 From: Googlebot Date: Mon, 21 Mar 2022 19:48:32 -0400 Subject: nvidia: Reverse Prime Sync --- nixos/modules/hardware/video/nvidia.nix | 121 ++++++++++++++++++++++++++------ 1 file changed, 100 insertions(+), 21 deletions(-) (limited to 'nixos/modules/hardware') diff --git a/nixos/modules/hardware/video/nvidia.nix b/nixos/modules/hardware/video/nvidia.nix index cee230ac41cb1..852675bbef3a3 100644 --- a/nixos/modules/hardware/video/nvidia.nix +++ b/nixos/modules/hardware/video/nvidia.nix @@ -21,7 +21,8 @@ let pCfg = cfg.prime; syncCfg = pCfg.sync; offloadCfg = pCfg.offload; - primeEnabled = syncCfg.enable || offloadCfg.enable; + reverseSyncCfg = pCfg.reverseSync; + primeEnabled = syncCfg.enable || reverseSyncCfg.enable || offloadCfg.enable; nvidiaPersistencedEnabled = cfg.nvidiaPersistenced; nvidiaSettings = cfg.nvidiaSettings; busIDType = types.strMatching "([[:print:]]+[\:\@][0-9]{1,3}\:[0-9]{1,2}\:[0-9])?"; @@ -31,7 +32,8 @@ 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" "allowExternalGpu" ] [ "hardware" "nvidia" "prime" "allowExternalGpu" ]) + (mkRenamedOptionModule [ "hardware" "nvidia" "prime" "sync" "allowExternalGpu" ] [ "hardware" "nvidia" "prime" "allowExternalGpu" ]) (mkRenamedOptionModule [ "hardware" "nvidia" "optimus_prime" "nvidiaBusId" ] [ "hardware" "nvidia" "prime" "nvidiaBusId" ]) (mkRenamedOptionModule [ "hardware" "nvidia" "optimus_prime" "intelBusId" ] [ "hardware" "nvidia" "prime" "intelBusId" ]) ]; @@ -104,16 +106,17 @@ in description = lib.mdDoc '' Enable NVIDIA Optimus support using the NVIDIA proprietary driver via PRIME. If enabled, the NVIDIA GPU will be always on and used for all rendering, - while enabling output to displays attached only to the integrated Intel GPU - without a multiplexer. + while enabling output to displays attached only to the integrated Intel/AMD + GPU without a multiplexer. Note that this option only has any effect if the "nvidia" driver is specified in {option}`services.xserver.videoDrivers`, and it should preferably 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.prime.nvidiaBusId` and - {option}`hardware.nvidia.prime.intelBusId`). + If this is enabled, then the bus IDs of the NVIDIA and Intel/AMD GPUs have to + be specified ({option}`hardware.nvidia.prime.nvidiaBusId` and + {option}`hardware.nvidia.prime.intelBusId` or + {option}`hardware.nvidia.prime.amdgpuBusId`). If you enable this, you may want to also enable kernel modesetting for the NVIDIA driver ({option}`hardware.nvidia.modesetting.enable`) in order @@ -125,11 +128,11 @@ in ''; }; - hardware.nvidia.prime.sync.allowExternalGpu = mkOption { + hardware.nvidia.prime.allowExternalGpu = mkOption { type = types.bool; default = false; description = lib.mdDoc '' - Configure X to allow external NVIDIA GPUs when using optimus. + Configure X to allow external NVIDIA GPUs when using Prime [Reverse] sync optimus. ''; }; @@ -139,9 +142,54 @@ in description = lib.mdDoc '' Enable render offload support using the NVIDIA proprietary driver via PRIME. - If this is enabled, then the bus IDs of the NVIDIA and Intel GPUs have to be - specified ({option}`hardware.nvidia.prime.nvidiaBusId` and - {option}`hardware.nvidia.prime.intelBusId`). + If this is enabled, then the bus IDs of the NVIDIA and Intel/AMD GPUs have to + be specified ({option}`hardware.nvidia.prime.nvidiaBusId` and + {option}`hardware.nvidia.prime.intelBusId` or + {option}`hardware.nvidia.prime.amdgpuBusId`). + ''; + }; + + hardware.nvidia.prime.offload.enableOffloadCmd = mkOption { + type = types.bool; + default = false; + description = lib.mdDoc '' + Adds a `nvidia-offload` convenience script to {option}`environment.systemPackages` + for offloading programs to an nvidia device. To work, should have also enabled + {option}`hardware.nvidia.prime.offload.enable` or {option}`hardware.nvidia.prime.reverseSync.enable`. + + Example usage `nvidia-offload sauerbraten_client`. + ''; + }; + + hardware.nvidia.prime.reverseSync.enable = mkOption { + type = types.bool; + default = false; + description = lib.mdDoc '' + Warning: This feature is relatively new, depending on your system this might + work poorly. AMD support, especially so. + See: https://forums.developer.nvidia.com/t/the-all-new-outputsink-feature-aka-reverse-prime/129828 + + Enable NVIDIA Optimus support using the NVIDIA proprietary driver via reverse + PRIME. If enabled, the Intel/AMD GPU will be used for all rendering, while + enabling output to displays attached only to the NVIDIA GPU without a + multiplexer. + + Note that this option only has any effect if the "nvidia" driver is specified + in {option}`services.xserver.videoDrivers`, and it should preferably + be the only driver there. + + If this is enabled, then the bus IDs of the NVIDIA and Intel/AMD GPUs have to + be specified ({option}`hardware.nvidia.prime.nvidiaBusId` and + {option}`hardware.nvidia.prime.intelBusId` or + {option}`hardware.nvidia.prime.amdgpuBusId`). + + If you enable this, you may want to also enable kernel modesetting for the + NVIDIA driver ({option}`hardware.nvidia.modesetting.enable`) in order + to prevent tearing. + + Note that this configuration will only be successful when a display manager + for which the {option}`services.xserver.displayManager.setupCommands` + option is supported is used. ''; }; @@ -205,6 +253,13 @@ in ''; } + { + assertion = offloadCfg.enableOffloadCmd -> offloadCfg.enable || reverseSyncCfg.enable; + message = '' + Offload command requires offloading or reverse prime sync to be enabled. + ''; + } + { assertion = primeEnabled -> pCfg.nvidiaBusId != "" && (pCfg.intelBusId != "" || pCfg.amdgpuBusId != ""); message = '' @@ -217,9 +272,19 @@ in message = "NVIDIA PRIME render offload is currently only supported on versions >= 435.21."; } + { + assertion = (reverseSyncCfg.enable && pCfg.amdgpuBusId != "") -> versionAtLeast nvidia_x11.version "470.0"; + message = "NVIDIA PRIME render offload for AMD APUs is currently only supported on versions >= 470 beta."; + } + { assertion = !(syncCfg.enable && offloadCfg.enable); - message = "Only one NVIDIA PRIME solution may be used at a time."; + message = "PRIME Sync and Offload cannot be both enabled"; + } + + { + assertion = !(syncCfg.enable && reverseSyncCfg.enable); + message = "PRIME Sync and PRIME Reverse Sync cannot be both enabled"; } { @@ -257,14 +322,16 @@ in # - Configure the display manager to run specific `xrandr` commands which will # configure/enable displays connected to the Intel iGPU / AMD APU. - services.xserver.drivers = let - in optional primeEnabled { + # reverse sync implies offloading + hardware.nvidia.prime.offload.enable = mkDefault reverseSyncCfg.enable; + + services.xserver.drivers = optional primeEnabled { name = igpuDriver; display = offloadCfg.enable; modules = optionals (igpuDriver == "amdgpu") [ pkgs.xorg.xf86videoamdgpu ]; deviceSection = '' BusID "${igpuBusId}" - ${optionalString (syncCfg.enable && igpuDriver != "amdgpu") ''Option "AccelMethod" "none"''} + ${optionalString (pCfg.enable && igpuDriver != "amdgpu") ''Option "AccelMethod" "none"''} ''; } ++ singleton { name = "nvidia"; @@ -273,7 +340,7 @@ in deviceSection = optionalString primeEnabled '' BusID "${pCfg.nvidiaBusId}" - ${optionalString syncCfg.allowExternalGpu "Option \"AllowExternalGpus\""} + ${optionalString pCfg.allowExternalGpu "Option \"AllowExternalGpus\""} ''; screenSection = '' @@ -290,19 +357,22 @@ in services.xserver.serverLayoutSection = optionalString syncCfg.enable '' Inactive "Device-${igpuDriver}[0]" + '' + optionalString reverseSyncCfg.enable '' + Inactive "Device-nvidia[0]" '' + optionalString offloadCfg.enable '' Option "AllowNVIDIAGPUScreens" ''; services.xserver.displayManager.setupCommands = let - sinkGpuProviderName = if igpuDriver == "amdgpu" then + gpuProviderName = if igpuDriver == "amdgpu" then # find the name of the provider if amdgpu "`${pkgs.xorg.xrandr}/bin/xrandr --listproviders | ${pkgs.gnugrep}/bin/grep -i AMD | ${pkgs.gnused}/bin/sed -n 's/^.*name://p'`" else igpuDriver; - in optionalString syncCfg.enable '' + providerCmdParams = if syncCfg.enable then "\"${gpuProviderName}\" NVIDIA-0" else "NVIDIA-G0 \"${gpuProviderName}\""; + in optionalString (syncCfg.enable || reverseSyncCfg.enable) '' # Added by nvidia configuration module for Optimus/PRIME. - ${pkgs.xorg.xrandr}/bin/xrandr --setprovideroutputsource "${sinkGpuProviderName}" NVIDIA-0 + ${pkgs.xorg.xrandr}/bin/xrandr --setprovideroutputsource ${providerCmdParams} ${pkgs.xorg.xrandr}/bin/xrandr --auto ''; @@ -325,7 +395,16 @@ in environment.systemPackages = [ nvidia_x11.bin ] ++ optionals cfg.nvidiaSettings [ nvidia_x11.settings ] - ++ optionals nvidiaPersistencedEnabled [ nvidia_x11.persistenced ]; + ++ optionals nvidiaPersistencedEnabled [ nvidia_x11.persistenced ] + ++ optionals offloadCfg.enableOffloadCmd [ + (pkgs.writeShellScriptBin "nvidia-offload" '' + export __NV_PRIME_RENDER_OFFLOAD=1 + export __NV_PRIME_RENDER_OFFLOAD_PROVIDER=NVIDIA-G0 + export __GLX_VENDOR_LIBRARY_NAME=nvidia + export __VK_LAYER_NV_optimus=NVIDIA_only + exec "$@" + '') + ]; systemd.packages = optional cfg.powerManagement.enable nvidia_x11.out; -- cgit 1.4.1