Nodes/SuperScaler/Pipeline SuperScaler
ComfyUI Node

Pipeline SuperScaler

The node that swallows your 12-node upscale chain

By tritant·Created 10 months ago·Updated 9 months ago· 169
Pipeline SuperScaler
  • image_in
  • mask_in
  • model_pass_1
  • vae_pass_1
  • positive_pass_1
  • negative_pass_1
  • model_pass_2
  • vae_pass_2
  • positive_pass_2
  • negative_pass_2
  • model_pass_3
  • vae_pass_3
  • positive_pass_3
  • negative_pass_3
  • image_out
enable_latent_passfalse
latent_upscale_by1.1
latent_denoise0.20
latent_sampler_name
latent_scheduler
latent_steps6
latent_cfg1.00
enable_tiled_pass_2true
tiled_upscale_by_22.0
tiled_denoise_20.25
tile_size_2960
tile_overlap_264
tiled_sampler_name_2
tiled_scheduler_2
tiled_steps_28
tiled_cfg_21.00
enable_tiled_pass_3false
tiled_upscale_by_32.0
tiled_denoise_30.25
tile_size_3960
tile_overlap_364
tiled_sampler_name_3
tiled_scheduler_3
tiled_steps_38
tiled_cfg_31.00
enable_sharpenfalse
sharpen_amount1.00
sharpen_radius1
enable_grainfalse
grain_typepoisson
grain_intensity0.014
grain_size1.3
saturation_mix0.20
adaptive_grain0.15
mask_blend_weight1.00
seed0

Generative upscaling in ComfyUI is normally a pile of nodes: an upscale, a VAE encode, a sampler, a decode, then a second pass on top, then a sharpen and a grain node bolted on the end. SuperScaler_Pipeline exists to collapse that pile into one collapsible box. You feed it an image, wire in a model, VAE and conditioning, and it runs a latent refine, up to two tiled generative upscales, frequency-split sharpening and film grain, then hands you a finished image_out - no Ultimate SD Upscale + tile-ControlNet + post-fx sprawl in between.

Where it sits in the upscaling picture matters. "Upscale" covers two different jobs: adding pixels (ESRGAN, Lanczos) and inventing detail (SUPIR, SeedVR2, tile-ControlNet). SuperScaler is firmly the second kind - it's not a model, it's a workflow, and it ships no weights. It downloads nothing and reuses whatever checkpoint, VAE and conditioning you already have loaded.

How it works

The node is four passes in sequence, each one toggled on or off (the JS drops each disabled section's widgets out of the UI, which is why the node doesn't look as terrifying as the parameter list suggests):

  • Pass 1, latent refine. VAE-encode, nearest-neighbor upscale the latent, sample, decode. A gentle img2img pass for refining before the real upscale. Off by default.
  • Pass 2 & 3, tiled generative upscales. This is the meat. It first does a plain bicubic upscale in pixel space, then chops that into overlapping tiles. Each tile is VAE-encoded, sampled through nodes.common_ksampler, decoded, multiplied by a feather mask, and blended over its neighbors - overlapping regions are averaged so you don't get visible seams. Tiling is what keeps big 2x+2x upscales on low-VRAM cards: peak memory is roughly one tile, not the whole image. The same seed runs through every tile, which is what stops adjacent tiles from going their own way and producing seams that even the feather mask can't hide.
  • Pass 4, post-FX. Frequency-split sharpen (scipy.ndimage.gaussian_filter) - blur a copy, subtract it to isolate the high-frequency detail, boost that, recombine. That's the trick that sharpens without halos. Then optional grain: poisson, gaussian or perlin noise, with saturation_mix to desaturate it and adaptive_grain to push more grain into shadows, because perfectly smooth skin reads as plastic.

There's also a masked final blend: feed a mask_in and the protected areas get swapped for a clean bicubic upscale of your original, so skies and smooth surfaces don't collect generative noise. Trap for newcomers: the mask logic is inverted from ComfyUI's usual convention. Black protects (clean upscale), white gets the full treatment. mask_blend_weight at 1.0 fully replaces the protected area, 0.5 gives a 50/50 mix, 0.0 does nothing.

The inputs that matter

You mostly live on these few, per pass:

  • enable_tiled_pass_2 - the workhorse. On by default.
  • tiled_upscale_by_2 / tiled_denoise_2 - how much you scale and how much the sampler is allowed to invent. 0.25–0.35 is the sweet spot for adding detail; above that and it starts rewriting your image.
  • tile_size_2 / tile_overlap_2 - larger tiles = fewer passes but more VRAM; more overlap = fewer seams but more redundant work.
  • seed - one global seed drives all three generative passes, with the standard fixed/increment/randomize control.

