200 lines
6.6 KiB
Nix
200 lines
6.6 KiB
Nix
{ ## 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
|
|
;
|
|
}
|