Sandpies commited on
Commit
21fbd92
·
1 Parent(s): ba6c750

upsampler: add REGEN2K_SIGMAS, sigmas pass-through, and R0 chunk shortening before tiling

Browse files
Files changed (1) hide show
  1. 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=CHUNK_FRAMES, chunk_overlap=CHUNK_OVERLAP,
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 = recipe_sigmas(model, denoise, steps, start_sigma)
 
 
 
 
 
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=budget,
1517
- steps=_chain_steps,
1518
- start_sigma=(st["start_sigma"] if float(denoise) > 0.0 else 0.0),
1519
- overlap_px=st["tile_overlap_px"], detail_sigma=st["detail_sigma"],
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": CHUNK_FRAMES, "chunk_overlap": CHUNK_OVERLAP,
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)."}),