vulkaninfo.c revision 5d8d6b4f93daceacca1de36be6de935a8264caf6
1/*
2 * Copyright (c) 2015-2016 The Khronos Group Inc.
3 * Copyright (c) 2015-2016 Valve Corporation
4 * Copyright (c) 2015-2016 LunarG, Inc.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 *     http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
19 * Author: David Pinedo <david@lunarg.com>
20 * Author: Mark Lobodzinski <mark@lunarg.com>
21 * Author: Rene Lindsay <rene@lunarg.com>
22 * Author: Jeremy Kniager <jeremyk@lunarg.com>
23 */
24
25#ifdef __GNUC__
26#ifndef _POSIX_C_SOURCE
27#define _POSIX_C_SOURCE 200809L
28#endif
29#else
30#define strndup(p, n) strdup(p)
31#endif
32
33#include <assert.h>
34#include <inttypes.h>
35#include <stdbool.h>
36#include <stdio.h>
37#include <stdlib.h>
38#include <string.h>
39
40#ifdef _WIN32
41#include <fcntl.h>
42#include <io.h>
43#endif  // _WIN32
44
45#if defined(VK_USE_PLATFORM_XLIB_KHR) || defined(VK_USE_PLATFORM_XCB_KHR)
46#include <X11/Xutil.h>
47#endif
48
49#if defined(VK_USE_PLATFORM_MIR_KHR)
50#warning "Vulkaninfo does not have code for Mir at this time"
51#endif
52
53#include <vulkan/vulkan.h>
54
55#define ERR(err) printf("%s:%d: failed with %s\n", __FILE__, __LINE__, VkResultString(err));
56
57#ifdef _WIN32
58
59#define snprintf _snprintf
60#define strdup   _strdup
61
62// Returns nonzero if the console is used only for this process. Will return
63// zero if another process (such as cmd.exe) is also attached.
64static int ConsoleIsExclusive(void) {
65    DWORD pids[2];
66    DWORD num_pids = GetConsoleProcessList(pids, ARRAYSIZE(pids));
67    return num_pids <= 1;
68}
69
70#define WAIT_FOR_CONSOLE_DESTROY                   \
71    do {                                           \
72        if (ConsoleIsExclusive()) Sleep(INFINITE); \
73    } while (0)
74#else
75#define WAIT_FOR_CONSOLE_DESTROY
76#endif
77
78#define ERR_EXIT(err)             \
79    do {                          \
80        ERR(err);                 \
81        fflush(stdout);           \
82        WAIT_FOR_CONSOLE_DESTROY; \
83        exit(-1);                 \
84    } while (0)
85
86#if defined(NDEBUG) && defined(__GNUC__)
87#define U_ASSERT_ONLY __attribute__((unused))
88#else
89#define U_ASSERT_ONLY
90#endif
91
92#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
93
94#define MAX_QUEUE_TYPES 5
95#define APP_SHORT_NAME "vulkaninfo"
96
97static const VkFormat format_check_list[] = {VK_FORMAT_UNDEFINED,
98                                             VK_FORMAT_R4G4_UNORM_PACK8,
99                                             VK_FORMAT_R4G4B4A4_UNORM_PACK16,
100                                             VK_FORMAT_B4G4R4A4_UNORM_PACK16,
101                                             VK_FORMAT_R5G6B5_UNORM_PACK16,
102                                             VK_FORMAT_B5G6R5_UNORM_PACK16,
103                                             VK_FORMAT_R5G5B5A1_UNORM_PACK16,
104                                             VK_FORMAT_B5G5R5A1_UNORM_PACK16,
105                                             VK_FORMAT_A1R5G5B5_UNORM_PACK16,
106                                             VK_FORMAT_R8_UNORM,
107                                             VK_FORMAT_R8_SNORM,
108                                             VK_FORMAT_R8_USCALED,
109                                             VK_FORMAT_R8_SSCALED,
110                                             VK_FORMAT_R8_UINT,
111                                             VK_FORMAT_R8_SINT,
112                                             VK_FORMAT_R8_SRGB,
113                                             VK_FORMAT_R8G8_UNORM,
114                                             VK_FORMAT_R8G8_SNORM,
115                                             VK_FORMAT_R8G8_USCALED,
116                                             VK_FORMAT_R8G8_SSCALED,
117                                             VK_FORMAT_R8G8_UINT,
118                                             VK_FORMAT_R8G8_SINT,
119                                             VK_FORMAT_R8G8_SRGB,
120                                             VK_FORMAT_R8G8B8_UNORM,
121                                             VK_FORMAT_R8G8B8_SNORM,
122                                             VK_FORMAT_R8G8B8_USCALED,
123                                             VK_FORMAT_R8G8B8_SSCALED,
124                                             VK_FORMAT_R8G8B8_UINT,
125                                             VK_FORMAT_R8G8B8_SINT,
126                                             VK_FORMAT_R8G8B8_SRGB,
127                                             VK_FORMAT_B8G8R8_UNORM,
128                                             VK_FORMAT_B8G8R8_SNORM,
129                                             VK_FORMAT_B8G8R8_USCALED,
130                                             VK_FORMAT_B8G8R8_SSCALED,
131                                             VK_FORMAT_B8G8R8_UINT,
132                                             VK_FORMAT_B8G8R8_SINT,
133                                             VK_FORMAT_B8G8R8_SRGB,
134                                             VK_FORMAT_R8G8B8A8_UNORM,
135                                             VK_FORMAT_R8G8B8A8_SNORM,
136                                             VK_FORMAT_R8G8B8A8_USCALED,
137                                             VK_FORMAT_R8G8B8A8_SSCALED,
138                                             VK_FORMAT_R8G8B8A8_UINT,
139                                             VK_FORMAT_R8G8B8A8_SINT,
140                                             VK_FORMAT_R8G8B8A8_SRGB,
141                                             VK_FORMAT_B8G8R8A8_UNORM,
142                                             VK_FORMAT_B8G8R8A8_SNORM,
143                                             VK_FORMAT_B8G8R8A8_USCALED,
144                                             VK_FORMAT_B8G8R8A8_SSCALED,
145                                             VK_FORMAT_B8G8R8A8_UINT,
146                                             VK_FORMAT_B8G8R8A8_SINT,
147                                             VK_FORMAT_B8G8R8A8_SRGB,
148                                             VK_FORMAT_A8B8G8R8_UNORM_PACK32,
149                                             VK_FORMAT_A8B8G8R8_SNORM_PACK32,
150                                             VK_FORMAT_A8B8G8R8_USCALED_PACK32,
151                                             VK_FORMAT_A8B8G8R8_SSCALED_PACK32,
152                                             VK_FORMAT_A8B8G8R8_UINT_PACK32,
153                                             VK_FORMAT_A8B8G8R8_SINT_PACK32,
154                                             VK_FORMAT_A8B8G8R8_SRGB_PACK32,
155                                             VK_FORMAT_A2R10G10B10_UNORM_PACK32,
156                                             VK_FORMAT_A2R10G10B10_SNORM_PACK32,
157                                             VK_FORMAT_A2R10G10B10_USCALED_PACK32,
158                                             VK_FORMAT_A2R10G10B10_SSCALED_PACK32,
159                                             VK_FORMAT_A2R10G10B10_UINT_PACK32,
160                                             VK_FORMAT_A2R10G10B10_SINT_PACK32,
161                                             VK_FORMAT_A2B10G10R10_UNORM_PACK32,
162                                             VK_FORMAT_A2B10G10R10_SNORM_PACK32,
163                                             VK_FORMAT_A2B10G10R10_USCALED_PACK32,
164                                             VK_FORMAT_A2B10G10R10_SSCALED_PACK32,
165                                             VK_FORMAT_A2B10G10R10_UINT_PACK32,
166                                             VK_FORMAT_A2B10G10R10_SINT_PACK32,
167                                             VK_FORMAT_R16_UNORM,
168                                             VK_FORMAT_R16_SNORM,
169                                             VK_FORMAT_R16_USCALED,
170                                             VK_FORMAT_R16_SSCALED,
171                                             VK_FORMAT_R16_UINT,
172                                             VK_FORMAT_R16_SINT,
173                                             VK_FORMAT_R16_SFLOAT,
174                                             VK_FORMAT_R16G16_UNORM,
175                                             VK_FORMAT_R16G16_SNORM,
176                                             VK_FORMAT_R16G16_USCALED,
177                                             VK_FORMAT_R16G16_SSCALED,
178                                             VK_FORMAT_R16G16_UINT,
179                                             VK_FORMAT_R16G16_SINT,
180                                             VK_FORMAT_R16G16_SFLOAT,
181                                             VK_FORMAT_R16G16B16_UNORM,
182                                             VK_FORMAT_R16G16B16_SNORM,
183                                             VK_FORMAT_R16G16B16_USCALED,
184                                             VK_FORMAT_R16G16B16_SSCALED,
185                                             VK_FORMAT_R16G16B16_UINT,
186                                             VK_FORMAT_R16G16B16_SINT,
187                                             VK_FORMAT_R16G16B16_SFLOAT,
188                                             VK_FORMAT_R16G16B16A16_UNORM,
189                                             VK_FORMAT_R16G16B16A16_SNORM,
190                                             VK_FORMAT_R16G16B16A16_USCALED,
191                                             VK_FORMAT_R16G16B16A16_SSCALED,
192                                             VK_FORMAT_R16G16B16A16_UINT,
193                                             VK_FORMAT_R16G16B16A16_SINT,
194                                             VK_FORMAT_R16G16B16A16_SFLOAT,
195                                             VK_FORMAT_R32_UINT,
196                                             VK_FORMAT_R32_SINT,
197                                             VK_FORMAT_R32_SFLOAT,
198                                             VK_FORMAT_R32G32_UINT,
199                                             VK_FORMAT_R32G32_SINT,
200                                             VK_FORMAT_R32G32_SFLOAT,
201                                             VK_FORMAT_R32G32B32_UINT,
202                                             VK_FORMAT_R32G32B32_SINT,
203                                             VK_FORMAT_R32G32B32_SFLOAT,
204                                             VK_FORMAT_R32G32B32A32_UINT,
205                                             VK_FORMAT_R32G32B32A32_SINT,
206                                             VK_FORMAT_R32G32B32A32_SFLOAT,
207                                             VK_FORMAT_R64_UINT,
208                                             VK_FORMAT_R64_SINT,
209                                             VK_FORMAT_R64_SFLOAT,
210                                             VK_FORMAT_R64G64_UINT,
211                                             VK_FORMAT_R64G64_SINT,
212                                             VK_FORMAT_R64G64_SFLOAT,
213                                             VK_FORMAT_R64G64B64_UINT,
214                                             VK_FORMAT_R64G64B64_SINT,
215                                             VK_FORMAT_R64G64B64_SFLOAT,
216                                             VK_FORMAT_R64G64B64A64_UINT,
217                                             VK_FORMAT_R64G64B64A64_SINT,
218                                             VK_FORMAT_R64G64B64A64_SFLOAT,
219                                             VK_FORMAT_B10G11R11_UFLOAT_PACK32,
220                                             VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
221                                             VK_FORMAT_D16_UNORM,
222                                             VK_FORMAT_X8_D24_UNORM_PACK32,
223                                             VK_FORMAT_D32_SFLOAT,
224                                             VK_FORMAT_S8_UINT,
225                                             VK_FORMAT_D16_UNORM_S8_UINT,
226                                             VK_FORMAT_D24_UNORM_S8_UINT,
227                                             VK_FORMAT_D32_SFLOAT_S8_UINT,
228                                             VK_FORMAT_BC1_RGB_UNORM_BLOCK,
229                                             VK_FORMAT_BC1_RGB_SRGB_BLOCK,
230                                             VK_FORMAT_BC1_RGBA_UNORM_BLOCK,
231                                             VK_FORMAT_BC1_RGBA_SRGB_BLOCK,
232                                             VK_FORMAT_BC2_UNORM_BLOCK,
233                                             VK_FORMAT_BC2_SRGB_BLOCK,
234                                             VK_FORMAT_BC3_UNORM_BLOCK,
235                                             VK_FORMAT_BC3_SRGB_BLOCK,
236                                             VK_FORMAT_BC4_UNORM_BLOCK,
237                                             VK_FORMAT_BC4_SNORM_BLOCK,
238                                             VK_FORMAT_BC5_UNORM_BLOCK,
239                                             VK_FORMAT_BC5_SNORM_BLOCK,
240                                             VK_FORMAT_BC6H_UFLOAT_BLOCK,
241                                             VK_FORMAT_BC6H_SFLOAT_BLOCK,
242                                             VK_FORMAT_BC7_UNORM_BLOCK,
243                                             VK_FORMAT_BC7_SRGB_BLOCK,
244                                             VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,
245                                             VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK,
246                                             VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK,
247                                             VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK,
248                                             VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK,
249                                             VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK,
250                                             VK_FORMAT_EAC_R11_UNORM_BLOCK,
251                                             VK_FORMAT_EAC_R11_SNORM_BLOCK,
252                                             VK_FORMAT_EAC_R11G11_UNORM_BLOCK,
253                                             VK_FORMAT_EAC_R11G11_SNORM_BLOCK,
254                                             VK_FORMAT_ASTC_4x4_UNORM_BLOCK,
255                                             VK_FORMAT_ASTC_4x4_SRGB_BLOCK,
256                                             VK_FORMAT_ASTC_5x4_UNORM_BLOCK,
257                                             VK_FORMAT_ASTC_5x4_SRGB_BLOCK,
258                                             VK_FORMAT_ASTC_5x5_UNORM_BLOCK,
259                                             VK_FORMAT_ASTC_5x5_SRGB_BLOCK,
260                                             VK_FORMAT_ASTC_6x5_UNORM_BLOCK,
261                                             VK_FORMAT_ASTC_6x5_SRGB_BLOCK,
262                                             VK_FORMAT_ASTC_6x6_UNORM_BLOCK,
263                                             VK_FORMAT_ASTC_6x6_SRGB_BLOCK,
264                                             VK_FORMAT_ASTC_8x5_UNORM_BLOCK,
265                                             VK_FORMAT_ASTC_8x5_SRGB_BLOCK,
266                                             VK_FORMAT_ASTC_8x6_UNORM_BLOCK,
267                                             VK_FORMAT_ASTC_8x6_SRGB_BLOCK,
268                                             VK_FORMAT_ASTC_8x8_UNORM_BLOCK,
269                                             VK_FORMAT_ASTC_8x8_SRGB_BLOCK,
270                                             VK_FORMAT_ASTC_10x5_UNORM_BLOCK,
271                                             VK_FORMAT_ASTC_10x5_SRGB_BLOCK,
272                                             VK_FORMAT_ASTC_10x6_UNORM_BLOCK,
273                                             VK_FORMAT_ASTC_10x6_SRGB_BLOCK,
274                                             VK_FORMAT_ASTC_10x8_UNORM_BLOCK,
275                                             VK_FORMAT_ASTC_10x8_SRGB_BLOCK,
276                                             VK_FORMAT_ASTC_10x10_UNORM_BLOCK,
277                                             VK_FORMAT_ASTC_10x10_SRGB_BLOCK,
278                                             VK_FORMAT_ASTC_12x10_UNORM_BLOCK,
279                                             VK_FORMAT_ASTC_12x10_SRGB_BLOCK,
280                                             VK_FORMAT_ASTC_12x12_UNORM_BLOCK,
281                                             VK_FORMAT_ASTC_12x12_SRGB_BLOCK,
282                                             VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG,
283                                             VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG,
284                                             VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG,
285                                             VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG,
286                                             VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG,
287                                             VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG,
288                                             VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG,
289                                             VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG};
290
291static const uint32_t format_check_list_count = ARRAY_SIZE(format_check_list);
292
293struct VkStructureHeader {
294    VkStructureType sType;
295    void *pNext;
296};
297
298struct AppGpu;
299
300struct AppDev {
301    struct AppGpu *gpu; /* point back to the GPU */
302
303    VkDevice obj;
304
305    VkFormatProperties format_props[ARRAY_SIZE(format_check_list)];
306    VkFormatProperties2KHR format_props2[ARRAY_SIZE(format_check_list)];
307};
308
309struct LayerExtensionList {
310    VkLayerProperties layer_properties;
311    uint32_t extension_count;
312    VkExtensionProperties *extension_properties;
313};
314
315struct AppInstance {
316    VkInstance instance;
317    uint32_t global_layer_count;
318    struct LayerExtensionList *global_layers;
319    uint32_t global_extension_count;
320    VkExtensionProperties *global_extensions;  // Instance Extensions
321
322    const char **inst_extensions;
323    uint32_t inst_extensions_count;
324
325    PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR;
326    PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR;
327    PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR;
328    PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR;
329    PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR;
330    PFN_vkGetPhysicalDeviceFormatProperties2KHR vkGetPhysicalDeviceFormatProperties2KHR;
331    PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR vkGetPhysicalDeviceQueueFamilyProperties2KHR;
332    PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR;
333    PFN_vkGetPhysicalDeviceMemoryProperties2KHR vkGetPhysicalDeviceMemoryProperties2KHR;
334    PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR vkGetPhysicalDeviceSurfaceCapabilities2KHR;
335    PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT vkGetPhysicalDeviceSurfaceCapabilities2EXT;
336
337    VkSurfaceCapabilitiesKHR surface_capabilities;
338    VkSurfaceCapabilities2KHR surface_capabilities2;
339    VkSharedPresentSurfaceCapabilitiesKHR shared_surface_capabilities;
340    VkSurfaceCapabilities2EXT surface_capabilities2_ext;
341
342    VkSurfaceKHR surface;
343    int width, height;
344
345#ifdef VK_USE_PLATFORM_WIN32_KHR
346    HINSTANCE h_instance;  // Windows Instance
347    HWND h_wnd;            // window handle
348#elif VK_USE_PLATFORM_XCB_KHR
349    xcb_connection_t *xcb_connection;
350    xcb_screen_t *xcb_screen;
351    xcb_window_t xcb_window;
352#elif VK_USE_PLATFORM_XLIB_KHR
353    Display *xlib_display;
354    Window xlib_window;
355#elif VK_USE_PLATFORM_ANDROID_KHR  // TODO
356    ANativeWindow *window;
357#endif
358};
359
360struct AppGpu {
361    uint32_t id;
362    VkPhysicalDevice obj;
363
364    VkPhysicalDeviceProperties props;
365    VkPhysicalDeviceProperties2KHR props2;
366
367    uint32_t queue_count;
368    VkQueueFamilyProperties *queue_props;
369    VkQueueFamilyProperties2KHR *queue_props2;
370    VkDeviceQueueCreateInfo *queue_reqs;
371
372    struct AppInstance *inst;
373
374    VkPhysicalDeviceMemoryProperties memory_props;
375    VkPhysicalDeviceMemoryProperties2KHR memory_props2;
376
377    VkPhysicalDeviceFeatures features;
378    VkPhysicalDeviceFeatures2KHR features2;
379    VkPhysicalDevice limits;
380
381    uint32_t device_extension_count;
382    VkExtensionProperties *device_extensions;
383
384    struct AppDev dev;
385};
386
387static VKAPI_ATTR VkBool32 VKAPI_CALL DbgCallback(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject,
388                                                  size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg,
389                                                  void *pUserData) {
390    char *message = (char *)malloc(strlen(pMsg) + 100);
391
392    assert(message);
393
394    if (msgFlags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
395        sprintf(message, "ERROR: [%s] Code %d : %s", pLayerPrefix, msgCode, pMsg);
396    } else if (msgFlags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
397        sprintf(message, "WARNING: [%s] Code %d : %s", pLayerPrefix, msgCode, pMsg);
398    } else if (msgFlags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) {
399        sprintf(message, "INFO: [%s] Code %d : %s", pLayerPrefix, msgCode, pMsg);
400    } else if (msgFlags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) {
401        sprintf(message, "DEBUG: [%s] Code %d : %s", pLayerPrefix, msgCode, pMsg);
402    }
403
404    printf("%s\n", message);
405    fflush(stdout);
406    free(message);
407
408    /*
409     * false indicates that layer should not bail-out of an
410     * API call that had validation failures. This may mean that the
411     * app dies inside the driver due to invalid parameter(s).
412     * That's what would happen without validation layers, so we'll
413     * keep that behavior here.
414     */
415    return false;
416}
417
418static const char *VkResultString(VkResult err) {
419    switch (err) {
420#define STR(r) \
421    case r:    \
422        return #r
423        STR(VK_SUCCESS);
424        STR(VK_NOT_READY);
425        STR(VK_TIMEOUT);
426        STR(VK_EVENT_SET);
427        STR(VK_EVENT_RESET);
428        STR(VK_ERROR_INITIALIZATION_FAILED);
429        STR(VK_ERROR_OUT_OF_HOST_MEMORY);
430        STR(VK_ERROR_OUT_OF_DEVICE_MEMORY);
431        STR(VK_ERROR_DEVICE_LOST);
432        STR(VK_ERROR_LAYER_NOT_PRESENT);
433        STR(VK_ERROR_EXTENSION_NOT_PRESENT);
434        STR(VK_ERROR_MEMORY_MAP_FAILED);
435        STR(VK_ERROR_INCOMPATIBLE_DRIVER);
436#undef STR
437        default:
438            return "UNKNOWN_RESULT";
439    }
440}
441
442static const char *VkPhysicalDeviceTypeString(VkPhysicalDeviceType type) {
443    switch (type) {
444#define STR(r)                        \
445    case VK_PHYSICAL_DEVICE_TYPE_##r: \
446        return #r
447        STR(OTHER);
448        STR(INTEGRATED_GPU);
449        STR(DISCRETE_GPU);
450        STR(VIRTUAL_GPU);
451        STR(CPU);
452#undef STR
453        default:
454            return "UNKNOWN_DEVICE";
455    }
456}
457
458static const char *VkFormatString(VkFormat fmt) {
459    switch (fmt) {
460#define STR(r)          \
461    case VK_FORMAT_##r: \
462        return #r
463        STR(UNDEFINED);
464        STR(R4G4_UNORM_PACK8);
465        STR(R4G4B4A4_UNORM_PACK16);
466        STR(B4G4R4A4_UNORM_PACK16);
467        STR(R5G6B5_UNORM_PACK16);
468        STR(B5G6R5_UNORM_PACK16);
469        STR(R5G5B5A1_UNORM_PACK16);
470        STR(B5G5R5A1_UNORM_PACK16);
471        STR(A1R5G5B5_UNORM_PACK16);
472        STR(R8_UNORM);
473        STR(R8_SNORM);
474        STR(R8_USCALED);
475        STR(R8_SSCALED);
476        STR(R8_UINT);
477        STR(R8_SINT);
478        STR(R8_SRGB);
479        STR(R8G8_UNORM);
480        STR(R8G8_SNORM);
481        STR(R8G8_USCALED);
482        STR(R8G8_SSCALED);
483        STR(R8G8_UINT);
484        STR(R8G8_SINT);
485        STR(R8G8_SRGB);
486        STR(R8G8B8_UNORM);
487        STR(R8G8B8_SNORM);
488        STR(R8G8B8_USCALED);
489        STR(R8G8B8_SSCALED);
490        STR(R8G8B8_UINT);
491        STR(R8G8B8_SINT);
492        STR(R8G8B8_SRGB);
493        STR(B8G8R8_UNORM);
494        STR(B8G8R8_SNORM);
495        STR(B8G8R8_USCALED);
496        STR(B8G8R8_SSCALED);
497        STR(B8G8R8_UINT);
498        STR(B8G8R8_SINT);
499        STR(B8G8R8_SRGB);
500        STR(R8G8B8A8_UNORM);
501        STR(R8G8B8A8_SNORM);
502        STR(R8G8B8A8_USCALED);
503        STR(R8G8B8A8_SSCALED);
504        STR(R8G8B8A8_UINT);
505        STR(R8G8B8A8_SINT);
506        STR(R8G8B8A8_SRGB);
507        STR(B8G8R8A8_UNORM);
508        STR(B8G8R8A8_SNORM);
509        STR(B8G8R8A8_USCALED);
510        STR(B8G8R8A8_SSCALED);
511        STR(B8G8R8A8_UINT);
512        STR(B8G8R8A8_SINT);
513        STR(B8G8R8A8_SRGB);
514        STR(A8B8G8R8_UNORM_PACK32);
515        STR(A8B8G8R8_SNORM_PACK32);
516        STR(A8B8G8R8_USCALED_PACK32);
517        STR(A8B8G8R8_SSCALED_PACK32);
518        STR(A8B8G8R8_UINT_PACK32);
519        STR(A8B8G8R8_SINT_PACK32);
520        STR(A8B8G8R8_SRGB_PACK32);
521        STR(A2R10G10B10_UNORM_PACK32);
522        STR(A2R10G10B10_SNORM_PACK32);
523        STR(A2R10G10B10_USCALED_PACK32);
524        STR(A2R10G10B10_SSCALED_PACK32);
525        STR(A2R10G10B10_UINT_PACK32);
526        STR(A2R10G10B10_SINT_PACK32);
527        STR(A2B10G10R10_UNORM_PACK32);
528        STR(A2B10G10R10_SNORM_PACK32);
529        STR(A2B10G10R10_USCALED_PACK32);
530        STR(A2B10G10R10_SSCALED_PACK32);
531        STR(A2B10G10R10_UINT_PACK32);
532        STR(A2B10G10R10_SINT_PACK32);
533        STR(R16_UNORM);
534        STR(R16_SNORM);
535        STR(R16_USCALED);
536        STR(R16_SSCALED);
537        STR(R16_UINT);
538        STR(R16_SINT);
539        STR(R16_SFLOAT);
540        STR(R16G16_UNORM);
541        STR(R16G16_SNORM);
542        STR(R16G16_USCALED);
543        STR(R16G16_SSCALED);
544        STR(R16G16_UINT);
545        STR(R16G16_SINT);
546        STR(R16G16_SFLOAT);
547        STR(R16G16B16_UNORM);
548        STR(R16G16B16_SNORM);
549        STR(R16G16B16_USCALED);
550        STR(R16G16B16_SSCALED);
551        STR(R16G16B16_UINT);
552        STR(R16G16B16_SINT);
553        STR(R16G16B16_SFLOAT);
554        STR(R16G16B16A16_UNORM);
555        STR(R16G16B16A16_SNORM);
556        STR(R16G16B16A16_USCALED);
557        STR(R16G16B16A16_SSCALED);
558        STR(R16G16B16A16_UINT);
559        STR(R16G16B16A16_SINT);
560        STR(R16G16B16A16_SFLOAT);
561        STR(R32_UINT);
562        STR(R32_SINT);
563        STR(R32_SFLOAT);
564        STR(R32G32_UINT);
565        STR(R32G32_SINT);
566        STR(R32G32_SFLOAT);
567        STR(R32G32B32_UINT);
568        STR(R32G32B32_SINT);
569        STR(R32G32B32_SFLOAT);
570        STR(R32G32B32A32_UINT);
571        STR(R32G32B32A32_SINT);
572        STR(R32G32B32A32_SFLOAT);
573        STR(R64_UINT);
574        STR(R64_SINT);
575        STR(R64_SFLOAT);
576        STR(R64G64_UINT);
577        STR(R64G64_SINT);
578        STR(R64G64_SFLOAT);
579        STR(R64G64B64_UINT);
580        STR(R64G64B64_SINT);
581        STR(R64G64B64_SFLOAT);
582        STR(R64G64B64A64_UINT);
583        STR(R64G64B64A64_SINT);
584        STR(R64G64B64A64_SFLOAT);
585        STR(B10G11R11_UFLOAT_PACK32);
586        STR(E5B9G9R9_UFLOAT_PACK32);
587        STR(D16_UNORM);
588        STR(X8_D24_UNORM_PACK32);
589        STR(D32_SFLOAT);
590        STR(S8_UINT);
591        STR(D16_UNORM_S8_UINT);
592        STR(D24_UNORM_S8_UINT);
593        STR(D32_SFLOAT_S8_UINT);
594        STR(BC1_RGB_UNORM_BLOCK);
595        STR(BC1_RGB_SRGB_BLOCK);
596        STR(BC2_UNORM_BLOCK);
597        STR(BC2_SRGB_BLOCK);
598        STR(BC3_UNORM_BLOCK);
599        STR(BC3_SRGB_BLOCK);
600        STR(BC4_UNORM_BLOCK);
601        STR(BC4_SNORM_BLOCK);
602        STR(BC5_UNORM_BLOCK);
603        STR(BC5_SNORM_BLOCK);
604        STR(BC6H_UFLOAT_BLOCK);
605        STR(BC6H_SFLOAT_BLOCK);
606        STR(BC7_UNORM_BLOCK);
607        STR(BC7_SRGB_BLOCK);
608        STR(ETC2_R8G8B8_UNORM_BLOCK);
609        STR(ETC2_R8G8B8A1_UNORM_BLOCK);
610        STR(ETC2_R8G8B8A8_UNORM_BLOCK);
611        STR(EAC_R11_UNORM_BLOCK);
612        STR(EAC_R11_SNORM_BLOCK);
613        STR(EAC_R11G11_UNORM_BLOCK);
614        STR(EAC_R11G11_SNORM_BLOCK);
615        STR(ASTC_4x4_UNORM_BLOCK);
616        STR(ASTC_4x4_SRGB_BLOCK);
617        STR(ASTC_5x4_UNORM_BLOCK);
618        STR(ASTC_5x4_SRGB_BLOCK);
619        STR(ASTC_5x5_UNORM_BLOCK);
620        STR(ASTC_5x5_SRGB_BLOCK);
621        STR(ASTC_6x5_UNORM_BLOCK);
622        STR(ASTC_6x5_SRGB_BLOCK);
623        STR(ASTC_6x6_UNORM_BLOCK);
624        STR(ASTC_6x6_SRGB_BLOCK);
625        STR(ASTC_8x5_UNORM_BLOCK);
626        STR(ASTC_8x5_SRGB_BLOCK);
627        STR(ASTC_8x6_UNORM_BLOCK);
628        STR(ASTC_8x6_SRGB_BLOCK);
629        STR(ASTC_8x8_UNORM_BLOCK);
630        STR(ASTC_8x8_SRGB_BLOCK);
631        STR(ASTC_10x5_UNORM_BLOCK);
632        STR(ASTC_10x5_SRGB_BLOCK);
633        STR(ASTC_10x6_UNORM_BLOCK);
634        STR(ASTC_10x6_SRGB_BLOCK);
635        STR(ASTC_10x8_UNORM_BLOCK);
636        STR(ASTC_10x8_SRGB_BLOCK);
637        STR(ASTC_10x10_UNORM_BLOCK);
638        STR(ASTC_10x10_SRGB_BLOCK);
639        STR(ASTC_12x10_UNORM_BLOCK);
640        STR(ASTC_12x10_SRGB_BLOCK);
641        STR(ASTC_12x12_UNORM_BLOCK);
642        STR(ASTC_12x12_SRGB_BLOCK);
643#undef STR
644        default:
645            return "UNKNOWN_FORMAT";
646    }
647}
648#if defined(VK_USE_PLATFORM_XCB_KHR) || defined(VK_USE_PLATFORM_XLIB_KHR) || defined(VK_USE_PLATFORM_WIN32_KHR)
649static const char *VkPresentModeString(VkPresentModeKHR mode) {
650    switch (mode) {
651#define STR(r)                \
652    case VK_PRESENT_MODE_##r: \
653        return #r
654        STR(IMMEDIATE_KHR);
655        STR(MAILBOX_KHR);
656        STR(FIFO_KHR);
657        STR(FIFO_RELAXED_KHR);
658#undef STR
659        default:
660            return "UNKNOWN_FORMAT";
661    }
662}
663#endif
664
665static bool CheckExtensionEnabled(const char *extension_to_check, const char **extension_list, uint32_t extension_count) {
666    for (uint32_t i = 0; i < extension_count; i++) {
667        if (!strcmp(extension_to_check, extension_list[i])) return true;
668    }
669    return false;
670}
671
672static void AppDevInitFormats(struct AppDev *dev) {
673    for (uint32_t i = 0; i < format_check_list_count; i++) {
674        vkGetPhysicalDeviceFormatProperties(dev->gpu->obj, format_check_list[i], &dev->format_props[i]);
675
676        if (CheckExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, dev->gpu->inst->inst_extensions,
677                                  dev->gpu->inst->inst_extensions_count)) {
678            dev->format_props2[i].sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR;
679            dev->format_props2[i].pNext = NULL;
680            dev->gpu->inst->vkGetPhysicalDeviceFormatProperties2KHR(dev->gpu->obj, format_check_list[i], &dev->format_props2[i]);
681        }
682    }
683}
684
685static void ExtractVersion(uint32_t version, uint32_t *major, uint32_t *minor, uint32_t *patch) {
686    *major = version >> 22;
687    *minor = (version >> 12) & 0x3ff;
688    *patch = version & 0xfff;
689}
690
691static void AppGetPhysicalDeviceLayerExtensions(struct AppGpu *gpu, char *layer_name, uint32_t *extension_count,
692                                                VkExtensionProperties **extension_properties) {
693    VkResult err;
694    uint32_t ext_count = 0;
695    VkExtensionProperties *ext_ptr = NULL;
696
697    /* repeat get until VK_INCOMPLETE goes away */
698    do {
699        err = vkEnumerateDeviceExtensionProperties(gpu->obj, layer_name, &ext_count, NULL);
700        assert(!err);
701
702        if (ext_ptr) {
703            free(ext_ptr);
704        }
705        ext_ptr = malloc(ext_count * sizeof(VkExtensionProperties));
706        err = vkEnumerateDeviceExtensionProperties(gpu->obj, layer_name, &ext_count, ext_ptr);
707    } while (err == VK_INCOMPLETE);
708    assert(!err);
709
710    *extension_count = ext_count;
711    *extension_properties = ext_ptr;
712}
713
714static void AppDevInit(struct AppDev *dev, struct AppGpu *gpu) {
715    VkDeviceCreateInfo info = {
716        .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
717        .pNext = NULL,
718        .flags = 0,
719        .queueCreateInfoCount = 0,
720        .pQueueCreateInfos = NULL,
721        .enabledLayerCount = 0,
722        .ppEnabledLayerNames = NULL,
723        .enabledExtensionCount = 0,
724        .ppEnabledExtensionNames = NULL,
725    };
726    VkResult U_ASSERT_ONLY err;
727
728    // Device extensions
729    AppGetPhysicalDeviceLayerExtensions(gpu, NULL, &gpu->device_extension_count, &gpu->device_extensions);
730
731    fflush(stdout);
732
733    /* request all queues */
734    info.queueCreateInfoCount = gpu->queue_count;
735    info.pQueueCreateInfos = gpu->queue_reqs;
736
737    info.enabledLayerCount = 0;
738    info.ppEnabledLayerNames = NULL;
739    info.enabledExtensionCount = 0;
740    info.ppEnabledExtensionNames = NULL;
741    dev->gpu = gpu;
742    err = vkCreateDevice(gpu->obj, &info, NULL, &dev->obj);
743    if (err) ERR_EXIT(err);
744}
745
746static void AppDevDestroy(struct AppDev *dev) {
747    vkDeviceWaitIdle(dev->obj);
748    vkDestroyDevice(dev->obj, NULL);
749}
750
751static void AppGetGlobalLayerExtensions(char *layer_name, uint32_t *extension_count, VkExtensionProperties **extension_properties) {
752    VkResult err;
753    uint32_t ext_count = 0;
754    VkExtensionProperties *ext_ptr = NULL;
755
756    /* repeat get until VK_INCOMPLETE goes away */
757    do {
758        // gets the extension count if the last parameter is NULL
759        err = vkEnumerateInstanceExtensionProperties(layer_name, &ext_count, NULL);
760        assert(!err);
761
762        if (ext_ptr) {
763            free(ext_ptr);
764        }
765        ext_ptr = malloc(ext_count * sizeof(VkExtensionProperties));
766        // gets the extension properties if the last parameter is not NULL
767        err = vkEnumerateInstanceExtensionProperties(layer_name, &ext_count, ext_ptr);
768    } while (err == VK_INCOMPLETE);
769    assert(!err);
770    *extension_count = ext_count;
771    *extension_properties = ext_ptr;
772}
773
774/* Gets a list of layer and instance extensions */
775static void AppGetInstanceExtensions(struct AppInstance *inst) {
776    VkResult U_ASSERT_ONLY err;
777
778    uint32_t count = 0;
779
780    /* Scan layers */
781    VkLayerProperties *global_layer_properties = NULL;
782    struct LayerExtensionList *global_layers = NULL;
783
784    do {
785        err = vkEnumerateInstanceLayerProperties(&count, NULL);
786        assert(!err);
787
788        if (global_layer_properties) {
789            free(global_layer_properties);
790        }
791        global_layer_properties = malloc(sizeof(VkLayerProperties) * count);
792        assert(global_layer_properties);
793
794        if (global_layers) {
795            free(global_layers);
796        }
797        global_layers = malloc(sizeof(struct LayerExtensionList) * count);
798        assert(global_layers);
799
800        err = vkEnumerateInstanceLayerProperties(&count, global_layer_properties);
801    } while (err == VK_INCOMPLETE);
802    assert(!err);
803
804    inst->global_layer_count = count;
805    inst->global_layers = global_layers;
806
807    for (uint32_t i = 0; i < inst->global_layer_count; i++) {
808        VkLayerProperties *src_info = &global_layer_properties[i];
809        struct LayerExtensionList *dst_info = &inst->global_layers[i];
810        memcpy(&dst_info->layer_properties, src_info, sizeof(VkLayerProperties));
811
812        // Save away layer extension info for report
813        // Gets layer extensions, if first parameter is not NULL
814        AppGetGlobalLayerExtensions(src_info->layerName, &dst_info->extension_count, &dst_info->extension_properties);
815    }
816    free(global_layer_properties);
817
818    // Collect global extensions
819    inst->global_extension_count = 0;
820    // Gets instance extensions, if no layer was specified in the first
821    // paramteter
822    AppGetGlobalLayerExtensions(NULL, &inst->global_extension_count, &inst->global_extensions);
823}
824
825static void AppCreateInstance(struct AppInstance *inst) {
826    AppGetInstanceExtensions(inst);
827
828//---Build a list of extensions to load---
829
830    const char *info_instance_extensions[] = {VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
831                                              VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME,
832                                              VK_KHR_SURFACE_EXTENSION_NAME,
833                                              VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME,
834                                              VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME,
835#ifdef VK_USE_PLATFORM_WIN32_KHR
836                                              VK_KHR_WIN32_SURFACE_EXTENSION_NAME
837#elif VK_USE_PLATFORM_XCB_KHR
838                                              VK_KHR_XCB_SURFACE_EXTENSION_NAME
839#elif VK_USE_PLATFORM_XLIB_KHR
840                                              VK_KHR_XLIB_SURFACE_EXTENSION_NAME
841#elif VK_USE_PLATFORM_WAYLAND_KHR
842                                              VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME
843#elif VK_USE_PLATFORM_ANDROID_KHR
844                                              VK_KHR_ANDROID_SURFACE_EXTENSION_NAME
845#endif
846    };
847    uint32_t info_instance_extensions_count = ARRAY_SIZE(info_instance_extensions);
848    inst->inst_extensions = malloc(sizeof(char *) * ARRAY_SIZE(info_instance_extensions));
849    inst->inst_extensions_count = 0;
850
851    for (uint32_t k = 0; (k < info_instance_extensions_count); k++) {
852        for (uint32_t j = 0; (j < inst->global_extension_count); j++) {
853            const char *found_name = inst->global_extensions[j].extensionName;
854            if (!strcmp(info_instance_extensions[k], found_name)) {
855                inst->inst_extensions[inst->inst_extensions_count++] = info_instance_extensions[k];
856                break;
857            }
858        }
859    }
860
861    //----------------------------------------
862
863    const VkApplicationInfo app_info = {
864        .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
865        .pNext = NULL,
866        .pApplicationName = APP_SHORT_NAME,
867        .applicationVersion = 1,
868        .pEngineName = APP_SHORT_NAME,
869        .engineVersion = 1,
870        .apiVersion = VK_API_VERSION_1_0,
871    };
872
873    VkInstanceCreateInfo inst_info = {.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
874                                      .pNext = NULL,
875                                      .pApplicationInfo = &app_info,
876                                      .enabledLayerCount = 0,
877                                      .ppEnabledLayerNames = NULL,
878                                      .enabledExtensionCount = inst->inst_extensions_count,
879                                      .ppEnabledExtensionNames = inst->inst_extensions};
880
881    VkDebugReportCallbackCreateInfoEXT dbg_info;
882    memset(&dbg_info, 0, sizeof(dbg_info));
883    dbg_info.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
884    dbg_info.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_INFORMATION_BIT_EXT;
885    dbg_info.pfnCallback = DbgCallback;
886    inst_info.pNext = &dbg_info;
887
888    VkResult U_ASSERT_ONLY err;
889    err = vkCreateInstance(&inst_info, NULL, &inst->instance);
890    if (err == VK_ERROR_INCOMPATIBLE_DRIVER) {
891        printf("Cannot create Vulkan instance.\n");
892        ERR_EXIT(err);
893    } else if (err) {
894        ERR_EXIT(err);
895    }
896
897    inst->vkGetPhysicalDeviceSurfaceSupportKHR =
898        (PFN_vkGetPhysicalDeviceSurfaceSupportKHR)vkGetInstanceProcAddr(inst->instance, "vkGetPhysicalDeviceSurfaceSupportKHR");
899    inst->vkGetPhysicalDeviceSurfaceCapabilitiesKHR = (PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR)vkGetInstanceProcAddr(
900        inst->instance, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR");
901    inst->vkGetPhysicalDeviceSurfaceFormatsKHR =
902        (PFN_vkGetPhysicalDeviceSurfaceFormatsKHR)vkGetInstanceProcAddr(inst->instance, "vkGetPhysicalDeviceSurfaceFormatsKHR");
903    inst->vkGetPhysicalDeviceSurfacePresentModesKHR = (PFN_vkGetPhysicalDeviceSurfacePresentModesKHR)vkGetInstanceProcAddr(
904        inst->instance, "vkGetPhysicalDeviceSurfacePresentModesKHR");
905    inst->vkGetPhysicalDeviceProperties2KHR =
906        (PFN_vkGetPhysicalDeviceProperties2KHR)vkGetInstanceProcAddr(inst->instance, "vkGetPhysicalDeviceProperties2KHR");
907    inst->vkGetPhysicalDeviceFormatProperties2KHR = (PFN_vkGetPhysicalDeviceFormatProperties2KHR)vkGetInstanceProcAddr(
908        inst->instance, "vkGetPhysicalDeviceFormatProperties2KHR");
909    inst->vkGetPhysicalDeviceQueueFamilyProperties2KHR = (PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR)vkGetInstanceProcAddr(
910        inst->instance, "vkGetPhysicalDeviceQueueFamilyProperties2KHR");
911    inst->vkGetPhysicalDeviceFeatures2KHR =
912        (PFN_vkGetPhysicalDeviceFeatures2KHR)vkGetInstanceProcAddr(inst->instance, "vkGetPhysicalDeviceFeatures2KHR");
913    inst->vkGetPhysicalDeviceMemoryProperties2KHR = (PFN_vkGetPhysicalDeviceMemoryProperties2KHR)vkGetInstanceProcAddr(
914        inst->instance, "vkGetPhysicalDeviceMemoryProperties2KHR");
915    inst->vkGetPhysicalDeviceSurfaceCapabilities2KHR = (PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR)vkGetInstanceProcAddr(
916        inst->instance, "vkGetPhysicalDeviceSurfaceCapabilities2KHR");
917    inst->vkGetPhysicalDeviceSurfaceCapabilities2EXT = (PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT)vkGetInstanceProcAddr(
918        inst->instance, "vkGetPhysicalDeviceSurfaceCapabilities2EXT");
919}
920
921//-----------------------------------------------------------
922
923static void AppDestroyInstance(struct AppInstance *inst) {
924    free(inst->global_extensions);
925    for (uint32_t i = 0; i < inst->global_layer_count; i++) {
926        free(inst->global_layers[i].extension_properties);
927    }
928    free(inst->global_layers);
929    free(inst->inst_extensions);
930    vkDestroyInstance(inst->instance, NULL);
931}
932
933static void AppGpuInit(struct AppGpu *gpu, struct AppInstance *inst, uint32_t id, VkPhysicalDevice obj) {
934    uint32_t i;
935
936    memset(gpu, 0, sizeof(*gpu));
937
938    gpu->id = id;
939    gpu->obj = obj;
940    gpu->inst = inst;
941
942    vkGetPhysicalDeviceProperties(gpu->obj, &gpu->props);
943
944    if (CheckExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, gpu->inst->inst_extensions,
945                              gpu->inst->inst_extensions_count)) {
946        gpu->props2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR;
947        gpu->props2.pNext = NULL;
948
949        inst->vkGetPhysicalDeviceProperties2KHR(gpu->obj, &gpu->props2);
950    }
951
952    /* get queue count */
953    vkGetPhysicalDeviceQueueFamilyProperties(gpu->obj, &gpu->queue_count, NULL);
954
955    gpu->queue_props = malloc(sizeof(gpu->queue_props[0]) * gpu->queue_count);
956
957    if (!gpu->queue_props) ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY);
958    vkGetPhysicalDeviceQueueFamilyProperties(gpu->obj, &gpu->queue_count, gpu->queue_props);
959
960    if (CheckExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, gpu->inst->inst_extensions,
961                              gpu->inst->inst_extensions_count)) {
962        gpu->queue_props2 = malloc(sizeof(gpu->queue_props2[0]) * gpu->queue_count);
963
964        if (!gpu->queue_props2) ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY);
965
966        for (i = 0; i < gpu->queue_count; i++) {
967            gpu->queue_props2[i].sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR;
968            gpu->queue_props2[i].pNext = NULL;
969        }
970
971        inst->vkGetPhysicalDeviceQueueFamilyProperties2KHR(gpu->obj, &gpu->queue_count, gpu->queue_props2);
972    }
973
974    /* set up queue requests */
975    gpu->queue_reqs = malloc(sizeof(*gpu->queue_reqs) * gpu->queue_count);
976    if (!gpu->queue_reqs) ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY);
977    for (i = 0; i < gpu->queue_count; i++) {
978        float *queue_priorities = malloc(gpu->queue_props[i].queueCount * sizeof(float));
979        if (!queue_priorities) ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY);
980        memset(queue_priorities, 0, gpu->queue_props[i].queueCount * sizeof(float));
981
982        gpu->queue_reqs[i].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
983        gpu->queue_reqs[i].pNext = NULL;
984        gpu->queue_reqs[i].flags = 0;
985        gpu->queue_reqs[i].queueFamilyIndex = i;
986        gpu->queue_reqs[i].queueCount = gpu->queue_props[i].queueCount;
987        gpu->queue_reqs[i].pQueuePriorities = queue_priorities;
988    }
989
990    vkGetPhysicalDeviceMemoryProperties(gpu->obj, &gpu->memory_props);
991
992    vkGetPhysicalDeviceFeatures(gpu->obj, &gpu->features);
993
994    if (CheckExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, gpu->inst->inst_extensions,
995                              gpu->inst->inst_extensions_count)) {
996        gpu->memory_props2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR;
997        gpu->memory_props2.pNext = NULL;
998
999        inst->vkGetPhysicalDeviceMemoryProperties2KHR(gpu->obj, &gpu->memory_props2);
1000
1001        gpu->features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR;
1002        gpu->features2.pNext = NULL;
1003
1004        inst->vkGetPhysicalDeviceFeatures2KHR(gpu->obj, &gpu->features2);
1005    }
1006
1007    AppDevInit(&gpu->dev, gpu);
1008    AppDevInitFormats(&gpu->dev);
1009}
1010
1011static void AppGpuDestroy(struct AppGpu *gpu) {
1012    AppDevDestroy(&gpu->dev);
1013    free(gpu->device_extensions);
1014
1015    for (uint32_t i = 0; i < gpu->queue_count; i++) {
1016        free((void *)gpu->queue_reqs[i].pQueuePriorities);
1017    }
1018    free(gpu->queue_reqs);
1019
1020    free(gpu->queue_props);
1021    if (CheckExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, gpu->inst->inst_extensions,
1022                              gpu->inst->inst_extensions_count)) {
1023        free(gpu->queue_props2);
1024    }
1025}
1026
1027// clang-format off
1028
1029//-----------------------------------------------------------
1030
1031//---------------------------Win32---------------------------
1032#ifdef VK_USE_PLATFORM_WIN32_KHR
1033
1034// MS-Windows event handling function:
1035LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
1036    return (DefWindowProc(hWnd, uMsg, wParam, lParam));
1037}
1038
1039static void AppCreateWin32Window(struct AppInstance *inst) {
1040    inst->h_instance = GetModuleHandle(NULL);
1041
1042    WNDCLASSEX win_class;
1043
1044    // Initialize the window class structure:
1045    win_class.cbSize = sizeof(WNDCLASSEX);
1046    win_class.style = CS_HREDRAW | CS_VREDRAW;
1047    win_class.lpfnWndProc = WndProc;
1048    win_class.cbClsExtra = 0;
1049    win_class.cbWndExtra = 0;
1050    win_class.hInstance = inst->h_instance;
1051    win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
1052    win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
1053    win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
1054    win_class.lpszMenuName = NULL;
1055    win_class.lpszClassName = APP_SHORT_NAME;
1056    win_class.hInstance = inst->h_instance;
1057    win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
1058    // Register window class:
1059    if (!RegisterClassEx(&win_class)) {
1060        // It didn't work, so try to give a useful error:
1061        printf("Failed to register the window class!\n");
1062        fflush(stdout);
1063        exit(1);
1064    }
1065    // Create window with the registered class:
1066    RECT wr = { 0, 0, inst->width, inst->height };
1067    AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
1068    inst->h_wnd = CreateWindowEx(0,
1069        APP_SHORT_NAME,       // class name
1070        APP_SHORT_NAME,       // app name
1071        //WS_VISIBLE | WS_SYSMENU |
1072        WS_OVERLAPPEDWINDOW,  // window style
1073        100, 100,             // x/y coords
1074        wr.right - wr.left,   // width
1075        wr.bottom - wr.top,   // height
1076        NULL,                 // handle to parent
1077        NULL,                 // handle to menu
1078        inst->h_instance,      // hInstance
1079        NULL);                // no extra parameters
1080    if (!inst->h_wnd) {
1081        // It didn't work, so try to give a useful error:
1082        printf("Failed to create a window!\n");
1083        fflush(stdout);
1084        exit(1);
1085    }
1086}
1087
1088static void AppCreateWin32Surface(struct AppInstance *inst) {
1089    VkResult U_ASSERT_ONLY err;
1090    VkWin32SurfaceCreateInfoKHR createInfo;
1091    createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
1092    createInfo.pNext = NULL;
1093    createInfo.flags = 0;
1094    createInfo.hinstance = inst->h_instance;
1095    createInfo.hwnd = inst->h_wnd;
1096    err = vkCreateWin32SurfaceKHR(inst->instance, &createInfo, NULL, &inst->surface);
1097    assert(!err);
1098}
1099
1100static void AppDestroyWin32Window(struct AppInstance *inst) {
1101    DestroyWindow(inst->h_wnd);
1102}
1103#endif //VK_USE_PLATFORM_WIN32_KHR
1104//-----------------------------------------------------------
1105
1106#if defined(VK_USE_PLATFORM_XCB_KHR)     || \
1107    defined(VK_USE_PLATFORM_XLIB_KHR)    || \
1108    defined(VK_USE_PLATFORM_WIN32_KHR)
1109static void AppDestroySurface(struct AppInstance *inst) { //same for all platforms
1110    vkDestroySurfaceKHR(inst->instance, inst->surface, NULL);
1111}
1112#endif
1113
1114//----------------------------XCB----------------------------
1115
1116#ifdef VK_USE_PLATFORM_XCB_KHR
1117static void AppCreateXcbWindow(struct AppInstance *inst) {
1118    //--Init Connection--
1119    const xcb_setup_t *setup;
1120    xcb_screen_iterator_t iter;
1121    int scr;
1122
1123    inst->xcb_connection = xcb_connect(NULL, &scr);
1124    if (inst->xcb_connection == NULL) {
1125        printf("XCB failed to connect to the X server.\nExiting ...\n");
1126        fflush(stdout);
1127        exit(1);
1128    }
1129
1130    int conn_error = xcb_connection_has_error(inst->xcb_connection);
1131    if (conn_error) {
1132        printf("XCB failed to connect to the X server due to error:%d.\nExiting ...\n", conn_error);
1133        fflush(stdout);
1134        exit(1);
1135    }
1136
1137    setup = xcb_get_setup(inst->xcb_connection);
1138    iter = xcb_setup_roots_iterator(setup);
1139    while (scr-- > 0) {
1140        xcb_screen_next(&iter);
1141    }
1142
1143    inst->xcb_screen = iter.data;
1144    //-------------------
1145
1146    inst->xcb_window = xcb_generate_id(inst->xcb_connection);
1147    xcb_create_window(inst->xcb_connection, XCB_COPY_FROM_PARENT, inst->xcb_window,
1148                      inst->xcb_screen->root, 0, 0, inst->width, inst->height, 0,
1149                      XCB_WINDOW_CLASS_INPUT_OUTPUT, inst->xcb_screen->root_visual,
1150                      0, NULL);
1151
1152    xcb_intern_atom_cookie_t cookie = xcb_intern_atom(inst->xcb_connection, 1, 12, "WM_PROTOCOLS");
1153    xcb_intern_atom_reply_t *reply =  xcb_intern_atom_reply(inst->xcb_connection, cookie, 0);
1154    free(reply);
1155}
1156
1157static void AppCreateXcbSurface(struct AppInstance *inst) {
1158    VkResult U_ASSERT_ONLY err;
1159    VkXcbSurfaceCreateInfoKHR xcb_createInfo;
1160    xcb_createInfo.sType      = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
1161    xcb_createInfo.pNext      = NULL;
1162    xcb_createInfo.flags      = 0;
1163    xcb_createInfo.connection = inst->xcb_connection;
1164    xcb_createInfo.window     = inst->xcb_window;
1165    err = vkCreateXcbSurfaceKHR(inst->instance, &xcb_createInfo, NULL, &inst->surface);
1166    assert(!err);
1167}
1168
1169static void AppDestroyXcbWindow(struct AppInstance *inst) {
1170    xcb_destroy_window(inst->xcb_connection, inst->xcb_window);
1171    xcb_disconnect(inst->xcb_connection);
1172}
1173//VK_USE_PLATFORM_XCB_KHR
1174//-----------------------------------------------------------
1175
1176//----------------------------XLib---------------------------
1177#elif VK_USE_PLATFORM_XLIB_KHR
1178static void AppCreateXlibWindow(struct AppInstance *inst) {
1179    long visualMask = VisualScreenMask;
1180    int numberOfVisuals;
1181
1182    inst->xlib_display = XOpenDisplay(NULL);
1183    if (inst->xlib_display == NULL) {
1184        printf("XLib failed to connect to the X server.\nExiting ...\n");
1185        fflush(stdout);
1186        exit(1);
1187    }
1188
1189    XVisualInfo vInfoTemplate={};
1190    vInfoTemplate.screen = DefaultScreen(inst->xlib_display);
1191    XVisualInfo *visualInfo = XGetVisualInfo(inst->xlib_display, visualMask,
1192                                             &vInfoTemplate, &numberOfVisuals);
1193    inst->xlib_window = XCreateWindow(
1194                inst->xlib_display, RootWindow(inst->xlib_display, vInfoTemplate.screen), 0, 0,
1195                inst->width, inst->height, 0, visualInfo->depth, InputOutput,
1196                visualInfo->visual, 0, NULL);
1197
1198    XSync(inst->xlib_display,false);
1199}
1200
1201static void AppCreateXlibSurface(struct AppInstance *inst) {
1202    VkResult U_ASSERT_ONLY err;
1203    VkXlibSurfaceCreateInfoKHR createInfo;
1204    createInfo.sType  = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
1205    createInfo.pNext  = NULL;
1206    createInfo.flags  = 0;
1207    createInfo.dpy    = inst->xlib_display;
1208    createInfo.window = inst->xlib_window;
1209    err = vkCreateXlibSurfaceKHR(inst->instance, &createInfo, NULL, &inst->surface);
1210    assert(!err);
1211}
1212
1213static void AppDestroyXlibWindow(struct AppInstance *inst) {
1214    XDestroyWindow(inst->xlib_display, inst->xlib_window);
1215    XCloseDisplay(inst->xlib_display);
1216}
1217#endif //VK_USE_PLATFORM_XLIB_KHR
1218//-----------------------------------------------------------
1219
1220#if defined(VK_USE_PLATFORM_XCB_KHR)     || \
1221    defined(VK_USE_PLATFORM_XLIB_KHR)    || \
1222    defined(VK_USE_PLATFORM_WIN32_KHR)
1223static int AppDumpSurfaceFormats(struct AppInstance *inst, struct AppGpu *gpu){
1224    // Get the list of VkFormat's that are supported:
1225    VkResult U_ASSERT_ONLY err;
1226    uint32_t format_count = 0;
1227    err = inst->vkGetPhysicalDeviceSurfaceFormatsKHR(gpu->obj, inst->surface, &format_count, NULL);
1228    assert(!err);
1229
1230    VkSurfaceFormatKHR *surf_formats = (VkSurfaceFormatKHR *)malloc(format_count * sizeof(VkSurfaceFormatKHR));
1231    if (!surf_formats)
1232        ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY);
1233    err = inst->vkGetPhysicalDeviceSurfaceFormatsKHR(gpu->obj, inst->surface, &format_count, surf_formats);
1234    assert(!err);
1235    printf("Formats:\t\tcount = %d\n", format_count);
1236
1237    for (uint32_t i = 0; i < format_count; i++) {
1238        printf("\t%s\n", VkFormatString(surf_formats[i].format));
1239    }
1240    fflush(stdout);
1241
1242    free(surf_formats);
1243    return format_count;
1244}
1245
1246static int AppDumpSurfacePresentModes(struct AppInstance *inst, struct AppGpu *gpu) {
1247    // Get the list of VkPresentMode's that are supported:
1248    VkResult U_ASSERT_ONLY err;
1249    uint32_t present_mode_count = 0;
1250    err = inst->vkGetPhysicalDeviceSurfacePresentModesKHR(gpu->obj, inst->surface, &present_mode_count, NULL);
1251    assert(!err);
1252
1253    VkPresentModeKHR *surf_present_modes = (VkPresentModeKHR *)malloc(present_mode_count * sizeof(VkPresentInfoKHR));
1254    if (!surf_present_modes)
1255        ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY);
1256    err = inst->vkGetPhysicalDeviceSurfacePresentModesKHR(gpu->obj, inst->surface, &present_mode_count, surf_present_modes);
1257    assert(!err);
1258    printf("Present Modes:\t\tcount = %d\n", present_mode_count);
1259
1260    for (uint32_t i = 0; i < present_mode_count; i++) {
1261        printf("\t%s\n", VkPresentModeString(surf_present_modes[i]));
1262    }
1263    printf("\n");
1264    fflush(stdout);
1265
1266    free(surf_present_modes);
1267    return present_mode_count;
1268}
1269
1270static void AppDumpSurfaceCapabilities(struct AppInstance *inst, struct AppGpu *gpu) {
1271    if (CheckExtensionEnabled(VK_KHR_SURFACE_EXTENSION_NAME, gpu->inst->inst_extensions, gpu->inst->inst_extensions_count)) {
1272
1273        inst->vkGetPhysicalDeviceSurfaceCapabilitiesKHR(gpu->obj, inst->surface, &inst->surface_capabilities);
1274
1275        printf("\nVkSurfaceCapabilitiesKHR:\n");
1276        printf("=========================\n\n");
1277        printf("\tminImageCount       = %u\n", inst->surface_capabilities.minImageCount);
1278        printf("\tmaxImageCount       = %u\n", inst->surface_capabilities.maxImageCount);
1279        printf("\tcurrentExtent:\n");
1280        printf("\t\twidth       = %u\n", inst->surface_capabilities.currentExtent.width);
1281        printf("\t\theight      = %u\n", inst->surface_capabilities.currentExtent.height);
1282        printf("\tminImageExtent:\n");
1283        printf("\t\twidth       = %u\n", inst->surface_capabilities.minImageExtent.width);
1284        printf("\t\theight      = %u\n", inst->surface_capabilities.minImageExtent.height);
1285        printf("\tmaxImageExtent:\n");
1286        printf("\t\twidth       = %u\n", inst->surface_capabilities.maxImageExtent.width);
1287        printf("\t\theight      = %u\n", inst->surface_capabilities.maxImageExtent.height);
1288        printf("\tmaxImageArrayLayers = %u\n", inst->surface_capabilities.maxImageArrayLayers);
1289        printf("\tsupportedTransform:\n");
1290        if (inst->surface_capabilities.supportedTransforms == 0) { printf("\t\tNone\n"); }
1291        if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR\n"); }
1292        if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR\n"); }
1293        if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR\n"); }
1294        if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR\n"); }
1295        if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR\n"); }
1296        if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR\n"); }
1297        if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR\n"); }
1298        if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR\n"); }
1299        if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_INHERIT_BIT_KHR\n"); }
1300        printf("\tcurrentTransform:\n");
1301        if (inst->surface_capabilities.currentTransform == 0) { printf("\t\tNone\n"); }
1302        if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR\n"); }
1303        else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR\n"); }
1304        else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR\n"); }
1305        else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR\n"); }
1306        else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR\n"); }
1307        else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR\n"); }
1308        else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR\n"); }
1309        else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR\n"); }
1310        else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_INHERIT_BIT_KHR\n"); }
1311        printf("\tsupportedCompositeAlpha:\n");
1312        if (inst->surface_capabilities.supportedCompositeAlpha == 0) { printf("\t\tNone\n"); }
1313        if (inst->surface_capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR) { printf("\t\tVK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR\n"); }
1314        if (inst->surface_capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR) { printf("\t\tVK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR\n"); }
1315        if (inst->surface_capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR) { printf("\t\tVK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR\n"); }
1316        if (inst->surface_capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR) { printf("\t\tVK_COMPOSITE_ALPHA_INHERIT_BIT_KHR\n"); }
1317        printf("\tsupportedUsageFlags:\n");
1318        if (inst->surface_capabilities.supportedUsageFlags == 0) { printf("\t\tNone\n"); }
1319        if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) { printf("\t\tVK_IMAGE_USAGE_TRANSFER_SRC_BIT\n"); }
1320        if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) { printf("\t\tVK_IMAGE_USAGE_TRANSFER_DST_BIT\n"); }
1321        if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) { printf("\t\tVK_IMAGE_USAGE_SAMPLED_BIT\n"); }
1322        if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_STORAGE_BIT) { printf("\t\tVK_IMAGE_USAGE_STORAGE_BIT\n"); }
1323        if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) { printf("\t\tVK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT\n"); }
1324        if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { printf("\t\tVK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT\n"); }
1325        if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) { printf("\t\tVK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT\n"); }
1326        if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) { printf("\t\tVK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT\n"); }
1327
1328        // Get additional surface capability information from vkGetPhysicalDeviceSurfaceCapabilities2EXT
1329        if (CheckExtensionEnabled(VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME, gpu->inst->inst_extensions, gpu->inst->inst_extensions_count)) {
1330            memset(&inst->surface_capabilities2_ext, 0, sizeof(VkSurfaceCapabilities2EXT));
1331            inst->surface_capabilities2_ext.sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES2_EXT;
1332            inst->surface_capabilities2_ext.pNext = NULL;
1333
1334            inst->vkGetPhysicalDeviceSurfaceCapabilities2EXT(gpu->obj, inst->surface, &inst->surface_capabilities2_ext);
1335
1336            printf("\nVkSurfaceCapabilities2EXT:\n");
1337            printf("==========================\n\n");
1338            printf("\tsupportedSurfaceCounters:\n");
1339            if (inst->surface_capabilities2_ext.supportedSurfaceCounters == 0) { printf("\t\tNone\n"); }
1340            if (inst->surface_capabilities2_ext.supportedSurfaceCounters & VK_SURFACE_COUNTER_VBLANK_EXT) { printf("\t\tVK_SURFACE_COUNTER_VBLANK_EXT\n"); }
1341        }
1342
1343        // Get additional surface capability information from vkGetPhysicalDeviceSurfaceCapabilities2KHR
1344        if (CheckExtensionEnabled(VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME, gpu->inst->inst_extensions, gpu->inst->inst_extensions_count)) {
1345            if (CheckExtensionEnabled(VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME, gpu->inst->inst_extensions, gpu->inst->inst_extensions_count)) {
1346                inst->shared_surface_capabilities.sType = VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR;
1347                inst->shared_surface_capabilities.pNext = NULL;
1348                inst->surface_capabilities2.pNext = &inst->shared_surface_capabilities;
1349            } else {
1350                inst->surface_capabilities2.pNext = NULL;
1351            }
1352
1353            inst->surface_capabilities2.sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR;
1354
1355            VkPhysicalDeviceSurfaceInfo2KHR surface_info;
1356            surface_info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR;
1357            surface_info.pNext = NULL;
1358            surface_info.surface = inst->surface;
1359
1360            inst->vkGetPhysicalDeviceSurfaceCapabilities2KHR(gpu->obj, &surface_info, &inst->surface_capabilities2);
1361
1362            void *place = inst->surface_capabilities2.pNext;
1363            while (place) {
1364                struct VkStructureHeader* work = (struct VkStructureHeader*) place;
1365                if (work->sType == VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR) {
1366                    printf("\nVkSharedPresentSurfaceCapabilitiesKHR:\n");
1367                    printf("========================================\n");
1368                    VkSharedPresentSurfaceCapabilitiesKHR* shared_surface_capabilities = (VkSharedPresentSurfaceCapabilitiesKHR*)place;
1369                    printf("\tsharedPresentSupportedUsageFlags:\n");
1370                    if (shared_surface_capabilities->sharedPresentSupportedUsageFlags == 0) { printf("\t\tNone\n"); }
1371                    if (shared_surface_capabilities->sharedPresentSupportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) { printf("\t\tVK_IMAGE_USAGE_TRANSFER_SRC_BIT\n"); }
1372                    if (shared_surface_capabilities->sharedPresentSupportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) { printf("\t\tVK_IMAGE_USAGE_TRANSFER_DST_BIT\n"); }
1373                    if (shared_surface_capabilities->sharedPresentSupportedUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) { printf("\t\tVK_IMAGE_USAGE_SAMPLED_BIT\n"); }
1374                    if (shared_surface_capabilities->sharedPresentSupportedUsageFlags & VK_IMAGE_USAGE_STORAGE_BIT) { printf("\t\tVK_IMAGE_USAGE_STORAGE_BIT\n"); }
1375                    if (shared_surface_capabilities->sharedPresentSupportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) { printf("\t\tVK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT\n"); }
1376                    if (shared_surface_capabilities->sharedPresentSupportedUsageFlags & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { printf("\t\tVK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT\n"); }
1377                    if (shared_surface_capabilities->sharedPresentSupportedUsageFlags & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) { printf("\t\tVK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT\n"); }
1378                    if (shared_surface_capabilities->sharedPresentSupportedUsageFlags & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) { printf("\t\tVK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT\n"); }
1379                }
1380
1381                place = work->pNext;
1382            }
1383        }
1384    }
1385}
1386
1387#endif
1388
1389static void AppDevDumpFormatProps(const struct AppDev *dev, VkFormat fmt)
1390{
1391    const VkFormatProperties *props = &dev->format_props[fmt];
1392    struct {
1393        const char *name;
1394        VkFlags flags;
1395    } features[3];
1396
1397    features[0].name  = "linearTiling   FormatFeatureFlags";
1398    features[0].flags = props->linearTilingFeatures;
1399    features[1].name  = "optimalTiling  FormatFeatureFlags";
1400    features[1].flags = props->optimalTilingFeatures;
1401    features[2].name  = "bufferFeatures FormatFeatureFlags";
1402    features[2].flags = props->bufferFeatures;
1403
1404    printf("\nFORMAT_%s:", VkFormatString(fmt));
1405    for (uint32_t i = 0; i < ARRAY_SIZE(features); i++) {
1406        printf("\n\t%s:", features[i].name);
1407        if (features[i].flags == 0) {
1408            printf("\n\t\tNone");
1409        } else {
1410            printf("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
1411               ((features[i].flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)                  ? "\n\t\tVK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT"                  : ""),  //0x0001
1412               ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT)                  ? "\n\t\tVK_FORMAT_FEATURE_STORAGE_IMAGE_BIT"                  : ""),  //0x0002
1413               ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT)           ? "\n\t\tVK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT"           : ""),  //0x0004
1414               ((features[i].flags & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT)           ? "\n\t\tVK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT"           : ""),  //0x0008
1415               ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT)           ? "\n\t\tVK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT"           : ""),  //0x0010
1416               ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT)    ? "\n\t\tVK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT"    : ""),  //0x0020
1417               ((features[i].flags & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)                  ? "\n\t\tVK_FORMAT_FEATURE_VERTEX_BUFFER_BIT"                  : ""),  //0x0040
1418               ((features[i].flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)               ? "\n\t\tVK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT"               : ""),  //0x0080
1419               ((features[i].flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT)         ? "\n\t\tVK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT"         : ""),  //0x0100
1420               ((features[i].flags & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)       ? "\n\t\tVK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT"       : ""),  //0x0200
1421               ((features[i].flags & VK_FORMAT_FEATURE_BLIT_SRC_BIT)                       ? "\n\t\tVK_FORMAT_FEATURE_BLIT_SRC_BIT"                       : ""),  //0x0400
1422               ((features[i].flags & VK_FORMAT_FEATURE_BLIT_DST_BIT)                       ? "\n\t\tVK_FORMAT_FEATURE_BLIT_DST_BIT"                       : ""),  //0x0800
1423               ((features[i].flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT)    ? "\n\t\tVK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT"    : ""),  //0x1000
1424               ((features[i].flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG) ? "\n\t\tVK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG" : ""),  //0x2000
1425               ((features[i].flags & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR)               ? "\n\t\tVK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR"               : ""),  //0x4000
1426               ((features[i].flags & VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR)               ? "\n\t\tVK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR"               : "")); //0x8000
1427        }
1428    }
1429    printf("\n");
1430}
1431
1432static void
1433AppDevDump(const struct AppDev *dev)
1434{
1435    printf("Format Properties:\n");
1436    printf("==================");
1437    VkFormat fmt;
1438
1439    for (fmt = 0; fmt < VK_FORMAT_RANGE_SIZE; fmt++) {
1440        AppDevDumpFormatProps(dev, fmt);
1441    }
1442}
1443
1444#ifdef _WIN32
1445#define PRINTF_SIZE_T_SPECIFIER    "%Iu"
1446#else
1447#define PRINTF_SIZE_T_SPECIFIER    "%zu"
1448#endif
1449
1450static void AppGpuDumpFeatures(const struct AppGpu *gpu)
1451{
1452    const VkPhysicalDeviceFeatures *features = &gpu->features;
1453
1454    printf("VkPhysicalDeviceFeatures:\n");
1455    printf("=========================\n");
1456
1457    printf("\trobustBufferAccess                      = %u\n", features->robustBufferAccess                     );
1458    printf("\tfullDrawIndexUint32                     = %u\n", features->fullDrawIndexUint32                    );
1459    printf("\timageCubeArray                          = %u\n", features->imageCubeArray                         );
1460    printf("\tindependentBlend                        = %u\n", features->independentBlend                       );
1461    printf("\tgeometryShader                          = %u\n", features->geometryShader                         );
1462    printf("\ttessellationShader                      = %u\n", features->tessellationShader                     );
1463    printf("\tsampleRateShading                       = %u\n", features->sampleRateShading                      );
1464    printf("\tdualSrcBlend                            = %u\n", features->dualSrcBlend                           );
1465    printf("\tlogicOp                                 = %u\n", features->logicOp                                );
1466    printf("\tmultiDrawIndirect                       = %u\n", features->multiDrawIndirect                      );
1467    printf("\tdrawIndirectFirstInstance               = %u\n", features->drawIndirectFirstInstance              );
1468    printf("\tdepthClamp                              = %u\n", features->depthClamp                             );
1469    printf("\tdepthBiasClamp                          = %u\n", features->depthBiasClamp                         );
1470    printf("\tfillModeNonSolid                        = %u\n", features->fillModeNonSolid                       );
1471    printf("\tdepthBounds                             = %u\n", features->depthBounds                            );
1472    printf("\twideLines                               = %u\n", features->wideLines                              );
1473    printf("\tlargePoints                             = %u\n", features->largePoints                            );
1474    printf("\talphaToOne                              = %u\n", features->alphaToOne                             );
1475    printf("\tmultiViewport                           = %u\n", features->multiViewport                          );
1476    printf("\tsamplerAnisotropy                       = %u\n", features->samplerAnisotropy                      );
1477    printf("\ttextureCompressionETC2                  = %u\n", features->textureCompressionETC2                 );
1478    printf("\ttextureCompressionASTC_LDR              = %u\n", features->textureCompressionASTC_LDR             );
1479    printf("\ttextureCompressionBC                    = %u\n", features->textureCompressionBC                   );
1480    printf("\tocclusionQueryPrecise                   = %u\n", features->occlusionQueryPrecise                  );
1481    printf("\tpipelineStatisticsQuery                 = %u\n", features->pipelineStatisticsQuery                );
1482    printf("\tvertexPipelineStoresAndAtomics          = %u\n", features->vertexPipelineStoresAndAtomics         );
1483    printf("\tfragmentStoresAndAtomics                = %u\n", features->fragmentStoresAndAtomics               );
1484    printf("\tshaderTessellationAndGeometryPointSize  = %u\n", features->shaderTessellationAndGeometryPointSize );
1485    printf("\tshaderImageGatherExtended               = %u\n", features->shaderImageGatherExtended              );
1486    printf("\tshaderStorageImageExtendedFormats       = %u\n", features->shaderStorageImageExtendedFormats      );
1487    printf("\tshaderStorageImageMultisample           = %u\n", features->shaderStorageImageMultisample          );
1488    printf("\tshaderStorageImageReadWithoutFormat     = %u\n", features->shaderStorageImageReadWithoutFormat    );
1489    printf("\tshaderStorageImageWriteWithoutFormat    = %u\n", features->shaderStorageImageWriteWithoutFormat   );
1490    printf("\tshaderUniformBufferArrayDynamicIndexing = %u\n", features->shaderUniformBufferArrayDynamicIndexing);
1491    printf("\tshaderSampledImageArrayDynamicIndexing  = %u\n", features->shaderSampledImageArrayDynamicIndexing );
1492    printf("\tshaderStorageBufferArrayDynamicIndexing = %u\n", features->shaderStorageBufferArrayDynamicIndexing);
1493    printf("\tshaderStorageImageArrayDynamicIndexing  = %u\n", features->shaderStorageImageArrayDynamicIndexing );
1494    printf("\tshaderClipDistance                      = %u\n", features->shaderClipDistance                     );
1495    printf("\tshaderCullDistance                      = %u\n", features->shaderCullDistance                     );
1496    printf("\tshaderFloat64                           = %u\n", features->shaderFloat64                          );
1497    printf("\tshaderInt64                             = %u\n", features->shaderInt64                            );
1498    printf("\tshaderInt16                             = %u\n", features->shaderInt16                            );
1499    printf("\tshaderResourceResidency                 = %u\n", features->shaderResourceResidency                );
1500    printf("\tshaderResourceMinLod                    = %u\n", features->shaderResourceMinLod                   );
1501    printf("\tsparseBinding                           = %u\n", features->sparseBinding                          );
1502    printf("\tsparseResidencyBuffer                   = %u\n", features->sparseResidencyBuffer                  );
1503    printf("\tsparseResidencyImage2D                  = %u\n", features->sparseResidencyImage2D                 );
1504    printf("\tsparseResidencyImage3D                  = %u\n", features->sparseResidencyImage3D                 );
1505    printf("\tsparseResidency2Samples                 = %u\n", features->sparseResidency2Samples                );
1506    printf("\tsparseResidency4Samples                 = %u\n", features->sparseResidency4Samples                );
1507    printf("\tsparseResidency8Samples                 = %u\n", features->sparseResidency8Samples                );
1508    printf("\tsparseResidency16Samples                = %u\n", features->sparseResidency16Samples               );
1509    printf("\tsparseResidencyAliased                  = %u\n", features->sparseResidencyAliased                 );
1510    printf("\tvariableMultisampleRate                 = %u\n", features->variableMultisampleRate                );
1511    printf("\tinheritedQueries                        = %u\n", features->inheritedQueries                       );
1512}
1513
1514static void AppDumpSparseProps(const VkPhysicalDeviceSparseProperties *sparse_props)
1515{
1516
1517    printf("\tVkPhysicalDeviceSparseProperties:\n");
1518    printf("\t---------------------------------\n");
1519
1520    printf("\t\tresidencyStandard2DBlockShape            = %u\n", sparse_props->residencyStandard2DBlockShape           );
1521    printf("\t\tresidencyStandard2DMultisampleBlockShape = %u\n", sparse_props->residencyStandard2DMultisampleBlockShape);
1522    printf("\t\tresidencyStandard3DBlockShape            = %u\n", sparse_props->residencyStandard3DBlockShape           );
1523    printf("\t\tresidencyAlignedMipSize                  = %u\n", sparse_props->residencyAlignedMipSize                 );
1524    printf("\t\tresidencyNonResidentStrict               = %u\n", sparse_props->residencyNonResidentStrict              );
1525}
1526
1527static void AppDumpLimits(const VkPhysicalDeviceLimits *limits)
1528{
1529    printf("\tVkPhysicalDeviceLimits:\n");
1530    printf("\t-----------------------\n");
1531    printf("\t\tmaxImageDimension1D                     = %u\n",                 limits->maxImageDimension1D                    );
1532    printf("\t\tmaxImageDimension2D                     = %u\n",                 limits->maxImageDimension2D                    );
1533    printf("\t\tmaxImageDimension3D                     = %u\n",                 limits->maxImageDimension3D                    );
1534    printf("\t\tmaxImageDimensionCube                   = %u\n",                 limits->maxImageDimensionCube                  );
1535    printf("\t\tmaxImageArrayLayers                     = %u\n",                 limits->maxImageArrayLayers                    );
1536    printf("\t\tmaxTexelBufferElements                  = 0x%" PRIxLEAST32 "\n", limits->maxTexelBufferElements                 );
1537    printf("\t\tmaxUniformBufferRange                   = 0x%" PRIxLEAST32 "\n", limits->maxUniformBufferRange                  );
1538    printf("\t\tmaxStorageBufferRange                   = 0x%" PRIxLEAST32 "\n", limits->maxStorageBufferRange                  );
1539    printf("\t\tmaxPushConstantsSize                    = %u\n",                 limits->maxPushConstantsSize                   );
1540    printf("\t\tmaxMemoryAllocationCount                = %u\n",                 limits->maxMemoryAllocationCount               );
1541    printf("\t\tmaxSamplerAllocationCount               = %u\n",                 limits->maxSamplerAllocationCount              );
1542    printf("\t\tbufferImageGranularity                  = 0x%" PRIxLEAST64 "\n", limits->bufferImageGranularity                 );
1543    printf("\t\tsparseAddressSpaceSize                  = 0x%" PRIxLEAST64 "\n", limits->sparseAddressSpaceSize                 );
1544    printf("\t\tmaxBoundDescriptorSets                  = %u\n",                 limits->maxBoundDescriptorSets                 );
1545    printf("\t\tmaxPerStageDescriptorSamplers           = %u\n",                 limits->maxPerStageDescriptorSamplers          );
1546    printf("\t\tmaxPerStageDescriptorUniformBuffers     = %u\n",                 limits->maxPerStageDescriptorUniformBuffers    );
1547    printf("\t\tmaxPerStageDescriptorStorageBuffers     = %u\n",                 limits->maxPerStageDescriptorStorageBuffers    );
1548    printf("\t\tmaxPerStageDescriptorSampledImages      = %u\n",                 limits->maxPerStageDescriptorSampledImages     );
1549    printf("\t\tmaxPerStageDescriptorStorageImages      = %u\n",                 limits->maxPerStageDescriptorStorageImages     );
1550    printf("\t\tmaxPerStageDescriptorInputAttachments   = %u\n",                 limits->maxPerStageDescriptorInputAttachments  );
1551    printf("\t\tmaxPerStageResources                    = %u\n",                 limits->maxPerStageResources                   );
1552    printf("\t\tmaxDescriptorSetSamplers                = %u\n",                 limits->maxDescriptorSetSamplers               );
1553    printf("\t\tmaxDescriptorSetUniformBuffers          = %u\n",                 limits->maxDescriptorSetUniformBuffers         );
1554    printf("\t\tmaxDescriptorSetUniformBuffersDynamic   = %u\n",                 limits->maxDescriptorSetUniformBuffersDynamic  );
1555    printf("\t\tmaxDescriptorSetStorageBuffers          = %u\n",                 limits->maxDescriptorSetStorageBuffers         );
1556    printf("\t\tmaxDescriptorSetStorageBuffersDynamic   = %u\n",                 limits->maxDescriptorSetStorageBuffersDynamic  );
1557    printf("\t\tmaxDescriptorSetSampledImages           = %u\n",                 limits->maxDescriptorSetSampledImages          );
1558    printf("\t\tmaxDescriptorSetStorageImages           = %u\n",                 limits->maxDescriptorSetStorageImages          );
1559    printf("\t\tmaxDescriptorSetInputAttachments        = %u\n",                 limits->maxDescriptorSetInputAttachments       );
1560    printf("\t\tmaxVertexInputAttributes                = %u\n",                 limits->maxVertexInputAttributes               );
1561    printf("\t\tmaxVertexInputBindings                  = %u\n",                 limits->maxVertexInputBindings                 );
1562    printf("\t\tmaxVertexInputAttributeOffset           = 0x%" PRIxLEAST32 "\n", limits->maxVertexInputAttributeOffset          );
1563    printf("\t\tmaxVertexInputBindingStride             = 0x%" PRIxLEAST32 "\n", limits->maxVertexInputBindingStride            );
1564    printf("\t\tmaxVertexOutputComponents               = %u\n",                 limits->maxVertexOutputComponents              );
1565    printf("\t\tmaxTessellationGenerationLevel          = %u\n",                 limits->maxTessellationGenerationLevel         );
1566    printf("\t\tmaxTessellationPatchSize                        = %u\n",                 limits->maxTessellationPatchSize                       );
1567    printf("\t\tmaxTessellationControlPerVertexInputComponents  = %u\n",                 limits->maxTessellationControlPerVertexInputComponents );
1568    printf("\t\tmaxTessellationControlPerVertexOutputComponents = %u\n",                 limits->maxTessellationControlPerVertexOutputComponents);
1569    printf("\t\tmaxTessellationControlPerPatchOutputComponents  = %u\n",                 limits->maxTessellationControlPerPatchOutputComponents );
1570    printf("\t\tmaxTessellationControlTotalOutputComponents     = %u\n",                 limits->maxTessellationControlTotalOutputComponents    );
1571    printf("\t\tmaxTessellationEvaluationInputComponents        = %u\n",                 limits->maxTessellationEvaluationInputComponents       );
1572    printf("\t\tmaxTessellationEvaluationOutputComponents       = %u\n",                 limits->maxTessellationEvaluationOutputComponents      );
1573    printf("\t\tmaxGeometryShaderInvocations            = %u\n",                 limits->maxGeometryShaderInvocations           );
1574    printf("\t\tmaxGeometryInputComponents              = %u\n",                 limits->maxGeometryInputComponents             );
1575    printf("\t\tmaxGeometryOutputComponents             = %u\n",                 limits->maxGeometryOutputComponents            );
1576    printf("\t\tmaxGeometryOutputVertices               = %u\n",                 limits->maxGeometryOutputVertices              );
1577    printf("\t\tmaxGeometryTotalOutputComponents        = %u\n",                 limits->maxGeometryTotalOutputComponents       );
1578    printf("\t\tmaxFragmentInputComponents              = %u\n",                 limits->maxFragmentInputComponents             );
1579    printf("\t\tmaxFragmentOutputAttachments            = %u\n",                 limits->maxFragmentOutputAttachments           );
1580    printf("\t\tmaxFragmentDualSrcAttachments           = %u\n",                 limits->maxFragmentDualSrcAttachments          );
1581    printf("\t\tmaxFragmentCombinedOutputResources      = %u\n",                 limits->maxFragmentCombinedOutputResources     );
1582    printf("\t\tmaxComputeSharedMemorySize              = 0x%" PRIxLEAST32 "\n", limits->maxComputeSharedMemorySize             );
1583    printf("\t\tmaxComputeWorkGroupCount[0]             = %u\n",                 limits->maxComputeWorkGroupCount[0]            );
1584    printf("\t\tmaxComputeWorkGroupCount[1]             = %u\n",                 limits->maxComputeWorkGroupCount[1]            );
1585    printf("\t\tmaxComputeWorkGroupCount[2]             = %u\n",                 limits->maxComputeWorkGroupCount[2]            );
1586    printf("\t\tmaxComputeWorkGroupInvocations          = %u\n",                 limits->maxComputeWorkGroupInvocations         );
1587    printf("\t\tmaxComputeWorkGroupSize[0]              = %u\n",                 limits->maxComputeWorkGroupSize[0]             );
1588    printf("\t\tmaxComputeWorkGroupSize[1]              = %u\n",                 limits->maxComputeWorkGroupSize[1]             );
1589    printf("\t\tmaxComputeWorkGroupSize[2]              = %u\n",                 limits->maxComputeWorkGroupSize[2]             );
1590    printf("\t\tsubPixelPrecisionBits                   = %u\n",                 limits->subPixelPrecisionBits                  );
1591    printf("\t\tsubTexelPrecisionBits                   = %u\n",                 limits->subTexelPrecisionBits                  );
1592    printf("\t\tmipmapPrecisionBits                     = %u\n",                 limits->mipmapPrecisionBits                    );
1593    printf("\t\tmaxDrawIndexedIndexValue                = %u\n",                 limits->maxDrawIndexedIndexValue               );
1594    printf("\t\tmaxDrawIndirectCount                    = %u\n",                 limits->maxDrawIndirectCount                   );
1595    printf("\t\tmaxSamplerLodBias                       = %f\n",                 limits->maxSamplerLodBias                      );
1596    printf("\t\tmaxSamplerAnisotropy                    = %f\n",                 limits->maxSamplerAnisotropy                   );
1597    printf("\t\tmaxViewports                            = %u\n",                 limits->maxViewports                           );
1598    printf("\t\tmaxViewportDimensions[0]                = %u\n",                 limits->maxViewportDimensions[0]               );
1599    printf("\t\tmaxViewportDimensions[1]                = %u\n",                 limits->maxViewportDimensions[1]               );
1600    printf("\t\tviewportBoundsRange[0]                  =%13f\n",                 limits->viewportBoundsRange[0]                 );
1601    printf("\t\tviewportBoundsRange[1]                  =%13f\n",                 limits->viewportBoundsRange[1]                 );
1602    printf("\t\tviewportSubPixelBits                    = %u\n",                 limits->viewportSubPixelBits                   );
1603    printf("\t\tminMemoryMapAlignment                   = " PRINTF_SIZE_T_SPECIFIER "\n", limits->minMemoryMapAlignment         );
1604    printf("\t\tminTexelBufferOffsetAlignment           = 0x%" PRIxLEAST64 "\n", limits->minTexelBufferOffsetAlignment          );
1605    printf("\t\tminUniformBufferOffsetAlignment         = 0x%" PRIxLEAST64 "\n", limits->minUniformBufferOffsetAlignment        );
1606    printf("\t\tminStorageBufferOffsetAlignment         = 0x%" PRIxLEAST64 "\n", limits->minStorageBufferOffsetAlignment        );
1607    printf("\t\tminTexelOffset                          =%3d\n",                 limits->minTexelOffset                         );
1608    printf("\t\tmaxTexelOffset                          =%3d\n",                 limits->maxTexelOffset                         );
1609    printf("\t\tminTexelGatherOffset                    =%3d\n",                 limits->minTexelGatherOffset                   );
1610    printf("\t\tmaxTexelGatherOffset                    =%3d\n",                 limits->maxTexelGatherOffset                   );
1611    printf("\t\tminInterpolationOffset                  =%9f\n",                 limits->minInterpolationOffset                 );
1612    printf("\t\tmaxInterpolationOffset                  =%9f\n",                 limits->maxInterpolationOffset                 );
1613    printf("\t\tsubPixelInterpolationOffsetBits         = %u\n",                 limits->subPixelInterpolationOffsetBits        );
1614    printf("\t\tmaxFramebufferWidth                     = %u\n",                 limits->maxFramebufferWidth                    );
1615    printf("\t\tmaxFramebufferHeight                    = %u\n",                 limits->maxFramebufferHeight                   );
1616    printf("\t\tmaxFramebufferLayers                    = %u\n",                 limits->maxFramebufferLayers                   );
1617    printf("\t\tframebufferColorSampleCounts            = %u\n",                 limits->framebufferColorSampleCounts           );
1618    printf("\t\tframebufferDepthSampleCounts            = %u\n",                 limits->framebufferDepthSampleCounts           );
1619    printf("\t\tframebufferStencilSampleCounts          = %u\n",                 limits->framebufferStencilSampleCounts         );
1620    printf("\t\tframebufferNoAttachmentsSampleCounts    = %u\n",                 limits->framebufferNoAttachmentsSampleCounts   );
1621    printf("\t\tmaxColorAttachments                     = %u\n",                 limits->maxColorAttachments                    );
1622    printf("\t\tsampledImageColorSampleCounts           = %u\n",                 limits->sampledImageColorSampleCounts          );
1623    printf("\t\tsampledImageDepthSampleCounts           = %u\n",                 limits->sampledImageDepthSampleCounts          );
1624    printf("\t\tsampledImageStencilSampleCounts         = %u\n",                 limits->sampledImageStencilSampleCounts        );
1625    printf("\t\tsampledImageIntegerSampleCounts         = %u\n",                 limits->sampledImageIntegerSampleCounts        );
1626    printf("\t\tstorageImageSampleCounts                = %u\n",                 limits->storageImageSampleCounts               );
1627    printf("\t\tmaxSampleMaskWords                      = %u\n",                 limits->maxSampleMaskWords                     );
1628    printf("\t\ttimestampComputeAndGraphics             = %u\n",                 limits->timestampComputeAndGraphics            );
1629    printf("\t\ttimestampPeriod                         = %f\n",                 limits->timestampPeriod                        );
1630    printf("\t\tmaxClipDistances                        = %u\n",                 limits->maxClipDistances                       );
1631    printf("\t\tmaxCullDistances                        = %u\n",                 limits->maxCullDistances                       );
1632    printf("\t\tmaxCombinedClipAndCullDistances         = %u\n",                 limits->maxCombinedClipAndCullDistances        );
1633    printf("\t\tdiscreteQueuePriorities                 = %u\n",                 limits->discreteQueuePriorities                );
1634    printf("\t\tpointSizeRange[0]                       = %f\n",                 limits->pointSizeRange[0]                      );
1635    printf("\t\tpointSizeRange[1]                       = %f\n",                 limits->pointSizeRange[1]                      );
1636    printf("\t\tlineWidthRange[0]                       = %f\n",                 limits->lineWidthRange[0]                      );
1637    printf("\t\tlineWidthRange[1]                       = %f\n",                 limits->lineWidthRange[1]                      );
1638    printf("\t\tpointSizeGranularity                    = %f\n",                 limits->pointSizeGranularity                   );
1639    printf("\t\tlineWidthGranularity                    = %f\n",                 limits->lineWidthGranularity                   );
1640    printf("\t\tstrictLines                             = %u\n",                 limits->strictLines                            );
1641    printf("\t\tstandardSampleLocations                 = %u\n",                 limits->standardSampleLocations                );
1642    printf("\t\toptimalBufferCopyOffsetAlignment        = 0x%" PRIxLEAST64 "\n", limits->optimalBufferCopyOffsetAlignment       );
1643    printf("\t\toptimalBufferCopyRowPitchAlignment      = 0x%" PRIxLEAST64 "\n", limits->optimalBufferCopyRowPitchAlignment     );
1644    printf("\t\tnonCoherentAtomSize                     = 0x%" PRIxLEAST64 "\n", limits->nonCoherentAtomSize                    );
1645}
1646
1647static void AppGpuDumpProps(const struct AppGpu *gpu)
1648{
1649    const VkPhysicalDeviceProperties *props = &gpu->props;
1650    const uint32_t apiVersion=props->apiVersion;
1651    const uint32_t major = VK_VERSION_MAJOR(apiVersion);
1652    const uint32_t minor = VK_VERSION_MINOR(apiVersion);
1653    const uint32_t patch = VK_VERSION_PATCH(apiVersion);
1654
1655    printf("VkPhysicalDeviceProperties:\n");
1656    printf("===========================\n");
1657    printf("\tapiVersion     = 0x%" PRIxLEAST32 "  (%d.%d.%d)\n", apiVersion, major, minor, patch);
1658    printf("\tdriverVersion  = %u (0x%" PRIxLEAST32 ")\n",props->driverVersion, props->driverVersion);
1659    printf("\tvendorID       = 0x%04x\n",                 props->vendorID);
1660    printf("\tdeviceID       = 0x%04x\n",                 props->deviceID);
1661    printf("\tdeviceType     = %s\n",                     VkPhysicalDeviceTypeString(props->deviceType));
1662    printf("\tdeviceName     = %s\n",                     props->deviceName);
1663
1664    AppDumpLimits(&gpu->props.limits);
1665    AppDumpSparseProps(&gpu->props.sparseProperties);
1666
1667    fflush(stdout);
1668}
1669// clang-format on
1670
1671static void AppDumpExtensions(const char *indent, const char *layer_name, const uint32_t extension_count,
1672                              const VkExtensionProperties *extension_properties) {
1673    uint32_t i;
1674    if (layer_name && (strlen(layer_name) > 0)) {
1675        printf("%s%s Extensions", indent, layer_name);
1676    } else {
1677        printf("%sExtensions", indent);
1678    }
1679    printf("\tcount = %d\n", extension_count);
1680    for (i = 0; i < extension_count; i++) {
1681        VkExtensionProperties const *ext_prop = &extension_properties[i];
1682
1683        printf("%s\t", indent);
1684        printf("%-36s: extension revision %2d\n", ext_prop->extensionName, ext_prop->specVersion);
1685    }
1686    fflush(stdout);
1687}
1688
1689static void AppGpuDumpQueueProps(const struct AppGpu *gpu, uint32_t id) {
1690    const VkQueueFamilyProperties *props = &gpu->queue_props[id];
1691
1692    printf("VkQueueFamilyProperties[%d]:\n", id);
1693    printf("===========================\n");
1694    char *sep = "";  // separator character
1695    printf("\tqueueFlags         = ");
1696    if (props->queueFlags & VK_QUEUE_GRAPHICS_BIT) {
1697        printf("GRAPHICS");
1698        sep = " | ";
1699    }
1700    if (props->queueFlags & VK_QUEUE_COMPUTE_BIT) {
1701        printf("%sCOMPUTE", sep);
1702        sep = " | ";
1703    }
1704    if (props->queueFlags & VK_QUEUE_TRANSFER_BIT) {
1705        printf("%sTRANSFER", sep);
1706        sep = " | ";
1707    }
1708    if (props->queueFlags & VK_QUEUE_SPARSE_BINDING_BIT) {
1709        printf("%sSPARSE", sep);
1710    }
1711    printf("\n");
1712
1713    printf("\tqueueCount         = %u\n", props->queueCount);
1714    printf("\ttimestampValidBits = %u\n", props->timestampValidBits);
1715    printf("\tminImageTransferGranularity = (%d, %d, %d)\n", props->minImageTransferGranularity.width,
1716           props->minImageTransferGranularity.height, props->minImageTransferGranularity.depth);
1717    fflush(stdout);
1718}
1719
1720// This prints a number of bytes in a human-readable format according to prefixes of the International System of Quantities (ISQ),
1721// defined in ISO/IEC 80000. The prefixes used here are not SI prefixes, but rather the binary prefixes based on powers of 1024
1722// (kibi-, mebi-, gibi- etc.).
1723#define kBufferSize 32
1724
1725static char *HumanReadable(const size_t sz) {
1726    const char prefixes[] = "KMGTPEZY";
1727    char buf[kBufferSize];
1728    int which = -1;
1729    double result = (double)sz;
1730    while (result > 1024 && which < 7) {
1731        result /= 1024;
1732        ++which;
1733    }
1734
1735    char unit[] = "\0i";
1736    if (which >= 0) {
1737        unit[0] = prefixes[which];
1738    }
1739    snprintf(buf, kBufferSize, "%.2f %sB", result, unit);
1740    return strndup(buf, kBufferSize);
1741}
1742
1743static void AppGpuDumpMemoryProps(const struct AppGpu *gpu) {
1744    const VkPhysicalDeviceMemoryProperties *props = &gpu->memory_props;
1745
1746    printf("VkPhysicalDeviceMemoryProperties:\n");
1747    printf("=================================\n");
1748    printf("\tmemoryTypeCount       = %u\n", props->memoryTypeCount);
1749    for (uint32_t i = 0; i < props->memoryTypeCount; i++) {
1750        printf("\tmemoryTypes[%u] :\n", i);
1751        printf("\t\theapIndex     = %u\n", props->memoryTypes[i].heapIndex);
1752        printf("\t\tpropertyFlags = 0x%" PRIxLEAST32 ":\n", props->memoryTypes[i].propertyFlags);
1753
1754        // Print each named flag, if it is set.
1755        VkFlags flags = props->memoryTypes[i].propertyFlags;
1756#define PRINT_FLAG(FLAG) \
1757    if (flags & FLAG) printf("\t\t\t" #FLAG "\n");
1758        PRINT_FLAG(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
1759        PRINT_FLAG(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
1760        PRINT_FLAG(VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
1761        PRINT_FLAG(VK_MEMORY_PROPERTY_HOST_CACHED_BIT)
1762        PRINT_FLAG(VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT)
1763#undef PRINT_FLAG
1764    }
1765    printf("\n");
1766    printf("\tmemoryHeapCount       = %u\n", props->memoryHeapCount);
1767    for (uint32_t i = 0; i < props->memoryHeapCount; i++) {
1768        printf("\tmemoryHeaps[%u] :\n", i);
1769        const VkDeviceSize memSize = props->memoryHeaps[i].size;
1770        char *mem_size_human_readable = HumanReadable((const size_t)memSize);
1771        printf("\t\tsize          = " PRINTF_SIZE_T_SPECIFIER " (0x%" PRIxLEAST64 ") (%s)\n", (size_t)memSize, memSize,
1772               mem_size_human_readable);
1773        free(mem_size_human_readable);
1774
1775        VkMemoryHeapFlags heap_flags = props->memoryHeaps[i].flags;
1776        printf("\t\tflags:\n\t\t\t");
1777        printf((heap_flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) ? "VK_MEMORY_HEAP_DEVICE_LOCAL_BIT\n" : "None\n");
1778    }
1779    fflush(stdout);
1780}
1781
1782static void AppGpuDump(const struct AppGpu *gpu) {
1783    uint32_t i;
1784
1785    printf("\nDevice Properties and Extensions :\n");
1786    printf("==================================\n");
1787    printf("GPU%u\n", gpu->id);
1788    AppGpuDumpProps(gpu);
1789    printf("\n");
1790    AppDumpExtensions("", "Device", gpu->device_extension_count, gpu->device_extensions);
1791    printf("\n");
1792    for (i = 0; i < gpu->queue_count; i++) {
1793        AppGpuDumpQueueProps(gpu, i);
1794        printf("\n");
1795    }
1796    AppGpuDumpMemoryProps(gpu);
1797    printf("\n");
1798    AppGpuDumpFeatures(gpu);
1799    printf("\n");
1800    AppDevDump(&gpu->dev);
1801}
1802
1803#ifdef _WIN32
1804// Enlarges the console window to have a large scrollback size.
1805static void ConsoleEnlarge() {
1806    HANDLE console_handle = GetStdHandle(STD_OUTPUT_HANDLE);
1807
1808    // make the console window bigger
1809    CONSOLE_SCREEN_BUFFER_INFO csbi;
1810    COORD buffer_size;
1811    if (GetConsoleScreenBufferInfo(console_handle, &csbi)) {
1812        buffer_size.X = csbi.dwSize.X + 30;
1813        buffer_size.Y = 20000;
1814        SetConsoleScreenBufferSize(console_handle, buffer_size);
1815    }
1816
1817    SMALL_RECT r;
1818    r.Left = r.Top = 0;
1819    r.Right = csbi.dwSize.X - 1 + 30;
1820    r.Bottom = 50;
1821    SetConsoleWindowInfo(console_handle, true, &r);
1822
1823    // change the console window title
1824    SetConsoleTitle(TEXT(APP_SHORT_NAME));
1825}
1826#endif
1827
1828int main(int argc, char **argv) {
1829    uint32_t vulkan_major, vulkan_minor, vulkan_patch;
1830    struct AppGpu *gpus;
1831    VkPhysicalDevice *objs;
1832    uint32_t gpu_count;
1833    VkResult err;
1834    struct AppInstance inst;
1835
1836#ifdef _WIN32
1837    if (ConsoleIsExclusive()) ConsoleEnlarge();
1838#endif
1839
1840    vulkan_major = VK_VERSION_MAJOR(VK_API_VERSION_1_0);
1841    vulkan_minor = VK_VERSION_MINOR(VK_API_VERSION_1_0);
1842    vulkan_patch = VK_VERSION_PATCH(VK_HEADER_VERSION);
1843
1844    printf("===========\n");
1845    printf("VULKAN INFO\n");
1846    printf("===========\n\n");
1847    printf("Vulkan API Version: %d.%d.%d\n\n", vulkan_major, vulkan_minor, vulkan_patch);
1848
1849    AppCreateInstance(&inst);
1850
1851    printf("\nInstance Extensions:\n");
1852    printf("====================\n");
1853    AppDumpExtensions("", "Instance", inst.global_extension_count, inst.global_extensions);
1854
1855    err = vkEnumeratePhysicalDevices(inst.instance, &gpu_count, NULL);
1856    if (err) ERR_EXIT(err);
1857    objs = malloc(sizeof(objs[0]) * gpu_count);
1858    if (!objs) ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY);
1859    err = vkEnumeratePhysicalDevices(inst.instance, &gpu_count, objs);
1860    if (err) ERR_EXIT(err);
1861
1862    gpus = malloc(sizeof(gpus[0]) * gpu_count);
1863    if (!gpus) ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY);
1864    for (uint32_t i = 0; i < gpu_count; i++) {
1865        AppGpuInit(&gpus[i], &inst, i, objs[i]);
1866        printf("\n\n");
1867    }
1868
1869    //---Layer-Device-Extensions---
1870    printf("Layers: count = %d\n", inst.global_layer_count);
1871    printf("=======\n");
1872    for (uint32_t i = 0; i < inst.global_layer_count; i++) {
1873        uint32_t layer_major, layer_minor, layer_patch;
1874        char spec_version[64], layer_version[64];
1875        VkLayerProperties const *layer_prop = &inst.global_layers[i].layer_properties;
1876
1877        ExtractVersion(layer_prop->specVersion, &layer_major, &layer_minor, &layer_patch);
1878        snprintf(spec_version, sizeof(spec_version), "%d.%d.%d", layer_major, layer_minor, layer_patch);
1879        snprintf(layer_version, sizeof(layer_version), "%d", layer_prop->implementationVersion);
1880        printf("%s (%s) Vulkan version %s, layer version %s\n", layer_prop->layerName, (char *)layer_prop->description,
1881               spec_version, layer_version);
1882
1883        AppDumpExtensions("\t", "Layer", inst.global_layers[i].extension_count, inst.global_layers[i].extension_properties);
1884
1885        char *layer_name = inst.global_layers[i].layer_properties.layerName;
1886        printf("\tDevices \tcount = %d\n", gpu_count);
1887        for (uint32_t j = 0; j < gpu_count; j++) {
1888            printf("\t\tGPU id       : %u (%s)\n", j, gpus[j].props.deviceName);
1889            uint32_t count = 0;
1890            VkExtensionProperties *props;
1891            AppGetPhysicalDeviceLayerExtensions(&gpus[j], layer_name, &count, &props);
1892            AppDumpExtensions("\t\t", "Layer-Device", count, props);
1893            free(props);
1894        }
1895        printf("\n");
1896    }
1897    fflush(stdout);
1898    //-----------------------------
1899
1900    printf("Presentable Surfaces:\n");
1901    printf("=====================\n");
1902    inst.width = 256;
1903    inst.height = 256;
1904    int format_count = 0;
1905    int present_mode_count = 0;
1906
1907#if defined(VK_USE_PLATFORM_XCB_KHR) || defined(VK_USE_PLATFORM_XLIB_KHR)
1908    if (getenv("DISPLAY") == NULL) {
1909        printf("'DISPLAY' environment variable not set... Exiting!\n");
1910        fflush(stdout);
1911        exit(1);
1912    }
1913#endif
1914//--WIN32--
1915#ifdef VK_USE_PLATFORM_WIN32_KHR
1916    if (CheckExtensionEnabled(VK_KHR_WIN32_SURFACE_EXTENSION_NAME, inst.inst_extensions, inst.inst_extensions_count)) {
1917        AppCreateWin32Window(&inst);
1918        for (uint32_t i = 0; i < gpu_count; i++) {
1919            AppCreateWin32Surface(&inst);
1920            printf("GPU id       : %u (%s)\n", i, gpus[i].props.deviceName);
1921            printf("Surface type : %s\n", VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
1922            format_count += AppDumpSurfaceFormats(&inst, &gpus[i]);
1923            present_mode_count += AppDumpSurfacePresentModes(&inst, &gpus[i]);
1924            AppDumpSurfaceCapabilities(&inst, &gpus[i]);
1925            AppDestroySurface(&inst);
1926        }
1927        AppDestroyWin32Window(&inst);
1928    }
1929//--XCB--
1930#elif VK_USE_PLATFORM_XCB_KHR
1931    if (CheckExtensionEnabled(VK_KHR_XCB_SURFACE_EXTENSION_NAME, inst.inst_extensions, inst.inst_extensions_count)) {
1932        AppCreateXcbWindow(&inst);
1933        for (uint32_t i = 0; i < gpu_count; i++) {
1934            AppCreateXcbSurface(&inst);
1935            printf("GPU id       : %u (%s)\n", i, gpus[i].props.deviceName);
1936            printf("Surface type : %s\n", VK_KHR_XCB_SURFACE_EXTENSION_NAME);
1937            format_count += AppDumpSurfaceFormats(&inst, &gpus[i]);
1938            present_mode_count += AppDumpSurfacePresentModes(&inst, &gpus[i]);
1939            AppDumpSurfaceCapabilities(&inst, &gpus[i]);
1940            AppDestroySurface(&inst);
1941        }
1942        AppDestroyXcbWindow(&inst);
1943    }
1944//--XLIB--
1945#elif VK_USE_PLATFORM_XLIB_KHR
1946    if (CheckExtensionEnabled(VK_KHR_XLIB_SURFACE_EXTENSION_NAME, inst.inst_extensions, inst.inst_extensions_count)) {
1947        AppCreateXlibWindow(&inst);
1948        for (uint32_t i = 0; i < gpu_count; i++) {
1949            AppCreateXlibSurface(&inst);
1950            printf("GPU id       : %u (%s)\n", i, gpus[i].props.deviceName);
1951            printf("Surface type : %s\n", VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
1952            format_count += AppDumpSurfaceFormats(&inst, &gpus[i]);
1953            present_mode_count += AppDumpSurfacePresentModes(&inst, &gpus[i]);
1954            AppDumpSurfaceCapabilities(&inst, &gpus[i]);
1955            AppDestroySurface(&inst);
1956        }
1957        AppDestroyXlibWindow(&inst);
1958    }
1959#endif
1960    // TODO: Android / Wayland / MIR
1961    if (!format_count && !present_mode_count) printf("None found\n");
1962    //---------
1963
1964    for (uint32_t i = 0; i < gpu_count; i++) {
1965        AppGpuDump(&gpus[i]);
1966        printf("\n\n");
1967    }
1968
1969    for (uint32_t i = 0; i < gpu_count; i++) AppGpuDestroy(&gpus[i]);
1970    free(gpus);
1971    free(objs);
1972
1973    AppDestroyInstance(&inst);
1974
1975    fflush(stdout);
1976#ifdef _WIN32
1977    if (ConsoleIsExclusive()) Sleep(INFINITE);
1978#endif
1979
1980    return 0;
1981}
1982