Karma KSampler Cycle
Your entire hires-fix loop in one node
- primary_model
- vae
- latent_image
- positive
- negative
- secondary_model
- upscale_model
- pos_additive
- neg_additive
- latent(s)
- vae
The classic way to get a sharp, high-resolution image is a chain: sample at native resolution, upscale, sample again at low denoise, maybe upscale and sample a third time. That's the hires-fix loop, and on paper it's simple. On canvas it's a sprawl of KSamplers, image scalers and latent resizers that you have to keep in sync by hand. Karma KSampler Cycle is the flagship node of this pack, and its whole pitch is that it runs that loop for you - one node, N cycles, progressive upscaling between each, and it handles the plumbing.
The way it works is worth understanding before you dial it in, because the defaults are not tuned for your model. Each cycle, the node samples your latent with a standard KSampler, then - on every cycle except the last - it upscales toward a single final target dimension and feeds the result back in for the next pass. In pixel space it decodes, upscales, and re-encodes (that's the basic and model methods). Or you pick latent, and it resizes the latent tensor directly with torch interpolation - no VAE roundtrip, meaningfully faster, slightly rougher. The total upscale factor is spread geometrically across cycles, so a 2-cycle run does one upscale operation at factor upscale_factor, while a 4-cycle run takes the fourth root each time.
That's the core. Everything else is automation on top. With denoise scaling on, denoise roughly halves each cycle and floors at denoise_min_threshold, so early cycles do the heavy lifting and later ones just add detail. Steps scaling either increments or decrements steps per cycle, clamped by a threshold you can set to auto (derived from your initial steps) or manual. You can switch to a secondary_model at a chosen cycle, blend extra pos_additive/neg_additive conditioning in with strength scaling, sharpen between cycles, and toggle tiled VAE for large outputs.
The inputs a beginner actually sets: total_cycles, starting_denoise, cycle_denoise, upscale_factor, and upscale_method. The rest of the ~40 inputs have sane defaults and you should touch them only when something's wrong. Wire up primary_model, vae, latent_image, positive, negative, pick a sampler_name/scheduler, and run. You get latent(s) (feed it to VAE Decode) and a passthrough vae.
Where people get burned:
upscale_method=modelwith no upscale model connected doesn't error - it silently falls back tobasicand prints a warning to the console. That's a nice degradation, but if your output suddenly looks softer than expected, check the console.- If your
stepsare lower thantotal_cycles, the node clamps the cycle count down to your steps. A 20-step, 6-cycle run is actually a 6-cycle run; a 4-step run with 6 cycles is a 4-cycle run. - Latent upscale "lanczos" isn't really lanczos. Torch's
interpolatehas no lanczos mode, so the node remaps it to bicubic. It's in the source, not the README. Fine in practice - just don't expect pure lanczos behavior. - VRAM. High upscale factors plus many cycles means decode/upscale/re-encode repeatedly. That's the OOM classic, and
use_tiled_vaeis the first thing to flip when it hits.
Installing it
Search "KarmaNodes" in ComfyUI Manager, or:
cd ComfyUI/custom_nodes
git clone https://github.com/KarmaSwint/ComfyUI-KarmaNodes
cd ComfyUI-KarmaNodes
pip install -r requirements.txt
Restart ComfyUI. No model files download - but if you want upscale_method = model, you supply your own upscale model (drop it in ComfyUI's models/upscale_models and connect it to the upscale_model input).
Tuning it
Start with 3–4 cycles, upscale_factor 1.5–2, starting_denoise 1.0, cycle_denoise 0.4–0.5. Denoise above ~0.5 on the final passes starts moving composition rather than adding detail, which is the usual reason the output drifts from your first-pass framing. For refinement, run steps scaling in decrement mode (20 → 15 → 10 → 5); for detail-hunting, use increment with a manual cap. The node prints a verbose play-by-play to the console with every cycle's denoise, steps and dimensions - genuinely useful when you're diagnosing, if noisy.
Is it a replacement for a hand-built hires-fix + ControlNet-Tile stack? Not quite - it's a convenience node, not a quality ceiling. But for the 80% case where you just want clean, progressively-refined output without maintaining a wall of nodes, it's the fastest route from latent to finished image in this pack.
Inputs (40)
| Name | Type | Default | Description |
|---|---|---|---|
| primary_model | MODEL | — | |
| vae | VAE | — | |
| latent_image | LATENT | — | |
| positive | CONDITIONING | The main positive conditioning. | |
| negative | CONDITIONING | The main negative conditioning. | |
| steps | INT | 201–10000 | — |
| seed | INT | 00–18446744073709550000 | — |
| cfg | FLOAT | 8.000–100 | — |
| sampler_name | COMBO | 44 options: euler, euler_cfg_pp, euler_ancestral, euler_ancestral_cfg_pp, heun, heunpp2, +38 | |
| scheduler | COMBO | 9 options: simple, sgm_uniform, karras, exponential, ddim_uniform, beta, +3 | |
| starting_denoise | FLOAT | 1.000–1 | — |
| cycle_denoise | FLOAT | 0.500–1 | — |
| total_cycles | INT | 22–12 | — |
| enable_denoise_scaling | BOOLEAN | true | Enable automatic denoise strength scaling between cycles |
| denoise_min_threshold | FLOAT | 0.100.01–1 | Minimum denoise threshold to prevent going too low |
| enable_steps_scaling | BOOLEAN | false | Enable automatic steps adjustment between cycles |
| steps_scaling_value | INT | 51–50 | Amount to adjust steps by each cycle |
| steps_adjustment_mode | COMBO | decrement | Whether to decrease or increase steps each cycle |
| steps_threshold_mode | COMBO | auto | Auto calculates threshold based on initial steps, manual uses fixed value |
| steps_manual_threshold | INT | 51–200 | Manual threshold value (only used when threshold mode is manual) |
| secondary_model_start_cycle | INT | 21–12 | Cycle at which to switch to secondary model (if provided) |
| upscale_factor | FLOAT | 2.00.1–8 | — |
| upscale_method | COMBO | basic | basic = PIL image upscale, model = upscale model, latent = direct latent space resize (fastest, no VAE decode/encode) |
| scale_sampling | COMBO | Resampling method for image upscaling | |
| latent_upscale_method | COMBO | lanczos | Resampling method for latent space upscaling |
| enable_gradual_upscaling | BOOLEAN | false | Enable gradual upscaling with multiple intermediate steps |
| gradual_upscale_steps | INT | 31–10 | Number of gradual upscaling steps (only used when gradual upscaling is enabled) |
| pos_add_strength | FLOAT | 0.250.01–1 | — |
| enable_pos_strength_scaling | BOOLEAN | false | Enable positive strength scaling between cycles |
| pos_add_strength_cutoff | FLOAT | 2.000.01–10 | — |
| neg_add_strength | FLOAT | 0.250.01–1 | — |
| enable_neg_strength_scaling | BOOLEAN | false | Enable negative strength scaling between cycles |
| neg_add_strength_cutoff | FLOAT | 2.000.01–10 | — |
| sharpen_strength | FLOAT | 0.000–10 | — |
| sharpen_radius | INT | 21–12 | — |
| use_tiled_vae | BOOLEAN | false | Use tiled VAE processing for large images |
| secondary_modelopt | MODEL | Optional secondary model to switch to at specified cycle | |
| upscale_modelopt | UPSCALE_MODEL | — | |
| pos_additiveopt | CONDITIONING | Additional positive conditioning to blend in. | |
| neg_additiveopt | CONDITIONING | Additional negative conditioning to blend in. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| latent(s) | LATENT | — |
| vae | VAE | — |