DOGMA LazyImage v56.7
The switch that saves you the entire diffusion pass
- fallback
- masks
- result
- IMAGE
ComfyUI has no if. There's no control flow node that says "if this category has masks, run the sampler; if not, skip it" - unless you exploit the lazy-input mechanism, which is what this node does. If you run a five-category street restoration, this is the node that makes an empty category cost zero GPU seconds instead of a full crop render.
The problem
A DOGMA graph declares its five category slots up front, and on any given image two or three of them will be empty. A category with no verified instances produces an empty mask tensor. If you feed that into the crop/sample/stitch chain anyway, the chain still executes - the sampler happily denoises a crop built from an empty mask, and you've spent a minute of GPU time to composite nothing over the original.
The usual fixes are worse. Bypassing nodes by hand breaks when you run a batch; putting a MaskToImage-style empty check in doesn't help because everything downstream still evaluates; and a fallback switch that evaluates both sides is exactly what you're trying to avoid.
How it works
The node declares its result input as lazy and implements check_lazy_status. In plain English: it inspects the mask, and only if the mask contains at least one pixel over 0.5 does it ask ComfyUI to go and compute result. Ask never, compute never - the upstream crop/diffusion branch is pruned from the execution plan before it starts.
def check_lazy_status(self, fallback, masks, result=None):
return ['result'] if masks.numel() and bool((masks >= .5).any()) and result is None else []
Then the pass-through mirrors that logic exactly: non-empty mask in, result out; empty mask in, fallback out. The two conditions are written to agree, which matters - if they diverge you get confusing behaviour where the node returns a value it never asked for.
The gate is a strict >= 0.5 test on the mask, so a sparse mask with a single pixel counts as live. That's deliberate. "Empty" here means genuinely nothing to composite, not "small." Whether a tiny detection is worth a diffusion pass is a decision made upstream by the geometry guard and the audit, not by this node.
Inputs and outputs
- fallback - what to use when there's nothing to restore. Almost always the untouched source crop, so the slot degrades into a pass-through.
- masks - the approved masks for this slot. Wire the same masks the crop chain uses.
- result - lazy IMAGE: the output of the restoration chain for this slot.
One IMAGE out. In the reference graph you use one of these per category slot, and the fallback is the original so a skipped category still produces a correctly stacked output rather than a hole in the list.
Install
comfy node install comfyui-dogma-nodes
# or
cd ComfyUI/custom_nodes
git clone https://github.com/axior/ComfyUI-DOGMA-Nodes
pip install -r ComfyUI-DOGMA-Nodes/requirements.txt
Restart ComfyUI, then load a v56.7-era workflow: the README's advice for pack 1.0.7 is to update through Manager, restart, and load V56.19. No models needed - this is list/lazy plumbing, not a model node.
Gotchas
The lazy input must be the only consumer of that branch. If anything else in the graph - a preview, an image saver, another stitch - pulls on the crops directly, the branch runs regardless and you're back to paying for it. Preview nodes on the crop chain are the classic culprit: handy while you're building, expensive once you're rendering 400 tiles.
Debugging tip: watch the console, not the canvas. When a slot is skipped, nothing draws and nothing errors - the graph just quietly does less. If you want to know what happened, put a preview on LazyImage's output and compare it with the source. Identical pixels means the slot was skipped; different pixels means the chain ran.
Don't use it as your only empty-check. This decides whether to run the diffusion; it says nothing about whether the mask was correct. A wrong mask still passes the >= 0.5 test, opens the lazy gate, and renders. Keeping a bad detection out is the audit chain's job - that's the whole v56.7 reason DOGMAFinalMasksV567 raises rather than shrugs.
masks must be a real MASK tensor, not a list. This node isn't INPUT_IS_LIST; it tests masks.numel(). Feed it a Python list and you get an attribute error rather than a skip.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| fallback | IMAGE | — | |
| masks | MASK | — | |
| result | IMAGE | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | — |