289 lines
10 KiB
Nix
289 lines
10 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
|
|
, libvdpau-va-gl
|
|
, intel-media-driver
|
|
, vaapiIntel
|
|
, pkgsi686Linux
|
|
, driversi686Linux
|
|
, zlib
|
|
, libdrm
|
|
, xorg
|
|
, wayland
|
|
, gcc
|
|
}:
|
|
|
|
let
|
|
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
|
|
'';
|
|
};
|
|
fetch_db = builtins.fromJSON (builtins.readFile ./nvidia_versions.json);
|
|
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.
|
|
*/
|
|
nvidiaPackages = { version, sha256 ? fetch_db."${version}".sha256 }:
|
|
let
|
|
nvidiaDrivers = (linuxPackages.nvidia_x11.override { }).overrideAttrs
|
|
(oldAttrs: {
|
|
pname = "nvidia";
|
|
name = "nvidia-x11-${version}-nixGL";
|
|
inherit version;
|
|
src =
|
|
let
|
|
url =
|
|
"https://download.nvidia.com/XFree86/Linux-x86_64/${version}/NVIDIA-Linux-x86_64-${version}.run";
|
|
in
|
|
fetchurl { inherit url sha256; };
|
|
useGLVND = true;
|
|
});
|
|
nvidiaLibsOnly = nvidiaDrivers.override {
|
|
libsOnly = true;
|
|
kernel = null;
|
|
};
|
|
nixNvidiaWrapper = api:
|
|
writeExecutable {
|
|
name = "nix${api}Nvidia-${version}";
|
|
text = ''
|
|
#!${runtimeShell}
|
|
${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)"}
|
|
|
|
${''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.json${
|
|
lib.optionalString enable32bits
|
|
":${nvidiaLibsOnly.lib32}/share/vulkan/icd.d/nvidia_icd.json"
|
|
}"''${VK_ICD_FILENAMES:+:$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}"
|
|
exec "$@"
|
|
'';
|
|
};
|
|
in
|
|
{
|
|
inherit nvidiaDrivers nvidiaLibsOnly;
|
|
|
|
nixGLNvidiaBumblebee = writeExecutable {
|
|
name = "nixGLNvidiaBumblebee-${version}";
|
|
text = ''
|
|
#!${runtimeShell}
|
|
export LD_LIBRARY_PATH=${
|
|
lib.makeLibraryPath [ nvidiaDrivers ]
|
|
}"''${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
|
|
${
|
|
bumblebee.override {
|
|
nvidia_x11 = nvidiaDrivers;
|
|
nvidia_x11_i686 = nvidiaDrivers.lib32;
|
|
}
|
|
}/bin/optirun --ldpath ${
|
|
lib.makeLibraryPath ([ libglvnd nvidiaDrivers ]
|
|
++ lib.optionals enable32bits [
|
|
nvidiaDrivers.lib32
|
|
pkgsi686Linux.libglvnd
|
|
])
|
|
} "$@"
|
|
'';
|
|
};
|
|
|
|
# TODO: 32bit version? Not tested.
|
|
inherit nixNvidiaWrapper;
|
|
|
|
# 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
|
|
mesa-drivers = [ mesa.drivers ]
|
|
++ lib.optional enable32bits pkgsi686Linux.mesa.drivers;
|
|
intel-driver = [ intel-media-driver vaapiIntel ]
|
|
# Note: intel-media-driver is disabled for i686 until https://github.com/NixOS/nixpkgs/issues/140471 is fixed
|
|
++ lib.optionals enable32bits [ /* pkgsi686Linux.intel-media-driver */ driversi686Linux.vaapiIntel ];
|
|
libvdpau = [ libvdpau-va-gl ]
|
|
++ lib.optional enable32bits pkgsi686Linux.libvdpau-va-gl;
|
|
glxindirect = runCommand "mesa_glxindirect" { } (
|
|
''
|
|
mkdir -p $out/lib
|
|
ln -s ${mesa.drivers}/lib/libGLX_mesa.so.0 $out/lib/libGLX_indirect.so.0
|
|
''
|
|
);
|
|
in
|
|
''
|
|
#!${runtimeShell}
|
|
export LIBGL_DRIVERS_PATH=${lib.makeSearchPathOutput "lib" "lib/dri" mesa-drivers}
|
|
export LIBVA_DRIVERS_PATH=${lib.makeSearchPathOutput "out" "lib/dri" intel-driver}
|
|
${''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 "$@"
|
|
'';
|
|
};
|
|
|
|
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:+:$VK_ICD_FILENAMES}"
|
|
export LD_LIBRARY_PATH=${
|
|
lib.makeLibraryPath [
|
|
zlib
|
|
libdrm
|
|
xorg.libX11
|
|
xorg.libxcb
|
|
xorg.libxshmfence
|
|
wayland
|
|
gcc.cc
|
|
]
|
|
}"''${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
|
|
exec "$@"
|
|
'';
|
|
};
|
|
|
|
nixGLCommon = nixGL:
|
|
runCommand "nixGL" { } ''
|
|
mkdir -p "$out/bin"
|
|
# star because nixGLNvidia... have version prefixed name
|
|
cp ${nixGL}/bin/* "$out/bin/nixGL";
|
|
'';
|
|
|
|
auto =
|
|
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 2> /dev/null || touch $out";
|
|
|
|
# The nvidia version. Either fixed by the `nvidiaVersion` argument, or
|
|
# auto-detected. Auto-detection is impure.
|
|
nvidiaVersionAuto =
|
|
if nvidiaVersion != null then
|
|
nvidiaVersion
|
|
else
|
|
# Get if from the nvidiaVersionFile
|
|
let
|
|
data = builtins.readFile _nvidiaVersionFile;
|
|
versionMatch = builtins.match ".*Module ([0-9.]+) .*" data;
|
|
in
|
|
if versionMatch != null then builtins.head versionMatch else null;
|
|
|
|
autoNvidia = nvidiaPackages { version = nvidiaVersionAuto; };
|
|
in
|
|
rec {
|
|
# The output derivation contains nixGL which point either to
|
|
# nixGLNvidia or nixGLIntel using an heuristic.
|
|
nixGLDefault =
|
|
if nvidiaVersionAuto != null then
|
|
nixGLCommon autoNvidia.nixGLNvidia
|
|
else
|
|
nixGLCommon nixGLIntel;
|
|
} // autoNvidia;
|
|
};
|
|
in
|
|
top // (if nvidiaVersion != null then
|
|
top.nvidiaPackages
|
|
{
|
|
version = nvidiaVersion;
|
|
sha256 = nvidiaHash;
|
|
}
|
|
else
|
|
{ })
|