76 setWindowTitle(
"Stable Diffusion Settings");
77 setMinimumSize(600, 600);
85 prompt_edit->setPlaceholderText(
"Describe the desired image style...");
100 server_edit->setPlaceholderText(default_stable_diffusion_server());
102 server_arguments_edit->setPlaceholderText(
"Optional flags, for example --vae-tiling --offload-to-cpu");
104 "Use quotes around values containing spaces.");
113 resolution_combo_box->addItems({
"512x512",
"576x320",
"640x384",
"704x448",
"768x448",
"768x512",
"832x512",
"896x512",
"1024x576",
"1024x1024",
"1152x640",
"1280x768",
"1344x768",
"1536x896",
"1920x1088"});
114 resolution_combo_box->setToolTip(
"Choose a preset or enter WIDTHxHEIGHT. Both dimensions must be "
115 "multiples of 64 between 64 and 2048 pixels.");
127 seed_spin_box->setRange(std::numeric_limits<int>::min(), std::numeric_limits<int>::max());
130 sampler_combo_box->addItems({
"euler_a",
"euler",
"dpm++2m",
"dpm++2mv2",
"lcm"});
134 upscale_check_box =
new QCheckBox(
"High-quality Vulkan compute upscale before shaders",
this);
135 upscale_check_box->setToolTip(
"Keep the native Stable Diffusion image size and run ACMXVK's "
136 "bicubic detail-preserving compute stage before user shaders.");
137 upscale_only_check_box =
new QCheckBox(
"Use ESRGAN upscale only before shaders (no image-to-image model)",
this);
138 upscale_only_check_box->setToolTip(
"Run the selected ESRGAN model through sd-server before the ACMXVK shader chain. "
139 "No diffusion model, prompt, sampler, or LoRA is used.");
142 "upscaler instead of ACMXVK's Vulkan compute upscaler.");
150 "The neural upscaler runs at this size before ACMXVK resizes to the final output.");
152 auto *model_group =
new QGroupBox(
"Image-to-Image Model",
this);
153 auto *model_layout =
new QFormLayout(model_group);
154 auto *model_row =
new QHBoxLayout;
157 model_layout->addRow(
"Safetensors model:", model_row);
161 auto *lora_group =
new QGroupBox(
"LoRA Models",
this);
162 lora_group->setToolTip(
"Optional adapters applied by sd-server. All selected LoRA files "
163 "must be in the same folder.");
164 auto *lora_layout =
new QVBoxLayout(lora_group);
166 auto *lora_controls =
new QHBoxLayout;
169 lora_controls->addStretch();
170 lora_controls->addWidget(
new QLabel(
"Selected multiplier:",
this));
172 lora_layout->addLayout(lora_controls);
174 auto *generation_group =
new QGroupBox(
"Generation",
this);
175 auto *generation_layout =
new QFormLayout(generation_group);
186 auto *upscale_model_row =
new QHBoxLayout;
189 generation_layout->addRow(
"Upscale model:", upscale_model_row);
192 auto *server_group =
new QGroupBox(
"Local sd-server",
this);
193 auto *server_layout =
new QFormLayout(server_group);
194 auto *server_row =
new QHBoxLayout;
197 server_layout->addRow(
"Executable:", server_row);
201 auto *contents =
new QWidget(
this);
202 auto *contents_layout =
new QVBoxLayout(contents);
204 contents_layout->addWidget(model_group);
205 contents_layout->addWidget(lora_group);
206 contents_layout->addWidget(generation_group);
207 contents_layout->addWidget(server_group);
208 contents_layout->addStretch();
210 auto *scroll_area =
new QScrollArea(
this);
211 scroll_area->setWidgetResizable(
true);
212 scroll_area->setWidget(contents);
214 auto *buttons =
new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Apply | QDialogButtonBox::Cancel,
this);
215 auto *layout =
new QVBoxLayout(
this);
216 layout->addWidget(scroll_area, 1);
217 layout->addWidget(buttons);
248 connect(buttons, &QDialogButtonBox::rejected,
this, &QDialog::reject);
409 QMessageBox::warning(
this,
"Stable Diffusion Model Required",
"Select an existing safetensors model file.");
412 QString lora_directory;
414 const QString filename =
lora_list_widget->item(row)->data(LORA_PATH_ROLE).toString();
415 const QFileInfo file_info(filename);
416 if (!file_info.isFile()) {
417 QMessageBox::warning(
this,
"LoRA Model Not Found", QStringLiteral(
"The selected LoRA model does not exist:\n%1").arg(filename));
420 if (lora_directory.isEmpty()) {
421 lora_directory = file_info.absolutePath();
422 }
else if (lora_directory != file_info.absolutePath()) {
423 QMessageBox::warning(
this,
424 "LoRA Folder Mismatch",
425 "All selected LoRA models must be in the same folder. "
426 "sd-server scans one LoRA model directory per launch.");
431 QMessageBox::warning(
this,
"Stable Diffusion Prompt Required",
"Enter an image-to-image prompt.");
435 QMessageBox::warning(
this,
"sd-server Required",
"Enter sd-server or select its executable.");
439 constexpr int MAX_SERVER_ARGUMENTS = 256;
440 constexpr int MAX_SERVER_ARGUMENT_BYTES = 8192;
441 if (server_arguments.size() > MAX_SERVER_ARGUMENTS) {
442 QMessageBox::warning(
this,
"Too Many sd-server Flags",
"Extra sd-server flags are limited to 256 arguments.");
445 for (
const QString &argument : server_arguments) {
446 if (argument.isEmpty() || argument.toUtf8().size() > MAX_SERVER_ARGUMENT_BYTES) {
447 QMessageBox::warning(
this,
448 "Invalid sd-server Flag",
449 "Each extra sd-server argument must be non-empty and no "
450 "larger than 8192 UTF-8 bytes.");
455 QMessageBox::warning(
this,
"Upscale Model Required",
"Select an existing ESRGAN or RealESRGAN model.");
459 QMessageBox::warning(
this,
"Upscale Model Required",
"Enable the sd-server ESRGAN model and select an existing model.");
463 if (!working_resolution.isEmpty()) {
464 int working_width = 0;
465 int working_height = 0;
466 if (!parse_stable_resolution(working_resolution, working_width, working_height) || working_width < 64 || working_width > 4096 || working_height < 64 || working_height > 4096) {
467 QMessageBox::warning(
this,
"Invalid ESRGAN Working Resolution",
"Enter WIDTHxHEIGHT between 64 and 4096 pixels, or leave this field blank for automatic sizing.");
475 QMessageBox::warning(
this,
"Invalid Stable Diffusion Resolution",
"Enter the resolution as WIDTHxHEIGHT, for example 640x384.");
478 if (width < STABLE_DIMENSION_MINIMUM || width > STABLE_DIMENSION_MAXIMUM || height < STABLE_DIMENSION_MINIMUM || height > STABLE_DIMENSION_MAXIMUM || (width % 64) != 0 || (height % 64) != 0) {
479 QMessageBox::warning(
this,
480 "Invalid Stable Diffusion Resolution",
481 "Width and height must be multiples of 64 between 64 and 2048 "
487 QMessageBox::warning(
this,
"Generation Method Required",
"Enter both a sampler and scheduler.");
494 QSettings settings(
"LostSideDead",
"acmx2");
495 enable_check_box->setChecked(settings.value(
"stable_diffusion/enabled",
false).toBool());
496 model_file_edit->setText(settings.value(
"stable_diffusion/model_file").toString());
497 const QStringList lora_files = settings.value(
"stable_diffusion/lora_files").toStringList();
498 const QStringList lora_multiplier_values = settings.value(
"stable_diffusion/lora_multipliers").toStringList();
499 for (
int index = 0; index < lora_files.size(); ++index) {
500 bool multiplier_ok =
false;
501 const double saved_multiplier = index < lora_multiplier_values.size() ? lora_multiplier_values.at(index).toDouble(&multiplier_ok) : 1.0;
502 add_lora_item(lora_files.at(index), multiplier_ok ? saved_multiplier : 1.0);
504 prompt_edit->setText(settings.value(
"stable_diffusion/prompt").toString());
506 server_edit->setText(settings.value(
"stable_diffusion/server", default_stable_diffusion_server()).toString());
509 const int width = settings.value(
"stable_diffusion/width", 576).toInt();
510 const int height = settings.value(
"stable_diffusion/height", 320).toInt();
511 const QString saved_resolution = settings.value(
"stable_diffusion/resolution", resolution_text(width, height)).toString();
513 int saved_height = 0;
514 if (parse_stable_resolution(saved_resolution, saved_width, saved_height)) {
519 steps_spin_box->setValue(settings.value(
"stable_diffusion/steps", 12).toInt());
520 strength_spin_box->setValue(settings.value(
"stable_diffusion/strength", 0.35).toDouble());
521 cfg_scale_spin_box->setValue(settings.value(
"stable_diffusion/cfg_scale", 5.0).toDouble());
522 seed_spin_box->setValue(settings.value(
"stable_diffusion/seed", 1234).toInt());
523 sampler_combo_box->setCurrentText(settings.value(
"stable_diffusion/sampler",
"euler_a").toString());
524 scheduler_combo_box->setCurrentText(settings.value(
"stable_diffusion/scheduler",
"discrete").toString());
525 upscale_model_edit->setText(settings.value(
"stable_diffusion/upscale_model_file").toString());
526 const int upscale_working_width = settings.value(
"stable_diffusion/upscale_working_width", 0).toInt();
527 const int upscale_working_height = settings.value(
"stable_diffusion/upscale_working_height", 0).toInt();
528 if (upscale_working_width > 0 && upscale_working_height > 0) {
532 upscale_check_box->setChecked(settings.value(
"stable_diffusion/upscale",
false).toBool());