• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
75         devices->push_back(device);
76 
77         adapter->Release();
78     }
79 
80     factory->Release();
81 
82     return (i > 0);
83 }
84 
85 }  // anonymous namespace
86 
GetSystemInfo(SystemInfo * info)87 bool GetSystemInfo(SystemInfo *info)
88 {
89     if (!GetDevicesFromDXGI(&info->gpus))
90     {
91         return false;
92     }
93 
94     if (info->gpus.size() == 0)
95     {
96         return false;
97     }
98 
99     // Call GetDualGPUInfo to populate activeGPUIndex, isOptimus, and isAMDSwitchable.
100     GetDualGPUInfo(info);
101 
102     // Override activeGPUIndex. The first index returned by EnumAdapters is the active GPU. We
103     // can override the heuristic to find the active GPU
104     info->activeGPUIndex = 0;
105 
106 #if !defined(ANGLE_ENABLE_WINDOWS_UWP)
107     // Override isOptimus. nvd3d9wrap.dll is loaded into all processes when Optimus is enabled.
108     HMODULE nvd3d9wrap = GetModuleHandleW(L"nvd3d9wrap.dll");
109     info->isOptimus    = nvd3d9wrap != nullptr;
110 #endif
111 
112     return true;
113 }
114 
115 }  // namespace angle
116