
Tiled upscaler for FLUX.2 klein (and similar models)
Explanation after the images.
FLUX.2 [klein] (and reference-latent edit models in general) have a resolution limit per call. If you want to add real detail to something (sharpen fabric texture, hair, stitching) you can do it working with it in pieces. The obvious way to do that turned out to be full of dead ends, so here's what I learned.
What it does: splits the image into overlapping tiles, regenerates each one at the model's native resolution, and blends them back into one image.
My first attempt did tiling the"proper" way: the MultiDiffusion/Mixture-of-Diffusers trick, where you slice the latent and blend the per-step noise predictions. That works great on convolutional UNets (SD1.5/SDXL), because a convolution is local, it doesn't care where in the canvas a patch sits.
FLUX is a transformer with absolute position embeddings (RoPE), not a UNet. Hand it a raw slice of a bigger latent and it has no idea it's a fragment, it just sees "a small complete image" and redraws the entire subject inside every tile. Every tile becomes a full (wrong-scale) copy of the whole scene.
I found that FLUX's RoPE positions can be shifted per-call via transformer_options so I tried telling each tile where it really sits in the canvas. Didn't help. Turns out FLUX applies that same shift to the tile and to any attached reference latent, so the relative offset between them (the only thing that matters for attention) never changes. Patching the model's forward pass to shift only the tile and not the reference removed the duplication, but the model still composed each slice as a standalone image, it was never trained to generate fragments, so proportions came out wrong regardless.
What actually worked: don't fight the model's training. Tile in pixel space. Every call is a complete image at a resolution it knows how to handle and solve everything else (continuity, color, blending) outside the model:
- each tile is cropped from the canvas of already-generated neighbours, so it continues real pixels instead of guessing that region blind
- per-tile color matching back to the source, so tiles don't drift in exposure/tint
- blend weights derived from the actual per-side overlap, not the requested one (if the fade is narrower than what two tiles really share, you get a flat 50/50 band in the middle.
One node, no manual ReferenceLatent/EmptyLatent/KSampler wiring. You just give it a model, plain CLIPTextEncode conditioning, a VAE and an image.
GitHub: https://github.com/GianlucaMancuso/ComfyUI-TiledUpscale
Also on the ComfyUI Registry, search "TiledUpscale" in Manager.
Happy to answer questions, and if anyone knows a cleaner way to condition a transformer edit model on true image fragments, I'd genuinely like to hear it.