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.
7
// SystemInfo_vulkan.cpp: Generic vulkan implementation of SystemInfo.h
10
#include <vulkan/vulkan.h>
11
#include "gpu_info_util/SystemInfo_internal.h"
16
#include "common/angleutils.h"
17
#include "common/debug.h"
21
class VulkanLibrary final : NonCopyable
27
if (mInstance != VK_NULL_HANDLE)
29
PFN_vkDestroyInstance pfnDestroyInstance =
30
reinterpret_cast<PFN_vkDestroyInstance>(dlsym(mLibVulkan, "vkDestroyInstance"));
31
if (pfnDestroyInstance)
33
pfnDestroyInstance(mInstance, nullptr);
39
VkInstance getVulkanInstance()
41
// Find the system's Vulkan library and open it:
42
mLibVulkan = dlopen("libvulkan.so", RTLD_NOW | RTLD_LOCAL);
45
// If Vulkan doesn't exist, bail-out early:
46
return VK_NULL_HANDLE;
49
// Determine the available Vulkan instance version:
50
uint32_t instanceVersion = VK_API_VERSION_1_0;
51
#if defined(VK_VERSION_1_1)
52
PFN_vkEnumerateInstanceVersion pfnEnumerateInstanceVersion =
53
reinterpret_cast<PFN_vkEnumerateInstanceVersion>(
54
dlsym(mLibVulkan, "vkEnumerateInstanceVersion"));
55
if (!pfnEnumerateInstanceVersion ||
56
pfnEnumerateInstanceVersion(&instanceVersion) != VK_SUCCESS)
58
instanceVersion = VK_API_VERSION_1_0;
60
#endif // VK_VERSION_1_1
62
// Create a Vulkan instance:
63
VkApplicationInfo appInfo;
64
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
65
appInfo.pNext = nullptr;
66
appInfo.pApplicationName = "";
67
appInfo.applicationVersion = 1;
68
appInfo.pEngineName = "";
69
appInfo.engineVersion = 1;
70
appInfo.apiVersion = instanceVersion;
72
VkInstanceCreateInfo createInstanceInfo;
73
createInstanceInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
74
createInstanceInfo.pNext = nullptr;
75
createInstanceInfo.flags = 0;
76
createInstanceInfo.pApplicationInfo = &appInfo;
77
createInstanceInfo.enabledLayerCount = 0;
78
createInstanceInfo.ppEnabledLayerNames = nullptr;
79
createInstanceInfo.enabledExtensionCount = 0;
80
createInstanceInfo.ppEnabledExtensionNames = nullptr;
82
PFN_vkCreateInstance pfnCreateInstance =
83
reinterpret_cast<PFN_vkCreateInstance>(dlsym(mLibVulkan, "vkCreateInstance"));
84
if (!pfnCreateInstance ||
85
pfnCreateInstance(&createInstanceInfo, nullptr, &mInstance) != VK_SUCCESS)
87
return VK_NULL_HANDLE;
92
void *gpa(std::string fn) { return dlsym(mLibVulkan, fn.c_str()); }
93
#define GPA(ob, type, fn) reinterpret_cast<type>(ob.gpa(fn))
96
void *mLibVulkan = nullptr;
97
VkInstance mInstance = VK_NULL_HANDLE;
100
ANGLE_FORMAT_PRINTF(1, 2)
101
std::string FormatString(const char *fmt, ...)
104
va_start(vararg, fmt);
106
std::vector<char> buffer(512);
107
size_t len = FormatStringIntoVector(fmt, vararg, buffer);
110
return std::string(&buffer[0], len);
113
bool GetSystemInfoVulkan(SystemInfo *info)
115
// This implementation builds on top of the Vulkan API, but cannot assume the existence of the
116
// Vulkan library. ANGLE can be installed on versions of Android as old as Ice Cream Sandwich.
117
// Therefore, we need to use dlopen()/dlsym() in order to see if Vulkan is installed on the
118
// system, and if so, to use it:
119
VulkanLibrary vkLibrary;
120
VkInstance instance = vkLibrary.getVulkanInstance();
121
if (instance == VK_NULL_HANDLE)
123
// If Vulkan doesn't exist, bail-out early:
127
// Enumerate the Vulkan physical devices, which are ANGLE gpus:
128
PFN_vkEnumeratePhysicalDevices pfnEnumeratePhysicalDevices =
129
GPA(vkLibrary, PFN_vkEnumeratePhysicalDevices, "vkEnumeratePhysicalDevices");
130
PFN_vkGetPhysicalDeviceProperties pfnGetPhysicalDeviceProperties =
131
GPA(vkLibrary, PFN_vkGetPhysicalDeviceProperties, "vkGetPhysicalDeviceProperties");
132
uint32_t physicalDeviceCount = 0;
133
if (!pfnEnumeratePhysicalDevices ||
134
pfnEnumeratePhysicalDevices(instance, &physicalDeviceCount, nullptr) != VK_SUCCESS)
138
std::vector<VkPhysicalDevice> physicalDevices(physicalDeviceCount);
139
if (pfnEnumeratePhysicalDevices(instance, &physicalDeviceCount, physicalDevices.data()) !=
145
// If we get to here, we will likely provide a valid answer (unless an unknown vendorID):
146
info->gpus.resize(physicalDeviceCount);
148
for (uint32_t i = 0; i < physicalDeviceCount; i++)
150
VkPhysicalDeviceProperties properties;
151
pfnGetPhysicalDeviceProperties(physicalDevices[i], &properties);
152
// Fill in data for a given physical device (a.k.a. gpu):
153
GPUDeviceInfo &gpu = info->gpus[i];
154
gpu.vendorId = properties.vendorID;
155
gpu.deviceId = properties.deviceID;
156
// Need to parse/re-format properties.driverVersion.
158
// TODO(ianelliott): Determine the formatting used for each vendor
159
// (http://anglebug.com/2677)
160
switch (properties.vendorID)
163
gpu.driverVendor = "Advanced Micro Devices, Inc";
164
gpu.driverVersion = FormatString("0x%x", properties.driverVersion);
165
gpu.detailedDriverVersion.major = properties.driverVersion;
168
gpu.driverVendor = "Arm Holdings";
169
gpu.driverVersion = FormatString("0x%x", properties.driverVersion);
170
gpu.detailedDriverVersion.major = properties.driverVersion;
172
case kVendorID_Broadcom:
173
gpu.driverVendor = "Broadcom";
174
gpu.driverVersion = FormatString("0x%x", properties.driverVersion);
175
gpu.detailedDriverVersion.major = properties.driverVersion;
177
case kVendorID_ImgTec:
178
gpu.driverVendor = "Imagination Technologies Limited";
179
gpu.driverVersion = FormatString("0x%x", properties.driverVersion);
180
gpu.detailedDriverVersion.major = properties.driverVersion;
182
case kVendorID_Intel:
183
gpu.driverVendor = "Intel Corporation";
184
gpu.driverVersion = FormatString("0x%x", properties.driverVersion);
185
gpu.detailedDriverVersion.major = properties.driverVersion;
187
case kVendorID_Kazan:
188
gpu.driverVendor = "Kazan Software";
189
gpu.driverVersion = FormatString("0x%x", properties.driverVersion);
190
gpu.detailedDriverVersion.major = properties.driverVersion;
192
case kVendorID_NVIDIA:
193
gpu.driverVendor = "NVIDIA Corporation";
194
gpu.driverVersion = FormatString("%d.%d.%d.%d", properties.driverVersion >> 22,
195
(properties.driverVersion >> 14) & 0XFF,
196
(properties.driverVersion >> 6) & 0XFF,
197
properties.driverVersion & 0x3F);
198
gpu.detailedDriverVersion.major = properties.driverVersion >> 22;
199
gpu.detailedDriverVersion.minor = (properties.driverVersion >> 14) & 0xFF;
200
gpu.detailedDriverVersion.subMinor = (properties.driverVersion >> 6) & 0xFF;
201
gpu.detailedDriverVersion.patch = properties.driverVersion & 0x3F;
203
case kVendorID_Qualcomm:
204
gpu.driverVendor = "Qualcomm Technologies, Inc";
205
if (properties.driverVersion & 0x80000000)
207
gpu.driverVersion = FormatString("%d.%d.%d", properties.driverVersion >> 22,
208
(properties.driverVersion >> 12) & 0X3FF,
209
properties.driverVersion & 0xFFF);
210
gpu.detailedDriverVersion.major = properties.driverVersion >> 22;
211
gpu.detailedDriverVersion.minor = (properties.driverVersion >> 12) & 0x3FF;
212
gpu.detailedDriverVersion.subMinor = properties.driverVersion & 0xFFF;
216
gpu.driverVersion = FormatString("0x%x", properties.driverVersion);
217
gpu.detailedDriverVersion.major = properties.driverVersion;
220
case kVendorID_VeriSilicon:
221
gpu.driverVendor = "VeriSilicon";
222
gpu.driverVersion = FormatString("0x%x", properties.driverVersion);
223
gpu.detailedDriverVersion.major = properties.driverVersion;
225
case kVendorID_Vivante:
226
gpu.driverVendor = "Vivante";
227
gpu.driverVersion = FormatString("0x%x", properties.driverVersion);
228
gpu.detailedDriverVersion.major = properties.driverVersion;