@@ -786,10 +786,43 @@ static std::pair<float, float> get_ancestral_step(float sigma_from,
786786 return {sigma_down, sigma_up};
787787}
788788
789+ static std::tuple<float , float , float > get_ancestral_step_flow (float sigma_from,
790+ float sigma_to,
791+ float eta = 1 .0f ) {
792+ float sigma_down = sigma_to;
793+ float sigma_up = 0 .0f ;
794+ float alpha_scale = 1 .0f ;
795+
796+ if (eta <= 0 .0f || sigma_from <= 0 .0f || sigma_to <= 0 .0f ) {
797+ return {sigma_down, sigma_up, alpha_scale};
798+ }
799+
800+ // Flow Euler ancestral sampling becomes numerically unstable for eta > 1, so
801+ // clamp to the valid maximum-noise regime instead of letting NaNs propagate.
802+ eta = std::min (eta, 1 .0f );
803+
804+ float sigma_ratio = sigma_to / sigma_from;
805+ sigma_down = sigma_to * (1 .0f + (sigma_ratio - 1 .0f ) * eta);
806+ sigma_down = std::max (0 .0f , std::min (sigma_to, sigma_down));
807+
808+ float denom = 1 .0f - sigma_down;
809+ if (denom <= 0 .0f ) {
810+ return {sigma_to, sigma_up, alpha_scale};
811+ }
812+
813+ alpha_scale = (1 .0f - sigma_to) / denom;
814+
815+ float term = (sigma_down / sigma_to) * alpha_scale;
816+ term = std::max (-1 .0f , std::min (1 .0f , term));
817+ sigma_up = sigma_to * std::sqrt (std::max (1 .0f - term * term, 0 .0f ));
818+ return {sigma_down, sigma_up, alpha_scale};
819+ }
820+
789821static sd::Tensor<float > sample_euler_ancestral (denoise_cb_t model,
790822 sd::Tensor<float > x,
791823 const std::vector<float >& sigmas,
792- std::shared_ptr<RNG> rng) {
824+ std::shared_ptr<RNG> rng,
825+ float eta) {
793826 int steps = static_cast <int >(sigmas.size ()) - 1 ;
794827 for (int i = 0 ; i < steps; i++) {
795828 float sigma = sigmas[i];
@@ -799,7 +832,7 @@ static sd::Tensor<float> sample_euler_ancestral(denoise_cb_t model,
799832 }
800833 sd::Tensor<float > denoised = std::move (denoised_opt);
801834 sd::Tensor<float > d = (x - denoised) / sigma;
802- auto [sigma_down, sigma_up] = get_ancestral_step (sigmas[i], sigmas[i + 1 ]);
835+ auto [sigma_down, sigma_up] = get_ancestral_step (sigmas[i], sigmas[i + 1 ], eta );
803836 x += d * (sigma_down - sigmas[i]);
804837 if (sigmas[i + 1 ] > 0 ) {
805838 x += sd::Tensor<float >::randn_like (x, rng) * sigma_up;
@@ -808,6 +841,30 @@ static sd::Tensor<float> sample_euler_ancestral(denoise_cb_t model,
808841 return x;
809842}
810843
844+ static sd::Tensor<float > sample_euler_flow (denoise_cb_t model,
845+ sd::Tensor<float > x,
846+ const std::vector<float >& sigmas,
847+ std::shared_ptr<RNG> rng,
848+ float eta) {
849+ int steps = static_cast <int >(sigmas.size ()) - 1 ;
850+ for (int i = 0 ; i < steps; i++) {
851+ float sigma = sigmas[i];
852+ auto denoised_opt = model (x, sigma, i + 1 );
853+ if (denoised_opt.empty ()) {
854+ return {};
855+ }
856+ sd::Tensor<float > denoised = std::move (denoised_opt);
857+ auto [sigma_down, sigma_up, alpha_scale] = get_ancestral_step_flow (sigma, sigmas[i + 1 ], eta);
858+ float sigma_ratio = sigma_down / sigma;
859+ x = sigma_ratio * x + (1 .0f - sigma_ratio) * denoised;
860+
861+ if (sigma_up > 0 .0f ) {
862+ x = alpha_scale * x + sd::Tensor<float >::randn_like (x, rng) * sigma_up;
863+ }
864+ }
865+ return x;
866+ }
867+
811868static sd::Tensor<float > sample_euler (denoise_cb_t model,
812869 sd::Tensor<float > x,
813870 const std::vector<float >& sigmas) {
@@ -885,7 +942,8 @@ static sd::Tensor<float> sample_dpm2(denoise_cb_t model,
885942static sd::Tensor<float > sample_dpmpp_2s_ancestral (denoise_cb_t model,
886943 sd::Tensor<float > x,
887944 const std::vector<float >& sigmas,
888- std::shared_ptr<RNG> rng) {
945+ std::shared_ptr<RNG> rng,
946+ float eta) {
889947 auto t_fn = [](float sigma) -> float { return -log (sigma); };
890948 auto sigma_fn = [](float t) -> float { return exp (-t); };
891949
@@ -896,7 +954,7 @@ static sd::Tensor<float> sample_dpmpp_2s_ancestral(denoise_cb_t model,
896954 return {};
897955 }
898956 sd::Tensor<float > denoised = std::move (denoised_opt);
899- auto [sigma_down, sigma_up] = get_ancestral_step (sigmas[i], sigmas[i + 1 ]);
957+ auto [sigma_down, sigma_up] = get_ancestral_step (sigmas[i], sigmas[i + 1 ], eta );
900958
901959 if (sigma_down == 0 ) {
902960 x = denoised;
@@ -1368,18 +1426,22 @@ static sd::Tensor<float> sample_k_diffusion(sample_method_t method,
13681426 sd::Tensor<float > x,
13691427 std::vector<float > sigmas,
13701428 std::shared_ptr<RNG> rng,
1371- float eta) {
1429+ float eta,
1430+ bool is_flow_denoiser) {
13721431 switch (method) {
13731432 case EULER_A_SAMPLE_METHOD:
1374- return sample_euler_ancestral (model, std::move (x), sigmas, rng);
1433+ if (is_flow_denoiser)
1434+ return sample_euler_flow (model, std::move (x), sigmas, rng, eta);
1435+ else
1436+ return sample_euler_ancestral (model, std::move (x), sigmas, rng, eta);
13751437 case EULER_SAMPLE_METHOD:
13761438 return sample_euler (model, std::move (x), sigmas);
13771439 case HEUN_SAMPLE_METHOD:
13781440 return sample_heun (model, std::move (x), sigmas);
13791441 case DPM2_SAMPLE_METHOD:
13801442 return sample_dpm2 (model, std::move (x), sigmas);
13811443 case DPMPP2S_A_SAMPLE_METHOD:
1382- return sample_dpmpp_2s_ancestral (model, std::move (x), sigmas, rng);
1444+ return sample_dpmpp_2s_ancestral (model, std::move (x), sigmas, rng, eta );
13831445 case DPMPP2M_SAMPLE_METHOD:
13841446 return sample_dpmpp_2m (model, std::move (x), sigmas);
13851447 case DPMPP2Mv2_SAMPLE_METHOD:
0 commit comments