mirror of
https://git.datalinker.icu/comfyanonymous/ComfyUI
synced 2026-09-08 07:27:01 +08:00
Fix IS_CHANGED for marking node as not changed
This commit is contained in:
parent
47d55b8b45
commit
2e5316232e
@ -93,7 +93,14 @@ class CacheKeySetInputSignature(CacheKeySet):
|
|||||||
self.subcache_keys[node_id] = (node_id, node["class_type"])
|
self.subcache_keys[node_id] = (node_id, node["class_type"])
|
||||||
|
|
||||||
def get_node_signature(self, dynprompt, node_id):
|
def get_node_signature(self, dynprompt, node_id):
|
||||||
|
node = dynprompt.get_node(node_id)
|
||||||
|
class_type = node["class_type"]
|
||||||
|
class_def = nodes.NODE_CLASS_MAPPINGS[class_type]
|
||||||
|
|
||||||
signature = []
|
signature = []
|
||||||
|
if hasattr(class_def, "IS_CHANGED"):
|
||||||
|
signature.append(self.get_immediate_node_signature(dynprompt, node_id, {}))
|
||||||
|
else:
|
||||||
ancestors, order_mapping = self.get_ordered_ancestry(dynprompt, node_id)
|
ancestors, order_mapping = self.get_ordered_ancestry(dynprompt, node_id)
|
||||||
signature.append(self.get_immediate_node_signature(dynprompt, node_id, order_mapping))
|
signature.append(self.get_immediate_node_signature(dynprompt, node_id, order_mapping))
|
||||||
for ancestor_id in ancestors:
|
for ancestor_id in ancestors:
|
||||||
@ -108,8 +115,13 @@ class CacheKeySetInputSignature(CacheKeySet):
|
|||||||
class_type = node["class_type"]
|
class_type = node["class_type"]
|
||||||
class_def = nodes.NODE_CLASS_MAPPINGS[class_type]
|
class_def = nodes.NODE_CLASS_MAPPINGS[class_type]
|
||||||
signature = [class_type, self.is_changed_cache.get(node_id)]
|
signature = [class_type, self.is_changed_cache.get(node_id)]
|
||||||
|
|
||||||
if self.include_node_id_in_input() or (hasattr(class_def, "NOT_IDEMPOTENT") and class_def.NOT_IDEMPOTENT) or include_unique_id_in_input(class_type):
|
if self.include_node_id_in_input() or (hasattr(class_def, "NOT_IDEMPOTENT") and class_def.NOT_IDEMPOTENT) or include_unique_id_in_input(class_type):
|
||||||
signature.append(node_id)
|
signature.append(node_id)
|
||||||
|
|
||||||
|
if hasattr(class_def, "IS_CHANGED"):
|
||||||
|
return signature
|
||||||
|
|
||||||
inputs = node["inputs"]
|
inputs = node["inputs"]
|
||||||
for key in sorted(inputs.keys()):
|
for key in sorted(inputs.keys()):
|
||||||
if is_link(inputs[key]):
|
if is_link(inputs[key]):
|
||||||
|
|||||||
@ -497,6 +497,36 @@ class TestExecution:
|
|||||||
assert numpy.array(images[0]).min() == 63 and numpy.array(images[0]).max() == 63, "Image should have value 0.25"
|
assert numpy.array(images[0]).min() == 63 and numpy.array(images[0]).max() == 63, "Image should have value 0.25"
|
||||||
assert not result.did_run(test_node), "The execution should have been cached"
|
assert not result.did_run(test_node), "The execution should have been cached"
|
||||||
|
|
||||||
|
# This tests that a node does not re-execute when IS_CHANGED returs the same value (even if
|
||||||
|
# inputs change)
|
||||||
|
def test_is_changed_overrides_default_checks(self, client: ComfyClient, builder: GraphBuilder):
|
||||||
|
g = builder
|
||||||
|
changing_input = g.node("StubImage", content="BLACK", height=512, width=512, batch_size=1)
|
||||||
|
test_node = g.node("TestCustomIsChanged", should_change=False, image=changing_input.out(0))
|
||||||
|
g.node("SaveImage", images=test_node.out(0))
|
||||||
|
|
||||||
|
result1 = client.run(g)
|
||||||
|
assert result1.did_run(test_node), "Node should run on first execution"
|
||||||
|
assert result1.did_run(changing_input), "Input should run on first execution"
|
||||||
|
|
||||||
|
changing_input.set_input('content', "WHITE") # Change input content
|
||||||
|
|
||||||
|
result2 = client.run(g)
|
||||||
|
assert result2.did_run(changing_input), "Input should re-execute due to content change"
|
||||||
|
assert not result2.did_run(test_node), "Node with IS_CHANGED should NOT re-execute when IS_CHANGED is consistent"
|
||||||
|
|
||||||
|
# verify the behavior when IS_CHANGED actually changes
|
||||||
|
test_node.set_input('should_change', True) # This should cause IS_CHANGED to return different value
|
||||||
|
|
||||||
|
result3 = client.run(g)
|
||||||
|
assert result3.did_run(test_node), "Node should re-execute when IS_CHANGED value actually changes"
|
||||||
|
|
||||||
|
changing_input.set_input('content', "BLACK") # Change input back
|
||||||
|
|
||||||
|
result4 = client.run(g)
|
||||||
|
assert result4.did_run(changing_input), "Input should re-execute due to content change"
|
||||||
|
assert result4.did_run(test_node), "Node should re-execute because IS_CHANGED returns changing value (NaN)"
|
||||||
|
|
||||||
# This tests that nodes with OUTPUT_IS_LIST function correctly when they receive an ExecutionBlocker
|
# This tests that nodes with OUTPUT_IS_LIST function correctly when they receive an ExecutionBlocker
|
||||||
# as input. We also test that when that list (containing an ExecutionBlocker) is passed to a node,
|
# as input. We also test that when that list (containing an ExecutionBlocker) is passed to a node,
|
||||||
# only that one entry in the list is blocked.
|
# only that one entry in the list is blocked.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user