MCPcopy Create free account
hub / github.com/PABannier/sam3.cpp / sam3_ddec_layer_forward

Function sam3_ddec_layer_forward

sam3.cpp:8438–8623  ·  view source on GitHub ↗

Single DETR decoder layer. queries: [D, N_q, B] where N_q = 201 (200 object queries + 1 presence token) query_pos: [D, N_q, B] positional encoding for queries enc_feats: [D, N_kv, B] conditioned image features from fusion encoder enc_pos: [D, N_kv, B] positional encoding for image features text_feats: [D, T, B] text features rpb_mask: [N_kv, N_q, n_heads, B] box-relative positional bias (or nullpt

Source from the content-addressed store, hash-verified

8436// rpb_mask: [N_kv, N_q, n_heads, B] box-relative positional bias (or nullptr)
8437// Returns: updated queries [D, N_q, B]
8438static struct ggml_tensor* sam3_ddec_layer_forward(
8439 struct ggml_context* ctx,
8440 const sam3_ddec_layer& ly,
8441 struct ggml_tensor* queries,
8442 struct ggml_tensor* query_pos,
8443 struct ggml_tensor* enc_feats,
8444 struct ggml_tensor* enc_pos,
8445 struct ggml_tensor* text_feats,
8446 int n_heads,
8447 struct ggml_tensor* text_attn_bias = nullptr,
8448 struct ggml_tensor* rpb_mask = nullptr,
8449 int layer_idx = -1) {
8450 const int64_t D = queries->ne[0];
8451
8452 // Python decoder layer order (all post-norm):
8453 // 1. Self-attention → norm2 (post-norm)
8454 // 2. Text cross-attention (ca_text) → catext_norm (post-norm)
8455 // 3. Image cross-attention (cross_attn) → norm1 (post-norm)
8456 // 4. FFN → norm3 (post-norm)
8457 //
8458 // Norm weight mapping:
8459 // ly.norm2_w = ".norm2.weight" = Python norm2 (post-SA)
8460 // ly.norm3_w = ".norm_ca_text.weight" = Python catext_norm (post-text-CA)
8461 // ly.norm1_w = ".norm1.weight" = Python norm1 (post-image-CA)
8462 // ly.norm4_w = ".norm3.weight" = Python norm3 (post-FFN)
8463
8464 // 1. Self-attention among queries (post-norm)
8465 {
8466 // Q = K = queries + query_pos, V = queries (no pos)
8467 auto* q_in = ggml_add(ctx, queries, query_pos);
8468
8469 auto* q_w = ggml_view_2d(ctx, ly.sa_in_proj_w, D, D, ly.sa_in_proj_w->nb[1], 0);
8470 auto* k_w = ggml_view_2d(ctx, ly.sa_in_proj_w, D, D, ly.sa_in_proj_w->nb[1], D * ly.sa_in_proj_w->nb[1]);
8471 auto* v_w = ggml_view_2d(ctx, ly.sa_in_proj_w, D, D, ly.sa_in_proj_w->nb[1], 2 * D * ly.sa_in_proj_w->nb[1]);
8472 auto* q_b = ggml_view_1d(ctx, ly.sa_in_proj_b, D, 0);
8473 auto* k_b = ggml_view_1d(ctx, ly.sa_in_proj_b, D, D * sizeof(float));
8474 auto* v_b = ggml_view_1d(ctx, ly.sa_in_proj_b, D, 2 * D * sizeof(float));
8475
8476 const int64_t N = queries->ne[1];
8477 const int64_t B = queries->ne[2];
8478 const int64_t HD = D / n_heads;
8479
8480 auto* Q = ggml_add(ctx, ggml_mul_mat(ctx, q_w, q_in), q_b);
8481 auto* K = ggml_add(ctx, ggml_mul_mat(ctx, k_w, q_in), k_b);
8482 auto* V = ggml_add(ctx, ggml_mul_mat(ctx, v_w, queries), v_b);
8483
8484 Q = ggml_reshape_4d(ctx, Q, HD, n_heads, N, B);
8485 Q = ggml_cont(ctx, ggml_permute(ctx, Q, 0, 2, 1, 3));
8486 K = ggml_reshape_4d(ctx, K, HD, n_heads, N, B);
8487 K = ggml_cont(ctx, ggml_permute(ctx, K, 0, 2, 1, 3));
8488 V = ggml_reshape_4d(ctx, V, HD, n_heads, N, B);
8489 V = ggml_permute(ctx, V, 0, 2, 1, 3);
8490
8491 float scale = 1.0f / sqrtf((float)HD);
8492 auto* sa_out = ggml_flash_attn_ext(ctx, Q, K, V, nullptr, scale, 0.0f, 0.0f);
8493 sa_out = ggml_reshape_3d(ctx, sa_out, D, N, B);
8494 sa_out = ggml_mul_mat(ctx, ly.sa_out_proj_w, sa_out);
8495 sa_out = ggml_add(ctx, sa_out, ly.sa_out_proj_b);

Callers 1

sam3_build_ddec_graphFunction · 0.85

Calls 2

sam3_layer_normFunction · 0.85

Tested by

no test coverage detected