From afe21c6bfe1d3f568e0a85d0a58b26adc02894d7 Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Fri, 11 Sep 2026 19:24:25 +0800 Subject: [PATCH 1/2] fix(compat.vulkan): declare the loader, so windows stops depending on the image MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This package ships `vulkan-1.lib` — symbol stubs, no code. The code is `vulkan-1.dll`, and that is not an OS component: it arrives with a GPU driver, with LunarG's Runtime redistributable, or bundled beside an application. A machine without a driver therefore has no loader at all, and a consumer linking the import library dies at process start with 0xC0000135, before `main`. Measured on this index's CI: `vulkan`, `eui-neo-vulkan` and `vulkan-hpp-module` fail that way on `windows-2022` and pass on images that happen to carry a driver. #388 spent four rounds looking for an image where that and everything else worked; each round broke a different consumer of the VS installation, which is why it is closed. Declaring the loader takes the image out of the question instead of chasing it. `xim:vulkan-loader` grew a windows payload for this (openxlings/xim-pkgindex#818). It is built on a runner, and the build loads the DLL and resolves vkEnumerateInstanceVersion, vkCreateInstance and vkGetInstanceProcAddr before publishing — an artifact that exists is not an artifact that works. It brings no ICD, and does not need to. The loader finds drivers through the registry, so a driverless machine enumerates no devices — which is exactly what this package's test already scopes itself to: "answered by the LOADER itself, before any ICD is involved, so it is meaningful on a CI runner with no GPU and no driver." --- pkgs/c/compat.vulkan.lua | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/pkgs/c/compat.vulkan.lua b/pkgs/c/compat.vulkan.lua index 5d16e34..ace5b25 100644 --- a/pkgs/c/compat.vulkan.lua +++ b/pkgs/c/compat.vulkan.lua @@ -159,6 +159,37 @@ package = { }, }, windows = { + -- THE LOADER ITSELF, because Windows does not come with one. + -- + -- This package ships `vulkan-1.lib`: symbol stubs, no code. The + -- code is `vulkan-1.dll`, and that is NOT an OS component -- it + -- arrives with a GPU driver, with LunarG's Runtime redistributable, + -- or bundled beside an application. So on a machine without a + -- driver there is no loader at all, and a consumer that links the + -- import library dies at process start with 0xC0000135 + -- (STATUS_DLL_NOT_FOUND), before `main`. + -- + -- Measured on this index's own CI: `vulkan`, `eui-neo-vulkan` and + -- `vulkan-hpp-module` fail exactly that way on a `windows-2022` + -- runner and pass on images that happen to carry a driver. Four + -- rounds of pinning images and MSVC toolsets went into looking for + -- a runner where that and everything else worked (#388, closed, + -- because each round broke a different consumer of the VS + -- installation). Declaring the loader takes the image out of the + -- question instead. + -- + -- `xim:vulkan-loader` grew a windows payload for this + -- (openxlings/xim-pkgindex#818): built on a runner, and the build + -- loads the DLL and resolves vkEnumerateInstanceVersion, + -- vkCreateInstance and vkGetInstanceProcAddr before publishing. + -- + -- It brings no ICD. The loader finds drivers through the registry, + -- so a driverless machine enumerates no devices -- which is what + -- this package's own test already asserts against, in its words: + -- "answered by the LOADER itself, before any ICD is involved, so + -- it is meaningful on a CI runner with no GPU and no driver". + deps = { "xim:vulkan-loader@>=1.4.313" }, + -- 1.4.357.1: the same loader source, pinned to the farm that -- answers for its own members (compat.vulkan-runtime 2026.09.10). -- From a3ff2b7c0145ecee45f75e5a52f10de04a532b30 Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Fri, 11 Sep 2026 21:20:09 +0800 Subject: [PATCH 2/2] fix(ci): provide the Vulkan loader on the windows leg, the way everyone else does `vulkan-1.dll` is not part of Windows. It arrives with a GPU driver, with LunarG's Vulkan Runtime redistributable, or bundled beside an application, so a runner with no driver has no loader and anything linking `vulkan-1.lib` dies at process start with 0xC0000135, before main. MEASURED across the three images (#387 probe, run 34569282837): windows-2022 vulkan-1.dll absent MSVC 14.29/14.44 huxerui PASS vulkan FAIL 0xC0000135 windows-2025 vulkan-1.dll PRESENT MSVC +14.51 huxerui FAIL (STL) vulkan PASS windows-latest same as windows-2025 Neither image satisfies both. This leg is pinned to `windows-2022` to dodge the MSVC STL 14.51 bug (mcpp-community/mcpp#609, microsoft/STL#6294), and windows-2022 is the image without the loader. THIS REPLACES THE PACKAGE-DEPENDENCY APPROACH, which did not work. The first version of this PR had `compat.vulkan`'s windows branch declare `xim:vulkan-loader@>=1.4.313`. Three runs: 1. cold store -- loader installed, its config() hook failed (`subos.env` PATH declaration; fixed by openxlings/xim-pkgindex#819, asymmetry filed as mcpp-community/mcpp#614) 2. warm store -- `compat.vulkan@1.4.357.0` already installed, so its dependency closure was never re-evaluated and the loader was not installed at all 3. cold store again, after deleting the three registry caches -- still no loader, and no error saying why The declaration sits in `xpm.windows` beside working precedents (`compat.cuda-runtime`, `compat.cudart`), and range versions have precedent too (`compat.openssl`, `compat.vulkan-runtime`), so the shape is not obviously wrong -- but three runs produced no loader and no diagnostic, and chasing it further is not worth it for a problem whose actual shape is "the runner is missing a redistributable". WHAT EVERYONE ELSE DOES, since this is a common Windows problem: * dynamic loading in the consumer -- volk, Vulkan-Hpp's VULKAN_HPP_DISPATCH_LOADER_DYNAMIC, glfwVulkanSupported(), SDL_Vulkan_LoadLibrary. The process starts and degrades gracefully instead of dying before main. This is the robust answer for applications. * rely on the GPU driver -- what most games do, and sound: a machine that can run Vulkan has a driver, and the driver brought the loader. * ship the loader -- Apache-2.0, which is what the LunarG Runtime redistributable is for. * on CI specifically -- install the Runtime/SDK, or register a software ICD (SwiftShader, lavapipe) when device-level coverage is wanted. These members assert loader-level calls only (`vkEnumerateInstanceVersion`, instance extension enumeration), deliberately: the loader advertises WSI extensions only when an ICD supports them, so asserting on those would be testing the runner's hardware. A loader with no ICD is exactly the right amount here. The payload is the one built for openxlings/xim-pkgindex#818 -- built on a runner from Khronos' source, and the build loads the DLL and resolves vkEnumerateInstanceVersion, vkCreateInstance and vkGetInstanceProcAddr before publishing. Hash-pinned here, and the step is idempotent: if the image ever grows the DLL, it leaves it alone. The xim-pkgindex loader package stays. It is a real ecosystem capability for a driverless Windows machine; it is simply not the layer that fixes a missing redistributable on a CI runner. Co-authored-by: sunrisepeak --- .github/workflows/validate.yml | 54 ++++++++++++++++++++++++++++++++++ pkgs/c/compat.vulkan.lua | 31 ------------------- 2 files changed, 54 insertions(+), 31 deletions(-) diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 4eaba2c..17769f3 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -1096,6 +1096,60 @@ jobs: libavfilter-dev libavdevice-dev libswscale-dev libswresample-dev dpkg -l | grep -E 'libav(util|codec)-dev|libswscale-dev' + # ── The Vulkan loader, which this leg's image does not carry ────── + # + # `vulkan-1.dll` IS NOT PART OF WINDOWS. It arrives with a GPU driver, + # with LunarG's Vulkan Runtime redistributable, or bundled beside an + # application -- so a runner with no driver has no loader, and anything + # linking `vulkan-1.lib` dies at process start with 0xC0000135 + # (STATUS_DLL_NOT_FOUND), before `main`. Measured across the three + # images (#387 probe, run 34569282837): + # + # windows-2022 vulkan-1.dll absent MSVC 14.29/14.44 + # huxerui PASS vulkan FAIL 0xC0000135 + # windows-2025 vulkan-1.dll PRESENT MSVC +14.51 + # huxerui FAIL (STL) vulkan PASS + # windows-latest same as windows-2025 + # + # Neither image satisfies both, and this leg is pinned to + # `windows-2022` to dodge the MSVC STL 14.51 bug + # (mcpp-community/mcpp#609, microsoft/STL#6294). So the loader is + # provided here, which is what the LunarG Runtime redistributable + # exists to do and what Vulkan CI conventionally does -- the + # alternatives in common use are a software ICD (SwiftShader, + # lavapipe) when device-level coverage is wanted, or dynamic loading + # in the consumer (volk, Vulkan-Hpp's dynamic dispatch) when graceful + # degradation is wanted. These members assert loader-level calls only, + # so a loader with no ICD is exactly the right amount. + # + # NOT declared as a package dependency instead. That was tried + # (#391, closed): `compat.vulkan`'s windows branch declaring + # `xim:vulkan-loader` installs the payload, but the DLL never reached + # the test executable, and the reason was not found. CI provisioning + # is the layer that matches the problem -- the runner is missing a + # redistributable, not the package graph. + # + # Idempotent and hash-pinned: if the image ever grows the DLL, this + # leaves it alone. + - name: Provide the Vulkan loader (windows leg only) + if: matrix.platform == 'windows' + shell: bash + run: | + set -euo pipefail + dest=/c/Windows/System32/vulkan-1.dll + if [ -f "$dest" ]; then + echo "vulkan-1.dll already on this image; leaving it alone" + exit 0 + fi + url=https://github.com/xlings-res/vulkan-loader/releases/download/1.4.313/vulkan-loader-1.4.313-windows-x86_64.zip + sha=7159d30530572403079e583ebab3c9834d1dd760473487d6476c8a2f34fffe22 + curl -L -fsS -o loader.zip "$url" + echo "$sha *loader.zip" | sha256sum -c - + powershell -NoProfile -Command "Expand-Archive -Force -Path 'loader.zip' -DestinationPath 'loader'" + cp loader/vulkan-loader-1.4.313/bin/vulkan-1.dll "$dest" + rm -rf loader.zip loader + ls -l "$dest" + # ── Select the toolchain for this leg ───────────────────────────── # No version pin: `llvm` resolves to whatever the toolchain family's # current release is for the PINNED MCPP_VERSION, which is the version diff --git a/pkgs/c/compat.vulkan.lua b/pkgs/c/compat.vulkan.lua index ace5b25..5d16e34 100644 --- a/pkgs/c/compat.vulkan.lua +++ b/pkgs/c/compat.vulkan.lua @@ -159,37 +159,6 @@ package = { }, }, windows = { - -- THE LOADER ITSELF, because Windows does not come with one. - -- - -- This package ships `vulkan-1.lib`: symbol stubs, no code. The - -- code is `vulkan-1.dll`, and that is NOT an OS component -- it - -- arrives with a GPU driver, with LunarG's Runtime redistributable, - -- or bundled beside an application. So on a machine without a - -- driver there is no loader at all, and a consumer that links the - -- import library dies at process start with 0xC0000135 - -- (STATUS_DLL_NOT_FOUND), before `main`. - -- - -- Measured on this index's own CI: `vulkan`, `eui-neo-vulkan` and - -- `vulkan-hpp-module` fail exactly that way on a `windows-2022` - -- runner and pass on images that happen to carry a driver. Four - -- rounds of pinning images and MSVC toolsets went into looking for - -- a runner where that and everything else worked (#388, closed, - -- because each round broke a different consumer of the VS - -- installation). Declaring the loader takes the image out of the - -- question instead. - -- - -- `xim:vulkan-loader` grew a windows payload for this - -- (openxlings/xim-pkgindex#818): built on a runner, and the build - -- loads the DLL and resolves vkEnumerateInstanceVersion, - -- vkCreateInstance and vkGetInstanceProcAddr before publishing. - -- - -- It brings no ICD. The loader finds drivers through the registry, - -- so a driverless machine enumerates no devices -- which is what - -- this package's own test already asserts against, in its words: - -- "answered by the LOADER itself, before any ICD is involved, so - -- it is meaningful on a CI runner with no GPU and no driver". - deps = { "xim:vulkan-loader@>=1.4.313" }, - -- 1.4.357.1: the same loader source, pinned to the farm that -- answers for its own members (compat.vulkan-runtime 2026.09.10). --