From 364081170f1c15853608db1f24ed9897763bdd09 Mon Sep 17 00:00:00 2001 From: Alexander Piskun <13381981+bigcat88@users.noreply.github.com> Date: Sun, 2 Aug 2026 17:10:47 +0300 Subject: [PATCH 1/2] [Partner Nodes] feat(Minimax): add 768P resolution for H3 model (#15227) Signed-off-by: Alexander Piskun --- comfy_api_nodes/nodes_minimax.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/comfy_api_nodes/nodes_minimax.py b/comfy_api_nodes/nodes_minimax.py index 2d7aef654..3c1d29257 100644 --- a/comfy_api_nodes/nodes_minimax.py +++ b/comfy_api_nodes/nodes_minimax.py @@ -467,7 +467,7 @@ def _hailuo03_model_inputs(include_ratio: bool = True, allow_adaptive: bool = Tr ), IO.Combo.Input( "resolution", - options=["2K"], + options=["768P", "2K"], tooltip="Resolution of the output video.", ), ] @@ -578,11 +578,12 @@ class MinimaxHailuo03TextToVideoNode(IO.ComfyNode): ], is_api_node=True, price_badge=IO.PriceBadge( - depends_on=IO.PriceBadgeDepends(widgets=["model.duration"]), + depends_on=IO.PriceBadgeDepends(widgets=["model.resolution", "model.duration"]), expr=""" ( $dur := $lookup(widgets, "model.duration"); - {"type": "usd", "usd": $dur * 0.1859} + $rate := $lookup(widgets, "model.resolution") = "768p" ? 0.1287 : 0.1859; + {"type": "usd", "usd": $dur * $rate} ) """, ), @@ -660,11 +661,12 @@ class MinimaxHailuo03FirstLastFrameNode(IO.ComfyNode): ], is_api_node=True, price_badge=IO.PriceBadge( - depends_on=IO.PriceBadgeDepends(widgets=["model.duration"]), + depends_on=IO.PriceBadgeDepends(widgets=["model.resolution", "model.duration"]), expr=""" ( $dur := $lookup(widgets, "model.duration"); - {"type": "usd", "usd": $dur * 0.1859} + $rate := $lookup(widgets, "model.resolution") = "768p" ? 0.1287 : 0.1859; + {"type": "usd", "usd": $dur * $rate} ) """, ), @@ -818,20 +820,21 @@ class MinimaxHailuo03ReferenceNode(IO.ComfyNode): is_api_node=True, price_badge=IO.PriceBadge( depends_on=IO.PriceBadgeDepends( - widgets=["model.duration"], + widgets=["model.resolution", "model.duration"], input_groups=["model.reference_images", "model.reference_videos"], ), expr=""" ( $dur := $lookup(widgets, "model.duration"); + $rate := $lookup(widgets, "model.resolution") = "768p" ? 0.1287 : 0.1859; $imgsRaw := $lookup(inputGroups, "model.reference_images"); $imgs := $imgsRaw ? $imgsRaw : 0; $vidsRaw := $lookup(inputGroups, "model.reference_videos"); $vids := $vidsRaw ? $vidsRaw : 0; - $base := $dur * 0.1859 + ($imgs > 5 ? ($imgs - 5) * 0.0572 : 0); + $base := $dur * $rate + ($imgs > 5 ? ($imgs - 5) * 0.0572 : 0); $vids > 0 - ? {"type": "range_usd", "min_usd": $base + $vids * 2 * 0.1859, - "max_usd": $base + 15 * 0.1859, "format": {"approximate": true}} + ? {"type": "range_usd", "min_usd": $base + $vids * 2 * $rate, + "max_usd": $base + 15 * $rate, "format": {"approximate": true}} : {"type": "usd", "usd": $base} ) """, From 611f2a4e0f30ea7f50451fd34ab25b8f9365ff2f Mon Sep 17 00:00:00 2001 From: rattus <46076784+rattus128@users.noreply.github.com> Date: Mon, 3 Aug 2026 01:16:06 +1000 Subject: [PATCH 2/2] fix pin registration priority (#15226) This priority scheme was broken in the case where you have pin registration exhaustion while loading a VBAR that gets a big evicition. The weight would stay in the loaded set but inherit the MRU priority against other workflow models WRT pin registration which leads to async offload without pinning. Fix by universally promiting active pin registration above workflow pins without concern for the weights/weights-loaded split. This diverges from the actual budgeting where the split still makes sense. --- comfy/model_management.py | 21 +++++++++++++++++---- comfy/pinned_memory.py | 6 +++--- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/comfy/model_management.py b/comfy/model_management.py index e3c94c15a..1000f69e1 100644 --- a/comfy/model_management.py +++ b/comfy/model_management.py @@ -671,6 +671,19 @@ def pin_eviction_tiers(loaded, evict_active): tiers.append((PIN_SUBSETS, True, True)) return tiers +def registration_eviction_tiers(evict_active): + subsets = PIN_SUBSETS + LOADED_PIN_SUBSETS + tiers = [ + (subsets, False, False), + (subsets, True, False), + ] + if evict_active: + tiers.extend([ + (subsets, False, True), + (subsets, True, True), + ]) + return tiers + def free_pins(size, evict_active=False, loaded=False): freed = 0 for subsets, current_prompt, active in pin_eviction_tiers(loaded, evict_active): @@ -703,19 +716,19 @@ def ensure_pin_budget(size, evict_active=False, loaded=False): to_free = shortfall + PIN_PRESSURE_HYSTERESIS return free_pins(to_free, evict_active=evict_active, loaded=loaded) >= shortfall -def free_registrations(shortfall, evict_active=True, loaded=False): +def free_registrations(shortfall, evict_active=True): if MAX_PINNED_MEMORY <= 0: return False if shortfall <= 0: return True shortfall += REGISTERABLE_PIN_HYSTERESIS - for subsets, current_prompt, active in pin_eviction_tiers(loaded, evict_active): + for subsets, current_prompt, active in registration_eviction_tiers(evict_active): shortfall -= free_model_pins(shortfall, subsets, current_prompt, active, registrations=True) return shortfall <= REGISTERABLE_PIN_HYSTERESIS -def ensure_pin_registerable(size, evict_active=True, loaded=False): - return free_registrations(TOTAL_PINNED_MEMORY + size - MAX_PINNED_MEMORY, evict_active=evict_active, loaded=loaded) +def ensure_pin_registerable(size, evict_active=True): + return free_registrations(TOTAL_PINNED_MEMORY + size - MAX_PINNED_MEMORY, evict_active=evict_active) class LoadedModel: def __init__(self, model: ModelPatcher): diff --git a/comfy/pinned_memory.py b/comfy/pinned_memory.py index d78ab3c76..e9a9a70e2 100644 --- a/comfy/pinned_memory.py +++ b/comfy/pinned_memory.py @@ -56,7 +56,7 @@ def get_pin(module, subset="weights"): _, _, stack_split, pinned_size, *_ = module._pin_state[subset] size = pin.nbytes - comfy.model_management.ensure_pin_registerable(size, loaded=subset.endswith("-loaded")) + comfy.model_management.ensure_pin_registerable(size) if torch.cuda.cudart().cudaHostRegister(pin.data_ptr(), size, 1) != 0: comfy.model_management.discard_cuda_async_error() @@ -93,7 +93,7 @@ def pin_memory(module, subset="weights", size=None): comfy.memory_management.extra_ram_release(comfy.memory_management.RAM_CACHE_HEADROOM) if (not comfy.model_management.ensure_pin_budget(size, loaded=loaded) or - not comfy.model_management.ensure_pin_registerable(registerable_size, loaded=loaded)): + not comfy.model_management.ensure_pin_registerable(registerable_size)): return _steal_pin(module, stack, buckets, size, priority, subset) offset = hostbuf.size @@ -105,7 +105,7 @@ def pin_memory(module, subset="weights", size=None): pin.untyped_storage()._comfy_hostbuf = hostbuf if torch.cuda.cudart().cudaHostRegister(pin.data_ptr(), size, 1) != 0: comfy.model_management.discard_cuda_async_error() - comfy.model_management.free_registrations(size, loaded=loaded) + comfy.model_management.free_registrations(size) if torch.cuda.cudart().cudaHostRegister(pin.data_ptr(), size, 1) != 0: comfy.model_management.discard_cuda_async_error() del pin