diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9e5a6a52f..28723f82e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -27,6 +27,7 @@
highly recommended for simple prompts
- general:
- `rembg` remove backgrounds support for **is-net** model
+ - **settings** now show markers for all items set to non-default values
- pre-create all system folders on startup
## Update for 2023-08-30
diff --git a/extensions-builtin/sd-webui-controlnet b/extensions-builtin/sd-webui-controlnet
index 42bb1b1a6..664ac74ca 160000
--- a/extensions-builtin/sd-webui-controlnet
+++ b/extensions-builtin/sd-webui-controlnet
@@ -1 +1 @@
-Subproject commit 42bb1b1a62181bf9ef5224015b1189a201ae103c
+Subproject commit 664ac74cae218cb4dea4b51bdf6ed2f0c81ebca9
diff --git a/html/locale_en.json b/html/locale_en.json
index c7b5c77f3..499af7083 100644
--- a/html/locale_en.json
+++ b/html/locale_en.json
@@ -2,11 +2,11 @@
{"id":"","label":"📘","localized":"","hint":"Read generation parameters from prompt or last generation if prompt is empty into user interface"},
{"id":"","label":"🚮","localized":"","hint":"Clear prompt"},
{"id":"","label":"🌐","localized":"","hint":"Show/hide extra networks"},
- {"id":"","label":"🧳","localized":"","hint":"Apply selected styles to current prompt"},
- {"id":"","label":"🛅","localized":"","hint":"Save current prompt as style template"},
+ {"id":"","label":"⏩","localized":"","hint":"Apply selected styles to current prompt"},
+ {"id":"","label":"⬇️","localized":"","hint":"Save current prompt as style template"},
{"id":"","label":"🔄","localized":"","hint":"Refresh"},
- {"id":"","label":"❌","localized":"","hint":"Close"},
- {"id":"","label":"📒","localized":"","hint":"Fill"},
+ {"id":"","label":"🛗","localized":"","hint":"Close"},
+ {"id":"","label":"⏫","localized":"","hint":"Fill"},
{"id":"","label":"🎲️","localized":"","hint":"Use random seed"},
{"id":"","label":"♻️","localized":"","hint":"Reuse previous seed"},
{"id":"","label":"⇅","localized":"","hint":"Swap values"}
diff --git a/javascript/amethyst-nightfall.css b/javascript/amethyst-nightfall.css
index 260d05423..fe66d2bf3 100644
--- a/javascript/amethyst-nightfall.css
+++ b/javascript/amethyst-nightfall.css
@@ -120,7 +120,7 @@ svg.feather.feather-image, .feather .feather-image { display: none }
#pnginfo_html2_info { margin-top: -18px; background-color: var(--input-background-fill); padding: var(--input-padding) }
#txt2img_tools > div > button, #img2img_tools > div > button { filter: hue-rotate(180deg) saturate(0.5); }
#txt2img_tools, #img2img_tools { margin-top: -4px; margin-bottom: -4px; }
-#txt2img_styles_row { margin-top: -6px; }
+#txt2img_styles_row, #img2img_styles_row { margin-top: -6px; }
/* custom elements overrides */
#steps-animation, #controlnet { border-width: 0; }
diff --git a/javascript/black-orange.css b/javascript/black-orange.css
index 36504c288..b1dd6f66a 100644
--- a/javascript/black-orange.css
+++ b/javascript/black-orange.css
@@ -115,7 +115,7 @@ svg.feather.feather-image, .feather .feather-image { display: none }
#pnginfo_html2_info { margin-top: -18px; background-color: var(--input-background-fill); padding: var(--input-padding) }
#txt2img_tools > div > button, #img2img_tools > div > button { filter: hue-rotate(180deg) saturate(0.5); }
#txt2img_tools, #img2img_tools { margin-top: -4px; margin-bottom: -4px; }
-#txt2img_styles_row { margin-top: -6px; }
+#txt2img_styles_row, #img2img_styles_row { margin-top: -6px; }
/* custom elements overrides */
#steps-animation, #controlnet { border-width: 0; }
diff --git a/javascript/black-teal.css b/javascript/black-teal.css
index 346da3d4f..54be70897 100644
--- a/javascript/black-teal.css
+++ b/javascript/black-teal.css
@@ -18,15 +18,13 @@
--highlight-color: var(--primary-200);
--inactive-color: var(--primary--800);
--background-color: #000000;
-}
-.light, .dark {
--input-padding: 4px;
- --radius-lg: 2px;
- --radius-sm: 1px;
+ --radius-lg: 4px;
+ --radius-sm: 2px;
--spacing-md: 4px;
- --spacing-xxl: 12px;
- --line-sm: 1.3em;
- --line-md: 1.3em;
+ --spacing-xxl: 8px;
+ --line-sm: 1.2em;
+ --line-md: 1.4em;
}
html { font-size: var(--font-size); }
@@ -35,10 +33,10 @@ button { font-size: 1.2rem; max-width: 400px; }
img { background-color: var(--background-color); }
input[type=checkbox] { background-color: transparent !important; }
input[type=range] { height: var(--line-sm); appearance: none; margin-top: 0; min-width: 160px; background-color: var(--background-color); width: 100%; background: transparent; }
-input[type=range]::-webkit-slider-runnable-track { width: 100%; height: 18px; cursor: pointer; box-shadow: 2px 2px 3px #111111; background: var(--input-background-fill); border-radius: var(--radius-lg); border: 0px solid #222222; }
-input[type=range]::-moz-range-track { width: 100%; height: 18px; cursor: pointer; box-shadow: 2px 2px 3px #111111; background: var(--input-background-fill); border-radius: var(--radius-lg); border: 0px solid #222222; }
-input[type=range]::-webkit-slider-thumb { box-shadow: 2px 2px 3px #111111; border: 0px solid #000000; height: 18px; width: 40px; border-radius: var(--radius-lg); background: var(--highlight-color); cursor: pointer; appearance: none; margin-top: 0px; }
-input[type=range]::-moz-range-thumb { box-shadow: 2px 2px 3px #111111; border: 0px solid #000000; height: 18px; width: 40px; border-radius: var(--radius-lg); background: var(--highlight-color); cursor: pointer; appearance: none; margin-top: 0px; }
+input[type=range]::-webkit-slider-runnable-track { width: 100%; height: var(--line-sm); cursor: pointer; box-shadow: 2px 2px 3px #111111; background: var(--input-background-fill); border-radius: var(--radius-lg); border: 0px solid #222222; }
+input[type=range]::-moz-range-track { width: 100%; height: var(--line-sm); cursor: pointer; box-shadow: 2px 2px 3px #111111; background: var(--input-background-fill); border-radius: var(--radius-lg); border: 0px solid #222222; }
+input[type=range]::-webkit-slider-thumb { box-shadow: 2px 2px 3px #111111; border: 0px solid #000000; height: var(--line-sm); width: var(--line-sm); border-radius: var(--radius-lg); background: var(--highlight-color); cursor: pointer; appearance: none; margin-top: 0px; }
+input[type=range]::-moz-range-thumb { box-shadow: 2px 2px 3px #111111; border: 0px solid #000000; height: var(--line-sm); width: var(--line-sm); border-radius: var(--radius-lg); background: var(--highlight-color); cursor: pointer; appearance: none; margin-top: 0px; }
::-webkit-scrollbar { width: 12px; }
::-webkit-scrollbar-track { background: #333333; }
::-webkit-scrollbar-thumb { background-color: var(--highlight-color); border-radius: var(--radius-lg); border-width: 0; box-shadow: 2px 2px 3px #111111; }
@@ -74,7 +72,7 @@ svg.feather.feather-image, .feather .feather-image { display: none }
.tab-nav { zoom: 120%; margin-bottom: 10px; border-bottom: 2px solid var(--highlight-color) !important; padding-bottom: 2px; }
.label-wrap { margin: 16px 0px 8px 0px; }
.gradio-slider input[type="number"] { width: 4.5em; font-size: 0.8rem; height: 20px; }
-.gradio-button.tool { border: none; background: none; box-shadow: none; }
+.gradio-button.tool { border: none; background: none; box-shadow: none; filter: hue-rotate(340deg) saturate(0.5); }
#tab_extensions table td, #tab_extensions table th { border: none; padding: 0.5em; }
#tab_extensions table { width: 96vw }
#tab_extensions table thead { background-color: var(--neutral-700); }
@@ -85,7 +83,9 @@ svg.feather.feather-image, .feather .feather-image { display: none }
.gallery-item { box-shadow: none !important; }
.performance { color: #888; }
.extra-networks { border-left: 2px solid var(--highlight-color) !important; padding-left: 4px; }
-.image-buttons { gap: 10px !important}
+.image-buttons { gap: 10px !important; justify-content: center; }
+.image-buttons > button { max-width: 160px; }
+#system_row > button, #settings_row > button, #config_row > button { max-width: 190px; }
/* gradio elements overrides */
#div.gradio-container { overflow-x: hidden; }
@@ -113,7 +113,6 @@ svg.feather.feather-image, .feather .feather-image { display: none }
#txt2img_results, #img2img_results, #extras_results { background-color: var(--background-color); padding: 0; }
#txt2img_settings { min-width: var(--left-column); max-width: var(--left-column); background-color: #111111; padding-top: 16px; }
#pnginfo_html2_info { margin-top: -18px; background-color: var(--input-background-fill); padding: var(--input-padding) }
-#txt2img_tools > div > button, #img2img_tools > div > button { filter: hue-rotate(340deg) saturate(0.5); }
#txt2img_tools, #img2img_tools { margin-top: -4px; margin-bottom: -4px; }
#txt2img_styles_row, #img2img_styles_row { margin-top: -6px; }
diff --git a/javascript/settings.js b/javascript/settings.js
index d9e96dcf8..1b48491d3 100644
--- a/javascript/settings.js
+++ b/javascript/settings.js
@@ -45,6 +45,7 @@ function markIfModified(setting_name, value) {
const changed_value = previous_value !== current_value;
if (changed_value) elem.title = `click to revert to previous value: ${previous_value}`;
const is_stored = opts_metadata[setting_name].is_stored;
+ if (is_stored) console.log('A', opts_metadata[setting_name]);
if (is_stored) elem.title = 'custom value';
elem.disabled = !changed_value && !is_stored;
elem.classList.toggle('changed', changed_value);
diff --git a/javascript/style.css b/javascript/style.css
index c5a72bfdf..866a1bb5a 100644
--- a/javascript/style.css
+++ b/javascript/style.css
@@ -239,7 +239,7 @@ table.settings-value-table td { padding: 0.4em; border: 1px solid #ccc; max-widt
.extra-network-cards .card { height: fit-content; margin: 0.5em; position: relative; scroll-snap-align: start; scroll-margin-top: 0; }
.extra-network-cards .card .overlay { position: absolute; bottom: 0; padding: 0.2em; z-index: 10; width: 100%; background: none; }
.extra-network-cards .card:hover .overlay { background: rgba(0, 0, 0, 0.40); }
-.extra-network-cards .card .overlay .name { font-size: 1.2em; font-weight: bold; line-break: anywhere; text-shadow: 1px 1px black; color: white; }
+.extra-network-cards .card .overlay .name { font-size: 1.1em; font-weight: bold; text-shadow: 1px 1px black; color: white; }
.extra-network-cards .card .overlay .tags { margin: 4px; display: none; overflow-wrap: break-word; }
.extra-network-cards .card .overlay .tag { padding: 2px; margin: 2px; background: var(--neutral-700); cursor: pointer; display: inline-block; }
.extra-network-cards .card .overlay .actions { font-size: 2.2em; display: none; text-align-last: center; cursor: pointer; font-variant: unicase; height: 0.8em }
diff --git a/modules/loader.py b/modules/loader.py
new file mode 100644
index 000000000..a578ca602
--- /dev/null
+++ b/modules/loader.py
@@ -0,0 +1,37 @@
+from __future__ import annotations
+import re
+import logging
+import warnings
+import urllib3
+from modules import timer, errors
+
+initialized = False
+logging.getLogger("DeepSpeed").disabled = True
+import torch # pylint: disable=C0411
+try:
+ import intel_extension_for_pytorch as ipex # pylint: disable=import-error, unused-import
+except Exception:
+ pass
+errors.log.debug(f'Loaded Torch=={torch.__version__}')
+urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
+import torchvision # pylint: disable=W0611,C0411
+import pytorch_lightning # pytorch_lightning should be imported after torch, but it re-enables warnings on import so import once to disable them # pylint: disable=W0611,C0411
+if ".dev" in torch.__version__ or "+git" in torch.__version__:
+ torch.__long_version__ = torch.__version__
+ torch.__version__ = re.search(r'[\d.]+[\d]', torch.__version__).group(0)
+logging.getLogger("xformers").addFilter(lambda record: 'A matching Triton is not available' not in record.getMessage())
+logging.getLogger("pytorch_lightning").disabled = True
+warnings.filterwarnings(action="ignore", category=DeprecationWarning)
+warnings.filterwarnings(action="ignore", category=FutureWarning)
+warnings.filterwarnings(action="ignore", category=UserWarning, module="torchvision")
+timer.startup.record("torch")
+
+from fastapi import FastAPI # pylint: disable=W0611,C0411
+import gradio # pylint: disable=W0611,C0411
+errors.log.debug(f'Loaded Gradio=={gradio.__version__}')
+timer.startup.record("gradio")
+errors.install([gradio])
+
+import diffusers # pylint: disable=W0611,C0411
+errors.log.debug(f'Loaded Diffusers=={diffusers.__version__}')
+timer.startup.record("diffusers")
diff --git a/modules/modelloader.py b/modules/modelloader.py
index 6468a9c70..fc456882a 100644
--- a/modules/modelloader.py
+++ b/modules/modelloader.py
@@ -244,12 +244,9 @@ def directory_has_changed(dir:str, *, recursive:bool=True) -> bool: # pylint: di
def directory_directories(dir:str, *, recursive:bool=True) -> dict[str,tuple[float,list[str]]]: # pylint: disable=redefined-builtin
dir = os.path.abspath(dir)
if directory_has_changed(dir, recursive=recursive):
- for _dir in modelloader_directories:
- try:
- if (os.path.exists(_dir) and os.path.isdir(_dir)):
- continue
- except Exception:
- pass
+ for _dir in list(modelloader_directories):
+ if os.path.exists(_dir) or os.path.isdir(_dir):
+ continue
del modelloader_directories[_dir]
for _dir, _files in walk(dir, lambda e, path: shared.log.debug(f"FS walk error: {e} {path}")):
try:
diff --git a/modules/processing.py b/modules/processing.py
index 0ab9a8c83..61fa941b1 100644
--- a/modules/processing.py
+++ b/modules/processing.py
@@ -27,6 +27,9 @@ import modules.sd_models as sd_models
import modules.sd_vae as sd_vae
+opt_C = 4
+opt_f = 8
+
def setup_color_correction(image):
shared.log.debug("Calibrating color correction.")
correction_target = cv2.cvtColor(np.asarray(image.copy()), cv2.COLOR_RGB2LAB)
@@ -933,8 +936,8 @@ class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing):
self.extra_generation_params["Hires steps"] = self.hr_second_pass_steps
if self.hr_upscaler is not None:
self.extra_generation_params["Hires upscaler"] = self.hr_upscaler
+ shared.log.debug(f'Init hires: upscaler={self.hr_upscaler} sampler={self.latent_sampler} resize={self.hr_resize_x}x{self.hr_resize_y} upscale={self.hr_upscale_to_x}x{self.hr_upscale_to_y}')
self.extra_generation_params["Secondary sampler"] = self.latent_sampler
- shared.log.debug(f'Init hires: upscaler={self.hr_upscaler} sampler={self.latent_sampler} resize={self.hr_resize_x}x{self.hr_resize_y} upscale={self.hr_upscale_to_x}x{self.hr_upscale_to_y}')
def sample(self, conditioning, unconditional_conditioning, seeds, subseeds, subseed_strength, prompts):
diff --git a/modules/scripts.py b/modules/scripts.py
index bfd04c30e..30136b561 100644
--- a/modules/scripts.py
+++ b/modules/scripts.py
@@ -4,7 +4,7 @@ import sys
import time
from collections import namedtuple
import gradio as gr
-from modules import paths, script_callbacks, extensions, script_loading, scripts_postprocessing, errors
+from modules import paths, script_callbacks, extensions, script_loading, scripts_postprocessing, errors, timer
from installer import log
@@ -226,13 +226,14 @@ def list_files_with_name(filename):
def load_scripts():
+ t = timer.Timer()
+ t0 = time.time()
global current_basedir # pylint: disable=global-statement
scripts_data.clear()
postprocessing_scripts_data.clear()
script_callbacks.clear_callbacks()
scripts_list = list_scripts("scripts", ".py")
syspath = sys.path
- time_load = {}
def register_scripts_from_module(module, scriptfile):
for script_class in module.__dict__.values():
@@ -245,7 +246,6 @@ def load_scripts():
postprocessing_scripts_data.append(ScriptClassData(script_class, scriptfile.path, scriptfile.basedir, module))
for scriptfile in scripts_list:
- t0 = time.time()
try:
if scriptfile.basedir != paths.script_path:
sys.path = [scriptfile.basedir] + sys.path
@@ -256,7 +256,7 @@ def load_scripts():
errors.display(e, f'Loading script: {scriptfile.filename}')
finally:
current_basedir = paths.script_path
- time_load[scriptfile.basedir] = time_load.get(scriptfile.basedir, 0) + (time.time()-t0)
+ t.record(os.path.basename(scriptfile.basedir))
sys.path = syspath
global scripts_txt2img, scripts_img2img, scripts_postproc # pylint: disable=global-statement
@@ -264,8 +264,7 @@ def load_scripts():
scripts_img2img = ScriptRunner()
scripts_postproc = scripts_postprocessing.ScriptPostprocessingRunner()
- time_summary = [f'{os.path.basename(k)}:{round(v,3)}s' for (k,v) in time_load.items() if v > 0.05]
- log.debug(f'Scripts load: {time_summary}')
+ return t, time.time()-t0
def wrap_call(func, filename, funcname, *args, default=None, **kwargs):
diff --git a/modules/sd_models.py b/modules/sd_models.py
index 7c0d79413..597147d9e 100644
--- a/modules/sd_models.py
+++ b/modules/sd_models.py
@@ -403,7 +403,8 @@ def load_model_weights(model: torch.nn.Module, checkpoint_info: CheckpointInfo,
try:
model.load_state_dict(state_dict, strict=False)
except Exception as e:
- shared.log.error(f'Error loading model weights: {checkpoint_info.filename} {e}')
+ shared.log.error(f'Error loading model weights: {checkpoint_info.filename}')
+ shared.log.error(' '.join(str(e).splitlines()[:2]))
return False
del state_dict
timer.record("apply")
@@ -813,7 +814,8 @@ def load_diffuser(checkpoint_info=None, already_loaded_state_dict=None, timer=No
shared.opts.diffusers_move_base=True
shared.opts.diffusers_move_refiner=True
shared.log.debug('Moving base model to CPU')
- model_data.sd_model.to(devices.cpu)
+ if model_data.sd_model is not None:
+ model_data.sd_model.to(devices.cpu)
devices.torch_gc(force=True)
sd_model.to(devices.device)
base_sent_to_cpu=True
@@ -1007,7 +1009,10 @@ def load_model(checkpoint_info=None, already_loaded_state_dict=None, timer=None,
model_data.sd_model = sd_model
current_checkpoint_info = None
unload_model_weights(op=op)
- shared.log.debug(f'Model weights unloaded: {memory_stats()}')
+ shared.log.debug(f'Model weights unloaded: {memory_stats()} op={op}')
+ if op == 'refiner':
+ # shared.opts.data['sd_model_refiner'] = 'None'
+ shared.opts.sd_model_refiner = 'None'
return
else:
shared.log.debug(f'Model weights loaded: {memory_stats()}')
@@ -1062,12 +1067,12 @@ def reload_model_weights(sd_model=None, info=None, reuse_dict=False, op='model')
lowvram.send_everything_to_cpu()
else:
sd_model.to(devices.cpu)
- if (reuse_dict or (shared.opts.model_reuse_dict and sd_model is not None)) and not sd_model.has_accelerate:
- shared.log.info('Reusing previous model dictionary')
- sd_hijack.model_hijack.undo_hijack(sd_model)
- else:
- unload_model_weights(op=op)
- sd_model = None
+ if (reuse_dict or shared.opts.model_reuse_dict) and not sd_model.has_accelerate:
+ shared.log.info('Reusing previous model dictionary')
+ sd_hijack.model_hijack.undo_hijack(sd_model)
+ else:
+ unload_model_weights(op=op)
+ sd_model = None
timer = Timer()
state_dict = get_checkpoint_state_dict(checkpoint_info, timer)
checkpoint_config = sd_models_config.find_checkpoint_config(state_dict, checkpoint_info)
@@ -1095,7 +1100,7 @@ def reload_model_weights(sd_model=None, info=None, reuse_dict=False, op='model')
timer.record("hijack")
script_callbacks.model_loaded_callback(sd_model)
timer.record("callbacks")
- if not shared.cmd_opts.lowvram and not shared.cmd_opts.medvram and not sd_model.has_accelerate:
+ if sd_model is not None and not shared.cmd_opts.lowvram and not shared.cmd_opts.medvram and not sd_model.has_accelerate:
sd_model.to(devices.device)
timer.record("device")
shared.log.info(f"Weights loaded in {timer.summary()}")
diff --git a/modules/shared.py b/modules/shared.py
index 7b5d44692..7eea2b708 100644
--- a/modules/shared.py
+++ b/modules/shared.py
@@ -635,7 +635,7 @@ options_templates.update(options_section(('extra_networks', "Extra Networks"), {
"extra_networks_height": OptionInfo(53, "UI height (%)", gr.Slider, {"minimum": 10, "maximum": 100, "step": 1}),
"extra_networks_sidebar_width": OptionInfo(35, "UI sidebar width (%)", gr.Slider, {"minimum": 10, "maximum": 80, "step": 1}),
"extra_networks_card_lazy": OptionInfo(True, "UI card preview lazy loading"),
- "extra_networks_card_size": OptionInfo(200, "UI card size (px)", gr.Slider, {"minimum": 20, "maximum": 2000, "step": 1}),
+ "extra_networks_card_size": OptionInfo(160, "UI card size (px)", gr.Slider, {"minimum": 20, "maximum": 2000, "step": 1}),
"extra_networks_card_square": OptionInfo(True, "UI disable variable aspect ratio"),
"extra_networks_card_fit": OptionInfo("cover", "UI image contain method", gr.Radio, lambda: {"choices": ["contain", "cover", "fill"]}),
"extra_network_skip_indexing": OptionInfo(False, "Do not automatically build extra network pages", gr.Checkbox),
@@ -767,7 +767,7 @@ class Options:
d = {k: self.data.get(k, self.data_labels.get(k).default) for k in self.data_labels.keys()}
metadata = {
k: {
- "is_stored": k in self.data,
+ "is_stored": k in self.data and self.data[k] != self.data_labels[k].default,
"tab_name": v.section[0]
} for k, v in self.data_labels.items()
}
diff --git a/modules/timer.py b/modules/timer.py
index 17dfac4f0..55a5e29ec 100644
--- a/modules/timer.py
+++ b/modules/timer.py
@@ -21,18 +21,15 @@ class Timer:
self.records[category] += e + extra_time
self.total += e + extra_time
- def summary(self):
- res = f"{self.total:.1f}s"
-
- additions = [x for x in self.records.items() if x[1] >= 0.05]
+ def summary(self, min_time=0.05):
+ res = f"{self.total:.2f}s"
+ additions = [x for x in self.records.items() if x[1] >= min_time]
if not additions:
return res
-
- res += " ("
- res += " ".join([f"{category}={time_taken:.1f}s" for category, time_taken in additions])
- res += ")"
-
+ res += " { " + " ".join([f"{category}={time_taken:.2f}s" for category, time_taken in additions]) + " }"
return res
def reset(self):
self.__init__()
+
+startup = Timer()
diff --git a/modules/ui.py b/modules/ui.py
index 0c914847e..a5a61f7cf 100644
--- a/modules/ui.py
+++ b/modules/ui.py
@@ -16,6 +16,8 @@ from modules.paths import script_path, data_path
from modules.shared import opts, cmd_opts, readfile
from modules.dml import directml_override_opts
from modules import prompt_parser
+from modules import timer
+import modules.ui_symbols as symbols
import modules.codeformer_model
import modules.generation_parameters_copypaste as parameters_copypaste
import modules.gfpgan_model
@@ -50,19 +52,6 @@ sample_img2img = "assets/stable-samples/img2img/sketch-mountains-input.jpg"
sample_img2img = sample_img2img if os.path.exists(sample_img2img) else None
paste_function = None
-# Using constants for these since the variation selector isn't visible.
-# Important that they exactly match script.js for tooltip to work.
-random_symbol = '\U0001f3b2\ufe0f' # 🎲️
-reuse_symbol = '\u267b\ufe0f' # ♻️
-paste_symbol = '\U0001F4D8' # '\u2199\ufe0f' # ↙
-refresh_symbol = '\U0001F504' # 🔄
-save_style_symbol = '\U0001F6C5' # '\U0001f4be' # 💾
-apply_style_symbol = '\U0001F9F3' # '\U0001f4cb' # 📋
-clear_prompt_symbol = '\U0001F6AE' # '\U0001f5d1\ufe0f' # 🗑️
-extra_networks_symbol = '\U0001F310' # '\U0001F3B4' # 🎴
-switch_values_symbol = '\U000021C5' # ⇅
-detect_image_size_symbol = '\U0001F4D0' # 📐
-
def create_output_panel(tabname, outdir): # may be referenced by extensions
a, b, c, _d, e = ui_common.create_output_panel(tabname, outdir)
@@ -161,13 +150,13 @@ def create_seed_inputs(tab, visible):
with FormRow(elem_id=f"{tab}_seed_row", variant="compact"):
seed = gr.Number(label='Seed', value=-1, elem_id=f"{tab}_seed")
seed.style(container=False)
- random_seed = ToolButton(random_symbol, elem_id=f"{tab}_random_seed", label='Random seed')
- reuse_seed = ToolButton(reuse_symbol, elem_id=f"{tab}_reuse_seed", label='Reuse seed')
+ random_seed = ToolButton(symbols.random, elem_id=f"{tab}_random_seed", label='Random seed')
+ reuse_seed = ToolButton(symbols.reuse, elem_id=f"{tab}_reuse_seed", label='Reuse seed')
with FormRow(visible=True, elem_id=f"{tab}_subseed_row"):
subseed = gr.Number(label='Variation seed', value=-1, elem_id=f"{tab}_subseed")
subseed.style(container=False)
- random_subseed = ToolButton(random_symbol, elem_id=f"{tab}_random_subseed")
- reuse_subseed = ToolButton(reuse_symbol, elem_id=f"{tab}_reuse_subseed")
+ random_subseed = ToolButton(symbols.random, elem_id=f"{tab}_random_subseed")
+ reuse_subseed = ToolButton(symbols.reuse, elem_id=f"{tab}_reuse_subseed")
subseed_strength = gr.Slider(label='Variation strength', value=0.0, minimum=0, maximum=1, step=0.01, elem_id=f"{tab}_subseed_strength")
with FormRow(visible=False):
seed_resize_from_w = gr.Slider(minimum=0, maximum=4096, step=8, label="Resize seed from width", value=0, elem_id=f"{tab}_seed_resize_from_w")
@@ -268,11 +257,11 @@ def create_toprow(is_img2img):
pause = gr.Button('Pause', elem_id=f"{id_part}_pause")
pause.click(fn=lambda: modules.shared.state.pause(), _js='checkPaused', inputs=[], outputs=[])
with gr.Row(elem_id=f"{id_part}_tools"):
- paste = ToolButton(value=paste_symbol, elem_id="paste")
- clear_prompt_button = ToolButton(value=clear_prompt_symbol, elem_id=f"{id_part}_clear_prompt_btn")
- extra_networks_button = ToolButton(value=extra_networks_symbol, elem_id=f"{id_part}_extra_networks_btn")
- prompt_style_apply = ToolButton(value=apply_style_symbol, elem_id=f"{id_part}_style_apply_btn")
- save_style = ToolButton(value=save_style_symbol, elem_id=f"{id_part}_style_create_btn")
+ paste = ToolButton(value=symbols.paste, elem_id="paste")
+ clear_prompt_button = ToolButton(value=symbols.clear, elem_id=f"{id_part}_clear_prompt_btn")
+ extra_networks_button = ToolButton(value=symbols.networks, elem_id=f"{id_part}_extra_networks_btn")
+ prompt_style_apply = ToolButton(value=symbols.apply, elem_id=f"{id_part}_style_apply_btn")
+ save_style = ToolButton(value=symbols.save, elem_id=f"{id_part}_style_create_btn")
clear_prompt_button.click(fn=lambda *x: x, _js="confirm_clear_prompt", inputs=[prompt, negative_prompt], outputs=[prompt, negative_prompt])
with gr.Row(elem_id=f"{id_part}_counters"):
token_counter = gr.HTML(value="0/75", elem_id=f"{id_part}_token_counter", elem_classes=["token-counter"])
@@ -348,8 +337,7 @@ def create_override_settings_dropdown(tabname, row): # pylint: disable=unused-ar
def create_ui(startup_timer = None):
if startup_timer is None:
- from modules import timer
- startup_timer = timer.Timer()
+ timer.startup = timer.Timer()
reload_javascript()
parameters_copypaste.reset()
ui_defaults = readfile(cmd_opts.ui_config)
@@ -372,7 +360,7 @@ def create_ui(startup_timer = None):
with FormRow():
width = gr.Slider(minimum=64, maximum=4096, step=8, label="Width", value=512, elem_id="txt2img_width")
height = gr.Slider(minimum=64, maximum=4096, step=8, label="Height", value=512, elem_id="txt2img_height")
- res_switch_btn = ToolButton(value=switch_values_symbol, elem_id="txt2img_res_switch_btn", label="Switch dims")
+ res_switch_btn = ToolButton(value=symbols.switch, elem_id="txt2img_res_switch_btn", label="Switch dims")
with FormRow(elem_classes="checkboxes-row", variant="compact"):
show_batch = gr.Checkbox(label='Batch', value=ui_defaults.get('txt2img/Batch/value', False), elem_id="txt2img_show_batch")
@@ -384,7 +372,7 @@ def create_ui(startup_timer = None):
with FormRow(elem_id="txt2img_row_batch"):
batch_count = gr.Slider(minimum=1, step=1, label='Batch count', value=1, elem_id="txt2img_batch_count")
batch_size = gr.Slider(minimum=1, maximum=32, step=1, label='Batch size', value=1, elem_id="txt2img_batch_size")
- batch_switch_btn = ToolButton(value=switch_values_symbol, elem_id="txt2img_batch_switch_btn", label="Switch dims")
+ batch_switch_btn = ToolButton(value=symbols.switch, elem_id="txt2img_batch_switch_btn", label="Switch dims")
seed_group, seed, reuse_seed, subseed, reuse_subseed, subseed_strength, seed_resize_from_h, seed_resize_from_w = create_seed_inputs('txt2img', show_seed.value)
@@ -535,7 +523,7 @@ def create_ui(startup_timer = None):
ui_extra_networks.setup_ui(extra_networks_ui, txt2img_gallery)
log.debug(f'UI interface: tab=txt2img batch={show_batch.value} seed={show_seed.value} advanced={show_advanced.value} second_pass={show_second_pass.value}')
- startup_timer.record("ui-txt2img")
+ timer.startup.record("ui-txt2img")
import modules.img2img # pylint: disable=redefined-outer-name
modules.scripts.scripts_current = modules.scripts.scripts_img2img
@@ -647,8 +635,8 @@ def create_ui(startup_timer = None):
height = gr.Slider(minimum=64, maximum=4096, step=8, label="Height", value=512, elem_id="img2img_height")
with gr.Column(elem_id="img2img_column_dim", scale=1, elem_classes="dimensions-tools"):
with FormRow():
- res_switch_btn = ToolButton(value=switch_values_symbol, elem_id="img2img_res_switch_btn")
- detect_image_size_btn = ToolButton(value=detect_image_size_symbol, elem_id="img2img_detect_image_size_btn")
+ res_switch_btn = ToolButton(value=symbols.switch, elem_id="img2img_res_switch_btn")
+ detect_image_size_btn = ToolButton(value=symbols.detect, elem_id="img2img_detect_image_size_btn")
with gr.Tab(label="Resize by") as tab_scale_by:
scale_by = gr.Slider(minimum=0.05, maximum=4.0, step=0.05, label="Scale", value=1.0, elem_id="img2img_scale")
@@ -895,21 +883,21 @@ def create_ui(startup_timer = None):
log.debug(f'UI interface: tab=img2img seed={show_seed.value} resize={show_resize.value} batch={show_batch.value} denoise={show_denoise.value} advanced={show_advanced.value}')
- startup_timer.record("ui-img2img")
+ timer.startup.record("ui-img2img")
modules.scripts.scripts_current = None
with gr.Blocks(analytics_enabled=False) as extras_interface:
ui_postprocessing.create_ui()
- startup_timer.record("ui-extras")
+ timer.startup.record("ui-extras")
with gr.Blocks(analytics_enabled=False) as train_interface:
ui_train.create_ui(txt2img_preview_params = [txt2img_prompt, txt2img_negative_prompt, steps, sampler_index, cfg_scale, seed, width, height])
- startup_timer.record("ui-train")
+ timer.startup.record("ui-train")
with gr.Blocks(analytics_enabled=False) as models_interface:
ui_models.create_ui()
- startup_timer.record("ui-models")
+ timer.startup.record("ui-models")
def create_setting_component(key, is_quicksettings=False):
def fun():
@@ -1015,7 +1003,7 @@ def create_ui(startup_timer = None):
return get_value_for_setting(key), opts.dumpjson()
with gr.Blocks(analytics_enabled=False) as settings_interface:
- with gr.Row():
+ with gr.Row(elem_id="system_row"):
restart_submit = gr.Button(value="Restart server", variant='primary', elem_id="restart_submit")
shutdown_submit = gr.Button(value="Shutdown server", variant='primary', elem_id="shutdown_submit")
unload_sd_model = gr.Button(value='Unload checkpoint', variant='primary', elem_id="sett_unload_sd_model")
@@ -1025,7 +1013,7 @@ def create_ui(startup_timer = None):
global ui_system_tabs # pylint: disable=global-statement
ui_system_tabs = system_tabs
with gr.TabItem("Settings", id="system_settings", elem_id="tab_settings"):
- with gr.Row():
+ with gr.Row(elem_id="settings_row"):
settings_submit = gr.Button(value="Apply settings", variant='primary', elem_id="settings_submit")
preview_theme = gr.Button(value="Preview theme", variant='primary', elem_id="settings_preview_theme")
defaults_submit = gr.Button(value="Restore defaults", variant='primary', elem_id="defaults_submit")
@@ -1096,7 +1084,7 @@ def create_ui(startup_timer = None):
request_notifications.click(fn=lambda: None, inputs=[], outputs=[], _js='function(){}')
preview_theme.click(fn=None, _js='preview_theme', inputs=[dummy_component], outputs=[dummy_component])
- startup_timer.record("ui-settings")
+ timer.startup.record("ui-settings")
interfaces = [
(txt2img_interface, "From Text", "txt2img"),
@@ -1109,7 +1097,7 @@ def create_ui(startup_timer = None):
interfaces += [(settings_interface, "System", "system")]
extensions_interface = ui_extensions.create_ui()
interfaces += [(extensions_interface, "Extensions", "extensions")]
- startup_timer.record("ui-extensions")
+ timer.startup.record("ui-extensions")
modules.shared.tab_names = []
for _interface, label, _ifid in interfaces:
@@ -1183,7 +1171,7 @@ def create_ui(startup_timer = None):
queue=False,
)
- startup_timer.record("ui-defaults")
+ timer.startup.record("ui-defaults")
loadsave.dump_defaults()
demo.ui_loadsave = loadsave
return demo
diff --git a/modules/ui_common.py b/modules/ui_common.py
index 1b0484cc0..58ea9f8f8 100644
--- a/modules/ui_common.py
+++ b/modules/ui_common.py
@@ -7,12 +7,10 @@ import subprocess
import gradio as gr
from modules import call_queue, shared
from modules.generation_parameters_copypaste import image_from_url_text
+import modules.ui_symbols as symbols
import modules.images
-folder_symbol = '\U0001f4c2' # 📂
-
-
def update_generation_info(generation_info, html_info, img_index):
try:
generation_info = json.loads(generation_info)
@@ -224,7 +222,6 @@ def create_refresh_button(refresh_component, refresh_method, refreshed_args, ele
return gr.update(**(args or {}))
from modules.ui_components import ToolButton
- refresh_symbol = '\U0001f504' # 🔄
- refresh_button = ToolButton(value=refresh_symbol, elem_id=elem_id)
+ refresh_button = ToolButton(value=symbols.refresh, elem_id=elem_id)
refresh_button.click(fn=refresh, inputs=[], outputs=[refresh_component])
return refresh_button
diff --git a/modules/ui_extra_networks.py b/modules/ui_extra_networks.py
index c38b3abdd..b8e473593 100644
--- a/modules/ui_extra_networks.py
+++ b/modules/ui_extra_networks.py
@@ -13,15 +13,13 @@ from starlette.responses import FileResponse, JSONResponse
from modules import shared, scripts, modelloader
from modules.generation_parameters_copypaste import image_from_url_text
from modules.ui_components import ToolButton
+import modules.ui_symbols as symbols
extra_pages = []
allowed_dirs = set()
dir_cache = {} # key=path, value=(mtime, listdir(path))
-refresh_symbol = '\U0001f504' # 🔄
-close_symbol = '\U0000274C' # ❌
-
def listdir(path):
if not os.path.exists(path):
@@ -344,8 +342,8 @@ def create_ui(container, button, tabname, skip_indexing = False):
ui.stored_extra_pages = extra_pages
ui.tabname = tabname
with gr.Tabs(elem_id=tabname+"_extra_tabs"):
- button_refresh = ToolButton(refresh_symbol, elem_id=tabname+"_extra_refresh")
- button_close = ToolButton(close_symbol, elem_id=tabname+"_extra_close")
+ button_refresh = ToolButton(symbols.refresh, elem_id=tabname+"_extra_refresh")
+ button_close = ToolButton(symbols.close, elem_id=tabname+"_extra_close")
ui.search = gr.Textbox('', show_label=False, elem_id=tabname+"_extra_search", placeholder="Search...", elem_classes="textbox", lines=1)
ui.description = gr.TextArea('', show_label=False, elem_id=tabname+"_description", placeholder="Save/Replace Extra Network Description...", elem_classes="textbox", lines=1)
ui.preview_target_filename = gr.Textbox('Preview save filename', elem_id=tabname+"_preview_filename", visible=False)
diff --git a/modules/ui_loadsave.py b/modules/ui_loadsave.py
index 4d8514d02..b0c647e05 100644
--- a/modules/ui_loadsave.py
+++ b/modules/ui_loadsave.py
@@ -174,7 +174,7 @@ class UiLoadsave:
def create_ui(self):
"""creates ui elements for editing defaults UI, without adding any logic to them"""
gr.HTML(f"Review changed values and apply them as new user interface defaults
Config file: {self.filename}")
- with gr.Row():
+ with gr.Row(elem_id="config_row"):
self.ui_defaults_view = gr.Button(value='View changes', elem_id="ui_defaults_view", variant="secondary")
self.ui_defaults_apply = gr.Button(value='Set new defaults', elem_id="ui_defaults_apply", variant="primary")
self.ui_defaults_restore = gr.Button(value='Restore system defaults', elem_id="ui_defaults_restore", variant="primary")
diff --git a/modules/ui_symbols.py b/modules/ui_symbols.py
new file mode 100644
index 000000000..86b9a5e64
--- /dev/null
+++ b/modules/ui_symbols.py
@@ -0,0 +1,14 @@
+refresh = '🔄'
+close = '🛗'
+load = '⬆️'
+save = '⬇️'
+apply = '⏩'
+clear = '🚮'
+fill = '⏫'
+networks = '🌐'
+switch = '⇅'
+detect = '📐'
+folder = '📂'
+random = '🎲️'
+reuse = '♻️'
+paste = '📘'
diff --git a/scripts/postprocessing_upscale.py b/scripts/postprocessing_upscale.py
index fd9ccd893..12996eb09 100644
--- a/scripts/postprocessing_upscale.py
+++ b/scripts/postprocessing_upscale.py
@@ -3,7 +3,8 @@ import numpy as np
import gradio as gr
from modules import scripts_postprocessing, shared
from modules.ui_components import FormRow, ToolButton
-from modules.ui import switch_values_symbol
+import modules.ui_symbols as symbols
+
upscale_cache = {}
@@ -26,7 +27,7 @@ class ScriptPostprocessingUpscale(scripts_postprocessing.ScriptPostprocessing):
with gr.Row(elem_id="upscaling_column_size", scale=4):
upscaling_resize_w = gr.Slider(minimum=64, maximum=4096, step=8, label="Width", value=512, elem_id="extras_upscaling_resize_w")
upscaling_resize_h = gr.Slider(minimum=64, maximum=4096, step=8, label="Height", value=512, elem_id="extras_upscaling_resize_h")
- upscaling_res_switch_btn = ToolButton(value=switch_values_symbol, elem_id="upscaling_res_switch_btn")
+ upscaling_res_switch_btn = ToolButton(value=symbols.switch, elem_id="upscaling_res_switch_btn")
upscaling_crop = gr.Checkbox(label='Crop to fit', value=True, elem_id="extras_upscaling_crop")
with FormRow():
@@ -114,7 +115,6 @@ class ScriptPostprocessingUpscaleSimple(ScriptPostprocessingUpscale):
with FormRow():
upscaler_name = gr.Dropdown(label='Upscaler', choices=[x.name for x in shared.sd_upscalers], value=shared.sd_upscalers[0].name)
upscale_by = gr.Slider(minimum=0.05, maximum=8.0, step=0.05, label="Upscale by", value=2)
-
return {
"upscale_by": upscale_by,
"upscaler_name": upscaler_name,
@@ -123,10 +123,8 @@ class ScriptPostprocessingUpscaleSimple(ScriptPostprocessingUpscale):
def process(self, pp: scripts_postprocessing.PostprocessedImage, upscale_by=2.0, upscaler_name=None): # pylint: disable=arguments-differ
if upscaler_name is None or upscaler_name == "None":
return
-
upscaler1 = next(iter([x for x in shared.sd_upscalers if x.name == upscaler_name]), None)
if upscaler1 is None:
shared.log.debug(f"Upscaler not found: {upscaler_name}")
-
pp.image = self.upscale(pp.image, pp.info, upscaler1, 0, upscale_by, 0, 0, False)
pp.info["Postprocess upscaler"] = upscaler1.name
diff --git a/scripts/xyz_grid.py b/scripts/xyz_grid.py
index aee489013..57ad5bab5 100644
--- a/scripts/xyz_grid.py
+++ b/scripts/xyz_grid.py
@@ -15,9 +15,7 @@ import modules.shared as shared
from modules import images, sd_samplers, processing, sd_models, sd_vae
from modules.processing import process_images, Processed, StableDiffusionProcessingTxt2Img
from modules.ui_components import ToolButton
-
-fill_values_symbol = "\U0001f4d2" # 📒
-AxisInfo = namedtuple('AxisInfo', ['axis', 'values'])
+import modules.ui_symbols as symbols
def apply_field(field):
@@ -387,19 +385,19 @@ class Script(scripts.Script):
x_type = gr.Dropdown(label="X type", choices=[x.label for x in self.current_axis_options], value=self.current_axis_options[0].label, type="index", elem_id=self.elem_id("x_type"))
x_values = gr.Textbox(label="X values", lines=1, elem_id=self.elem_id("x_values"))
x_values_dropdown = gr.Dropdown(label="X values",visible=False,multiselect=True,interactive=True)
- fill_x_button = ToolButton(value=fill_values_symbol, elem_id="xyz_grid_fill_x_tool_button", visible=False)
+ fill_x_button = ToolButton(value=symbols.fill, elem_id="xyz_grid_fill_x_tool_button", visible=False)
with gr.Row():
y_type = gr.Dropdown(label="Y type", choices=[x.label for x in self.current_axis_options], value=self.current_axis_options[0].label, type="index", elem_id=self.elem_id("y_type"))
y_values = gr.Textbox(label="Y values", lines=1, elem_id=self.elem_id("y_values"))
y_values_dropdown = gr.Dropdown(label="Y values",visible=False,multiselect=True,interactive=True)
- fill_y_button = ToolButton(value=fill_values_symbol, elem_id="xyz_grid_fill_y_tool_button", visible=False)
+ fill_y_button = ToolButton(value=symbols.fill, elem_id="xyz_grid_fill_y_tool_button", visible=False)
with gr.Row():
z_type = gr.Dropdown(label="Z type", choices=[x.label for x in self.current_axis_options], value=self.current_axis_options[0].label, type="index", elem_id=self.elem_id("z_type"))
z_values = gr.Textbox(label="Z values", lines=1, elem_id=self.elem_id("z_values"))
z_values_dropdown = gr.Dropdown(label="Z values",visible=False,multiselect=True,interactive=True)
- fill_z_button = ToolButton(value=fill_values_symbol, elem_id="xyz_grid_fill_z_tool_button", visible=False)
+ fill_z_button = ToolButton(value=symbols.fill, elem_id="xyz_grid_fill_z_tool_button", visible=False)
with gr.Row(variant="compact", elem_id="axis_options"):
draw_legend = gr.Checkbox(label='Draw legend', value=True, elem_id=self.elem_id("draw_legend"))
no_fixed_seeds = gr.Checkbox(label='Keep random for seeds', value=False, elem_id=self.elem_id("no_fixed_seeds"))
@@ -570,6 +568,7 @@ class Script(scripts.Script):
total_steps *= p.n_iter
image_cell_count = p.n_iter * p.batch_size
shared.log.info(f"XYZ grid: images={len(xs)*len(ys)*len(zs)*image_cell_count} grid={len(zs)} {len(xs)}x{len(ys)} cells={len(zs)} steps={total_steps}")
+ AxisInfo = namedtuple('AxisInfo', ['axis', 'values'])
shared.state.xyz_plot_x = AxisInfo(x_opt, xs)
shared.state.xyz_plot_y = AxisInfo(y_opt, ys)
shared.state.xyz_plot_z = AxisInfo(z_opt, zs)
diff --git a/webui.py b/webui.py
index c8d1214ca..37bba31d1 100644
--- a/webui.py
+++ b/webui.py
@@ -1,51 +1,18 @@
-from __future__ import annotations
import os
-import re
import sys
import glob
import signal
import asyncio
import logging
-import warnings
import importlib
from threading import Thread
-import urllib3
+import modules.loader
+import torch # pylint: disable=wrong-import-order
from modules import timer, errors, paths # pylint: disable=unused-import
-startup_timer = timer.Timer()
local_url = None
-
-logging.getLogger("DeepSpeed").disabled = True
-import torch # pylint: disable=C0411
-try:
- import intel_extension_for_pytorch as ipex # pylint: disable=import-error, unused-import
-except Exception:
- pass
-errors.log.debug(f'Loaded Torch=={torch.__version__}')
-urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
-import torchvision # pylint: disable=W0611,C0411
-import pytorch_lightning # pytorch_lightning should be imported after torch, but it re-enables warnings on import so import once to disable them # pylint: disable=W0611,C0411
-if ".dev" in torch.__version__ or "+git" in torch.__version__:
- torch.__long_version__ = torch.__version__
- torch.__version__ = re.search(r'[\d.]+[\d]', torch.__version__).group(0)
-logging.getLogger("xformers").addFilter(lambda record: 'A matching Triton is not available' not in record.getMessage())
-logging.getLogger("pytorch_lightning").disabled = True
-warnings.filterwarnings(action="ignore", category=DeprecationWarning)
-warnings.filterwarnings(action="ignore", category=FutureWarning)
-warnings.filterwarnings(action="ignore", category=UserWarning, module="torchvision")
-startup_timer.record("torch")
-
-from fastapi import FastAPI # pylint: disable=W0611,C0411
-import gradio # pylint: disable=W0611,C0411
-errors.log.debug(f'Loaded Gradio=={gradio.__version__}')
-startup_timer.record("gradio")
-errors.install([gradio])
-
-import diffusers # pylint: disable=W0611,C0411
-errors.log.debug(f'Loaded Diffusers=={diffusers.__version__}')
-startup_timer.record("diffusers")
-
-errors.log.debug('Loading Modules')
+if not modules.loader.initialized:
+ errors.log.debug('Loading modules')
from installer import log, setup_logging, git_commit
import ldm.modules.encoders.modules # pylint: disable=W0611,C0411,E0401
from modules.call_queue import queue_lock, wrap_queued_call, wrap_gradio_gpu_call # pylint: disable=W0611,C0411,C0412
@@ -71,10 +38,12 @@ import modules.ui
from modules.shared import cmd_opts, opts
import modules.hypernetworks.hypernetwork
from modules.middleware import setup_middleware
-startup_timer.record("libraries")
-log.info('Libraries loaded')
-log.setLevel(logging.DEBUG if cmd_opts.debug else logging.INFO)
-logging.disable(logging.NOTSET if cmd_opts.debug else logging.DEBUG)
+
+if not modules.loader.initialized:
+ timer.startup.record("libraries")
+ log.info('Loaded librareis')
+ log.setLevel(logging.DEBUG if cmd_opts.debug else logging.INFO)
+ logging.disable(logging.NOTSET if cmd_opts.debug else logging.DEBUG)
if cmd_opts.server_name:
server_name = cmd_opts.server_name
else:
@@ -92,7 +61,7 @@ fastapi_args = {
"deepLinking": False,
}
}
-
+modules.loader.initialized = True
def check_rollback_vae():
if shared.cmd_opts.rollback_vae:
@@ -113,37 +82,38 @@ def initialize():
check_rollback_vae()
modules.sd_samplers.list_samplers()
- startup_timer.record("samplers")
+ timer.startup.record("samplers")
modules.sd_vae.refresh_vae_list()
- startup_timer.record("vae")
+ timer.startup.record("vae")
extensions.list_extensions()
- startup_timer.record("extensions")
+ timer.startup.record("extensions")
modelloader.cleanup_models()
modules.sd_models.setup_model()
- startup_timer.record("models")
+ timer.startup.record("models")
codeformer.setup_model(opts.codeformer_models_path)
- startup_timer.record("codeformer")
+ timer.startup.record("codeformer")
gfpgan.setup_model(opts.gfpgan_models_path)
- startup_timer.record("gfpgan")
+ timer.startup.record("gfpgan")
- log.debug('Loading scripts')
- modules.scripts.load_scripts()
- startup_timer.record("scripts")
+ log.debug('Loading extensions')
+ t_timer, t_total = modules.scripts.load_scripts()
+ timer.startup.record("extensions")
+ timer.startup.records["extensions"] = t_total # scripts can reset the time
+ setup_logging() # reset since scripts can hijaack logging
+ log.info(f'Extensions time: {t_timer.summary()}')
modelloader.load_upscalers()
- startup_timer.record("upscalers")
-
- setup_logging() # needs a reset since scripts can hijaack logging
+ timer.startup.record("upscalers")
shared.opts.onchange("sd_vae", wrap_queued_call(lambda: modules.sd_vae.reload_vae_weights()), call=False)
shared.opts.onchange("temp_dir", ui_tempdir.on_tmpdir_changed)
shared.opts.onchange("gradio_theme", shared.reload_gradio_theme)
- startup_timer.record("onchange")
+ timer.startup.record("onchange")
modules.textual_inversion.textual_inversion.list_textual_inversion_templates()
shared.reload_hypernetworks()
@@ -152,7 +122,7 @@ def initialize():
ui_extra_networks.register_default_pages()
extra_networks.initialize()
extra_networks.register_default_extra_networks()
- startup_timer.record("extra-networks")
+ timer.startup.record("extra-networks")
if cmd_opts.tls_keyfile is not None and cmd_opts.tls_certfile is not None:
try:
@@ -165,7 +135,7 @@ def initialize():
log.error("TLS setup invalid, running webui without TLS")
else:
log.info("Running with TLS")
- startup_timer.record("tls")
+ timer.startup.record("tls")
# make the program just exit at ctrl+c without waiting for anything
def sigint_handler(_sig, _frame):
@@ -198,7 +168,7 @@ def load_model():
shared.opts.onchange("sd_model_dict", wrap_queued_call(lambda: modules.sd_models.reload_model_weights(op='dict')), call=False)
shared.opts.onchange("sd_vae", wrap_queued_call(lambda: modules.sd_vae.reload_vae_weights()), call=False)
shared.opts.onchange("sd_backend", wrap_queued_call(lambda: modules.sd_models.change_backend()), call=False)
- startup_timer.record("checkpoint")
+ timer.startup.record("checkpoint")
def create_api(app):
@@ -247,15 +217,15 @@ def start_common():
initialize()
if shared.opts.clean_temp_dir_at_start:
ui_tempdir.cleanup_tmpdr()
- startup_timer.record("cleanup")
+ timer.startup.record("cleanup")
def start_ui():
log.debug('Creating UI')
modules.script_callbacks.before_ui_callback()
- startup_timer.record("before-ui")
- shared.demo = modules.ui.create_ui(startup_timer)
- startup_timer.record("ui")
+ timer.startup.record("before-ui")
+ shared.demo = modules.ui.create_ui(timer.startup)
+ timer.startup.record("ui")
if cmd_opts.disable_queue:
log.info('Server queues disabled')
shared.demo.progress_tracking = False
@@ -303,19 +273,20 @@ def start_ui():
setup_middleware(app, cmd_opts)
if cmd_opts.subpath:
+ import gradio
gradio.mount_gradio_app(app, shared.demo, path=f"/{cmd_opts.subpath}")
shared.log.info(f'Redirector mounted: /{cmd_opts.subpath}')
- startup_timer.record("launch")
+ timer.startup.record("launch")
modules.progress.setup_progress_api(app)
create_api(app)
- startup_timer.record("api")
+ timer.startup.record("api")
ui_extra_networks.add_pages_to_demo(app)
modules.script_callbacks.app_started_callback(shared.demo, app)
- startup_timer.record("app-started")
+ timer.startup.record("app-started")
time_setup = [f'{k}:{round(v,3)}s' for (k,v) in modules.scripts.time_setup.items() if v > 0.005]
shared.log.debug(f'Scripts setup: {time_setup}')
@@ -333,7 +304,7 @@ def webui(restart=False):
modules.sd_models.write_metadata()
load_model()
shared.opts.save(shared.config_filename)
- log.info(f"Startup time: {startup_timer.summary()}")
+ log.info(f"Startup time: {timer.startup.summary()}")
if not restart:
# override all loggers to use the same handlers as the main logger
@@ -356,13 +327,14 @@ def webui(restart=False):
def api_only():
start_common()
+ from fastapi import FastAPI
app = FastAPI(**fastapi_args)
setup_middleware(app, cmd_opts)
api = create_api(app)
api.wants_restart = False
modules.script_callbacks.app_started_callback(None, app)
modules.sd_models.write_metadata()
- log.info(f"Startup time: {startup_timer.summary()}")
+ log.info(f"Startup time: {timer.startup.summary()}")
server = api.launch()
return server