diff --git a/CHANGELOG.md b/CHANGELOG.md index 3211a4752..1931bd2b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -124,6 +124,7 @@ ### Fixes - add `SD_NO_CACHE=true` env variable to disable file/folder caching +- add settings -> networks -> embeddings -> enable/disable - update `diffusers` - fix README links - fix sdxl controlnet single-file loader diff --git a/modules/errors.py b/modules/errors.py index 527884cf1..5f2c54cb7 100644 --- a/modules/errors.py +++ b/modules/errors.py @@ -59,14 +59,14 @@ def exception(suppress=[]): console.print_exception(show_locals=False, max_frames=16, extra_lines=2, suppress=suppress, theme="ansi_dark", word_wrap=False, width=min([console.width, 200])) -def profile(profiler, msg: str, n: int = 5): +def profile(profiler, msg: str, n: int = 16): profiler.disable() import io import pstats stream = io.StringIO() # pylint: disable=abstract-class-instantiated p = pstats.Stats(profiler, stream=stream) p.sort_stats(pstats.SortKey.CUMULATIVE) - p.print_stats(100) + p.print_stats(200) # p.print_title() # p.print_call_heading(10, 'time') # p.print_callees(10) @@ -81,6 +81,7 @@ def profile(profiler, msg: str, n: int = 5): and '_lsprof' not in x and '/profiler' not in x and 'rich' not in x + and 'profile_torch' not in x and x.strip() != '' ] txt = '\n'.join(lines[:min(n, len(lines))]) diff --git a/modules/ipadapter.py b/modules/ipadapter.py index d5bfbec8c..4e93a6eee 100644 --- a/modules/ipadapter.py +++ b/modules/ipadapter.py @@ -14,6 +14,7 @@ from modules import processing, shared, devices, sd_models clip_repo = "h94/IP-Adapter" clip_loaded = None +adapters_loaded = [] ADAPTERS_NONE = { 'None': { 'name': 'none', 'repo': 'none', 'subfolder': 'none' }, } @@ -129,9 +130,12 @@ def crop_images(images, crops): def unapply(pipe): # pylint: disable=arguments-differ + if len(adapters_loaded) == 0: + return try: if hasattr(pipe, 'set_ip_adapter_scale'): pipe.set_ip_adapter_scale(0) + pipe.unload_ip_adapter() if hasattr(pipe, 'unet') and hasattr(pipe.unet, 'config') and pipe.unet.config.encoder_hid_dim_type == 'ip_image_proj': pipe.unet.encoder_hid_proj = None pipe.config.encoder_hid_dim_type = None @@ -141,7 +145,7 @@ def unapply(pipe): # pylint: disable=arguments-differ def apply(pipe, p: processing.StableDiffusionProcessing, adapter_names=[], adapter_scales=[1.0], adapter_crops=[False], adapter_starts=[0.0], adapter_ends=[1.0], adapter_images=[]): - global clip_loaded # pylint: disable=global-statement + global clip_loaded, adapters_loaded # pylint: disable=global-statement # overrides if hasattr(p, 'ip_adapter_names'): if isinstance(p.ip_adapter_names, str): @@ -274,6 +278,7 @@ def apply(pipe, p: processing.StableDiffusionProcessing, adapter_names=[], adapt subfolders = [adapter['subfolder'] for adapter in adapters] names = [adapter['name'] for adapter in adapters] pipe.load_ip_adapter(repos, subfolder=subfolders, weight_name=names) + adapters_loaded = names if hasattr(p, 'ip_adapter_layers'): pipe.set_ip_adapter_scale(p.ip_adapter_layers) ip_str = ';'.join(adapter_names) + ':' + json.dumps(p.ip_adapter_layers) diff --git a/modules/processing.py b/modules/processing.py index b4839e402..4bc5e3c81 100644 --- a/modules/processing.py +++ b/modules/processing.py @@ -179,6 +179,8 @@ def process_images(p: StableDiffusionProcessing) -> Processed: timer.process.record('pre') if shared.cmd_opts.profile: + timer.startup.profile = True + timer.process.profile = True with context_hypertile_vae(p), context_hypertile_unet(p): import torch.profiler # pylint: disable=redefined-outer-name activities=[torch.profiler.ProfilerActivity.CPU] @@ -476,7 +478,7 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed: p.scripts.postprocess(p, processed) timer.process.record('post') if not p.disable_extra_networks: - shared.log.info(f'Processed: images={len(output_images)} its={(p.steps * len(output_images)) / (t1 - t0):.2f} time={t1-t0:.2f} timers={timer.process.dct(min_time=0.02)} memory={memstats.memory_stats()}') + shared.log.info(f'Processed: images={len(output_images)} its={(p.steps * len(output_images)) / (t1 - t0):.2f} time={t1-t0:.2f} timers={timer.process.dct()} memory={memstats.memory_stats()}') devices.torch_gc(force=True) return processed diff --git a/modules/processing_diffusers.py b/modules/processing_diffusers.py index adb047511..581589262 100644 --- a/modules/processing_diffusers.py +++ b/modules/processing_diffusers.py @@ -4,6 +4,7 @@ import time import numpy as np import torch import torchvision.transforms.functional as TF +from PIL import Image from modules import shared, devices, processing, sd_models, errors, sd_hijack_hypertile, processing_vae, sd_models_compile, hidiffusion, timer, modelstats, extra_networks from modules.processing_helpers import resize_hires, calculate_base_steps, calculate_hires_steps, calculate_refiner_steps, save_intermediate, update_sampler, is_txt2img, is_refiner_enabled from modules.processing_args import set_pipeline_args @@ -447,6 +448,9 @@ def process_diffusers(p: processing.StableDiffusionProcessing): sd_models_compile.openvino_recompile_model(p, hires=False, refiner=False) # recompile if a parameter changes + if hasattr(p, 'dummy'): + images = [Image.new(mode='RGB', size=(p.width, p.height))] + return images if 'base' not in p.skip: output = process_base(p) else: diff --git a/modules/prompt_parser_diffusers.py b/modules/prompt_parser_diffusers.py index 8c140e0d6..4e31c747a 100644 --- a/modules/prompt_parser_diffusers.py +++ b/modules/prompt_parser_diffusers.py @@ -63,6 +63,8 @@ class PromptEmbedder: self.positive_schedule = None self.negative_schedule = None self.scheduled_prompt = False + if hasattr(p, 'dummy'): + return earlyout = self.checkcache(p) if earlyout: return diff --git a/modules/shared.py b/modules/shared.py index 2a1e8c19d..c3fc4e905 100644 --- a/modules/shared.py +++ b/modules/shared.py @@ -931,8 +931,11 @@ options_templates.update(options_section(('extra_networks', "Networks"), { "extra_networks_styles_sep": OptionInfo("