From deee4df6539713a29c73d9047356c20ef4777901 Mon Sep 17 00:00:00 2001 From: ItsDrike Date: Mon, 10 Jun 2024 13:54:03 +0200 Subject: [PATCH] Fix nvidia on hybrid setups --- hosts/herugrim/default.nix | 2 +- hosts/herugrim/hardware-configuration.nix | 7 +++ options/device/hardware.nix | 11 ++++- system/shared/hardware/gpu/nvidia.nix | 56 +++++++++++++++++------ 4 files changed, 60 insertions(+), 16 deletions(-) diff --git a/hosts/herugrim/default.nix b/hosts/herugrim/default.nix index 81c4c9d..6b6beb7 100644 --- a/hosts/herugrim/default.nix +++ b/hosts/herugrim/default.nix @@ -59,7 +59,7 @@ virtual-machine = false; }; cpu.type = "amd"; - gpu.type = "nvidia"; + gpu.type = "hybrid-nvidia"; hasTPM = true; }; diff --git a/hosts/herugrim/hardware-configuration.nix b/hosts/herugrim/hardware-configuration.nix index c785643..28065df 100644 --- a/hosts/herugrim/hardware-configuration.nix +++ b/hosts/herugrim/hardware-configuration.nix @@ -66,4 +66,11 @@ nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; + + # Enable prime-offload + # This machine has AMD igpu + nvidia dgpu, so we need hybrid + hardware.nvidia.prime = { + nvidiaBusId = "PCI:1:0:0"; + amdgpuBusId = "PCI:5:0:0"; + }; } diff --git a/options/device/hardware.nix b/options/device/hardware.nix index cddde3f..5b03a78 100644 --- a/options/device/hardware.nix +++ b/options/device/hardware.nix @@ -15,12 +15,21 @@ in }; gpu.type = mkOption { - type = with types; nullOr (enum [ "nvidia" "amd" "intel" ]); + type = with types; nullOr (enum [ "nvidia" "amd" "intel" "hybrid-nvidia" "hybrid-amd" ]); default = null; description = '' The manifaturer/type of the primary system GPU. Allows the correct GPU drivers to be loaded, potentially optimizing video output performance. + + If you're on a hybrid system (intel/amd igpu + nvidia/amd dgpu) make sure to use + the hybrid options, only specifying the dgpu will not work properly. + + Note that if using hybrid-nvidia, you will need to set `hardware.nvidia.prime.nvidiaBusId` + and `intelBusId` (or `amdgpuBusId`) to "PCI:x:y:z". To find the correct bus IDs, you can + use `sudo lshw -c display`. Note that you will need to convert the bus ID format from + hexadecimal to decimal, remove the padding (leading zeroes) and replace the dot with a + colon (so for example 0e:00.0 -> PCI:14:0:0). ''; }; diff --git a/system/shared/hardware/gpu/nvidia.nix b/system/shared/hardware/gpu/nvidia.nix index fed1519..5679760 100644 --- a/system/shared/hardware/gpu/nvidia.nix +++ b/system/shared/hardware/gpu/nvidia.nix @@ -1,29 +1,36 @@ { config, lib, pkgs, ... }: let dev = config.myOptions.device; + isWayland = config.myOptions.home-manager.wms.isWayland; + + inherit (lib) mkIf mkDefault mkMerge; in { - config = lib.mkIf (dev.gpu.type == "nvidia") { + config = mkIf (builtins.elem dev.gpu.type ["nvidia" "hybrid-nvidia"]) { # Nvidia drivers are unfree software nixpkgs.config.allowUnfree = true; # Enable nvidia driver for Xorg and Wayland services.xserver.videoDrivers = ["nvidia"]; + # blacklist nouveau module so that it does not conflict with nvidia drm stuff + # also the nouveau performance is horrible in comparison. + boot.blacklistedKernelModules = ["nouveau"]; + hardware = { nvidia = { # modeestting is required - modesetting.enable = lib.mkDefault true; + modesetting.enable = mkDefault true; # Nvidia power managerment. Experimental, and can cause sleep/suspend to fail. # Enable this if you have graphical corruption issues or application crashes after waking # up from sleep. This fixes it by saving the entire VRAM memory to /tmp/ instead of just # the bare essentials - powerManagement.enable = lib.mkDefault true; + powerManagement.enable = mkDefault true; # Fine-grained power management. Turns off GPU when not in use. # Experimental and only works on modern Nvidia GPUs (Turing or newer) - powerManagement.finegrained = lib.mkDefault false; + powerManagement.finegrained = mkDefault false; # Use the NVidia open source kernel module (not to be confused with the # independent third-party "nouveau" open source driver). @@ -32,14 +39,27 @@ in # # Enable this by default, hosts may override this option if their gpu is not # supported by the open source drivers - open = lib.mkDefault true; + open = mkDefault true; # Add the Nvidia settings package, accessible via `nvidia-settings`. # (useless on NixOS) - nvidiaSettings = false; + nvidiaSettings = mkDefault false; # This ensures all GPUs stay awake even during headless mode. nvidiaPersistenced = true; + + # On Hybrid setups, using Nvidia Optimus PRIME is necessary + # + # There are various options/modes prime can work in, this will default to + # using the offload mode, which will default to running everything on igpu + # except apps that run with certain environmental variables set. To simplify + # things, this will also enable the `nvidia-offload` wrapper script/command. + prime.offload = let + isHybrid = dev.gpu.type == "hybrid-nvidia"; + in { + enable = isHybrid; + enableOffloadCmd = isHybrid; + }; }; # Enable OpenGL @@ -52,10 +72,6 @@ in }; }; - # blacklist nouveau module so that it does not conflict with nvidia drm stuff - # also the nouveau performance is horrible in comparison. - boot.blacklistedKernelModules = ["nouveau"]; - environment = { systemPackages = with pkgs; [ mesa @@ -67,12 +83,24 @@ in libva libva-utils + + glxinfo ]; - sessionVariables = { - LIBVA_DRIVER_NAME = "nvidia"; - WLR_NO_HARDWARE_CURSORS = "1"; - }; + sessionVariables = mkMerge [ + { LIBVA_DRIVER_NAME = "nvidia"; } + + (mkIf isWayland { + WLR_NO_HARDWARE_CURSORS = "1"; + }) + + # Run the compositor itself with nvidia GPU? + # Currently disabled + (mkIf (isWayland && (dev.gpu == "hybrid-nvidia")) { + #__NV_PRIME_RENDER_OFFLOAD = "1"; + #WLR_DRM_DEVICES = mkDefault "/dev/dri/card1:/dev/dri/card0"; + }) + ]; }; }; }