Jesse Hall | d02edcb | 2015-09-08 07:44:48 -0700 | [diff] [blame] | 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 | |
Jesse Hall | 73ab0ac | 2015-08-25 15:09:15 +0100 | [diff] [blame] | 17 | #include <inttypes.h> |
Jesse Hall | 04f4f47 | 2015-08-16 19:51:04 -0700 | [diff] [blame] | 18 | #include <stdlib.h> |
Jesse Hall | 1f91d39 | 2015-12-11 16:28:44 -0800 | [diff] [blame] | 19 | #include <sstream> |
Jesse Hall | 04f4f47 | 2015-08-16 19:51:04 -0700 | [diff] [blame] | 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 | |
| 28 | namespace { |
| 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; |
Jesse Hall | 04f4f47 | 2015-08-16 19:51:04 -0700 | [diff] [blame] | 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; |
Jesse Hall | 04f4f47 | 2015-08-16 19:51:04 -0700 | [diff] [blame] | 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; |
Jesse Hall | 5ae3abb | 2015-10-08 14:00:22 -0700 | [diff] [blame] | 42 | case VK_ERROR_INITIALIZATION_FAILED: result_str = "VK_ERROR_INITIALIZATION_FAILED"; break; |
Jesse Hall | 04f4f47 | 2015-08-16 19:51:04 -0700 | [diff] [blame] | 43 | case VK_ERROR_DEVICE_LOST: result_str = "VK_ERROR_DEVICE_LOST"; break; |
Jesse Hall | 04f4f47 | 2015-08-16 19:51:04 -0700 | [diff] [blame] | 44 | case VK_ERROR_MEMORY_MAP_FAILED: result_str = "VK_ERROR_MEMORY_MAP_FAILED"; break; |
Jesse Hall | 5ae3abb | 2015-10-08 14:00:22 -0700 | [diff] [blame] | 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; |
Jesse Hall | 04f4f47 | 2015-08-16 19:51:04 -0700 | [diff] [blame] | 47 | case VK_ERROR_INCOMPATIBLE_DRIVER: result_str = "VK_ERROR_INCOMPATIBLE_DRIVER"; break; |
Jesse Hall | 04f4f47 | 2015-08-16 19:51:04 -0700 | [diff] [blame] | 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 | |
Jesse Hall | c1ab303 | 2016-01-04 07:26:53 -0800 | [diff] [blame] | 55 | uint32_t ExtractMajorVersion(uint32_t version) { |
| 56 | return (version >> 22) & 0x3FF; |
| 57 | } |
| 58 | uint32_t ExtractMinorVersion(uint32_t version) { |
| 59 | return (version >> 12) & 0x3FF; |
| 60 | } |
| 61 | uint32_t ExtractPatchVersion(uint32_t version) { |
| 62 | return (version >> 0) & 0xFFF; |
| 63 | } |
| 64 | |
Jesse Hall | 04f4f47 | 2015-08-16 19:51:04 -0700 | [diff] [blame] | 65 | const 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 | |
Jesse Hall | 5ae3abb | 2015-10-08 14:00:22 -0700 | [diff] [blame] | 82 | const 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"; |
Jesse Hall | 65ab552 | 2015-11-30 00:07:16 -0800 | [diff] [blame] | 88 | case VK_QUEUE_TRANSFER_BIT: |
| 89 | return "TRANSFER"; |
Jesse Hall | b00daad | 2015-11-29 19:46:20 -0800 | [diff] [blame] | 90 | case VK_QUEUE_SPARSE_BINDING_BIT: |
Jesse Hall | 5ae3abb | 2015-10-08 14:00:22 -0700 | [diff] [blame] | 91 | return "SPARSE"; |
Jesse Hall | 5ae3abb | 2015-10-08 14:00:22 -0700 | [diff] [blame] | 92 | } |
| 93 | } |
| 94 | |
Jesse Hall | c1ab303 | 2016-01-04 07:26:53 -0800 | [diff] [blame] | 95 | struct VulkanInfo { |
| 96 | std::vector<VkExtensionProperties> extensions; |
| 97 | std::vector<VkLayerProperties> layers; |
| 98 | std::vector<std::vector<VkExtensionProperties>> layer_extensions; |
| 99 | }; |
| 100 | |
Jesse Hall | 04f4f47 | 2015-08-16 19:51:04 -0700 | [diff] [blame] | 101 | void DumpPhysicalDevice(uint32_t idx, VkPhysicalDevice pdev) { |
| 102 | VkResult result; |
Jesse Hall | 73ab0ac | 2015-08-25 15:09:15 +0100 | [diff] [blame] | 103 | std::ostringstream strbuf; |
Jesse Hall | 04f4f47 | 2015-08-16 19:51:04 -0700 | [diff] [blame] | 104 | |
| 105 | VkPhysicalDeviceProperties props; |
Jesse Hall | 606a54e | 2015-11-19 22:17:28 -0800 | [diff] [blame] | 106 | vkGetPhysicalDeviceProperties(pdev, &props); |
Jesse Hall | 04f4f47 | 2015-08-16 19:51:04 -0700 | [diff] [blame] | 107 | printf(" %u: \"%s\" (%s) %u.%u.%u/%#x [%04x:%04x]\n", idx, |
| 108 | props.deviceName, VkPhysicalDeviceTypeStr(props.deviceType), |
Jesse Hall | c1ab303 | 2016-01-04 07:26:53 -0800 | [diff] [blame] | 109 | ExtractMajorVersion(props.apiVersion), |
| 110 | ExtractMinorVersion(props.apiVersion), |
| 111 | ExtractPatchVersion(props.apiVersion), props.driverVersion, |
| 112 | props.vendorID, props.deviceID); |
Jesse Hall | 73ab0ac | 2015-08-25 15:09:15 +0100 | [diff] [blame] | 113 | |
| 114 | VkPhysicalDeviceMemoryProperties mem_props; |
Jesse Hall | 606a54e | 2015-11-19 22:17:28 -0800 | [diff] [blame] | 115 | vkGetPhysicalDeviceMemoryProperties(pdev, &mem_props); |
Jesse Hall | 73ab0ac | 2015-08-25 15:09:15 +0100 | [diff] [blame] | 116 | for (uint32_t heap = 0; heap < mem_props.memoryHeapCount; heap++) { |
Jesse Hall | 5ae3abb | 2015-10-08 14:00:22 -0700 | [diff] [blame] | 117 | if ((mem_props.memoryHeaps[heap].flags & |
Jesse Hall | d1af812 | 2015-11-29 23:50:38 -0800 | [diff] [blame] | 118 | VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) != 0) |
| 119 | strbuf << "DEVICE_LOCAL"; |
Jesse Hall | 73ab0ac | 2015-08-25 15:09:15 +0100 | [diff] [blame] | 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; |
Jesse Hall | d1af812 | 2015-11-29 23:50:38 -0800 | [diff] [blame] | 129 | if ((flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) != 0) |
Jesse Hall | 1f91d39 | 2015-12-11 16:28:44 -0800 | [diff] [blame] | 130 | strbuf << " DEVICE_LOCAL"; |
Jesse Hall | 73ab0ac | 2015-08-25 15:09:15 +0100 | [diff] [blame] | 131 | if ((flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0) |
Jesse Hall | 1f91d39 | 2015-12-11 16:28:44 -0800 | [diff] [blame] | 132 | strbuf << " HOST_VISIBLE"; |
Jesse Hall | d1af812 | 2015-11-29 23:50:38 -0800 | [diff] [blame] | 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"; |
Jesse Hall | 73ab0ac | 2015-08-25 15:09:15 +0100 | [diff] [blame] | 137 | if ((flags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) != 0) |
| 138 | strbuf << " LAZILY_ALLOCATED"; |
Jesse Hall | 1f91d39 | 2015-12-11 16:28:44 -0800 | [diff] [blame] | 139 | printf(" Type %u:%s\n", type, strbuf.str().c_str()); |
Jesse Hall | 73ab0ac | 2015-08-25 15:09:15 +0100 | [diff] [blame] | 140 | strbuf.str(std::string()); |
| 141 | } |
| 142 | } |
Jesse Hall | 5ae3abb | 2015-10-08 14:00:22 -0700 | [diff] [blame] | 143 | |
| 144 | uint32_t num_queue_families; |
Jesse Hall | 606a54e | 2015-11-19 22:17:28 -0800 | [diff] [blame] | 145 | vkGetPhysicalDeviceQueueFamilyProperties(pdev, &num_queue_families, |
| 146 | nullptr); |
Jesse Hall | 5ae3abb | 2015-10-08 14:00:22 -0700 | [diff] [blame] | 147 | std::vector<VkQueueFamilyProperties> queue_family_properties( |
| 148 | num_queue_families); |
Jesse Hall | 606a54e | 2015-11-19 22:17:28 -0800 | [diff] [blame] | 149 | vkGetPhysicalDeviceQueueFamilyProperties(pdev, &num_queue_families, |
| 150 | queue_family_properties.data()); |
Jesse Hall | 5ae3abb | 2015-10-08 14:00:22 -0700 | [diff] [blame] | 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 | } |
Jesse Hall | acfa534 | 2015-11-19 21:51:33 -0800 | [diff] [blame] | 161 | printf(" Queue Family %u: %2ux %s timestamps:%ub\n", family, |
Jesse Hall | 5ae3abb | 2015-10-08 14:00:22 -0700 | [diff] [blame] | 162 | qprops.queueCount, strbuf.str().c_str(), |
Jesse Hall | acfa534 | 2015-11-19 21:51:33 -0800 | [diff] [blame] | 163 | qprops.timestampValidBits); |
Jesse Hall | 5ae3abb | 2015-10-08 14:00:22 -0700 | [diff] [blame] | 164 | strbuf.str(std::string()); |
| 165 | } |
Jesse Hall | 04f4f47 | 2015-08-16 19:51:04 -0700 | [diff] [blame] | 166 | } |
| 167 | |
Jesse Hall | c1ab303 | 2016-01-04 07:26:53 -0800 | [diff] [blame] | 168 | void 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 | |
| 184 | void 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 | |
| 203 | void 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 | |
| 209 | void 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 | |
Jesse Hall | 04f4f47 | 2015-08-16 19:51:04 -0700 | [diff] [blame] | 231 | } // namespace |
| 232 | |
| 233 | int main(int /*argc*/, char const* /*argv*/ []) { |
Jesse Hall | c1ab303 | 2016-01-04 07:26:53 -0800 | [diff] [blame] | 234 | VulkanInfo info; |
| 235 | GatherInfo(&info); |
| 236 | PrintInfo(info); |
| 237 | |
Jesse Hall | 04f4f47 | 2015-08-16 19:51:04 -0700 | [diff] [blame] | 238 | VkResult result; |
| 239 | |
| 240 | VkInstance instance; |
| 241 | const VkInstanceCreateInfo create_info = { |
| 242 | .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, |
| 243 | .pNext = nullptr, |
Jesse Hall | 3fbc856 | 2015-11-29 22:10:52 -0800 | [diff] [blame] | 244 | .pApplicationInfo = nullptr, |
Jesse Hall | 03b6fe1 | 2015-11-24 12:44:21 -0800 | [diff] [blame] | 245 | .enabledLayerNameCount = 0, |
Jesse Hall | 04f4f47 | 2015-08-16 19:51:04 -0700 | [diff] [blame] | 246 | .ppEnabledLayerNames = nullptr, |
Jesse Hall | 03b6fe1 | 2015-11-24 12:44:21 -0800 | [diff] [blame] | 247 | .enabledExtensionNameCount = 0, |
Jesse Hall | 04f4f47 | 2015-08-16 19:51:04 -0700 | [diff] [blame] | 248 | .ppEnabledExtensionNames = nullptr, |
| 249 | }; |
Jesse Hall | 03b6fe1 | 2015-11-24 12:44:21 -0800 | [diff] [blame] | 250 | result = vkCreateInstance(&create_info, nullptr, &instance); |
Jesse Hall | 04f4f47 | 2015-08-16 19:51:04 -0700 | [diff] [blame] | 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 | } |
Jesse Hall | c1ab303 | 2016-01-04 07:26:53 -0800 | [diff] [blame] | 271 | printf("PhysicalDevices [%zu]:\n", physical_devices.size()); |
Jesse Hall | 04f4f47 | 2015-08-16 19:51:04 -0700 | [diff] [blame] | 272 | for (uint32_t i = 0; i < physical_devices.size(); i++) |
| 273 | DumpPhysicalDevice(i, physical_devices[i]); |
| 274 | |
Jesse Hall | 03b6fe1 | 2015-11-24 12:44:21 -0800 | [diff] [blame] | 275 | vkDestroyInstance(instance, nullptr); |
Jesse Hall | 04f4f47 | 2015-08-16 19:51:04 -0700 | [diff] [blame] | 276 | |
| 277 | return 0; |
| 278 | } |