1{ lib
2, bison
3, buildPackages
4, directx-headers
5, elfutils
6, expat
7, fetchCrate
8, fetchurl
9, fetchpatch
10, file
11, flex
12, glslang
13, intltool
14, jdupes
15, libdrm
16, libglvnd
17, libomxil-bellagio
18, libunwind
19, libva-minimal
20, libvdpau
21, llvmPackages
22, lm_sensors
23, meson
24, ninja
25, pkg-config
26, python3Packages
27, rust-bindgen
28, rust-cbindgen
29, rustPlatform
30, rustc
31, spirv-llvm-translator
32, stdenv
33, udev
34, valgrind-light
35, vulkan-loader
36, wayland
37, wayland-protocols
38, wayland-scanner
39, xcbutilkeysyms
40, xorg
41, zstd
42, enablePatentEncumberedCodecs ? true
43
44, galliumDrivers ? [
45 "d3d12" # WSL emulated GPU (aka Dozen)
46 "iris" # new Intel (Broadwell+)
47 "kmsro" # special "render only" driver for GPUs without a display controller
48 "nouveau" # Nvidia
49 "radeonsi" # new AMD (GCN+)
50 "r300" # very old AMD
51 "r600" # less old AMD
52 "swrast" # software renderer (aka LLVMPipe)
53 "svga" # VMWare virtualized GPU
54 "virgl" # QEMU virtualized GPU (aka VirGL)
55 "zink" # generic OpenGL over Vulkan, experimental
56 ] ++ lib.optionals (stdenv.isAarch64 || stdenv.isAarch32) [
57 "etnaviv" # Vivante GPU designs (mostly NXP/Marvell SoCs)
58 "freedreno" # Qualcomm Adreno (all Qualcomm SoCs)
59 "lima" # ARM Mali 4xx
60 "panfrost" # ARM Mali Midgard and up (T/G series)
61 "vc4" # Broadcom VC4 (Raspberry Pi 0-3)
62 ] ++ lib.optionals stdenv.isAarch64 [
63 "tegra" # Nvidia Tegra SoCs
64 "v3d" # Broadcom VC5 (Raspberry Pi 4)
65 ] ++ lib.optionals stdenv.hostPlatform.isx86 [
66 "crocus" # Intel legacy, x86 only
67 "i915" # Intel extra legacy, x86 only
68 ]
69, vulkanDrivers ? [
70 "amd" # AMD (aka RADV)
71 "intel" # new Intel (aka ANV)
72 "microsoft-experimental" # WSL virtualized GPU (aka DZN/Dozen)
73 "nouveau" # Nouveau (aka NVK)
74 "swrast" # software renderer (aka Lavapipe)
75 ] ++ lib.optionals (stdenv.hostPlatform.isAarch -> lib.versionAtLeast stdenv.hostPlatform.parsed.cpu.version "6") [
76 # QEMU virtualized GPU (aka VirGL)
77 # Requires ATOMIC_INT_LOCK_FREE == 2.
78 "virtio"
79 ] ++ lib.optionals stdenv.isAarch64 [
80 "broadcom" # Broadcom VC5 (Raspberry Pi 4, aka V3D)
81 "freedreno" # Qualcomm Adreno (all Qualcomm SoCs)
82 "imagination-experimental" # PowerVR Rogue (currently N/A)
83 "panfrost" # ARM Mali Midgard and up (T/G series)
84 ] ++ lib.optionals stdenv.hostPlatform.isx86 [
85 "intel_hasvk" # Intel Haswell/Broadwell, "legacy" Vulkan driver (https://www.phoronix.com/news/Intel-HasVK-Drop-Dead-Code)
86 ]
87, eglPlatforms ? [ "x11" "wayland" ]
88, vulkanLayers ? [
89 "device-select"
90 "overlay"
91 "intel-nullhw"
92 ]
93, mesa
94, makeSetupHook
95}:
96
97let
98 rustDeps = [
99 {
100 pname = "paste";
101 version = "1.0.14";
102 hash = "sha256-+J1h7New5MEclUBvwDQtTYJCHKKqAEOeQkuKy+g0vEc=";
103 }
104 {
105 pname = "proc-macro2";
106 version = "1.0.70";
107 hash = "sha256-e4ZgyZUTu5nAtaH5QVkLelqJQX/XPj/rWkzf/g2c+1g=";
108 }
109 {
110 pname = "quote";
111 version = "1.0.33";
112 hash = "sha256-VWRCZJO0/DJbNu0/V9TLaqlwMot65YjInWT9VWg57DY=";
113 }
114 {
115 pname = "syn";
116 version = "2.0.39";
117 hash = "sha256-Mjen2L/omhVbhU/+Ao65mogs3BP3fY+Bodab3uU63EI=";
118 }
119 {
120 pname = "unicode-ident";
121 version = "1.0.12";
122 hash = "sha256-KX8NqYYw6+rGsoR9mdZx8eT1HIPEUUyxErdk2H/Rlj8=";
123 }
124 ];
125
126 copyRustDep = dep: ''
127 cp -R --no-preserve=mode,ownership ${fetchCrate dep} subprojects/${dep.pname}-${dep.version}
128 cp -R subprojects/packagefiles/${dep.pname}/* subprojects/${dep.pname}-${dep.version}/
129 '';
130
131 copyRustDeps = lib.concatStringsSep "\n" (builtins.map copyRustDep rustDeps);
132
133 needNativeCLC = !stdenv.buildPlatform.canExecute stdenv.hostPlatform;
134
135 common = import ./common.nix { inherit lib fetchurl; };
136in stdenv.mkDerivation {
137 inherit (common) pname version src meta;
138
139 patches = [
140 ./opencl.patch
141
142 # https://gitlab.freedesktop.org/mesa/mesa/-/issues/11533
143 (fetchpatch {
144 name = "ffmpeg.patch";
145 url = "https://gitlab.freedesktop.org/mesa/mesa/-/commit/241f70e5a13bb9c13a168282446ad074e16c3d74.patch";
146 hash = "sha256-Cx7OL8iXGAOuDbCQReCCxSrWYvfZVrGoP0txIKSLTvs=";
147 })
148 ];
149
150 postPatch = ''
151 patchShebangs .
152
153 # The drirc.d directory cannot be installed to $drivers as that would cause a cyclic dependency:
154 substituteInPlace src/util/xmlconfig.c --replace \
155 'DATADIR "/drirc.d"' '"${placeholder "out"}/share/drirc.d"'
156 substituteInPlace src/util/meson.build --replace \
157 "get_option('datadir')" "'${placeholder "out"}/share'"
158 substituteInPlace src/amd/vulkan/meson.build --replace \
159 "get_option('datadir')" "'${placeholder "out"}/share'"
160
161 ${copyRustDeps}
162 '';
163
164 outputs = [
165 "out" "dev" "drivers" "driversdev" "opencl" "teflon" "osmesa"
166 # the Dozen drivers depend on libspirv2dxil, but link it statically, and
167 # libspirv2dxil itself is pretty chonky, so relocate it to its own output in
168 # case anything wants to use it at some point
169 "spirv2dxil"
170 ];
171
172 # Keep build-ids so drivers can use them for caching, etc.
173 # Also some drivers segfault without this.
174 separateDebugInfo = true;
175
176 # Needed to discover llvm-config for cross
177 preConfigure = ''
178 PATH=${llvmPackages.libllvm.dev}/bin:$PATH
179 '';
180
181 mesonFlags = [
182 "--sysconfdir=/etc"
183 "--datadir=${placeholder "drivers"}/share"
184
185 # What to build
186 (lib.mesonOption "platforms" (lib.concatStringsSep "," eglPlatforms))
187 (lib.mesonOption "gallium-drivers" (lib.concatStringsSep "," galliumDrivers))
188 (lib.mesonOption "vulkan-drivers" (lib.concatStringsSep "," vulkanDrivers))
189 (lib.mesonOption "vulkan-layers" (builtins.concatStringsSep "," vulkanLayers))
190
191 # Make sure we know where to find all the drivers
192 (lib.mesonOption "dri-drivers-path" "${placeholder "drivers"}/lib/dri")
193 (lib.mesonOption "vdpau-libs-path" "${placeholder "drivers"}/lib/vdpau")
194 (lib.mesonOption "omx-libs-path" "${placeholder "drivers"}/lib/bellagio")
195 (lib.mesonOption "va-libs-path" "${placeholder "drivers"}/lib/dri")
196 (lib.mesonOption "d3d-drivers-path" "${placeholder "drivers"}/lib/d3d")
197
198 # Set search paths for non-Mesa drivers (e.g. Nvidia)
199 (lib.mesonOption "dri-search-path" "${libglvnd.driverLink}/lib/dri")
200 (lib.mesonOption "gbm-backends-path" "${libglvnd.driverLink}/lib/gbm:${placeholder "out"}/lib/gbm")
201
202 # Enable glvnd for dynamic libGL dispatch
203 (lib.mesonEnable "glvnd" true)
204
205 (lib.mesonBool "gallium-nine" true) # Direct3D in Wine
206 (lib.mesonBool "osmesa" true) # used by wine
207 (lib.mesonBool "teflon" true) # TensorFlow frontend
208
209 # Enable Intel RT stuff when available
210 (lib.mesonBool "install-intel-clc" true)
211 (lib.mesonEnable "intel-rt" stdenv.isx86_64)
212 (lib.mesonOption "clang-libdir" "${llvmPackages.clang-unwrapped.lib}/lib")
213
214 # Clover, old OpenCL frontend
215 (lib.mesonOption "gallium-opencl" "icd")
216 (lib.mesonBool "opencl-spirv" true)
217
218 # Rusticl, new OpenCL frontend
219 (lib.mesonBool "gallium-rusticl" true)
220
221 # meson auto_features enables this, but we do not want it
222 (lib.mesonEnable "android-libbacktrace" false)
223 (lib.mesonEnable "microsoft-clc" false) # Only relevant on Windows (OpenCL 1.2 API on top of D3D12)
224 ] ++ lib.optionals enablePatentEncumberedCodecs [
225 (lib.mesonOption "video-codecs" "all")
226 ] ++ lib.optionals needNativeCLC [
227 (lib.mesonOption "intel-clc" "system")
228 ];
229
230 strictDeps = true;
231
232 buildInputs = with xorg; [
233 directx-headers
234 elfutils
235 expat
236 glslang
237 libglvnd
238 libomxil-bellagio
239 libunwind
240 libva-minimal
241 libvdpau
242 libX11
243 libxcb
244 libXext
245 libXfixes
246 libXrandr
247 libxshmfence
248 libXxf86vm
249 llvmPackages.clang
250 llvmPackages.clang-unwrapped
251 llvmPackages.libclc
252 llvmPackages.libllvm
253 lm_sensors
254 python3Packages.python # for shebang
255 spirv-llvm-translator
256 udev
257 valgrind-light
258 vulkan-loader
259 wayland
260 wayland-protocols
261 xcbutilkeysyms
262 xorgproto
263 zstd
264 ];
265
266 depsBuildBuild = [
267 pkg-config
268 buildPackages.stdenv.cc
269 ];
270
271 nativeBuildInputs = [
272 meson
273 pkg-config
274 ninja
275 intltool
276 bison
277 flex
278 file
279 python3Packages.python
280 python3Packages.packaging
281 python3Packages.pycparser
282 python3Packages.mako
283 python3Packages.ply
284 jdupes
285 glslang
286 rustc
287 rust-bindgen
288 rust-cbindgen
289 rustPlatform.bindgenHook
290 wayland-scanner
291 ] ++ lib.optionals needNativeCLC [
292 buildPackages.mesa.driversdev
293 ];
294
295 disallowedRequisites = lib.optionals needNativeCLC [
296 buildPackages.mesa.driversdev
297 ];
298
299 propagatedBuildInputs = [ libdrm ];
300
301 doCheck = false;
302
303 postInstall = ''
304 # Move driver-related bits to $drivers
305 moveToOutput "lib/lib*_mesa*" $drivers
306 moveToOutput "lib/libpowervr_rogue*" $drivers
307 moveToOutput "lib/libxatracker*" $drivers
308 moveToOutput "lib/libvulkan_*" $drivers
309
310 # Update search path used by glvnd (it's pointing to $out but drivers are in $drivers)
311 for js in $drivers/share/glvnd/egl_vendor.d/*.json; do
312 substituteInPlace "$js" --replace-fail '"libEGL_' '"'"$drivers/lib/libEGL_"
313 done
314
315 # And same for Vulkan
316 for js in $drivers/share/vulkan/icd.d/*.json; do
317 substituteInPlace "$js" --replace-fail "$out" "$drivers"
318 done
319
320 # Move Vulkan layers to $drivers and update manifests
321 moveToOutput "lib/libVkLayer*" $drivers
322 for js in $drivers/share/vulkan/{im,ex}plicit_layer.d/*.json; do
323 substituteInPlace "$js" --replace '"libVkLayer_' '"'"$drivers/lib/libVkLayer_"
324 done
325
326 # Construct our own .icd files that contain absolute paths.
327 mkdir -p $opencl/etc/OpenCL/vendors/
328 echo $opencl/lib/libMesaOpenCL.so > $opencl/etc/OpenCL/vendors/mesa.icd
329 echo $opencl/lib/libRusticlOpenCL.so > $opencl/etc/OpenCL/vendors/rusticl.icd
330
331 moveToOutput bin/intel_clc $driversdev
332 moveToOutput lib/gallium-pipe $opencl
333 moveToOutput "lib/lib*OpenCL*" $opencl
334 moveToOutput "lib/libOSMesa*" $osmesa
335 moveToOutput bin/spirv2dxil $spirv2dxil
336 moveToOutput "lib/libspirv_to_dxil*" $spirv2dxil
337 moveToOutput lib/libteflon.so $teflon
338 '';
339
340 postFixup = ''
341 # set the default search path for DRI drivers; used e.g. by X server
342 for pc in lib/pkgconfig/{dri,d3d}.pc; do
343 [ -f "$dev/$pc" ] && substituteInPlace "$dev/$pc" --replace "$drivers" "${libglvnd.driverLink}"
344 done
345
346 # remove pkgconfig files for GL/EGL; they are provided by libGL.
347 rm -f $dev/lib/pkgconfig/{gl,egl}.pc
348
349 # Move development files for libraries in $drivers to $driversdev
350 mkdir -p $driversdev/include
351 mv $dev/include/xa_* $dev/include/d3d* -t $driversdev/include || true
352 mkdir -p $driversdev/lib/pkgconfig
353 for pc in lib/pkgconfig/{xatracker,d3d}.pc; do
354 if [ -f "$dev/$pc" ]; then
355 substituteInPlace "$dev/$pc" --replace $out $drivers
356 mv $dev/$pc $driversdev/$pc
357 fi
358 done
359
360 # Don't depend on build python
361 patchShebangs --host --update $out/bin/*
362
363 # NAR doesn't support hard links, so convert them to symlinks to save space.
364 jdupes --hard-links --link-soft --recurse "$drivers"
365
366 # add RPATH so the drivers can find the moved libgallium and libdricore9
367 # moved here to avoid problems with stripping patchelfed files
368 for lib in $drivers/lib/*.so* $drivers/lib/*/*.so*; do
369 if [[ ! -L "$lib" ]]; then
370 patchelf --set-rpath "$(patchelf --print-rpath $lib):$drivers/lib" "$lib"
371 fi
372 done
373
374 # add RPATH here so Zink can find libvulkan.so
375 patchelf --add-rpath ${vulkan-loader}/lib $drivers/lib/dri/zink_dri.so
376 '';
377
378 env.NIX_CFLAGS_COMPILE = toString ([
379 "-UPIPE_SEARCH_DIR"
380 "-DPIPE_SEARCH_DIR=\"${placeholder "opencl"}/lib/gallium-pipe\""
381 ]);
382
383 passthru = {
384 inherit (libglvnd) driverLink;
385 inherit llvmPackages;
386
387 tests.devDoesNotDependOnLLVM = stdenv.mkDerivation {
388 name = "mesa-dev-does-not-depend-on-llvm";
389 buildCommand = ''
390 echo ${mesa.dev} >>$out
391 '';
392 disallowedRequisites = [ llvmPackages.llvm mesa.drivers ];
393 };
394
395 llvmpipeHook = makeSetupHook {
396 name = "llvmpipe-hook";
397 substitutions.drivers = mesa.drivers;
398 } ./llvmpipe-hook.sh;
399 };
400}