vkinfo.cpp revision c1ab303f6fc8339d386d6cf127534677929fddfb
1/*
2 * Copyright 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <inttypes.h>
18#include <stdlib.h>
19#include <sstream>
20#include <vector>
21
22#define VK_PROTOTYPES
23#include <vulkan/vulkan.h>
24
25#define LOG_TAG "vkinfo"
26#include <log/log.h>
27
28namespace {
29
30[[noreturn]] void die(const char* proc, VkResult result) {
31    const char* result_str;
32    switch (result) {
33        // clang-format off
34        case VK_SUCCESS: result_str = "VK_SUCCESS"; break;
35        case VK_NOT_READY: result_str = "VK_NOT_READY"; break;
36        case VK_TIMEOUT: result_str = "VK_TIMEOUT"; break;
37        case VK_EVENT_SET: result_str = "VK_EVENT_SET"; break;
38        case VK_EVENT_RESET: result_str = "VK_EVENT_RESET"; break;
39        case VK_INCOMPLETE: result_str = "VK_INCOMPLETE"; break;
40        case VK_ERROR_OUT_OF_HOST_MEMORY: result_str = "VK_ERROR_OUT_OF_HOST_MEMORY"; break;
41        case VK_ERROR_OUT_OF_DEVICE_MEMORY: result_str = "VK_ERROR_OUT_OF_DEVICE_MEMORY"; break;
42        case VK_ERROR_INITIALIZATION_FAILED: result_str = "VK_ERROR_INITIALIZATION_FAILED"; break;
43        case VK_ERROR_DEVICE_LOST: result_str = "VK_ERROR_DEVICE_LOST"; break;
44        case VK_ERROR_MEMORY_MAP_FAILED: result_str = "VK_ERROR_MEMORY_MAP_FAILED"; break;
45        case VK_ERROR_LAYER_NOT_PRESENT: result_str = "VK_ERROR_LAYER_NOT_PRESENT"; break;
46        case VK_ERROR_EXTENSION_NOT_PRESENT: result_str = "VK_ERROR_EXTENSION_NOT_PRESENT"; break;
47        case VK_ERROR_INCOMPATIBLE_DRIVER: result_str = "VK_ERROR_INCOMPATIBLE_DRIVER"; break;
48        default: result_str = "<unknown VkResult>"; break;
49            // clang-format on
50    }
51    fprintf(stderr, "%s failed: %s (%d)\n", proc, result_str, result);
52    exit(1);
53}
54
55uint32_t ExtractMajorVersion(uint32_t version) {
56    return (version >> 22) & 0x3FF;
57}
58uint32_t ExtractMinorVersion(uint32_t version) {
59    return (version >> 12) & 0x3FF;
60}
61uint32_t ExtractPatchVersion(uint32_t version) {
62    return (version >> 0) & 0xFFF;
63}
64
65const char* VkPhysicalDeviceTypeStr(VkPhysicalDeviceType type) {
66    switch (type) {
67        case VK_PHYSICAL_DEVICE_TYPE_OTHER:
68            return "OTHER";
69        case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
70            return "INTEGRATED_GPU";
71        case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
72            return "DISCRETE_GPU";
73        case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:
74            return "VIRTUAL_GPU";
75        case VK_PHYSICAL_DEVICE_TYPE_CPU:
76            return "CPU";
77        default:
78            return "<UNKNOWN>";
79    }
80}
81
82const char* VkQueueFlagBitStr(VkQueueFlagBits bit) {
83    switch (bit) {
84        case VK_QUEUE_GRAPHICS_BIT:
85            return "GRAPHICS";
86        case VK_QUEUE_COMPUTE_BIT:
87            return "COMPUTE";
88        case VK_QUEUE_TRANSFER_BIT:
89            return "TRANSFER";
90        case VK_QUEUE_SPARSE_BINDING_BIT:
91            return "SPARSE";
92    }
93}
94
95struct VulkanInfo {
96    std::vector<VkExtensionProperties> extensions;
97    std::vector<VkLayerProperties> layers;
98    std::vector<std::vector<VkExtensionProperties>> layer_extensions;
99};
100
101void DumpPhysicalDevice(uint32_t idx, VkPhysicalDevice pdev) {
102    VkResult result;
103    std::ostringstream strbuf;
104
105    VkPhysicalDeviceProperties props;
106    vkGetPhysicalDeviceProperties(pdev, &props);
107    printf("  %u: \"%s\" (%s) %u.%u.%u/%#x [%04x:%04x]\n", idx,
108           props.deviceName, VkPhysicalDeviceTypeStr(props.deviceType),
109           ExtractMajorVersion(props.apiVersion),
110           ExtractMinorVersion(props.apiVersion),
111           ExtractPatchVersion(props.apiVersion), props.driverVersion,
112           props.vendorID, props.deviceID);
113
114    VkPhysicalDeviceMemoryProperties mem_props;
115    vkGetPhysicalDeviceMemoryProperties(pdev, &mem_props);
116    for (uint32_t heap = 0; heap < mem_props.memoryHeapCount; heap++) {
117        if ((mem_props.memoryHeaps[heap].flags &
118             VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) != 0)
119            strbuf << "DEVICE_LOCAL";
120        printf("     Heap %u: 0x%" PRIx64 " %s\n", heap,
121               mem_props.memoryHeaps[heap].size, strbuf.str().c_str());
122        strbuf.str(std::string());
123
124        for (uint32_t type = 0; type < mem_props.memoryTypeCount; type++) {
125            if (mem_props.memoryTypes[type].heapIndex != heap)
126                continue;
127            VkMemoryPropertyFlags flags =
128                mem_props.memoryTypes[type].propertyFlags;
129            if ((flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) != 0)
130                strbuf << " DEVICE_LOCAL";
131            if ((flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0)
132                strbuf << " HOST_VISIBLE";
133            if ((flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) != 0)
134                strbuf << " COHERENT";
135            if ((flags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) != 0)
136                strbuf << " CACHED";
137            if ((flags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) != 0)
138                strbuf << " LAZILY_ALLOCATED";
139            printf("       Type %u:%s\n", type, strbuf.str().c_str());
140            strbuf.str(std::string());
141        }
142    }
143
144    uint32_t num_queue_families;
145    vkGetPhysicalDeviceQueueFamilyProperties(pdev, &num_queue_families,
146                                             nullptr);
147    std::vector<VkQueueFamilyProperties> queue_family_properties(
148        num_queue_families);
149    vkGetPhysicalDeviceQueueFamilyProperties(pdev, &num_queue_families,
150                                             queue_family_properties.data());
151    for (uint32_t family = 0; family < num_queue_families; family++) {
152        const VkQueueFamilyProperties& qprops = queue_family_properties[family];
153        const char* sep = "";
154        int bit, queue_flags = static_cast<int>(qprops.queueFlags);
155        while ((bit = __builtin_ffs(queue_flags)) != 0) {
156            VkQueueFlagBits flag = VkQueueFlagBits(1 << (bit - 1));
157            strbuf << sep << VkQueueFlagBitStr(flag);
158            queue_flags &= ~flag;
159            sep = "+";
160        }
161        printf("     Queue Family %u: %2ux %s timestamps:%ub\n", family,
162               qprops.queueCount, strbuf.str().c_str(),
163               qprops.timestampValidBits);
164        strbuf.str(std::string());
165    }
166}
167
168void EnumerateInstanceExtensions(
169    const char* layer_name,
170    std::vector<VkExtensionProperties>* extensions) {
171    VkResult result;
172    uint32_t count;
173    result =
174        vkEnumerateInstanceExtensionProperties(layer_name, &count, nullptr);
175    if (result != VK_SUCCESS)
176        die("vkEnumerateInstanceExtensionProperties (count)", result);
177    extensions->resize(count);
178    result = vkEnumerateInstanceExtensionProperties(layer_name, &count,
179                                                    extensions->data());
180    if (result != VK_SUCCESS)
181        die("vkEnumerateInstanceExtensionProperties (data)", result);
182}
183
184void GatherInfo(VulkanInfo* info) {
185    VkResult result;
186    uint32_t count;
187
188    result = vkEnumerateInstanceLayerProperties(&count, nullptr);
189    if (result != VK_SUCCESS)
190        die("vkEnumerateInstanceLayerProperties (count)", result);
191    info->layers.resize(count);
192    result = vkEnumerateInstanceLayerProperties(&count, info->layers.data());
193    if (result != VK_SUCCESS)
194        die("vkEnumerateInstanceLayerProperties (data)", result);
195    info->layer_extensions.resize(info->layers.size());
196
197    EnumerateInstanceExtensions(nullptr, &info->extensions);
198    for (size_t i = 0; i < info->extensions.size(); i++)
199        EnumerateInstanceExtensions(info->layers[i].layerName,
200                                    &info->layer_extensions[i]);
201}
202
203void PrintExtensions(const std::vector<VkExtensionProperties>& extensions,
204                     const char* prefix) {
205    for (const auto& e : extensions)
206        printf("%s%s (v%u)\n", prefix, e.extensionName, e.specVersion);
207}
208
209void PrintInfo(const VulkanInfo& info) {
210    printf("Instance Extensions [%u]:\n", info.extensions.size());
211    PrintExtensions(info.extensions, "  ");
212    if (!info.layers.empty()) {
213        printf("Instance Layers [%u]:\n", info.layers.size());
214        for (size_t i = 0; i < info.layers.size(); i++) {
215            const auto& layer = info.layers[i];
216            printf(
217                "  %s %u.%u.%u/%u \"%s\"\n",
218                layer.layerName, ExtractMajorVersion(layer.specVersion),
219                ExtractMinorVersion(layer.specVersion),
220                ExtractPatchVersion(layer.specVersion),
221                layer.implementationVersion, layer.description);
222            if (!info.layer_extensions[i].empty()) {
223                printf("     Extensions [%zu]:\n",
224                       info.layer_extensions.size());
225                PrintExtensions(info.layer_extensions[i], "       ");
226            }
227        }
228    }
229}
230
231}  // namespace
232
233int main(int /*argc*/, char const* /*argv*/ []) {
234    VulkanInfo info;
235    GatherInfo(&info);
236    PrintInfo(info);
237
238    VkResult result;
239
240    VkInstance instance;
241    const VkInstanceCreateInfo create_info = {
242        .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
243        .pNext = nullptr,
244        .pApplicationInfo = nullptr,
245        .enabledLayerNameCount = 0,
246        .ppEnabledLayerNames = nullptr,
247        .enabledExtensionNameCount = 0,
248        .ppEnabledExtensionNames = nullptr,
249    };
250    result = vkCreateInstance(&create_info, nullptr, &instance);
251    if (result != VK_SUCCESS)
252        die("vkCreateInstance", result);
253
254    uint32_t num_physical_devices;
255    result =
256        vkEnumeratePhysicalDevices(instance, &num_physical_devices, nullptr);
257    if (result != VK_SUCCESS)
258        die("vkEnumeratePhysicalDevices (count)", result);
259    std::vector<VkPhysicalDevice> physical_devices(num_physical_devices,
260                                                   VK_NULL_HANDLE);
261    result = vkEnumeratePhysicalDevices(instance, &num_physical_devices,
262                                        physical_devices.data());
263    if (result != VK_SUCCESS)
264        die("vkEnumeratePhysicalDevices (data)", result);
265    if (num_physical_devices != physical_devices.size()) {
266        fprintf(stderr,
267                "number of physical devices decreased from %zu to %u!\n",
268                physical_devices.size(), num_physical_devices);
269        physical_devices.resize(num_physical_devices);
270    }
271    printf("PhysicalDevices [%zu]:\n", physical_devices.size());
272    for (uint32_t i = 0; i < physical_devices.size(); i++)
273        DumpPhysicalDevice(i, physical_devices[i]);
274
275    vkDestroyInstance(instance, nullptr);
276
277    return 0;
278}
279