Fix local inference on Windows: silent CPU fallback, dead CLI flags, and broken engine packaging - #313
Open
alnavone wants to merge 1 commit into
Open
Conversation
Four bugs in the sd.cpp local-inference path, found while setting the feature up on Windows with an RTX 3090. 1. Windows CUDA builds silently fell back to CPU. The cuda12 asset ships ggml-cuda.dll but not the CUDA runtime it links against; those DLLs are a separate asset in the same release. ggml skips the backend it cannot load and reports no error, so the app looked like it was working while leaving the GPU idle. Add ensureCudaRuntime() to fetch and stage them. 2. --sd-version and --flux no longer exist upstream. sd-cli aborts with "unknown argument" before doing any work, so every SDXL model in the catalog failed 100% of the time. The architecture is detected from the checkpoint now, so just stop passing them. 3. SDXL's sampler was spelled dpmpp2m; the accepted name is dpm++2m. This was masked by Anil-matcha#2, which failed argument parsing first. 4. stage-local-ai-binary.js copied an allowlist of filenames, which on Windows meant sd-cli.exe alone out of the ~24 files the runtime needs. Packaged builds shipped an engine that could not start at all (0xC0000135 STATUS_DLL_NOT_FOUND). Stage the whole source directory and keep REQUIRED_FILES as a validation gate instead of a copy manifest. Adds tests/stageLocalAiBinary.test.js covering the staging fix. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fix local inference on Windows: silent CPU fallback, dead CLI flags, and broken engine packaging
Four bugs in the sd.cpp local-inference path, found while setting the feature up on a Windows + RTX 3090 machine. Each is independently reproducible; the first three make local generation unusable or silently slow, the fourth ships a non-functional engine in packaged Windows builds.
Tested against
leejet/stable-diffusion.cppmaster-813-bfbef5bon Windows 11 x64, RTX 3090 (24 GB), no CUDA toolkit installed.1. Windows CUDA builds silently fall back to CPU
downloadBinary()fetchessd-master-*-bin-win-cuda12-x64.zip, which shipsggml-cuda.dllbut not the CUDA runtime it links against.cudart64_12.dll,cublas64_12.dll, andcublasLt64_12.dllare published as a separate asset (cudart-sd-bin-win-cu12-x64.zip) in the same release.Without them, ggml skips the CUDA backend and falls back to CPU. There is no error, no warning, and nothing in the UI to suggest anything is wrong — the app looks like it is working, just slowly.
Before, on a 24 GB RTX 3090:
GPU utilisation 0%, VRAM 19 MiB, 2259 s of CPU time, still unfinished after 7 minutes at 512x512 / 20 steps.
After:
Fix: new
ensureCudaRuntime()runs after the engine extracts. On Windows only, whenggml-cuda.dllis present but the runtime DLLs are not, it pulls thecudart-*asset from the same release, extracts it besidesd-cli.exe, and flattens any nested layout. No-op on macOS/Linux and on CPU/Vulkan/ROCm builds. It re-checks afterwards and warns rather than failing silently if the install comes up short.Anyone who already installed the engine is unaffected on upgrade — the check is idempotent and skips when the DLLs are present.
2.
--sd-versionand--fluxno longer existgenerate()passes--sd-version sdxlfor SDXL models and--sd-version sd2for SD2. Upstream removed those flags; the architecture is now detected from the checkpoint.--fluxis gone the same way.The result is not a degraded image —
sd-cliaborts before doing any work:This makes every SDXL model in the catalog fail 100% of the time on current sd.cpp builds.
Fix: dropped the branch. sd.cpp reports
Version: SDXLon its own from the same checkpoint.3. SDXL's sampler name is invalid
modelCatalog.jssetssampler: 'dpmpp2m'for SDXL Base. The accepted spelling isdpm++2m:Masked by bug #2 — argument parsing failed on
--sd-versionfirst — so it only surfaces once that is fixed.Fix:
dpmpp2m->dpm++2m.4. Packaged Windows builds bundle a dead engine
stage-local-ai-binary.jscopies an allowlist of filenames. On Windows that list is['sd-cli.exe'], plus an optional'sd-server'that never matches anything because the Windows binary issd-server.exe. Sonpm run electron:build:winbundles exactly one file out of the ~24 the runtime needs.Reproducing the old staging output —
sd-cli.exealone in a directory:The process cannot start at all. Not
--help, nothing.The allowlist is wrong in principle, not just in its entries: sd.cpp spreads its runtime across
stable-diffusion.dll, theggml*.dllfamily (including nine per-ISA CPU variants), codec DLLs, and the CUDA runtime — and that set varies by platform and build flavour. macOS and Linux were under-staged too, just less fatally, since they also shiplibggml*alongsidelibstable-diffusion.*.Fix: replaced the allowlist with a recursive
copyTree()that stages the whole source directory.REQUIRED_FILESis kept as a validation gate rather than a copy manifest, and gainsstable-diffusion.dllon Windows for symmetry with the darwin/linux entries. Removed the deadOPTIONAL_FILES.Verified against a real CUDA build: 24 files, 1147 MB staged, and the staged binary generates on
CUDA0standalone.Tests
New
tests/stageLocalAiBinary.test.js(4 tests,node:test, matching the existing suite): full-runtime staging with a realistic CUDA file set, rejection of a source directory missing the core shared library, unsupported-platform rejection, and nested-binresolution.17 pre-existing tests still pass.
End-to-end verification
Driving the app's own
local-ai:generateIPC handler against all three model families:Bugs #1 and #4 are Windows-specific. #2 and #3 affect SDXL on every platform.