@@ -148,9 +148,13 @@ llama_model_dflash::graph<false>::graph(const llama_model & model, const llm_gra
148148 cb (noise_embd, " inp_noise_embd" , -1 );
149149 res->add_input (std::move (inp));
150150
151- // injected target context: [n_embd, n_enc] from llama_cross::v_embd
152- ggml_tensor * target_ctx = build_inp_cross_embd ();
153- const int64_t n_ctx = target_ctx->ne [1 ];
151+ // P2b step A: fixed-size injected target context [n_embd, n_ctx_max] so the decoder graph
152+ // shape is constant across draft steps (enables graph reuse + CUDA graphs). The active context
153+ // length varies per step; padded rows are masked out by dflash_kq_mask. Filled by cb-name.
154+ const int64_t n_ctx = cparams.n_ctx ;
155+ ggml_tensor * target_ctx = ggml_new_tensor_2d (ctx0, GGML_TYPE_F32 , n_embd, n_ctx);
156+ ggml_set_input (target_ctx);
157+ cb (target_ctx, " dflash_target_ctx" , -1 );
154158
155159 const int64_t n_tokens_kv = n_ctx + n_tokens;
156160
@@ -162,6 +166,14 @@ llama_model_dflash::graph<false>::graph(const llama_model & model, const llm_gra
162166 // query positions = the noise block (last n_tokens entries)
163167 ggml_tensor * inp_pos_q = ggml_view_1d (ctx0, inp_pos_full, n_tokens, n_ctx * ggml_element_size (inp_pos_full));
164168
169+ // additive attention mask [n_kv, n_q]: 0 = attend, -INF = masked. Masks the padded context
170+ // rows [n_valid, n_ctx); valid context + the noise block are visible. Filled by cb-name.
171+ // flash attention requires an F16 mask; the non-flash soft-max path takes F32
172+ ggml_tensor * kq_mask = ggml_new_tensor_4d (ctx0,
173+ cparams.flash_attn ? GGML_TYPE_F16 : GGML_TYPE_F32 , n_tokens_kv, n_tokens, 1 , 1 );
174+ ggml_set_input (kq_mask);
175+ cb (kq_mask, " dflash_kq_mask" , -1 );
176+
165177 const float kq_scale = 1 .0f /sqrtf (float (n_embd_head));
166178
167179 ggml_tensor * inpL = noise_embd;
@@ -206,9 +218,8 @@ llama_model_dflash::graph<false>::graph(const llama_model & model, const llm_gra
206218 ext_factor, attn_factor, beta_fast, beta_slow);
207219 cb (Qcur, " Qcur_rope" , il);
208220
209- // single-block baseline: full attention (no causal mask). The block-diffusion mask
210- // (causal-to-anchor for context, bidirectional within block) is added with np>1.
211- ggml_tensor * cur = build_attn_mha (Qcur, Kcur, Vcur, nullptr , nullptr , nullptr , nullptr , kq_scale, il);
221+ // attention with the padded-context mask (see dflash_kq_mask above)
222+ ggml_tensor * cur = build_attn_mha (Qcur, Kcur, Vcur, nullptr , kq_mask, nullptr , nullptr , kq_scale, il);
212223 cb (cur, " kqv_out" , il);
213224
214225 cur = build_lora_mm (layer.wo , cur);
0 commit comments