llm: use host Vulkan loader on Windows (#16869)
Stop bundling the Vulkan loader and resolve the host runtime for Windows Vulkan discovery and backend dependency loading. Fixes #16677
This commit is contained in:
@@ -501,26 +501,6 @@ if(OLLAMA_RUNNER_DIR)
|
|||||||
RUNTIME DESTINATION "${_base_dest}/${OLLAMA_RUNNER_DIR}" COMPONENT llama-server
|
RUNTIME DESTINATION "${_base_dest}/${OLLAMA_RUNNER_DIR}" COMPONENT llama-server
|
||||||
LIBRARY DESTINATION "${_base_dest}/${OLLAMA_RUNNER_DIR}" COMPONENT llama-server
|
LIBRARY DESTINATION "${_base_dest}/${OLLAMA_RUNNER_DIR}" COMPONENT llama-server
|
||||||
)
|
)
|
||||||
if(WIN32)
|
|
||||||
# Bundle the system Vulkan loader, not an arbitrary SDK copy.
|
|
||||||
# The loader is supplied by the installed Vulkan runtime or
|
|
||||||
# GPU driver; using that copy avoids PATH-dependent SDK drift.
|
|
||||||
if(DEFINED ENV{SystemRoot})
|
|
||||||
file(TO_CMAKE_PATH "$ENV{SystemRoot}" _ollama_windows_root)
|
|
||||||
else()
|
|
||||||
set(_ollama_windows_root "C:/Windows")
|
|
||||||
endif()
|
|
||||||
find_file(_vulkan_loader_dll
|
|
||||||
NAMES vulkan-1.dll
|
|
||||||
HINTS "${_ollama_windows_root}/System32"
|
|
||||||
NO_DEFAULT_PATH)
|
|
||||||
if(NOT _vulkan_loader_dll)
|
|
||||||
message(FATAL_ERROR "Could not find vulkan-1.dll in the Windows Vulkan runtime. Install the Vulkan runtime from the GPU driver or VULKAN_SDK/Helpers/VulkanRT.exe.")
|
|
||||||
endif()
|
|
||||||
install(FILES "${_vulkan_loader_dll}"
|
|
||||||
DESTINATION "${_base_dest}/${OLLAMA_RUNNER_DIR}"
|
|
||||||
COMPONENT llama-server)
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
else()
|
else()
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ package llm
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -13,25 +14,12 @@ import (
|
|||||||
|
|
||||||
const windowsVulkanRuntimeDLLName = "vulkan-1.dll"
|
const windowsVulkanRuntimeDLLName = "vulkan-1.dll"
|
||||||
|
|
||||||
type windowsVulkanRuntimeDLL struct {
|
|
||||||
path string
|
|
||||||
source string
|
|
||||||
bundledPath string
|
|
||||||
bundledVer windowsFileVersion
|
|
||||||
bundledVerOK bool
|
|
||||||
systemPath string
|
|
||||||
systemVer windowsFileVersion
|
|
||||||
systemVerOK bool
|
|
||||||
systemDir string
|
|
||||||
bundledDir string
|
|
||||||
}
|
|
||||||
|
|
||||||
func WindowsVulkanRuntimeDLLPath(libDirs []string) (string, error) {
|
func WindowsVulkanRuntimeDLLPath(libDirs []string) (string, error) {
|
||||||
choice, err := windowsVulkanRuntimeDLLChoice(libDirs)
|
systemDir, err := windows.GetSystemDirectory()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return choice.path, nil
|
return windowsVulkanRuntimeDLLPath(systemDir, os.Getenv("PATH"), libDirs, fileExists)
|
||||||
}
|
}
|
||||||
|
|
||||||
func adjustWindowsVulkanLibraryPaths(paths, gpuLibs []string) []string {
|
func adjustWindowsVulkanLibraryPaths(paths, gpuLibs []string) []string {
|
||||||
@@ -40,74 +28,68 @@ func adjustWindowsVulkanLibraryPaths(paths, gpuLibs []string) []string {
|
|||||||
return paths
|
return paths
|
||||||
}
|
}
|
||||||
|
|
||||||
choice, err := windowsVulkanRuntimeDLLChoice(gpuLibs)
|
vulkanPath, err := WindowsVulkanRuntimeDLLPath(gpuLibs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.Debug("windows Vulkan loader selection unavailable", "error", err)
|
slog.Debug("windows Vulkan loader selection unavailable", "error", err)
|
||||||
return paths
|
return paths
|
||||||
}
|
}
|
||||||
|
|
||||||
slog.Debug("selected windows Vulkan loader",
|
slog.Debug("selected windows Vulkan loader", "path", vulkanPath)
|
||||||
"loader_source", choice.source,
|
|
||||||
"path", choice.path,
|
|
||||||
"bundled", choice.bundledPath,
|
|
||||||
"bundled_version", choice.bundledVer.String(),
|
|
||||||
"system", choice.systemPath,
|
|
||||||
"system_version", choice.systemVer.String(),
|
|
||||||
)
|
|
||||||
|
|
||||||
if choice.source != "system" || choice.systemDir == "" {
|
return insertPathBefore(paths, filepath.Dir(vulkanPath), vulkanDir)
|
||||||
return paths
|
|
||||||
}
|
|
||||||
|
|
||||||
return insertPathBefore(paths, choice.systemDir, vulkanDir)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prefer the system Vulkan loader when present, but keep a bundled loader as a
|
// Use the host Vulkan loader supplied by the installed Vulkan runtime or GPU
|
||||||
// fallback for hosts without a Vulkan runtime. If both versions are available
|
// driver. Ollama no longer packages the loader; exclude backend library
|
||||||
// and the bundled loader is newer, select the bundled copy.
|
// directories from PATH probing so stale app-local copies from older installs
|
||||||
func windowsVulkanRuntimeDLLChoice(libDirs []string) (windowsVulkanRuntimeDLL, error) {
|
// cannot shadow the host runtime.
|
||||||
systemDir, err := windows.GetSystemDirectory()
|
func windowsVulkanRuntimeDLLPath(
|
||||||
if err != nil {
|
systemDir string,
|
||||||
return windowsVulkanRuntimeDLL{}, err
|
pathEnv string,
|
||||||
}
|
libDirs []string,
|
||||||
|
exists func(string) bool,
|
||||||
|
) (string, error) {
|
||||||
systemDir = filepath.Clean(systemDir)
|
systemDir = filepath.Clean(systemDir)
|
||||||
|
|
||||||
bundledPath := firstExistingFile(libDirs, windowsVulkanRuntimeDLLName)
|
|
||||||
systemPath := filepath.Join(systemDir, windowsVulkanRuntimeDLLName)
|
systemPath := filepath.Join(systemDir, windowsVulkanRuntimeDLLName)
|
||||||
systemExists := fileExists(systemPath)
|
if exists(systemPath) {
|
||||||
|
return systemPath, nil
|
||||||
choice := windowsVulkanRuntimeDLL{
|
|
||||||
path: bundledPath,
|
|
||||||
source: "bundled",
|
|
||||||
bundledPath: bundledPath,
|
|
||||||
systemPath: systemPath,
|
|
||||||
systemDir: systemDir,
|
|
||||||
}
|
|
||||||
if bundledPath != "" {
|
|
||||||
choice.bundledDir = filepath.Dir(bundledPath)
|
|
||||||
choice.bundledVer, choice.bundledVerOK = readWindowsFileVersion(bundledPath)
|
|
||||||
}
|
|
||||||
if systemExists {
|
|
||||||
choice.systemVer, choice.systemVerOK = readWindowsFileVersion(systemPath)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
if path := firstWindowsVulkanRuntimeDLLOnPath(pathEnv, libDirs, exists); path != "" {
|
||||||
case bundledPath != "" && systemExists:
|
return path, nil
|
||||||
if choice.bundledVerOK && choice.systemVerOK && choice.bundledVer.Compare(choice.systemVer) > 0 {
|
}
|
||||||
return choice, nil
|
|
||||||
|
return "", errors.New("no host vulkan-1.dll runtime DLL found")
|
||||||
|
}
|
||||||
|
|
||||||
|
func firstWindowsVulkanRuntimeDLLOnPath(pathEnv string, excludedDirs []string, exists func(string) bool) string {
|
||||||
|
for _, dir := range filepath.SplitList(pathEnv) {
|
||||||
|
dir = strings.Trim(filepath.Clean(strings.Trim(dir, `"`)), `"`)
|
||||||
|
if dir == "." || dir == "" || windowsDirInList(dir, excludedDirs) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
path := filepath.Join(dir, windowsVulkanRuntimeDLLName)
|
||||||
|
if exists(path) {
|
||||||
|
return filepath.Clean(path)
|
||||||
}
|
}
|
||||||
choice.path = systemPath
|
|
||||||
choice.source = "system"
|
|
||||||
return choice, nil
|
|
||||||
case systemExists:
|
|
||||||
choice.path = systemPath
|
|
||||||
choice.source = "system"
|
|
||||||
return choice, nil
|
|
||||||
case bundledPath != "":
|
|
||||||
return choice, nil
|
|
||||||
default:
|
|
||||||
return windowsVulkanRuntimeDLL{}, errors.New("no vulkan-1.dll runtime DLL found")
|
|
||||||
}
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func windowsDirInList(dir string, dirs []string) bool {
|
||||||
|
dir = strings.ToLower(filepath.Clean(dir))
|
||||||
|
for _, candidate := range dirs {
|
||||||
|
candidate = strings.ToLower(filepath.Clean(candidate))
|
||||||
|
if candidate == "" || candidate == "." {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if dir == candidate || strings.HasPrefix(dir, candidate+string(filepath.Separator)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func firstWindowsVulkanLibDir(libDirs []string) string {
|
func firstWindowsVulkanLibDir(libDirs []string) string {
|
||||||
|
|||||||
@@ -800,7 +800,7 @@ function newDependencyAuditJob($payloadDir, $label, $reportPath, $dependencyDirs
|
|||||||
"winhttp.dll", "winmm.dll", "ws2_32.dll"
|
"winhttp.dll", "winmm.dll", "ws2_32.dll"
|
||||||
)
|
)
|
||||||
$driverDlls = @(
|
$driverDlls = @(
|
||||||
"nvcuda.dll", "nvml.dll"
|
"nvcuda.dll", "nvml.dll", "vulkan-1.dll"
|
||||||
)
|
)
|
||||||
|
|
||||||
$dependencyRoots = @()
|
$dependencyRoots = @()
|
||||||
|
|||||||
Reference in New Issue
Block a user