Skip to main content

qualia_core_db/inference/
metal_lane.rs

1//! Metal mega-pass orchestrator: chain all transformer layers into one Metal
2//! command buffer with a single fence at the end. No per-layer readback.
3//!
4//! This mirrors the CUDA `cuda_lane/mega_pass.rs` architecture but targets
5//! Apple Silicon via `metal-rs` or wgpu's Metal backend. On non-Apple
6//! platforms, all functions return `None`/`false` — the wgpu WGSL path
7//! handles inference instead.
8//!
9//! ## Architecture
10//!
11//! 1. Upload hidden state to device buffer (once).
12//! 2. For each layer:
13//!    a. RMSNorm + QKV + RoPE (fused dispatch via `fused-qkv-rope` MSL kernel)
14//!    b. KV cache write
15//!    c. SDPA decode (via `sdpa-decode` MSL kernel)
16//!    d. O-proj GEMV + residual add
17//!    e. RMSNorm + SwiGLU (fused)
18//!    f. Down GEMV + residual add
19//! 3. Output norm + logits GEMV + argmax
20//! 4. Single readback of the final token
21//!
22//! All dispatches share one command buffer — the GPU never idles waiting
23//! for CPU between layers.
24
25#![allow(dead_code, unused_variables)]
26
27/// Per-layer weight references for the Metal mega-pass.
28pub struct MetalPassLayerWeights<'a> {
29    pub attn_norm: &'a [f32],
30    pub q_raw: &'a [u8],
31    pub k_raw: &'a [u8],
32    pub v_raw: &'a [u8],
33    pub o_raw: &'a [u8],
34    pub ffn_norm: &'a [f32],
35    pub gate_raw: &'a [u8],
36    pub up_raw: &'a [u8],
37    pub down_raw: &'a [u8],
38}
39
40/// Per-layer matmul dimensions (pre-computed by caller).
41pub struct MetalPassLayerDims {
42    pub q_in: usize,
43    pub q_out: usize,
44    pub kv_in: usize,
45    pub kv_out: usize,
46    pub o_in: usize,
47    pub o_out: usize,
48    pub gate_in: usize,
49    pub gate_out: usize,
50    pub up_in: usize,
51    pub up_out: usize,
52    pub down_in: usize,
53    pub down_out: usize,
54}
55
56/// Metal mega-pass: chain all transformer layers into one Metal command buffer
57/// with a **single fence** at the end. No per-layer readback. The hidden state
58/// stays on-device for the entire forward pass; only the final logits/token
59/// come back to host.
60///
61/// This is the Apple Silicon equivalent of `try_cuda_mega_pass`.
62///
63/// **Requirements:**
64/// - `metal-rs` crate (or wgpu Metal backend) must be available.
65/// - Device KV cache must be initialized.
66/// - All weights must be resident on-device.
67///
68/// Returns `Some(token)` on success, `None` if Metal is unavailable or
69/// any kernel fails.
70pub fn try_metal_mega_pass(
71    n_embd: usize,
72    n_head: usize,
73    n_kv: usize,
74    head_dim: usize,
75    n_layer: u32,
76    token_idx: u32,
77    max_context: u32,
78    layer_stride: u32,
79    slot_kv_elems: u32,
80    rope_base: f32,
81    rope_scale: f32,
82    rms_eps: f32,
83    hidden: &[f32],
84    layers: &[MetalPassLayerWeights<'_>],
85    layer_dims: &[MetalPassLayerDims],
86    output_norm: Option<&[f32]>,
87    lm_head_raw: Option<&[u8]>,
88    lm_head_in: usize,
89    lm_head_out: usize,
90) -> Option<u32> {
91    // Metal is only available on macOS. On other platforms, return None
92    // and let the wgpu WGSL path handle inference.
93    #[cfg(not(target_os = "macos"))]
94    {
95        None
96    }
97    #[cfg(target_os = "macos")]
98    {
99        // TODO: implement via metal-rs when available on the build target.
100        // The MSL kernels (rmsnorm, fused-qkv-rope, sdpa-decode, gemv-simd-matrix)
101        // are already emitted by the MSL emitter. The execution bridge needs
102        // `WgpuPipeline::compile_msl` to be implemented with metal-rs.
103        log::info!("metal_mega_pass: not yet implemented on this build");
104        None
105    }
106}
107
108/// Check if the Metal mega-pass is available on this platform.
109pub fn metal_mega_pass_available() -> bool {
110    cfg!(target_os = "macos")
111}
112
113/// Warm the Metal context (pre-compile kernels, pre-allocate arenas).
114/// On non-Apple platforms, this is a no-op.
115pub fn warm_metal_context() {
116    #[cfg(target_os = "macos")]
117    {
118        // TODO: pre-compile MSL kernels and cache them
119    }
120}
121
122/// MSL double-buffered weight streaming: overlap H2D weight copies with
123/// compute using `MTLBlitCommandEncoder` on a separate Metal command buffer.
124/// This is the Metal equivalent of CUDA's `write_view_prefetch` + `join_prefetch`
125/// on a secondary stream.
126///
127/// **Architecture:**
128/// 1. Issue async H2D copies for next layer's weights via `MTLBlitCommandEncoder`
129///    on a dedicated command buffer (prefetch buffer).
130/// 2. Encode compute kernels for current layer on the main command buffer.
131/// 3. Insert a `MTLEvent` signal so compute waits for prefetch to complete.
132/// 4. Repeat for each layer — compute and prefetch overlap.
133///
134/// **Requirements:** `metal-rs` crate (macOS only). Not implementable on
135/// non-Apple platforms.
136pub fn metal_double_buffered_prefetch(_weight_data: &[u8], _dst_offset: u64) -> bool {
137    #[cfg(target_os = "macos")]
138    {
139        // TODO: implement via metal-rs MTLBlitCommandEncoder
140        false
141    }
142    #[cfg(not(target_os = "macos"))]
143    {
144        false
145    }
146}
147
148#[cfg(test)]
149mod tests {
150    use super::*;
151
152    #[test]
153    fn metal_mega_pass_unavailable_on_non_macos() {
154        if cfg!(not(target_os = "macos")) {
155            assert!(!metal_mega_pass_available());
156            assert!(try_metal_mega_pass(
157                0,
158                0,
159                0,
160                0,
161                0,
162                0,
163                0,
164                0,
165                0,
166                0.0,
167                0.0,
168                0.0,
169                &[],
170                &[],
171                &[],
172                None,
173                None,
174                0,
175                0,
176            )
177            .is_none());
178        }
179    }
180}