diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c7342617..3ae82df35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -140,6 +140,7 @@ For details, see [ChangeLog](https://github.com/vladmandic/automatic/blob/master - **Detailer** add option to merge multiple results from each detailer model for example, hands model can result in two hands each being processed separately or both hands can be merged into one composite job - **Control** auto-update width/height on image upload + - **Control** auto-determine image save path depending on operations performed - autodetect **V-prediction** models and override default sampler prediction type as needed - **SDNQ** - use inference context during quantization diff --git a/extensions-builtin/sdnext-modernui b/extensions-builtin/sdnext-modernui index e51d35da7..e03553419 160000 --- a/extensions-builtin/sdnext-modernui +++ b/extensions-builtin/sdnext-modernui @@ -1 +1 @@ -Subproject commit e51d35da7ceb4b01d733a46850a434cc56975af6 +Subproject commit e03553419cc8daf1d0bcf0e72f1c44e4dc6b5c1a diff --git a/modules/control/run.py b/modules/control/run.py index f66df8399..9690843f3 100644 --- a/modules/control/run.py +++ b/modules/control/run.py @@ -464,6 +464,8 @@ def control_run(state: str = '', # pylint: disable=keyword-arg-before-vararg if frame is not None: inputs = [Image.fromarray(frame)] # cv2 to pil for i, input_image in enumerate(inputs): + if input_image is not None: + p.ops.append('img2img') if pipe is None: # pipe may have been reset externally pipe = set_pipe(p, has_models, unit_type, selected_models, active_model, active_strength, control_conditioning, control_guidance_start, control_guidance_end, inits) debug_log(f'Control pipeline reinit: class={pipe.__class__.__name__}') @@ -526,6 +528,14 @@ def control_run(state: str = '', # pylint: disable=keyword-arg-before-vararg if unit_type == 'lite': instance.apply(selected_models, processed_image, control_conditioning) + # what are we doing? + if 'control' in p.ops: + p.outpath_samples = shared.opts.outdir_samples or shared.opts.outdir_control_samples + elif 'img2img' in p.ops: + p.outpath_samples = shared.opts.outdir_samples or shared.opts.outdir_img2img_samples + elif 'txt2img' in p.ops: + p.outpath_samples = shared.opts.outdir_samples or shared.opts.outdir_txt2img_samples + # pipeline output = None script_run = False diff --git a/modules/images.py b/modules/images.py index 6b3bba16a..6009e658c 100644 --- a/modules/images.py +++ b/modules/images.py @@ -149,7 +149,7 @@ def save_image(image, save_to_dirs=None, ): fn = f'{sys._getframe(2).f_code.co_name}:{sys._getframe(1).f_code.co_name}' # pylint: disable=protected-access - debug(f'Save: fn={fn}') # pylint: disable=protected-access + debug_save(f'Save: fn={fn}') # pylint: disable=protected-access if image is None: shared.log.warning('Image is none') return None, None, None diff --git a/modules/memstats.py b/modules/memstats.py index 5af35d6be..47469fd77 100644 --- a/modules/memstats.py +++ b/modules/memstats.py @@ -63,12 +63,12 @@ def memory_stats(): if stats.get('num_ooms', 0) > 0: shared.state.oom = True mem.update({ - 'job': shared.state.job, 'gpu': gpu, 'active': gb(stats.get('active_bytes.all.current', 0)), 'peak': gb(stats.get('active_bytes.all.peak', 0)), 'retries': stats.get('num_alloc_retries', 0), 'oom': stats.get('num_ooms', 0), + 'job': shared.state.job, }) mem['swap'] = round(mem['active'] - mem['gpu']['used'], 2) if mem['active'] > mem['gpu']['used'] else 0 return mem diff --git a/modules/processing.py b/modules/processing.py index bd98b3251..15d22e076 100644 --- a/modules/processing.py +++ b/modules/processing.py @@ -456,8 +456,11 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed: if p.scripts is not None and isinstance(p.scripts, scripts_manager.ScriptRunner) and not (shared.state.interrupted or shared.state.skipped): p.scripts.postprocess(p, processed) timer.process.record('post') + p.ops = list(set(p.ops)) 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()} memory={memstats.memory_stats()}') + shared.log.info(f'Processed: images={len(output_images)} its={(p.steps * len(output_images)) / (t1 - t0):.2f} ops={p.ops}') + shared.log.debug(f'Processed: timers={timer.process.dct()}') + shared.log.debug(f'Processed: memory={memstats.memory_stats()}') devices.torch_gc(force=True, reason='final') return processed