diff --git a/modules/processing.py b/modules/processing.py index 45b6a0df..42831196 100644 --- a/modules/processing.py +++ b/modules/processing.py @@ -420,6 +420,7 @@ class StableDiffusionProcessing: return ( required_prompts, self.distilled_cfg_scale, + self.hr_distilled_cfg, steps, hires_steps, use_old_scheduling, @@ -1156,6 +1157,8 @@ class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing): hr_scheduler: str = None hr_prompt: str = '' hr_negative_prompt: str = '' + hr_cfg: float = 1.0 + hr_distilled_cfg: float = 3.5 force_task_id: str = None cached_hr_uc = [None, None, None] @@ -1253,6 +1256,10 @@ class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing): self.extra_generation_params["Hires prompt"] = get_hr_prompt self.extra_generation_params["Hires negative prompt"] = get_hr_negative_prompt + self.extra_generation_params["Hires CFG Scale"] = self.hr_cfg + if shared.sd_model.use_distilled_cfg_scale: + self.extra_generation_params['Hires Distilled CFG Scale'] = self.hr_distilled_cfg + self.extra_generation_params["Hires schedule type"] = None # to be set in sd_samplers_kdiffusion.py if self.hr_scheduler is None: @@ -1494,8 +1501,8 @@ class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing): if self.hr_c is not None: return - hr_prompts = prompt_parser.SdConditioning(self.hr_prompts, width=self.hr_upscale_to_x, height=self.hr_upscale_to_y, distilled_cfg_scale=self.distilled_cfg_scale) - hr_negative_prompts = prompt_parser.SdConditioning(self.hr_negative_prompts, width=self.hr_upscale_to_x, height=self.hr_upscale_to_y, is_negative_prompt=True, distilled_cfg_scale=self.distilled_cfg_scale) + hr_prompts = prompt_parser.SdConditioning(self.hr_prompts, width=self.hr_upscale_to_x, height=self.hr_upscale_to_y, distilled_cfg_scale=self.hr_distilled_cfg) + hr_negative_prompts = prompt_parser.SdConditioning(self.hr_negative_prompts, width=self.hr_upscale_to_x, height=self.hr_upscale_to_y, is_negative_prompt=True, distilled_cfg_scale=self.hr_distilled_cfg) sampler_config = sd_samplers.find_sampler_config(self.hr_sampler_name or self.sampler_name) steps = self.hr_second_pass_steps or self.steps @@ -1570,6 +1577,8 @@ class StableDiffusionProcessingImg2Img(StableDiffusionProcessing): latent_mask: Image = None force_task_id: str = None + hr_distilled_cfg: float = 3.5 # needed here for cached_params + image_mask: Any = field(default=None, init=False) nmask: torch.Tensor = field(default=None, init=False) diff --git a/modules/sd_samplers_cfg_denoiser.py b/modules/sd_samplers_cfg_denoiser.py index b34b5418..95f82402 100644 --- a/modules/sd_samplers_cfg_denoiser.py +++ b/modules/sd_samplers_cfg_denoiser.py @@ -184,6 +184,9 @@ class CFGDenoiser(torch.nn.Module): cfg_denoiser_callback(denoiser_params) # NGMS + if self.p.is_hr_pass == True: + cond_scale = self.p.hr_cfg + if shared.opts.skip_early_cond > 0 and self.step / self.total_steps <= shared.opts.skip_early_cond: cond_scale = 1.0 self.p.extra_generation_params["Skip Early CFG"] = shared.opts.skip_early_cond diff --git a/modules/txt2img.py b/modules/txt2img.py index ef3801aa..8441ed1b 100644 --- a/modules/txt2img.py +++ b/modules/txt2img.py @@ -12,7 +12,7 @@ import gradio as gr from modules_forge import main_thread -def txt2img_create_processing(id_task: str, request: gr.Request, prompt: str, negative_prompt: str, prompt_styles, n_iter: int, batch_size: int, cfg_scale: float, distilled_cfg_scale: float, height: int, width: int, enable_hr: bool, denoising_strength: float, hr_scale: float, hr_upscaler: str, hr_second_pass_steps: int, hr_resize_x: int, hr_resize_y: int, hr_checkpoint_name: str, hr_sampler_name: str, hr_scheduler: str, hr_prompt: str, hr_negative_prompt, override_settings_texts, *args, force_enable_hr=False): +def txt2img_create_processing(id_task: str, request: gr.Request, prompt: str, negative_prompt: str, prompt_styles, n_iter: int, batch_size: int, cfg_scale: float, distilled_cfg_scale: float, height: int, width: int, enable_hr: bool, denoising_strength: float, hr_scale: float, hr_upscaler: str, hr_second_pass_steps: int, hr_resize_x: int, hr_resize_y: int, hr_checkpoint_name: str, hr_sampler_name: str, hr_scheduler: str, hr_prompt: str, hr_negative_prompt, hr_cfg: float, hr_distilled_cfg: float, override_settings_texts, *args, force_enable_hr=False): override_settings = create_override_settings_dict(override_settings_texts) if force_enable_hr: @@ -42,6 +42,8 @@ def txt2img_create_processing(id_task: str, request: gr.Request, prompt: str, ne hr_scheduler=None if hr_scheduler == 'Use same scheduler' else hr_scheduler, hr_prompt=hr_prompt, hr_negative_prompt=hr_negative_prompt, + hr_cfg=hr_cfg, + hr_distilled_cfg=hr_distilled_cfg, override_settings=override_settings, ) diff --git a/modules/ui.py b/modules/ui.py index 2193eb35..b2929370 100644 --- a/modules/ui.py +++ b/modules/ui.py @@ -314,7 +314,6 @@ def create_ui(): elif category == "cfg": with gr.Row(): distilled_cfg_scale = gr.Slider(minimum=0.0, maximum=30.0, step=0.1, label='Distilled CFG Scale', value=3.5, elem_id="txt2img_distilled_cfg_scale") - with gr.Row(): cfg_scale = gr.Slider(minimum=1.0, maximum=30.0, step=0.1, label='CFG Scale', value=7.0, elem_id="txt2img_cfg_scale") cfg_scale.change(lambda x: gr.update(interactive=(x != 1)), inputs=[cfg_scale], outputs=[toprow.negative_prompt], queue=False, show_progress=False) @@ -338,6 +337,10 @@ def create_ui(): hr_resize_x = gr.Slider(minimum=0, maximum=2048, step=8, label="Resize width to", value=0, elem_id="txt2img_hr_resize_x") hr_resize_y = gr.Slider(minimum=0, maximum=2048, step=8, label="Resize height to", value=0, elem_id="txt2img_hr_resize_y") + with FormRow(elem_id="txt2img_hires_fix_row_cfg", variant="compact"): + hr_distilled_cfg = gr.Slider(minimum=0.0, maximum=30.0, step=0.1, label="Hires Distilled CFG Scale", value=3.5, elem_id="txt2img_hr_distilled_cfg") + hr_cfg = gr.Slider(minimum=1.0, maximum=30.0, step=0.1, label="Hires CFG Scale", value=7.0, elem_id="txt2img_hr_cfg") + with FormRow(elem_id="txt2img_hires_fix_row3", variant="compact", visible=shared.opts.hires_fix_show_sampler) as hr_sampler_container: hr_checkpoint_name = gr.Dropdown(label='Checkpoint', elem_id="hr_checkpoint", choices=["Use same checkpoint"], value="Use same checkpoint", visible=False, interactive=False) @@ -347,12 +350,12 @@ def create_ui(): hr_scheduler = gr.Dropdown(label='Hires schedule type', elem_id="hr_scheduler", choices=["Use same scheduler"] + [x.label for x in sd_schedulers.schedulers], value="Use same scheduler") with FormRow(elem_id="txt2img_hires_fix_row4", variant="compact", visible=shared.opts.hires_fix_show_prompts) as hr_prompts_container: - with gr.Column(scale=80): - with gr.Row(): - hr_prompt = gr.Textbox(label="Hires prompt", elem_id="hires_prompt", show_label=False, lines=3, placeholder="Prompt for hires fix pass.\nLeave empty to use the same prompt as in first pass.", elem_classes=["prompt"]) - with gr.Column(scale=80): - with gr.Row(): - hr_negative_prompt = gr.Textbox(label="Hires negative prompt", elem_id="hires_neg_prompt", show_label=False, lines=3, placeholder="Negative prompt for hires fix pass.\nLeave empty to use the same negative prompt as in first pass.", elem_classes=["prompt"]) + with gr.Column(): + hr_prompt = gr.Textbox(label="Hires prompt", elem_id="hires_prompt", show_label=False, lines=3, placeholder="Prompt for hires fix pass.\nLeave empty to use the same prompt as in first pass.", elem_classes=["prompt"]) + with gr.Column(): + hr_negative_prompt = gr.Textbox(label="Hires negative prompt", elem_id="hires_neg_prompt", show_label=False, lines=3, placeholder="Negative prompt for hires fix pass.\nLeave empty to use the same negative prompt as in first pass.", elem_classes=["prompt"]) + + hr_cfg.change(lambda x: gr.update(interactive=(x != 1)), inputs=[hr_cfg], outputs=[hr_negative_prompt], queue=False, show_progress=False) scripts.scripts_txt2img.setup_ui_for_section(category) @@ -417,6 +420,8 @@ def create_ui(): hr_scheduler, hr_prompt, hr_negative_prompt, + hr_cfg, + hr_distilled_cfg, override_settings, ] + custom_inputs @@ -447,7 +452,7 @@ def create_ui(): show_progress=False, ) - res_switch_btn.click(fn=None, _js="function(){switchWidthHeight('txt2img')}", inputs=None, outputs=None, show_progress=False) + res_switch_btn.click(lambda w, h: (h, w), inputs=[width, height], outputs=[width, height], show_progress=False) toprow.restore_progress_button.click( fn=progress.restore_progress, @@ -484,6 +489,8 @@ def create_ui(): PasteField(hr_sampler_container, lambda d: gr.update(visible=True) if d.get("Hires sampler", "Use same sampler") != "Use same sampler" or d.get("Hires checkpoint", "Use same checkpoint") != "Use same checkpoint" or d.get("Hires schedule type", "Use same scheduler") != "Use same scheduler" else gr.update()), PasteField(hr_prompt, "Hires prompt", api="hr_prompt"), PasteField(hr_negative_prompt, "Hires negative prompt", api="hr_negative_prompt"), + PasteField(hr_cfg, "Hires CFG Scale", api="hr_cfg"), + PasteField(hr_distilled_cfg, "Hires Distilled CFG Scale", api="hr_distilled_cfg"), PasteField(hr_prompts_container, lambda d: gr.update(visible=True) if d.get("Hires prompt", "") != "" or d.get("Hires negative prompt", "") != "" else gr.update()), *scripts.scripts_txt2img.infotext_fields ] @@ -660,9 +667,8 @@ def create_ui(): elif category == "cfg": with gr.Row(): - distilled_cfg_scale = gr.Slider(minimum=0.0, maximum=30.0, step=0.5, label='Distilled CFG Scale', value=3.5, elem_id="img2img_distilled_cfg_scale") - with gr.Row(): - cfg_scale = gr.Slider(minimum=1.0, maximum=30.0, step=0.5, label='CFG Scale', value=7.0, elem_id="img2img_cfg_scale") + distilled_cfg_scale = gr.Slider(minimum=0.0, maximum=30.0, step=0.1, label='Distilled CFG Scale', value=3.5, elem_id="img2img_distilled_cfg_scale") + cfg_scale = gr.Slider(minimum=1.0, maximum=30.0, step=0.1, label='CFG Scale', value=7.0, elem_id="img2img_cfg_scale") image_cfg_scale = gr.Slider(minimum=0, maximum=3.0, step=0.05, label='Image CFG Scale', value=1.5, elem_id="img2img_image_cfg_scale", visible=False) cfg_scale.change(lambda x: gr.update(interactive=(x != 1)), inputs=[cfg_scale], outputs=[toprow.negative_prompt], queue=False, show_progress=False) @@ -796,7 +802,7 @@ def create_ui(): toprow.prompt.submit(**img2img_args) toprow.submit.click(**img2img_args) - res_switch_btn.click(fn=None, _js="function(){switchWidthHeight('img2img')}", inputs=None, outputs=None, show_progress=False) + res_switch_btn.click(lambda w, h: (h, w), inputs=[width, height], outputs=[width, height], show_progress=False) detect_image_size_btn.click( fn=lambda w, h: (w or gr.update(), h or gr.update()), diff --git a/modules_forge/main_entry.py b/modules_forge/main_entry.py index e84b766d..964f16f5 100644 --- a/modules_forge/main_entry.py +++ b/modules_forge/main_entry.py @@ -266,6 +266,8 @@ def forge_main_entry(): ui_img2img_sampler = get_a1111_ui_component('img2img', 'sampler_name') ui_img2img_scheduler = get_a1111_ui_component('img2img', 'scheduler') + ui_txt2img_hr_distilled_cfg = get_a1111_ui_component('txt2img', 'Hires Distilled CFG Scale') + output_targets = [ ui_vae, ui_clip_skip, @@ -284,7 +286,8 @@ def forge_main_entry(): ui_txt2img_sampler, ui_img2img_sampler, ui_txt2img_scheduler, - ui_img2img_scheduler + ui_img2img_scheduler, + ui_txt2img_hr_distilled_cfg, ] ui_forge_preset.change(on_preset_change, inputs=[ui_forge_preset], outputs=output_targets, queue=False, show_progress=False) @@ -319,6 +322,7 @@ def on_preset_change(preset=None): gr.update(value='Euler a'), # ui_img2img_sampler gr.update(value='Automatic'), # ui_txt2img_scheduler gr.update(value='Automatic'), # ui_img2img_scheduler + gr.update(visible=False, value=3.5), # ui_txt2img_hr_distilled_cfg ] if shared.opts.forge_preset == 'xl': @@ -341,6 +345,7 @@ def on_preset_change(preset=None): gr.update(value='DPM++ 2M SDE'), # ui_img2img_sampler gr.update(value='Karras'), # ui_txt2img_scheduler gr.update(value='Karras'), # ui_img2img_scheduler + gr.update(visible=False, value=3.5), # ui_txt2img_hr_distilled_cfg ] if shared.opts.forge_preset == 'flux': @@ -363,6 +368,7 @@ def on_preset_change(preset=None): gr.update(value='Euler'), # ui_img2img_sampler gr.update(value='Simple'), # ui_txt2img_scheduler gr.update(value='Simple'), # ui_img2img_scheduler + gr.update(visible=True, value=3.5), # ui_txt2img_hr_distilled_cfg ] loadsave = ui_loadsave.UiLoadsave(cmd_opts.ui_config_file) @@ -387,4 +393,5 @@ def on_preset_change(preset=None): gr.update(value=ui_settings_from_file['customscript/sampler.py/img2img/Sampling method/value']), # ui_img2img_sampler gr.update(value=ui_settings_from_file['customscript/sampler.py/txt2img/Schedule type/value']), # ui_txt2img_scheduler gr.update(value=ui_settings_from_file['customscript/sampler.py/img2img/Schedule type/value']), # ui_img2img_scheduler + gr.update(visible=True, value=ui_settings_from_file['txt2img/Hires Distilled CFG Scale/value']), # ui_txt2img_hr_distilled_cfg ]