@@ -421,29 +421,88 @@ namespace Krea2 {
421421 ggml_tensor* forward (GGMLRunnerContext* ctx,
422422 ggml_tensor* x,
423423 ggml_tensor* vec,
424- ggml_tensor* pe) {
424+ ggml_tensor* pe,
425+ ggml_tensor* vec_refs = nullptr ,
426+ int64_t ref_start = -1 ) {
425427 auto mod = std::dynamic_pointer_cast<KreaDoubleSharedModulation>(blocks[" mod" ]);
426428 auto prenorm = std::dynamic_pointer_cast<KreaRMSNorm>(blocks[" prenorm" ]);
427429 auto postnorm = std::dynamic_pointer_cast<KreaRMSNorm>(blocks[" postnorm" ]);
428430 auto attn = std::dynamic_pointer_cast<KreaAttention>(blocks[" attn" ]);
429431 auto mlp = std::dynamic_pointer_cast<KreaSwiGLU>(blocks[" mlp" ]);
430432
431- auto mods = mod->forward (ctx, vec);
432- auto attn_input = Flux::modulate (ctx->ggml_ctx ,
433- prenorm->forward (ctx, x),
434- mods[1 ],
435- mods[0 ],
436- true );
437- auto attn_out = attn->forward (ctx, attn_input, pe);
438- x = ggml_add (ctx->ggml_ctx , x, ggml_mul (ctx->ggml_ctx , attn_out, mods[2 ]));
439-
440- auto mlp_input = Flux::modulate (ctx->ggml_ctx ,
441- postnorm->forward (ctx, x),
442- mods[4 ],
443- mods[3 ],
444- true );
445- auto mlp_out = mlp->forward (ctx, mlp_input);
446- x = ggml_add (ctx->ggml_ctx , x, ggml_mul (ctx->ggml_ctx , mlp_out, mods[5 ]));
433+ if (ref_start >= 0 && vec_refs) {
434+ // same as normal, but since vec is different for refs and the rest, needs a lot of views and concats
435+ auto mods_main = mod->forward (ctx, vec);
436+ auto mods_refs = mod->forward (ctx, vec_refs);
437+
438+ int64_t D = x->ne [0 ];
439+ int64_t N = x->ne [1 ];
440+ int64_t B = x->ne [2 ];
441+ size_t nb1 = x->nb [1 ];
442+ size_t nb2 = x->nb [2 ];
443+
444+ int64_t len_main = ref_start;
445+ int64_t len_refs = N - ref_start;
446+
447+ auto pre_x = prenorm->forward (ctx, x);
448+
449+ auto pre_x_main = ggml_view_3d (ctx->ggml_ctx , pre_x, D, len_main, B, nb1, nb2, 0 );
450+ auto pre_x_refs = ggml_view_3d (ctx->ggml_ctx , pre_x, D, len_refs, B, nb1, nb2, len_main * nb1);
451+
452+ auto attn_in_main = Flux::modulate (ctx->ggml_ctx , pre_x_main, mods_main[1 ], mods_main[0 ], true );
453+ auto attn_in_refs = Flux::modulate (ctx->ggml_ctx , pre_x_refs, mods_refs[1 ], mods_refs[0 ], true );
454+
455+ auto attn_input = ggml_concat (ctx->ggml_ctx , attn_in_main, attn_in_refs, 1 );
456+
457+ auto attn_out = attn->forward (ctx, attn_input, pe);
458+
459+ auto attn_out_main = ggml_view_3d (ctx->ggml_ctx , attn_out, D, len_main, B, attn_out->nb [1 ], attn_out->nb [2 ], 0 );
460+ auto attn_out_refs = ggml_view_3d (ctx->ggml_ctx , attn_out, D, len_refs, B, attn_out->nb [1 ], attn_out->nb [2 ], len_main * attn_out->nb [1 ]);
461+
462+ auto res_main = ggml_mul (ctx->ggml_ctx , attn_out_main, mods_main[2 ]);
463+ auto res_refs = ggml_mul (ctx->ggml_ctx , attn_out_refs, mods_refs[2 ]);
464+
465+ auto attn_res = ggml_concat (ctx->ggml_ctx , res_main, res_refs, 1 );
466+
467+ x = ggml_add (ctx->ggml_ctx , x, attn_res);
468+
469+ auto post_x = postnorm->forward (ctx, x);
470+
471+ auto post_x_main = ggml_view_3d (ctx->ggml_ctx , post_x, D, len_main, B, post_x->nb [1 ], post_x->nb [2 ], 0 );
472+ auto post_x_refs = ggml_view_3d (ctx->ggml_ctx , post_x, D, len_refs, B, post_x->nb [1 ], post_x->nb [2 ], len_main * post_x->nb [1 ]);
473+
474+ auto mlp_in_main = Flux::modulate (ctx->ggml_ctx , post_x_main, mods_main[4 ], mods_main[3 ], true );
475+ auto mlp_in_refs = Flux::modulate (ctx->ggml_ctx , post_x_refs, mods_refs[4 ], mods_refs[3 ], true );
476+
477+ auto mlp_input = ggml_concat (ctx->ggml_ctx , mlp_in_main, mlp_in_refs, 1 );
478+ auto mlp_out = mlp->forward (ctx, mlp_input);
479+
480+ auto mlp_out_main = ggml_view_3d (ctx->ggml_ctx , mlp_out, D, len_main, B, mlp_out->nb [1 ], mlp_out->nb [2 ], 0 );
481+ auto mlp_out_refs = ggml_view_3d (ctx->ggml_ctx , mlp_out, D, len_refs, B, mlp_out->nb [1 ], mlp_out->nb [2 ], len_main * mlp_out->nb [1 ]);
482+
483+ auto mlp_res_main = ggml_mul (ctx->ggml_ctx , mlp_out_main, mods_main[5 ]);
484+ auto mlp_res_refs = ggml_mul (ctx->ggml_ctx , mlp_out_refs, mods_refs[5 ]);
485+
486+ auto mlp_res = ggml_concat (ctx->ggml_ctx , mlp_res_main, mlp_res_refs, 1 );
487+ x = ggml_add (ctx->ggml_ctx , x, mlp_res);
488+ } else {
489+ auto mods = mod->forward (ctx, vec);
490+ auto attn_input = Flux::modulate (ctx->ggml_ctx ,
491+ prenorm->forward (ctx, x),
492+ mods[1 ],
493+ mods[0 ],
494+ true );
495+ auto attn_out = attn->forward (ctx, attn_input, pe);
496+ x = ggml_add (ctx->ggml_ctx , x, ggml_mul (ctx->ggml_ctx , attn_out, mods[2 ]));
497+
498+ auto mlp_input = Flux::modulate (ctx->ggml_ctx ,
499+ postnorm->forward (ctx, x),
500+ mods[4 ],
501+ mods[3 ],
502+ true );
503+ auto mlp_out = mlp->forward (ctx, mlp_input);
504+ x = ggml_add (ctx->ggml_ctx , x, ggml_mul (ctx->ggml_ctx , mlp_out, mods[5 ]));
505+ }
447506 return x;
448507 }
449508
@@ -555,7 +614,8 @@ namespace Krea2 {
555614 ggml_tensor* x,
556615 ggml_tensor* timestep,
557616 ggml_tensor* context,
558- ggml_tensor* pe) {
617+ ggml_tensor* pe,
618+ std::vector<ggml_tensor*> ref_latents = {}) {
559619 int64_t W = x->ne [0 ];
560620 int64_t H = x->ne [1 ];
561621 int64_t N = x->ne [3 ];
@@ -570,26 +630,44 @@ namespace Krea2 {
570630
571631 auto img = DiT::pad_and_patchify (ctx, x, config.patch_size , config.patch_size , true );
572632 int64_t img_len = img->ne [1 ];
633+ if (ref_latents.size () > 0 ) {
634+ for (ggml_tensor* ref : ref_latents) {
635+ ref = DiT::pad_and_patchify (ctx, ref, config.patch_size , config.patch_size , true );
636+ img = ggml_concat (ctx->ggml_ctx , img, ref, 1 );
637+ }
638+ }
639+ int64_t ref_len = img->ne [1 ] - img_len;
573640 img = first->forward (ctx, img);
574641
575642 auto t = ggml_ext_timestep_embedding (ctx->ggml_ctx , timestep, static_cast <int >(config.timestep_dim ), 10000 , 1000 .f );
576643 t = tmlp->forward (ctx, t);
577644 t = ggml_reshape_3d (ctx->ggml_ctx , t, t->ne [0 ], 1 , t->ne [1 ]);
578645 auto tvec = tproj->forward (ctx, t);
579646
647+ ggml_tensor* tvec_0 = nullptr ;
648+ if (ref_latents.size () > 0 ) {
649+ // "index_timestep_zero" mode: use timestep = 0 for ref latents
650+ auto timestep_0 = ggml_scale (ctx->ggml_ctx , timestep, 0 .0f );
651+ auto t_0 = ggml_ext_timestep_embedding (ctx->ggml_ctx , timestep_0, static_cast <int >(config.timestep_dim ), 10000 , 1000 .f );
652+ t_0 = tmlp->forward (ctx, t_0);
653+ t_0 = ggml_reshape_3d (ctx->ggml_ctx , t_0, t_0->ne [0 ], 1 , t_0->ne [1 ]);
654+ tvec_0 = tproj->forward (ctx, t_0);
655+ }
656+
580657 auto txt = txtfusion->forward (ctx, context);
581658 txt = txtmlp->forward (ctx, txt);
582659 int64_t txt_len = txt->ne [1 ];
583660
584661 auto hidden_states = ggml_concat (ctx->ggml_ctx , txt, img, 1 );
662+ int64_t ref_start = hidden_states->ne [1 ] - ref_len;
585663 for (int i = 0 ; i < config.layers ; ++i) {
586664 auto block = std::dynamic_pointer_cast<KreaSingleStreamBlock>(blocks[" blocks." + std::to_string (i)]);
587- hidden_states = block->forward (ctx, hidden_states, tvec, pe);
665+ hidden_states = block->forward (ctx, hidden_states, tvec, pe, tvec_0, ref_start );
588666 sd::ggml_graph_cut::mark_graph_cut (hidden_states, " krea2.blocks." + std::to_string (i), " hidden_states" );
589667 }
590668
591- hidden_states = last->forward (ctx, hidden_states, t);
592669 hidden_states = ggml_ext_slice (ctx->ggml_ctx , hidden_states, 1 , txt_len, txt_len + img_len);
670+ hidden_states = last->forward (ctx, hidden_states, t);
593671 hidden_states = DiT::unpatchify_and_crop (ctx->ggml_ctx , hidden_states, H, W, config.patch_size , config.patch_size , true );
594672 return hidden_states;
595673 }
@@ -601,10 +679,16 @@ namespace Krea2 {
601679 int bs,
602680 int context_len,
603681 float theta,
604- const std::vector<int >& axes_dim) {
682+ const std::vector<int >& axes_dim,
683+ const std::vector<ggml_tensor*>& ref_latents,
684+ Rope::RefIndexMode ref_index_mode) {
605685 auto txt_ids = Rope::gen_flux_txt_ids (bs, context_len, 3 , {});
606686 auto img_ids = Rope::gen_flux_img_ids (h, w, patch_size, bs, 3 , 0 , 0 , 0 , false );
607687 auto ids = Rope::concat_ids (txt_ids, img_ids, bs);
688+ if (ref_latents.size () > 0 ) {
689+ auto refs_ids = Rope::gen_refs_ids (patch_size, bs, 3 , 1 , ref_latents, ref_index_mode, 1 .0f , false , 0 );
690+ ids = Rope::concat_ids (ids, refs_ids, bs);
691+ }
608692 return Rope::embed_nd (ids, bs, theta, axes_dim);
609693 }
610694
@@ -633,37 +717,49 @@ namespace Krea2 {
633717
634718 ggml_cgraph* build_graph (const sd::Tensor<float >& x_tensor,
635719 const sd::Tensor<float >& timesteps_tensor,
636- const sd::Tensor<float >& context_tensor) {
720+ const sd::Tensor<float >& context_tensor,
721+ const std::vector<sd::Tensor<float >>& ref_latents_tensor = {},
722+ Rope::RefIndexMode ref_index_mode = Rope::RefIndexMode::FIXED ) {
637723 ggml_cgraph* gf = new_graph_custom (KREA2_GRAPH_SIZE );
638724 ggml_tensor* x = make_input (x_tensor);
639725 ggml_tensor* timesteps = make_input (timesteps_tensor);
640726 GGML_ASSERT (x->ne [3 ] == 1 );
641727 GGML_ASSERT (!context_tensor.empty ());
642728 ggml_tensor* context = make_input (context_tensor);
643729
730+ std::vector<ggml_tensor*> ref_latents;
731+ ref_latents.reserve (ref_latents_tensor.size ());
732+ for (const auto & ref_latent_tensor : ref_latents_tensor) {
733+ ref_latents.push_back (make_input (ref_latent_tensor));
734+ }
735+
644736 pe_vec = gen_krea2_pe (static_cast <int >(x->ne [1 ]),
645737 static_cast <int >(x->ne [0 ]),
646738 config.patch_size ,
647739 static_cast <int >(x->ne [3 ]),
648740 static_cast <int >(context->ne [1 ]),
649741 config.theta ,
650- config.axes_dim );
742+ config.axes_dim ,
743+ ref_latents,
744+ ref_index_mode);
651745 int pos_len = static_cast <int >(pe_vec.size () / config.axes_dim_sum / 2 );
652746 auto pe = ggml_new_tensor_4d (compute_ctx, GGML_TYPE_F32 , 2 , 2 , config.axes_dim_sum / 2 , pos_len);
653747 set_backend_tensor_data (pe, pe_vec.data ());
654748
655749 auto runner_ctx = get_context ();
656- ggml_tensor* out = model.forward (&runner_ctx, x, timesteps, context, pe);
750+ ggml_tensor* out = model.forward (&runner_ctx, x, timesteps, context, pe, ref_latents );
657751 ggml_build_forward_expand (gf, out);
658752 return gf;
659753 }
660754
661755 sd::Tensor<float > compute (int n_threads,
662756 const sd::Tensor<float >& x,
663757 const sd::Tensor<float >& timesteps,
664- const sd::Tensor<float >& context) {
758+ const sd::Tensor<float >& context,
759+ const std::vector<sd::Tensor<float >>& ref_latents = {},
760+ Rope::RefIndexMode ref_index_mode = Rope::RefIndexMode::FIXED ) {
665761 auto get_graph = [&]() -> ggml_cgraph* {
666- return build_graph (x, timesteps, context);
762+ return build_graph (x, timesteps, context, ref_latents, ref_index_mode );
667763 };
668764 return restore_trailing_singleton_dims (GGMLRunner::compute<float >(get_graph, n_threads, false , false , false ), x.dim ());
669765 }
@@ -672,10 +768,13 @@ namespace Krea2 {
672768 const DiffusionParams& diffusion_params) override {
673769 GGML_ASSERT (diffusion_params.x != nullptr );
674770 GGML_ASSERT (diffusion_params.timesteps != nullptr );
771+ static const std::vector<sd::Tensor<float >> empty_ref_latents;
675772 return compute (n_threads,
676773 *diffusion_params.x ,
677774 *diffusion_params.timesteps ,
678- tensor_or_empty (diffusion_params.context ));
775+ tensor_or_empty (diffusion_params.context ),
776+ diffusion_params.ref_latents ? *diffusion_params.ref_latents : empty_ref_latents,
777+ diffusion_params.ref_index_mode );
679778 }
680779 };
681780} // namespace Krea2
0 commit comments