self-hosted/ai
§01·recipe · image

Qwen-Image-2.1 on RTX 5090: what stays resident in 32 GB, int8 vs bf16, and third-party timings

imageintermediate12GB+ VRAMSep 23, 2026

This intermediate recipe sets up Qwen-Image-2.1 on the RTX 5090, needing about 12 GB of VRAM.

models
tools
prerequisites
  • NVIDIA RTX 5090 32 GB (Blackwell GB202, compute capability 12.0)
  • ComfyUI v0.37.0 or newer: the v0.37.0 Windows portable (the nvidia build, not the cu126 one) or a git install
  • A CUDA 13 (cu130) build of PyTorch and an NVIDIA driver from the 580 branch or newer
  • 18 GB free disk for the int8 diffusion model, int8 text encoder and VAE (17.28 GB as Hugging Face counts it)
  • System RAM: not established; of the RTX 5090 runs cited on this page, only PR #16430 names its RAM (96 GB)
  • Research or evaluation use only: the Qwen Research License forbids commercial use of the weights

What You'll Build

A local Qwen-Image-2.1 setup on one RTX 5090 in ComfyUI, using the int8 files ComfyUI's own templates load: text-to-image at 1024×1024 and at the model's native 2048×2048, RGBA output with a real alpha channel, and instruction-based editing with reference images. Qwen-Image-2.1 is a 7B single-stream diffusion transformer (32 layers, per the repo's transformer/config.json) behind a Qwen3-VL-8B text encoder and a four-channel RGBA autoencoder, released 2026-09-20.

On the 12 and 16 GB pages in this series the question is what has to move on and off the card. On this card it does not come up: the three template files are 16.096 GiB against the 31.842 GiB the card reports on Windows, and they stay on the card together at 2048×2048 as well, under both of ComfyUI's loaders (What 32 GB keeps resident, below). The question here is the opposite one — whether to load something bigger, or smaller, because it fits. This page's answer is to keep the template, for reasons worked out below and labelled by the kind of evidence behind each: on an RTX 5090, the int8 files took about half the time of the bf16 files in a controlled third-party comparison; the bf16 encoder-plus-transformer pair does not stay on the card through a decode even at 32 GB; and the 4-bit builds change the picture for a gain that has been measured once, together with a patched encoder.

This page was written on 2026-09-23 from public sources.

⚠️ Read the licence before you download 17 GB. The weights ship under the Qwen Research License Agreement. Section 1.i defines "Non-Commercial" as the only permitted use — it "shall mean for research or evaluation purposes only." — and section 2.a grants the licence "FOR NON-COMMERCIAL PURPOSES ONLY". The grant is worldwide and there is no clause excluding any territory (section 4.a only reminds you that export controls may apply); the restriction is on purpose, not on place. Section 4.b reaches outputs in one specific case: "If you use the Materials or any outputs or results therefrom to create, train, fine-tune, or improve an AI model that is distributed or made available, you shall prominently display “Built with Qwen” or “Improved using Qwen” in the related product documentation." Every repack on this page — Comfy-Org's int8 files and the community NVFP4 build included — is a derivative and carries the same terms. Section 2.b gives an address for a commercial licence; a reader reports in the vendor's discussion #7 that mail to it bounces. This is a reader's summary of the text, not legal advice.

Hardware data: RTX 5090 (32 GB VRAM, Blackwell GB202, compute capability 12.0) · not measured on this card by this site; the budgets are derived and the timings are third parties' · Windows reports the card as 34,190,458,880 B = 31.842 GiB, against 16.096 GiB for all three template files · See benchmark data

ℹ️ Nothing on this page was measured on an RTX 5090 by this site. The timings on it are other people's, each attributed where it appears and listed together under Results. The site operator's two sessions for this model ran on a different card, an RTX 5060 Ti 16GB (cu130 session, cu128 session). This page uses them for three facts about the software and the files, never as a time or a memory figure for this card, and labels each use where it appears: (1) what the cu130 warning costs the int8 path (Troubleshooting, the cu130 entry); (2) which of the int8 and bf16 diffusion models was faster per step on each build — int8 on the cu130 install, bf16 on the cu128 one (Running, the bf16 swap); (3) that the int8 and bf16 diffusion models gave nearly the same image from the same seed (Why this page stays on the template; Running, the bf16 swap). Each is one rig, one operator, unreplicated. Every VRAM figure below is arithmetic over byte counts and ComfyUI's own source at tag v0.37.0, shown so you can check it. If you run it, post your numbers.

The card. NVIDIA's RTX Blackwell architecture whitepaper (Appendix A, Table 3) lists the RTX 5090 as a GB202 with 32 GB of GDDR7 on a 512-bit bus and a PCI Express Gen 5 interface, and gives its dense peak tensor rates at boost clock as 838 TOPS for INT8, 209.5 TFLOPS for BF16 with FP32 accumulation, and 1676 TFLOPS for FP4. NVIDIA's CUDA GPU list puts it at compute capability 12.0. Those rates are why the int8-against-bf16 question gets a section on this page — on this card BF16 with FP32 accumulation peaks at a quarter of INT8 — but they are peak rates, not a measurement of this model, and nothing below converts them into a time.

What the budgets need is the capacity CUDA reports. ComfyUI prints it at startup as Total VRAM … MB (MiB, rounded), and its system-stats block prints the exact bytes as VRAM Total. A search of the ComfyUI tracker (queries listed at the end of this page; bodies and comments of all 157 threads they returned parsed) found 73 distinct startup logs from a desktop RTX 5090. Windows (MSC-built Python, drive-letter paths): 47 logs, 44 of them reading Total VRAM 32607 MB and three 32606 MB (#12998, #13157, #15666); 23 system-stats blocks give VRAM Total as exactly 34,190,458,880 B = 32,606.56 MiB = 31.842 GiB, among them #15255 on PyTorch 2.13.0+cu130. Native Linux (GCC-built Python, /home paths): 22 logs reading 32,087 to 32,120 MB, the lowest in PR #12658, a ComfyUI contributor's Linux machine, and five system-stats blocks between 33,668,857,856 and 33,680,457,728 B. Two more logs come from a Linux userland but read the Windows figure (#8634, and #10999, whose log also shows a Windows PowerShell prompt) — most likely WSL2, an inference; two carry no OS evidence. The budgets below use 34,190,458,880 B = 31.842 GiB on Windows (a 32606 MB reading is at most about 1 MiB lower, which moves no figure by more than 0.001 GiB) and, on native Linux, the lowest reading, 32,087 MiB = 33,645,658,112 B = 31.335 GiB (rounded to the MiB as printed). Linux therefore starts 544,800,768 B = 0.507 GiB lower; its reserves are also smaller, and every table gives both.

The capacity does not say how much of it the desktop, the CUDA context and other software hold. System-stats blocks give an example, with limits. In eleven Windows reports whose block shows Torch VRAM Total: 0 — PyTorch holding nothing — 1,694,040,064 to 1,964,572,672 B = 1.578 to 1.830 GiB of the card was not free when the report was written (#15259 and #12758 among them); in two Linux reports (#10696, #12105), 0.494 to 0.495 GiB. Each block was captured when its error report was generated, after work had run in that session, not at startup, and none says what held the memory. This page uses them only as example sizes for the share every "left" figure below still has to cover, and calls them the error-report shares wherever they appear.

Requirements

ComponentMinimumThis recipe
GPU12 GB VRAM for this install, NVIDIARTX 5090 (32 GB) — not measured by this site; the budget below is derived (/contribute)
RAMnot established; the RTX 5090 run in PR #16430 states 96 GB— the edit cache's RAM fallback asks for four times its size free (Editing)
Storage17,283,091,112 B = 16.096 GiB (int8 DiT + int8 encoder + VAE)— byte counts from the Comfy-Org tree API
SoftwareComfyUI ≥ v0.37.0, PyTorch cu130, driver ≥ 580

The three files the official templates load, byte-exact from the Comfy-Org repack at revision ace0edeb. The repo's head has moved twice since — to 5dc5850e on 2026-09-22 and 9a44dbdb on 2026-09-23, README updates by their titles — and every weight file has the same size and LFS sha256 at ace0edeb and at the head (tree API, read 2026-09-23).

FileBytesGiBDestination
diffusion_models/qwen_image_2.1_int8_convrot.safetensors7,256,783,0646.758models/diffusion_models/
text_encoders/qwen3vl_8b_int8_convrot.safetensors9,350,798,3608.709models/text_encoders/
vae/qwen_image_2.1_vae_bf16.safetensors675,509,6880.629models/vae/

The same repo holds a bf16 diffusion model (14,230,280,616 B = 13.253 GiB), a bf16 encoder (17,534,334,616 B = 16.330 GiB), a w4a8 encoder (6,312,105,364 B = 5.879 GiB) and two qwen3.5_9b_qwen_image_2.1_pe_{t2i,i2i}.int8_convrot.safetensors files of 9,471,072,252 B = 8.821 GiB each, which are prompt enhancers, not encoders (Running, the prompt enhancer). Its recursive tree lists exactly two diffusion-model files, bf16 and int8: there is no Comfy-Org fp8 or nvfp4 diffusion model for 2.1 in it. The ComfyUI docs page was synced with the templates on 2026-09-22 (source at 9d133794, unchanged since) and lists the two int8 files as the ones the templates load, with the bf16 files as the full-precision alternatives.

min_vram_gb is 12: the smallest card size in this catalogue on which every stage of this install keeps its weights whole under both loaders — the definition this model's RTX 3060 page uses. It is not this card's number.

What 32 GB keeps resident

ComfyUI has two loaders, and they budget VRAM differently. On this card the default is DynamicVRAM: main.py at v0.37.0 enables it on NVIDIA once PyTorch is 2.8 or newer and comfy-aimdo initialises, and the log says DynamicVRAM support detected and enabled. You land on the legacy estimate-based loader if you pass --disable-dynamic-vram (or --highvram, --gpu-only, --novram, --cpu). Both views come from ComfyUI's source at tag v0.37.0 (comfy/model_management.py, comfy/sampler_helpers.py, comfy/sd.py, comfy/model_patcher.py), from comfy-aimdo v0.5.5 (the version requirements.txt pins), and from byte counts. All sums are over unrounded bytes, rounded once.

DynamicVRAM (the default). ComfyUI's memory estimates do not decide residency here: the comment on memory_required() says that with every model dynamic the estimate "is ignored and its all done dynamically." The floor is comfy-aimdo's. On Windows the aimdo DLL is built from the Windows sources (build workflow), and src-win/shmem-detect.c keeps 512 MiB free against both the WDDM budget and NVML's free-VRAM reading. On Linux, src/plat.h defines VRAM_HEADROOM (256 * 1024 * 1024) and src/control.c keeps that much free against live free VRAM. Weights load on demand and are evicted only when an allocation needs the room — the comfy-aimdo README describes "on-demand offloading of model weights when the primary pytorch VRAM allocator comes under pressure" — and free_memory() does not unload one dynamic model for another (its comment: "don't actually unload dynamic models for the sake of other dynamic models"). So on this loader "resident" means: the weights plus the floor plus the stage's real allocations stay under what the card has free. No loader estimates those allocations; this page uses the legacy loader's VAE-decode estimate (below) as a stand-in for the largest of them, 1.758 GiB at 1024² and 7.031 GiB at 2048², and says so. Which sets stay whole, left over on Windows / native Linux, before the CUDA context, the display and any other software:

Weights on the cardWeightsAfter the aimdo floorAfter a 1024² decode near the stand-inAfter a 2048² decode near the stand-in
int8 DiT + int8 encoder (the template)16.096 GiB15.246 / 14.98913.488 / 13.2318.215 / 7.958
bf16 DiT + int8 encoder22.591 GiB8.752 / 8.4946.994 / 6.7361.720 / 1.463
int8 DiT + bf16 encoder23.718 GiB7.625 / 7.3675.867 / 5.6100.593 / 0.336
bf16 DiT + bf16 encoder30.212 GiB1.130 / 0.873over by 0.628 / 0.885over by 5.901 / 6.159
template + one prompt enhancer24.917 GiB6.426 / 6.1684.668 / 4.410over by 0.606 / 0.863

Every row includes the 0.629 GiB VAE. When the left-over figure does not cover the desktop, the context and the stage's allocations, aimdo evicts weights — and it evicts by priority, not by model: the aimdo README says "The most recent VBARs are the highest priority", and ComfyUI moves each dynamic model to the top when it loads it (vbar.prioritize() in model_patcher.py), so the model used longest ago loses weights first. That order is a reading of the source, not a measurement.

Legacy loader (only if you are on it). Here the reserve is real. minimum_inference_memory() is 0.8 GiB plus EXTRA_RESERVED_VRAM, which model_management.py (lines 877–881) sets to 400 MiB on Linux and 600 MiB on Windows, adding 100 MiB on Windows when the card's total exceeds 15 × 1024 MiB, which this card's does: so 700 MiB on Windows, and a fixed floor of 1.484 GiB on Windows and 1.191 GiB on Linux. The activation formula is area × 2 bytes × 0.01 × 6.0 MiB (memory_usage_factor 6.0 in supported_models.py). sampler_helpers.py computes it twice: an estimate at double batch (noise_shape[0] * 2, whatever the cfg) — 0.960 GiB at 1024², 3.840 GiB at 2048² — and a minimum at batch 1, 0.480 and 1.920 GiB. The VAE decode passes 900 × h × w × 256 × 2 bytes over the latent grid (sd.py, line 844): 1.758 GiB at 1024², 7.031 GiB at 2048². Two different figures come out of load_models_gpu(), and they answer different questions:

  • the unload request — before loading a model, free_memory() asks for 1.1 × the weights it is about to load plus the larger of the fixed floor and (the stage's estimate + EXTRA_RESERVED_VRAM). If less than that is free, it partially unloads other models, copying their weights back to system RAM, until it is (model_management.py, LoadedModel.model_unloadpartially_unload). This is what decides whether the other models stay.
  • the residency threshold — the model being loaded goes on the card whole if free VRAM covers its weights plus the larger of the fixed floor and (the minimum + EXTRA_RESERVED_VRAM); otherwise it loads partly.

For a set to stay whole through a generation, no stage's unload request may exceed what is free. The largest request comes at the decode, when the encoder and the diffusion model are already on the card: their weights + 1.1 × the VAE + the larger of the fixed floor and (the decode estimate + EXTRA_RESERVED_VRAM). Against the card, Windows / native Linux:

Set (legacy loader)Largest request, 1024²Left, 1024²Largest request, 2048²Left, 2048²
the template18.600 / 18.307 GiB13.242 / 13.02723.874 / 23.581 GiB7.968 / 7.754
bf16 DiT + int8 encoder25.095 / 24.802 GiB6.747 / 6.53330.368 / 30.075 GiB1.474 / 1.259
int8 DiT + bf16 encoder26.222 / 25.929 GiB5.620 / 5.40631.495 / 31.202 GiB0.347 / 0.133
bf16 DiT + bf16 encoder32.552 / 32.259 GiB at samplingover by 0.710 / 0.924over
template + one prompt enhancer27.421 / 27.128 GiB4.421 / 4.20732.695 / 32.402 GiBover by 0.852 / 1.067

"Left" must still cover the CUDA context, the display and other software. On a later generation the models are already loaded, so their requests shrink to the fixed floor or the stage's estimate; these first-run figures are the larger ones.

What that means, set by set:

  1. The template stays whole at both sizes, on both OSes, under both loaders. Its tightest figure is 7.754 GiB left (legacy, Linux, 2K decode), more than four times the largest error-report share. A prompt change re-runs the encoder and moves no weights; a seed change skips the encode; by the arithmetic above, a 2K decode of one image pushes nothing off. That is the 32 GB result, and it is why nothing on this card needs a smaller file.
  2. bf16 DiT + int8 encoder stays whole at 1024²; at 2048² it depends on your desktop. On the legacy loader the 2K decode leaves 1.474 GiB on Windows, and at the error-report shares (1.578 to 1.830 GiB) the loader has to find another 111,471,216 to 382,003,824 B = 0.104 to 0.356 GiB by partially unloading one of the resident models before the decode (which one depends on reference counts the arithmetic cannot see). Under DynamicVRAM a decode near the stand-in leaves 1.720 GiB on Windows, which sits inside that share range. On Linux, where the error-report shares are near 0.5 GiB, both loaders keep it whole.
  3. int8 DiT + bf16 encoder stays whole at 1024² only. At 2048² it has 0.347 GiB (legacy) or 0.593 GiB (DynamicVRAM, stand-in) on Windows for the context and the display, less than any error-report share. One published run shows this set not staying whole at 2K: the memory panels in PR #16430, on a Linux RTX 5090 with five 2048×2048 images in one batch, show the encoder as QwenImage21TEModel_ at 16.3 GB — by its size, the bf16 file (the PR names none) — with 3.8 GB of it on the card and 12.5 GB unloaded before that PR's change, and 13.7 GB on the card after it. That is a batch of five, whose activations are larger than one image's, and the PR does not state which commit its "before" run used.
  4. bf16 DiT + bf16 encoder does not stay whole even at 1024². The encoder and the diffusion model alone are 31,764,615,232 B = 29.583 GiB. On the legacy loader the first sampling request is 761,979,765 B = 0.710 GiB over the whole Windows card before anything else holds VRAM, so part of the encoder's weights leave the card before sampling — at least that much, plus the desktop's share — and the decode asks for more. Under DynamicVRAM 1.130 GiB is left on Windows after the floor, less than the error-report shares, and a decode near the 1.758 GiB stand-in is more than that again. Either way, weights go back and forth on this set: the card fits it on paper and not in use.

The prompt-enhancer row is under Running.

Why this page stays on the template

  • It is ComfyUI's own default, not a low-VRAM workaround: the templates load these files on every card (Running).
  • On this card, the int8 files were about twice as fast as the bf16 ones in the one controlled comparison on an RTX 5090 found in the sources searched (third-party, sourced): the NVFP4 converter's validation notes time three weight sets on an RTX 5090 under Windows, at 1024×1024 and 40 steps, whole pipeline: 15.629 s for the official bf16 files and 7.553 s for the official int8 ConvRot files (warm medians). The build is one commit before the v0.37.0 tag (its banner reads ComfyUI 0.36.0), and the runs used non-default flags. Details and limits are under Results; which part of the gap is sampling and which is the loading those runs repeated each time is not separated.
  • The bf16 pair does not stay on the card (arithmetic, above), and bf16 DiT + int8 encoder is only borderline at 2K on Windows.
  • No measurement in the sources searched shows bf16 drawing a better picture than int8. On the operator's RTX 5060 Ti, the int8 and bf16 diffusion models gave nearly the same image from the same seed, judged by eye, with the images unpublished (first-party use 3; one rig, one operator, unreplicated; cu128 session).

"It fits" is therefore not a reason to switch on this card. The bf16 diffusion model is documented below as a reference for readers who want to compare, with its cost stated; the 4-bit builds are documented with theirs.

Installation

1. ComfyUI v0.37.0 or newer, on a cu130 PyTorch

Support landed in ComfyUI core with PR #16400 (author kijai, merged 2026-09-19), and tag v0.37.0 (commit 73c9bad4) contains it. The v0.37.0 release, with its Windows portable builds, was published at 07:35 UTC on 2026-09-21 and was still the latest GitHub release at 13:07 UTC on 2026-09-23. A v0.37.1 tag was cut at 19:12 UTC on 2026-09-22 (commit 3f767e7f67), with no release object behind it as of that check; against v0.37.0 it adds three commits — Hunyuan Image 3.5 partner nodes (#16462), the workflow-templates pin raised from 0.11.66 to 0.11.68 (#16466), and the version bump. None of the three changes this model's code or any of the three Qwen-Image-2.1 workflow files, which are unchanged since 371a7b7171, the commit templates 0.11.66 already carried; what templates 0.11.67–0.11.68 add for 2.1 is translated titles and descriptions for its background-removal template and a trailing comma in bundles.json. The backport PR #16467 was closed without merging. This page keeps v0.37.0 as its floor.

Windows portable. Take ComfyUI_windows_portable_nvidia.7z from the v0.37.0 release. The ComfyUI README says "The portable above currently comes with python 3.13 and pytorch cuda 13.0." Do not take ComfyUI_windows_portable_nvidia_cu126.7z: the README labels it for 10-series and older cards, adding "DO NOT USE THIS ON NEWER 20 SERIES AND ABOVE GPUS", and on this card a CUDA 12 build switches off the fast int8 kernels (step 2).

Git (Linux; on Windows use the portable). Install PyTorch from the cu130 index first, then the requirements — the torch line in requirements.txt is unpinned, so the order decides which build you get:

git clone https://github.com/Comfy-Org/ComfyUI
cd ComfyUI
git checkout v0.37.0          # the floor and the safer default; see "Tag or master?" below
python3 -m venv .venv && source .venv/bin/activate
pip install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu130
pip install -r requirements.txt
python -c "import torch; print(torch.__version__, torch.version.cuda, torch.cuda.get_device_capability())"
# expect a +cu130 build, 13.0, and (12, 0)

The README states the requirement as policy — "Using a cu130 or above version of pytorch is required on Nvidia 20 series and above." — and a CUDA 13 build needs an NVIDIA driver from the R580 branch or newer, per NVIDIA's CUDA release notes. ComfyUI's maintainer put the support position plainly on #16455: "We do not support using cuda 12 on newer GPUs." requirements.txt at the tag pins comfy-kitchen==0.2.35, comfy-aimdo==0.5.5 and comfyui-workflow-templates==0.11.66; that comfy-kitchen release builds its wheels with 120f in the CUDA architecture list on Windows and Linux (setup.py), which covers compute capability 12.0. Leave this shell open with .venv active: step 3 runs in it.

Tag or master? master was v0.37.0 plus 15 commits at 13:07 UTC on 2026-09-23 (head b5cc8830). Three of them change the 2.1 transformer file, comfy/ldm/qwen_image21/model.py: PR #16429, which changes where the edit path's K/V cache is placed, PR #16430, which compiles the 2.1 transformer blocks, and PR #16419, which lets a model file choose the attention used per block. A fourth, PR #16442, adds a system-prompt argument to TextGenerate, and PR #16425 extends fast-disk detection to all model loaders. None is needed to run the templates. The crash report that matters most for this card is from this card: in open PR #16481, its author (sqz269, a community contributor) reports on Windows 11 with an RTX 5090, torch 2.13.0+cu130, the template's int8 diffusion model and encoder, DynamicVRAM on and QwenImage21Cache at auto, that the first generation succeeded and the second aborted during sampler cleanup, with text-to-image and edit workflows alike. The PR attributes it to the prefix cache's pinned system-RAM slots being unpinned while a copy may still be reading them. Its log says ComfyUI 0.37.0, but its stack's line numbers (qwen_image21/model.py 238, model_base.py 2678, model_patcher.py 1318) are those of master after the tag; at v0.37.0 and v0.37.1 the same lines are 236, 2674 and 1316 (the version file on master still reads 0.37.0, so the banner cannot tell them apart). The code the PR patches, PoseBranchCache._free_slot calling unpin_memory (model_animate2.py), is the same at the tag, so going back to the tag is not a known fix. On 2026-09-23 the PR was open and unmerged, and its only review was an automated bot's; no report of this crash on the tag turned up in the tracker threads read, which is an absence of reports, not a finding that the tag is unaffected. Its own stack's innermost frame, printed first, is model_animate2.py line 169 in free, which at the tag is self._staging = {}, reached after the slot-freeing loop has returned; so where exactly the process aborts is the PR's account, not something its stack shows. What the tag's code does suggest for this card is under Editing: a cache kept on the card holds neither pinned host memory nor staging buffers, and on 32 GB you can keep it there. The tag is the safer default, not a proven-immune one.

2. What compute capability 12.0 gets from these files

Both int8 files carry, per layer, the format int8_tensorwise with convrot: true and a group size of 256 (read from each file's safetensors header). What happens to them differs between the two models.

For the diffusion model, ComfyUI decides per device which formats run natively in get_disabled_quant_formats() in comfy/ops.py, and prints the result when it loads a quantised model as a line starting Native ops:. On compute capability 12.0 every check in model_management.py passes: supports_int8_compute() has no compute-capability test, supports_fp8_compute() is true from major 9, supports_nvfp4_compute() from major 10, and supports_mxfp8_compute() from major 10 with PyTorch 2.10 or newer. An RTX 5090 log on the recommended build line shows exactly that: #15480 (Windows, ComfyUI 0.31.1, PyTorch 2.13.0+cu130) prints Native ops: float8_e4m3fn, float8_e5m2, mxfp8, int8_tensorwise, convrot_w4a4, nvfp4, asym_w4a8_int8 with no emulated part, and Found comfy_kitchen backend cuda: with 'available': True, 'disabled': False. On PyTorch 2.9.1, mxfp8 alone moves to emulated ops (#15566), which does not matter for these files.

Which kernel then serves a native layer is decided one level down, in comfy-kitchen's CUDA backend (backends/cuda/__init__.py, pinned at the commit tagged v0.2.35):

  • int8 (the template's DiT): the CUTLASS INT8 path is enabled for compute-capability major 8 and above, so on this card the activations are rotated and quantised in a fused kernel and the GEMM runs as INT8.
  • nvfp4: scaled_mm_nvfp4 is registered with min_compute_capability=(10, 0), so it is native here.
  • convrot_w4a4 (the INT4 ConvRot builds): _cuda_device_supports_native_int4_mma() ends in return major == 8; its comment calls the kernel's MMA the "sm80+ integer MMA shape" and sends Hopper to the INT8 fallback. The test admits major 8 only, so compute capability 12.0 takes the fallback too: the activations are quantised to int8, not int4, and multiplied against the 4-bit weights — effectively W4A8. No source here shows whether sm_120 could run that MMA natively (the whitepaper lists FP4 and INT8 tensor rates and no INT4 rate).

For the text encoder none of that applies at encode time. At v0.37.0 every quantised encoder is built with mixed_precision_ops(..., full_precision_mm=True) in comfy/sd1_clip.py, so each weight is dequantised for its matmul on every card. CLIP.generate() in sd.py switches quantised matmuls back on (use_quantized_matmul) for text generation, which the prompt enhancer uses; the conditioning encode does not go through it. The encoder's file format is a memory choice, not a speed choice — and on this card memory is not the constraint.

Without cu130 the diffusion model still runs, the slow way. The gate is in comfy/quant_ops.py: below CUDA 13 it calls ck.registry.disable("cuda") and logs "WARNING: You need pytorch with cu130 or higher to use optimized CUDA operations." comfy-kitchen then falls through its backend order (cuda, triton — off by default — then eager), and the eager int8_linear applies the rotation as ordinary torch ops and still multiplies in INT8, without the fusion. The Native ops line will not warn you: it reflects the hardware, not which backend is alive. The tells are that WARNING and 'disabled': True in the Found comfy_kitchen backend cuda: line. That holds for the diffusion model only: text generation (the prompt enhancer) is reported failing outright on a CUDA 12 build with a pre-580 driver (Running, the prompt enhancer).

3. Download the weights

The repo's folder names match ComfyUI's models/ layout, so --local-dir models lands each file where the loaders look. On a git install, run this from the ComfyUI folder with .venv active:

pip install -U huggingface_hub
hf download Comfy-Org/Qwen-Image-2.1 \
  diffusion_models/qwen_image_2.1_int8_convrot.safetensors \
  text_encoders/qwen3vl_8b_int8_convrot.safetensors \
  vae/qwen_image_2.1_vae_bf16.safetensors \
  --revision ace0edeb3791a594ddfa36ed5f41a178a394e921 --local-dir models

On the Windows portable there is no pip or hf on PATH. Use the Python the portable ships, python_embeded\python.exe — the interpreter its run_nvidia_gpu.bat starts ComfyUI with and its updater runs pip through — from the portable's top folder:

python_embeded\python.exe -s -m pip install -U huggingface_hub
python_embeded\python.exe -s -m huggingface_hub.cli.hf download Comfy-Org/Qwen-Image-2.1 diffusion_models/qwen_image_2.1_int8_convrot.safetensors text_encoders/qwen3vl_8b_int8_convrot.safetensors vae/qwen_image_2.1_vae_bf16.safetensors --revision ace0edeb3791a594ddfa36ed5f41a178a394e921 --local-dir ComfyUI\models

(-m huggingface_hub.cli.hf is the module behind the hf command; it runs directly because cli/hf.py ends in a __main__ guard.)

Check the bytes against the LFS hashes before you debug anything (on Windows, certutil -hashfile <file> SHA256 prints the same hash):

sha256sum models/diffusion_models/qwen_image_2.1_int8_convrot.safetensors
# cb74113cb03faecd79611b01fd7fd642f0aa60d6f0b95086abee214d75eaa57d
sha256sum models/text_encoders/qwen3vl_8b_int8_convrot.safetensors
# 8bfd0f6e12abf2d2d697ecc888e5e90b0d6741d6708f05799f53afa560452e8f
sha256sum models/vae/qwen_image_2.1_vae_bf16.safetensors
# bb21f7473051e1ac368515dd3f2e15cd44d7a11748ee8823e1ddca3e4876b7c9

About the encoder. Comfy-Org's qwen3vl_8b_bf16.safetensors carries the same LFS sha256 (68bdc82b…) in the 2.1 repack and in Comfy-Org/Qwen3-VL, a repository that predates this model, and on the vendor's discussion #5 two readers report comparing tensors against stock Qwen3-VL-8B-Instruct and finding no retraining; Qwen's GitHub README names the text encoder as Qwen3-VL 8B without saying whether its weights differ from stock Qwen3-VL-8B, its HF card does not name the encoder, and no Qwen-member post in the vendor's discussions read says either way. Comfy-Org/Qwen3-VL also holds an fp8_scaled 8B file (10,588,637,512 B = 9.861 GiB) and an nvfp4 one (6,305,221,764 B = 5.872 GiB). Both are dequantised for the encode like every format, so on this card neither buys anything the int8 file does not.

Running

Start ComfyUI normally — no --lowvram, no --reserve-vram, no --highvram:

python main.py

On the portable, run run_nvidia_gpu.bat. Read the first screen of the log: ComfyUI version: 0.37.0 or higher; pytorch version: ending in +cu130 with no cu130 WARNING; Found comfy_kitchen backend cuda: with 'disabled': False; Total VRAM 32607 MB (or 32606) on Windows, between 32087 and 32120 MB on native Linux; DynamicVRAM support detected and enabled. --highvram would switch DynamicVRAM off and put you on the legacy loader (enables_dynamic_vram() in comfy/cli_args.py); on this card it buys nothing, since the template already stays whole. --lowvram is documented as "Doesn't do anything if dynamic vram is enabled." If you want more kept free for other software, --vram-headroom N adds N GiB on top of aimdo's checks; --reserve-vram N raises only the check against the card's total capacity (aimdo's control.py), and it is also what replaces EXTRA_RESERVED_VRAM on the legacy loader.

Text-to-image

Open the Template Library and load Qwen Image 2.1: Text to Image (image_qwen_image_2_1_t2i.json, templates 0.11.66, the version v0.37.0 pins). The values that govern it sit on the outer subgraph node: UNETLoaderqwen_image_2.1_int8_convrot.safetensors, CLIPLoaderqwen3vl_8b_int8_convrot.safetensors with type qwen_image, VAELoaderqwen_image_2.1_vae_bf16.safetensors, 25 steps, cfg 1, euler / simple, 1024×1024. The template's note on the setting people change first: "negative_prompt: unused while cfg is 1.", and on cfg: "cfg: keep 1 for the Qwen Image 2.1 official path. Raise it only if you use a negative prompt." Raising cfg adds a second model pass on every step.

On steps: the vendor's diffusers example runs 40, the template 25. One user on the repack's discussion #11 reports faint banding on skin, fabric and fur at the template's 25 steps, with the int8 and the bf16 files and with both schedulers, and writes "Artifact disappeared completely at 40" steps at 1024×1024 (16:00 UTC, 2026-09-22). A second user replied at 18:01 UTC with a different workflow; at 22:11 UTC the first wrote that with that workflow and a prompt toned down from "high definition" they "see no streaks"; and at 01:15 UTC on 2026-09-23 a third user wrote "Use 40 steps and choose 2k quality". So two remedies are reported, by a handful of users and no maintainer: 40 steps, or a different workflow with a milder prompt. Neither was tested for this page.

A step-distilled option for 2.1 appeared on 2026-09-22: Viggle/Qwen-Image-2.1-viggle-turbo, a third-party 4-step distillation by Viggle, shipped as a rank-64 LoRA and as a full bf16 transformer and labelled a v0.1 preview. Its card says the release "still falls short of the base model": text-to-image at 4 steps is usable, complicated edits are clearly worse. The card documents diffusers only, with its own scheduler setting, and names no ComfyUI workflow; nothing on this page was run with it. By 09:40 UTC on 2026-09-23 three third-party ComfyUI-side conversions had appeared — t8star/Qwen-Image-2.1-viggle-turbo-4step-r64-comfy (the rank-64 LoRA converted to ComfyUI's format), Abiray/Qwen-Image-2.1-viggle-4-steps-turbo-GGUF and realrebelai/Viggle_Qwen-Image-2.1-Turbo_GGUFs (GGUFs of the transformer) — and nothing on this page was run with them either. If you load a LoRA onto the template's int8 diffusion model, know that PR #16493 (opened and closed unmerged by its author on 2026-09-23) reports, on master with a Qwen-Image-2.1 int8 checkpoint, that adding or removing a LoRA on an already-loaded quantised model raises RuntimeError: Cannot set version_counter for inference tensor; the same error class is open as #15733, with a fix proposed in open PR #15734. The PR's stack runs through the base ModelPatcher.unpatch_model() restore loop into comfy/utils.py set_attr_param; at the tag both carry the same code (utils.py lines 975–980, model_patcher.py lines 1144–1151). The report is from master, on that legacy restore path. The default loader restores its own backups through the same function: ModelPatcherDynamic.load() calls restore_loaded_backups() (model_patcher.py line 1872), which runs set_attr_param on every entry in its backup (lines 1846–1850). Whether that backup holds quantised weights when a LoRA changes is not established either way; that is a reading of the code, not a test, and no report either way on the tag turned up in the tracker threads read. Separately, on the ComfyUI tracker issue #16496 one user reported edits coming out shifted to the left on the standard 2.1 edit workflow, then wrote on 2026-09-23 "THIS ONLY HAPPENS WITH VIGGLE 4step lora." and closed the issue the same minute; the report names no card and no build.

For a transparent image, wrap the prompt the way the model card does — This is an RGBA image with transparency. <your subject>. The image has alpha channel and the background is transparent. — and keep the template's SaveImageAdvanced at PNG, which keeps the alpha channel.

Native 2K

For native 2K the template's note says "For native 2K, set 1:1 and 4 megapixels". On this card nothing leaves the card for it (What 32 GB keeps resident): the legacy loader's 2K decode request leaves 7.968 GiB on Windows, and under DynamicVRAM a decode near the 7.031 GiB stand-in leaves 8.215 GiB. So a 2K seed change on this card should not re-stage anything, unlike on the 12 and 16 GB cards — an inference from the arithmetic, not a measurement. 2K runs on an RTX 5090 are reported: PR #16430's author ran five 2048×2048 images in one batch on one, but with the bf16 encoder (set 3, What 32 GB keeps resident), part of which was off the card, so that run says nothing about the template (Results), and a user on the vendor's discussion #27 ran edits at 2K with the 8-bit ConvRot files, cfg 1 and 25 steps on an RTX 5090, giving no timing or memory figure. The sampling schedule does not follow the resolution: ComfyUI fixes this model's shift at 0.69, the value its source comment gives for 1024×1024, and open #16447 reports that the vendor's pipeline shifts dynamically instead; a ComfyUI maintainer replied that the fixed value is partly deliberate.

Editing with reference images

Load Qwen Image 2.1: Image Edit (image_qwen_image_2_1_image_edit.json, same release). Same three loaders, plus TextEncodeQwenImage21 with the VAE connected — each reference is seen by the encoder's vision tower and spliced into the sequence as latents — and resolution at 0 on its outer node, whose note says "This template starts at 0: no resize beyond a multiple of 32." A QwenImage21Cache node sits at device auto, dtype default.

Set resolution to 1056 before you edit. Open #16435 reports broken edits (over-sharpened speckle, or the instruction ignored) at particular reference grids, and its two reports disagree on which: 1024×1024 broken on Apple MPS and CPU, while on an RTX 5070 Ti (v0.37.0 tag, cu130, the bf16 DiT with the int8 encoder) 1024×1024 was clean and 1536×1024 broke, at resolution 0 and at 1248. resolution 512 and 1056 were clean in both reports, and 512 shrinks the references to a quarter megapixel, so use 1056; it resizes the output canvas to about 1056×1056 pixels in the first reference's aspect ratio. Disconnecting the VAE from the node also removed it in both, at the cost of much weaker reference adherence. The two setups differ in backend, OS, build, attention path, encoder precision, reference image and step count, so neither isolates a cause; neither report, and none in the sources searched, comes from an RTX 5090. The issue was open on 2026-09-23. PR #16444, a proposed fix, was closed without merging on 2026-09-22 by kijai; no fix is linked to #16435 now.

On this card, set the cache's dtype to int8 and the edit cache stays on the card. comfy/ldm/qwen_image21/model.py sizes the text-and-reference prefix cache at 2 × 32 layers × tokens × 4096 × 2 bytes — 524,288 B per token. The template's two 896×1152 references at resolution 1056 resize to 928×1184, 2 × 58 × 74 = 8,584 tokens: 4,500,488,192 B = 4.191 GiB in bf16, before the prompt's own tokens, and 2,250,244,096 B = 2.096 GiB with dtype int8. At v0.37.0, select_prefix_cache() in auto places the cache on the GPU only if four times its size is free there, else in system RAM under the same four-times rule, and otherwise recomputes the prefix on every step. With the template's three files on the card, at most 34,190,458,880 − 17,283,091,112 = 16,907,367,768 B = 15.746 GiB can be free on Windows (15.239 GiB on native Linux):

  • in bf16, four times the cache is 16.766 GiB, so the GPU leg fails by at least 1.019 GiB with nothing else on the card, and the cache goes to system RAM if 16.766 GiB of RAM is free — otherwise every step recomputes. At resolution 0 (8,064 tokens) four times the cache is 15.750 GiB, which still misses by 4,065,960 B.
  • with dtype int8, four times the cache is 9,000,976,384 B = 8.383 GiB, so it lands on the GPU whenever everything else on the card — context, display, activations at that moment — holds less than 7,906,391,384 B = 7.363 GiB on Windows (6.856 GiB on native Linux), before the prompt's own tokens. The error-report shares are a quarter of that.

The node's own tooltip in comfy_extras/nodes_qwen.py puts the trade as "int8 halves the cache at about bf16 accuracy", while int4 "quarters it but roughly doubles the per-step error." This is the card-specific setting on this page: on the 12 and 16 GB cards in this series the int8 cache takes the GPU leg only if almost nothing else is on the card, if at all, and here it has room. It also bears on PR #16481 (Tag or master?). At the tag, pin_memory() returns False for any tensor not on the CPU (model_management.py line 1648), so PoseBranchCache.put() pins host memory only for a slot stored in system RAM, and prefetch() allocates its staging buffers only when a slot sits on a different device from the compute (model_animate2.py lines 202 and 211). A cache kept on the card therefore has neither the pinned host memory the PR blames nor the staging buffers free() drops at line 169, the innermost frame of the PR's stack. That is a reading of the tag's code, not a test; the tag is not a known fix, and the PR's reports are from master, whose placement logic differs (PR #16429). A text-to-image prefix is only the prompt's tokens — 524,288 B each, so 0.5 GiB for a 1,000-token prompt — so at the tag it takes the GPU leg in auto on this card anyway, with room to spare; also a reading of the code. If a second generation ever aborts on the tag with the cache on the card, that PR is the place to report it.

Optional: the bf16 diffusion model

If you want the full-precision diffusion model as a reference — for instance to compare an image against the int8 one — it is one file from the same repo and revision, and it stays on the card with the template's int8 encoder at 1024² (What 32 GB keeps resident):

hf download Comfy-Org/Qwen-Image-2.1 diffusion_models/qwen_image_2.1_bf16.safetensors \
  --revision ace0edeb3791a594ddfa36ed5f41a178a394e921 --local-dir models
sha256sum models/diffusion_models/qwen_image_2.1_bf16.safetensors
# 89f4158d066cc33906a199fca85634f766892dd78f49b6698dabf187ac86c4bc

(On the portable, prefix the download with python_embeded\python.exe -s -m huggingface_hub.cli.hf, use --local-dir ComfyUI\models, and check with certutil -hashfile <file> SHA256.) Then set unet_name on the template's outer node to qwen_image_2.1_bf16.safetensors and leave the encoder as it is. What it costs, by kind of evidence:

  • Time, on this card (third-party): in the converter's RTX 5090 comparison the official bf16 files took 15.629 s per 1024², 40-step image against 7.553 s for the official int8 files (Results). That row loaded the bf16 encoder too, the set that does not stay on the card here, so part of its time may be weights moving (inference).
  • Time per step, on another card (first-party use 2): on the operator's RTX 5060 Ti with the v0.37.0 cu130 portable, the int8 diffusion model ran at 0.61 s/it against 1.38 s/it for bf16 at 1024², and 4.35 against 7.43 s/it at 2048², both with the int8 encoder (one rig, one operator, unreplicated; cu130 session). That is a 5060 Ti's ordering, not this card's time; on a cu128 install with the eager int8 path the same rig had bf16 faster.
  • Picture (first-party use 3): on that rig the int8 and bf16 diffusion models gave nearly the same image from the same seed, judged by eye, with the images unpublished (one rig, one operator, unreplicated; cu128 session). No bf16-against-int8 image comparison on an RTX 5090 turned up in the sources searched.

Do not load the bf16 encoder with it: that is the pair that does not stay on the card (What 32 GB keeps resident, item 4), and the encoder's format buys no speed (Installation, step 2).

Optional: NVFP4 and other 4-bit builds

This card runs NVFP4 natively (Installation, step 2). The NVFP4 timings of this model on an RTX 5090 found in the sources searched are BennyDaBall's, in ComfyUI, and ModelsLab's, in Nunchaku, another runtime (Results); other builds' cards time NVFP4 on other hardware — among them pottokao's about 20–22 s for a 1024², 25-step image on a GB10 in ComfyUI; HangGlidersRule's ModelOpt export 4.78 s per 1024², 20-step image on an RTX PRO 6000 Blackwell, run in a diffusers pipeline with the NVFP4 weights dequantised to bf16 on load, beside 4.73 s for its bf16 control — so not an NVFP4 speed-up; and catplusplus's Nunchaku build about 20 s for a 1024², 25-step image on an RTX 5060 Ti. On a card where the template already stays whole, a 4-bit diffusion model does not change what is resident; what is left to buy is file size and speed. The evidence, labelled:

  • Measured on an RTX 5090, with a patched encoder (third-party): BennyDaBall/Qwen-Image-2.1-NVFP4's validation notes put its package — NVFP4 diffusion model, NVFP4 encoder and the author's GPL-3.0 patch that runs the encode in FP4 — at a 6.746 s warm median against 7.553 s for the official int8 files, 10.7% less time, in the same controlled run as the bf16 figure above. That row changes the diffusion model, the encoder and the encoder's code path at once, so the gain is not attributable to the diffusion model alone, and the author calls it one controlled test, not a speed guarantee. On stock master without that patch, the same author's PR #16432 reports 6.290 s for the NVFP4 package's complete text-to-image pipeline (1024², 40 steps, three warm runs, --cache-none --use-ck-attention, commit c194dd00), and 6.446 s with the patch in the same run — so in that author's own measurement the patch did not make text-to-image faster. That table has no int8 row, so it cannot be set against the 7.553 s, and the diffusion model's own share of the VALIDATION gain is still unmeasured.
  • What it costs (sourced): the diffusion model becomes a third party's 4-bit requantisation of the model that draws the image. The file is 4,197,574,664 B = 3.909 GiB; its header marks all 192 quantised matrices nvfp4 and keeps the embedding, modulation, normalisation and output tensors in bf16. The validation notes publish 24 same-seed pairs against bf16 and list real differences (changed portrait details, object placement, typography layout).
  • The diffusion-model-only swap — NVFP4 transformer with the template's int8 encoder, 14,223,882,712 B = 13.247 GiB of encoder and transformer weights with the VAE — needs no patch and stays whole on this card, but it is not one of the combinations that notes lists as tested (those mix bf16 and NVFP4 weights), and its speed against the int8 diffusion model alone has not been measured on any card in the sources searched.

This page's decision: document the NVFP4 swap, do not install it. It trades a third party's requantisation of the image model for a gain measured once, in a combination that also changes the encoder. If you want to try the diffusion-model-only swap:

hf download BennyDaBall/Qwen-Image-2.1-NVFP4 diffusion_models/qwen_image_2.1_nvfp4.safetensors \
  --revision 1a38d44a3a2f35cb0b543a25b04da0a963e7b5e6 --local-dir models
sha256sum models/diffusion_models/qwen_image_2.1_nvfp4.safetensors
# 4fdbaec94c19f7b8888f1e1ddbae05354c014492f9b2547b1cd8dca0ce923526

Set unet_name to qwen_image_2.1_nvfp4.safetensors; the Native ops line should list nvfp4 as native when it loads. The useful report is a time per image with both diffusion models on the same install: /contribute.

Other 4-bit and fp8 builds. Several more NVFP4 and 4-bit diffusion models are on the Hub (among them pottokao's, ModelsLab's and HangGlidersRule's); this page did not evaluate them. toxicdog/Qwen-Image-2.1-INT4ConvRot-ComfyUI runs through the int8-activation fallback on this card (Installation, step 2), so it is not the 4-bit kernel its name suggests here. The fp8 diffusion models found — unsloth/Qwen-Image-2.1-FP8 and HangGlidersRule's ModelOpt export — are diffusers-side files; unsloth's header uses diffusers tensor names with _weight_scale entries and carries no comfy_quant markers, the per-layer format ComfyUI's quantised loaders read, and none was tried here. GGUF diffusion models dequantise each weight before the matmul, so on this card they give up the INT8 or FP4 GEMM and save nothing that matters at 32 GB. For completeness: Abiray/Qwen-Image-2.1-GGUF's files declare general.architecture = qwen_image, which city96's loader.py (head unchanged since 2026-01-12) hands to ComfyUI core; leejet/Qwen-Image-2.1-GGUF's carry no metadata keys and need leejet's fork; pull requests adding detection for those to city96's node (#483) and loading the vision projector for Qwen3-VL encoder GGUFs (#485) were open and unmerged on 2026-09-23.

The prompt enhancer beside the template

The two qwen3.5_9b_qwen_image_2.1_pe_… files are Qwen3.5-9B language models that rewrite your prompt. The repack's README says they "are for prompt enhancement, to be used with the TextGenerate -node."; in the text-encoder slot one gives garbled images, per a reader on the repack's discussion #4. None of the three shipped 2.1 templates contains a TextGenerate node (read at 371a7b7171), so wiring it in is up to you, and this page gives no workflow for it. What 32 GB decides is whether one fits beside the template, and it does at 1024²:

  • Fit (arithmetic, What 32 GB keeps resident): the template plus one enhancer is 26,754,163,364 B = 24.917 GiB. Under DynamicVRAM that leaves 6.426 GiB on Windows after aimdo's floor, and 4.668 GiB after a 1024² decode near the stand-in — room for the error-report shares. The enhancer's own generation cache comes on top, and no loader estimates it (the Qwen3.5 text-encoder class defines no memory estimate at the tag). At 2048² a decode near the stand-in is 0.606 GiB over on Windows before the desktop, and since the enhancer ran first it has the lowest priority, so its weights are the ones evicted and the next enhancement re-stages part of it (inference from aimdo's priority order). On the legacy loader the 2K decode request is 0.852 GiB over on Windows.
  • Known failures, all reported against v0.37.0: open #16441, a hard abort on the second generate() inside one node execution (first on an RTX 5070 Ti with the Qwen3-VL encoder file, then reproduced by a second user on an RTX 4060 Ti with the PE-I2I file, both in workflows that run the node more than once within one execution — a batch, a list input); a third commenter's reading of the code blames per-layer CUDA graphs that are dropped only at the end of each node's execution. #16449 (closed by its reporter as not planned) reports text generation failing on a cu128 build with a CUDA 12.9 driver, and open #16455 reports deltanet_conv_step launch rejected for the PE-T2I file on an RTX 4090 with driver 570 and cu128, while the same container worked on an L40S with driver 580; both got the reply quoted in Installation. On this page's install (cu130, driver R580 or newer) those two do not apply — an inference from their reports.
  • Speed on this card: no timing of the enhancer on an RTX 5090 turned up in the sources searched.

Results

  • Speed: no timing on this card is this site's. These are the third-party figures that name an RTX 5090 found in the sources searched, each with what it does and does not cover:

    • The converter's controlled comparison (VALIDATION.md, raw): Windows, PyTorch 2.14.0+cu130, comfy-kitchen 0.2.35, comfy-aimdo 0.5.5, ComfyUI at base commit 99073836, banner 0.36.0 — the parent of the v0.37.0 tag, which differs from it only in version strings and the frontend pin — plus the author's encoder patch, which per its README leaves the bf16 and int8 checkpoints on their original path. One 1024×1024 product prompt, 40 steps, euler / simple, cfg 1, --cache-none so every node including the loaders ran on every repeat, Comfy Kitchen attention (in this ComfyUI, the non-default --use-ck-attention flag) and --disable-all-custom-nodes; server-side time from execution start to success, one run after an unload and three warm runs per set. Warm medians: official bf16 files 15.629 s, official int8 ConvRot files 7.553 s, the NVFP4 package with its patch 6.746 s (first run after unload 18.932, 9.973 and 8.083 s). The largest 100 ms sample of whole-card GPU use was 31,677, 18,433 and 13,249 MiB, which the notes describe as whole-GPU usage including Windows, not PyTorch peak allocated memory and not a minimum requirement. The int8 figure — 18,433 MiB = 18.001 GiB — is what the three template files (16,482 MiB) plus a Windows desktop and the activations would come to, which fits the arithmetic above (an inference, not a check).
    • PR #16481 (sqz269): with its fix applied on a master build, the template's int8 files, Windows 11, torch 2.13.0+cu130, six consecutive generations — text-to-image 9.0, 6.1 and 6.0 s, edits 90.7, 9.1 and 9.1 s. The PR states neither resolution nor step count, nor what the times include.
    • PR #16432 (the NVFP4 converter): 6.290 s complete pipeline for the NVFP4 package on stock master c194dd00, 1024², 40 steps (Running, NVFP4).
    • PR #16430 (rattus128, a ComfyUI contributor): Linux, 96 GB RAM, the int8 diffusion model (6920MB Staged) with the bf16 text encoder (16.3 GB in the PR's memory panels, so set 3 above, not the template), five 2048×2048 text-to-image images in one batch at 25 steps — 25/25 [01:27<00:00, 3.51s/it] before that PR's change and 3.40 s/it after it, with part of the encoder unloaded in both panels (What 32 GB keeps resident, item 3). Sampling only, a batch of five, and the change is on master, not in v0.37.0.
    • Other runtimes on this card, for scale only, since none is ComfyUI or this install: ModelsLab's W4A4 NVFP4 card gives 7.653 s on an RTX 5090 (and 7.747 s on an RTX PRO 6000 Max-Q) for 1024×1024 at 40 steps, seed 42, six prompts, with its 4-bit transformer running on Nunchaku's fused kernel (nunchaku==1.3.0.dev20260306+cu13.0torch2.12) inside a diffusers pipeline, and 21.53 in the column its table heads "resident GB"; LightX2V's Qwen-Image-2.1 README gives 5.930 s end to end for a 1024² text-to-image at 40 steps with its FP8 diffusion model, SageAttention2 and the text encoder offloaded to the CPU, model loading excluded; SGLang's cookbook describes a native-precision RTX 5090 setup with the encoder streamed from host RAM at 14.12 s per 1024², 40-step image, while its own table note says the RTX 5090 recipe streams the diffusion model layer by layer and had not been retested with the updated checkpoint; the card of a Tenstorrent port compares against diffusers bf16 on an RTX 5090 in the same host, at 377–387 ms per step and 28.8–33.0 s end to end, run with model CPU offload because, it says, the two models do not fit 32 GB; and on the vendor's discussion #32 a user measured diffusers on Windows 11 with fp8 (torchao) and NF4 (bitsandbytes) weights at 19.3 and 19.2 s for 1024², 40 steps.

    If you time the template on this card — steps, resolution, seconds per image, cold or warm, tag or masterpost it; it becomes the first datapoint on /check/qwen-image-2-1/rtx-5090.

  • VRAM usage: derived, not measured by this site. The template's three files are 16.096 GiB; with every reserve and the 2K decode it comes to at most 23.874 GiB (legacy, Windows), leaving 7.968 GiB, and under DynamicVRAM, with aimdo's floor and a 2K decode near the legacy estimate, 23.627 GiB, leaving 8.215 GiB. The vendor's HF card and GitHub README give no VRAM figure, only enable_model_cpu_offload() as their memory advice (Qwen's blog was not checked). The measured figures for this model on an RTX 5090 found in the sources searched are whole-card samples or come from other runtimes: the whole-card figures above, and the diffusers post on discussion #32, which reports peaks of 21.3 GB at 1024² and 22.6 GB at 2048² with its fp8 weights, as the post labels them, with every component on the GPU.

  • Quality notes: the VAE has a reported grid artifact. The vendor's discussion #12, titled "Diamond grid pattern caused by VAE", says "It's more noticeable when you generate a high-resolution image that has people with light skin tones and zoom in on their faces." (Rkss, community, crediting the example image to another user), with an encode–decode round trip given as the way to see it; another commenter argues that a similar stripe pattern in a different model came from the DiT, so the attribution is a community reading, not the vendor's. The mitigations named there are workarounds (a GLSL post-process node, a node pack, re-encoding through the Flux VAE), none tied to a card. The 25-step banding report is under Text-to-image; nothing ties it to the VAE grid. On editing, the RTX 5090 user on discussion #27 found the model tended to paste the edited face or parts onto the image, and preferred another model for consistent characters — one user's judgement. Inspect native-2K portraits at 100%.

For the full benchmark data, see /check/qwen-image-2-1/rtx-5090.

Troubleshooting

TextEncodeQwenImage21 or QwenImage21Cache missing when the template loads

You are below v0.37.0. Update to the v0.37.0 portable, or on a git install git fetch --tags && git checkout v0.37.0 && pip install -r requirements.txt (a bare git pull lands on master), then check the version line. The ComfyUI docs page lists not running the latest version as the first reason nodes go missing.

The startup log prints the cu130 WARNING

Your PyTorch is a CUDA 12 build — on Windows, usually the cu126 portable or an older Desktop install. The diffusion model still runs, on comfy-kitchen's eager INT8 path; reinstall PyTorch from the cu130 index (or take the nvidia portable) and confirm torch.version.cuda prints 13.0. What the warning costs has not been measured on this card. On a different card, the operator's RTX 5060 Ti 16GB, the same template took 21.4 s from a cold start on the v0.37.0 cu130 portable against 69.4 s on an install that printed this warning (first-party use 1; one rig, one operator, unreplicated; cu130 session, cu128 session). That is one install against another, not one flag flipped, and it is a 5060 Ti's time, not this card's. On a second 5060 Ti a user on 2.10.0+cu128 reports in #16470 that the int8 file ran slower than a Q8 GGUF at about 4 MP, and kijai, a ComfyUI collaborator, answered: "You need pytorch with cu130 for int8 models to work properly." A different line, Failed to import comfy_kitchen, is worse: the int8 formats are defined by that package, so fix the import first — pip install -r requirements.txt in the venv restores the pinned 0.2.35.

Fatal Python error: Aborted after the second image's sampling

PR #16481, from an RTX 5090, under Tag or master? in Installation. On the tag, set QwenImage21Cachedtype to int8 for edits so the cache stays on the card, where it holds neither pinned host memory nor staging buffers (Editing); text-to-image caches take the GPU leg at the tag on this card anyway. Both are readings of the code, not tests, and the tag is not a known fix. If it still happens on the tag, report it on that PR with your commit.

Edit output is over-sharpened and speckled, or ignores the edit; text-to-image is clean

Issue #16435, under Editing. Set resolution to 1056; 512 was clean in both reports too, but shrinks the references. At resolution 0 the grid the node resolves to is the first reference rounded to a multiple of 32.

Edits are far slower than text-to-image

Most likely the prefix cache found no room on the GPU in bf16 and either went to system RAM or, with too little RAM free, fell back to recomputing every step — see Editing. On this card set QwenImage21Cachedtype to int8, which keeps the template's two-reference cache on the card.

On master: Fatal Python error: Aborted at 0/25 when editing

#16443, open, reports a hard abort at 0/25 on image editing, on a git checkout with DynamicVRAM active. Read in full on 2026-09-23 (four comments, the last at 14:08 UTC on 2026-09-22): both people in it have an RTX 5060 Ti 16 GB, neither has seen text-to-image crash, and both see it only on edits and only intermittently. The stack ends in the prefix cache's takeprefetch at qwen_image21/model.py line 353, which is cache.take on master and other code at the tag; open PR #16450, without maintainer review, blames the block-weight allocation recording that master wraps around the block loop. No report of it on the tag turned up in the tracker threads read. If you hit it on master, go back with git checkout v0.37.0. On the portable, update_comfyui_stable.bat checks out the newest v* tag, which has been v0.37.1 since 19:12 UTC on 2026-09-22 — not v0.37.0, though it changes none of this model's code (Installation, step 1).

Shape error [1, 338, 5120] from the text encoder

The CLIP loader was given something other than the 4096-wide Qwen3-VL-8B. The reporter of the repack's discussion #2 saw exactly this and closed it as a wrong-encoder mistake. Load qwen3vl_8b_int8_convrot.safetensors with type qwen_image — not a qwen3.5_9b_…_pe_… file, which belongs in a TextGenerate graph (Running, the prompt enhancer).

Expecting value: line 1 column 1 (char 0) while the encoder loads

Reported once, in #16472, loading the template's int8 encoder; open PR #16474 attributes it to a layer whose quantisation marker is empty. kijai replied: "This is most likely a corrupt/incomplete model file." The reporter downloaded the file again, it loaded, and kijai closed the issue as completed on 2026-09-22. Check the sha256 against step 3 before anything else.

Models reload between generations

With the template on this card they should not: all three stay whole at both sizes (What 32 GB keeps resident). If the log shows them staging again on every prompt, something else is holding VRAM — another workflow's models, another application — or you have the bf16 encoder loaded, whose pair with any diffusion model is the tight one. Reloads are also the trigger of open #16437, which reports that on an RX 9070 XT every image after a model reload comes back with its channels in a [B, A, B, A] pattern until a restart; the reporter adds "I don't have an NVIDIA card to test whether this is ROCm-specific." and no NVIDIA report of it was found in the tracker threads read.

GGUF: This model is not currently supported - (Unknown model architecture!)

city96's node refusing a GGUF with no general.architecture key — leejet's files. Use Abiray's files with city96's node, or leejet's files with leejet's fork, not a mix (Running, other 4-bit builds).

See also: the RTX 4090 page in this series, the 24 GB card where the template is resident at 1 MP and native 2K comes within a few hundred MB; the RTX 5080 page for the 16 GB Blackwell budget. The 2025 20B predecessor has its own page for this card — Qwen-Image on RTX 5090.

Sources searched for reports on this card, on 2026-09-23: the ComfyUI tracker — the startup-log queries "Total VRAM" "RTX 5090" (121 results), "GeForce RTX 5090" (117), "VRAM Total" "RTX 5090" (121), and "RTX 5090" with posix (12), GCC (32), "OS linux" (16) or linux (56), 157 distinct threads with every body and comment parsed; the 23 threads created since 2026-09-18 matching "Qwen Image 2.1", "Qwen-Image-2.1", "qwen 2.1", qwen_image21 or QwenImage21, plus #16441 and #16449, read in full (an RTX 5090 is named only in PRs #16430, #16432 and #16481); every discussion on the vendor's repo (40), the Comfy-Org repack (15), Comfy-Org/Qwen3-VL (7), the two prompt-enhancer repos and the NVFP4, INT4, GGUF and turbo repos named on this page (an RTX 5090 is named only in the vendor's #27 and #32); all 196 comments of the Hacker News launch thread (no RTX 5090 or 32 GB mention); the README of every repo the Hugging Face search returns for "Qwen-Image-2.1" (157 repos, 146 with a README; an RTX 5090 is named with a timing only on BennyDaBall's, ModelsLab's and the Tenstorrent port's cards); and the SGLang and LightX2V pages named above. Reddit was not searched. This is launch week and the tracker moves by the hour; report problems, or better a measured run on this card, via the submission form.

common questions
How much VRAM does Qwen-Image-2.1 need?

About 12 GB — the minimum this recipe targets.

Which GPUs is Qwen-Image-2.1 tested on?

RTX 5090 (32 GB).

How hard is this setup?

Intermediate — follow the steps above.

next