diff --git a/README.md b/README.md index 79d05b4..ef83e02 100644 --- a/README.md +++ b/README.md @@ -21,8 +21,8 @@ libGL error: failed to load driver: swrast NixGL provides a set of wrappers able to launch GL or Vulkan applications: ```bash -$ nixGL program -$ nixVulkan program +nixGL program +nixVulkan program ``` # Installation @@ -32,8 +32,8 @@ $ nixVulkan program To get started, ```bash -$ nix-channel --add https://github.com/nix-community/nixGL/archive/main.tar.gz nixgl && nix-channel --update -$ nix-env -iA nixgl.auto.nixGLDefault # or replace `nixGLDefault` with your desired wrapper +nix-channel --add https://github.com/nix-community/nixGL/archive/main.tar.gz nixgl && nix-channel --update +nix-env -iA nixgl.auto.nixGLDefault # or replace `nixGLDefault` with your desired wrapper ``` Many wrappers are available, depending on your hardware and the graphical API you want to use (i.e. Vulkan or OpenGL). You may want to install a few of them, for example if you want to support OpenGL and Vulkan on a laptop with an hybrid configuration. @@ -84,7 +84,6 @@ nix profile install github:guibou/nixGL --impure This will result in a lighter download and execution time. Also, this evaluation is pure. - #### Error about experimental features You can directly use: @@ -98,6 +97,7 @@ Or set the appropriate conf in `~/.config/nix/nix.conf` / `/etc/nix/nix.conf` / #### Error with GLIBC version if you get errors with messages similar to + ``` /nix/store/g02b1lpbddhymmcjb923kf0l7s9nww58-glibc-2.33-123/lib/libc.so.6: version `GLIBC_2.34' not found (required by /nix/store/hrl51nkr7dszlwcs29wmyxq0jsqlaszn-libglvnd-1.4.0/lib/libGLX.so.0) ``` @@ -108,7 +108,6 @@ It means that there's a mismatch between the versions of `nixpkgs` used by `nixG Add nixGL as a flake input: - ```Nix { inputs = { @@ -134,12 +133,40 @@ Then, use the flake's `overlay` attr: } ``` +### Install from RHEL repository (Rocky, CentOS, Fedora, etc.) + +On RHEL the NVIDIA driver is typically installed via the official NVIDIA driver repositories. Trying to install the driver from the download site will commonly fail with a 404 error. This is due to the fact that NVIDIA is not providing consistent versions of their drivers across distribution channels, so you might have a driver version installed on your system that is not available on the download site. Therefore on RHEL distros the driver should be retrieved from the RHEL repository, and extracted from an official `.rpm`. + +To get the driver from the RHEL `.rpm` instead of the driver download site, simply set `driverSource` to `rhel`. Also ensure that `enable32bits` is changed from its default to `false`, as a 32bit version of the driver is not included. Here's an example flake using +the nixGL overlay with `home-manager`: + +```nix +{ + home.packages = with pkgs; [ + (nixgl.override { + driverSource = "rhel"; + enable32bits = false; + }).auto.nixGLDefault + (config.lib.nixGL.wrap ghostty) + ]; + + nixGL = { + packages = pkgs.nixgl.override { + driverSource = "rhel"; + enable32bits = false; + rhelMajorVersion = 10; + }; + defaultWrapper = "nvidia"; + }; +}; +``` + ## Installation from source ```bash -$ git clone https://github.com/nix-community/nixGL -$ cd nixGL -$ nix-env -f ./ -iA +git clone https://github.com/nix-community/nixGL +cd nixGL +nix-env -f ./ -iA ``` # Usage @@ -149,17 +176,17 @@ Just launch the program you want prefixed by the right wrapper. For example, for OpenGL programs: ```bash -$ nixGL program args # For the `nixGLDefault` wrapper, recommended. -$ nixGLNvidia program args -$ nixGLIntel program args -$ nixGLNvidiaBumblebee program args +nixGL program args # For the `nixGLDefault` wrapper, recommended. +nixGLNvidia program args +nixGLIntel program args +nixGLNvidiaBumblebee program args ``` For Vulkan programs: ```bash -$ nixVulkanNvidia program args -$ nixVulkanIntel program args +nixVulkanNvidia program args +nixVulkanIntel program args ``` # OpenGL - Hybrid Intel + Nvidia laptop @@ -176,7 +203,7 @@ OpenGL version string: 4.6.0 NVIDIA 390.25 If the program you'd like to run is already installed by nix in your current environment, you can simply run it with the wrapper, for example: ```bash -$ nixGLIntel blender +nixGLIntel blender ``` # Vulkan - Intel GPU @@ -216,7 +243,6 @@ nix-build -A auto.nixGLNvidia --argstr nvidiaVersion 440.82 (or `nixGLNvidiaBumblebee`, `nixVulkanNividia`) - The version of your driver can be found using `glxinfo` from your system default package manager, or `nvidia-settings`. ## On nixOS diff --git a/nixGL.nix b/nixGL.nix index e8556c8..0ff8b35 100644 --- a/nixGL.nix +++ b/nixGL.nix @@ -9,14 +9,18 @@ nvidiaHash ? null, # /proc/driver/nvidia/version. Nix doesn't like zero-sized files (see # https://github.com/NixOS/nix/issues/3539 ). nvidiaVersionFile ? null, +# Nvidia driver source selection: "driver" (default) or "rhel" (downloads RPMs from NVIDIA's RHEL repo) +driverSource ? "driver", +# RHEL major version (e.g., 9 or 10) for NVIDIA RPM URLs. User must set this if using driverSource = "rhel" +rhelMajorVersion ? 10, # Enable 32 bits driver # This is one by default, you can switch it to off if you want to reduce a # bit the size of nixGL closure. -enable32bits ? stdenv.hostPlatform.isx86 -, stdenv, writeTextFile, shellcheck, pcre, runCommand, linuxPackages -, fetchurl, lib, runtimeShell, bumblebee, libglvnd, vulkan-validation-layers -, mesa, libvdpau-va-gl, intel-media-driver, pkgsi686Linux, driversi686Linux -, zlib, libdrm, xorg, wayland, gcc, zstd }: +enable32bits ? stdenv.hostPlatform.isx86, stdenv, writeTextFile, shellcheck +, pcre, runCommand, linuxPackages, fetchurl, lib, runtimeShell, bumblebee +, libglvnd, vulkan-validation-layers, mesa, libvdpau-va-gl, intel-media-driver +, pkgsi686Linux, driversi686Linux, zlib, libdrm, xorg, wayland, gcc, zstd, rpm +, cpio }: let writeExecutable = { name, text }: @@ -37,7 +41,8 @@ let ''; }; - writeNixGL = name: vadrivers: writeExecutable { + writeNixGL = name: vadrivers: + writeExecutable { inherit name; # add the 32 bits drivers if needed text = let @@ -51,25 +56,81 @@ let ''); in '' #!${runtimeShell} - export LIBGL_DRIVERS_PATH=${lib.makeSearchPathOutput "lib" "lib/dri" mesa-drivers} - export LIBVA_DRIVERS_PATH=${lib.makeSearchPathOutput "out" "lib/dri" (mesa-drivers ++ vadrivers)} - ${''export __EGL_VENDOR_LIBRARY_FILENAMES=${mesa.drivers}/share/glvnd/egl_vendor.d/50_mesa.json${ - lib.optionalString enable32bits - ":${pkgsi686Linux.mesa.drivers}/share/glvnd/egl_vendor.d/50_mesa.json" - }"''${__EGL_VENDOR_LIBRARY_FILENAMES:+:$__EGL_VENDOR_LIBRARY_FILENAMES}"'' + export LIBGL_DRIVERS_PATH=${ + lib.makeSearchPathOutput "lib" "lib/dri" mesa-drivers } - export LD_LIBRARY_PATH=${lib.makeLibraryPath mesa-drivers}:${lib.makeSearchPathOutput "lib" "lib/vdpau" libvdpau}:${glxindirect}/lib:${lib.makeLibraryPath [libglvnd]}"''${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" + export LIBVA_DRIVERS_PATH=${ + lib.makeSearchPathOutput "out" "lib/dri" (mesa-drivers ++ vadrivers) + } + ${'' + export __EGL_VENDOR_LIBRARY_FILENAMES=${mesa.drivers}/share/glvnd/egl_vendor.d/50_mesa.json${ + lib.optionalString enable32bits + ":${pkgsi686Linux.mesa.drivers}/share/glvnd/egl_vendor.d/50_mesa.json" + }"''${__EGL_VENDOR_LIBRARY_FILENAMES:+:$__EGL_VENDOR_LIBRARY_FILENAMES}"''} + export LD_LIBRARY_PATH=${lib.makeLibraryPath mesa-drivers}:${ + lib.makeSearchPathOutput "lib" "lib/vdpau" libvdpau + }:${glxindirect}/lib:${ + lib.makeLibraryPath [ libglvnd ] + }"''${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" exec "$@" ''; }; + top = rec { - /* - It contains the builder for different nvidia configuration, parametrized by - the version of the driver and sha256 sum of the driver installer file. + /* It contains the builder for different nvidia configuration, parametrized by + the version of the driver and sha256 sum of the driver installer file. */ nvidiaPackages = { version, sha256 ? null }: rec { - nvidiaDrivers = (linuxPackages.nvidia_x11.override { }).overrideAttrs - (oldAttrs: rec { + + # download rpm packages if RHEL is selected as driver source + rpmLibs = if driverSource == "rhel" then + builtins.fetchurl { + url = + "https://developer.download.nvidia.com/compute/cuda/repos/rhel${toString rhelMajorVersion}/x86_64/nvidia-driver-libs-${version}-1.el${toString rhelMajorVersion}.x86_64.rpm"; + } + else + null; + + # also get the ml library if RHEL is selected as driver source, required by btop and other tools + rpmMl = if driverSource == "rhel" then + builtins.fetchurl { + url = + "https://developer.download.nvidia.com/compute/cuda/repos/rhel${toString rhelMajorVersion}/x86_64/libnvidia-ml-${version}-1.el${toString rhelMajorVersion}.x86_64.rpm"; + } + else + null; + + # Extract NVIDIA shared libraries from RPM + nvidiaFromRpm = stdenv.mkDerivation { + pname = "nvidia"; + name = "nvidia-${version}-nixGL-rpm"; + version = version; + preferLocalBuild = true; + allowSubstitutes = false; + nativeBuildInputs = [ rpm cpio ]; + srcs = [ rpmLibs rpmMl ]; + unpackPhase = '' + mkdir -p $TMPDIR + cp ${rpmLibs} $TMPDIR/nvidia-driver-libs.rpm + cp ${rpmMl} $TMPDIR/libnvidia-ml.rpm + ''; + buildPhase = '' + mkdir -p $out $out/lib $out/share + cd $TMPDIR + + rpm2cpio nvidia-driver-libs.rpm | cpio -idmv + mv usr/lib64/* $out/lib + mv usr/share/* $out/share + + rpm2cpio libnvidia-ml.rpm | cpio -idmv + mv usr/lib64/* $out/lib + ''; + }; + + nvidiaDrivers = if driverSource == "rhel" then + null + else + (linuxPackages.nvidia_x11.override { }).overrideAttrs (oldAttrs: rec { pname = "nvidia"; name = "nvidia-x11-${version}-nixGL"; inherit version; @@ -81,13 +142,16 @@ let else builtins.fetchurl url; useGLVND = true; - nativeBuildInputs = oldAttrs.nativeBuildInputs or [] ++ [zstd]; + nativeBuildInputs = oldAttrs.nativeBuildInputs or [ ] ++ [ zstd ]; }); - nvidiaLibsOnly = nvidiaDrivers.override { - libsOnly = true; - kernel = null; - }; + nvidiaLibsOnly = if driverSource == "rhel" then + nvidiaFromRpm + else + (nvidiaDrivers.override { + libsOnly = true; + kernel = null; + }); nixGLNvidiaBumblebee = writeExecutable { name = "nixGLNvidiaBumblebee-${version}"; @@ -120,20 +184,20 @@ let ${lib.optionalString (api == "Vulkan") "export VK_LAYER_PATH=${vulkan-validation-layers}/share/vulkan/explicit_layer.d"} NVIDIA_JSON=(${nvidiaLibsOnly}/share/glvnd/egl_vendor.d/*nvidia.json) - ${lib.optionalString enable32bits "NVIDIA_JSON32=(${nvidiaLibsOnly.lib32}/share/glvnd/egl_vendor.d/*nvidia.json)"} + ${lib.optionalString enable32bits + "NVIDIA_JSON32=(${nvidiaLibsOnly.lib32}/share/glvnd/egl_vendor.d/*nvidia.json)"} - ${''export __EGL_VENDOR_LIBRARY_FILENAMES=''${NVIDIA_JSON[*]}${ - lib.optionalString enable32bits - '':''${NVIDIA_JSON32[*]}'' - }"''${__EGL_VENDOR_LIBRARY_FILENAMES:+:$__EGL_VENDOR_LIBRARY_FILENAMES}"'' - } + ${'' + export __EGL_VENDOR_LIBRARY_FILENAMES=''${NVIDIA_JSON[*]}${ + lib.optionalString enable32bits ":\${NVIDIA_JSON32[*]}" + }"''${__EGL_VENDOR_LIBRARY_FILENAMES:+:$__EGL_VENDOR_LIBRARY_FILENAMES}"''} ${ - lib.optionalString (api == "Vulkan") - ''export VK_ICD_FILENAMES=${nvidiaLibsOnly}/share/vulkan/icd.d/nvidia_icd.x86_64.json${ - lib.optionalString enable32bits - ":${nvidiaLibsOnly.lib32}/share/vulkan/icd.d/nvidia_icd.i686.json" - }"''${VK_ICD_FILENAMES:+:$VK_ICD_FILENAMES}"'' + lib.optionalString (api == "Vulkan") '' + export VK_ICD_FILENAMES=${nvidiaLibsOnly}/share/vulkan/icd.d/nvidia_icd.x86_64.json${ + lib.optionalString enable32bits + ":${nvidiaLibsOnly.lib32}/share/vulkan/icd.d/nvidia_icd.i686.json" + }"''${VK_ICD_FILENAMES:+:$VK_ICD_FILENAMES}"'' } export LD_LIBRARY_PATH=${ lib.makeLibraryPath ([ libglvnd nvidiaLibsOnly ] @@ -154,12 +218,10 @@ let nixVulkanNvidia = nixNvidiaWrapper "Vulkan"; }; + nixGLMesa = writeNixGL "nixGLMesa" [ ]; - nixGLMesa = writeNixGL "nixGLMesa" [ ]; - - nixGLIntel = writeNixGL "nixGLIntel" - ([ intel-media-driver ] - ++ lib.optionals enable32bits [ pkgsi686Linux.intel-media-driver ]); + nixGLIntel = writeNixGL "nixGLIntel" ([ intel-media-driver ] + ++ lib.optionals enable32bits [ pkgsi686Linux.intel-media-driver ]); nixVulkanMesa = writeExecutable { name = "nixVulkanIntel"; @@ -236,7 +298,7 @@ let versionMatch = builtins.match ".*Module ([0-9.]+) .*" data; in if versionMatch != null then builtins.head versionMatch else null; - autoNvidia = nvidiaPackages {version = nvidiaVersionAuto; }; + autoNvidia = nvidiaPackages { version = nvidiaVersionAuto; }; in rec { # The output derivation contains nixGL which point either to # nixGLNvidia or nixGLIntel using an heuristic.