Need help with writing my configuration for nvidia dgpu

i want my base config(the one that is booted automatically into) to NOT use the dgpu at all, and i want a specialisation that has nvidia enabled for full power consumption(i have a laptop).
i have attatched both files below.
The problem i am facing is that, the default config is still using nouveau even though it is blacklisted. gaming-time is working well.

# default.nix
boot = {
    extraModprobeConfig = lib.mkDefault ''
      blacklist nouveau
      options nouveau modeset=0
    '';
    blacklistedKernelModules = lib.mkDefault [
      "nouveau"
      "nvidia"
      "nvidiafb"
      "nvidia_drm"
      "nvidia-uvm"
      "nvidia_modeset"
      "nv"
      "rivafb"
      "rivatv"
      "ipmi_msghandler"
      "ipmi_devintf"
    ];
  };

  services.udev.extraRules = lib.mkDefault ''
    # Remove NVIDIA USB xHCI Host Controller devices, if present
    ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x0c0330", ATTR{power/control}="auto", ATTR{remove}="1"
    # Remove NVIDIA USB Type-C UCSI devices, if present
    ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x0c8000", ATTR{power/control}="auto", ATTR{remove}="1"
    # Remove NVIDIA Audio devices, if present
    ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x040300", ATTR{power/control}="auto", ATTR{remove}="1"
    # Remove NVIDIA VGA/2D controller devices
    ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x03[0-9]*", ATTR{power/control}="auto", ATTR{remove}="1"
  '';
};
# gamig-time.nix
{
  lib,
  pkgs,
  config,
  ...
}: {
  specialisation = {
    gaming-time.configuration = {
      hardware.nvidia-container-toolkit.enable = true;
      services.xserver.videoDrivers = lib.mkForce ["nvidia"];

      hardware.graphics = {
        enable = true;
        enable32Bit = true;
        extraPackages = with pkgs; [
          # https://discourse.nixos.org/t/nvidia-open-breaks-hardware-acceleration/58770/2
          nvidia-vaapi-driver
          vaapiVdpau
          libvdpau
          libvdpau-va-gl
          vdpauinfo
          libva
          libva-utils
          # https://wiki.nixos.org/wiki/Intel_Graphics
          #vpl-gpu-rt
        ];
      };

      hardware.nvidia = {
        # This will no longer be necessary when
        # https://github.com/NixOS/nixpkgs/pull/326369 hits stable
        #modesetting.enable = true;
        modesetting.enable = lib.mkForce true;
        dynamicBoost.enable = true;
        prime = {
          amdgpuBusId = "PCI:5:0:0";
          nvidiaBusId = "PCI:1:0:0";
        };
        nvidiaSettings = true;
        # package = config.boot.kernelPackages.nvidiaPackages.beta;
        open = lib.mkForce true; #https://wiki.nixos.org/wiki/NVIDIA#cite_note-1
        package = config.boot.kernelPackages.nvidiaPackages.mkDriver {
          version = "570.86.16"; # use new 570 drivers
          sha256_64bit = "sha256-RWPqS7ZUJH9JEAWlfHLGdqrNlavhaR1xMyzs8lJhy9U=";
          openSha256 = "sha256-DuVNA63+pJ8IB7Tw2gM4HbwlOh1bcDg2AN2mbEU9VPE=";
          settingsSha256 = "sha256-9rtqh64TyhDF5fFAYiWl3oDHzKJqyOW3abpcf2iNRT8=";
          usePersistenced = false;
        };

        prime.reverseSync.enable = lib.mkForce true;
        powerManagement.enable = lib.mkForce false;
        powerManagement.finegrained = lib.mkForce false;
        prime.offload = {
          enable = lib.mkForce false;
          enableOffloadCmd = lib.mkForce false;
        };
      };

      boot = {
        # kernelPackages = lib.mkForce pkgs.linuxKernel.packages.linux_xanmod;
        # kernelPackages = pkgs.linuxPackages_6_6; # use 6.6 LTS kernel

        kernelParams = lib.mkMerge [
          ["nvidia-drm.fbdev=1"]
          [
            "nvidia.NVreg_UsePageAttributeTable=1" # why this isn't default is beyond me.
            "nvidia_modeset.disable_vrr_memclk_switch=1" # stop really high memclk when vrr is in use.
          ]
          (lib.mkIf config.hardware.nvidia.powerManagement.enable [
            "nvidia.NVreg_TemporaryFilePath=/var/tmp" # store on disk, not /tmp which is on RAM
          ])
        ];

        blacklistedKernelModules = ["nouveau"];
        kernelModules = ["nvidia-uvm"];
      };

      environment = {
        systemPackages = (
          with pkgs; [
            # nvidia-vaapi-driver
            # # libva
            # libva-utils
            # nvidia-utils
            # # libvdpau-va-gl
            # # vaapiVdpau
            # # libva-vdpau-driver
            nvtopPackages.full
            # nvidia-container-toolkit
          ]
        );
        # sessionVariables = {
        #   "__EGL_VENDOR_LIBRARY_FILENAMES" = "${config.hardware.nvidia.package}/share/glvnd/egl_vendor.d/10_nvidia.json";
        # };

        variables = {
          # https://discourse.nixos.org/t/nvidia-open-breaks-hardware-acceleration/58770/12?u=randomizedcoder
          # https://gist.github.com/chrisheib/162c8cad466638f568f0fb7e5a6f4f6b#file-config-nix-L193
          MOZ_DISABLE_RDD_SANDBOX = "1";
          LIBVA_DRIVER_NAME = "nvidia";
          GBM_BACKEND = "nvidia-drm";
          NVD_BACKEND = "direct";
          EGL_PLATFORM = "wayland";
          # prevents cursor disappear when using Nvidia drivers
          WLR_NO_HARDWARE_CURSORS = "1";

          MOZ_ENABLE_WAYLAND = "1";
          XDG_SESSION_TYPE = "wayland";
          NIXOS_OZONE_WL = "1";
          __NV_PRIME_RENDER_OFFLOAD = "1";
          __NV_PRIME_RENDER_OFFLOAD_PROVIDER = "NVIDIA-G0";
          __GLX_VENDOR_LIBRARY_NAME = "nvidia";
          __VK_LAYER_NV_optimus = "NVIDIA_only";
        };
      };
    };
  };
}

