From f77361f49a771a457f70930c23da1ecd42dbb9ee Mon Sep 17 00:00:00 2001 From: James58899 Date: Tue, 20 Jan 2026 20:58:04 +0800 Subject: [PATCH 01/10] Fix rocm triton windows patch --- modules/rocm_triton_windows.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/rocm_triton_windows.py b/modules/rocm_triton_windows.py index 88c509b6d..4bcbaff18 100644 --- a/modules/rocm_triton_windows.py +++ b/modules/rocm_triton_windows.py @@ -59,7 +59,7 @@ if sys.platform == "win32": return zluda.core.to_hip_stream(_cuda_getCurrentRawStream(device)) def get_default_agent() -> Union[Agent, None]: - if shared.devices.backend == "rocm": + if shared.devices.has_rocm(): return devices.get_hip_agent() else: from modules import zluda From b82132c17dc6c8c330da9f2080b6aa823720788d Mon Sep 17 00:00:00 2001 From: vladmandic Date: Tue, 20 Jan 2026 17:30:22 +0100 Subject: [PATCH 02/10] cleanup Signed-off-by: vladmandic --- modules/rocm.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/rocm.py b/modules/rocm.py index c4c205bcb..eea5c7522 100644 --- a/modules/rocm.py +++ b/modules/rocm.py @@ -138,6 +138,8 @@ class Agent: return None def get_gfx_version(self) -> Union[str, None]: + if self.gfx_version is None: + return None if self.gfx_version >= 0x1100 and self.gfx_version < 0x1200: return "11.0.0" elif self.gfx_version != 0x1030 and self.gfx_version >= 0x1000 and self.gfx_version < 0x1100: @@ -294,7 +296,7 @@ if sys.platform == "win32": build_targets = torch.cuda.get_arch_list() agents = get_agents() if all(available.name not in build_targets for available in agents): - log.warning('ROCm: torch-rocm is installed, but none of build targets is available') + log.warning('ROCm: torch-rocm is installed, but none of build targets are available') # use cpu instead of crashing torch.cuda.is_available = lambda: False From b3a99274e223f5dd943951ab8650b22fcdc42605 Mon Sep 17 00:00:00 2001 From: vladmandic Date: Tue, 20 Jan 2026 18:12:05 +0100 Subject: [PATCH 03/10] enhance SD_DEVICE_DEBUG Signed-off-by: vladmandic --- modules/rocm.py | 2 ++ modules/shared.py | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/modules/rocm.py b/modules/rocm.py index eea5c7522..c21929b0c 100644 --- a/modules/rocm.py +++ b/modules/rocm.py @@ -295,12 +295,14 @@ if sys.platform == "win32": build_targets = torch.cuda.get_arch_list() agents = get_agents() + log.debug(f'ROCm: agents={agents}') if all(available.name not in build_targets for available in agents): log.warning('ROCm: torch-rocm is installed, but none of build targets are available') # use cpu instead of crashing torch.cuda.is_available = lambda: False agent = get_hip_agent() + log.debug(f'ROCm: selected={agents}') if not agent.blaslt_supported: log.warning(f'ROCm: hipBLASLt unavailable agent={agent}') if (agent.gfx_version & 0xFFF0) == 0x1200: diff --git a/modules/shared.py b/modules/shared.py index 5deb96825..0ac6511a1 100644 --- a/modules/shared.py +++ b/modules/shared.py @@ -87,16 +87,22 @@ elif cmd_opts.use_ipex or devices.has_xpu(): ok, e = ipex_init() if not ok: log.error(f'IPEX initialization failed: {e}') + if os.environ.get('SD_DEVICE_DEBUG', None) is not None: + errors.display(e, 'IPEX') elif cmd_opts.use_directml: from modules.dml import directml_init ok, e = directml_init() if not ok: log.error(f'DirectML initialization failed: {e}') + if os.environ.get('SD_DEVICE_DEBUG', None) is not None: + errors.display(e, 'DirectML') elif cmd_opts.use_rocm or devices.has_rocm(): from modules.rocm import rocm_init ok, e = rocm_init() if not ok: log.error(f'ROCm initialization failed: {e}') + if os.environ.get('SD_DEVICE_DEBUG', None) is not None: + errors.display(e, 'ROCm') devices.backend = devices.get_backend(cmd_opts) devices.device = devices.get_optimal_device() mem_stat = memory_stats() From bb1e62f2ae9ce89b6d1ee949f44622e12759d456 Mon Sep 17 00:00:00 2001 From: vladmandic Date: Tue, 20 Jan 2026 18:32:19 +0100 Subject: [PATCH 04/10] fix_seed Signed-off-by: vladmandic --- modules/processing_helpers.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/modules/processing_helpers.py b/modules/processing_helpers.py index 222409738..d2a33ba62 100644 --- a/modules/processing_helpers.py +++ b/modules/processing_helpers.py @@ -236,10 +236,16 @@ def get_fixed_seed(seed): def fix_seed(p): p.seed = get_fixed_seed(p.seed) p.subseed = get_fixed_seed(p.subseed) - for i in range(len(p.all_seeds)): - p.all_seeds[i] = get_fixed_seed(p.all_seeds[i]) - for i in range(len(p.all_subseeds)): - p.all_subseeds[i] = get_fixed_seed(p.all_subseeds[i]) + if p.all_seeds is None or len(p.all_seeds) == 0: + p.all_seeds = [p.seed] + else: + for i in range(len(p.all_seeds)): + p.all_seeds[i] = get_fixed_seed(p.all_seeds[i]) + if p.all_subseeds is None or len(p.all_subseeds) == 0: + p.all_subseeds = [p.subseed] + else: + for i in range(len(p.all_subseeds)): + p.all_subseeds[i] = get_fixed_seed(p.all_subseeds[i]) def old_hires_fix_first_pass_dimensions(width, height): From a7b69cd805c9a1829618f9bb1eba078070540629 Mon Sep 17 00:00:00 2001 From: vladmandic Date: Tue, 20 Jan 2026 18:33:39 +0100 Subject: [PATCH 05/10] fix get_fixed_seed Signed-off-by: vladmandic --- modules/processing_helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/processing_helpers.py b/modules/processing_helpers.py index d2a33ba62..786156bf0 100644 --- a/modules/processing_helpers.py +++ b/modules/processing_helpers.py @@ -227,7 +227,7 @@ def decode_first_stage(model, x): def get_fixed_seed(seed): - if seed is None or seed == '' or seed == -1: + if (seed is None) or (seed == '') or (seed == -1): random.seed() seed = int(random.randrange(4294967294)) return seed From 84ad7bf20b33c5a56be7728ea4dd4be0ec2420f2 Mon Sep 17 00:00:00 2001 From: vladmandic Date: Tue, 20 Jan 2026 18:56:49 +0100 Subject: [PATCH 06/10] improve wrap_gradio_call Signed-off-by: vladmandic --- CHANGELOG.md | 6 ++++++ modules/call_queue.py | 12 ++++++------ modules/video_models/video_run.py | 1 + modules/video_models/video_ui.py | 2 +- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 286cf5776..3fade3459 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Change Log for SD.Next +## Update for 2026-01-21 + +- add `SD_DEVICE_DEBUG` env variable to trace rocm/xpu/directml init failures +- fix `all_seeds` +- improve `wrap_gradio` error handling + ## Update for 2026-01-20 ### Highlights for 2026-01-20 diff --git a/modules/call_queue.py b/modules/call_queue.py index 7ed03e5b9..ebfe58f0f 100644 --- a/modules/call_queue.py +++ b/modules/call_queue.py @@ -37,7 +37,6 @@ def wrap_gradio_gpu_call(func, extra_outputs=None, name=None): id_task = None with get_lock(): progress.start_task(id_task) - res = [None, '', '', ''] try: res = func(*args, **kwargs) progress.record_results(id_task, res) @@ -45,7 +44,8 @@ def wrap_gradio_gpu_call(func, extra_outputs=None, name=None): shared.log.error(f"Exception: {e}") shared.log.error(f"Arguments: args={str(args)[:10240]} kwargs={str(kwargs)[:10240]}") errors.display(e, 'gradio call') - res[-1] = f"
{html.escape(str(e))}
" + res = extra_outputs or [] + res.append(f"
{html.escape(str(e))}
") finally: progress.finish_task(id_task) return res @@ -70,7 +70,8 @@ def wrap_gradio_call(func, extra_outputs=None, add_stats=False, name=None): if res is None: msg = "No result returned from function" shared.log.warning(msg) - res = [None, '', '', f"
{html.escape(msg)}
"] + res = extra_outputs_array or [] + res.append(f"
{html.escape(msg)}
") else: res = list(res) if shared.cmd_opts.profile: @@ -78,9 +79,8 @@ def wrap_gradio_call(func, extra_outputs=None, add_stats=False, name=None): errors.profile(pr, 'Wrap') except Exception as e: errors.display(e, 'gradio call') - if extra_outputs_array is None: - extra_outputs_array = [None, ''] - res = extra_outputs_array + [f"
{html.escape(type(e).__name__+': '+str(e))}
"] + res = extra_outputs_array or [] + res.append(f"
{html.escape(type(e).__name__+': '+str(e))}
") shared.state.end(jobid) if not add_stats: return tuple(res) diff --git a/modules/video_models/video_run.py b/modules/video_models/video_run.py index 8f478fa15..a8603679a 100644 --- a/modules/video_models/video_run.py +++ b/modules/video_models/video_run.py @@ -11,6 +11,7 @@ debug = shared.log.trace if os.environ.get('SD_VIDEO_DEBUG', None) is not None e def generate(*args, **kwargs): task_id, ui_state, engine, model, prompt, negative, styles, width, height, frames, steps, sampler_index, sampler_shift, dynamic_shift, seed, guidance_scale, guidance_true, init_image, init_strength, last_image, vae_type, vae_tile_frames, mp4_fps, mp4_interpolate, mp4_codec, mp4_ext, mp4_opt, mp4_video, mp4_frames, mp4_sf, vlm_enhance, vlm_model, vlm_system_prompt, override_settings = args + if engine is None or model is None or engine == 'None' or model == 'None': return video_utils.queue_err('model not selected') # videojob = shared.state.begin('Video') diff --git a/modules/video_models/video_ui.py b/modules/video_models/video_ui.py index de0511d64..fdcefec46 100644 --- a/modules/video_models/video_ui.py +++ b/modules/video_models/video_ui.py @@ -190,7 +190,7 @@ def create_ui(prompt, negative, styles, overrides, init_image, init_strength, la ] video_dict = dict( - fn=call_queue.wrap_gradio_gpu_call(video_run.generate, extra_outputs=[None, '', ''], name='Video'), + fn=call_queue.wrap_gradio_gpu_call(video_run.generate, extra_outputs=[gr.update(), gr.update(), gr.update(), gr.update()], name='Video'), _js="submit_video", inputs=state_inputs + video_inputs, outputs=video_outputs, From ffa2150d426a2697b8e98e9c5ef4b9fa45139644 Mon Sep 17 00:00:00 2001 From: awsr <43862868+awsr@users.noreply.github.com> Date: Tue, 20 Jan 2026 22:07:44 -0800 Subject: [PATCH 07/10] Re-enable file deletion --- modules/ui_common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ui_common.py b/modules/ui_common.py index 4c0c6979e..b96e0daff 100644 --- a/modules/ui_common.py +++ b/modules/ui_common.py @@ -88,7 +88,7 @@ def delete_files(js_data, files, all_files, index): continue if os.path.exists(fn) and os.path.isfile(fn): deleted.append(fn) - # os.remove(fn) + os.remove(fn) if fn in all_files: all_files.remove(fn) shared.log.info(f'Delete: image="{fn}"') From bfbe4af598d00e488d592df4a09258bf0b3370c2 Mon Sep 17 00:00:00 2001 From: vladmandic Date: Wed, 21 Jan 2026 08:45:45 +0100 Subject: [PATCH 08/10] fix lora load Signed-off-by: vladmandic --- CHANGELOG.md | 6 ++++-- modules/lora/extra_networks_lora.py | 8 +++++--- modules/lora/lora_load.py | 2 +- modules/sd_offload.py | 5 +++-- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3fade3459..15a279279 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,8 +3,10 @@ ## Update for 2026-01-21 - add `SD_DEVICE_DEBUG` env variable to trace rocm/xpu/directml init failures -- fix `all_seeds` -- improve `wrap_gradio` error handling +- fix lora load when using non-native loader +- fix `all_seeds` +- fix image delete +- improve `wrap_gradio` error handling ## Update for 2026-01-20 diff --git a/modules/lora/extra_networks_lora.py b/modules/lora/extra_networks_lora.py index 882c0d91b..3db727d1a 100644 --- a/modules/lora/extra_networks_lora.py +++ b/modules/lora/extra_networks_lora.py @@ -173,7 +173,7 @@ class ExtraNetworkLora(extra_networks.ExtraNetwork): def signature(self, names: List[str], te_multipliers: List, unet_multipliers: List): return [f'{name}:{te}:{unet}' for name, te, unet in zip(names, te_multipliers, unet_multipliers)] - def changed(self, requested: List[str], include: List[str], exclude: List[str]): + def changed(self, requested: List[str], include: List[str] = None, exclude: List[str] = None) -> bool: if shared.opts.lora_force_reload: return True sd_model = shared.sd_model.pipe if hasattr(shared.sd_model, 'pipe') else shared.sd_model @@ -213,15 +213,17 @@ class ExtraNetworkLora(extra_networks.ExtraNetwork): debug_log(f'Network load: type=LoRA include={include} exclude={exclude} method={load_method} requested={requested} fn={fn}') if load_method == 'diffusers': - has_changed = False # diffusers handles its own loading - if len(exclude) == 0: + has_changed = self.changed(requested) + if has_changed: jobid = shared.state.begin('LoRA') lora_load.network_load(names, te_multipliers, unet_multipliers, dyn_dims, lora_modules) # load only on first call sd_models.set_diffuser_offload(shared.sd_model, op="model") shared.state.end(jobid) + elif load_method == 'nunchaku': from modules.lora import lora_nunchaku has_changed = lora_nunchaku.load_nunchaku(names, unet_multipliers) + else: # native lora_load.network_load(names, te_multipliers, unet_multipliers, dyn_dims) # load has_changed = self.changed(requested, include, exclude) diff --git a/modules/lora/lora_load.py b/modules/lora/lora_load.py index 14ee012ad..77695ee3f 100644 --- a/modules/lora/lora_load.py +++ b/modules/lora/lora_load.py @@ -304,7 +304,7 @@ def network_load(names, te_multipliers=None, unet_multipliers=None, dyn_dims=Non shared.log.error(f'Network load: type=LoRA action=fuse {str(e)}') if l.debug: errors.display(e, 'LoRA') - shared.sd_model = sd_models.apply_balanced_offload(shared.sd_model, force=True) # some layers may end up on cpu without hook + shared.sd_model = sd_models.apply_balanced_offload(shared.sd_model, force=True, silent=True) # some layers may end up on cpu without hook if len(l.loaded_networks) > 0 and l.debug: shared.log.debug(f'Network load: type=LoRA loaded={[n.name for n in l.loaded_networks]} cache={list(lora_cache)} fuse={shared.opts.lora_fuse_native}:{shared.opts.lora_fuse_diffusers}') diff --git a/modules/sd_offload.py b/modules/sd_offload.py index c7b2b0e66..d0efd5d47 100644 --- a/modules/sd_offload.py +++ b/modules/sd_offload.py @@ -466,7 +466,7 @@ def report_model_stats(module_name, module): shared.log.error(f'Module stats: name={module_name} {e}') -def apply_balanced_offload(sd_model=None, exclude=None, force=False): +def apply_balanced_offload(sd_model=None, exclude:list[str]=None, force:bool=False, silent:bool=False): global offload_hook_instance # pylint: disable=global-statement if shared.opts.diffusers_offload_mode != "balanced": return sd_model @@ -499,7 +499,8 @@ def apply_balanced_offload(sd_model=None, exclude=None, force=False): module.module_name = module_name module.offload_dir = os.path.join(shared.opts.accelerate_offload_path, checkpoint_name, module_name) apply_balanced_offload_to_module(module, op='apply') - report_model_stats(module_name, module) + if not silent: + report_model_stats(module_name, module) set_accelerate(sd_model) t = time.time() - t0 From 40e366acf727018dfe1ae4b192823b1f8543544d Mon Sep 17 00:00:00 2001 From: Seunghoon Lee Date: Wed, 21 Jan 2026 17:07:39 +0900 Subject: [PATCH 09/10] rocm hipblaslt detection fix --- modules/rocm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/rocm.py b/modules/rocm.py index c21929b0c..dd1c8d33a 100644 --- a/modules/rocm.py +++ b/modules/rocm.py @@ -110,7 +110,7 @@ class Agent: else: self.arch = MicroArchitecture.GCN self.is_apu = (self.gfx_version & 0xFFF0 == 0x1150) or self.gfx_version in (0x801, 0x902, 0x90c, 0x1013, 0x1033, 0x1035, 0x1036, 0x1103,) - self.blaslt_supported = False if blaslt_tensile_libpath is None else os.path.exists(os.path.join(blaslt_tensile_libpath, f"Kernels.so-000-{self.name}.hsaco" if sys.platform == "win32" else f"extop_{self.name}.co")) + self.blaslt_supported = False if blaslt_tensile_libpath is None else os.path.exists(os.path.join(blaslt_tensile_libpath, f"TensileLibrary_lazy_{self.name}.dat")) def __str__(self) -> str: return self.name From 42ff7aa961d8e86b22e8abd9553be837b11c44ad Mon Sep 17 00:00:00 2001 From: vladmandic Date: Wed, 21 Jan 2026 09:26:49 +0100 Subject: [PATCH 10/10] update changelog Signed-off-by: vladmandic --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 15a279279..9dfcab66b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,9 +3,10 @@ ## Update for 2026-01-21 - add `SD_DEVICE_DEBUG` env variable to trace rocm/xpu/directml init failures -- fix lora load when using non-native loader -- fix `all_seeds` +- fix lora load when using peft/diffusers loader +- fix rocm hipblaslt detection - fix image delete +- fix `all_seeds` error - improve `wrap_gradio` error handling ## Update for 2026-01-20