xref: /aosp_15_r20/external/angle/src/gpu_info_util/SystemInfo_win.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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)28 bool 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)89 bool 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