Metal on AMD Radeon 780M for macOS Tahoe.
GPU bring-up, a display driver WindowServer composites on, and Metal over Vulkan (Mesa RADV)
for Phoenix / Hawk Point APUs (RDNA 3, GC 11.0.1, gfx1103).
English · Русский
Measured on the reference machine — Firebat U6C, Ryzen 7 H 255, Radeon 780M, 2560×1600 120 Hz eDP, macOS Tahoe 26.6.2 — in October 2026:
| Desktop | WindowServer composites on the 780M at the panel's 120 Hz. CoreAnimation runs at 119–120 fps; dragging a window, 116 fps. |
| Liquid Glass | Dock, widgets, Control Center and in-app glass are drawn by the GPU with Apple's own compositor shaders (translated). |
| Metal in apps | Every process gets the Metal device, sandboxed WebKit GPU processes included. About 46 apps checked with no crashes, Safari, Chess and Spotify among them. |
| Display sleep / wake | Works. |
| First use of a new effect | A one-time pause of about 1–3 s while its shader is translated and compiled. After that it comes from the disk cache. |
| Not yet | External displays (HDMI, USB-C), hardware video decode/encode, backlight control. |
Other Radeon 780M / 760M machines (Phoenix, Hawk Point) are untested.
flowchart TD
apps["Apps · WindowServer"] -->|Metal| plugin["NVMTLDriver.bundle<br/>Metal objects on Vulkan"]
plugin -->|"AIR → SPIR-V"| xlate["libnvmtl_translate"]
plugin -->|Vulkan| radv["Mesa RADV<br/>libvulkan_radeon.dylib"]
plugin -->|IOAccelerator| accel["PhxAccel.kext<br/>NMXAccel · PhxAMDFB · PhxAGDC"]
radv -->|"IOKit user client"| bringup["PhxBringup.kext<br/>PSP · MES · GPUVM"]
bringup --> gpu[("Radeon 780M")]
accel -->|scan-out| panel["eDP panel · DCN 3.1.4"]
| Component | Installed in | Source | Role |
|---|---|---|---|
PhxBringup.kext |
OpenCore EFI/OC/Kexts |
src/phxbringup |
Loads firmware through the PSP, powers up GFX (SMU/IMU), starts the MES scheduler and the compute and graphics queues, gives every process its own GPUVM address space, implements the BO/submit ABI RADV uses. |
PhxAccel.kext |
Auxiliary kernel collection | src/phxaccel |
NMXAccel IOAccelerator, the PhxAMDFB framebuffer (VRAM pool, 120 Hz vblank, frame copy to scan-out) and PhxAGDC display control. |
NVMTLDriver.bundle |
/System/Library/CoreServices/CoreTypes.bundle/Contents/Library/PhxGPU, linked from /Library/GPUBundles |
src/nmplugin |
The Metal driver plugin: Metal on Vulkan, zero-copy IOSurfaces, shader caches. |
libvulkan_radeon.dylib |
PhxGPU/nvmtl |
Mesa + mesa-patches-phoenix |
RADV for gfx1103 with a Darwin winsys. |
phxboot |
LaunchDaemon local.phxboot |
tools/phxctl/phxboot.sh |
Brings the GPU up at boot before WindowServer opens the panel, with fail-safes that fall back to the firmware framebuffer. |
libnvmtl_translate.dylib (Metal AIR → SPIR-V, LGPL-3.0, based on metal2vulkan) ships prebuilt with NullMoth's
plugin; its source is attached to every release. The NVMTL prefix is NullMoth's too: none of this is an NVIDIA driver.
Download nullarc-<version>.zip from the releases page and follow
docs/INSTALL.md. In short: add PhxBringup.kext and the boot-args to OpenCore, reboot, run
sudo ./install.sh --windowserver from the release folder, reboot twice.
Warning
WindowServer only loads an ad-hoc signed driver with AMFI relaxed (amfi=0x80, amfi_get_out_of_my_way=0x1).
That turns library validation off system-wide and FairPlay playback (Apple TV+, Netflix in Safari) stops working.
uninstall.sh and the guide's last section undo everything.
On the Mac (Command Line Tools, MacKernelSDK):
sh src/phxbringup/build.sh /path/to/MacKernelSDK # PhxBringup.kext
sh src/phxaccel/build.sh /path/to/MacKernelSDK # PhxAccel.kextThe plugin builds from src/nmplugin/NVMTLDevice.m, which includes the rest of src/nmplugin. RADV: Mesa
f5cb8ee0 + Cobalt64's Darwin patches + mesa-patches-phoenix.
Unit tests (firmware parsing, IP discovery) run on Linux or macOS and in CI:
make fixtures # Phoenix firmware from linux-firmware
make test- Zero-copy IOSurfaces — textures are linear images over the surface's own pages; WindowServer CPU 77 % → 36 %.
- Surface keep cache — CoreAnimation re-wraps the same IOSurfaces every frame; keeping their imports took a dragged window from 64–69 to 116 fps.
- VRAM pool — per-allocation contiguous memory fragmented after hours and display wake froze; one 512 MB pool now.
- RADV mutable descriptor lists — indexed by the sorted binding order instead of the original one; broke CoreImage blurs and Tahoe's layered icons.
- Nested loop unrolling (Mesa 0006) — a new compositor shader variant compiled ~2 s in RADV, one loop level per optimisation round; now ~1 s with identical code.
null + arc: the empty-set sign of a driver that did not exist, its ring opened into an arc. See the brand guide.
Several licenses apply; see LICENSE, THIRD_PARTY_NOTICES.md and LICENSES/.
- Code written for nullarc (
src/phxbringup,tools/phxctl, …): MIT, or GPL-2.0-only at your option. src/phxaccel,src/nmplugin,tools/nvmtl-patches: derived from NullMoth's macOS driver, PolyForm Noncommercial 1.0.0 — no commercial use.mesa-patches-phoenix: MIT, as Mesa. Release packages also carry LGPL-3.0 (shader translator), LLVM and AMD firmware; see the notices.
Built on the work of the Linux amdgpu team, Mesa, NullMoth, Cobalt64,
Acidanthera and the AMD-OSX community.