kopitiam_gpu/lib.rs
1//! # kopitiam-gpu — GPU parallel-compute foundation for KOPITIAM
2//!
3//! A shared, **domain-agnostic** parallel-compute layer built on
4//! [`wgpu`](https://docs.rs/wgpu). It is general compute infrastructure — the
5//! same foundation AI matmul, iterative root-finding kernels, and plot shaders
6//! all sit on — not a tool for any one field. First cut = compute pipelines;
7//! render pipelines come later.
8//!
9//! ## The two rules that shape this crate
10//!
11//! **1. wgpu is non-optional at compile.** There is no feature gate on the GPU.
12//! The wgpu code path is *always* compiled into the binary. wgpu itself
13//! Cargo-builds with pure-Rust backends (no C toolchain at build time), so this
14//! does not break KOPITIAM's Pure Rust Core build promise — it only needs GPU
15//! *drivers* at **runtime**, and their absence is handled below, not by a `cfg`.
16//!
17//! **2. A missing GPU is a runtime condition, handled by a `Result` cascade.**
18//! Plenty of machines have no usable GPU: headless CI, a GPU-less tablet, an
19//! Android Termux userland with no Vulkan driver installed. So:
20//!
21//! ```text
22//! GPU (wgpu compute shader) -- fast path, when a GPU is present
23//! | Err / no adapter
24//! v
25//! CPU (pure Rust) -- correct path, always available
26//! ```
27//!
28//! This mirrors KOPITIAM's Offline-First pipeline (existing -> native -> local
29//! -> cloud), here as **GPU -> CPU**. [`GpuContext::new`] probes for a GPU once
30//! and returns `Err` (never panics) if there is none; [`Executor`] caches that
31//! probe and runs each [`ComputeOp`] GPU-first, CPU-on-failure. Because the CPU
32//! twin is a real, correct pure-Rust implementation — not a stub — the answer is
33//! guaranteed on every machine.
34//!
35//! ## Quick start
36//!
37//! ```
38//! use kopitiam_gpu::{Executor, ops::VectorAdd, ops::VectorAddInput};
39//!
40//! // Builds fine and runs correctly whether or not this machine has a GPU.
41//! let exec = Executor::new();
42//! let a = [1.0f32, 2.0, 3.0];
43//! let b = [10.0f32, 20.0, 30.0];
44//! let sum = exec.run(&VectorAdd, &VectorAddInput { a: &a, b: &b });
45//! assert_eq!(sum, vec![11.0, 22.0, 33.0]);
46//! ```
47//!
48//! ## Headless & Termux
49//!
50//! The compute path requests its adapter and device with **no surface / no
51//! window**, which is exactly what lets it run under Android Termux (no display
52//! context). The instance enables the `Vulkan | GL` backends — the two that
53//! matter on Android. Whether a GPU is actually reachable there depends on the
54//! device's Vulkan driver (Adreno via Mesa Turnip works well; Mali via Panfrost
55//! is immature and often falls back to CPU). See [`GpuContext::new`] for the
56//! full driver rundown, and the crate README for the on-device Termux test
57//! recipe. Use [`GpuContext::describe_backend`] (logged once at init) to verify
58//! on the tablet whether the GPU engaged or the cascade fell back to CPU.
59//!
60//! ## Scope of the first cut
61//!
62//! The public API is deliberately on plain Rust types (`&[f32]`, `Vec<f32>`) so
63//! the crate is standalone (no internal KOPITIAM deps) and publishable on its
64//! own. Integrating with `kopitiam-core` / `kopitiam-tensor` (their `Device` and
65//! dtype types) is a follow-up, not part of this cut.
66
67mod context;
68mod executor;
69pub mod ops;
70
71pub use context::{GpuContext, GpuUnavailable};
72pub use executor::{ComputeOp, Executor, GpuOpError};
73pub use ops::{
74 block_q8_matmul_nt_cpu, matmul_nt_cpu, matmul_nt_gpu, MatmulNt, MatmulNtInput,
75 ResidentBlockQ8Weight, BLOCK,
76};