Nodes/WAS Affine/Ultimate Affine KSampler
ComfyUI Node

Ultimate Affine KSampler

Ultimate Affine KSampler, no upscale

By WASasquatch·Created about a year ago·Updated 5 months ago· 5
Ultimate Affine KSampler
  • image
  • model
  • positive
  • negative
  • vae
  • external_mask
  • options
  • noise_options
  • affine_schedule
  • IMAGE
seed0
steps20
cfg8.0
sampler_nameeuler
schedulersimple
denoise0.20
affine_interval1
max_scale1.2000
max_bias0.0000
patternwhite_noise
affine_seed0
affine_seed_incrementfalse
tile_width0
tile_height0
tile_overlap64
tiled_decodefalse
tiled_tile_size512
tiled_overlap64
tiled_temporal_size64
tiled_temporal_overlap8
batch_size0
merge_frames_in_batchtrue
vae_encode_batch_modeimages

WASUltimateCustomAdvancedAffineNoUpscale - "Ultimate Affine KSampler" in the UI - is the pack's flagship image node, and the one behind the README's 720p → 2k demo. It takes an image, re-encodes it to latent, runs a tiled sampling pass with Affine's scale/bias enhancement baked into every few steps, and hands you back pixels. The "No Upscale" in the name is the key: unlike the sibling USDU node it doesn't scale the image up with a model first. It's a quality pass, not a size pass - low-denoise, tiled, and detail-targeted.

If you've ever done the hi-res-fix dance - upscale, re-sampler at low denoise, watch the seams - this is that idea collapsed into one node with the seams handled for you. The tiling is the Ultimate SD Upscale approach: split into overlapping tiles, sample each, blend, no VRAM ceiling on output size. The README's own "Things to take note of" on the 2k example - better rock, natural brush, preserved foreground, reduced contrast - is the Affine pitch in one screenshot: it tames the burned, over-contrasted output that speed LoRAs love to produce.

How it works

At its core it's a KSampler with three things bolted on:

Tiling. tile_width/tile_height (default 0) in image pixels. 0 disables tiling (one pass over the whole image); -1 auto-sizes tiles to ≤1024px; explicit values give you control. tile_overlap (default 64px) is how much tiles bleed into each other so the seams don't show. Tiling is what lets you process a 2K image on a card that can't touch a 2K image in one shot.

Affine, scheduled during sampling. Every affine_interval steps (default 1 = every step), the sampler applies z' = scale * z + bias through a mask generated from pattern (26 choices, default white_noise). max_scale (default 1.2) is the peak - the scale ramps as 1 + (max_scale-1)*t - and max_bias (default 0) adds a brightness offset that also scales with progress. The affine_seed controls the mask; toggle affine_seed_increment to vary it per application for temporal variety. Optionally drop a grayscale external_mask on it to gate the whole thing to specific regions, and layer the option dicts (options + pattern-specific noise_options) for finer control.

Standard sampler controls. sampler_name (default euler, 44 choices), scheduler (default simple), steps (20), cfg (8), denoise (default 0.2). That low default denoise is the whole trick - you're not regenerating, you're re-detailing. You can even pass a per-step list as cfg for schedule-shaped guidance.

The VRAM knobs are worth naming because they're why this node works on modest cards: tiled_decode (uses ComfyUI's VAE tiled decode for big outputs), batch_size (chunks the batch dimension), and merge_frames_in_batch (flattens 5D video decodes so batches concatenate safely). vae_encode_batch_mode mirrors the Wan encode node: images or frames, depending on whether your input batch is stills or video frames.

The output

One IMAGE, ready for a preview or save node - and that's the point, it's a complete replace-in-line upscale-and-refine stage.

Installing it

Part of WAS Affine (WASasquatch/was_affine). Manager: search "WAS Affine", install, restart. Or:

cd ComfyUI/custom_nodes
git clone https://github.com/WASasquatch/was_affine.git

No model downloads, deps are torch/numpy (plus matplotlib). Despite the name, it explicitly does not require UltimateSDUpscale nodes.

