|
12 | 12 |
|
13 | 13 | #include "core/common/cpuid_info.h" |
14 | 14 | #include "core/common/logging/logging.h" |
| 15 | +#include "core/platform/env.h" |
15 | 16 | #include "core/session/abi_devices.h" |
16 | 17 |
|
17 | 18 | //// For SetupApi info |
@@ -56,6 +57,26 @@ struct DeviceInfo { |
56 | 57 | std::unordered_map<std::wstring, std::wstring> metadata; |
57 | 58 | }; |
58 | 59 |
|
| 60 | +struct DriverInfo { |
| 61 | + std::wstring driver_versions; |
| 62 | + std::wstring driver_names; |
| 63 | + |
| 64 | + void AddDevice(const std::wstring& driver_version, const std::wstring& driver_name) { |
| 65 | + if (!driver_version.empty()) { |
| 66 | + if (!driver_versions.empty()) { |
| 67 | + driver_versions += L", "; |
| 68 | + } |
| 69 | + driver_versions += driver_version; |
| 70 | + } |
| 71 | + if (!driver_name.empty()) { |
| 72 | + if (!driver_names.empty()) { |
| 73 | + driver_names += L", "; |
| 74 | + } |
| 75 | + driver_names += driver_name; |
| 76 | + } |
| 77 | + } |
| 78 | +}; |
| 79 | + |
59 | 80 | uint64_t GetDeviceKey(uint32_t vendor_id, uint32_t device_id) { |
60 | 81 | return (uint64_t(vendor_id) << 32) | device_id; |
61 | 82 | } |
@@ -91,6 +112,8 @@ std::unordered_map<uint64_t, DeviceInfo> GetDeviceInfoSetupApi(const std::unorde |
91 | 112 | const GUID local_DXCORE_HARDWARE_TYPE_ATTRIBUTE_NPU = {0xd46140c4, 0xadd7, 0x451b, 0x9e, 0x56, 0x6, 0xfe, 0x8c, 0x3b, 0x58, 0xed}; |
92 | 113 | const GUID local_GUID_DEVCLASS_COMPUTEACCELERATOR = {0xf01a9d53, 0x3ff6, 0x48d2, 0x9f, 0x97, 0xc8, 0xa7, 0x00, 0x4b, 0xe1, 0x0c}; |
93 | 114 |
|
| 115 | + std::unordered_map<OrtHardwareDeviceType, DriverInfo> device_version_info; |
| 116 | + |
94 | 117 | std::array<GUID, 3> guids = { |
95 | 118 | GUID_DEVCLASS_DISPLAY, |
96 | 119 | GUID_DEVCLASS_PROCESSOR, |
@@ -232,11 +255,52 @@ std::unordered_map<uint64_t, DeviceInfo> GetDeviceInfoSetupApi(const std::unorde |
232 | 255 | entry->vendor = std::wstring(buffer, wcslen(buffer)); |
233 | 256 | } |
234 | 257 | } |
| 258 | + |
| 259 | + // Generate telemetry event to log the GPU and NPU driver name and version. |
| 260 | + if (entry->type == OrtHardwareDeviceType_CPU) { |
| 261 | + // Skip processor entries for telemetry. |
| 262 | + continue; |
| 263 | + } |
| 264 | + |
| 265 | + // Open the device's driver registry key |
| 266 | + HKEY dev_reg_key = SetupDiOpenDevRegKey(devInfo, &devData, |
| 267 | + DICS_FLAG_GLOBAL, |
| 268 | + 0, |
| 269 | + DIREG_DRV, |
| 270 | + KEY_READ); |
| 271 | + |
| 272 | + if (dev_reg_key != INVALID_HANDLE_VALUE) { |
| 273 | + // Query the "DriverVersion" string |
| 274 | + std::wstring driver_version_str; |
| 275 | + wchar_t driver_version[256]; |
| 276 | + DWORD str_size = sizeof(driver_version); |
| 277 | + DWORD type = 0; |
| 278 | + if (RegQueryValueExW(dev_reg_key, L"DriverVersion", |
| 279 | + nullptr, &type, |
| 280 | + reinterpret_cast<LPBYTE>(driver_version), |
| 281 | + &str_size) == ERROR_SUCCESS && |
| 282 | + type == REG_SZ) { |
| 283 | + // Ensure proper null termination of a string retrieved from the Windows Registry API. |
| 284 | + driver_version[(str_size / sizeof(wchar_t)) - 1] = 0; |
| 285 | + driver_version_str = driver_version; |
| 286 | + } |
| 287 | + RegCloseKey(dev_reg_key); |
| 288 | + device_version_info[entry->type].AddDevice(driver_version_str, entry->description); |
| 289 | + } |
235 | 290 | } |
236 | 291 |
|
237 | 292 | SetupDiDestroyDeviceInfoList(devInfo); |
238 | 293 | } |
239 | 294 |
|
| 295 | + // Log driver information for GPUs and NPUs |
| 296 | + const Env& env = Env::Default(); |
| 297 | + for (const auto& [type, info] : device_version_info) { |
| 298 | + if (!info.driver_versions.empty() || !info.driver_names.empty()) { |
| 299 | + const std::string_view driver_class = (type == OrtHardwareDeviceType_GPU) ? "GPU" : "NPU"; |
| 300 | + env.GetTelemetryProvider().LogDriverInfoEvent(driver_class, info.driver_names, info.driver_versions); |
| 301 | + } |
| 302 | + } |
| 303 | + |
240 | 304 | return device_info; |
241 | 305 | } |
242 | 306 |
|
|
0 commit comments