Issues / #1155

#1155 [Windows / AMD] --vision cpu is still unreachable: hip_vision()'s WIN gate, find_vcvars()'s VS-18 range, and no encoder in the ready-made engine

open · @Hugua700 · 0 comentarios · En GitHub

Setup & installServer & APIAMD / HIPNVIDIA / CUDAModels & quantsWindowsLinux

Descripción

# [Windows / AMD] `--vision cpu` is still unreachable: the `hip_vision()` gate, `find_vcvars()`'s version range, and the ready-made engine installing no encoder

Follow-up to #881 (closed as completed). 0.1.40 fixed the two bugs reported there — the `package_windows.py` encoding
and the `call "None"` batch file — but the two blockers listed in [#881's follow-up comment](https://github.com/Niko1221/Strata/issues/881#issuecomment-6011543135)
were not answered, and they still stand on `main` (82f46a8, 0.1.40.1). `--vision cpu` on Windows + AMD cannot work
today, on a ready-made engine or a self-built one.

Everything below was read from `main`, not from memory of 0.1.39. The encoder itself is fine — it is a plain CPU
program with an MSVC branch, and it builds and runs on two Windows-AMD machines when the gate is opened by hand
(an RX 6800M / gfx1031 and a Strix Halo / gfx1151). What is missing is the plumbing.

## 1. `hip_vision()` refuses `--vision cpu` on Windows (setup.py:2212)

```python
if asked == "cpu" and WIN:
    warn("images on the CPU with an AMD card are Linux-only for now (the ready-made Windows AMD engine has no "
         "image encoder): images off")
    return "none"
```

There is nothing Linux-only about `tools/vision`: it is a standalone CMake project (`add_executable(strata-vision
strata_vision.cpp)`, linking llama.cpp's `mtmd` + `llama`), not a HIP/CUDA target; its `CMakeLists.txt` has an explicit
`if(STRATA_PORTABLE AND MSVC)` branch and `strata_vision.cpp` contains `#ifdef _WIN32`. The reason for the message is
the packaging gap in §4, not a capability gap.

## 2. `find_vcvars()` cannot see Visual Studio 2026 (setup.py:1122)

```python
p = out([str(vswhere), "-latest", "-products", "*", "-version", "[16.0,18.0)", "-requires",
         "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", "-property", "installationPath"]).strip()
```

The range exists because CUDA 13 accepts VS 2019/2022 only, and that reasoning is right for the CUDA path. It is
applied to every caller, though, including the CUDA-less CPU encoder build. On a machine whose only C++ tools are
VS 2026 (version 18) this returns `None`. Measured on the RX 6800M machine:

```
> vswhere -latest -products * -version "[16.0,18.0)" -requires ...VC.Tools.x86.x64 -property installationPath
                                   (empty)
> vswhere -latest -products * -requires ...VC.Tools.x86.x64 -property installationPath
C:\Program Files (x86)\Microsoft Visual Studio\18\BuildTools          # vcvars64.bat is there
```

Note that `tools/hip/build_windows.bat:55` already calls vswhere **without** the range and builds the whole HIP engine
with VS 2026 — so the packaging path works on VS 18 while setup cannot even find it.

The other half of this, reported from the Strix Halo machine: with a range that matches, vswhere's `-latest` can pick
an install that is present but broken (there, VS 2019 Build Tools without `mspdbcore.dll` → `C1356`), with no way to
point setup at the one that works. Until 0.1.40 that was a silent failure; now it is a clean `fail()`, which is an
improvement but still a dead end.

## 3. The ready-made Windows-AMD engine never installs an encoder (setup.py:4656)

```python
if eng is not None and not hip and json.loads((eng / "BUILD.json").read_text(encoding="utf-8")).get("source") != "local":
    ...
    if vision != "none" and not (eng / VEXE).exists():
        warn("the ready-made engine has no image encoder: compiling it")
        eng = None
    else:
        vision = prebuilt_vision(...)
```

The `not hip` in that condition means the whole vision block is skipped for Windows + AMD: the ready-made engine is
kept, `build_engine_hip()` is never reached, and no encoder is built or installed. This is the prediction in #881 §4 —
"the Windows-HIP prebuilt path never builds or installs an encoder at all — even if `hip_vision()` were changed to
allow `--vision cpu`" — still true after 0.1.40, and it is why the 0.1.40 fix in `build_vision_cpu()` (passing
`find_vcvars()`, which #881 asked for) is unreachable code on this platform.

It also means opening the gate in §1 alone would be a regression rather than a fix, because `vision` would stay `cpu`
and setup.py:4911-4917 writes the model config's `vision` block pointing at `engine/strata-vision.exe`:

```python
if vision != "none":
    cfg["vision"] = {"exe": str(eng / VEXE), ...}
```

— a path that nothing created. The server would then be configured for an encoder that is not there.

## 4. The ready-made zip carries no encoder (tools/hip/package_windows.py:36)

```python
PROGRAMS = ("strata.exe", "strata-device.exe")
```

So even a user who is willing to let setup compile the encoder gets nothing from the prebuilt path, and a user without
the C++ build tools has no route to images at all.

## What I did to confirm the encoder works (both machines, by hand)

1. Build it with MSVC + Ninja (VS 2026 Build Tools on the RX 6800M machine, VS 2026 Community on the Strix Halo one):

   ```
   call "<VS>\VC\Auxiliary\Build\vcvars64.bat"
   cmake -G Ninja -S tools/vision -B build-vision -DCMAKE_BUILD_TYPE=Release \
         -DLLAMA_DIR=third_party/llama.cpp -DSTRATA_VISION_CUDA=OFF -DSTRATA_PORTABLE=ON
   cmake --build build-vision --target strata-vision
   ```

2. Copy `strata-vision.exe` into `engine/`, record `"vision": "cpu"` + `vision_src` in `engine/BUILD.json`.

3. Remove the `if asked == "cpu" and WIN:` branch above, then run
   `START-HERE.bat --setup --yes --family qwen --model <m> --vision cpu --no-start`.

Result on both machines: setup reports `images: on (encoder on the CPU)`, `/health` reports `"images": true`, and a
test image is described correctly through `/v1/chat/completions` (5.6 s on gfx1151 for a 400x200 image; ~20 s
including CPU encoding for a 720x360 one on gfx1031).

Note `-DSTRATA_PORTABLE=ON` in that recipe: it gives the encoder the static MSVC runtime, like the engine in the
ready-made zip. `setup.py`'s `build_vision_cpu()` does not pass it.

## Suggested fix

| # | Where | Change |
|---|---|---|
| 1 | `setup.py` `hip_vision()` | drop the `and WIN` gate; `--vision cpu` means the CPU encoder on every platform |
| 2 | `setup.py` `find_vcvars()` | take the version range as a parameter (CUDA 13 asks for it, nothing else does), and honour a `STRATA_VCVARS` override for a broken or unusual install |
| 3 | `setup.py` `build_vision_cpu()` | when Windows has no usable MSVC, warn and leave images off instead of stopping the whole setup — the engine is already installed and works |
| 4 | `setup.py` `main()` | let the ready-made Windows-AMD engine install the CPU encoder beside itself (build the encoder only, never the HIP engine), or the encoder can never arrive for prebuilt users |
| 5 | `tools/hip/package_windows.py` + `build_windows.bat` | build the CPU encoder in the packaging run and put `strata-vision.exe` in the zip, so images work with no toolchain at all |

1-4 are enough for `--vision cpu` to work on Windows + AMD with the C++ build tools present; 5 additionally removes the
toolchain requirement. I have a branch with 1-4 written and a second commit for 5, and I am happy to open it as a PR if
that is wanted — and to test a build here (RX 6800M / gfx1031, Windows 11, Chinese locale, VS 2026 only) either way.

Machines: Windows 11, R9 5900HX + RX 6800M (gfx1031), 31 GB RAM, self-built 0.1.40 HIP engine — and nencinif's Strix
Halo (Ryzen AI Max+ 395 + Radeon 8060S / gfx1151) for §1 and §2.

En el sitio

Enlaces a install, modelos, releases.