Where people get burned

  • Start with the Affine dials low. The README hammers this: latent space is sensitive, scale=0.95 can be strong. The default max_scale of 1.2 is a big swing on some models - pull it toward 1.05 before blaming the sampler.
  • Model sensitivity varies wildly. The README flags that Flux/Krea-family models may want inverted (positive) scale behavior, and that Lightning LoRAs pair best with CFG 1–2. If your first run looks wrong, check these before anything else.
  • Pattern choices are 26 but defaulting is fine. White noise works as a general mask; perlin/worley for organic content, velvet/ring for fine detail. Don't feel obligated to options-node every pattern.
  • Tiling ≠ free. Very small tiles with heavy overlap multiply the sampling work; -1 auto-sizing is usually the best price/quality point.
Categoryimage/upscaling

Inputs (32)

NameTypeDefaultDescription
imageIMAGEInput IMAGE or VIDEO tensor. Supports [B,H,W,C] or [B,F,H,W,C].
modelMODELDiffusion model to sample with.
positiveCONDITIONINGPositive prompt conditioning.
negativeCONDITIONINGNegative prompt conditioning.
vaeVAEVAE used to encode/decode latents during USDU.
seedINT00–18446744073709550000Seed for base sampler (noise).
stepsINT201–10000Number of denoising steps.
cfgFLOAT8.00–100Classifier-free guidance scale. Can be a single float or a per-step list (short lists repeat last value).
sampler_nameCOMBOeulerBase sampler algorithm.
schedulerCOMBOsimpleScheduler for sigma schedule.
denoiseFLOAT0.200–1Denoise fraction (<=1).
external_maskoptIMAGEOptional external mask to gate affine.
optionsoptDICTBase options for Affine (common/full options).
noise_optionsoptDICTPattern-specific overrides layered onto 'options'.
affine_intervaloptINT11–100Apply affine every N steps (1 = every step).
max_scaleoptFLOAT1.20000–2Scale at schedule peak: 1 + (max_scale-1)*t.
max_biasoptFLOAT0.0000-2–2Bias at schedule peak: max_bias*t.
patternoptCOMBOwhite_noiseAffine mask pattern.
affine_seedoptINT00–18446744073709550000Seed for affine mask generation (separate from sampler seed).
affine_seed_incrementoptBOOLEANfalseIncrement affine seed after each application (temporal).
affine_scheduleoptDICTWASAffineScheduleOptions dict; interpreted over total steps with repeat-last behavior.
tile_widthoptINT0-1–16384IMAGE-space sampling tile width in pixels. 0 disables IMAGE tiling (single pass). -1 auto-calculates proportional tile size ≤1024 pixels.
tile_heightoptINT0-1–16384IMAGE-space sampling tile height in pixels. 0 disables IMAGE tiling (single pass). -1 auto-calculates proportional tile size ≤1024 pixels.
tile_overlapoptINT640–2048IMAGE-space overlap between sampling tiles (pixels).
tiled_decodeoptBOOLEANfalseUse VAE tiled decode to reduce VRAM spikes for large outputs/video.
tiled_tile_sizeoptINT51264–8192Target output tile size (pixels) for VAE tiled decode.
tiled_overlapoptINT640–1024Output-space overlap (pixels) for tiled decode.
tiled_temporal_sizeoptINT640–4096Temporal window size (frames) for video tiled decode. 0 disables temporal tiling.
tiled_temporal_overlapoptINT80–512Temporal overlap (frames) for video tiled decode.
batch_sizeoptINT00–4096Process the batch dimension in chunks of this size to reduce peak VRAM. 0 = process all at once. Applies to non-tiling path.
merge_frames_in_batchoptBOOLEANtrueIf decoded IMAGE is 5D [B,F,H,W,C], merge F into batch for concat.
vae_encode_batch_modeoptCOMBOimagesimages: treat batch dim as separate images [B,C,1,H,W]. frames: treat batch dim as video frames [1,C,B,H,W].

Outputs (1)

NameTypeDescription
IMAGEIMAGE