ComfyUI Node

Universal NN Latent Upscale

A smarter hires-fix latent upscaler for SD, Flux, and Wan — if you read the fine print

By DenRakEiw·Created about a year ago·Updated a day ago· 27
Universal NN Latent Upscale
  • latent
  • LATENT
version
upscale1.50
force_reloadfalse

First, the thing everyone gets wrong about this node: it does not give you a bigger image. Its output is a bigger latent - a tensor of VAE-compressed noise vectors you feed back into a sampler. This is the "hires fix" trick: VAE-encode, blow the latent up, denoise again at low strength, and let the model paint detail at the higher resolution. The pixel upscalers you've read about (ESRGAN, SeedVR2) work in image space; this works before the decoder, so it's nearly free and can't add detail that was never there.

Universal NN Latent Upscale does that job a little better than the stock bilinear interpolation ComfyUI ships. It's a fork of Ttl's ComfyUi_NNLatentUpscale with small trained networks covering SD 1.5, SDXL, Flux, and Wan 2.2 in one node - a WIP pack from a single author (DenRakEiw) with no community footprint, so treat it as a neat experiment.

How it works

Each architecture's latents live in a differently-scaled space, which is why a "universal" upscaler needs per-model weights. SD latents are 4 channels; Flux and Wan are 16. The node normalizes the input by a per-model scale factor (0.13025 for SD/SDXL, 0.3611 for Flux, 0.3604 for Wan), runs a tiny CNN - three conv layers, a transposed-conv upsampler, a residual skip connection - then denormalizes. That skip connection is the point: the model learns a correction on top of the bilinear baseline rather than building the upscale from scratch. The README's Wan numbers are honest about the size of the win: SSIM 0.3247 vs 0.2690 for bilinear (20.7% better), but PSNR barely moves. Meaningful, not magical.

It also handles Wan's 5D video latents [B, C, T, H, W]: single-frame latents squeeze to 4D and upscale normally, multi-frame ones process frame by frame (more in the gotchas).

The inputs that matter

Only three inputs really matter:

  • version - the dropdown. Must match the model that produced the latent. SD 1.5 and SDXL are both 4-channel but have separate weights; Flux and Wan are 16-channel. This is the one input beginners get wrong, and the mismatch is silent - see below.
  • upscale - 1.0× to 2.0×, default 1.5, which is the right default. 1.5 keeps the second denoise pass cheap; 2.0 doubles what the sampler has to fill, and you'll pay in quality drift.
  • latent - the LATENT output of VAE Encode (or a Wan image-encoder / sampler for video).

force_reload (default off) is a developer switch that reloads the model and forces re-execution every run. Leave it alone unless you're swapping weights.

Output: a single LATENT, wired into a KSampler at low denoise (0.3–0.5), then VAE Decode. VAE Encode → Universal NN Latent Upscale → KSampler → VAE Decode is the whole workflow.

Installing it

Manager is the easy path: ComfyUI Manager → Install Custom Node → search "WAN_NN_Latent_Upscale". Or by hand:

cd ComfyUI/custom_nodes
git clone https://github.com/DenRakEiw/WAN_NN_Latent_Upscale

Restart ComfyUI and the node appears under Add Node → latent → Universal NN Latent Upscale. No heavy dependencies - it's plain PyTorch plus numpy, all of which ComfyUI already has - so there's no install step beyond the clone. The four model weights (12.6MB each for SD/SDXL, 25.3MB Flux, 3.9MB Wan) are checked into the repo and come with the clone; nothing extra to fetch.

Gotchas and honest troubleshooting

  • The README lies about auto-download. It claims models "download on first use if not present," but the code downloads nothing - if a weight file is missing it logs a warning and silently falls back to bilinear interpolation. The weights ship in the repo so this rarely bites, but if you ever delete models/, you'll get "neural upscale" that is secretly just bilinear. Also skip the clone URL in the README body - it's a placeholder that doesn't exist; use the one above.
  • Wrong version = silent degradation. Mismatched channels make the state dict fail to load, and the node falls back to bilinear rather than erroring. To confirm the NN is actually running, watch the console for "Loaded … model".
  • It won't add detail. This is the cheap rung of upscaling. Soft or damaged sources want SeedVR2/SUPIR territory; this node just starts the second pass from a slightly better baseline than bilinear.
  • Video caveat. Wan latents with more than one frame are upscaled frame-by-frame, with no temporal consistency, so fine texture can shimmer between frames. For the common "generate video, upscale the first frame" pattern (T=1) you're fine; don't use it as a whole-clip upscaler.

Where this earns its keep is the Wan 2.2 path - that's the model the author actually trained for, and the one that didn't already have a good latent-upscale story. On SDXL or Flux, bilinear is a fine baseline and you have faster hires options anyway.

Categorylatent

Inputs (4)

NameTypeDefaultDescription
latentLATENT
versionCOMBO4 options: SD 1.5, SDXL, Flux, Wan2.2
upscaleFLOAT1.501–2
force_reloadoptBOOLEANfalse

Outputs (1)

NameTypeDescription
LATENTLATENT