Donut Tiled Upscale
Tiled img2img that works on any model
- image
- upscale_model
- model
- positive
- negative
- vae
- clip
- edit_model
- edit_source_image
- edit_source_image_b
- color_reference
- nag_negative
- nag_ref_boost_mask
- image
- debug_image
The wall every ComfyUI user hits eventually: your image looks great at 1024×1024, but at 4K the GPU chokes, and the moment you try to denoise a big latent you get CUDA out of memory. The standard escape is tiled upscaling - process the image in overlapping tiles, blend the seams, and never hold the whole thing in VRAM at once. DonutTiledUpscale is that idea, but deliberately model-agnostic: it samples with the same approach as the core KSampler, so it works with SDXL, Z-Image/Lumina2, and the rest of the modern architectures rather than being hard-wired to one UNet layout.
How it works
Two passes, the standard shape for this kind of node:
- Pixel upscale - your
upscale_model(an ESRGAN-style model like 4x-UltraSharp, or whatever you load into an Upscale Model loader) resizes the image, tiled internally with overlap so the upscaler itself doesn't blow memory. - Diffusion refinement - the upscaled canvas is sliced into roughly 1-megapixel tiles, each run through an img2img denoise with your prompt, then stitched back with feathered overlap so seams don't show.
feather(default 15, as a % of tile size) is your seam-blending knob.
That two-stage flow matters. The pixel pass adds the pixels; the diffusion pass adds the detail - this is "more detail" territory, not just "more pixels," so expect the model to gently re-render things. Keep your denoise low (default 0.35) unless you want a rewrite.
Inputs that actually matter
The plumbing is standard: image, upscale_model, model, positive/negative, vae - then sampler settings (seed, steps, cfg, sampler_name, scheduler, denoise) exactly like a KSampler. The Donut-specific ones:
- rescale_factor - the upscale factor (1–8, default 2). The tooltip explains the real behavior: regular mode picks ~1MP tiles; edit mode snaps the target to a 32px grid.
- resampling_method - lanczos (default), bicubic, bilinear, or nearest. Lanczos is the right default.
- feather - seam blend width, regular mode only.
- tiled_vae - use a tiled VAE decode to save even more VRAM (regular mode only).
- tiled_diffusion (optional, default on) - process in overlapping diffusion tiles. Turn it off for one full-resolution diffusion pass; the tooltip is not kidding about needing "substantially more VRAM."
- turbo_mode (optional) - for distilled models (Z-Image Turbo, Lightning): treats your steps as the model's supported Turbo steps and snaps denoise to the nearest valid scheduler point. Use this if your images come out over-sampled on a Turbo model.
Outputs are image and debug_image - the second shows the tile layout, which is genuinely useful the first time seams appear.
The edit mode
There's an optional edit_mode that's a completely different animal: one full-frame Krea2 img2img upscale against a full reference, no diffusion or VAE tiling. It needs clip (required in this mode), an edit_source_image identity reference, edit_prompt/edit_negative_prompt, and optionally edit_model (a Krea2 model with the Identity Edit LoRA pre-applied). If that sentence means nothing to you, ignore the toggle - it's for identity-preserving edits on Krea2 models, and the default off is the sensible place for it.
Install
Ships in ComfyUI-DonutNodes: ComfyUI Manager → search "DonutNodes" → install → restart. Manual:
cd ComfyUI/custom_nodes
git clone https://github.com/DonutsDelivery/ComfyUI-DonutNodes.git donutnodes
cd donutnodes
python -m pip install -r requirements.txt
No model downloads in the pack itself - but the node needs an upscale_model you supply (any ESRGAN-style .safetensors in your upscale_models folder). Dependencies are opencv-python-headless, scipy, matplotlib, psutil, tqdm, requests.
Where people get burned
- Seams or tile-boundary artifacts - raise
feather, and glance atdebug_imageto see your actual grid. - Content drift at high denoise - this is a detail pass, not a free lunch. Denoise above ~0.5 and the model starts re-imagining; below ~0.2 and it does almost nothing. 0.3–0.4 is the honest sweet spot for most models.
- Edit mode with no CLIP - it hard-requires
clipand anedit_source_image; wire them or the mode is a footgun. - VRAM still OOMs - that's
tiled_diffusionoff ortiled_vaeoff. Turn both on for the memory-friendly path.
Compared to the established giants (Ultimate SD Upscale from Impact Pack, Tiled Diffusion), this doesn't reinvent the wheel - its selling point is that it samples like core ComfyUI, so it keeps working as new architectures (Z-Image and friends) arrive. If you're on SDXL and already happy with Ultimate SD Upscale, there's no urgent reason to switch. If you're on a newer model where the old tiling nodes misbehave, this is the one to reach for.
Inputs (55)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| upscale_model | UPSCALE_MODEL | — | |
| model | MODEL | — | |
| positive | CONDITIONING | — | |
| negative | CONDITIONING | — | |
| vae | VAE | — | |
| seed | INT | 00–18446744073709550000 | — |
| steps | INT | 201–10000 | — |
| cfg | FLOAT | 7.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 | |
| denoise | FLOAT | 0.350–1 | — |
| rescale_factor | FLOAT | 2.01–8 | Upscale factor relative to the input image. The selected VAE preserves these dimensions, including the internally 2x VAE. Tiled mode uses ~1MP diffusion tiles; full-frame mode aligns the sampling canvas to 32 pixels. |
| resampling_method | COMBO | lanczos | 4 options: lanczos, nearest, bilinear, bicubic |
| feather | FLOAT | 150–50 | Regular tiled mode only. Feather/blend zone as percentage of tile size. |
| tiled_vae | BOOLEAN | false | Regular mode only. Edit mode forces one full-frame regular VAE decode. |
| edit_modeopt | BOOLEAN | false | Run one full-frame Krea2 img2img upscale against the full reference at the configured denoise; no diffusion or VAE tiling. |
| clipopt | CLIP | Required when edit_mode is enabled. | |
| edit_modelopt | MODEL | Optional Krea2 model with the Identity Edit LoRA already applied. Falls back to model. | |
| edit_source_imageopt | IMAGE | Full identity reference used for edit-mode source patching and grounded encoding. | |
| edit_promptopt | STRING | — | |
| edit_negative_promptopt | STRING | — | |
| grounding_pxopt | INT | 7680–4096 | — |
| turbo_modeopt | BOOLEAN | false | Treat steps as the model's supported Turbo steps and snap denoise to the nearest valid scheduler point. |
| tiled_diffusionopt | BOOLEAN | true | Process the upscaled canvas in overlapping diffusion tiles. Disable for one full-resolution diffusion pass; this requires substantially more VRAM. |
| edit_source_image_bopt | IMAGE | Optional second edit reference (subject/identity). edit_source_image is the scene/base. | |
| color_referenceopt | IMAGE | Optional color reference. Defaults to the input image. | |
| color_preserve_strengthopt | FLOAT | 0.000–1 | 0 disables preservation; 1 fully matches output RGB mean/std to the reference after sampling and decode. |
| nag_enabledopt | BOOLEAN | false | Apply Krea2 NAG inside sampling (requires krea2-nag). Uses CFG 1; Turbo negative conditioning stays zeroed. |
| nag_negativeopt | CONDITIONING | Unzeroed negative prompt for NAG. Fusion Rebalance/taps are applied to match the positive stream. Defaults to edit_negative_prompt in edit mode, otherwise negative. | |
| nag_phiopt | FLOAT | 4.00–20 | — |
| nag_tauopt | FLOAT | 2.500.01–20 | — |
| nag_alphaopt | FLOAT | 0.250–1 | — |
| nag_sigma_startopt | FLOAT | 1000.00–1000 | — |
| nag_sigma_endopt | FLOAT | 0.00–1000 | — |
| nag_ref_boostopt | FLOAT | 1.000–1000 | — |
| nag_ref_boost_aopt | FLOAT | 1.000–1000 | — |
| nag_fit_modeopt | COMBO | fit | 2 options: fit, crop (legacy) |
| nag_ref_boost_maskopt | MASK | — | |
| nag_auto_phiopt | BOOLEAN | false | Derive phi from alpha so alpha*phi keeps the upstream default linear guidance strength (0.25*4 = 1.0). |
| nag_phi_scaleopt | FLOAT | 1.000–4 | Multiplier for auto phi. 1.0 keeps upstream-default linear guidance strength; higher/lower scales it. |
| enabledopt | BOOLEAN | true | — |
| upscale_engineopt | COMBO | Donut | Donut keeps the existing upscale + diffusion pass. SeedVR2 uses its own native model/VAE; only the stage seed, scale and resize filter are shared. |
| seedvr2_model_nameopt | COMBO | seedvr2_3b_int8_convrot.safetensors | 2 options: seedvr2_3b_int8_convrot.safetensors, seedvr2_7b_int8_convrot.safetensors |
| seedvr2_vae_nameopt | COMBO | seedvr2_ema_vae_fp16.safetensors | 1 options: seedvr2_ema_vae_fp16.safetensors |
| seedvr2_stepsopt | INT | 11–100 | — |
| seedvr2_denoiseopt | FLOAT | 1.000.01–1 | — |
| seedvr2_color_correctionopt | COMBO | none | 4 options: none, lab, wavelet, adain |
| seedvr2_vae_tile_sizeopt | INT | 1024128–4096 | Native VAE encode/decode tiling only, NOT diffusion tiling. 1024 is the quality-oriented high-resolution default; SeedVR2 diffusion still uses the full output canvas. |
| seedvr2_vae_overlapopt | INT | 1280–1024 | VAE tile overlap in pixels. 128 is the upstream high-resolution recommendation for 1024-pixel tiles. |
| vae_damage_correctionopt | BOOLEAN | false | Subtract estimated VAE damage after decoding, using the selected VAE's encoder and decoder for one extra round trip per image or face crop. The 2x VAE filters back to the current image size before subtraction. No original reference is needed. |
| vae_damage_strengthopt | FLOAT | 1.000–4 | 0 skips correction; 1 is one-pass VAE damage subtraction. Values above 1 strengthen the same correction and can amplify artifacts. Does not add more iterations. |
| nag_alpha_scheduleopt | COMBO | constant | NAG alpha over this stage's executed denoising steps. The global Settings / Configuration panel mirrors the same curve to every NAG stage; each stage spans its own effective step range. |
| nag_alpha_startopt | FLOAT | 0.250–1 | First executed step's NAG alpha for the shared dynamic schedule. |
| nag_alpha_endopt | FLOAT | 0.250–1 | Last executed step's NAG alpha for the shared dynamic schedule. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| debug_image | IMAGE | — |