diff --git a/.gitignore b/.gitignore index 519c1a2..f59928a 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,7 @@ CLAUDE.md # local benchmark outputs /test_outputs/ /.wty_results/ +/assets/minimax-h3-ref2va/ # local-only CPU profiling / benchmark tooling (not for commit) /scripts/run_image_cmp.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index 1292d29..f472f74 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,6 +29,7 @@ option(ED_ENABLE_CUDNN_SDPA "Enable experimental cuDNN SDPA backend for CUDA fla option(ED_ENABLE_CUDA_NORM "Enable edge CUDA norm fast paths for ggml CUDA backend" ON) option(ED_ENABLE_CUDA_ROPE "Enable edge CUDA RoPE fast paths for ggml CUDA backend" ON) option(ED_ENABLE_CUDA_MODULATION "Enable edge CUDA fused modulation fast paths for ggml CUDA backend" ON) +option(ED_ENABLE_CUDA_GRAPHS "Compile CUDA Graph support for opt-in edge inference" ON) option(ED_ENABLE_CUDA_SAGE_ATTN "Enable SageAttention2-style INT8-QK + F16-PV fused attention for ggml CUDA backend" OFF) option(ED_ENABLE_PARALLEL "Enable edge-dit lightweight parallel runtime" OFF) option(ED_ENABLE_NCCL "Enable NCCL communication backend" OFF) @@ -254,6 +255,9 @@ if(ED_ENABLE_CUDA_MODULATION AND ED_GGML_CUDA) endif() if(ED_GGML_CUDA) + if(ED_ENABLE_CUDA_GRAPHS) + set(GGML_CUDA_GRAPHS ON CACHE BOOL "ggml: use CUDA graphs" FORCE) + endif() find_package(CUDAToolkit REQUIRED) target_sources(ggml-cuda PRIVATE @@ -291,9 +295,10 @@ if(ED_ENABLE_CUDNN_SDPA) PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src/core/backend/cuDNN/ed_cudnn_conv2d.cu ${CMAKE_CURRENT_SOURCE_DIR}/src/core/backend/cuDNN/ed_cudnn_conv3d.cu + ${CMAKE_CURRENT_SOURCE_DIR}/src/core/backend/cuDNN/ed_cudnn_conv_transpose_1d.cu ${CMAKE_CURRENT_SOURCE_DIR}/src/core/backend/cuDNN/ed_cudnn_sdpa.cu ) - target_compile_definitions(ggml-cuda PRIVATE ED_ENABLE_CUDNN_SDPA ED_ENABLE_CUDNN_CONV2D ED_ENABLE_CUDNN_CONV3D) + target_compile_definitions(ggml-cuda PRIVATE ED_ENABLE_CUDNN_SDPA ED_ENABLE_CUDNN_CONV2D ED_ENABLE_CUDNN_CONV3D ED_ENABLE_CUDNN_CONV_TRANSPOSE_1D) target_include_directories(ggml-cuda PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src/core/backend/cuDNN @@ -391,7 +396,7 @@ target_compile_definitions(edgedit ) if(ED_ENABLE_CUDNN_SDPA) - target_compile_definitions(edgedit PRIVATE ED_ENABLE_CUDNN_SDPA ED_ENABLE_CUDNN_CONV2D ED_ENABLE_CUDNN_CONV3D) + target_compile_definitions(edgedit PRIVATE ED_ENABLE_CUDNN_SDPA ED_ENABLE_CUDNN_CONV2D ED_ENABLE_CUDNN_CONV3D ED_ENABLE_CUDNN_CONV_TRANSPOSE_1D) endif() if(ED_ENABLE_CUDA_MODULATION AND ED_GGML_CUDA) diff --git a/README.md b/README.md index b7eb988..694e4df 100644 --- a/README.md +++ b/README.md @@ -19,9 +19,9 @@ runtime for image generation, image editing, and video generation across local, edge, and resource-constrained deployment environments. It supports major DiT model families including **FLUX.1, FLUX.2 [klein] 4B, -Stable Diffusion 3/3.5, Qwen-Image, and Wan**, with explicit control over model -loading, memory usage, graph execution, quantization, device placement, and -backend selection. +Stable Diffusion 3/3.5, Qwen-Image, Wan, and MiniMax-H3**, with explicit control +over model loading, memory usage, graph execution, quantization, device +placement, and backend selection. ## Features @@ -34,7 +34,7 @@ backend selection. - **Unified across tasks and model families** - **Text-to-image**, **image editing**, and **video generation** in one runtime - SD3/SD3.5, FLUX.1, FLUX.1-Kontext, FLUX.2 [klein] 4B, Qwen-Image, - Qwen-Image-Edit, and Wan 2.1 + Qwen-Image-Edit, Wan 2.1, and MiniMax-H3 video+audio - **Few-step distilled models** auto-detected β€” Turbo / Lightning / schnell default to a **4–8 step** schedule - Shared **C API, CLI, HTTP server, and Python** interfaces across every family @@ -54,6 +54,7 @@ backend selection. ## Latest News +- **2026-08-14:** πŸš€ Added **MiniMax-H3 FL2VA and Ref2VA video+audio generation** with image, video, embedded/paired audio, and mixed references; full or pruned BF16 DiTs, persistent Q8_0 conversion, Q4_K_M weights, and automatic VRAM fitting are supported ([usage and H200 results](docs/minimax-h3.md)). - **2026-08-05:** πŸš€ Completed the **RTX 4090 (24 GB) benchmark** β€” full cross-system speed / VRAM / image-quality across text-to-image, editing, and video ([results](docs/performance-4090.md)). - **2026-07-30:** πŸš€ Added **per-component offload** (`--dit-offload` / `--text-encoder-offload` / `--vae-offload`), unifying all offload paths on one semantics. - **2026-07-29:** πŸš€ Added **`--auto-fit`** β€” one flag picks DiT quantization *and* per-component placement to fit a hard VRAM budget. @@ -80,6 +81,7 @@ the current support commitment unless documented in | **Qwen-Image** | Text-to-image | `Qwen/Qwen-Image` | Qwen-Image Lightning *(LoRA)* | Supported | | **Qwen-Image-Edit** | Image editing | `Qwen/Qwen-Image-Edit` | Qwen-Image-Edit Lightning *(LoRA)* | Supported | | **Wan 2.1** | Video generation | `Wan-AI/Wan2.1-T2V-1.3B` (and 14B) | Wan2.1-T2V-1.3B Distill | Supported (Vulkan still optimizing) | +| **MiniMax-H3** | Video + audio generation | FL2VA / Ref2VA component checkpoints | β€” | Supported (CUDA validated) | Distilled checkpoints load through the same pipeline as the base model and are **auto-detected** (default **4–8 steps** when `--steps` is unset). Most ship as @@ -158,6 +160,17 @@ Load time follows each runtime's reported initialization boundary and may reflect different weight materialization or memory-mapping strategies. Generation latency is the primary cross-runtime performance metric. +MiniMax-H3 has a separate 124-frame H200 benchmark because it generates video +and audio rather than one image. In the current resident-component BF16 +comparison, Edge is faster than Diffusers in all four FL2VA and all four Ref2VA +generation paths while using less peak VRAM. FL2VA text-to-video takes +`51.396s` versus `53.986s`; Ref2VA image and mixed-reference generation reach +`1.08x` and `1.06x` speedups. Full and pruned BF16 DiTs are supported directly, +and either can be converted once to persistent Q8_0 GGUF. `--auto-fit` has also +been validated down to a 24 GB VRAM budget. See [MiniMax-H3 usage and +performance](docs/minimax-h3.md) for inputs, weights, memory placement, and the +complete comparison. + ## Open-Source Interfaces edge-dit.cpp exposes the same runtime through several public integration diff --git a/docs/cli.md b/docs/cli.md index 8e54bda..24e6ee8 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -273,6 +273,7 @@ Video flags: ```text --video --frames +--video-duration # MiniMax-H3 only --fps --video-format auto|avi|mp4|mov|mkv|webm ``` @@ -366,6 +367,7 @@ Memory-oriented flags: --vae-offload --max-vram --auto-allocate +--auto-fit ``` `--vae-tiling` is tri-state `on|off|auto` and defaults to `auto`, which enables @@ -401,6 +403,31 @@ requested resolution (`-W`/`-H`, and `--frames` for video) to size the resident headroom, so pass the generation size you intend to use. Without a size it falls back to a conservative fixed headroom. +MiniMax-H3 applies this policy to four independently placeable components: DiT, +Qwen3-VL, video VAE, and audio VAE. Its measurement graph conservatively includes +mixed image, video, paired-audio, and additional-audio conditioning, so the same +placement remains valid across FL2VA and Ref2VA workflows. The MiniMax-H3 video +VAE also keeps its model-specific fixed `16x16` tiling regardless of the generic +`--vae-tiling`/`--vae-tile-size` values. + +For MiniMax-H3, `--video-duration ` converts a requested duration at +the model's fixed 24 fps to the nearest legal `17k+5` frame count. Keep using +`--video-frames` when an exact legal count is required; the two options are +mutually exclusive. + +```bash +# MiniMax-H3 Q8_0 under a 40 GiB hard placement budget. +./build-cuda/bin/ed-cli --video \ + --diffusion-model /path/to/minimax_h3_fl2va-diffusers-Q8_0.gguf \ + --vae /path/to/minimax_h3_video_vae_fp16.safetensors \ + --audio-vae /path/to/minimax_h3_audio_vae_fp32.safetensors \ + --llm /path/to/qwen3vl_32b_minimax_h3-Q8_0.gguf \ + --auto-fit --max-vram 40 --vae-tiling auto \ + -W 864 -H 480 --video-duration 5 --steps 20 --cfg-scale 1 \ + --prompt "A cinematic sunset over layered mountain ridges." \ + --video-format mp4 --output minimax-h3-autofit.mp4 +``` + ```bash # Fully automatic under an 8 GiB budget β€” system picks DiT quant + placement. ./build-cuda/bin/ed-cli \ @@ -700,4 +727,4 @@ See [API and bindings](api.md) for HTTP endpoints and curl examples. - [performance (RTX 4090)](performance-4090.md) - [performance (H200)](performance-H200.md) - [API and bindings](api.md) -- [Development and contributing](development.md) \ No newline at end of file +- [Development and contributing](development.md) diff --git a/docs/minimax-h3.md b/docs/minimax-h3.md index 90c51fc..3ffca88 100644 --- a/docs/minimax-h3.md +++ b/docs/minimax-h3.md @@ -1,211 +1,248 @@ # MiniMax-H3 -edge-dit.cpp supports MiniMax-H3 video + audio generation through the standalone -component-loading path. The implementation follows the MiniMax-H3 interface used -by `stable-diffusion.cpp`: one diffusion checkpoint, Qwen3-VL text/vision encoder, -video VAE, and optional audio VAE. +edge-dit.cpp supports MiniMax-H3 video-and-audio generation through standalone +components: one FL2VA or Ref2VA diffusion model, one Qwen3-VL text/vision +encoder, the video VAE, and the optional audio VAE. CUDA is the validated +backend for this model family. -## Model files - -MiniMax-H3 runs with four model components. The diffusion checkpoint changes by -mode; the encoder and VAEs are shared. - -| Component | File name | Source | -|---|---|---| -| Qwen3-VL text/vision encoder | `qwen3vl_32b_minimax_h3-Q4_K_M.gguf` | [leejet/MiniMax-H3-GGUF](https://huggingface.co/leejet/MiniMax-H3-GGUF) | -| Video VAE | `minimax_h3_video_vae_fp16.safetensors` | [Comfy-Org/MiniMax-H3](https://huggingface.co/Comfy-Org/MiniMax-H3) | -| Audio VAE | `minimax_h3_audio_vae_fp32.safetensors` | [Comfy-Org/MiniMax-H3](https://huggingface.co/Comfy-Org/MiniMax-H3) | - -### FL2VA checkpoint - -| Component | File name | Source | -|---|---|---| -| Diffusion model | `minimax_h3_fl2va-Q4_K_M.gguf` | [leejet/MiniMax-H3-GGUF](https://huggingface.co/leejet/MiniMax-H3-GGUF) | +## Checkpoints and inputs -Supported modes: +FL2VA and Ref2VA share Qwen3-VL and both VAEs, but require different diffusion +checkpoints. -| Mode | Inputs | Output | -|---|---|---| -| T2VA | Text prompt | Video + audio | -| I2VA | Text prompt + first frame image | Video + audio | -| FL2VA | Text prompt + first frame image + last frame image | Video + audio | - -### Ref2VA checkpoint - -| Component | File name | Source | -|---|---|---| -| Diffusion model | `minimax_h3_ref2va_pruned-Q4_K_M.gguf` | [leejet/MiniMax-H3-GGUF](https://huggingface.co/leejet/MiniMax-H3-GGUF) | +| Checkpoint | Supported conditioning | +|---|---| +| FL2VA | Text; first frame; last frame; first and last frames | +| Ref2VA | Repeatable reference images, videos, paired video audio, and additional audio | -Supported reference inputs: +FL2VA uses `--image`/`--init-img` for the first frame and `--end-img` for the +last frame. Ref2VA uses the following options: -| Input | CLI flag | Notes | +| Input | CLI option | Behavior | |---|---|---| -| Reference image | `--ref-image ` | Repeatable. Presented as `` to Qwen3-VL. | -| Reference video | `--ref-video ` | Repeatable. Directory of image frames sorted lexicographically; treated as 24 fps. | -| Paired video audio | `--ref-video-audio ` | Repeatable. The Nth WAV is paired with the Nth `--ref-video`. | -| Standalone audio | `--ref-audio ` | Repeatable. Independent audio reference, not attached to a video. | +| Image | `--ref-image ` | Repeatable; presented as `` | +| Video | `--ref-video ` | Repeatable frame directory or `mp4`/`mov`/`mkv`/`webm`/`avi`; media files require `ffmpeg` | +| Paired audio | `--ref-video-audio ` | The Nth WAV is paired with the Nth video and overrides embedded audio | +| Additional audio | `--ref-audio ` | Repeatable; requires at least one image or video reference | -The reference inputs can be combined freely within Ref2VA. Ref2VA cannot be used -with `--image` or `--end-img` in the same request. +When `--ref-video` points to a media file, the CLI decodes it at 24 fps and +automatically extracts an embedded audio track. Explicit paired WAV files map +positionally to videos. Additional audio is numbered after paired or embedded +video audio. Ref2VA references cannot be combined with FL2VA first/last-frame +options, and audio-only Ref2VA requests are rejected. -MiniMax-H3 control frames are not supported for either checkpoint. - -## Common parameters +## Model files -MiniMax-H3 is a 24 fps audio-video model. The usual full-resolution setting is: +### Downloadable weights + +The complete, unpruned checkpoints are recommended for the best quality. Edge +also supports pruned DiT weights in BF16 safetensors format. Both full and +pruned BF16 DiTs can be converted to Q8_0 GGUF with `ed-convert`, and the +resulting Q8_0 DiTs can be loaded directly. Performance and quality results from +pruned and full DiTs are not directly comparable. + +| Precision | Component | File | Repository | +|---|---|---|---| +| Q4_K_M | FL2VA DiT | `minimax_h3_fl2va-Q4_K_M.gguf` | [`leejet/MiniMax-H3-GGUF`](https://huggingface.co/leejet/MiniMax-H3-GGUF) | +| Q4_K_M | Ref2VA DiT | `minimax_h3_ref2va-Q4_K_M.gguf` | [`leejet/MiniMax-H3-GGUF`](https://huggingface.co/leejet/MiniMax-H3-GGUF) | +| Q4_K_M | Qwen3-VL | `qwen3vl_32b_minimax_h3-Q4_K_M.gguf` | [`leejet/MiniMax-H3-GGUF`](https://huggingface.co/leejet/MiniMax-H3-GGUF) | +| BF16 | FL2VA DiT | `diffusion_models/minimax_h3_fl2va_bf16.safetensors` | [`Comfy-Org/MiniMax-H3`](https://huggingface.co/Comfy-Org/MiniMax-H3) | +| BF16 | Ref2VA DiT | `diffusion_models/minimax_h3_ref2va_bf16.safetensors` | [`Comfy-Org/MiniMax-H3`](https://huggingface.co/Comfy-Org/MiniMax-H3) | +| BF16, pruned | FL2VA DiT | `diffusion_models/minimax_h3_fl2va_pruned_bf16.safetensors` | [`Comfy-Org/MiniMax-H3 diffusion models`](https://huggingface.co/Comfy-Org/MiniMax-H3/tree/main/diffusion_models) | +| BF16, pruned | Ref2VA DiT | `diffusion_models/minimax_h3_ref2va_pruned_bf16.safetensors` | [`Comfy-Org/MiniMax-H3 diffusion models`](https://huggingface.co/Comfy-Org/MiniMax-H3/tree/main/diffusion_models) | +| BF16 | Qwen3-VL | `text_encoders/qwen3vl_32b_minimax_h3_bf16.safetensors` | [`Comfy-Org/MiniMax-H3`](https://huggingface.co/Comfy-Org/MiniMax-H3) | +| FP16 | Video VAE | `vae/minimax_h3_video_vae_fp16.safetensors` | [`Comfy-Org/MiniMax-H3`](https://huggingface.co/Comfy-Org/MiniMax-H3) | +| FP32 | Audio VAE | `vae/minimax_h3_audio_vae_fp32.safetensors` | [`Comfy-Org/MiniMax-H3`](https://huggingface.co/Comfy-Org/MiniMax-H3) | + +The official [`MiniMaxAI/MiniMax-H3`](https://huggingface.co/MiniMaxAI/MiniMax-H3) +Diffusers shard indexes are also accepted for BF16 transformer loading. Merged +Comfy-Org files are usually more convenient for standalone component commands. + +Example downloads with the Hugging Face CLI: ```bash --W 864 -H 480 --fps 24 --video-frames 56 --cfg-scale 1.0 --diffusion-fa --rng cpu +hf download leejet/MiniMax-H3-GGUF \ + minimax_h3_fl2va-Q4_K_M.gguf minimax_h3_ref2va-Q4_K_M.gguf \ + qwen3vl_32b_minimax_h3-Q4_K_M.gguf --local-dir models/minimax-h3-q4 + +hf download Comfy-Org/MiniMax-H3 \ + diffusion_models/minimax_h3_fl2va_bf16.safetensors \ + diffusion_models/minimax_h3_ref2va_bf16.safetensors \ + text_encoders/qwen3vl_32b_minimax_h3_bf16.safetensors \ + vae/minimax_h3_video_vae_fp16.safetensors \ + vae/minimax_h3_audio_vae_fp32.safetensors \ + --local-dir models/minimax-h3 ``` -The frame count must satisfy `17k + 5` (for example `5`, `22`, `39`, `56`). The -examples below use 56 frames and 20 steps. - -Use `--video-format mp4` for H.264/AAC MP4 output when `ffmpeg` is available. -Without `--audio-vae`, the model can still generate video, but no generated audio -is decoded or muxed. +### Persistent Q8_0 GGUF -## FL2VA usage - -### Text to video + audio +Q8_0 benchmark files are offline conversions of the full BF16 DiTs and Qwen3-VL, +not Comfy-Org INT8 ConvRot weights. A pruned BF16 DiT can be converted with the +same command when lower storage and memory usage are preferred. Convert once +with `ed-convert` instead of quantizing during every model load: ```bash -ed-cli --video \ - --diffusion-model minimax_h3_fl2va-Q4_K_M.gguf \ - --vae minimax_h3_video_vae_fp16.safetensors \ - --audio-vae minimax_h3_audio_vae_fp32.safetensors \ - --llm qwen3vl_32b_minimax_h3-Q4_K_M.gguf \ - -p "A cat surfs on an ocean wave with upbeat surf-rock music." \ - --cfg-scale 1 -W 864 -H 480 --fps 24 --video-frames 56 --steps 20 \ - --diffusion-fa --rng cpu --video-format mp4 \ - -o minimax_h3_t2va.mp4 +ed-convert --model models/minimax-h3/diffusion_models/minimax_h3_fl2va_bf16.safetensors \ + --type q8_0 --output models/minimax-h3-q8/minimax_h3_fl2va-Q8_0.gguf +ed-convert --model models/minimax-h3/diffusion_models/minimax_h3_ref2va_bf16.safetensors \ + --type q8_0 --output models/minimax-h3-q8/minimax_h3_ref2va-Q8_0.gguf +ed-convert --model models/minimax-h3/text_encoders/qwen3vl_32b_minimax_h3_bf16.safetensors \ + --type q8_0 --output models/minimax-h3-q8/qwen3vl_32b_minimax_h3-Q8_0.gguf ``` -### First-frame image to video + audio +The same converter accepts an official transformer +`model.safetensors.index.json`; the resulting persistent GGUF is equivalent at +the selected quantization type and avoids repeated online conversion. -```bash -ed-cli --video \ - --diffusion-model minimax_h3_fl2va-Q4_K_M.gguf \ - --vae minimax_h3_video_vae_fp16.safetensors \ - --audio-vae minimax_h3_audio_vae_fp32.safetensors \ - --llm qwen3vl_32b_minimax_h3-Q4_K_M.gguf \ - --image first_frame.png \ - -p "Animate the provided first frame into a cinematic shot with matching sound." \ - --cfg-scale 1 -W 864 -H 480 --fps 24 --video-frames 56 --steps 20 \ - --diffusion-fa --rng cpu --video-format mp4 \ - -o minimax_h3_i2va.mp4 -``` +## Duration and frame count -### First + last frame to video + audio +MiniMax-H3 always generates at 24 fps. Its frame count must satisfy `17k + 5`, +for example `5`, `22`, `39`, `56`, `73`, `90`, `107`, or `124`. -```bash -ed-cli --video \ - --diffusion-model minimax_h3_fl2va-Q4_K_M.gguf \ - --vae minimax_h3_video_vae_fp16.safetensors \ - --audio-vae minimax_h3_audio_vae_fp32.safetensors \ - --llm qwen3vl_32b_minimax_h3-Q4_K_M.gguf \ - --image first_frame.png --end-img last_frame.png \ - -p "Create a smooth transition from the first frame to the last frame with natural audio." \ - --cfg-scale 1 -W 864 -H 480 --fps 24 --video-frames 56 --steps 20 \ - --diffusion-fa --rng cpu --video-format mp4 \ - -o minimax_h3_fl2va.mp4 -``` - -## Ref2VA usage +Use `--video-duration ` for the convenient interface. The CLI converts +the requested duration at 24 fps and selects the nearest legal frame count. For +example, `--video-duration 5` resolves to 124 frames, or approximately 5.17 +seconds. The resolved value is printed before generation. Use +`--video-frames ` when an exact legal frame count is required. The two +options are mutually exclusive. -When using references, write the prompt so it explicitly mentions the reference -slots, such as ``, `