Skip to content

Add ability to get driver from NVIDIA's official RHEL repository, to avoid version issues #197

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 42 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.
Expand Down Expand Up @@ -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:
Expand All @@ -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)
```
Expand All @@ -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 = {
Expand All @@ -134,12 +133,39 @@ 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;
};
defaultWrapper = "nvidia";
};
};
```

## Installation from source

```bash
$ git clone https://github.com/nix-community/nixGL
$ cd nixGL
$ nix-env -f ./ -iA <your desired wrapper name>
git clone https://github.com/nix-community/nixGL
cd nixGL
nix-env -f ./ -iA <your desired wrapper name>
```

# Usage
Expand All @@ -149,17 +175,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
Expand All @@ -176,7 +202,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
Expand Down Expand Up @@ -216,7 +242,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
Expand Down
141 changes: 101 additions & 40 deletions nixGL.nix
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,17 @@ 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) which will attempt to download .run file from NVIDIA's driver site
# or "rhel", which downloads the RPM packages from NVIDIA's RHEL repository, ensuring a version match in RHEL systems like Rocky Linux, Fedora or CentOS.
driverSource ? "driver",
# 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 }:
Expand All @@ -37,7 +40,8 @@ let
'';
};

writeNixGL = name: vadrivers: writeExecutable {
writeNixGL = name: vadrivers:
writeExecutable {
inherit name;
# add the 32 bits drivers if needed
text = let
Expand All @@ -51,25 +55,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/rhel9/x86_64/nvidia-driver-libs-${version}-1.el9.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/rhel9/x86_64/libnvidia-ml-${version}-1.el9.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;
Expand All @@ -81,13 +141,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}";
Expand Down Expand Up @@ -120,20 +183,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 ]
Expand All @@ -154,12 +217,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";
Expand Down Expand Up @@ -236,7 +297,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.
Expand Down
Loading