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

Function edgetam_perceiver_layer_forward

sam3.cpp:5437–5539  ·  view source on GitHub ↗

Helper: build one perceiver layer on latents, given features x. latents: [D, N_lat, batch] (D=64, N_lat = n latent tokens) x: [D, N_x, batch] (D=64, N_x = n feature tokens) pos: [D, N_x, batch] or nullptr (added to K and V after projection) Returns updated latents [D, N_lat, batch].

Source from the content-addressed store, hash-verified

5435// pos: [D, N_x, batch] or nullptr (added to K and V after projection)
5436// Returns updated latents [D, N_lat, batch].
5437static struct ggml_tensor* edgetam_perceiver_layer_forward(
5438 struct ggml_context* ctx,
5439 struct ggml_tensor* latents,
5440 struct ggml_tensor* x,
5441 struct ggml_tensor* pos,
5442 const edgetam_perceiver_layer& layer) {
5443 const int64_t D = latents->ne[0]; // 64
5444 const int64_t N_lat = latents->ne[1]; // 256 (1D) or 1 (2D per window)
5445 const int64_t batch = latents->ne[2]; // 1 (1D) or 256 (2D)
5446 const int64_t N_x = x->ne[1]; // H*W (1D) or 16 (2D per window)
5447 const float scale = 1.0f / sqrtf((float)D); // 0.125 for D=64
5448
5449 // ── Cross-attention: latents attend to features ─────────────────────
5450 {
5451 auto* lat_n = sam3_layer_norm(ctx, latents, layer.ca_norm_latents_w,
5452 layer.ca_norm_latents_b);
5453 auto* x_n = sam3_layer_norm(ctx, x, layer.ca_norm_x_w, layer.ca_norm_x_b);
5454
5455 // Q from latents: [D, N_lat, batch] → [D, N_lat, batch]
5456 auto* q = ggml_mul_mat(ctx, layer.ca_q_w, lat_n); // [D, N_lat, batch]
5457
5458 // KV from features: [2*D, N_x, batch]
5459 auto* kv = ggml_mul_mat(ctx, layer.ca_kv_w, x_n); // [2*D, N_x, batch]
5460
5461 // Split into K and V via views — kv is contiguous [2*D, N_x, batch]
5462 auto* k_raw = ggml_view_3d(ctx, kv, D, N_x, batch,
5463 kv->nb[1], kv->nb[2], 0); // [D, N_x, batch]
5464 auto* v_raw = ggml_view_3d(ctx, kv, D, N_x, batch,
5465 kv->nb[1], kv->nb[2], D * sizeof(float)); // [D, N_x, batch]
5466
5467 // Add positional encoding to K and V
5468 struct ggml_tensor* k;
5469 struct ggml_tensor* v;
5470 if (pos) {
5471 k = ggml_add(ctx, k_raw, pos);
5472 v = ggml_add(ctx, v_raw, pos);
5473 } else {
5474 k = ggml_cont(ctx, k_raw);
5475 v = ggml_cont(ctx, v_raw);
5476 }
5477
5478 // Reshape for flash_attn_ext (1 head):
5479 // Q: [D, N_lat, 1, batch] K: [D, N_x, 1, batch] V: [D, N_x, 1, batch]
5480 q = ggml_reshape_4d(ctx, q, D, N_lat, 1, batch);
5481 k = ggml_reshape_4d(ctx, k, D, N_x, 1, batch);
5482 v = ggml_reshape_4d(ctx, v, D, N_x, 1, batch);
5483
5484 auto* attn = ggml_flash_attn_ext(ctx, q, k, v, nullptr, scale, 0.0f, 0.0f);
5485 // Output: [D, 1, N_lat, batch] (permuted) → reshape to [D, N_lat, batch]
5486 attn = ggml_reshape_3d(ctx, attn, D, N_lat, batch);
5487
5488 // Output projection
5489 auto* ca_out = ggml_mul_mat(ctx, layer.ca_out_w, attn); // [D, N_lat, batch]
5490
5491 // Residual
5492 latents = ggml_add(ctx, latents, ca_out);
5493 }
5494

Callers 1

Calls 1

sam3_layer_normFunction · 0.85

Tested by

no test coverage detected