decntai commited on
Commit
2066a7d
Β·
verified Β·
1 Parent(s): affc1e5

Upload folder using huggingface_hub

Browse files
Files changed (6) hide show
  1. Dockerfile.sd-cli-cu12 +109 -0
  2. Dockerfile.sd-cli-cu13 +86 -0
  3. LICENSE +15 -0
  4. NOTICE +6 -0
  5. README.md +19 -0
  6. build-and-validate-sd-cli.sh +158 -0
Dockerfile.sd-cli-cu12 ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Dockerfile.sd-cli-cu12 β€” arch-correct multi-arch sd-cli (CUDA 12.8 toolchain)
2
+ # ---------------------------------------------------------------------------
3
+ # WHY THIS EXISTS
4
+ # The prebuilt sd-cli currently shipped at /download/sd-cli-cu12 was compiled
5
+ # on CUDA 12.4 with NO CMAKE_CUDA_ARCHITECTURES, so it emits no sm_120 SASS
6
+ # and throws "no kernel image is available for execution on the device" on
7
+ # Blackwell (RTX 50-series, sm_120) cards. sd-cli powers EVERY sdcpp model
8
+ # (z-image, SD3.5, FLUX.2-klein, HiDream, WAN), so all of them are dead on
9
+ # Blackwell until this fat binary replaces it.
10
+ #
11
+ # WHAT CHANGED vs the golden recipe
12
+ # NOTHING except the architecture list. Same upstream repo, same pinned ref,
13
+ # same feature flags (-DSD_CUDA=ON -DSD_WEBM=ON -DSD_WEBP=ON). The ONLY added
14
+ # flag is -DCMAKE_CUDA_ARCHITECTURES, which makes this a strict SUPERSET of
15
+ # the current binary: it still runs on every card the old one did (Turing,
16
+ # Ampere, Ada, Hopper) AND adds Blackwell (sm_120) + a 120-virtual PTX tail
17
+ # for forward-compat JIT on future archs.
18
+ #
19
+ # ARCH LIST (CUDA 12.8 β€” broad coverage of older cards)
20
+ # 70-real Volta (V100)
21
+ # 75-real Turing (RTX 20xx, T4, GTX 16xx)
22
+ # 80-real Ampere (A100)
23
+ # 86-real Ampere (RTX 30xx, A10, A40)
24
+ # 89-real Ada (RTX 40xx, L4, L40)
25
+ # 90-real Hopper (H100, H200)
26
+ # 100-real Blackwell DC (B100/B200, GB100)
27
+ # 120-real Blackwell (RTX 50xx, GB202) <-- the whole point
28
+ # 120-virtual PTX tail for compute_120 (JIT forward-compat)
29
+ # The "-real" suffix bakes SASS cubins; "-virtual" bakes PTX. CUDA 12.8 is the
30
+ # first toolkit that supports sm_100 + sm_120, so 12.8.x is the FLOOR for this
31
+ # image β€” do not downgrade the base.
32
+ #
33
+ # VERIFY THE LIST: the build prints `nvcc --list-gpu-arch` below. If cmake errors
34
+ # with "unsupported gpu architecture", reconcile CUDA_ARCHS against that printout
35
+ # (a listed-but-unsupported arch fails the build β€” that is the guard, by design).
36
+ #
37
+ # This image is NOT shipped. The operator builds it, extracts /out/sd-cli, and
38
+ # (after Blackwell validation + Ada/Ampere regression) scp's the binary to the
39
+ # VPS. See docs/build/build-and-validate-sd-cli.sh.
40
+ # ---------------------------------------------------------------------------
41
+
42
+ # CUDA 12.8 devel (toolchain + headers). 22.04 base β†’ glibc 2.35 floor, which
43
+ # keeps the extracted binary portable across the varied provider boxes that pull
44
+ # it. Bump the patch tag (12.8.x) only to another tag that exists on Docker Hub.
45
+ # Tag VERIFIED present on Docker Hub 2026-06-11 (nvidia/cuda registry).
46
+ FROM nvidia/cuda:12.8.1-devel-ubuntu22.04
47
+
48
+ ENV DEBIAN_FRONTEND=noninteractive
49
+
50
+ RUN apt-get update && apt-get install -y --no-install-recommends \
51
+ git cmake build-essential binutils ca-certificates \
52
+ && rm -rf /var/lib/apt/lists/*
53
+
54
+ # --- Identical upstream source to the golden recipe ------------------------
55
+ # Repo + ref are LOCKED to what docs/golden-provider-image.md validated. These
56
+ # pin the feature set (--ref-image, --llm_vision, vid_gen, --diffusion-fa) that
57
+ # image-edit + video depend on. DO NOT change the repo or ref to "add arches" β€”
58
+ # arches are added purely via CMAKE_CUDA_ARCHITECTURES below.
59
+ ARG SDCPP_REPO=https://github.com/leejet/stable-diffusion.cpp
60
+ # Pinned to the leejet release TAG master-656-0e4ee04 (full SHA
61
+ # 0e4ee04488159b81d95a9ffcd983a077fd5dcb77, dated 2026-05-28). A named release
62
+ # tag is preferred over a bare 7-char short hash: immutable, unambiguous as the
63
+ # repo grows, and self-documenting. This is the SAME commit the golden recipe
64
+ # validated β€” all four required flags (--ref-image, --llm_vision, vid_gen,
65
+ # --diffusion-fa) are registered in examples/common/common.cpp at this ref, so
66
+ # the build carries them. See docs/golden-provider-image.md (SOURCE OF TRUTH).
67
+ ARG SDCPP_REF=master-656-0e4ee04
68
+
69
+ # Broadest set CUDA 12.8 supports, ALWAYS including 120-real + 120-virtual.
70
+ ARG CUDA_ARCHS="70-real;75-real;80-real;86-real;89-real;90-real;100-real;120-real;120-virtual"
71
+
72
+ WORKDIR /opt
73
+ RUN git clone "${SDCPP_REPO}" sdcpp \
74
+ && cd sdcpp \
75
+ && git checkout "${SDCPP_REF}" \
76
+ && git submodule update --init --recursive
77
+
78
+ WORKDIR /opt/sdcpp
79
+
80
+ # Print the toolkit's ground-truth arch list for operator verification. The
81
+ # build log will show this right before configure; cross-check CUDA_ARCHS here.
82
+ RUN echo "=== nvcc --list-gpu-arch (CUDA 12.8) ===" && nvcc --list-gpu-arch && \
83
+ echo "=== CMAKE_CUDA_ARCHITECTURES = ${CUDA_ARCHS} ==="
84
+
85
+ # IDENTICAL cmake flags to the golden recipe + the one functional add:
86
+ # -DCMAKE_CUDA_ARCHITECTURES. ggml (sd.cpp's CUDA backend) honors the standard
87
+ # CMAKE_CUDA_ARCHITECTURES var; if a future ggml bump ignores it, the fallback
88
+ # is -DGGML_CUDA_ARCHITECTURES with the same value.
89
+ RUN cmake -B build \
90
+ -DCMAKE_BUILD_TYPE=Release \
91
+ -DSD_CUDA=ON -DSD_WEBM=ON -DSD_WEBP=ON \
92
+ -DCMAKE_CUDA_ARCHITECTURES="${CUDA_ARCHS}" \
93
+ && cmake --build build --config Release --target sd-cli -j"$(nproc)"
94
+
95
+ # Park the binary at a known path for `docker create` + `docker cp` extraction.
96
+ RUN mkdir -p /out \
97
+ && cp "$(find build -name sd-cli -type f -perm -u+x | head -n1)" /out/sd-cli \
98
+ && chmod 755 /out/sd-cli \
99
+ && echo "sd-cli (cu12 fat binary) staged at /out/sd-cli"
100
+
101
+ # Flag sanity β€” GPU-FREE. Do NOT run the binary here. The docker BUILD sandbox has
102
+ # no GPU: libcuda is only present at `docker run --gpus`, so `/out/sd-cli --help`
103
+ # can fail to init the CUDA backend and error out BEFORE printing its flags β€” which
104
+ # would falsely trip "missing flags" on a perfectly good build. Instead, confirm the
105
+ # flag literals are baked into the binary's string table; `strings` needs no CUDA.
106
+ # The real runtime check (--help + a generation) runs WITH the GPU in
107
+ # build-and-validate-sd-cli.sh, the only place the binary can actually execute.
108
+ RUN strings /out/sd-cli | grep -E -- '--ref-image|--llm_vision|vid_gen|--diffusion-fa' \
109
+ || (echo "BUILD MISSING REQUIRED FLAG LITERALS β€” wrong ref?" && exit 1)
Dockerfile.sd-cli-cu13 ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Dockerfile.sd-cli-cu13 β€” arch-correct multi-arch sd-cli (CUDA 13 toolchain)
2
+ # ---------------------------------------------------------------------------
3
+ # Companion to Dockerfile.sd-cli-cu12. Same upstream repo + ref + feature flags;
4
+ # the ONLY difference between the two images is the CUDA toolkit and therefore
5
+ # the architecture list. See Dockerfile.sd-cli-cu12 for the full "why".
6
+ #
7
+ # WHY A SEPARATE CUDA 13 IMAGE
8
+ # setup.py picks the prebuilt by driver: `cu13` when the host CUDA major >= 13,
9
+ # else `cu12` (downloads/setup.py fetch_or_build_sdcli). A binary built against
10
+ # the CUDA 13 runtime needs the CUDA 13 toolchain. Blackwell boxes on a CUDA 13
11
+ # driver pull THIS one.
12
+ #
13
+ # CUDA 13 RAISED ITS ARCH FLOOR β€” the lists differ BY DESIGN.
14
+ # CUDA 13 dropped the older virtual/real arches (Maxwell sm_50/52/53, Pascal
15
+ # sm_60/61/62, and Volta sm_70). Its supported floor is Turing sm_75. So the
16
+ # cu13 list starts at 75-real (NOT 70-real like cu12) and runs up through 120:
17
+ # 75-real Turing (RTX 20xx, T4)
18
+ # 80-real Ampere (A100)
19
+ # 86-real Ampere (RTX 30xx, A10, A40)
20
+ # 89-real Ada (RTX 40xx, L4, L40)
21
+ # 90-real Hopper (H100, H200)
22
+ # 100-real Blackwell DC (B100/B200)
23
+ # 120-real Blackwell (RTX 50xx) <-- the whole point
24
+ # 120-virtual PTX tail for compute_120 (JIT forward-compat)
25
+ # Putting 70-real here would FAIL the build (sm_70 unsupported in CUDA 13) β€”
26
+ # that is the intended divergence, not an omission. Volta/Pascal/Maxwell users
27
+ # stay on the cu12 binary, which setup.py already routes them to.
28
+ #
29
+ # VERIFY: the build prints `nvcc --list-gpu-arch` (CUDA 13) below. If cmake errors
30
+ # on an unsupported arch, reconcile CUDA_ARCHS against that printout.
31
+ # ---------------------------------------------------------------------------
32
+
33
+ # CUDA 13 devel. Keep ubuntu22.04 (glibc 2.35) for binary portability, matching
34
+ # the cu12 image. VERIFIED 2026-06-11: nvidia/cuda:13.0.1-devel-ubuntu22.04 DOES
35
+ # exist on Docker Hub, so cu13 stays on 22.04 / glibc 2.35 β€” NO elevated glibc
36
+ # floor vs cu12. (13.0.1-devel-ubuntu24.04 also exists; only fall back to it if a
37
+ # future 13.x drops the 22.04 variant β€” that would raise the binary's floor to
38
+ # glibc 2.39 on provider boxes, so note it on swap if you ever do.)
39
+ FROM nvidia/cuda:13.0.1-devel-ubuntu22.04
40
+
41
+ ENV DEBIAN_FRONTEND=noninteractive
42
+
43
+ RUN apt-get update && apt-get install -y --no-install-recommends \
44
+ git cmake build-essential binutils ca-certificates \
45
+ && rm -rf /var/lib/apt/lists/*
46
+
47
+ # Same locked upstream as the golden recipe and the cu12 image. Pinned to the
48
+ # leejet release TAG master-656-0e4ee04 (full SHA
49
+ # 0e4ee04488159b81d95a9ffcd983a077fd5dcb77, dated 2026-05-28) β€” a named tag,
50
+ # not a bare short hash. All four required flags (--ref-image, --llm_vision,
51
+ # vid_gen, --diffusion-fa) are present in examples/common/common.cpp at this ref.
52
+ ARG SDCPP_REPO=https://github.com/leejet/stable-diffusion.cpp
53
+ ARG SDCPP_REF=master-656-0e4ee04
54
+
55
+ # Broadest set CUDA 13 supports (floor = sm_75), ALWAYS including 120-real +
56
+ # 120-virtual. NOTE the absence of 70-real vs the cu12 list β€” intentional.
57
+ ARG CUDA_ARCHS="75-real;80-real;86-real;89-real;90-real;100-real;120-real;120-virtual"
58
+
59
+ WORKDIR /opt
60
+ RUN git clone "${SDCPP_REPO}" sdcpp \
61
+ && cd sdcpp \
62
+ && git checkout "${SDCPP_REF}" \
63
+ && git submodule update --init --recursive
64
+
65
+ WORKDIR /opt/sdcpp
66
+
67
+ RUN echo "=== nvcc --list-gpu-arch (CUDA 13) ===" && nvcc --list-gpu-arch && \
68
+ echo "=== CMAKE_CUDA_ARCHITECTURES = ${CUDA_ARCHS} ==="
69
+
70
+ RUN cmake -B build \
71
+ -DCMAKE_BUILD_TYPE=Release \
72
+ -DSD_CUDA=ON -DSD_WEBM=ON -DSD_WEBP=ON \
73
+ -DCMAKE_CUDA_ARCHITECTURES="${CUDA_ARCHS}" \
74
+ && cmake --build build --config Release --target sd-cli -j"$(nproc)"
75
+
76
+ RUN mkdir -p /out \
77
+ && cp "$(find build -name sd-cli -type f -perm -u+x | head -n1)" /out/sd-cli \
78
+ && chmod 755 /out/sd-cli \
79
+ && echo "sd-cli (cu13 fat binary) staged at /out/sd-cli"
80
+
81
+ # Flag sanity β€” GPU-FREE (see Dockerfile.sd-cli-cu12 for the full why). The build
82
+ # sandbox has no GPU, so running `/out/sd-cli --help` can error before printing and
83
+ # falsely report "missing flags". Check the binary's string table instead β€” no CUDA
84
+ # needed. The real runtime check runs WITH the GPU in build-and-validate-sd-cli.sh.
85
+ RUN strings /out/sd-cli | grep -E -- '--ref-image|--llm_vision|vid_gen|--diffusion-fa' \
86
+ || (echo "BUILD MISSING REQUIRED FLAG LITERALS β€” wrong ref?" && exit 1)
LICENSE ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License β€” build recipe Β© 2026 DEcntAI
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
15
+ OTHER LIABILITY ARISING FROM THE USE OF THE SOFTWARE.
NOTICE ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ Prebuilt sd-cli binaries (in Releases) are compiled from:
2
+ stable-diffusion.cpp - https://github.com/leejet/stable-diffusion.cpp (MIT)
3
+ ggml - https://github.com/ggml-org/ggml (MIT)
4
+ built at ref master-656-0e4ee04. Credit for the inference engine goes to
5
+ leejet and the ggml authors. This repo adds only a multi-arch build recipe
6
+ (CUDA 12/13, sm_70 through sm_120 incl. Blackwell).
README.md ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # sd-cli - multi-arch stable-diffusion.cpp builds (incl. Blackwell)
2
+
3
+ Prebuilt `sd-cli` binaries from leejet/stable-diffusion.cpp @ `master-656-0e4ee04`,
4
+ plus the build recipe. Two CUDA variants, both carrying `sm_120` (Blackwell):
5
+
6
+ | binary | toolkit | arches (real + PTX) | driver floor |
7
+ |---------------|---------|--------------------------------------|---------------|
8
+ | `sd-cli-cu12` | 12.8 | 70 75 80 86 89 90 100 120 (+120 PTX) | sm_70 (Volta) |
9
+ | `sd-cli-cu13` | 13.0 | 75 80 86 89 90 100 120 (+120 PTX) | sm_75 (Turing)|
10
+
11
+ Download from **Releases**. Dynamically linked against the CUDA runtime
12
+ (cudart/cublas/nccl) - same as upstream - so run on a box where those are on
13
+ the loader path (a PyTorch/CUDA image, or `pip install nvidia-cuda-runtime-cu12
14
+ nvidia-cublas-cu12 nvidia-nccl-cu12` + LD_LIBRARY_PATH). Build it yourself via
15
+ the included Dockerfiles + `build-and-validate-sd-cli.sh`.
16
+
17
+ ## License
18
+ Build recipe: MIT (see LICENSE). Binaries derive from stable-diffusion.cpp and
19
+ ggml, both MIT - see NOTICE.
build-and-validate-sd-cli.sh ADDED
@@ -0,0 +1,158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ # build-and-validate-sd-cli.sh
3
+ # ===========================================================================
4
+ # OPERATOR script. Run this ON A REAL BLACKWELL (RTX 50-series, sm_120) NODE
5
+ # that has Docker + the NVIDIA container toolkit. It:
6
+ # 1. Builds BOTH arch-correct sd-cli images (cu12 + cu13).
7
+ # 2. Extracts BOTH binaries to ./dist/ locally (no container left running).
8
+ # 3. Runs a REAL generation with the arch-matching binary against a small
9
+ # sdcpp model and greps the output for "no kernel image" / failure.
10
+ # (NOT `--help` β€” that never loads a CUDA kernel and would falsely pass.)
11
+ # 4. PRINTS (does NOT perform) the final scp to the VPS downloads/ dir, plus
12
+ # the Ada/Ampere regression-test reminder.
13
+ #
14
+ # This script never scp's, never touches the live /download/sd-cli-* binaries,
15
+ # and never runs on the VPS. It builds + validates only. The live swap is a
16
+ # deliberate, separate, manual step you perform AFTER the checks below pass.
17
+ #
18
+ # DISK NOTE: the CUDA *-devel base images are several GB each; both builds plus
19
+ # layers can exceed ~30 GB. Point Docker's data-root at a big volume first, e.g.
20
+ # sudo mkdir -p /mnt/big/docker
21
+ # echo '{"data-root":"/mnt/big/docker"}' | sudo tee /etc/docker/daemon.json
22
+ # sudo systemctl restart docker
23
+ # ===========================================================================
24
+ set -uo pipefail
25
+
26
+ HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
27
+ DIST="${HERE}/dist"
28
+ mkdir -p "${DIST}"
29
+
30
+ # --- Tunables (override via env) -------------------------------------------
31
+ # A small sdcpp model + a real generation command. sd-cli MUST actually load a
32
+ # CUDA kernel for this to prove sm_120 works, so point MODEL at a small checkpoint
33
+ # already on this box (e.g. an SD1.5 / z-image GGUF). Adjust GEN_ARGS to whatever
34
+ # minimal valid invocation your model needs.
35
+ MODEL="${MODEL:-/workspace/models/sd-v1-5.safetensors}"
36
+ GEN_PROMPT="${GEN_PROMPT:-a red apple on a table}"
37
+ GEN_OUT="${GEN_OUT:-${DIST}/_validate_out.png}"
38
+ # Keep it tiny + fast: small res, few steps. Override if your model needs more.
39
+ GEN_ARGS="${GEN_ARGS:---steps 4 -W 256 -H 256 --cfg-scale 1.0}"
40
+
41
+ VPS_USER="${VPS_USER:-youruser}"
42
+ VPS_HOST="${VPS_HOST:-your.server.example}"
43
+ VPS_DLDIR="${VPS_DLDIR:-/path/to/your/downloads}"
44
+
45
+ CU12_IMG="decntai/sd-cli-build:cu12"
46
+ CU13_IMG="decntai/sd-cli-build:cu13"
47
+
48
+ say() { printf '\n\033[1;36m== %s ==\033[0m\n' "$*"; }
49
+ warn() { printf '\033[1;33m%s\033[0m\n' "$*"; }
50
+ die() { printf '\033[1;31mFATAL: %s\033[0m\n' "$*" >&2; exit 1; }
51
+
52
+ command -v docker >/dev/null || die "docker not found"
53
+ command -v nvidia-smi >/dev/null || warn "nvidia-smi not found β€” is this a GPU box?"
54
+
55
+ # --- 1. Build both images --------------------------------------------------
56
+ say "Building cu12 image (${CU12_IMG})"
57
+ docker build -f "${HERE}/Dockerfile.sd-cli-cu12" -t "${CU12_IMG}" "${HERE}" \
58
+ || die "cu12 build failed (check the nvcc --list-gpu-arch printout vs CUDA_ARCHS)"
59
+
60
+ say "Building cu13 image (${CU13_IMG})"
61
+ docker build -f "${HERE}/Dockerfile.sd-cli-cu13" -t "${CU13_IMG}" "${HERE}" \
62
+ || die "cu13 build failed (check the nvcc --list-gpu-arch printout vs CUDA_ARCHS)"
63
+
64
+ # --- 2. Extract both binaries to ./dist ------------------------------------
65
+ extract() { # $1=image $2=dest
66
+ local cid
67
+ cid="$(docker create "$1")" || die "docker create $1 failed"
68
+ docker cp "${cid}:/out/sd-cli" "$2" || { docker rm -f "${cid}" >/dev/null; die "cp from $1 failed"; }
69
+ docker rm -f "${cid}" >/dev/null
70
+ chmod 755 "$2"
71
+ printf ' extracted %s (%s MB)\n' "$2" "$(( $(stat -c%s "$2") / 1024 / 1024 ))"
72
+ }
73
+ say "Extracting binaries to ${DIST}"
74
+ extract "${CU12_IMG}" "${DIST}/sd-cli-cu12"
75
+ extract "${CU13_IMG}" "${DIST}/sd-cli-cu13"
76
+
77
+ # --- 3. REAL generation with the arch-matching binary ----------------------
78
+ # Pick the binary by host CUDA major (mirrors setup.py's fetch logic).
79
+ CUDA_MAJOR="$(nvidia-smi --query-gpu=driver_version --format=csv,noheader 2>/dev/null | head -n1 | cut -d. -f1)"
80
+ # driver_version major != CUDA major; the reliable signal is `nvcc` if present,
81
+ # else fall back to the CUDA runtime reported by nvidia-smi.
82
+ if command -v nvcc >/dev/null; then
83
+ TK_MAJOR="$(nvcc --version | grep -oE 'release [0-9]+' | grep -oE '[0-9]+' | head -n1)"
84
+ else
85
+ TK_MAJOR="$(nvidia-smi | grep -oE 'CUDA Version: [0-9]+' | grep -oE '[0-9]+' | head -n1)"
86
+ fi
87
+ TK_MAJOR="${TK_MAJOR:-12}"
88
+ if [ "${TK_MAJOR}" -ge 13 ]; then
89
+ VAL_BIN="${DIST}/sd-cli-cu13"; VAL_ARCH="cu13"
90
+ else
91
+ VAL_BIN="${DIST}/sd-cli-cu12"; VAL_ARCH="cu12"
92
+ fi
93
+
94
+ # --- 3a. Runtime flag check (functional β€” moved OUT of the Dockerfiles) -------
95
+ # THIS is the right place to run the binary: this is a GPU box (libcuda present),
96
+ # unlike the docker BUILD sandbox where `--help` can fail to init CUDA and error
97
+ # before printing. The Dockerfiles only do a GPU-free `strings` smoke; here we
98
+ # assert all four required flags actually surface in --help on real hardware.
99
+ say "Runtime flag check: ${VAL_ARCH} --help must list all four required flags"
100
+ HELP_OUT="$("${VAL_BIN}" --help 2>&1 || true)"
101
+ for f in '--ref-image' '--llm_vision' 'vid_gen' '--diffusion-fa'; do
102
+ echo "${HELP_OUT}" | grep -qF -- "$f" \
103
+ || die "Required flag '$f' absent from ${VAL_ARCH} --help β€” wrong/old ref? Do NOT ship."
104
+ done
105
+ say "All four required flags present in ${VAL_ARCH} --help"
106
+
107
+ say "Validating ${VAL_ARCH} binary on THIS GPU with a real generation"
108
+ if [ ! -f "${MODEL}" ]; then
109
+ warn "MODEL not found at ${MODEL}."
110
+ warn "Set MODEL=/path/to/a/small/sdcpp/checkpoint and re-run. CANNOT validate"
111
+ warn "sm_120 without loading a real CUDA kernel β€” skipping gen, build NOT proven."
112
+ exit 2
113
+ fi
114
+
115
+ rm -f "${GEN_OUT}"
116
+ GEN_LOG="${DIST}/_validate_${VAL_ARCH}.log"
117
+ # shellcheck disable=SC2086
118
+ "${VAL_BIN}" -m "${MODEL}" -p "${GEN_PROMPT}" -o "${GEN_OUT}" ${GEN_ARGS} \
119
+ > "${GEN_LOG}" 2>&1
120
+ GEN_RC=$?
121
+
122
+ echo " exit=${GEN_RC} log=${GEN_LOG}"
123
+ if grep -qiE 'no kernel image|invalid device function|CUDA error|out of memory|failed' "${GEN_LOG}"; then
124
+ warn "---- offending log lines ----"
125
+ grep -niE 'no kernel image|invalid device function|CUDA error|out of memory|failed' "${GEN_LOG}" | sed 's/^/ /'
126
+ die "Generation reported a CUDA/kernel failure on sm_120 β€” the fat binary is NOT good. Do NOT ship."
127
+ fi
128
+ if [ "${GEN_RC}" -ne 0 ] || [ ! -s "${GEN_OUT}" ]; then
129
+ die "Generation exited ${GEN_RC} or produced no output (${GEN_OUT}). Do NOT ship."
130
+ fi
131
+ say "VALIDATION PASSED on Blackwell (${VAL_ARCH}) β€” real image written to ${GEN_OUT}"
132
+
133
+ # --- 4. Next steps: PRINT ONLY (no scp performed here) ---------------------
134
+ cat <<EOF
135
+
136
+ ============================================================================
137
+ NEXT STEPS β€” performed MANUALLY by you, NOT by this script
138
+ ============================================================================
139
+ 1) REGRESSION TEST FIRST. Before any live swap, run the SAME real generation
140
+ with the matching binary on an Ada (sm_89, e.g. RTX 4060) AND an Ampere
141
+ (sm_86, e.g. RTX 3060) box. The fat binary MUST still work there β€” it is a
142
+ strict superset, not a replacement. If either regresses, do NOT ship.
143
+
144
+ 2) Only after Blackwell PASS + Ada/Ampere regression PASS, copy the binaries
145
+ to the VPS (this script does NOT do this for you):
146
+
147
+ scp ${DIST}/sd-cli-cu12 ${VPS_USER}@${VPS_HOST}:${VPS_DLDIR}/sd-cli-cu12
148
+ scp ${DIST}/sd-cli-cu13 ${VPS_USER}@${VPS_HOST}:${VPS_DLDIR}/sd-cli-cu13
149
+ ssh ${VPS_USER}@${VPS_HOST} 'chmod 755 ${VPS_DLDIR}/sd-cli-cu12 ${VPS_DLDIR}/sd-cli-cu13'
150
+
151
+ 3) Confirm they serve:
152
+ curl -sI https://ai.decntai.com/download/sd-cli-cu12 # expect 200
153
+ curl -sI https://ai.decntai.com/download/sd-cli-cu13 # expect 200
154
+
155
+ New providers fetch these via setup.py fetch_or_build_sdcli (cu13 when host
156
+ CUDA major >= 13, else cu12). Existing providers re-run setup.py / re-fetch.
157
+ ============================================================================
158
+ EOF