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
This commit is contained in:
ccicnce113424
2026-03-11 02:10:10 +08:00
parent d8f2a8e00b
commit 78f6ee7ba2
2 changed files with 53 additions and 19 deletions
+46 -4
View File
@@ -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 ];
}
+7 -15
View File
@@ -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