use crate::real_forward::RealForwardError;
use crate::real_forward_dispatch::encode_gemv_any;
use crate::real_forward_types::DecodeScratch;
use crate::real_forward_utils::norm_view;
use super::layer_tensor;
use super::state::RMS_EPS;
#[allow(clippy::too_many_arguments)]
pub(crate) fn encode_mlp_block(
context: &mut gpu::MetalContext,
pass: &gpu::PassEncoder,
weights: &gpu::ResidentGpuWeights,
index: &model_io::ResidentIndex,
scratch: &DecodeScratch,
ffn_hist: Option<&crate::ffn_hist::FfnActHist>,
layer: usize,
hidden: usize,
inter: usize,
x_off: u64,
) -> Result<(), RealForwardError> {
let gpu_err = RealForwardError::Gpu;
let pre_ffn = norm_view(
weights,
index,
&layer_tensor(layer, "post_attention_layernorm.weight"),
hidden,
)?;
gpu::encode_rms_norm_bf16w(
context,
pass,
(&scratch.x, x_off),
pre_ffn,
(&scratch.ffn_normed, 0),
hidden as u32,
RMS_EPS,
)
.map_err(gpu_err)?;
for (suffix, out) in [
("mlp.gate_proj.weight", &scratch.ffn_gate),
("mlp.up_proj.weight", &scratch.ffn_up),
] {
encode_gemv_any(
context,
pass,
weights,
index,
&layer_tensor(layer, suffix),
inter,
hidden,
(&scratch.ffn_normed, 0),
(out, 0),
)?;
}
let act = match ffn_hist {
Some(hist) => (&hist.capture, (layer * inter * 2) as u64),
None => (&scratch.ffn_act, 0),
};
gpu::encode_gelu_erf_mul(
context,
pass,
(&scratch.ffn_gate, 0),
(&scratch.ffn_up, 0),
act,
inter as u32,
)
.map_err(gpu_err)?;
encode_gemv_any(
context,
pass,
weights,
index,
&layer_tensor(layer, "mlp.down_proj.weight"),
hidden,
inter,
act,
(&scratch.ffn_out, 0),
)?;
gpu::encode_residual_add(
context,
pass,
(&scratch.x, x_off),
(&scratch.ffn_out, 0),
hidden as u32,
)
.map_err(gpu_err)?;
Ok(())
}