The GPU's own firmware, booted from a macOS kext. A real display driver, compute, video decode, Vulkan, and Metal coming up on top.
Not a framebuffer hack. Not a VM. Bare metal.
What works · Numbers · How it fits together · Build · Support · Credits
Note
Made for fun, on one PC, by one person with a lot of reboots. It's not a product and it's not ready for your daily machine. If you'd like it to become a real driver, here's how you can help.
Apple never shipped a driver for any NVIDIA card newer than Kepler. From Mojave onwards there's nothing at all. On a modern Hackintosh an RTX card is dead weight, or at best a dumb framebuffer sitting on the firmware's GOP screen.
We wanted to see how far one person could actually push it. Turns out, pretty far.
Everything here ran on real hardware, on this exact box:
| Board | MSI X870E GAMING PLUS WIFI |
| CPU | AMD Ryzen 9 7950X |
| GPU | NVIDIA GeForce RTX 4080 16 GB (AD103, Ada Lovelace) |
| OS | macOS Sonoma 14.8.9 |
| GPU firmware | NVIDIA GSP-RM r570.144 |
- GSP-RM boot from a macOS kext. The FWSEC and SEC2 booter chain is all done by us.
- Display: 4K 60 Hz on DisplayPort, EDID, hotplug, vblank interrupts, DPMS.
- Resizable BAR set up by the kext itself. 16 GiB BAR1, even though macOS only sizes BARs up to 1 GiB.
- Write-combined VRAM mappings. We fixed the PAT so XNU's WC is real: CPU writes to VRAM went from 2.1 to 9.4 GB/s.
- Power: idles in P8 like on Windows, boosts to ~2850 MHz under load.
- Compute: our own QMD submission, with shaders compiled by Mesa's NAK.
- Vulkan: NVK (Mesa) runs on our kext. Host-visible buffers live in VRAM (vkcopy 44 GB/s).
- Video decode: NVDEC H.264 through VideoToolbox, bit-exact against libavcodec. HEVC works too.
- Metal: device, buffers, textures, blits, compute, render, MSAA, tessellation, MPS kernels.
- WindowServer composites on our GPU. Flips go through IOAccelDisplayPipe but are still a CPU copy (6.6 ms per 4K frame).
- Activity Monitor: GPU graph and per-app GPU memory.
- Full login session on the native Metal path. Some draws hang the graphics engine in a real user session. This is the main thing being chased.
- Hardware cursor. The core channel throws an exception.
- GPU reset recovery without a reboot. Partial.
- Sleep (S3). GSP comes back, but the display PLL isn't reprogrammed, so the monitor sees no signal.
- macOS Tahoe 26. Not ported yet. Tahoe already installs and boots on the same PC with the GPU driver off.
| Test | Linux (NVIDIA 570) | Windows (NVIDIA) | macOS + OpenNVDA |
|---|---|---|---|
| GPU memory fill | 663 GB/s | 649 GB/s | 668.5 GB/s |
| GPU copy kernel | 293 GB/s | 290 GB/s | 309.0 GB/s |
| FP32 compute | 47.27 TFLOPS | 47.38 TFLOPS | 47.72 TFLOPS |
| Host ↔ GPU (pinned / shared) | 26.9 / 26.4 GB/s | 26.8 / 26.4 GB/s | 26 GB/s |
On raw compute, the 4080 on macOS keeps up with NVIDIA's own drivers on the same machine.
Important
These numbers come from our low-level runtime (nvrun + NAK shaders), not from Metal apps. Metal on top is much younger. Tiled SGEMM through Metal does about 3.2 TFLOPS today, and dispatch latency is around 50 µs. Closing that gap is the main work left.
How these were measured
- Setup: same PC, same card, booted into each OS in turn.
- Linux and Windows: NVIDIA's official driver.
- macOS: OpenNVDA with
nvrunand the gold kernels frommacos-lab-tools(nvrun,bench,nakc/kernels). - Warm-up: every run is warmed up so the GPU is at its boost clock. A cold short run on macOS gave 42 TFLOPS, only because the clock hadn't ramped yet.
flowchart TB
subgraph user["User space"]
WS["WindowServer / apps"]
MTL["NVMTLDriver<br/>(Metal driver bundle)"]
NVK["nvk-macos<br/>(Vulkan)"]
VT["VideoToolbox<br/>+ nvdec"]
end
subgraph kernel["Kernel (kexts)"]
ACC["NVAccelerator<br/>IOAcceleratorFamily2"]
DISP["NVDisplay<br/>IOFramebuffer"]
CTRL["NVGspControl<br/>GSP boot · RM · memory · channels · IRQs"]
end
GPU[("RTX 4080<br/>GSP-RM firmware")]
WS --> MTL --> ACC --> CTRL
WS --> DISP --> CTRL
NVK --> CTRL
VT --> CTRL
CTRL <--> GPU
What's in each folder
| Folder | What it is |
|---|---|
drivers/NVGspControl |
The main kext. Boots GSP, owns RM, memory, channels, interrupts, the display engine, sleep/wake |
drivers/NVGspCore |
Header-only core shared by the kexts and the host tests (ABI structs, boot staging, VA arena, heap) |
drivers/NVDisplay |
IOFramebuffer driver on top of NVGspControl, the thing WindowServer talks to |
drivers/NVAccelerator |
IOAcceleratorFamily2 accelerator, the kernel half of Metal |
drivers/NVMTLDriver |
Metal driver bundle, the user half of Metal |
drivers/nvdec |
H.264 and HEVC decode on NVDEC |
drivers/nvenc |
NVENC encode, early |
drivers/NVVTDecoder |
VideoToolbox decoder plug-in (parked experiment) |
drivers/nvk-macos |
Mesa's NVK Vulkan driver, ported to run on our kext |
drivers/NVFramebuffer |
The first framebuffer kext, only scans out the GOP surface. Kept as a fallback |
drivers/NVFBProbe |
The early probe that measured BARs, console and VBIOS before anything real existed |
research/full-metal-rnd |
Notes and experiments on the road to full Metal |
tools/gen_booter_unload.py |
Makes the one NVIDIA firmware header the kext needs, from your own linux-firmware copy |
You need MacKernelSDK and a workspace from macos-lab/workspace.sh, which links drivers/NV* into the layout the build script expects:
python3 tools/gen_booter_unload.py /path/to/linux-firmware/nvidia/ad103/gsp/booter_unload-570.144.bin
sh tools/build_kext.sh NVGspControl /path/to/MacKernelSDK [gsp-package.bin]
sh tools/build_kext.sh NVDisplay /path/to/MacKernelSDKCaution
No NVIDIA firmware is in this repo, and none ever will be. GSP-RM, the booters and the VBIOS belong to NVIDIA. You take them from linux-firmware or your own NVIDIA driver install, and nvgsp_package.py packs them for the kext.
Host tests live next to each part:
drivers/NVGspControl/testsdrivers/nvdec/tests/*/run.shdrivers/nvk-macos/tests/nvkmd_macos/run.sh
- It's written for one card (AD103) on one board. Other Ada cards might get somewhere; anything older won't.
- You need:
- our OpenCore setup;
- SIP and authenticated root turned off;
- a second OS you can boot when a test goes wrong.
- A bad GPU state can hang the machine until a cold reboot. Back up your data. We're not responsible for what happens to your machine.
- Not affiliated with NVIDIA or Apple. All trademarks belong to their owners.
- GSP-RM boot, display, ReBAR, write-combining, power states
- Compute, copy engines, Vulkan (NVK), NVDEC
- Metal basics, WindowServer on our GPU
- Stable login session on the native Metal path
- Direct scan-out flips (no CPU copy)
- Metal apps at the same speed as the raw numbers
- Hardware cursor, sleep/wake, GPU reset recovery
- macOS Tahoe 26
- PyTorch (MPS), then MLX, on the RTX
Right now it's a hobby: nights and weekends on one PC. To turn it into something other people can install and trust, it needs:
- time (months, not weeks);
- more cards to test on: a 4070 or 4090, a 30-series;
- a spare machine, so one broken boot doesn't stop everything.
Backers get their name in this README. If a company or a group wants to fund proper work (more cards, Tahoe support, a stable release), open an issue titled "Funding" and let's talk.
Even a ⭐ or a share helps. It tells us people actually want this.
Built by bdwithganesh.
To be upfront: a lot of the code was written with AI help. The rest was me:
- the idea, and the stubbornness to keep going;
- every direction call;
- the hardware and every test on it: hundreds of reboots, Linux and Windows reference captures, reading logs at 3 am;
- deciding what "working" actually means.
This stands on other people's shoulders:
| Project | What we owe them |
|---|---|
| nouveau | Years of reverse engineering NVIDIA GPUs |
| NVIDIA open-gpu-kernel-modules / open-gpu-doc | Without these, GSP-RM would be a black box |
| Mesa (NVK, NAK) | The Vulkan driver and the shader compiler we build on |
| envytools | Register documentation |
| acidanthera | MacKernelSDK, Lilu, OpenCore |
| WebKit | The VideoToolbox SPI declarations |
Where our code follows one of them closely, the comment right there says so. Full list with licences: THIRD_PARTY_NOTICES.md.
MIT, see LICENSE. Third-party files keep their own headers and licences.