Add primus and extend bumblebee to support 32bit/64bit multilib architectures. Using primusrun will work as expected in a multilib environment. Even if the initial program executes a antoehr program of the another architecture. Assuming the program does not modify LD_LIBRARY_PATH inappropriately.

This does not update virtualgl for seemless multilib. I was unable to get a mixed 64/32 bit
environment to work with VirtualGL. The mechanism VirtualGL uses to inject the fake GL library would
fail if both 32bit and 64 bit libraries were in the environment. Instead the bumblebee package
creates a optirun32 executable that can be used to run a 32bit executable with optimus on a 64 bit
host. This is not created if the host is 32bit.

For my usage, gaming under wine, the primusrun executable works as expected regardless of
32bit/64bit.

+160 -26
+1 -1
nixos/modules/hardware/video/bumblebee.nix
··· 30 boot.kernelModules = [ "bbswitch" ]; 31 boot.extraModulePackages = [ kernel.bbswitch kernel.nvidia_x11 ]; 32 33 - environment.systemPackages = [ pkgs.bumblebee ]; 34 35 systemd.services.bumblebeed = { 36 description = "Bumblebee Hybrid Graphics Switcher";
··· 30 boot.kernelModules = [ "bbswitch" ]; 31 boot.extraModulePackages = [ kernel.bbswitch kernel.nvidia_x11 ]; 32 33 + environment.systemPackages = [ pkgs.bumblebee pkgs.primus ]; 34 35 systemd.services.bumblebeed = { 36 description = "Bumblebee Hybrid Graphics Switcher";
+65 -24
pkgs/tools/X11/bumblebee/default.nix
··· 1 # The bumblebee package allows a program to be rendered on an 2 - # dedicated video card by spawning an additional X11 server 3 - # and streaming the results via VirtualGL to the primary server. 4 5 # The package is rather chaotic; it's also quite recent. 6 # As it may change a lot, some of the hacks in this nix expression 7 # will hopefully not be needed in the future anymore. 8 9 - # To test: make sure that the 'bbswitch' kernel module is installed, 10 - # then run 'bumblebeed' as root and 'optirun glxgears' as user. 11 # To use at startup, see hardware.bumblebee options. 12 13 # This nix expression supports for now only the native nvidia driver. 14 # It should not be hard to generalize this approach to support the 15 - # nouveau driver as well (parameterize commonEnv over the module 16 - # package, and parameterize the two wrappers as well) 17 18 { stdenv, fetchurl, pkgconfig, help2man 19 , libX11, glibc, glib, libbsd 20 , makeWrapper, buildEnv, module_init_tools 21 - , linuxPackages, virtualgl, xorg, xkeyboard_config 22 }: 23 - 24 let 25 version = "3.2.1"; 26 name = "bumblebee-${version}"; 27 28 - # isolated X11 environment with the nvidia module 29 - # it should include all components needed for bumblebeed and 30 # optirun to spawn the second X server and to connect to it. 31 - commonEnv = buildEnv { 32 name = "bumblebee-env"; 33 paths = [ 34 module_init_tools 35 - 36 - linuxPackages.nvidia_x11 37 xorg.xorgserver 38 xorg.xrandr 39 xorg.xrdb 40 xorg.setxkbmap 41 xorg.libX11 42 xorg.libXext 43 44 virtualgl 45 ]; 46 47 - # the nvidia GLX module overwrites the one of xorgserver, 48 - # thus nvidia_x11 must be before xorgserver in the paths. 49 - ignoreCollisions = true; 50 - }; 51 52 in stdenv.mkDerivation { 53 inherit name; ··· 63 # Substitute the path to the actual modinfo program in module.c. 64 # Note: module.c also calls rmmod and modprobe, but those just have to 65 # be in PATH, and thus no action for them is required. 66 substituteInPlace src/module.c \ 67 --replace "/sbin/modinfo" "${module_init_tools}/sbin/modinfo" 68 ··· 75 # Note that it has several runtime dependencies. 76 buildInputs = [ stdenv makeWrapper pkgconfig help2man libX11 glib libbsd ]; 77 78 configureFlags = [ 79 "--with-udev-rules=$out/lib/udev/rules.d" 80 "CONF_DRIVER=nvidia" 81 "CONF_DRIVER_MODULE_NVIDIA=nvidia" 82 - "CONF_LDPATH_NVIDIA=${commonEnv}/lib" 83 - "CONF_MODPATH_NVIDIA=${commonEnv}/lib/xorg/modules" 84 ]; 85 86 # create a wrapper environment for bumblebeed and optirun 87 postInstall = '' 88 wrapProgram "$out/sbin/bumblebeed" \ 89 - --prefix PATH : "${commonEnv}/sbin:${commonEnv}/bin:\$PATH" \ 90 - --prefix LD_LIBRARY_PATH : "${commonEnv}/lib:\$LD_LIBRARY_PATH" \ 91 --set XKB_BINDIR "${xorg.xkbcomp}/bin" \ 92 --set XKB_DIR "${xkeyboard_config}/etc/X11/xkb" 93 94 wrapProgram "$out/bin/optirun" \ 95 - --prefix PATH : "${commonEnv}/sbin:${commonEnv}/bin" \ 96 - --prefix LD_LIBRARY_PATH : "${commonEnv}/lib" \ 97 - ''; 98 99 meta = { 100 homepage = http://github.com/Bumblebee-Project/Bumblebee;
··· 1 # The bumblebee package allows a program to be rendered on an 2 + # dedicated video card by spawning an additional X11 server and 3 + # streaming the results via VirtualGL or primus to the primary server. 4 5 # The package is rather chaotic; it's also quite recent. 6 # As it may change a lot, some of the hacks in this nix expression 7 # will hopefully not be needed in the future anymore. 8 9 + # To test: 10 + # 1. make sure that the 'bbswitch' kernel module is installed, 11 + # 2. then run 'bumblebeed' as root 12 + # 3. Then either 'optirun glxinfo' or 'primusrun glxinfo' as user. 13 + # 14 + # The glxinfo output should indicate the NVidia driver is being used 15 + # and all expected extensions are supported. 16 + # 17 # To use at startup, see hardware.bumblebee options. 18 19 # This nix expression supports for now only the native nvidia driver. 20 # It should not be hard to generalize this approach to support the 21 + # nouveau driver as well (parameterize hostEnv, i686Env over the 22 + # module package, and parameterize the two wrappers as well) 23 24 { stdenv, fetchurl, pkgconfig, help2man 25 , libX11, glibc, glib, libbsd 26 , makeWrapper, buildEnv, module_init_tools 27 + , xorg, xkeyboard_config 28 + , nvidia_x11, virtualgl 29 + # The below should only be non-null in a x86_64 system. On a i686 30 + # system the above nvidia_x11 and virtualgl will be the i686 packages. 31 + # TODO: Confusing. Perhaps use "SubArch" instead of i686? 32 + , nvidia_x11_i686 ? null 33 + , virtualgl_i686 ? null 34 }: 35 + with stdenv.lib; 36 let 37 version = "3.2.1"; 38 name = "bumblebee-${version}"; 39 40 + # Isolated X11 environment without the acceleration driver module. 41 + # Includes the rest of the components needed for bumblebeed and 42 # optirun to spawn the second X server and to connect to it. 43 + x11Env = buildEnv { 44 name = "bumblebee-env"; 45 paths = [ 46 module_init_tools 47 xorg.xorgserver 48 xorg.xrandr 49 xorg.xrdb 50 xorg.setxkbmap 51 xorg.libX11 52 xorg.libXext 53 + xorg.xf86inputevdev 54 + ]; 55 + }; 56 57 + # The environment for the host architecture. 58 + hostEnv = buildEnv { 59 + name = "bumblebee-x64-env"; 60 + paths = [ 61 + nvidia_x11 62 virtualgl 63 ]; 64 + }; 65 66 + # The environment for the sub architecture, i686, if there is one 67 + i686Env = if virtualgl_i686 != null 68 + then buildEnv { 69 + name = "bumblebee-i686-env"; 70 + paths = [ 71 + nvidia_x11_i686 72 + virtualgl_i686 73 + ]; 74 + } 75 + else null; 76 + 77 + allEnvs = [hostEnv] ++ optional (i686Env != null) i686Env; 78 + ldPathString = makeLibraryPath allEnvs; 79 80 in stdenv.mkDerivation { 81 inherit name; ··· 91 # Substitute the path to the actual modinfo program in module.c. 92 # Note: module.c also calls rmmod and modprobe, but those just have to 93 # be in PATH, and thus no action for them is required. 94 + 95 substituteInPlace src/module.c \ 96 --replace "/sbin/modinfo" "${module_init_tools}/sbin/modinfo" 97 ··· 104 # Note that it has several runtime dependencies. 105 buildInputs = [ stdenv makeWrapper pkgconfig help2man libX11 glib libbsd ]; 106 107 + # The order of LDPATH is very specific: First X11 then the host 108 + # environment then the optional sub architecture paths. 109 + # 110 + # The order for MODPATH is the opposite: First the environment that 111 + # includes the acceleration driver. As this is used for the X11 112 + # server, which runs under the host architecture, this does not 113 + # include the sub architecture components. 114 configureFlags = [ 115 "--with-udev-rules=$out/lib/udev/rules.d" 116 "CONF_DRIVER=nvidia" 117 "CONF_DRIVER_MODULE_NVIDIA=nvidia" 118 + "CONF_LDPATH_NVIDIA=${x11Env}/lib:${ldPathString}" 119 + "CONF_MODPATH_NVIDIA=${hostEnv}/lib/xorg/modules,${x11Env}/lib/xorg/modules" 120 ]; 121 122 # create a wrapper environment for bumblebeed and optirun 123 postInstall = '' 124 wrapProgram "$out/sbin/bumblebeed" \ 125 + --prefix PATH : "${x11Env}/sbin:${x11Env}/bin:${hostEnv}/bin:\$PATH" \ 126 + --prefix LD_LIBRARY_PATH : "${x11Env}/lib:${hostEnv}/lib:\$LD_LIBRARY_PATH" \ 127 + --set FONTCONFIG_FILE "/etc/fonts/fonts.conf" \ 128 --set XKB_BINDIR "${xorg.xkbcomp}/bin" \ 129 --set XKB_DIR "${xkeyboard_config}/etc/X11/xkb" 130 131 wrapProgram "$out/bin/optirun" \ 132 + --prefix PATH : "${hostEnv}/bin" 133 + '' + (if i686Env == null 134 + then "" 135 + else '' 136 + makeWrapper "$out/bin/.optirun-wrapped" "$out/bin/optirun32" \ 137 + --prefix PATH : "${i686Env}/bin" 138 + ''); 139 140 meta = { 141 homepage = http://github.com/Bumblebee-Project/Bumblebee;
+12
pkgs/tools/X11/primus/builder.sh
···
··· 1 + source $stdenv/setup 2 + 3 + cp -r $src src 4 + cd src 5 + 6 + export LIBDIR=$out/lib 7 + export PRIMUS_libGLa=$nvidia/lib/libGL.so 8 + export PRIMUS_libGLd=$mesa/lib/libGL.so 9 + export PRIMUS_LOAD_GLOBAL=$mesa/lib/libglapi.so 10 + 11 + make 12 + ln -s $LIBDIR/libGL.so.1 $LIBDIR/libGL.so
+40
pkgs/tools/X11/primus/default.nix
···
··· 1 + # For a 64bit + 32bit system the LD_LIBRARY_PATH must contain both the 32bit and 64bit primus 2 + # libraries. Providing a different primusrun for each architecture will not work as expected. EG: 3 + # Using steam under wine can involve both 32bit and 64bit process. All of which inherit the 4 + # same LD_LIBRARY_PATH. 5 + # Other distributions do the same. 6 + { stdenv 7 + , primusLib 8 + , writeScript 9 + , primusLib_i686 ? null 10 + }: 11 + with stdenv.lib; 12 + let 13 + version = "1.0.0748176"; 14 + ldPath = makeLibraryPath ([primusLib] ++ optional (primusLib_i686 != null) primusLib_i686); 15 + primusrun = writeScript "primusrun" 16 + '' 17 + export LD_LIBRARY_PATH=${ldPath}:\$LD_LIBRARY_PATH 18 + # see: https://github.com/amonakov/primus/issues/138 19 + # On my system, as of 3.16.6, the intel driver dies when the pixel buffers try to read from the 20 + # source memory directly. Setting PRIMUS_UPLOAD causes an indirection through textures which 21 + # avoids this issue. 22 + export PRIMUS_UPLOAD=1 23 + exec "$@" 24 + ''; 25 + in 26 + stdenv.mkDerivation { 27 + name = "primus-${version}"; 28 + builder = writeScript "builder" 29 + '' 30 + source $stdenv/setup 31 + mkdir -p $out/bin 32 + cp ${primusrun} $out/bin/primusrun 33 + ''; 34 + 35 + meta = { 36 + homepage = https://github.com/amonakov/primus; 37 + description = "Faster OpenGL offloading for Bumblebee"; 38 + maintainer = maintainers.coconnor; 39 + }; 40 + }
+20
pkgs/tools/X11/primus/lib.nix
···
··· 1 + { stdenv, fetchgit 2 + , x11, mesa 3 + , nvidia 4 + }: 5 + let 6 + version = "1.0.0748176"; 7 + in 8 + stdenv.mkDerivation { 9 + name = "primus-lib-${version}"; 10 + src = fetchgit { 11 + url = git://github.com/amonakov/primus.git; 12 + rev = "074817614c014e3a99259388cb18fd54648b659a"; 13 + sha256 = "0mrh432md6zrm16avxyk57mgszrqpgwdjahspchvlaccqxp3x82v"; 14 + }; 15 + 16 + inherit nvidia mesa; 17 + 18 + buildInputs = [ x11 mesa ]; 19 + builder = ./builder.sh; 20 + }
+22 -1
pkgs/top-level/all-packages.nix
··· 10993 10994 virtualgl = callPackage ../tools/X11/virtualgl { }; 10995 10996 - bumblebee = callPackage ../tools/X11/bumblebee { }; 10997 10998 vkeybd = callPackage ../applications/audio/vkeybd { 10999 inherit (xlibs) libX11;
··· 10993 10994 virtualgl = callPackage ../tools/X11/virtualgl { }; 10995 10996 + primus = callPackage ../tools/X11/primus { 10997 + primusLib = callPackage ../tools/X11/primus/lib.nix { 10998 + nvidia = linuxPackages.nvidia_x11; 10999 + }; 11000 + 11001 + primusLib_i686 = if system == "x86_64-linux" 11002 + then callPackage_i686 ../tools/X11/primus/lib.nix { 11003 + nvidia = pkgsi686Linux.linuxPackages.nvidia_x11.override { libsOnly = true; }; 11004 + } 11005 + else null; 11006 + }; 11007 + 11008 + bumblebee = callPackage ../tools/X11/bumblebee { 11009 + nvidia_x11 = linuxPackages.nvidia_x11; 11010 + nvidia_x11_i686 = if system == "x86_64-linux" 11011 + then pkgsi686Linux.linuxPackages.nvidia_x11.override { libsOnly = true; } 11012 + else null; 11013 + virtualgl = virtualgl; 11014 + virtualgl_i686 = if system == "x86_64-linux" 11015 + then pkgsi686Linux.virtualgl 11016 + else null; 11017 + }; 11018 11019 vkeybd = callPackage ../applications/audio/vkeybd { 11020 inherit (xlibs) libX11;