Skip to content

Reduce auto temporal tile size to 32f: avoids silent Metal conv2d corruption (gray-frame decodes) - #47

Open
kayadibi1 wants to merge 1 commit into
Blaizzy:mainfrom
kayadibi1:fix/vae-tiling-metal-conv2d
Open

Reduce auto temporal tile size to 32f: avoids silent Metal conv2d corruption (gray-frame decodes)#47
kayadibi1 wants to merge 1 commit into
Blaizzy:mainfrom
kayadibi1:fix/vae-tiling-metal-conv2d

Conversation

@kayadibi1

Copy link
Copy Markdown

Problem

Decoding Wan 2.1/2.2 videos at common sizes (e.g. 81 frames, 768x512) with the current auto tiling (spatial 512px / temporal 64f) produces flat gray output for the regions covered by large tiles — no exception, no warning. Smaller edge tiles decode correctly, so it presents as a blending bug: gray for the first ~40 frames and the left ~450px of every frame, content fading in near tile overlaps.

Root cause (isolated, not guessed)

MLX's Metal conv2d silently returns all zeros for large batched inputs — filed with a 30-line standalone repro as ml-explore/mlx#3979. At C_in=192 it breaks between 1.61e9 and 2.01e9 input elements (C_in=128 is still correct at 3.22e9, so it's a channel-dependent kernel path).

The Wan VAE hits it inside Resample: frames are folded into batch ([B*T, H, W, C]) before the spatial-upsample Conv2d. With 64-frame temporal tiles at 512px spatial tiles, the 192→96 upsample stage receives [64, 512, 512, 192] = 3.2e9 elements → zeros. A layer bisect (real weights, random latents) shows activation std collapsing from 3.44 to 0.02 at exactly that stage.

Change

TilingConfig.auto: temporal tiles 64 → 32 frames (overlap unchanged). Every conv input stays under the threshold.

Validation

  • 41-frame roundtrip, spatial 512/64 + temporal 32/24 vs untiled ground truth: mean abs diff 4e-4 (blend-zone noise), per-frame stats identical.
  • End-to-end 81f 768x512 and 512x768 Wan 2.2 I2V renders: input image reproduced faithfully at frame 0, no gray regions, no seams.
  • Cost: ~2x temporal tile count; decode 136s → ~205s for 81f 768x512 on an M5 Pro 48 GB. Correctness over speed for a default.

TilingConfig.default() still uses 64f — happy to change it too if you prefer; auto is what generate uses. Longer term, tile sizes could be computed dynamically to keep each Resample conv input under a safe element budget until the MLX kernel is fixed.

🤖 Generated with Claude Code

…v2d corruption

With 512px spatial tiles, 64-frame temporal tiles push the Wan VAE
Resample Conv2d input past ~2e9 elements, where MLX's Metal conv2d
silently returns all-zero output (ml-explore/mlx#3979). Affected tiles
decode as flat gray with no error raised anywhere.

32-frame tiles keep every conv input under the threshold. Validated
against untiled ground truth on a 41-frame roundtrip (mean abs diff
4e-4, blend-zone noise only) and end-to-end on 81f 768x512 / 512x768
Wan 2.2 I2V renders (no gray regions, no seams). Cost: ~2x temporal
tile count, decode 136s -> ~205s for 81f 768x512 on an M5 Pro 48GB.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant