1 /* 2 * Copyright (c) 2015-2016 The Khronos Group Inc. 3 * Copyright (c) 2015-2016 Valve Corporation 4 * Copyright (c) 2015-2016 LunarG, Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and/or associated documentation files (the "Materials"), to 8 * deal in the Materials without restriction, including without limitation the 9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 * sell copies of the Materials, and to permit persons to whom the Materials are 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice(s) and this permission notice shall be included in 14 * all copies or substantial portions of the Materials. 15 * 16 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 * 20 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 22 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE 23 * USE OR OTHER DEALINGS IN THE MATERIALS. 24 * 25 * Author: Courtney Goeltzenleuchter <courtney (at) LunarG.com> 26 * Author: David Pinedo <david (at) lunarg.com> 27 * Author: Mark Lobodzinski <mark (at) lunarg.com> 28 */ 29 #include <stdlib.h> 30 #include <stdio.h> 31 #include <stdbool.h> 32 #include <string.h> 33 #include <assert.h> 34 #include <inttypes.h> 35 36 #ifdef _WIN32 37 #include <fcntl.h> 38 #include <io.h> 39 #endif // _WIN32 40 41 #include <vulkan/vulkan.h> 42 43 #define ERR(err) \ 44 printf("%s:%d: failed with %s\n", __FILE__, __LINE__, \ 45 vk_result_string(err)); 46 47 #ifdef _WIN32 48 49 #define snprintf _snprintf 50 51 // Returns nonzero if the console is used only for this process. Will return 52 // zero if another process (such as cmd.exe) is also attached. 53 static int ConsoleIsExclusive(void) { 54 DWORD pids[2]; 55 DWORD num_pids = GetConsoleProcessList(pids, ARRAYSIZE(pids)); 56 return num_pids <= 1; 57 } 58 59 #define WAIT_FOR_CONSOLE_DESTROY \ 60 do { \ 61 if (ConsoleIsExclusive()) \ 62 Sleep(INFINITE); \ 63 } while (0) 64 #else 65 #define WAIT_FOR_CONSOLE_DESTROY 66 #endif 67 68 #define ERR_EXIT(err) \ 69 do { \ 70 ERR(err); \ 71 fflush(stdout); \ 72 WAIT_FOR_CONSOLE_DESTROY; \ 73 exit(-1); \ 74 } while (0) 75 76 #if defined(NDEBUG) && defined(__GNUC__) 77 #define U_ASSERT_ONLY __attribute__((unused)) 78 #else 79 #define U_ASSERT_ONLY 80 #endif 81 82 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 83 84 #define MAX_GPUS 8 85 86 #define MAX_QUEUE_TYPES 5 87 #define APP_SHORT_NAME "vulkaninfo" 88 89 struct app_gpu; 90 91 struct app_dev { 92 struct app_gpu *gpu; /* point back to the GPU */ 93 94 VkDevice obj; 95 96 VkFormatProperties format_props[VK_FORMAT_RANGE_SIZE]; 97 }; 98 99 struct layer_extension_list { 100 VkLayerProperties layer_properties; 101 uint32_t extension_count; 102 VkExtensionProperties *extension_properties; 103 }; 104 105 struct app_instance { 106 VkInstance instance; 107 uint32_t global_layer_count; 108 struct layer_extension_list *global_layers; 109 uint32_t global_extension_count; 110 VkExtensionProperties *global_extensions; 111 }; 112 113 struct app_gpu { 114 uint32_t id; 115 VkPhysicalDevice obj; 116 117 VkPhysicalDeviceProperties props; 118 119 uint32_t queue_count; 120 VkQueueFamilyProperties *queue_props; 121 VkDeviceQueueCreateInfo *queue_reqs; 122 123 VkPhysicalDeviceMemoryProperties memory_props; 124 VkPhysicalDeviceFeatures features; 125 VkPhysicalDevice limits; 126 127 uint32_t device_layer_count; 128 struct layer_extension_list *device_layers; 129 130 uint32_t device_extension_count; 131 VkExtensionProperties *device_extensions; 132 133 struct app_dev dev; 134 }; 135 136 static VKAPI_ATTR VkBool32 VKAPI_CALL 137 dbg_callback(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType, 138 uint64_t srcObject, size_t location, int32_t msgCode, 139 const char *pLayerPrefix, const char *pMsg, void *pUserData) { 140 char *message = (char *)malloc(strlen(pMsg) + 100); 141 142 assert(message); 143 144 if (msgFlags & VK_DEBUG_REPORT_ERROR_BIT_EXT) { 145 sprintf(message, "ERROR: [%s] Code %d : %s", pLayerPrefix, msgCode, 146 pMsg); 147 } else if (msgFlags & VK_DEBUG_REPORT_WARNING_BIT_EXT) { 148 sprintf(message, "WARNING: [%s] Code %d : %s", pLayerPrefix, msgCode, 149 pMsg); 150 } else if (msgFlags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) { 151 sprintf(message, "INFO: [%s] Code %d : %s", pLayerPrefix, msgCode, 152 pMsg); 153 } else if (msgFlags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) { 154 sprintf(message, "DEBUG: [%s] Code %d : %s", pLayerPrefix, msgCode, 155 pMsg); 156 } 157 158 printf("%s\n", message); 159 fflush(stdout); 160 free(message); 161 162 /* 163 * false indicates that layer should not bail-out of an 164 * API call that had validation failures. This may mean that the 165 * app dies inside the driver due to invalid parameter(s). 166 * That's what would happen without validation layers, so we'll 167 * keep that behavior here. 168 */ 169 return false; 170 } 171 172 static const char *vk_result_string(VkResult err) { 173 switch (err) { 174 #define STR(r) \ 175 case r: \ 176 return #r 177 STR(VK_SUCCESS); 178 STR(VK_NOT_READY); 179 STR(VK_TIMEOUT); 180 STR(VK_EVENT_SET); 181 STR(VK_EVENT_RESET); 182 STR(VK_ERROR_INITIALIZATION_FAILED); 183 STR(VK_ERROR_OUT_OF_HOST_MEMORY); 184 STR(VK_ERROR_OUT_OF_DEVICE_MEMORY); 185 STR(VK_ERROR_DEVICE_LOST); 186 STR(VK_ERROR_LAYER_NOT_PRESENT); 187 STR(VK_ERROR_EXTENSION_NOT_PRESENT); 188 STR(VK_ERROR_MEMORY_MAP_FAILED); 189 STR(VK_ERROR_INCOMPATIBLE_DRIVER); 190 #undef STR 191 default: 192 return "UNKNOWN_RESULT"; 193 } 194 } 195 196 static const char *vk_physical_device_type_string(VkPhysicalDeviceType type) { 197 switch (type) { 198 #define STR(r) \ 199 case VK_PHYSICAL_DEVICE_TYPE_##r: \ 200 return #r 201 STR(OTHER); 202 STR(INTEGRATED_GPU); 203 STR(DISCRETE_GPU); 204 STR(VIRTUAL_GPU); 205 #undef STR 206 default: 207 return "UNKNOWN_DEVICE"; 208 } 209 } 210 211 static const char *vk_format_string(VkFormat fmt) { 212 switch (fmt) { 213 #define STR(r) \ 214 case VK_FORMAT_##r: \ 215 return #r 216 STR(UNDEFINED); 217 STR(R4G4_UNORM_PACK8); 218 STR(R4G4B4A4_UNORM_PACK16); 219 STR(B4G4R4A4_UNORM_PACK16); 220 STR(R5G6B5_UNORM_PACK16); 221 STR(B5G6R5_UNORM_PACK16); 222 STR(R5G5B5A1_UNORM_PACK16); 223 STR(B5G5R5A1_UNORM_PACK16); 224 STR(A1R5G5B5_UNORM_PACK16); 225 STR(R8_UNORM); 226 STR(R8_SNORM); 227 STR(R8_USCALED); 228 STR(R8_SSCALED); 229 STR(R8_UINT); 230 STR(R8_SINT); 231 STR(R8_SRGB); 232 STR(R8G8_UNORM); 233 STR(R8G8_SNORM); 234 STR(R8G8_USCALED); 235 STR(R8G8_SSCALED); 236 STR(R8G8_UINT); 237 STR(R8G8_SINT); 238 STR(R8G8_SRGB); 239 STR(R8G8B8_UNORM); 240 STR(R8G8B8_SNORM); 241 STR(R8G8B8_USCALED); 242 STR(R8G8B8_SSCALED); 243 STR(R8G8B8_UINT); 244 STR(R8G8B8_SINT); 245 STR(R8G8B8_SRGB); 246 STR(B8G8R8_UNORM); 247 STR(B8G8R8_SNORM); 248 STR(B8G8R8_USCALED); 249 STR(B8G8R8_SSCALED); 250 STR(B8G8R8_UINT); 251 STR(B8G8R8_SINT); 252 STR(B8G8R8_SRGB); 253 STR(R8G8B8A8_UNORM); 254 STR(R8G8B8A8_SNORM); 255 STR(R8G8B8A8_USCALED); 256 STR(R8G8B8A8_SSCALED); 257 STR(R8G8B8A8_UINT); 258 STR(R8G8B8A8_SINT); 259 STR(R8G8B8A8_SRGB); 260 STR(B8G8R8A8_UNORM); 261 STR(B8G8R8A8_SNORM); 262 STR(B8G8R8A8_USCALED); 263 STR(B8G8R8A8_SSCALED); 264 STR(B8G8R8A8_UINT); 265 STR(B8G8R8A8_SINT); 266 STR(B8G8R8A8_SRGB); 267 STR(A8B8G8R8_UNORM_PACK32); 268 STR(A8B8G8R8_SNORM_PACK32); 269 STR(A8B8G8R8_USCALED_PACK32); 270 STR(A8B8G8R8_SSCALED_PACK32); 271 STR(A8B8G8R8_UINT_PACK32); 272 STR(A8B8G8R8_SINT_PACK32); 273 STR(A8B8G8R8_SRGB_PACK32); 274 STR(A2R10G10B10_UNORM_PACK32); 275 STR(A2R10G10B10_SNORM_PACK32); 276 STR(A2R10G10B10_USCALED_PACK32); 277 STR(A2R10G10B10_SSCALED_PACK32); 278 STR(A2R10G10B10_UINT_PACK32); 279 STR(A2R10G10B10_SINT_PACK32); 280 STR(A2B10G10R10_UNORM_PACK32); 281 STR(A2B10G10R10_SNORM_PACK32); 282 STR(A2B10G10R10_USCALED_PACK32); 283 STR(A2B10G10R10_SSCALED_PACK32); 284 STR(A2B10G10R10_UINT_PACK32); 285 STR(A2B10G10R10_SINT_PACK32); 286 STR(R16_UNORM); 287 STR(R16_SNORM); 288 STR(R16_USCALED); 289 STR(R16_SSCALED); 290 STR(R16_UINT); 291 STR(R16_SINT); 292 STR(R16_SFLOAT); 293 STR(R16G16_UNORM); 294 STR(R16G16_SNORM); 295 STR(R16G16_USCALED); 296 STR(R16G16_SSCALED); 297 STR(R16G16_UINT); 298 STR(R16G16_SINT); 299 STR(R16G16_SFLOAT); 300 STR(R16G16B16_UNORM); 301 STR(R16G16B16_SNORM); 302 STR(R16G16B16_USCALED); 303 STR(R16G16B16_SSCALED); 304 STR(R16G16B16_UINT); 305 STR(R16G16B16_SINT); 306 STR(R16G16B16_SFLOAT); 307 STR(R16G16B16A16_UNORM); 308 STR(R16G16B16A16_SNORM); 309 STR(R16G16B16A16_USCALED); 310 STR(R16G16B16A16_SSCALED); 311 STR(R16G16B16A16_UINT); 312 STR(R16G16B16A16_SINT); 313 STR(R16G16B16A16_SFLOAT); 314 STR(R32_UINT); 315 STR(R32_SINT); 316 STR(R32_SFLOAT); 317 STR(R32G32_UINT); 318 STR(R32G32_SINT); 319 STR(R32G32_SFLOAT); 320 STR(R32G32B32_UINT); 321 STR(R32G32B32_SINT); 322 STR(R32G32B32_SFLOAT); 323 STR(R32G32B32A32_UINT); 324 STR(R32G32B32A32_SINT); 325 STR(R32G32B32A32_SFLOAT); 326 STR(R64_UINT); 327 STR(R64_SINT); 328 STR(R64_SFLOAT); 329 STR(R64G64_UINT); 330 STR(R64G64_SINT); 331 STR(R64G64_SFLOAT); 332 STR(R64G64B64_UINT); 333 STR(R64G64B64_SINT); 334 STR(R64G64B64_SFLOAT); 335 STR(R64G64B64A64_UINT); 336 STR(R64G64B64A64_SINT); 337 STR(R64G64B64A64_SFLOAT); 338 STR(B10G11R11_UFLOAT_PACK32); 339 STR(E5B9G9R9_UFLOAT_PACK32); 340 STR(D16_UNORM); 341 STR(X8_D24_UNORM_PACK32); 342 STR(D32_SFLOAT); 343 STR(S8_UINT); 344 STR(D16_UNORM_S8_UINT); 345 STR(D24_UNORM_S8_UINT); 346 STR(D32_SFLOAT_S8_UINT); 347 STR(BC1_RGB_UNORM_BLOCK); 348 STR(BC1_RGB_SRGB_BLOCK); 349 STR(BC2_UNORM_BLOCK); 350 STR(BC2_SRGB_BLOCK); 351 STR(BC3_UNORM_BLOCK); 352 STR(BC3_SRGB_BLOCK); 353 STR(BC4_UNORM_BLOCK); 354 STR(BC4_SNORM_BLOCK); 355 STR(BC5_UNORM_BLOCK); 356 STR(BC5_SNORM_BLOCK); 357 STR(BC6H_UFLOAT_BLOCK); 358 STR(BC6H_SFLOAT_BLOCK); 359 STR(BC7_UNORM_BLOCK); 360 STR(BC7_SRGB_BLOCK); 361 STR(ETC2_R8G8B8_UNORM_BLOCK); 362 STR(ETC2_R8G8B8A1_UNORM_BLOCK); 363 STR(ETC2_R8G8B8A8_UNORM_BLOCK); 364 STR(EAC_R11_UNORM_BLOCK); 365 STR(EAC_R11_SNORM_BLOCK); 366 STR(EAC_R11G11_UNORM_BLOCK); 367 STR(EAC_R11G11_SNORM_BLOCK); 368 STR(ASTC_4x4_UNORM_BLOCK); 369 STR(ASTC_4x4_SRGB_BLOCK); 370 STR(ASTC_5x4_UNORM_BLOCK); 371 STR(ASTC_5x4_SRGB_BLOCK); 372 STR(ASTC_5x5_UNORM_BLOCK); 373 STR(ASTC_5x5_SRGB_BLOCK); 374 STR(ASTC_6x5_UNORM_BLOCK); 375 STR(ASTC_6x5_SRGB_BLOCK); 376 STR(ASTC_6x6_UNORM_BLOCK); 377 STR(ASTC_6x6_SRGB_BLOCK); 378 STR(ASTC_8x5_UNORM_BLOCK); 379 STR(ASTC_8x5_SRGB_BLOCK); 380 STR(ASTC_8x6_UNORM_BLOCK); 381 STR(ASTC_8x6_SRGB_BLOCK); 382 STR(ASTC_8x8_UNORM_BLOCK); 383 STR(ASTC_8x8_SRGB_BLOCK); 384 STR(ASTC_10x5_UNORM_BLOCK); 385 STR(ASTC_10x5_SRGB_BLOCK); 386 STR(ASTC_10x6_UNORM_BLOCK); 387 STR(ASTC_10x6_SRGB_BLOCK); 388 STR(ASTC_10x8_UNORM_BLOCK); 389 STR(ASTC_10x8_SRGB_BLOCK); 390 STR(ASTC_10x10_UNORM_BLOCK); 391 STR(ASTC_10x10_SRGB_BLOCK); 392 STR(ASTC_12x10_UNORM_BLOCK); 393 STR(ASTC_12x10_SRGB_BLOCK); 394 STR(ASTC_12x12_UNORM_BLOCK); 395 STR(ASTC_12x12_SRGB_BLOCK); 396 #undef STR 397 default: 398 return "UNKNOWN_FORMAT"; 399 } 400 } 401 402 static void app_dev_init_formats(struct app_dev *dev) { 403 VkFormat f; 404 405 for (f = 0; f < VK_FORMAT_RANGE_SIZE; f++) { 406 const VkFormat fmt = f; 407 408 vkGetPhysicalDeviceFormatProperties(dev->gpu->obj, fmt, 409 &dev->format_props[f]); 410 } 411 } 412 413 static void extract_version(uint32_t version, uint32_t *major, uint32_t *minor, 414 uint32_t *patch) { 415 *major = version >> 22; 416 *minor = (version >> 12) & 0x3ff; 417 *patch = version & 0xfff; 418 } 419 420 static void app_get_physical_device_layer_extensions( 421 struct app_gpu *gpu, char *layer_name, uint32_t *extension_count, 422 VkExtensionProperties **extension_properties) { 423 VkResult err; 424 uint32_t ext_count = 0; 425 VkExtensionProperties *ext_ptr = NULL; 426 427 /* repeat get until VK_INCOMPLETE goes away */ 428 do { 429 err = vkEnumerateDeviceExtensionProperties(gpu->obj, layer_name, 430 &ext_count, NULL); 431 assert(!err); 432 433 if (ext_ptr) { 434 free(ext_ptr); 435 } 436 ext_ptr = malloc(ext_count * sizeof(VkExtensionProperties)); 437 err = vkEnumerateDeviceExtensionProperties(gpu->obj, layer_name, 438 &ext_count, ext_ptr); 439 } while (err == VK_INCOMPLETE); 440 assert(!err); 441 442 *extension_count = ext_count; 443 *extension_properties = ext_ptr; 444 } 445 446 static void app_dev_init(struct app_dev *dev, struct app_gpu *gpu) { 447 VkDeviceCreateInfo info = { 448 .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, 449 .pNext = NULL, 450 .queueCreateInfoCount = 0, 451 .pQueueCreateInfos = NULL, 452 .enabledLayerCount = 0, 453 .ppEnabledLayerNames = NULL, 454 .enabledExtensionCount = 0, 455 .ppEnabledExtensionNames = NULL, 456 }; 457 VkResult U_ASSERT_ONLY err; 458 // Extensions to enable 459 static const char *known_extensions[] = { 460 VK_KHR_SWAPCHAIN_EXTENSION_NAME, 461 }; 462 463 uint32_t count = 0; 464 465 /* Scan layers */ 466 VkLayerProperties *device_layer_properties = NULL; 467 struct layer_extension_list *device_layers = NULL; 468 469 do { 470 err = vkEnumerateDeviceLayerProperties(gpu->obj, &count, NULL); 471 assert(!err); 472 473 if (device_layer_properties) { 474 free(device_layer_properties); 475 } 476 device_layer_properties = malloc(sizeof(VkLayerProperties) * count); 477 assert(device_layer_properties); 478 479 if (device_layers) { 480 free(device_layers); 481 } 482 device_layers = malloc(sizeof(struct layer_extension_list) * count); 483 assert(device_layers); 484 485 err = vkEnumerateDeviceLayerProperties(gpu->obj, &count, 486 device_layer_properties); 487 } while (err == VK_INCOMPLETE); 488 assert(!err); 489 490 gpu->device_layer_count = count; 491 gpu->device_layers = device_layers; 492 493 for (uint32_t i = 0; i < gpu->device_layer_count; i++) { 494 VkLayerProperties *src_info = &device_layer_properties[i]; 495 struct layer_extension_list *dst_info = &gpu->device_layers[i]; 496 memcpy(&dst_info->layer_properties, src_info, 497 sizeof(VkLayerProperties)); 498 499 /* Save away layer extension info for report */ 500 app_get_physical_device_layer_extensions( 501 gpu, src_info->layerName, &dst_info->extension_count, 502 &dst_info->extension_properties); 503 } 504 free(device_layer_properties); 505 506 app_get_physical_device_layer_extensions( 507 gpu, NULL, &gpu->device_extension_count, &gpu->device_extensions); 508 509 fflush(stdout); 510 511 uint32_t enabled_extension_count = 0; 512 uint32_t known_extension_count = ARRAY_SIZE(known_extensions); 513 514 for (uint32_t i = 0; i < known_extension_count; i++) { 515 VkBool32 extension_found = 0; 516 for (uint32_t j = 0; j < gpu->device_extension_count; j++) { 517 VkExtensionProperties *ext_prop = &gpu->device_extensions[j]; 518 if (!strcmp(known_extensions[i], ext_prop->extensionName)) { 519 520 extension_found = 1; 521 enabled_extension_count++; 522 } 523 } 524 if (!extension_found) { 525 printf("Cannot find extension: %s\n", known_extensions[i]); 526 ERR_EXIT(VK_ERROR_EXTENSION_NOT_PRESENT); 527 } 528 } 529 530 /* request all queues */ 531 info.queueCreateInfoCount = gpu->queue_count; 532 info.pQueueCreateInfos = gpu->queue_reqs; 533 534 info.enabledLayerCount = 0; 535 info.ppEnabledLayerNames = NULL; 536 info.enabledExtensionCount = enabled_extension_count; 537 info.ppEnabledExtensionNames = (const char *const *)known_extensions; 538 dev->gpu = gpu; 539 err = vkCreateDevice(gpu->obj, &info, NULL, &dev->obj); 540 if (err) 541 ERR_EXIT(err); 542 } 543 544 static void app_dev_destroy(struct app_dev *dev) { 545 vkDestroyDevice(dev->obj, NULL); 546 } 547 548 static void 549 app_get_global_layer_extensions(char *layer_name, uint32_t *extension_count, 550 VkExtensionProperties **extension_properties) { 551 VkResult err; 552 uint32_t ext_count = 0; 553 VkExtensionProperties *ext_ptr = NULL; 554 555 /* repeat get until VK_INCOMPLETE goes away */ 556 do { 557 err = vkEnumerateInstanceExtensionProperties(layer_name, &ext_count, 558 NULL); 559 assert(!err); 560 561 if (ext_ptr) { 562 free(ext_ptr); 563 } 564 ext_ptr = malloc(ext_count * sizeof(VkExtensionProperties)); 565 err = vkEnumerateInstanceExtensionProperties(layer_name, &ext_count, 566 ext_ptr); 567 } while (err == VK_INCOMPLETE); 568 assert(!err); 569 570 *extension_count = ext_count; 571 *extension_properties = ext_ptr; 572 } 573 574 static void app_create_instance(struct app_instance *inst) { 575 const VkApplicationInfo app_info = { 576 .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, 577 .pNext = NULL, 578 .pApplicationName = APP_SHORT_NAME, 579 .applicationVersion = 1, 580 .pEngineName = APP_SHORT_NAME, 581 .engineVersion = 1, 582 .apiVersion = VK_API_VERSION_1_0, 583 }; 584 VkInstanceCreateInfo inst_info = { 585 .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, 586 .pNext = NULL, 587 .pApplicationInfo = &app_info, 588 .enabledLayerCount = 0, 589 .ppEnabledLayerNames = NULL, 590 .enabledExtensionCount = 0, 591 .ppEnabledExtensionNames = NULL, 592 }; 593 VkResult U_ASSERT_ONLY err; 594 // Global Extensions to enable 595 static char *known_extensions[] = { 596 VK_KHR_SURFACE_EXTENSION_NAME, 597 #ifdef VK_USE_PLATFORM_ANDROID_KHR 598 VK_KHR_ANDROID_SURFACE_EXTENSION_NAME, 599 #endif 600 #ifdef VK_USE_PLATFORM_MIR_KHR 601 VK_KHR_MIR_SURFACE_EXTENSION_NAME, 602 #endif 603 #ifdef VK_USE_PLATFORM_WAYLAND_KHR 604 VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME, 605 #endif 606 #ifdef VK_USE_PLATFORM_WIN32_KHR 607 VK_KHR_WIN32_SURFACE_EXTENSION_NAME, 608 #endif 609 #ifdef VK_USE_PLATFORM_XCB_KHR 610 VK_KHR_XCB_SURFACE_EXTENSION_NAME, 611 #endif 612 #ifdef VK_USE_PLATFORM_XLIB_KHR 613 VK_KHR_XLIB_SURFACE_EXTENSION_NAME, 614 #endif 615 }; 616 617 uint32_t global_extension_count = 0; 618 uint32_t count = 0; 619 620 /* Scan layers */ 621 VkLayerProperties *global_layer_properties = NULL; 622 struct layer_extension_list *global_layers = NULL; 623 624 do { 625 err = vkEnumerateInstanceLayerProperties(&count, NULL); 626 assert(!err); 627 628 if (global_layer_properties) { 629 free(global_layer_properties); 630 } 631 global_layer_properties = malloc(sizeof(VkLayerProperties) * count); 632 assert(global_layer_properties); 633 634 if (global_layers) { 635 free(global_layers); 636 } 637 global_layers = malloc(sizeof(struct layer_extension_list) * count); 638 assert(global_layers); 639 640 err = 641 vkEnumerateInstanceLayerProperties(&count, global_layer_properties); 642 } while (err == VK_INCOMPLETE); 643 assert(!err); 644 645 inst->global_layer_count = count; 646 inst->global_layers = global_layers; 647 648 for (uint32_t i = 0; i < inst->global_layer_count; i++) { 649 VkLayerProperties *src_info = &global_layer_properties[i]; 650 struct layer_extension_list *dst_info = &inst->global_layers[i]; 651 memcpy(&dst_info->layer_properties, src_info, 652 sizeof(VkLayerProperties)); 653 654 /* Save away layer extension info for report */ 655 app_get_global_layer_extensions(src_info->layerName, 656 &dst_info->extension_count, 657 &dst_info->extension_properties); 658 } 659 free(global_layer_properties); 660 661 /* Collect global extensions */ 662 inst->global_extension_count = 0; 663 app_get_global_layer_extensions(NULL, &inst->global_extension_count, 664 &inst->global_extensions); 665 666 for (uint32_t i = 0; i < ARRAY_SIZE(known_extensions); i++) { 667 VkBool32 extension_found = 0; 668 for (uint32_t j = 0; j < inst->global_extension_count; j++) { 669 VkExtensionProperties *extension_prop = &inst->global_extensions[j]; 670 if (!strcmp(known_extensions[i], extension_prop->extensionName)) { 671 672 extension_found = 1; 673 global_extension_count++; 674 } 675 } 676 if (!extension_found) { 677 printf("Cannot find extension: %s\n", known_extensions[i]); 678 ERR_EXIT(VK_ERROR_EXTENSION_NOT_PRESENT); 679 } 680 } 681 682 inst_info.enabledExtensionCount = global_extension_count; 683 inst_info.ppEnabledExtensionNames = (const char *const *)known_extensions; 684 685 VkDebugReportCallbackCreateInfoEXT dbg_info; 686 memset(&dbg_info, 0, sizeof(dbg_info)); 687 dbg_info.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT; 688 dbg_info.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | 689 VK_DEBUG_REPORT_WARNING_BIT_EXT | 690 VK_DEBUG_REPORT_INFORMATION_BIT_EXT; 691 dbg_info.pfnCallback = dbg_callback; 692 inst_info.pNext = &dbg_info; 693 694 err = vkCreateInstance(&inst_info, NULL, &inst->instance); 695 if (err == VK_ERROR_INCOMPATIBLE_DRIVER) { 696 printf("Cannot create Vulkan instance.\n"); 697 ERR_EXIT(err); 698 } else if (err) { 699 ERR_EXIT(err); 700 } 701 } 702 703 static void app_destroy_instance(struct app_instance *inst) { 704 free(inst->global_extensions); 705 vkDestroyInstance(inst->instance, NULL); 706 } 707 708 static void app_gpu_init(struct app_gpu *gpu, uint32_t id, 709 VkPhysicalDevice obj) { 710 uint32_t i; 711 712 memset(gpu, 0, sizeof(*gpu)); 713 714 gpu->id = id; 715 gpu->obj = obj; 716 717 vkGetPhysicalDeviceProperties(gpu->obj, &gpu->props); 718 719 /* get queue count */ 720 vkGetPhysicalDeviceQueueFamilyProperties(gpu->obj, &gpu->queue_count, NULL); 721 722 gpu->queue_props = malloc(sizeof(gpu->queue_props[0]) * gpu->queue_count); 723 724 if (!gpu->queue_props) 725 ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY); 726 vkGetPhysicalDeviceQueueFamilyProperties(gpu->obj, &gpu->queue_count, 727 gpu->queue_props); 728 729 /* set up queue requests */ 730 gpu->queue_reqs = malloc(sizeof(*gpu->queue_reqs) * gpu->queue_count); 731 if (!gpu->queue_reqs) 732 ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY); 733 for (i = 0; i < gpu->queue_count; i++) { 734 float *queue_priorities = 735 malloc(gpu->queue_props[i].queueCount * sizeof(float)); 736 memset(queue_priorities, 0, 737 gpu->queue_props[i].queueCount * sizeof(float)); 738 gpu->queue_reqs[i].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; 739 gpu->queue_reqs[i].pNext = NULL; 740 gpu->queue_reqs[i].queueFamilyIndex = i; 741 gpu->queue_reqs[i].queueCount = gpu->queue_props[i].queueCount; 742 gpu->queue_reqs[i].pQueuePriorities = queue_priorities; 743 } 744 745 vkGetPhysicalDeviceMemoryProperties(gpu->obj, &gpu->memory_props); 746 747 vkGetPhysicalDeviceFeatures(gpu->obj, &gpu->features); 748 749 app_dev_init(&gpu->dev, gpu); 750 app_dev_init_formats(&gpu->dev); 751 } 752 753 static void app_gpu_destroy(struct app_gpu *gpu) { 754 app_dev_destroy(&gpu->dev); 755 free(gpu->device_extensions); 756 757 for (uint32_t i = 0; i < gpu->queue_count; i++) { 758 free((void *)gpu->queue_reqs[i].pQueuePriorities); 759 } 760 free(gpu->queue_reqs); 761 free(gpu->queue_props); 762 } 763 764 // clang-format off 765 static void app_dev_dump_format_props(const struct app_dev *dev, VkFormat fmt) 766 { 767 const VkFormatProperties *props = &dev->format_props[fmt]; 768 struct { 769 const char *name; 770 VkFlags flags; 771 } features[3]; 772 uint32_t i; 773 774 features[0].name = "linearTiling FormatFeatureFlags"; 775 features[0].flags = props->linearTilingFeatures; 776 features[1].name = "optimalTiling FormatFeatureFlags"; 777 features[1].flags = props->optimalTilingFeatures; 778 features[2].name = "bufferFeatures FormatFeatureFlags"; 779 features[2].flags = props->bufferFeatures; 780 781 printf("\nFORMAT_%s:", vk_format_string(fmt)); 782 for (i = 0; i < ARRAY_SIZE(features); i++) { 783 printf("\n\t%s:", features[i].name); 784 if (features[i].flags == 0) { 785 printf("\n\t\tNone"); 786 } else { 787 printf("%s%s%s%s%s%s%s%s%s%s%s%s%s", 788 ((features[i].flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) ? "\n\t\tVK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT" : ""), 789 ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) ? "\n\t\tVK_FORMAT_FEATURE_STORAGE_IMAGE_BIT" : ""), 790 ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT) ? "\n\t\tVK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT" : ""), 791 ((features[i].flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) ? "\n\t\tVK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT" : ""), 792 ((features[i].flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT) ? "\n\t\tVK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT" : ""), 793 ((features[i].flags & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) ? "\n\t\tVK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT" : ""), 794 ((features[i].flags & VK_FORMAT_FEATURE_BLIT_SRC_BIT) ? "\n\t\tVK_FORMAT_FEATURE_BLIT_SRC_BIT" : ""), 795 ((features[i].flags & VK_FORMAT_FEATURE_BLIT_DST_BIT) ? "\n\t\tVK_FORMAT_FEATURE_BLIT_DST_BIT" : ""), 796 ((features[i].flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT) ? "\n\t\tVK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT" : ""), 797 ((features[i].flags & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT) ? "\n\t\tVK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT" : ""), 798 ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT) ? "\n\t\tVK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT" : ""), 799 ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT) ? "\n\t\tVK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT" : ""), 800 ((features[i].flags & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) ? "\n\t\tVK_FORMAT_FEATURE_VERTEX_BUFFER_BIT" : "")); 801 } 802 } 803 printf("\n"); 804 } 805 806 807 static void 808 app_dev_dump(const struct app_dev *dev) 809 { 810 VkFormat fmt; 811 812 for (fmt = 0; fmt < VK_FORMAT_RANGE_SIZE; fmt++) { 813 app_dev_dump_format_props(dev, fmt); 814 } 815 } 816 817 #ifdef _WIN32 818 #define PRINTF_SIZE_T_SPECIFIER "%Iu" 819 #else 820 #define PRINTF_SIZE_T_SPECIFIER "%zu" 821 #endif 822 823 static void app_gpu_dump_features(const struct app_gpu *gpu) 824 { 825 const VkPhysicalDeviceFeatures *features = &gpu->features; 826 827 printf("VkPhysicalDeviceFeatures:\n"); 828 printf("=========================\n"); 829 830 printf("\trobustBufferAccess = %u\n", features->robustBufferAccess ); 831 printf("\tfullDrawIndexUint32 = %u\n", features->fullDrawIndexUint32 ); 832 printf("\timageCubeArray = %u\n", features->imageCubeArray ); 833 printf("\tindependentBlend = %u\n", features->independentBlend ); 834 printf("\tgeometryShader = %u\n", features->geometryShader ); 835 printf("\ttessellationShader = %u\n", features->tessellationShader ); 836 printf("\tsampleRateShading = %u\n", features->sampleRateShading ); 837 printf("\tdualSrcBlend = %u\n", features->dualSrcBlend ); 838 printf("\tlogicOp = %u\n", features->logicOp ); 839 printf("\tmultiDrawIndirect = %u\n", features->multiDrawIndirect ); 840 printf("\tdrawIndirectFirstInstance = %u\n", features->drawIndirectFirstInstance ); 841 printf("\tdepthClamp = %u\n", features->depthClamp ); 842 printf("\tdepthBiasClamp = %u\n", features->depthBiasClamp ); 843 printf("\tfillModeNonSolid = %u\n", features->fillModeNonSolid ); 844 printf("\tdepthBounds = %u\n", features->depthBounds ); 845 printf("\twideLines = %u\n", features->wideLines ); 846 printf("\tlargePoints = %u\n", features->largePoints ); 847 printf("\ttextureCompressionETC2 = %u\n", features->textureCompressionETC2 ); 848 printf("\ttextureCompressionASTC_LDR = %u\n", features->textureCompressionASTC_LDR ); 849 printf("\ttextureCompressionBC = %u\n", features->textureCompressionBC ); 850 printf("\tocclusionQueryPrecise = %u\n", features->occlusionQueryPrecise ); 851 printf("\tpipelineStatisticsQuery = %u\n", features->pipelineStatisticsQuery ); 852 printf("\tvertexSideEffects = %u\n", features->vertexPipelineStoresAndAtomics ); 853 printf("\ttessellationSideEffects = %u\n", features->fragmentStoresAndAtomics ); 854 printf("\tgeometrySideEffects = %u\n", features->shaderTessellationAndGeometryPointSize ); 855 printf("\tshaderImageGatherExtended = %u\n", features->shaderImageGatherExtended ); 856 printf("\tshaderStorageImageExtendedFormats = %u\n", features->shaderStorageImageExtendedFormats ); 857 printf("\tshaderStorageImageMultisample = %u\n", features->shaderStorageImageMultisample ); 858 printf("\tshaderStorageImageReadWithoutFormat = %u\n", features->shaderStorageImageReadWithoutFormat ); 859 printf("\tshaderStorageImageWriteWithoutFormat = %u\n", features->shaderStorageImageWriteWithoutFormat ); 860 printf("\tshaderUniformBufferArrayDynamicIndexing = %u\n", features->shaderUniformBufferArrayDynamicIndexing); 861 printf("\tshaderSampledImageArrayDynamicIndexing = %u\n", features->shaderSampledImageArrayDynamicIndexing ); 862 printf("\tshaderStorageBufferArrayDynamicIndexing = %u\n", features->shaderStorageBufferArrayDynamicIndexing); 863 printf("\tshaderStorageImageArrayDynamicIndexing = %u\n", features->shaderStorageImageArrayDynamicIndexing ); 864 printf("\tshaderClipDistance = %u\n", features->shaderClipDistance ); 865 printf("\tshaderCullDistance = %u\n", features->shaderCullDistance ); 866 printf("\tshaderFloat64 = %u\n", features->shaderFloat64 ); 867 printf("\tshaderInt64 = %u\n", features->shaderInt64 ); 868 printf("\tshaderInt16 = %u\n", features->shaderInt16 ); 869 printf("\tshaderResourceResidency = %u\n", features->shaderResourceResidency ); 870 printf("\tshaderResourceMinLod = %u\n", features->shaderResourceMinLod ); 871 printf("\talphaToOne = %u\n", features->alphaToOne ); 872 printf("\tsparseBinding = %u\n", features->sparseBinding ); 873 printf("\tsparseResidencyBuffer = %u\n", features->sparseResidencyBuffer ); 874 printf("\tsparseResidencyImage2D = %u\n", features->sparseResidencyImage2D ); 875 printf("\tsparseResidencyImage3D = %u\n", features->sparseResidencyImage3D ); 876 printf("\tsparseResidency2Samples = %u\n", features->sparseResidency2Samples ); 877 printf("\tsparseResidency4Samples = %u\n", features->sparseResidency4Samples ); 878 printf("\tsparseResidency8Samples = %u\n", features->sparseResidency8Samples ); 879 printf("\tsparseResidency16Samples = %u\n", features->sparseResidency16Samples ); 880 printf("\tsparseResidencyAliased = %u\n", features->sparseResidencyAliased ); 881 printf("\tvariableMultisampleRate = %u\n", features->variableMultisampleRate ); 882 printf("\tiheritedQueries = %u\n", features->inheritedQueries ); 883 } 884 885 static void app_dump_sparse_props(const VkPhysicalDeviceSparseProperties *sparseProps) 886 { 887 888 printf("\tVkPhysicalDeviceSparseProperties:\n"); 889 printf("\t---------------------------------\n"); 890 891 printf("\t\tresidencyStandard2DBlockShape = %u\n", sparseProps->residencyStandard2DBlockShape ); 892 printf("\t\tresidencyStandard2DMultisampleBlockShape = %u\n", sparseProps->residencyStandard2DMultisampleBlockShape); 893 printf("\t\tresidencyStandard3DBlockShape = %u\n", sparseProps->residencyStandard3DBlockShape ); 894 printf("\t\tresidencyAlignedMipSize = %u\n", sparseProps->residencyAlignedMipSize ); 895 printf("\t\tresidencyNonResidentStrict = %u\n", sparseProps->residencyNonResidentStrict ); 896 } 897 898 static void app_dump_limits(const VkPhysicalDeviceLimits *limits) 899 { 900 printf("\tVkPhysicalDeviceLimits:\n"); 901 printf("\t-----------------------\n"); 902 903 printf("\t\tmaxImageDimension1D = 0x%" PRIxLEAST32 "\n", limits->maxImageDimension1D ); 904 printf("\t\tmaxImageDimension2D = 0x%" PRIxLEAST32 "\n", limits->maxImageDimension2D ); 905 printf("\t\tmaxImageDimension3D = 0x%" PRIxLEAST32 "\n", limits->maxImageDimension3D ); 906 printf("\t\tmaxImageDimensionCube = 0x%" PRIxLEAST32 "\n", limits->maxImageDimensionCube ); 907 printf("\t\tmaxImageArrayLayers = 0x%" PRIxLEAST32 "\n", limits->maxImageArrayLayers ); 908 printf("\t\tmaxTexelBufferElements = 0x%" PRIxLEAST32 "\n", limits->maxTexelBufferElements ); 909 printf("\t\tmaxUniformBufferRange = 0x%" PRIxLEAST32 "\n", limits->maxUniformBufferRange ); 910 printf("\t\tmaxStorageBufferRange = 0x%" PRIxLEAST32 "\n", limits->maxStorageBufferRange ); 911 printf("\t\tmaxPushConstantsSize = 0x%" PRIxLEAST32 "\n", limits->maxPushConstantsSize ); 912 printf("\t\tmaxMemoryAllocationCount = 0x%" PRIxLEAST32 "\n", limits->maxMemoryAllocationCount ); 913 printf("\t\tmaxSamplerAllocationCount = 0x%" PRIxLEAST32 "\n", limits->maxSamplerAllocationCount ); 914 printf("\t\tbufferImageGranularity = 0x%" PRIxLEAST64 "\n", limits->bufferImageGranularity ); 915 printf("\t\tsparseAddressSpaceSize = 0x%" PRIxLEAST64 "\n", limits->sparseAddressSpaceSize ); 916 printf("\t\tmaxBoundDescriptorSets = 0x%" PRIxLEAST32 "\n", limits->maxBoundDescriptorSets ); 917 printf("\t\tmaxPerStageDescriptorSamplers = 0x%" PRIxLEAST32 "\n", limits->maxPerStageDescriptorSamplers ); 918 printf("\t\tmaxPerStageDescriptorUniformBuffers = 0x%" PRIxLEAST32 "\n", limits->maxPerStageDescriptorUniformBuffers ); 919 printf("\t\tmaxPerStageDescriptorStorageBuffers = 0x%" PRIxLEAST32 "\n", limits->maxPerStageDescriptorStorageBuffers ); 920 printf("\t\tmaxPerStageDescriptorSampledImages = 0x%" PRIxLEAST32 "\n", limits->maxPerStageDescriptorSampledImages ); 921 printf("\t\tmaxPerStageDescriptorStorageImages = 0x%" PRIxLEAST32 "\n", limits->maxPerStageDescriptorStorageImages ); 922 printf("\t\tmaxPerStageDescriptorInputAttachments = 0x%" PRIxLEAST32 "\n", limits->maxPerStageDescriptorInputAttachments ); 923 printf("\t\tmaxPerStageResources = 0x%" PRIxLEAST32 "\n", limits->maxPerStageResources ); 924 printf("\t\tmaxDescriptorSetSamplers = 0x%" PRIxLEAST32 "\n", limits->maxDescriptorSetSamplers ); 925 printf("\t\tmaxDescriptorSetUniformBuffers = 0x%" PRIxLEAST32 "\n", limits->maxDescriptorSetUniformBuffers ); 926 printf("\t\tmaxDescriptorSetUniformBuffersDynamic = 0x%" PRIxLEAST32 "\n", limits->maxDescriptorSetUniformBuffersDynamic ); 927 printf("\t\tmaxDescriptorSetStorageBuffers = 0x%" PRIxLEAST32 "\n", limits->maxDescriptorSetStorageBuffers ); 928 printf("\t\tmaxDescriptorSetStorageBuffersDynamic = 0x%" PRIxLEAST32 "\n", limits->maxDescriptorSetStorageBuffersDynamic ); 929 printf("\t\tmaxDescriptorSetSampledImages = 0x%" PRIxLEAST32 "\n", limits->maxDescriptorSetSampledImages ); 930 printf("\t\tmaxDescriptorSetStorageImages = 0x%" PRIxLEAST32 "\n", limits->maxDescriptorSetStorageImages ); 931 printf("\t\tmaxDescriptorSetInputAttachments = 0x%" PRIxLEAST32 "\n", limits->maxDescriptorSetInputAttachments ); 932 printf("\t\tmaxVertexInputAttributes = 0x%" PRIxLEAST32 "\n", limits->maxVertexInputAttributes ); 933 printf("\t\tmaxVertexInputBindings = 0x%" PRIxLEAST32 "\n", limits->maxVertexInputBindings ); 934 printf("\t\tmaxVertexInputAttributeOffset = 0x%" PRIxLEAST32 "\n", limits->maxVertexInputAttributeOffset ); 935 printf("\t\tmaxVertexInputBindingStride = 0x%" PRIxLEAST32 "\n", limits->maxVertexInputBindingStride ); 936 printf("\t\tmaxVertexOutputComponents = 0x%" PRIxLEAST32 "\n", limits->maxVertexOutputComponents ); 937 printf("\t\tmaxTessellationGenerationLevel = 0x%" PRIxLEAST32 "\n", limits->maxTessellationGenerationLevel ); 938 printf("\t\tmaxTessellationPatchSize = 0x%" PRIxLEAST32 "\n", limits->maxTessellationPatchSize ); 939 printf("\t\tmaxTessellationControlPerVertexInputComponents = 0x%" PRIxLEAST32 "\n", limits->maxTessellationControlPerVertexInputComponents ); 940 printf("\t\tmaxTessellationControlPerVertexOutputComponents = 0x%" PRIxLEAST32 "\n", limits->maxTessellationControlPerVertexOutputComponents); 941 printf("\t\tmaxTessellationControlPerPatchOutputComponents = 0x%" PRIxLEAST32 "\n", limits->maxTessellationControlPerPatchOutputComponents ); 942 printf("\t\tmaxTessellationControlTotalOutputComponents = 0x%" PRIxLEAST32 "\n", limits->maxTessellationControlTotalOutputComponents ); 943 printf("\t\tmaxTessellationEvaluationInputComponents = 0x%" PRIxLEAST32 "\n", limits->maxTessellationEvaluationInputComponents ); 944 printf("\t\tmaxTessellationEvaluationOutputComponents = 0x%" PRIxLEAST32 "\n", limits->maxTessellationEvaluationOutputComponents ); 945 printf("\t\tmaxGeometryShaderInvocations = 0x%" PRIxLEAST32 "\n", limits->maxGeometryShaderInvocations ); 946 printf("\t\tmaxGeometryInputComponents = 0x%" PRIxLEAST32 "\n", limits->maxGeometryInputComponents ); 947 printf("\t\tmaxGeometryOutputComponents = 0x%" PRIxLEAST32 "\n", limits->maxGeometryOutputComponents ); 948 printf("\t\tmaxGeometryOutputVertices = 0x%" PRIxLEAST32 "\n", limits->maxGeometryOutputVertices ); 949 printf("\t\tmaxGeometryTotalOutputComponents = 0x%" PRIxLEAST32 "\n", limits->maxGeometryTotalOutputComponents ); 950 printf("\t\tmaxFragmentInputComponents = 0x%" PRIxLEAST32 "\n", limits->maxFragmentInputComponents ); 951 printf("\t\tmaxFragmentOutputAttachments = 0x%" PRIxLEAST32 "\n", limits->maxFragmentOutputAttachments ); 952 printf("\t\tmaxFragmentDualSrcAttachments = 0x%" PRIxLEAST32 "\n", limits->maxFragmentDualSrcAttachments ); 953 printf("\t\tmaxFragmentCombinedOutputResources = 0x%" PRIxLEAST32 "\n", limits->maxFragmentCombinedOutputResources ); 954 printf("\t\tmaxComputeSharedMemorySize = 0x%" PRIxLEAST32 "\n", limits->maxComputeSharedMemorySize ); 955 printf("\t\tmaxComputeWorkGroupCount[0] = 0x%" PRIxLEAST32 "\n", limits->maxComputeWorkGroupCount[0] ); 956 printf("\t\tmaxComputeWorkGroupCount[1] = 0x%" PRIxLEAST32 "\n", limits->maxComputeWorkGroupCount[1] ); 957 printf("\t\tmaxComputeWorkGroupCount[2] = 0x%" PRIxLEAST32 "\n", limits->maxComputeWorkGroupCount[2] ); 958 printf("\t\tmaxComputeWorkGroupInvocations = 0x%" PRIxLEAST32 "\n", limits->maxComputeWorkGroupInvocations ); 959 printf("\t\tmaxComputeWorkGroupSize[0] = 0x%" PRIxLEAST32 "\n", limits->maxComputeWorkGroupSize[0] ); 960 printf("\t\tmaxComputeWorkGroupSize[1] = 0x%" PRIxLEAST32 "\n", limits->maxComputeWorkGroupSize[1] ); 961 printf("\t\tmaxComputeWorkGroupSize[2] = 0x%" PRIxLEAST32 "\n", limits->maxComputeWorkGroupSize[2] ); 962 printf("\t\tsubPixelPrecisionBits = 0x%" PRIxLEAST32 "\n", limits->subPixelPrecisionBits ); 963 printf("\t\tsubTexelPrecisionBits = 0x%" PRIxLEAST32 "\n", limits->subTexelPrecisionBits ); 964 printf("\t\tmipmapPrecisionBits = 0x%" PRIxLEAST32 "\n", limits->mipmapPrecisionBits ); 965 printf("\t\tmaxDrawIndexedIndexValue = 0x%" PRIxLEAST32 "\n", limits->maxDrawIndexedIndexValue ); 966 printf("\t\tmaxDrawIndirectCount = 0x%" PRIxLEAST32 "\n", limits->maxDrawIndirectCount ); 967 printf("\t\tmaxSamplerLodBias = %f\n", limits->maxSamplerLodBias ); 968 printf("\t\tmaxSamplerAnisotropy = %f\n", limits->maxSamplerAnisotropy ); 969 printf("\t\tmaxViewports = 0x%" PRIxLEAST32 "\n", limits->maxViewports ); 970 printf("\t\tmaxViewportDimensions[0] = 0x%" PRIxLEAST32 "\n", limits->maxViewportDimensions[0] ); 971 printf("\t\tmaxViewportDimensions[1] = 0x%" PRIxLEAST32 "\n", limits->maxViewportDimensions[1] ); 972 printf("\t\tviewportBoundsRange[0] = %f\n", limits->viewportBoundsRange[0] ); 973 printf("\t\tviewportBoundsRange[1] = %f\n", limits->viewportBoundsRange[1] ); 974 printf("\t\tviewportSubPixelBits = 0x%" PRIxLEAST32 "\n", limits->viewportSubPixelBits ); 975 printf("\t\tminMemoryMapAlignment = " PRINTF_SIZE_T_SPECIFIER "\n", limits->minMemoryMapAlignment ); 976 printf("\t\tminTexelBufferOffsetAlignment = 0x%" PRIxLEAST64 "\n", limits->minTexelBufferOffsetAlignment ); 977 printf("\t\tminUniformBufferOffsetAlignment = 0x%" PRIxLEAST64 "\n", limits->minUniformBufferOffsetAlignment ); 978 printf("\t\tminStorageBufferOffsetAlignment = 0x%" PRIxLEAST64 "\n", limits->minStorageBufferOffsetAlignment ); 979 printf("\t\tminTexelOffset = 0x%" PRIxLEAST32 "\n", limits->minTexelOffset ); 980 printf("\t\tmaxTexelOffset = 0x%" PRIxLEAST32 "\n", limits->maxTexelOffset ); 981 printf("\t\tminTexelGatherOffset = 0x%" PRIxLEAST32 "\n", limits->minTexelGatherOffset ); 982 printf("\t\tmaxTexelGatherOffset = 0x%" PRIxLEAST32 "\n", limits->maxTexelGatherOffset ); 983 printf("\t\tminInterpolationOffset = %f\n", limits->minInterpolationOffset ); 984 printf("\t\tmaxInterpolationOffset = %f\n", limits->maxInterpolationOffset ); 985 printf("\t\tsubPixelInterpolationOffsetBits = 0x%" PRIxLEAST32 "\n", limits->subPixelInterpolationOffsetBits ); 986 printf("\t\tmaxFramebufferWidth = 0x%" PRIxLEAST32 "\n", limits->maxFramebufferWidth ); 987 printf("\t\tmaxFramebufferHeight = 0x%" PRIxLEAST32 "\n", limits->maxFramebufferHeight ); 988 printf("\t\tmaxFramebufferLayers = 0x%" PRIxLEAST32 "\n", limits->maxFramebufferLayers ); 989 printf("\t\tframebufferColorSampleCounts = 0x%" PRIxLEAST32 "\n", limits->framebufferColorSampleCounts ); 990 printf("\t\tframebufferDepthSampleCounts = 0x%" PRIxLEAST32 "\n", limits->framebufferDepthSampleCounts ); 991 printf("\t\tframebufferStencilSampleCounts = 0x%" PRIxLEAST32 "\n", limits->framebufferStencilSampleCounts ); 992 printf("\t\tmaxColorAttachments = 0x%" PRIxLEAST32 "\n", limits->maxColorAttachments ); 993 printf("\t\tsampledImageColorSampleCounts = 0x%" PRIxLEAST32 "\n", limits->sampledImageColorSampleCounts ); 994 printf("\t\tsampledImageDepthSampleCounts = 0x%" PRIxLEAST32 "\n", limits->sampledImageDepthSampleCounts ); 995 printf("\t\tsampledImageStencilSampleCounts = 0x%" PRIxLEAST32 "\n", limits->sampledImageStencilSampleCounts ); 996 printf("\t\tsampledImageIntegerSampleCounts = 0x%" PRIxLEAST32 "\n", limits->sampledImageIntegerSampleCounts ); 997 printf("\t\tstorageImageSampleCounts = 0x%" PRIxLEAST32 "\n", limits->storageImageSampleCounts ); 998 printf("\t\tmaxSampleMaskWords = 0x%" PRIxLEAST32 "\n", limits->maxSampleMaskWords ); 999 printf("\t\ttimestampComputeAndGraphics = %u\n", limits->timestampComputeAndGraphics ); 1000 printf("\t\ttimestampPeriod = 0x%f\n", limits->timestampPeriod ); 1001 printf("\t\tmaxClipDistances = 0x%" PRIxLEAST32 "\n", limits->maxClipDistances ); 1002 printf("\t\tmaxCullDistances = 0x%" PRIxLEAST32 "\n", limits->maxCullDistances ); 1003 printf("\t\tmaxCombinedClipAndCullDistances = 0x%" PRIxLEAST32 "\n", limits->maxCombinedClipAndCullDistances ); 1004 printf("\t\tpointSizeRange[0] = %f\n", limits->pointSizeRange[0] ); 1005 printf("\t\tpointSizeRange[1] = %f\n", limits->pointSizeRange[1] ); 1006 printf("\t\tlineWidthRange[0] = %f\n", limits->lineWidthRange[0] ); 1007 printf("\t\tlineWidthRange[1] = %f\n", limits->lineWidthRange[1] ); 1008 printf("\t\tpointSizeGranularity = %f\n", limits->pointSizeGranularity ); 1009 printf("\t\tlineWidthGranularity = %f\n", limits->lineWidthGranularity ); 1010 printf("\t\tstrictLines = %u\n", limits->strictLines ); 1011 printf("\t\tstandardSampleLocations = %u\n", limits->standardSampleLocations ); 1012 printf("\t\toptimalBufferCopyOffsetAlignment = 0x%" PRIxLEAST64 "\n", limits->optimalBufferCopyOffsetAlignment ); 1013 printf("\t\toptimalBufferCopyRowPitchAlignment = 0x%" PRIxLEAST64 "\n", limits->optimalBufferCopyRowPitchAlignment ); 1014 printf("\t\tnonCoherentAtomSize = 0x%" PRIxLEAST64 "\n", limits->nonCoherentAtomSize ); 1015 } 1016 1017 static void app_gpu_dump_props(const struct app_gpu *gpu) 1018 { 1019 const VkPhysicalDeviceProperties *props = &gpu->props; 1020 1021 printf("VkPhysicalDeviceProperties:\n"); 1022 printf("===========================\n"); 1023 printf("\tapiVersion = %u\n", props->apiVersion); 1024 printf("\tdriverVersion = %u\n", props->driverVersion); 1025 printf("\tvendorID = 0x%04x\n", props->vendorID); 1026 printf("\tdeviceID = 0x%04x\n", props->deviceID); 1027 printf("\tdeviceType = %s\n", vk_physical_device_type_string(props->deviceType)); 1028 printf("\tdeviceName = %s\n", props->deviceName); 1029 1030 app_dump_limits(&gpu->props.limits); 1031 app_dump_sparse_props(&gpu->props.sparseProperties); 1032 1033 fflush(stdout); 1034 } 1035 // clang-format on 1036 1037 static void 1038 app_dump_extensions(const char *indent, const char *layer_name, 1039 const uint32_t extension_count, 1040 const VkExtensionProperties *extension_properties) { 1041 uint32_t i; 1042 if (layer_name && (strlen(layer_name) > 0)) { 1043 printf("%s%s Extensions", indent, layer_name); 1044 } else { 1045 printf("Extensions"); 1046 } 1047 printf("\tcount = %d\n", extension_count); 1048 for (i = 0; i < extension_count; i++) { 1049 VkExtensionProperties const *ext_prop = &extension_properties[i]; 1050 1051 printf("%s\t", indent); 1052 printf("%-32s: extension revision %2d\n", ext_prop->extensionName, 1053 ext_prop->specVersion); 1054 } 1055 printf("\n"); 1056 fflush(stdout); 1057 } 1058 1059 static void app_gpu_dump_queue_props(const struct app_gpu *gpu, uint32_t id) { 1060 const VkQueueFamilyProperties *props = &gpu->queue_props[id]; 1061 1062 printf("VkQueueFamilyProperties[%d]:\n", id); 1063 printf("============================\n"); 1064 printf("\tqueueFlags = %c%c%c\n", 1065 (props->queueFlags & VK_QUEUE_GRAPHICS_BIT) ? 'G' : '.', 1066 (props->queueFlags & VK_QUEUE_COMPUTE_BIT) ? 'C' : '.', 1067 (props->queueFlags & VK_QUEUE_TRANSFER_BIT) ? 'D' : '.'); 1068 printf("\tqueueCount = %u\n", props->queueCount); 1069 printf("\ttimestampValidBits = %u\n", props->timestampValidBits); 1070 printf("\tminImageTransferGranularity = (%d, %d, %d)\n", 1071 props->minImageTransferGranularity.width, 1072 props->minImageTransferGranularity.height, 1073 props->minImageTransferGranularity.depth); 1074 fflush(stdout); 1075 } 1076 1077 static void app_gpu_dump_memory_props(const struct app_gpu *gpu) { 1078 const VkPhysicalDeviceMemoryProperties *props = &gpu->memory_props; 1079 1080 printf("VkPhysicalDeviceMemoryProperties:\n"); 1081 printf("=================================\n"); 1082 printf("\tmemoryTypeCount = %u\n", props->memoryTypeCount); 1083 for (uint32_t i = 0; i < props->memoryTypeCount; i++) { 1084 printf("\tmemoryTypes[%u] : \n", i); 1085 printf("\t\tpropertyFlags = %u\n", props->memoryTypes[i].propertyFlags); 1086 printf("\t\theapIndex = %u\n", props->memoryTypes[i].heapIndex); 1087 } 1088 printf("\tmemoryHeapCount = %u\n", props->memoryHeapCount); 1089 for (uint32_t i = 0; i < props->memoryHeapCount; i++) { 1090 printf("\tmemoryHeaps[%u] : \n", i); 1091 printf("\t\tsize = " PRINTF_SIZE_T_SPECIFIER "\n", 1092 (size_t)props->memoryHeaps[i].size); 1093 } 1094 fflush(stdout); 1095 } 1096 1097 static void app_gpu_dump(const struct app_gpu *gpu) { 1098 uint32_t i; 1099 1100 printf("Device Extensions and layers:\n"); 1101 printf("=============================\n"); 1102 printf("GPU%u\n", gpu->id); 1103 app_gpu_dump_props(gpu); 1104 printf("\n"); 1105 app_dump_extensions("", "Device", gpu->device_extension_count, 1106 gpu->device_extensions); 1107 printf("\n"); 1108 printf("Layers\tcount = %d\n", gpu->device_layer_count); 1109 for (uint32_t i = 0; i < gpu->device_layer_count; i++) { 1110 uint32_t major, minor, patch; 1111 char spec_version[64], layer_version[64]; 1112 struct layer_extension_list const *layer_info = &gpu->device_layers[i]; 1113 1114 extract_version(layer_info->layer_properties.specVersion, &major, 1115 &minor, &patch); 1116 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d", major, minor, 1117 patch); 1118 snprintf(layer_version, sizeof(layer_version), "%d", 1119 layer_info->layer_properties.implementationVersion); 1120 printf("\t%s (%s) Vulkan version %s, layer version %s\n", 1121 layer_info->layer_properties.layerName, 1122 (char *)layer_info->layer_properties.description, spec_version, 1123 layer_version); 1124 1125 app_dump_extensions("\t", layer_info->layer_properties.layerName, 1126 layer_info->extension_count, 1127 layer_info->extension_properties); 1128 fflush(stdout); 1129 } 1130 printf("\n"); 1131 for (i = 0; i < gpu->queue_count; i++) { 1132 app_gpu_dump_queue_props(gpu, i); 1133 printf("\n"); 1134 } 1135 app_gpu_dump_memory_props(gpu); 1136 printf("\n"); 1137 app_gpu_dump_features(gpu); 1138 printf("\n"); 1139 app_dev_dump(&gpu->dev); 1140 } 1141 1142 #ifdef _WIN32 1143 // Enlarges the console window to have a large scrollback size. 1144 static void ConsoleEnlarge() { 1145 HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE); 1146 1147 // make the console window bigger 1148 CONSOLE_SCREEN_BUFFER_INFO csbi; 1149 COORD bufferSize; 1150 if (GetConsoleScreenBufferInfo(consoleHandle, &csbi)) 1151 { 1152 bufferSize.X = csbi.dwSize.X + 30; 1153 bufferSize.Y = 20000; 1154 SetConsoleScreenBufferSize(consoleHandle, bufferSize); 1155 } 1156 1157 SMALL_RECT r; 1158 r.Left = r.Top = 0; 1159 r.Right = csbi.dwSize.X - 1 + 30; 1160 r.Bottom = 50; 1161 SetConsoleWindowInfo(consoleHandle, true, &r); 1162 1163 // change the console window title 1164 SetConsoleTitle(TEXT(APP_SHORT_NAME)); 1165 } 1166 #endif 1167 1168 int main(int argc, char **argv) { 1169 unsigned int major, minor, patch; 1170 struct app_gpu gpus[MAX_GPUS]; 1171 VkPhysicalDevice objs[MAX_GPUS]; 1172 uint32_t gpu_count, i; 1173 VkResult err; 1174 struct app_instance inst; 1175 1176 #ifdef _WIN32 1177 if (ConsoleIsExclusive()) 1178 ConsoleEnlarge(); 1179 #endif 1180 1181 major = VK_API_VERSION_1_0 >> 22; 1182 minor = (VK_API_VERSION_1_0 >> 12) & 0x3ff; 1183 patch = VK_HEADER_VERSION & 0xfff; 1184 printf("===========\n"); 1185 printf("VULKAN INFO\n"); 1186 printf("===========\n\n"); 1187 printf("Vulkan API Version: %d.%d.%d\n\n", major, minor, patch); 1188 1189 app_create_instance(&inst); 1190 1191 printf("Instance Extensions and layers:\n"); 1192 printf("===============================\n"); 1193 app_dump_extensions("", "Instance", inst.global_extension_count, 1194 inst.global_extensions); 1195 1196 printf("Instance Layers\tcount = %d\n", inst.global_layer_count); 1197 for (uint32_t i = 0; i < inst.global_layer_count; i++) { 1198 uint32_t major, minor, patch; 1199 char spec_version[64], layer_version[64]; 1200 VkLayerProperties const *layer_prop = 1201 &inst.global_layers[i].layer_properties; 1202 1203 extract_version(layer_prop->specVersion, &major, &minor, &patch); 1204 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d", major, minor, 1205 patch); 1206 snprintf(layer_version, sizeof(layer_version), "%d", 1207 layer_prop->implementationVersion); 1208 printf("\t%s (%s) Vulkan version %s, layer version %s\n", 1209 layer_prop->layerName, (char *)layer_prop->description, 1210 spec_version, layer_version); 1211 1212 app_dump_extensions("\t", 1213 inst.global_layers[i].layer_properties.layerName, 1214 inst.global_layers[i].extension_count, 1215 inst.global_layers[i].extension_properties); 1216 } 1217 1218 err = vkEnumeratePhysicalDevices(inst.instance, &gpu_count, NULL); 1219 if (err) 1220 ERR_EXIT(err); 1221 if (gpu_count > MAX_GPUS) { 1222 printf("Too many GPUS found \n"); 1223 ERR_EXIT(-1); 1224 } 1225 err = vkEnumeratePhysicalDevices(inst.instance, &gpu_count, objs); 1226 if (err) 1227 ERR_EXIT(err); 1228 1229 for (i = 0; i < gpu_count; i++) { 1230 app_gpu_init(&gpus[i], i, objs[i]); 1231 app_gpu_dump(&gpus[i]); 1232 printf("\n\n"); 1233 } 1234 1235 for (i = 0; i < gpu_count; i++) 1236 app_gpu_destroy(&gpus[i]); 1237 1238 app_destroy_instance(&inst); 1239 1240 fflush(stdout); 1241 #ifdef _WIN32 1242 if (ConsoleIsExclusive()) 1243 Sleep(INFINITE); 1244 #endif 1245 1246 return 0; 1247 } 1248