• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2020 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_vulkan.cpp: Generic vulkan implementation of SystemInfo.h
8 // TODO: Use VK_KHR_driver_properties. http://anglebug.com/5103
9 
10 #include <vulkan/vulkan.h>
11 #include "gpu_info_util/SystemInfo_internal.h"
12 
13 #include <cstring>
14 #include <fstream>
15 
16 #include "common/angleutils.h"
17 #include "common/debug.h"
18 #include "common/system_utils.h"
19 #include "common/vulkan/libvulkan_loader.h"
20 
21 namespace angle
22 {
23 class VulkanLibrary final : NonCopyable
24 {
25   public:
26     VulkanLibrary() = default;
27 
~VulkanLibrary()28     ~VulkanLibrary()
29     {
30         if (mInstance != VK_NULL_HANDLE)
31         {
32             auto pfnDestroyInstance = getProc<PFN_vkDestroyInstance>("vkDestroyInstance");
33             if (pfnDestroyInstance)
34             {
35                 pfnDestroyInstance(mInstance, nullptr);
36             }
37         }
38     }
39 
getVulkanInstance()40     VkInstance getVulkanInstance()
41     {
42         mLibVulkan = vk::OpenLibVulkan();
43         if (!mLibVulkan)
44         {
45             // If Vulkan doesn't exist, bail-out early:
46             return VK_NULL_HANDLE;
47         }
48 
49         // Determine the available Vulkan instance version:
50         uint32_t instanceVersion = VK_API_VERSION_1_0;
51 #if defined(VK_VERSION_1_1)
52         auto pfnEnumerateInstanceVersion =
53             getProc<PFN_vkEnumerateInstanceVersion>("vkEnumerateInstanceVersion");
54         if (!pfnEnumerateInstanceVersion ||
55             pfnEnumerateInstanceVersion(&instanceVersion) != VK_SUCCESS)
56         {
57             instanceVersion = VK_API_VERSION_1_0;
58         }
59 #endif  // VK_VERSION_1_1
60 
61         // Create a Vulkan instance:
62         VkApplicationInfo appInfo;
63         appInfo.sType              = VK_STRUCTURE_TYPE_APPLICATION_INFO;
64         appInfo.pNext              = nullptr;
65         appInfo.pApplicationName   = "";
66         appInfo.applicationVersion = 1;
67         appInfo.pEngineName        = "";
68         appInfo.engineVersion      = 1;
69         appInfo.apiVersion         = instanceVersion;
70 
71         VkInstanceCreateInfo createInstanceInfo;
72         createInstanceInfo.sType                   = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
73         createInstanceInfo.pNext                   = nullptr;
74         createInstanceInfo.flags                   = 0;
75         createInstanceInfo.pApplicationInfo        = &appInfo;
76         createInstanceInfo.enabledLayerCount       = 0;
77         createInstanceInfo.ppEnabledLayerNames     = nullptr;
78         createInstanceInfo.enabledExtensionCount   = 0;
79         createInstanceInfo.ppEnabledExtensionNames = nullptr;
80 
81         auto pfnCreateInstance = getProc<PFN_vkCreateInstance>("vkCreateInstance");
82         if (!pfnCreateInstance ||
83             pfnCreateInstance(&createInstanceInfo, nullptr, &mInstance) != VK_SUCCESS)
84         {
85             return VK_NULL_HANDLE;
86         }
87 
88         return mInstance;
89     }
90 
91     template <typename Func>
getProc(const char * fn) const92     Func getProc(const char *fn) const
93     {
94         return reinterpret_cast<Func>(mLibVulkan->getSymbol(fn));
95     }
96 
97   private:
98     std::unique_ptr<Library> mLibVulkan = nullptr;
99     VkInstance mInstance                = VK_NULL_HANDLE;
100 };
101 
102 ANGLE_FORMAT_PRINTF(1, 2)
FormatString(const char * fmt,...)103 std::string FormatString(const char *fmt, ...)
104 {
105     va_list vararg;
106     va_start(vararg, fmt);
107 
108     std::vector<char> buffer;
109     size_t len = FormatStringIntoVector(fmt, vararg, buffer);
110     va_end(vararg);
111 
112     return std::string(&buffer[0], len);
113 }
114 
GetSystemInfoVulkan(SystemInfo * info)115 bool GetSystemInfoVulkan(SystemInfo *info)
116 {
117     // This implementation builds on top of the Vulkan API, but cannot assume the existence of the
118     // Vulkan library.  ANGLE can be installed on versions of Android as old as Ice Cream Sandwich.
119     // Therefore, we need to use dlopen()/dlsym() in order to see if Vulkan is installed on the
120     // system, and if so, to use it:
121     VulkanLibrary vkLibrary;
122     VkInstance instance = vkLibrary.getVulkanInstance();
123     if (instance == VK_NULL_HANDLE)
124     {
125         // If Vulkan doesn't exist, bail-out early:
126         return false;
127     }
128 
129     // Enumerate the Vulkan physical devices, which are ANGLE gpus:
130     auto pfnEnumeratePhysicalDevices =
131         vkLibrary.getProc<PFN_vkEnumeratePhysicalDevices>("vkEnumeratePhysicalDevices");
132     auto pfnGetPhysicalDeviceProperties =
133         vkLibrary.getProc<PFN_vkGetPhysicalDeviceProperties>("vkGetPhysicalDeviceProperties");
134     uint32_t physicalDeviceCount = 0;
135     if (!pfnEnumeratePhysicalDevices || !pfnGetPhysicalDeviceProperties ||
136         pfnEnumeratePhysicalDevices(instance, &physicalDeviceCount, nullptr) != VK_SUCCESS)
137     {
138         return false;
139     }
140     std::vector<VkPhysicalDevice> physicalDevices(physicalDeviceCount);
141     if (pfnEnumeratePhysicalDevices(instance, &physicalDeviceCount, physicalDevices.data()) !=
142         VK_SUCCESS)
143     {
144         return false;
145     }
146 
147     // If we get to here, we will likely provide a valid answer (unless an unknown vendorID):
148     info->gpus.resize(physicalDeviceCount);
149 
150     for (uint32_t i = 0; i < physicalDeviceCount; i++)
151     {
152         VkPhysicalDeviceProperties properties;
153         pfnGetPhysicalDeviceProperties(physicalDevices[i], &properties);
154         // Fill in data for a given physical device (a.k.a. gpu):
155         GPUDeviceInfo &gpu = info->gpus[i];
156         gpu.vendorId       = properties.vendorID;
157         gpu.deviceId       = properties.deviceID;
158         // Need to parse/re-format properties.driverVersion.
159         //
160         // TODO(ianelliott): Determine the formatting used for each vendor
161         // (http://anglebug.com/2677)
162         switch (properties.vendorID)
163         {
164             case kVendorID_AMD:
165                 gpu.driverVendor                = "Advanced Micro Devices, Inc";
166                 gpu.driverVersion               = FormatString("0x%x", properties.driverVersion);
167                 gpu.detailedDriverVersion.major = properties.driverVersion;
168                 break;
169             case kVendorID_ARM:
170                 gpu.driverVendor                = "Arm Holdings";
171                 gpu.driverVersion               = FormatString("0x%x", properties.driverVersion);
172                 gpu.detailedDriverVersion.major = properties.driverVersion;
173                 break;
174             case kVendorID_Broadcom:
175                 gpu.driverVendor                = "Broadcom";
176                 gpu.driverVersion               = FormatString("0x%x", properties.driverVersion);
177                 gpu.detailedDriverVersion.major = properties.driverVersion;
178                 break;
179             case kVendorID_ImgTec:
180                 gpu.driverVendor                = "Imagination Technologies Limited";
181                 gpu.driverVersion               = FormatString("0x%x", properties.driverVersion);
182                 gpu.detailedDriverVersion.major = properties.driverVersion;
183                 break;
184             case kVendorID_Intel:
185                 gpu.driverVendor                = "Intel Corporation";
186                 gpu.driverVersion               = FormatString("0x%x", properties.driverVersion);
187                 gpu.detailedDriverVersion.major = properties.driverVersion;
188                 break;
189             case kVendorID_Kazan:
190                 gpu.driverVendor                = "Kazan Software";
191                 gpu.driverVersion               = FormatString("0x%x", properties.driverVersion);
192                 gpu.detailedDriverVersion.major = properties.driverVersion;
193                 break;
194             case kVendorID_NVIDIA:
195                 gpu.driverVendor  = "NVIDIA Corporation";
196                 gpu.driverVersion = FormatString("%d.%d.%d.%d", properties.driverVersion >> 22,
197                                                  (properties.driverVersion >> 14) & 0XFF,
198                                                  (properties.driverVersion >> 6) & 0XFF,
199                                                  properties.driverVersion & 0x3F);
200                 gpu.detailedDriverVersion.major    = properties.driverVersion >> 22;
201                 gpu.detailedDriverVersion.minor    = (properties.driverVersion >> 14) & 0xFF;
202                 gpu.detailedDriverVersion.subMinor = (properties.driverVersion >> 6) & 0xFF;
203                 gpu.detailedDriverVersion.patch    = properties.driverVersion & 0x3F;
204                 break;
205             case kVendorID_Qualcomm:
206                 gpu.driverVendor = "Qualcomm Technologies, Inc";
207                 if (properties.driverVersion & 0x80000000)
208                 {
209                     gpu.driverVersion = FormatString("%d.%d.%d", properties.driverVersion >> 22,
210                                                      (properties.driverVersion >> 12) & 0X3FF,
211                                                      properties.driverVersion & 0xFFF);
212                     gpu.detailedDriverVersion.major    = properties.driverVersion >> 22;
213                     gpu.detailedDriverVersion.minor    = (properties.driverVersion >> 12) & 0x3FF;
214                     gpu.detailedDriverVersion.subMinor = properties.driverVersion & 0xFFF;
215                 }
216                 else
217                 {
218                     gpu.driverVersion = FormatString("0x%x", properties.driverVersion);
219                     gpu.detailedDriverVersion.major = properties.driverVersion;
220                 }
221                 break;
222             case kVendorID_VeriSilicon:
223                 gpu.driverVendor                = "VeriSilicon";
224                 gpu.driverVersion               = FormatString("0x%x", properties.driverVersion);
225                 gpu.detailedDriverVersion.major = properties.driverVersion;
226                 break;
227             case kVendorID_Vivante:
228                 gpu.driverVendor                = "Vivante";
229                 gpu.driverVersion               = FormatString("0x%x", properties.driverVersion);
230                 gpu.detailedDriverVersion.major = properties.driverVersion;
231                 break;
232             default:
233                 return false;
234         }
235         gpu.driverDate = "";
236     }
237 
238     return true;
239 }
240 
241 }  // namespace angle
242