From 21ae4d62e0f5b84abfc59d97b94dea6f905ecb8b Mon Sep 17 00:00:00 2001 From: Chris Dumas Date: Thu, 3 Sep 2026 19:59:50 +0000 Subject: [PATCH] Keep latent upscale shrink steps 32-aligned --- dumas_h3_latent_upscale.py | 27 ++++++++++++++++++--------- tests/test_dumas_h3_longvideos.py | 2 ++ 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/dumas_h3_latent_upscale.py b/dumas_h3_latent_upscale.py index 55b9996..b544f91 100644 --- a/dumas_h3_latent_upscale.py +++ b/dumas_h3_latent_upscale.py @@ -420,6 +420,13 @@ def _compute_spatial_grid(h, w, th, tw, ol_h, ol_w, min_th=0, min_tw=0): def _shrink_model_tile_param(param): + def _halve_32(v): + v = int(v or 0) + if v <= 0: + return 0 + v = (v // 2 // 32) * 32 + return max(0, v) + next_param = dict(param) mode = str(next_param.get("tile_size_mode") or "specific_size") if mode == "rows_cols": @@ -429,23 +436,25 @@ def _shrink_model_tile_param(param): return None next_param["grid_rows"] = rows next_param["grid_cols"] = cols - next_param["spatial_w_overlap"] = max(0, int(next_param.get("spatial_w_overlap", 0) or 0) // 2) - next_param["spatial_h_overlap"] = max(0, int(next_param.get("spatial_h_overlap", 0) or 0) // 2) - next_param["fade_width"] = max(0, int(next_param.get("fade_width", 0) or 0) // 2) - next_param["fade_height"] = max(0, int(next_param.get("fade_height", 0) or 0) // 2) + next_param["spatial_w_overlap"] = _halve_32(next_param.get("spatial_w_overlap", 0)) + next_param["spatial_h_overlap"] = _halve_32(next_param.get("spatial_h_overlap", 0)) + next_param["fade_width"] = _halve_32(next_param.get("fade_width", 0)) + next_param["fade_height"] = _halve_32(next_param.get("fade_height", 0)) return next_param tile_w = int(next_param.get("tile_width", 0) or 0) tile_h = int(next_param.get("tile_height", 0) or 0) - new_w = max(32, (max(32, tile_w) // 2 // 32) * 32) - new_h = max(32, (max(32, tile_h) // 2 // 32) * 32) + new_w = _halve_32(tile_w) + new_h = _halve_32(tile_h) + if new_w < 32 or new_h < 32: + return None if new_w >= tile_w and new_h >= tile_h: return None next_param["tile_width"] = new_w next_param["tile_height"] = new_h - next_param["overlap"] = max(0, int(next_param.get("overlap", 0) or 0) // 2) - next_param["fade_width"] = max(0, int(next_param.get("fade_width", 0) or 0) // 2) - next_param["fade_height"] = max(0, int(next_param.get("fade_height", 0) or 0) // 2) + next_param["overlap"] = _halve_32(next_param.get("overlap", 0)) + next_param["fade_width"] = _halve_32(next_param.get("fade_width", 0)) + next_param["fade_height"] = _halve_32(next_param.get("fade_height", 0)) return next_param diff --git a/tests/test_dumas_h3_longvideos.py b/tests/test_dumas_h3_longvideos.py index fd2ea50..fba4a4c 100644 --- a/tests/test_dumas_h3_longvideos.py +++ b/tests/test_dumas_h3_longvideos.py @@ -1173,6 +1173,8 @@ class DumasH3LongVideosHelperTests(unittest.TestCase): self.assertIsNotNone(smaller) self.assertLess(smaller["tile_width"], 512) self.assertLess(smaller["tile_height"], 512) + self.assertEqual(smaller["fade_width"] % 32, 0) + self.assertEqual(smaller["fade_height"] % 32, 0) def test_compose_persistent_does_not_expand_ambiguous_plural_to_full_cast(self): active = self.module.parse_wardrobe(