Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions .github/actions/install-vulkan-sdk-windows/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: Install Vulkan SDK (Windows)
description: Install the pinned LunarG Vulkan SDK built for the target architecture and export VULKAN_SDK.
inputs:
arch:
description: Target architecture, x64 or arm64
required: true
runs:
using: composite
steps:
- name: Install Vulkan SDK
shell: pwsh
env:
SDK_ARCH: ${{ inputs.arch }}
run: |
$ver = "1.4.313.2"
# LunarG files the native ARM64 SDK under its "warm" platform. The x64
# SDK's vulkan-1.lib is x64-only, and lld-link (VS 2026 ClangCL) refuses
# it for ARM64. Digests come from https://vulkan.lunarg.com/sdk/files.json.
switch ($env:SDK_ARCH) {
"x64" {
$url = "https://sdk.lunarg.com/sdk/download/$ver/windows/vulkansdk-windows-X64-$ver.exe"
$sha = "34a921d951858274ca8e470e9d0a3b7624db41216b3908ccea9f73c8a1b7500e"
$machine = "x64"
}
"arm64" {
$url = "https://sdk.lunarg.com/sdk/download/$ver/warm/vulkansdk-windows-ARM64-$ver.exe"
$sha = "29c3e7b9ff9c9d38455708bed7e744f879c770c15f3fedae55c409817c375515"
$machine = "ARM64"
}
default { throw "Unsupported Vulkan SDK arch: $env:SDK_ARCH" }
}
$installer = Join-Path $env:RUNNER_TEMP "VulkanSDK-Installer.exe"
curl.exe -fsSL -o $installer $url
if ($LASTEXITCODE -ne 0) { throw "Vulkan SDK download failed: $url" }
$actual = (Get-FileHash $installer -Algorithm SHA256).Hash.ToLowerInvariant()
if ($actual -ne $sha) { throw "Vulkan SDK installer SHA-256 $actual does not match $sha" }
& $installer --accept-licenses --default-answer --confirm-command install
$sdk = "C:\VulkanSDK\$ver"
$lib = Join-Path $sdk "Lib\vulkan-1.lib"
if (-not (Test-Path $lib)) { throw "Missing $lib" }
# dumpbin comes from the job's MSVC developer environment.
$headers = (& dumpbin /headers $lib) -join "`n"
if ($headers -notmatch "\($machine\)") { throw "$lib is not a $machine import library" }
Add-Content $env:GITHUB_ENV "VULKAN_SDK=$sdk"
Add-Content $env:GITHUB_PATH "$sdk\Bin"
9 changes: 3 additions & 6 deletions .github/workflows/native_release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -827,12 +827,9 @@ jobs:
Add-Content $env:GITHUB_ENV "CMAKE_CXX_COMPILER_LAUNCHER="
- name: Install Vulkan SDK
if: ${{ matrix.needs_vulkan }}
run: |
$ver = "1.4.313.2"
curl.exe -o $env:RUNNER_TEMP/VulkanSDK-Installer.exe -L "https://sdk.lunarg.com/sdk/download/$ver/windows/vulkansdk-windows-X64-$ver.exe"
& "$env:RUNNER_TEMP\VulkanSDK-Installer.exe" --accept-licenses --default-answer --confirm-command install
Add-Content $env:GITHUB_ENV "VULKAN_SDK=C:\VulkanSDK\$ver"
Add-Content $env:GITHUB_PATH "C:\VulkanSDK\$ver\Bin"
uses: ./.github/actions/install-vulkan-sdk-windows
with:
arch: ${{ matrix.arch }}
- name: Build
run: python tools/build.py windows --arch ${{ matrix.arch }} --backend ${{ matrix.backend }}
- name: Validate Windows backend artifacts
Expand Down
42 changes: 41 additions & 1 deletion .github/workflows/validate_wrapper.yml
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,46 @@ jobs:
$env:PATH = "$wrapperDir;$upstreamDir;$env:PATH"
ctest --test-dir build/wa64 -C Release --timeout 120 --verbose --output-on-failure

windows-arm64-vulkan:
needs: changes
if: needs.changes.outputs.native == 'true'
runs-on: windows-11-vs2026-arm
timeout-minutes: 45
strategy:
fail-fast: false
matrix:
upstream: [pinned, v0.5.0]
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
submodules: recursive
- name: Setup ARM64 MSVC environment
uses: TheMrMilchmann/setup-msvc-dev@v4.1.0
with:
arch: arm64
- name: Select candidate upstream
if: matrix.upstream != 'pinned'
shell: bash
run: |
git -C third_party/llama.cpp fetch --depth=1 origin "$LLAMADART_V050_QUALIFICATION_SHA"
git -C third_party/llama.cpp checkout --detach "$LLAMADART_V050_QUALIFICATION_SHA"
test "$(git -C third_party/llama.cpp rev-parse HEAD)" = "$LLAMADART_V050_QUALIFICATION_SHA"
- name: Install the release Vulkan SDK
uses: ./.github/actions/install-vulkan-sdk-windows
with:
arch: arm64
- name: Build the release Windows ARM64 Vulkan lane
run: python tools/build.py windows --arch arm64 --backend vulkan
- name: Check the backend is ARM64 and imports the Vulkan loader
run: |
$dll = "bin/windows/arm64/ggml-vulkan.dll"
if (-not (Test-Path $dll)) { throw "Missing $dll" }
$headers = (& dumpbin /headers $dll) -join "`n"
if ($headers -notmatch "\(ARM64\)") { throw "$dll is not ARM64" }
$deps = (& dumpbin /dependents $dll) -join "`n"
if ($deps -notmatch "(?im)^\s*vulkan-1\.dll\s*$") { throw "$dll does not import vulkan-1.dll" }

