Skip to content

Studio: build VAE tile blend weights on CPU so MPS tiled encode works - #12937

Merged
Lyxot merged 4 commits into
unslothai:mainfrom
gokay-ai:fix-vae-tiling-mps-float64
Oct 8, 2026
Merged

Lyxot merged 4 commits into
unslothai:mainfrom
gokay-ai:fix-vae-tiling-mps-float64

Conversation

@gokay-ai

@gokay-ai gokay-ai commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

Fixes #12935

axis_weights() in diffusion_vae_tiling.py built its float64 blend weights directly on the VAE's device. On Apple Silicon that raises Cannot convert a MPS Tensor to float64 dtype as soon as tiled_encode runs, so every Qwen-Image-2.1 generation with an input image failed before the first step.

The weights are now built on CPU in float64 and only the fp32 result is moved to the device, the same way video_ltx2_vae_tiles.axis_weights already does it. The vectors are one per tile axis, so the extra copy is negligible. Results on CUDA/CPU are unchanged.

Added test_axis_weights_never_put_float64_on_the_device (same spy test as the LTX-2 one, on a meta device). It fails on main and passes with the fix. test_diffusion_vae_tiling.py, test_diffusion_vae_tiling_general.py, test_vae_tile_geometry.py and test_video_ltx2_vae_tiles.py pass locally (545 passed, 39 skipped, CPU torch). I don't have an Apple Silicon machine, so this isn't checked on real MPS.

Thanks @iMonZ for the clear report and the suggested fix.

axis_weights() in diffusion_vae_tiling built its float64 weights directly on
the target device, so a tiled encode on Apple Silicon raised before the first
step (MPS has no float64). Build them on CPU and move only the fp32 result,
matching video_ltx2_vae_tiles.axis_weights.

Fixes unslothai#12935

Signed-off-by: GokayAI <[email protected]>
Copilot AI balanced review requested due to automatic review settings October 7, 2026 10:33

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@danielhanchen

Copy link
Copy Markdown
Member

Confirmed main still builds the float64 blend weights on the VAE device in diffusion_vae_tiling.py, which MPS rejects on every tiled encode, and moving only the fp32 result over looks right. Will get this reviewed, ideally with a run on a real Apple Silicon machine.

@iMonZ

iMonZ commented Oct 7, 2026

Copy link
Copy Markdown

@gokay-ai Thank you for the PR. I tested this on Apple Silicon and verified it works.

@danielhanchen

Copy link
Copy Markdown
Member

Neither red check is from this PR. Repo tests (CPU, studio) fails test_embedding_model_controls_stack_on_the_narrowest_viewports, red on main since #12875 and fixed in #12945. GGUF inference smoke stalled in the tool-calling step after the bash tool passed (no output from 11:49 until the 20 minute timeout); I have re-run it.

@Lyxot Lyxot self-assigned this Oct 8, 2026
Lyxot added 3 commits October 8, 2026 14:26
…ks float64

The tile blend weights were moved to an unconditional CPU build to keep float64 off MPS. Gate that on the device's float64 capability instead, the way the RoPE demotion already is: a device with float64 builds them in place exactly as before, and only MPS builds on CPU and receives the fp32 result. The regression test now watches every tensor the build produces rather than the constructor arguments, so a float64 tensor reaching the device through a later move or cast is caught too.
…E tiles

The LTX-2 axis_weights was a copy of the image one that differed only in its default margin and ramp, and the image copy missed the MPS float64 handling the LTX-2 copy had. Delegate to the image implementation with the LTX-2 defaults so the float64 capability is decided in one place.
@Lyxot

Lyxot commented Oct 8, 2026

Copy link
Copy Markdown
Collaborator

Pushed two commits on top of the original fix, plus a merge of the latest main.

What changed

  • axis_weights now decides where to build its float64 values from the device's supports_float64 capability (new float64_device helper in diffusion_device.py), the same flag force_float32_rope already keys off. A device with float64 builds in place exactly as main does, so CUDA / XPU / CPU run the same operations as before; only MPS builds on CPU and receives the fp32 result.
  • The LTX-2 axis_weights was a copy of the image one that differed only in its default margin and ramp. It now delegates to the image implementation, so the float64 handling lives in one place.
  • The regression test records the dtype and device of every tensor the build produces instead of the constructor keyword arguments. The earlier spy test still passed with .to(device).float() in place of .float().to(device), which puts float64 on the device.

Validation

  • Apple Silicon (MPS, torch 2.10): on main, axis_weights, the tiled encode and the tiled decode of a small random AutoencoderKLQwenImage21 all raise the float64 TypeError; with this branch all three run, and the weights are fp32 on mps and bit-equal to the CPU weights.
  • CUDA (RTX 4070 SUPER, torch 2.11): weights built in float64 on cuda are bit-equal to weights built on CPU across 1592 tile geometries (image decode 8x / 16x / 32x, image encode, LTX-2), so moving the LTX-2 build onto the device changes no output.
cd studio/backend
python -m pytest tests/test_diffusion_vae_tiling.py tests/test_video_ltx2_vae_tiles.py tests/test_diffusion_device.py tests/test_vae_tile_geometry.py -q
# 816 passed

@Lyxot

Lyxot commented Oct 8, 2026

Copy link
Copy Markdown
Collaborator

Review and CI status for head e9ca0e2d4b, run on a staging PR with the same head.

@Lyxot Lyxot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified on Apple Silicon: tiled encode and decode run on MPS, and blend weights are bit-identical on CUDA and CPU. Codex found no issues; the one red CI check is the unrelated hub-token test failure already on main.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Studio (macOS/MPS): image generation with an input image fails — VAE tiling builds float64 weights on MPS

5 participants