Have you tried it without the lib.mkDefault?

1 Like

What I understand is: if I want to make an option changeable, I use mkDefault, so I put mkDefault in the base config. If I want to override the base config, I use mkForce, which i used in gaming-time.

No, that’s not what it does.
Only the highest priority is picked, and if you have other definitions of that option that have higher priority than mkDefault (1000) then your mkDefault definitions will get ignored. See https://nixos.org/manual/nixos/stable/#sec-option-definitions-setting-priorities.

The only reason to use mkDefault (1000) is so that mkForce (50) isn’t necessary when overriding. If you’re going to use mkForce then you might as well remove the mkDefault (especially since you might be using other modules that don’t use mkDefault).

what i had in mind was,
i set base as nvidia off, and added a specialisation, it is like a branch in git. when i boot into default, its options are used. but when i select the specialisation, it will be like the follows,

option number 1 2 3 4
default a b c d
spec x y
boot into default a b c d
boot into spec a x y d

also another doubt, if i do like

boot.kernelModules = mkDefault [ a,b,c];

and then

boot.kernelModules = mkForce [ a2, b2];

will the individual [ ] be checked or it will be merged like [ a2, b2, c] ?

The highest priority (i.e. the lowest priority #) is picked, then the merging happens. Your mkDefault setting will be ignored entirely. If you want values to merge, they all need to be the same priority. That’s why I linked the manual, I suggest you read it.

i’ll look more into the documentation, thanks for the heads up.

if i’m not wrong, if i set
services.xserver.videoDrivers = lib.mkForce ["nvidia"];
and
services.xserver.videoDrivers = lib.mkForce ["modesetting"];
it gives an error and doesnt merge

And what is the error?

it is like this,

Then it seems services.xserver.videoDrivers is a special option, you should only have one option enabled.
I don’t know why it’s even a list-type option in that case.

also, what do i do about this?

 error: A definition for option `specialisation.gaming-time.configuration.boot.kernelParams' is not of type `list of string, with spaces inside double quotes'. Definition values:
       - In `/nix/store/6qrxk1h713197fav0iy31908gdy588yn-source/modules/gaming/specialisation.nix':
           {
             _type = "merge";
             contents = [
               [
                 "nvidia-drm.fbdev=1"
           ...

with code

# gaming-time.nix
boot = lib.mkForce {
        # kernelPackages = lib.mkForce pkgs.linuxKernel.packages.linux_xanmod;
        # kernelPackages = pkgs.linuxPackages_6_6; # use 6.6 LTS kernel

        kernelParams = lib.mkMerge [
          ["nvidia-drm.fbdev=1"]
          [
            "nvidia.NVreg_UsePageAttributeTable=1" # why this isn't default is beyond me.
            "nvidia_modeset.disable_vrr_memclk_switch=1" # stop really high memclk when vrr is in use.
          ]
          (lib.mkIf config.hardware.nvidia.powerManagement.enable [
            "nvidia.NVreg_TemporaryFilePath=/var/tmp" # store on disk, not /tmp which is on RAM
          ])
        ];

        blacklistedKernelModules = ["nouveau"];
        kernelModules = ["nvidia-uvm"];
      };