Nodes/ComfyUI-FluxProgressiveLockedUpscale/Flux: Locked Progressive Upscale 3-Stage (RES4LYF)
ComfyUI Node

Flux: Locked Progressive Upscale 3-Stage (RES4LYF)

The Flux Upscale That Doesn't Redraw Your Image

By lookuters22·Created 3 months ago·Updated 3 months ago· 0
Flux: Locked Progressive Upscale 3-Stage (RES4LYF)
  • model
  • latent
  • positive
  • negative
  • vae
  • sampler
  • base_sampler
  • refine_sampler
  • upscale_model
  • latent
  • image
  • seed
cfg1.0
seed0
base_steps20
base_schedulerbeta57
upscale_factor6.00
max_step_scale1.60
upscale_steps20
upscale_schedulerbeta57
tail_steps_first_upscale6
tail_steps_last_upscale3
enable_refinetrue
refine_steps20
refine_schedulerbeta57
refine_enter_sigma0.60

If you've ever upscaled a Flux image and watched the face subtly become a different person on the second pass, you know the problem this node exists to kill. Normal latent upscaling re-noises the whole image, so the model is free to drift composition, faces, and text every time you jump up in resolution. This single node - Flux: Locked Progressive Upscale 3-Stage (RES4LYF) - is a one-node pipeline that generates at a small base size, walks it up to full res with locked-noise progressive stages, and finishes with an optional refine pass. Feed it an empty latent and a finished image comes out the other end.

What it is

It's a Flux port of ComfyUI-ZImageTurboProgressiveLockedUpscale, reworked so every stage samples through comfy.sample.sample_custom with a SAMPLER object you wire in, instead of the built-in KSampler. Practically: plug in a RES4LYF ClownSampler and you get the whole engine - eta, SDE noise modes, res_2m/res_3s, bongmath - with none of it hardcoded into this node. You tune the sampler on the ClownSampler, not here.

How the locking works

Four mechanics, all latent-shape based so they're model-agnostic:

  1. Progressive scale ladder - the total upscale is split into small steps each ≤ max_step_scale instead of one big jump.
  2. Locked noise - the noise for the new resolution keeps the previous stage's coarse modes exactly and only injects fresh noise in the orthogonal (high-frequency) complement. It's still statistically N(0,I), so the sampler behaves normally - but composition survives.
  3. Pixel-space lifting - between stages the latent is decoded, upscaled (with your upscale_model if provided, else bicubic), and re-encoded, so detail rides on real pixels.
  4. Sigma-sliced partial denoise - each upscale stage runs only the tail of the schedule, so the model refines rather than redraws.

The inputs that matter

The shared three you actually set: model, latent, and sampler. The latent decides the mode - feed an empty EmptyLatentImage (say 144×208) and Stage 1 runs a full base generation; feed a VAE Encode of an existing image and Stage 1 is skipped, leaving just upscale + refine. The sampler input is where your ClownSampler goes; base_sampler and refine_sampler override it per stage if you want an eta=0.5 base and a clean eta=0.0 refine. Keep cfg at 1.0 for distilled Flux and drive guidance with a FluxGuidance node on the positive conditioning.

Stage 2 knobs a beginner actually touches: upscale_factor (default 6.0, the total upscale), max_step_scale (1.6 - smaller means more, gentler stages; the stage count is roughly ceil(log(factor)/log(max_step_scale))), and the tail-step ramp, where tail_steps_first_upscale/tail_steps_last_upscale (6 and 3 by default) go from a stronger refine on the small first stage to a lighter touch on the last. upscale_model is optional - drop a RealESRGAN in for the pixel-space lifts instead of bicubic.

Stage 3's refine_enter_sigma is the one to tune: it decides how deep into the schedule the refine starts. Lower = less denoise = more preservation. Flux's flow sigmas differ from Z-Image's, so start around 0.5–0.8 and raise it for a stronger refine. Outputs are latent, image, and seed.

Install

ComfyUI Manager → Install via Git URL, or:

cd ComfyUI/custom_nodes
git clone https://github.com/lookuters22/ComfyUI-FluxProgressiveLockedUpscale

Then restart. No extra Python dependencies - it only uses what ComfyUI already ships. Do install RES4LYF too, because it's the intended pairing and there's a real gotcha hiding here: the default schedulers (beta57, ays_kl) come from RES4LYF's extended scheduler list. Without it, the dropdown falls back to stock schedulers and the node's defaults don't resolve the way the README assumes.

Where people trip

The refine_enter_sigma retune is the big one - porting the Z-Image default straight over gives you a stronger or weaker refine than you want, and it's the first thing to move if faces feel plastic. The stage-count math also surprises: 6.0 factor at 1.6 max isn't "one 6× jump," it's ~4 small stages, which is exactly why starting from a ~140×200 base is cheap and fast. And note everything currently shares one Flux model - cross-model setups like a Z-Image base with Flux refine are planned (the pixel-space handoffs are built for it) but not here yet.

One more thing worth knowing before you build your dream workflow on this: RES4LYF itself is AGPL-3.0 with a rider that bars commercial image-generation services without a separate license. This node is MIT, but the sampler you pair it with carries that baggage.

Categoryupscale

Inputs (23)

NameTypeDefaultDescription
modelMODEL
latentLATENT
positiveCONDITIONING
negativeCONDITIONING
vaeVAE
samplerSAMPLERMain SAMPLER (RES4LYF ClownSampler). Used for the UPSCALE stages, and as the fallback for the base/refine stages if no dedicated sampler is wired.
cfgFLOAT1.01–30Keep 1.0 for guidance-distilled Flux (use a FluxGuidance node on conditioning).
seedINT00–18446744073709550000
base_stepsINT201–99STAGE 1 (base generation, only if an EMPTY latent is fed). Full schedule length.
base_schedulerCOMBObeta57STAGE 1 scheduler for the from-noise base generation.
upscale_factorFLOAT6.001–24STAGE 2. Total upscale. Number of internal stages = ceil(log(factor)/log(max_step_scale)).
max_step_scaleFLOAT1.601.1–6STAGE 2. Max per-stage upscale ratio. Smaller = more, gentler stages.
upscale_stepsINT204–99STAGE 2. Base schedule length; each stage runs only its tail.
upscale_schedulerCOMBObeta57STAGE 2 scheduler (beta57 / ays_kl / comfy schedulers all work).
tail_steps_first_upscaleINT61–24STAGE 2. Tail steps for the first (smallest) upscale. More = stronger refine.
tail_steps_last_upscaleINT31–24STAGE 2. Tail steps for the last (largest) upscale. Fewer = lighter touch.
enable_refineBOOLEANtrueSTAGE 3 on/off. When off, the node returns the upscale result directly.
refine_stepsINT201–99STAGE 3 schedule length. Executed steps depend on refine_enter_sigma.
refine_schedulerCOMBObeta57STAGE 3 scheduler.
refine_enter_sigmaFLOAT0.600.01–15STAGE 3. Enter the schedule at this sigma. Lower = less denoise = more preservation. Retune for Flux's flow sigmas (often higher than the Z-Image default).
base_sampleroptSAMPLERSTAGE 1 sampler override. If unconnected, the main 'sampler' is used.
refine_sampleroptSAMPLERSTAGE 3 sampler override. If unconnected, the main 'sampler' is used.
upscale_modeloptUPSCALE_MODELSTAGE 2. Pixel-space upscaler (e.g. RealESRGAN) used between stages instead of bicubic.

Outputs (3)

NameTypeDescription
latentLATENT
imageIMAGE
seedINT