2 * Copyright (c) 2015-2016 The Khronos Group Inc.
3 * Copyright (c) 2015-2016 Valve Corporation
4 * Copyright (c) 2015-2016 LunarG, Inc.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
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 * Author: Shannon McPherson <shannon@lunarg.com>
27 #ifndef _POSIX_C_SOURCE
28 #define _POSIX_C_SOURCE 200809L
31 #define strndup(p, n) strdup(p)
46 #if defined(VK_USE_PLATFORM_XLIB_KHR) || defined(VK_USE_PLATFORM_XCB_KHR)
47 #include <X11/Xutil.h>
50 #if defined(VK_USE_PLATFORM_MIR_KHR)
51 #warning "Vulkaninfo does not have code for Mir at this time"
54 #include <vulkan/vulkan.h>
56 #define ERR(err) fprintf(stderr, "%s:%d: failed with %s\n", __FILE__, __LINE__, VkResultString(err));
60 #define snprintf _snprintf
61 #define strdup _strdup
63 // Returns nonzero if the console is used only for this process. Will return
64 // zero if another process (such as cmd.exe) is also attached.
65 static int ConsoleIsExclusive(void) {
67 DWORD num_pids = GetConsoleProcessList(pids, ARRAYSIZE(pids));
71 #define WAIT_FOR_CONSOLE_DESTROY \
73 if (ConsoleIsExclusive()) Sleep(INFINITE); \
76 #define WAIT_FOR_CONSOLE_DESTROY
79 #define ERR_EXIT(err) \
84 WAIT_FOR_CONSOLE_DESTROY; \
88 #if defined(NDEBUG) && defined(__GNUC__)
89 #define U_ASSERT_ONLY __attribute__((unused))
94 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
96 #define MAX_QUEUE_TYPES 5
97 #define APP_SHORT_NAME "vulkaninfo"
99 static bool html_output = false;
100 static bool human_readable_output = true;
101 static bool json_output = false;
102 static uint32_t selected_gpu = 0;
104 struct VkStructureHeader {
105 VkStructureType sType;
109 struct pNextChainBuildingBlockInfo {
110 VkStructureType sType;
114 struct LayerExtensionList {
115 VkLayerProperties layer_properties;
116 uint32_t extension_count;
117 VkExtensionProperties *extension_properties;
122 uint32_t global_layer_count;
123 struct LayerExtensionList *global_layers;
124 uint32_t global_extension_count;
125 VkExtensionProperties *global_extensions; // Instance Extensions
127 const char **inst_extensions;
128 uint32_t inst_extensions_count;
130 PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR;
131 PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR;
132 PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR;
133 PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR;
134 PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR;
135 PFN_vkGetPhysicalDeviceFormatProperties2KHR vkGetPhysicalDeviceFormatProperties2KHR;
136 PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR vkGetPhysicalDeviceQueueFamilyProperties2KHR;
137 PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR;
138 PFN_vkGetPhysicalDeviceMemoryProperties2KHR vkGetPhysicalDeviceMemoryProperties2KHR;
139 PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR vkGetPhysicalDeviceSurfaceCapabilities2KHR;
140 PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT vkGetPhysicalDeviceSurfaceCapabilities2EXT;
142 VkSurfaceCapabilitiesKHR surface_capabilities;
143 VkSurfaceCapabilities2KHR surface_capabilities2;
144 VkSharedPresentSurfaceCapabilitiesKHR shared_surface_capabilities;
145 VkSurfaceCapabilities2EXT surface_capabilities2_ext;
147 VkSurfaceKHR surface;
150 #ifdef VK_USE_PLATFORM_WIN32_KHR
151 HINSTANCE h_instance; // Windows Instance
152 HWND h_wnd; // window handle
153 #elif VK_USE_PLATFORM_XCB_KHR
154 xcb_connection_t *xcb_connection;
155 xcb_screen_t *xcb_screen;
156 xcb_window_t xcb_window;
157 #elif VK_USE_PLATFORM_XLIB_KHR
158 Display *xlib_display;
160 #elif VK_USE_PLATFORM_ANDROID_KHR // TODO
161 ANativeWindow *window;
167 VkPhysicalDevice obj;
169 VkPhysicalDeviceProperties props;
170 VkPhysicalDeviceProperties2KHR props2;
172 uint32_t queue_count;
173 VkQueueFamilyProperties *queue_props;
174 VkQueueFamilyProperties2KHR *queue_props2;
175 VkDeviceQueueCreateInfo *queue_reqs;
177 struct AppInstance *inst;
179 VkPhysicalDeviceMemoryProperties memory_props;
180 VkPhysicalDeviceMemoryProperties2KHR memory_props2;
182 VkPhysicalDeviceFeatures features;
183 VkPhysicalDeviceFeatures2KHR features2;
184 VkPhysicalDevice limits;
186 uint32_t device_extension_count;
187 VkExtensionProperties *device_extensions;
190 static VKAPI_ATTR VkBool32 VKAPI_CALL DbgCallback(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject,
191 size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg,
193 char *message = (char *)malloc(strlen(pMsg) + 100);
197 if (msgFlags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
198 sprintf(message, "ERROR: [%s] Code %d : %s", pLayerPrefix, msgCode, pMsg);
199 } else if (msgFlags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
200 sprintf(message, "WARNING: [%s] Code %d : %s", pLayerPrefix, msgCode, pMsg);
201 } else if (msgFlags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) {
202 sprintf(message, "INFO: [%s] Code %d : %s", pLayerPrefix, msgCode, pMsg);
203 } else if (msgFlags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) {
204 sprintf(message, "DEBUG: [%s] Code %d : %s", pLayerPrefix, msgCode, pMsg);
207 printf("%s\n", message);
212 * false indicates that layer should not bail-out of an
213 * API call that had validation failures. This may mean that the
214 * app dies inside the driver due to invalid parameter(s).
215 * That's what would happen without validation layers, so we'll
216 * keep that behavior here.
221 static const char *VkResultString(VkResult err) {
231 STR(VK_ERROR_INITIALIZATION_FAILED);
232 STR(VK_ERROR_OUT_OF_HOST_MEMORY);
233 STR(VK_ERROR_OUT_OF_DEVICE_MEMORY);
234 STR(VK_ERROR_DEVICE_LOST);
235 STR(VK_ERROR_LAYER_NOT_PRESENT);
236 STR(VK_ERROR_EXTENSION_NOT_PRESENT);
237 STR(VK_ERROR_MEMORY_MAP_FAILED);
238 STR(VK_ERROR_INCOMPATIBLE_DRIVER);
241 return "UNKNOWN_RESULT";
245 static const char *VkPhysicalDeviceTypeString(VkPhysicalDeviceType type) {
248 case VK_PHYSICAL_DEVICE_TYPE_##r: \
257 return "UNKNOWN_DEVICE";
261 static const char *VkFormatString(VkFormat fmt) {
264 case VK_FORMAT_##r: \
267 STR(R4G4_UNORM_PACK8);
268 STR(R4G4B4A4_UNORM_PACK16);
269 STR(B4G4R4A4_UNORM_PACK16);
270 STR(R5G6B5_UNORM_PACK16);
271 STR(B5G6R5_UNORM_PACK16);
272 STR(R5G5B5A1_UNORM_PACK16);
273 STR(B5G5R5A1_UNORM_PACK16);
274 STR(A1R5G5B5_UNORM_PACK16);
305 STR(R8G8B8A8_USCALED);
306 STR(R8G8B8A8_SSCALED);
312 STR(B8G8R8A8_USCALED);
313 STR(B8G8R8A8_SSCALED);
317 STR(A8B8G8R8_UNORM_PACK32);
318 STR(A8B8G8R8_SNORM_PACK32);
319 STR(A8B8G8R8_USCALED_PACK32);
320 STR(A8B8G8R8_SSCALED_PACK32);
321 STR(A8B8G8R8_UINT_PACK32);
322 STR(A8B8G8R8_SINT_PACK32);
323 STR(A8B8G8R8_SRGB_PACK32);
324 STR(A2R10G10B10_UNORM_PACK32);
325 STR(A2R10G10B10_SNORM_PACK32);
326 STR(A2R10G10B10_USCALED_PACK32);
327 STR(A2R10G10B10_SSCALED_PACK32);
328 STR(A2R10G10B10_UINT_PACK32);
329 STR(A2R10G10B10_SINT_PACK32);
330 STR(A2B10G10R10_UNORM_PACK32);
331 STR(A2B10G10R10_SNORM_PACK32);
332 STR(A2B10G10R10_USCALED_PACK32);
333 STR(A2B10G10R10_SSCALED_PACK32);
334 STR(A2B10G10R10_UINT_PACK32);
335 STR(A2B10G10R10_SINT_PACK32);
350 STR(R16G16B16_UNORM);
351 STR(R16G16B16_SNORM);
352 STR(R16G16B16_USCALED);
353 STR(R16G16B16_SSCALED);
356 STR(R16G16B16_SFLOAT);
357 STR(R16G16B16A16_UNORM);
358 STR(R16G16B16A16_SNORM);
359 STR(R16G16B16A16_USCALED);
360 STR(R16G16B16A16_SSCALED);
361 STR(R16G16B16A16_UINT);
362 STR(R16G16B16A16_SINT);
363 STR(R16G16B16A16_SFLOAT);
372 STR(R32G32B32_SFLOAT);
373 STR(R32G32B32A32_UINT);
374 STR(R32G32B32A32_SINT);
375 STR(R32G32B32A32_SFLOAT);
384 STR(R64G64B64_SFLOAT);
385 STR(R64G64B64A64_UINT);
386 STR(R64G64B64A64_SINT);
387 STR(R64G64B64A64_SFLOAT);
388 STR(B10G11R11_UFLOAT_PACK32);
389 STR(E5B9G9R9_UFLOAT_PACK32);
391 STR(X8_D24_UNORM_PACK32);
394 STR(D16_UNORM_S8_UINT);
395 STR(D24_UNORM_S8_UINT);
396 STR(D32_SFLOAT_S8_UINT);
397 STR(BC1_RGB_UNORM_BLOCK);
398 STR(BC1_RGB_SRGB_BLOCK);
399 STR(BC1_RGBA_UNORM_BLOCK);
400 STR(BC1_RGBA_SRGB_BLOCK);
401 STR(BC2_UNORM_BLOCK);
403 STR(BC3_UNORM_BLOCK);
405 STR(BC4_UNORM_BLOCK);
406 STR(BC4_SNORM_BLOCK);
407 STR(BC5_UNORM_BLOCK);
408 STR(BC5_SNORM_BLOCK);
409 STR(BC6H_UFLOAT_BLOCK);
410 STR(BC6H_SFLOAT_BLOCK);
411 STR(BC7_UNORM_BLOCK);
413 STR(ETC2_R8G8B8_UNORM_BLOCK);
414 STR(ETC2_R8G8B8_SRGB_BLOCK);
415 STR(ETC2_R8G8B8A1_UNORM_BLOCK);
416 STR(ETC2_R8G8B8A1_SRGB_BLOCK);
417 STR(ETC2_R8G8B8A8_UNORM_BLOCK);
418 STR(ETC2_R8G8B8A8_SRGB_BLOCK);
419 STR(EAC_R11_UNORM_BLOCK);
420 STR(EAC_R11_SNORM_BLOCK);
421 STR(EAC_R11G11_UNORM_BLOCK);
422 STR(EAC_R11G11_SNORM_BLOCK);
423 STR(ASTC_4x4_UNORM_BLOCK);
424 STR(ASTC_4x4_SRGB_BLOCK);
425 STR(ASTC_5x4_UNORM_BLOCK);
426 STR(ASTC_5x4_SRGB_BLOCK);
427 STR(ASTC_5x5_UNORM_BLOCK);
428 STR(ASTC_5x5_SRGB_BLOCK);
429 STR(ASTC_6x5_UNORM_BLOCK);
430 STR(ASTC_6x5_SRGB_BLOCK);
431 STR(ASTC_6x6_UNORM_BLOCK);
432 STR(ASTC_6x6_SRGB_BLOCK);
433 STR(ASTC_8x5_UNORM_BLOCK);
434 STR(ASTC_8x5_SRGB_BLOCK);
435 STR(ASTC_8x6_UNORM_BLOCK);
436 STR(ASTC_8x6_SRGB_BLOCK);
437 STR(ASTC_8x8_UNORM_BLOCK);
438 STR(ASTC_8x8_SRGB_BLOCK);
439 STR(ASTC_10x5_UNORM_BLOCK);
440 STR(ASTC_10x5_SRGB_BLOCK);
441 STR(ASTC_10x6_UNORM_BLOCK);
442 STR(ASTC_10x6_SRGB_BLOCK);
443 STR(ASTC_10x8_UNORM_BLOCK);
444 STR(ASTC_10x8_SRGB_BLOCK);
445 STR(ASTC_10x10_UNORM_BLOCK);
446 STR(ASTC_10x10_SRGB_BLOCK);
447 STR(ASTC_12x10_UNORM_BLOCK);
448 STR(ASTC_12x10_SRGB_BLOCK);
449 STR(ASTC_12x12_UNORM_BLOCK);
450 STR(ASTC_12x12_SRGB_BLOCK);
453 return "UNKNOWN_FORMAT";
456 #if defined(VK_USE_PLATFORM_XCB_KHR) || defined(VK_USE_PLATFORM_XLIB_KHR) || defined(VK_USE_PLATFORM_WIN32_KHR)
457 static const char *VkPresentModeString(VkPresentModeKHR mode) {
460 case VK_PRESENT_MODE_##r: \
465 STR(FIFO_RELAXED_KHR);
468 return "UNKNOWN_FORMAT";
473 static bool CheckExtensionEnabled(const char *extension_to_check, const char **extension_list, uint32_t extension_count) {
474 for (uint32_t i = 0; i < extension_count; ++i) {
475 if (!strcmp(extension_to_check, extension_list[i])) {
482 static bool CheckPhysicalDeviceExtensionIncluded(const char *extension_to_check, VkExtensionProperties *extension_list,
483 uint32_t extension_count) {
484 for (uint32_t i = 0; i < extension_count; ++i) {
485 if (!strcmp(extension_to_check, extension_list[i].extensionName)) {
492 static void buildpNextChain(struct VkStructureHeader *first, const struct pNextChainBuildingBlockInfo *chain_info,
493 uint32_t chain_info_len) {
494 struct VkStructureHeader *place = first;
496 for (uint32_t i = 0; i < chain_info_len; i++) {
497 place->pNext = malloc(chain_info[i].mem_size);
499 ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY);
501 place = place->pNext;
502 place->sType = chain_info[i].sType;
508 static void freepNextChain(struct VkStructureHeader *first) {
509 struct VkStructureHeader *place = first;
510 struct VkStructureHeader *next = NULL;
519 static void ExtractVersion(uint32_t version, uint32_t *major, uint32_t *minor, uint32_t *patch) {
520 *major = version >> 22;
521 *minor = (version >> 12) & 0x3ff;
522 *patch = version & 0xfff;
525 static void AppGetPhysicalDeviceLayerExtensions(struct AppGpu *gpu, char *layer_name, uint32_t *extension_count,
526 VkExtensionProperties **extension_properties) {
528 uint32_t ext_count = 0;
529 VkExtensionProperties *ext_ptr = NULL;
531 /* repeat get until VK_INCOMPLETE goes away */
533 err = vkEnumerateDeviceExtensionProperties(gpu->obj, layer_name, &ext_count, NULL);
539 ext_ptr = malloc(ext_count * sizeof(VkExtensionProperties));
540 err = vkEnumerateDeviceExtensionProperties(gpu->obj, layer_name, &ext_count, ext_ptr);
541 } while (err == VK_INCOMPLETE);
544 *extension_count = ext_count;
545 *extension_properties = ext_ptr;
548 static void AppGetGlobalLayerExtensions(char *layer_name, uint32_t *extension_count, VkExtensionProperties **extension_properties) {
550 uint32_t ext_count = 0;
551 VkExtensionProperties *ext_ptr = NULL;
553 /* repeat get until VK_INCOMPLETE goes away */
555 // gets the extension count if the last parameter is NULL
556 err = vkEnumerateInstanceExtensionProperties(layer_name, &ext_count, NULL);
562 ext_ptr = malloc(ext_count * sizeof(VkExtensionProperties));
563 // gets the extension properties if the last parameter is not NULL
564 err = vkEnumerateInstanceExtensionProperties(layer_name, &ext_count, ext_ptr);
565 } while (err == VK_INCOMPLETE);
567 *extension_count = ext_count;
568 *extension_properties = ext_ptr;
571 /* Gets a list of layer and instance extensions */
572 static void AppGetInstanceExtensions(struct AppInstance *inst) {
573 VkResult U_ASSERT_ONLY err;
578 VkLayerProperties *global_layer_properties = NULL;
579 struct LayerExtensionList *global_layers = NULL;
582 err = vkEnumerateInstanceLayerProperties(&count, NULL);
585 if (global_layer_properties) {
586 free(global_layer_properties);
588 global_layer_properties = malloc(sizeof(VkLayerProperties) * count);
589 assert(global_layer_properties);
594 global_layers = malloc(sizeof(struct LayerExtensionList) * count);
595 assert(global_layers);
597 err = vkEnumerateInstanceLayerProperties(&count, global_layer_properties);
598 } while (err == VK_INCOMPLETE);
601 inst->global_layer_count = count;
602 inst->global_layers = global_layers;
604 for (uint32_t i = 0; i < inst->global_layer_count; ++i) {
605 VkLayerProperties *src_info = &global_layer_properties[i];
606 struct LayerExtensionList *dst_info = &inst->global_layers[i];
607 memcpy(&dst_info->layer_properties, src_info, sizeof(VkLayerProperties));
609 // Save away layer extension info for report
610 // Gets layer extensions, if first parameter is not NULL
611 AppGetGlobalLayerExtensions(src_info->layerName, &dst_info->extension_count, &dst_info->extension_properties);
613 free(global_layer_properties);
615 // Collect global extensions
616 inst->global_extension_count = 0;
617 // Gets instance extensions, if no layer was specified in the first
619 AppGetGlobalLayerExtensions(NULL, &inst->global_extension_count, &inst->global_extensions);
622 // Prints opening code for html output file
623 void PrintHtmlHeader(FILE *out) {
624 fprintf(out, "<!doctype html>\n");
625 fprintf(out, "<html>\n");
626 fprintf(out, "\t<head>\n");
627 fprintf(out, "\t\t<title>Vulkan Info</title>\n");
628 fprintf(out, "\t\t<style type='text/css'>\n");
629 fprintf(out, "\t\thtml {\n");
630 fprintf(out, "\t\t\tbackground-color: #0b1e48;\n");
631 fprintf(out, "\t\t\tbackground-image: url(\"https://vulkan.lunarg.com/img/bg-starfield.jpg\");\n");
632 fprintf(out, "\t\t\tbackground-position: center;\n");
633 fprintf(out, "\t\t\t-webkit-background-size: cover;\n");
634 fprintf(out, "\t\t\t-moz-background-size: cover;\n");
635 fprintf(out, "\t\t\t-o-background-size: cover;\n");
636 fprintf(out, "\t\t\tbackground-size: cover;\n");
637 fprintf(out, "\t\t\tbackground-attachment: fixed;\n");
638 fprintf(out, "\t\t\tbackground-repeat: no-repeat;\n");
639 fprintf(out, "\t\t\theight: 100%%;\n");
640 fprintf(out, "\t\t}\n");
641 fprintf(out, "\t\t#header {\n");
642 fprintf(out, "\t\t\tz-index: -1;\n");
643 fprintf(out, "\t\t}\n");
644 fprintf(out, "\t\t#header>img {\n");
645 fprintf(out, "\t\t\tposition: absolute;\n");
646 fprintf(out, "\t\t\twidth: 160px;\n");
647 fprintf(out, "\t\t\tmargin-left: -280px;\n");
648 fprintf(out, "\t\t\ttop: -10px;\n");
649 fprintf(out, "\t\t\tleft: 50%%;\n");
650 fprintf(out, "\t\t}\n");
651 fprintf(out, "\t\t#header>h1 {\n");
652 fprintf(out, "\t\t\tfont-family: Arial, \"Helvetica Neue\", Helvetica, sans-serif;\n");
653 fprintf(out, "\t\t\tfont-size: 44px;\n");
654 fprintf(out, "\t\t\tfont-weight: 200;\n");
655 fprintf(out, "\t\t\ttext-shadow: 4px 4px 5px #000;\n");
656 fprintf(out, "\t\t\tcolor: #eee;\n");
657 fprintf(out, "\t\t\tposition: absolute;\n");
658 fprintf(out, "\t\t\twidth: 400px;\n");
659 fprintf(out, "\t\t\tmargin-left: -80px;\n");
660 fprintf(out, "\t\t\ttop: 8px;\n");
661 fprintf(out, "\t\t\tleft: 50%%;\n");
662 fprintf(out, "\t\t}\n");
663 fprintf(out, "\t\tbody {\n");
664 fprintf(out, "\t\t\tfont-family: Consolas, monaco, monospace;\n");
665 fprintf(out, "\t\t\tfont-size: 14px;\n");
666 fprintf(out, "\t\t\tline-height: 20px;\n");
667 fprintf(out, "\t\t\tcolor: #eee;\n");
668 fprintf(out, "\t\t\theight: 100%%;\n");
669 fprintf(out, "\t\t\tmargin: 0;\n");
670 fprintf(out, "\t\t\toverflow: hidden;\n");
671 fprintf(out, "\t\t}\n");
672 fprintf(out, "\t\t#wrapper {\n");
673 fprintf(out, "\t\t\tbackground-color: rgba(0, 0, 0, 0.7);\n");
674 fprintf(out, "\t\t\tborder: 1px solid #446;\n");
675 fprintf(out, "\t\t\tbox-shadow: 0px 0px 10px #000;\n");
676 fprintf(out, "\t\t\tpadding: 8px 12px;\n\n");
677 fprintf(out, "\t\t\tdisplay: inline-block;\n");
678 fprintf(out, "\t\t\tposition: absolute;\n");
679 fprintf(out, "\t\t\ttop: 80px;\n");
680 fprintf(out, "\t\t\tbottom: 25px;\n");
681 fprintf(out, "\t\t\tleft: 50px;\n");
682 fprintf(out, "\t\t\tright: 50px;\n");
683 fprintf(out, "\t\t\toverflow: auto;\n");
684 fprintf(out, "\t\t}\n");
685 fprintf(out, "\t\tdetails>details {\n");
686 fprintf(out, "\t\t\tmargin-left: 22px;\n");
687 fprintf(out, "\t\t}\n");
688 fprintf(out, "\t\tdetails>summary:only-child::-webkit-details-marker {\n");
689 fprintf(out, "\t\t\tdisplay: none;\n");
690 fprintf(out, "\t\t}\n");
691 fprintf(out, "\t\t.var, .type, .val {\n");
692 fprintf(out, "\t\t\tdisplay: inline;\n");
693 fprintf(out, "\t\t}\n");
694 fprintf(out, "\t\t.var {\n");
695 fprintf(out, "\t\t}\n");
696 fprintf(out, "\t\t.type {\n");
697 fprintf(out, "\t\t\tcolor: #acf;\n");
698 fprintf(out, "\t\t\tmargin: 0 12px;\n");
699 fprintf(out, "\t\t}\n");
700 fprintf(out, "\t\t.val {\n");
701 fprintf(out, "\t\t\tcolor: #afa;\n");
702 fprintf(out, "\t\t\tbackground: #222;\n");
703 fprintf(out, "\t\t\ttext-align: right;\n");
704 fprintf(out, "\t\t}\n");
705 fprintf(out, "\t\t</style>\n");
706 fprintf(out, "\t</head>\n");
707 fprintf(out, "\t<body>\n");
708 fprintf(out, "\t\t<div id='header'>\n");
709 fprintf(out, "\t\t\t<h1>Vulkan Info</h1>\n");
710 fprintf(out, "\t\t</div>\n");
711 fprintf(out, "\t\t<div id='wrapper'>\n");
714 // Prints closing code for html output file
715 void PrintHtmlFooter(FILE *out) {
716 fprintf(out, "\t\t</div>\n");
717 fprintf(out, "\t</body>\n");
718 fprintf(out, "</html>");
721 // Prints opening code for json output file
722 void PrintJsonHeader(const int vulkan_major, const int vulkan_minor, const int vulkan_patch) {
724 printf("\t\"$schema\": \"https://schema.khronos.org/vulkan/devsim_1_0_0.json#\",\n");
725 printf("\t\"comments\": {\n");
726 printf("\t\t\"desc\": \"JSON configuration file describing GPU %u. Generated using the VulkanInfo program.\",\n", selected_gpu);
727 printf("\t\t\"vulkanApiVersion\": \"%d.%d.%d\"\n", vulkan_major, vulkan_minor, vulkan_patch);
731 // Checks if current argument specifies json output, interprets/updates gpu selection
732 void CheckForJsonOption(const char *arg) {
733 if (strncmp("--json", arg, 6) == 0 || strcmp(arg, "-j") == 0) {
734 if (strlen(arg) > 7 && strncmp("--json=", arg, 7) == 0) {
735 selected_gpu = strtol(arg + 7, NULL, 10);
737 human_readable_output = false;
742 // static void AppCreateInstance(struct AppInstance *inst, int argc, ...) {
743 static void AppCreateInstance(struct AppInstance *inst) {
744 AppGetInstanceExtensions(inst);
746 //---Build a list of extensions to load---
748 const char *info_instance_extensions[] = {VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME,
749 VK_KHR_DISPLAY_EXTENSION_NAME,
750 VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
751 VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME,
752 VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME,
753 VK_KHR_SURFACE_EXTENSION_NAME,
754 VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME,
755 #ifdef VK_USE_PLATFORM_WIN32_KHR
756 VK_KHR_WIN32_SURFACE_EXTENSION_NAME
757 #elif VK_USE_PLATFORM_XCB_KHR
758 VK_KHR_XCB_SURFACE_EXTENSION_NAME
759 #elif VK_USE_PLATFORM_XLIB_KHR
760 VK_KHR_XLIB_SURFACE_EXTENSION_NAME
761 #elif VK_USE_PLATFORM_WAYLAND_KHR
762 VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME
763 #elif VK_USE_PLATFORM_ANDROID_KHR
764 VK_KHR_ANDROID_SURFACE_EXTENSION_NAME
767 const uint32_t info_instance_extensions_count = ARRAY_SIZE(info_instance_extensions);
768 inst->inst_extensions = malloc(sizeof(char *) * ARRAY_SIZE(info_instance_extensions));
769 inst->inst_extensions_count = 0;
771 for (uint32_t k = 0; (k < info_instance_extensions_count); ++k) {
772 for (uint32_t j = 0; (j < inst->global_extension_count); ++j) {
773 const char *found_name = inst->global_extensions[j].extensionName;
774 if (!strcmp(info_instance_extensions[k], found_name)) {
775 inst->inst_extensions[inst->inst_extensions_count++] = info_instance_extensions[k];
781 //----------------------------------------
783 const VkApplicationInfo app_info = {
784 .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
786 .pApplicationName = APP_SHORT_NAME,
787 .applicationVersion = 1,
788 .pEngineName = APP_SHORT_NAME,
790 .apiVersion = VK_API_VERSION_1_0,
793 VkInstanceCreateInfo inst_info = {.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
795 .pApplicationInfo = &app_info,
796 .enabledLayerCount = 0,
797 .ppEnabledLayerNames = NULL,
798 .enabledExtensionCount = inst->inst_extensions_count,
799 .ppEnabledExtensionNames = inst->inst_extensions};
801 VkDebugReportCallbackCreateInfoEXT dbg_info;
802 memset(&dbg_info, 0, sizeof(dbg_info));
803 dbg_info.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
804 dbg_info.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
805 dbg_info.pfnCallback = DbgCallback;
806 inst_info.pNext = &dbg_info;
808 VkResult U_ASSERT_ONLY err;
809 err = vkCreateInstance(&inst_info, NULL, &inst->instance);
810 if (err == VK_ERROR_INCOMPATIBLE_DRIVER) {
811 fprintf(stderr, "Cannot create Vulkan instance.\n");
817 inst->vkGetPhysicalDeviceSurfaceSupportKHR =
818 (PFN_vkGetPhysicalDeviceSurfaceSupportKHR)vkGetInstanceProcAddr(inst->instance, "vkGetPhysicalDeviceSurfaceSupportKHR");
819 inst->vkGetPhysicalDeviceSurfaceCapabilitiesKHR = (PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR)vkGetInstanceProcAddr(
820 inst->instance, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR");
821 inst->vkGetPhysicalDeviceSurfaceFormatsKHR =
822 (PFN_vkGetPhysicalDeviceSurfaceFormatsKHR)vkGetInstanceProcAddr(inst->instance, "vkGetPhysicalDeviceSurfaceFormatsKHR");
823 inst->vkGetPhysicalDeviceSurfacePresentModesKHR = (PFN_vkGetPhysicalDeviceSurfacePresentModesKHR)vkGetInstanceProcAddr(
824 inst->instance, "vkGetPhysicalDeviceSurfacePresentModesKHR");
825 inst->vkGetPhysicalDeviceProperties2KHR =
826 (PFN_vkGetPhysicalDeviceProperties2KHR)vkGetInstanceProcAddr(inst->instance, "vkGetPhysicalDeviceProperties2KHR");
827 inst->vkGetPhysicalDeviceFormatProperties2KHR = (PFN_vkGetPhysicalDeviceFormatProperties2KHR)vkGetInstanceProcAddr(
828 inst->instance, "vkGetPhysicalDeviceFormatProperties2KHR");
829 inst->vkGetPhysicalDeviceQueueFamilyProperties2KHR = (PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR)vkGetInstanceProcAddr(
830 inst->instance, "vkGetPhysicalDeviceQueueFamilyProperties2KHR");
831 inst->vkGetPhysicalDeviceFeatures2KHR =
832 (PFN_vkGetPhysicalDeviceFeatures2KHR)vkGetInstanceProcAddr(inst->instance, "vkGetPhysicalDeviceFeatures2KHR");
833 inst->vkGetPhysicalDeviceMemoryProperties2KHR = (PFN_vkGetPhysicalDeviceMemoryProperties2KHR)vkGetInstanceProcAddr(
834 inst->instance, "vkGetPhysicalDeviceMemoryProperties2KHR");
835 inst->vkGetPhysicalDeviceSurfaceCapabilities2KHR = (PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR)vkGetInstanceProcAddr(
836 inst->instance, "vkGetPhysicalDeviceSurfaceCapabilities2KHR");
837 inst->vkGetPhysicalDeviceSurfaceCapabilities2EXT = (PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT)vkGetInstanceProcAddr(
838 inst->instance, "vkGetPhysicalDeviceSurfaceCapabilities2EXT");
841 //-----------------------------------------------------------
843 static void AppDestroyInstance(struct AppInstance *inst) {
844 free(inst->global_extensions);
845 for (uint32_t i = 0; i < inst->global_layer_count; ++i) {
846 free(inst->global_layers[i].extension_properties);
848 free(inst->global_layers);
849 free((char **)inst->inst_extensions);
850 vkDestroyInstance(inst->instance, NULL);
853 static void AppGpuInit(struct AppGpu *gpu, struct AppInstance *inst, uint32_t id, VkPhysicalDevice obj) {
856 memset(gpu, 0, sizeof(*gpu));
862 vkGetPhysicalDeviceProperties(gpu->obj, &gpu->props);
864 if (CheckExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, gpu->inst->inst_extensions,
865 gpu->inst->inst_extensions_count)) {
866 struct pNextChainBuildingBlockInfo chain_info[] = {
867 {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT,
868 .mem_size = sizeof(VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT)},
869 {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES_KHR,
870 .mem_size = sizeof(VkPhysicalDevicePointClippingPropertiesKHR)},
871 {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR,
872 .mem_size = sizeof(VkPhysicalDevicePushDescriptorPropertiesKHR)},
873 {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISCARD_RECTANGLE_PROPERTIES_EXT,
874 .mem_size = sizeof(VkPhysicalDeviceDiscardRectanglePropertiesEXT)},
875 {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHR,
876 .mem_size = sizeof(VkPhysicalDeviceMultiviewPropertiesKHR)}};
878 uint32_t chain_info_len = ARRAY_SIZE(chain_info);
880 gpu->props2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR;
881 buildpNextChain((struct VkStructureHeader *)&gpu->props2, chain_info, chain_info_len);
883 inst->vkGetPhysicalDeviceProperties2KHR(gpu->obj, &gpu->props2);
886 /* get queue count */
887 vkGetPhysicalDeviceQueueFamilyProperties(gpu->obj, &gpu->queue_count, NULL);
889 gpu->queue_props = malloc(sizeof(gpu->queue_props[0]) * gpu->queue_count);
891 if (!gpu->queue_props) {
892 ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY);
894 vkGetPhysicalDeviceQueueFamilyProperties(gpu->obj, &gpu->queue_count, gpu->queue_props);
896 if (CheckExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, gpu->inst->inst_extensions,
897 gpu->inst->inst_extensions_count)) {
898 gpu->queue_props2 = malloc(sizeof(gpu->queue_props2[0]) * gpu->queue_count);
900 if (!gpu->queue_props2) {
901 ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY);
904 for (i = 0; i < gpu->queue_count; ++i) {
905 gpu->queue_props2[i].sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR;
906 gpu->queue_props2[i].pNext = NULL;
909 inst->vkGetPhysicalDeviceQueueFamilyProperties2KHR(gpu->obj, &gpu->queue_count, gpu->queue_props2);
912 /* set up queue requests */
913 gpu->queue_reqs = malloc(sizeof(*gpu->queue_reqs) * gpu->queue_count);
914 if (!gpu->queue_reqs) {
915 ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY);
917 for (i = 0; i < gpu->queue_count; ++i) {
918 float *queue_priorities = NULL;
919 if (CheckExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, gpu->inst->inst_extensions,
920 gpu->inst->inst_extensions_count)) {
921 queue_priorities = malloc(gpu->queue_props2[i].queueFamilyProperties.queueCount * sizeof(float));
923 queue_priorities = malloc(gpu->queue_props[i].queueCount * sizeof(float));
925 if (!queue_priorities) {
926 ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY);
929 if (CheckExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, gpu->inst->inst_extensions,
930 gpu->inst->inst_extensions_count)) {
931 memset(queue_priorities, 0, gpu->queue_props2[i].queueFamilyProperties.queueCount * sizeof(float));
933 memset(queue_priorities, 0, gpu->queue_props[i].queueCount * sizeof(float));
936 gpu->queue_reqs[i].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
937 gpu->queue_reqs[i].pNext = NULL;
938 gpu->queue_reqs[i].flags = 0;
939 gpu->queue_reqs[i].queueFamilyIndex = i;
941 if (CheckExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, gpu->inst->inst_extensions,
942 gpu->inst->inst_extensions_count)) {
943 gpu->queue_reqs[i].queueCount = gpu->queue_props2[i].queueFamilyProperties.queueCount;
945 gpu->queue_reqs[i].queueCount = gpu->queue_props[i].queueCount;
948 gpu->queue_reqs[i].pQueuePriorities = queue_priorities;
951 vkGetPhysicalDeviceMemoryProperties(gpu->obj, &gpu->memory_props);
953 vkGetPhysicalDeviceFeatures(gpu->obj, &gpu->features);
955 if (CheckExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, gpu->inst->inst_extensions,
956 gpu->inst->inst_extensions_count)) {
957 gpu->memory_props2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR;
958 gpu->memory_props2.pNext = NULL;
960 inst->vkGetPhysicalDeviceMemoryProperties2KHR(gpu->obj, &gpu->memory_props2);
962 struct pNextChainBuildingBlockInfo chain_info[] = {
963 {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR,
964 .mem_size = sizeof(VkPhysicalDevice16BitStorageFeaturesKHR)},
965 {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES_KHR,
966 .mem_size = sizeof(VkPhysicalDeviceSamplerYcbcrConversionFeaturesKHR)},
967 {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR,
968 .mem_size = sizeof(VkPhysicalDeviceVariablePointerFeaturesKHR)},
969 {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT,
970 .mem_size = sizeof(VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT)},
971 {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR,
972 .mem_size = sizeof(VkPhysicalDeviceMultiviewFeaturesKHR)}};
974 uint32_t chain_info_len = ARRAY_SIZE(chain_info);
976 gpu->features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR;
977 buildpNextChain((struct VkStructureHeader *)&gpu->features2, chain_info, chain_info_len);
979 inst->vkGetPhysicalDeviceFeatures2KHR(gpu->obj, &gpu->features2);
982 AppGetPhysicalDeviceLayerExtensions(gpu, NULL, &gpu->device_extension_count, &gpu->device_extensions);
985 static void AppGpuDestroy(struct AppGpu *gpu) {
986 free(gpu->device_extensions);
988 if (CheckExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, gpu->inst->inst_extensions,
989 gpu->inst->inst_extensions_count)) {
990 freepNextChain(gpu->features2.pNext);
993 for (uint32_t i = 0; i < gpu->queue_count; ++i) {
994 free((void *)gpu->queue_reqs[i].pQueuePriorities);
996 free(gpu->queue_reqs);
998 free(gpu->queue_props);
999 if (CheckExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, gpu->inst->inst_extensions,
1000 gpu->inst->inst_extensions_count)) {
1001 free(gpu->queue_props2);
1003 freepNextChain(gpu->props2.pNext);
1009 //-----------------------------------------------------------
1011 //---------------------------Win32---------------------------
1012 #ifdef VK_USE_PLATFORM_WIN32_KHR
1014 // MS-Windows event handling function:
1015 LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
1016 return (DefWindowProc(hWnd, uMsg, wParam, lParam));
1019 static void AppCreateWin32Window(struct AppInstance *inst) {
1020 inst->h_instance = GetModuleHandle(NULL);
1022 WNDCLASSEX win_class;
1024 // Initialize the window class structure:
1025 win_class.cbSize = sizeof(WNDCLASSEX);
1026 win_class.style = CS_HREDRAW | CS_VREDRAW;
1027 win_class.lpfnWndProc = WndProc;
1028 win_class.cbClsExtra = 0;
1029 win_class.cbWndExtra = 0;
1030 win_class.hInstance = inst->h_instance;
1031 win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
1032 win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
1033 win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
1034 win_class.lpszMenuName = NULL;
1035 win_class.lpszClassName = APP_SHORT_NAME;
1036 win_class.hInstance = inst->h_instance;
1037 win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
1038 // Register window class:
1039 if (!RegisterClassEx(&win_class)) {
1040 // It didn't work, so try to give a useful error:
1041 fprintf(stderr, "Failed to register the window class!\n");
1044 // Create window with the registered class:
1045 RECT wr = { 0, 0, inst->width, inst->height };
1046 AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
1047 inst->h_wnd = CreateWindowEx(0,
1048 APP_SHORT_NAME, // class name
1049 APP_SHORT_NAME, // app name
1050 //WS_VISIBLE | WS_SYSMENU |
1051 WS_OVERLAPPEDWINDOW, // window style
1052 100, 100, // x/y coords
1053 wr.right - wr.left, // width
1054 wr.bottom - wr.top, // height
1055 NULL, // handle to parent
1056 NULL, // handle to menu
1057 inst->h_instance, // hInstance
1058 NULL); // no extra parameters
1060 // It didn't work, so try to give a useful error:
1061 fprintf(stderr, "Failed to create a window!\n");
1066 static void AppCreateWin32Surface(struct AppInstance *inst) {
1067 VkResult U_ASSERT_ONLY err;
1068 VkWin32SurfaceCreateInfoKHR createInfo;
1069 createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
1070 createInfo.pNext = NULL;
1071 createInfo.flags = 0;
1072 createInfo.hinstance = inst->h_instance;
1073 createInfo.hwnd = inst->h_wnd;
1074 err = vkCreateWin32SurfaceKHR(inst->instance, &createInfo, NULL, &inst->surface);
1078 static void AppDestroyWin32Window(struct AppInstance *inst) {
1079 DestroyWindow(inst->h_wnd);
1081 #endif //VK_USE_PLATFORM_WIN32_KHR
1082 //-----------------------------------------------------------
1084 #if defined(VK_USE_PLATFORM_XCB_KHR) || \
1085 defined(VK_USE_PLATFORM_XLIB_KHR) || \
1086 defined(VK_USE_PLATFORM_WIN32_KHR)
1087 static void AppDestroySurface(struct AppInstance *inst) { //same for all platforms
1088 vkDestroySurfaceKHR(inst->instance, inst->surface, NULL);
1092 //----------------------------XCB----------------------------
1094 #ifdef VK_USE_PLATFORM_XCB_KHR
1095 static void AppCreateXcbWindow(struct AppInstance *inst) {
1096 //--Init Connection--
1097 const xcb_setup_t *setup;
1098 xcb_screen_iterator_t iter;
1101 // API guarantees non-null xcb_connection
1102 inst->xcb_connection = xcb_connect(NULL, &scr);
1103 int conn_error = xcb_connection_has_error(inst->xcb_connection);
1105 fprintf(stderr, "XCB failed to connect to the X server due to error:%d.\n", conn_error);
1107 inst->xcb_connection = NULL;
1110 setup = xcb_get_setup(inst->xcb_connection);
1111 iter = xcb_setup_roots_iterator(setup);
1113 xcb_screen_next(&iter);
1116 inst->xcb_screen = iter.data;
1117 //-------------------
1119 inst->xcb_window = xcb_generate_id(inst->xcb_connection);
1120 xcb_create_window(inst->xcb_connection, XCB_COPY_FROM_PARENT, inst->xcb_window,
1121 inst->xcb_screen->root, 0, 0, inst->width, inst->height, 0,
1122 XCB_WINDOW_CLASS_INPUT_OUTPUT, inst->xcb_screen->root_visual,
1125 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(inst->xcb_connection, 1, 12, "WM_PROTOCOLS");
1126 xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(inst->xcb_connection, cookie, 0);
1130 static void AppCreateXcbSurface(struct AppInstance *inst) {
1131 if (!inst->xcb_connection) {
1135 VkResult U_ASSERT_ONLY err;
1136 VkXcbSurfaceCreateInfoKHR xcb_createInfo;
1137 xcb_createInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
1138 xcb_createInfo.pNext = NULL;
1139 xcb_createInfo.flags = 0;
1140 xcb_createInfo.connection = inst->xcb_connection;
1141 xcb_createInfo.window = inst->xcb_window;
1142 err = vkCreateXcbSurfaceKHR(inst->instance, &xcb_createInfo, NULL, &inst->surface);
1146 static void AppDestroyXcbWindow(struct AppInstance *inst) {
1147 if (!inst->xcb_connection) {
1148 return; // Nothing to destroy
1151 xcb_destroy_window(inst->xcb_connection, inst->xcb_window);
1152 xcb_disconnect(inst->xcb_connection);
1154 //VK_USE_PLATFORM_XCB_KHR
1155 //-----------------------------------------------------------
1157 //----------------------------XLib---------------------------
1158 #elif VK_USE_PLATFORM_XLIB_KHR
1159 static void AppCreateXlibWindow(struct AppInstance *inst) {
1160 long visualMask = VisualScreenMask;
1161 int numberOfVisuals;
1163 inst->xlib_display = XOpenDisplay(NULL);
1164 if (inst->xlib_display == NULL) {
1165 fprintf(stderr, "XLib failed to connect to the X server.\nExiting ...\n");
1169 XVisualInfo vInfoTemplate={};
1170 vInfoTemplate.screen = DefaultScreen(inst->xlib_display);
1171 XVisualInfo *visualInfo = XGetVisualInfo(inst->xlib_display, visualMask,
1172 &vInfoTemplate, &numberOfVisuals);
1173 inst->xlib_window = XCreateWindow(
1174 inst->xlib_display, RootWindow(inst->xlib_display, vInfoTemplate.screen), 0, 0,
1175 inst->width, inst->height, 0, visualInfo->depth, InputOutput,
1176 visualInfo->visual, 0, NULL);
1178 XSync(inst->xlib_display,false);
1181 static void AppCreateXlibSurface(struct AppInstance *inst) {
1182 VkResult U_ASSERT_ONLY err;
1183 VkXlibSurfaceCreateInfoKHR createInfo;
1184 createInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
1185 createInfo.pNext = NULL;
1186 createInfo.flags = 0;
1187 createInfo.dpy = inst->xlib_display;
1188 createInfo.window = inst->xlib_window;
1189 err = vkCreateXlibSurfaceKHR(inst->instance, &createInfo, NULL, &inst->surface);
1193 static void AppDestroyXlibWindow(struct AppInstance *inst) {
1194 XDestroyWindow(inst->xlib_display, inst->xlib_window);
1195 XCloseDisplay(inst->xlib_display);
1197 #endif //VK_USE_PLATFORM_XLIB_KHR
1198 //-----------------------------------------------------------
1200 #if defined(VK_USE_PLATFORM_XCB_KHR) || \
1201 defined(VK_USE_PLATFORM_XLIB_KHR) || \
1202 defined(VK_USE_PLATFORM_WIN32_KHR)
1203 static int AppDumpSurfaceFormats(struct AppInstance *inst, struct AppGpu *gpu, FILE *out) {
1204 // Get the list of VkFormat's that are supported
1205 VkResult U_ASSERT_ONLY err;
1206 uint32_t format_count = 0;
1207 err = inst->vkGetPhysicalDeviceSurfaceFormatsKHR(gpu->obj, inst->surface, &format_count, NULL);
1210 VkSurfaceFormatKHR *surf_formats = (VkSurfaceFormatKHR *)malloc(format_count * sizeof(VkSurfaceFormatKHR));
1212 ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY);
1213 err = inst->vkGetPhysicalDeviceSurfaceFormatsKHR(gpu->obj, inst->surface, &format_count, surf_formats);
1217 fprintf(out, "\t\t\t\t<details><summary>Formats: count = <div class='val'>%d</div></summary>", format_count);
1218 if (format_count > 0) {
1221 fprintf(out, "</details>\n");
1223 } else if (human_readable_output) {
1224 printf("Formats:\t\tcount = %d\n", format_count);
1226 for (uint32_t i = 0; i < format_count; ++i) {
1228 fprintf(out, "\t\t\t\t\t<details><summary><div class='type'>%s</div></summary></details>\n",
1229 VkFormatString(surf_formats[i].format));
1230 } else if (human_readable_output) {
1231 printf("\t%s\n", VkFormatString(surf_formats[i].format));
1234 if (format_count > 0 && html_output) {
1235 fprintf(out, "\t\t\t\t</details>\n");
1242 return format_count;
1245 static int AppDumpSurfacePresentModes(struct AppInstance *inst, struct AppGpu *gpu, FILE *out) {
1246 // Get the list of VkPresentMode's that are supported:
1247 VkResult U_ASSERT_ONLY err;
1248 uint32_t present_mode_count = 0;
1249 err = inst->vkGetPhysicalDeviceSurfacePresentModesKHR(gpu->obj, inst->surface, &present_mode_count, NULL);
1252 VkPresentModeKHR *surf_present_modes = (VkPresentModeKHR *)malloc(present_mode_count * sizeof(VkPresentInfoKHR));
1253 if (!surf_present_modes)
1254 ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY);
1255 err = inst->vkGetPhysicalDeviceSurfacePresentModesKHR(gpu->obj, inst->surface, &present_mode_count, surf_present_modes);
1259 fprintf(out, "\t\t\t\t<details><summary>Present Modes: count = <div class='val'>%d</div></summary>", present_mode_count);
1260 if (present_mode_count > 0) {
1263 fprintf(out, "</details>");
1265 } else if (human_readable_output) {
1266 printf("Present Modes:\t\tcount = %d\n", present_mode_count);
1268 for (uint32_t i = 0; i < present_mode_count; ++i) {
1270 fprintf(out, "\t\t\t\t\t<details><summary><div class='type'>%s</div></summary></details>\n",
1271 VkPresentModeString(surf_present_modes[i]));
1272 } else if (human_readable_output) {
1273 printf("\t%s\n", VkPresentModeString(surf_present_modes[i]));
1276 if (present_mode_count > 0 && html_output) {
1277 fprintf(out, "\t\t\t\t</details>\n");
1282 free(surf_present_modes);
1284 return present_mode_count;
1287 static void AppDumpSurfaceCapabilities(struct AppInstance *inst, struct AppGpu *gpu, FILE *out) {
1288 if (CheckExtensionEnabled(VK_KHR_SURFACE_EXTENSION_NAME, gpu->inst->inst_extensions, gpu->inst->inst_extensions_count)) {
1289 inst->vkGetPhysicalDeviceSurfaceCapabilitiesKHR(gpu->obj, inst->surface, &inst->surface_capabilities);
1292 fprintf(out, "\t\t\t\t<details><summary>VkSurfaceCapabilitiesKHR</summary>\n");
1293 fprintf(out, "\t\t\t\t\t<details><summary>minImageCount = <div class='val'>%u</div></summary></details>\n", inst->surface_capabilities.minImageCount);
1294 fprintf(out, "\t\t\t\t\t<details><summary>maxImageCount = <div class='val'>%u</div></summary></details>\n", inst->surface_capabilities.maxImageCount);
1295 fprintf(out, "\t\t\t\t\t<details><summary>currentExtent</summary>\n");
1296 fprintf(out, "\t\t\t\t\t\t<details><summary>width = <div class='val'>%u</div></summary></details>\n", inst->surface_capabilities.currentExtent.width);
1297 fprintf(out, "\t\t\t\t\t\t<details><summary>height = <div class='val'>%u</div></summary></details>\n", inst->surface_capabilities.currentExtent.height);
1298 fprintf(out, "\t\t\t\t\t</details>\n");
1299 fprintf(out, "\t\t\t\t\t<details><summary>minImageExtent</summary>\n");
1300 fprintf(out, "\t\t\t\t\t\t<details><summary>width = <div class='val'>%u</div></summary></details>\n", inst->surface_capabilities.minImageExtent.width);
1301 fprintf(out, "\t\t\t\t\t\t<details><summary>height = <div class='val'>%u</div></summary></details>\n", inst->surface_capabilities.minImageExtent.height);
1302 fprintf(out, "\t\t\t\t\t</details>\n");
1303 fprintf(out, "\t\t\t\t\t<details><summary>maxImageExtent</summary>\n");
1304 fprintf(out, "\t\t\t\t\t\t<details><summary>width = <div class='val'>%u</div></summary></details>\n", inst->surface_capabilities.maxImageExtent.width);
1305 fprintf(out, "\t\t\t\t\t\t<details><summary>height = <div class='val'>%u</div></summary></details>\n", inst->surface_capabilities.maxImageExtent.height);
1306 fprintf(out, "\t\t\t\t\t</details>\n");
1307 fprintf(out, "\t\t\t\t\t<details><summary>maxImageArrayLayers = <div class='val'>%u</div></summary></details>\n", inst->surface_capabilities.maxImageArrayLayers);
1308 fprintf(out, "\t\t\t\t\t<details><summary>supportedTransform</summary>\n");
1309 if (inst->surface_capabilities.supportedTransforms == 0) {
1310 fprintf(out, "\t\t\t\t\t\t<details><summary>None</summary></details>\n");
1312 if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) {
1313 fprintf(out, "\t\t\t\t\t\t<details><summary><div class='type'>VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR</div></summary></details>\n");
1315 if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR) {
1316 fprintf(out, "\t\t\t\t\t\t\t<details><summary><div class='type'>VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR</div></summary></details>\n");
1318 if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR) {
1319 fprintf(out, "\t\t\t\t\t\t\t<details><summary><div class='type'>VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR</div></summary></details>\n");
1321 if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR) {
1322 fprintf(out, "\t\t\t\t\t\t\t<details><summary><div class='type'>VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR</div></summary></details>\n");
1324 if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR) {
1325 fprintf(out, "\t\t\t\t\t\t\t<details><summary><div class='type'>VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR</div></summary></details>\n");
1327 if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR) {
1328 fprintf(out, "\t\t\t\t\t\t\t<details><summary><div class='type'>VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR</div></summary></details>\n");
1330 if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR) {
1331 fprintf(out, "\t\t\t\t\t\t\t<details><summary><div class='type'>VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR</div></summary></details>\n");
1333 if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR) {
1334 fprintf(out, "\t\t\t\t\t\t\t<details><summary><div class='type'>VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR</div></summary></details>\n");
1336 if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR) {
1337 fprintf(out, "\t\t\t\t\t\t\t<details><summary><div class='type'>VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR</div></summary></details>\n");
1339 fprintf(out, "\t\t\t\t\t</details>\n");
1340 fprintf(out, "\t\t\t\t\t<details><summary>currentTransform</summary>\n");
1341 if (inst->surface_capabilities.currentTransform == 0) {
1342 fprintf(out, "\t\t\t\t\t\t<details><summary>None</summary></details>\n");
1344 if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) {
1345 fprintf(out, "\t\t\t\t\t\t<details><summary><div class='type'>VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR</div></summary></details>\n");
1346 } else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR) {
1347 fprintf(out, "\t\t\t\t\t\t<details><summary><div class='type'>VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR</div></summary></details>\n");
1348 } else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR) {
1349 fprintf(out, "\t\t\t\t\t\t<details><summary><div class='type'>VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR</div></summary></details>\n");
1350 } else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR) {
1351 fprintf(out, "\t\t\t\t\t\t<details><summary><div class='type'>VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR</div></summary></details>\n");
1352 } else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR) {
1353 fprintf(out, "\t\t\t\t\t\t<details><summary><div class='type'>VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR</div></summary></details>\n");
1354 } else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR) {
1355 fprintf(out, "\t\t\t\t\t<details><summary><div class='type'>VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR</div></summary></details>\n");
1356 } else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR) {
1357 fprintf(out, "\t\t\t\t\t\t<details><summary><div class='type'>VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR</div></summary></details>\n");
1358 } else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR) {
1359 fprintf(out, "\t\t\t\t\t\t<details><summary><div class='type'>VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR</div></summary></details>\n");
1360 } else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR) {
1361 fprintf(out, "\t\t\t\t\t\t<details><summary><div class='type'>VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR</div></summary></details>\n");
1363 fprintf(out, "\t\t\t\t\t</details>\n");
1364 fprintf(out, "\t\t\t\t\t<details><summary>supportedCompositeAlpha</summary>\n");
1365 if (inst->surface_capabilities.supportedCompositeAlpha == 0) {
1366 fprintf(out, "\t\t\t\t\t\t<details><summary>None</summary></details>\n");
1368 if (inst->surface_capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR) {
1369 fprintf(out, "\t\t\t\t\t\t<details><summary><div class='type'>VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR</div></summary></details>\n");
1371 if (inst->surface_capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR) {
1372 fprintf(out, "\t\t\t\t\t\t<details><summary><div class='type'>VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR</div></summary></details>\n");
1374 if (inst->surface_capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR) {
1375 fprintf(out, "\t\t\t\t\t\t<details><summary><div class='type'>VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR</div></summary></details>\n");
1377 if (inst->surface_capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR) {
1378 fprintf(out, "\t\t\t\t\t\t<details><summary><div class='type'>VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR</div></summary></details>\n");
1380 fprintf(out, "\t\t\t\t\t</details>\n");
1381 fprintf(out, "\t\t\t\t\t<details><summary>supportedUsageFlags</summary>\n");
1382 if (inst->surface_capabilities.supportedUsageFlags == 0) {
1383 fprintf(out, "\t\t\t\t\t\t<details><summary>None</summary></details>\n");
1385 if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) {
1386 fprintf(out, "\t\t\t\t\t\t<details><summary><div class='type'>VK_IMAGE_USAGE_TRANSFER_SRC_BIT</div></summary></details>\n");
1388 if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) {
1389 fprintf(out, "\t\t\t\t\t\t<details><summary><div class='type'>VK_IMAGE_USAGE_TRANSFER_DST_BIT</div></summary></details>\n");
1391 if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) {
1392 fprintf(out, "\t\t\t\t\t\t<details><summary><div class='type'>VK_IMAGE_USAGE_SAMPLED_BIT</div></summary></details>\n");
1394 if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_STORAGE_BIT) {
1395 fprintf(out, "\t\t\t\t\t\t<details><summary><div class='type'>VK_IMAGE_USAGE_STORAGE_BIT</div></summary></details>\n");
1397 if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
1398 fprintf(out, "\t\t\t\t\t\t<details><summary><div class='type'>VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT</div></summary></details>\n");
1400 if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
1401 fprintf(out, "\t\t\t\t\t\t<details><summary><div class='type'>VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT</div></summary></details>\n");
1403 if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) {
1404 fprintf(out, "\t\t\t\t\t\t<details><summary><div class='type'>VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT</div></summary></details>\n");
1406 if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) {
1407 fprintf(out, "\t\t\t\t\t\t<details><summary><div class='type'>VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT</div></summary></details>\n");
1409 fprintf(out, "\t\t\t\t\t</details>\n");
1410 } else if (human_readable_output) {
1411 printf("\nVkSurfaceCapabilitiesKHR:\n");
1412 printf("=========================\n");
1413 printf("\tminImageCount = %u\n", inst->surface_capabilities.minImageCount);
1414 printf("\tmaxImageCount = %u\n", inst->surface_capabilities.maxImageCount);
1415 printf("\tcurrentExtent:\n");
1416 printf("\t\twidth = %u\n", inst->surface_capabilities.currentExtent.width);
1417 printf("\t\theight = %u\n", inst->surface_capabilities.currentExtent.height);
1418 printf("\tminImageExtent:\n");
1419 printf("\t\twidth = %u\n", inst->surface_capabilities.minImageExtent.width);
1420 printf("\t\theight = %u\n", inst->surface_capabilities.minImageExtent.height);
1421 printf("\tmaxImageExtent:\n");
1422 printf("\t\twidth = %u\n", inst->surface_capabilities.maxImageExtent.width);
1423 printf("\t\theight = %u\n", inst->surface_capabilities.maxImageExtent.height);
1424 printf("\tmaxImageArrayLayers = %u\n", inst->surface_capabilities.maxImageArrayLayers);
1425 printf("\tsupportedTransform:\n");
1426 if (inst->surface_capabilities.supportedTransforms == 0) { printf("\t\tNone\n"); }
1427 if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR\n"); }
1428 if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR\n"); }
1429 if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR\n"); }
1430 if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR\n"); }
1431 if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR\n"); }
1432 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"); }
1433 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"); }
1434 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"); }
1435 if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_INHERIT_BIT_KHR\n"); }
1436 printf("\tcurrentTransform:\n");
1437 if (inst->surface_capabilities.currentTransform == 0) { printf("\t\tNone\n"); }
1438 if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR\n"); }
1439 else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR\n"); }
1440 else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR\n"); }
1441 else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR\n"); }
1442 else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR\n"); }
1443 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"); }
1444 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"); }
1445 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"); }
1446 else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_INHERIT_BIT_KHR\n"); }
1447 printf("\tsupportedCompositeAlpha:\n");
1448 if (inst->surface_capabilities.supportedCompositeAlpha == 0) { printf("\t\tNone\n"); }
1449 if (inst->surface_capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR) { printf("\t\tVK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR\n"); }
1450 if (inst->surface_capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR) { printf("\t\tVK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR\n"); }
1451 if (inst->surface_capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR) { printf("\t\tVK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR\n"); }
1452 if (inst->surface_capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR) { printf("\t\tVK_COMPOSITE_ALPHA_INHERIT_BIT_KHR\n"); }
1453 printf("\tsupportedUsageFlags:\n");
1454 if (inst->surface_capabilities.supportedUsageFlags == 0) { printf("\t\tNone\n"); }
1455 if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) { printf("\t\tVK_IMAGE_USAGE_TRANSFER_SRC_BIT\n"); }
1456 if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) { printf("\t\tVK_IMAGE_USAGE_TRANSFER_DST_BIT\n"); }
1457 if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) { printf("\t\tVK_IMAGE_USAGE_SAMPLED_BIT\n"); }
1458 if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_STORAGE_BIT) { printf("\t\tVK_IMAGE_USAGE_STORAGE_BIT\n"); }
1459 if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) { printf("\t\tVK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT\n"); }
1460 if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { printf("\t\tVK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT\n"); }
1461 if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) { printf("\t\tVK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT\n"); }
1462 if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) { printf("\t\tVK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT\n"); }
1465 // Get additional surface capability information from vkGetPhysicalDeviceSurfaceCapabilities2EXT
1466 if (CheckExtensionEnabled(VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME, gpu->inst->inst_extensions, gpu->inst->inst_extensions_count)) {
1467 memset(&inst->surface_capabilities2_ext, 0, sizeof(VkSurfaceCapabilities2EXT));
1468 inst->surface_capabilities2_ext.sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT;
1469 inst->surface_capabilities2_ext.pNext = NULL;
1471 inst->vkGetPhysicalDeviceSurfaceCapabilities2EXT(gpu->obj, inst->surface, &inst->surface_capabilities2_ext);
1474 fprintf(out, "\t\t\t\t\t<details><summary>VkSurfaceCapabilities2EXT</summary>\n");
1475 fprintf(out, "\t\t\t\t\t\t<details><summary>supportedSurfaceCounters</summary>\n");
1476 if (inst->surface_capabilities2_ext.supportedSurfaceCounters == 0) {
1477 fprintf(out, "\t\t\t\t\t\t\t<details><summary>None</summary></details>\n");
1479 if (inst->surface_capabilities2_ext.supportedSurfaceCounters & VK_SURFACE_COUNTER_VBLANK_EXT) {
1480 fprintf(out, "\t\t\t\t\t\t\t<details><summary><div class='type'>VK_SURFACE_COUNTER_VBLANK_EXT</div></summary></details>\n");
1482 fprintf(out, "\t\t\t\t\t\t</details>\n");
1483 fprintf(out, "\t\t\t\t\t</details>\n");
1484 } else if (human_readable_output) {
1485 printf("\nVkSurfaceCapabilities2EXT:\n");
1486 printf("==========================\n");
1487 printf("\tsupportedSurfaceCounters:\n");
1488 if (inst->surface_capabilities2_ext.supportedSurfaceCounters == 0) {
1489 printf("\t\tNone\n");
1491 if (inst->surface_capabilities2_ext.supportedSurfaceCounters & VK_SURFACE_COUNTER_VBLANK_EXT) {
1492 printf("\t\tVK_SURFACE_COUNTER_VBLANK_EXT\n");
1497 // Get additional surface capability information from vkGetPhysicalDeviceSurfaceCapabilities2KHR
1498 if (CheckExtensionEnabled(VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME, gpu->inst->inst_extensions, gpu->inst->inst_extensions_count)) {
1499 if (CheckExtensionEnabled(VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME, gpu->inst->inst_extensions, gpu->inst->inst_extensions_count)) {
1500 inst->shared_surface_capabilities.sType = VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR;
1501 inst->shared_surface_capabilities.pNext = NULL;
1502 inst->surface_capabilities2.pNext = &inst->shared_surface_capabilities;
1504 inst->surface_capabilities2.pNext = NULL;
1507 inst->surface_capabilities2.sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR;
1509 VkPhysicalDeviceSurfaceInfo2KHR surface_info;
1510 surface_info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR;
1511 surface_info.pNext = NULL;
1512 surface_info.surface = inst->surface;
1514 inst->vkGetPhysicalDeviceSurfaceCapabilities2KHR(gpu->obj, &surface_info, &inst->surface_capabilities2);
1516 void *place = inst->surface_capabilities2.pNext;
1518 struct VkStructureHeader* work = (struct VkStructureHeader*) place;
1519 if (work->sType == VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR) {
1520 VkSharedPresentSurfaceCapabilitiesKHR* shared_surface_capabilities = (VkSharedPresentSurfaceCapabilitiesKHR*)place;
1522 fprintf(out, "\t\t\t\t\t<details><summary>VkSharedPresentSurfaceCapabilitiesKHR</summary>\n");
1523 fprintf(out, "\t\t\t\t\t\t<details><summary>sharedPresentSupportedUsageFlags</summary>\n");
1524 if (shared_surface_capabilities->sharedPresentSupportedUsageFlags == 0) {
1525 fprintf(out, "\t\t\t\t\t\t\t<details><summary>None</summary></details>\n");
1527 if (shared_surface_capabilities->sharedPresentSupportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) {
1528 fprintf(out, "\t\t\t\t\t\t\t<details><summary><div class='type'>VK_IMAGE_USAGE_TRANSFER_SRC_BIT</div></summary></details>\n");
1530 if (shared_surface_capabilities->sharedPresentSupportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) {
1531 fprintf(out, "\t\t\t\t\t\t\t<details><summary><div class='type'>VK_IMAGE_USAGE_TRANSFER_DST_BIT</div></summary></details>\n");
1533 if (shared_surface_capabilities->sharedPresentSupportedUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) {
1534 fprintf(out, "\t\t\t\t\t\t\t<details><summary><div class='type'>VK_IMAGE_USAGE_SAMPLED_BIT</div></summary></details>\n");
1536 if (shared_surface_capabilities->sharedPresentSupportedUsageFlags & VK_IMAGE_USAGE_STORAGE_BIT) {
1537 fprintf(out, "\t\t\t\t\t\t\t<details><summary><div class='type'>VK_IMAGE_USAGE_STORAGE_BIT</div></summary></details>\n");
1539 if (shared_surface_capabilities->sharedPresentSupportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
1540 fprintf(out, "\t\t\t\t\t\t\t<details><summary><div class='type'>VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT</div></summary></details>\n");
1542 if (shared_surface_capabilities->sharedPresentSupportedUsageFlags & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
1543 fprintf(out, "\t\t\t\t\t\t\t<details><summary><div class='type'>VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT</div></summary></details>\n");
1545 if (shared_surface_capabilities->sharedPresentSupportedUsageFlags & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) {
1546 fprintf(out, "\t\t\t\t\t\t\t<details><summary><div class='type'>VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT</div></summary></details>\n");
1548 if (shared_surface_capabilities->sharedPresentSupportedUsageFlags & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) {
1549 fprintf(out, "\t\t\t\t\t\t\t<details><summary><div class='type'>VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT</div></summary></details>\n");
1551 fprintf(out, "\t\t\t\t\t\t</details>\n");
1552 fprintf(out, "\t\t\t\t\t</details>\n");
1553 } else if (human_readable_output) {
1554 printf("\nVkSharedPresentSurfaceCapabilitiesKHR:\n");
1555 printf("========================================\n");
1556 printf("\tsharedPresentSupportedUsageFlags:\n");
1557 if (shared_surface_capabilities->sharedPresentSupportedUsageFlags == 0) { printf("\t\tNone\n"); }
1558 if (shared_surface_capabilities->sharedPresentSupportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) { printf("\t\tVK_IMAGE_USAGE_TRANSFER_SRC_BIT\n"); }
1559 if (shared_surface_capabilities->sharedPresentSupportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) { printf("\t\tVK_IMAGE_USAGE_TRANSFER_DST_BIT\n"); }
1560 if (shared_surface_capabilities->sharedPresentSupportedUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) { printf("\t\tVK_IMAGE_USAGE_SAMPLED_BIT\n"); }
1561 if (shared_surface_capabilities->sharedPresentSupportedUsageFlags & VK_IMAGE_USAGE_STORAGE_BIT) { printf("\t\tVK_IMAGE_USAGE_STORAGE_BIT\n"); }
1562 if (shared_surface_capabilities->sharedPresentSupportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) { printf("\t\tVK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT\n"); }
1563 if (shared_surface_capabilities->sharedPresentSupportedUsageFlags & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { printf("\t\tVK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT\n"); }
1564 if (shared_surface_capabilities->sharedPresentSupportedUsageFlags & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) { printf("\t\tVK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT\n"); }
1565 if (shared_surface_capabilities->sharedPresentSupportedUsageFlags & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) { printf("\t\tVK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT\n"); }
1568 place = work->pNext;
1572 fprintf(out, "\t\t\t\t</details>\n");
1579 static void AppDevDumpFormatProps(const struct AppGpu *gpu, VkFormat fmt, bool *first_in_list, FILE *out) {
1580 VkFormatProperties props;
1581 vkGetPhysicalDeviceFormatProperties(gpu->obj, fmt, &props);
1587 features[0].name = "linearTiling FormatFeatureFlags";
1588 features[0].flags = props.linearTilingFeatures;
1589 features[1].name = "optimalTiling FormatFeatureFlags";
1590 features[1].flags = props.optimalTilingFeatures;
1591 features[2].name = "bufferFeatures FormatFeatureFlags";
1592 features[2].flags = props.bufferFeatures;
1595 fprintf(out, "\t\t\t\t\t\t<details><summary><div class='type'>FORMAT_%s</div></summary>\n", VkFormatString(fmt));
1596 } else if (human_readable_output) {
1597 printf("\nFORMAT_%s:", VkFormatString(fmt));
1599 for (uint32_t i = 0; i < ARRAY_SIZE(features); ++i) {
1601 fprintf(out, "\t\t\t\t\t\t\t<details open><summary>%s</summary>\n", features[i].name);
1602 if (features[i].flags == 0) {
1603 fprintf(out, "\t\t\t\t\t\t\t\t<details><summary>None</summary></details>\n");
1605 fprintf(out, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
1606 ((features[i].flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) ? "\t\t\t\t\t\t\t\t<details><summary><div class='type'>VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT</div></summary></details>\n" : ""), //0x0001
1607 ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) ? "\t\t\t\t\t\t\t\t<details><summary><div class='type'>VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT</div></summary></details>\n" : ""), //0x0002
1608 ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT) ? "\t\t\t\t\t\t\t\t<details><summary><div class='type'>VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT</div></summary></details>\n" : ""), //0x0004
1609 ((features[i].flags & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT) ? "\t\t\t\t\t\t\t\t<details><summary><div class='type'>VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT</div></summary></details>\n" : ""), //0x0008
1610 ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT) ? "\t\t\t\t\t\t\t\t<details><summary><div class='type'>VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT</div></summary></details>\n" : ""), //0x0010
1611 ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT) ? "\t\t\t\t\t\t\t\t<details><summary><div class='type'>VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT</div></summary></details>\n" : ""), //0x0020
1612 ((features[i].flags & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) ? "\t\t\t\t\t\t\t\t<details><summary><div class='type'>VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT</div></summary></details>\n" : ""), //0x0040
1613 ((features[i].flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) ? "\t\t\t\t\t\t\t\t<details><summary><div class='type'>VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT</div></summary></details>\n" : ""), //0x0080
1614 ((features[i].flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT) ? "\t\t\t\t\t\t\t\t<details><summary><div class='type'>VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT</div></summary></details>\n" : ""), //0x0100
1615 ((features[i].flags & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) ? "\t\t\t\t\t\t\t\t<details><summary><div class='type'>VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT</div></summary></details>\n" : ""), //0x0200
1616 ((features[i].flags & VK_FORMAT_FEATURE_BLIT_SRC_BIT) ? "\t\t\t\t\t\t\t\t<details><summary><div class='type'>VK_FORMAT_FEATURE_BLIT_SRC_BIT</div></summary></details>\n" : ""), //0x0400
1617 ((features[i].flags & VK_FORMAT_FEATURE_BLIT_DST_BIT) ? "\t\t\t\t\t\t\t\t<details><summary><div class='type'>VK_FORMAT_FEATURE_BLIT_DST_BIT</div></summary></details>\n" : ""), //0x0800
1618 ((features[i].flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT) ? "\t\t\t\t\t\t\t\t<details><summary><div class='type'>VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT</div></summary></details>\n" : ""), //0x1000
1619 ((features[i].flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG) ? "\t\t\t\t\t\t\t\t<details><summary><div class='type'>VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG</div></summary></details>\n" : ""), //0x2000
1620 ((features[i].flags & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR) ? "\t\t\t\t\t\t\t\t<details><summary><div class='type'>VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR</div></summary></details>\n" : ""), //0x4000
1621 ((features[i].flags & VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR) ? "\t\t\t\t\t\t\t\t<details><summary><div class='type'>VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR</div></summary></details>\n" : "")); //0x8000
1623 fprintf(out, "\t\t\t\t\t\t\t</details>\n");
1624 } else if (human_readable_output) {
1625 printf("\n\t%s:", features[i].name);
1626 if (features[i].flags == 0) {
1627 printf("\n\t\tNone");
1629 printf("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
1630 ((features[i].flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) ? "\n\t\tVK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT" : ""), //0x0001
1631 ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) ? "\n\t\tVK_FORMAT_FEATURE_STORAGE_IMAGE_BIT" : ""), //0x0002
1632 ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT) ? "\n\t\tVK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT" : ""), //0x0004
1633 ((features[i].flags & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT) ? "\n\t\tVK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT" : ""), //0x0008
1634 ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT) ? "\n\t\tVK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT" : ""), //0x0010
1635 ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT) ? "\n\t\tVK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT" : ""), //0x0020
1636 ((features[i].flags & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) ? "\n\t\tVK_FORMAT_FEATURE_VERTEX_BUFFER_BIT" : ""), //0x0040
1637 ((features[i].flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) ? "\n\t\tVK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT" : ""), //0x0080
1638 ((features[i].flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT) ? "\n\t\tVK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT" : ""), //0x0100
1639 ((features[i].flags & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) ? "\n\t\tVK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT" : ""), //0x0200
1640 ((features[i].flags & VK_FORMAT_FEATURE_BLIT_SRC_BIT) ? "\n\t\tVK_FORMAT_FEATURE_BLIT_SRC_BIT" : ""), //0x0400
1641 ((features[i].flags & VK_FORMAT_FEATURE_BLIT_DST_BIT) ? "\n\t\tVK_FORMAT_FEATURE_BLIT_DST_BIT" : ""), //0x0800
1642 ((features[i].flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT) ? "\n\t\tVK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT" : ""), //0x1000
1643 ((features[i].flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG) ? "\n\t\tVK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG" : ""), //0x2000
1644 ((features[i].flags & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR) ? "\n\t\tVK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR" : ""), //0x4000
1645 ((features[i].flags & VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR) ? "\n\t\tVK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR" : "")); //0x8000
1650 fprintf(out, "\t\t\t\t\t\t</details>\n");
1651 } else if (human_readable_output) {
1654 if (json_output && (props.linearTilingFeatures || props.optimalTilingFeatures || props.bufferFeatures)) {
1655 if (!(*first_in_list)) {
1658 *first_in_list = false;
1662 printf("\t\t\t\"formatID\": %d,\n", fmt);
1663 printf("\t\t\t\"linearTilingFeatures\": %u,\n", props.linearTilingFeatures);
1664 printf("\t\t\t\"optimalTilingFeatures\": %u,\n", props.optimalTilingFeatures);
1665 printf("\t\t\t\"bufferFeatures\": %u\n", props.bufferFeatures);
1670 static void AppDevDump(const struct AppGpu *gpu, FILE *out) {
1672 fprintf(out, "\t\t\t\t\t<details><summary>Format Properties</summary>\n");
1673 } else if (human_readable_output) {
1674 printf("Format Properties:\n");
1675 printf("==================");
1679 printf("\t\"ArrayOfVkFormatProperties\": [");
1682 bool first_in_list = true; // Used for commas in json output
1683 for (VkFormat fmt = 0; fmt < VK_FORMAT_RANGE_SIZE; ++fmt) {
1684 AppDevDumpFormatProps(gpu, fmt, &first_in_list, out);
1687 fprintf(out, "\t\t\t\t\t</details>\n");
1695 #define PRINTF_SIZE_T_SPECIFIER "%Iu"
1697 #define PRINTF_SIZE_T_SPECIFIER "%zu"
1700 static void AppGpuDumpFeatures(const struct AppGpu *gpu, FILE *out) {
1701 VkPhysicalDeviceFeatures features;
1703 if (CheckExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, gpu->inst->inst_extensions,
1704 gpu->inst->inst_extensions_count)) {
1705 const VkPhysicalDeviceFeatures *features2_const = &gpu->features2.features;
1706 features = *features2_const;
1708 const VkPhysicalDeviceFeatures *features_const = &gpu->features;
1709 features = *features_const;
1713 fprintf(out, "\t\t\t\t\t<details><summary>VkPhysicalDeviceFeatures</summary>\n");
1714 fprintf(out, "\t\t\t\t\t\t<details><summary>alphaToOne = <div class='val'>%u</div></summary></details>\n", features.alphaToOne );
1715 fprintf(out, "\t\t\t\t\t\t<details><summary>depthBiasClamp = <div class='val'>%u</div></summary></details>\n", features.depthBiasClamp );
1716 fprintf(out, "\t\t\t\t\t\t<details><summary>depthBounds = <div class='val'>%u</div></summary></details>\n", features.depthBounds );
1717 fprintf(out, "\t\t\t\t\t\t<details><summary>depthClamp = <div class='val'>%u</div></summary></details>\n", features.depthClamp );
1718 fprintf(out, "\t\t\t\t\t\t<details><summary>drawIndirectFirstInstance = <div class='val'>%u</div></summary></details>\n", features.drawIndirectFirstInstance );
1719 fprintf(out, "\t\t\t\t\t\t<details><summary>dualSrcBlend = <div class='val'>%u</div></summary></details>\n", features.dualSrcBlend );
1720 fprintf(out, "\t\t\t\t\t\t<details><summary>fillModeNonSolid = <div class='val'>%u</div></summary></details>\n", features.fillModeNonSolid );
1721 fprintf(out, "\t\t\t\t\t\t<details><summary>fragmentStoresAndAtomics = <div class='val'>%u</div></summary></details>\n", features.fragmentStoresAndAtomics );
1722 fprintf(out, "\t\t\t\t\t\t<details><summary>fullDrawIndexUint32 = <div class='val'>%u</div></summary></details>\n", features.fullDrawIndexUint32 );
1723 fprintf(out, "\t\t\t\t\t\t<details><summary>geometryShader = <div class='val'>%u</div></summary></details>\n", features.geometryShader );
1724 fprintf(out, "\t\t\t\t\t\t<details><summary>imageCubeArray = <div class='val'>%u</div></summary></details>\n", features.imageCubeArray );
1725 fprintf(out, "\t\t\t\t\t\t<details><summary>independentBlend = <div class='val'>%u</div></summary></details>\n", features.independentBlend );
1726 fprintf(out, "\t\t\t\t\t\t<details><summary>inheritedQueries = <div class='val'>%u</div></summary></details>\n", features.inheritedQueries );
1727 fprintf(out, "\t\t\t\t\t\t<details><summary>largePoints = <div class='val'>%u</div></summary></details>\n", features.largePoints );
1728 fprintf(out, "\t\t\t\t\t\t<details><summary>logicOp = <div class='val'>%u</div></summary></details>\n", features.logicOp );
1729 fprintf(out, "\t\t\t\t\t\t<details><summary>multiDrawIndirect = <div class='val'>%u</div></summary></details>\n", features.multiDrawIndirect );
1730 fprintf(out, "\t\t\t\t\t\t<details><summary>multiViewport = <div class='val'>%u</div></summary></details>\n", features.multiViewport );
1731 fprintf(out, "\t\t\t\t\t\t<details><summary>occlusionQueryPrecise = <div class='val'>%u</div></summary></details>\n", features.occlusionQueryPrecise );
1732 fprintf(out, "\t\t\t\t\t\t<details><summary>pipelineStatisticsQuery = <div class='val'>%u</div></summary></details>\n", features.pipelineStatisticsQuery );
1733 fprintf(out, "\t\t\t\t\t\t<details><summary>robustBufferAccess = <div class='val'>%u</div></summary></details>\n", features.robustBufferAccess );
1734 fprintf(out, "\t\t\t\t\t\t<details><summary>samplerAnisotropy = <div class='val'>%u</div></summary></details>\n", features.samplerAnisotropy );
1735 fprintf(out, "\t\t\t\t\t\t<details><summary>sampleRateShading = <div class='val'>%u</div></summary></details>\n", features.sampleRateShading );
1736 fprintf(out, "\t\t\t\t\t\t<details><summary>shaderClipDistance = <div class='val'>%u</div></summary></details>\n", features.shaderClipDistance );
1737 fprintf(out, "\t\t\t\t\t\t<details><summary>shaderCullDistance = <div class='val'>%u</div></summary></details>\n", features.shaderCullDistance );
1738 fprintf(out, "\t\t\t\t\t\t<details><summary>shaderFloat64 = <div class='val'>%u</div></summary></details>\n", features.shaderFloat64 );
1739 fprintf(out, "\t\t\t\t\t\t<details><summary>shaderImageGatherExtended = <div class='val'>%u</div></summary></details>\n", features.shaderImageGatherExtended );
1740 fprintf(out, "\t\t\t\t\t\t<details><summary>shaderInt16 = <div class='val'>%u</div></summary></details>\n", features.shaderInt16 );
1741 fprintf(out, "\t\t\t\t\t\t<details><summary>shaderInt64 = <div class='val'>%u</div></summary></details>\n", features.shaderInt64 );
1742 fprintf(out, "\t\t\t\t\t\t<details><summary>shaderResourceMinLod = <div class='val'>%u</div></summary></details>\n", features.shaderResourceMinLod );
1743 fprintf(out, "\t\t\t\t\t\t<details><summary>shaderResourceResidency = <div class='val'>%u</div></summary></details>\n", features.shaderResourceResidency );
1744 fprintf(out, "\t\t\t\t\t\t<details><summary>shaderSampledImageArrayDynamicIndexing = <div class='val'>%u</div></summary></details>\n", features.shaderSampledImageArrayDynamicIndexing );
1745 fprintf(out, "\t\t\t\t\t\t<details><summary>shaderStorageBufferArrayDynamicIndexing = <div class='val'>%u</div></summary></details>\n", features.shaderStorageBufferArrayDynamicIndexing);
1746 fprintf(out, "\t\t\t\t\t\t<details><summary>shaderStorageImageArrayDynamicIndexing = <div class='val'>%u</div></summary></details>\n", features.shaderStorageImageArrayDynamicIndexing );
1747 fprintf(out, "\t\t\t\t\t\t<details><summary>shaderStorageImageExtendedFormats = <div class='val'>%u</div></summary></details>\n", features.shaderStorageImageExtendedFormats );
1748 fprintf(out, "\t\t\t\t\t\t<details><summary>shaderStorageImageMultisample = <div class='val'>%u</div></summary></details>\n", features.shaderStorageImageMultisample );
1749 fprintf(out, "\t\t\t\t\t\t<details><summary>shaderStorageImageReadWithoutFormat = <div class='val'>%u</div></summary></details>\n", features.shaderStorageImageReadWithoutFormat );
1750 fprintf(out, "\t\t\t\t\t\t<details><summary>shaderStorageImageWriteWithoutFormat = <div class='val'>%u</div></summary></details>\n", features.shaderStorageImageWriteWithoutFormat );
1751 fprintf(out, "\t\t\t\t\t\t<details><summary>shaderTessellationAndGeometryPointSize = <div class='val'>%u</div></summary></details>\n", features.shaderTessellationAndGeometryPointSize );
1752 fprintf(out, "\t\t\t\t\t\t<details><summary>shaderUniformBufferArrayDynamicIndexing = <div class='val'>%u</div></summary></details>\n", features.shaderUniformBufferArrayDynamicIndexing);
1753 fprintf(out, "\t\t\t\t\t\t<details><summary>sparseBinding = <div class='val'>%u</div></summary></details>\n", features.sparseBinding );
1754 fprintf(out, "\t\t\t\t\t\t<details><summary>sparseResidency2Samples = <div class='val'>%u</div></summary></details>\n", features.sparseResidency2Samples );
1755 fprintf(out, "\t\t\t\t\t\t<details><summary>sparseResidency4Samples = <div class='val'>%u</div></summary></details>\n", features.sparseResidency4Samples );
1756 fprintf(out, "\t\t\t\t\t\t<details><summary>sparseResidency8Samples = <div class='val'>%u</div></summary></details>\n", features.sparseResidency8Samples );
1757 fprintf(out, "\t\t\t\t\t\t<details><summary>sparseResidency16Samples = <div class='val'>%u</div></summary></details>\n", features.sparseResidency16Samples );
1758 fprintf(out, "\t\t\t\t\t\t<details><summary>sparseResidencyAliased = <div class='val'>%u</div></summary></details>\n", features.sparseResidencyAliased );
1759 fprintf(out, "\t\t\t\t\t\t<details><summary>sparseResidencyBuffer = <div class='val'>%u</div></summary></details>\n", features.sparseResidencyBuffer );
1760 fprintf(out, "\t\t\t\t\t\t<details><summary>sparseResidencyImage2D = <div class='val'>%u</div></summary></details>\n", features.sparseResidencyImage2D );
1761 fprintf(out, "\t\t\t\t\t\t<details><summary>sparseResidencyImage3D = <div class='val'>%u</div></summary></details>\n", features.sparseResidencyImage3D );
1762 fprintf(out, "\t\t\t\t\t\t<details><summary>tessellationShader = <div class='val'>%u</div></summary></details>\n", features.tessellationShader );
1763 fprintf(out, "\t\t\t\t\t\t<details><summary>textureCompressionASTC_LDR = <div class='val'>%u</div></summary></details>\n", features.textureCompressionASTC_LDR );
1764 fprintf(out, "\t\t\t\t\t\t<details><summary>textureCompressionBC = <div class='val'>%u</div></summary></details>\n", features.textureCompressionBC );
1765 fprintf(out, "\t\t\t\t\t\t<details><summary>textureCompressionETC2 = <div class='val'>%u</div></summary></details>\n", features.textureCompressionETC2 );
1766 fprintf(out, "\t\t\t\t\t\t<details><summary>variableMultisampleRate = <div class='val'>%u</div></summary></details>\n", features.variableMultisampleRate );
1767 fprintf(out, "\t\t\t\t\t\t<details><summary>vertexPipelineStoresAndAtomics = <div class='val'>%u</div></summary></details>\n", features.vertexPipelineStoresAndAtomics );
1768 fprintf(out, "\t\t\t\t\t\t<details><summary>wideLines = <div class='val'>%u</div></summary></details>\n", features.wideLines );
1769 fprintf(out, "\t\t\t\t\t</details>\n");
1770 } else if (human_readable_output) {
1771 printf("VkPhysicalDeviceFeatures:\n");
1772 printf("=========================\n");
1773 printf("\talphaToOne = %u\n", features.alphaToOne );
1774 printf("\tdepthBiasClamp = %u\n", features.depthBiasClamp );
1775 printf("\tdepthBounds = %u\n", features.depthBounds );
1776 printf("\tdepthClamp = %u\n", features.depthClamp );
1777 printf("\tdrawIndirectFirstInstance = %u\n", features.drawIndirectFirstInstance );
1778 printf("\tdualSrcBlend = %u\n", features.dualSrcBlend );
1779 printf("\tfillModeNonSolid = %u\n", features.fillModeNonSolid );
1780 printf("\tfragmentStoresAndAtomics = %u\n", features.fragmentStoresAndAtomics );
1781 printf("\tfullDrawIndexUint32 = %u\n", features.fullDrawIndexUint32 );
1782 printf("\tgeometryShader = %u\n", features.geometryShader );
1783 printf("\timageCubeArray = %u\n", features.imageCubeArray );
1784 printf("\tindependentBlend = %u\n", features.independentBlend );
1785 printf("\tinheritedQueries = %u\n", features.inheritedQueries );
1786 printf("\tlargePoints = %u\n", features.largePoints );
1787 printf("\tlogicOp = %u\n", features.logicOp );
1788 printf("\tmultiDrawIndirect = %u\n", features.multiDrawIndirect );
1789 printf("\tmultiViewport = %u\n", features.multiViewport );
1790 printf("\tocclusionQueryPrecise = %u\n", features.occlusionQueryPrecise );
1791 printf("\tpipelineStatisticsQuery = %u\n", features.pipelineStatisticsQuery );
1792 printf("\trobustBufferAccess = %u\n", features.robustBufferAccess );
1793 printf("\tsamplerAnisotropy = %u\n", features.samplerAnisotropy );
1794 printf("\tsampleRateShading = %u\n", features.sampleRateShading );
1795 printf("\tshaderClipDistance = %u\n", features.shaderClipDistance );
1796 printf("\tshaderCullDistance = %u\n", features.shaderCullDistance );
1797 printf("\tshaderFloat64 = %u\n", features.shaderFloat64 );
1798 printf("\tshaderImageGatherExtended = %u\n", features.shaderImageGatherExtended );
1799 printf("\tshaderInt16 = %u\n", features.shaderInt16 );
1800 printf("\tshaderInt64 = %u\n", features.shaderInt64 );
1801 printf("\tshaderSampledImageArrayDynamicIndexing = %u\n", features.shaderSampledImageArrayDynamicIndexing );
1802 printf("\tshaderStorageBufferArrayDynamicIndexing = %u\n", features.shaderStorageBufferArrayDynamicIndexing);
1803 printf("\tshaderStorageImageArrayDynamicIndexing = %u\n", features.shaderStorageImageArrayDynamicIndexing );
1804 printf("\tshaderStorageImageExtendedFormats = %u\n", features.shaderStorageImageExtendedFormats );
1805 printf("\tshaderStorageImageMultisample = %u\n", features.shaderStorageImageMultisample );
1806 printf("\tshaderStorageImageReadWithoutFormat = %u\n", features.shaderStorageImageReadWithoutFormat );
1807 printf("\tshaderStorageImageWriteWithoutFormat = %u\n", features.shaderStorageImageWriteWithoutFormat );
1808 printf("\tshaderTessellationAndGeometryPointSize = %u\n", features.shaderTessellationAndGeometryPointSize );
1809 printf("\tshaderUniformBufferArrayDynamicIndexing = %u\n", features.shaderUniformBufferArrayDynamicIndexing);
1810 printf("\tsparseBinding = %u\n", features.sparseBinding );
1811 printf("\tsparseResidency2Samples = %u\n", features.sparseResidency2Samples );
1812 printf("\tsparseResidency4Samples = %u\n", features.sparseResidency4Samples );
1813 printf("\tsparseResidency8Samples = %u\n", features.sparseResidency8Samples );
1814 printf("\tsparseResidency16Samples = %u\n", features.sparseResidency16Samples );
1815 printf("\tsparseResidencyAliased = %u\n", features.sparseResidencyAliased );
1816 printf("\tsparseResidencyBuffer = %u\n", features.sparseResidencyBuffer );
1817 printf("\tsparseResidencyImage2D = %u\n", features.sparseResidencyImage2D );
1818 printf("\tsparseResidencyImage3D = %u\n", features.sparseResidencyImage3D );
1819 printf("\tshaderResourceMinLod = %u\n", features.shaderResourceMinLod );
1820 printf("\tshaderResourceResidency = %u\n", features.shaderResourceResidency );
1821 printf("\ttessellationShader = %u\n", features.tessellationShader );
1822 printf("\ttextureCompressionASTC_LDR = %u\n", features.textureCompressionASTC_LDR );
1823 printf("\ttextureCompressionBC = %u\n", features.textureCompressionBC );
1824 printf("\ttextureCompressionETC2 = %u\n", features.textureCompressionETC2 );
1825 printf("\tvariableMultisampleRate = %u\n", features.variableMultisampleRate );
1826 printf("\tvertexPipelineStoresAndAtomics = %u\n", features.vertexPipelineStoresAndAtomics );
1827 printf("\twideLines = %u\n", features.wideLines );
1831 printf("\t\"VkPhysicalDeviceFeatures\": {\n");
1832 printf("\t\t\"alphaToOne\": %u,\n", features.alphaToOne);
1833 printf("\t\t\"depthBiasClamp\": %u,\n", features.depthBiasClamp);
1834 printf("\t\t\"depthBounds\": %u,\n", features.depthBounds);
1835 printf("\t\t\"depthClamp\": %u,\n", features.depthClamp);
1836 printf("\t\t\"drawIndirectFirstInstance\": %u,\n", features.drawIndirectFirstInstance);
1837 printf("\t\t\"dualSrcBlend\": %u,\n", features.dualSrcBlend);
1838 printf("\t\t\"fillModeNonSolid\": %u,\n", features.fillModeNonSolid);
1839 printf("\t\t\"fragmentStoresAndAtomics\": %u,\n", features.fragmentStoresAndAtomics);
1840 printf("\t\t\"fullDrawIndexUint32\": %u,\n", features.fullDrawIndexUint32);
1841 printf("\t\t\"geometryShader\": %u,\n", features.geometryShader);
1842 printf("\t\t\"imageCubeArray\": %u,\n", features.imageCubeArray);
1843 printf("\t\t\"independentBlend\": %u,\n", features.independentBlend);
1844 printf("\t\t\"inheritedQueries\": %u,\n", features.inheritedQueries);
1845 printf("\t\t\"largePoints\": %u,\n", features.largePoints);
1846 printf("\t\t\"logicOp\": %u,\n", features.logicOp);
1847 printf("\t\t\"multiDrawIndirect\": %u,\n", features.multiDrawIndirect);
1848 printf("\t\t\"multiViewport\": %u,\n", features.multiViewport);
1849 printf("\t\t\"occlusionQueryPrecise\": %u,\n", features.occlusionQueryPrecise);
1850 printf("\t\t\"pipelineStatisticsQuery\": %u,\n", features.pipelineStatisticsQuery);
1851 printf("\t\t\"robustBufferAccess\": %u,\n", features.robustBufferAccess);
1852 printf("\t\t\"samplerAnisotropy\": %u,\n", features.samplerAnisotropy);
1853 printf("\t\t\"sampleRateShading\": %u,\n", features.sampleRateShading);
1854 printf("\t\t\"shaderClipDistance\": %u,\n", features.shaderClipDistance);
1855 printf("\t\t\"shaderCullDistance\": %u,\n", features.shaderCullDistance);
1856 printf("\t\t\"shaderFloat64\": %u,\n", features.shaderFloat64);
1857 printf("\t\t\"shaderImageGatherExtended\": %u,\n", features.shaderImageGatherExtended);
1858 printf("\t\t\"shaderInt16\": %u,\n", features.shaderInt16);
1859 printf("\t\t\"shaderInt64\": %u,\n", features.shaderInt64);
1860 printf("\t\t\"shaderResourceMinLod\": %u,\n", features.shaderResourceMinLod);
1861 printf("\t\t\"shaderResourceResidency\": %u,\n", features.shaderResourceResidency);
1862 printf("\t\t\"shaderSampledImageArrayDynamicIndexing\": %u,\n", features.shaderSampledImageArrayDynamicIndexing);
1863 printf("\t\t\"shaderStorageBufferArrayDynamicIndexing\": %u,\n", features.shaderStorageBufferArrayDynamicIndexing);
1864 printf("\t\t\"shaderStorageImageArrayDynamicIndexing\": %u,\n", features.shaderStorageImageArrayDynamicIndexing);
1865 printf("\t\t\"shaderStorageImageExtendedFormats\": %u,\n", features.shaderStorageImageExtendedFormats);
1866 printf("\t\t\"shaderStorageImageMultisample\": %u,\n", features.shaderStorageImageMultisample);
1867 printf("\t\t\"shaderStorageImageReadWithoutFormat\": %u,\n", features.shaderStorageImageReadWithoutFormat);
1868 printf("\t\t\"shaderStorageImageWriteWithoutFormat\": %u,\n", features.shaderStorageImageWriteWithoutFormat);
1869 printf("\t\t\"shaderTessellationAndGeometryPointSize\": %u,\n", features.shaderTessellationAndGeometryPointSize);
1870 printf("\t\t\"shaderUniformBufferArrayDynamicIndexing\": %u,\n", features.shaderUniformBufferArrayDynamicIndexing);
1871 printf("\t\t\"sparseBinding\": %u,\n", features.sparseBinding);
1872 printf("\t\t\"sparseResidency2Samples\": %u,\n", features.sparseResidency2Samples);
1873 printf("\t\t\"sparseResidency4Samples\": %u,\n", features.sparseResidency4Samples);
1874 printf("\t\t\"sparseResidency8Samples\": %u,\n", features.sparseResidency8Samples);
1875 printf("\t\t\"sparseResidency16Samples\": %u,\n", features.sparseResidency16Samples);
1876 printf("\t\t\"sparseResidencyAliased\": %u,\n", features.sparseResidencyAliased);
1877 printf("\t\t\"sparseResidencyBuffer\": %u,\n", features.sparseResidencyBuffer);
1878 printf("\t\t\"sparseResidencyImage2D\": %u,\n", features.sparseResidencyImage2D);
1879 printf("\t\t\"sparseResidencyImage3D\": %u,\n", features.sparseResidencyImage3D);
1880 printf("\t\t\"tessellationShader\": %u,\n", features.tessellationShader);
1881 printf("\t\t\"textureCompressionASTC_LDR\": %u,\n", features.textureCompressionASTC_LDR);
1882 printf("\t\t\"textureCompressionBC\": %u,\n", features.textureCompressionBC);
1883 printf("\t\t\"textureCompressionETC2\": %u,\n", features.textureCompressionETC2);
1884 printf("\t\t\"variableMultisampleRate\": %u,\n", features.variableMultisampleRate);
1885 printf("\t\t\"vertexPipelineStoresAndAtomics\": %u,\n", features.vertexPipelineStoresAndAtomics);
1886 printf("\t\t\"wideLines\": %u\n", features.wideLines);
1890 if (CheckExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, gpu->inst->inst_extensions,
1891 gpu->inst->inst_extensions_count)) {
1892 void *place = gpu->features2.pNext;
1894 struct VkStructureHeader *structure = (struct VkStructureHeader*) place;
1895 if (structure->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR && CheckPhysicalDeviceExtensionIncluded(VK_KHR_16BIT_STORAGE_EXTENSION_NAME, gpu->device_extensions, gpu->device_extension_count)) {
1896 VkPhysicalDevice16BitStorageFeaturesKHR *b16_store_features = (VkPhysicalDevice16BitStorageFeaturesKHR*)structure;
1898 fprintf(out, "\n\t\t\t\t\t<details><summary>VkPhysicalDevice16BitStorageFeatures</summary>\n");
1899 fprintf(out, "\t\t\t\t\t\t<details><summary>storageBuffer16BitAccess = <div class='val'>%u</div></summary></details>\n", b16_store_features->storageBuffer16BitAccess );
1900 fprintf(out, "\t\t\t\t\t\t<details><summary>uniformAndStorageBuffer16BitAccess = <div class='val'>%u</div></summary></details>\n", b16_store_features->uniformAndStorageBuffer16BitAccess);
1901 fprintf(out, "\t\t\t\t\t\t<details><summary>storagePushConstant16 = <div class='val'>%u</div></summary></details>\n", b16_store_features->storagePushConstant16 );
1902 fprintf(out, "\t\t\t\t\t\t<details><summary>storageInputOutput16 = <div class='val'>%u</div></summary></details>\n", b16_store_features->storageInputOutput16 );
1903 fprintf(out, "\t\t\t\t\t</details>\n");
1904 } else if (human_readable_output) {
1905 printf("\nVkPhysicalDevice16BitStorageFeatures:\n");
1906 printf("=====================================\n");
1907 printf("\tstorageBuffer16BitAccess = %u\n", b16_store_features->storageBuffer16BitAccess );
1908 printf("\tuniformAndStorageBuffer16BitAccess = %u\n", b16_store_features->uniformAndStorageBuffer16BitAccess);
1909 printf("\tstoragePushConstant16 = %u\n", b16_store_features->storagePushConstant16 );
1910 printf("\tstorageInputOutput16 = %u\n", b16_store_features->storageInputOutput16 );
1912 } else if (structure->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES_KHR && CheckPhysicalDeviceExtensionIncluded(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME, gpu->device_extensions, gpu->device_extension_count)) {
1913 VkPhysicalDeviceSamplerYcbcrConversionFeaturesKHR *sampler_ycbcr_features = (VkPhysicalDeviceSamplerYcbcrConversionFeaturesKHR*)structure;
1915 fprintf(out, "\n\t\t\t\t\t<details><summary>VkPhysicalDeviceSamplerYcbcrConversionFeatures</summary>\n");
1916 fprintf(out, "\t\t\t\t\t\t<details><summary>samplerYcbcrConversion = <div class='val'>%u</div></summary></details>\n", sampler_ycbcr_features->samplerYcbcrConversion);
1917 fprintf(out, "\t\t\t\t\t</details>\n");
1918 } else if (human_readable_output) {
1919 printf("\nVkPhysicalDeviceSamplerYcbcrConversionFeatures:\n");
1920 printf("===============================================\n");
1921 printf("\tsamplerYcbcrConversion = %u\n", sampler_ycbcr_features->samplerYcbcrConversion);
1923 } else if (structure->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR && CheckPhysicalDeviceExtensionIncluded(VK_KHR_VARIABLE_POINTERS_EXTENSION_NAME, gpu->device_extensions, gpu->device_extension_count)) {
1924 VkPhysicalDeviceVariablePointerFeaturesKHR *var_pointer_features = (VkPhysicalDeviceVariablePointerFeaturesKHR*)structure;
1926 fprintf(out, "\n\t\t\t\t\t<details><summary>VkPhysicalDeviceVariablePointerFeatures</summary>\n");
1927 fprintf(out, "\t\t\t\t\t\t<details><summary>variablePointersStorageBuffer = <div class='val'>%u</div></summary></details>\n", var_pointer_features->variablePointersStorageBuffer);
1928 fprintf(out, "\t\t\t\t\t\t<details><summary>variablePointers = <div class='val'>%u</div></summary></details>\n", var_pointer_features->variablePointers );
1929 fprintf(out, "\t\t\t\t\t</details>\n");
1930 } else if (human_readable_output) {
1931 printf("\nVkPhysicalDeviceVariablePointerFeatures:\n");
1932 printf("========================================\n");
1933 printf("\tvariablePointersStorageBuffer = %u\n", var_pointer_features->variablePointersStorageBuffer);
1934 printf("\tvariablePointers = %u\n", var_pointer_features->variablePointers );
1936 } else if (structure->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_FEATURES_EXT && CheckPhysicalDeviceExtensionIncluded(VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME, gpu->device_extensions, gpu->device_extension_count)) {
1937 VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT *blend_op_adv_features = (VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT*)structure;
1939 fprintf(out, "\n\t\t\t\t\t<details><summary>VkPhysicalDeviceBlendOperationAdvancedFeatures</summary>\n");
1940 fprintf(out, "\t\t\t\t\t\t<details><summary>advancedBlendCoherentOperations = <div class='val'>%u</div></summary></details>\n", blend_op_adv_features->advancedBlendCoherentOperations);
1941 fprintf(out, "\t\t\t\t\t</details>\n");
1942 } else if (human_readable_output) {
1943 printf("\nVkPhysicalDeviceBlendOperationAdvancedFeatures:\n");
1944 printf("===============================================\n");
1945 printf("\tadvancedBlendCoherentOperations = %u\n", blend_op_adv_features->advancedBlendCoherentOperations);
1947 } else if (structure->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR && CheckPhysicalDeviceExtensionIncluded(VK_KHR_MULTIVIEW_EXTENSION_NAME, gpu->device_extensions, gpu->device_extension_count)) {
1948 VkPhysicalDeviceMultiviewFeaturesKHR *multiview_features = (VkPhysicalDeviceMultiviewFeaturesKHR*)structure;
1950 fprintf(out, "\n\t\t\t\t\t<details><summary>VkPhysicalDeviceMultiviewFeatures</summary>\n");
1951 fprintf(out, "\t\t\t\t\t\t<details><summary>multiview = <div class='val'>%u</div></summary></details>\n", multiview_features->multiview );
1952 fprintf(out, "\t\t\t\t\t\t<details><summary>multiviewGeometryShader = <div class='val'>%u</div></summary></details>\n", multiview_features->multiviewGeometryShader );
1953 fprintf(out, "\t\t\t\t\t\t<details><summary>multiviewTessellationShader = <div class='val'>%u</div></summary></details>\n", multiview_features->multiviewTessellationShader);
1954 fprintf(out, "\t\t\t\t\t</details>\n");
1956 else if (human_readable_output) {
1957 printf("\nVkPhysicalDeviceMultiviewFeatures:\n");
1958 printf("==================================\n");
1959 printf("\tmultiview = %u\n", multiview_features->multiview );
1960 printf("\tmultiviewGeometryShader = %u\n", multiview_features->multiviewGeometryShader );
1961 printf("\tmultiviewTessellationShader = %u\n", multiview_features->multiviewTessellationShader);
1964 place = structure->pNext;
1969 static void AppDumpSparseProps(const VkPhysicalDeviceSparseProperties *sparse_props, FILE *out) {
1971 fprintf(out, "\t\t\t\t\t<details><summary>VkPhysicalDeviceSparseProperties</summary>\n");
1972 fprintf(out, "\t\t\t\t\t\t<details><summary>residencyStandard2DBlockShape = <div class='val'>%u</div></summary></details>\n", sparse_props->residencyStandard2DBlockShape );
1973 fprintf(out, "\t\t\t\t\t\t<details><summary>residencyStandard2DMultisampleBlockShape = <div class='val'>%u</div></summary></details>\n", sparse_props->residencyStandard2DMultisampleBlockShape);
1974 fprintf(out, "\t\t\t\t\t\t<details><summary>residencyStandard3DBlockShape = <div class='val'>%u</div></summary></details>\n", sparse_props->residencyStandard3DBlockShape );
1975 fprintf(out, "\t\t\t\t\t\t<details><summary>residencyAlignedMipSize = <div class='val'>%u</div></summary></details>\n", sparse_props->residencyAlignedMipSize );
1976 fprintf(out, "\t\t\t\t\t\t<details><summary>residencyNonResidentStrict = <div class='val'>%u</div></summary></details>\n", sparse_props->residencyNonResidentStrict );
1977 fprintf(out, "\t\t\t\t\t</details>\n");
1978 } else if (human_readable_output) {
1979 printf("\tVkPhysicalDeviceSparseProperties:\n");
1980 printf("\t---------------------------------\n");
1981 printf("\t\tresidencyStandard2DBlockShape = %u\n", sparse_props->residencyStandard2DBlockShape );
1982 printf("\t\tresidencyStandard2DMultisampleBlockShape = %u\n", sparse_props->residencyStandard2DMultisampleBlockShape);
1983 printf("\t\tresidencyStandard3DBlockShape = %u\n", sparse_props->residencyStandard3DBlockShape );
1984 printf("\t\tresidencyAlignedMipSize = %u\n", sparse_props->residencyAlignedMipSize );
1985 printf("\t\tresidencyNonResidentStrict = %u\n", sparse_props->residencyNonResidentStrict );
1989 printf("\t\t\"sparseProperties\": {\n");
1990 printf("\t\t\t\"residencyAlignedMipSize\": %u,\n", sparse_props->residencyAlignedMipSize);
1991 printf("\t\t\t\"residencyNonResidentStrict\": %u,\n", sparse_props->residencyNonResidentStrict);
1992 printf("\t\t\t\"residencyStandard2DBlockShape\": %u,\n", sparse_props->residencyStandard2DBlockShape);
1993 printf("\t\t\t\"residencyStandard2DMultisampleBlockShape\": %u,\n", sparse_props->residencyStandard2DMultisampleBlockShape);
1994 printf("\t\t\t\"residencyStandard3DBlockShape\": %u\n", sparse_props->residencyStandard3DBlockShape);
1999 static void AppDumpLimits(const VkPhysicalDeviceLimits *limits, FILE *out) {
2001 fprintf(out, "\t\t\t\t\t<details><summary>VkPhysicalDeviceLimits</summary>\n");
2002 fprintf(out, "\t\t\t\t\t\t<details><summary>maxImageDimension1D = <div class='val'>%u</div></summary></details>\n", limits->maxImageDimension1D );
2003 fprintf(out, "\t\t\t\t\t\t<details><summary>maxImageDimension2D = <div class='val'>%u</div></summary></details>\n", limits->maxImageDimension2D );
2004 fprintf(out, "\t\t\t\t\t\t<details><summary>maxImageDimension3D = <div class='val'>%u</div></summary></details>\n", limits->maxImageDimension3D );
2005 fprintf(out, "\t\t\t\t\t\t<details><summary>maxImageDimensionCube = <div class='val'>%u</div></summary></details>\n", limits->maxImageDimensionCube );
2006 fprintf(out, "\t\t\t\t\t\t<details><summary>maxImageArrayLayers = <div class='val'>%u</div></summary></details>\n", limits->maxImageArrayLayers );
2007 fprintf(out, "\t\t\t\t\t\t<details><summary>maxTexelBufferElements = <div class='val'>0x%" PRIxLEAST32 "</div></summary></details>\n", limits->maxTexelBufferElements );
2008 fprintf(out, "\t\t\t\t\t\t<details><summary>maxUniformBufferRange = <div class='val'>0x%" PRIxLEAST32 "</div></summary></details>\n", limits->maxUniformBufferRange );
2009 fprintf(out, "\t\t\t\t\t\t<details><summary>maxStorageBufferRange = <div class='val'>0x%" PRIxLEAST32 "</div></summary></details>\n", limits->maxStorageBufferRange );
2010 fprintf(out, "\t\t\t\t\t\t<details><summary>maxPushConstantsSize = <div class='val'>%u</div></summary></details>\n", limits->maxPushConstantsSize );
2011 fprintf(out, "\t\t\t\t\t\t<details><summary>maxMemoryAllocationCount = <div class='val'>%u</div></summary></details>\n", limits->maxMemoryAllocationCount );
2012 fprintf(out, "\t\t\t\t\t\t<details><summary>maxSamplerAllocationCount = <div class='val'>%u</div></summary></details>\n", limits->maxSamplerAllocationCount );
2013 fprintf(out, "\t\t\t\t\t\t<details><summary>bufferImageGranularity = <div class='val'>0x%" PRIxLEAST64 "</div></summary></details>\n", limits->bufferImageGranularity );
2014 fprintf(out, "\t\t\t\t\t\t<details><summary>sparseAddressSpaceSize = <div class='val'>0x%" PRIxLEAST64 "</div></summary></details>\n", limits->sparseAddressSpaceSize );
2015 fprintf(out, "\t\t\t\t\t\t<details><summary>maxBoundDescriptorSets = <div class='val'>%u</div></summary></details>\n", limits->maxBoundDescriptorSets );
2016 fprintf(out, "\t\t\t\t\t\t<details><summary>maxPerStageDescriptorSamplers = <div class='val'>%u</div></summary></details>\n", limits->maxPerStageDescriptorSamplers );
2017 fprintf(out, "\t\t\t\t\t\t<details><summary>maxPerStageDescriptorUniformBuffers = <div class='val'>%u</div></summary></details>\n", limits->maxPerStageDescriptorUniformBuffers );
2018 fprintf(out, "\t\t\t\t\t\t<details><summary>maxPerStageDescriptorStorageBuffers = <div class='val'>%u</div></summary></details>\n", limits->maxPerStageDescriptorStorageBuffers );
2019 fprintf(out, "\t\t\t\t\t\t<details><summary>maxPerStageDescriptorSampledImages = <div class='val'>%u</div></summary></details>\n", limits->maxPerStageDescriptorSampledImages );
2020 fprintf(out, "\t\t\t\t\t\t<details><summary>maxPerStageDescriptorStorageImages = <div class='val'>%u</div></summary></details>\n", limits->maxPerStageDescriptorStorageImages );
2021 fprintf(out, "\t\t\t\t\t\t<details><summary>maxPerStageDescriptorInputAttachments = <div class='val'>%u</div></summary></details>\n", limits->maxPerStageDescriptorInputAttachments );
2022 fprintf(out, "\t\t\t\t\t\t<details><summary>maxPerStageResources = <div class='val'>%u</div></summary></details>\n", limits->maxPerStageResources );
2023 fprintf(out, "\t\t\t\t\t\t<details><summary>maxDescriptorSetSamplers = <div class='val'>%u</div></summary></details>\n", limits->maxDescriptorSetSamplers );
2024 fprintf(out, "\t\t\t\t\t\t<details><summary>maxDescriptorSetUniformBuffers = <div class='val'>%u</div></summary></details>\n", limits->maxDescriptorSetUniformBuffers );
2025 fprintf(out, "\t\t\t\t\t\t<details><summary>maxDescriptorSetUniformBuffersDynamic = <div class='val'>%u</div></summary></details>\n", limits->maxDescriptorSetUniformBuffersDynamic );
2026 fprintf(out, "\t\t\t\t\t\t<details><summary>maxDescriptorSetStorageBuffers = <div class='val'>%u</div></summary></details>\n", limits->maxDescriptorSetStorageBuffers );
2027 fprintf(out, "\t\t\t\t\t\t<details><summary>maxDescriptorSetStorageBuffersDynamic = <div class='val'>%u</div></summary></details>\n", limits->maxDescriptorSetStorageBuffersDynamic );
2028 fprintf(out, "\t\t\t\t\t\t<details><summary>maxDescriptorSetSampledImages = <div class='val'>%u</div></summary></details>\n", limits->maxDescriptorSetSampledImages );
2029 fprintf(out, "\t\t\t\t\t\t<details><summary>maxDescriptorSetStorageImages = <div class='val'>%u</div></summary></details>\n", limits->maxDescriptorSetStorageImages );
2030 fprintf(out, "\t\t\t\t\t\t<details><summary>maxDescriptorSetInputAttachments = <div class='val'>%u</div></summary></details>\n", limits->maxDescriptorSetInputAttachments );
2031 fprintf(out, "\t\t\t\t\t\t<details><summary>maxVertexInputAttributes = <div class='val'>%u</div></summary></details>\n", limits->maxVertexInputAttributes );
2032 fprintf(out, "\t\t\t\t\t\t<details><summary>maxVertexInputBindings = <div class='val'>%u</div></summary></details>\n", limits->maxVertexInputBindings );
2033 fprintf(out, "\t\t\t\t\t\t<details><summary>maxVertexInputAttributeOffset = <div class='val'>0x%" PRIxLEAST32 "</div></summary></details>\n", limits->maxVertexInputAttributeOffset );
2034 fprintf(out, "\t\t\t\t\t\t<details><summary>maxVertexInputBindingStride = <div class='val'>0x%" PRIxLEAST32 "</div></summary></details>\n", limits->maxVertexInputBindingStride );
2035 fprintf(out, "\t\t\t\t\t\t<details><summary>maxVertexOutputComponents = <div class='val'>%u</div></summary></details>\n", limits->maxVertexOutputComponents );
2036 fprintf(out, "\t\t\t\t\t\t<details><summary>maxTessellationGenerationLevel = <div class='val'>%u</div></summary></details>\n", limits->maxTessellationGenerationLevel );
2037 fprintf(out, "\t\t\t\t\t\t<details><summary>maxTessellationPatchSize = <div class='val'>%u</div></summary></details>\n", limits->maxTessellationPatchSize );
2038 fprintf(out, "\t\t\t\t\t\t<details><summary>maxTessellationControlPerVertexInputComponents = <div class='val'>%u</div></summary></details>\n", limits->maxTessellationControlPerVertexInputComponents );
2039 fprintf(out, "\t\t\t\t\t\t<details><summary>maxTessellationControlPerVertexOutputComponents = <div class='val'>%u</div></summary></details>\n", limits->maxTessellationControlPerVertexOutputComponents);
2040 fprintf(out, "\t\t\t\t\t\t<details><summary>maxTessellationControlPerPatchOutputComponents = <div class='val'>%u</div></summary></details>\n", limits->maxTessellationControlPerPatchOutputComponents );
2041 fprintf(out, "\t\t\t\t\t\t<details><summary>maxTessellationControlTotalOutputComponents = <div class='val'>%u</div></summary></details>\n", limits->maxTessellationControlTotalOutputComponents );
2042 fprintf(out, "\t\t\t\t\t\t<details><summary>maxTessellationEvaluationInputComponents = <div class='val'>%u</div></summary></details>\n", limits->maxTessellationEvaluationInputComponents );
2043 fprintf(out, "\t\t\t\t\t\t<details><summary>maxTessellationEvaluationOutputComponents = <div class='val'>%u</div></summary></details>\n", limits->maxTessellationEvaluationOutputComponents );
2044 fprintf(out, "\t\t\t\t\t\t<details><summary>maxGeometryShaderInvocations = <div class='val'>%u</div></summary></details>\n", limits->maxGeometryShaderInvocations );
2045 fprintf(out, "\t\t\t\t\t\t<details><summary>maxGeometryInputComponents = <div class='val'>%u</div></summary></details>\n", limits->maxGeometryInputComponents );
2046 fprintf(out, "\t\t\t\t\t\t<details><summary>maxGeometryOutputComponents = <div class='val'>%u</div></summary></details>\n", limits->maxGeometryOutputComponents );
2047 fprintf(out, "\t\t\t\t\t\t<details><summary>maxGeometryOutputVertices = <div class='val'>%u</div></summary></details>\n", limits->maxGeometryOutputVertices );
2048 fprintf(out, "\t\t\t\t\t\t<details><summary>maxGeometryTotalOutputComponents = <div class='val'>%u</div></summary></details>\n", limits->maxGeometryTotalOutputComponents );
2049 fprintf(out, "\t\t\t\t\t\t<details><summary>maxFragmentInputComponents = <div class='val'>%u</div></summary></details>\n", limits->maxFragmentInputComponents );
2050 fprintf(out, "\t\t\t\t\t\t<details><summary>maxFragmentOutputAttachments = <div class='val'>%u</div></summary></details>\n", limits->maxFragmentOutputAttachments );
2051 fprintf(out, "\t\t\t\t\t\t<details><summary>maxFragmentDualSrcAttachments = <div class='val'>%u</div></summary></details>\n", limits->maxFragmentDualSrcAttachments );
2052 fprintf(out, "\t\t\t\t\t\t<details><summary>maxFragmentCombinedOutputResources = <div class='val'>%u</div></summary></details>\n", limits->maxFragmentCombinedOutputResources );
2053 fprintf(out, "\t\t\t\t\t\t<details><summary>maxComputeSharedMemorySize = <div class='val'>0x%" PRIxLEAST32 "</div></summary></details>\n", limits->maxComputeSharedMemorySize );
2054 fprintf(out, "\t\t\t\t\t\t<details><summary>maxComputeWorkGroupCount[0] = <div class='val'>%u</div></summary></details>\n", limits->maxComputeWorkGroupCount[0] );
2055 fprintf(out, "\t\t\t\t\t\t<details><summary>maxComputeWorkGroupCount[1] = <div class='val'>%u</div></summary></details>\n", limits->maxComputeWorkGroupCount[1] );
2056 fprintf(out, "\t\t\t\t\t\t<details><summary>maxComputeWorkGroupCount[2] = <div class='val'>%u</div></summary></details>\n", limits->maxComputeWorkGroupCount[2] );
2057 fprintf(out, "\t\t\t\t\t\t<details><summary>maxComputeWorkGroupInvocations = <div class='val'>%u</div></summary></details>\n", limits->maxComputeWorkGroupInvocations );
2058 fprintf(out, "\t\t\t\t\t\t<details><summary>maxComputeWorkGroupSize[0] = <div class='val'>%u</div></summary></details>\n", limits->maxComputeWorkGroupSize[0] );
2059 fprintf(out, "\t\t\t\t\t\t<details><summary>maxComputeWorkGroupSize[1] = <div class='val'>%u</div></summary></details>\n", limits->maxComputeWorkGroupSize[1] );
2060 fprintf(out, "\t\t\t\t\t\t<details><summary>maxComputeWorkGroupSize[2] = <div class='val'>%u</div></summary></details>\n", limits->maxComputeWorkGroupSize[2] );
2061 fprintf(out, "\t\t\t\t\t\t<details><summary>subPixelPrecisionBits = <div class='val'>%u</div></summary></details>\n", limits->subPixelPrecisionBits );
2062 fprintf(out, "\t\t\t\t\t\t<details><summary>subTexelPrecisionBits = <div class='val'>%u</div></summary></details>\n", limits->subTexelPrecisionBits );
2063 fprintf(out, "\t\t\t\t\t\t<details><summary>mipmapPrecisionBits = <div class='val'>%u</div></summary></details>\n", limits->mipmapPrecisionBits );
2064 fprintf(out, "\t\t\t\t\t\t<details><summary>maxDrawIndexedIndexValue = <div class='val'>%u</div></summary></details>\n", limits->maxDrawIndexedIndexValue );
2065 fprintf(out, "\t\t\t\t\t\t<details><summary>maxDrawIndirectCount = <div class='val'>%u</div></summary></details>\n", limits->maxDrawIndirectCount );
2066 fprintf(out, "\t\t\t\t\t\t<details><summary>maxSamplerLodBias = <div class='val'>%f</div></summary></details>\n", limits->maxSamplerLodBias );
2067 fprintf(out, "\t\t\t\t\t\t<details><summary>maxSamplerAnisotropy = <div class='val'>%f</div></summary></details>\n", limits->maxSamplerAnisotropy );
2068 fprintf(out, "\t\t\t\t\t\t<details><summary>maxViewports = <div class='val'>%u</div></summary></details>\n", limits->maxViewports );
2069 fprintf(out, "\t\t\t\t\t\t<details><summary>maxViewportDimensions[0] = <div class='val'>%u</div></summary></details>\n", limits->maxViewportDimensions[0] );
2070 fprintf(out, "\t\t\t\t\t\t<details><summary>maxViewportDimensions[1] = <div class='val'>%u</div></summary></details>\n", limits->maxViewportDimensions[1] );
2071 fprintf(out, "\t\t\t\t\t\t<details><summary>viewportBoundsRange[0] =<div class='val'>%13f</div></summary></details>\n", limits->viewportBoundsRange[0] );
2072 fprintf(out, "\t\t\t\t\t\t<details><summary>viewportBoundsRange[1] =<div class='val'>%13f</div></summary></details>\n", limits->viewportBoundsRange[1] );
2073 fprintf(out, "\t\t\t\t\t\t<details><summary>viewportSubPixelBits = <div class='val'>%u</div></summary></details>\n", limits->viewportSubPixelBits );
2074 fprintf(out, "\t\t\t\t\t\t<details><summary>minMemoryMapAlignment = <div class='val'>" PRINTF_SIZE_T_SPECIFIER "</div></summary></details>\n", limits->minMemoryMapAlignment );
2075 fprintf(out, "\t\t\t\t\t\t<details><summary>minTexelBufferOffsetAlignment = <div class='val'>0x%" PRIxLEAST64 "</div></summary></details>\n", limits->minTexelBufferOffsetAlignment );
2076 fprintf(out, "\t\t\t\t\t\t<details><summary>minUniformBufferOffsetAlignment = <div class='val'>0x%" PRIxLEAST64 "</div></summary></details>\n", limits->minUniformBufferOffsetAlignment );
2077 fprintf(out, "\t\t\t\t\t\t<details><summary>minStorageBufferOffsetAlignment = <div class='val'>0x%" PRIxLEAST64 "</div></summary></details>\n", limits->minStorageBufferOffsetAlignment );
2078 fprintf(out, "\t\t\t\t\t\t<details><summary>minTexelOffset =<div class='val'>%3d</div></summary></details>\n", limits->minTexelOffset );
2079 fprintf(out, "\t\t\t\t\t\t<details><summary>maxTexelOffset =<div class='val'>%3d</div></summary></details>\n", limits->maxTexelOffset );
2080 fprintf(out, "\t\t\t\t\t\t<details><summary>minTexelGatherOffset =<div class='val'>%3d</div></summary></details>\n", limits->minTexelGatherOffset );
2081 fprintf(out, "\t\t\t\t\t\t<details><summary>maxTexelGatherOffset =<div class='val'>%3d</div></summary></details>\n", limits->maxTexelGatherOffset );
2082 fprintf(out, "\t\t\t\t\t\t<details><summary>minInterpolationOffset =<div class='val'>%9f</div></summary></details>\n", limits->minInterpolationOffset );
2083 fprintf(out, "\t\t\t\t\t\t<details><summary>maxInterpolationOffset =<div class='val'>%9f</div></summary></details>\n", limits->maxInterpolationOffset );
2084 fprintf(out, "\t\t\t\t\t\t<details><summary>subPixelInterpolationOffsetBits = <div class='val'>%u</div></summary></details>\n", limits->subPixelInterpolationOffsetBits );
2085 fprintf(out, "\t\t\t\t\t\t<details><summary>maxFramebufferWidth = <div class='val'>%u</div></summary></details>\n", limits->maxFramebufferWidth );
2086 fprintf(out, "\t\t\t\t\t\t<details><summary>maxFramebufferHeight = <div class='val'>%u</div></summary></details>\n", limits->maxFramebufferHeight );
2087 fprintf(out, "\t\t\t\t\t\t<details><summary>maxFramebufferLayers = <div class='val'>%u</div></summary></details>\n", limits->maxFramebufferLayers );
2088 fprintf(out, "\t\t\t\t\t\t<details><summary>framebufferColorSampleCounts = <div class='val'>%u</div></summary></details>\n", limits->framebufferColorSampleCounts );
2089 fprintf(out, "\t\t\t\t\t\t<details><summary>framebufferDepthSampleCounts = <div class='val'>%u</div></summary></details>\n", limits->framebufferDepthSampleCounts );
2090 fprintf(out, "\t\t\t\t\t\t<details><summary>framebufferStencilSampleCounts = <div class='val'>%u</div></summary></details>\n", limits->framebufferStencilSampleCounts );
2091 fprintf(out, "\t\t\t\t\t\t<details><summary>framebufferNoAttachmentsSampleCounts = <div class='val'>%u</div></summary></details>\n", limits->framebufferNoAttachmentsSampleCounts );
2092 fprintf(out, "\t\t\t\t\t\t<details><summary>maxColorAttachments = <div class='val'>%u</div></summary></details>\n", limits->maxColorAttachments );
2093 fprintf(out, "\t\t\t\t\t\t<details><summary>sampledImageColorSampleCounts = <div class='val'>%u</div></summary></details>\n", limits->sampledImageColorSampleCounts );
2094 fprintf(out, "\t\t\t\t\t\t<details><summary>sampledImageDepthSampleCounts = <div class='val'>%u</div></summary></details>\n", limits->sampledImageDepthSampleCounts );
2095 fprintf(out, "\t\t\t\t\t\t<details><summary>sampledImageStencilSampleCounts = <div class='val'>%u</div></summary></details>\n", limits->sampledImageStencilSampleCounts );
2096 fprintf(out, "\t\t\t\t\t\t<details><summary>sampledImageIntegerSampleCounts = <div class='val'>%u</div></summary></details>\n", limits->sampledImageIntegerSampleCounts );
2097 fprintf(out, "\t\t\t\t\t\t<details><summary>storageImageSampleCounts = <div class='val'>%u</div></summary></details>\n", limits->storageImageSampleCounts );
2098 fprintf(out, "\t\t\t\t\t\t<details><summary>maxSampleMaskWords = <div class='val'>%u</div></summary></details>\n", limits->maxSampleMaskWords );
2099 fprintf(out, "\t\t\t\t\t\t<details><summary>timestampComputeAndGraphics = <div class='val'>%u</div></summary></details>\n", limits->timestampComputeAndGraphics );
2100 fprintf(out, "\t\t\t\t\t\t<details><summary>timestampPeriod = <div class='val'>%f</div></summary></details>\n", limits->timestampPeriod );
2101 fprintf(out, "\t\t\t\t\t\t<details><summary>maxClipDistances = <div class='val'>%u</div></summary></details>\n", limits->maxClipDistances );
2102 fprintf(out, "\t\t\t\t\t\t<details><summary>maxCullDistances = <div class='val'>%u</div></summary></details>\n", limits->maxCullDistances );
2103 fprintf(out, "\t\t\t\t\t\t<details><summary>maxCombinedClipAndCullDistances = <div class='val'>%u</div></summary></details>\n", limits->maxCombinedClipAndCullDistances );
2104 fprintf(out, "\t\t\t\t\t\t<details><summary>discreteQueuePriorities = <div class='val'>%u</div></summary></details>\n", limits->discreteQueuePriorities );
2105 fprintf(out, "\t\t\t\t\t\t<details><summary>pointSizeRange[0] = <div class='val'>%f</div></summary></details>\n", limits->pointSizeRange[0] );
2106 fprintf(out, "\t\t\t\t\t\t<details><summary>pointSizeRange[1] = <div class='val'>%f</div></summary></details>\n", limits->pointSizeRange[1] );
2107 fprintf(out, "\t\t\t\t\t\t<details><summary>lineWidthRange[0] = <div class='val'>%f</div></summary></details>\n", limits->lineWidthRange[0] );
2108 fprintf(out, "\t\t\t\t\t\t<details><summary>lineWidthRange[1] = <div class='val'>%f</div></summary></details>\n", limits->lineWidthRange[1] );
2109 fprintf(out, "\t\t\t\t\t\t<details><summary>pointSizeGranularity = <div class='val'>%f</div></summary></details>\n", limits->pointSizeGranularity );
2110 fprintf(out, "\t\t\t\t\t\t<details><summary>lineWidthGranularity = <div class='val'>%f</div></summary></details>\n", limits->lineWidthGranularity );
2111 fprintf(out, "\t\t\t\t\t\t<details><summary>strictLines = <div class='val'>%u</div></summary></details>\n", limits->strictLines );
2112 fprintf(out, "\t\t\t\t\t\t<details><summary>standardSampleLocations = <div class='val'>%u</div></summary></details>\n", limits->standardSampleLocations );
2113 fprintf(out, "\t\t\t\t\t\t<details><summary>optimalBufferCopyOffsetAlignment = <div class='val'>0x%" PRIxLEAST64 "</div></summary></details>\n", limits->optimalBufferCopyOffsetAlignment );
2114 fprintf(out, "\t\t\t\t\t\t<details><summary>optimalBufferCopyRowPitchAlignment = <div class='val'>0x%" PRIxLEAST64 "</div></summary></details>\n", limits->optimalBufferCopyRowPitchAlignment );
2115 fprintf(out, "\t\t\t\t\t\t<details><summary>nonCoherentAtomSize = <div class='val'>0x%" PRIxLEAST64 "</div></summary></details>\n", limits->nonCoherentAtomSize );
2116 fprintf(out, "\t\t\t\t\t</details>\n");
2117 } else if (human_readable_output) {
2118 printf("\tVkPhysicalDeviceLimits:\n");
2119 printf("\t-----------------------\n");
2120 printf("\t\tmaxImageDimension1D = %u\n", limits->maxImageDimension1D );
2121 printf("\t\tmaxImageDimension2D = %u\n", limits->maxImageDimension2D );
2122 printf("\t\tmaxImageDimension3D = %u\n", limits->maxImageDimension3D );
2123 printf("\t\tmaxImageDimensionCube = %u\n", limits->maxImageDimensionCube );
2124 printf("\t\tmaxImageArrayLayers = %u\n", limits->maxImageArrayLayers );
2125 printf("\t\tmaxTexelBufferElements = 0x%" PRIxLEAST32 "\n", limits->maxTexelBufferElements );
2126 printf("\t\tmaxUniformBufferRange = 0x%" PRIxLEAST32 "\n", limits->maxUniformBufferRange );
2127 printf("\t\tmaxStorageBufferRange = 0x%" PRIxLEAST32 "\n", limits->maxStorageBufferRange );
2128 printf("\t\tmaxPushConstantsSize = %u\n", limits->maxPushConstantsSize );
2129 printf("\t\tmaxMemoryAllocationCount = %u\n", limits->maxMemoryAllocationCount );
2130 printf("\t\tmaxSamplerAllocationCount = %u\n", limits->maxSamplerAllocationCount );
2131 printf("\t\tbufferImageGranularity = 0x%" PRIxLEAST64 "\n", limits->bufferImageGranularity );
2132 printf("\t\tsparseAddressSpaceSize = 0x%" PRIxLEAST64 "\n", limits->sparseAddressSpaceSize );
2133 printf("\t\tmaxBoundDescriptorSets = %u\n", limits->maxBoundDescriptorSets );
2134 printf("\t\tmaxPerStageDescriptorSamplers = %u\n", limits->maxPerStageDescriptorSamplers );
2135 printf("\t\tmaxPerStageDescriptorUniformBuffers = %u\n", limits->maxPerStageDescriptorUniformBuffers );
2136 printf("\t\tmaxPerStageDescriptorStorageBuffers = %u\n", limits->maxPerStageDescriptorStorageBuffers );
2137 printf("\t\tmaxPerStageDescriptorSampledImages = %u\n", limits->maxPerStageDescriptorSampledImages );
2138 printf("\t\tmaxPerStageDescriptorStorageImages = %u\n", limits->maxPerStageDescriptorStorageImages );
2139 printf("\t\tmaxPerStageDescriptorInputAttachments = %u\n", limits->maxPerStageDescriptorInputAttachments );
2140 printf("\t\tmaxPerStageResources = %u\n", limits->maxPerStageResources );
2141 printf("\t\tmaxDescriptorSetSamplers = %u\n", limits->maxDescriptorSetSamplers );
2142 printf("\t\tmaxDescriptorSetUniformBuffers = %u\n", limits->maxDescriptorSetUniformBuffers );
2143 printf("\t\tmaxDescriptorSetUniformBuffersDynamic = %u\n", limits->maxDescriptorSetUniformBuffersDynamic );
2144 printf("\t\tmaxDescriptorSetStorageBuffers = %u\n", limits->maxDescriptorSetStorageBuffers );
2145 printf("\t\tmaxDescriptorSetStorageBuffersDynamic = %u\n", limits->maxDescriptorSetStorageBuffersDynamic );
2146 printf("\t\tmaxDescriptorSetSampledImages = %u\n", limits->maxDescriptorSetSampledImages );
2147 printf("\t\tmaxDescriptorSetStorageImages = %u\n", limits->maxDescriptorSetStorageImages );
2148 printf("\t\tmaxDescriptorSetInputAttachments = %u\n", limits->maxDescriptorSetInputAttachments );
2149 printf("\t\tmaxVertexInputAttributes = %u\n", limits->maxVertexInputAttributes );
2150 printf("\t\tmaxVertexInputBindings = %u\n", limits->maxVertexInputBindings );
2151 printf("\t\tmaxVertexInputAttributeOffset = 0x%" PRIxLEAST32 "\n", limits->maxVertexInputAttributeOffset );
2152 printf("\t\tmaxVertexInputBindingStride = 0x%" PRIxLEAST32 "\n", limits->maxVertexInputBindingStride );
2153 printf("\t\tmaxVertexOutputComponents = %u\n", limits->maxVertexOutputComponents );
2154 printf("\t\tmaxTessellationGenerationLevel = %u\n", limits->maxTessellationGenerationLevel );
2155 printf("\t\tmaxTessellationPatchSize = %u\n", limits->maxTessellationPatchSize );
2156 printf("\t\tmaxTessellationControlPerVertexInputComponents = %u\n", limits->maxTessellationControlPerVertexInputComponents );
2157 printf("\t\tmaxTessellationControlPerVertexOutputComponents = %u\n", limits->maxTessellationControlPerVertexOutputComponents);
2158 printf("\t\tmaxTessellationControlPerPatchOutputComponents = %u\n", limits->maxTessellationControlPerPatchOutputComponents );
2159 printf("\t\tmaxTessellationControlTotalOutputComponents = %u\n", limits->maxTessellationControlTotalOutputComponents );
2160 printf("\t\tmaxTessellationEvaluationInputComponents = %u\n", limits->maxTessellationEvaluationInputComponents );
2161 printf("\t\tmaxTessellationEvaluationOutputComponents = %u\n", limits->maxTessellationEvaluationOutputComponents );
2162 printf("\t\tmaxGeometryShaderInvocations = %u\n", limits->maxGeometryShaderInvocations );
2163 printf("\t\tmaxGeometryInputComponents = %u\n", limits->maxGeometryInputComponents );
2164 printf("\t\tmaxGeometryOutputComponents = %u\n", limits->maxGeometryOutputComponents );
2165 printf("\t\tmaxGeometryOutputVertices = %u\n", limits->maxGeometryOutputVertices );
2166 printf("\t\tmaxGeometryTotalOutputComponents = %u\n", limits->maxGeometryTotalOutputComponents );
2167 printf("\t\tmaxFragmentInputComponents = %u\n", limits->maxFragmentInputComponents );
2168 printf("\t\tmaxFragmentOutputAttachments = %u\n", limits->maxFragmentOutputAttachments );
2169 printf("\t\tmaxFragmentDualSrcAttachments = %u\n", limits->maxFragmentDualSrcAttachments );
2170 printf("\t\tmaxFragmentCombinedOutputResources = %u\n", limits->maxFragmentCombinedOutputResources );
2171 printf("\t\tmaxComputeSharedMemorySize = 0x%" PRIxLEAST32 "\n", limits->maxComputeSharedMemorySize );
2172 printf("\t\tmaxComputeWorkGroupCount[0] = %u\n", limits->maxComputeWorkGroupCount[0] );
2173 printf("\t\tmaxComputeWorkGroupCount[1] = %u\n", limits->maxComputeWorkGroupCount[1] );
2174 printf("\t\tmaxComputeWorkGroupCount[2] = %u\n", limits->maxComputeWorkGroupCount[2] );
2175 printf("\t\tmaxComputeWorkGroupInvocations = %u\n", limits->maxComputeWorkGroupInvocations );
2176 printf("\t\tmaxComputeWorkGroupSize[0] = %u\n", limits->maxComputeWorkGroupSize[0] );
2177 printf("\t\tmaxComputeWorkGroupSize[1] = %u\n", limits->maxComputeWorkGroupSize[1] );
2178 printf("\t\tmaxComputeWorkGroupSize[2] = %u\n", limits->maxComputeWorkGroupSize[2] );
2179 printf("\t\tsubPixelPrecisionBits = %u\n", limits->subPixelPrecisionBits );
2180 printf("\t\tsubTexelPrecisionBits = %u\n", limits->subTexelPrecisionBits );
2181 printf("\t\tmipmapPrecisionBits = %u\n", limits->mipmapPrecisionBits );
2182 printf("\t\tmaxDrawIndexedIndexValue = %u\n", limits->maxDrawIndexedIndexValue );
2183 printf("\t\tmaxDrawIndirectCount = %u\n", limits->maxDrawIndirectCount );
2184 printf("\t\tmaxSamplerLodBias = %f\n", limits->maxSamplerLodBias );
2185 printf("\t\tmaxSamplerAnisotropy = %f\n", limits->maxSamplerAnisotropy );
2186 printf("\t\tmaxViewports = %u\n", limits->maxViewports );
2187 printf("\t\tmaxViewportDimensions[0] = %u\n", limits->maxViewportDimensions[0] );
2188 printf("\t\tmaxViewportDimensions[1] = %u\n", limits->maxViewportDimensions[1] );
2189 printf("\t\tviewportBoundsRange[0] =%13f\n", limits->viewportBoundsRange[0] );
2190 printf("\t\tviewportBoundsRange[1] =%13f\n", limits->viewportBoundsRange[1] );
2191 printf("\t\tviewportSubPixelBits = %u\n", limits->viewportSubPixelBits );
2192 printf("\t\tminMemoryMapAlignment = " PRINTF_SIZE_T_SPECIFIER "\n", limits->minMemoryMapAlignment );
2193 printf("\t\tminTexelBufferOffsetAlignment = 0x%" PRIxLEAST64 "\n", limits->minTexelBufferOffsetAlignment );
2194 printf("\t\tminUniformBufferOffsetAlignment = 0x%" PRIxLEAST64 "\n", limits->minUniformBufferOffsetAlignment );
2195 printf("\t\tminStorageBufferOffsetAlignment = 0x%" PRIxLEAST64 "\n", limits->minStorageBufferOffsetAlignment );
2196 printf("\t\tminTexelOffset =%3d\n", limits->minTexelOffset );
2197 printf("\t\tmaxTexelOffset =%3d\n", limits->maxTexelOffset );
2198 printf("\t\tminTexelGatherOffset =%3d\n", limits->minTexelGatherOffset );
2199 printf("\t\tmaxTexelGatherOffset =%3d\n", limits->maxTexelGatherOffset );
2200 printf("\t\tminInterpolationOffset =%9f\n", limits->minInterpolationOffset );
2201 printf("\t\tmaxInterpolationOffset =%9f\n", limits->maxInterpolationOffset );
2202 printf("\t\tsubPixelInterpolationOffsetBits = %u\n", limits->subPixelInterpolationOffsetBits );
2203 printf("\t\tmaxFramebufferWidth = %u\n", limits->maxFramebufferWidth );
2204 printf("\t\tmaxFramebufferHeight = %u\n", limits->maxFramebufferHeight );
2205 printf("\t\tmaxFramebufferLayers = %u\n", limits->maxFramebufferLayers );
2206 printf("\t\tframebufferColorSampleCounts = %u\n", limits->framebufferColorSampleCounts );
2207 printf("\t\tframebufferDepthSampleCounts = %u\n", limits->framebufferDepthSampleCounts );
2208 printf("\t\tframebufferStencilSampleCounts = %u\n", limits->framebufferStencilSampleCounts );
2209 printf("\t\tframebufferNoAttachmentsSampleCounts = %u\n", limits->framebufferNoAttachmentsSampleCounts );
2210 printf("\t\tmaxColorAttachments = %u\n", limits->maxColorAttachments );
2211 printf("\t\tsampledImageColorSampleCounts = %u\n", limits->sampledImageColorSampleCounts );
2212 printf("\t\tsampledImageDepthSampleCounts = %u\n", limits->sampledImageDepthSampleCounts );
2213 printf("\t\tsampledImageStencilSampleCounts = %u\n", limits->sampledImageStencilSampleCounts );
2214 printf("\t\tsampledImageIntegerSampleCounts = %u\n", limits->sampledImageIntegerSampleCounts );
2215 printf("\t\tstorageImageSampleCounts = %u\n", limits->storageImageSampleCounts );
2216 printf("\t\tmaxSampleMaskWords = %u\n", limits->maxSampleMaskWords );
2217 printf("\t\ttimestampComputeAndGraphics = %u\n", limits->timestampComputeAndGraphics );
2218 printf("\t\ttimestampPeriod = %f\n", limits->timestampPeriod );
2219 printf("\t\tmaxClipDistances = %u\n", limits->maxClipDistances );
2220 printf("\t\tmaxCullDistances = %u\n", limits->maxCullDistances );
2221 printf("\t\tmaxCombinedClipAndCullDistances = %u\n", limits->maxCombinedClipAndCullDistances );
2222 printf("\t\tdiscreteQueuePriorities = %u\n", limits->discreteQueuePriorities );
2223 printf("\t\tpointSizeRange[0] = %f\n", limits->pointSizeRange[0] );
2224 printf("\t\tpointSizeRange[1] = %f\n", limits->pointSizeRange[1] );
2225 printf("\t\tlineWidthRange[0] = %f\n", limits->lineWidthRange[0] );
2226 printf("\t\tlineWidthRange[1] = %f\n", limits->lineWidthRange[1] );
2227 printf("\t\tpointSizeGranularity = %f\n", limits->pointSizeGranularity );
2228 printf("\t\tlineWidthGranularity = %f\n", limits->lineWidthGranularity );
2229 printf("\t\tstrictLines = %u\n", limits->strictLines );
2230 printf("\t\tstandardSampleLocations = %u\n", limits->standardSampleLocations );
2231 printf("\t\toptimalBufferCopyOffsetAlignment = 0x%" PRIxLEAST64 "\n", limits->optimalBufferCopyOffsetAlignment );
2232 printf("\t\toptimalBufferCopyRowPitchAlignment = 0x%" PRIxLEAST64 "\n", limits->optimalBufferCopyRowPitchAlignment );
2233 printf("\t\tnonCoherentAtomSize = 0x%" PRIxLEAST64 "\n", limits->nonCoherentAtomSize );
2237 printf("\t\t\"limits\": {\n");
2238 printf("\t\t\t\"bufferImageGranularity\": %llu,\n", (unsigned long long)limits->bufferImageGranularity);
2239 printf("\t\t\t\"discreteQueuePriorities\": %u,\n", limits->discreteQueuePriorities);
2240 printf("\t\t\t\"framebufferColorSampleCounts\": %u,\n", limits->framebufferColorSampleCounts);
2241 printf("\t\t\t\"framebufferDepthSampleCounts\": %u,\n", limits->framebufferDepthSampleCounts);
2242 printf("\t\t\t\"framebufferNoAttachmentsSampleCounts\": %u,\n", limits->framebufferNoAttachmentsSampleCounts);
2243 printf("\t\t\t\"framebufferStencilSampleCounts\": %u,\n", limits->framebufferStencilSampleCounts);
2244 printf("\t\t\t\"lineWidthGranularity\": %g,\n", limits->lineWidthGranularity);
2245 printf("\t\t\t\"lineWidthRange\": [\n");
2246 printf("\t\t\t\t%g,\n", limits->lineWidthRange[0]);
2247 printf("\t\t\t\t%g\n", limits->lineWidthRange[1]);
2248 printf("\t\t\t],\n");
2249 printf("\t\t\t\"maxBoundDescriptorSets\": %u,\n", limits->maxBoundDescriptorSets);
2250 printf("\t\t\t\"maxClipDistances\": %u,\n", limits->maxClipDistances);
2251 printf("\t\t\t\"maxColorAttachments\": %u,\n", limits->maxColorAttachments);
2252 printf("\t\t\t\"maxCombinedClipAndCullDistances\": %u,\n", limits->maxCombinedClipAndCullDistances);
2253 printf("\t\t\t\"maxComputeSharedMemorySize\": %u,\n", limits->maxComputeSharedMemorySize);
2254 printf("\t\t\t\"maxComputeWorkGroupCount\": [\n");
2255 printf("\t\t\t\t%u,\n", limits->maxComputeWorkGroupCount[0]);
2256 printf("\t\t\t\t%u,\n", limits->maxComputeWorkGroupCount[1]);
2257 printf("\t\t\t\t%u\n", limits->maxComputeWorkGroupCount[2]);
2258 printf("\t\t\t],\n");
2259 printf("\t\t\t\"maxComputeWorkGroupInvocations\": %u,\n", limits->maxComputeWorkGroupInvocations);
2260 printf("\t\t\t\"maxComputeWorkGroupSize\": [\n");
2261 printf("\t\t\t\t%u,\n", limits->maxComputeWorkGroupSize[0]);
2262 printf("\t\t\t\t%u,\n", limits->maxComputeWorkGroupSize[1]);
2263 printf("\t\t\t\t%u\n", limits->maxComputeWorkGroupSize[2]);
2264 printf("\t\t\t],\n");
2265 printf("\t\t\t\"maxCullDistances\": %u,\n", limits->maxCullDistances);
2266 printf("\t\t\t\"maxDescriptorSetInputAttachments\": %u,\n", limits->maxDescriptorSetInputAttachments);
2267 printf("\t\t\t\"maxDescriptorSetSampledImages\": %u,\n", limits->maxDescriptorSetSampledImages);
2268 printf("\t\t\t\"maxDescriptorSetSamplers\": %u,\n", limits->maxDescriptorSetSamplers);
2269 printf("\t\t\t\"maxDescriptorSetStorageBuffers\": %u,\n", limits->maxDescriptorSetStorageBuffers);
2270 printf("\t\t\t\"maxDescriptorSetStorageBuffersDynamic\": %u,\n", limits->maxDescriptorSetStorageBuffersDynamic);
2271 printf("\t\t\t\"maxDescriptorSetStorageImages\": %u,\n", limits->maxDescriptorSetStorageImages);
2272 printf("\t\t\t\"maxDescriptorSetUniformBuffers\": %u,\n", limits->maxDescriptorSetUniformBuffers);
2273 printf("\t\t\t\"maxDescriptorSetUniformBuffersDynamic\": %u,\n", limits->maxDescriptorSetUniformBuffersDynamic);
2274 printf("\t\t\t\"maxDrawIndexedIndexValue\": %u,\n", limits->maxDrawIndexedIndexValue);
2275 printf("\t\t\t\"maxDrawIndirectCount\": %u,\n", limits->maxDrawIndirectCount);
2276 printf("\t\t\t\"maxFragmentCombinedOutputResources\": %u,\n", limits->maxFragmentCombinedOutputResources);
2277 printf("\t\t\t\"maxFragmentDualSrcAttachments\": %u,\n", limits->maxFragmentDualSrcAttachments);
2278 printf("\t\t\t\"maxFragmentInputComponents\": %u,\n", limits->maxFragmentInputComponents);
2279 printf("\t\t\t\"maxFragmentOutputAttachments\": %u,\n", limits->maxFragmentOutputAttachments);
2280 printf("\t\t\t\"maxFramebufferHeight\": %u,\n", limits->maxFramebufferHeight);
2281 printf("\t\t\t\"maxFramebufferLayers\": %u,\n", limits->maxFramebufferLayers);
2282 printf("\t\t\t\"maxFramebufferWidth\": %u,\n", limits->maxFramebufferWidth);
2283 printf("\t\t\t\"maxGeometryInputComponents\": %u,\n", limits->maxGeometryInputComponents);
2284 printf("\t\t\t\"maxGeometryOutputComponents\": %u,\n", limits->maxGeometryOutputComponents);
2285 printf("\t\t\t\"maxGeometryOutputVertices\": %u,\n", limits->maxGeometryOutputVertices);
2286 printf("\t\t\t\"maxGeometryShaderInvocations\": %u,\n", limits->maxGeometryShaderInvocations);
2287 printf("\t\t\t\"maxGeometryTotalOutputComponents\": %u,\n", limits->maxGeometryTotalOutputComponents);
2288 printf("\t\t\t\"maxImageArrayLayers\": %u,\n", limits->maxImageArrayLayers);
2289 printf("\t\t\t\"maxImageDimension1D\": %u,\n", limits->maxImageDimension1D);
2290 printf("\t\t\t\"maxImageDimension2D\": %u,\n", limits->maxImageDimension2D);
2291 printf("\t\t\t\"maxImageDimension3D\": %u,\n", limits->maxImageDimension3D);
2292 printf("\t\t\t\"maxImageDimensionCube\": %u,\n", limits->maxImageDimensionCube);
2293 printf("\t\t\t\"maxInterpolationOffset\": %g,\n", limits->maxInterpolationOffset);
2294 printf("\t\t\t\"maxMemoryAllocationCount\": %u,\n", limits->maxMemoryAllocationCount);
2295 printf("\t\t\t\"maxPerStageDescriptorInputAttachments\": %u,\n", limits->maxPerStageDescriptorInputAttachments);
2296 printf("\t\t\t\"maxPerStageDescriptorSampledImages\": %u,\n", limits->maxPerStageDescriptorSampledImages);
2297 printf("\t\t\t\"maxPerStageDescriptorSamplers\": %u,\n", limits->maxPerStageDescriptorSamplers);
2298 printf("\t\t\t\"maxPerStageDescriptorStorageBuffers\": %u,\n", limits->maxPerStageDescriptorStorageBuffers);
2299 printf("\t\t\t\"maxPerStageDescriptorStorageImages\": %u,\n", limits->maxPerStageDescriptorStorageImages);
2300 printf("\t\t\t\"maxPerStageDescriptorUniformBuffers\": %u,\n", limits->maxPerStageDescriptorUniformBuffers);
2301 printf("\t\t\t\"maxPerStageResources\": %u,\n", limits->maxPerStageResources);
2302 printf("\t\t\t\"maxPushConstantsSize\": %u,\n", limits->maxPushConstantsSize);
2303 printf("\t\t\t\"maxSampleMaskWords\": %u,\n", limits->maxSampleMaskWords);
2304 printf("\t\t\t\"maxSamplerAllocationCount\": %u,\n", limits->maxSamplerAllocationCount);
2305 printf("\t\t\t\"maxSamplerAnisotropy\": %g,\n", limits->maxSamplerAnisotropy);
2306 printf("\t\t\t\"maxSamplerLodBias\": %g,\n", limits->maxSamplerLodBias);
2307 printf("\t\t\t\"maxStorageBufferRange\": %u,\n", limits->maxStorageBufferRange);
2308 printf("\t\t\t\"maxTessellationControlPerPatchOutputComponents\": %u,\n", limits->maxTessellationControlPerPatchOutputComponents);
2309 printf("\t\t\t\"maxTessellationControlPerVertexInputComponents\": %u,\n", limits->maxTessellationControlPerVertexInputComponents);
2310 printf("\t\t\t\"maxTessellationControlPerVertexOutputComponents\": %u,\n", limits->maxTessellationControlPerVertexOutputComponents);
2311 printf("\t\t\t\"maxTessellationControlTotalOutputComponents\": %u,\n", limits->maxTessellationControlTotalOutputComponents);
2312 printf("\t\t\t\"maxTessellationEvaluationInputComponents\": %u,\n", limits->maxTessellationEvaluationInputComponents);
2313 printf("\t\t\t\"maxTessellationEvaluationOutputComponents\": %u,\n", limits->maxTessellationEvaluationOutputComponents);
2314 printf("\t\t\t\"maxTessellationGenerationLevel\": %u,\n", limits->maxTessellationGenerationLevel);
2315 printf("\t\t\t\"maxTessellationPatchSize\": %u,\n", limits->maxTessellationPatchSize);
2316 printf("\t\t\t\"maxTexelBufferElements\": %u,\n", limits->maxTexelBufferElements);
2317 printf("\t\t\t\"maxTexelGatherOffset\": %u,\n", limits->maxTexelGatherOffset);
2318 printf("\t\t\t\"maxTexelOffset\": %u,\n", limits->maxTexelOffset);
2319 printf("\t\t\t\"maxUniformBufferRange\": %u,\n", limits->maxUniformBufferRange);
2320 printf("\t\t\t\"maxVertexInputAttributeOffset\": %u,\n", limits->maxVertexInputAttributeOffset);
2321 printf("\t\t\t\"maxVertexInputAttributes\": %u,\n", limits->maxVertexInputAttributes);
2322 printf("\t\t\t\"maxVertexInputBindings\": %u,\n", limits->maxVertexInputBindings);
2323 printf("\t\t\t\"maxVertexInputBindingStride\": %u,\n", limits->maxVertexInputBindingStride);
2324 printf("\t\t\t\"maxVertexOutputComponents\": %u,\n", limits->maxVertexOutputComponents);
2325 printf("\t\t\t\"maxViewportDimensions\": [\n");
2326 printf("\t\t\t\t%u,\n", limits->maxViewportDimensions[0]);
2327 printf("\t\t\t\t%u\n", limits->maxViewportDimensions[1]);
2328 printf("\t\t\t],\n");
2329 printf("\t\t\t\"maxViewports\": %u,\n", limits->maxViewports);
2330 printf("\t\t\t\"minInterpolationOffset\": %g,\n", limits->minInterpolationOffset);
2331 printf("\t\t\t\"minMemoryMapAlignment\": " PRINTF_SIZE_T_SPECIFIER ",\n", limits->minMemoryMapAlignment);
2332 printf("\t\t\t\"minStorageBufferOffsetAlignment\": %llu,\n", (unsigned long long)limits->minStorageBufferOffsetAlignment);
2333 printf("\t\t\t\"minTexelBufferOffsetAlignment\": %llu,\n", (unsigned long long)limits->minTexelBufferOffsetAlignment);
2334 printf("\t\t\t\"minTexelGatherOffset\": %d,\n", limits->minTexelGatherOffset);
2335 printf("\t\t\t\"minTexelOffset\": %d,\n", limits->minTexelOffset);
2336 printf("\t\t\t\"minUniformBufferOffsetAlignment\": %llu,\n", (unsigned long long)limits->minUniformBufferOffsetAlignment);
2337 printf("\t\t\t\"mipmapPrecisionBits\": %u,\n", limits->mipmapPrecisionBits);
2338 printf("\t\t\t\"nonCoherentAtomSize\": %llu,\n", (unsigned long long)limits->nonCoherentAtomSize);
2339 printf("\t\t\t\"optimalBufferCopyOffsetAlignment\": %llu,\n", (unsigned long long)limits->optimalBufferCopyOffsetAlignment);
2340 printf("\t\t\t\"optimalBufferCopyRowPitchAlignment\": %llu,\n", (unsigned long long)limits->optimalBufferCopyRowPitchAlignment);
2341 printf("\t\t\t\"pointSizeGranularity\": %g,\n", limits->pointSizeGranularity);
2342 printf("\t\t\t\"pointSizeRange\": [\n");
2343 printf("\t\t\t\t%g,\n", limits->pointSizeRange[0]);
2344 printf("\t\t\t\t%g\n", limits->pointSizeRange[1]);
2345 printf("\t\t\t],\n");
2346 printf("\t\t\t\"sampledImageColorSampleCounts\": %u,\n", limits->sampledImageColorSampleCounts);
2347 printf("\t\t\t\"sampledImageDepthSampleCounts\": %u,\n", limits->sampledImageDepthSampleCounts);
2348 printf("\t\t\t\"sampledImageIntegerSampleCounts\": %u,\n", limits->sampledImageIntegerSampleCounts);
2349 printf("\t\t\t\"sampledImageStencilSampleCounts\": %u,\n", limits->sampledImageStencilSampleCounts);
2350 printf("\t\t\t\"sparseAddressSpaceSize\": %llu,\n", (unsigned long long)limits->sparseAddressSpaceSize);
2351 printf("\t\t\t\"standardSampleLocations\": %u,\n", limits->standardSampleLocations);
2352 printf("\t\t\t\"storageImageSampleCounts\": %u,\n", limits->storageImageSampleCounts);
2353 printf("\t\t\t\"strictLines\": %u,\n", limits->strictLines);
2354 printf("\t\t\t\"subPixelInterpolationOffsetBits\": %u,\n", limits->subPixelInterpolationOffsetBits);
2355 printf("\t\t\t\"subPixelPrecisionBits\": %u,\n", limits->subPixelPrecisionBits);
2356 printf("\t\t\t\"subTexelPrecisionBits\": %u,\n", limits->subTexelPrecisionBits);
2357 printf("\t\t\t\"timestampComputeAndGraphics\": %u,\n", limits->timestampComputeAndGraphics);
2358 printf("\t\t\t\"timestampPeriod\": %g,\n", limits->timestampPeriod);
2359 printf("\t\t\t\"viewportBoundsRange\": [\n");
2360 printf("\t\t\t\t%g,\n", limits->viewportBoundsRange[0]);
2361 printf("\t\t\t\t%g\n", limits->viewportBoundsRange[1]);
2362 printf("\t\t\t],\n");
2363 printf("\t\t\t\"viewportSubPixelBits\": %u\n", limits->viewportSubPixelBits);
2368 static void AppGpuDumpProps(const struct AppGpu *gpu, FILE *out) {
2369 VkPhysicalDeviceProperties props;
2371 if (CheckExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, gpu->inst->inst_extensions,
2372 gpu->inst->inst_extensions_count)) {
2373 const VkPhysicalDeviceProperties *props2_const = &gpu->props2.properties;
2374 props = *props2_const;
2376 const VkPhysicalDeviceProperties *props_const = &gpu->props;
2377 props = *props_const;
2379 const uint32_t apiVersion = props.apiVersion;
2380 const uint32_t major = VK_VERSION_MAJOR(apiVersion);
2381 const uint32_t minor = VK_VERSION_MINOR(apiVersion);
2382 const uint32_t patch = VK_VERSION_PATCH(apiVersion);
2385 fprintf(out, "\t\t\t\t\t<details><summary>VkPhysicalDeviceProperties</summary>\n");
2386 fprintf(out, "\t\t\t\t\t\t<details><summary>apiVersion = <div class='val'>0x%" PRIxLEAST32 "</div> (<div class='val'>%d.%d.%d</div>)</summary></details>\n", apiVersion, major, minor, patch);
2387 fprintf(out, "\t\t\t\t\t\t<details><summary>driverVersion = <div class='val'>%u</div> (<div class='val'>0x%" PRIxLEAST32 "</div>)</summary></details>\n", props.driverVersion, props.driverVersion);
2388 fprintf(out, "\t\t\t\t\t\t<details><summary>vendorID = <div class='val'>0x%04x</div></summary></details>\n", props.vendorID);
2389 fprintf(out, "\t\t\t\t\t\t<details><summary>deviceID = <div class='val'>0x%04x</div></summary></details>\n", props.deviceID);
2390 fprintf(out, "\t\t\t\t\t\t<details><summary>deviceType = %s</summary></details>\n", VkPhysicalDeviceTypeString(props.deviceType));
2391 fprintf(out, "\t\t\t\t\t\t<details><summary>deviceName = %s</summary></details>\n", props.deviceName);
2392 fprintf(out, "\t\t\t\t\t</details>\n");
2393 } else if (human_readable_output) {
2394 printf("VkPhysicalDeviceProperties:\n");
2395 printf("===========================\n");
2396 printf("\tapiVersion = 0x%" PRIxLEAST32 " (%d.%d.%d)\n", apiVersion, major, minor, patch);
2397 printf("\tdriverVersion = %u (0x%" PRIxLEAST32 ")\n", props.driverVersion, props.driverVersion);
2398 printf("\tvendorID = 0x%04x\n", props.vendorID);
2399 printf("\tdeviceID = 0x%04x\n", props.deviceID);
2400 printf("\tdeviceType = %s\n", VkPhysicalDeviceTypeString(props.deviceType));
2401 printf("\tdeviceName = %s\n", props.deviceName);
2405 printf("\t\"VkPhysicalDeviceProperties\": {\n");
2406 printf("\t\t\"apiVersion\": %u,\n", apiVersion);
2407 printf("\t\t\"deviceID\": %u,\n", props.deviceID);
2408 printf("\t\t\"deviceName\": \"%s\",\n", props.deviceName);
2409 printf("\t\t\"deviceType\": %u,\n", props.deviceType);
2410 printf("\t\t\"driverVersion\": %u", props.driverVersion);
2413 if (CheckExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, gpu->inst->inst_extensions, gpu->inst->inst_extensions_count)) {
2414 AppDumpLimits(&gpu->props2.properties.limits, out);
2416 AppDumpLimits(&gpu->props.limits, out);
2419 // Dump pipeline cache UUIDs to json
2422 printf("\t\t\"pipelineCacheUUID\": [");
2423 for (uint32_t i = 0; i < VK_UUID_SIZE; ++i) {
2428 printf("\t\t\t%u", props.pipelineCacheUUID[i]);
2434 if (CheckExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, gpu->inst->inst_extensions, gpu->inst->inst_extensions_count)) {
2435 AppDumpSparseProps(&gpu->props2.properties.sparseProperties, out);
2437 AppDumpSparseProps(&gpu->props.sparseProperties, out);
2442 printf("\t\t\"vendorID\": %u\n", props.vendorID);
2446 if (CheckExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, gpu->inst->inst_extensions,
2447 gpu->inst->inst_extensions_count)) {
2448 void *place = gpu->props2.pNext;
2450 struct VkStructureHeader *structure = (struct VkStructureHeader*) place;
2451 if (structure->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT && CheckPhysicalDeviceExtensionIncluded(VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME, gpu->device_extensions, gpu->device_extension_count)) {
2452 VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT *blend_op_adv_props = (VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT*)structure;
2454 fprintf(out, "\n\t\t\t\t\t<details><summary>VkPhysicalDeviceBlendOperationAdvancedProperties</summary>\n");
2455 fprintf(out, "\t\t\t\t\t\t<details><summary>advancedBlendMaxColorAttachments = <div class='val'>%u</div></summary></details>\n", blend_op_adv_props->advancedBlendMaxColorAttachments );
2456 fprintf(out, "\t\t\t\t\t\t<details><summary>advancedBlendIndependentBlend = <div class='val'>%u</div></summary></details>\n", blend_op_adv_props->advancedBlendIndependentBlend );
2457 fprintf(out, "\t\t\t\t\t\t<details><summary>advancedBlendNonPremultipliedSrcColor = <div class='val'>%u</div></summary></details>\n", blend_op_adv_props->advancedBlendNonPremultipliedSrcColor);
2458 fprintf(out, "\t\t\t\t\t\t<details><summary>advancedBlendNonPremultipliedDstColor = <div class='val'>%u</div></summary></details>\n", blend_op_adv_props->advancedBlendNonPremultipliedDstColor);
2459 fprintf(out, "\t\t\t\t\t\t<details><summary>advancedBlendCorrelatedOverlap = <div class='val'>%u</div></summary></details>\n", blend_op_adv_props->advancedBlendCorrelatedOverlap );
2460 fprintf(out, "\t\t\t\t\t\t<details><summary>advancedBlendAllOperations = <div class='val'>%u</div></summary></details>\n", blend_op_adv_props->advancedBlendAllOperations );
2461 fprintf(out, "\t\t\t\t\t</details>\n");
2462 } else if (human_readable_output) {
2463 printf("\nVkPhysicalDeviceBlendOperationAdvancedProperties:\n");
2464 printf("=================================================\n");
2465 printf("\tadvancedBlendMaxColorAttachments = %u\n", blend_op_adv_props->advancedBlendMaxColorAttachments );
2466 printf("\tadvancedBlendIndependentBlend = %u\n", blend_op_adv_props->advancedBlendIndependentBlend );
2467 printf("\tadvancedBlendNonPremultipliedSrcColor = %u\n", blend_op_adv_props->advancedBlendNonPremultipliedSrcColor);
2468 printf("\tadvancedBlendNonPremultipliedDstColor = %u\n", blend_op_adv_props->advancedBlendNonPremultipliedDstColor);
2469 printf("\tadvancedBlendCorrelatedOverlap = %u\n", blend_op_adv_props->advancedBlendCorrelatedOverlap );
2470 printf("\tadvancedBlendAllOperations = %u\n", blend_op_adv_props->advancedBlendAllOperations );
2472 } else if (structure->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES_KHR && CheckPhysicalDeviceExtensionIncluded(VK_KHR_MAINTENANCE2_EXTENSION_NAME, gpu->device_extensions, gpu->device_extension_count)) {
2473 VkPhysicalDevicePointClippingPropertiesKHR *pt_clip_props = (VkPhysicalDevicePointClippingPropertiesKHR*)structure;
2475 fprintf(out, "\n\t\t\t\t\t<details><summary>VkPhysicalDevicePointClippingProperties</summary>\n");
2476 fprintf(out, "\t\t\t\t\t\t<details><summary>pointClippingBehavior = <div class='val'>%u</div></summary></details>\n", pt_clip_props->pointClippingBehavior);
2477 fprintf(out, "\t\t\t\t\t</details>\n");
2478 } else if (human_readable_output) {
2479 printf("\nVkPhysicalDevicePointClippingProperties:\n");
2480 printf("========================================\n");
2481 printf("\tpointClippingBehavior = %u\n", pt_clip_props->pointClippingBehavior);
2483 } else if (structure->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR && CheckPhysicalDeviceExtensionIncluded(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME, gpu->device_extensions, gpu->device_extension_count)) {
2484 VkPhysicalDevicePushDescriptorPropertiesKHR *push_desc_props = (VkPhysicalDevicePushDescriptorPropertiesKHR*)structure;
2486 fprintf(out, "\n\t\t\t\t\t<details><summary>VkPhysicalDevicePushDescriptorProperties</summary>\n");
2487 fprintf(out, "\t\t\t\t\t\t<details><summary>maxPushDescriptors = <div class='val'>%u</div></summary></details>\n", push_desc_props->maxPushDescriptors);
2488 fprintf(out, "\t\t\t\t\t</details>\n");
2489 } else if (human_readable_output) {
2490 printf("\nVkPhysicalDevicePushDescriptorProperties:\n");
2491 printf("=========================================\n");
2492 printf("\tmaxPushDescriptors = %u\n", push_desc_props->maxPushDescriptors);
2494 } else if (structure->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISCARD_RECTANGLE_PROPERTIES_EXT && CheckPhysicalDeviceExtensionIncluded(VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME, gpu->device_extensions, gpu->device_extension_count)) {
2495 VkPhysicalDeviceDiscardRectanglePropertiesEXT *discard_rect_props = (VkPhysicalDeviceDiscardRectanglePropertiesEXT*)structure;
2497 fprintf(out, "\n\t\t\t\t\t<details><summary>VkPhysicalDeviceDiscardRectangleProperties</summary>\n");
2498 fprintf(out, "\t\t\t\t\t\t<details><summary>maxDiscardRectangles = <div class='val'>%u</div></summary></details>\n", discard_rect_props->maxDiscardRectangles);
2499 fprintf(out, "\t\t\t\t\t</details>\n");
2500 } else if (human_readable_output) {
2501 printf("\nVkPhysicalDeviceDiscardRectangleProperties:\n");
2502 printf("=========================================\n");
2503 printf("\tmaxDiscardRectangles = %u\n", discard_rect_props->maxDiscardRectangles);
2505 } else if (structure->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHR && CheckPhysicalDeviceExtensionIncluded(VK_KHR_MULTIVIEW_EXTENSION_NAME, gpu->device_extensions, gpu->device_extension_count)) {
2506 VkPhysicalDeviceMultiviewPropertiesKHR *multiview_props = (VkPhysicalDeviceMultiviewPropertiesKHR*)structure;
2508 fprintf(out, "\n\t\t\t\t\t<details><summary>VkPhysicalDeviceMultiviewProperties</summary>\n");
2509 fprintf(out, "\t\t\t\t\t\t<details><summary>maxMultiviewInstanceIndex = <div class='val'>%u</div></summary></details>\n", multiview_props->maxMultiviewInstanceIndex);
2510 fprintf(out, "\t\t\t\t\t\t<details><summary>maxMultiviewViewCount = <div class='val'>%u</div></summary></details>\n", multiview_props->maxMultiviewViewCount );
2511 fprintf(out, "\t\t\t\t\t</details>\n");
2513 else if (human_readable_output) {
2514 printf("\nVkPhysicalDeviceMultiviewProperties:\n");
2515 printf("=========================================\n");
2516 printf("\tmaxMultiviewInstanceIndex = %u\n", multiview_props->maxMultiviewInstanceIndex);
2517 printf("\tmaxMultiviewViewCount = %u\n", multiview_props->maxMultiviewViewCount );
2520 place = structure->pNext;
2528 static void AppDumpExtensions(const char *indent, const char *layer_name, const uint32_t extension_count,
2529 const VkExtensionProperties *extension_properties, FILE *out) {
2531 fprintf(out, "\t\t\t%s<details><summary>", indent);
2533 if (layer_name && (strlen(layer_name) > 0)) {
2535 fprintf(out, "%s Extensions", layer_name);
2536 } else if (human_readable_output) {
2537 printf("%s%s Extensions", indent, layer_name);
2541 fprintf(out, "Extensions");
2542 } else if (human_readable_output) {
2543 printf("%sExtensions", indent);
2547 fprintf(out, "\tcount = <div class='val'>%d</div></summary>", extension_count);
2548 if (extension_count > 0) {
2551 } else if (human_readable_output) {
2552 printf("\tcount = %d\n", extension_count);
2555 const bool is_device_type = strcmp(layer_name, "Device") == 0;
2556 if (is_device_type && json_output) {
2558 printf("\t\"ArrayOfVkExtensionProperties\": [");
2561 for (uint32_t i = 0; i < extension_count; ++i) {
2562 VkExtensionProperties const *ext_prop = &extension_properties[i];
2564 fprintf(out, "\t\t\t\t%s<details><summary>", indent);
2565 fprintf(out, "<div class='type'>%s</div>: extension revision <div class='val'>%d</div>", ext_prop->extensionName,
2566 ext_prop->specVersion);
2567 fprintf(out, "</summary></details>\n");
2568 } else if (human_readable_output) {
2569 printf("%s\t", indent);
2570 printf("%-36s: extension revision %2d\n", ext_prop->extensionName, ext_prop->specVersion);
2572 if (is_device_type && json_output) {
2578 printf("\t\t\t\"extensionName\": \"%s\",\n", ext_prop->extensionName);
2579 printf("\t\t\t\"specVersion\": %u\n", ext_prop->specVersion);
2584 if (extension_count > 0) {
2585 fprintf(out, "\t\t\t%s</details>\n", indent);
2587 fprintf(out, "</details>\n");
2590 if (is_device_type && json_output) {
2591 if (extension_count > 0) {
2601 static void AppGpuDumpQueueProps(const struct AppGpu *gpu, uint32_t id, FILE *out) {
2602 VkQueueFamilyProperties props;
2604 if (CheckExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, gpu->inst->inst_extensions,
2605 gpu->inst->inst_extensions_count)) {
2606 const VkQueueFamilyProperties *props2_const = &gpu->queue_props2[id].queueFamilyProperties;
2607 props = *props2_const;
2609 const VkQueueFamilyProperties *props_const = &gpu->queue_props[id];
2610 props = *props_const;
2614 fprintf(out, "\t\t\t\t\t<details><summary>VkQueueFamilyProperties[<div class='val'>%d</div>]</summary>\n", id);
2615 fprintf(out, "\t\t\t\t\t\t<details><summary>queueFlags = ");
2616 } else if (human_readable_output) {
2617 printf("VkQueueFamilyProperties[%d]:\n", id);
2618 printf("===========================\n");
2619 printf("\tqueueFlags = ");
2621 if (html_output || human_readable_output) {
2622 char *sep = ""; // separator character
2623 if (props.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
2624 fprintf(out, "GRAPHICS");
2627 if (props.queueFlags & VK_QUEUE_COMPUTE_BIT) {
2628 fprintf(out, "%sCOMPUTE", sep);
2631 if (props.queueFlags & VK_QUEUE_TRANSFER_BIT) {
2632 fprintf(out, "%sTRANSFER", sep);
2635 if (props.queueFlags & VK_QUEUE_SPARSE_BINDING_BIT) {
2636 fprintf(out, "%sSPARSE", sep);
2641 fprintf(out, "</summary></details>\n");
2642 fprintf(out, "\t\t\t\t\t\t<details><summary>queueCount = <div class='val'>%u</div></summary></details>\n", props.queueCount);
2643 fprintf(out, "\t\t\t\t\t\t<details><summary>timestampValidBits = <div class='val'>%u</div></summary></details>\n", props.timestampValidBits);
2644 fprintf(out, "\t\t\t\t\t\t<details><summary>minImageTransferGranularity = (<div class='val'>%d</div>, <div class='val'>%d</div>, <div class='val'>%d</div>)</summary></details>\n",
2645 props.minImageTransferGranularity.width, props.minImageTransferGranularity.height, props.minImageTransferGranularity.depth);
2646 fprintf(out, "\t\t\t\t\t</details>\n");
2647 } else if (human_readable_output) {
2649 printf("\tqueueCount = %u\n", props.queueCount);
2650 printf("\ttimestampValidBits = %u\n", props.timestampValidBits);
2651 printf("\tminImageTransferGranularity = (%d, %d, %d)\n", props.minImageTransferGranularity.width,
2652 props.minImageTransferGranularity.height, props.minImageTransferGranularity.depth);
2656 printf("\t\t\t\"minImageTransferGranularity\": {\n");
2657 printf("\t\t\t\t\"depth\": %u,\n", props.minImageTransferGranularity.depth);
2658 printf("\t\t\t\t\"height\": %u,\n", props.minImageTransferGranularity.height);
2659 printf("\t\t\t\t\"width\": %u\n", props.minImageTransferGranularity.width);
2660 printf("\t\t\t},\n");
2661 printf("\t\t\t\"queueCount\": %u,\n", props.queueCount);
2662 printf("\t\t\t\"queueFlags\": %u,\n", props.queueFlags);
2663 printf("\t\t\t\"timestampValidBits\": %u\n", props.timestampValidBits);
2671 // This prints a number of bytes in a human-readable format according to prefixes of the International System of Quantities (ISQ),
2672 // defined in ISO/IEC 80000. The prefixes used here are not SI prefixes, but rather the binary prefixes based on powers of 1024
2673 // (kibi-, mebi-, gibi- etc.).
2674 #define kBufferSize 32
2676 static char *HumanReadable(const size_t sz) {
2677 const char prefixes[] = "KMGTPEZY";
2678 char buf[kBufferSize];
2680 double result = (double)sz;
2681 while (result > 1024 && which < 7) {
2686 char unit[] = "\0i";
2688 unit[0] = prefixes[which];
2690 snprintf(buf, kBufferSize, "%.2f %sB", result, unit);
2691 return strndup(buf, kBufferSize);
2694 static void AppGpuDumpMemoryProps(const struct AppGpu *gpu, FILE *out) {
2695 VkPhysicalDeviceMemoryProperties props;
2697 if (CheckExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, gpu->inst->inst_extensions,
2698 gpu->inst->inst_extensions_count)) {
2699 const VkPhysicalDeviceMemoryProperties *props2_const = &gpu->memory_props2.memoryProperties;
2700 props = *props2_const;
2702 const VkPhysicalDeviceMemoryProperties *props_const = &gpu->memory_props;
2703 props = *props_const;
2707 fprintf(out, "\t\t\t\t\t<details><summary>VkPhysicalDeviceMemoryProperties</summary>\n");
2708 fprintf(out, "\t\t\t\t\t\t<details><summary>memoryHeapCount = <div class='val'>%u</div></summary>", props.memoryHeapCount);
2709 if (props.memoryHeapCount > 0) {
2712 } else if (human_readable_output) {
2713 printf("VkPhysicalDeviceMemoryProperties:\n");
2714 printf("=================================\n");
2715 printf("\tmemoryHeapCount = %u\n", props.memoryHeapCount);
2719 printf("\t\"VkPhysicalDeviceMemoryProperties\": {\n");
2720 printf("\t\t\"memoryHeaps\": [");
2722 for (uint32_t i = 0; i < props.memoryHeapCount; ++i) {
2723 const VkDeviceSize memSize = props.memoryHeaps[i].size;
2724 char *mem_size_human_readable = HumanReadable((const size_t)memSize);
2727 fprintf(out, "\t\t\t\t\t\t\t<details><summary>memoryHeaps[<div class='val'>%u</div>]</summary>\n", i);
2728 fprintf(out, "\t\t\t\t\t\t\t\t<details><summary>size = <div class='val'>" PRINTF_SIZE_T_SPECIFIER "</div> (<div class='val'>0x%" PRIxLEAST64 "</div>) (<div class='val'>%s</div>)</summary></details>\n",
2729 (size_t)memSize, memSize, mem_size_human_readable);
2730 } else if (human_readable_output) {
2731 printf("\tmemoryHeaps[%u] :\n", i);
2732 printf("\t\tsize = " PRINTF_SIZE_T_SPECIFIER " (0x%" PRIxLEAST64 ") (%s)\n", (size_t)memSize, memSize,
2733 mem_size_human_readable);
2735 free(mem_size_human_readable);
2737 const VkMemoryHeapFlags heap_flags = props.memoryHeaps[i].flags;
2739 fprintf(out, "\t\t\t\t\t\t\t\t<details open><summary>flags</summary>\n");
2740 fprintf(out, "\t\t\t\t\t\t\t\t\t<details><summary>");
2741 fprintf(out, (heap_flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) ? "<div class='type'>VK_MEMORY_HEAP_DEVICE_LOCAL_BIT</div>" : "None");
2742 fprintf(out, "</summary></details>\n");
2743 fprintf(out, "\t\t\t\t\t\t\t\t</details>\n");
2744 fprintf(out, "\t\t\t\t\t\t\t</details>\n");
2745 } else if (human_readable_output) {
2746 printf("\t\tflags:\n\t\t\t");
2747 printf((heap_flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) ? "VK_MEMORY_HEAP_DEVICE_LOCAL_BIT\n" : "None\n");
2754 printf("\t\t\t{\n");
2755 printf("\t\t\t\t\"flags\": %u,\n", heap_flags);
2756 printf("\t\t\t\t\"size\": " PRINTF_SIZE_T_SPECIFIER "\n", (size_t)memSize);
2761 if (props.memoryHeapCount > 0) {
2762 fprintf(out, "\t\t\t\t\t\t");
2764 fprintf(out, "</details>\n");
2767 if (props.memoryHeapCount > 0) {
2774 fprintf(out, "\t\t\t\t\t\t<details><summary>memoryTypeCount = <div class='val'>%u</div></summary>", props.memoryTypeCount);
2775 if (props.memoryTypeCount > 0) {
2778 } else if (human_readable_output) {
2779 printf("\tmemoryTypeCount = %u\n", props.memoryTypeCount);
2783 printf("\t\t\"memoryTypes\": [");
2785 for (uint32_t i = 0; i < props.memoryTypeCount; ++i) {
2787 fprintf(out, "\t\t\t\t\t\t\t<details><summary>memoryTypes[<div class='val'>%u</div>]</summary>\n", i);
2788 fprintf(out, "\t\t\t\t\t\t\t\t<details><summary>heapIndex = <div class='val'>%u</div></summary></details>\n", props.memoryTypes[i].heapIndex);
2789 fprintf(out, "\t\t\t\t\t\t\t\t<details open><summary>propertyFlags = <div class='val'>0x%" PRIxLEAST32 "</div></summary>", props.memoryTypes[i].propertyFlags);
2790 if (props.memoryTypes[i].propertyFlags == 0) {
2791 fprintf(out, "</details>\n");
2795 } else if (human_readable_output) {
2796 printf("\tmemoryTypes[%u] :\n", i);
2797 printf("\t\theapIndex = %u\n", props.memoryTypes[i].heapIndex);
2798 printf("\t\tpropertyFlags = 0x%" PRIxLEAST32 ":\n", props.memoryTypes[i].propertyFlags);
2805 printf("\t\t\t{\n");
2806 printf("\t\t\t\t\"heapIndex\": %u,\n", props.memoryTypes[i].heapIndex);
2807 printf("\t\t\t\t\"propertyFlags\": %u\n", props.memoryTypes[i].propertyFlags);
2811 // Print each named flag to html or std output if it is set
2812 const VkFlags flags = props.memoryTypes[i].propertyFlags;
2814 if (flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) fprintf(out, "\t\t\t\t\t\t\t\t\t<details><summary><div class='type'>VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT</div></summary></details>\n");
2815 if (flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) fprintf(out, "\t\t\t\t\t\t\t\t\t<details><summary><div class='type'>VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT</div></summary></details>\n");
2816 if (flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) fprintf(out, "\t\t\t\t\t\t\t\t\t<details><summary><div class='type'>VK_MEMORY_PROPERTY_HOST_COHERENT_BIT</div></summary></details>\n");
2817 if (flags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) fprintf(out, "\t\t\t\t\t\t\t\t\t<details><summary><div class='type'>VK_MEMORY_PROPERTY_HOST_CACHED_BIT</div></summary></details>\n");
2818 if (flags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) fprintf(out, "\t\t\t\t\t\t\t\t\t<details><summary><div class='type'>VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT</div></summary></details>\n");
2819 if (props.memoryTypes[i].propertyFlags > 0) fprintf(out, "\t\t\t\t\t\t\t\t</details>\n");
2820 fprintf(out, "\t\t\t\t\t\t\t</details>\n");
2821 } else if (human_readable_output) {
2822 if (flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) printf("\t\t\tVK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT\n");
2823 if (flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) printf("\t\t\tVK_MEMORY_PROPERTY_HOST_VISIBLE_BIT\n");
2824 if (flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) printf("\t\t\tVK_MEMORY_PROPERTY_HOST_COHERENT_BIT\n");
2825 if (flags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) printf("\t\t\tVK_MEMORY_PROPERTY_HOST_CACHED_BIT\n");
2826 if (flags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) printf("\t\t\tVK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT\n");
2830 if (props.memoryTypeCount > 0) {
2831 fprintf(out, "\t\t\t\t\t\t");
2833 fprintf(out, "</details>\n");
2834 fprintf(out, "\t\t\t\t\t</details>\n");
2837 if (props.memoryTypeCount > 0) {
2849 static void AppGpuDump(const struct AppGpu *gpu, FILE *out) {
2851 fprintf(out, "\t\t\t<details><summary>Device Properties and Extensions</summary>\n");
2852 fprintf(out, "\t\t\t\t<details><summary>GPU%u</summary>\n", gpu->id);
2853 } else if (human_readable_output) {
2854 printf("\nDevice Properties and Extensions :\n");
2855 printf("==================================\n");
2856 printf("GPU%u\n", gpu->id);
2859 AppGpuDumpProps(gpu, out);
2861 AppDumpExtensions("\t\t", "Device", gpu->device_extension_count, gpu->device_extensions, out);
2862 } else if (human_readable_output) {
2864 AppDumpExtensions("", "Device", gpu->device_extension_count, gpu->device_extensions, out);
2870 printf("\t\"ArrayOfVkQueueFamilyProperties\": [");
2872 for (uint32_t i = 0; i < gpu->queue_count; ++i) {
2879 AppGpuDumpQueueProps(gpu, i, out);
2880 if (human_readable_output) {
2885 if (gpu->queue_count > 0) {
2891 AppGpuDumpMemoryProps(gpu, out);
2892 if (human_readable_output) {
2896 AppGpuDumpFeatures(gpu, out);
2897 if (human_readable_output) {
2901 AppDevDump(gpu, out);
2903 fprintf(out, "\t\t\t\t</details>\n");
2904 fprintf(out, "\t\t\t</details>\n");
2908 static void AppGroupDump(const VkPhysicalDeviceGroupProperties *group, const uint32_t id, const struct AppInstance *inst,
2911 fprintf(out, "\t\t\t\t<details><summary>Device Group Properties (Group %u)</summary>\n", id);
2912 fprintf(out, "\t\t\t\t\t<details><summary>physicalDeviceCount = <div class='val'>%u</div></summary>\n",
2913 group->physicalDeviceCount);
2914 } else if (human_readable_output) {
2915 printf("\tDevice Group Properties (Group %u) :\n", id);
2916 printf("\t\tphysicalDeviceCount = %u\n", group->physicalDeviceCount);
2919 // Keep a record of all physical device properties to give the user clearer information as output.
2920 VkPhysicalDeviceProperties *props = malloc(sizeof(props[0]) * group->physicalDeviceCount);
2922 ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY);
2924 for (uint32_t i = 0; i < group->physicalDeviceCount; ++i) {
2925 vkGetPhysicalDeviceProperties(group->physicalDevices[i], &props[i]);
2928 // Output information to the user.
2929 for (uint32_t i = 0; i < group->physicalDeviceCount; ++i) {
2931 fprintf(out, "\t\t\t\t\t\t<details><summary>%s (ID: <div class='val'>%d</div>)</summary></details>\n",
2932 props[i].deviceName, i);
2933 } else if (human_readable_output) {
2934 printf("\n\t\t\t%s (ID: %d)\n", props[i].deviceName, i);
2939 fprintf(out, "\t\t\t\t\t</details>\n");
2943 fprintf(out, "\t\t\t\t\t<details><summary>subsetAllocation = <div class='val'>%u</div></summary></details>\n",
2944 group->subsetAllocation);
2945 } else if (human_readable_output) {
2946 printf("\n\t\tsubsetAllocation = %u\n", group->subsetAllocation);
2950 fprintf(out, "\t\t\t\t</details>\n");
2953 // Build create info for logical device made from all physical devices in this group.
2954 char *extensions_list = VK_KHR_DEVICE_GROUP_EXTENSION_NAME;
2956 VkDeviceGroupDeviceCreateInfoKHR dg_ci = {.sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR,
2958 .physicalDeviceCount = group->physicalDeviceCount,
2959 .pPhysicalDevices = group->physicalDevices};
2961 VkDeviceQueueCreateInfo q_ci = {
2962 .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, .pNext = NULL, .queueFamilyIndex = 0, .queueCount = 1};
2964 VkDeviceCreateInfo device_ci = {.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
2966 .queueCreateInfoCount = 1,
2967 .pQueueCreateInfos = &q_ci,
2968 .enabledExtensionCount = 1,
2969 .ppEnabledExtensionNames = &extensions_list};
2971 VkDevice logical_device = VK_NULL_HANDLE;
2973 VkResult err = vkCreateDevice(group->physicalDevices[0], &device_ci, NULL, &logical_device);
2977 fprintf(out, "\t\t\t\t<details><summary>Device Group Present Capabilities (Group %d)</summary>\n", id);
2978 } else if (human_readable_output) {
2979 printf("\n\tDevice Group Present Capabilities (Group %d) :\n", id);
2982 VkDeviceGroupPresentCapabilitiesKHR group_capabilities = {.sType = VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR,
2985 // If the KHR_device_group extension is present, write the capabilities of the logical device into a struct for later output
2987 PFN_vkGetDeviceGroupPresentCapabilitiesKHR vkGetDeviceGroupPresentCapabilitiesKHR =
2988 (PFN_vkGetDeviceGroupPresentCapabilitiesKHR)vkGetInstanceProcAddr(inst->instance,
2989 "vkGetDeviceGroupPresentCapabilitiesKHR");
2990 vkGetDeviceGroupPresentCapabilitiesKHR(logical_device, &group_capabilities);
2992 for (uint32_t i = 0; i < group->physicalDeviceCount; i++) {
2994 fprintf(out, "\t\t\t\t\t<details><summary>%s (ID: <div class='val'>%d</div>)</summary></details>\n",
2995 props[i].deviceName, i);
2996 fprintf(out, "\t\t\t\t\t<details><summary>Can present images from the following devices:</summary>\n");
2997 if (group_capabilities.presentMask[i] != 0) {
2998 for (uint32_t j = 0; j < group->physicalDeviceCount; ++j) {
2999 uint32_t mask = 1 << j;
3000 if (group_capabilities.presentMask[i] & mask) {
3001 fprintf(out, "\t\t\t\t\t\t<details><summary>%s (ID: <div class='val'>%d</div>)</summary></details>\n",
3002 props[j].deviceName, j);
3006 fprintf(out, "\t\t\t\t\t\t<details><summary>None</summary></details>\n");
3008 fprintf(out, "\t\t\t\t\t</details>\n");
3009 } else if (human_readable_output) {
3010 printf("\n\t\t%s (ID: %d)\n", props[i].deviceName, i);
3011 printf("\t\tCan present images from the following devices:\n");
3012 if (group_capabilities.presentMask[i] != 0) {
3013 for (uint32_t j = 0; j < group->physicalDeviceCount; ++j) {
3014 uint32_t mask = 1 << j;
3015 if (group_capabilities.presentMask[i] & mask) {
3016 printf("\t\t\t%s (ID: %d)\n", props[j].deviceName, j);
3020 printf("\t\t\tNone\n");
3027 fprintf(out, "\t\t\t\t\t<details><summary>Present modes</summary>\n");
3028 if (group_capabilities.modes & VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR)
3029 fprintf(out, "\t\t\t\t\t\t<details><summary>VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR</summary></details>\n");
3030 if (group_capabilities.modes & VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR)
3031 fprintf(out, "\t\t\t\t\t\t<details><summary>VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR</summary></details>\n");
3032 if (group_capabilities.modes & VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR)
3033 fprintf(out, "\t\t\t\t\t\t<details><summary>VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR</summary></details>\n");
3034 if (group_capabilities.modes & VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR)
3037 "\t\t\t\t\t\t<details><summary>VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR</summary></details>\n");
3038 fprintf(out, "\t\t\t\t\t</details>\n");
3039 } else if (human_readable_output) {
3040 printf("\t\tPresent modes:\n");
3041 if (group_capabilities.modes & VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR)
3042 printf("\t\t\tVK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR\n");
3043 if (group_capabilities.modes & VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR)
3044 printf("\t\t\tVK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR\n");
3045 if (group_capabilities.modes & VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR)
3046 printf("\t\t\tVK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR\n");
3047 if (group_capabilities.modes & VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR)
3048 printf("\t\t\tVK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR\n");
3052 fprintf(out, "\t\t\t\t</details>\n");
3056 // Clean up after ourselves.
3058 vkDestroyDevice(logical_device, NULL);
3062 // Enlarges the console window to have a large scrollback size.
3063 static void ConsoleEnlarge() {
3064 const HANDLE console_handle = GetStdHandle(STD_OUTPUT_HANDLE);
3066 // make the console window bigger
3067 CONSOLE_SCREEN_BUFFER_INFO csbi;
3069 if (GetConsoleScreenBufferInfo(console_handle, &csbi)) {
3070 buffer_size.X = csbi.dwSize.X + 30;
3071 buffer_size.Y = 20000;
3072 SetConsoleScreenBufferSize(console_handle, buffer_size);
3077 r.Right = csbi.dwSize.X - 1 + 30;
3079 SetConsoleWindowInfo(console_handle, true, &r);
3081 // change the console window title
3082 SetConsoleTitle(TEXT(APP_SHORT_NAME));
3086 int main(int argc, char **argv) {
3089 struct AppInstance inst;
3093 if (ConsoleIsExclusive()) ConsoleEnlarge();
3095 PFN_vkEnumerateInstanceVersion enumerate_instance_version =
3096 (PFN_vkEnumerateInstanceVersion)vkGetInstanceProcAddr(NULL, "vkEnumerateInstanceVersion");
3098 uint32_t instance_version = VK_API_VERSION_1_0;
3100 if (enumerate_instance_version != NULL) {
3101 enumerate_instance_version(&instance_version);
3104 const uint32_t vulkan_major = VK_VERSION_MAJOR(instance_version);
3105 const uint32_t vulkan_minor = VK_VERSION_MINOR(instance_version);
3106 const uint32_t vulkan_patch = VK_VERSION_PATCH(VK_HEADER_VERSION);
3108 for (int i = 1; i < argc; i++) {
3109 if (strcmp(argv[i], "--html") == 0) {
3110 out = fopen("vulkaninfo.html", "w");
3111 human_readable_output = false;
3115 CheckForJsonOption(argv[i]);
3119 PrintHtmlHeader(out);
3120 fprintf(out, "\t\t\t<details><summary>");
3121 } else if (human_readable_output) {
3122 printf("===========\n");
3123 printf("VULKAN INFO\n");
3124 printf("===========\n\n");
3126 if (html_output || human_readable_output) {
3127 fprintf(out, "Vulkan Instance Version: ");
3130 fprintf(out, "<div class='val'>%d.%d.%d</div></summary></details>\n", vulkan_major, vulkan_minor, vulkan_patch);
3131 fprintf(out, "\t\t\t<br />\n");
3132 } else if (human_readable_output) {
3133 printf("%d.%d.%d\n\n", vulkan_major, vulkan_minor, vulkan_patch);
3136 AppCreateInstance(&inst);
3138 err = vkEnumeratePhysicalDevices(inst.instance, &gpu_count, NULL);
3143 VkPhysicalDevice *objs = malloc(sizeof(objs[0]) * gpu_count);
3145 ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY);
3148 err = vkEnumeratePhysicalDevices(inst.instance, &gpu_count, objs);
3153 struct AppGpu *gpus = malloc(sizeof(gpus[0]) * gpu_count);
3155 ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY);
3158 for (uint32_t i = 0; i < gpu_count; ++i) {
3159 AppGpuInit(&gpus[i], &inst, i, objs[i]);
3160 if (human_readable_output) {
3165 // If json output, confirm the desired gpu exists
3167 if (selected_gpu >= gpu_count) {
3170 PrintJsonHeader(vulkan_major, vulkan_minor, vulkan_patch);
3173 if (human_readable_output) {
3174 printf("Instance Extensions:\n");
3175 printf("====================\n");
3177 AppDumpExtensions("", "Instance", inst.global_extension_count, inst.global_extensions, out);
3179 //---Layer-Device-Extensions---
3181 fprintf(out, "\t\t\t<details><summary>Layers: count = <div class='val'>%d</div></summary>", inst.global_layer_count);
3182 if (inst.global_layer_count > 0) {
3185 } else if (human_readable_output) {
3186 printf("Layers: count = %d\n", inst.global_layer_count);
3187 printf("=======\n");
3189 if (json_output && (inst.global_layer_count > 0)) {
3191 printf("\t\"ArrayOfVkLayerProperties\": [");
3193 for (uint32_t i = 0; i < inst.global_layer_count; ++i) {
3194 uint32_t layer_major, layer_minor, layer_patch;
3195 char spec_version[64], layer_version[64];
3196 VkLayerProperties const *layer_prop = &inst.global_layers[i].layer_properties;
3198 ExtractVersion(layer_prop->specVersion, &layer_major, &layer_minor, &layer_patch);
3199 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d", layer_major, layer_minor, layer_patch);
3200 snprintf(layer_version, sizeof(layer_version), "%d", layer_prop->implementationVersion);
3203 fprintf(out, "\t\t\t\t<details><summary>");
3204 fprintf(out, "<div class='type'>%s</div> (%s) Vulkan version <div class='val'>%s</div>, ", layer_prop->layerName,
3205 (char *)layer_prop->description, spec_version);
3206 fprintf(out, "layer version <div class='val'>%s</div></summary>\n", layer_version);
3207 AppDumpExtensions("\t\t", "Layer", inst.global_layers[i].extension_count, inst.global_layers[i].extension_properties,
3209 } else if (human_readable_output) {
3210 printf("%s (%s) Vulkan version %s, layer version %s\n", layer_prop->layerName, (char *)layer_prop->description,
3211 spec_version, layer_version);
3212 AppDumpExtensions("\t", "Layer", inst.global_layers[i].extension_count, inst.global_layers[i].extension_properties,
3221 printf("\t\t\t\"layerName\": \"%s\",\n", layer_prop->layerName);
3222 printf("\t\t\t\"specVersion\": %u,\n", layer_prop->specVersion);
3223 printf("\t\t\t\"implementationVersion\": %u,\n", layer_prop->implementationVersion);
3224 printf("\t\t\t\"description\": \"%s\"\n", layer_prop->description);
3229 fprintf(out, "\t\t\t\t\t<details><summary>Devices count = <div class='val'>%d</div></summary>\n", gpu_count);
3230 } else if (human_readable_output) {
3231 printf("\tDevices \tcount = %d\n", gpu_count);
3234 char *layer_name = inst.global_layers[i].layer_properties.layerName;
3236 for (uint32_t j = 0; j < gpu_count; ++j) {
3238 fprintf(out, "\t\t\t\t\t\t<details><summary>");
3239 fprintf(out, "GPU id: <div class='val'>%u</div> (%s)</summary></details>\n", j, gpus[j].props.deviceName);
3240 } else if (human_readable_output) {
3241 printf("\t\tGPU id : %u (%s)\n", j, gpus[j].props.deviceName);
3244 VkExtensionProperties *props;
3245 AppGetPhysicalDeviceLayerExtensions(&gpus[j], layer_name, &count, &props);
3247 AppDumpExtensions("\t\t\t", "Layer-Device", count, props, out);
3248 fprintf(out, "\t\t\t\t\t</details>\n");
3249 } else if (human_readable_output) {
3250 AppDumpExtensions("\t\t", "Layer-Device", count, props, out);
3256 fprintf(out, "\t\t\t\t</details>\n");
3257 } else if (human_readable_output) {
3263 fprintf(out, "\t\t\t</details>\n");
3265 if (json_output && (inst.global_layer_count > 0)) {
3271 //-----------------------------
3274 fprintf(out, "\t\t\t<details><summary>Presentable Surfaces</summary>");
3275 if (gpu_count > 0) {
3278 fprintf(out, "</details>\n");
3280 } else if (human_readable_output) {
3281 printf("Presentable Surfaces:\n");
3282 printf("=====================\n");
3286 int format_count = 0;
3287 int present_mode_count = 0;
3289 #if defined(VK_USE_PLATFORM_XCB_KHR) || defined(VK_USE_PLATFORM_XLIB_KHR)
3290 bool has_display = true;
3291 const char *display_var = getenv("DISPLAY");
3292 if (display_var == NULL || strlen(display_var) == 0) {
3293 fprintf(stderr, "'DISPLAY' environment variable not set... skipping surface info\n");
3295 has_display = false;
3300 #ifdef VK_USE_PLATFORM_WIN32_KHR
3301 if (CheckExtensionEnabled(VK_KHR_WIN32_SURFACE_EXTENSION_NAME, inst.inst_extensions, inst.inst_extensions_count)) {
3302 AppCreateWin32Window(&inst);
3303 for (uint32_t i = 0; i < gpu_count; ++i) {
3304 AppCreateWin32Surface(&inst);
3306 fprintf(out, "\t\t\t\t<details><summary>GPU id : <div class='val'>%u</div> (%s)</summary></details>\n", i,
3307 gpus[i].props.deviceName);
3308 fprintf(out, "\t\t\t\t<details><summary>Surface type : <div class='type'>%s</div></summary></details>\n",
3309 VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
3310 } else if (human_readable_output) {
3311 printf("GPU id : %u (%s)\n", i, gpus[i].props.deviceName);
3312 printf("Surface type : %s\n", VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
3314 format_count += AppDumpSurfaceFormats(&inst, &gpus[i], out);
3315 present_mode_count += AppDumpSurfacePresentModes(&inst, &gpus[i], out);
3316 AppDumpSurfaceCapabilities(&inst, &gpus[i], out);
3317 AppDestroySurface(&inst);
3319 AppDestroyWin32Window(&inst);
3322 #elif VK_USE_PLATFORM_XCB_KHR
3323 if (has_display && CheckExtensionEnabled(VK_KHR_XCB_SURFACE_EXTENSION_NAME, inst.inst_extensions, inst.inst_extensions_count)) {
3324 AppCreateXcbWindow(&inst);
3325 for (uint32_t i = 0; i < gpu_count; ++i) {
3326 AppCreateXcbSurface(&inst);
3328 fprintf(out, "\t\t\t\t<details><summary>GPU id : <div class='val'>%u</div> (%s)</summary></details>\n", i,
3329 gpus[i].props.deviceName);
3330 fprintf(out, "\t\t\t\t<details><summary>Surface type : <div class='type'>%s</div></summary></details>\n",
3331 VK_KHR_XCB_SURFACE_EXTENSION_NAME);
3332 } else if (human_readable_output) {
3333 printf("GPU id : %u (%s)\n", i, gpus[i].props.deviceName);
3334 printf("Surface type : %s\n", VK_KHR_XCB_SURFACE_EXTENSION_NAME);
3336 format_count += AppDumpSurfaceFormats(&inst, &gpus[i], out);
3337 present_mode_count += AppDumpSurfacePresentModes(&inst, &gpus[i], out);
3338 AppDumpSurfaceCapabilities(&inst, &gpus[i], out);
3339 AppDestroySurface(&inst);
3341 AppDestroyXcbWindow(&inst);
3344 #elif VK_USE_PLATFORM_XLIB_KHR
3346 CheckExtensionEnabled(VK_KHR_XLIB_SURFACE_EXTENSION_NAME, inst.inst_extensions, inst.inst_extensions_count)) {
3347 AppCreateXlibWindow(&inst);
3348 for (uint32_t i = 0; i < gpu_count; ++i) {
3349 AppCreateXlibSurface(&inst);
3351 fprintf(out, "\t\t\t\t<details><summary>GPU id : <div class='val'>%u</div> (%s)</summary></details>\n", i,
3352 gpus[i].props.deviceName);
3353 fprintf(out, "\t\t\t\t<details><summary>Surface type : <div class='type'>%s</div></summary></details>\n",
3354 VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
3355 } else if (human_readable_output) {
3356 printf("GPU id : %u (%s)\n", i, gpus[i].props.deviceName);
3357 printf("Surface type : %s\n", VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
3359 format_count += AppDumpSurfaceFormats(&inst, &gpus[i], out);
3360 present_mode_count += AppDumpSurfacePresentModes(&inst, &gpus[i], out);
3361 AppDumpSurfaceCapabilities(&inst, &gpus[i], out);
3362 AppDestroySurface(&inst);
3364 AppDestroyXlibWindow(&inst);
3368 // TODO: Android / Wayland / MIR
3369 if (!format_count && !present_mode_count) {
3371 fprintf(out, "\t\t\t\t<details><summary>None found</summary></details>\n");
3372 } else if (human_readable_output) {
3373 printf("None found\n");
3378 fprintf(out, "\t\t\t</details>\n");
3379 } else if (human_readable_output) {
3384 if (CheckExtensionEnabled(VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME, inst.inst_extensions, inst.inst_extensions_count)) {
3385 PFN_vkEnumeratePhysicalDeviceGroupsKHR vkEnumeratePhysicalDeviceGroupsKHR =
3386 (PFN_vkEnumeratePhysicalDeviceGroupsKHR)vkGetInstanceProcAddr(inst.instance, "vkEnumeratePhysicalDeviceGroupsKHR");
3388 uint32_t group_count;
3389 err = vkEnumeratePhysicalDeviceGroupsKHR(inst.instance, &group_count, NULL);
3394 VkPhysicalDeviceGroupProperties *groups = malloc(sizeof(groups[0]) * group_count);
3396 ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY);
3399 err = vkEnumeratePhysicalDeviceGroupsKHR(inst.instance, &group_count, groups);
3405 fprintf(out, "\t\t\t<details><summary>Groups</summary>\n");
3406 } else if (human_readable_output) {
3407 printf("\nGroups :\n");
3408 printf("========\n");
3411 for (uint32_t i = 0; i < group_count; ++i) {
3412 AppGroupDump(&groups[i], i, &inst, out);
3413 if (human_readable_output) {
3419 fprintf(out, "\t\t\t</details>\n");
3425 for (uint32_t i = 0; i < gpu_count; ++i) {
3426 if (json_output && selected_gpu != i) {
3427 // Toggle json_output to allow html output without json output
3428 json_output = false;
3429 AppGpuDump(&gpus[i], out);
3432 AppGpuDump(&gpus[i], out);
3434 if (human_readable_output) {
3439 for (uint32_t i = 0; i < gpu_count; ++i) {
3440 AppGpuDestroy(&gpus[i]);
3445 AppDestroyInstance(&inst);
3448 PrintHtmlFooter(out);
3459 if (ConsoleIsExclusive() && human_readable_output) {