Nodes/ComfyUI-PolyhedronLoRAStack/⬡ Polyhedron Power Upscale
ComfyUI Node

⬡ Polyhedron Power Upscale

MoE-aware tiled upscaler: one node in place of a chained double upscale setup, mirroring the sampler's Single / High+Low split. Tile size is chosen against free VRAM rather than a fixed guess, the pixel model can sit in front of the stages or behind the last decode (which is where it earns its time) - and there the output canvas is YOUR factor, not the model's native one, so swapping pixel models changes their imprint, never the file size. Every stage reports its own seconds so the slow one is visible instead of merely suspected.

By PolyhedronAI·Created 3 months ago·Updated 17 days ago· 2
⬡ Polyhedron Power Upscale
  • model
  • positive
  • negative
  • vae
  • upscale_model
  • image
  • video
  • model_low
  • upscale_model_low
  • image
  • video
dual_moefalse
upscale_by1.10
denoise0.19
steps3
cfg1.6
upscale_by_low1.30
denoise_low0.25
steps_low5
cfg_low1.9
seed0
sampler_name
scheduler
tile_size1024
tile_overlap64
sigma_shift0.00
sampler_lowsame as high
scheduler_lowsame as high
result_previewtrue
process_previewOff
mute_staging_logstrue
resize_methodlanczos (cpu)
per_batch8
vae_tilingOff
pixel_stagemodel + fit
final_upscale_by1.00
sigma_shift_low-1.00
CategoryPolyhedron/Upscaling

Inputs (35)

