vkinfo.cpp revision b147127b06c1ce6443839e8102d1ed2631a57b07
1d02edcbb40d476b6d3b5ae279a6ccef786be8848Jesse Hall/*
2d02edcbb40d476b6d3b5ae279a6ccef786be8848Jesse Hall * Copyright 2015 The Android Open Source Project
3d02edcbb40d476b6d3b5ae279a6ccef786be8848Jesse Hall *
4d02edcbb40d476b6d3b5ae279a6ccef786be8848Jesse Hall * Licensed under the Apache License, Version 2.0 (the "License");
5d02edcbb40d476b6d3b5ae279a6ccef786be8848Jesse Hall * you may not use this file except in compliance with the License.
6d02edcbb40d476b6d3b5ae279a6ccef786be8848Jesse Hall * You may obtain a copy of the License at
7d02edcbb40d476b6d3b5ae279a6ccef786be8848Jesse Hall *
8d02edcbb40d476b6d3b5ae279a6ccef786be8848Jesse Hall *      http://www.apache.org/licenses/LICENSE-2.0
9d02edcbb40d476b6d3b5ae279a6ccef786be8848Jesse Hall *
10d02edcbb40d476b6d3b5ae279a6ccef786be8848Jesse Hall * Unless required by applicable law or agreed to in writing, software
11d02edcbb40d476b6d3b5ae279a6ccef786be8848Jesse Hall * distributed under the License is distributed on an "AS IS" BASIS,
12d02edcbb40d476b6d3b5ae279a6ccef786be8848Jesse Hall * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d02edcbb40d476b6d3b5ae279a6ccef786be8848Jesse Hall * See the License for the specific language governing permissions and
14d02edcbb40d476b6d3b5ae279a6ccef786be8848Jesse Hall * limitations under the License.
15d02edcbb40d476b6d3b5ae279a6ccef786be8848Jesse Hall */
16d02edcbb40d476b6d3b5ae279a6ccef786be8848Jesse Hall
174da3bd68ab085b1e07304e64d3deada3dac994e0Jesse Hall#include <algorithm>
184da3bd68ab085b1e07304e64d3deada3dac994e0Jesse Hall#include <array>
1973ab0acc1990326b4e51b675f4b2b44b6366c0a7Jesse Hall#include <inttypes.h>
2004f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall#include <stdlib.h>
211f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall#include <sstream>
2204f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall#include <vector>
2304f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall
2404f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall#include <vulkan/vulkan.h>
254da3bd68ab085b1e07304e64d3deada3dac994e0Jesse Hall#include <vulkan/vk_ext_debug_report.h>
2604f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall
2704f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall#define LOG_TAG "vkinfo"
2804f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall#include <log/log.h>
2904f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall
3004f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hallnamespace {
3104f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall
3209559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hallstruct GpuInfo {
3309559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    VkPhysicalDeviceProperties properties;
3409559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    VkPhysicalDeviceMemoryProperties memory;
35b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    VkPhysicalDeviceFeatures features;
3609559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    std::vector<VkQueueFamilyProperties> queue_families;
376e4ab316ba910c70a25c5264b3edabb759819098Jesse Hall    std::vector<VkExtensionProperties> extensions;
386e4ab316ba910c70a25c5264b3edabb759819098Jesse Hall    std::vector<VkLayerProperties> layers;
396e4ab316ba910c70a25c5264b3edabb759819098Jesse Hall    std::vector<std::vector<VkExtensionProperties>> layer_extensions;
4009559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall};
4109559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hallstruct VulkanInfo {
4209559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    std::vector<VkExtensionProperties> extensions;
4309559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    std::vector<VkLayerProperties> layers;
4409559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    std::vector<std::vector<VkExtensionProperties>> layer_extensions;
4509559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    std::vector<GpuInfo> gpus;
4609559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall};
4709559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall
4809559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall// ----------------------------------------------------------------------------
4909559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall
5004f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall[[noreturn]] void die(const char* proc, VkResult result) {
5104f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall    const char* result_str;
5204f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall    switch (result) {
5304f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall        // clang-format off
5404f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall        case VK_SUCCESS: result_str = "VK_SUCCESS"; break;
5504f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall        case VK_NOT_READY: result_str = "VK_NOT_READY"; break;
5604f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall        case VK_TIMEOUT: result_str = "VK_TIMEOUT"; break;
5704f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall        case VK_EVENT_SET: result_str = "VK_EVENT_SET"; break;
5804f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall        case VK_EVENT_RESET: result_str = "VK_EVENT_RESET"; break;
5904f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall        case VK_INCOMPLETE: result_str = "VK_INCOMPLETE"; break;
6004f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall        case VK_ERROR_OUT_OF_HOST_MEMORY: result_str = "VK_ERROR_OUT_OF_HOST_MEMORY"; break;
6104f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall        case VK_ERROR_OUT_OF_DEVICE_MEMORY: result_str = "VK_ERROR_OUT_OF_DEVICE_MEMORY"; break;
625ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall        case VK_ERROR_INITIALIZATION_FAILED: result_str = "VK_ERROR_INITIALIZATION_FAILED"; break;
6304f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall        case VK_ERROR_DEVICE_LOST: result_str = "VK_ERROR_DEVICE_LOST"; break;
6404f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall        case VK_ERROR_MEMORY_MAP_FAILED: result_str = "VK_ERROR_MEMORY_MAP_FAILED"; break;
655ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall        case VK_ERROR_LAYER_NOT_PRESENT: result_str = "VK_ERROR_LAYER_NOT_PRESENT"; break;
665ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall        case VK_ERROR_EXTENSION_NOT_PRESENT: result_str = "VK_ERROR_EXTENSION_NOT_PRESENT"; break;
6704f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall        case VK_ERROR_INCOMPATIBLE_DRIVER: result_str = "VK_ERROR_INCOMPATIBLE_DRIVER"; break;
6804f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall        default: result_str = "<unknown VkResult>"; break;
6904f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall            // clang-format on
7004f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall    }
7104f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall    fprintf(stderr, "%s failed: %s (%d)\n", proc, result_str, result);
7204f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall    exit(1);
7304f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall}
7404f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall
754da3bd68ab085b1e07304e64d3deada3dac994e0Jesse Hallbool HasExtension(const std::vector<VkExtensionProperties>& extensions,
764da3bd68ab085b1e07304e64d3deada3dac994e0Jesse Hall                  const char* name) {
774da3bd68ab085b1e07304e64d3deada3dac994e0Jesse Hall    return std::find_if(extensions.cbegin(), extensions.cend(),
784da3bd68ab085b1e07304e64d3deada3dac994e0Jesse Hall                        [=](const VkExtensionProperties& prop) {
794da3bd68ab085b1e07304e64d3deada3dac994e0Jesse Hall                            return strcmp(prop.extensionName, name) == 0;
804da3bd68ab085b1e07304e64d3deada3dac994e0Jesse Hall                        }) != extensions.end();
814da3bd68ab085b1e07304e64d3deada3dac994e0Jesse Hall}
824da3bd68ab085b1e07304e64d3deada3dac994e0Jesse Hall
8309559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hallvoid EnumerateInstanceExtensions(
8409559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    const char* layer_name,
8509559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    std::vector<VkExtensionProperties>* extensions) {
8609559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    VkResult result;
8709559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    uint32_t count;
8809559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    result =
8909559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall        vkEnumerateInstanceExtensionProperties(layer_name, &count, nullptr);
9009559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    if (result != VK_SUCCESS)
9109559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall        die("vkEnumerateInstanceExtensionProperties (count)", result);
9209559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    do {
9309559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall        extensions->resize(count);
9409559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall        result = vkEnumerateInstanceExtensionProperties(layer_name, &count,
9509559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall                                                        extensions->data());
9609559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    } while (result == VK_INCOMPLETE);
9709559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    if (result != VK_SUCCESS)
9809559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall        die("vkEnumerateInstanceExtensionProperties (data)", result);
9909559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall}
10009559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall
1016e4ab316ba910c70a25c5264b3edabb759819098Jesse Hallvoid EnumerateDeviceExtensions(VkPhysicalDevice gpu,
1026e4ab316ba910c70a25c5264b3edabb759819098Jesse Hall                               const char* layer_name,
1036e4ab316ba910c70a25c5264b3edabb759819098Jesse Hall                               std::vector<VkExtensionProperties>* extensions) {
1046e4ab316ba910c70a25c5264b3edabb759819098Jesse Hall    VkResult result;
1056e4ab316ba910c70a25c5264b3edabb759819098Jesse Hall    uint32_t count;
1066e4ab316ba910c70a25c5264b3edabb759819098Jesse Hall    result =
1076e4ab316ba910c70a25c5264b3edabb759819098Jesse Hall        vkEnumerateDeviceExtensionProperties(gpu, layer_name, &count, nullptr);
1086e4ab316ba910c70a25c5264b3edabb759819098Jesse Hall    if (result != VK_SUCCESS)
1096e4ab316ba910c70a25c5264b3edabb759819098Jesse Hall        die("vkEnumerateDeviceExtensionProperties (count)", result);
1106e4ab316ba910c70a25c5264b3edabb759819098Jesse Hall    do {
1116e4ab316ba910c70a25c5264b3edabb759819098Jesse Hall        extensions->resize(count);
1126e4ab316ba910c70a25c5264b3edabb759819098Jesse Hall        result = vkEnumerateDeviceExtensionProperties(gpu, layer_name, &count,
1136e4ab316ba910c70a25c5264b3edabb759819098Jesse Hall                                                      extensions->data());
1146e4ab316ba910c70a25c5264b3edabb759819098Jesse Hall    } while (result == VK_INCOMPLETE);
1156e4ab316ba910c70a25c5264b3edabb759819098Jesse Hall    if (result != VK_SUCCESS)
1166e4ab316ba910c70a25c5264b3edabb759819098Jesse Hall        die("vkEnumerateDeviceExtensionProperties (data)", result);
1176e4ab316ba910c70a25c5264b3edabb759819098Jesse Hall}
1186e4ab316ba910c70a25c5264b3edabb759819098Jesse Hall
119b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hallvoid GatherGpuInfo(VkPhysicalDevice gpu, GpuInfo& info) {
120b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    VkResult result;
121b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    uint32_t count;
122b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall
123b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    vkGetPhysicalDeviceProperties(gpu, &info.properties);
124b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    vkGetPhysicalDeviceMemoryProperties(gpu, &info.memory);
125b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    vkGetPhysicalDeviceFeatures(gpu, &info.features);
126b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall
127b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    vkGetPhysicalDeviceQueueFamilyProperties(gpu, &count, nullptr);
128b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    info.queue_families.resize(count);
129b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    vkGetPhysicalDeviceQueueFamilyProperties(gpu, &count,
130b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall                                             info.queue_families.data());
131b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall
132b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    result = vkEnumerateDeviceLayerProperties(gpu, &count, nullptr);
133b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    if (result != VK_SUCCESS)
134b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall        die("vkEnumerateDeviceLayerProperties (count)", result);
135b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    do {
136b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall        info.layers.resize(count);
137b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall        result =
138b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall            vkEnumerateDeviceLayerProperties(gpu, &count, info.layers.data());
139b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    } while (result == VK_INCOMPLETE);
140b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    if (result != VK_SUCCESS)
141b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall        die("vkEnumerateDeviceLayerProperties (data)", result);
142b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    info.layer_extensions.resize(info.layers.size());
143b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall
144b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    EnumerateDeviceExtensions(gpu, nullptr, &info.extensions);
145b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    for (size_t i = 0; i < info.layers.size(); i++) {
146b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall        EnumerateDeviceExtensions(gpu, info.layers[i].layerName,
147b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall                                  &info.layer_extensions[i]);
148b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    }
149b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall
150b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    const std::array<const char*, 1> kDesiredExtensions = {
151b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall        {VK_KHR_SWAPCHAIN_EXTENSION_NAME},
152b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    };
153b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    const char* extensions[kDesiredExtensions.size()];
154b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    uint32_t num_extensions = 0;
155b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    for (const auto& desired_ext : kDesiredExtensions) {
156b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall        bool available = HasExtension(info.extensions, desired_ext);
157b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall        for (size_t i = 0; !available && i < info.layer_extensions.size(); i++)
158b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall            available = HasExtension(info.layer_extensions[i], desired_ext);
159b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall        if (available)
160b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall            extensions[num_extensions++] = desired_ext;
161b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    }
162b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall
163b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    VkDevice device;
164b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    const VkDeviceQueueCreateInfo queue_create_info = {
165b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall        .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
166b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall        .queueFamilyIndex = 0,
167b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall        .queueCount = 1,
168b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    };
169b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    const VkDeviceCreateInfo create_info = {
170b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall        .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
171b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall        .queueCreateInfoCount = 1,
172b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall        .pQueueCreateInfos = &queue_create_info,
173b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall        .enabledExtensionCount = num_extensions,
174b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall        .ppEnabledExtensionNames = extensions,
175b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall        .pEnabledFeatures = &info.features,
176b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    };
177b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    result = vkCreateDevice(gpu, &create_info, nullptr, &device);
178b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    if (result != VK_SUCCESS)
179b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall        die("vkCreateDevice", result);
180b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    vkDestroyDevice(device, nullptr);
181b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall}
182b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall
18309559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hallvoid GatherInfo(VulkanInfo* info) {
18409559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    VkResult result;
18509559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    uint32_t count;
18609559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall
18709559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    result = vkEnumerateInstanceLayerProperties(&count, nullptr);
18809559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    if (result != VK_SUCCESS)
18909559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall        die("vkEnumerateInstanceLayerProperties (count)", result);
19009559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    do {
19109559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall        info->layers.resize(count);
19209559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall        result =
19309559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall            vkEnumerateInstanceLayerProperties(&count, info->layers.data());
19409559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    } while (result == VK_INCOMPLETE);
19509559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    if (result != VK_SUCCESS)
19609559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall        die("vkEnumerateInstanceLayerProperties (data)", result);
19709559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    info->layer_extensions.resize(info->layers.size());
19809559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall
19909559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    EnumerateInstanceExtensions(nullptr, &info->extensions);
20009559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    for (size_t i = 0; i < info->layers.size(); i++) {
20109559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall        EnumerateInstanceExtensions(info->layers[i].layerName,
20209559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall                                    &info->layer_extensions[i]);
20309559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    }
20409559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall
2054da3bd68ab085b1e07304e64d3deada3dac994e0Jesse Hall    const std::array<const char*, 1> kDesiredExtensions = {
2064da3bd68ab085b1e07304e64d3deada3dac994e0Jesse Hall        {VK_EXT_DEBUG_REPORT_EXTENSION_NAME},
2074da3bd68ab085b1e07304e64d3deada3dac994e0Jesse Hall    };
2084da3bd68ab085b1e07304e64d3deada3dac994e0Jesse Hall    const char* extensions[kDesiredExtensions.size()];
2094da3bd68ab085b1e07304e64d3deada3dac994e0Jesse Hall    uint32_t num_extensions = 0;
2104da3bd68ab085b1e07304e64d3deada3dac994e0Jesse Hall    for (const auto& desired_ext : kDesiredExtensions) {
2114da3bd68ab085b1e07304e64d3deada3dac994e0Jesse Hall        bool available = HasExtension(info->extensions, desired_ext);
2124da3bd68ab085b1e07304e64d3deada3dac994e0Jesse Hall        for (size_t i = 0; !available && i < info->layer_extensions.size(); i++)
2134da3bd68ab085b1e07304e64d3deada3dac994e0Jesse Hall            available = HasExtension(info->layer_extensions[i], desired_ext);
2144da3bd68ab085b1e07304e64d3deada3dac994e0Jesse Hall        if (available)
2154da3bd68ab085b1e07304e64d3deada3dac994e0Jesse Hall            extensions[num_extensions++] = desired_ext;
2164da3bd68ab085b1e07304e64d3deada3dac994e0Jesse Hall    }
2174da3bd68ab085b1e07304e64d3deada3dac994e0Jesse Hall
21809559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    const VkInstanceCreateInfo create_info = {
21909559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall        .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
2204da3bd68ab085b1e07304e64d3deada3dac994e0Jesse Hall        .enabledExtensionCount = num_extensions,
2214da3bd68ab085b1e07304e64d3deada3dac994e0Jesse Hall        .ppEnabledExtensionNames = extensions,
22209559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    };
2234da3bd68ab085b1e07304e64d3deada3dac994e0Jesse Hall    VkInstance instance;
22409559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    result = vkCreateInstance(&create_info, nullptr, &instance);
22509559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    if (result != VK_SUCCESS)
22609559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall        die("vkCreateInstance", result);
22709559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall
22809559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    uint32_t num_gpus;
22909559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    result = vkEnumeratePhysicalDevices(instance, &num_gpus, nullptr);
23009559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    if (result != VK_SUCCESS)
23109559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall        die("vkEnumeratePhysicalDevices (count)", result);
23209559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    std::vector<VkPhysicalDevice> gpus(num_gpus, VK_NULL_HANDLE);
23309559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    do {
23409559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall        gpus.resize(num_gpus, VK_NULL_HANDLE);
23509559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall        result = vkEnumeratePhysicalDevices(instance, &num_gpus, gpus.data());
23609559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    } while (result == VK_INCOMPLETE);
23709559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    if (result != VK_SUCCESS)
23809559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall        die("vkEnumeratePhysicalDevices (data)", result);
23909559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall
24009559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    info->gpus.resize(num_gpus);
241b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    for (size_t i = 0; i < gpus.size(); i++)
242b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall        GatherGpuInfo(gpus[i], info->gpus.at(i));
24309559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall
24409559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    vkDestroyInstance(instance, nullptr);
24509559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall}
24609559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall
24709559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall// ----------------------------------------------------------------------------
24809559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall
249c1ab303f6fc8339d386d6cf127534677929fddfbJesse Halluint32_t ExtractMajorVersion(uint32_t version) {
250c1ab303f6fc8339d386d6cf127534677929fddfbJesse Hall    return (version >> 22) & 0x3FF;
251c1ab303f6fc8339d386d6cf127534677929fddfbJesse Hall}
252c1ab303f6fc8339d386d6cf127534677929fddfbJesse Halluint32_t ExtractMinorVersion(uint32_t version) {
253c1ab303f6fc8339d386d6cf127534677929fddfbJesse Hall    return (version >> 12) & 0x3FF;
254c1ab303f6fc8339d386d6cf127534677929fddfbJesse Hall}
255c1ab303f6fc8339d386d6cf127534677929fddfbJesse Halluint32_t ExtractPatchVersion(uint32_t version) {
256c1ab303f6fc8339d386d6cf127534677929fddfbJesse Hall    return (version >> 0) & 0xFFF;
257c1ab303f6fc8339d386d6cf127534677929fddfbJesse Hall}
258c1ab303f6fc8339d386d6cf127534677929fddfbJesse Hall
25904f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hallconst char* VkPhysicalDeviceTypeStr(VkPhysicalDeviceType type) {
26004f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall    switch (type) {
26104f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall        case VK_PHYSICAL_DEVICE_TYPE_OTHER:
26204f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall            return "OTHER";
26304f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall        case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
26404f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall            return "INTEGRATED_GPU";
26504f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall        case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
26604f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall            return "DISCRETE_GPU";
26704f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall        case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:
26804f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall            return "VIRTUAL_GPU";
26904f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall        case VK_PHYSICAL_DEVICE_TYPE_CPU:
27004f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall            return "CPU";
27104f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall        default:
27204f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall            return "<UNKNOWN>";
27304f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall    }
27404f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall}
27504f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall
2765ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hallconst char* VkQueueFlagBitStr(VkQueueFlagBits bit) {
2775ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall    switch (bit) {
2785ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall        case VK_QUEUE_GRAPHICS_BIT:
2795ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall            return "GRAPHICS";
2805ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall        case VK_QUEUE_COMPUTE_BIT:
2815ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall            return "COMPUTE";
28265ab552c18df3e94c5d275294a20dd4d20dda119Jesse Hall        case VK_QUEUE_TRANSFER_BIT:
28365ab552c18df3e94c5d275294a20dd4d20dda119Jesse Hall            return "TRANSFER";
284b00daadc165d4c3fad13b7cc4aeaa1e85e6df9a0Jesse Hall        case VK_QUEUE_SPARSE_BINDING_BIT:
2855ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall            return "SPARSE";
2865ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall    }
2875ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall}
2885ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall
28909559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hallvoid PrintExtensions(const std::vector<VkExtensionProperties>& extensions,
29009559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall                     const char* prefix) {
29109559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    for (const auto& e : extensions)
2928966bf4149947dfc6d8ee0251efffc3a75663543Jesse Hall        printf("%s%s (v%u)\n", prefix, e.extensionName, e.specVersion);
29309559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall}
294c1ab303f6fc8339d386d6cf127534677929fddfbJesse Hall
295aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hallvoid PrintLayers(
296aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    const std::vector<VkLayerProperties>& layers,
297aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    const std::vector<std::vector<VkExtensionProperties>> extensions,
298aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    const char* prefix) {
299aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    std::string ext_prefix(prefix);
300aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    ext_prefix.append("    ");
301aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    for (size_t i = 0; i < layers.size(); i++) {
302aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        printf(
303aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            "%s%s %u.%u.%u/%u\n"
304aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            "%s  %s\n",
305aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            prefix, layers[i].layerName,
306aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            ExtractMajorVersion(layers[i].specVersion),
307aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            ExtractMinorVersion(layers[i].specVersion),
308aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            ExtractPatchVersion(layers[i].specVersion),
309aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            layers[i].implementationVersion, prefix, layers[i].description);
310aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        if (!extensions[i].empty())
311aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall            printf("%s  Extensions [%zu]:\n", prefix, extensions[i].size());
312aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        PrintExtensions(extensions[i], ext_prefix.c_str());
313aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall    }
314aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall}
315aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall
31609559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hallvoid PrintGpuInfo(const GpuInfo& info) {
31704f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall    VkResult result;
31873ab0acc1990326b4e51b675f4b2b44b6366c0a7Jesse Hall    std::ostringstream strbuf;
31904f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall
3208966bf4149947dfc6d8ee0251efffc3a75663543Jesse Hall    printf("  \"%s\" (%s) %u.%u.%u/%#x [%04x:%04x]\n",
32109559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall           info.properties.deviceName,
32209559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall           VkPhysicalDeviceTypeStr(info.properties.deviceType),
32309559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall           ExtractMajorVersion(info.properties.apiVersion),
32409559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall           ExtractMinorVersion(info.properties.apiVersion),
32509559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall           ExtractPatchVersion(info.properties.apiVersion),
32609559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall           info.properties.driverVersion, info.properties.vendorID,
32709559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall           info.properties.deviceID);
32809559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall
32909559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    for (uint32_t heap = 0; heap < info.memory.memoryHeapCount; heap++) {
33009559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall        if ((info.memory.memoryHeaps[heap].flags &
331d1af812f20e0793d94702817d441ab799bf46df7Jesse Hall             VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) != 0)
332d1af812f20e0793d94702817d441ab799bf46df7Jesse Hall            strbuf << "DEVICE_LOCAL";
3338966bf4149947dfc6d8ee0251efffc3a75663543Jesse Hall        printf("    Heap %u: %" PRIu64 " MiB (0x%" PRIx64 " B) %s\n", heap,
3348966bf4149947dfc6d8ee0251efffc3a75663543Jesse Hall               info.memory.memoryHeaps[heap].size / 0x1000000,
33509559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall               info.memory.memoryHeaps[heap].size, strbuf.str().c_str());
33673ab0acc1990326b4e51b675f4b2b44b6366c0a7Jesse Hall        strbuf.str(std::string());
33773ab0acc1990326b4e51b675f4b2b44b6366c0a7Jesse Hall
33809559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall        for (uint32_t type = 0; type < info.memory.memoryTypeCount; type++) {
33909559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall            if (info.memory.memoryTypes[type].heapIndex != heap)
34073ab0acc1990326b4e51b675f4b2b44b6366c0a7Jesse Hall                continue;
34173ab0acc1990326b4e51b675f4b2b44b6366c0a7Jesse Hall            VkMemoryPropertyFlags flags =
34209559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall                info.memory.memoryTypes[type].propertyFlags;
343d1af812f20e0793d94702817d441ab799bf46df7Jesse Hall            if ((flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) != 0)
3441f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall                strbuf << " DEVICE_LOCAL";
34573ab0acc1990326b4e51b675f4b2b44b6366c0a7Jesse Hall            if ((flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0)
3461f91d390ac013ea2514a67e12ddb083119d636d7Jesse Hall                strbuf << " HOST_VISIBLE";
347d1af812f20e0793d94702817d441ab799bf46df7Jesse Hall            if ((flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) != 0)
348d1af812f20e0793d94702817d441ab799bf46df7Jesse Hall                strbuf << " COHERENT";
349d1af812f20e0793d94702817d441ab799bf46df7Jesse Hall            if ((flags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) != 0)
350d1af812f20e0793d94702817d441ab799bf46df7Jesse Hall                strbuf << " CACHED";
35173ab0acc1990326b4e51b675f4b2b44b6366c0a7Jesse Hall            if ((flags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) != 0)
35273ab0acc1990326b4e51b675f4b2b44b6366c0a7Jesse Hall                strbuf << " LAZILY_ALLOCATED";
35309559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall            printf("      Type %u:%s\n", type, strbuf.str().c_str());
35473ab0acc1990326b4e51b675f4b2b44b6366c0a7Jesse Hall            strbuf.str(std::string());
35573ab0acc1990326b4e51b675f4b2b44b6366c0a7Jesse Hall        }
35673ab0acc1990326b4e51b675f4b2b44b6366c0a7Jesse Hall    }
3575ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall
35809559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    for (uint32_t family = 0; family < info.queue_families.size(); family++) {
35909559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall        const VkQueueFamilyProperties& qprops = info.queue_families[family];
3608966bf4149947dfc6d8ee0251efffc3a75663543Jesse Hall        VkQueueFlags flags = qprops.queueFlags;
3618966bf4149947dfc6d8ee0251efffc3a75663543Jesse Hall        char flags_str[5];
3628966bf4149947dfc6d8ee0251efffc3a75663543Jesse Hall        flags_str[0] = (flags & VK_QUEUE_GRAPHICS_BIT) ? 'G' : '_';
3638966bf4149947dfc6d8ee0251efffc3a75663543Jesse Hall        flags_str[1] = (flags & VK_QUEUE_COMPUTE_BIT) ? 'C' : '_';
3648966bf4149947dfc6d8ee0251efffc3a75663543Jesse Hall        flags_str[2] = (flags & VK_QUEUE_TRANSFER_BIT) ? 'T' : '_';
3658966bf4149947dfc6d8ee0251efffc3a75663543Jesse Hall        flags_str[3] = (flags & VK_QUEUE_SPARSE_BINDING_BIT) ? 'S' : '_';
3668966bf4149947dfc6d8ee0251efffc3a75663543Jesse Hall        flags_str[4] = '\0';
3678966bf4149947dfc6d8ee0251efffc3a75663543Jesse Hall        printf(
3688966bf4149947dfc6d8ee0251efffc3a75663543Jesse Hall            "    Queue Family %u: %ux %s\n"
3698966bf4149947dfc6d8ee0251efffc3a75663543Jesse Hall            "      timestampValidBits: %ub\n"
3708966bf4149947dfc6d8ee0251efffc3a75663543Jesse Hall            "      minImageTransferGranularity: (%u,%u,%u)\n",
3718966bf4149947dfc6d8ee0251efffc3a75663543Jesse Hall            family, qprops.queueCount, flags_str, qprops.timestampValidBits,
3728966bf4149947dfc6d8ee0251efffc3a75663543Jesse Hall            qprops.minImageTransferGranularity.width,
3738966bf4149947dfc6d8ee0251efffc3a75663543Jesse Hall            qprops.minImageTransferGranularity.height,
3748966bf4149947dfc6d8ee0251efffc3a75663543Jesse Hall            qprops.minImageTransferGranularity.depth);
375b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    }
3766e4ab316ba910c70a25c5264b3edabb759819098Jesse Hall
377b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    if (!info.extensions.empty()) {
378b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall        printf("    Extensions [%zu]:\n", info.extensions.size());
379b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall        PrintExtensions(info.extensions, "      ");
380b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    }
381b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall    if (!info.layers.empty()) {
382b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall        printf("    Layers [%zu]:\n", info.layers.size());
383b147127b06c1ce6443839e8102d1ed2631a57b07Jesse Hall        PrintLayers(info.layers, info.layer_extensions, "      ");
3845ae3abb3ca6728de04935b0c81bcdbdfc37b0d47Jesse Hall    }
38504f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall}
38604f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall
387c1ab303f6fc8339d386d6cf127534677929fddfbJesse Hallvoid PrintInfo(const VulkanInfo& info) {
38809559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    std::ostringstream strbuf;
38909559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall
39030ac78b43ce408eb6d666c8667d184b8e44ed9e6Jesse Hall    printf("Instance Extensions [%zu]:\n", info.extensions.size());
391c1ab303f6fc8339d386d6cf127534677929fddfbJesse Hall    PrintExtensions(info.extensions, "  ");
392c1ab303f6fc8339d386d6cf127534677929fddfbJesse Hall    if (!info.layers.empty()) {
39330ac78b43ce408eb6d666c8667d184b8e44ed9e6Jesse Hall        printf("Instance Layers [%zu]:\n", info.layers.size());
394aa410941d29cba4a3a56e90cb3f0be3f03c76ceaJesse Hall        PrintLayers(info.layers, info.layer_extensions, "  ");
395c1ab303f6fc8339d386d6cf127534677929fddfbJesse Hall    }
39609559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall
39709559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    printf("PhysicalDevices [%zu]:\n", info.gpus.size());
39809559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall    for (const auto& gpu : info.gpus)
39909559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall        PrintGpuInfo(gpu);
400c1ab303f6fc8339d386d6cf127534677929fddfbJesse Hall}
401c1ab303f6fc8339d386d6cf127534677929fddfbJesse Hall
40204f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall}  // namespace
40304f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall
40409559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall// ----------------------------------------------------------------------------
40509559b53a83342ee8b4c5ae3e29bb252a02908dbJesse Hall
40604f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hallint main(int /*argc*/, char const* /*argv*/ []) {
407c1ab303f6fc8339d386d6cf127534677929fddfbJesse Hall    VulkanInfo info;
408c1ab303f6fc8339d386d6cf127534677929fddfbJesse Hall    GatherInfo(&info);
409c1ab303f6fc8339d386d6cf127534677929fddfbJesse Hall    PrintInfo(info);
41004f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall    return 0;
41104f4f4746481571148eaf3aaf768ee5c6dccec9dJesse Hall}
412