Skip to content

Commit 2d6c4f8

Browse files
committed
Merge branch 'concedo_experimental' into crokeso
2 parents c8f98b7 + 21881a8 commit 2d6c4f8

File tree

5 files changed

+255
-58
lines changed

5 files changed

+255
-58
lines changed

expose.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,8 @@ struct sd_load_model_inputs
176176
const char * vae_filename = nullptr;
177177
const char * lora_filename = nullptr;
178178
const float lora_multiplier = 1.0f;
179-
const int side_limit = 0;
180-
const int square_limit = 0;
179+
const int img_hard_limit = 0;
180+
const int img_soft_limit = 0;
181181
const bool quiet = false;
182182
const int debugmode = 0;
183183
};

koboldcpp.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -305,8 +305,8 @@ class sd_load_model_inputs(ctypes.Structure):
305305
("vae_filename", ctypes.c_char_p),
306306
("lora_filename", ctypes.c_char_p),
307307
("lora_multiplier", ctypes.c_float),
308-
("side_limit", ctypes.c_int),
309-
("square_limit", ctypes.c_int),
308+
("img_hard_limit", ctypes.c_int),
309+
("img_soft_limit", ctypes.c_int),
310310
("quiet", ctypes.c_bool),
311311
("debugmode", ctypes.c_int)]
312312

