1{
2 lib,
3 bison,
4 buildPackages,
5 directx-headers,
6 elfutils,
7 expat,
8 fetchCrate,
9 fetchFromGitLab,
10 file,
11 flex,
12 glslang,
13 spirv-tools,
14 intltool,
15 jdupes,
16 libdrm,
17 libgbm,
18 libglvnd,
19 libpng,
20 libunwind,
21 libva-minimal,
22 libvdpau,
23 llvmPackages,
24 lm_sensors,
25 meson,
26 ninja,
27 pkg-config,
28 python3Packages,
29 runCommand,
30 rust-bindgen,
31 rust-cbindgen,
32 rustc,
33 spirv-llvm-translator,
34 stdenv,
35 udev,
36 valgrind-light,
37 vulkan-loader,
38 wayland,
39 wayland-protocols,
40 wayland-scanner,
41 xcbutilkeysyms,
42 xorg,
43 zstd,
44 enablePatentEncumberedCodecs ? true,
45 withValgrind ? lib.meta.availableOn stdenv.hostPlatform valgrind-light,
46
47 # We enable as many drivers as possible here, to build cross tools
48 # and support emulation use cases (emulated x86_64 on aarch64, etc)
49 galliumDrivers ? [
50 "asahi" # Apple AGX
51 "crocus" # Intel legacy
52 "d3d12" # WSL emulated GPU (aka Dozen)
53 "etnaviv" # Vivante GPU designs (mostly NXP/Marvell SoCs)
54 "freedreno" # Qualcomm Adreno (all Qualcomm SoCs)
55 "i915" # Intel extra legacy
56 "iris" # new Intel (Broadwell+)
57 "lima" # ARM Mali 4xx
58 "llvmpipe" # software renderer
59 "nouveau" # Nvidia
60 "panfrost" # ARM Mali Midgard and up (T/G series)
61 "r300" # very old AMD
62 "r600" # less old AMD
63 "radeonsi" # new AMD (GCN+)
64 "softpipe" # older software renderer
65 "svga" # VMWare virtualized GPU
66 "tegra" # Nvidia Tegra SoCs
67 "v3d" # Broadcom VC5 (Raspberry Pi 4)
68 "vc4" # Broadcom VC4 (Raspberry Pi 0-3)
69 "virgl" # QEMU virtualized GPU (aka VirGL)
70 "zink" # generic OpenGL over Vulkan, experimental
71 ],
72 vulkanDrivers ? [
73 "amd" # AMD (aka RADV)
74 "asahi" # Apple AGX
75 "broadcom" # Broadcom VC5 (Raspberry Pi 4, aka V3D)
76 "freedreno" # Qualcomm Adreno (all Qualcomm SoCs)
77 "gfxstream" # Android virtualized GPU
78 "imagination-experimental" # PowerVR Rogue (currently N/A)
79 "intel_hasvk" # Intel Haswell/Broadwell, "legacy" Vulkan driver (https://www.phoronix.com/news/Intel-HasVK-Drop-Dead-Code)
80 "intel" # new Intel (aka ANV)
81 "microsoft-experimental" # WSL virtualized GPU (aka DZN/Dozen)
82 "nouveau" # Nouveau (aka NVK)
83 "panfrost" # ARM Mali Midgard and up (T/G series)
84 "swrast" # software renderer (aka Lavapipe)
85 ]
86 ++
87 lib.optionals
88 (stdenv.hostPlatform.isAarch -> lib.versionAtLeast stdenv.hostPlatform.parsed.cpu.version "6")
89 [
90 # QEMU virtualized GPU (aka VirGL)
91 # Requires ATOMIC_INT_LOCK_FREE == 2.
92 "virtio"
93 ],
94 eglPlatforms ? [
95 "x11"
96 "wayland"
97 ],
98 vulkanLayers ? [
99 "device-select"
100 "intel-nullhw"
101 "overlay"
102 "screenshot"
103 "vram-report-limit"
104 ],
105 mesa,
106 mesa-gl-headers,
107 makeSetupHook,
108}:
109
110let
111 rustDeps = lib.importJSON ./wraps.json;
112
113 fetchDep =
114 dep:
115 fetchCrate {
116 inherit (dep) pname version hash;
117 unpack = false;
118 };
119
120 toCommand = dep: "ln -s ${dep} $out/${dep.pname}-${dep.version}.tar.gz";
121
122 packageCacheCommand = lib.pipe rustDeps [
123 (builtins.map fetchDep)
124 (builtins.map toCommand)
125 (lib.concatStringsSep "\n")
126 ];
127
128 packageCache = runCommand "mesa-rust-package-cache" { } ''
129 mkdir -p $out
130 ${packageCacheCommand}
131 '';
132
133 needNativeCLC = !stdenv.buildPlatform.canExecute stdenv.hostPlatform;
134
135 common = import ./common.nix { inherit lib fetchFromGitLab; };
136in
137stdenv.mkDerivation {
138 inherit (common)
139 pname
140 version
141 src
142 meta
143 ;
144
145 patches = [
146 ./opencl.patch
147 # https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/37027
148 ./gallivm-llvm-21.patch
149 ];
150
151 postPatch = ''
152 patchShebangs .
153
154 for header in ${toString mesa-gl-headers.headers}; do
155 if ! diff -q $header ${mesa-gl-headers}/$header; then
156 echo "File $header does not match between mesa and mesa-gl-headers, please update mesa-gl-headers first!"
157 exit 42
158 fi
159 done
160 '';
161
162 outputs = [
163 "out"
164 # OpenCL drivers pull in ~1G of extra LLVM stuff, so don't install them
165 # if the user didn't explicitly ask for it
166 "opencl"
167 # the Dozen drivers depend on libspirv2dxil, but link it statically, and
168 # libspirv2dxil itself is pretty chonky, so relocate it to its own output in
169 # case anything wants to use it at some point
170 "spirv2dxil"
171 ]
172 ++ lib.optionals (!needNativeCLC) [
173 # tools for the host platform to be used when cross-compiling.
174 # mesa builds these only when not already built. hence:
175 # - for a non-cross build (needNativeCLC = false), we do not provide mesa
176 # with any `*-clc` binaries, so it builds them and installs them.
177 # - for a cross build (needNativeCLC = true), we provide mesa with `*-clc`
178 # binaries, so it skips building & installing any new CLC files.
179 "cross_tools"
180 ];
181
182 # Keep build-ids so drivers can use them for caching, etc.
183 # Also some drivers segfault without this.
184 separateDebugInfo = true;
185 __structuredAttrs = true;
186
187 # Needed to discover llvm-config for cross
188 preConfigure = ''
189 PATH=${lib.getDev llvmPackages.libllvm}/bin:$PATH
190 '';
191
192 env.MESON_PACKAGE_CACHE_DIR = packageCache;
193
194 mesonFlags = [
195 "--sysconfdir=/etc"
196
197 # What to build
198 (lib.mesonOption "platforms" (lib.concatStringsSep "," eglPlatforms))
199 (lib.mesonOption "gallium-drivers" (lib.concatStringsSep "," galliumDrivers))
200 (lib.mesonOption "vulkan-drivers" (lib.concatStringsSep "," vulkanDrivers))
201 (lib.mesonOption "vulkan-layers" (lib.concatStringsSep "," vulkanLayers))
202
203 # Enable glvnd for dynamic libGL dispatch
204 (lib.mesonEnable "glvnd" true)
205 (lib.mesonEnable "gbm" true)
206 (lib.mesonBool "libgbm-external" true)
207
208 (lib.mesonBool "teflon" true) # TensorFlow frontend
209
210 # Enable all freedreno kernel mode drivers. (For example, virtio can be
211 # used with a virtio-gpu device supporting drm native context.) This option
212 # is ignored when freedreno is not being built.
213 (lib.mesonOption "freedreno-kmds" "msm,kgsl,virtio,wsl")
214
215 # Required for OpenCL
216 (lib.mesonOption "clang-libdir" "${lib.getLib llvmPackages.clang-unwrapped}/lib")
217
218 # Rusticl, new OpenCL frontend
219 (lib.mesonBool "gallium-rusticl" true)
220 (lib.mesonOption "gallium-rusticl-enable-drivers" "auto")
221
222 # Enable more sensors in gallium-hud
223 (lib.mesonBool "gallium-extra-hud" true)
224
225 # Disable valgrind on targets where it's not available
226 (lib.mesonEnable "valgrind" withValgrind)
227
228 # Enable Intel RT stuff when available
229 (lib.mesonEnable "intel-rt" (stdenv.hostPlatform.isx86_64 || stdenv.hostPlatform.isAarch64))
230
231 # meson auto_features enables these, but we do not want them
232 (lib.mesonEnable "gallium-mediafoundation" false) # Windows only
233 (lib.mesonEnable "android-libbacktrace" false) # Android only
234 (lib.mesonEnable "microsoft-clc" false) # Only relevant on Windows (OpenCL 1.2 API on top of D3D12)
235 ]
236 ++ lib.optionals enablePatentEncumberedCodecs [
237 (lib.mesonOption "video-codecs" "all")
238 ]
239 ++ lib.optionals (!needNativeCLC) [
240 # Build and install extra tools for cross
241 (lib.mesonOption "tools" "asahi,panfrost")
242 (lib.mesonBool "install-mesa-clc" true)
243 (lib.mesonBool "install-precomp-compiler" true)
244 ]
245 ++ lib.optionals needNativeCLC [
246 (lib.mesonOption "mesa-clc" "system")
247 (lib.mesonOption "precomp-compiler" "system")
248 ];
249
250 strictDeps = true;
251
252 buildInputs =
253 with xorg;
254 [
255 directx-headers
256 elfutils
257 expat
258 spirv-tools
259 libdrm
260 libgbm
261 libglvnd
262 libpng
263 libunwind
264 libva-minimal
265 libvdpau
266 libX11
267 libxcb
268 libXext
269 libXfixes
270 libXrandr
271 libxshmfence
272 libXxf86vm
273 llvmPackages.clang
274 llvmPackages.clang-unwrapped
275 llvmPackages.libclc
276 llvmPackages.libllvm
277 lm_sensors
278 python3Packages.python # for shebang
279 spirv-llvm-translator
280 udev
281 vulkan-loader
282 wayland
283 wayland-protocols
284 xcbutilkeysyms
285 xorgproto
286 zstd
287 ]
288 ++ lib.optionals withValgrind [
289 valgrind-light
290 ];
291
292 depsBuildBuild = [
293 pkg-config
294 buildPackages.stdenv.cc
295 ];
296
297 nativeBuildInputs = [
298 meson
299 pkg-config
300 ninja
301 intltool
302 bison
303 flex
304 file
305 python3Packages.python
306 python3Packages.packaging
307 python3Packages.pycparser
308 python3Packages.mako
309 python3Packages.ply
310 python3Packages.pyyaml
311 jdupes
312 # Use bin output from glslang to not propagate the dev output at
313 # the build time with the host glslang.
314 (lib.getBin glslang)
315 rustc
316 rust-bindgen
317 rust-cbindgen
318 wayland-scanner
319 ]
320 ++ lib.optionals needNativeCLC [
321 # `or null` to not break eval with `attribute missing` on darwin to linux cross
322 (buildPackages.mesa.cross_tools or null)
323 ];
324
325 disallowedRequisites = lib.optional (
326 needNativeCLC && buildPackages.mesa ? cross_tools
327 ) buildPackages.mesa.cross_tools;
328
329 doCheck = false;
330
331 postInstall = ''
332 moveToOutput bin/asahi_clc $cross_tools
333 moveToOutput bin/intel_clc $cross_tools
334 moveToOutput bin/mesa_clc $cross_tools
335 moveToOutput bin/panfrost_compile $cross_tools
336 moveToOutput bin/panfrost_texfeatures $cross_tools
337 moveToOutput bin/panfrostdump $cross_tools
338 moveToOutput bin/vtn_bindgen2 $cross_tools
339
340 moveToOutput "lib/lib*OpenCL*" $opencl
341 # Construct our own .icd file that contains an absolute path.
342 mkdir -p $opencl/etc/OpenCL/vendors/
343 echo $opencl/lib/libRusticlOpenCL.so > $opencl/etc/OpenCL/vendors/rusticl.icd
344
345 moveToOutput bin/spirv2dxil $spirv2dxil
346 moveToOutput "lib/libspirv_to_dxil*" $spirv2dxil
347 '';
348
349 postFixup = ''
350 # set full path in EGL driver manifest
351 for js in $out/share/glvnd/egl_vendor.d/*.json; do
352 substituteInPlace "$js" --replace-fail '"libEGL_' '"'"$out/lib/libEGL_"
353 done
354
355 # and in Vulkan layer manifests
356 for js in $out/share/vulkan/{im,ex}plicit_layer.d/*.json; do
357 substituteInPlace "$js" --replace '"libVkLayer_' '"'"$out/lib/libVkLayer_"
358 done
359
360 # remove DRI pkg-config file, provided by dri-pkgconfig-stub
361 rm -f $out/lib/pkgconfig/dri.pc
362
363 # remove headers moved to mesa-gl-headers
364 for header in ${toString mesa-gl-headers.headers}; do
365 rm -f $out/$header
366 done
367
368 # clean up after removing stuff
369 find $out -type d -empty -delete
370
371 # Don't depend on build python
372 patchShebangs --host --update $out/bin/*
373
374 # NAR doesn't support hard links, so convert them to symlinks to save space.
375 jdupes --hard-links --link-soft --recurse "$out"
376
377 # add RPATH here so Zink can find libvulkan.so
378 patchelf --add-rpath ${vulkan-loader}/lib $out/lib/libgallium*.so
379 '';
380
381 passthru = {
382 inherit (libglvnd) driverLink;
383 inherit llvmPackages;
384 inherit
385 eglPlatforms
386 galliumDrivers
387 vulkanDrivers
388 vulkanLayers
389 ;
390
391 # for compatibility
392 drivers = lib.warn "`mesa.drivers` is deprecated, use `mesa` instead" mesa;
393
394 tests.outDoesNotDependOnLLVM = stdenv.mkDerivation {
395 name = "mesa-does-not-depend-on-llvm";
396 buildCommand = ''
397 echo ${mesa} >>$out
398 '';
399 disallowedRequisites = [ llvmPackages.llvm ];
400 };
401
402 llvmpipeHook = makeSetupHook {
403 name = "llvmpipe-hook";
404 substitutions.mesa = mesa;
405 } ./llvmpipe-hook.sh;
406 };
407}