1 // 2 // Copyright 2013 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 // SystemInfo_win.cpp: implementation of the Windows-specific parts of SystemInfo.h 8 9 #include "gpu_info_util/SystemInfo_internal.h" 10 11 #include "common/debug.h" 12 #include "common/string_utils.h" 13 14 // Windows.h needs to be included first 15 #include <windows.h> 16 17 #include <dxgi.h> 18 19 #include <array> 20 #include <sstream> 21 22 namespace angle 23 { 24 25 namespace 26 { 27 GetDevicesFromDXGI(std::vector<GPUDeviceInfo> * devices)28bool GetDevicesFromDXGI(std::vector<GPUDeviceInfo> *devices) 29 { 30 #if defined(ANGLE_ENABLE_WINDOWS_UWP) 31 IDXGIFactory1 *factory; 32 if (!SUCCEEDED( 33 CreateDXGIFactory1(__uuidof(IDXGIFactory1), reinterpret_cast<void **>(&factory)))) 34 { 35 return false; 36 } 37 #else 38 IDXGIFactory *factory; 39 if (!SUCCEEDED(CreateDXGIFactory(__uuidof(IDXGIFactory), reinterpret_cast<void **>(&factory)))) 40 { 41 return false; 42 } 43 #endif 44 45 UINT i = 0; 46 IDXGIAdapter *adapter = nullptr; 47 while (factory->EnumAdapters(i++, &adapter) != DXGI_ERROR_NOT_FOUND) 48 { 49 DXGI_ADAPTER_DESC desc; 50 adapter->GetDesc(&desc); 51 52 LARGE_INTEGER umdVersion; 53 if (adapter->CheckInterfaceSupport(__uuidof(IDXGIDevice), &umdVersion) == 54 DXGI_ERROR_UNSUPPORTED) 55 { 56 adapter->Release(); 57 continue; 58 } 59 60 // The UMD driver version here is the same as in the registry except for the last number. 61 uint64_t intVersion = umdVersion.QuadPart; 62 std::ostringstream o; 63 64 constexpr uint64_t kMask16 = std::numeric_limits<uint16_t>::max(); 65 o << ((intVersion >> 48) & kMask16) << "."; 66 o << ((intVersion >> 32) & kMask16) << "."; 67 o << ((intVersion >> 16) & kMask16) << "."; 68 o << (intVersion & kMask16); 69 70 GPUDeviceInfo device; 71 device.vendorId = desc.VendorId; 72 device.deviceId = desc.DeviceId; 73 device.driverVersion = o.str(); 74 device.systemDeviceId = 75 GetSystemDeviceIdFromParts(desc.AdapterLuid.HighPart, desc.AdapterLuid.LowPart); 76 77 devices->push_back(device); 78 79 adapter->Release(); 80 } 81 82 factory->Release(); 83 84 return (i > 0); 85 } 86 87 } // anonymous namespace 88 GetSystemInfo(SystemInfo * info)89bool GetSystemInfo(SystemInfo *info) 90 { 91 if (!GetDevicesFromDXGI(&info->gpus)) 92 { 93 return false; 94 } 95 96 if (info->gpus.size() == 0) 97 { 98 return false; 99 } 100 101 // Call GetDualGPUInfo to populate activeGPUIndex, isOptimus, and isAMDSwitchable. 102 GetDualGPUInfo(info); 103 104 // Override activeGPUIndex. The first index returned by EnumAdapters is the active GPU. We 105 // can override the heuristic to find the active GPU 106 info->activeGPUIndex = 0; 107 108 #if !defined(ANGLE_ENABLE_WINDOWS_UWP) 109 // Override isOptimus. nvd3d9wrap.dll is loaded into all processes when Optimus is enabled. 110 HMODULE nvd3d9wrap = GetModuleHandleW(L"nvd3d9wrap.dll"); 111 info->isOptimus = nvd3d9wrap != nullptr; 112 #endif 113 114 return true; 115 } 116 117 } // namespace angle 118