Downsample: pre_block → spatial DW s=2 → channel expand → FFN + residual
| 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, |
| 4769 | struct ggml_tensor* x, |
| 4770 | const edgetam_repvit_downsample& ds) { |
| 4771 | // Pre-block at current channels |
| 4772 | x = edgetam_repvit_block_forward(ctx, x, ds.pre_block); |
| 4773 | |
| 4774 | // Spatial downsample: DW 3×3 conv, stride=2, pad=1 |
| 4775 | auto* ds_w_f32 = (ds.spatial_w->type == GGML_TYPE_F32) ? ds.spatial_w |
| 4776 | : ggml_cast(ctx, ds.spatial_w, GGML_TYPE_F32); |
| 4777 | x = ggml_conv_2d_dw_direct(ctx, ds_w_f32, x, 2, 2, 1, 1, 1, 1); |
| 4778 | x = edgetam_conv2d_bias(ctx, x, ds.spatial_b); |
| 4779 | |
| 4780 | // Channel expand: 1×1 conv (mul_mat path) |
| 4781 | x = edgetam_conv1x1_mulmat(ctx, x, ds.channel_w, ds.channel_b); |
| 4782 | |
| 4783 | // FFN + residual (mul_mat path for 1×1 convs) |
| 4784 | auto* ffn_in = x; |
| 4785 | auto* ffn = edgetam_conv1x1_mulmat(ctx, x, ds.ffn_conv1_w, ds.ffn_conv1_b); |
| 4786 | ffn = ggml_gelu(ctx, ffn); |
| 4787 | ffn = edgetam_conv1x1_mulmat(ctx, ffn, ds.ffn_conv2_w, ds.ffn_conv2_b); |
| 4788 | x = ggml_add(ctx, ffn, ffn_in); |
| 4789 | |
| 4790 | return x; |
| 4791 | } |
| 4792 | |
| 4793 | // Build the full RepViT backbone graph. |
| 4794 | // Input: [W, H, 3, 1] image |
no test coverage detected