From d3fffdf04653edca94d6bdbebf4646e8e808f4ea Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Fri, 11 Sep 2026 21:59:56 +0800 Subject: [PATCH 1/2] docs: Vulkan cross-platform closure design for the mcpp/xlings ecosystem Design only -- nothing implemented. Written for review. Separates the three runtime layers (loader / ICD / layer) because the whole problem comes from conflating them: a missing loader kills the process before main (0xC0000135), a missing ICD merely enumerates zero devices. The goal is to make every failure the second kind. Records the inventory finding that makes this small: every payload already exists -- xim:vulkan-loader (linux + windows), xim:moltenvk (macosx), xim:mesa-lavapipe (linux + windows) -- and mcpp already deploys a dependency's *.dll beside the executable and already treats vulkan-1.dll as must-ship in pack. Only the mcpp-index wiring is missing. Also records what not to retry: the xpm..deps route produced three runs with no loader and no diagnostic, and that path is used by 2 windows packages in the whole index, neither of them tested on Windows. Co-authored-by: sunrisepeak --- ...11-vulkan-cross-platform-closure-design.md | 326 ++++++++++++++++++ 1 file changed, 326 insertions(+) create mode 100644 .agents/docs/2026-09-11-vulkan-cross-platform-closure-design.md diff --git a/.agents/docs/2026-09-11-vulkan-cross-platform-closure-design.md b/.agents/docs/2026-09-11-vulkan-cross-platform-closure-design.md new file mode 100644 index 00000000..7a3fa2a3 --- /dev/null +++ b/.agents/docs/2026-09-11-vulkan-cross-platform-closure-design.md @@ -0,0 +1,326 @@ +# Vulkan 跨平台闭环设计 —— mcpp / xlings 生态 + +日期:2026-09-11 · 状态:**设计待 review,未实施** +涉及:`mcpp-index`、`xim-pkgindex`、`mcpp`(仅诊断层需要其配合) + +--- + +## 1. 目标 + +两条,来自用户,按优先级: + +1. **开发者侧不报错。** 在 linux / macOS / windows 上开发 Vulkan 相关的库和应用, + `mcpp build` / `mcpp test` 不应出现构建或启动失败。若环境确实不具备条件, + 必须在**构建期**给出可操作的说明,而不是运行期崩溃。 +2. **分发能跑。** `mcpp pack` 产出的程序、以及经 xlings 分发的程序, + 在目标机器上能启动并正常工作。 + +注意这两条的差别:第 1 条要的是**诊断质量**,第 2 条要的是**产物完整性**。 +现状下两条都不满足,但原因不同。 + +--- + +## 2. 前提:Vulkan 运行期由三层组成 + +任何设计都必须先分清这三者,混为一谈是本文要避免的主要错误。 + +| 层 | 是什么 | 谁提供 | 可否随应用分发 | +|---|---|---|---| +| **Loader** | `vulkan-1.dll` / `libvulkan.so.1`。ABI 入口,做 trampoline 与分发 | Khronos,Apache-2.0 | **可以**,LunarG Runtime redistributable 即为此存在 | +| **ICD(驱动)** | 真正实现 Vulkan 的后端 | GPU 驱动厂商;或软件实现(lavapipe / SwiftShader / MoltenVK) | 厂商驱动**不可**;软件实现**可以** | +| **Layer** | validation、overlay(Steam/OBS/RTSS) | 各自安装 | 不涉及 | + +发现路径: + +- Windows:loader 从 `HKLM\SOFTWARE\Khronos\Vulkan\Drivers` 读 ICD 清单 +- Linux:loader 搜 `$XDG_DATA_DIRS/vulkan/icd.d` +- macOS:无原生 Vulkan,ICD 只能是 MoltenVK(Metal 之上的翻译层) + +**关键推论:loader 缺失和 ICD 缺失是两种完全不同的故障。** + +- 缺 loader → 进程在 `main` 之前死,Windows 弹系统级"丢失 vulkan-1.dll",退出码 `0xC0000135` +- 缺 ICD → 进程正常启动,`vkEnumerateInstanceVersion` 正常返回, + `vkEnumeratePhysicalDevices` 返回 0 个设备 + +第一种是"这软件坏了",第二种是"这台机器没有 Vulkan 驱动"。 +**本设计的核心,就是让所有故障落到第二种。** + +--- + +## 3. 现状:实测的缺口 + +### 3.1 mcpp-index 的声明 + +`compat.vulkan` 三个平台的 `mcpp..runtime` 都声明了需求: + +```lua +-- windows +runtime = { + -- vulkan-1.dll ships with the GPU driver, not with us. + dlopen_libs = { "vulkan-1.dll" }, + capabilities = { "vulkan.icd.driver" }, +}, +``` + +linux / macosx 同样声明 `capabilities = { "vulkan.icd.driver" }`。 + +### 3.2 供给方只有一个 + +| 能力 | linux | macOS | windows | +|---|---|---|---| +| `vulkan.icd.driver` | ✅ `compat.vulkan-runtime` | ❌ 无 | ❌ 无 | +| loader 本体 | 源码静态编入 | 源码静态编入 | ❌ **无**(只链接导入库) | + +**需求声明齐全,供给方缺两个平台。** 这是全部问题的根。 + +### 3.3 实测证据 + +`#387` 探针,run `34569282837`,三个 GitHub runner 镜像: + +``` +windows-2022 vulkan-1.dll absent MSVC 14.29/14.44 + huxerui-module PASS vulkan FAIL 0xC0000135 +windows-2025 vulkan-1.dll PRESENT MSVC +14.51 + huxerui-module FAIL vulkan PASS +windows-latest 同 windows-2025 +``` + +`0xC0000135` = `STATUS_DLL_NOT_FOUND`。`#392` 的全量矩阵在 windows 分片上独立复现。 + +macOS 未实测,但 `xim:moltenvk` 的描述符已写明: +"Without it a machine running macOS enumerates no Vulkan device at all, +and every macOS runner in this ecosystem is such a machine." + +### 3.4 已失败的尝试(不要重走) + +`#391` 第一版让 `compat.vulkan` 的 windows 块声明 +`deps = { "xim:vulkan-loader@>=1.4.313" }`。**三次运行,零效果,零诊断:** + +1. 冷存储 —— loader 装上了,其 `config()` 钩子失败(`subos.env`;已由 xim#819 修复) +2. 热存储 —— `compat.vulkan@1.4.357.0` 已安装,依赖闭包从不重新求值,loader 根本没装 +3. 删光三份 registry 缓存后再冷跑 —— 依然没装,且没有任何报错 + +根因线索:`xpm..deps` 的使用分布是 +**linux 20 个包 / macosx 4 个 / windows 2 个**, +而 windows 那两个(`riscv-virt-rt`、`std-freestanding`)**没有任何 workspace 成员在 Windows 上测**。 +即:**这是一条基本未被执行过的代码路径。** + +**结论:Windows 的运行期供给不要走 `xpm.deps`,走 `runtime` 契约。** + +--- + +## 4. 零件盘点 —— 需要的东西已经全部存在 + +这是本设计最重要的发现:**不需要新建任何 payload。** + +| 平台 | loader payload | ICD payload | +|---|---|---| +| linux | `xim:vulkan-loader` (1.4.313) | `xim:mesa-lavapipe` (26.2.0)、`xim:mesa` | +| macOS | compat.vulkan 源码编译 | **`xim:moltenvk` (1.4.2)** | +| windows | **`xim:vulkan-loader` (1.4.313)**(2026-09-11 新增) | **`xim:mesa-lavapipe` (26.2.0) 有 windows 分支** | + +`mesa-lavapipe` 的 windows 分支是完整实现:处理 `vulkan_lvp.dll`, +并把 ICD JSON 里的 `library_path` 改写成 Windows 路径(含对 `\U` 转义的处理)。 + +mcpp 侧的机制也齐了: + +- `plan.cppm` / `runtimeDeployFiles`:把依赖 `runtime.library_dirs` 下的每个 `*.dll` + **拷到所生成可执行文件旁边**(`bin/`)。过滤条件是 `.dll` 后缀而非平台判断, + 所以非 Windows 平台自动为空 +- `pack/binfmt.cppm` / `kPeSystem`:`vulkan-1.dll` **不在**系统 DLL 白名单里 + (`opengl32.dll`、`d3d11/12.dll`、`dxgi.dll` 在)。 + **所以 pack 已经会把它当作必须随包携带的库处理** +- `compat.glx-runtime` 有现成的未满足诊断文案: + `"... is published by no installed payload ... Add the ecosystem package that provides it"` + +**缺的只有 mcpp-index 里的接线。** + +--- + +## 5. 设计 + +### 5.1 三层职责 + +``` +L1 供给层 谁提供 loader / ICD → 新增 compat.* 包,依赖已有 xim payload +L2 部署层 怎么到 exe 旁边 / 进 pack → runtime.library_dirs(已有机制) +L3 诊断层 未满足时说人话 → capabilities 未供给时构建期报错 +``` + +### 5.2 能力命名 + +现有 `vulkan.icd.driver` 只描述了 ICD。**loader 需要一个独立的能力名**, +因为两者的故障形态和可分发性都不同: + +| 能力 | 含义 | 缺失后果 | +|---|---|---| +| `vulkan.loader` | 进程能找到 `vulkan-1.dll` / `libvulkan.so.1` | 启动即崩 | +| `vulkan.icd.driver` | 至少有一个可用 ICD | 设备数为 0 | + +### 5.3 关键决策:loader 总是供给,ICD 绝不默认供给 + +**loader —— 总是供给。** + +- 构建机 ≠ 运行机。构建期探测"宿主有没有 loader"是不成立的:产物会被拷走 +- "有时带有时不带" = 同源码在两台机器上产出不同二进制,支持成本极高 +- 代价:我们的 loader 是 1.4.313,若用户驱动带了更新版本, + exe 旁边的会赢(Windows DLL 搜索顺序 exe 目录优先)。 + loader 对 ICD 向后兼容、会正常读注册表找到显卡驱动, + 但**更新的 loader 级扩展**我们这份没有。这是所有 bundling 应用共同的代价,可接受 + +**ICD —— 绝不默认供给,显式 opt-in。** + +- 在 linux / windows 上,真正的 GPU 驱动应该赢。 + 默认塞一个软件光栅器(lavapipe)会**掩盖"驱动没装"**, + 并给出灾难性的性能,用户还不知道为什么 +- 因此 lavapipe 只作为 feature / 显式依赖提供,供 CI 和无头环境使用 + +**macOS 是唯一例外:MoltenVK 是必需依赖,不是 fallback。** +macOS 上没有别的 Vulkan 实现,不带 MoltenVK 就等于没有 Vulkan。 + +### 5.4 每平台接线 + +#### linux(基本已完成,只补 loader 能力名) + +``` +compat.vulkan (linux) + ├─ loader:源码静态编入(已有) → provides vulkan.loader + └─ capabilities: vulkan.icd.driver → compat.vulkan-runtime 提供(已有) +``` + +改动:`compat.vulkan` 的 linux `runtime` 增加 `provides = { "vulkan.loader" }`。 + +#### windows(主要工作量) + +**新增 `compat.vulkan-loader`(windows only):** + +```lua +xpm = { windows = { ["1.4.313"] = { ... } } } -- 或直接复用 xim payload +mcpp = { + windows = { + runtime = { + library_dirs = { "bin" }, -- mcpp 据此把 vulkan-1.dll 拷到 exe 旁 + provides = { "vulkan.loader" }, + }, + }, +} +``` + +`compat.vulkan` 的 windows `runtime` 增加 `capabilities = { "vulkan.loader" }`, +并把该包列为 windows 依赖。 + +**ICD 保持不供给。** 有显卡驱动的机器照常工作;无驱动的机器程序能启动、设备数为 0。 + +#### macOS + +**新增 `compat.moltenvk`(macosx only)**,依赖 `xim:moltenvk`, +`provides = { "vulkan.icd.driver" }`,并把 ICD JSON 放进 loader 能搜到的位置。 + +`compat.vulkan` 的 macosx 块把它列为依赖。 + +**额外必须做的一件事**(否则装了也没用):MoltenVK 的清单声明 +`"is_portability_driver": true`,loader **不会**把 portability driver 交给 +`vkEnumeratePhysicalDevices`,除非实例启用了 +`VK_KHR_portability_enumeration` 并设置 +`VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR`。 +这是**消费方 API 层的事**,包做不了。 +→ `compat.vulkan` 的 macosx 路径必须在文档和构建期提示里写明这一点。 + +#### CI(与上述正交,已落地) + +`mcpp-index` 的 windows 腿钉在 `windows-2022`(为绕开 MSVC STL 14.51 的 +`_Find_vectorized` bug,见 mcpp#609 / microsoft/STL#6294),该镜像没有 loader。 +`#391` 在 CI 里直接供给 loader —— 这是业界 CI 的通行做法, +与 L1/L2 的包级方案互不冲突,且先落地。 + +--- + +## 6. 改动清单 + +| # | 位置 | 改动 | 规模 | +|---|---|---|---| +| 1 | `mcpp-index/pkgs/c/compat.vulkan-loader.lua` | **新增**,windows only,依赖 `xim:vulkan-loader` | 中 | +| 2 | `mcpp-index/pkgs/c/compat.moltenvk.lua` | **新增**,macosx only,依赖 `xim:moltenvk` | 中 | +| 3 | `mcpp-index/pkgs/c/compat.vulkan.lua` | 三个平台的 `runtime` 补 `provides`/`capabilities`;windows/macosx 加依赖 | 小 | +| 4 | `tests/examples/vulkan/` | 增加"无 ICD 时设备数为 0 属正常"的断言;macOS 启用 portability | 小 | +| 5 | `mcpp-index/pkgs/c/compat.mesa-lavapipe.lua` | **新增**(可选),软件 ICD,显式 opt-in,供 CI | 中 | +| 6 | mcpp 诊断 | 能力未供给时的构建期报错文案 | 需 mcpp 配合 | + +第 6 项若 mcpp 暂不支持,退化为包 `install()` 里的 `log.warn`,不阻塞前五项。 + +--- + +## 7. 分发路径的闭环 + +### `mcpp pack` + +`vulkan-1.dll` 不在 `kPeSystem` 白名单 → pack 视其为必带库。 +接线完成后,它来自**我们供给的受控版本**, +而不是"开发者机器上显卡驱动装的那一份"(当前行为,版本不受控)。 + +**待验证**:pack 是否从 `runtimeDeployFiles` 的产物目录取, +还是从系统路径解析导入表。这是本设计唯一未经实测的环节。 + +### xlings 分发 + +xlings 侧 payload 已具备(`xim:vulkan-loader` / `xim:moltenvk` / `xim:mesa-lavapipe`), +`selfcontain.seal`(ELF RPATH)在 linux 上已闭环; +Windows 无 RPATH,靠 exe 同目录,与上述 L2 一致。 + +--- + +## 8. 明确不做的事 + +| 不做 | 理由 | +|---|---| +| 默认塞软件 ICD | 掩盖"驱动没装",性能灾难且不可见 | +| 往 System32 写 DLL | 系统级副作用。仅 CI runner(一次性环境)可接受 | +| 走 `xpm..deps` 实现 Windows 供给 | 三次实测无效、无诊断;该路径在本索引里基本未被执行过 | +| 改 `compat.vulkan` 为动态加载(volk 风格) | 是正确方向,但属于**接口变更**,影响所有消费方,应单独立项。见 §10 | +| 给 compat.vulkan 升版本号以强制重装 | 成员是精确 pin,会级联到 `khronos.vulkan-hpp`、`compat.eui-neo` 各自的版本 | + +--- + +## 9. 验证计划 + +每一步都要有可失败的断言,不接受"CI 绿了"作为证据。 + +1. **L1 供给** —— 无驱动的 Windows 环境里,`mcpp build` 后 + `bin/vulkan-1.dll` 存在,且 sha 与我们的 payload 一致(不是系统那份) +2. **L1 启动** —— 同环境运行测试二进制,**退出码不是 `0xC0000135`**; + `vkEnumerateInstanceVersion` 返回成功 +3. **L1 设备** —— 同环境 `vkEnumeratePhysicalDevices` 返回 0 且**不崩溃** +4. **macOS** —— 装 `compat.moltenvk` 后,启用 portability 的实例 + 枚举到 ≥1 个设备;不启用时枚举到 0(负向验证,证明门控真实) +5. **pack** —— `mcpp pack` 产出在一台**干净的**无驱动 Windows 上解包即跑 +6. **负向** —— 故意不装 `compat.vulkan-loader`, + 确认得到的是**构建期的可操作提示**,而不是运行期崩溃 + +第 6 条是第 1 条目标(开发者侧不报错)的真正验收标准。 + +--- + +## 10. 风险与未决 + +| 项 | 性质 | +|---|---| +| pack 的 DLL 来源未实测(§7) | **需先验证**,否则第 2 条目标不能宣称闭环 | +| 我们的 loader 版本可能旧于用户驱动带的 | 已知代价,所有 bundling 应用共担 | +| 同进程内两个 loader 实例 | 应用带一份、插件(如 Steam overlay)加载系统那份时会出现,行为未定义。业界已知问题,无通用解 | +| macOS portability 位需要消费方配合 | 包无法代劳,只能文档 + 提示 | +| `xpm.windows.deps` 为何静默失效,根因未查明 | 独立于本设计,但影响任何想在 Windows 上声明安装期依赖的包,**建议单独提 issue** | +| 动态加载(volk / `VULKAN_HPP_DISPATCH_LOADER_DYNAMIC`) | 能把"缺 loader"从崩溃变成可读提示,是最彻底的解。属接口变更,单独立项 | + +--- + +## 11. 与本设计相关的既有工作 + +| | | +|---|---| +| `openxlings/xim-pkgindex#818` | vulkan-loader 的 Windows payload(构建 + 发布 + LoadLibrary 自检) | +| `openxlings/xim-pkgindex#819` | 改用 `exports.runtime.libdirs` 声明 DLL 位置 | +| `mcpplibs/mcpp-index#391` | CI 侧供给 loader(本设计的 CI 正交部分) | +| `mcpplibs/mcpp-index#388` | 已关。四轮尝试用 runner 镜像绕开,不收敛 | +| `mcpp-community/mcpp#609` | MSVC STL 14.51 的 `_Find_vectorized`,windows-2022 钉子的起因 | +| `mcpp-community/mcpp#614` | `XLINGS_PROJECT_DIR` 在 Windows/POSIX 的不对称 | +| `microsoft/STL#6294` | 上游 | From c5850fc2d9d4a75ebcbb700a582845975351f1ce Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Fri, 11 Sep 2026 22:44:07 +0800 Subject: [PATCH 2/2] docs(vulkan): the cross-platform closure as implemented and measured Rewrites the design written for review earlier today into a record of what was done, what was measured, where it departs from the design, and why. The headline: a Windows machine with no GPU driver no longer dies before `main` (0xC0000135). compat.vulkan 1.4.357.3 ships the loader DLL and mcpp deploys it beside every consuming executable. Measured on `windows-2022` with no system loader for `mcpp build`, `mcpp test`, and `mcpp pack` followed by a run from a clean directory; transitive consumers (eui-neo's vulkan feature) included. Departures from the design, each with its reason in the doc: no new `compat.vulkan-loader` package (compat.openblas already had the exact shape); the `xpm..deps` route abandoned (three runs, no loader, no diagnostic); versions bumped rather than pins moved (warm stores record pins); khronos.vulkan-hpp split into a follow-up (a member gets one project index, and the two-index failure still reproduces on 2026.9.11.2 although mcpp#238 and xlings#374 are closed); no `vulkan.loader` capability (mcpp does not error on an unserved one); CI provisioning of the DLL dropped (it would pass whether or not the package works). macOS, measured on `macos-15`: without MoltenVK nothing crashes; with `libMoltenVK.dylib` and `vulkan/icd.d/MoltenVK_icd.json` beside the executable (relative library_path) a real device enumerates, and the layout survives copying bin/ elsewhere. What is missing is mcpp deploying those two files -- filed as mcpp-community/mcpp#615. `mcpp pack` also refuses Mach-O programs today, which is recorded as the mcpp limitation it is. Also records the two install hooks found deriving paths from the version (eui-neo, xim:vulkan-loader) and the stray gitcode asset from a misnamed upload. Co-authored-by: sunrisepeak --- ...11-vulkan-cross-platform-closure-design.md | 412 +++++++----------- 1 file changed, 167 insertions(+), 245 deletions(-) diff --git a/.agents/docs/2026-09-11-vulkan-cross-platform-closure-design.md b/.agents/docs/2026-09-11-vulkan-cross-platform-closure-design.md index 7a3fa2a3..319008d7 100644 --- a/.agents/docs/2026-09-11-vulkan-cross-platform-closure-design.md +++ b/.agents/docs/2026-09-11-vulkan-cross-platform-closure-design.md @@ -1,326 +1,248 @@ -# Vulkan 跨平台闭环设计 —— mcpp / xlings 生态 +# Vulkan 跨平台闭环 —— mcpp / xlings 生态 -日期:2026-09-11 · 状态:**设计待 review,未实施** -涉及:`mcpp-index`、`xim-pkgindex`、`mcpp`(仅诊断层需要其配合) +日期:2026-09-11 · 状态:**Windows / xlings / CI 已实施并实测;macOS 已实测,落地需要 mcpp 一项能力** +涉及:`mcpp-index`、`xim-pkgindex`、`xlings-res`、`mcpp`(仅 macOS 部署) ---- - -## 1. 目标 - -两条,来自用户,按优先级: - -1. **开发者侧不报错。** 在 linux / macOS / windows 上开发 Vulkan 相关的库和应用, - `mcpp build` / `mcpp test` 不应出现构建或启动失败。若环境确实不具备条件, - 必须在**构建期**给出可操作的说明,而不是运行期崩溃。 -2. **分发能跑。** `mcpp pack` 产出的程序、以及经 xlings 分发的程序, - 在目标机器上能启动并正常工作。 - -注意这两条的差别:第 1 条要的是**诊断质量**,第 2 条要的是**产物完整性**。 -现状下两条都不满足,但原因不同。 +本文最初是一份待 review 的设计。实施过程中有几处原方案被实测否定或被更简单的既有机制取代, +所以现在它记录的是**做了什么、测到了什么、和原设计哪里不同、为什么**。原设计中仍成立的部分保留。 --- -## 2. 前提:Vulkan 运行期由三层组成 - -任何设计都必须先分清这三者,混为一谈是本文要避免的主要错误。 +## 0. 结论 -| 层 | 是什么 | 谁提供 | 可否随应用分发 | +| | 开发者侧不报错 | `mcpp pack` 分发能跑 | xlings 分发能跑 | |---|---|---|---| -| **Loader** | `vulkan-1.dll` / `libvulkan.so.1`。ABI 入口,做 trampoline 与分发 | Khronos,Apache-2.0 | **可以**,LunarG Runtime redistributable 即为此存在 | -| **ICD(驱动)** | 真正实现 Vulkan 的后端 | GPU 驱动厂商;或软件实现(lavapipe / SwiftShader / MoltenVK) | 厂商驱动**不可**;软件实现**可以** | -| **Layer** | validation、overlay(Steam/OBS/RTSS) | 各自安装 | 不涉及 | +| **Windows,有显卡驱动** | ✅ | ✅ | ✅ | +| **Windows,无显卡驱动**(用户重点) | ✅ 实测 | ✅ 实测(干净目录) | ✅(分发 pack 产物即可;xim 包亦有 1.4.357) | +| **Linux** | ✅ 实测 | ✅(RPATH,既有) | ✅(既有) | +| **macOS,无 MoltenVK** | ✅ 实测:不崩溃,设备数 0 | ⚠️ `mcpp pack` 目前**拒绝打包 Mach-O 程序**(mcpp 自身限制,与 Vulkan 无关);分发构建目录可运行 | ✅ 不崩溃 | +| **macOS,要真实设备** | ⚠️ 需 mcpp#615 的部署能力;当下 `VK_DRIVER_FILES` 实测可用 | ⚠️ 同上,且依赖 pack 支持 Mach-O | ⚠️ 机制具备(xim:moltenvk + shim `envs` 设 `VK_DRIVER_FILES`),`VK_DRIVER_FILES` 路径实测可枚举设备,未经 xlings 端到端 | -发现路径: +"无驱动 Windows 上 `0xC0000135` 启动即崩"这一核心问题已消除,并在没有任何系统 loader 的 +`windows-2022` 上,对 `mcpp build`、`mcpp test`、`mcpp pack` 后在干净目录运行三种情形逐一实测。 -- Windows:loader 从 `HKLM\SOFTWARE\Khronos\Vulkan\Drivers` 读 ICD 清单 -- Linux:loader 搜 `$XDG_DATA_DIRS/vulkan/icd.d` -- macOS:无原生 Vulkan,ICD 只能是 MoltenVK(Metal 之上的翻译层) - -**关键推论:loader 缺失和 ICD 缺失是两种完全不同的故障。** +--- -- 缺 loader → 进程在 `main` 之前死,Windows 弹系统级"丢失 vulkan-1.dll",退出码 `0xC0000135` -- 缺 ICD → 进程正常启动,`vkEnumerateInstanceVersion` 正常返回, - `vkEnumeratePhysicalDevices` 返回 0 个设备 +## 1. 目标(不变) -第一种是"这软件坏了",第二种是"这台机器没有 Vulkan 驱动"。 -**本设计的核心,就是让所有故障落到第二种。** +1. **开发者侧不报错。** 三平台开发 Vulkan 库/应用,`mcpp build`/`mcpp test` 不应构建或启动失败。 +2. **分发能跑。** `mcpp pack` 产物、经 xlings 分发的程序,在目标机器上能启动。 --- -## 3. 现状:实测的缺口 +## 2. 前提:三层,以及两种不同的故障 -### 3.1 mcpp-index 的声明 +| 层 | 缺失后果 | 可否随程序分发 | +|---|---|---| +| **Loader**(`vulkan-1.dll` / 静态 loader) | 进程在 `main` 之前死(Windows `0xC0000135`) | 可以(Apache-2.0) | +| **ICD**(驱动) | 正常启动,`vkCreateInstance` 返回 `VK_ERROR_INCOMPATIBLE_DRIVER`,设备数 0 | 厂商驱动不可;MoltenVK / lavapipe 可以 | -`compat.vulkan` 三个平台的 `mcpp..runtime` 都声明了需求: +**设计目标:让所有故障都落在第二种。** 这一条贯穿实施,且已在 Windows 与 macOS 上实测成立。 -```lua --- windows -runtime = { - -- vulkan-1.dll ships with the GPU driver, not with us. - dlopen_libs = { "vulkan-1.dll" }, - capabilities = { "vulkan.icd.driver" }, -}, -``` +--- -linux / macosx 同样声明 `capabilities = { "vulkan.icd.driver" }`。 +## 3. 实施了什么 -### 3.2 供给方只有一个 +| PR | 内容 | 状态 | +|---|---|---| +| mcpp-index **#395** | `compat.vulkan` **1.4.357.3**:Windows 产物带 `bin/vulkan-1.dll` + `LICENSE.txt`;`mcpp.windows.runtime.library_dirs = {"bin"}`;`compat.eui-neo` **0.5.9.1**(vulkan feature 改 pin);成员 pin;`tests/examples/vulkan` 在 Windows 上断言 loader 就在 exe 同目录;修 eui-neo install hook | 见 PR | +| mcpp-index **#394** | PR 不再自动升级为全量 CI(仅 cron / 手动) | 已合 | +| mcpp-index **#392** | mysql-connector-cpp:stdlib 限制写明 + llvm 腿跳过 | 已合 | +| xim-pkgindex **#821** | `vulkan-loader` windows **1.4.357**、`latest` 指向它;install 目录由版本推导;声明平台版本分叉 | 已合 | +| xlings-res/vulkan-loader | release **1.4.357**:Windows loader,由 runner 构建并 LoadLibrary 自检 | 已发布 | +| xlings-res/vulkan-import | release **1.4.357.3**:扁平产物(见 §5.1) | 已发布 + CN 镜像 | +| mcpp-index #391 | CI 往 System32 放 DLL | **已关闭**:会掩盖真实修复 | +| mcpp-index #396 | 临时探针(Windows pack、macOS ICD 发现),runs 34610618549 / 34611138464 | 已关闭,结论见 §5 | +| mcpp-community/mcpp **#615** | macOS:让依赖把 `.dylib` 与子目录里的 ICD 清单部署到可执行文件旁(附实测) | 已提 | + +后续(依赖 #395 合入并发布索引):`khronos.vulkan-hpp` **1.4.357.1** 改 pin + `vulkan-hpp-module` 成员(§4.4)。 -| 能力 | linux | macOS | windows | -|---|---|---|---| -| `vulkan.icd.driver` | ✅ `compat.vulkan-runtime` | ❌ 无 | ❌ 无 | -| loader 本体 | 源码静态编入 | 源码静态编入 | ❌ **无**(只链接导入库) | +--- -**需求声明齐全,供给方缺两个平台。** 这是全部问题的根。 +## 4. 与原设计的偏差,以及原因 -### 3.3 实测证据 +### 4.1 没有新建 `compat.vulkan-loader` 包 —— 用 openblas 的既有形状 -`#387` 探针,run `34569282837`,三个 GitHub runner 镜像: +原设计打算新建一个 `compat.vulkan-loader`,经 `xim:vulkan-loader` 依赖取 payload。实施时发现 +**同一件事已经有被 CI 验证过的先例**:`compat.openblas`(mcpp #185 / v0.0.73,mcpp-index #55)—— +compat 描述符自己的 `xpm.windows` 直接指向一个扁平预编译包,`mcpp.windows.runtime.library_dirs = +{"bin"}` 让 mcpp 把 DLL 拷到可执行文件旁。 -``` -windows-2022 vulkan-1.dll absent MSVC 14.29/14.44 - huxerui-module PASS vulkan FAIL 0xC0000135 -windows-2025 vulkan-1.dll PRESENT MSVC +14.51 - huxerui-module FAIL vulkan PASS -windows-latest 同 windows-2025 -``` +于是 DLL 直接放进 `compat.vulkan` 自己的 Windows 产物。**每个已经依赖 compat.vulkan 的消费者自动获得它, +不需要任何人新增依赖边。** -`0xC0000135` = `STATUS_DLL_NOT_FOUND`。`#392` 的全量矩阵在 windows 分片上独立复现。 +### 4.2 放弃 `xpm..deps` 路线(原设计 §3.4 的判断被坐实) -macOS 未实测,但 `xim:moltenvk` 的描述符已写明: -"Without it a machine running macOS enumerates no Vulkan device at all, -and every macOS runner in this ecosystem is such a machine." +#391 首版在 `compat.vulkan` 的 windows 块声明 `deps = { "xim:vulkan-loader@>=1.4.313" }`,三次运行零效果、 +零诊断(冷存储 / 热存储 / 删光缓存后冷跑)。该路径在本索引中:**linux 20 个包使用,windows 2 个, +且那 2 个没有任何成员在 Windows 上测**。§4.1 的做法完全不经过它。 -### 3.4 已失败的尝试(不要重走) +### 4.3 必须升版本号,不能原地改 pin -`#391` 第一版让 `compat.vulkan` 的 windows 块声明 -`deps = { "xim:vulkan-loader@>=1.4.313" }`。**三次运行,零效果,零诊断:** +已安装的副本记录着它解析时的 pin。原地改 pin 到不了热存储——#391 第二次运行就是这样:热缓存保留 +`compat.vulkan@1.4.357.0`,闭包从不重新求值,loader 根本没装。与 compat.vulkan 1.4.357.1 的规则一致。 -1. 冷存储 —— loader 装上了,其 `config()` 钩子失败(`subos.env`;已由 xim#819 修复) -2. 热存储 —— `compat.vulkan@1.4.357.0` 已安装,依赖闭包从不重新求值,loader 根本没装 -3. 删光三份 registry 缓存后再冷跑 —— 依然没装,且没有任何报错 +`mcpp` 表是版本无关的,所以新增 `library_dirs = {"bin"}` 对旧版本也可见;旧版本产物没有 `bin/`, +mcpp 对不存在的运行期目录直接跳过(`plan.cppm`:`if (!is_directory) continue`),对它们无效果。 -根因线索:`xpm..deps` 的使用分布是 -**linux 20 个包 / macosx 4 个 / windows 2 个**, -而 windows 那两个(`riscv-virt-rt`、`std-freestanding`)**没有任何 workspace 成员在 Windows 上测**。 -即:**这是一条基本未被执行过的代码路径。** +### 4.4 `khronos.vulkan-hpp` 拆到后续 PR -**结论:Windows 的运行期供给不要走 `xpm.deps`,走 `runtime` 契约。** +`vulkan-hpp-module` 只把 `khronos` 命名空间重定向到本 checkout,`compat` 来自**已发布**索引, +而 1.4.357.3 在 #395 合入前并不存在: ---- +``` +xlings install_packages failed (exit 1) for 'compat.vulkan@1.4.357.3' +with 1 index repo configured [mcpplibs -> https://github.com/mcpplibs/mcpp-index.git] +``` -## 4. 零件盘点 —— 需要的东西已经全部存在 +尝试同时重定向 `compat`,被拒绝: -这是本设计最重要的发现:**不需要新建任何 payload。** +``` +≥2 project-level index repos is a known xlings resolution gap +(mcpp #238; root cause openxlings/xlings#374) +``` -| 平台 | loader payload | ICD payload | -|---|---|---| -| linux | `xim:vulkan-loader` (1.4.313) | `xim:mesa-lavapipe` (26.2.0)、`xim:mesa` | -| macOS | compat.vulkan 源码编译 | **`xim:moltenvk` (1.4.2)** | -| windows | **`xim:vulkan-loader` (1.4.313)**(2026-09-11 新增) | **`xim:mesa-lavapipe` (26.2.0) 有 windows 分支** | +**注意:mcpp#238 与 xlings#374 均已关闭(2026-07-18/19),但 mcpp 2026.9.11.2 自带的 xlings 上仍能复现。** +要么修复未进入 vendored xlings,要么有回归。这是一条独立的待查项(§6)。 -`mesa-lavapipe` 的 windows 分支是完整实现:处理 `vulkan_lvp.dll`, -并把 ICD JSON 里的 `library_path` 改写成 Windows 路径(含对 `\U` 转义的处理)。 +### 4.5 能力名(`vulkan.loader`)暂未引入 -mcpp 侧的机制也齐了: +原设计 §5.2 提议新增 `vulkan.loader` 能力。实施中确认 mcpp 对未满足的能力**不会**构建期报错 +(`vulkan.icd.driver` 在 macOS/Windows 上一直未被满足,构建照常成功),所以新增一个"需求" +既不能带来原设计 L3 想要的诊断,反而有误导性。loader 的供给改为由产物本身保证(§4.1)。 -- `plan.cppm` / `runtimeDeployFiles`:把依赖 `runtime.library_dirs` 下的每个 `*.dll` - **拷到所生成可执行文件旁边**(`bin/`)。过滤条件是 `.dll` 后缀而非平台判断, - 所以非 Windows 平台自动为空 -- `pack/binfmt.cppm` / `kPeSystem`:`vulkan-1.dll` **不在**系统 DLL 白名单里 - (`opengl32.dll`、`d3d11/12.dll`、`dxgi.dll` 在)。 - **所以 pack 已经会把它当作必须随包携带的库处理** -- `compat.glx-runtime` 有现成的未满足诊断文案: - `"... is published by no installed payload ... Add the ecosystem package that provides it"` +### 4.6 CI 往 System32 放 DLL 的方案被放弃 -**缺的只有 mcpp-index 里的接线。** +#391 第二版在 CI 里供给 loader。它能让 windows 腿变绿,**但无论包是否正确都会变绿**。 +`windows-2022` 恰好没有系统 loader,是验证"无 vulkan dll 的 Windows"的理想环境,不应被掩盖。 --- -## 5. 设计 - -### 5.1 三层职责 - -``` -L1 供给层 谁提供 loader / ICD → 新增 compat.* 包,依赖已有 xim payload -L2 部署层 怎么到 exe 旁边 / 进 pack → runtime.library_dirs(已有机制) -L3 诊断层 未满足时说人话 → capabilities 未供给时构建期报错 -``` - -### 5.2 能力命名 - -现有 `vulkan.icd.driver` 只描述了 ICD。**loader 需要一个独立的能力名**, -因为两者的故障形态和可分发性都不同: - -| 能力 | 含义 | 缺失后果 | -|---|---|---| -| `vulkan.loader` | 进程能找到 `vulkan-1.dll` / `libvulkan.so.1` | 启动即崩 | -| `vulkan.icd.driver` | 至少有一个可用 ICD | 设备数为 0 | +## 5. 实测 -### 5.3 关键决策:loader 总是供给,ICD 绝不默认供给 +### 5.1 产物与兼容性 -**loader —— 总是供给。** +`xlings-res/vulkan-import` **1.4.357.3**,sha256 `8118f1bd897e553baffabf484a14db980ce1f0a6cfdb5a6222c0a236ecdf12f5`: -- 构建机 ≠ 运行机。构建期探测"宿主有没有 loader"是不成立的:产物会被拷走 -- "有时带有时不带" = 同源码在两台机器上产出不同二进制,支持成本极高 -- 代价:我们的 loader 是 1.4.313,若用户驱动带了更新版本, - exe 旁边的会赢(Windows DLL 搜索顺序 exe 目录优先)。 - loader 对 ICD 向后兼容、会正常读注册表找到显卡驱动, - 但**更新的 loader 级扩展**我们这份没有。这是所有 bundling 应用共同的代价,可接受 - -**ICD —— 绝不默认供给,显式 opt-in。** +| 文件 | 来源 | +|---|---| +| `bin/vulkan-1.dll` | tag `vulkan-sdk-1.4.357.0`,xlings-res/vulkan-loader windows workflow(run 34608619850),构建时 LoadLibrary 并解析 `vkEnumerateInstanceVersion` / `vkCreateInstance` / `vkGetInstanceProcAddr` | +| `lib/vulkan-1.lib` | 与 1.4.357.1 产物**字节一致** | +| `vulkan-1.def` | 上游原样 | +| `LICENSE.txt` | Vulkan-Loader Apache-2.0 —— 分发二进制须附许可证 | -- 在 linux / windows 上,真正的 GPU 驱动应该赢。 - 默认塞一个软件光栅器(lavapipe)会**掩盖"驱动没装"**, - 并给出灾难性的性能,用户还不知道为什么 -- 因此 lavapipe 只作为 feature / 显式依赖提供,供 CI 和无头环境使用 +- 确定性打包(排序、固定 mtime、数值 owner、`gzip -n`),两次 sha 一致;GitHub 回读一致;gitcode 镜像字节一致 +- **导出表:DLL 导出与 `vulkan-1.def` 的 265 个名字完全一致,差集 0**(`llvm-readobj --coff-exports`)。 + 早先担心的"新导入库配旧 DLL → 找不到入口点"不存在;1.4.313 的 DLL 同样是这 265 个 +- PE:`IMAGE_FILE_MACHINE_AMD64`,自报版本 1.4.357 -**macOS 是唯一例外:MoltenVK 是必需依赖,不是 fallback。** -macOS 上没有别的 Vulkan 实现,不带 MoltenVK 就等于没有 Vulkan。 +### 5.2 mcpp 部署机制(本地,mcpp 2026.9.11.2) -### 5.4 每平台接线 +| 验证 | 结果 | +|---|---| +| 传递依赖 `app → mid → dep(bin/vulkan-1.dll)` | DLL 部署到 `app` 旁 ✅ | +| `mcpp test` 的测试二进制 | DLL 部署到测试可执行文件旁 ✅ | +| `pack.cppm` | PE 闭包"始终搜索产物自身目录";`vulkan-1.dll` 不在 `kPeSystem` 白名单(`opengl32`/`d3d12`/`dxgi` 在)| -#### linux(基本已完成,只补 loader 能力名) +### 5.3 Windows(探针 #396,`windows-2022`,**已确认无系统 loader**) ``` -compat.vulkan (linux) - ├─ loader:源码静态编入(已有) → provides vulkan.loader - └─ capabilities: vulkan.icd.driver → compat.vulkan-runtime 提供(已有) +no system vulkan-1.dll: confirmed +-- mcpp build, 原地运行 -- +PROBE: loader api 1.4.357 +PROBE: vulkan-1.dll = D:\a\_temp\vkprobe\target\x86_64-windows-msvc\...\bin\vulkan-1.dll +PROBE: portability_enumeration=1 vkCreateInstance=-9 +PROBE: devices=0 (no instance) +-- mcpp pack -- +archive: target/dist/vkprobe-0.1.0-x86_64-pc-windows-msvc.zip + 741376 vkprobe-0.1.0-x86_64-pc-windows-msvc/vulkan-1.dll +-- 解压到干净目录,PATH 只有 System32 -- +PROBE: loader api 1.4.357 +PROBE: vulkan-1.dll = D:\a\_temp\clean-run\vkprobe-0.1.0-x86_64-pc-windows-msvc\vulkan-1.dll +PROBE: devices=0 (no instance) ``` -改动:`compat.vulkan` 的 linux `runtime` 增加 `provides = { "vulkan.loader" }`。 - -#### windows(主要工作量) +`-9` = `VK_ERROR_INCOMPATIBLE_DRIVER`:无 ICD 的机器的正确状态,不是故障。 -**新增 `compat.vulkan-loader`(windows only):** +#395 自己的 CI(`windows-2022`,同一台无 loader 的镜像)上,两个被判定的成员: -```lua -xpm = { windows = { ["1.4.313"] = { ... } } } -- 或直接复用 xim payload -mcpp = { - windows = { - runtime = { - library_dirs = { "bin" }, -- mcpp 据此把 vulkan-1.dll 拷到 exe 旁 - provides = { "vulkan.loader" }, - }, - }, -} ``` +Downloading compat.vulkan v1.4.357.3 +compat.vulkan: loader deployed beside the executable (...\tests\examples\vulkan\target\x86_64-windows-msvc\...\bin\vulkan-1.dll) +compat.vulkan: ok (loader api 1.4.357, 4 loader extension(s), WSI trampolines linked) -`compat.vulkan` 的 windows `runtime` 增加 `capabilities = { "vulkan.loader" }`, -并把该包列为 windows 依赖。 - -**ICD 保持不供给。** 有显卡驱动的机器照常工作;无驱动的机器程序能启动、设备数为 0。 - -#### macOS - -**新增 `compat.moltenvk`(macosx only)**,依赖 `xim:moltenvk`, -`provides = { "vulkan.icd.driver" }`,并把 ICD JSON 放进 loader 能搜到的位置。 - -`compat.vulkan` 的 macosx 块把它列为依赖。 - -**额外必须做的一件事**(否则装了也没用):MoltenVK 的清单声明 -`"is_portability_driver": true`,loader **不会**把 portability driver 交给 -`vkEnumeratePhysicalDevices`,除非实例启用了 -`VK_KHR_portability_enumeration` 并设置 -`VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR`。 -这是**消费方 API 层的事**,包做不了。 -→ `compat.vulkan` 的 macosx 路径必须在文档和构建期提示里写明这一点。 +Downloading compat.eui-neo v0.5.9.1 +Downloading compat.vulkan v1.4.357.3 +compat.eui-neo[vulkan]: ok (backend=vulkan, loader api 1.4.357) +``` -#### CI(与上述正交,已落地) +第一条来自 `tests/examples/vulkan` 新增的断言:加载的 `vulkan-1.dll` 必须与 exe 同目录。第二条是经 +eui-neo 的 feature 传递依赖到 compat.vulkan 的路径。同一腿上 `vulkan-hpp-module` 仍失败,原因如 §4.4 +所预测:它从已发布索引解析到 compat.vulkan 1.4.357.0。 -`mcpp-index` 的 windows 腿钉在 `windows-2022`(为绕开 MSVC STL 14.51 的 -`_Find_vectorized` bug,见 mcpp#609 / microsoft/STL#6294),该镜像没有 loader。 -`#391` 在 CI 里直接供给 loader —— 这是业界 CI 的通行做法, -与 L1/L2 的包级方案互不冲突,且先落地。 +### 5.4 Linux(本地) ---- +`vulkan`(compat.vulkan 1.4.357.3,loader api 1.4.357)、`eui-neo-vulkan`(eui-neo 0.5.9.1 → compat.vulkan +1.4.357.3,`backend=vulkan, loader api 1.4.357`)均通过。 -## 6. 改动清单 +### 5.5 macOS(探针 #396,`macos-15` arm64) -| # | 位置 | 改动 | 规模 | -|---|---|---|---| -| 1 | `mcpp-index/pkgs/c/compat.vulkan-loader.lua` | **新增**,windows only,依赖 `xim:vulkan-loader` | 中 | -| 2 | `mcpp-index/pkgs/c/compat.moltenvk.lua` | **新增**,macosx only,依赖 `xim:moltenvk` | 中 | -| 3 | `mcpp-index/pkgs/c/compat.vulkan.lua` | 三个平台的 `runtime` 补 `provides`/`capabilities`;windows/macosx 加依赖 | 小 | -| 4 | `tests/examples/vulkan/` | 增加"无 ICD 时设备数为 0 属正常"的断言;macOS 启用 portability | 小 | -| 5 | `mcpp-index/pkgs/c/compat.mesa-lavapipe.lua` | **新增**(可选),软件 ICD,显式 opt-in,供 CI | 中 | -| 6 | mcpp 诊断 | 能力未供给时的构建期报错文案 | 需 mcpp 配合 | - -第 6 项若 mcpp 暂不支持,退化为包 `install()` 里的 `log.warn`,不阻塞前五项。 - ---- +CoreFoundation 对未打包可执行文件: -## 7. 分发路径的闭环 - -### `mcpp pack` - -`vulkan-1.dll` 不在 `kPeSystem` 白名单 → pack 视其为必带库。 -接线完成后,它来自**我们供给的受控版本**, -而不是"开发者机器上显卡驱动装的那一份"(当前行为,版本不受控)。 +``` +PROBE: bundle url = /Users/runner/work/_temp/cfprobe/bin +PROBE: resources dir = /Users/runner/work/_temp/cfprobe/bin ← 就是 exe 所在目录 +``` -**待验证**:pack 是否从 `runtimeDeployFiles` 的产物目录取, -还是从系统路径解析导入表。这是本设计唯一未经实测的环节。 +静态 loader(`APPLE_STATIC_LOADER`)在 `loader.c` 中把 `/vulkan/icd.d` 放在搜索路径最前。 -### xlings 分发 +| 场景 | 退出 | 结果 | +|---|---|---| +| A 无 MoltenVK | 0 | `vkCreateInstance=-9`,"Found no drivers!",设备 0 —— **不崩溃** | +| B `bin/libMoltenVK.dylib` + `bin/vulkan/icd.d/MoltenVK_icd.json`(`library_path: "../../libMoltenVK.dylib"`) | 0 | `vkCreateInstance=0`,**devices=1,Apple Paravirtual device** | +| B2 同上,绝对路径 | 0 | devices=1 | +| B3 **把整个 `bin/` 拷到别处**再运行 | 0 | 在新位置找到清单,**devices=1 —— 布局可随程序迁移** | +| C `VK_DRIVER_FILES`(xim:moltenvk 文档的方式) | 0 | devices=1 | -xlings 侧 payload 已具备(`xim:vulkan-loader` / `xim:moltenvk` / `xim:mesa-lavapipe`), -`selfcontain.seal`(ELF RPATH)在 linux 上已闭环; -Windows 无 RPATH,靠 exe 同目录,与上述 L2 一致。 +所有设备枚举都要求实例启用 `VK_KHR_portability_enumeration` 并设置 +`VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR`——这是消费方 API 层的事,包无法代劳。 --- -## 8. 明确不做的事 +## 6. 仍未闭环的部分 -| 不做 | 理由 | -|---|---| -| 默认塞软件 ICD | 掩盖"驱动没装",性能灾难且不可见 | -| 往 System32 写 DLL | 系统级副作用。仅 CI runner(一次性环境)可接受 | -| 走 `xpm..deps` 实现 Windows 供给 | 三次实测无效、无诊断;该路径在本索引里基本未被执行过 | -| 改 `compat.vulkan` 为动态加载(volk 风格) | 是正确方向,但属于**接口变更**,影响所有消费方,应单独立项。见 §10 | -| 给 compat.vulkan 升版本号以强制重装 | 成员是精确 pin,会级联到 `khronos.vulkan-hpp`、`compat.eui-neo` 各自的版本 | +| 项 | 性质 | 去向 | +|---|---|---| +| **macOS 部署 MoltenVK** | mcpp 目前只把 `*.dll` **平铺**拷进 `bin/`;macOS 需要 `.dylib` 与 `vulkan/icd.d/` **子目录**。§5.5 B3 证明该布局可行且可迁移,缺的只是部署能力 | **mcpp#615** | +| **`mcpp pack` 拒绝 Mach-O 程序** | "cannot package the Mach-O program … yet":闭包靠 `LD_TRACE_LOADED_OBJECTS` 解析,dyld 不认。与 Vulkan 无关,但决定了 macOS 上 pack 这条分发路径目前不存在 | mcpp 既有限制 | +| 双项目 indices 仍失败 | mcpp#238 / xlings#374 已关闭,2026.9.11.2 上仍复现 | 待查,可能是 vendored xlings 回归 | +| `APPLE_STATIC_LOADER` 为上游不支持的配置 | CMake 原话:"not supported or tested as part of the loader. Use it at your own risk" / "only exists at the request of Google for Chromium. No other project should use this!" | 风险记录;§5.5 实测未见问题 | +| exe 旁的 loader 优先于系统 loader | 用户驱动若带更新版本,用的仍是我们的 1.4.357;ICD 仍是用户的驱动,导出表稳定,但更新的 loader 级扩展不可用 | 已知代价,所有 bundling 应用共担 | +| 同进程双 loader | 应用带一份、注入的插件加载系统那份 | 业界已知问题,无通用解 | +| gitcode `xlings-res/vulkan-loader@1.4.357` 有一个误名资产 `loader357.zip` | 首次上传用错了文件名;gitcode 资产不能经 API 删除 | 需网页删除;描述符指向正确命名的资产 | --- -## 9. 验证计划 +## 7. 实施中发现并修复的 bug -每一步都要有可失败的断言,不接受"CI 绿了"作为证据。 - -1. **L1 供给** —— 无驱动的 Windows 环境里,`mcpp build` 后 - `bin/vulkan-1.dll` 存在,且 sha 与我们的 payload 一致(不是系统那份) -2. **L1 启动** —— 同环境运行测试二进制,**退出码不是 `0xC0000135`**; - `vkEnumerateInstanceVersion` 返回成功 -3. **L1 设备** —— 同环境 `vkEnumeratePhysicalDevices` 返回 0 且**不崩溃** -4. **macOS** —— 装 `compat.moltenvk` 后,启用 portability 的实例 - 枚举到 ≥1 个设备;不启用时枚举到 0(负向验证,证明门控真实) -5. **pack** —— `mcpp pack` 产出在一台**干净的**无驱动 Windows 上解包即跑 -6. **负向** —— 故意不装 `compat.vulkan-loader`, - 确认得到的是**构建期的可操作提示**,而不是运行期崩溃 - -第 6 条是第 1 条目标(开发者侧不报错)的真正验收标准。 - ---- - -## 10. 风险与未决 +| 位置 | 问题 | 修复 | +|---|---|---| +| `compat.eui-neo` install hook | 用包版本拼上游目录名:`0.5.9.1` 找 `EUI-NEO-0.5.9.1/`,而归档是 `EUI-NEO-0.5.9/`,报 "neither wrapped nor flat" | 查找前剥掉第四段(实测 `0.5.9.1→0.5.9`、`1.2.3.45→1.2.3`、`0.5.10`/`0.5.9-rc1` 不变) | +| `xim:vulkan-loader` install | 写死目录 `vulkan-loader-1.4.313`;加第二个版本就会移动空目录 | 由版本推导,缺失即报错 | +| 描述符注释 | `compat.vulkan` 头部与 windows `runtime` 仍写着"DLL 随显卡驱动来,不随我们" | 按 1.4.357.3 修正 | +| `tests/examples/vulkan` 注释 | "compat.vulkan has no windows entry" 早已不实 | 删除 | -| 项 | 性质 | -|---|---| -| pack 的 DLL 来源未实测(§7) | **需先验证**,否则第 2 条目标不能宣称闭环 | -| 我们的 loader 版本可能旧于用户驱动带的 | 已知代价,所有 bundling 应用共担 | -| 同进程内两个 loader 实例 | 应用带一份、插件(如 Steam overlay)加载系统那份时会出现,行为未定义。业界已知问题,无通用解 | -| macOS portability 位需要消费方配合 | 包无法代劳,只能文档 + 提示 | -| `xpm.windows.deps` 为何静默失效,根因未查明 | 独立于本设计,但影响任何想在 Windows 上声明安装期依赖的包,**建议单独提 issue** | -| 动态加载(volk / `VULKAN_HPP_DISPATCH_LOADER_DYNAMIC`) | 能把"缺 loader"从崩溃变成可读提示,是最彻底的解。属接口变更,单独立项 | +两处 hook bug 同属一类:**hook 从版本号推导路径,只在第二个版本共用同一个归档之前成立。** --- -## 11. 与本设计相关的既有工作 +## 8. 附:参考 | | | |---|---| -| `openxlings/xim-pkgindex#818` | vulkan-loader 的 Windows payload(构建 + 发布 + LoadLibrary 自检) | -| `openxlings/xim-pkgindex#819` | 改用 `exports.runtime.libdirs` 声明 DLL 位置 | -| `mcpplibs/mcpp-index#391` | CI 侧供给 loader(本设计的 CI 正交部分) | -| `mcpplibs/mcpp-index#388` | 已关。四轮尝试用 runner 镜像绕开,不收敛 | -| `mcpp-community/mcpp#609` | MSVC STL 14.51 的 `_Find_vectorized`,windows-2022 钉子的起因 | -| `mcpp-community/mcpp#614` | `XLINGS_PROJECT_DIR` 在 Windows/POSIX 的不对称 | -| `microsoft/STL#6294` | 上游 | +| mcpp `src/build/plan.cppm` | `runtimeDeployFiles`:依赖 `runtime.library_dirs` 下的 `*.dll` → `bin/` | +| mcpp `src/pack/pack.cppm` | PE 闭包搜索产物自身目录;`kPeSystem` 白名单 | +| mcpp `.agents/docs/2026-06-29-windows-runtime-dll-deployment-and-openblas.md` | 部署机制的原始设计 | +| Vulkan-Loader `loader/loader.c` | macOS 下 bundle Resources + `vulkan/icd.d` 搜索 | +| mcpp-community/mcpp#609 / microsoft/STL#6294 | windows-2022 钉子的起因 | +| mcpp-community/mcpp#614 | `XLINGS_PROJECT_DIR` 的 Windows/POSIX 不对称 |