Status: Proposed (v3.0 design phase, branch v3)
Date: 2026-04-21
Updated: 2026-04-28 — vendor scope clarified after Phase B.4 verified; wgpu retirement reframed per-chipset (v4.0 AMD, v5.0 NVIDIA, v5.1 Intel) instead of a single v4.0 event. See development/roadmap.md.
Supersedes: n/a
Related: ADR 004 (C launcher FFI — stays in-tree until per-chipset retirement; full removal at v5.1), ADR 005 (public API surface marking)
Mabda ships today on a C launcher + wgpu-native foundation (ADR 004). That path gets consumers onto a stable GPU surface immediately and inherits wgpu-native's portability work. It is load-bearing.
For three reasons, mabda also needs a pure-Cyrius GPU backend:
- Sovereignty. AGNOS's stated direction is to own the stack down to the kernel. Indefinitely depending on wgpu-native — a Rust artifact linked as C — undermines that. A native Cyrius backend is a prerequisite for the AGNOS kernel GPU driver arc.
- Measurement story. Without a second backend, we cannot cleanly attribute future benchmark wins. Cyrius 5.6.x is landing a compiler optimization arc (O1–O6). If the only GPU path in mabda is the C-FFI one, the benchmark comparison conflates backend and codegen changes. Two backends × two cyrius generations gives us a 4-way matrix where each axis can be isolated.
- Long-horizon API stability. Consumers wrote against the v2.1.1
# @publicsurface on the promise that it would survive backend changes. Validating that promise requires running the same bench suite and the sameexamples/stdlib-consumer/project under an independent backend.
What this ADR is not: a replacement for ADR 004 during v3.x. ADR 004 stays accepted and load-bearing throughout the v3.x line. v4.0 is when the C path retires; that retirement is consumer-driven (every consumer has been running native in production across a full release cycle), not calendar-driven.
Ship a second mabda backend in v3.0, vendor-by-vendor across the v3.x–v5.x line:
- Name:
native(vs. the existingwgpubackend), with vendor variants —BACKEND_KIND_AMD(v3.0),BACKEND_KIND_NVIDIA(v4.0),BACKEND_KIND_INTEL(v5.0, tentative). - v3.0 scope: pure Cyrius DRM/KMS on Linux for AMD hardware
only — direct
ioctl(DRM_IOCTL_AMDGPU_*), GFX9 PM4 packet streams, pre-compiled GFX9 ISA. No libdrm, no libwayland, no wgpu-native, no C launcher. Phase B.4 verified end-to-end on AMD Cezanne (gfx90c). NVIDIA and Intel hardware run on the existing wgpu path through v3.x. AGNOS kernel GPU driver integration is a downstream v3.x+ follow-up once the userspace DRM/KMS path is stable. - Selection: per-consumer build-time. Compile-time constant
MABDA_BACKEND_KINDinsrc/lib.cyr(perdocs/proposals/v3-backend-interface.md); promotable to acyrius.cymlflag in v3.1+ if consumer CI matrices need it. - Default for v3.0:
wgpu. Consumers opt intonativeexplicitly. This keeps v3.0 byte-compatible for every existing consumer and makes the native backend the thing under test rather than the thing under load. - Public API is unchanged. ADR 005's
@publicsurface from v2.1.1 stays the same across both backends. ADR 005 is the machine-readable contract.
-
Backend abstraction layer (
src/backend.cyr,@internal)- Defines the set of operations every backend must implement: context creation, buffer create/write/map/release, compute pipeline create/dispatch, texture create/upload/release, render pipeline create/release, render pass begin/end, surface acquire/present, query timestamp.
- Each operation is a function-pointer slot on a
Backendstruct.GpuContextholds a pointer to its backend. - Existing wgpu-path fn-pointer dispatch (wgpu_ffi.cyr's 65-slot
table) sits under the wgpu backend's implementation; it does
not surface to
@publiccode.
-
src/backend_wgpu.cyr(@internal)- Implementation of the
Backendinterface that calls into the existing wgpu FFI tables. Existing code moves here behind the new indirection;@publiccallers never see the move.
- Implementation of the
-
src/backend_native.cyr(@internal)- Implementation of the
Backendinterface that talks directly to DRM/KMS. New module; scope carved up in follow-up proposals (Vulkan-on-kernel-driver vs. raw submission, WGSL lowering path, command ring buffer, allocator integration).
- Implementation of the
-
Dual-backend bench harness
make bench-gpuruns the 13-bench suite under each backend.bench-history.csvgrows abackendcolumn.docs/benchmarks-rust-v-cyrius.mdrefreshes with columns for Rust v1, wgpu-backend pre-5.6.x, wgpu-backend post-5.6.x, native-backend pre-5.6.x, native-backend post-5.6.x.
-
Consumer migration path (per-chipset retirement)
- v3.0:
wgpuis the default for everyone. AMD consumers can opt intoBACKEND_KIND_AMD(native). NVIDIA + Intel + macOS + Windows consumers stay onwgpu. - v3.x: AMD consumers test
nativein their CI matrix when ready. - v4.0: NVIDIA native (
BACKEND_KIND_NVIDIA) lands; AMD wgpu retires. AMD consumers run on AMD native only. NVIDIA + Intel still on wgpu. The wgpu binding stays in-tree to serve them. - v5.0: Intel native (
BACKEND_KIND_INTEL) lands (tentative); NVIDIA wgpu retires. Intel may still be on wgpu if v5.0 ships only the NVIDIA-side retirement. - v5.1: Intel wgpu retires and the entire wgpu+C scaffolding
leaves the tree (
deps/wgpu_main.c,deps/wgpu-native/,src/wgpu_*.cyr,src/backend_wgpu.cyrall removed). Mabda is fully native-Cyrius across every supported vendor. - Each per-chipset retirement is gated on every consumer on that vendor having flipped voluntarily; calendar dates are not the gate. v5.1 is gated on Intel native (v5.0) having shipped.
- v3.0:
- Backend swap in v3.0 (original roadmap). Rejected. Loses the measurement baseline, forces every consumer to move on our schedule rather than theirs, and makes a v3.0 regression in the native backend immediately user-visible without a fallback.
- Native backend on a long-lived feature branch, never in-tree. Rejected. Feature branches rot; the only way the native backend stays in parity with the public API is if it ships in-tree behind a flag and runs in CI.
- libdrm wrapper. Rejected. libdrm is another C dependency; the
whole point is zero C artifacts for GPU work in the native path.
DRM/KMS ioctls are callable directly from cyrius via
syscall.
Positive:
- AGNOS's sovereignty trajectory advances without destabilizing existing consumers.
- The 4-way bench matrix isolates cyrius codegen wins from backend architecture wins — directly enables the "worth writing about" story post-5.6.x.
- The
@publicstability contract gets tested against a real second implementation instead of being an untested claim. - Consumers migrate on their own timelines.
Negative:
- Two backends means two maintenance surfaces. Every new wgpu FFI entry needs a native-backend counterpart (or an explicit "not implemented on native yet" error). At v4.0+ the surface count grows (AMD native + NVIDIA native + wgpu remainder); at v5.x it peaks (three native backends + wgpu) before contracting at v5.1 back down to three.
- CI matrix roughly doubles the GPU test time per supported vendor. Mitigated because CPU-only tests (387 assertions, 7 CPU benches) run once regardless.
src/grows by the abstraction layer + per-vendor backend modules;dist/mabda.cyrgrows accordingly until v5.1's wgpu removal.
Neutral:
- The per-chipset retirement timeline is set by consumer cutover, not calendar. If consumers move fast on a vendor, that vendor's retirement window is near; if not, that vendor stays on wgpu longer. Either outcome is fine under this ADR.
- v5.1 is the explicit "wgpu fully out" milestone. If Intel native (v5.0) doesn't actually ship, v5.1 doesn't ship either — the wgpu binding stays in-tree to serve Intel until the gate is met.
Resolved during v3.0 design spike (some by Phase B.4 verification on 2026-04-28, others by the v3-backend-interface proposal):
- AMD WGSL → GFX9 ISA lowering. v3.0 takes pre-compiled GFX9 ISA bytes; lowering path landed as a v3.0 in-scope item (not yet implemented in code, but scoped — see roadmap). NVIDIA / Intel lowering paths are per-vendor v4.0 / v5.0 design items.
- Selector ergonomics. Resolved: compile-time constant
MABDA_BACKEND_KINDinsrc/lib.cyr, perdocs/proposals/v3-backend-interface.md. Promotable to acyrius.cymlflag in v3.1+ if needed.
Still open at the time of this update:
- Memory model. How does the native backend integrate with
mabda's manual
alloc/store64discipline? Does DRM/KMS BO management surface to theResourcetracker? (B.4 sidesteps this by allocating per-program; real consumer flows need an answer.) - Surface / present path. DRM/KMS provides raw scanout. Consumers (soorat, aethersafta) expect a surface abstraction compatible with what wgpu gives them today. Mapping TBD; gated on Phase D.
- Error model. wgpu errors come back through the FFI callback
path. Native backend errors come through syscall return. The
GpuErrcodes already exist (src/error.cyr); mapping TBD when the backend interface lands in code. - Per-vendor ADRs. Each vendor expansion (NVIDIA v4.0, Intel v5.0) gets its own ADR. ADR 007 = NVIDIA. ADR 008 = Intel. Both filed when their respective design phases open, not now.
- Flesh out the
Backendinterface in a proposal underdocs/proposals/before writingsrc/backend.cyr. - First DRM/KMS spike: compute-only path in
programs/native_compute_spike.cyr. Success criterion: a trivial compute shader dispatches and reads back via the native backend with no wgpu-native linked. - Update
docs/stdlib-integration.mdto document the backend flag once syntax is finalized. - Add
backendcolumn tobench-history.csvon first bench run under either backend (schema change is forward-compatible). - Log any cyrius-compiler friction encountered during native-backend
work in
docs/proposals/cyrius-5.6x-optimization-requests.mdfor upstream filing.