mirror of
https://github.com/leejet/stable-diffusion.cpp.git
synced 2026-07-23 19:30:54 -05:00
Compare commits
13 Commits
master-76c
...
master-bd1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bd1eaef93e | ||
|
|
ab835f7d39 | ||
|
|
26f3f61d37 | ||
|
|
1896b28ef2 | ||
|
|
0739361bfe | ||
|
|
ca0bd9396e | ||
|
|
a772dca27a | ||
|
|
6d84a30c66 | ||
|
|
dafc32d0dd | ||
|
|
225162f270 | ||
|
|
b9e4718fac | ||
|
|
1ce1c1adca | ||
|
|
19fbfd8639 |
15
README.md
15
README.md
@@ -282,14 +282,14 @@ usage: ./bin/sd [arguments]
|
||||
|
||||
arguments:
|
||||
-h, --help show this help message and exit
|
||||
-M, --mode [MODEL] run mode (txt2img or img2img or convert, default: txt2img)
|
||||
-M, --mode [MODE] run mode, one of: [img_gen, convert], default: img_gen
|
||||
-t, --threads N number of threads to use during computation (default: -1)
|
||||
If threads <= 0, then threads will be set to the number of CPU physical cores
|
||||
-m, --model [MODEL] path to full model
|
||||
--diffusion-model path to the standalone diffusion model
|
||||
--clip_l path to the clip-l text encoder
|
||||
--clip_g path to the clip-g text encoder
|
||||
--t5xxl path to the the t5xxl text encoder
|
||||
--t5xxl path to the t5xxl text encoder
|
||||
--vae [VAE] path to vae
|
||||
--taesd [TAESD_PATH] path to taesd. Using Tiny AutoEncoder for fast decoding (low quality)
|
||||
--control-net [CONTROL_PATH] path to control net model
|
||||
@@ -301,16 +301,18 @@ arguments:
|
||||
--upscale-repeats Run the ESRGAN upscaler this many times (default 1)
|
||||
--type [TYPE] weight type (examples: f32, f16, q4_0, q4_1, q5_0, q5_1, q8_0, q2_K, q3_K, q4_K)
|
||||
If not specified, the default is the type of the weight file
|
||||
--tensor-type-rules [EXPRESSION] weight type per tensor pattern (example: "^vae\.=f16,model\.=q8_0")
|
||||
--lora-model-dir [DIR] lora model directory
|
||||
-i, --init-img [IMAGE] path to the input image, required by img2img
|
||||
--mask [MASK] path to the mask image, required by img2img with mask
|
||||
--control-image [IMAGE] path to image condition, control net
|
||||
-r, --ref_image [PATH] reference image for Flux Kontext models (can be used multiple times)
|
||||
-r, --ref-image [PATH] reference image for Flux Kontext models (can be used multiple times)
|
||||
-o, --output OUTPUT path to write result image to (default: ./output.png)
|
||||
-p, --prompt [PROMPT] the prompt to render
|
||||
-n, --negative-prompt PROMPT the negative prompt (default: "")
|
||||
--cfg-scale SCALE unconditional guidance scale: (default: 7.0)
|
||||
--guidance SCALE guidance scale for img2img (default: 3.5)
|
||||
--img-cfg-scale SCALE image guidance scale for inpaint or instruct-pix2pix models: (default: same as --cfg-scale)
|
||||
--guidance SCALE distilled guidance scale for models with guidance input (default: 3.5)
|
||||
--slg-scale SCALE skip layer guidance (SLG) scale, only for DiT models: (default: 0)
|
||||
0 means disabled, a value of 2.5 is nice for sd3.5 medium
|
||||
--eta SCALE eta in DDIM, only for DDIM and TCD: (default: 0)
|
||||
@@ -319,7 +321,7 @@ arguments:
|
||||
--skip-layer-end END SLG disabling point: (default: 0.2)
|
||||
SLG will be enabled at step int([STEPS]*[START]) and disabled at int([STEPS]*[END])
|
||||
--strength STRENGTH strength for noising/unnoising (default: 0.75)
|
||||
--style-ratio STYLE-RATIO strength for keeping input identity (default: 20%)
|
||||
--style-ratio STYLE-RATIO strength for keeping input identity (default: 20)
|
||||
--control-strength STRENGTH strength to apply Control Net (default: 0.9)
|
||||
1.0 corresponds to full destruction of information in init image
|
||||
-H, --height H image height, in pixel space (default: 512)
|
||||
@@ -371,7 +373,7 @@ Using formats of different precisions will yield results of varying quality.
|
||||
|
||||
|
||||
```
|
||||
./bin/sd --mode img2img -m ../models/sd-v1-4.ckpt -p "cat with blue eyes" -i ./output.png -o ./img2img_output.png --strength 0.4
|
||||
./bin/sd -m ../models/sd-v1-4.ckpt -p "cat with blue eyes" -i ./output.png -o ./img2img_output.png --strength 0.4
|
||||
```
|
||||
|
||||
<p align="center">
|
||||
@@ -407,6 +409,7 @@ These projects use `stable-diffusion.cpp` as a backend for their image generatio
|
||||
- [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)
|
||||
- [sd.cpp-webui](https://github.com/daniandtheweb/sd.cpp-webui)
|
||||
|
||||
## Contributors
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ You can download the preconverted gguf weights from [FLUX.1-Kontext-dev-GGUF](ht
|
||||
For example:
|
||||
|
||||
```
|
||||
.\bin\Release\sd.exe -M edit -r .\flux1-dev-q8_0.png --diffusion-model ..\models\flux1-kontext-dev-q8_0.gguf --vae ..\models\ae.sft --clip_l ..\models\clip_l.safetensors --t5xxl ..\models\t5xxl_fp16.safetensors -p "change 'flux.cpp' to 'kontext.cpp'" --cfg-scale 1.0 --sampling-method euler -v
|
||||
.\bin\Release\sd.exe -r .\flux1-dev-q8_0.png --diffusion-model ..\models\flux1-kontext-dev-q8_0.gguf --vae ..\models\ae.sft --clip_l ..\models\clip_l.safetensors --t5xxl ..\models\t5xxl_fp16.safetensors -p "change 'flux.cpp' to 'kontext.cpp'" --cfg-scale 1.0 --sampling-method euler -v
|
||||
```
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -840,18 +840,34 @@ __STATIC_INLINE__ struct ggml_tensor* ggml_nn_attention_ext(struct ggml_context*
|
||||
|
||||
float scale = (1.0f / sqrt((float)d_head));
|
||||
|
||||
// if (flash_attn) {
|
||||
// LOG_DEBUG("attention_ext L_q:%d L_k:%d n_head:%d C:%d d_head:%d N:%d", L_q, L_k, n_head, C, d_head, N);
|
||||
// }
|
||||
int kv_pad = 0;
|
||||
//if (flash_attn) {
|
||||
// LOG_DEBUG("attention_ext L_q:%d L_k:%d n_head:%d C:%d d_head:%d N:%d", L_q, L_k, n_head, C, d_head, N);
|
||||
//}
|
||||
// is there anything oddly shaped?? ping Green-Sky if you can trip this assert
|
||||
GGML_ASSERT(((L_k % 256 == 0) && L_q == L_k) || !(L_k % 256 == 0));
|
||||
|
||||
bool can_use_flash_attn = true;
|
||||
can_use_flash_attn = can_use_flash_attn && (
|
||||
d_head == 64 ||
|
||||
d_head == 80 ||
|
||||
d_head == 96 ||
|
||||
d_head == 112 ||
|
||||
d_head == 128 ||
|
||||
d_head == 256
|
||||
);
|
||||
#if 0
|
||||
can_use_flash_attn = can_use_flash_attn && L_k % 256 == 0;
|
||||
can_use_flash_attn = can_use_flash_attn && d_head % 64 == 0; // double check
|
||||
|
||||
// cuda max d_head seems to be 256, cpu does seem to work with 512
|
||||
can_use_flash_attn = can_use_flash_attn && d_head <= 256; // double check
|
||||
#else
|
||||
if (can_use_flash_attn && L_k % 256 != 0) {
|
||||
// TODO(Green-Sky): might be worth just padding by default
|
||||
if (L_k == 77 || L_k == 4208 || L_k == 3952) {
|
||||
kv_pad = GGML_PAD(L_k, 256) - L_k;
|
||||
} else {
|
||||
can_use_flash_attn = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mask != nullptr) {
|
||||
// TODO(Green-Sky): figure out if we can bend t5 to work too
|
||||
@@ -864,11 +880,18 @@ __STATIC_INLINE__ struct ggml_tensor* ggml_nn_attention_ext(struct ggml_context*
|
||||
ggml_tensor* kqv = nullptr;
|
||||
// GGML_ASSERT((flash_attn && can_use_flash_attn) || !flash_attn);
|
||||
if (can_use_flash_attn && flash_attn) {
|
||||
// LOG_DEBUG("using flash attention");
|
||||
//LOG_DEBUG(" uses flash attention");
|
||||
if (kv_pad != 0) {
|
||||
//LOG_DEBUG(" padding k and v dim1 by %d", kv_pad);
|
||||
k = ggml_pad(ctx, k, 0, kv_pad, 0, 0);
|
||||
}
|
||||
k = ggml_cast(ctx, k, GGML_TYPE_F16);
|
||||
|
||||
v = ggml_cont(ctx, ggml_permute(ctx, v, 0, 2, 1, 3)); // [N, n_head, L_k, d_head]
|
||||
v = ggml_reshape_3d(ctx, v, d_head, L_k, n_head * N); // [N * n_head, L_k, d_head]
|
||||
if (kv_pad != 0) {
|
||||
v = ggml_pad(ctx, v, 0, kv_pad, 0, 0);
|
||||
}
|
||||
v = ggml_cast(ctx, v, GGML_TYPE_F16);
|
||||
|
||||
if (mask != nullptr) {
|
||||
|
||||
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());
|
||||
|
||||
211
model.cpp
211
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) {
|
||||
@@ -337,6 +338,10 @@ std::unordered_map<std::string, std::unordered_map<std::string, std::string>> su
|
||||
{"to_v", "v"},
|
||||
{"to_out_0", "proj_out"},
|
||||
{"group_norm", "norm"},
|
||||
{"key", "k"},
|
||||
{"query", "q"},
|
||||
{"value", "v"},
|
||||
{"proj_attn", "proj_out"},
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -361,6 +366,10 @@ std::unordered_map<std::string, std::unordered_map<std::string, std::string>> su
|
||||
{"to_v", "v"},
|
||||
{"to_out.0", "proj_out"},
|
||||
{"group_norm", "norm"},
|
||||
{"key", "k"},
|
||||
{"query", "q"},
|
||||
{"value", "v"},
|
||||
{"proj_attn", "proj_out"},
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -432,6 +441,10 @@ std::string convert_diffusers_name_to_compvis(std::string key, char seq) {
|
||||
return format("model%cdiffusion_model%ctime_embed%c", seq, seq, seq) + std::to_string(std::stoi(m[0]) * 2 - 2) + m[1];
|
||||
}
|
||||
|
||||
if (match(m, std::regex(format("unet%cadd_embedding%clinear_(\\d+)(.*)", seq, seq)), key)) {
|
||||
return format("model%cdiffusion_model%clabel_emb%c0%c", seq, seq, seq, seq) + std::to_string(std::stoi(m[0]) * 2 - 2) + m[1];
|
||||
}
|
||||
|
||||
if (match(m, std::regex(format("unet%cdown_blocks%c(\\d+)%c(attentions|resnets)%c(\\d+)%c(.+)", seq, seq, seq, seq, seq)), key)) {
|
||||
std::string suffix = get_converted_suffix(m[1], m[3]);
|
||||
// LOG_DEBUG("%s %s %s %s", m[0].c_str(), m[1].c_str(), m[2].c_str(), m[3].c_str());
|
||||
@@ -469,6 +482,19 @@ std::string convert_diffusers_name_to_compvis(std::string key, char seq) {
|
||||
return format("cond_stage_model%ctransformer%ctext_model", seq, seq) + m[0];
|
||||
}
|
||||
|
||||
// clip-g
|
||||
if (match(m, std::regex(format("te%c1%ctext_model%cencoder%clayers%c(\\d+)%c(.+)", seq, seq, seq, seq, seq, seq)), key)) {
|
||||
return format("cond_stage_model%c1%ctransformer%ctext_model%cencoder%clayers%c", seq, seq, seq, seq, seq, seq) + m[0] + seq + m[1];
|
||||
}
|
||||
|
||||
if (match(m, std::regex(format("te%c1%ctext_model(.*)", seq, seq)), key)) {
|
||||
return format("cond_stage_model%c1%ctransformer%ctext_model", seq, seq, seq) + m[0];
|
||||
}
|
||||
|
||||
if (match(m, std::regex(format("te%c1%ctext_projection", seq, seq)), key)) {
|
||||
return format("cond_stage_model%c1%ctransformer%ctext_model%ctext_projection", seq, seq, seq, seq);
|
||||
}
|
||||
|
||||
// vae
|
||||
if (match(m, std::regex(format("vae%c(.*)%cconv_norm_out(.*)", seq, seq)), key)) {
|
||||
return format("first_stage_model%c%s%cnorm_out%s", seq, m[0].c_str(), seq, m[1].c_str());
|
||||
@@ -605,6 +631,8 @@ std::string convert_tensor_name(std::string name) {
|
||||
std::string new_key = convert_diffusers_name_to_compvis(name_without_network_parts, '.');
|
||||
if (new_key.empty()) {
|
||||
new_name = name;
|
||||
} else if (new_key == "cond_stage_model.1.transformer.text_model.text_projection") {
|
||||
new_name = new_key;
|
||||
} else {
|
||||
new_name = new_key + "." + network_part;
|
||||
}
|
||||
@@ -787,6 +815,7 @@ void f8_e4m3_to_f16_vec(uint8_t* src, uint16_t* dst, int64_t n) {
|
||||
dst[i] = f8_e4m3_to_f16(src[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void f8_e5m2_to_f16_vec(uint8_t* src, uint16_t* dst, int64_t n) {
|
||||
// support inplace op
|
||||
for (int64_t i = n - 1; i >= 0; i--) {
|
||||
@@ -794,6 +823,20 @@ void f8_e5m2_to_f16_vec(uint8_t* src, uint16_t* dst, int64_t n) {
|
||||
}
|
||||
}
|
||||
|
||||
void f64_to_f32_vec(double* src, float* dst, int64_t n) {
|
||||
// support inplace op
|
||||
for (int64_t i = 0; i < n; i++) {
|
||||
dst[i] = (float)src[i];
|
||||
}
|
||||
}
|
||||
|
||||
void i64_to_i32_vec(int64_t* src, int32_t* dst, int64_t n) {
|
||||
// support inplace op
|
||||
for (int64_t i = 0; i < n; i++) {
|
||||
dst[i] = (int32_t)src[i];
|
||||
}
|
||||
}
|
||||
|
||||
void convert_tensor(void* src,
|
||||
ggml_type src_type,
|
||||
void* dst,
|
||||
@@ -1028,10 +1071,14 @@ ggml_type str_to_ggml_type(const std::string& dtype) {
|
||||
ttype = GGML_TYPE_F32;
|
||||
} else if (dtype == "F32") {
|
||||
ttype = GGML_TYPE_F32;
|
||||
} else if (dtype == "F64") {
|
||||
ttype = GGML_TYPE_F32;
|
||||
} else if (dtype == "F8_E4M3") {
|
||||
ttype = GGML_TYPE_F16;
|
||||
} else if (dtype == "F8_E5M2") {
|
||||
ttype = GGML_TYPE_F16;
|
||||
} else if (dtype == "I64") {
|
||||
ttype = GGML_TYPE_I32;
|
||||
}
|
||||
return ttype;
|
||||
}
|
||||
@@ -1044,6 +1091,7 @@ bool ModelLoader::init_from_safetensors_file(const std::string& file_path, const
|
||||
std::ifstream file(file_path, std::ios::binary);
|
||||
if (!file.is_open()) {
|
||||
LOG_ERROR("failed to open '%s'", file_path.c_str());
|
||||
file_paths_.pop_back();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1055,6 +1103,7 @@ bool ModelLoader::init_from_safetensors_file(const std::string& file_path, const
|
||||
// read header size
|
||||
if (file_size_ <= ST_HEADER_SIZE_LEN) {
|
||||
LOG_ERROR("invalid safetensor file '%s'", file_path.c_str());
|
||||
file_paths_.pop_back();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1068,6 +1117,7 @@ bool ModelLoader::init_from_safetensors_file(const std::string& file_path, const
|
||||
size_t header_size_ = read_u64(header_size_buf);
|
||||
if (header_size_ >= file_size_) {
|
||||
LOG_ERROR("invalid safetensor file '%s'", file_path.c_str());
|
||||
file_paths_.pop_back();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1078,6 +1128,7 @@ bool ModelLoader::init_from_safetensors_file(const std::string& file_path, const
|
||||
file.read(header_buf.data(), header_size_);
|
||||
if (!file) {
|
||||
LOG_ERROR("read safetensors header failed: '%s'", file_path.c_str());
|
||||
file_paths_.pop_back();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1149,6 +1200,14 @@ bool ModelLoader::init_from_safetensors_file(const std::string& file_path, const
|
||||
tensor_storage.is_f8_e5m2 = true;
|
||||
// f8 -> f16
|
||||
GGML_ASSERT(tensor_storage.nbytes() == tensor_data_size * 2);
|
||||
} else if (dtype == "F64") {
|
||||
tensor_storage.is_f64 = true;
|
||||
// f64 -> f32
|
||||
GGML_ASSERT(tensor_storage.nbytes() * 2 == tensor_data_size);
|
||||
} else if (dtype == "I64") {
|
||||
tensor_storage.is_i64 = true;
|
||||
// i64 -> i32
|
||||
GGML_ASSERT(tensor_storage.nbytes() * 2 == tensor_data_size);
|
||||
} else {
|
||||
GGML_ASSERT(tensor_storage.nbytes() == tensor_data_size);
|
||||
}
|
||||
@@ -1165,18 +1224,45 @@ bool ModelLoader::init_from_safetensors_file(const std::string& file_path, const
|
||||
/*================================================= DiffusersModelLoader ==================================================*/
|
||||
|
||||
bool ModelLoader::init_from_diffusers_file(const std::string& file_path, const std::string& prefix) {
|
||||
std::string unet_path = path_join(file_path, "unet/diffusion_pytorch_model.safetensors");
|
||||
std::string vae_path = path_join(file_path, "vae/diffusion_pytorch_model.safetensors");
|
||||
std::string clip_path = path_join(file_path, "text_encoder/model.safetensors");
|
||||
std::string unet_path = path_join(file_path, "unet/diffusion_pytorch_model.safetensors");
|
||||
std::string vae_path = path_join(file_path, "vae/diffusion_pytorch_model.safetensors");
|
||||
std::string clip_path = path_join(file_path, "text_encoder/model.safetensors");
|
||||
std::string clip_g_path = path_join(file_path, "text_encoder_2/model.safetensors");
|
||||
|
||||
if (!init_from_safetensors_file(unet_path, "unet.")) {
|
||||
return false;
|
||||
}
|
||||
for (auto ts : tensor_storages) {
|
||||
if (ts.name.find("add_embedding") != std::string::npos || ts.name.find("label_emb") != std::string::npos) {
|
||||
// probably SDXL
|
||||
LOG_DEBUG("Fixing name for SDXL output blocks.2.2");
|
||||
for (auto& tensor_storage : tensor_storages) {
|
||||
int len = 34;
|
||||
auto pos = tensor_storage.name.find("unet.up_blocks.0.upsamplers.0.conv");
|
||||
if (pos == std::string::npos) {
|
||||
len = 44;
|
||||
pos = tensor_storage.name.find("model.diffusion_model.output_blocks.2.1.conv");
|
||||
}
|
||||
if (pos != std::string::npos) {
|
||||
tensor_storage.name = "model.diffusion_model.output_blocks.2.2.conv" + tensor_storage.name.substr(len);
|
||||
LOG_DEBUG("NEW NAME: %s", tensor_storage.name.c_str());
|
||||
add_preprocess_tensor_storage_types(tensor_storages_types, tensor_storage.name, tensor_storage.type);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!init_from_safetensors_file(vae_path, "vae.")) {
|
||||
return false;
|
||||
LOG_WARN("Couldn't find working VAE in %s", file_path.c_str());
|
||||
// return false;
|
||||
}
|
||||
if (!init_from_safetensors_file(clip_path, "te.")) {
|
||||
return false;
|
||||
LOG_WARN("Couldn't find working text encoder in %s", file_path.c_str());
|
||||
// return false;
|
||||
}
|
||||
if (!init_from_safetensors_file(clip_g_path, "te.1.")) {
|
||||
LOG_DEBUG("Couldn't find working second text encoder in %s", file_path.c_str());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1539,6 +1625,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;
|
||||
@@ -1561,7 +1656,7 @@ SDVersion ModelLoader::get_sd_version() {
|
||||
if (tensor_storage.name.find("model.diffusion_model.joint_blocks.") != std::string::npos) {
|
||||
return VERSION_SD3;
|
||||
}
|
||||
if (tensor_storage.name.find("model.diffusion_model.input_blocks.") != std::string::npos) {
|
||||
if (tensor_storage.name.find("model.diffusion_model.input_blocks.") != std::string::npos || tensor_storage.name.find("unet.down_blocks.") != std::string::npos) {
|
||||
is_unet = true;
|
||||
if (has_multiple_encoders) {
|
||||
is_xl = true;
|
||||
@@ -1570,7 +1665,7 @@ SDVersion ModelLoader::get_sd_version() {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tensor_storage.name.find("conditioner.embedders.1") != std::string::npos || tensor_storage.name.find("cond_stage_model.1") != std::string::npos) {
|
||||
if (tensor_storage.name.find("conditioner.embedders.1") != std::string::npos || tensor_storage.name.find("cond_stage_model.1") != std::string::npos || tensor_storage.name.find("te.1") != std::string::npos) {
|
||||
has_multiple_encoders = true;
|
||||
if (is_unet) {
|
||||
is_xl = true;
|
||||
@@ -1592,7 +1687,7 @@ SDVersion ModelLoader::get_sd_version() {
|
||||
token_embedding_weight = tensor_storage;
|
||||
// break;
|
||||
}
|
||||
if (tensor_storage.name == "model.diffusion_model.input_blocks.0.0.weight" || tensor_storage.name == "model.diffusion_model.img_in.weight") {
|
||||
if (tensor_storage.name == "model.diffusion_model.input_blocks.0.0.weight" || tensor_storage.name == "model.diffusion_model.img_in.weight" || tensor_storage.name == "unet.conv_in.weight") {
|
||||
input_block_weight = tensor_storage;
|
||||
input_block_checked = true;
|
||||
if (found_family) {
|
||||
@@ -1601,10 +1696,14 @@ SDVersion ModelLoader::get_sd_version() {
|
||||
}
|
||||
}
|
||||
bool is_inpaint = input_block_weight.ne[2] == 9;
|
||||
bool is_ip2p = input_block_weight.ne[2] == 8;
|
||||
if (is_xl) {
|
||||
if (is_inpaint) {
|
||||
return VERSION_SDXL_INPAINT;
|
||||
}
|
||||
if (is_ip2p) {
|
||||
return VERSION_SDXL_PIX2PIX;
|
||||
}
|
||||
return VERSION_SDXL;
|
||||
}
|
||||
|
||||
@@ -1620,6 +1719,9 @@ SDVersion ModelLoader::get_sd_version() {
|
||||
if (is_inpaint) {
|
||||
return VERSION_SD1_INPAINT;
|
||||
}
|
||||
if (is_ip2p) {
|
||||
return VERSION_SD1_PIX2PIX;
|
||||
}
|
||||
return VERSION_SD1;
|
||||
} else if (token_embedding_weight.ne[0] == 1024) {
|
||||
if (is_inpaint) {
|
||||
@@ -1677,7 +1779,7 @@ ggml_type ModelLoader::get_diffusion_model_wtype() {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tensor_storage.name.find("model.diffusion_model.") == std::string::npos) {
|
||||
if (tensor_storage.name.find("model.diffusion_model.") == std::string::npos && tensor_storage.name.find("unet.") == std::string::npos) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1841,7 +1943,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;
|
||||
bool partial = false;
|
||||
for (auto& tensor_storage : processed_tensor_storages) {
|
||||
if (tensor_storage.file_index != file_index) {
|
||||
++tensor_count;
|
||||
@@ -1866,7 +1968,12 @@ bool ModelLoader::load_tensors(on_new_tensor_cb_t on_new_tensor_cb, ggml_backend
|
||||
// for the CPU and Metal backend, we can copy directly into the tensor
|
||||
if (tensor_storage.type == dst_tensor->type) {
|
||||
GGML_ASSERT(ggml_nbytes(dst_tensor) == tensor_storage.nbytes());
|
||||
read_data(tensor_storage, (char*)dst_tensor->data, nbytes_to_read);
|
||||
if (tensor_storage.is_f64 || tensor_storage.is_i64) {
|
||||
read_buffer.resize(tensor_storage.nbytes_to_read());
|
||||
read_data(tensor_storage, (char*)read_buffer.data(), nbytes_to_read);
|
||||
} else {
|
||||
read_data(tensor_storage, (char*)dst_tensor->data, nbytes_to_read);
|
||||
}
|
||||
|
||||
if (tensor_storage.is_bf16) {
|
||||
// inplace op
|
||||
@@ -1877,9 +1984,13 @@ bool ModelLoader::load_tensors(on_new_tensor_cb_t on_new_tensor_cb, ggml_backend
|
||||
} else if (tensor_storage.is_f8_e5m2) {
|
||||
// inplace op
|
||||
f8_e5m2_to_f16_vec((uint8_t*)dst_tensor->data, (uint16_t*)dst_tensor->data, tensor_storage.nelements());
|
||||
} else if (tensor_storage.is_f64) {
|
||||
f64_to_f32_vec((double*)read_buffer.data(), (float*)dst_tensor->data, tensor_storage.nelements());
|
||||
} else if (tensor_storage.is_i64) {
|
||||
i64_to_i32_vec((int64_t*)read_buffer.data(), (int32_t*)dst_tensor->data, tensor_storage.nelements());
|
||||
}
|
||||
} else {
|
||||
read_buffer.resize(tensor_storage.nbytes());
|
||||
read_buffer.resize(std::max(tensor_storage.nbytes(), tensor_storage.nbytes_to_read()));
|
||||
read_data(tensor_storage, (char*)read_buffer.data(), nbytes_to_read);
|
||||
|
||||
if (tensor_storage.is_bf16) {
|
||||
@@ -1891,13 +2002,19 @@ bool ModelLoader::load_tensors(on_new_tensor_cb_t on_new_tensor_cb, ggml_backend
|
||||
} else if (tensor_storage.is_f8_e5m2) {
|
||||
// inplace op
|
||||
f8_e5m2_to_f16_vec((uint8_t*)read_buffer.data(), (uint16_t*)read_buffer.data(), tensor_storage.nelements());
|
||||
} else if (tensor_storage.is_f64) {
|
||||
// inplace op
|
||||
f64_to_f32_vec((double*)read_buffer.data(), (float*)read_buffer.data(), tensor_storage.nelements());
|
||||
} else if (tensor_storage.is_i64) {
|
||||
// inplace op
|
||||
i64_to_i32_vec((int64_t*)read_buffer.data(), (int32_t*)read_buffer.data(), tensor_storage.nelements());
|
||||
}
|
||||
|
||||
convert_tensor((void*)read_buffer.data(), tensor_storage.type, dst_tensor->data,
|
||||
dst_tensor->type, (int)tensor_storage.nelements() / (int)tensor_storage.ne[0], (int)tensor_storage.ne[0]);
|
||||
}
|
||||
} else {
|
||||
read_buffer.resize(tensor_storage.nbytes());
|
||||
read_buffer.resize(std::max(tensor_storage.nbytes(), tensor_storage.nbytes_to_read()));
|
||||
read_data(tensor_storage, (char*)read_buffer.data(), nbytes_to_read);
|
||||
|
||||
if (tensor_storage.is_bf16) {
|
||||
@@ -1909,6 +2026,12 @@ bool ModelLoader::load_tensors(on_new_tensor_cb_t on_new_tensor_cb, ggml_backend
|
||||
} else if (tensor_storage.is_f8_e5m2) {
|
||||
// inplace op
|
||||
f8_e5m2_to_f16_vec((uint8_t*)read_buffer.data(), (uint16_t*)read_buffer.data(), tensor_storage.nelements());
|
||||
} else if (tensor_storage.is_f64) {
|
||||
// inplace op
|
||||
f64_to_f32_vec((double*)read_buffer.data(), (float*)read_buffer.data(), tensor_storage.nelements());
|
||||
} else if (tensor_storage.is_i64) {
|
||||
// inplace op
|
||||
i64_to_i32_vec((int64_t*)read_buffer.data(), (int32_t*)read_buffer.data(), tensor_storage.nelements());
|
||||
}
|
||||
|
||||
if (tensor_storage.type == dst_tensor->type) {
|
||||
@@ -1924,9 +2047,9 @@ bool ModelLoader::load_tensors(on_new_tensor_cb_t on_new_tensor_cb, ggml_backend
|
||||
}
|
||||
}
|
||||
size_t tensor_max = processed_tensor_storages.size();
|
||||
int64_t t2 = ggml_time_ms();
|
||||
int64_t t2 = ggml_time_ms();
|
||||
pretty_progress(++tensor_count, tensor_max, (t2 - t1) / 1000.0f);
|
||||
t1 = t2;
|
||||
t1 = t2;
|
||||
partial = tensor_count != tensor_max;
|
||||
}
|
||||
|
||||
@@ -2015,6 +2138,41 @@ bool ModelLoader::load_tensors(std::map<std::string, struct ggml_tensor*>& tenso
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<std::pair<std::string, ggml_type>> parse_tensor_type_rules(const std::string& tensor_type_rules) {
|
||||
std::vector<std::pair<std::string, ggml_type>> result;
|
||||
for (const auto& item : splitString(tensor_type_rules, ',')) {
|
||||
if (item.size() == 0)
|
||||
continue;
|
||||
std::string::size_type pos = item.find('=');
|
||||
if (pos == std::string::npos) {
|
||||
LOG_WARN("ignoring invalid quant override \"%s\"", item.c_str());
|
||||
continue;
|
||||
}
|
||||
std::string tensor_pattern = item.substr(0, pos);
|
||||
std::string type_name = item.substr(pos + 1);
|
||||
|
||||
ggml_type tensor_type = GGML_TYPE_COUNT;
|
||||
|
||||
if (type_name == "f32") {
|
||||
tensor_type = GGML_TYPE_F32;
|
||||
} else {
|
||||
for (size_t i = 0; i < SD_TYPE_COUNT; i++) {
|
||||
auto trait = ggml_get_type_traits((ggml_type)i);
|
||||
if (trait->to_float && trait->type_size && type_name == trait->type_name) {
|
||||
tensor_type = (ggml_type)i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tensor_type != GGML_TYPE_COUNT) {
|
||||
result.emplace_back(tensor_pattern, tensor_type);
|
||||
} else {
|
||||
LOG_WARN("ignoring invalid quant override \"%s\"", item.c_str());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ModelLoader::tensor_should_be_converted(const TensorStorage& tensor_storage, ggml_type type) {
|
||||
const std::string& name = tensor_storage.name;
|
||||
if (type != GGML_TYPE_COUNT) {
|
||||
@@ -2046,7 +2204,7 @@ bool ModelLoader::tensor_should_be_converted(const TensorStorage& tensor_storage
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ModelLoader::save_to_gguf_file(const std::string& file_path, ggml_type type) {
|
||||
bool ModelLoader::save_to_gguf_file(const std::string& file_path, ggml_type type, const std::string& tensor_type_rules_str) {
|
||||
auto backend = ggml_backend_cpu_init();
|
||||
size_t mem_size = 1 * 1024 * 1024; // for padding
|
||||
mem_size += tensor_storages.size() * ggml_tensor_overhead();
|
||||
@@ -2056,12 +2214,23 @@ bool ModelLoader::save_to_gguf_file(const std::string& file_path, ggml_type type
|
||||
|
||||
gguf_context* gguf_ctx = gguf_init_empty();
|
||||
|
||||
auto tensor_type_rules = parse_tensor_type_rules(tensor_type_rules_str);
|
||||
|
||||
auto on_new_tensor_cb = [&](const TensorStorage& tensor_storage, ggml_tensor** dst_tensor) -> bool {
|
||||
const std::string& name = tensor_storage.name;
|
||||
ggml_type tensor_type = tensor_storage.type;
|
||||
ggml_type dst_type = type;
|
||||
|
||||
ggml_type tensor_type = tensor_storage.type;
|
||||
if (tensor_should_be_converted(tensor_storage, type)) {
|
||||
tensor_type = type;
|
||||
for (const auto& tensor_type_rule : tensor_type_rules) {
|
||||
std::regex pattern(tensor_type_rule.first);
|
||||
if (std::regex_search(name, pattern)) {
|
||||
dst_type = tensor_type_rule.second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (tensor_should_be_converted(tensor_storage, dst_type)) {
|
||||
tensor_type = dst_type;
|
||||
}
|
||||
|
||||
ggml_tensor* tensor = ggml_new_tensor(ggml_ctx, tensor_type, tensor_storage.n_dims, tensor_storage.ne);
|
||||
@@ -2120,7 +2289,7 @@ int64_t ModelLoader::get_params_mem_size(ggml_backend_t backend, ggml_type type)
|
||||
return mem_size;
|
||||
}
|
||||
|
||||
bool convert(const char* input_path, const char* vae_path, const char* output_path, sd_type_t output_type) {
|
||||
bool convert(const char* input_path, const char* vae_path, const char* output_path, sd_type_t output_type, const char* tensor_type_rules) {
|
||||
ModelLoader model_loader;
|
||||
|
||||
if (!model_loader.init_from_file(input_path)) {
|
||||
@@ -2134,6 +2303,6 @@ bool convert(const char* input_path, const char* vae_path, const char* output_pa
|
||||
return false;
|
||||
}
|
||||
}
|
||||
bool success = model_loader.save_to_gguf_file(output_path, (ggml_type)output_type);
|
||||
bool success = model_loader.save_to_gguf_file(output_path, (ggml_type)output_type, tensor_type_rules);
|
||||
return success;
|
||||
}
|
||||
|
||||
25
model.h
25
model.h
@@ -21,10 +21,12 @@
|
||||
enum SDVersion {
|
||||
VERSION_SD1,
|
||||
VERSION_SD1_INPAINT,
|
||||
VERSION_SD1_PIX2PIX,
|
||||
VERSION_SD2,
|
||||
VERSION_SD2_INPAINT,
|
||||
VERSION_SDXL,
|
||||
VERSION_SDXL_INPAINT,
|
||||
VERSION_SDXL_PIX2PIX,
|
||||
VERSION_SVD,
|
||||
VERSION_SD3,
|
||||
VERSION_FLUX,
|
||||
@@ -47,7 +49,7 @@ static inline bool sd_version_is_sd3(SDVersion version) {
|
||||
}
|
||||
|
||||
static inline bool sd_version_is_sd1(SDVersion version) {
|
||||
if (version == VERSION_SD1 || version == VERSION_SD1_INPAINT) {
|
||||
if (version == VERSION_SD1 || version == VERSION_SD1_INPAINT || version == VERSION_SD1_PIX2PIX) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -61,7 +63,7 @@ static inline bool sd_version_is_sd2(SDVersion version) {
|
||||
}
|
||||
|
||||
static inline bool sd_version_is_sdxl(SDVersion version) {
|
||||
if (version == VERSION_SDXL || version == VERSION_SDXL_INPAINT) {
|
||||
if (version == VERSION_SDXL || version == VERSION_SDXL_INPAINT || version == VERSION_SDXL_PIX2PIX) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -81,6 +83,14 @@ static inline bool sd_version_is_dit(SDVersion version) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool sd_version_is_unet_edit(SDVersion version) {
|
||||
return version == VERSION_SD1_PIX2PIX || version == VERSION_SDXL_PIX2PIX;
|
||||
}
|
||||
|
||||
static bool sd_version_is_inpaint_or_unet_edit(SDVersion version) {
|
||||
return sd_version_is_unet_edit(version) || sd_version_is_inpaint(version);
|
||||
}
|
||||
|
||||
enum PMVersion {
|
||||
PM_VERSION_1,
|
||||
PM_VERSION_2,
|
||||
@@ -92,6 +102,8 @@ struct TensorStorage {
|
||||
bool is_bf16 = false;
|
||||
bool is_f8_e4m3 = false;
|
||||
bool is_f8_e5m2 = false;
|
||||
bool is_f64 = false;
|
||||
bool is_i64 = false;
|
||||
int64_t ne[SD_MAX_DIMS] = {1, 1, 1, 1, 1};
|
||||
int n_dims = 0;
|
||||
|
||||
@@ -123,6 +135,8 @@ struct TensorStorage {
|
||||
int64_t nbytes_to_read() const {
|
||||
if (is_bf16 || is_f8_e4m3 || is_f8_e5m2) {
|
||||
return nbytes() / 2;
|
||||
} else if (is_f64 || is_i64) {
|
||||
return nbytes() * 2;
|
||||
} else {
|
||||
return nbytes();
|
||||
}
|
||||
@@ -173,6 +187,10 @@ struct TensorStorage {
|
||||
type_name = "f8_e4m3";
|
||||
} else if (is_f8_e5m2) {
|
||||
type_name = "f8_e5m2";
|
||||
} else if (is_f64) {
|
||||
type_name = "f64";
|
||||
} else if (is_i64) {
|
||||
type_name = "i64";
|
||||
}
|
||||
ss << name << " | " << type_name << " | ";
|
||||
ss << n_dims << " [";
|
||||
@@ -210,6 +228,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();
|
||||
@@ -221,7 +240,7 @@ public:
|
||||
ggml_backend_t backend,
|
||||
std::set<std::string> ignore_tensors = {});
|
||||
|
||||
bool save_to_gguf_file(const std::string& file_path, ggml_type type);
|
||||
bool save_to_gguf_file(const std::string& file_path, ggml_type type, const std::string& tensor_type_rules);
|
||||
bool tensor_should_be_converted(const TensorStorage& tensor_storage, ggml_type type);
|
||||
int64_t get_params_mem_size(ggml_backend_t backend, ggml_type type = GGML_TYPE_COUNT);
|
||||
~ModelLoader() = default;
|
||||
|
||||
1279
stable-diffusion.cpp
1279
stable-diffusion.cpp
File diff suppressed because it is too large
Load Diff
@@ -30,7 +30,8 @@ extern "C" {
|
||||
|
||||
enum rng_type_t {
|
||||
STD_DEFAULT_RNG,
|
||||
CUDA_RNG
|
||||
CUDA_RNG,
|
||||
RNG_TYPE_COUNT
|
||||
};
|
||||
|
||||
enum sample_method_t {
|
||||
@@ -46,7 +47,7 @@ enum sample_method_t {
|
||||
LCM,
|
||||
DDIM_TRAILING,
|
||||
TCD,
|
||||
N_SAMPLE_METHODS
|
||||
SAMPLE_METHOD_COUNT
|
||||
};
|
||||
|
||||
enum schedule_t {
|
||||
@@ -56,7 +57,7 @@ enum schedule_t {
|
||||
EXPONENTIAL,
|
||||
AYS,
|
||||
GITS,
|
||||
N_SCHEDULES
|
||||
SCHEDULE_COUNT
|
||||
};
|
||||
|
||||
// same as enum ggml_type
|
||||
@@ -103,8 +104,6 @@ enum sd_type_t {
|
||||
SD_TYPE_COUNT = 39,
|
||||
};
|
||||
|
||||
SD_API const char* sd_type_name(enum sd_type_t type);
|
||||
|
||||
enum sd_log_level_t {
|
||||
SD_LOG_DEBUG,
|
||||
SD_LOG_INFO,
|
||||
@@ -112,6 +111,98 @@ enum sd_log_level_t {
|
||||
SD_LOG_ERROR
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
const char* model_path;
|
||||
const char* clip_l_path;
|
||||
const char* clip_g_path;
|
||||
const char* t5xxl_path;
|
||||
const char* diffusion_model_path;
|
||||
const char* vae_path;
|
||||
const char* taesd_path;
|
||||
const char* control_net_path;
|
||||
const char* lora_model_dir;
|
||||
const char* embedding_dir;
|
||||
const char* stacked_id_embed_dir;
|
||||
bool vae_decode_only;
|
||||
bool vae_tiling;
|
||||
bool free_params_immediately;
|
||||
int n_threads;
|
||||
enum sd_type_t wtype;
|
||||
enum rng_type_t rng_type;
|
||||
enum schedule_t schedule;
|
||||
bool keep_clip_on_cpu;
|
||||
bool keep_control_net_on_cpu;
|
||||
bool keep_vae_on_cpu;
|
||||
bool diffusion_flash_attn;
|
||||
bool chroma_use_dit_mask;
|
||||
bool chroma_use_t5_mask;
|
||||
int chroma_t5_mask_pad;
|
||||
} sd_ctx_params_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t channel;
|
||||
uint8_t* data;
|
||||
} sd_image_t;
|
||||
|
||||
typedef struct {
|
||||
int* layers;
|
||||
size_t layer_count;
|
||||
float layer_start;
|
||||
float layer_end;
|
||||
float scale;
|
||||
} sd_slg_params_t;
|
||||
|
||||
typedef struct {
|
||||
float txt_cfg;
|
||||
float img_cfg;
|
||||
float min_cfg;
|
||||
float distilled_guidance;
|
||||
sd_slg_params_t slg;
|
||||
} sd_guidance_params_t;
|
||||
|
||||
typedef struct {
|
||||
const char* prompt;
|
||||
const char* negative_prompt;
|
||||
int clip_skip;
|
||||
sd_guidance_params_t guidance;
|
||||
sd_image_t init_image;
|
||||
sd_image_t* ref_images;
|
||||
int ref_images_count;
|
||||
sd_image_t mask_image;
|
||||
int width;
|
||||
int height;
|
||||
enum sample_method_t sample_method;
|
||||
int sample_steps;
|
||||
float eta;
|
||||
float strength;
|
||||
int64_t seed;
|
||||
int batch_count;
|
||||
const sd_image_t* control_cond;
|
||||
float control_strength;
|
||||
float style_strength;
|
||||
bool normalize_input;
|
||||
const char* input_id_images_path;
|
||||
} sd_img_gen_params_t;
|
||||
|
||||
typedef struct {
|
||||
sd_image_t init_image;
|
||||
int width;
|
||||
int height;
|
||||
sd_guidance_params_t guidance;
|
||||
enum sample_method_t sample_method;
|
||||
int sample_steps;
|
||||
float strength;
|
||||
int64_t seed;
|
||||
int video_frames;
|
||||
int motion_bucket_id;
|
||||
int fps;
|
||||
float augmentation_level;
|
||||
} sd_vid_gen_params_t;
|
||||
|
||||
typedef struct sd_ctx_t sd_ctx_t;
|
||||
|
||||
typedef void (*sd_log_cb_t)(enum sd_log_level_t level, const char* text, void* data);
|
||||
typedef void (*sd_progress_cb_t)(int step, int steps, float time, void* data);
|
||||
|
||||
@@ -120,134 +211,27 @@ SD_API void sd_set_progress_callback(sd_progress_cb_t cb, void* data);
|
||||
SD_API int32_t get_num_physical_cores();
|
||||
SD_API const char* sd_get_system_info();
|
||||
|
||||
typedef struct {
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t channel;
|
||||
uint8_t* data;
|
||||
} sd_image_t;
|
||||
SD_API const char* sd_type_name(enum sd_type_t type);
|
||||
SD_API enum sd_type_t str_to_sd_type(const char* str);
|
||||
SD_API const char* sd_rng_type_name(enum rng_type_t rng_type);
|
||||
SD_API enum rng_type_t str_to_rng_type(const char* str);
|
||||
SD_API const char* sd_sample_method_name(enum sample_method_t sample_method);
|
||||
SD_API enum sample_method_t str_to_sample_method(const char* str);
|
||||
SD_API const char* sd_schedule_name(enum schedule_t schedule);
|
||||
SD_API enum schedule_t str_to_schedule(const char* str);
|
||||
|
||||
typedef struct sd_ctx_t sd_ctx_t;
|
||||
|
||||
SD_API sd_ctx_t* new_sd_ctx(const char* model_path,
|
||||
const char* clip_l_path,
|
||||
const char* clip_g_path,
|
||||
const char* t5xxl_path,
|
||||
const char* diffusion_model_path,
|
||||
const char* vae_path,
|
||||
const char* taesd_path,
|
||||
const char* control_net_path_c_str,
|
||||
const char* lora_model_dir,
|
||||
const char* embed_dir_c_str,
|
||||
const char* stacked_id_embed_dir_c_str,
|
||||
bool vae_decode_only,
|
||||
bool vae_tiling,
|
||||
bool free_params_immediately,
|
||||
int n_threads,
|
||||
enum sd_type_t wtype,
|
||||
enum rng_type_t rng_type,
|
||||
enum schedule_t s,
|
||||
bool keep_clip_on_cpu,
|
||||
bool keep_control_net_cpu,
|
||||
bool keep_vae_on_cpu,
|
||||
bool diffusion_flash_attn,
|
||||
bool chroma_use_dit_mask,
|
||||
bool chroma_use_t5_mask,
|
||||
int chroma_t5_mask_pad);
|
||||
SD_API void sd_ctx_params_init(sd_ctx_params_t* sd_ctx_params);
|
||||
SD_API char* sd_ctx_params_to_str(const sd_ctx_params_t* sd_ctx_params);
|
||||
|
||||
SD_API sd_ctx_t* new_sd_ctx(const sd_ctx_params_t* sd_ctx_params);
|
||||
SD_API void free_sd_ctx(sd_ctx_t* sd_ctx);
|
||||
|
||||
SD_API sd_image_t* txt2img(sd_ctx_t* sd_ctx,
|
||||
const char* prompt,
|
||||
const char* negative_prompt,
|
||||
int clip_skip,
|
||||
float cfg_scale,
|
||||
float guidance,
|
||||
float eta,
|
||||
int width,
|
||||
int height,
|
||||
enum sample_method_t sample_method,
|
||||
int sample_steps,
|
||||
int64_t seed,
|
||||
int batch_count,
|
||||
const sd_image_t* control_cond,
|
||||
float control_strength,
|
||||
float style_strength,
|
||||
bool normalize_input,
|
||||
const char* input_id_images_path,
|
||||
int* skip_layers,
|
||||
size_t skip_layers_count,
|
||||
float slg_scale,
|
||||
float skip_layer_start,
|
||||
float skip_layer_end);
|
||||
SD_API void sd_img_gen_params_init(sd_img_gen_params_t* sd_img_gen_params);
|
||||
SD_API char* sd_img_gen_params_to_str(const sd_img_gen_params_t* sd_img_gen_params);
|
||||
SD_API sd_image_t* generate_image(sd_ctx_t* sd_ctx, const sd_img_gen_params_t* sd_img_gen_params);
|
||||
|
||||
SD_API sd_image_t* img2img(sd_ctx_t* sd_ctx,
|
||||
sd_image_t init_image,
|
||||
sd_image_t mask_image,
|
||||
const char* prompt,
|
||||
const char* negative_prompt,
|
||||
int clip_skip,
|
||||
float cfg_scale,
|
||||
float guidance,
|
||||
float eta,
|
||||
int width,
|
||||
int height,
|
||||
enum sample_method_t sample_method,
|
||||
int sample_steps,
|
||||
float strength,
|
||||
int64_t seed,
|
||||
int batch_count,
|
||||
const sd_image_t* control_cond,
|
||||
float control_strength,
|
||||
float style_strength,
|
||||
bool normalize_input,
|
||||
const char* input_id_images_path,
|
||||
int* skip_layers,
|
||||
size_t skip_layers_count,
|
||||
float slg_scale,
|
||||
float skip_layer_start,
|
||||
float skip_layer_end);
|
||||
|
||||
SD_API sd_image_t* img2vid(sd_ctx_t* sd_ctx,
|
||||
sd_image_t init_image,
|
||||
int width,
|
||||
int height,
|
||||
int video_frames,
|
||||
int motion_bucket_id,
|
||||
int fps,
|
||||
float augmentation_level,
|
||||
float min_cfg,
|
||||
float cfg_scale,
|
||||
enum sample_method_t sample_method,
|
||||
int sample_steps,
|
||||
float strength,
|
||||
int64_t seed);
|
||||
|
||||
SD_API sd_image_t* edit(sd_ctx_t* sd_ctx,
|
||||
sd_image_t* ref_images,
|
||||
int ref_images_count,
|
||||
const char* prompt,
|
||||
const char* negative_prompt,
|
||||
int clip_skip,
|
||||
float cfg_scale,
|
||||
float guidance,
|
||||
float eta,
|
||||
int width,
|
||||
int height,
|
||||
enum sample_method_t sample_method,
|
||||
int sample_steps,
|
||||
float strength,
|
||||
int64_t seed,
|
||||
int batch_count,
|
||||
const sd_image_t* control_cond,
|
||||
float control_strength,
|
||||
float style_strength,
|
||||
bool normalize_input,
|
||||
int* skip_layers,
|
||||
size_t skip_layers_count,
|
||||
float slg_scale,
|
||||
float skip_layer_start,
|
||||
float skip_layer_end);
|
||||
SD_API void sd_vid_gen_params_init(sd_vid_gen_params_t* sd_vid_gen_params);
|
||||
SD_API sd_image_t* generate_video(sd_ctx_t* sd_ctx, const sd_vid_gen_params_t* sd_vid_gen_params); // broken
|
||||
|
||||
typedef struct upscaler_ctx_t upscaler_ctx_t;
|
||||
|
||||
@@ -257,7 +241,11 @@ SD_API void free_upscaler_ctx(upscaler_ctx_t* upscaler_ctx);
|
||||
|
||||
SD_API sd_image_t upscale(upscaler_ctx_t* upscaler_ctx, sd_image_t input_image, uint32_t upscale_factor);
|
||||
|
||||
SD_API bool convert(const char* input_path, const char* vae_path, const char* output_path, enum sd_type_t output_type);
|
||||
SD_API bool convert(const char* input_path,
|
||||
const char* vae_path,
|
||||
const char* output_path,
|
||||
enum sd_type_t output_type,
|
||||
const char* tensor_type_rules);
|
||||
|
||||
SD_API uint8_t* preprocess_canny(uint8_t* img,
|
||||
int width,
|
||||
|
||||
2
unet.hpp
2
unet.hpp
@@ -207,6 +207,8 @@ public:
|
||||
}
|
||||
if (sd_version_is_inpaint(version)) {
|
||||
in_channels = 9;
|
||||
} else if (sd_version_is_unet_edit(version)) {
|
||||
in_channels = 8;
|
||||
}
|
||||
|
||||
// dims is always 2
|
||||
|
||||
4
util.cpp
4
util.cpp
@@ -441,10 +441,6 @@ const char* sd_get_system_info() {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
const char* sd_type_name(enum sd_type_t type) {
|
||||
return ggml_type_name((ggml_type)type);
|
||||
}
|
||||
|
||||
sd_image_f32_t sd_image_t_to_sd_image_f32_t(sd_image_t image) {
|
||||
sd_image_f32_t converted_image;
|
||||
converted_image.width = image.width;
|
||||
|
||||
3
util.h
3
util.h
@@ -7,6 +7,9 @@
|
||||
|
||||
#include "stable-diffusion.h"
|
||||
|
||||
#define SAFE_STR(s) ((s) ? (s) : "")
|
||||
#define BOOL_STR(b) ((b) ? "true" : "false")
|
||||
|
||||
bool ends_with(const std::string& str, const std::string& ending);
|
||||
bool starts_with(const std::string& str, const std::string& start);
|
||||
bool contains(const std::string& str, const std::string& substr);
|
||||
|
||||
Reference in New Issue
Block a user