@@ -2263,8 +2263,8 @@ def sd_load_model(model_filename,vae_filename,lora_filename,t5xxl_filename,clipl
22632263
inputs.t5xxl_filename = t5xxl_filename.encode("UTF-8")
22642264
inputs.clipl_filename = clipl_filename.encode("UTF-8")
22652265
inputs.clipg_filename = clipg_filename.encode("UTF-8")
2266-
inputs.side_limit = args.sdclamped
2267-
inputs.square_limit = args.sdrestrictsquare
2266+
inputs.img_hard_limit = args.sdclamped
2267+
inputs.img_soft_limit = args.sdclampedsoft
22682268
inputs = set_backend_props(inputs)
22692269
ret = handle.sd_load_model(inputs)
22702270
return ret
@@ -6151,7 +6151,7 @@ def hide_tooltip(event):
61516151
sd_vaeauto_var = ctk.IntVar(value=0)
61526152
sd_notile_var = ctk.IntVar(value=0)
61536153
sd_clamped_var = ctk.StringVar(value="0")
6154-
sd_restrict_square_var = ctk.StringVar(value="0")
6154+
sd_clamped_soft_var = ctk.StringVar(value="0")
61556155
sd_threads_var = ctk.StringVar(value=str(default_threads))
61566156
sd_quant_var = ctk.IntVar(value=0)
61576157

@@ -6912,8 +6912,8 @@ def togglehorde(a,b,c):
69126912

69136913
images_tab = tabcontent["Image Gen"]
69146914
makefileentry(images_tab, "Image Gen. Model (safetensors/gguf):", "Select Image Gen Model File", sd_model_var, 1, width=280, singlecol=True, filetypes=[("*.safetensors *.gguf","*.safetensors *.gguf")], tooltiptxt="Select a .safetensors or .gguf Image Generation model file on disk to be loaded.")
6915-
makelabelentry(images_tab, "Clamped Mode (Limit Resolution):", sd_clamped_var, 4, 50, padx=290,singleline=True,tooltip="Limit generation steps and resolution settings for shared use.\nSet to 0 to disable, otherwise value is the size limit (min 512px).")
6916-
makelabelentry(images_tab, "Restrict Square Size:", sd_restrict_square_var, 6, 50, padx=290,singleline=True,tooltip="Square image size restriction, to protect the server against memory crashes.\nAllows width-height tradeoffs, eg. 640 allows 640x640 and 512x768\nLeave at 0 for the default value: 832 for SD1.5/SD2, 1024 otherwise.")
6915+
makelabelentry(images_tab, "Clamp Resolution Limit (Hard):", sd_clamped_var, 4, 50, padx=190,singleline=True,tooltip="Limit generation steps and output image size for shared use.\nSet to 0 to disable, otherwise value is clamped to the max size limit (min 512px).")
6916+
makelabelentry(images_tab, "(Soft):", sd_clamped_soft_var, 4, 50, padx=290,singleline=True,tooltip="Square image size restriction, to protect the server against memory crashes.\nAllows width-height tradeoffs, eg. 640 allows 640x640 and 512x768\nLeave at 0 for the default value: 832 for SD1.5/SD2, 1024 otherwise.",labelpadx=250)
69176917
makelabelentry(images_tab, "Image Threads:" , sd_threads_var, 8, 50,padx=290,singleline=True,tooltip="How many threads to use during image generation.\nIf left blank, uses same value as threads.")
69186918
sd_model_var.trace("w", gui_changed_modelfile)
69196919
makecheckbox(images_tab, "Compress Weights (Saves Memory)", sd_quant_var, 10,tooltiptxt="Quantizes the SD model weights to save memory. May degrade quality.")
@@ -7208,7 +7208,7 @@ def export_vars():
72087208

72097209
args.sdthreads = (0 if sd_threads_var.get()=="" else int(sd_threads_var.get()))
72107210
args.sdclamped = (0 if int(sd_clamped_var.get())<=0 else int(sd_clamped_var.get()))
7211-
args.sdrestrictsquare = (0 if int(sd_restrict_square_var.get())<=0 else int(sd_restrict_square_var.get()))
7211+
args.sdclampedsoft = (0 if int(sd_clamped_soft_var.get())<=0 else int(sd_clamped_soft_var.get()))
72127212
args.sdnotile = (True if sd_notile_var.get()==1 else False)
72137213
if sd_vaeauto_var.get()==1:
72147214
args.sdvaeauto = True
@@ -7441,7 +7441,7 @@ def import_vars(dict):
74417441

74427442
sd_model_var.set(dict["sdmodel"] if ("sdmodel" in dict and dict["sdmodel"]) else "")
74437443
sd_clamped_var.set(int(dict["sdclamped"]) if ("sdclamped" in dict and dict["sdclamped"]) else 0)
7444-
sd_restrict_square_var.set(int(dict["sdrestrictsquare"]) if ("sdrestrictsquare" in dict and dict["sdrestrictsquare"]) else 0)
7444+
sd_clamped_soft_var.set(int(dict["sdclampedsoft"]) if ("sdclampedsoft" in dict and dict["sdclampedsoft"]) else 0)
74457445
sd_threads_var.set(str(dict["sdthreads"]) if ("sdthreads" in dict and dict["sdthreads"]) else str(default_threads))
74467446
sd_quant_var.set(1 if ("sdquant" in dict and dict["sdquant"]) else 0)
74477447
sd_vae_var.set(dict["sdvae"] if ("sdvae" in dict and dict["sdvae"]) else "")
@@ -9406,8 +9406,8 @@ def range_checker(arg: str):
94069406
sdparsergroup = parser.add_argument_group('Image Generation Commands')
94079407
sdparsergroup.add_argument("--sdmodel", metavar=('[filename]'), help="Specify an image generation safetensors or gguf model to enable image generation.", default="")
94089408
sdparsergroup.add_argument("--sdthreads", metavar=('[threads]'), help="Use a different number of threads for image generation if specified. Otherwise, has the same value as --threads.", type=int, default=0)
9409-
sdparsergroup.add_argument("--sdclamped", metavar=('[maxres]'), help="If specified, limit generation steps and resolution settings for shared use. Accepts an extra optional parameter that indicates maximum resolution (eg. 768 clamps to 768x768, min 512px, disabled if 0).", nargs='?', const=512, type=int, default=0)
9410-
sdparsergroup.add_argument("--sdrestrictsquare", metavar=('[maxres]'), help="If specified, restrict square image sides to this value, in pixels, to avoid server crashes related to excessive memory usage. Similar to --sdclamped, but allows trade-offs between width and height (e.g. 640 would allow 640x640, 512x768 and 768x512 images). If 0 or unspecified, use a model-specific safe value: 832 for SD1.5/SD2, 1024 otherwise. Total resolution cannot exceed 1MP.", type=int, default=0)
9409+
sdparsergroup.add_argument("--sdclamped", metavar=('[maxres]'), help="If specified, limit generation steps and image size for shared use. Accepts an extra optional parameter that indicates maximum resolution (eg. 768 clamps to 768x768, min 512px, disabled if 0).", nargs='?', const=512, type=int, default=0)
9410+
sdparsergroup.add_argument("--sdclampedsoft", metavar=('[maxres]'), help="If specified, limit max image size to curb memory usage. Similar to --sdclamped, but less strict, allows trade-offs between width and height (e.g. 640 would allow 640x640, 512x768 and 768x512 images). Total resolution cannot exceed 1MP.", type=int, default=0)
94119411
sdparsergroup.add_argument("--sdt5xxl", metavar=('[filename]'), help="Specify a T5-XXL safetensors model for use in SD3 or Flux. Leave blank if prebaked or unused.", default="")
94129412
sdparsergroup.add_argument("--sdclipl", metavar=('[filename]'), help="Specify a Clip-L safetensors model for use in SD3 or Flux. Leave blank if prebaked or unused.", default="")
94139413
sdparsergroup.add_argument("--sdclipg", metavar=('[filename]'), help="Specify a Clip-G safetensors model for use in SD3. Leave blank if prebaked or unused.", default="")

otherarch/sdcpp/ggml_extend.hpp

Lines changed: 130 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,10 @@ __STATIC_INLINE__ void ggml_merge_tensor_2d(struct ggml_tensor* input,
470470
struct ggml_tensor* output,
471471
int x,
472472
int y,
473-
int overlap) {
473+
int overlap_x,
474+
int overlap_y,
475+
int x_skip = 0,
476+
int y_skip = 0) {
474477
int64_t width = input->ne[0];
475478
int64_t height = input->ne[1];
476479
int64_t channels = input->ne[2];
@@ -479,17 +482,17 @@ __STATIC_INLINE__ void ggml_merge_tensor_2d(struct ggml_tensor* input,
479482
int64_t img_height = output->ne[1];
480483

481484
GGML_ASSERT(input->type == GGML_TYPE_F32 && output->type == GGML_TYPE_F32);
482-
for (int iy = 0; iy < height; iy++) {
483-
for (int ix = 0; ix < width; ix++) {
485+
for (int iy = y_skip; iy < height; iy++) {
486+
for (int ix = x_skip; ix < width; ix++) {
484487
for (int k = 0; k < channels; k++) {
485488
float new_value = ggml_tensor_get_f32(input, ix, iy, k);
486-
if (overlap > 0) { // blend colors in overlapped area
489+
if (overlap_x > 0 || overlap_y > 0) { // blend colors in overlapped area
487490
float old_value = ggml_tensor_get_f32(output, x + ix, y + iy, k);
488491

489-
const float x_f_0 = (x > 0) ? ix / float(overlap) : 1;
490-
const float x_f_1 = (x < (img_width - width)) ? (width - ix) / float(overlap) : 1;
491-
const float y_f_0 = (y > 0) ? iy / float(overlap) : 1;
492-
const float y_f_1 = (y < (img_height - height)) ? (height - iy) / float(overlap) : 1;
492+
const float x_f_0 = (overlap_x > 0 && x > 0) ? (ix - x_skip) / float(overlap_x) : 1;
493+
const float x_f_1 = (overlap_x > 0 && x < (img_width - width)) ? (width - ix) / float(overlap_x) : 1;
494+
const float y_f_0 = (overlap_y > 0 && y > 0) ? (iy - y_skip) / float(overlap_y) : 1;
495+
const float y_f_1 = (overlap_y > 0 && y < (img_height - height)) ? (height - iy) / float(overlap_y) : 1;
493496

494497
const float x_f = std::min(std::min(x_f_0, x_f_1), 1.f);
495498
const float y_f = std::min(std::min(y_f_0, y_f_1), 1.f);
@@ -602,21 +605,96 @@ __STATIC_INLINE__ void ggml_tensor_scale_output(struct ggml_tensor* src) {
602605

603606
typedef std::function<void(ggml_tensor*, ggml_tensor*, bool)> on_tile_process;
604607

608+
__STATIC_INLINE__ void
609+
sd_tiling_calc_tiles(int &num_tiles_dim, float& tile_overlap_factor_dim, int small_dim, int tile_size, const float tile_overlap_factor) {
610+
611+
int tile_overlap = (tile_size * tile_overlap_factor);
612+
int non_tile_overlap = tile_size - tile_overlap;
613+
614+
num_tiles_dim = (small_dim - tile_overlap) / non_tile_overlap;
615+
int overshoot_dim = ((num_tiles_dim + 1) * non_tile_overlap + tile_overlap) % small_dim;
616+
617+
if ((overshoot_dim != non_tile_overlap) && (overshoot_dim <= num_tiles_dim * (tile_size / 2 - tile_overlap))) {
618+
// if tiles don't fit perfectly using the desired overlap
619+
// and there is enough room to squeeze an extra tile without overlap becoming >0.5
620+
num_tiles_dim++;
621+
}
622+
623+
tile_overlap_factor_dim = (float)(tile_size * num_tiles_dim - small_dim) / (float)(tile_size * (num_tiles_dim - 1));
624+
if (num_tiles_dim <= 2) {
625+
if (small_dim <= tile_size) {
626+
num_tiles_dim = 1;
627+
tile_overlap_factor_dim = 0;
628+
} else {
629+
num_tiles_dim = 2;
630+
tile_overlap_factor_dim = (2 * tile_size - small_dim) / (float)tile_size;
631+
}
632+
}
633+
}
634+
605635
// Tiling
606-
__STATIC_INLINE__ void sd_tiling(ggml_tensor* input, ggml_tensor* output, const int scale, const int tile_size, const float tile_overlap_factor, on_tile_process on_processing) {
636+
__STATIC_INLINE__ void sd_tiling_non_square(ggml_tensor* input, ggml_tensor* output, const int scale,
637+
const int p_tile_size_x, const int p_tile_size_y,
638+
const float tile_overlap_factor, on_tile_process on_processing) {
639+
607640
output = ggml_set_f32(output, 0);
641+
608642
int input_width = (int)input->ne[0];
609643
int input_height = (int)input->ne[1];
610644
int output_width = (int)output->ne[0];
611645
int output_height = (int)output->ne[1];
646+
647+
GGML_ASSERT(input_width / output_width == input_height / output_height && output_width / input_width == output_height / input_height);
648+
GGML_ASSERT(input_width / output_width == scale || output_width / input_width == scale);
649+
650+
int small_width = output_width;
651+
int small_height = output_height;
652+
653+
bool big_out = output_width > input_width;
654+
if (big_out) {
655+
// Ex: decode
656+
small_width = input_width;
657+
small_height = input_height;
658+
}
659+
660+
int num_tiles_x;
661+
float tile_overlap_factor_x;
662+
sd_tiling_calc_tiles(num_tiles_x, tile_overlap_factor_x, small_width, p_tile_size_x, tile_overlap_factor);
663+
664+
int num_tiles_y;
665+
float tile_overlap_factor_y;
666+
sd_tiling_calc_tiles(num_tiles_y, tile_overlap_factor_y, small_height, p_tile_size_y, tile_overlap_factor);
667+
668+
// LOG_DEBUG("num tiles : %d, %d ", num_tiles_x, num_tiles_y);
669+
// LOG_DEBUG("optimal overlap : %f, %f (targeting %f)", tile_overlap_factor_x, tile_overlap_factor_y, tile_overlap_factor);
670+
612671
GGML_ASSERT(input_width % 2 == 0 && input_height % 2 == 0 && output_width % 2 == 0 && output_height % 2 == 0); // should be multiple of 2
613672

614-
int tile_overlap = (int32_t)(tile_size * tile_overlap_factor);
615-
int non_tile_overlap = tile_size - tile_overlap;
673+
int tile_overlap_x = (int32_t)(p_tile_size_x * tile_overlap_factor_x);
674+
int non_tile_overlap_x = p_tile_size_x - tile_overlap_x;
675+
676+
int tile_overlap_y = (int32_t)(p_tile_size_y * tile_overlap_factor_y);
677+
int non_tile_overlap_y = p_tile_size_y - tile_overlap_y;
678+
679+
int tile_size_x = p_tile_size_x < small_width ? p_tile_size_x : small_width;
680+
int tile_size_y = p_tile_size_y < small_height ? p_tile_size_y : small_height;
681+
682+
int input_tile_size_x = tile_size_x;
683+
int input_tile_size_y = tile_size_y;
684+
int output_tile_size_x = tile_size_x;
685+
int output_tile_size_y = tile_size_y;
686+
687+
if (big_out) {
688+
output_tile_size_x *= scale;
689+
output_tile_size_y *= scale;
690+
} else {
691+
input_tile_size_x *= scale;
692+
input_tile_size_y *= scale;
693+
}
616694

617695
struct ggml_init_params params = {};
618-
params.mem_size += tile_size * tile_size * input->ne[2] * sizeof(float); // input chunk
619-
params.mem_size += (tile_size * scale) * (tile_size * scale) * output->ne[2] * sizeof(float); // output chunk
696+
params.mem_size += input_tile_size_x * input_tile_size_y * input->ne[2] * sizeof(float); // input chunk
697+
params.mem_size += output_tile_size_x * output_tile_size_y * output->ne[2] * sizeof(float); // output chunk
620698
params.mem_size += 3 * ggml_tensor_overhead();
621699
params.mem_buffer = NULL;
622700
params.no_alloc = false;
@@ -631,29 +709,50 @@ __STATIC_INLINE__ void sd_tiling(ggml_tensor* input, ggml_tensor* output, const
631709
}
632710

633711
// tiling
634-
ggml_tensor* input_tile = ggml_new_tensor_4d(tiles_ctx, GGML_TYPE_F32, tile_size, tile_size, input->ne[2], 1);
635-
ggml_tensor* output_tile = ggml_new_tensor_4d(tiles_ctx, GGML_TYPE_F32, tile_size * scale, tile_size * scale, output->ne[2], 1);
636-
on_processing(input_tile, NULL, true);
637-
int num_tiles = ceil((float)input_width / non_tile_overlap) * ceil((float)input_height / non_tile_overlap);
712+
ggml_tensor* input_tile = ggml_new_tensor_4d(tiles_ctx, GGML_TYPE_F32, input_tile_size_x, input_tile_size_y, input->ne[2], 1);
713+
ggml_tensor* output_tile = ggml_new_tensor_4d(tiles_ctx, GGML_TYPE_F32, output_tile_size_x, output_tile_size_y, output->ne[2], 1);
714+
int num_tiles = num_tiles_x * num_tiles_y;
638715
LOG_INFO("processing %i tiles", num_tiles);
639-
pretty_progress(1, num_tiles, 0.0f);
716+
pretty_progress(0, num_tiles, 0.0f);
640717
int tile_count = 1;
641718
bool last_y = false, last_x = false;
642719
float last_time = 0.0f;
643-
for (int y = 0; y < input_height && !last_y; y += non_tile_overlap) {
644-
if (y + tile_size >= input_height) {
645-
y = input_height - tile_size;
720+
for (int y = 0; y < small_height && !last_y; y += non_tile_overlap_y) {
721+
int dy = 0;
722+
if (y + tile_size_y >= small_height) {
723+
int _y = y;
724+
y = small_height - tile_size_y;
725+
dy = _y - y;
726+
if (big_out) {
727+
dy *= scale;
728+
}
646729
last_y = true;
647730
}
648-
for (int x = 0; x < input_width && !last_x; x += non_tile_overlap) {
649-
if (x + tile_size >= input_width) {
650-
x = input_width - tile_size;
731+
for (int x = 0; x < small_width && !last_x; x += non_tile_overlap_x) {
732+
int dx = 0;
733+
if (x + tile_size_x >= small_width) {
734+
int _x = x;
735+
x = small_width - tile_size_x;
736+
dx = _x - x;
737+
if (big_out) {
738+
dx *= scale;
739+
}
651740
last_x = true;
652741
}
742+
743+
int x_in = big_out ? x : scale * x;
744+
int y_in = big_out ? y : scale * y;
745+
int x_out = big_out ? x * scale : x;
746+
int y_out = big_out ? y * scale : y;
747+
748+
int overlap_x_out = big_out ? tile_overlap_x * scale : tile_overlap_x;
749+
int overlap_y_out = big_out ? tile_overlap_y * scale : tile_overlap_y;
750+
653751
int64_t t1 = ggml_time_ms();
654-
ggml_split_tensor_2d(input, input_tile, x, y);
752+
ggml_split_tensor_2d(input, input_tile, x_in, y_in);
655753
on_processing(input_tile, output_tile, false);
656-
ggml_merge_tensor_2d(output_tile, output, x * scale, y * scale, tile_overlap * scale);
754+
ggml_merge_tensor_2d(output_tile, output, x_out, y_out, overlap_x_out, overlap_y_out, dx, dy);
755+
657756
int64_t t2 = ggml_time_ms();
658757
last_time = (t2 - t1) / 1000.0f;
659758
pretty_progress(tile_count, num_tiles, last_time);
@@ -667,6 +766,11 @@ __STATIC_INLINE__ void sd_tiling(ggml_tensor* input, ggml_tensor* output, const
667766
ggml_free(tiles_ctx);
668767
}
669768

769+
__STATIC_INLINE__ void sd_tiling(ggml_tensor* input, ggml_tensor* output, const int scale,
770+
const int tile_size, const float tile_overlap_factor, on_tile_process on_processing) {
771+
sd_tiling_non_square(input, output, scale, tile_size, tile_size, tile_overlap_factor, on_processing);
772+
}
773+
670774
__STATIC_INLINE__ struct ggml_tensor* ggml_group_norm_32(struct ggml_context* ctx,
671775
struct ggml_tensor* a) {
672776
const float eps = 1e-6f; // default eps parameter

0 commit comments

Comments
 (0)