linux-artifact-contract:
needs: changes
if: needs.changes.outputs.native == 'true'
Expand Down Expand Up @@ -380,7 +420,7 @@ jobs:

wrapper-validation:
if: always()
needs: [changes, android-arm64-isa, android-vulkan-shaders, kleidiai-dispatch-emulated, windows-arm64-kleidiai, linux-artifact-contract, wrapper-contract, msvc-mtmd-link-contract]
needs: [changes, android-arm64-isa, android-vulkan-shaders, kleidiai-dispatch-emulated, windows-arm64-kleidiai, windows-arm64-vulkan, linux-artifact-contract, wrapper-contract, msvc-mtmd-link-contract]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
Expand Down
4 changes: 4 additions & 0 deletions docs/platform_backend_strategy.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ The Android artifact check is `tools/validate_android_cpu_isa.py --help`.
VS 2022 installed, configure directly with
`cmake --preset windows-arm64-full -G "Visual Studio 17 2022"` in a fresh
build directory.
- Windows ARM64 Vulkan links LunarG's native ARM64 SDK (`warm` platform), whose
`vulkan-1.lib` is ARM64. The x64 SDK's import library is x64-only, which
VS 2026's ClangCL linker (`lld-link`) rejects. `.github/actions/install-vulkan-sdk-windows`
pins both installers by SHA-256 and checks the import library's machine type.
- Windows MSVC builds disable IPO/LTCG for `llama-common` and `mtmd` by default.
Current MSVC `link.exe` can access-violate when linking the large
`llama-common` utility DLL with `/LTCG`. CMake's automatic Windows export
Expand Down
2 changes: 1 addition & 1 deletion tests/test_ci_scope.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from verify_release_provenance import workflow_job

JOBS = ('android-arm64-isa', 'android-vulkan-shaders', 'kleidiai-dispatch-emulated',
'windows-arm64-kleidiai', 'linux-artifact-contract',
'windows-arm64-kleidiai', 'windows-arm64-vulkan', 'linux-artifact-contract',
'wrapper-contract', 'msvc-mtmd-link-contract')


Expand Down
31 changes: 31 additions & 0 deletions tests/test_windows_vulkan_sdk.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from __future__ import annotations

from pathlib import Path
import unittest

ROOT = Path(__file__).resolve().parents[1]


class WindowsVulkanSdkTest(unittest.TestCase):
def test_arm64_uses_native_arm64_sdk_and_checks_import_library(self) -> None:
action = (ROOT / ".github/actions/install-vulkan-sdk-windows/action.yml").read_text(encoding="utf-8")
self.assertIn("/warm/vulkansdk-windows-ARM64-$ver.exe", action)
self.assertIn("/windows/vulkansdk-windows-X64-$ver.exe", action)
self.assertIn("29c3e7b9ff9c9d38455708bed7e744f879c770c15f3fedae55c409817c375515", action)
self.assertIn("34a921d951858274ca8e470e9d0a3b7624db41216b3908ccea9f73c8a1b7500e", action)
self.assertIn("Get-FileHash $installer -Algorithm SHA256", action)
self.assertIn('dumpbin /headers $lib', action)

def test_release_and_validation_lanes_use_the_action(self) -> None:
release = (ROOT / ".github/workflows/native_release.yml").read_text(encoding="utf-8")
windows_job = release.split("\n build-windows:\n", 1)[1].split("\n smoke-release-contract:\n", 1)[0]
self.assertIn("uses: ./.github/actions/install-vulkan-sdk-windows\n with:\n arch: ${{ matrix.arch }}", windows_job)
self.assertNotIn("sdk.lunarg.com", release)
validate = (ROOT / ".github/workflows/validate_wrapper.yml").read_text(encoding="utf-8")
lane = validate.split("\n windows-arm64-vulkan:\n", 1)[1].split("\n linux-artifact-contract:\n", 1)[0]
self.assertIn("uses: ./.github/actions/install-vulkan-sdk-windows\n with:\n arch: arm64", lane)
self.assertIn("python tools/build.py windows --arch arm64 --backend vulkan", lane)


if __name__ == "__main__":
unittest.main()
2 changes: 1 addition & 1 deletion tools/ci_scope.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def validate_results(needs):
return False
expected = 'success' if selected == 'true' else 'skipped'
jobs = {'android-arm64-isa', 'android-vulkan-shaders', 'kleidiai-dispatch-emulated',
'windows-arm64-kleidiai', 'linux-artifact-contract',
'windows-arm64-kleidiai', 'windows-arm64-vulkan', 'linux-artifact-contract',
'wrapper-contract', 'msvc-mtmd-link-contract'}
return set(needs) == jobs | {'changes'} and all(
needs[job].get('result') == expected for job in jobs
Expand Down
Loading