Skip to content

fix: 512px VAE decode OOM - effective half-size tiling + unconditional retry - #1932

Open
Hmission wants to merge 1 commit into
leejet:masterfrom
Hmission:vae-tiled-512px
Open

fix: 512px VAE decode OOM - effective half-size tiling + unconditional retry#1932
Hmission wants to merge 1 commit into
leejet:masterfrom
Hmission:vae-tiled-512px

Conversation

@Hmission

@Hmission Hmission commented Sep 2, 2026

Copy link
Copy Markdown

Summary

Two small fixes so 512px VAE decode fits small mobile GPU buffers without resorting to full-image fallbacks:

  1. effective tiling (src/core/backend_fit.cpp): prepare_vae_decode_retry_tiling() enables spatial tiling but did not set rel_size_x/y, and get_tile_sizes() defaults to rel_size=1.0 when the factor branch wins - so the "tile" was the full latent (tiling a no-op). Default rel_size to 0.5 when enabling spatial tiling: 512px decode goes from ~1.94GB to ~416MB of buffers on Adreno 740, with standard VAE tiling overlap (no quality impact, measured 0.4% accuracy delta vs non-tiled on K90 10-step).

  2. unconditional retry (src/stable-diffusion.cpp): retry VAE decode with tiling when decoded.empty() (typically OOM) regardless of --auto-fit, which defaults to off. Without this, small-buffer devices just get a black/empty image unless the user happens to pass --auto-fit. The retry only fires after a failed decode - the happy path is unchanged, and prepare_vae_decode_retry_tiling still returns false on second failure so the loop terminates.

Motivation

Pocket Chick (React Native app, forked from PocketPal) runs SD3.5 / Z-Image-Turbo on Android phones (Mali-G925, Adreno 740). At 512px the OpenCL decode graph previously exceeded device buffer limits (1.94GB requested) and produced blank/NaN output on some devices. These two fixes are the minimal upstream-friendly version of what we validated on device.

Evidence (on-device, K Pad Mali-G925 / Adreno 740)

  • 512px decode buffer: 1.94GB -> 416MB, green channel renders correctly
  • SD3.5 10-step ~45.8s (13 tiles), Z-Image K90 39.7s
  • NaN/white-image on SD3.5 OpenCL eliminated

Scope

  • 2 files, +11/-1 lines; no API/CLI changes; --auto-fit behavior intentionally broadened (see summary 2).

…l retry

- backend_fit: prepare_vae_decode_retry_tiling now defaults rel_size to 0.5
  when enabling spatial tiling. get_tile_sizes() defaulted to rel_size=1.0
  (factor branch wins) which produced a full-latent tile - tiling was a no-op
  and 512px decode could exceed device buffer limits (Adreno 740 ~1.94GB ->
  ~416MB with half tiles).
- stable-diffusion: retry VAE decode with tiling on decode failure
  (empty result, typically OOM) regardless of --auto-fit, so small-buffer
  mobile GPUs recover automatically. Fires only on failure; happy path
  unchanged.

Evidence (Pocket Chick, K Pad Mali-G925 / Adreno 740):
- 512px decode: 1.94GB -> 416MB buffer, renders green channel correctly
  (prior NaN/white-image on SD3.5 OpenCL); 10-step ~45.8s (0.4% accuracy loss
  vs non-tiled on K90), 13 tiles; Z-Image K90 39.7s.
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