Compare commits

..

1 Commits

Author SHA1 Message Date
Guillaume Bouchard
078b69f2e2 Add tentative for Ati version 2018-03-19 11:47:40 +01:00
9 changed files with 196 additions and 587 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

214
README.md
View File

@ -1,15 +1,27 @@
# NixGL
This tool tries to solve the "OpenGL" problem on nix. Works with Nvidia cards (with bumblebee) and intel cards.
NixGL solve the "OpenGL" problem with [nix](https://nixos.org/nix/). Works all mesa
drivers (intel cards and "free" version fro Nvidia or AMD cards), Nvidia
proprietary drivers, even with hybrid configuration (with bumblebee). It works
for Vulkan programs too.
# Quick start
Suppose you have a configuration with an nvidia card, host driver version `390.25`
```
# clone the repository
git clone https://github.com/guibou/nixGL
cd nixGL
# build and install the wrapper
nix-build -A nixGLNvidia --argstr nvidiaVersion 390.25
nix-env -i ./result
# use it with any OpenGL application
nixGLNvidia blender
```
# Motivation
You use Nix on any distribution, and any GL application installed fails with this error:
```bash
```
$ program
libGL error: unable to load driver: i965_dri.so
libGL error: driver pointer missing
@ -21,153 +33,101 @@ libGL error: unable to load driver: swrast_dri.so
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 application:
```bash
$ nixGLXXX program
$ nixVulkanXXX program
```
nixGLXXX program
```
# Installation
# Installation / Usage
Clone this git repository:
```bash
$ git clone https://github.com/guibou/nixGL
$ cd nixGL
```
git clone https://github.com/guibou/nixGL
cd nixGL
```
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.
## Optional (if NVIDIA): Grab your NVIDIA driver version
## 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.
- `nix-env -f ./ -iA nixGLNvidia`: Proprietary Nvidia driver.
- `nix-env -f ./ -iA nixGLDefault`: Tries to auto-detect and install Nvidia,
if not, fallback to mesa.
```
$ glxinfo | grep NVIDIA
...
OpenGL core profile version string: 4.5.0 NVIDIA 390.25
...
```
## Vulkan wrappers
## Build
- `nix-env -f ./ -iA nixVulkanNvidia`: Proprietary Nvidia driver.
- `nix-env -f ./ -iA nixVulkanIntel`: Mesa Vulkan implementation.
For intel:
```
nix-build -A nixGLIntel
```
For NVIDIA alone:
```
nix-build -A nixGLNvidia --argstr nvidiaVersion 390.25
```
(replace `390.25` with the host driver version gathered earlier.)
For Nvidia with bumblebee:
```
nix-build -A nixGLNvidiaBumblebee --argstr nvidiaVersion 390.25
```
(replace `390.25` with the host driver version gathered earlier.)
For Ati (untested):
```
nix-build ./default.nix -A nixGLAti --argstr atiUrl "https://www2.ati.com/drivers/linux/radeon-crimson-15.12-15.302-151217a-297685e.zip" --argstr atiVersion "15.12"
```
(replace the url and the version with the correct ones. At the time of this writting, I have no idea on how we can detect that, ati seems to have a weird file naming convention).
## Install
```
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
Just launch the program you want prefixed by the right wrapped.
For OpenGL programs:
```bash
$ nixGLXXX program args
```
nixGLXXX program args
```
For Vulkan programs:
For example (on my dual GPU laptop):
```bash
$ nixVulkanXXX program args
```
Replace `XXX` by the implementation pour previously selected, such as `nixGLIntel` or `nixGLNvidia`.
## Examples
# OpenGL - Hybrid Intel + Nvidia laptop
After installing `nixGLIntel` and `nixGLNvidiaBumblebee`.
```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
$ 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
```
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
```
# Vulkan - Intel GPU
After installing `nixVulkanIntel`.
```bash
$ sudo apt install mesa-vulkan-drivers
...
$ nixVulkanIntel $(nix-build '<nixpkgs>' --no-out-link -A vulkan-tools)/bin/vulkaninfo | grep VkPhysicalDeviceProperties -A 7
VkPhysicalDeviceProperties:
===========================
apiVersion = 0x400036 (1.0.54)
driverVersion = 71311368 (0x4402008)
vendorID = 0x8086
deviceID = 0x591b
deviceType = INTEGRATED_GPU
deviceName = Intel(R) HD Graphics 630 (Kaby Lake GT2)
```
# Troubleshooting
## Nvidia auto detection does not work
```bash
building '/nix/store/ijs5h6h07faai0k74diiy5b2xlxh891g-auto-detect-nvidia.drv'...
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:
```bash
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 nixGLXXX` can be used to get `nixGL` executable which fallsback to `nixGLXXX`. It is a shorter name for people with only one OpenGL configuration.
For example:
```
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.
Does not work now for AMD drivers because I dont' have the 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.
# Comparaison with similar tools
# Hacking
[nix-install-vendor-gl.sh](https://github.com/deepfire/nix-install-vendor-gl)
provides a similar system with a different approach:
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.
- 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.

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)
'';
});
}

109
default.nix Normal file
View File

@ -0,0 +1,109 @@
{ system ? builtins.currentSystem,
nvidiaVersion ? null,
atiUrl ? null,
atiVersion ? null
}:
let
pkgs = import <nixpkgs> { inherit system; };
version = "1.0.0";
in
with pkgs;
rec {
nvidiaLibsOnly = (linuxPackages.nvidia_x11.override {
libsOnly = true;
kernel = null;
}).overrideAttrs(oldAttrs: rec {
name = "nvidia-${nvidiaVersion}";
src = fetchurl {
url = "http://download.nvidia.com/XFree86/Linux-x86_64/${nvidiaVersion}/NVIDIA-Linux-x86_64-${nvidiaVersion}.run";
sha256 = null;
};
useGLVND = 0;
});
ati = (linuxPackages.ati_drivers_x11.override {
libsOnly = true;
kernel = null;
}).overrideAttrs(oldAttrs : rec {
name = "ati_drivers-${atiVersion}";
src = fetchurl {
url = atiUrl;
sha256 = null;
curlOpts = "--referer http://support.amd.com/en-us/download/desktop?os=Linux+x86_64";
};
});
nixGLNvidiaBumblebee = runCommand "nixGLNvidiaBumblebee-${version}" {
buildInputs = [ nvidiaLibsOnly 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=${nvidiaLibsOnly}/lib
${bumblebee}/bin/optirun "\$@"
FOO
chmod u+x $out/bin/nixGLNvidiaBumblebee
'';
nixGLNvidia = runCommand "nixGLNvidia-${version}" {
buildInputs = [ nvidiaLibsOnly ];
meta = with pkgs.stdenv.lib; {
description = "A tool to launch OpenGL application on system other than NixOS - Nvidia version";
homepage = "https://github.com/guibou/nixGL";
};
} ''
mkdir -p $out/bin
cat > $out/bin/nixGLNvidia << FOO
#!/usr/bin/env sh
export LD_LIBRARY_PATH=${nvidiaLibsOnly}/lib
"\$@"
FOO
chmod u+x $out/bin/nixGLNvidia
'';
nixGLIntel = runCommand "nixGLIntel-${version}" {
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
"\$@"
FOO
chmod u+x $out/bin/nixGLIntel
'';
nixGLAti = runCommand "nixGLAti-${version}" {
buildInputs = [ mesa_drivers ];
meta = with pkgs.stdenv.lib; {
description = "A tool to launch OpenGL application on system other than NixOS - Ati version";
homepage = "https://github.com/guibou/nixGL";
};
} ''
mkdir -p $out/bin
cat > $out/bin/nixGLAti << FOO
#!/usr/bin/env sh
export LD_LIBRARY_PATH=${ati}/lib
"\$@"
FOO
chmod u+x $out/bin/nixGLAti
'';
}

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
;
}