Note the defaults: pass 2 uses CFG 1.0 and 8 steps, which is a guidance-distilled (Flux-style) model's territory. On SDXL you'll want to raise tiled_cfg_2 toward 6–7 or you'll get mush.

Installing it

ComfyUI Manager → search "SuperScaler", or:

cd ComfyUI/custom_nodes
git clone https://github.com/tritant/ComfyUI_SuperScaler

Restart ComfyUI. No model downloads - it uses your existing checkpoints. One real gotcha: the node imports scipy at module load, but the pack's pyproject.toml declares no dependencies, so Manager won't always pull it in. If the node refuses to appear, install it yourself:

pip install scipy

Where people get burned

The most common failure is leaving Pass 1 on without wiring its model inputs - the node skips any pass whose model/VAE/conditioning aren't connected, so your "refine" silently never runs. Watch the console, too: it logs every tile (PASS 2: Inférence de la tuile 12/45... - the author's French leaks through, harmless). A 4K upscale is a lot of sequential tiles, so this is not a fast node; it's a patient, VRAM-bounded one. That's the honest trade: convenience and memory fit, at the cost of speed you'd only notice on a big image. For one-off "make it 4K and film-like" jobs it's the node I'd actually reach for over rebuilding the chain from scratch.

Categoryupscaling

Inputs (50)

NameTypeDefaultDescription
image_inIMAGE
mask_inoptMASK
enable_latent_passoptBOOLEANfalse
model_pass_1optMODEL
vae_pass_1optVAE
positive_pass_1optCONDITIONING
negative_pass_1optCONDITIONING
latent_upscale_byoptFLOAT1.11–4
latent_denoiseoptFLOAT0.200–1
latent_sampler_nameoptCOMBO44 options: euler, euler_cfg_pp, euler_ancestral, euler_ancestral_cfg_pp, heun, heunpp2, +38
latent_scheduleroptCOMBO9 options: simple, sgm_uniform, karras, exponential, ddim_uniform, beta, +3
latent_stepsoptINT61–1000
latent_cfgoptFLOAT1.000–100
enable_tiled_pass_2optBOOLEANtrue
model_pass_2optMODEL
vae_pass_2optVAE
positive_pass_2optCONDITIONING
negative_pass_2optCONDITIONING
tiled_upscale_by_2optFLOAT2.01–8
tiled_denoise_2optFLOAT0.250–1
tile_size_2optINT960256–2048
tile_overlap_2optINT6432–512
tiled_sampler_name_2optCOMBO44 options: euler, euler_cfg_pp, euler_ancestral, euler_ancestral_cfg_pp, heun, heunpp2, +38
tiled_scheduler_2optCOMBO9 options: simple, sgm_uniform, karras, exponential, ddim_uniform, beta, +3
tiled_steps_2optINT81–1000
tiled_cfg_2optFLOAT1.000–100
enable_tiled_pass_3optBOOLEANfalse
model_pass_3optMODEL
vae_pass_3optVAE
positive_pass_3optCONDITIONING
negative_pass_3optCONDITIONING
tiled_upscale_by_3optFLOAT2.01–8
tiled_denoise_3optFLOAT0.250–1
tile_size_3optINT960256–2048
tile_overlap_3optINT6432–512
tiled_sampler_name_3optCOMBO44 options: euler, euler_cfg_pp, euler_ancestral, euler_ancestral_cfg_pp, heun, heunpp2, +38
tiled_scheduler_3optCOMBO9 options: simple, sgm_uniform, karras, exponential, ddim_uniform, beta, +3
tiled_steps_3optINT81–1000
tiled_cfg_3optFLOAT1.000–100
enable_sharpenoptBOOLEANfalse
sharpen_amountoptFLOAT1.000–5
sharpen_radiusoptINT11–20
enable_grainoptBOOLEANfalse
grain_typeoptCOMBOpoisson3 options: poisson, gaussian, perlin
grain_intensityoptFLOAT0.0140.001–1
grain_sizeoptFLOAT1.31–16
saturation_mixoptFLOAT0.200–1
adaptive_grainoptFLOAT0.150–2
mask_blend_weightoptFLOAT1.000–1
seedoptINT00–18446744073709550000

Outputs (1)

NameTypeDescription
image_outIMAGE