Built 2026-10-21 on the Legion (macOS Tahoe 26.7.1 25G241, Core Ultra 9 275HX), native x86_64, nothing installed outside ~/src/xe-userland and the new venv ~/.venvs/mesa. Result: the build works, and all 28 simulated Intel chips create a device and compile the compute pipeline through the Darwin noop drm-shim.
| Tree | Commit | Patch | Patch sha256 (first 16) | Status |
|---|---|---|---|---|
libdrm (drm/) |
b97cbde15c5c3abfe44d78e8f57139e50f612fec (2.4.134, "amdgpu: add missing marketing names and minor name fixes") |
NvGfx-wt-n67/gpu-port/patches/libdrm-macos.patch |
a82d4d40b7090926 |
git apply --check clean, applied, 3 files |
Mesa (mesa/) |
bffd91947efc1932da99aca69fc540d6d4201b0c (26.3.0-devel, "nvk: Use meta gfx for depth copies", 2026-10-10) |
NvGfx-wt-n67/gpu-port/patches/mesa-macos.patch |
5ebeef3a0466e7d3 |
git apply --check clean, applied, 12 files (11 modified + drm_shim_darwin.c) |
| Vulkan-Headers, Vulkan-Loader | tag v1.4.328 (Khronos GitHub) |
none | test loader for vkprobe only |
Both patches applied with no rejects. No source change was needed on top of them. Mesa was fetched shallow (depth 1) by full SHA, which was resolved from the short one through the GitLab API.
Apple clang 21.0.0 (CLT), SDKROOT=/Library/Developer/CommandLineTools/SDKs/MacOSX15.5.sdk, MacPorts meson 1.12.1, ninja, glslang 16.6.0, cmake, LLVM 20.1.8 (host tools only), SPIRV-LLVM-Translator from ~/.local/nvgfx-llvm/lib/pkgconfig (host tools only). Python 3.14.8 venv ~/.venvs/mesa (from MacPorts python3.14) with mako 1.4.3, PyYAML 6.0.3, packaging 26.3; its bin is first in PATH so meson's python finds mako.
scripts/env.sh: PATH, SDKROOT pin,CC=/usr/bin/clang, deployment target.scripts/build_libdrm.sh(logs/libdrm.log): prefix~/src/xe-userland/prefix,--libdir=lib, release, every driver off,-Dintel=disabled(see deviations), tests, man pages, cairo, valgrind off.PKG_CONFIG_LIBDIRlimited to the prefix.scripts/build_host_clc.sh(logs/host-clc.log):mesa_clcandvtn_bindgen2from the same patched Mesa tree, LLVM 20 shared, installed to~/src/xe-userland/host/bin. Options as in NvGfxbuild_nvk.shstep 1 (-Dmesa-clc=enabled -Dinstall-mesa-clc=true -Dllvm=enabled -Dshared-llvm=enabled, all drivers off), native file withcmake = 'false'. These run only on the build machine.scripts/build_mesa.sh(logs/mesa.log), the target build:
meson setup mesa/build mesa --native-file native-target.ini --prefix=$X/prefix --libdir=lib \
-Dbuildtype=release -Db_ndebug=true \
-D{c,cpp,objc}_args=-mmacosx-version-min=14.4 -D{c,cpp}_link_args=-mmacosx-version-min=14.4 \
-Dvulkan-drivers=intel -Dgallium-drivers= -Dplatforms= -Dtools=drm-shim -Dllvm=disabled \
-Dmesa-clc=system -Dprecomp-compiler=auto \
-Dopengl=false -Dgles1=disabled -Dgles2=disabled -Degl=disabled -Dglx=disabled -Dglvnd=disabled -Dgbm=disabled \
-Dvulkan-layers= -Dbuild-tests=false -Dexpat=enabled -Dzstd=disabled -Dlibunwind=disabled -Dlmsensors=disabled \
-Dvalgrind=disabled -Dxlib-lease=disabled -Dgallium-rusticl=false -Dvideo-codecs=
native-target.ini sets cmake = 'false' and llvm-config = 'false'; PATH has host/bin first so -Dmesa-clc=system finds mesa_clc and vtn_bindgen2; PKG_CONFIG_LIBDIR=$X/prefix/lib/pkgconfig:$X/sdk-pc. -Dllvm=disabled works: ANV needs LLVM only for its precompiled OpenCL helper kernels (src/intel/shaders, built by mesa_clc + vtn_bindgen2), and no intel_clc is needed at this commit. The target dylib links no LLVM. 62 compiler warnings, none fatal.
scripts/build_loader.sh(logs/loader.log): Khronos headers and loader intoloader-prefix/, for vkprobe only.- vkprobe and drmlist in
tools/:fill.compcompiled withglslangValidator -V --target-env vulkan1.3, checked withspirv-val, turned intofill_spv.hwithxxd -i -n fill_spv;vkprobelinked againstloader-prefix/lib/libvulkan.dylib,drmlistagainst the new libdrm (built, not run: there are no/dev/drinodes yet).
No diffs to Mesa or libdrm sources beyond the two NullMoth patches. Build-side changes:
- libdrm
-Dintel=disabledinstead ofenabled.-Dintelbuildslibdrm_intel, the legacy GEM helper, which hard-requires libpciaccess (no Darwin backend, not installed). Mesa useslibdrm_intelonly for gallium i915 (meson.build:777-779); ANV and the noop shim use core libdrm only. So the corelibdrm.2.dylibis all ANV needs. - libdrm b97cbde has no
freedrenooption; it was dropped from the option list. - expat from the macOS SDK. With
-Dexpat=disabled,libintel_decoder_gen.ahas no sources and Applearrefuses an empty archive (ar: no archive members specified). Rather than pull in MacPorts expat,sdk-pc/expat.pcpoints at the SDK's-lexpat(2.7.1,/usr/lib/libexpat.1.dylib):
Name: expat
Version: 2.7.1
Libs: -lexpat
Cflags:
- ICD manifest for tests:
intel_test_icd.jsonpoints atprefix/lib/libvulkan_intel.dylib.
-mmacosx-version-min=11.0compiles and links (log kept aslogs/mesa-min11.0.log), but the binary is not correct there: the patch's futex code insrc/util/futex.ccallsos_sync_wait_on_address,os_sync_wait_on_address_with_timeout,os_sync_wake_by_address_any/all, which are macOS 14.4 API and get weak-linked, so they would be NULL calls on older systems.intel_measure.calso usesmkfifoat(13.0, only withINTEL_MEASURE).- Shipped build: Mesa at 14.4 (
minos 14.4, no-Wunguarded-availabilitywarnings left), libdrm at 11.0 (minos 11.0, no newer API used). Going below 14.4 would need a runtime fallback infutex.c(for example__ulock_wait, private API), not done.
| File | Size (bytes) | sha256 (first 16) | minos / sdk |
|---|---|---|---|
prefix/lib/libvulkan_intel.dylib |
32,829,768 | bb83266133d6d545 |
14.4 / 15.5 |
prefix/lib/libintel_noop_drm_shim.dylib |
275,408 | e65e5c39253ba92d |
14.4 / 15.5 |
prefix/lib/libdrm.2.dylib |
81,080 | 53f7f1588fcdf8d7 |
11.0 / 15.5 |
Also installed: prefix/share/vulkan/icd.d/intel_icd.x86_64.json (api_version 1.4.363), prefix/share/drirc.d/00-{mesa,anv}-defaults.conf, libdrm headers and libdrm.pc.
otool -L libvulkan_intel.dylib:
/Users/bash/src/xe-userland/prefix/lib/libvulkan_intel.dylib
/usr/lib/libSystem.B.dylib (current 1351.0.0)
/Users/bash/src/xe-userland/prefix/lib/libdrm.2.dylib (compat 2.0.0)
/usr/lib/libz.1.dylib (current 1.2.12)
/usr/lib/libexpat.1.dylib (current 8.0.0)
/usr/lib/libc++.1.dylib (current 1900.180.0)
The install names are absolute paths into this tree; a package will need install_name_tool -id and -change (or @rpath) for libdrm. The shim links only libdrm and libSystem.
11,195 undefined in total: 261 from libSystem, libc++, libz, libexpat; 58 from libdrm (drmIoctl, drmGetDevices2, drmMode*, drmCrtc*Sequence, and so on); 10,876 weak, flat-namespace, "dynamically looked up", none of them non-weak. By prefix: anv_ 4085, vk_ 1569, wsi_ 742, gfx9_/gfx11_/gfx12_ 648 each, gfx125_/gfx20_/gfx30_/gfx35_ 634 each. These are the entrypoint-table slots for Vulkan commands a layer does not implement (for example anv_AllocateCommandBuffers, which vk_common covers), left undefined on purpose by the patch's b_lundef=false and resolved to NULL at load. Two things to keep in mind:
- Flat-namespace lookup means a same-named exported symbol in another image of the process would be bound instead of NULL. Mesa drivers keep these names hidden, so this is theoretical, but loading ANV and NVK in one process should be tested once.
- Exports: the three
vk_icd*functions, plus 140gfx*_libanv_*,gfx*_write_*,gfx*_copy_data/set_datasymbols from thevtn_bindgen2-generated shader bindings, which are not hidden. On Linux the version script hides them; on Darwin nothing does. Harmless for function, but an-exported_symbols_listwould be cleaner.
scripts/vk_chip_matrix_intel.sh is the Intel half of NullMoth's vk_chip_matrix.sh with this tree's paths. Each run uses env -i, DYLD_INSERT_LIBRARIES=prefix/lib/libintel_noop_drm_shim.dylib, VK_ICD_FILENAMES=VK_DRIVER_FILES=intel_test_icd.json, MESA_SHADER_CACHE_DISABLE=true (so every chip really compiles), and INTEL_STUB_GPU_PLATFORM=<name> or INTEL_STUB_GPU_DEVICE_ID=<id>. The loader log (VK_LOADER_DEBUG=driver) confirms only our dylib is loaded. Per-chip output is in logs/matrix/, the summary in logs/chip-matrix.txt.
| Chip | PCI ID | Device name | vkCreateDevice | Compute pipeline |
|---|---|---|---|---|
| Gen12 TGL | 0x9a49 | Iris Xe Graphics (TGL GT2) | OK | OK |
| Gen12 RKL | 0x4c8a | Graphics (RKL GT1) | OK | OK |
| Gen12 DG1 | 0x4905 | Iris Xe MAX Graphics (DG1) | OK | OK |
| Gen12 ADL | 0x4680 | UHD Graphics 770 (ADL-S GT1) | OK | OK |
| Gen12 RPL | 0xa780 | Graphics (RPL-S) | OK | OK |
| Gen12 RPL-P | 0xa7a0 | Iris Xe Graphics (RPL-P) | OK | OK |
| Xe-HPG DG2 | 0x5690 | Arc A770M Graphics (DG2) | OK | OK |
| Xe-HPG DG2 | 0x56a0 | Arc A770 Graphics (DG2) | OK | OK |
| Xe-LPG MTL | 0x7d60 | Graphics (MTL) | OK | OK |
| Xe-LPG MTL | 0x7dd5 | Graphics (MTL) | OK | OK |
| Xe-LPG MTL | 0x7d55 | Arc Graphics (MTL) | OK | OK |
| ARL (Legion iGPU) | 0x7d67 | Graphics (ARL) | OK | OK |
| ARL | 0x7d41 | Graphics (ARL) | OK | OK |
| ARL | 0x7d51 | Graphics (ARL) | OK | OK |
| Xe2 LNL | 0x64a0 | Graphics (LNL) | OK | OK |
| Xe2 BMG | 0xe202 | Graphics (BMG G21) | OK | OK |
| Xe3 PTL | 0xb080 | Arc B390 (PTL) | OK | OK |
Older chips also pass: SKL, BXT, KBL, GLK, CFL, WHL, CML, ICL, EHL, JSL. Total 28 of 28.
For 0x7D67 the compute shader really compiles to Xe ISA: logs/arl-intel-debug-cs.txt (INTEL_DEBUG=cs) shows "SIMD16 shader: 11 instructions ... 2 sends" with the store.ugm.d32.a32 and EOT sends.
Limits of this proof: the noop shim fakes the i915 uAPI for every chip (it prints a few unknown query/getparam ids, which ANV tolerates), so LNL, BMG and PTL pass here through ANV's i915 path, while on real hardware they need the xe KMD path. Nothing is submitted to a GPU; this proves the driver loads, picks the device info, creates a device and runs the brw compiler on macOS. It does not exercise the xe uAPI, drm_mmap through NMX_DRM_IOCTL_MMAP, or a real /dev/dri node.
On top of NullMoth's two patches, for real XeGfx hardware: patches/libdrm-xegfx.patch (adds xf86drm_xegfx.c, the dma-buf and sync_file stand-ins, called first from drmIoctl()) and patches/mesa-xegfx.patch (intel_ioctl() through drmIoctl(), i915 GEM mappings through drmNmxMmap/drmNmxMunmap with a fallback to mmap(2) for drm-shim). Apply with git apply in drm/ and mesa/ after the NullMoth patches, then rerun build_libdrm.sh and the Mesa build. The noop drm-shim matrix still passes 28 of 28 chips with both applied.