RepViT block forward: token_mixer DW → optional SE → channel_mixer + residual
| 4730 | |
| 4731 | // RepViT block forward: token_mixer DW → optional SE → channel_mixer + residual |
| 4732 | static struct ggml_tensor* edgetam_repvit_block_forward(struct ggml_context* ctx, |
| 4733 | struct ggml_tensor* x, |
| 4734 | const edgetam_repvit_block& blk) { |
| 4735 | // x layout: [W, H, C, 1] |
| 4736 | // Token mixer: DW 3×3 conv, stride=1, pad=1 (RepVGG-reparameterized, no residual) |
| 4737 | // Use ggml_conv_2d_dw_direct which requires F32 kernel |
| 4738 | auto* tm_w_f32 = (blk.tm_w->type == GGML_TYPE_F32) ? blk.tm_w |
| 4739 | : ggml_cast(ctx, blk.tm_w, GGML_TYPE_F32); |
| 4740 | x = ggml_conv_2d_dw_direct(ctx, tm_w_f32, x, 1, 1, 1, 1, 1, 1); |
| 4741 | x = edgetam_conv2d_bias(ctx, x, blk.tm_b); |
| 4742 | |
| 4743 | // Squeeze-and-excitation (optional, on even-indexed blocks) |
| 4744 | if (blk.has_se) { |
| 4745 | int W = (int)x->ne[0]; |
| 4746 | int H = (int)x->ne[1]; |
| 4747 | // Global average pool: [W, H, C, 1] → [1, 1, C, 1] |
| 4748 | auto* pooled = ggml_pool_2d(ctx, x, GGML_OP_POOL_AVG, W, H, W, H, 0, 0); |
| 4749 | // SE operates on tiny [1,1,C,1] — keep using ggml_conv_2d (overhead negligible) |
| 4750 | auto* se = ggml_conv_2d(ctx, blk.se_fc1_w, pooled, 1, 1, 0, 0, 1, 1); |
| 4751 | se = edgetam_conv2d_bias(ctx, se, blk.se_fc1_b); |
| 4752 | se = ggml_relu(ctx, se); |
| 4753 | se = ggml_conv_2d(ctx, blk.se_fc2_w, se, 1, 1, 0, 0, 1, 1); |
| 4754 | se = edgetam_conv2d_bias(ctx, se, blk.se_fc2_b); |
| 4755 | se = ggml_sigmoid(ctx, se); |
| 4756 | x = ggml_mul(ctx, x, se); |
| 4757 | } |
| 4758 | |
| 4759 | // Channel mixer: 1×1 expand → GELU → 1×1 project (use mul_mat path) |
| 4760 | auto* identity = x; |
| 4761 | auto* cm = edgetam_conv1x1_mulmat(ctx, x, blk.cm_conv1_w, blk.cm_conv1_b); |
| 4762 | cm = ggml_gelu(ctx, cm); |
| 4763 | cm = edgetam_conv1x1_mulmat(ctx, cm, blk.cm_conv2_w, blk.cm_conv2_b); |
| 4764 | return ggml_add(ctx, cm, identity); |
| 4765 | } |
| 4766 | |
| 4767 | // Downsample: pre_block → spatial DW s=2 → channel expand → FFN + residual |
| 4768 | static struct ggml_tensor* edgetam_repvit_downsample_forward(struct ggml_context* ctx, |
no test coverage detected