Sandpies commited on
Commit ·
21fbd92
1
Parent(s): ba6c750
upsampler: add REGEN2K_SIGMAS, sigmas pass-through, and R0 chunk shortening before tiling
Browse files- tiled_upsampler.py +67 -13
tiled_upsampler.py
CHANGED
|
@@ -64,6 +64,15 @@ _FLUSH_S = [0.0] # seconds spent in sample_tile's cache flush (log onl
|
|
| 64 |
_LAST_OOM = [0] # OOM retries in the most recent redraw_chunk call (log only)
|
| 65 |
_LAST_BUDGET = [TOKEN_BUDGET] # budget redraw_chunk / upsample finished at
|
| 66 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 67 |
# --- the guided re-draw (not part of the recipe) ----------------------------
|
| 68 |
#
|
| 69 |
# With an h3upscale LoRA on the re-draw model, the same one step also gets the
|
|
@@ -1186,12 +1195,41 @@ def _free(model):
|
|
| 1186 |
mm.soft_empty_cache()
|
| 1187 |
|
| 1188 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1189 |
def upsample(model, conditioning, latent, sampler, upscaler, megapixels,
|
| 1190 |
denoise=DENOISE, guide=None, budget=TOKEN_BUDGET, steps=STEPS,
|
| 1191 |
start_sigma=0.0, overlap_px=TILE_OVERLAP_PX, detail_sigma=0.0,
|
| 1192 |
-
chunk_frames=
|
| 1193 |
anchor=ANCHOR_AUG, seed=SEED, noise="per_chunk",
|
| 1194 |
-
attn_chunks=4, ffn_chunks=2):
|
| 1195 |
"""The whole recipe on an H3 AV latent. -> the upsampled AV latent dict.
|
| 1196 |
|
| 1197 |
`conditioning` is one conditioning for the whole clip, or a callable
|
|
@@ -1230,7 +1268,12 @@ def upsample(model, conditioning, latent, sampler, upscaler, megapixels,
|
|
| 1230 |
w_px, h_px = target_size(video.shape[4] * SPATIAL, video.shape[3] * SPATIAL,
|
| 1231 |
megapixels)
|
| 1232 |
model = _apply_low_vram_patches(model, attn_chunks, ffn_chunks)
|
| 1233 |
-
sigmas
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1234 |
plan = chunks(tv, int(chunk_frames), int(chunk_overlap))
|
| 1235 |
print(f"[{TAG}] {video.shape[4] * SPATIAL}x{video.shape[3] * SPATIAL} -> "
|
| 1236 |
f"{w_px}x{h_px} ({w_px * h_px / 1048576.0:.2f} MP), {len(plan)} "
|
|
@@ -1472,7 +1515,8 @@ def match_levels(frames, ref, chunk=16, in_place=False):
|
|
| 1472 |
|
| 1473 |
def upsample_chain(model, sampler, vae, hops, megapixels, master=None,
|
| 1474 |
upscaler=UPSCALER_FILE, decode=None, denoise=DENOISE,
|
| 1475 |
-
alloc=None, guide=None, budget=TOKEN_BUDGET, settings=None
|
|
|
|
| 1476 |
"""The recipe over a finished chain. -> (IMAGE [N,H,W,3], note).
|
| 1477 |
|
| 1478 |
`hops` are per-hop dicts: video/audio (the hop's delivered sampler
|
|
@@ -1508,18 +1552,28 @@ def upsample_chain(model, sampler, vae, hops, megapixels, master=None,
|
|
| 1508 |
want = sum(int(h["frames"]) for h in hops)
|
| 1509 |
frames, at, runs = None, 0, 0
|
| 1510 |
_segs = segments(hops)
|
|
|
|
| 1511 |
for seg in _segs:
|
| 1512 |
_t0 = time.perf_counter()
|
| 1513 |
v, a = stitch(seg)
|
| 1514 |
lat = {"samples": nt.NestedTensor((v, a))}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1515 |
out = upsample(model, cond_by_frame(seg), lat, sampler, upscaler,
|
| 1516 |
-
megapixels, denoise, guide=guide, budget=
|
| 1517 |
-
|
| 1518 |
-
|
| 1519 |
-
|
| 1520 |
-
chunk_frames=st["chunk_frames"], chunk_overlap=st["chunk_overlap"],
|
| 1521 |
-
anchor=st["anchor_strength"], seed=st["seed"], noise=st["noise"],
|
| 1522 |
-
attn_chunks=st["attn_chunks"], ffn_chunks=st["ffn_chunks"])
|
| 1523 |
vid = out["samples"].tensors[0]
|
| 1524 |
_free(model)
|
| 1525 |
if _device().type == "cuda":
|
|
@@ -1638,7 +1692,7 @@ class HTCTiledUpsampler:
|
|
| 1638 |
SETTINGS_TYPE = "HTC_UPSAMPLE"
|
| 1639 |
CHAIN_DEFAULTS = {
|
| 1640 |
"steps": STEPS, "start_sigma": 0.0, "noise": "per_chunk", "seed": SEED,
|
| 1641 |
-
"chunk_frames":
|
| 1642 |
"anchor_strength": ANCHOR_AUG, "tile_overlap_px": TILE_OVERLAP_PX, "detail_sigma": 0.0,
|
| 1643 |
"attn_chunks": 4, "ffn_chunks": 2, "sampler": None,
|
| 1644 |
}
|
|
@@ -1690,7 +1744,7 @@ class HTCUpsampleSettings:
|
|
| 1690 |
"tooltip": "Noise seed of the re-draw (the recipe uses 444). Fixed: "
|
| 1691 |
"it does not change between runs."}),
|
| 1692 |
"chunk_frames": ("INT", {
|
| 1693 |
-
"default": d["chunk_frames"], "min": 34, "max": 1020, "step": 17,
|
| 1694 |
"tooltip": "Frames per time chunk, a multiple of 17. Longer chunks "
|
| 1695 |
"mean fewer joins but more tokens per pass (more tiles "
|
| 1696 |
"or more VRAM)."}),
|
|
|
|
| 64 |
_LAST_OOM = [0] # OOM retries in the most recent redraw_chunk call (log only)
|
| 65 |
_LAST_BUDGET = [TOKEN_BUDGET] # budget redraw_chunk / upsample finished at
|
| 66 |
|
| 67 |
+
|
| 68 |
+
class _DefaultInt(int):
|
| 69 |
+
"""Sentinel int equal to CHUNK_FRAMES that marks an un-overridden default."""
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
_DEFAULT_CHUNK_FRAMES = _DefaultInt(CHUNK_FRAMES)
|
| 73 |
+
REGEN2K_MIN_CHUNK_FRAMES = 68
|
| 74 |
+
REGEN2K_SIGMAS = torch.tensor([0.909375, 6.0 / 7.0, 2.0 / 3.0, 0.0], dtype=torch.float32)
|
| 75 |
+
|
| 76 |
# --- the guided re-draw (not part of the recipe) ----------------------------
|
| 77 |
#
|
| 78 |
# With an h3upscale LoRA on the re-draw model, the same one step also gets the
|
|
|
|
| 1195 |
mm.soft_empty_cache()
|
| 1196 |
|
| 1197 |
|
| 1198 |
+
def _regen2k_chunk_frames(w_px, h_px, budget, chunk_frames=_DEFAULT_CHUNK_FRAMES,
|
| 1199 |
+
overlap_px=TILE_OVERLAP_PX, explicit=None):
|
| 1200 |
+
"""Pick chunk length from `budget` for regen2k mode (R0).
|
| 1201 |
+
|
| 1202 |
+
If `chunk_frames` was not explicitly set on `HTCUpsampleSettings` and a
|
| 1203 |
+
102 f full-frame chunk exceeds `budget`, shorten `chunk_frames` in steps
|
| 1204 |
+
of 17 down to a floor of 68 f (20 steps) before allowing spatial tiles.
|
| 1205 |
+
"""
|
| 1206 |
+
if explicit is None:
|
| 1207 |
+
explicit = not isinstance(chunk_frames, _DefaultInt)
|
| 1208 |
+
cf = int(chunk_frames)
|
| 1209 |
+
if not explicit and cf > REGEN2K_MIN_CHUNK_FRAMES:
|
| 1210 |
+
while cf > REGEN2K_MIN_CHUNK_FRAMES:
|
| 1211 |
+
steps = max(1, (cf // 17) * 5)
|
| 1212 |
+
if seq_len(w_px, h_px, steps) <= int(budget):
|
| 1213 |
+
break
|
| 1214 |
+
cf = max(REGEN2K_MIN_CHUNK_FRAMES, cf - 17)
|
| 1215 |
+
steps = max(1, (cf // 17) * 5)
|
| 1216 |
+
grid = solve_grid(w_px, h_px, steps, overlap_px=snap_overlap(overlap_px),
|
| 1217 |
+
budget=int(budget))
|
| 1218 |
+
if grid is not None and grid[0] == 1 and grid[1] == 1:
|
| 1219 |
+
print(f"[{TAG}] regen2k: budget {int(budget)} -> chunk {cf} f full-frame",
|
| 1220 |
+
flush=True)
|
| 1221 |
+
elif grid is not None:
|
| 1222 |
+
print(f"[{TAG}] regen2k: budget {int(budget)} -> chunk {cf} f "
|
| 1223 |
+
f"-> {grid[0]}x{grid[1]} tiles", flush=True)
|
| 1224 |
+
return cf, grid
|
| 1225 |
+
|
| 1226 |
+
|
| 1227 |
def upsample(model, conditioning, latent, sampler, upscaler, megapixels,
|
| 1228 |
denoise=DENOISE, guide=None, budget=TOKEN_BUDGET, steps=STEPS,
|
| 1229 |
start_sigma=0.0, overlap_px=TILE_OVERLAP_PX, detail_sigma=0.0,
|
| 1230 |
+
chunk_frames=_DEFAULT_CHUNK_FRAMES, chunk_overlap=CHUNK_OVERLAP,
|
| 1231 |
anchor=ANCHOR_AUG, seed=SEED, noise="per_chunk",
|
| 1232 |
+
attn_chunks=4, ffn_chunks=2, sigmas=None):
|
| 1233 |
"""The whole recipe on an H3 AV latent. -> the upsampled AV latent dict.
|
| 1234 |
|
| 1235 |
`conditioning` is one conditioning for the whole clip, or a callable
|
|
|
|
| 1268 |
w_px, h_px = target_size(video.shape[4] * SPATIAL, video.shape[3] * SPATIAL,
|
| 1269 |
megapixels)
|
| 1270 |
model = _apply_low_vram_patches(model, attn_chunks, ffn_chunks)
|
| 1271 |
+
if sigmas is not None:
|
| 1272 |
+
sigmas = (sigmas.detach().cpu().float() if isinstance(sigmas, torch.Tensor)
|
| 1273 |
+
else torch.tensor(list(sigmas), dtype=torch.float32))
|
| 1274 |
+
chunk_frames, _ = _regen2k_chunk_frames(w_px, h_px, budget, chunk_frames, overlap_px)
|
| 1275 |
+
else:
|
| 1276 |
+
sigmas = recipe_sigmas(model, denoise, steps, start_sigma)
|
| 1277 |
plan = chunks(tv, int(chunk_frames), int(chunk_overlap))
|
| 1278 |
print(f"[{TAG}] {video.shape[4] * SPATIAL}x{video.shape[3] * SPATIAL} -> "
|
| 1279 |
f"{w_px}x{h_px} ({w_px * h_px / 1048576.0:.2f} MP), {len(plan)} "
|
|
|
|
| 1515 |
|
| 1516 |
def upsample_chain(model, sampler, vae, hops, megapixels, master=None,
|
| 1517 |
upscaler=UPSCALER_FILE, decode=None, denoise=DENOISE,
|
| 1518 |
+
alloc=None, guide=None, budget=TOKEN_BUDGET, settings=None,
|
| 1519 |
+
sigmas=None):
|
| 1520 |
"""The recipe over a finished chain. -> (IMAGE [N,H,W,3], note).
|
| 1521 |
|
| 1522 |
`hops` are per-hop dicts: video/audio (the hop's delivered sampler
|
|
|
|
| 1552 |
want = sum(int(h["frames"]) for h in hops)
|
| 1553 |
frames, at, runs = None, 0, 0
|
| 1554 |
_segs = segments(hops)
|
| 1555 |
+
_cur_budget = budget
|
| 1556 |
for seg in _segs:
|
| 1557 |
_t0 = time.perf_counter()
|
| 1558 |
v, a = stitch(seg)
|
| 1559 |
lat = {"samples": nt.NestedTensor((v, a))}
|
| 1560 |
+
if _cur_budget is not None:
|
| 1561 |
+
_LAST_BUDGET[0] = int(_cur_budget)
|
| 1562 |
+
_ukw = dict(
|
| 1563 |
+
steps=_chain_steps,
|
| 1564 |
+
start_sigma=(st["start_sigma"] if float(denoise) > 0.0 else 0.0),
|
| 1565 |
+
overlap_px=st["tile_overlap_px"], detail_sigma=st["detail_sigma"],
|
| 1566 |
+
chunk_frames=st["chunk_frames"], chunk_overlap=st["chunk_overlap"],
|
| 1567 |
+
anchor=st["anchor_strength"], seed=st["seed"], noise=st["noise"],
|
| 1568 |
+
attn_chunks=st["attn_chunks"], ffn_chunks=st["ffn_chunks"],
|
| 1569 |
+
)
|
| 1570 |
+
if sigmas is not None:
|
| 1571 |
+
_ukw["sigmas"] = sigmas
|
| 1572 |
out = upsample(model, cond_by_frame(seg), lat, sampler, upscaler,
|
| 1573 |
+
megapixels, denoise, guide=guide, budget=_cur_budget,
|
| 1574 |
+
**_ukw)
|
| 1575 |
+
if _cur_budget is not None and _LAST_BUDGET[0] < int(_cur_budget):
|
| 1576 |
+
_cur_budget = int(_LAST_BUDGET[0])
|
|
|
|
|
|
|
|
|
|
| 1577 |
vid = out["samples"].tensors[0]
|
| 1578 |
_free(model)
|
| 1579 |
if _device().type == "cuda":
|
|
|
|
| 1692 |
SETTINGS_TYPE = "HTC_UPSAMPLE"
|
| 1693 |
CHAIN_DEFAULTS = {
|
| 1694 |
"steps": STEPS, "start_sigma": 0.0, "noise": "per_chunk", "seed": SEED,
|
| 1695 |
+
"chunk_frames": _DEFAULT_CHUNK_FRAMES, "chunk_overlap": CHUNK_OVERLAP,
|
| 1696 |
"anchor_strength": ANCHOR_AUG, "tile_overlap_px": TILE_OVERLAP_PX, "detail_sigma": 0.0,
|
| 1697 |
"attn_chunks": 4, "ffn_chunks": 2, "sampler": None,
|
| 1698 |
}
|
|
|
|
| 1744 |
"tooltip": "Noise seed of the re-draw (the recipe uses 444). Fixed: "
|
| 1745 |
"it does not change between runs."}),
|
| 1746 |
"chunk_frames": ("INT", {
|
| 1747 |
+
"default": int(d["chunk_frames"]), "min": 34, "max": 1020, "step": 17,
|
| 1748 |
"tooltip": "Frames per time chunk, a multiple of 17. Longer chunks "
|
| 1749 |
"mean fewer joins but more tokens per pass (more tiles "
|
| 1750 |
"or more VRAM)."}),
|