Skip to content

LTX-2.5 FULL PORT: close every refused arm, prove the prompted path on real weights, and lift the resolution ceiling #644

Description

@localai-bot

The core port landed in cefacd2d0 (#435): DiT, both VAEs and their encoders, pipeline, quantized loaders (FP8 / torchao-NVFP4 / first-party NVFP4), the Gemma-4 tower, and a typed prompt wired to cross-attention. It renders a coherent scene.

It is not a complete port. This issue is the campaign to make it one. Directive: complete the LTX port, with all features, complete e2e, landed in main.

The gaps, from the code rather than from the summary

A — the prompted path is WIRED but never run on real weights (highest value)

--encoder + --prompt is reachable, has_encoder() is true, and prompt → tokenizer → Gemma-4 tower → caption projections → connector → cross-attention closes. But every gate on it is a reduced-dimension synthetic fixture. No real-checkpoint prompted render has been run in either direction, so we can say neither that it works nor that it fails. Until this is measured, "you can prompt it" is unproven.

B — image / keyframe / reference-video / reference-audio conditioning is REFUSED

The MiniMax-parity gap. H3 serves fl2va (keyframes) and ref2va (references); LTX-2.5 refuses all four kinds by name at ltx2_video.cpp:1122. Two distinct causes, both real:

  1. The VAE encoder landed (L11, Ltx2ConvVideoEncode) but nothing reaches it — the engine materializes the decoder key filter only, so no VAE_ENCODER_COMFY_KEYS_FILTER / VideoEncoderConfigurator path puts encoder weights in memory.
  2. The request-side work is unported: image decode, aspect-fill resize, and the H.264 CRF round trip upstream performs before encoding (ImageConditioner.resolve_crfpreprocess, skipped only at crf == 0).

C — the resolution ceiling is memory, and it is in the HOST VAE DECODE

Measured: 128x128/9f and 320x192/25f complete; 448x256/25f stops. MemAvailable is flat at 75.2 GiB through both denoise phases, then falls 73.0 → 13.8 GiB in 24 s with process RSS flat at 4.9 GB — on the decode side of the last drain, so no drain can shrink it. Named next steps: instrument Ltx2ConvVideoDecode's own allocations, then temporal chunking + spatial tiling (H3 needed both; either alone was worse than neither), then a device decode. No ceiling is declared — this is an unresolved implementation gap, not a limit of the hardware.

D–I — arms refused by name, each recorded rather than silently dropped

  • DiffVAE / NADiffusionDecoder — the higher-quality decoder, built on neighborhood attention. Needs a new kernel.
  • Temporal x2 upsampler (the spatial one ships).
  • LoRA fusion.
  • Multishot.
  • int8-convrot (ComfyUI-only quantization).
  • Multi-GPU / CFG parallelism.

J–N — correctness and completeness debt

  • No value oracle for the conditioning composition. Scaling it x1.5 or reversing its rows passes every assertion; last_conditioning() is a change detector. Closure path exists: gen-ltx2-pipeline-goldens.py already executes upstream embeddings_connector.py under a pinned SHA, so a section executing EmbeddingsProcessor.process_hidden_states end to end would give the join a real oracle.
  • The shipped NVFP4 tower is never compared to an independent oracle — its goldens come from our own low-first helper. PR L9a: the first-party NVFP4 DiT loads -- it was SWIZZLED and HIGH-nibble-first, not linear (#435) #571 built exactly the correlation technique that would close this.
  • The text encoder runs on a CPU queue even on the device arm, because it is f32 by declaration.
  • duration_head_path is accepted and never read (LTX-2.5: duration_head_path is accepted and never read — a caller who supplies it silently gets the recipe default #611) — a caller supplying it silently gets the recipe default.
  • Speed is structurally PENDING: vLLM-Omni carries no native 2.5 and its diffusers adapter is a black box (supports_step_execution=False), so no production-configuration denominator exists. Needs an explicitly ratified alternative denominator or a documented refusal.

Order

A first — it is cheap, it is the headline claim, and its result changes what B and C are worth. Then B (parity with our own H3 lane), then C (the ceiling). D–I are independent and parallelisable. J–N ride along with whichever row touches them.

Each gets a row and a committed spec before code, per AGENTS.md.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions