mirror of
https://github.com/ollama/ollama.git
synced 2026-08-04 14:56:15 +00:00
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:
parent
33878e671a
commit
89a171cc70
3 changed files with 51 additions and 89 deletions
|
|
@ -501,26 +501,6 @@ if(OLLAMA_RUNNER_DIR)
|
|||
RUNTIME 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()
|
||||
else()
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ package llm
|
|||
import (
|
||||
"errors"
|
||||
"log/slog"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
|
|
@ -13,25 +14,12 @@ import (
|
|||
|
||||
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) {
|
||||
choice, err := windowsVulkanRuntimeDLLChoice(libDirs)
|
||||
systemDir, err := windows.GetSystemDirectory()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return choice.path, nil
|
||||
return windowsVulkanRuntimeDLLPath(systemDir, os.Getenv("PATH"), libDirs, fileExists)
|
||||
}
|
||||
|
||||
func adjustWindowsVulkanLibraryPaths(paths, gpuLibs []string) []string {
|
||||
|
|
@ -40,74 +28,68 @@ func adjustWindowsVulkanLibraryPaths(paths, gpuLibs []string) []string {
|
|||
return paths
|
||||
}
|
||||
|
||||
choice, err := windowsVulkanRuntimeDLLChoice(gpuLibs)
|
||||
vulkanPath, err := WindowsVulkanRuntimeDLLPath(gpuLibs)
|
||||
if err != nil {
|
||||
slog.Debug("windows Vulkan loader selection unavailable", "error", err)
|
||||
return paths
|
||||
}
|
||||
|
||||
slog.Debug("selected windows Vulkan loader",
|
||||
"loader_source", choice.source,
|
||||
"path", choice.path,
|
||||
"bundled", choice.bundledPath,
|
||||
"bundled_version", choice.bundledVer.String(),
|
||||
"system", choice.systemPath,
|
||||
"system_version", choice.systemVer.String(),
|
||||
)
|
||||
slog.Debug("selected windows Vulkan loader", "path", vulkanPath)
|
||||
|
||||
if choice.source != "system" || choice.systemDir == "" {
|
||||
return paths
|
||||
}
|
||||
|
||||
return insertPathBefore(paths, choice.systemDir, vulkanDir)
|
||||
return insertPathBefore(paths, filepath.Dir(vulkanPath), vulkanDir)
|
||||
}
|
||||
|
||||
// Prefer the system Vulkan loader when present, but keep a bundled loader as a
|
||||
// fallback for hosts without a Vulkan runtime. If both versions are available
|
||||
// and the bundled loader is newer, select the bundled copy.
|
||||
func windowsVulkanRuntimeDLLChoice(libDirs []string) (windowsVulkanRuntimeDLL, error) {
|
||||
systemDir, err := windows.GetSystemDirectory()
|
||||
if err != nil {
|
||||
return windowsVulkanRuntimeDLL{}, err
|
||||
}
|
||||
// Use the host Vulkan loader supplied by the installed Vulkan runtime or GPU
|
||||
// driver. Ollama no longer packages the loader; exclude backend library
|
||||
// directories from PATH probing so stale app-local copies from older installs
|
||||
// cannot shadow the host runtime.
|
||||
func windowsVulkanRuntimeDLLPath(
|
||||
systemDir string,
|
||||
pathEnv string,
|
||||
libDirs []string,
|
||||
exists func(string) bool,
|
||||
) (string, error) {
|
||||
systemDir = filepath.Clean(systemDir)
|
||||
|
||||
bundledPath := firstExistingFile(libDirs, windowsVulkanRuntimeDLLName)
|
||||
systemPath := filepath.Join(systemDir, windowsVulkanRuntimeDLLName)
|
||||
systemExists := fileExists(systemPath)
|
||||
|
||||
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)
|
||||
if exists(systemPath) {
|
||||
return systemPath, nil
|
||||
}
|
||||
|
||||
switch {
|
||||
case bundledPath != "" && systemExists:
|
||||
if choice.bundledVerOK && choice.systemVerOK && choice.bundledVer.Compare(choice.systemVer) > 0 {
|
||||
return choice, nil
|
||||
if path := firstWindowsVulkanRuntimeDLLOnPath(pathEnv, libDirs, exists); path != "" {
|
||||
return path, 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 {
|
||||
|
|
|
|||
|
|
@ -800,7 +800,7 @@ function newDependencyAuditJob($payloadDir, $label, $reportPath, $dependencyDirs
|
|||
"winhttp.dll", "winmm.dll", "ws2_32.dll"
|
||||
)
|
||||
$driverDlls = @(
|
||||
"nvcuda.dll", "nvml.dll"
|
||||
"nvcuda.dll", "nvml.dll", "vulkan-1.dll"
|
||||
)
|
||||
|
||||
$dependencyRoots = @()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue