Reuse conditioning for refinement tiles
This commit is contained in:
+50
-6
@@ -4076,6 +4076,52 @@ def _retarget_conditioning_spatial(cond, latent_h, latent_w):
|
|||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def _pad_to_h3_patch_size(tensor):
|
||||||
|
try:
|
||||||
|
import comfy.ldm.common_dit as common_dit
|
||||||
|
return common_dit.pad_to_patch_size(tensor, (1, 2, 2))
|
||||||
|
except Exception:
|
||||||
|
return tensor
|
||||||
|
|
||||||
|
|
||||||
|
def _crop_conditioning_to_tile(cond, source_h, source_w, row, col, tile_h, tile_w):
|
||||||
|
"""Crop H3 keyframe latents in existing conditioning for a spatial tile."""
|
||||||
|
out = []
|
||||||
|
for item in cond:
|
||||||
|
try:
|
||||||
|
tensor, data = item
|
||||||
|
except Exception:
|
||||||
|
out.append(item)
|
||||||
|
continue
|
||||||
|
nd = dict(data)
|
||||||
|
keyframes = nd.get("minimax_keyframes")
|
||||||
|
if keyframes:
|
||||||
|
cropped_keyframes = []
|
||||||
|
for keyframe in keyframes:
|
||||||
|
nkf = dict(keyframe)
|
||||||
|
latent_value = nkf.get("latent")
|
||||||
|
if latent_value is not None and len(getattr(latent_value, "shape", ())) >= 5:
|
||||||
|
kh, kw = latent_value.shape[3], latent_value.shape[4]
|
||||||
|
if kh != source_h or kw != source_w:
|
||||||
|
b, c, t, h, w = latent_value.shape
|
||||||
|
latent_value = torch.nn.functional.interpolate(
|
||||||
|
latent_value.to(torch.float32).reshape(b * t, c, h, w),
|
||||||
|
size=(source_h, source_w),
|
||||||
|
mode="bilinear",
|
||||||
|
align_corners=False,
|
||||||
|
).reshape(b, c, t, source_h, source_w).to(
|
||||||
|
device=latent_value.device,
|
||||||
|
dtype=latent_value.dtype,
|
||||||
|
)
|
||||||
|
nkf["latent"] = _pad_to_h3_patch_size(
|
||||||
|
latent_value[:, :, :, row:row + tile_h, col:col + tile_w].contiguous()
|
||||||
|
)
|
||||||
|
cropped_keyframes.append(nkf)
|
||||||
|
nd["minimax_keyframes"] = cropped_keyframes
|
||||||
|
out.append([tensor, nd])
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
def _latent_with_replaced_samples(template_latent, sampled_latent):
|
def _latent_with_replaced_samples(template_latent, sampled_latent):
|
||||||
"""Reuse the original latent payload, but swap in freshly sampled tensors."""
|
"""Reuse the original latent payload, but swap in freshly sampled tensors."""
|
||||||
if not isinstance(template_latent, dict):
|
if not isinstance(template_latent, dict):
|
||||||
@@ -6828,12 +6874,10 @@ class H3LongVideos:
|
|||||||
for col_index, c0 in enumerate(cols):
|
for col_index, c0 in enumerate(cols):
|
||||||
tc = tcols[col_index]
|
tc = tcols[col_index]
|
||||||
ovw = col_ovl[col_index]
|
ovw = col_ovl[col_index]
|
||||||
tile_target_w = int(tc) * 16
|
tile_cond = _crop_conditioning_to_tile(
|
||||||
tile_target_h = int(tr) * 16
|
upscale_cond, int(up_h), int(up_w), r0, c0, tr, tc
|
||||||
tile_cond, tile_latent = _build_shot_conditioning(
|
)
|
||||||
clip, vae, prompt, tile_target_w, tile_target_h, ln, fps, handoff,
|
tile_latent = dict(upscale_latent) if isinstance(upscale_latent, dict) else {}
|
||||||
ref_images=refs, ref_image_size=ref_image_size,
|
|
||||||
ref_noise_aug=ref_noise_aug, audio_vae=audio_vae, silent=silent)
|
|
||||||
tile_video = upscaled_video[:, :, :, r0:r0 + tr, c0:c0 + tc].contiguous()
|
tile_video = upscaled_video[:, :, :, r0:r0 + tr, c0:c0 + tc].contiguous()
|
||||||
tr_s = tr + (tr % 2)
|
tr_s = tr + (tr % 2)
|
||||||
tc_s = tc + (tc % 2)
|
tc_s = tc + (tc % 2)
|
||||||
|
|||||||
@@ -482,6 +482,12 @@ class DumasH3LongVideosHelperTests(unittest.TestCase):
|
|||||||
else:
|
else:
|
||||||
self.module.comfy.nested_tensor.NestedTensor = original_nested
|
self.module.comfy.nested_tensor.NestedTensor = original_nested
|
||||||
|
|
||||||
|
def test_latent_refine_tiles_do_not_rebuild_conditioning(self):
|
||||||
|
source = inspect.getsource(self.module.H3LongVideos._render)
|
||||||
|
tile_branch = source[source.index("for col_index, c0 in enumerate(cols):"):]
|
||||||
|
self.assertIn("_crop_conditioning_to_tile", tile_branch)
|
||||||
|
self.assertNotIn("_build_shot_conditioning(", tile_branch)
|
||||||
|
|
||||||
def test_latent_upscale_off_skips_second_pass(self):
|
def test_latent_upscale_off_skips_second_pass(self):
|
||||||
calls = []
|
calls = []
|
||||||
original_common_ksampler = self.module.nodes.common_ksampler
|
original_common_ksampler = self.module.nodes.common_ksampler
|
||||||
|
|||||||
Reference in New Issue
Block a user