mirror of
https://github.com/leejet/stable-diffusion.cpp.git
synced 2026-07-24 11:50:54 -05:00
Compare commits
12 Commits
master-ecf
...
master-225
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
225162f270 | ||
|
|
b9e4718fac | ||
|
|
1ce1c1adca | ||
|
|
19fbfd8639 | ||
|
|
76c72628b1 | ||
|
|
3bae667f3d | ||
|
|
8d0819c548 | ||
|
|
7a8ff2e819 | ||
|
|
0927e8e322 | ||
|
|
83ef4e44ce | ||
|
|
7dac89ad75 | ||
|
|
9251756086 |
@@ -50,7 +50,7 @@ Inference of Stable Diffusion and Flux in pure C/C++
|
||||
- Linux
|
||||
- Mac OS
|
||||
- Windows
|
||||
- Android (via Termux)
|
||||
- Android (via Termux, [Local Diffusion](https://github.com/rmatif/Local-Diffusion))
|
||||
|
||||
### TODO
|
||||
|
||||
@@ -392,10 +392,12 @@ Using formats of different precisions will yield results of varying quality.
|
||||
|
||||
These projects wrap `stable-diffusion.cpp` for easier use in other languages/frameworks.
|
||||
|
||||
* Golang: [seasonjs/stable-diffusion](https://github.com/seasonjs/stable-diffusion)
|
||||
* Golang (non-cgo): [seasonjs/stable-diffusion](https://github.com/seasonjs/stable-diffusion)
|
||||
* Golang (cgo): [Binozo/GoStableDiffusion](https://github.com/Binozo/GoStableDiffusion)
|
||||
* C#: [DarthAffe/StableDiffusion.NET](https://github.com/DarthAffe/StableDiffusion.NET)
|
||||
* Python: [william-murray1204/stable-diffusion-cpp-python](https://github.com/william-murray1204/stable-diffusion-cpp-python)
|
||||
* Rust: [newfla/diffusion-rs](https://github.com/newfla/diffusion-rs)
|
||||
* Flutter/Dart: [rmatif/Local-Diffusion](https://github.com/rmatif/Local-Diffusion)
|
||||
|
||||
## UIs
|
||||
|
||||
@@ -404,6 +406,7 @@ These projects use `stable-diffusion.cpp` as a backend for their image generatio
|
||||
- [Jellybox](https://jellybox.com)
|
||||
- [Stable Diffusion GUI](https://github.com/fszontagh/sd.cpp.gui.wx)
|
||||
- [Stable Diffusion CLI-GUI](https://github.com/piallai/stable-diffusion.cpp)
|
||||
- [Local Diffusion](https://github.com/rmatif/Local-Diffusion)
|
||||
|
||||
## Contributors
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ public:
|
||||
auto conv = std::dynamic_pointer_cast<Conv2d>(blocks["conv"]);
|
||||
|
||||
x = ggml_upscale(ctx, x, 2, GGML_SCALE_MODE_NEAREST); // [N, channels, h*2, w*2]
|
||||
x = conv->forward(ctx, x); // [N, out_channels, h*2, w*2]
|
||||
x = conv->forward(ctx, x); // [N, out_channels, h*2, w*2]
|
||||
return x;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -459,8 +459,8 @@ struct FrozenCLIPEmbedderWithCustomWords : public Conditioner {
|
||||
if (sd_version_is_sdxl(version)) {
|
||||
text_model2->compute(n_threads,
|
||||
input_ids2,
|
||||
0,
|
||||
NULL,
|
||||
num_custom_embeddings,
|
||||
token_embed_custom.data(),
|
||||
max_token_idx,
|
||||
false,
|
||||
&chunk_hidden_states2, work_ctx);
|
||||
@@ -470,8 +470,8 @@ struct FrozenCLIPEmbedderWithCustomWords : public Conditioner {
|
||||
if (chunk_idx == 0) {
|
||||
text_model2->compute(n_threads,
|
||||
input_ids2,
|
||||
0,
|
||||
NULL,
|
||||
num_custom_embeddings,
|
||||
token_embed_custom.data(),
|
||||
max_token_idx,
|
||||
true,
|
||||
&pooled,
|
||||
|
||||
59
denoiser.hpp
59
denoiser.hpp
@@ -168,24 +168,21 @@ struct AYSSchedule : SigmaSchedule {
|
||||
std::vector<float> inputs;
|
||||
std::vector<float> results(n + 1);
|
||||
|
||||
switch (version) {
|
||||
case VERSION_SD2: /* fallthrough */
|
||||
LOG_WARN("AYS not designed for SD2.X models");
|
||||
case VERSION_SD1:
|
||||
LOG_INFO("AYS using SD1.5 noise levels");
|
||||
inputs = noise_levels[0];
|
||||
break;
|
||||
case VERSION_SDXL:
|
||||
LOG_INFO("AYS using SDXL noise levels");
|
||||
inputs = noise_levels[1];
|
||||
break;
|
||||
case VERSION_SVD:
|
||||
LOG_INFO("AYS using SVD noise levels");
|
||||
inputs = noise_levels[2];
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Version not compatable with AYS scheduler");
|
||||
return results;
|
||||
if (sd_version_is_sd2((SDVersion)version)) {
|
||||
LOG_WARN("AYS not designed for SD2.X models");
|
||||
} /* fallthrough */
|
||||
else if (sd_version_is_sd1((SDVersion)version)) {
|
||||
LOG_INFO("AYS using SD1.5 noise levels");
|
||||
inputs = noise_levels[0];
|
||||
} else if (sd_version_is_sdxl((SDVersion)version)) {
|
||||
LOG_INFO("AYS using SDXL noise levels");
|
||||
inputs = noise_levels[1];
|
||||
} else if (version == VERSION_SVD) {
|
||||
LOG_INFO("AYS using SVD noise levels");
|
||||
inputs = noise_levels[2];
|
||||
} else {
|
||||
LOG_ERROR("Version not compatible with AYS scheduler");
|
||||
return results;
|
||||
}
|
||||
|
||||
/* Stretches those pre-calculated reference levels out to the desired
|
||||
@@ -346,6 +343,32 @@ struct CompVisVDenoiser : public CompVisDenoiser {
|
||||
}
|
||||
};
|
||||
|
||||
struct EDMVDenoiser : public CompVisVDenoiser {
|
||||
float min_sigma = 0.002;
|
||||
float max_sigma = 120.0;
|
||||
|
||||
EDMVDenoiser(float min_sigma = 0.002, float max_sigma = 120.0)
|
||||
: min_sigma(min_sigma), max_sigma(max_sigma) {
|
||||
schedule = std::make_shared<ExponentialSchedule>();
|
||||
}
|
||||
|
||||
float t_to_sigma(float t) {
|
||||
return std::exp(t * 4 / (float)TIMESTEPS);
|
||||
}
|
||||
|
||||
float sigma_to_t(float s) {
|
||||
return 0.25 * std::log(s);
|
||||
}
|
||||
|
||||
float sigma_min() {
|
||||
return min_sigma;
|
||||
}
|
||||
|
||||
float sigma_max() {
|
||||
return max_sigma;
|
||||
}
|
||||
};
|
||||
|
||||
float time_snr_shift(float alpha, float t) {
|
||||
if (alpha == 1.0f) {
|
||||
return t;
|
||||
|
||||
@@ -60,6 +60,7 @@ const char* modes_str[] = {
|
||||
"edit",
|
||||
"convert",
|
||||
};
|
||||
#define SD_ALL_MODES_STR "txt2img, img2img, edit, convert"
|
||||
|
||||
enum SDMode {
|
||||
TXT2IMG,
|
||||
@@ -199,14 +200,18 @@ void print_usage(int argc, const char* argv[]) {
|
||||
printf("\n");
|
||||
printf("arguments:\n");
|
||||
printf(" -h, --help show this help message and exit\n");
|
||||
printf(" -M, --mode [MODEL] run mode (txt2img or img2img or convert, default: txt2img)\n");
|
||||
printf(" -M, --mode [MODE] run mode, one of:\n");
|
||||
printf(" txt2img: generate an image from a text prompt (default)\n");
|
||||
printf(" img2img: generate an image from a text prompt and an initial image (--init-img)\n");
|
||||
printf(" edit: modify an image (--ref-image) based on text instructions\n");
|
||||
printf(" convert: convert a model file to gguf format, optionally with quantization\n");
|
||||
printf(" -t, --threads N number of threads to use during computation (default: -1)\n");
|
||||
printf(" If threads <= 0, then threads will be set to the number of CPU physical cores\n");
|
||||
printf(" -m, --model [MODEL] path to full model\n");
|
||||
printf(" --diffusion-model path to the standalone diffusion model\n");
|
||||
printf(" --clip_l path to the clip-l text encoder\n");
|
||||
printf(" --clip_g path to the clip-g text encoder\n");
|
||||
printf(" --t5xxl path to the the t5xxl text encoder\n");
|
||||
printf(" --t5xxl path to the t5xxl text encoder\n");
|
||||
printf(" --vae [VAE] path to vae\n");
|
||||
printf(" --taesd [TAESD_PATH] path to taesd. Using Tiny AutoEncoder for fast decoding (low quality)\n");
|
||||
printf(" --control-net [CONTROL_PATH] path to control net model\n");
|
||||
@@ -222,7 +227,7 @@ void print_usage(int argc, const char* argv[]) {
|
||||
printf(" -i, --init-img [IMAGE] path to the input image, required by img2img\n");
|
||||
printf(" --mask [MASK] path to the mask image, required by img2img with mask\n");
|
||||
printf(" --control-image [IMAGE] path to image condition, control net\n");
|
||||
printf(" -r, --ref_image [PATH] reference image for Flux Kontext models (can be used multiple times) \n");
|
||||
printf(" -r, --ref-image [PATH] reference image for Flux Kontext models (can be used multiple times) \n");
|
||||
printf(" -o, --output OUTPUT path to write result image to (default: ./output.png)\n");
|
||||
printf(" -p, --prompt [PROMPT] the prompt to render\n");
|
||||
printf(" -n, --negative-prompt PROMPT the negative prompt (default: \"\")\n");
|
||||
@@ -291,8 +296,8 @@ void parse_args(int argc, const char** argv, SDParams& params) {
|
||||
}
|
||||
if (mode_found == -1) {
|
||||
fprintf(stderr,
|
||||
"error: invalid mode %s, must be one of [txt2img, img2img, img2vid, convert]\n",
|
||||
mode_selected);
|
||||
"error: invalid mode %s, must be one of [%s]\n",
|
||||
mode_selected, SD_ALL_MODES_STR);
|
||||
exit(1);
|
||||
}
|
||||
params.mode = (SDMode)mode_found;
|
||||
@@ -655,7 +660,7 @@ void parse_args(int argc, const char** argv, SDParams& params) {
|
||||
params.ref_image_paths.push_back(argv[i]);
|
||||
} else if (arg == "--chroma-disable-dit-mask") {
|
||||
params.chroma_use_dit_mask = false;
|
||||
} else if (arg == "--chroma-use-t5-mask") {
|
||||
} else if (arg == "--chroma-enable-t5-mask") {
|
||||
params.chroma_use_t5_mask = true;
|
||||
} else if (arg == "--chroma-t5-mask-pad") {
|
||||
if (++i >= argc) {
|
||||
@@ -1218,4 +1223,4 @@ int main(int argc, const char* argv[]) {
|
||||
free(input_image_buffer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ __STATIC_INLINE__ struct ggml_tensor* ggml_kronecker(ggml_context* ctx, struct g
|
||||
a->ne[1] * b->ne[1],
|
||||
a->ne[2] * b->ne[2],
|
||||
a->ne[3] * b->ne[3],
|
||||
GGML_SCALE_MODE_NEAREST),
|
||||
GGML_SCALE_MODE_NEAREST),
|
||||
b);
|
||||
}
|
||||
|
||||
|
||||
5
lora.hpp
5
lora.hpp
@@ -3,7 +3,7 @@
|
||||
|
||||
#include "ggml_extend.hpp"
|
||||
|
||||
#define LORA_GRAPH_SIZE 15360
|
||||
#define LORA_GRAPH_BASE_SIZE 10240
|
||||
|
||||
struct LoraModel : public GGMLRunner {
|
||||
enum lora_t {
|
||||
@@ -238,7 +238,8 @@ struct LoraModel : public GGMLRunner {
|
||||
}
|
||||
|
||||
struct ggml_cgraph* build_lora_graph(std::map<std::string, struct ggml_tensor*> model_tensors, SDVersion version) {
|
||||
struct ggml_cgraph* gf = ggml_new_graph_custom(compute_ctx, LORA_GRAPH_SIZE, false);
|
||||
size_t lora_graph_size = LORA_GRAPH_BASE_SIZE + lora_tensors.size() * 10;
|
||||
struct ggml_cgraph* gf = ggml_new_graph_custom(compute_ctx, lora_graph_size, false);
|
||||
|
||||
zero_index = ggml_new_tensor_1d(compute_ctx, GGML_TYPE_I32, 1);
|
||||
set_backend_tensor_data(zero_index, zero_index_vec.data());
|
||||
|
||||
77
model.cpp
77
model.cpp
@@ -100,6 +100,7 @@ const char* unused_tensors[] = {
|
||||
"model_ema.diffusion_model",
|
||||
"embedding_manager",
|
||||
"denoiser.sigmas",
|
||||
"text_encoders.t5xxl.transformer.encoder.embed_tokens.weight", // only used during training
|
||||
};
|
||||
|
||||
bool is_unused_tensor(std::string name) {
|
||||
@@ -181,6 +182,64 @@ std::unordered_map<std::string, std::string> pmid_v2_name_map = {
|
||||
std::string convert_open_clip_to_hf_clip(const std::string& name) {
|
||||
std::string new_name = name;
|
||||
std::string prefix;
|
||||
if (contains(new_name, ".enc.")) {
|
||||
// llama.cpp naming convention for T5
|
||||
size_t pos = new_name.find(".enc.");
|
||||
if (pos != std::string::npos) {
|
||||
new_name.replace(pos, 5, ".encoder.");
|
||||
}
|
||||
pos = new_name.find("blk.");
|
||||
if (pos != std::string::npos) {
|
||||
new_name.replace(pos, 4, "block.");
|
||||
}
|
||||
pos = new_name.find("output_norm.");
|
||||
if (pos != std::string::npos) {
|
||||
new_name.replace(pos, 12, "final_layer_norm.");
|
||||
}
|
||||
pos = new_name.find("attn_k.");
|
||||
if (pos != std::string::npos) {
|
||||
new_name.replace(pos, 7, "layer.0.SelfAttention.k.");
|
||||
}
|
||||
pos = new_name.find("attn_v.");
|
||||
if (pos != std::string::npos) {
|
||||
new_name.replace(pos, 7, "layer.0.SelfAttention.v.");
|
||||
}
|
||||
pos = new_name.find("attn_o.");
|
||||
if (pos != std::string::npos) {
|
||||
new_name.replace(pos, 7, "layer.0.SelfAttention.o.");
|
||||
}
|
||||
pos = new_name.find("attn_q.");
|
||||
if (pos != std::string::npos) {
|
||||
new_name.replace(pos, 7, "layer.0.SelfAttention.q.");
|
||||
}
|
||||
pos = new_name.find("attn_norm.");
|
||||
if (pos != std::string::npos) {
|
||||
new_name.replace(pos, 10, "layer.0.layer_norm.");
|
||||
}
|
||||
pos = new_name.find("ffn_norm.");
|
||||
if (pos != std::string::npos) {
|
||||
new_name.replace(pos, 9, "layer.1.layer_norm.");
|
||||
}
|
||||
pos = new_name.find("ffn_up.");
|
||||
if (pos != std::string::npos) {
|
||||
new_name.replace(pos, 7, "layer.1.DenseReluDense.wi_1.");
|
||||
}
|
||||
pos = new_name.find("ffn_down.");
|
||||
if (pos != std::string::npos) {
|
||||
new_name.replace(pos, 9, "layer.1.DenseReluDense.wo.");
|
||||
}
|
||||
pos = new_name.find("ffn_gate.");
|
||||
if (pos != std::string::npos) {
|
||||
new_name.replace(pos, 9, "layer.1.DenseReluDense.wi_0.");
|
||||
}
|
||||
pos = new_name.find("attn_rel_b.");
|
||||
if (pos != std::string::npos) {
|
||||
new_name.replace(pos, 11, "layer.0.SelfAttention.relative_attention_bias.");
|
||||
}
|
||||
} else if (name == "text_encoders.t5xxl.transformer.token_embd.weight") {
|
||||
new_name = "text_encoders.t5xxl.transformer.shared.weight";
|
||||
}
|
||||
|
||||
if (starts_with(new_name, "conditioner.embedders.0.open_clip.")) {
|
||||
prefix = "cond_stage_model.";
|
||||
new_name = new_name.substr(strlen("conditioner.embedders.0.open_clip."));
|
||||
@@ -1481,6 +1540,15 @@ bool ModelLoader::init_from_ckpt_file(const std::string& file_path, const std::s
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ModelLoader::model_is_unet() {
|
||||
for (auto& tensor_storage : tensor_storages) {
|
||||
if (tensor_storage.name.find("model.diffusion_model.input_blocks.") != std::string::npos) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
SDVersion ModelLoader::get_sd_version() {
|
||||
TensorStorage token_embedding_weight, input_block_weight;
|
||||
bool input_block_checked = false;
|
||||
@@ -1783,6 +1851,7 @@ bool ModelLoader::load_tensors(on_new_tensor_cb_t on_new_tensor_cb, ggml_backend
|
||||
};
|
||||
int tensor_count = 0;
|
||||
int64_t t1 = ggml_time_ms();
|
||||
bool partial = false;
|
||||
for (auto& tensor_storage : processed_tensor_storages) {
|
||||
if (tensor_storage.file_index != file_index) {
|
||||
++tensor_count;
|
||||
@@ -1864,15 +1933,21 @@ bool ModelLoader::load_tensors(on_new_tensor_cb_t on_new_tensor_cb, ggml_backend
|
||||
ggml_backend_tensor_set(dst_tensor, convert_buffer.data(), 0, ggml_nbytes(dst_tensor));
|
||||
}
|
||||
}
|
||||
size_t tensor_max = processed_tensor_storages.size();
|
||||
int64_t t2 = ggml_time_ms();
|
||||
pretty_progress(++tensor_count, processed_tensor_storages.size(), (t2 - t1) / 1000.0f);
|
||||
pretty_progress(++tensor_count, tensor_max, (t2 - t1) / 1000.0f);
|
||||
t1 = t2;
|
||||
partial = tensor_count != tensor_max;
|
||||
}
|
||||
|
||||
if (zip != NULL) {
|
||||
zip_close(zip);
|
||||
}
|
||||
|
||||
if (partial) {
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
break;
|
||||
}
|
||||
|
||||
1
model.h
1
model.h
@@ -210,6 +210,7 @@ public:
|
||||
std::map<std::string, enum ggml_type> tensor_storages_types;
|
||||
|
||||
bool init_from_file(const std::string& file_path, const std::string& prefix = "");
|
||||
bool model_is_unet();
|
||||
SDVersion get_sd_version();
|
||||
ggml_type get_sd_wtype();
|
||||
ggml_type get_conditioner_wtype();
|
||||
|
||||
@@ -103,6 +103,9 @@ public:
|
||||
bool vae_tiling = false;
|
||||
bool stacked_id = false;
|
||||
|
||||
bool is_using_v_parameterization = false;
|
||||
bool is_using_edm_v_parameterization = false;
|
||||
|
||||
std::map<std::string, struct ggml_tensor*> tensors;
|
||||
|
||||
std::string lora_model_dir;
|
||||
@@ -210,16 +213,25 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
if (diffusion_model_path.size() > 0) {
|
||||
LOG_INFO("loading diffusion model from '%s'", diffusion_model_path.c_str());
|
||||
if (!model_loader.init_from_file(diffusion_model_path, "model.diffusion_model.")) {
|
||||
LOG_WARN("loading diffusion model from '%s' failed", diffusion_model_path.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
bool is_unet = model_loader.model_is_unet();
|
||||
|
||||
if (clip_l_path.size() > 0) {
|
||||
LOG_INFO("loading clip_l from '%s'", clip_l_path.c_str());
|
||||
if (!model_loader.init_from_file(clip_l_path, "text_encoders.clip_l.transformer.")) {
|
||||
if (!model_loader.init_from_file(clip_l_path, is_unet ? "cond_stage_model.transformer." : "text_encoders.clip_l.transformer.")) {
|
||||
LOG_WARN("loading clip_l from '%s' failed", clip_l_path.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (clip_g_path.size() > 0) {
|
||||
LOG_INFO("loading clip_g from '%s'", clip_g_path.c_str());
|
||||
if (!model_loader.init_from_file(clip_g_path, "text_encoders.clip_g.transformer.")) {
|
||||
if (!model_loader.init_from_file(clip_g_path, is_unet ? "cond_stage_model.1.transformer." : "text_encoders.clip_g.transformer.")) {
|
||||
LOG_WARN("loading clip_g from '%s' failed", clip_g_path.c_str());
|
||||
}
|
||||
}
|
||||
@@ -231,13 +243,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
if (diffusion_model_path.size() > 0) {
|
||||
LOG_INFO("loading diffusion model from '%s'", diffusion_model_path.c_str());
|
||||
if (!model_loader.init_from_file(diffusion_model_path, "model.diffusion_model.")) {
|
||||
LOG_WARN("loading diffusion model from '%s' failed", diffusion_model_path.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (vae_path.size() > 0) {
|
||||
LOG_INFO("loading vae from '%s'", vae_path.c_str());
|
||||
if (!model_loader.init_from_file(vae_path, "vae.")) {
|
||||
@@ -543,12 +548,17 @@ public:
|
||||
LOG_INFO("loading model from '%s' completed, taking %.2fs", model_path.c_str(), (t1 - t0) * 1.0f / 1000);
|
||||
|
||||
// check is_using_v_parameterization_for_sd2
|
||||
bool is_using_v_parameterization = false;
|
||||
|
||||
if (sd_version_is_sd2(version)) {
|
||||
if (is_using_v_parameterization_for_sd2(ctx, sd_version_is_inpaint(version))) {
|
||||
is_using_v_parameterization = true;
|
||||
}
|
||||
} else if (sd_version_is_sdxl(version)) {
|
||||
if (model_loader.tensor_storages_types.find("edm_vpred.sigma_max") != model_loader.tensor_storages_types.end()) {
|
||||
// CosXL models
|
||||
// TODO: get sigma_min and sigma_max values from file
|
||||
is_using_edm_v_parameterization = true;
|
||||
}
|
||||
if (model_loader.tensor_storages_types.find("v_pred") != model_loader.tensor_storages_types.end()) {
|
||||
is_using_v_parameterization = true;
|
||||
}
|
||||
@@ -573,6 +583,9 @@ public:
|
||||
} else if (is_using_v_parameterization) {
|
||||
LOG_INFO("running in v-prediction mode");
|
||||
denoiser = std::make_shared<CompVisVDenoiser>();
|
||||
} else if (is_using_edm_v_parameterization) {
|
||||
LOG_INFO("running in v-prediction EDM mode");
|
||||
denoiser = std::make_shared<EDMVDenoiser>();
|
||||
} else {
|
||||
LOG_INFO("running in eps-prediction mode");
|
||||
}
|
||||
@@ -1396,7 +1409,7 @@ sd_image_t* generate_image(sd_ctx_t* sd_ctx,
|
||||
SDCondition uncond;
|
||||
if (cfg_scale != 1.0) {
|
||||
bool force_zero_embeddings = false;
|
||||
if (sd_version_is_sdxl(sd_ctx->sd->version) && negative_prompt.size() == 0) {
|
||||
if (sd_version_is_sdxl(sd_ctx->sd->version) && negative_prompt.size() == 0 && !sd_ctx->sd->is_using_edm_v_parameterization) {
|
||||
force_zero_embeddings = true;
|
||||
}
|
||||
uncond = sd_ctx->sd->cond_stage_model->get_learned_condition(work_ctx,
|
||||
@@ -1555,6 +1568,29 @@ sd_image_t* generate_image(sd_ctx_t* sd_ctx,
|
||||
return result_images;
|
||||
}
|
||||
|
||||
ggml_tensor* generate_init_latent(sd_ctx_t* sd_ctx,
|
||||
ggml_context* work_ctx,
|
||||
int width,
|
||||
int height) {
|
||||
int C = 4;
|
||||
if (sd_version_is_sd3(sd_ctx->sd->version)) {
|
||||
C = 16;
|
||||
} else if (sd_version_is_flux(sd_ctx->sd->version)) {
|
||||
C = 16;
|
||||
}
|
||||
int W = width / 8;
|
||||
int H = height / 8;
|
||||
ggml_tensor* init_latent = ggml_new_tensor_4d(work_ctx, GGML_TYPE_F32, W, H, C, 1);
|
||||
if (sd_version_is_sd3(sd_ctx->sd->version)) {
|
||||
ggml_set_f32(init_latent, 0.0609f);
|
||||
} else if (sd_version_is_flux(sd_ctx->sd->version)) {
|
||||
ggml_set_f32(init_latent, 0.1159f);
|
||||
} else {
|
||||
ggml_set_f32(init_latent, 0.f);
|
||||
}
|
||||
return init_latent;
|
||||
}
|
||||
|
||||
sd_image_t* txt2img(sd_ctx_t* sd_ctx,
|
||||
const char* prompt_c_str,
|
||||
const char* negative_prompt_c_str,
|
||||
@@ -1611,27 +1647,12 @@ sd_image_t* txt2img(sd_ctx_t* sd_ctx,
|
||||
|
||||
std::vector<float> sigmas = sd_ctx->sd->denoiser->get_sigmas(sample_steps);
|
||||
|
||||
int C = 4;
|
||||
if (sd_version_is_sd3(sd_ctx->sd->version)) {
|
||||
C = 16;
|
||||
} else if (sd_version_is_flux(sd_ctx->sd->version)) {
|
||||
C = 16;
|
||||
}
|
||||
int W = width / 8;
|
||||
int H = height / 8;
|
||||
ggml_tensor* init_latent = ggml_new_tensor_4d(work_ctx, GGML_TYPE_F32, W, H, C, 1);
|
||||
if (sd_version_is_sd3(sd_ctx->sd->version)) {
|
||||
ggml_set_f32(init_latent, 0.0609f);
|
||||
} else if (sd_version_is_flux(sd_ctx->sd->version)) {
|
||||
ggml_set_f32(init_latent, 0.1159f);
|
||||
} else {
|
||||
ggml_set_f32(init_latent, 0.f);
|
||||
}
|
||||
|
||||
if (sd_version_is_inpaint(sd_ctx->sd->version)) {
|
||||
LOG_WARN("This is an inpainting model, this should only be used in img2img mode with a mask");
|
||||
}
|
||||
|
||||
ggml_tensor* init_latent = generate_init_latent(sd_ctx, work_ctx, width, height);
|
||||
|
||||
sd_image_t* result_images = generate_image(sd_ctx,
|
||||
work_ctx,
|
||||
init_latent,
|
||||
@@ -2035,23 +2056,6 @@ sd_image_t* edit(sd_ctx_t* sd_ctx,
|
||||
}
|
||||
sd_ctx->sd->rng->manual_seed(seed);
|
||||
|
||||
int C = 4;
|
||||
if (sd_version_is_sd3(sd_ctx->sd->version)) {
|
||||
C = 16;
|
||||
} else if (sd_version_is_flux(sd_ctx->sd->version)) {
|
||||
C = 16;
|
||||
}
|
||||
int W = width / 8;
|
||||
int H = height / 8;
|
||||
ggml_tensor* init_latent = ggml_new_tensor_4d(work_ctx, GGML_TYPE_F32, W, H, C, 1);
|
||||
if (sd_version_is_sd3(sd_ctx->sd->version)) {
|
||||
ggml_set_f32(init_latent, 0.0609f);
|
||||
} else if (sd_version_is_flux(sd_ctx->sd->version)) {
|
||||
ggml_set_f32(init_latent, 0.1159f);
|
||||
} else {
|
||||
ggml_set_f32(init_latent, 0.f);
|
||||
}
|
||||
|
||||
size_t t0 = ggml_time_ms();
|
||||
|
||||
std::vector<struct ggml_tensor*> ref_latents;
|
||||
@@ -2074,6 +2078,8 @@ sd_image_t* edit(sd_ctx_t* sd_ctx,
|
||||
|
||||
std::vector<float> sigmas = sd_ctx->sd->denoiser->get_sigmas(sample_steps);
|
||||
|
||||
ggml_tensor* init_latent = generate_init_latent(sd_ctx, work_ctx, width, height);
|
||||
|
||||
sd_image_t* result_images = generate_image(sd_ctx,
|
||||
work_ctx,
|
||||
init_latent,
|
||||
|
||||
Reference in New Issue
Block a user