# ComfyUI + Z-Image Turbo on AMD BC-250 — Complete Setup Guide > **Hardware**: AMD BC-250 (Cyan Skillfish, gfx1013→gfx1010, 24 CUs, shared RAM) > **Backend**: ROCm 7.2.0 / PyTorch 2.5.1+rocm6.2 > **OS**: CachyOS, kernel 6.18.8-3-cachyos > **ComfyUI Version**: 0.15.1 > **Date**: 2026-03-02 --- ## Table of Contents 1. [Overview](#1-overview) 2. [Architecture](#2-architecture) 3. [Prerequisites](#3-prerequisites) 4. [Installation — Step by Step](#4-installation--step-by-step) 5. [Model Setup](#5-model-setup) 6. [Launch Script](#6-launch-script) 7. [ComfyUI Workflow — Z-Image Turbo](#7-comfyui-workflow--z-image-turbo) 8. [BC-250 Specific Tuning](#8-bc-250-specific-tuning) 9. [Troubleshooting](#9-troubleshooting) 10. [File Inventory](#10-file-inventory) 11. [Performance Notes](#11-performance-notes) --- ## 1. Overview ComfyUI is a node-based Stable Diffusion GUI that runs Z-Image Turbo (a Lumina2-architecture model) via PyTorch with ROCm/HIP on the AMD BC-250 GPU. The model uses a GGUF-quantized diffusion model (Q5_K_S) loaded via the ComfyUI-GGUF custom node, with a Gemma 2 2B text encoder and a Flux-compatible VAE. ### What's Running | Component | File | Size | Format | |-----------|------|------|--------| | Diffusion Model | `z_image_turbo-Q5_K_S.gguf` | 5.2 GB | GGUF Q5_K_S | | Text Encoder | `gemma2_2b_lumina2.safetensors` | 9.8 GB | Safetensors (f32) | | VAE | `ae.safetensors` | 335 MB | Safetensors (f32) | ### Pipeline ``` [ComfyUI WebUI :8188] → [PyTorch] → [ROCm/HIP] → [AMD BC-250 GPU] ↓ [Gemma 2 2B Text Encoder] → CLIP Encode → [Z-Image Turbo Diffusion] → [VAE Decode] → Image ``` --- ## 2. Architecture ### Z-Image Turbo Details - **Architecture**: Lumina2 (Lumina-Image 2.0 family) - **Base**: Z-Image by Freepik, turbo-distilled variant - **Text Encoder**: Gemma 2 2B (Google, 2304-dim embeddings) - **VAE**: Flux-compatible autoencoder (`ae.safetensors`) - **Sampler**: Euler with SGM Uniform scheduler, 8 steps (turbo) - **CFG Scale**: 3.0 (turbo models use low CFG) - **Latent Format**: Flux-style latent space ### Why GGUF? The BC-250 has ~14.7 GB shared system RAM. The full FP16 diffusion model would be too large. GGUF Q5_K_S quantization reduces the model from ~12+ GB to 5.2 GB, making it feasible alongside the text encoder and VAE. --- ## 3. Prerequisites Before starting, you need ROCm working on the BC-250. See `ROCm_BC250_Documentation.md` for the full ROCm setup. ### Required - ROCm 7.2.0 installed and working (`rocminfo` detects BC-250) - Python 3.11 (`/usr/bin/python3.11`) - Git - ~30 GB free disk space ### Verify ROCm ```bash rocminfo | grep "Name:" # Should show: gfx1010 and AMD BC-250 ``` --- ## 4. Installation — Step by Step ### 4.1 Clone ComfyUI ```bash cd ~ git clone https://github.com/comfyanonymous/ComfyUI.git cd ComfyUI ``` ### 4.2 Create Python 3.11 Virtual Environment Python 3.11 is required — Python 3.14 (system default) is too new for PyTorch ROCm wheels. ```bash python3.11 -m venv venv source venv/bin/activate ``` ### 4.3 Install PyTorch with ROCm Support ```bash pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/rocm6.2 ``` This downloads ~4 GB. The ROCm 6.2 PyTorch wheel is compatible with the ROCm 7.2 runtime. **Verify installation:** ```bash python -c "import torch; print(torch.version.cuda); print(torch.cuda.is_available())" # Should print: 6.2 and True ``` ### 4.4 Install ComfyUI Dependencies ```bash pip install -r requirements.txt ``` ### 4.5 Install ComfyUI-GGUF Custom Node This enables loading GGUF-quantized models in ComfyUI. ```bash cd ~/ComfyUI/custom_nodes git clone https://github.com/city96/ComfyUI-GGUF.git source ~/ComfyUI/venv/bin/activate pip install gguf ``` ### 4.6 Install huggingface-hub (for model downloads) ```bash pip install huggingface-hub ``` --- ## 5. Model Setup ### 5.1 Directory Structure ComfyUI looks for models in `~/ComfyUI/models/`. Our models live in `~/sd-models/` and are symlinked. ``` ~/ComfyUI/models/ ├── unet/ │ └── z_image_turbo-Q5_K_S.gguf → ~/sd-models/diffusion_models/z_image_turbo-Q5_K_S.gguf ├── text_encoders/ │ └── gemma2_2b_lumina2.safetensors (merged from 3 shards, 9.8 GB) ├── vae/ │ └── ae.safetensors → ~/sd-models/vae/ae.safetensors └── ... ``` ### 5.2 Symlink Diffusion Model (GGUF) The Z-Image Turbo GGUF model must go in `models/unet/` (ComfyUI-GGUF's `UnetLoaderGGUF` node reads from there): ```bash ln -sf /home/dars/sd-models/diffusion_models/z_image_turbo-Q5_K_S.gguf \ ~/ComfyUI/models/unet/z_image_turbo-Q5_K_S.gguf ``` ### 5.3 Text Encoder — Gemma 2 2B Z-Image Turbo uses the Gemma 2 2B text encoder from the Lumina-Image-2.0 family. The original model is sharded into 3 safetensors files. We merge them into a single file for ComfyUI. **Download from Alpha-VLLM (not gated, no login required):** ```bash source ~/ComfyUI/venv/bin/activate python3 -c " from huggingface_hub import hf_hub_download import os repo = 'Alpha-VLLM/Lumina-Image-2.0' dest = os.path.expanduser('~/sd-models/text_encoders/lumina2_gemma2_2b') os.makedirs(dest, exist_ok=True) files = [ 'text_encoder/config.json', 'text_encoder/model.safetensors.index.json', 'text_encoder/model-00001-of-00003.safetensors', 'text_encoder/model-00002-of-00003.safetensors', 'text_encoder/model-00003-of-00003.safetensors', ] for f in files: print(f'Downloading {f}...') hf_hub_download(repo, f, local_dir=dest) print('Done!') " ``` **Merge shards into single file:** ```bash source ~/ComfyUI/venv/bin/activate python3 << 'EOF' import safetensors.torch import torch import os, json base_dir = os.path.expanduser("~/sd-models/text_encoders/lumina2_gemma2_2b/text_encoder") output = os.path.expanduser("~/ComfyUI/models/text_encoders/gemma2_2b_lumina2.safetensors") os.makedirs(os.path.dirname(output), exist_ok=True) with open(os.path.join(base_dir, "model.safetensors.index.json")) as f: index = json.load(f) all_tensors = {} shards = set(index["weight_map"].values()) print(f"Loading {len(shards)} shards with {len(index['weight_map'])} tensors...") for shard in sorted(shards): path = os.path.join(base_dir, shard) print(f" Loading {shard}...") tensors = safetensors.torch.load_file(path, device="cpu") all_tensors.update(tensors) print(f"Total tensors: {len(all_tensors)}") print(f"Saving merged file...") safetensors.torch.save_file(all_tensors, output) print(f"Done! Size: {os.path.getsize(output)/1e9:.2f} GB") EOF ``` **Clean up shards (optional):** ```bash rm -rf ~/sd-models/text_encoders/lumina2_gemma2_2b/ ``` ### 5.4 VAE ```bash ln -sf /home/dars/sd-models/vae/ae.safetensors \ ~/ComfyUI/models/vae/ae.safetensors ``` ### 5.5 Verify All Models in Place ```bash ls -lh ~/ComfyUI/models/unet/*.gguf \ ~/ComfyUI/models/text_encoders/*.safetensors \ ~/ComfyUI/models/vae/*.safetensors ``` Expected output: ``` 9.8G ~/ComfyUI/models/text_encoders/gemma2_2b_lumina2.safetensors 5.2G ~/ComfyUI/models/unet/z_image_turbo-Q5_K_S.gguf (symlink) 335M ~/ComfyUI/models/vae/ae.safetensors (symlink) ``` --- ## 6. Launch Script ### Location: `~/start-comfyui.sh` ```bash #!/bin/bash # ============================================================= # ComfyUI Launch Script for AMD BC-250 (ROCm / gfx1013) # ============================================================= set -euo pipefail echo "==========================================" echo " ComfyUI — BC-250 ROCm Launcher" echo "==========================================" # --- GPU Health Check --- if dmesg 2>/dev/null | tail -50 | grep -qi "KIQ fence timeout"; then echo "[ABORT] KIQ fence timeout detected in dmesg — reboot required!" exit 1 fi echo "[OK] GPU health check passed" # --- ROCm Environment for BC-250 (gfx1013 → gfx1010 spoof) --- export HSA_OVERRIDE_GFX_VERSION=10.1.0 export HSA_ENABLE_SDMA=0 export HIP_VISIBLE_DEVICES=0 export ROCM_PATH=/opt/rocm export HSA_TOOLS_LIB="" export HSA_TOOLS_REPORT_LOAD_FAILURE=0 export PATH="/opt/rocm/bin:$PATH" export LD_LIBRARY_PATH="/opt/rocm/lib" # --- Unset old workaround variables that destroy performance --- unset GPU_MAX_HW_QUEUES 2>/dev/null || true unset HIP_LAUNCH_BLOCKING 2>/dev/null || true unset GGML_CUDA_ENABLE_UNIFIED_MEMORY 2>/dev/null || true unset GGML_HIP_HOST_ALLOC 2>/dev/null || true unset GGML_CUDA_NO_PINNED 2>/dev/null || true unset GGML_HIP_NO_COARSE_GRAIN 2>/dev/null || true unset HSA_DISABLE_FRAGMENT_ALLOCATOR 2>/dev/null || true # --- PyTorch ROCm tuning --- export PYTORCH_HIP_ALLOC_CONF="expandable_segments:False" echo "[OK] ROCm environment configured" # --- Activate venv --- cd ~/ComfyUI source venv/bin/activate # --- Launch ComfyUI --- echo "[START] Launching ComfyUI on http://0.0.0.0:8188" echo "==========================================" python main.py \ --listen 0.0.0.0 \ --port 8188 \ --force-fp32 \ --lowvram \ "$@" ``` ### Usage ```bash # Foreground (see logs): bash ~/start-comfyui.sh # Background with logging: nohup bash ~/start-comfyui.sh > /tmp/comfyui.log 2>&1 & # Check if running: curl -s http://localhost:8188/system_stats | python3 -m json.tool ``` ### CLI Flags Explained | Flag | Why | |------|-----| | `--listen 0.0.0.0` | Accept connections from any interface (access from other machines) | | `--port 8188` | Default ComfyUI port | | `--force-fp32` | BC-250 gfx1010 has limited FP16 support in PyTorch ROCm; FP32 prevents crashes | | `--lowvram` | Enables aggressive model offloading — essential for 14.7 GB shared RAM | --- ## 7. ComfyUI Workflow — Z-Image Turbo ### Access the WebUI Open in browser: **http://localhost:8188** (or `http://:8188` from another machine) ### Pre-made Workflow A ready-to-use workflow is saved at: ``` ~/ComfyUI/workflows/z_image_turbo_bc250.json ``` Load it via: **Menu → Load → select `z_image_turbo_bc250.json`** ### Manual Node Setup If building the workflow from scratch, create these nodes: #### Node 1: UnetLoaderGGUF - **Type**: `UnetLoaderGGUF` (from ComfyUI-GGUF custom node, category: bootleg) - **unet_name**: `z_image_turbo-Q5_K_S.gguf` - **Output**: MODEL → connect to KSampler's "model" input #### Node 2: CLIPLoader - **Type**: `CLIPLoader` (built-in, category: advanced/loaders) - **clip_name**: `gemma2_2b_lumina2.safetensors` - **type**: `lumina2` ← **CRITICAL: must be set to lumina2** - **Output**: CLIP → connect to both CLIP Text Encode nodes #### Node 3: CLIP Text Encode (Positive) - **Type**: `CLIPTextEncode` - **text**: Your prompt (e.g., "a beautiful sunset over the ocean") - **Input**: clip ← from CLIPLoader - **Output**: CONDITIONING → connect to KSampler's "positive" input #### Node 4: CLIP Text Encode (Negative) - **Type**: `CLIPTextEncode` - **text**: Empty string `""` (turbo models work best with empty negative) - **Input**: clip ← from CLIPLoader - **Output**: CONDITIONING → connect to KSampler's "negative" input #### Node 5: Empty Latent Image - **Type**: `EmptyLatentImage` - **width**: `512` - **height**: `512` - **batch_size**: `1` - **Output**: LATENT → connect to KSampler's "latent_image" input #### Node 6: KSampler - **Type**: `KSampler` - **seed**: Any number (42) - **control_after_generate**: `fixed` (or `randomize` for variety) - **steps**: `8` (turbo — more steps won't improve quality) - **cfg**: `3.0` (turbo models use low CFG guidance) - **sampler_name**: `euler` - **scheduler**: `sgm_uniform` - **denoise**: `1.0` - **Inputs**: model, positive, negative, latent_image - **Output**: LATENT → connect to VAEDecode #### Node 7: VAELoader - **Type**: `VAELoader` - **vae_name**: `ae.safetensors` - **Output**: VAE → connect to VAEDecode's "vae" input #### Node 8: VAE Decode - **Type**: `VAEDecode` - **Inputs**: samples (from KSampler), vae (from VAELoader) - **Output**: IMAGE → connect to SaveImage #### Node 9: Save Image - **Type**: `SaveImage` - **filename_prefix**: `ComfyUI` - **Input**: images ← from VAEDecode - Output images saved to: `~/ComfyUI/output/` ### Wiring Summary ``` UnetLoaderGGUF ───MODEL──→ KSampler CLIPLoader ───CLIP──→ CLIPTextEncode (positive) ──CONDITIONING──→ KSampler CLIPLoader ───CLIP──→ CLIPTextEncode (negative) ──CONDITIONING──→ KSampler EmptyLatentImage ──LATENT──→ KSampler KSampler ──LATENT──→ VAEDecode VAELoader ──VAE──→ VAEDecode VAEDecode ──IMAGE──→ SaveImage ``` --- ## 8. BC-250 Specific Tuning ### Environment Variables (set in launch script) | Variable | Value | Why | |----------|-------|-----| | `HSA_OVERRIDE_GFX_VERSION` | `10.1.0` | BC-250 (gfx1013) needs gfx1010 spoof for ROCm | | `HSA_ENABLE_SDMA` | `0` | SDMA engine has hardware bugs on gfx1013 | | `HIP_VISIBLE_DEVICES` | `0` | Select the BC-250 GPU | | `ROCM_PATH` | `/opt/rocm` | ROCm installation path | | `HSA_TOOLS_LIB` | `""` | Disable profiling tools (stability) | | `HSA_TOOLS_REPORT_LOAD_FAILURE` | `0` | Suppress tool warnings | | `PYTORCH_HIP_ALLOC_CONF` | `expandable_segments:False` | Prevent memory fragmentation | ### Variables to NEVER Set These old workarounds **destroy performance** and must NOT be set: | Variable | Why it's bad | |----------|-------------| | `GPU_MAX_HW_QUEUES=1` | Serializes all GPU ops to 1 queue | | `HIP_LAUNCH_BLOCKING=1` | Forces synchronous kernel launches | | `GGML_CUDA_ENABLE_UNIFIED_MEMORY=1` | Page fault overhead | | `GGML_HIP_HOST_ALLOC=1` | Zero-copy over PCIe is slow | ### Memory Considerations - Total available: ~14.7 GB shared system RAM - Diffusion model (GGUF Q5_K_S): ~5.2 GB - Text encoder (Gemma 2 2B f32): ~9.8 GB - VAE: ~335 MB - Total model footprint: ~15.3 GB — exceeds available RAM - **`--lowvram` is essential**: it offloads models to CPU when not in active use - Only one component is on GPU at a time during inference ### Resolution Recommendations | Resolution | Latent Size | Notes | |-----------|-------------|-------| | 512×512 | 64×64 | Fastest, recommended for testing | | 768×768 | 96×96 | Good quality, slower | | 1024×1024 | 128×128 | May OOM on BC-250 | --- ## 9. Troubleshooting ### "KIQ fence timeout" in dmesg → Reboot ```bash sudo dmesg | grep -i "KIQ fence timeout" ``` If this appears, the GPU is in a bad state. **Reboot the machine.** ### ComfyUI won't start — "No module named torch" Make sure you activated the venv: ```bash source ~/ComfyUI/venv/bin/activate python -c "import torch; print(torch.__version__)" ``` ### "CLIP type not found" or wrong model type Make sure the CLIPLoader node type is set to **`lumina2`** — NOT `stable_diffusion`. ### OOM (Out of Memory) during generation 1. Reduce resolution to 512×512 2. Ensure `--lowvram` is set 3. Close other programs using RAM 4. Try `--use-split-cross-attention` flag ### Model not showing in dropdown Verify symlinks are not broken: ```bash ls -la ~/ComfyUI/models/unet/z_image_turbo-Q5_K_S.gguf ls -la ~/ComfyUI/models/vae/ae.safetensors ls -la ~/ComfyUI/models/text_encoders/gemma2_2b_lumina2.safetensors ``` ### "UnetLoaderGGUF" node not found Ensure ComfyUI-GGUF is installed: ```bash ls ~/ComfyUI/custom_nodes/ComfyUI-GGUF/ pip list | grep gguf ``` ### PyTorch ROCm version mismatch ```bash python -c "import torch; print(torch.version.cuda)" # Should print: 6.2 ``` --- ## 10. File Inventory ### Installation Files | File | Purpose | |------|---------| | `~/ComfyUI/` | ComfyUI installation directory | | `~/ComfyUI/venv/` | Python 3.11 virtual environment | | `~/ComfyUI/custom_nodes/ComfyUI-GGUF/` | GGUF model loader custom node | | `~/ComfyUI/workflows/z_image_turbo_bc250.json` | Pre-made Z-Image Turbo workflow | | `~/start-comfyui.sh` | Launch script with ROCm env vars | ### Model Files | File | Size | Format | |------|------|--------| | `~/ComfyUI/models/unet/z_image_turbo-Q5_K_S.gguf` | 5.2 GB | Symlink → `~/sd-models/diffusion_models/` | | `~/ComfyUI/models/text_encoders/gemma2_2b_lumina2.safetensors` | 9.8 GB | Merged from Alpha-VLLM/Lumina-Image-2.0 | | `~/ComfyUI/models/vae/ae.safetensors` | 335 MB | Symlink → `~/sd-models/vae/` | ### Output | File | Purpose | |------|---------| | `~/ComfyUI/output/` | Generated images saved here | ### Python Packages (key ones) | Package | Version | |---------|---------| | torch | 2.5.1+rocm6.2 | | torchvision | 0.20.1+rocm6.2 | | torchaudio | 2.5.1+rocm6.2 | | pytorch-triton-rocm | 3.1.0 | | transformers | 5.2.0 | | safetensors | 0.7.0 | | gguf | 0.18.0 | | comfyui-frontend-package | 1.39.19 | --- ## 11. Performance Notes ### Startup Output (successful launch) ``` Total VRAM 14750 MB, total RAM 15205 MB pytorch version: 2.5.1+rocm6.2 AMD arch: gfx1010 ROCm version: (6, 2) Forcing FP32 Set vram state to: LOW_VRAM Device: cuda:0 AMD Radeon Graphics : native ComfyUI version: 0.15.1 ComfyUI-GGUF: Partial torch compile only, consider updating pytorch ``` ### Expected Timing (BC-250, 512×512, 8 steps) | Phase | Estimated Time | |-------|---------------| | Model Loading (first run) | 30-60s | | Text Encoding (Gemma 2 2B) | ~2-5s | | Sampling (8 steps, Euler) | ~60-90s | | VAE Decode | ~10-15s | | **Total (first image)** | **~2-3 min** | | **Total (subsequent)** | **~1-2 min** | ### Comparison with sdcpp-restapi | | ComfyUI + PyTorch | sdcpp-restapi | |---|---|---| | Frontend | Full node-based GUI | REST API + simple WebUI | | Model format | GGUF + safetensors | GGUF only | | Memory management | PyTorch (--lowvram) | ggml manual | | Flexibility | Full workflow customization | Fixed pipeline | | Turbo steps | Configurable per-run | Config-based | --- ## Appendix: Quick Start Cheatsheet ```bash # 1. Launch ComfyUI bash ~/start-comfyui.sh # 2. Open browser # http://localhost:8188 # 3. Load workflow # Menu → Load → z_image_turbo_bc250.json # 4. Click "Queue Prompt" to generate # 5. Images saved in ~/ComfyUI/output/ ``` --- *Document generated: 2026-03-02 | System: CachyOS + AMD BC-250 + ROCm 7.2.0*