v0.2.3
stable-diffusion-go v0.2.3 — pure-Go binding + prebuilt native libraries.
Built from leejet/stable-diffusion.cpp @ 19bdfe2 (upstream pin: master-685-19bdfe2).
go get github.com/Pendra-Cloud/stable-diffusion-go@v0.2.3 for the
binding; the lib archives attached here match this exact tag. Each archive
contains a self-contained libstable-diffusion (ggml statically linked,
hidden visibility — exports only the sd_* symbols pkg/sd/load.go registers).
CUDA archives require a matching host CUDA runtime; Vulkan archives require
a Vulkan loader/ICD on the host. The Windows archive carries the per-CPU/GPU
(avx2/avx512/avx/noavx/vulkan/cuda13) subdir tree the binding selects from.
Problem
On a Windows GPU host, image generation runs entirely on CPU even though a working GPU build is bundled. Confirmed live on a GCP NVIDIA L4 / Windows Server 2022 worker (Pendra v3.40.2): SDXL loaded with VRAM 0.00MB / RAM 4590MB, pegging the CPU for 5+ minutes with zero nvidia-smi activity.
Root cause
windowsLibCandidates builds the wrong candidate order:
if SD_VK_DEVICE == "true" { ...vulkan only if vulkaninfo detects a GPU... }
else if GetGPUName() == "NVIDIA" { candidates += "cuda13/..." } // ← our host
candidates += GetCpuAVX() // avx2 fallback- The Pendra Windows installer bundles no
cuda13SD build (onlyavx*/noavx+vulkan), so the NVIDIA branch dead-ends and falls through toavx2(CPU). - The working
vulkanbuild is gated behindSD_VK_DEVICE=trueandGetVulkanGPU(), which shells out tovulkaninfo— a Vulkan-SDK tool that GPU drivers don't install. So the GPU path is effectively unreachable by default.
Fix
Select the Vulkan build for any detected GPU when the Vulkan loader is present:
- Order candidates vendor-optimal (
cuda13/rocm) →vulkan→ CPU.Load()already opens the first candidate whose file exists and skips the rest, so listing an unbundled variant (e.g.cuda13) is free — the NVIDIA host now lands onvulkan. - Detect the loader via
vulkan-1.dllin%SystemRoot%\System32(installed by every vendor's Windows driver) instead of thevulkaninfoCLI. - Keep
SD_VK_DEVICE=trueas an explicit force override.
Verified
- End-to-end on hardware: routing the L4 to the bundled
vulkanbuild drove the GPU at 91–99% SM utilisation and finished generations in seconds (vs 5+ min on CPU). - Unit tests (no GPU / no native lib needed — detection injected via package vars): NVIDIA & AMD prefer Vulkan-before-CPU; no Vulkan loader ⇒ no Vulkan offered; no GPU ⇒ CPU-only;
SD_VK_DEVICE=trueforces Vulkan. go build ./...,go test ./..., andGOOS=windows/GOOS=darwincross-builds all pass.
Downstream
After this is tagged (e.g. v0.2.3), bump the dependency in Pendra-Cloud/pendra (packages/worker/go.mod) so the worker picks up GPU image generation on Windows.
What's Changed
- fix(windows): prefer the bundled Vulkan GPU build on a GPU host by @tomcrawf90 in #26
Full Changelog: v0.2.2...v0.2.3