use model_io::ResidentIndex;
use crate::families::qwen4::state::RealQwen4State;
use crate::real_forward_dispatch::encode_gemv_any;
use crate::real_forward_types::RealForwardError;
use crate::real_forward_utils::norm_view;
#[allow(clippy::too_many_arguments)]
pub(crate) fn encode_hyper_connection(
context: &mut gpu::MetalContext,
pass: &gpu::PassEncoder,
weights: &gpu::ResidentGpuWeights,
index: &ResidentIndex,
qwen4: &RealQwen4State,
wide: (&gpu::MetalBuffer, u64),
name_prefix: &str,
hidden: usize,
mixed_out: (&gpu::MetalBuffer, u64),
has_inject_gate: bool,
inject_row_offset: u64,
) -> Result<(), RealForwardError> {
let gpu_err = RealForwardError::Gpu;
let hc_count = qwen4.hc_count;
let wide_dim = hidden * hc_count;
let name = |suffix: &str| format!("{name_prefix}.{suffix}");
let hc_norm_w = norm_view(weights, index, &name("hc_norm.weight"), wide_dim)?;
gpu::encode_rms_norm_bf16w_grouped(
context,
pass,
wide,
hc_norm_w,
(&qwen4.hc_normed, 0),
hc_count as u32,
hidden as u32,
crate::families::qwen4::RMS_EPS,
)
.map_err(gpu_err)?;
encode_gemv_any(
context,
pass,
weights,
index,
&name("input_mix_weight_down.weight"),
qwen4.hc_lowrank,
wide_dim,
(&qwen4.hc_normed, 0),
(&qwen4.hc_low, 0),
)?;
gpu::encode_scalar_mul(
context,
pass,
(&qwen4.hc_low, 0),
1.0 / hc_count as f32,
qwen4.hc_lowrank as u32,
)
.map_err(gpu_err)?;
gpu::encode_silu(context, pass, (&qwen4.hc_low, 0), qwen4.hc_lowrank as u32)
.map_err(gpu_err)?;
encode_gemv_any(
context,
pass,
weights,
index,
&name("input_mix_weight_up.weight"),
wide_dim,
qwen4.hc_lowrank,
(&qwen4.hc_low, 0),
(&qwen4.hc_up, 0),
)?;
gpu::encode_sigmoid(context, pass, (&qwen4.hc_up, 0), wide_dim as u32).map_err(gpu_err)?;
gpu::encode_hc_mix(
context,
pass,
(&qwen4.hc_up, 0),
(&qwen4.hc_normed, 0),
mixed_out,
hc_count as u32,
hidden as u32,
)
.map_err(gpu_err)?;
if has_inject_gate {
encode_gemv_any(
context,
pass,
weights,
index,
&name("block_inject_weight.weight"),
hc_count,
wide_dim,
(&qwen4.hc_normed, 0),
(&qwen4.hc_inject, inject_row_offset),
)?;
gpu::encode_scalar_mul(
context,
pass,
(&qwen4.hc_inject, inject_row_offset),
1.0 / hc_count as f32,
hc_count as u32,
)
.map_err(gpu_err)?;
gpu::encode_sigmoid(
context,
pass,
(&qwen4.hc_inject, inject_row_offset),
hc_count as u32,
)
.map_err(gpu_err)?;
gpu::encode_scalar_mul(
context,
pass,
(&qwen4.hc_inject, inject_row_offset),
2.0,
hc_count as u32,
)
.map_err(gpu_err)?;
}
Ok(())
}