Nodes/ComfyUI Impact Pack/TwoSamplersForMask Upscaler Provider
ComfyUI Node Runs on cloud

TwoSamplersForMask Upscaler Provider

Mask-split sampling, plugged into Iterative Upscale

By ltdrdata·Created 3 years ago·Updated 4 months ago· 3,242
TwoSamplersForMask Upscaler Provider
  • base_sampler
  • mask_sampler
  • mask
  • vae
  • full_sampler_opt
  • upscale_model_opt
  • pk_hook_base_opt
  • pk_hook_mask_opt
  • pk_hook_full_opt
  • UPSCALER
scale_method
full_sample_schedule
use_tiled_vaefalse
tile_size512

The mask-aware Upscaler for Iterative Upscale: it extends TwoSamplersForMask's split-region idea - a base sampler outside the mask, a different sampler inside it - so that split-region sampling happens at every step of an iterative upscale, not just once. Per the README, "This is an Upscaler that extends TwoSamplersForMask to be used in Iterative Upscale."

Unlike the pack's basic_pipe-based upscaler providers, this one only needs a vae on top of its two samplers - model, positive and negative are already bundled inside the KSAMPLER objects you build with KSamplerProvider, so there's nothing separate left to supply.

How it works

You give it a vae, a mask, and two KSAMPLERs (base_sampler for outside the mask, mask_sampler for inside it). When Iterative Upscale calls this Upscaler at each step, it scales the image with scale_method, then samples the unmasked and masked regions with their respective samplers - same split as TwoSamplersForMask, repeated at every upscale step instead of once.

full_sample_schedule adds a third mode: at certain steps (controlled by the schedule - options like interleave1, last2, or combinations like interleave2+last1) the node runs a full, non-split sampling pass across the whole image instead, using full_sampler_opt if supplied. That's useful for letting the whole image reconcile globally between mask-split steps, so the base and mask regions don't drift apart tonally across many iterations. use_tiled_vae swaps the VAE decode/encode for a tiled version inside each step, trading a little speed for lower VRAM.

The inputs and outputs that matter

  • vae (required) - used for the internal decode/upscale/encode round-trip at each step.
  • base_sampler / mask_sampler (both KSAMPLER, required) - build with KSamplerProvider (or TiledKSamplerProvider for a tiled sampler on either side). Base outside the mask, mask sampler inside it.
  • mask (required) - defines the split.
  • scale_method (nearest-exact / bilinear / lanczos / area) - how each step's resize happens.
  • full_sample_schedule - when (if ever) a whole-image pass runs instead of the split. none disables it entirely.
  • use_tiled_vae (default false) and tile_size (default 512) - VRAM controls for the internal VAE steps.
  • Optional: full_sampler_opt (needed if full_sample_schedule isn't none), upscale_model_opt (an ESRGAN-family model for the resize step), and up to three pk_hook slots (pk_hook_base_opt, pk_hook_mask_opt, pk_hook_full_opt) for attaching separate PK_HOOK behaviors - a CFG schedule, a denoise schedule - to each of the three sampling paths independently.

Output is a single UPSCALER - a plugin, not an image. Wire it into Iterative Upscale (Latent/on Pixel Space) or Iterative Upscale (Image).

How to install it

Via ComfyUI Manager: search ComfyUI Impact Pack, install, restart. Manually:

cd ComfyUI/custom_nodes
git clone https://github.com/ltdrdata/ComfyUI-Impact-Pack comfyui-impact-pack
cd comfyui-impact-pack
python -m pip install -r requirements.txt   # ComfyUI's python; python_embeded on portable

then restart. If either sampler is a TiledKSamplerProvider, you'll also need BlenderNeko/ComfyUI_TiledKSampler - not required if you're using plain KSamplerProviders. For upscale_model_opt, grab an ESRGAN-family model into ComfyUI/models/upscale_models, separately from the base pack install.

Common issues & troubleshooting

Nothing happens when connected alone. By design - this only produces an UPSCALER plugin. Feed the output into an Iterative Upscale node, which actually loops and samples.

Set full_sample_schedule but no full-frame pass fires. Check that full_sampler_opt is actually connected - the schedule only fires a full-image pass if you've supplied a sampler for it.

Base and mask regions drift apart after several iterations. That's exactly what full_sample_schedule exists to counter. Add full_sampler_opt and a schedule like interleave2+last1 to periodically reconcile the whole frame.

Ran out of VRAM on a large iterative upscale. Turn on use_tiled_vae and/or lower tile_size. This node does real sampling at every step, so it's heavier than a plain interpolation-only upscaler by design.

Do you need this over the pipe version, TwoSamplersForMaskUpscalerProviderPipe? They're functionally equivalent - the difference is purely how model/positive/negative get supplied. This one skips a basic_pipe because those three already live inside your two KSAMPLER objects; the pipe version wants them bundled separately. Use whichever matches what's already in your graph.

CategoryImpactPack/Upscale

Inputs (13)

NameTypeDefaultDescription
scale_methodCOMBO4 options: nearest-exact, bilinear, lanczos, area
full_sample_scheduleCOMBO9 options: none, interleave1, interleave2, interleave3, last1, last2, +3
use_tiled_vaeBOOLEANfalse
base_samplerKSAMPLER
mask_samplerKSAMPLER
maskMASK
vaeVAE
tile_sizeINT512320–4096
full_sampler_optoptKSAMPLER
upscale_model_optoptUPSCALE_MODEL
pk_hook_base_optoptPK_HOOK
pk_hook_mask_optoptPK_HOOK
pk_hook_full_optoptPK_HOOK

Outputs (1)

NameTypeDescription
UPSCALERUPSCALER