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