| 4663 | // ggml_conv_2d_dw_direct |
| 4664 | |
| 4665 | struct ggml_tensor * ggml_conv_2d_dw_direct( |
| 4666 | struct ggml_context * ctx, |
| 4667 | struct ggml_tensor * a, |
| 4668 | struct ggml_tensor * b, |
| 4669 | int stride0, |
| 4670 | int stride1, |
| 4671 | int pad0, |
| 4672 | int pad1, |
| 4673 | int dilation0, |
| 4674 | int dilation1) { |
| 4675 | GGML_ASSERT(a->ne[2] == 1); |
| 4676 | GGML_ASSERT(a->ne[3] == b->ne[2]); |
| 4677 | int64_t ne[4]; |
| 4678 | ne[0] = ggml_calc_conv_output_size(b->ne[0], a->ne[0], stride0, pad0, dilation0); |
| 4679 | ne[1] = ggml_calc_conv_output_size(b->ne[1], a->ne[1], stride1, pad1, dilation1); |
| 4680 | ne[2] = b->ne[2]; |
| 4681 | ne[3] = b->ne[3]; |
| 4682 | |
| 4683 | struct ggml_tensor * result = ggml_new_tensor(ctx, b->type, 4, ne); |
| 4684 | |
| 4685 | if (ggml_is_contiguous_channels(b)) { |
| 4686 | // Result will be permuted the same way as input (CWHN order) |
| 4687 | const int64_t type_size = ggml_type_size(result->type); |
| 4688 | GGML_ASSERT(ggml_blck_size(result->type) == 1); |
| 4689 | result->nb[0] = result->ne[2] * type_size; |
| 4690 | result->nb[1] = result->ne[0] * result->nb[0]; |
| 4691 | result->nb[2] = type_size; |
| 4692 | } |
| 4693 | |
| 4694 | int32_t params[] = { stride0, stride1, pad0, pad1, dilation0, dilation1 }; |
| 4695 | ggml_set_op_params(result, params, sizeof(params)); |
| 4696 | |
| 4697 | result->op = GGML_OP_CONV_2D_DW; |
| 4698 | result->src[0] = a; |
| 4699 | result->src[1] = b; |
| 4700 | return result; |
| 4701 | } |
| 4702 | |
| 4703 | // ggml_conv_2d_direct |
| 4704 | |