use crate::real_forward_types::RealForwardError;
pub(crate) const GGUF_BLOCK_DTYPES: [u8; 18] = [
DTYPE_GGUF_Q8_0,
DTYPE_GGUF_Q4_K,
DTYPE_GGUF_Q6_K,
DTYPE_GGUF_Q4_0,
DTYPE_GGUF_IQ3_XXS,
DTYPE_GGUF_IQ4_NL,
DTYPE_GGUF_IQ4_XS,
DTYPE_GGUF_Q5_K,
DTYPE_GGUF_MXFP4,
DTYPE_GGUF_Q2_K,
DTYPE_GGUF_IQ2_XXS,
DTYPE_GGUF_IQ2_XS,
DTYPE_GGUF_IQ1_S,
DTYPE_GGUF_IQ3_S,
DTYPE_GGUF_IQ2_S,
DTYPE_GGUF_IQ1_M,
DTYPE_GGUF_Q3_K,
DTYPE_GGUF_Q2_0,
];
pub(crate) const DTYPE_GGUF_Q8_0: u8 = 6;
pub(crate) const DTYPE_GGUF_Q4_K: u8 = 7;
pub(crate) const DTYPE_GGUF_Q6_K: u8 = 8;
pub(crate) const DTYPE_GGUF_Q4_0: u8 = 9;
pub(crate) const DTYPE_GGUF_IQ3_XXS: u8 = 10;
pub(crate) const DTYPE_GGUF_IQ4_NL: u8 = 11;
pub(crate) const DTYPE_GGUF_IQ4_XS: u8 = 12;
pub(crate) const DTYPE_GGUF_Q5_K: u8 = 13;
pub(crate) const DTYPE_GGUF_MXFP4: u8 = 14;
pub(crate) const DTYPE_GGUF_Q2_K: u8 = 17;
pub(crate) const DTYPE_GGUF_IQ2_XXS: u8 = 18;
pub(crate) const DTYPE_GGUF_IQ2_XS: u8 = 19;
pub(crate) const DTYPE_GGUF_IQ1_S: u8 = 20;
pub(crate) const DTYPE_GGUF_IQ3_S: u8 = 21;
pub(crate) const DTYPE_GGUF_IQ2_S: u8 = 22;
pub(crate) const DTYPE_GGUF_IQ1_M: u8 = 23;
pub(crate) const DTYPE_GGUF_Q3_K: u8 = 24;
pub(crate) const DTYPE_GGUF_Q2_0: u8 = 25;
pub(crate) const DTYPE_RAW_BF16: u8 = 1;
pub(crate) const DTYPE_RAW_FP16: u8 = 2;
pub(crate) const VISION_PREFIX: &str = "vision.";
pub(crate) fn readable_resident_dtype(name: &str, dtype: u8) -> bool {
if dtype == DTYPE_RAW_FP16 {
return name.starts_with(VISION_PREFIX);
}
matches!(
dtype,
DTYPE_RAW_BF16 | 4 | 5 | DTYPE_INT1_AFFINE | DTYPE_INT2_AFFINE
) || EXECUTABLE_GGUF_DTYPES.contains(&dtype)
}
pub(crate) const DTYPE_INT1_AFFINE: u8 = 15;
pub(crate) const DTYPE_INT2_AFFINE: u8 = 16;
pub(crate) const EXECUTABLE_GGUF_DTYPES: [u8; 15] = [
DTYPE_GGUF_Q8_0,
DTYPE_GGUF_Q4_K,
DTYPE_GGUF_Q6_K,
DTYPE_GGUF_IQ3_XXS,
DTYPE_GGUF_IQ4_NL,
DTYPE_GGUF_IQ4_XS,
DTYPE_GGUF_Q5_K,
DTYPE_GGUF_Q2_K,
DTYPE_GGUF_IQ2_XXS,
DTYPE_GGUF_IQ2_XS,
DTYPE_GGUF_IQ1_S,
DTYPE_GGUF_IQ3_S,
DTYPE_GGUF_IQ2_S,
DTYPE_GGUF_IQ1_M,
DTYPE_GGUF_Q3_K,
];
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub(crate) enum RoutedBlobLayout {
Affine,
GgufQ8_0,
GgufQ4K,
GgufIq3Xxs,
GgufIq4Xs,
GgufIq4Nl,
GgufMxfp4,
GgufQ6K,
GgufQ2_0,
GgufIq2S,
GgufIq2Xxs,
GgufIq1M,
}
impl RoutedBlobLayout {
pub(crate) fn from_gguf_dtype(dtype: &str) -> Result<Self, RealForwardError> {
Ok(match dtype {
"q8_0" => RoutedBlobLayout::GgufQ8_0,
"q4_k" => RoutedBlobLayout::GgufQ4K,
"iq3_xxs" => RoutedBlobLayout::GgufIq3Xxs,
"iq4_xs" => RoutedBlobLayout::GgufIq4Xs,
"iq4_nl" => RoutedBlobLayout::GgufIq4Nl,
"q6_k" => RoutedBlobLayout::GgufQ6K,
"q2_0" => RoutedBlobLayout::GgufQ2_0,
"iq2_s" => RoutedBlobLayout::GgufIq2S,
"iq2_xxs" => RoutedBlobLayout::GgufIq2Xxs,
"iq1_m" => RoutedBlobLayout::GgufIq1M,
"mxfp4" => RoutedBlobLayout::GgufMxfp4,
other => {
return Err(RealForwardError::Unsupported(format!(
"routed expert sub-tensor dtype {other} has no decode kernel in this port"
)))
}
})
}
pub(crate) fn source_function(self) -> (&'static str, &'static str) {
match self {
RoutedBlobLayout::Affine => {
(gpu::moe_decode_source(), "moe_phase1_gate_up_act_u16load")
}
RoutedBlobLayout::GgufQ8_0
| RoutedBlobLayout::GgufQ4K
| RoutedBlobLayout::GgufIq3Xxs
| RoutedBlobLayout::GgufIq4Xs
| RoutedBlobLayout::GgufIq4Nl
| RoutedBlobLayout::GgufMxfp4
| RoutedBlobLayout::GgufQ6K => (gpu::moe_gguf_source(), "moe_phase1_gate_up_act_q8_0"),
RoutedBlobLayout::GgufIq2S
| RoutedBlobLayout::GgufIq2Xxs
| RoutedBlobLayout::GgufIq1M => (gpu::moe_gguf_source(), "moe_phase1_gate_up_act_q8_0"),
RoutedBlobLayout::GgufQ2_0 => (gpu::moe_gguf_source(), "moe_phase1_gate_up_act_q2_0"),
}
}
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub(crate) struct RoutedLayerLayout {
pub(crate) phase1: RoutedBlobLayout,
pub(crate) phase2: RoutedBlobLayout,
}
fn require_ascending_layers(
layout: &model_io::PackedExpertsLayout,
) -> Result<(), RealForwardError> {
for pair in layout.layers.windows(2) {
if pair[0].layer >= pair[1].layer {
return Err(RealForwardError::Unsupported(format!(
"packed layout layers are not in strictly ascending order: layer {} followed by {}",
pair[0].layer, pair[1].layer
)));
}
}
Ok(())
}
pub(crate) fn routed_layouts_from_layout(
layout: &model_io::PackedExpertsLayout,
) -> Result<Vec<RoutedLayerLayout>, RealForwardError> {
require_ascending_layers(layout)?;
layout
.layers
.iter()
.map(|l| {
let subs = &l
.experts
.first()
.ok_or_else(|| {
RealForwardError::Unsupported(format!("layer {} has no experts", l.layer))
})?
.sub_tensors;
if subs.contains_key("gate_scales") {
return Ok(RoutedLayerLayout {
phase1: RoutedBlobLayout::Affine,
phase2: RoutedBlobLayout::Affine,
});
}
let of = |role: &str| -> Result<RoutedBlobLayout, RealForwardError> {
let entry = subs.get(role).ok_or_else(|| {
RealForwardError::MissingTensor(format!("expert blob {role}"))
})?;
RoutedBlobLayout::from_gguf_dtype(&entry.dtype)
};
let (gate, up) = (of("gate")?, of("up")?);
if gate != up {
return Err(RealForwardError::Unsupported(format!(
"layer {} packs a {gate:?} gate against a {up:?} up; one phase-1 kernel \
reads both, so they cannot differ",
l.layer
)));
}
Ok(RoutedLayerLayout {
phase1: gate,
phase2: of("down")?,
})
})
.collect()
}
pub(crate) fn validate_routed_layouts_for_top_k(
layouts: &[RoutedLayerLayout],
top_k: i64,
) -> Result<(), RealForwardError> {
for (layer, l) in layouts.iter().enumerate() {
if l.phase2 == RoutedBlobLayout::GgufQ2_0 && top_k != 10 {
return Err(RealForwardError::Unsupported(format!(
"layer {layer} down-projection carries Q2_0 routed layout, which requires \
top_k=10 in this port (got top_k={top_k})"
)));
}
}
Ok(())
}
pub(crate) fn moe_offsets_from_layout(
layout: &model_io::PackedExpertsLayout,
) -> Result<Vec<gpu::MoeExpertOffsets>, RealForwardError> {
require_ascending_layers(layout)?;
layout
.layers
.iter()
.map(|l| {
let entry = &l
.experts
.first()
.ok_or_else(|| {
RealForwardError::Unsupported(format!("layer {} has no experts", l.layer))
})?
.sub_tensors;
let get = |name: &str| -> Result<u32, RealForwardError> {
let sub = entry.get(name).ok_or_else(|| {
RealForwardError::MissingTensor(format!("expert blob {name}"))
})?;
u32::try_from(sub.offset).map_err(|_| {
RealForwardError::Unsupported(format!(
"layer {} expert blob {name} offset {} exceeds 32-bit address space",
l.layer, sub.offset
))
})
};
let companion = |name: &str| -> Result<u32, RealForwardError> {
let Some(s) = entry.get(name) else {
return Ok(0);
};
u32::try_from(s.offset).map_err(|_| {
RealForwardError::Unsupported(format!(
"layer {} expert blob {name} offset {} exceeds 32-bit address space",
l.layer, s.offset
))
})
};
let planar = entry.contains_key("gate_scales");
let offsets = gpu::MoeExpertOffsets {
gate_w: get("gate")?,
gate_s: companion("gate_scales")?,
gate_b: companion("gate_biases")?,
up_w: get("up")?,
up_s: companion("up_scales")?,
up_b: companion("up_biases")?,
down_w: get("down")?,
down_s: companion("down_scales")?,
down_b: companion("down_biases")?,
};
if planar && offsets.down_w % 4 != 0 {
return Err(RealForwardError::Unsupported(format!(
"layer {} down projection offset {} is not 4-byte aligned",
l.layer, offsets.down_w
)));
}
if !planar {
for (role, offset) in [
("gate", offsets.gate_b),
("up", offsets.up_b),
("down", offsets.down_b),
] {
if offset != 0 && offset % 4 != 0 {
return Err(RealForwardError::Unsupported(format!(
"layer {} {role} bias offset {offset} is not 4-byte aligned \
(MXFP4's `device const float*` bias read requires it)",
l.layer
)));
}
}
}
Ok(offsets)
})
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
use model_io::{ExpertEntry, LayerLayout, PackedExpertsLayout, SubTensorEntry};
use std::collections::BTreeMap;
fn make_test_layout(
layer_indices: &[usize],
gate_offset: u64,
) -> model_io::PackedExpertsLayout {
let layers = layer_indices
.iter()
.map(|&layer| {
let mut sub_tensors = BTreeMap::new();
sub_tensors.insert(
"gate".to_string(),
model_io::SubTensorEntry {
offset: gate_offset,
size: 64,
dtype: "Q4_0".to_string(),
},
);
sub_tensors.insert(
"up".to_string(),
model_io::SubTensorEntry {
offset: 64,
size: 64,
dtype: "Q4_0".to_string(),
},
);
sub_tensors.insert(
"down".to_string(),
model_io::SubTensorEntry {
offset: 128,
size: 64,
dtype: "Q4_0".to_string(),
},
);
model_io::LayerLayout {
layer,
file: format!("layer_{layer}.bin"),
expert_stride: 256,
experts: vec![model_io::ExpertEntry {
expert: 0,
offset: 0,
size: 256,
sub_tensors,
}],
}
})
.collect();
model_io::PackedExpertsLayout {
expert_stride: 256,
num_layers: layer_indices.len(),
experts_per_layer: 1,
layers,
}
}
fn sub(offset: u64) -> SubTensorEntry {
SubTensorEntry {
offset,
size: 4,
dtype: "mxfp4".to_string(),
}
}
fn routed_dtype_layout(gate_up: &str, down: &str) -> PackedExpertsLayout {
let entry = |offset, dtype: &str| SubTensorEntry {
offset,
size: 64,
dtype: dtype.to_string(),
};
let mut sub_tensors = BTreeMap::new();
sub_tensors.insert("gate".to_string(), entry(0, gate_up));
sub_tensors.insert("up".to_string(), entry(64, gate_up));
sub_tensors.insert("down".to_string(), entry(128, down));
PackedExpertsLayout {
expert_stride: 192,
num_layers: 1,
experts_per_layer: 1,
layers: vec![LayerLayout {
layer: 0,
file: "layer_00.bin".to_string(),
expert_stride: 192,
experts: vec![ExpertEntry {
expert: 0,
offset: 0,
size: 192,
sub_tensors,
}],
}],
}
}
#[test]
fn qwen4_exp_routed_gguf_dtypes_resolve_by_phase() {
for (gate_up, expected) in [
("iq2_s", RoutedBlobLayout::GgufIq2S),
("iq2_xxs", RoutedBlobLayout::GgufIq2Xxs),
("iq1_m", RoutedBlobLayout::GgufIq1M),
] {
let layout = routed_dtype_layout(gate_up, "q2_0");
let routed = routed_layouts_from_layout(&layout).expect("routed types resolve");
assert_eq!(routed[0].phase1, expected, "gate/up dtype {gate_up}");
assert_eq!(routed[0].phase2, RoutedBlobLayout::GgufQ2_0);
}
let q2_0 = routed_dtype_layout("q2_0", "q2_0");
let routed = routed_layouts_from_layout(&q2_0).expect("Q2_0 routes both phases");
assert_eq!(routed[0].phase1, RoutedBlobLayout::GgufQ2_0);
assert_eq!(routed[0].phase2, RoutedBlobLayout::GgufQ2_0);
}
fn misaligned_mxfp4_layout() -> PackedExpertsLayout {
let mut subs = BTreeMap::new();
subs.insert("gate".to_string(), sub(0));
subs.insert("up".to_string(), sub(100));
subs.insert("down".to_string(), sub(200));
subs.insert("gate_biases".to_string(), sub(302));
subs.insert("up_biases".to_string(), sub(320));
subs.insert("down_biases".to_string(), sub(340));
PackedExpertsLayout {
expert_stride: 400,
num_layers: 1,
experts_per_layer: 1,
layers: vec![LayerLayout {
layer: 0,
file: "layer_00.bin".to_string(),
expert_stride: 400,
experts: vec![ExpertEntry {
expert: 0,
offset: 0,
size: 400,
sub_tensors: subs,
}],
}],
}
}
#[test]
fn out_of_order_layers_are_refused() {
let layout = make_test_layout(&[1, 0], 0);
let err = routed_layouts_from_layout(&layout).expect_err("out of order layers");
match err {
RealForwardError::Unsupported(msg) => {
assert!(
msg.contains("not in strictly ascending order"),
"msg: {msg}"
);
}
other => panic!("expected Unsupported error, got {other:?}"),
}
let err2 = moe_offsets_from_layout(&layout).expect_err("out of order layers");
match err2 {
RealForwardError::Unsupported(msg) => {
assert!(
msg.contains("not in strictly ascending order"),
"msg: {msg}"
);
}
other => panic!("expected Unsupported error, got {other:?}"),
}
}
#[test]
fn offset_overflowing_u32_is_refused() {
let layout = make_test_layout(&[0], (u32::MAX as u64) + 1);
let err = moe_offsets_from_layout(&layout).expect_err("overflowing offset");
match err {
RealForwardError::Unsupported(msg) => {
assert!(msg.contains("exceeds 32-bit address space"), "msg: {msg}");
}
other => panic!("expected Unsupported error, got {other:?}"),
}
}
#[test]
fn a_misaligned_mxfp4_bias_offset_is_refused() {
let layout = misaligned_mxfp4_layout();
let err = moe_offsets_from_layout(&layout).expect_err("2-mod-4 bias offset must refuse");
let msg = err.to_string();
assert!(msg.contains("gate"), "{msg}");
assert!(msg.contains("4-byte aligned"), "{msg}");
}
#[test]
fn a_4_byte_aligned_mxfp4_bias_offset_is_accepted() {
let mut layout = misaligned_mxfp4_layout();
for name in ["gate_biases", "up_biases", "down_biases"] {
layout.layers[0].experts[0]
.sub_tensors
.get_mut(name)
.unwrap()
.offset &= !3;
}
let offsets = moe_offsets_from_layout(&layout).expect("4-byte-aligned offsets are fine");
assert_eq!(offsets.len(), 1);
}
#[test]
fn a_gguf_layer_with_no_bias_planes_is_unaffected() {
let mut subs = BTreeMap::new();
subs.insert("gate".to_string(), sub(0));
subs.insert("up".to_string(), sub(100));
subs.insert("down".to_string(), sub(200));
let layout = PackedExpertsLayout {
expert_stride: 300,
num_layers: 1,
experts_per_layer: 1,
layers: vec![LayerLayout {
layer: 0,
file: "layer_00.bin".to_string(),
expert_stride: 300,
experts: vec![ExpertEntry {
expert: 0,
offset: 0,
size: 300,
sub_tensors: subs,
}],
}],
};
let offsets = moe_offsets_from_layout(&layout).expect("no bias planes is fine");
assert_eq!(offsets[0].gate_b, 0);
assert_eq!(offsets[0].up_b, 0);
assert_eq!(offsets[0].down_b, 0);
}
#[test]
fn q2_0_phase2_layout_requires_top_10() {
let q2_0_layout = vec![RoutedLayerLayout {
phase1: RoutedBlobLayout::GgufQ2_0,
phase2: RoutedBlobLayout::GgufQ2_0,
}];
assert!(validate_routed_layouts_for_top_k(&q2_0_layout, 10).is_ok());
for non_10 in [1, 2, 4, 6, 8, 12] {
let err = validate_routed_layouts_for_top_k(&q2_0_layout, non_10)
.expect_err("non-10 top_k must fail");
match err {
RealForwardError::Unsupported(msg) => {
assert!(msg.contains("requires top_k=10"), "msg: {msg}");
assert!(msg.contains(&format!("got top_k={non_10}")), "msg: {msg}");
}
other => panic!("expected Unsupported error, got {other:?}"),
}
}
let affine_layout = vec![RoutedLayerLayout {
phase1: RoutedBlobLayout::Affine,
phase2: RoutedBlobLayout::Affine,
}];
assert!(validate_routed_layouts_for_top_k(&affine_layout, 2).is_ok());
let q8_0_layout = vec![RoutedLayerLayout {
phase1: RoutedBlobLayout::GgufQ8_0,
phase2: RoutedBlobLayout::GgufQ8_0,
}];
assert!(validate_routed_layouts_for_top_k(&q8_0_layout, 2).is_ok());
}
}