Compare commits

..

2 Commits

Author SHA1 Message Date
Guillaume Bouchard
758ac7f57b Add documentation for legacy driver now that we switch to GLVND 2018-07-10 03:33:40 +02:00
Guillaume Bouchard
103e0cd30b Use GLVND
This fixes missing symbols
2018-07-10 03:07:48 +02:00
10 changed files with 262 additions and 558 deletions

View File

@ -1,13 +0,0 @@
name: 'Test'
on: [ push, pull_request ]
jobs:
test:
name: 'Test'
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
- uses: cachix/install-nix-action@v8
- run: nix-build all.nix

1
.gitignore vendored
View File

@ -1 +0,0 @@
/result

218
README.md
View File

@ -1,15 +1,29 @@
# NixGL This tool tries to solve the "OpenGL" problem on nix. Works with Nvidia cards (with bumblebee) and most of the card supported by mesa (such as Intel, AMD and nouveau using the free driver). It works for Vulkan programs too.
NixGL solve the "OpenGL" problem with [nix](https://nixos.org/nix/). Works all mesa # Quick start
drivers (intel cards and "free" version fro Nvidia or AMD cards), Nvidia
proprietary drivers, even with hybrid configuration (with bumblebee). It works Suppose you have a configuration with an nvidia card, host driver version `390.25`
for Vulkan programs too.
```
# clone the repository
git clone https://github.com/guibou/nixGL
cd nixGL
# build and install the wrapper
./nvidiaInstall.py 390.25 nixGLNvidia
# install the wrapper
nix-env -i ./result
# use it with any OpenGL application
nixGLNvidia blender
```
# Motivation # Motivation
You use Nix on any distribution, and any GL application installed fails with this error: You use Nix on any distribution, and any GL application installed fails with this error:
```bash ```
$ program $ program
libGL error: unable to load driver: i965_dri.so libGL error: unable to load driver: i965_dri.so
libGL error: driver pointer missing libGL error: driver pointer missing
@ -21,87 +35,117 @@ libGL error: unable to load driver: swrast_dri.so
libGL error: failed to load driver: swrast libGL error: failed to load driver: swrast
``` ```
NixGL provides a set of wrappers able to launch GL or Vulkan applications: This library contains a wrapper which is able to launch GL or Vulkan applications:
```bash ```
$ nixGLXXX program nixGLXXX program
$ nixVulkanXXX program nixVulkanXXX program
``` ```
# Installation # Installation / Usage
Clone this git repository: Clone this git repository:
```bash ```
$ git clone https://github.com/guibou/nixGL git clone https://github.com/guibou/nixGL
$ cd nixGL cd nixGL
``` ```
Many wrappers are available, depending on your hardware and the graphical API ## Optional (if NVIDIA): Grab your NVIDIA driver version
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.
## OpenGL wrappers Using `glxinfo` from your host system, grab the driver version, here `390.25`:
- `nix-env -f ./ -iA nixGLIntel`: Mesa OpenGL implementation (intel, amd, nouveau, ...). ```
- `nix-env -f ./ -iA nixGLNvidiaBumblebee`: Proprietary Nvidia driver on hybrid hardware. $ glxinfo | grep NVIDIA
- `nix-env -f ./ -iA nixGLNvidia`: Proprietary Nvidia driver. ...
- `nix-env -f ./ -iA nixGLDefault`: Tries to auto-detect and install Nvidia, OpenGL core profile version string: 4.5.0 NVIDIA 390.25
if not, fallback to mesa. ...
```
## Vulkan wrappers ## Build
- `nix-env -f ./ -iA nixVulkanNvidia`: Proprietary Nvidia driver. ### For mesa (intel, amd, nouveau, ...)
- `nix-env -f ./ -iA nixVulkanIntel`: Mesa Vulkan implementation.
For mesa (intel, amd, nouveau) GL, the package is historically called `nixGLIntel`:
```
nix-build -A nixGLIntel
```
For Intel Vulkan:
```
nix-build -A nixVulkanIntel
```
### For nvidia
Due to some restriction on `nix` 2.0, the `nix-build` must be called with a wrapper script.
For NVIDIA GL alone:
```
./nvidiaInstall.py 390.25 nixGLNvidia
```
For NVIDIA Vulkan alone:
Note that the NVIDIA GL and Vulkan wrappers are identical aside from the name
```
./nvidiaInstall.py 390.25 nixVulkanNvidia
```
(replace `390.25` with the host driver version gathered earlier.)
For Nvidia with bumblebee:
```
./nvidiaInstall.py 390.25 nixGLNvidiaBumblebee
```
(replace `390.25` with the host driver version gathered earlier.)
## Install
The previous commands only build the wrapper, now stored inside `./result`, you need to install it:
```
nix-env -i ./result
```
(Note, you can iterate many time on this process to install as many driver as needed. Common example are `nixGLIntel` with `nixGLNvidiaBumblebee`)
The Vulkan wrapper also sets `VK_LAYER_PATH` the validation layers in the nix store.
# Usage # Usage
Just launch the program you want prefixed by the right wrapped. For GL programs
For OpenGL programs: ```
nixGLXXX program args
```bash
$ nixGLXXX program args
``` ```
For Vulkan programs: For Vulkan programs
```bash ```
$ nixVulkanXXX program args nixVulkanXXX program args
``` ```
Replace `XXX` by the implementation pour previously selected, such as `nixGLIntel` or `nixGLNvidia`. For example (on my dual GPU laptop):
## Examples
# OpenGL - Hybrid Intel + Nvidia laptop
After installing `nixGLIntel` and `nixGLNvidiaBumblebee`.
```bash ```bash
$ nixGLIntel $(nix run nixpkgs.glxinfo -c glxinfo) | grep -i 'OpenGL version string' $ nixGLIntel glxinfo | grep -i 'OpenGL version string'
OpenGL version string: 3.0 Mesa 17.3.3 OpenGL version string: 3.0 Mesa 17.3.3
$ nixGLNvidiaBumblebee $(nix run nixpkgs.glxinfo -c glxinfo) | grep -i 'OpenGL version string' $ nixGLNvidiaBumblebee glxinfo | grep -i 'OpenGL version string'
OpenGL version string: 4.6.0 NVIDIA 390.25 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: Another example (on an XPS 9560 with the Intel GPU selected):
```bash
$ nixGLIntel blender
```
# Vulkan - Intel GPU
After installing `nixVulkanIntel`.
```bash ```bash
$ sudo apt install mesa-vulkan-drivers $ sudo apt install mesa-vulkan-drivers
... ...
$ nixVulkanIntel $(nix-build '<nixpkgs>' --no-out-link -A vulkan-tools)/bin/vulkaninfo | grep VkPhysicalDeviceProperties -A 7 $ nixVulkanIntel $(nix-build '<nixpkgs>' --no-out-link -A vulkan-loader)/bin/vulkaninfo | grep VkPhysicalDeviceProperties -A 7
VkPhysicalDeviceProperties: VkPhysicalDeviceProperties:
=========================== ===========================
apiVersion = 0x400036 (1.0.54) apiVersion = 0x400036 (1.0.54)
@ -112,38 +156,34 @@ VkPhysicalDeviceProperties:
deviceName = Intel(R) HD Graphics 630 (Kaby Lake GT2) deviceName = Intel(R) HD Graphics 630 (Kaby Lake GT2)
``` ```
# Limitations
Does not work now for AMD drivers because I dont' have the hardware.
# Comparaison with similar tools
[nix-install-vendor-gl.sh](https://github.com/deepfire/nix-install-vendor-gl)
provides a similar system with a different approach:
- it auto detect the host driver
- it needs root access and set your system for a specific driver
- it only provides wrappers for nvidia (without bumblebee)
Both projects are now really similar and the only reason I did not
contributed to `nix-install-vendor-gl.sh` was because initial `nixGL`
had a totally different approach.
# Troubleshooting # Troubleshooting
## Nvidia auto detection does not work If by any chance it does not work, you need to install nixGL using the same nixpkgs checkout than the one of your application. For example:
```bash ```bash
building '/nix/store/ijs5h6h07faai0k74diiy5b2xlxh891g-auto-detect-nvidia.drv'... NIX_PATH=nixpkgs=https://github.com/nixos/nixpkgs/archive/94d80eb72474bf8243b841058ce45eac2b163943.tar.gz nix build -f ./default.nix nixGLIntel
pcregrep: Failed to open /proc/driver/nvidia/ersion: No such file or directory
builder for '/nix/store/ijs5h6h07faai0k74diiy5b2xlxh891g-auto-detect-nvidia.drv' failed with exit code 2
error: build of '/nix/store/ijs5h6h07faai0k74diiy5b2xlxh891g-auto-detect-nvidia.drv' faile
``` ```
You can run the Nvidia installer using an explicit version string instead of the automatic detection method: # Old nvidia drivers
```bash Users of nvidia legacy driver should use the `backport/noGLVND` branch.
nix-build -A nixGLNvidia --argstr nvidiaVersion 440.82
```
The version of your driver can be found using `glxinfo` from your system default package manager, or `nvidia-settings`.
## On nixOS
`nixGL` can also be used on nixOS if the system is installed with a different
nixpkgs clone than the one your application are installed with. Override the
`pkgs` argument of the script with the correct nixpkgs clone:
```bash
nix-build ./default.nix -A nixGLIntel --arg pkgs "import path_to_your_nixpkgs {}".
```
## Old nvidia drivers
Users of Nvidia legacy driver should use the `backport/noGLVND` branch. This branch is not tested and may not work well, please open a bug report, it will be taken care of as soon as possible.
# `nixGLCommon` # `nixGLCommon`
@ -153,21 +193,3 @@ For example:
``` ```
nix-build -E "with import ./default.nix {}; nixGLCommon nixGLIntel" nix-build -E "with import ./default.nix {}; nixGLCommon nixGLIntel"
```
# Using nixGL in your project
# Limitations
`nixGL` is badly tested, mostly because it is difficult to test automatically in a continuous integration context because you need access to different type of hardware.
Some OpenGL configurations may not work, for example AMD proprietary drivers. There is no fundamental limitation, so if you want support for theses configurations, open an issue.
# Hacking
One great way to contribute to nixGL is to run the test suite. Just run
`./Test.hs` in the main directory and check that all the test relevant to your
hardware are green.

110
Test.hs
View File

@ -1,110 +0,0 @@
#!/usr/bin/env nix-shell
#!nix-shell -i runhaskell -p "haskellPackages.ghcWithPackages(p: with p; [hspec process])" -p nix
{-# LANGUAGE OverloadedStrings #-}
import Test.Hspec
import System.Process
import qualified Data.Text as Text
import Data.Text (Text)
import Control.Monad.IO.Class (liftIO)
import Data.List (find)
-- nixos-19-09 is used so hopefully it will have a different libc than
-- the current `<nixpkgs>` used in a current nixOS system, so it will trigger the
-- driver failure.
-- Run `./Test.hs --match "/Sanity/"` to ensure that non wrapped
-- binaries fails on NixOS.
currentChannel = "channel:nixos-19.09-small"
-- | Utils function: run a command and returns its output.
processOutput p args = Text.strip . Text.pack <$> readCreateProcess ((proc (Text.unpack p) (Text.unpack <$> args)) { std_err = Inherit }) ""
-- * OpenGL
-- | Returns the path to the nixGLXXX binary.
getNixGLBin version = (<>("/bin/"<>version)) <$> processOutput "nix-build" ["./", "-A", version, "-I", "nixpkgs=" <> currentChannel]
-- | Returns the vendor string associated with a glxinfo wrapped by a nixGL.
getVendorString io = do
output <- Text.lines <$> io
pure $ Text.unpack <$> find ("OpenGL version string"`Text.isPrefixOf`) output
-- | Checks that a nixGL wrapper works with glxinfo 32 & 64 bits.
checkOpenGL_32_64 glxinfo32 glxinfo64 vendorName nixGLName = do
beforeAll (getNixGLBin nixGLName) $ do
it "32 bits" $ \nixGLBin -> do
Just vendorString <- getVendorString (processOutput nixGLBin [glxinfo32, "-B"])
vendorString `shouldContain` vendorName
it "64 bits" $ \nixGLBin -> do
Just vendorString <- getVendorString (processOutput nixGLBin [glxinfo64, "-B"])
vendorString `shouldContain` vendorName
-- * Vulkan
-- | Heuristic to detect if vulkan work. `driverName` must appears in the output
checkVulkanIsWorking io = do
res <- io
res `shouldSatisfy` ("driverName"`Text.isInfixOf`)
-- | Checks that a nixGL wrapper works with glxinfo 32 & 64 bits.
checkVulkan_32_64 vulkaninfo32 vulkaninfo64 vendorName nixGLName = do
beforeAll (getNixGLBin nixGLName) $ do
it "32 bits" $ \nixGLBin -> do
checkVulkanIsWorking (processOutput nixGLBin [vulkaninfo32])
it "64 bits" $ \nixGLBin -> do
checkVulkanIsWorking (processOutput nixGLBin [vulkaninfo64])
main = do
putStrLn "Running tests for nixGL"
putStrLn "It can take a while, this will build and test all drivers in the background"
glxinfo64 <- (<>"/bin/glxinfo") <$> processOutput "nix-build" [currentChannel, "-A", "glxinfo"]
glxinfo32 <- (<>"/bin/glxinfo") <$> processOutput "nix-build" [currentChannel, "-A", "pkgsi686Linux.glxinfo"]
vulkaninfo64 <- (<>"/bin/vulkaninfo") <$> processOutput "nix-build" [currentChannel, "-A", "vulkan-tools"]
vulkaninfo32 <- (<>"/bin/vulkaninfo") <$> processOutput "nix-build" [currentChannel, "-A", "pkgsi686Linux.vulkan-tools"]
let checkOpenGL = checkOpenGL_32_64 glxinfo32 glxinfo64
checkVulkan = checkVulkan_32_64 vulkaninfo32 vulkaninfo64
hspec $ do
-- This category ensure that tests are failing if not run with nixGL
-- This allows testing on nixOS
describe "Sanity" $ do
describe "OpenGL" $ do
it "fails with unwrapped glxinfo64" $ do
vendorString <- getVendorString (processOutput glxinfo64 ["-B"])
vendorString `shouldBe` Nothing
it "fails with unwrapped glxinfo32" $ do
vendorString <- getVendorString (processOutput glxinfo32 ["-B"])
vendorString `shouldBe` Nothing
describe "Vulkan" $ do
it "fails with unwrapped vulkaninfo64" $ do
processOutput vulkaninfo64 [] `shouldThrow` anyIOException
it "fails with unwrapped vulkaninfo32" $ do
processOutput vulkaninfo32 [] `shouldThrow` anyIOException
describe "NixGL" $ do
describe "Mesa" $ do
describe "OpenGL" $ do
checkOpenGL "Mesa" "nixGLIntel"
describe "Vulkan" $ do
checkVulkan "Mesa" "nixVulkanIntel"
describe "Nvidia - Bumblebee" $ do
describe "OpenGL" $ do
checkOpenGL "NVIDIA" "nixGLNvidiaBumblebee"
xdescribe "Vulkan" $ do
-- Not tested: I don't have the hardware (@guibou)
checkVulkan "NVIDIA" "nixVulkanNvidiaBumblebee"
-- TODO: check Nvidia (I don't have this hardware)
describe "Nvidia" $ do
describe "OpenGL" $ do
checkOpenGL "NVIDIA" "nixGLNvidia"
describe "Vulkan" $ do
checkVulkan "NVIDIA" "nixVulkanNvidia"

16
all.nix
View File

@ -1,16 +0,0 @@
let
pkgs = import <nixpkgs> { config = { allowUnfree = true; }; };
in
{
pure = pkgs.recurseIntoAttrs (pkgs.callPackage ./nixGL.nix {
nvidiaVersion = "440.82";
nvidiaHash = "edd415acf2f75a659e0f3b4f27c1fab770cf21614e84a18152d94f0d004a758e";
});
versionFile = pkgs.recurseIntoAttrs (pkgs.callPackage ./nixGL.nix {
nvidiaVersionFile = pkgs.writeText "nvidia-version-440.82" ''
NVRM version: NVIDIA UNIX x86_64 Kernel Module 440.82 Wed Apr 1 20:04:33 UTC 2020
GCC version: gcc version 9.3.0 (Arch Linux 9.3.0-1)
'';
});
}

129
default.nix Normal file
View File

@ -0,0 +1,129 @@
{ system ? builtins.currentSystem,
nvidiaVersion ? null,
nvidiaHash ? null,
pkgs ? import <nixpkgs>
}:
let
overlay = self: super:
{
linuxPackages = super.linuxPackages //
{
nvidia_x11 = (super.linuxPackages.nvidia_x11.override {
}).overrideAttrs(oldAttrs: rec {
name = "nvidia-${nvidiaVersion}";
src = super.fetchurl {
url = "http://download.nvidia.com/XFree86/Linux-x86_64/${nvidiaVersion}/NVIDIA-Linux-x86_64-${nvidiaVersion}.run";
sha256 = nvidiaHash;
};
useGLVND = true;
});
};
};
nixpkgs = pkgs { overlays = [overlay]; config = {allowUnfree = true;};};
in
with nixpkgs;
rec {
nvidia = linuxPackages.nvidia_x11;
nvidiaLibsOnly = nvidia.override {
libsOnly = true;
kernel = null;
};
nixGLNvidiaBumblebee = runCommand "nixGLNvidiaBumblebee" {
buildInputs = [ nvidia bumblebee ];
meta = with pkgs.stdenv.lib; {
description = "A tool to launch OpenGL application on system other than NixOS - Nvidia bumblebee version";
homepage = "https://github.com/guibou/nixGL";
};
} ''
mkdir -p $out/bin
cat > $out/bin/nixGLNvidiaBumblebee << FOO
#!/usr/bin/env sh
export LD_LIBRARY_PATH=${nvidia}/lib
${bumblebee}/bin/optirun --ldpath ${libglvnd}/lib:${nvidia}/lib "\$@"
FOO
chmod u+x $out/bin/nixGLNvidiaBumblebee
'';
nixNvidiaWrapper = api: runCommand "nix${api}Nvidia" {
buildInputs = [ nvidiaLibsOnly ];
meta = with pkgs.stdenv.lib; {
description = "A tool to launch ${api} application on system other than NixOS - Nvidia version";
homepage = "https://github.com/guibou/nixGL";
};
} ''
mkdir -p $out/bin
cat > $out/bin/nix${api}Nvidia << FOO
#!/usr/bin/env sh
export LD_LIBRARY_PATH=${libglvnd}/lib:${nvidiaLibsOnly}/lib
"\$@"
FOO
chmod u+x $out/bin/nix${api}Nvidia
'';
nixGLNvidia = nixNvidiaWrapper "GL";
nixVulkanNvidia = nixNvidiaWrapper "Vulkan";
nixGLIntel = runCommand "nixGLIntel" {
buildInputs = [ mesa_drivers ];
meta = with pkgs.stdenv.lib; {
description = "A tool to launch OpenGL application on system other than NixOS - Intel version";
homepage = "https://github.com/guibou/nixGL";
};
} ''
mkdir -p $out/bin
cat > $out/bin/nixGLIntel << FOO
#!/usr/bin/env sh
export LIBGL_DRIVERS_PATH=${mesa_drivers}/lib/dri
export LD_LIBRARY_PATH=${mesa_drivers}/lib
"\$@"
FOO
chmod u+x $out/bin/nixGLIntel
'';
nixVulkanIntel = runCommand "nixVulkanIntel" {
meta = with pkgs.stdenv.lib; {
description = "A tool to launch Vulkan application on system other than NixOS - Intel version";
homepage = "https://github.com/guibou/nixGL";
};
} ''
mkdir -p "$out/bin"
cat > "$out/bin/nixVulkanIntel" << EOF
#!/usr/bin/env bash
if [ ! -z "$LD_LIBRARY_PATH" ]; then
echo "Warning, nixVulkanIntel overwriting existing LD_LIBRARY_PATH" 1>&2
fi
export LD_LIBRARY_PATH=${lib.makeLibraryPath [
zlib
libdrm
xorg.libX11
xorg.libxcb
xorg.libxshmfence
wayland
gcc.cc
]}
exec "\$@"
EOF
chmod u+x "$out/bin/nixVulkanIntel"
${shellcheck}/bin/shellcheck "$out/bin/nixVulkanIntel"
'';
nixGLCommon = nixGL:
runCommand "nixGLCommon" {
buildInuts = [nixGL];
}
''
mkdir -p "$out/bin"
cp "${nixGL}/bin/${nixGL.name}" "$out/bin/nixGL";
'';
}

View File

@ -1,72 +0,0 @@
{
"nodes": {
"lowdown-src": {
"flake": false,
"locked": {
"lastModified": 1598695561,
"narHash": "sha256-gyH/5j+h/nWw0W8AcR2WKvNBUsiQ7QuxqSJNXAwV+8E=",
"owner": "kristapsdz",
"repo": "lowdown",
"rev": "1705b4a26fbf065d9574dce47a94e8c7c79e052f",
"type": "github"
},
"original": {
"owner": "kristapsdz",
"repo": "lowdown",
"type": "github"
}
},
"nix": {
"inputs": {
"lowdown-src": "lowdown-src",
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1604964115,
"narHash": "sha256-ANcswniHS4eYeMNyCGdiG3z0M35vEyvWoCsdLnTvObA=",
"owner": "NixOS",
"repo": "nix",
"rev": "0ed7c957bed18d963df65d55f0c0ffc79dee656d",
"type": "github"
},
"original": {
"id": "nix",
"type": "indirect"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1602702596,
"narHash": "sha256-fqJ4UgOb4ZUnCDIapDb4gCrtAah5Rnr2/At3IzMitig=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "ad0d20345219790533ebe06571f82ed6b034db31",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "nixos-20.09-small",
"type": "indirect"
}
},
"nixpkgs_2": {
"locked": {
"narHash": "sha256-wLDweKqbmufa2wonCKBf4Wfl8I0eS1CGS7WdR5tPHKo=",
"type": "tarball",
"url": "https://github.com/NixOS/nixpkgs/archive/60330b60655b3fa3a18624bdd7069855bb37af99.tar.gz"
},
"original": {
"type": "tarball",
"url": "https://github.com/NixOS/nixpkgs/archive/60330b60655b3fa3a18624bdd7069855bb37af99.tar.gz"
}
},
"root": {
"inputs": {
"nix": "nix",
"nixpkgs": "nixpkgs_2"
}
}
},
"root": "root",
"version": 7
}

View File

@ -1,49 +0,0 @@
{
description = "";
inputs = {
nixpkgs.url = https://github.com/NixOS/nixpkgs/archive/60330b60655b3fa3a18624bdd7069855bb37af99.tar.gz;
};
outputs = { nixpkgs, nix, self, ... }@inputs : {
defaultPackage.x86_64-linux =
let pkgs = import nixpkgs { system = "x86_64-linux"; config = { allowUnfree = true; }; }; in
(pkgs.callPackage ./nixGL.nix {
nvidiaVersionFile = null;
nvidiaVersion = "455.28"; nvidiaHash = "03ysf61qrb272yqkn7bhn9d65lcfhmqc2c0dbh5prp5f2ndlkqg4";
# nvidiaVersion = "455.23.04"; nvidiaHash = "0rvbb9s4ijb0gyiscd93chbgim4lqmy4ksfy15b4abf078qk7q4g";
# …
enable32bits = true;
}).nixGLIntel; # nixGLNvidia;
# nixpkgs.stdenv.mkDerivation {
# builsInputs = [];
# { ## Nvidia informations.
# # Version of the system kernel module. Let it to null to enable auto-detection.
# nvidiaVersion ? null,
# # Hash of the Nvidia driver .run file. null is fine, but fixing a value here
# # will be more reproducible and more efficient.
# nvidiaHash ? null,
# # Alternatively, you can pass a path that points to a nvidia version file
# # and let nixGL extract the version from it. That file must be a copy of
# # /proc/driver/nvidia/version. Nix doesn't like zero-sized files (see
# # https://github.com/NixOS/nix/issues/3539 ).
# nvidiaVersionFile ? null,
# # 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 ? true,
# # Make sure to enable config.allowUnfree to the instance of nixpkgs to be
# # able to access the nvidia drivers.
# pkgs ? import <nixpkgs> {
# config = { allowUnfree = true; };
# }
# }:
# pkgs.callPackage ./nixGL.nix {
# inherit
# nvidiaVersion
# nvidiaVersionFile
# nvidiaHash
# enable32bits
# ;
# };
# };
};
}

199
nixGL.nix
View File

@ -1,199 +0,0 @@
{ ## Nvidia informations.
# Version of the system kernel module. Let it to null to enable auto-detection.
nvidiaVersion ? null,
# Hash of the Nvidia driver .run file. null is fine, but fixing a value here
# will be more reproducible and more efficient.
nvidiaHash ? null,
# Alternatively, you can pass a path that points to a nvidia version file
# and let nixGL extract the version from it. That file must be a copy of
# /proc/driver/nvidia/version. Nix doesn't like zero-sized files (see
# https://github.com/NixOS/nix/issues/3539 ).
nvidiaVersionFile ? null,
# 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 ? true,
writeTextFile, shellcheck, pcre, runCommand, linuxPackages, fetchurl, lib,
runtimeShell, bumblebee, libglvnd, vulkan-validation-layers, mesa_drivers,
pkgsi686Linux,zlib, libdrm, xorg, wayland, gcc
}:
let
_nvidiaVersionFile =
if nvidiaVersionFile != null then
nvidiaVersionFile
else
# HACK: Get the version from /proc. It turns out that /proc is mounted
# inside of the build sandbox and varies from machine to machine.
#
# builtins.readFile is not able to read /proc files. See
# https://github.com/NixOS/nix/issues/3539.
runCommand "impure-nvidia-version-file" {
# To avoid sharing the build result over time or between machine,
# Add an impure parameter to force the rebuild on each access.
time = builtins.currentTime;
preferLocalBuild = true;
allowSubstitutes = false;
}
"cp /proc/driver/nvidia/version $out || touch $out";
# The nvidia version. Either fixed by the `nvidiaVersion` argument, or
# auto-detected. Auto-detection is impure.
_nvidiaVersion =
if nvidiaVersion != null then
nvidiaVersion
else
# Get if from the nvidiaVersionFile
let
data = builtins.readFile _nvidiaVersionFile;
versionMatch = builtins.match ".*Module +([0-9]+\\.[0-9]+).*" data;
in
if versionMatch != null then
builtins.head versionMatch
else
null;
addNvidiaVersion = drv: drv.overrideAttrs(oldAttrs: {
name = oldAttrs.name + "-${_nvidiaVersion}";
});
writeExecutable = { name, text } : writeTextFile {
inherit name text;
executable = true;
destination = "/bin/${name}";
checkPhase = ''
${shellcheck}/bin/shellcheck "$out/bin/${name}"
# Check that all the files listed in the output binary exists
for i in $(${pcre}/bin/pcregrep -o0 '/nix/store/.*?/[^ ":]+' $out/bin/${name})
do
ls $i > /dev/null || (echo "File $i, referenced in $out/bin/${name} does not exists."; exit -1)
done
'';
};
in
rec {
nvidia = (linuxPackages.nvidia_x11.override {
}).overrideAttrs(oldAttrs: rec {
name = "nvidia-${_nvidiaVersion}";
src = let url ="http://download.nvidia.com/XFree86/Linux-x86_64/${_nvidiaVersion}/NVIDIA-Linux-x86_64-${_nvidiaVersion}.run";
in if nvidiaHash != null
then fetchurl {
inherit url;
sha256 = nvidiaHash;
} else
builtins.fetchurl url;
useGLVND = true;
});
nvidiaLibsOnly = nvidia.override {
libsOnly = true;
kernel = null;
};
nixGLNvidiaBumblebee = addNvidiaVersion (writeExecutable {
name = "nixGLNvidiaBumblebee";
text = ''
#!${runtimeShell}
export LD_LIBRARY_PATH=${lib.makeLibraryPath [nvidia]}:$LD_LIBRARY_PATH
${bumblebee.override {nvidia_x11 = nvidia; nvidia_x11_i686 = nvidia.lib32;}}/bin/optirun --ldpath ${lib.makeLibraryPath ([libglvnd nvidia] ++ lib.optionals enable32bits [nvidia.lib32 pkgsi686Linux.libglvnd])} "$@"
'';
});
# TODO: 32bit version? Not tested.
nixNvidiaWrapper = api: addNvidiaVersion (writeExecutable {
name = "nix${api}Nvidia";
text = ''
#!${runtimeShell}
${lib.optionalString (api == "Vulkan") ''export VK_LAYER_PATH=${vulkan-validation-layers}/share/vulkan/explicit_layer.d''}
${lib.optionalString (api == "Vulkan") ''export VK_ICD_FILENAMES=${nvidiaLibsOnly}/share/vulkan/icd.d/nvidia.json${lib.optionalString enable32bits ":${nvidiaLibsOnly.lib32}/share/vulkan/icd.d/nvidia.json"}:$VK_ICD_FILENAMES''}
export LD_LIBRARY_PATH=${lib.makeLibraryPath ([
libglvnd
nvidiaLibsOnly
] ++ lib.optional (api == "Vulkan") vulkan-validation-layers
++ lib.optionals enable32bits [nvidiaLibsOnly.lib32 pkgsi686Linux.libglvnd])
}:''${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}
"$@"
'';
});
# TODO: 32bit version? Not tested.
nixGLNvidia = nixNvidiaWrapper "GL";
# TODO: 32bit version? Not tested.
nixVulkanNvidia = nixNvidiaWrapper "Vulkan";
nixGLIntel = writeExecutable {
name = "nixGLIntel";
# add the 32 bits drivers if needed
text = let
drivers = [mesa_drivers] ++ lib.optional enable32bits pkgsi686Linux.mesa_drivers;
in ''
#!${runtimeShell}
export LIBGL_DRIVERS_PATH=${lib.makeSearchPathOutput "lib" "lib/dri" drivers}
export LD_LIBRARY_PATH=${
lib.makeLibraryPath drivers
}:$LD_LIBRARY_PATH
"$@"
'';
};
nixVulkanIntel = writeExecutable {
name = "nixVulkanIntel";
text = let
# generate a file with the listing of all the icd files
icd = runCommand "mesa_icd" {}
(
# 64 bits icd
''ls ${mesa_drivers}/share/vulkan/icd.d/*.json > f
''
# 32 bits ones
+ lib.optionalString enable32bits ''ls ${pkgsi686Linux.mesa_drivers}/share/vulkan/icd.d/*.json >> f
''
# concat everything as a one line string with ":" as seperator
+ ''cat f | xargs | sed "s/ /:/g" > $out''
);
in ''
#!${runtimeShell}
if [ -n "$LD_LIBRARY_PATH" ]; then
echo "Warning, nixVulkanIntel overwriting existing LD_LIBRARY_PATH" 1>&2
fi
export VK_LAYER_PATH=${vulkan-validation-layers}/share/vulkan/explicit_layer.d
ICDS=$(cat ${icd})
export VK_ICD_FILENAMES=$ICDS:$VK_ICD_FILENAMES
export LD_LIBRARY_PATH=${lib.makeLibraryPath [
zlib
libdrm
xorg.libX11
xorg.libxcb
xorg.libxshmfence
wayland
gcc.cc
]}:$LD_LIBRARY_PATH
exec "$@"
'';
};
nixGLCommon = nixGL:
runCommand "nixGLCommon" {
buildInuts = [nixGL];
}
''
mkdir -p "$out/bin"
# star because nixGLNvidia... have version prefixed name
cp ${nixGL}/bin/* "$out/bin/nixGL";
'';
# The output derivation contains nixGL which point either to
# nixGLNvidia or nixGLIntel using an heuristic.
nixGLDefault =
if _nvidiaVersion != null then
nixGLCommon nixGLNvidia
else
nixGLCommon nixGLIntel
;
}

13
nvidiaInstall.py Executable file
View File

@ -0,0 +1,13 @@
#! /usr/bin/env nix-shell
#! nix-shell -i python3 -p python3
import sys
import subprocess
nvidiaVersion = sys.argv[1]
tool = sys.argv[2]
nvidiaUrl = f"http://download.nvidia.com/XFree86/Linux-x86_64/{nvidiaVersion}/NVIDIA-Linux-x86_64-{nvidiaVersion}.run"
nvidiaHash = subprocess.check_output(["nix-prefetch-url", nvidiaUrl]).strip()
subprocess.check_call(["nix-build", "-A", tool, "--argstr", "nvidiaVersion", nvidiaVersion, "--argstr", "nvidiaHash", nvidiaHash])