Merge branch 'video-tab' into video-wan
This commit is contained in:
commit
27541663e1
2 changed files with 56 additions and 0 deletions
|
|
@ -780,6 +780,27 @@ class VideoBackend:
|
|||
|
||||
# ── generation ───────────────────────────────────────────────────────────
|
||||
|
||||
@staticmethod
|
||||
def _reset_step_cache(pipe: Any) -> None:
|
||||
"""Clear FBCache residuals on the resident DiT(s) before a generation.
|
||||
|
||||
diffusers keys the residuals on the long-lived transformer and no pipeline
|
||||
resets them, so the next clip would compare against the previous request's
|
||||
state: a shape mismatch when the resolution changed, stale reuse otherwise.
|
||||
``_reset_stateful_cache`` is the transformer-level entry point in diffusers
|
||||
0.39 (``reset_stateful_hooks`` lives only on the HookRegistry). Best-effort:
|
||||
an uncached transformer is a silent no-op."""
|
||||
for name in ("transformer", "transformer_2"):
|
||||
module = getattr(pipe, name, None)
|
||||
reset = getattr(module, "_reset_stateful_cache", None) or getattr(
|
||||
module, "reset_stateful_hooks", None
|
||||
)
|
||||
if callable(reset):
|
||||
try:
|
||||
reset()
|
||||
except Exception: # noqa: BLE001 -- reset is best-effort, never fail a generation
|
||||
pass
|
||||
|
||||
def generate(
|
||||
self,
|
||||
*,
|
||||
|
|
@ -877,6 +898,8 @@ class VideoBackend:
|
|||
if "callback_on_step_end" in call_params:
|
||||
kwargs["callback_on_step_end"] = _on_step
|
||||
|
||||
if state.transformer_cache:
|
||||
self._reset_step_cache(pipe)
|
||||
with torch.inference_mode():
|
||||
output = pipe(**kwargs)
|
||||
if cancel.is_set():
|
||||
|
|
|
|||
|
|
@ -388,6 +388,39 @@ def test_generate_defaults_from_variant(fake_runtime, tmp_path):
|
|||
assert call["guidance_scale"] == 1.0
|
||||
|
||||
|
||||
def test_generate_resets_step_cache_only_when_engaged(fake_runtime, tmp_path):
|
||||
# FBCache residuals live on the long-lived DiT(s) and survive a generation, so
|
||||
# the next clip at a new resolution would crash on stale state. generate must
|
||||
# reset them when a cache is engaged (diffusers 0.39 exposes
|
||||
# _reset_stateful_cache on the transformer; reset_stateful_hooks only exists on
|
||||
# the HookRegistry) and must not touch an uncached load. transformer_2 (the Wan
|
||||
# dual expert) resets too when present.
|
||||
import dataclasses
|
||||
|
||||
(tmp_path / "ltx-2.3-22b-distilled-1.1-Q4_K_M.gguf").write_bytes(b"w")
|
||||
backend = VideoBackend()
|
||||
backend.load_pipeline(
|
||||
str(tmp_path),
|
||||
gguf_filename = "ltx-2.3-22b-distilled-1.1-Q4_K_M.gguf",
|
||||
base_repo = "Lightricks/LTX-2",
|
||||
family_override = "ltx-2",
|
||||
)
|
||||
resets = []
|
||||
backend._state.pipe.transformer = types.SimpleNamespace(
|
||||
_reset_stateful_cache = lambda: resets.append("transformer")
|
||||
)
|
||||
backend._state.pipe.transformer_2 = types.SimpleNamespace(
|
||||
_reset_stateful_cache = lambda: resets.append("transformer_2")
|
||||
)
|
||||
# No cache engaged -> no reset.
|
||||
backend.generate(prompt = "a sloth")
|
||||
assert resets == []
|
||||
# Cache engaged -> both resident DiTs reset before the pipe call.
|
||||
backend._state = dataclasses.replace(backend._state, transformer_cache = "fbcache")
|
||||
backend.generate(prompt = "a sloth")
|
||||
assert resets == ["transformer", "transformer_2"]
|
||||
|
||||
|
||||
def test_is_ltx23_checkpoint_gguf(monkeypatch, tmp_path):
|
||||
# diffusers maps every LTX-2 single file to the 2.0 config; a 2.3 checkpoint
|
||||
# (9-row modulation tables in the header) must be detected so the loader
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue