Nodes/Artfat Resolution/Artfat Upscale Chain
ComfyUI Node

Artfat Upscale Chain

The two numbers your upscale workflow keeps getting wrong

By artfat-creator·Created 3 months ago·Updated a day ago· 3
Artfat Upscale Chain
    • mid_scale
    • final_short
    ◄width—►
    ◄height—►
    ◄mid_scale1.50►
    ◄final_scale1.50►
    ◄multiple16►

    A low-base-plus-upscale pipeline has two numbers that matter: how much you scale the latent between your two samplers, and how big the final image ends up. In most ComfyUI graphs they live in different widgets on different nodes, nobody agrees what "1.5x" rounds to, and you find out the final size after the render instead of before it. Artfat Upscale Chain holds both in one place and hands them out as wires.

    It's the companion to the pack's resolution picker, Artfat Resolution: that node decides your base size, this one turns it into a plan.

    What it actually does

    Almost nothing, and that's the appeal. There's no image processing here, no model, no model download. The plan() method does arithmetic: for each stage it multiplies the dimension by your scale and snaps the result to your chosen multiple. 1.0 on a stage is a true passthrough - no multiply, no snap, so your base survives untouched. It then returns the mid scale as a float and the short edge of the final image as an int.

    That last part is the whole point. Most final-pass upscalers don't want a W×H pair, they want a target, and SeedVR2 in particular takes the short edge as resolution - which is exactly what this node's second output is. Instead of eyeballing 1472 and hoping, you wire a number that was actually computed from your base.

    That's the 2026 consensus workflow: generate small inside the model's comfortable native range, then let a latent upscale and a generative restorer carry the detail. Current models in the 1–2MP band degrade softly rather than duplicating anatomy, and blowing past that band is where tiling and stretched limbs come from.

    The five inputs, and the two outputs

    Both width and height are forceInput - sockets, not typeable widgets. Wire them from Artfat Resolution's width/height outputs, or anything else producing ints. Drop the node in bare and it has nothing to compute, which is intended, not a bug.

    The two that you'll actually tune:

    • mid_scale (default 1.5, range 1.0–8.0) - the latent upscale between samplers. Wire the mid_scale output into your latent upscaler's scale. The author's own note is that SesquiLSR only works from 1.0 to 2.0, and that's accurate - it's a 3M-parameter learned latent upscaler released by LoganBooker in mid-2026 and advertised as multiscale 1–2x. Going to 2.5 on it isn't a big upscale, it's just out of range.
    • final_scale (default 1.5, range 1.0–8.0) - pixel-side upscale after decoding, stacked on top of the mid stage. This one goes to SeedVR2 or an ESRGAN pass.

    multiple is a string enum of "2", "8", "16", "32", defaulting to "16". It's what every computed side gets snapped to, and snapping isn't cosmetic: SeedVR2 wants even sizes, and the author's own note on the pack's other node calls 16 and 32 safe for Krea 2, Qwen and H3.

    Outputs are just mid_scale (FLOAT) and final_short (INT). No image, no latent, no info string. If you want the full base -> mid -> final readout in text, that's Artfat Resolution's info output, not this node's.

    Install

    Same pack, same install, no dependencies. It uses torch and comfy.utils, both of which ship with ComfyUI - there's no requirements.txt and no model to fetch.

    ComfyUI Manager → Custom Nodes Manager → Install via Git URL → paste https://github.com/artfat-creator/ComfyUI-Artfat-Resolution. Or by hand:

    cd ComfyUI/custom_nodes
    git clone https://github.com/artfat-creator/ComfyUI-Artfat-Resolution.git
    

    Then restart ComfyUI properly - not just a browser refresh. Node classes only register on startup.

    Where people get burned

    The node that won't run. Because width and height are forced inputs, ComfyUI treats them as required sockets - leave either unwired and you get a validation error, not a default. There's no widget to type into as a fallback.

    Mismatched multiple. Artfat Resolution defaults its snap to 32; this node defaults to 16. They don't have to match, but if you're comparing the chain's final_short against the base node's info readout and the numbers disagree by a handful of pixels, a different multiple is why. Pick one and set both.

    Snapping nudges the aspect. Each side rounds independently, so an awkward ratio can land a pixel or two off what you asked for - noticeable only when you're tiling final renders into a grid.

    Expecting it to upscale anything. It hands out numbers. The latent upscaler and the pixel upscaler still have to exist in the graph, and their own snapping can differ from this plan's. The chain gives you a sane target; it can't police what's downstream.

    Categoryartfat

    Inputs (5)

    NameTypeDefaultDescription
    widthINTBase width (from Artfat Resolution).
    heightINTBase height (from Artfat Resolution).
    mid_scaleFLOAT1.501–8Latent upscale between the two samplers. Wire mid_scale into the latent upscaler's scale (SesquiLSR works from 1.0 to 2.0).
    final_scaleFLOAT1.501–8Image upscale after decoding, on top of mid_scale.
    multipleCOMBO16Snap the sizes to a multiple. Even sizes are required by SeedVR2.

    Outputs (2)

    NameTypeDescription
    mid_scaleFLOATInto the latent upscaler's scale.
    final_shortINTShort edge of the final image: into SeedVR2's `resolution` (it takes the short edge).