NameTypeDefaultDescription
modelMODELThe diffusion model refining the tiles. In High + Low this is the HIGH-noise expert (structure); the LOW expert plugs into 'model_low'.
positiveCONDITIONINGConditioning to include (shared by both stages).
negativeCONDITIONINGConditioning to exclude (shared by both stages).
vaeVAEThe VAE encoding/decoding every tile. A Wan VAE turns the whole frame stack of a tile into ONE 5D video latent, so the video model itself keeps time consistent inside the tile.
upscale_modelUPSCALE_MODELPixel upscale model for the stage pre-pass (ESRGAN family via core/spandrel). In High + Low this serves the HIGH stage; the LOW stage uses 'upscale_model_low' when wired, else this one.
dual_moeBOOLEANfalseUpscaling architecture. Single: one stage — ESRGAN x upscale_by, then a tiled refine on 'model'. High + Low: the mixture-of-experts STAGE CHAIN — stage H (the HIGH-noise expert, 'model') shapes structure at upscale_by/denoise/steps/cfg, then stage L (the LOW-noise expert, 'model_low') polishes detail at the *_low values, each stage with its own upscale model. This is the correct MoE translation for refine-strength denoises: a sigma-boundary split (the sampler's Handoff) would hand the HIGH expert zero steps below the boundary.
upscale_byFLOAT1.101–8Stage-H size factor (Single: the whole factor). The stage canvas snaps to the VAE /8 grid.
denoiseFLOAT0.190–1Stage-H refine strength. ~0.2 keeps the input and adds detail; higher re-imagines.
stepsINT31–10000Stage-H steps per tile (Lightning/distilled experts need few).
cfgFLOAT1.60–100Stage-H CFG. Distilled / Lightning LoRAs live near 1.
upscale_by_lowFLOAT1.301–8High + Low: stage-L size factor (total = product of both).
denoise_lowFLOAT0.250–1High + Low: stage-L refine strength (detail polish).
steps_lowINT51–10000High + Low: stage-L steps per tile.
cfg_lowFLOAT1.90–100High + Low: stage-L CFG.
seedINT00–18446744073709550000Base seed. Every tile derives its noise seed from (seed, tile index) — deliberately NOT from the frame number, so a video batch keeps the same noise structure per tile over time (less flicker).
sampler_nameCOMBOSampling algorithm — the full list, no per-model subset.
schedulerCOMBOSigma schedule — the full list.
tile_sizeINT102464–4096Tile edge for the refine (constant per axis — uniform tiles are what diffusion models like). Clamped to the canvas.
tile_overlapINT640–1024Target overlap between neighbouring tiles. Tiles are stitched as a weighted sum with smoothstep feathers whose accumulated weight is EXACTLY 1 everywhere — the reason this node has no seam-fix family: none is needed. When a canvas can't host the requested overlap safely, the planner narrows it (correct beats wide).
sigma_shiftFLOAT0.000–20Flow-matching sigma shift, the sampler's own mechanism (0 = off). Wan 2.2 wants its native shift (typically 8.0) or the tile schedules are mis-scaled. Applied to both experts in High + Low.
sampler_lowCOMBOsame as highHigh + Low: sampling ALGORITHM for stage L ('sampler_name' drives stage H). The stages are independent runs, so this is always honoured. Ancestral / SDE samplers (*_a, *_sde) inject fresh noise per step — at refine strengths that changes the grain.
scheduler_lowCOMBOsame as highHigh + Low: sigma SCHEDULE for stage L. Always honoured — stage L builds its own schedule from steps_low / denoise_low anyway, so a second scheduler breaks nothing (no handoff, no seam).
result_previewBOOLEANtrueShow the finished frames inside the node (small temp JPEGs; multi-frame runs play as a flipbook at the source frame rate). Never touches the outputs.
process_previewCOMBOOffWatch the refine LIVE: the tile being sampled right now, a minimap locating it on the stage canvas, and stage/tile/step counters. Off = zero overhead (the probe is never built). latent2rgb = free, but it reads the LATENT's grid (/8 - a 768 tile is 96px, and it looks it). vae (sharp) = a real decode of one frame per event: full resolution, at the cost of one vae forward - measured against the stage clock and dropped back to latent2rgb on its own if it starts eating the pass.
mute_staging_logsBOOLEANtrueSilence ComfyUI's per-tile staging INFO lines ('prepared for dynamic VRAM loading', 'x models unloaded') while a stage runs. Restored byte-exactly after. Turn Off when debugging VRAM.
resize_methodCOMBOlanczos (cpu)Fit onto the stage canvas after the pixel upscale. 'lanczos (cpu)' = the historic path, byte-identical. bicubic/bilinear/area/nearest run chunked on the GPU (fast). nvidia_rtx_vsr = Maxine VideoSuperRes (needs nvvfx + RTX).
per_batchINT81–256Frames per chunk for the ESRGAN pass and its fit (the upscale + fit are FUSED per chunk, so the peak holds only this many frames at the intermediate size). 129 frames through a 4x model is a ~15 GB tensor in one go - this is the OOM guard. There is no 0 any more: it meant 'whole batch', which is exactly the 14.7 GB path this node removed. For the old behaviour set 256.
vae_tilingCOMBOOffSpatial VAE tiling for each tile's encode/decode. Off = the historic path (byte-identical). A size (512/640/768) cuts the VAE peak on big canvases, at the cost of a tiny internal blend at the VAE tile borders. NEVER temporal: a Wan VAE compresses time 4:1, so time tiles would stutter.
pixel_stageCOMBOmodel + fitHow each stage reaches its canvas. 'model + fit' = the wired UPSCALE_MODEL runs first, the fit lands it on the exact stage size (the classic recipe). 'fit only' IGNORES the wired model; resize_method does the whole upscale -- seconds instead of minutes, and the refine paints the detail anyway. 'model only' = the canvas IS the model factor; upscale_by is ignored (loudly), the fit only corrects to the /8 snap. 'model final' = the stages run pure fit and the last stage's pixel model runs ONCE behind the final decode -- the measured place for it: no VAE follows, its detail goes straight to the file (resize_method='none' keeps the raw model result; a kernel supersamples it back to the dialled canvas). Measured: a pixel model in FRONT of a VAE round trip is nearly free of effect -- the /8 compression cannot carry its fine detail. Switch without unplugging.
final_upscale_byFLOAT1.000.25–8Canvas of the FINAL pixel pass (pixel_stage='model final'), as a factor of the stage result. The model always computes its native factor; the kernel then lands it on THIS canvas -- the model's imprint reaches the file while the size stays yours (swap a 2x/4x/8x model: the imprint changes, the size never). 1.0 = the stage canvas (classic supersample refine); below 1.0 = supersampled DOWNscale (sprite work). Ignored (loudly) when resize_method='none', which keeps the raw model result.
sigma_shift_lowFLOAT-1.00-1–20Flow-matching sigma shift for stage L (the LOW-noise expert). -1 = 'same as high': stage L follows sigma_shift, so both stages are shifted alike. 0 = OFF for stage L only -- its model_sampling is left alone even when sigma_shift is set. Any positive value gives stage L its OWN shift (e.g. sigma_shift 8.0 with sigma_shift_low 5.0). Always honoured: the stages are independent runs, so unlike the Sampler there is no mode in which this goes inert. Works with or without a wired 'model_low' -- without one, stage L falls back to the 'model' input and gets its own shifted copy of it.
imageoptIMAGEFrame input [N,H,W,C] — stills or an unpacked video. Wire EXACTLY one of image / video.
videooptVIDEONative VIDEO input (green). Its frames are upscaled; its audio and frame rate ride through losslessly into the VIDEO output. Wire EXACTLY one of image / video.
model_lowoptMODELHigh + Low: the LOW-noise expert for stage L. Unwired -> stage L falls back to 'model'.
upscale_model_lowoptUPSCALE_MODELHigh + Low: stage-L pixel upscale model - and, with pixel_stage='model final', the model of the FINAL pass behind the last decode. Unwired -> stage L runs a plain fit (the H model is NOT inherited) and a 'model final' run says so and skips the final pass.

Outputs (2)

NameTypeDescription
imageIMAGE
videoVIDEO