Unverified Commit 620aa4ff authored by Thiago Kenji Okada's avatar Thiago Kenji Okada Committed by GitHub
Browse files

Merge pull request #165188 from GoogleBot42/master

nvidia: Add Reverse Prime Sync
parents 4f185da4 458c1628
Loading
Loading
Loading
Loading
+99 −20
Original line number Diff line number Diff line
@@ -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,8 +322,10 @@ 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 ];
@@ -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;