mirror of
https://github.com/vladmandic/automatic
synced 2026-09-19 09:14:35 +02:00
@@ -1,5 +1,14 @@
|
||||
# Change Log for SD.Next
|
||||
|
||||
## Update for 2026-01-21
|
||||
|
||||
- add `SD_DEVICE_DEBUG` env variable to trace rocm/xpu/directml init failures
|
||||
- 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
|
||||
|
||||
### Highlights for 2026-01-20
|
||||
|
||||
@@ -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"<div class='error'>{html.escape(str(e))}</div>"
|
||||
res = extra_outputs or []
|
||||
res.append(f"<div class='error'>{html.escape(str(e))}</div>")
|
||||
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"<div class='error'>{html.escape(msg)}</div>"]
|
||||
res = extra_outputs_array or []
|
||||
res.append(f"<div class='error'>{html.escape(msg)}</div>")
|
||||
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"<div class='error'>{html.escape(type(e).__name__+': '+str(e))}</div>"]
|
||||
res = extra_outputs_array or []
|
||||
res.append(f"<div class='error'>{html.escape(type(e).__name__+': '+str(e))}</div>")
|
||||
shared.state.end(jobid)
|
||||
if not add_stats:
|
||||
return tuple(res)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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}')
|
||||
|
||||
@@ -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
|
||||
@@ -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):
|
||||
|
||||
+6
-2
@@ -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
|
||||
@@ -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:
|
||||
@@ -293,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 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
|
||||
|
||||
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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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}"')
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user