diff --git a/denoiser.hpp b/denoiser.hpp index 339c0cfb9..20d5f726a 100644 --- a/denoiser.hpp +++ b/denoiser.hpp @@ -251,6 +251,35 @@ struct KarrasSchedule : SigmaSchedule { } }; +// Close to Beta Schedule, but increadably simple in code. +struct SmoothStepSchedule : SigmaSchedule { + static constexpr float smoothstep(float x) { + return x * x * (3.0f - 2.0f * x); + } + + std::vector get_sigmas(uint32_t n, float /*sigma_min*/, float /*sigma_max*/, t_to_sigma_t t_to_sigma) override { + std::vector result; + result.reserve(n + 1); + + const int t_max = TIMESTEPS - 1; + if (n == 0) { + return result; + } else if (n == 1) { + result.push_back(t_to_sigma((float)t_max)); + result.push_back(0.f); + return result; + } + + for (uint32_t i = 0; i < n; i++) { + float u = 1.f - float(i) / float(n); + result.push_back(t_to_sigma(std::round(smoothstep(u) * t_max))); + } + + result.push_back(0.f); + return result; + } +}; + struct Denoiser { std::shared_ptr scheduler = std::make_shared(); virtual float sigma_min() = 0; diff --git a/examples/cli/main.cpp b/examples/cli/main.cpp index 098c98cc5..8dbf964ef 100644 --- a/examples/cli/main.cpp +++ b/examples/cli/main.cpp @@ -238,7 +238,7 @@ void print_usage(int argc, const char* argv[]) { printf(" --skip-layers LAYERS Layers to skip for SLG steps: (default: [7,8,9])\n"); printf(" --skip-layer-start START SLG enabling point: (default: 0.01)\n"); printf(" --skip-layer-end END SLG disabling point: (default: 0.2)\n"); - printf(" --scheduler {discrete, karras, exponential, ays, gits} Denoiser sigma scheduler (default: discrete)\n"); + printf(" --scheduler {discrete, karras, exponential, ays, gits, smoothstep} Denoiser sigma scheduler (default: discrete)\n"); printf(" --sampling-method {euler, euler_a, heun, dpm2, dpm++2s_a, dpm++2m, dpm++2mv2, ipndm, ipndm_v, lcm, ddim_trailing, tcd}\n"); printf(" sampling method (default: \"euler_a\")\n"); printf(" --steps STEPS number of sample steps (default: 20)\n"); @@ -251,7 +251,7 @@ void print_usage(int argc, const char* argv[]) { printf(" --high-noise-skip-layers LAYERS (high noise) Layers to skip for SLG steps: (default: [7,8,9])\n"); printf(" --high-noise-skip-layer-start (high noise) SLG enabling point: (default: 0.01)\n"); printf(" --high-noise-skip-layer-end END (high noise) SLG disabling point: (default: 0.2)\n"); - printf(" --high-noise-scheduler {discrete, karras, exponential, ays, gits} Denoiser sigma scheduler (default: discrete)\n"); + printf(" --high-noise-scheduler {discrete, karras, exponential, ays, gits, smoothstep} Denoiser sigma scheduler (default: discrete)\n"); printf(" --high-noise-sampling-method {euler, euler_a, heun, dpm2, dpm++2s_a, dpm++2m, dpm++2mv2, ipndm, ipndm_v, lcm, ddim_trailing, tcd}\n"); printf(" (high noise) sampling method (default: \"euler_a\")\n"); printf(" --high-noise-steps STEPS (high noise) number of sample steps (default: -1 = auto)\n"); diff --git a/stable-diffusion.cpp b/stable-diffusion.cpp index 088947311..410c7aa7d 100644 --- a/stable-diffusion.cpp +++ b/stable-diffusion.cpp @@ -750,6 +750,10 @@ class StableDiffusionGGML { denoiser->scheduler = std::make_shared(); denoiser->scheduler->version = version; break; + case SMOOTHSTEP: + LOG_INFO("Running with SmoothStep scheduler"); + denoiser->scheduler = std::make_shared(); + break; case DEFAULT: // Don't touch anything. break; @@ -1533,6 +1537,7 @@ const char* schedule_to_str[] = { "exponential", "ays", "gits", + "smoothstep", }; const char* sd_schedule_name(enum scheduler_t scheduler) { diff --git a/stable-diffusion.h b/stable-diffusion.h index 34b0d1492..0f47a7632 100644 --- a/stable-diffusion.h +++ b/stable-diffusion.h @@ -57,6 +57,7 @@ enum scheduler_t { EXPONENTIAL, AYS, GITS, + SMOOTHSTEP, SCHEDULE_COUNT };