|
1 | 1 | #include <stddef.h> |
| 2 | +#include <map> |
2 | 3 | #include <vector> |
3 | 4 |
|
4 | 5 | #include <vulkan/vulkan.hpp> |
5 | 6 |
|
| 7 | +constexpr std::uint32_t VK_VENDOR_ID_AMD = 0x1002; |
| 8 | +constexpr std::uint32_t VK_VENDOR_ID_APPLE = 0x106b; |
| 9 | +constexpr std::uint32_t VK_VENDOR_ID_INTEL = 0x8086; |
| 10 | +constexpr std::uint32_t VK_VENDOR_ID_NVIDIA = 0x10de; |
| 11 | + |
6 | 12 | typedef void (*gpuInfoVulkanWarningLogCallback_t)(const char* message); |
7 | 13 |
|
8 | | -static bool enumerateVulkanDevices(size_t* total, size_t* used, size_t* unifiedMemorySize, bool addDeviceNames, std::vector<std::string> * deviceNames, gpuInfoVulkanWarningLogCallback_t warningLogCallback, bool * checkSupported) { |
| 14 | +static vk::Instance vulkanInstance() { |
9 | 15 | vk::ApplicationInfo appInfo("node-llama-cpp GPU info", 1, "llama.cpp", 1, VK_API_VERSION_1_2); |
10 | 16 | vk::InstanceCreateInfo createInfo(vk::InstanceCreateFlags(), &appInfo, {}, {}); |
11 | | - vk::Instance instance = vk::createInstance(createInfo); |
| 17 | + return vk::createInstance(createInfo); |
| 18 | +} |
12 | 19 |
|
| 20 | +static std::vector<vk::PhysicalDevice> dedupedDevices() { |
| 21 | + vk::Instance instance = vulkanInstance(); |
13 | 22 | auto physicalDevices = instance.enumeratePhysicalDevices(); |
| 23 | + std::vector<vk::PhysicalDevice> dedupedDevices; |
| 24 | + dedupedDevices.reserve(physicalDevices.size()); |
| 25 | + |
| 26 | + // adapted from `ggml_vk_instance_init` in `ggml-vulkan.cpp` |
| 27 | + for (const auto& device : physicalDevices) { |
| 28 | + vk::PhysicalDeviceProperties2 newProps; |
| 29 | + vk::PhysicalDeviceDriverProperties newDriver; |
| 30 | + vk::PhysicalDeviceIDProperties newId; |
| 31 | + newProps.pNext = &newDriver; |
| 32 | + newDriver.pNext = &newId; |
| 33 | + device.getProperties2(&newProps); |
| 34 | + |
| 35 | + auto oldDevice = std::find_if( |
| 36 | + dedupedDevices.begin(), |
| 37 | + dedupedDevices.end(), |
| 38 | + [&newId](const vk::PhysicalDevice& oldDevice) { |
| 39 | + vk::PhysicalDeviceProperties2 oldProps; |
| 40 | + vk::PhysicalDeviceDriverProperties oldDriver; |
| 41 | + vk::PhysicalDeviceIDProperties oldId; |
| 42 | + oldProps.pNext = &oldDriver; |
| 43 | + oldDriver.pNext = &oldId; |
| 44 | + oldDevice.getProperties2(&oldProps); |
| 45 | + |
| 46 | + bool equals = std::equal(std::begin(oldId.deviceUUID), std::end(oldId.deviceUUID), std::begin(newId.deviceUUID)); |
| 47 | + equals = equals || ( |
| 48 | + oldId.deviceLUIDValid && newId.deviceLUIDValid && |
| 49 | + std::equal(std::begin(oldId.deviceLUID), std::end(oldId.deviceLUID), std::begin(newId.deviceLUID)) |
| 50 | + ); |
| 51 | + |
| 52 | + return equals; |
| 53 | + } |
| 54 | + ); |
| 55 | + |
| 56 | + if (oldDevice == dedupedDevices.end()) { |
| 57 | + dedupedDevices.push_back(device); |
| 58 | + continue; |
| 59 | + } |
| 60 | + |
| 61 | + vk::PhysicalDeviceProperties2 oldProps; |
| 62 | + vk::PhysicalDeviceDriverProperties oldDriver; |
| 63 | + oldProps.pNext = &oldDriver; |
| 64 | + oldDevice->getProperties2(&oldProps); |
| 65 | + |
| 66 | + std::map<vk::DriverId, int> driverPriorities {}; |
| 67 | + int oldPriority = 1000; |
| 68 | + int newPriority = 1000; |
| 69 | + |
| 70 | + switch (oldProps.properties.vendorID) { |
| 71 | + case VK_VENDOR_ID_AMD: |
| 72 | + driverPriorities[vk::DriverId::eMesaRadv] = 1; |
| 73 | + driverPriorities[vk::DriverId::eAmdOpenSource] = 2; |
| 74 | + driverPriorities[vk::DriverId::eAmdProprietary] = 3; |
| 75 | + break; |
| 76 | + case VK_VENDOR_ID_INTEL: |
| 77 | + driverPriorities[vk::DriverId::eIntelOpenSourceMESA] = 1; |
| 78 | + driverPriorities[vk::DriverId::eIntelProprietaryWindows] = 2; |
| 79 | + break; |
| 80 | + case VK_VENDOR_ID_NVIDIA: |
| 81 | + driverPriorities[vk::DriverId::eNvidiaProprietary] = 1; |
| 82 | +#if defined(VK_API_VERSION_1_3) && VK_HEADER_VERSION >= 235 |
| 83 | + driverPriorities[vk::DriverId::eMesaNvk] = 2; |
| 84 | +#endif |
| 85 | + break; |
| 86 | + } |
| 87 | + driverPriorities[vk::DriverId::eMesaDozen] = 4; |
| 88 | + |
| 89 | + if (driverPriorities.count(oldDriver.driverID)) { |
| 90 | + oldPriority = driverPriorities[oldDriver.driverID]; |
| 91 | + } |
| 92 | + if (driverPriorities.count(newDriver.driverID)) { |
| 93 | + newPriority = driverPriorities[newDriver.driverID]; |
| 94 | + } |
| 95 | + |
| 96 | + if (newPriority < oldPriority) { |
| 97 | + dedupedDevices.erase(std::remove(dedupedDevices.begin(), dedupedDevices.end(), *oldDevice), dedupedDevices.end()); |
| 98 | + dedupedDevices.push_back(device); |
| 99 | + } |
| 100 | + } |
| 101 | + |
| 102 | + return dedupedDevices; |
| 103 | +} |
| 104 | + |
| 105 | +static bool enumerateVulkanDevices(size_t* total, size_t* used, size_t* unifiedMemorySize, bool addDeviceNames, std::vector<std::string> * deviceNames, gpuInfoVulkanWarningLogCallback_t warningLogCallback, bool * checkSupported) { |
| 106 | + auto physicalDevices = dedupedDevices(); |
14 | 107 |
|
15 | 108 | size_t usedMem = 0; |
16 | 109 | size_t totalMem = 0; |
|
0 commit comments