dotfiles/out-of-tree/nixGL/nixGL.nix

294 lines
9.9 KiB
Nix
Raw Permalink Normal View History

2023-01-12 20:01:11 +00:00
{
# # Nvidia informations.
# Version of the system kernel module. Let it to null to enable auto-detection.
2023-06-18 00:46:31 +00:00
nvidiaVersion ? null,
# Hash of the Nvidia driver .run file. null is fine, but fixing a value here
2023-01-12 20:01:11 +00:00
# will be more reproducible and more efficient.
2023-06-18 00:46:31 +00:00
nvidiaHash ? null,
# Alternatively, you can pass a path that points to a nvidia version file
2023-01-12 20:01:11 +00:00
# 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 ).
2023-06-18 00:46:31 +00:00
nvidiaVersionFile ? null,
# Enable 32 bits driver
2023-01-12 20:01:11 +00:00
# This is one by default, you can switch it to off if you want to reduce a
# bit the size of nixGL closure.
2023-06-18 00:46:31 +00:00
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,
}:
2022-12-30 08:45:15 +00:00
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
'';
};
2023-01-13 00:22:56 +00:00
fetch_db = builtins.fromJSON (builtins.readFile ./nvidia_versions.json);
2022-12-30 08:45:15 +00:00
top = rec {
/*
2023-06-18 00:46:31 +00:00
It contains the builder for different nvidia configuration, parametrized by
the version of the driver and sha256 sum of the driver installer file.
2022-12-30 08:45:15 +00:00
*/
2023-06-18 00:46:31 +00:00
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")
2023-01-12 20:01:11 +00:00
"export VK_LAYER_PATH=${vulkan-validation-layers}/share/vulkan/explicit_layer.d"}
2023-06-18 00:46:31 +00:00
NVIDIA_JSON=(${nvidiaLibsOnly}/share/glvnd/egl_vendor.d/*nvidia.json)
${lib.optionalString enable32bits "NVIDIA_JSON32=(${nvidiaLibsOnly.lib32}/share/glvnd/egl_vendor.d/*nvidia.json)"}
2022-12-30 08:45:15 +00:00
2023-06-18 00:46:31 +00:00
${''export __EGL_VENDOR_LIBRARY_FILENAMES=''${NVIDIA_JSON[*]}${
2023-01-12 20:01:11 +00:00
lib.optionalString enable32bits
'':''${NVIDIA_JSON32[*]}''
2023-06-18 00:46:31 +00:00
}"''${__EGL_VENDOR_LIBRARY_FILENAMES:+:$__EGL_VENDOR_LIBRARY_FILENAMES}"''}
2023-06-18 00:46:31 +00:00
${
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 [
2023-06-18 00:46:31 +00:00
nvidiaLibsOnly.lib32
pkgsi686Linux.libglvnd
])
2023-06-18 00:46:31 +00:00
}"''${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
exec "$@"
'';
};
2023-06-18 00:46:31 +00:00
in {
inherit nvidiaDrivers nvidiaLibsOnly;
2023-06-18 00:46:31 +00:00
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
])
} "$@"
'';
};
2023-01-12 20:01:11 +00:00
2023-06-18 00:46:31 +00:00
# TODO: 32bit version? Not tested.
inherit nixNvidiaWrapper;
2023-01-12 20:01:11 +00:00
2023-06-18 00:46:31 +00:00
# TODO: 32bit version? Not tested.
nixGLNvidia = nixNvidiaWrapper "GL";
# TODO: 32bit version? Not tested.
nixVulkanNvidia = nixNvidiaWrapper "Vulkan";
};
2022-12-30 08:45:15 +00:00
nixGLIntel = writeExecutable {
name = "nixGLIntel";
# add the 32 bits drivers if needed
2023-06-18 00:46:31 +00:00
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${
2023-01-12 20:01:11 +00:00
lib.optionalString enable32bits
":${pkgsi686Linux.mesa.drivers}/share/glvnd/egl_vendor.d/50_mesa.json"
2023-06-18 00:46:31 +00:00
}"''${__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 "$@"
'';
2022-12-30 08:45:15 +00:00
};
nixVulkanIntel = writeExecutable {
name = "nixVulkanIntel";
2023-06-18 00:46:31 +00:00
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 "$@"
'';
2022-12-30 08:45:15 +00:00
};
nixGLCommon = nixGL:
2023-06-18 00:46:31 +00:00
runCommand "nixGL" {} ''
2022-12-30 08:45:15 +00:00
mkdir -p "$out/bin"
# star because nixGLNvidia... have version prefixed name
cp ${nixGL}/bin/* "$out/bin/nixGL";
'';
2023-06-18 00:46:31 +00:00
auto = let
_nvidiaVersionFile =
if nvidiaVersionFile != null
then nvidiaVersionFile
else
2023-01-12 20:01:11 +00:00
# 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.
2023-06-18 00:46:31 +00:00
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";
2023-01-12 20:01:11 +00:00
2023-06-18 00:46:31 +00:00
# The nvidia version. Either fixed by the `nvidiaVersion` argument, or
# auto-detected. Auto-detection is impure.
nvidiaVersionAuto =
if nvidiaVersion != null
then nvidiaVersion
else
2023-01-12 20:01:11 +00:00
# Get if from the nvidiaVersionFile
2023-06-18 00:46:31 +00:00
let
data = builtins.readFile _nvidiaVersionFile;
versionMatch = builtins.match ".*Module ([0-9.]+) .*" data;
in
if versionMatch != null
then builtins.head versionMatch
else null;
2023-01-12 20:01:11 +00:00
2023-06-18 00:46:31 +00:00
autoNvidia = nvidiaPackages {version = nvidiaVersionAuto;};
in
2023-01-12 20:01:11 +00:00
rec {
# The output derivation contains nixGL which point either to
# nixGLNvidia or nixGLIntel using an heuristic.
nixGLDefault =
2023-06-18 00:46:31 +00:00
if nvidiaVersionAuto != null
then nixGLCommon autoNvidia.nixGLNvidia
else nixGLCommon nixGLIntel;
}
// autoNvidia;
2022-12-30 08:45:15 +00:00
};
2023-01-12 20:01:11 +00:00
in
2023-06-18 00:46:31 +00:00
top
// (
if nvidiaVersion != null
then
top.nvidiaPackages
{
version = nvidiaVersion;
sha256 = nvidiaHash;
}
else {}
)