load_file() is mmap-based; a cache file with a readable header but damaged
data region crashes the whole process with a Windows fatal 'page error'
(uncatchable). Read the file as plain bytes and parse with safetensors.torch.load
so the same damage surfaces as OSError -> existing except returns {} -> caller
falls back to re-fuse. Verified: broken cache returns empty dict (no crash),
good cache still loads fully.
Four-part technical write-up of the AMD/ROCm compatibility release:
purpose, modified files, full code, and detailed explanation with the
virtual AMD test suite results (50/50 checks).
Documents the automatic behavior on systems where nunchaku is unavailable:
nunchaku-dependent nodes are not registered, while the Krea2 ControlNet
nodes (Krea2ControlNetLoraLoader, NunchakuQwenImageDiffsynthControlnet)
remain fully functional.
NODE_DISPLAY_NAME_MAPPINGS still contained the two hardcoded
NunchakuQwenImageLoraLoader/Stack entries on AMD systems, so display names
referenced nodes that were not registered. Gate them on _NUNCHAKU_AVAILABLE
(mirrors reference repo 6608421 pattern).
Mirrors the AMD compatibility approach from ComfyUI-NunchakuFluxLoraStacker
(PR #6 + follow-up): probe nunchaku availability, gate registration of all
nunchaku-dependent nodes (QwenImage/Z-ImageTurbo LoRA), and guard runtime
nunchaku imports so they raise a clear RuntimeError instead of ImportError.
The nunchaku-independent Krea2 ControlNet LoRA loader and the ControlNet node
stay registered on every platform.
Replicates the krea2_controlnet_pose.json reference workflow inside this node
(ostris nodes are no longer required):
- _krea2_make_ref_kv_forward: replaces diffusion_model.forward so reference
latents run in isolated kv_cache mode — one t=0 ref-only pass precomputes
every block's K/V (refs attend only to each other), reused as extra
attention keys each denoising step. This matches the ai-toolkit kv_cache
training convention the openpose control LoRA was trained with
- New helpers: _krea2_patchify, _krea2_ref_pack (RoPE axis-0 index i+1),
_krea2_ref_attn_kv (K/V capture/inject), _krea2_ref_block_forward,
_krea2_ref_precompute_kv, _krea2_forward_with_cached_refs,
_krea2_ref_fingerprint (content-keyed cache)
- New optional node input use_kv_cache (default True); when False the stock
joint-mode ref path is used instead
- extra_conds ref injection retained: skipped when conditioning already
carries reference_latents (TextEncodeKrea2OstrisEdit compat), so the VLM
vision path can still be combined without double injection
- depth / zimage / nunchaku_qwenimage / qwenimage_standard routes unchanged
The openpose control LoRA is a Kontext-style conditioning LoRA (blocks +
txtfusion, no expanded first projection). The previous openpose path only
applied the LoRA patches and never injected the pose image, so generation had
no pose control at all.
- _apply_krea2_openpose_control now VAE-encodes the control image (fit ~1MP,
snapped /16, ai-toolkit convention) and injects it as a reference latent
via patched extra_conds / extra_conds_shapes with
ref_latents_method=index_timestep_zero (native Krea2 ref pathway)
- Injection is skipped when the conditioning already carries
reference_latents (e.g. TextEncodeKrea2OstrisEdit), so the VLM vision path
wins and no double injection occurs
- depth / zimage / nunchaku_qwenimage / qwenimage_standard routes unchanged
- Add _classify_krea2_control_type() to detect depth vs openpose by first.weight presence
- Add _apply_krea2_openpose_control() for pure block LoRA (no first projection, no control latent)
- Route txtfusion.* keys in _krea2_target_key for layerwise/refiner blocks
- Split krea2 route into depth (unchanged) / openpose (new) exclusive branches
- No changes to zimage/nunchaku/qwenimage_standard routes or loader node
Post-merge additional fixes for PR #52 (per md/PR52_MERGE_PLAN.md):
- compose_loras_v2: restore _cached_first_lora_state_dict so the first
LoRA state dict loaded during section-3 debug inspection is reused in
the section-4 main loop. Without this the first LoRA is read from disk
twice whenever the precompiled cache is disabled (default).
- qwenimage_v2.py IS_CHANGED: drop the `model` arg (ComfyUI never passes
MODEL inputs to IS_CHANGED; the TypeError -> NaN path forced re-compose
every run) and remove str(model) from the hash (object repr changes
every run, which also forced constant re-execution).