From 78f6ee7ba2ff786906dc3525a97f52c5912cc042 Mon Sep 17 00:00:00 2001 From: ccicnce113424 Date: Wed, 11 Mar 2026 02:10:10 +0800 Subject: [PATCH] nixos/nvidia: utilize ICD libraries built from source This changes the NVIDIA NixOS module to use ICD libraries built from source rather than relying on the pre-compiled bundled versions. Additionally, this adds a necessary workaround for driver versions below 595 to ensure proper compatibility. For more context on the workaround, see the discussion at: https://github.com/NixOS/nixpkgs/pull/497342#issuecomment-4034876793 --- nixos/modules/hardware/video/nvidia.nix | 50 ++++++++++++++++++-- pkgs/os-specific/linux/nvidia-x11/builder.sh | 22 +++------ 2 files changed, 53 insertions(+), 19 deletions(-) diff --git a/nixos/modules/hardware/video/nvidia.nix b/nixos/modules/hardware/video/nvidia.nix index 6aebb9faba53..2d49a937a277 100644 --- a/nixos/modules/hardware/video/nvidia.nix +++ b/nixos/modules/hardware/video/nvidia.nix @@ -401,10 +401,52 @@ in KERNEL=="nvidia_uvm", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-uvm c $$(grep nvidia-uvm /proc/devices | cut -d \ -f 1) 0'" KERNEL=="nvidia_uvm", RUN+="${pkgs.runtimeShell} -c 'mknod -m 666 /dev/nvidia-uvm-tools c $$(grep nvidia-uvm /proc/devices | cut -d \ -f 1) 1'" ''; - hardware.graphics = { - extraPackages = [ nvidia_x11.out ]; - extraPackages32 = [ nvidia_x11.lib32 ]; - }; + hardware.graphics = + let + icd = [ + "egl-wayland" + ] + # GBM support was added in 495. + ++ lib.optionals (lib.versionAtLeast nvidia_x11.version "495") [ + "egl-gbm" + ] + # ICDs below use a new driver interface, which is added in the 560 series drivers. + ++ lib.optionals (lib.versionAtLeast nvidia_x11.version "560") [ + "egl-wayland2" + "egl-x11" + ]; + combineIcdPkgs = + icd: pkgs: + pkgs.symlinkJoin { + name = "nvidia-egl-external-platforms${lib.optionalString pkgs.stdenv.is32bit "-x32"}"; + paths = lib.attrVals icd pkgs; + # Remediate reversed priorities in pre-595 drivers, + # https://github.com/NixOS/nixpkgs/pull/497342#issuecomment-4034876793 + postBuild = lib.optionalString (lib.versionOlder nvidia_x11.version "595") '' + pushd $out/share/egl/egl_external_platform.d + for f in [0-9][0-9]_*; do + num=''${f:0:2} + rest=''${f:2} + new=$(printf "%02d" $((99 - 10#$num))) + mv -- "$f" "tmp-$new$rest" + done + for f in tmp-*; do + mv -- "$f" "''${f#tmp-}" + done + popd + ''; + }; + in + { + extraPackages = [ + nvidia_x11.out + (combineIcdPkgs icd pkgs) + ]; + extraPackages32 = [ + nvidia_x11.lib32 + (combineIcdPkgs icd pkgs.pkgsi686Linux) + ]; + }; environment.systemPackages = [ nvidia_x11.bin ]; } diff --git a/pkgs/os-specific/linux/nvidia-x11/builder.sh b/pkgs/os-specific/linux/nvidia-x11/builder.sh index 12ef9f9e5698..8fa9b8b8fe8b 100755 --- a/pkgs/os-specific/linux/nvidia-x11/builder.sh +++ b/pkgs/os-specific/linux/nvidia-x11/builder.sh @@ -51,6 +51,7 @@ installPhase() { rm -f $i/lib/lib{glx,nvidia-wfb}.so.* # handled separately rm -f $i/lib/libnvidia-gtk* # built from source rm -f $i/lib/libnvidia-wayland-client* # built from source + rm -f $i/lib/libnvidia-egl-* # built from source if [ "$useGLVND" = "1" ]; then # Pre-built libglvnd rm $i/lib/lib{GL,GLX,EGL,GLESv1_CM,GLESv2,OpenGL,GLdispatch}.so.* @@ -79,13 +80,7 @@ installPhase() { else sed -E "s#(libGLX_nvidia)#$i/lib/\\1#" nvidia_icd.json > nvidia_icd.json.fixed fi - - # nvidia currently only supports x86_64 and i686 - if [ "$i" == "$lib32" ]; then - install -Dm644 nvidia_icd.json.fixed $i/share/vulkan/icd.d/nvidia_icd.i686.json - else - install -Dm644 nvidia_icd.json.fixed $i/share/vulkan/icd.d/nvidia_icd.x86_64.json - fi + install -Dm644 nvidia_icd.json.fixed $i/share/vulkan/icd.d/nvidia_icd.json fi if [ -e nvidia_layers.json ]; then @@ -95,17 +90,14 @@ installPhase() { # EGL if [ "$useGLVND" = "1" ]; then - mkdir -p "$i/share/egl/egl_external_platform.d" - for icdname in $(find . -name '*_nvidia*.json') - do - cat "$icdname" | jq ".ICD.library_path |= \"$i/lib/\(.)\"" | tee "$i/share/egl/egl_external_platform.d/$icdname" - done - # glvnd icd mkdir -p "$i/share/glvnd/egl_vendor.d" - mv "$i/share/egl/egl_external_platform.d/10_nvidia.json" "$i/share/glvnd/egl_vendor.d/10_nvidia.json" + for icdname in "10_nvidia.json"; + do + cat "$icdname" | jq ".ICD.library_path |= \"$i/lib/\(.)\"" | tee "$i/share/glvnd/egl_vendor.d/$icdname" + done - if [[ -f "$i/share/egl/egl_external_platform.d/15_nvidia_gbm.json" ]]; then + if [[ -f "15_nvidia_gbm.json" ]]; then mkdir -p $i/lib/gbm ln -s $i/lib/libnvidia-allocator.so $i/lib/gbm/nvidia-drm_gbm.so fi