diff --git a/CHANGELOG.md b/CHANGELOG.md index 16c64afb2..59573f410 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ - implement img2img and inpainting (experimental) actual support and qualiy depends on model it works as expected for sd 1.5, but not so much for sd-xl for now + - implement limited stop/interrupt for diffusers + works between stages, not within steps - add option to save image before refiner pass - option to set vae upcast in settings - enable fp16 vae decode when using optimized vae diff --git a/modules/processing_diffusers.py b/modules/processing_diffusers.py index 4fcf36ac9..726917808 100644 --- a/modules/processing_diffusers.py +++ b/modules/processing_diffusers.py @@ -112,10 +112,21 @@ def process_diffusers(p: StableDiffusionProcessing, seeds, prompts, negative_pro ) output = shared.sd_model(**pipe_args) # pylint: disable=not-callable + if shared.state.interrupted or shared.state.skipped: + return results + if shared.sd_refiner is None or not p.enable_hr: output.images = vae_decode(output.images, shared.sd_model) if shared.sd_refiner is not None and p.enable_hr: + for i in range(len(output.images)): + if shared.opts.save and not p.do_not_save_samples and shared.opts.save_images_before_refiner and hasattr(shared.sd_model, 'vae'): + from modules.processing import create_infotext + info=create_infotext(p, p.all_prompts, p.all_seeds, p.all_subseeds, [], iteration=p.iteration, position_in_batch=i) + decoded = vae_decode(output.images, shared.sd_model, output_type='pil') + for i in range(len(decoded)): + images.save_image(decoded[i], path=p.outpath_samples, basename="", seed=seeds[i], prompt=prompts[i], extension=shared.opts.samples_format, info=info, p=p, suffix="-before-refiner") + if shared.opts.diffusers_move_base: shared.log.debug('Moving base model to CPU') shared.sd_model.to('cpu') @@ -126,18 +137,13 @@ def process_diffusers(p: StableDiffusionProcessing, seeds, prompts, negative_pro sampler = sd_samplers.all_samplers_map.get("UniPC") sd_samplers.create_sampler(sampler.name, shared.sd_refiner) # TODO(Patrick): For wrapped pipelines this is currently a no-op + if shared.state.interrupted or shared.state.skipped: + return results + shared.sd_refiner.to(devices.device) devices.torch_gc() for i in range(len(output.images)): - - if shared.opts.save and not p.do_not_save_samples and shared.opts.save_images_before_refiner and hasattr(shared.sd_model, 'vae'): - from modules.processing import create_infotext - info=create_infotext(p, p.all_prompts, p.all_seeds, p.all_subseeds, [], iteration=p.iteration, position_in_batch=i) - decoded = vae_decode(output.images, shared.sd_model, output_type='pil') - for i in range(len(decoded)): - images.save_image(decoded[i], path=p.outpath_samples, basename="", seed=seeds[i], prompt=prompts[i], extension=shared.opts.samples_format, info=info, p=p, suffix="-before-refiner") - pipe_args = set_pipeline_args( model=shared.sd_refiner, prompt=[p.refiner_prompt] if len(p.refiner_prompt) > 0 else prompts, @@ -154,6 +160,9 @@ def process_diffusers(p: StableDiffusionProcessing, seeds, prompts, negative_pro output_type='latent' if hasattr(shared.sd_model, 'vae') else 'np', ) output = shared.sd_refiner(**pipe_args) # pylint: disable=not-callable + if shared.state.interrupted or shared.state.skipped: + return results + output.images = vae_decode(output.images, shared.sd_model) results.append(output.images[0]) diff --git a/scripts/xyz_grid.py b/scripts/xyz_grid.py index ca5b55ac6..88b7ec8a5 100644 --- a/scripts/xyz_grid.py +++ b/scripts/xyz_grid.py @@ -263,7 +263,6 @@ def draw_xyz_grid(p, xs, ys, zs, x_labels, y_labels, z_labels, cell, draw_legend shared.state.job = f"{index(ix, iy, iz) + 1} out of {list_size}" processed: Processed = cell(x, y, z, ix, iy, iz) if processed_result is None: - # Use our first processed result object as a template container to hold our full results processed_result = copy(processed) processed_result.images = [None] * list_size processed_result.all_prompts = [None] * list_size @@ -272,7 +271,6 @@ def draw_xyz_grid(p, xs, ys, zs, x_labels, y_labels, z_labels, cell, draw_legend processed_result.index_of_first_image = 1 idx = index(ix, iy, iz) if processed.images: - # Non-empty list indicates some degree of success. processed_result.images[idx] = processed.images[0] processed_result.all_prompts[idx] = processed.prompt processed_result.all_seeds[idx] = processed.seed @@ -282,7 +280,6 @@ def draw_xyz_grid(p, xs, ys, zs, x_labels, y_labels, z_labels, cell, draw_legend cell_size = (processed_result.width, processed_result.height) if processed_result.images[0] is not None: cell_mode = processed_result.images[0].mode - #This corrects size in case of batches: cell_size = processed_result.images[0].size processed_result.images[idx] = Image.new(cell_mode, cell_size) @@ -318,7 +315,6 @@ def draw_xyz_grid(p, xs, ys, zs, x_labels, y_labels, z_labels, cell, draw_legend process_cell(x, y, z, ix, iy, iz) if not processed_result: - # Should never happen, I've only seen it on one of four open tabs and it needed to refresh. shared.log.error("XYZ grid: Processing could not begin, you may need to refresh the tab or restart the service") return Processed(p, []) elif not any(processed_result.images):