Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -110,18 +110,28 @@ Two Z-Image ControlNets are available as starters (both are part of the bundle):
- **Z-Image ControlNet Tile** is useful for upscaling and adding detail. The **Upscale** tool can use it as an
optional anchor; see [Upscaling](/users-guide/image-generation/upscale/).

Every Z-Image Turbo Fun-ControlNet alibaba-pai has published can be installed from its `.safetensors` file:
the first Union release, Union 2.0, the Union and Tile 2.1 builds (8-step, 2601 and 2602 included) and the 2.1
Lite builds. Invoke tells them apart by their weights. Invoke does not inpaint through a Z-Image ControlNet:
a control layer takes a control image only.

On the Canvas, add a **Control Layer** while a Z-Image model is selected. The layer uses a Z-Image
ControlNet with a default weight of `0.75`. The weight ranges from `0` to `2`, and `0.65` to `0.80` is the
recommended range. **Only one** Z-Image control layer can be used per generation.

Earlier Invoke versions placed the hints of the Lite and first Union builds after the wrong layers, and left
out the refiner hints of 2.0 and 2.1 (2.0 also refined its control through the wrong blocks). Applied as they were trained, these ControlNets now follow the control image
more strongly at the same weight; lower the weight if a control image constrains the result too much.

In the workflow editor, the same thing is the **Z-Image ControlNet** node feeding the **Control** input of
**Denoise - Z-Image**. That node also needs the **VAE** input connected, which it uses to encode the
control image.

## Regional prompting

Z-Image supports **Regional Guidance** layers on the Canvas with **positive** prompts. Regional negative
prompts, auto-negative and regional reference images are not supported for Z-Image.
Z-Image supports **Regional Guidance** layers on the Canvas with **positive** prompts, together with a
control layer if you like. Regional negative prompts, auto-negative and regional reference images are not
supported for Z-Image.

In the workflow editor, **Prompt - Z-Image** takes an optional mask, and **Denoise - Z-Image** accepts
either one conditioning or a collection of them.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ compared with PyTorch's default attention there:
| --- | --- | --- | --- |
| FLUX.1 dev (FP8) | 16.1 s → 14.0 s (−13 %) | 84.2 s → 54.8 s (−35 %) | Also serves ControlNets inside the denoising loop. |
| FLUX.2 Klein 9B (FP8) | 15.6 s → 15.1 s (−3 %) | 27.1 s → 23.1 s (−15 %) | |
| Z-Image (FP8) | 10.4 s → 10.0 s (−5 %) | 33.7 s → 25.9 s (−23 %) | Z-Image Control masks its attention and keeps PyTorch's. |
| Z-Image (FP8) | 10.4 s → 10.0 s (−5 %) | 33.7 s → 25.9 s (−23 %) | Also serves ControlNets inside the denoising loop. |
| Qwen-Image 2512 (GGUF Q4_K_M) | 78.8 s → 73.5 s (−7 %) | 208.9 s → 150.3 s (−28 %) | One block reaches about 17 % error per call; images were still judged equivalent. |
| Krea-2 Turbo (GGUF Q4_K_M) | 11.5 s → 11.0 s (−4 %) | 42.7 s → 36.2 s (−15 %) | Off while `INVOKE_KREA2_SDPA_BACKEND` pins a PyTorch kernel. |
| SDXL | 4.4 s → 4.2 s (−5 %) | 19.6 s → 16.1 s (−18 %) | Text cross-attention stays on PyTorch (too short to gain). Also serves ControlNets. |
Expand Down
15 changes: 10 additions & 5 deletions invokeai/app/invocations/vae/z_image_image_to_latents.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,14 @@ def vae_encode(
image_tensor: torch.Tensor,
tiled: bool = False,
tile_size: int = 0,
deterministic: bool = False,
) -> torch.Tensor:
"""Encode an image to a Z-Image latent.
"""Encode an image to a Z-Image latent: a sample of the encoder's distribution, or its mode when
``deterministic``.

`z_image_denoise` also encodes its control image here, at generation resolution. That is
usually small enough to encode whole, but an upscale's generation resolution is the
enlarged frame, so the control field carries its own `tiled` and `tile_size`.
`z_image_denoise` also encodes its control image here, deterministically as VideoX-Fun does, at
generation resolution. That is usually small enough to encode whole, but an upscale's generation
resolution is the enlarged frame, so the control field carries its own `tiled` and `tile_size`.
"""
if not isinstance(vae_info.model, AutoencoderKL):
raise TypeError(
Expand Down Expand Up @@ -87,7 +89,10 @@ def vae_encode(
# other node that reaches this class. Tiling is a property of this one encode, so the
# state is scoped and restored rather than switched off by hand and left behind.
with torch.inference_mode(), scoped_vae_tiling(vae, effective_tile_size):
latents: torch.Tensor = vae.encode(image_tensor).latent_dist.sample().to(dtype=vae.dtype)
latent_dist = vae.encode(image_tensor).latent_dist
latents: torch.Tensor = (latent_dist.mode() if deterministic else latent_dist.sample()).to(
dtype=vae.dtype
)

# Apply scaling_factor and shift_factor from VAE config.
# Z-Image uses: latents = (latents - shift_factor) * scaling_factor
Expand Down
Loading
Loading