vulkaninfo.c revision 4b36dd453ecb809731dbc68ccdb50e83f5417dd6
1/* 2 * Vulkan 3 * 4 * Copyright (C) 2014 LunarG, Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included 14 * in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS 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. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 * DEALINGS IN THE SOFTWARE. 23 */ 24#include <stdlib.h> 25#include <stdio.h> 26#include <stdbool.h> 27#include <string.h> 28#include <assert.h> 29#include <inttypes.h> 30 31#ifdef _WIN32 32#include <Windows.h> 33#include <fcntl.h> 34#include <io.h> 35#endif 36 37#include "vk_ext_khr_swapchain.h" 38#include "vk_ext_khr_device_swapchain.h" 39 40#include <vulkan.h> 41 42#define ERR(err) printf("%s:%d: failed with %s\n", \ 43 __FILE__, __LINE__, vk_result_string(err)); 44 45#ifdef _WIN32 46 47#define snprintf _snprintf 48 49bool consoleCreated = false; 50 51#define WAIT_FOR_CONSOLE_DESTROY \ 52 do { \ 53 if (consoleCreated) \ 54 Sleep(INFINITE); \ 55 } while (0) 56#else 57 #define WAIT_FOR_CONSOLE_DESTROY 58#endif 59 60 61#define ERR_EXIT(err) \ 62 do { \ 63 ERR(err); \ 64 fflush(stdout); \ 65 WAIT_FOR_CONSOLE_DESTROY; \ 66 exit(-1); \ 67 } while (0) 68 69#if defined(NDEBUG) && defined(__GNUC__) 70#define U_ASSERT_ONLY __attribute__((unused)) 71#else 72#define U_ASSERT_ONLY 73#endif 74 75#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 76 77#define MAX_GPUS 8 78 79#define MAX_QUEUE_TYPES 5 80#define APP_SHORT_NAME "vulkaninfo" 81 82struct app_gpu; 83 84struct app_dev { 85 struct app_gpu *gpu; /* point back to the GPU */ 86 87 VkDevice obj; 88 89 90 VkFormatProperties format_props[VK_FORMAT_NUM]; 91}; 92 93struct layer_extension_list { 94 VkLayerProperties layer_properties; 95 uint32_t extension_count; 96 VkExtensionProperties *extension_properties; 97}; 98 99struct app_instance { 100 VkInstance instance; 101 uint32_t global_layer_count; 102 struct layer_extension_list *global_layers; 103 uint32_t global_extension_count; 104 VkExtensionProperties *global_extensions; 105}; 106 107struct app_gpu { 108 uint32_t id; 109 VkPhysicalDevice obj; 110 111 VkPhysicalDeviceProperties props; 112 113 uint32_t queue_count; 114 VkQueueFamilyProperties *queue_props; 115 VkDeviceQueueCreateInfo *queue_reqs; 116 117 VkPhysicalDeviceMemoryProperties memory_props; 118 VkPhysicalDeviceFeatures features; 119 VkPhysicalDeviceLimits limits; 120 121 uint32_t device_layer_count; 122 struct layer_extension_list *device_layers; 123 124 uint32_t device_extension_count; 125 VkExtensionProperties *device_extensions; 126 127 struct app_dev dev; 128}; 129 130static const char *vk_result_string(VkResult err) 131{ 132 switch (err) { 133#define STR(r) case r: return #r 134 STR(VK_SUCCESS); 135 STR(VK_UNSUPPORTED); 136 STR(VK_NOT_READY); 137 STR(VK_TIMEOUT); 138 STR(VK_EVENT_SET); 139 STR(VK_EVENT_RESET); 140 STR(VK_ERROR_UNKNOWN); 141 STR(VK_ERROR_UNAVAILABLE); 142 STR(VK_ERROR_INITIALIZATION_FAILED); 143 STR(VK_ERROR_OUT_OF_HOST_MEMORY); 144 STR(VK_ERROR_OUT_OF_DEVICE_MEMORY); 145 STR(VK_ERROR_DEVICE_ALREADY_CREATED); 146 STR(VK_ERROR_DEVICE_LOST); 147 STR(VK_ERROR_INVALID_POINTER); 148 STR(VK_ERROR_INVALID_VALUE); 149 STR(VK_ERROR_INVALID_HANDLE); 150 STR(VK_ERROR_INVALID_ORDINAL); 151 STR(VK_ERROR_INVALID_MEMORY_SIZE); 152 STR(VK_ERROR_INVALID_EXTENSION); 153 STR(VK_ERROR_INVALID_FLAGS); 154 STR(VK_ERROR_INVALID_ALIGNMENT); 155 STR(VK_ERROR_INVALID_FORMAT); 156 STR(VK_ERROR_INVALID_IMAGE); 157 STR(VK_ERROR_INVALID_DESCRIPTOR_SET_DATA); 158 STR(VK_ERROR_INVALID_QUEUE_TYPE); 159 STR(VK_ERROR_UNSUPPORTED_SHADER_IL_VERSION); 160 STR(VK_ERROR_BAD_SHADER_CODE); 161 STR(VK_ERROR_BAD_PIPELINE_DATA); 162 STR(VK_ERROR_NOT_MAPPABLE); 163 STR(VK_ERROR_MEMORY_MAP_FAILED); 164 STR(VK_ERROR_MEMORY_UNMAP_FAILED); 165 STR(VK_ERROR_INCOMPATIBLE_DEVICE); 166 STR(VK_ERROR_INCOMPATIBLE_DRIVER); 167 STR(VK_ERROR_INCOMPLETE_COMMAND_BUFFER); 168 STR(VK_ERROR_BUILDING_COMMAND_BUFFER); 169 STR(VK_ERROR_MEMORY_NOT_BOUND); 170 STR(VK_ERROR_INCOMPATIBLE_QUEUE); 171#undef STR 172 default: return "UNKNOWN_RESULT"; 173 } 174} 175 176static const char *vk_physical_device_type_string(VkPhysicalDeviceType type) 177{ 178 switch (type) { 179#define STR(r) case VK_PHYSICAL_DEVICE_TYPE_ ##r: return #r 180 STR(OTHER); 181 STR(INTEGRATED_GPU); 182 STR(DISCRETE_GPU); 183 STR(VIRTUAL_GPU); 184#undef STR 185 default: return "UNKNOWN_DEVICE"; 186 } 187} 188 189static const char *vk_format_string(VkFormat fmt) 190{ 191 switch (fmt) { 192#define STR(r) case VK_FORMAT_ ##r: return #r 193 STR(UNDEFINED); 194 STR(R4G4_UNORM); 195 STR(R4G4_USCALED); 196 STR(R4G4B4A4_UNORM); 197 STR(R4G4B4A4_USCALED); 198 STR(R5G6B5_UNORM); 199 STR(R5G6B5_USCALED); 200 STR(R5G5B5A1_UNORM); 201 STR(R5G5B5A1_USCALED); 202 STR(R8_UNORM); 203 STR(R8_SNORM); 204 STR(R8_USCALED); 205 STR(R8_SSCALED); 206 STR(R8_UINT); 207 STR(R8_SINT); 208 STR(R8_SRGB); 209 STR(R8G8_UNORM); 210 STR(R8G8_SNORM); 211 STR(R8G8_USCALED); 212 STR(R8G8_SSCALED); 213 STR(R8G8_UINT); 214 STR(R8G8_SINT); 215 STR(R8G8_SRGB); 216 STR(R8G8B8_UNORM); 217 STR(R8G8B8_SNORM); 218 STR(R8G8B8_USCALED); 219 STR(R8G8B8_SSCALED); 220 STR(R8G8B8_UINT); 221 STR(R8G8B8_SINT); 222 STR(R8G8B8_SRGB); 223 STR(R8G8B8A8_UNORM); 224 STR(R8G8B8A8_SNORM); 225 STR(R8G8B8A8_USCALED); 226 STR(R8G8B8A8_SSCALED); 227 STR(R8G8B8A8_UINT); 228 STR(R8G8B8A8_SINT); 229 STR(R8G8B8A8_SRGB); 230 STR(R10G10B10A2_UNORM); 231 STR(R10G10B10A2_SNORM); 232 STR(R10G10B10A2_USCALED); 233 STR(R10G10B10A2_SSCALED); 234 STR(R10G10B10A2_UINT); 235 STR(R10G10B10A2_SINT); 236 STR(R16_UNORM); 237 STR(R16_SNORM); 238 STR(R16_USCALED); 239 STR(R16_SSCALED); 240 STR(R16_UINT); 241 STR(R16_SINT); 242 STR(R16_SFLOAT); 243 STR(R16G16_UNORM); 244 STR(R16G16_SNORM); 245 STR(R16G16_USCALED); 246 STR(R16G16_SSCALED); 247 STR(R16G16_UINT); 248 STR(R16G16_SINT); 249 STR(R16G16_SFLOAT); 250 STR(R16G16B16_UNORM); 251 STR(R16G16B16_SNORM); 252 STR(R16G16B16_USCALED); 253 STR(R16G16B16_SSCALED); 254 STR(R16G16B16_UINT); 255 STR(R16G16B16_SINT); 256 STR(R16G16B16_SFLOAT); 257 STR(R16G16B16A16_UNORM); 258 STR(R16G16B16A16_SNORM); 259 STR(R16G16B16A16_USCALED); 260 STR(R16G16B16A16_SSCALED); 261 STR(R16G16B16A16_UINT); 262 STR(R16G16B16A16_SINT); 263 STR(R16G16B16A16_SFLOAT); 264 STR(R32_UINT); 265 STR(R32_SINT); 266 STR(R32_SFLOAT); 267 STR(R32G32_UINT); 268 STR(R32G32_SINT); 269 STR(R32G32_SFLOAT); 270 STR(R32G32B32_UINT); 271 STR(R32G32B32_SINT); 272 STR(R32G32B32_SFLOAT); 273 STR(R32G32B32A32_UINT); 274 STR(R32G32B32A32_SINT); 275 STR(R32G32B32A32_SFLOAT); 276 STR(R64_SFLOAT); 277 STR(R64G64_SFLOAT); 278 STR(R64G64B64_SFLOAT); 279 STR(R64G64B64A64_SFLOAT); 280 STR(R11G11B10_UFLOAT); 281 STR(R9G9B9E5_UFLOAT); 282 STR(D16_UNORM); 283 STR(D24_UNORM); 284 STR(D32_SFLOAT); 285 STR(S8_UINT); 286 STR(D16_UNORM_S8_UINT); 287 STR(D24_UNORM_S8_UINT); 288 STR(D32_SFLOAT_S8_UINT); 289 STR(BC1_RGB_UNORM); 290 STR(BC1_RGB_SRGB); 291 STR(BC2_UNORM); 292 STR(BC2_SRGB); 293 STR(BC3_UNORM); 294 STR(BC3_SRGB); 295 STR(BC4_UNORM); 296 STR(BC4_SNORM); 297 STR(BC5_UNORM); 298 STR(BC5_SNORM); 299 STR(BC6H_UFLOAT); 300 STR(BC6H_SFLOAT); 301 STR(BC7_UNORM); 302 STR(BC7_SRGB); 303 STR(ETC2_R8G8B8_UNORM); 304 STR(ETC2_R8G8B8A1_UNORM); 305 STR(ETC2_R8G8B8A8_UNORM); 306 STR(EAC_R11_UNORM); 307 STR(EAC_R11_SNORM); 308 STR(EAC_R11G11_UNORM); 309 STR(EAC_R11G11_SNORM); 310 STR(ASTC_4x4_UNORM); 311 STR(ASTC_4x4_SRGB); 312 STR(ASTC_5x4_UNORM); 313 STR(ASTC_5x4_SRGB); 314 STR(ASTC_5x5_UNORM); 315 STR(ASTC_5x5_SRGB); 316 STR(ASTC_6x5_UNORM); 317 STR(ASTC_6x5_SRGB); 318 STR(ASTC_6x6_UNORM); 319 STR(ASTC_6x6_SRGB); 320 STR(ASTC_8x5_UNORM); 321 STR(ASTC_8x5_SRGB); 322 STR(ASTC_8x6_UNORM); 323 STR(ASTC_8x6_SRGB); 324 STR(ASTC_8x8_UNORM); 325 STR(ASTC_8x8_SRGB); 326 STR(ASTC_10x5_UNORM); 327 STR(ASTC_10x5_SRGB); 328 STR(ASTC_10x6_UNORM); 329 STR(ASTC_10x6_SRGB); 330 STR(ASTC_10x8_UNORM); 331 STR(ASTC_10x8_SRGB); 332 STR(ASTC_10x10_UNORM); 333 STR(ASTC_10x10_SRGB); 334 STR(ASTC_12x10_UNORM); 335 STR(ASTC_12x10_SRGB); 336 STR(ASTC_12x12_UNORM); 337 STR(ASTC_12x12_SRGB); 338 STR(B5G6R5_UNORM); 339 STR(B5G6R5_USCALED); 340 STR(B8G8R8_UNORM); 341 STR(B8G8R8_SNORM); 342 STR(B8G8R8_USCALED); 343 STR(B8G8R8_SSCALED); 344 STR(B8G8R8_UINT); 345 STR(B8G8R8_SINT); 346 STR(B8G8R8_SRGB); 347 STR(B8G8R8A8_UNORM); 348 STR(B8G8R8A8_SNORM); 349 STR(B8G8R8A8_USCALED); 350 STR(B8G8R8A8_SSCALED); 351 STR(B8G8R8A8_UINT); 352 STR(B8G8R8A8_SINT); 353 STR(B8G8R8A8_SRGB); 354 STR(B10G10R10A2_UNORM); 355 STR(B10G10R10A2_SNORM); 356 STR(B10G10R10A2_USCALED); 357 STR(B10G10R10A2_SSCALED); 358 STR(B10G10R10A2_UINT); 359 STR(B10G10R10A2_SINT); 360#undef STR 361 default: return "UNKNOWN_FORMAT"; 362 } 363} 364 365static void app_dev_init_formats(struct app_dev *dev) 366{ 367 VkFormat f; 368 369 for (f = 0; f < VK_FORMAT_NUM; f++) { 370 const VkFormat fmt = f; 371 VkResult err; 372 373 err = vkGetPhysicalDeviceFormatProperties(dev->gpu->obj, fmt, &dev->format_props[f]); 374 if (err) { 375 memset(&dev->format_props[f], 0, 376 sizeof(dev->format_props[f])); 377 } 378 } 379} 380 381static void extract_version(uint32_t version, uint32_t *major, uint32_t *minor, uint32_t *patch) 382{ 383 *major = version >> 22; 384 *minor = (version >> 12) & 0x3ff; 385 *patch = version & 0xfff; 386} 387 388static void app_get_physical_device_layer_extensions( 389 struct app_gpu *gpu, 390 char *layer_name, 391 uint32_t *extension_count, 392 VkExtensionProperties **extension_properties) 393{ 394 VkResult err; 395 uint32_t ext_count = 0; 396 VkExtensionProperties *ext_ptr = NULL; 397 398 /* repeat get until VK_INCOMPLETE goes away */ 399 do { 400 err = vkGetPhysicalDeviceExtensionProperties(gpu->obj, layer_name, &ext_count, NULL); 401 assert(!err); 402 403 if (ext_ptr) { 404 free(ext_ptr); 405 } 406 ext_ptr = malloc(ext_count * sizeof(VkExtensionProperties)); 407 err = vkGetPhysicalDeviceExtensionProperties(gpu->obj, layer_name, &ext_count, ext_ptr); 408 } while (err == VK_INCOMPLETE); 409 assert(!err); 410 411 *extension_count = ext_count; 412 *extension_properties = ext_ptr; 413} 414 415static void app_dev_init(struct app_dev *dev, struct app_gpu *gpu) 416{ 417 VkDeviceCreateInfo info = { 418 .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, 419 .pNext = NULL, 420 .queueRecordCount = 0, 421 .pRequestedQueues = NULL, 422 .layerCount = 0, 423 .ppEnabledLayerNames = NULL, 424 .extensionCount = 0, 425 .ppEnabledExtensionNames = NULL, 426 }; 427 VkResult U_ASSERT_ONLY err; 428 // Extensions to enable 429 static const char *known_extensions[] = { 430 VK_EXT_KHR_DEVICE_SWAPCHAIN_EXTENSION_NAME, 431 }; 432 433 uint32_t count = 0; 434 435 /* Scan layers */ 436 VkLayerProperties *device_layer_properties = NULL; 437 struct layer_extension_list *device_layers = NULL; 438 439 do { 440 err = vkGetPhysicalDeviceLayerProperties(gpu->obj, &count, NULL); 441 assert(!err); 442 443 if (device_layer_properties) { 444 free(device_layer_properties); 445 } 446 device_layer_properties = malloc(sizeof(VkLayerProperties) * count); 447 assert(device_layer_properties); 448 449 if (device_layers) { 450 free(device_layers); 451 } 452 device_layers = malloc(sizeof(struct layer_extension_list) * count); 453 assert(device_layers); 454 455 err = vkGetPhysicalDeviceLayerProperties(gpu->obj, &count, device_layer_properties); 456 } while (err == VK_INCOMPLETE); 457 assert(!err); 458 459 gpu->device_layer_count = count; 460 gpu->device_layers = device_layers; 461 462 for (uint32_t i = 0; i < gpu->device_layer_count; i++) { 463 VkLayerProperties *src_info = &device_layer_properties[i]; 464 struct layer_extension_list *dst_info = &gpu->device_layers[i]; 465 memcpy(&dst_info->layer_properties, src_info, sizeof(VkLayerProperties)); 466 467 /* Save away layer extension info for report */ 468 app_get_physical_device_layer_extensions( 469 gpu, 470 src_info->layerName, 471 &dst_info->extension_count, 472 &dst_info->extension_properties); 473 } 474 free(device_layer_properties); 475 476 app_get_physical_device_layer_extensions( 477 gpu, 478 NULL, 479 &gpu->device_extension_count, 480 &gpu->device_extensions); 481 482 fflush(stdout); 483 484 uint32_t enabled_extension_count = 0; 485 uint32_t known_extension_count = ARRAY_SIZE(known_extensions); 486 487 for (uint32_t i = 0; i < known_extension_count; i++) { 488 VkBool32 extension_found = 0; 489 for (uint32_t j = 0; j < gpu->device_extension_count; j++) { 490 VkExtensionProperties *ext_prop = &gpu->device_extensions[j]; 491 if (!strcmp(known_extensions[i], ext_prop->extName)) { 492 493 extension_found = 1; 494 enabled_extension_count++; 495 } 496 } 497 if (!extension_found) { 498 printf("Cannot find extension: %s\n", known_extensions[i]); 499 ERR_EXIT(VK_ERROR_INVALID_EXTENSION); 500 } 501 } 502 503 /* request all queues */ 504 info.queueRecordCount = gpu->queue_count; 505 info.pRequestedQueues = gpu->queue_reqs; 506 507 info.layerCount = 0; 508 info.ppEnabledLayerNames = NULL; 509 info.extensionCount = enabled_extension_count; 510 info.ppEnabledExtensionNames = (const char*const*) known_extensions; 511 dev->gpu = gpu; 512 err = vkCreateDevice(gpu->obj, &info, &dev->obj); 513 if (err) 514 ERR_EXIT(err); 515 516} 517 518static void app_dev_destroy(struct app_dev *dev) 519{ 520 vkDestroyDevice(dev->obj); 521} 522 523static void app_get_global_layer_extensions( 524 char *layer_name, 525 uint32_t *extension_count, 526 VkExtensionProperties **extension_properties) 527{ 528 VkResult err; 529 uint32_t ext_count = 0; 530 VkExtensionProperties *ext_ptr = NULL; 531 532 /* repeat get until VK_INCOMPLETE goes away */ 533 do { 534 err = vkGetGlobalExtensionProperties(layer_name, &ext_count, NULL); 535 assert(!err); 536 537 if (ext_ptr) { 538 free(ext_ptr); 539 } 540 ext_ptr = malloc(ext_count * sizeof(VkExtensionProperties)); 541 err = vkGetGlobalExtensionProperties(layer_name, &ext_count, ext_ptr); 542 } while (err == VK_INCOMPLETE); 543 assert(!err); 544 545 *extension_count = ext_count; 546 *extension_properties = ext_ptr; 547} 548 549static void app_create_instance(struct app_instance *inst) 550{ 551 const VkApplicationInfo app_info = { 552 .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, 553 .pNext = NULL, 554 .pAppName = APP_SHORT_NAME, 555 .appVersion = 1, 556 .pEngineName = APP_SHORT_NAME, 557 .engineVersion = 1, 558 .apiVersion = VK_API_VERSION, 559 }; 560 VkInstanceCreateInfo inst_info = { 561 .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, 562 .pNext = NULL, 563 .pAppInfo = &app_info, 564 .pAllocCb = NULL, 565 .layerCount = 0, 566 .ppEnabledLayerNames = NULL, 567 .extensionCount = 0, 568 .ppEnabledExtensionNames = NULL, 569 }; 570 VkResult U_ASSERT_ONLY err; 571 // Global Extensions to enable 572 static char *known_extensions[] = { 573 "VK_EXT_KHR_swapchain", 574 }; 575 576 uint32_t global_extension_count = 0; 577 uint32_t count = 0; 578 579 /* Scan layers */ 580 VkLayerProperties *global_layer_properties = NULL; 581 struct layer_extension_list *global_layers = NULL; 582 583 do { 584 err = vkGetGlobalLayerProperties(&count, NULL); 585 assert(!err); 586 587 if (global_layer_properties) { 588 free(global_layer_properties); 589 } 590 global_layer_properties = malloc(sizeof(VkLayerProperties) * count); 591 assert(global_layer_properties); 592 593 if (global_layers) { 594 free(global_layers); 595 } 596 global_layers = malloc(sizeof(struct layer_extension_list) * count); 597 assert(global_layers); 598 599 err = vkGetGlobalLayerProperties(&count, global_layer_properties); 600 } while (err == VK_INCOMPLETE); 601 assert(!err); 602 603 inst->global_layer_count = count; 604 inst->global_layers = global_layers; 605 606 for (uint32_t i = 0; i < inst->global_layer_count; i++) { 607 VkLayerProperties *src_info = &global_layer_properties[i]; 608 struct layer_extension_list *dst_info = &inst->global_layers[i]; 609 memcpy(&dst_info->layer_properties, src_info, sizeof(VkLayerProperties)); 610 611 /* Save away layer extension info for report */ 612 app_get_global_layer_extensions( 613 src_info->layerName, 614 &dst_info->extension_count, 615 &dst_info->extension_properties); 616 } 617 free(global_layer_properties); 618 619 /* Collect global extensions */ 620 inst->global_extension_count = 0; 621 app_get_global_layer_extensions( 622 NULL, 623 &inst->global_extension_count, 624 &inst->global_extensions); 625 626 for (uint32_t i = 0; i < ARRAY_SIZE(known_extensions); i++) { 627 VkBool32 extension_found = 0; 628 for (uint32_t j = 0; j < inst->global_extension_count; j++) { 629 VkExtensionProperties *extension_prop = &inst->global_extensions[j]; 630 if (!strcmp(known_extensions[i], extension_prop->extName)) { 631 632 extension_found = 1; 633 global_extension_count++; 634 } 635 } 636 if (!extension_found) { 637 printf("Cannot find extension: %s\n", known_extensions[i]); 638 ERR_EXIT(VK_ERROR_INVALID_EXTENSION); 639 } 640 } 641 642 inst_info.extensionCount = global_extension_count; 643 inst_info.ppEnabledExtensionNames = (const char * const *) known_extensions; 644 645 err = vkCreateInstance(&inst_info, &inst->instance); 646 if (err == VK_ERROR_INCOMPATIBLE_DRIVER) { 647 printf("Cannot create Vulkan instance.\n"); 648 ERR_EXIT(err); 649 } else if (err) { 650 ERR_EXIT(err); 651 } 652} 653 654static void app_destroy_instance(struct app_instance *inst) 655{ 656 free(inst->global_extensions); 657 vkDestroyInstance(inst->instance); 658} 659 660 661static void app_gpu_init(struct app_gpu *gpu, uint32_t id, VkPhysicalDevice obj) 662{ 663 VkResult err; 664 uint32_t i; 665 666 memset(gpu, 0, sizeof(*gpu)); 667 668 gpu->id = id; 669 gpu->obj = obj; 670 671 err = vkGetPhysicalDeviceProperties(gpu->obj, &gpu->props); 672 if (err) 673 ERR_EXIT(err); 674 675 /* get queue count */ 676 err = vkGetPhysicalDeviceQueueFamilyProperties(gpu->obj, &gpu->queue_count, NULL); 677 if (err) 678 ERR_EXIT(err); 679 680 gpu->queue_props = 681 malloc(sizeof(gpu->queue_props[0]) * gpu->queue_count); 682 683 if (!gpu->queue_props) 684 ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY); 685 err = vkGetPhysicalDeviceQueueFamilyProperties(gpu->obj, &gpu->queue_count, gpu->queue_props); 686 if (err) 687 ERR_EXIT(err); 688 689 /* set up queue requests */ 690 gpu->queue_reqs = malloc(sizeof(*gpu->queue_reqs) * gpu->queue_count); 691 if (!gpu->queue_reqs) 692 ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY); 693 for (i = 0; i < gpu->queue_count; i++) { 694 gpu->queue_reqs[i].queueFamilyIndex = i; 695 gpu->queue_reqs[i].queueCount = gpu->queue_props[i].queueCount; 696 } 697 698 err = vkGetPhysicalDeviceMemoryProperties(gpu->obj, &gpu->memory_props); 699 if (err) 700 ERR_EXIT(err); 701 702 err = vkGetPhysicalDeviceFeatures(gpu->obj, &gpu->features); 703 if (err) 704 ERR_EXIT(err); 705 706 err = vkGetPhysicalDeviceLimits(gpu->obj, &gpu->limits); 707 if (err) 708 ERR_EXIT(err); 709 710 app_dev_init(&gpu->dev, gpu); 711 app_dev_init_formats(&gpu->dev); 712} 713 714static void app_gpu_destroy(struct app_gpu *gpu) 715{ 716 app_dev_destroy(&gpu->dev); 717 free(gpu->device_extensions); 718 free(gpu->queue_reqs); 719 free(gpu->queue_props); 720} 721 722static void app_dev_dump_format_props(const struct app_dev *dev, VkFormat fmt) 723{ 724 const VkFormatProperties *props = &dev->format_props[fmt]; 725 struct { 726 const char *name; 727 VkFlags flags; 728 } features[3]; 729 uint32_t i; 730 731 features[0].name = "linearTiling FormatFeatureFlags"; 732 features[0].flags = props->linearTilingFeatures; 733 features[1].name = "optimalTiling FormatFeatureFlags"; 734 features[1].flags = props->optimalTilingFeatures; 735 features[2].name = "bufferFeatures FormatFeatureFlags"; 736 features[2].flags = props->bufferFeatures; 737 738 printf("\nFORMAT_%s:", vk_format_string(fmt)); 739 for (i = 0; i < ARRAY_SIZE(features); i++) { 740 printf("\n\t%s:", features[i].name); 741 if (features[i].flags == 0) { 742 printf("\n\t\tNone"); 743 } else { 744 printf("%s%s%s%s%s%s%s%s%s%s%s%s%s", 745 ((features[i].flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) ? "\n\t\tVK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT" : ""), 746 ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) ? "\n\t\tVK_FORMAT_FEATURE_STORAGE_IMAGE_BIT" : ""), 747 ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT) ? "\n\t\tVK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT" : ""), 748 ((features[i].flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) ? "\n\t\tVK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT" : ""), 749 ((features[i].flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT) ? "\n\t\tVK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT" : ""), 750 ((features[i].flags & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) ? "\n\t\tVK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT" : ""), 751 ((features[i].flags & VK_FORMAT_FEATURE_CONVERSION_BIT) ? "\n\t\tVK_FORMAT_FEATURE_CONVERSION_BIT" : ""), 752 ((features[i].flags & VK_FORMAT_FEATURE_BLIT_SOURCE_BIT) ? "\n\t\tVK_FORMAT_FEATURE_BLIT_SOURCE_BIT" : ""), 753 ((features[i].flags & VK_FORMAT_FEATURE_BLIT_DESTINATION_BIT) ? "\n\t\tVK_FORMAT_FEATURE_BLIT_DESTINATION_BIT" : ""), 754 ((features[i].flags & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT) ? "\n\t\tVK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT" : ""), 755 ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT) ? "\n\t\tVK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT" : ""), 756 ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT) ? "\n\t\tVK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT" : ""), 757 ((features[i].flags & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) ? "\n\t\tVK_FORMAT_FEATURE_VERTEX_BUFFER_BIT" : "")); 758 } 759 } 760 printf("\n"); 761} 762 763 764static void 765app_dev_dump(const struct app_dev *dev) 766{ 767 VkFormat fmt; 768 769 for (fmt = 0; fmt < VK_FORMAT_NUM; fmt++) { 770 app_dev_dump_format_props(dev, fmt); 771 } 772} 773 774#ifdef _WIN32 775#define PRINTF_SIZE_T_SPECIFIER "%Iu" 776#else 777#define PRINTF_SIZE_T_SPECIFIER "%zu" 778#endif 779 780static void app_gpu_dump_features(const struct app_gpu *gpu) 781{ 782 const VkPhysicalDeviceFeatures *features = &gpu->features; 783 784 printf("VkPhysicalDeviceFeatures:\n"); 785 printf("=========================\n"); 786 787 printf("\trobustBufferAccess = %u\n", features->robustBufferAccess ); 788 printf("\tfullDrawIndexUint32 = %u\n", features->fullDrawIndexUint32 ); 789 printf("\timageCubeArray = %u\n", features->imageCubeArray ); 790 printf("\tindependentBlend = %u\n", features->independentBlend ); 791 printf("\tgeometryShader = %u\n", features->geometryShader ); 792 printf("\ttessellationShader = %u\n", features->tessellationShader ); 793 printf("\tsampleRateShading = %u\n", features->sampleRateShading ); 794 printf("\tdualSourceBlend = %u\n", features->dualSourceBlend ); 795 printf("\tlogicOp = %u\n", features->logicOp ); 796 printf("\tmultiDrawIndirect = %u\n", features->multiDrawIndirect ); 797 printf("\tdepthClip = %u\n", features->depthClip ); 798 printf("\tdepthBiasClamp = %u\n", features->depthBiasClamp ); 799 printf("\tfillModeNonSolid = %u\n", features->fillModeNonSolid ); 800 printf("\tdepthBounds = %u\n", features->depthBounds ); 801 printf("\twideLines = %u\n", features->wideLines ); 802 printf("\tlargePoints = %u\n", features->largePoints ); 803 printf("\ttextureCompressionETC2 = %u\n", features->textureCompressionETC2 ); 804 printf("\ttextureCompressionASTC_LDR = %u\n", features->textureCompressionASTC_LDR ); 805 printf("\ttextureCompressionBC = %u\n", features->textureCompressionBC ); 806 printf("\tpipelineStatisticsQuery = %u\n", features->pipelineStatisticsQuery ); 807 printf("\tvertexSideEffects = %u\n", features->vertexSideEffects ); 808 printf("\ttessellationSideEffects = %u\n", features->tessellationSideEffects ); 809 printf("\tgeometrySideEffects = %u\n", features->geometrySideEffects ); 810 printf("\tfragmentSideEffects = %u\n", features->fragmentSideEffects ); 811 printf("\tshaderTessellationPointSize = %u\n", features->shaderTessellationPointSize ); 812 printf("\tshaderGeometryPointSize = %u\n", features->shaderGeometryPointSize ); 813 printf("\tshaderImageGatherExtended = %u\n", features->shaderImageGatherExtended ); 814 printf("\tshaderStorageImageExtendedFormats = %u\n", features->shaderStorageImageExtendedFormats ); 815 printf("\tshaderStorageImageMultisample = %u\n", features->shaderStorageImageMultisample ); 816 printf("\tshaderUniformBufferArrayDynamicIndexing = %u\n", features->shaderUniformBufferArrayDynamicIndexing); 817 printf("\tshaderSampledImageArrayDynamicIndexing = %u\n", features->shaderSampledImageArrayDynamicIndexing ); 818 printf("\tshaderStorageBufferArrayDynamicIndexing = %u\n", features->shaderStorageBufferArrayDynamicIndexing); 819 printf("\tshaderStorageImageArrayDynamicIndexing = %u\n", features->shaderStorageImageArrayDynamicIndexing ); 820 printf("\tshaderClipDistance = %u\n", features->shaderClipDistance ); 821 printf("\tshaderCullDistance = %u\n", features->shaderCullDistance ); 822 printf("\tshaderFloat64 = %u\n", features->shaderFloat64 ); 823 printf("\tshaderInt64 = %u\n", features->shaderInt64 ); 824 printf("\tshaderInt16 = %u\n", features->shaderInt16 ); 825 printf("\tshaderResourceResidency = %u\n", features->shaderResourceResidency ); 826 printf("\tshaderResourceMinLOD = %u\n", features->shaderResourceMinLOD ); 827 printf("\talphaToOne = %u\n", features->alphaToOne ); 828 printf("\tsparse = %u\n", features->sparse ); 829 printf("\tsparseResidencyBuffer = %u\n", features->sparseResidencyBuffer ); 830 printf("\tsparseResidencyImage2D = %u\n", features->sparseResidencyImage2D ); 831 printf("\tsparseResidencyImage3D = %u\n", features->sparseResidencyImage3D ); 832 printf("\tsparseResidency2Samples = %u\n", features->sparseResidency2Samples ); 833 printf("\tsparseResidency4Samples = %u\n", features->sparseResidency4Samples ); 834 printf("\tsparseResidency8Samples = %u\n", features->sparseResidency8Samples ); 835 printf("\tsparseResidency16Samples = %u\n", features->sparseResidency16Samples ); 836 printf("\tsparseResidencyStandard2DBlockShape = %u\n", features->sparseResidencyStandard2DBlockShape ); 837 printf("\tsparseResidencyStandard2DMSBlockShape = %u\n", features->sparseResidencyStandard2DMSBlockShape ); 838 printf("\tsparseResidencyStandard3DBlockShape = %u\n", features->sparseResidencyStandard3DBlockShape ); 839 printf("\tsparseResidencyAlignedMipSize = %u\n", features->sparseResidencyAlignedMipSize ); 840 printf("\tsparseResidencyNonResident = %u\n", features->sparseResidencyNonResident ); 841 printf("\tsparseResidencyNonResidentStrict = %u\n", features->sparseResidencyNonResidentStrict ); 842 printf("\tsparseResidencyAliased = %u\n", features->sparseResidencyAliased ); 843} 844 845static void app_gpu_dump_limits(const struct app_gpu *gpu) 846{ 847 const VkPhysicalDeviceLimits *limits = &gpu->limits; 848 849 printf("VkPhysicalDeviceLimits:\n"); 850 printf("=======================\n"); 851 852 printf("\tmaxImageDimension1D = 0x%" PRIxLEAST32 "\n", limits->maxImageDimension1D ); 853 printf("\tmaxImageDimension2D = 0x%" PRIxLEAST32 "\n", limits->maxImageDimension2D ); 854 printf("\tmaxImageDimension3D = 0x%" PRIxLEAST32 "\n", limits->maxImageDimension3D ); 855 printf("\tmaxImageDimensionCube = 0x%" PRIxLEAST32 "\n", limits->maxImageDimensionCube ); 856 printf("\tmaxImageArrayLayers = 0x%" PRIxLEAST32 "\n", limits->maxImageArrayLayers ); 857 printf("\tmaxTexelBufferSize = 0x%" PRIxLEAST32 "\n", limits->maxTexelBufferSize ); 858 printf("\tmaxUniformBufferSize = 0x%" PRIxLEAST32 "\n", limits->maxUniformBufferSize ); 859 printf("\tmaxStorageBufferSize = 0x%" PRIxLEAST32 "\n", limits->maxStorageBufferSize ); 860 printf("\tmaxPushConstantsSize = 0x%" PRIxLEAST32 "\n", limits->maxPushConstantsSize ); 861 printf("\tmaxMemoryAllocationCount = 0x%" PRIxLEAST32 "\n", limits->maxMemoryAllocationCount ); 862 printf("\tbufferImageGranularity = 0x%" PRIxLEAST64 "\n", limits->bufferImageGranularity ); 863 printf("\tmaxBoundDescriptorSets = 0x%" PRIxLEAST32 "\n", limits->maxBoundDescriptorSets ); 864 printf("\tmaxDescriptorSets = 0x%" PRIxLEAST32 "\n", limits->maxDescriptorSets ); 865 printf("\tmaxPerStageDescriptorSamplers = 0x%" PRIxLEAST32 "\n", limits->maxPerStageDescriptorSamplers ); 866 printf("\tmaxPerStageDescriptorUniformBuffers = 0x%" PRIxLEAST32 "\n", limits->maxPerStageDescriptorUniformBuffers ); 867 printf("\tmaxPerStageDescriptorStorageBuffers = 0x%" PRIxLEAST32 "\n", limits->maxPerStageDescriptorStorageBuffers ); 868 printf("\tmaxPerStageDescriptorSampledImages = 0x%" PRIxLEAST32 "\n", limits->maxPerStageDescriptorSampledImages ); 869 printf("\tmaxPerStageDescriptorStorageImages = 0x%" PRIxLEAST32 "\n", limits->maxPerStageDescriptorStorageImages ); 870 printf("\tmaxDescriptorSetSamplers = 0x%" PRIxLEAST32 "\n", limits->maxDescriptorSetSamplers ); 871 printf("\tmaxDescriptorSetUniformBuffers = 0x%" PRIxLEAST32 "\n", limits->maxDescriptorSetUniformBuffers ); 872 printf("\tmaxDescriptorSetStorageBuffers = 0x%" PRIxLEAST32 "\n", limits->maxDescriptorSetStorageBuffers ); 873 printf("\tmaxDescriptorSetSampledImages = 0x%" PRIxLEAST32 "\n", limits->maxDescriptorSetSampledImages ); 874 printf("\tmaxDescriptorSetStorageImages = 0x%" PRIxLEAST32 "\n", limits->maxDescriptorSetStorageImages ); 875 printf("\tmaxVertexInputAttributes = 0x%" PRIxLEAST32 "\n", limits->maxVertexInputAttributes ); 876 printf("\tmaxVertexInputAttributeOffset = 0x%" PRIxLEAST32 "\n", limits->maxVertexInputAttributeOffset ); 877 printf("\tmaxVertexInputBindingStride = 0x%" PRIxLEAST32 "\n", limits->maxVertexInputBindingStride ); 878 printf("\tmaxVertexOutputComponents = 0x%" PRIxLEAST32 "\n", limits->maxVertexOutputComponents ); 879 printf("\tmaxTessGenLevel = 0x%" PRIxLEAST32 "\n", limits->maxTessGenLevel ); 880 printf("\tmaxTessPatchSize = 0x%" PRIxLEAST32 "\n", limits->maxTessPatchSize ); 881 printf("\tmaxTessControlPerVertexInputComponents = 0x%" PRIxLEAST32 "\n", limits->maxTessControlPerVertexInputComponents ); 882 printf("\tmaxTessControlPerVertexOutputComponents = 0x%" PRIxLEAST32 "\n", limits->maxTessControlPerVertexOutputComponents); 883 printf("\tmaxTessControlPerPatchOutputComponents = 0x%" PRIxLEAST32 "\n", limits->maxTessControlPerPatchOutputComponents ); 884 printf("\tmaxTessControlTotalOutputComponents = 0x%" PRIxLEAST32 "\n", limits->maxTessControlTotalOutputComponents ); 885 printf("\tmaxTessEvaluationInputComponents = 0x%" PRIxLEAST32 "\n", limits->maxTessEvaluationInputComponents ); 886 printf("\tmaxTessEvaluationOutputComponents = 0x%" PRIxLEAST32 "\n", limits->maxTessEvaluationOutputComponents ); 887 printf("\tmaxGeometryShaderInvocations = 0x%" PRIxLEAST32 "\n", limits->maxGeometryShaderInvocations ); 888 printf("\tmaxGeometryInputComponents = 0x%" PRIxLEAST32 "\n", limits->maxGeometryInputComponents ); 889 printf("\tmaxGeometryOutputComponents = 0x%" PRIxLEAST32 "\n", limits->maxGeometryOutputComponents ); 890 printf("\tmaxGeometryOutputVertices = 0x%" PRIxLEAST32 "\n", limits->maxGeometryOutputVertices ); 891 printf("\tmaxGeometryTotalOutputComponents = 0x%" PRIxLEAST32 "\n", limits->maxGeometryTotalOutputComponents ); 892 printf("\tmaxFragmentInputComponents = 0x%" PRIxLEAST32 "\n", limits->maxFragmentInputComponents ); 893 printf("\tmaxFragmentOutputBuffers = 0x%" PRIxLEAST32 "\n", limits->maxFragmentOutputBuffers ); 894 printf("\tmaxFragmentDualSourceBuffers = 0x%" PRIxLEAST32 "\n", limits->maxFragmentDualSourceBuffers ); 895 printf("\tmaxFragmentCombinedOutputResources = 0x%" PRIxLEAST32 "\n", limits->maxFragmentCombinedOutputResources ); 896 printf("\tmaxComputeSharedMemorySize = 0x%" PRIxLEAST32 "\n", limits->maxComputeSharedMemorySize ); 897 printf("\tmaxComputeWorkGroupCount[0] = 0x%" PRIxLEAST32 "\n", limits->maxComputeWorkGroupCount[0] ); 898 printf("\tmaxComputeWorkGroupCount[1] = 0x%" PRIxLEAST32 "\n", limits->maxComputeWorkGroupCount[1] ); 899 printf("\tmaxComputeWorkGroupCount[2] = 0x%" PRIxLEAST32 "\n", limits->maxComputeWorkGroupCount[2] ); 900 printf("\tmaxComputeWorkGroupInvocations = 0x%" PRIxLEAST32 "\n", limits->maxComputeWorkGroupInvocations ); 901 printf("\tmaxComputeWorkGroupSize[0] = 0x%" PRIxLEAST32 "\n", limits->maxComputeWorkGroupSize[0] ); 902 printf("\tmaxComputeWorkGroupSize[1] = 0x%" PRIxLEAST32 "\n", limits->maxComputeWorkGroupSize[1] ); 903 printf("\tmaxComputeWorkGroupSize[2] = 0x%" PRIxLEAST32 "\n", limits->maxComputeWorkGroupSize[2] ); 904 printf("\tsubPixelPrecisionBits = 0x%" PRIxLEAST32 "\n", limits->subPixelPrecisionBits ); 905 printf("\tsubTexelPrecisionBits = 0x%" PRIxLEAST32 "\n", limits->subTexelPrecisionBits ); 906 printf("\tmipmapPrecisionBits = 0x%" PRIxLEAST32 "\n", limits->mipmapPrecisionBits ); 907 printf("\tmaxDrawIndexedIndexValue = 0x%" PRIxLEAST32 "\n", limits->maxDrawIndexedIndexValue ); 908 printf("\tmaxDrawIndirectInstanceCount = 0x%" PRIxLEAST32 "\n", limits->maxDrawIndirectInstanceCount ); 909 printf("\tprimitiveRestartForPatches = 0x%" PRIxLEAST32 "\n", limits->primitiveRestartForPatches ); 910 printf("\tmaxSamplerLodBias = %f\n", limits->maxSamplerLodBias ); 911 printf("\tmaxSamplerAnisotropy = %f\n", limits->maxSamplerAnisotropy ); 912 printf("\tmaxViewports = 0x%" PRIxLEAST32 "\n", limits->maxViewports ); 913 printf("\tmaxDynamicViewportStates = 0x%" PRIxLEAST32 "\n", limits->maxDynamicViewportStates ); 914 printf("\tmaxViewportDimensions[0] = 0x%" PRIxLEAST32 "\n", limits->maxViewportDimensions[0] ); 915 printf("\tmaxViewportDimensions[1] = 0x%" PRIxLEAST32 "\n", limits->maxViewportDimensions[1] ); 916 printf("\tviewportBoundsRange[0] = %f\n", limits->viewportBoundsRange[0] ); 917 printf("\tviewportBoundsRange[1] = %f\n", limits->viewportBoundsRange[1] ); 918 printf("\tviewportSubPixelBits = 0x%" PRIxLEAST32 "\n", limits->viewportSubPixelBits ); 919 printf("\tminMemoryMapAlignment = 0x%" PRIxLEAST32 "\n", limits->minMemoryMapAlignment ); 920 printf("\tminTexelBufferOffsetAlignment = 0x%" PRIxLEAST32 "\n", limits->minTexelBufferOffsetAlignment ); 921 printf("\tminUniformBufferOffsetAlignment = 0x%" PRIxLEAST32 "\n", limits->minUniformBufferOffsetAlignment ); 922 printf("\tminStorageBufferOffsetAlignment = 0x%" PRIxLEAST32 "\n", limits->minStorageBufferOffsetAlignment ); 923 printf("\tminTexelOffset = 0x%" PRIxLEAST32 "\n", limits->minTexelOffset ); 924 printf("\tmaxTexelOffset = 0x%" PRIxLEAST32 "\n", limits->maxTexelOffset ); 925 printf("\tminTexelGatherOffset = 0x%" PRIxLEAST32 "\n", limits->minTexelGatherOffset ); 926 printf("\tmaxTexelGatherOffset = 0x%" PRIxLEAST32 "\n", limits->maxTexelGatherOffset ); 927 printf("\tminInterpolationOffset = %f\n", limits->minInterpolationOffset ); 928 printf("\tmaxInterpolationOffset = %f\n", limits->maxInterpolationOffset ); 929 printf("\tsubPixelInterpolationOffsetBits = 0x%" PRIxLEAST32 "\n", limits->subPixelInterpolationOffsetBits ); 930 printf("\tmaxFramebufferWidth = 0x%" PRIxLEAST32 "\n", limits->maxFramebufferWidth ); 931 printf("\tmaxFramebufferHeight = 0x%" PRIxLEAST32 "\n", limits->maxFramebufferHeight ); 932 printf("\tmaxFramebufferLayers = 0x%" PRIxLEAST32 "\n", limits->maxFramebufferLayers ); 933 printf("\tmaxFramebufferColorSamples = 0x%" PRIxLEAST32 "\n", limits->maxFramebufferColorSamples ); 934 printf("\tmaxFramebufferDepthSamples = 0x%" PRIxLEAST32 "\n", limits->maxFramebufferDepthSamples ); 935 printf("\tmaxFramebufferStencilSamples = 0x%" PRIxLEAST32 "\n", limits->maxFramebufferStencilSamples ); 936 printf("\tmaxColorAttachments = 0x%" PRIxLEAST32 "\n", limits->maxColorAttachments ); 937 printf("\tmaxSampledImageColorSamples = 0x%" PRIxLEAST32 "\n", limits->maxSampledImageColorSamples ); 938 printf("\tmaxSampledImageDepthSamples = 0x%" PRIxLEAST32 "\n", limits->maxSampledImageDepthSamples ); 939 printf("\tmaxSampledImageIntegerSamples = 0x%" PRIxLEAST32 "\n", limits->maxSampledImageIntegerSamples ); 940 printf("\tmaxStorageImageSamples = 0x%" PRIxLEAST32 "\n", limits->maxStorageImageSamples ); 941 printf("\tmaxSampleMaskWords = 0x%" PRIxLEAST32 "\n", limits->maxSampleMaskWords ); 942 printf("\ttimestampFrequency = 0x%" PRIxLEAST64 "\n", limits->timestampFrequency ); 943 printf("\tmaxClipDistances = 0x%" PRIxLEAST32 "\n", limits->maxClipDistances ); 944 printf("\tmaxCullDistances = 0x%" PRIxLEAST32 "\n", limits->maxCullDistances ); 945 printf("\tmaxCombinedClipAndCullDistances = 0x%" PRIxLEAST32 "\n", limits->maxCombinedClipAndCullDistances ); 946 printf("\tpointSizeRange[0] = %f\n", limits->pointSizeRange[0] ); 947 printf("\tpointSizeRange[1] = %f\n", limits->pointSizeRange[1] ); 948 printf("\tlineWidthRange[0] = %f\n", limits->lineWidthRange[0] ); 949 printf("\tlineWidthRange[1] = %f\n", limits->lineWidthRange[1] ); 950 printf("\tpointSizeGranularity = %f\n", limits->pointSizeGranularity ); 951 printf("\tlineWidthGranularity = %f\n", limits->lineWidthGranularity ); 952} 953 954static void app_gpu_dump_props(const struct app_gpu *gpu) 955{ 956 const VkPhysicalDeviceProperties *props = &gpu->props; 957 958 printf("VkPhysicalDeviceProperties:\n"); 959 printf("===========================\n"); 960 printf("\tapiVersion = %u\n", props->apiVersion); 961 printf("\tdriverVersion = %u\n", props->driverVersion); 962 printf("\tvendorId = 0x%04x\n", props->vendorId); 963 printf("\tdeviceId = 0x%04x\n", props->deviceId); 964 printf("\tdeviceType = %s\n", vk_physical_device_type_string(props->deviceType)); 965 printf("\tdeviceName = %s\n", props->deviceName); 966 fflush(stdout); 967} 968 969static void app_dump_extensions( 970 const char *indent, 971 const char *layer_name, 972 const uint32_t extension_count, 973 const VkExtensionProperties *extension_properties) 974{ 975 uint32_t i; 976 if (layer_name && (strlen(layer_name) > 0)) { 977 printf("%s%s Extensions", indent, layer_name); 978 } else { 979 printf("Extensions"); 980 } 981 printf("\tcount = %d\n", extension_count); 982 for (i=0; i< extension_count; i++) { 983 VkExtensionProperties const *ext_prop = &extension_properties[i]; 984 985 if (i>0) 986 printf("\n"); // separator between extensions 987 988 printf("%s\t", indent); 989 printf("%-32s: extension revision %2d", 990 ext_prop->extName, ext_prop->specVersion); 991 } 992 printf("\n"); 993 fflush(stdout); 994} 995 996static void app_gpu_dump_queue_props(const struct app_gpu *gpu, uint32_t id) 997{ 998 const VkQueueFamilyProperties *props = &gpu->queue_props[id]; 999 1000 printf("VkQueueFamilyProperties[%d]:\n", id); 1001 printf("============================\n"); 1002 printf("\tqueueFlags = %c%c%c%c\n", 1003 (props->queueFlags & VK_QUEUE_GRAPHICS_BIT) ? 'G' : '.', 1004 (props->queueFlags & VK_QUEUE_COMPUTE_BIT) ? 'C' : '.', 1005 (props->queueFlags & VK_QUEUE_DMA_BIT) ? 'D' : '.', 1006 (props->queueFlags & VK_QUEUE_EXTENDED_BIT) ? 'X' : '.'); 1007 printf("\tqueueCount = %u\n", props->queueCount); 1008 printf("\tsupportsTimestamps = %u\n", props->supportsTimestamps); 1009 fflush(stdout); 1010} 1011 1012static void app_gpu_dump_memory_props(const struct app_gpu *gpu) 1013{ 1014 const VkPhysicalDeviceMemoryProperties *props = &gpu->memory_props; 1015 1016 printf("VkPhysicalDeviceMemoryProperties:\n"); 1017 printf("=================================\n"); 1018 printf("\tmemoryTypeCount = %u\n", props->memoryTypeCount); 1019 for (uint32_t i = 0; i < props->memoryTypeCount; i++) { 1020 printf("\tmemoryTypes[%u] : \n", i); 1021 printf("\t\tpropertyFlags = %u\n", props->memoryTypes[i].propertyFlags); 1022 printf("\t\theapIndex = %u\n", props->memoryTypes[i].heapIndex); 1023 } 1024 printf("\tmemoryHeapCount = %u\n", props->memoryHeapCount); 1025 for (uint32_t i = 0; i < props->memoryHeapCount; i++) { 1026 printf("\tmemoryHeaps[%u] : \n", i); 1027 printf("\t\tsize = " PRINTF_SIZE_T_SPECIFIER "\n", props->memoryHeaps[i].size); 1028 } 1029 fflush(stdout); 1030} 1031 1032static void app_gpu_dump(const struct app_gpu *gpu) 1033{ 1034 uint32_t i; 1035 1036 printf("Device Extensions and layers:\n"); 1037 printf("=============================\n"); 1038 printf("GPU%u\n", gpu->id); 1039 app_gpu_dump_props(gpu); 1040 printf("\n"); 1041 app_dump_extensions("", "Device", gpu->device_extension_count, gpu->device_extensions); 1042 printf("\n"); 1043 printf("Layers\tcount = %d\n", gpu->device_layer_count); 1044 for (uint32_t i = 0; i < gpu->device_layer_count; i++) { 1045 uint32_t major, minor, patch; 1046 char spec_version[64], layer_version[64]; 1047 struct layer_extension_list const *layer_info = &gpu->device_layers[i]; 1048 1049 extract_version(layer_info->layer_properties.specVersion, &major, &minor, &patch); 1050 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d", major, minor, patch); 1051 extract_version(layer_info->layer_properties.implVersion, &major, &minor, &patch); 1052 snprintf(layer_version, sizeof(layer_version), "%d.%d.%d", major, minor, patch); 1053 printf("\t%s (%s) Vulkan version %s, layer version %s\n", 1054 layer_info->layer_properties.layerName, 1055 (char*) layer_info->layer_properties.description, 1056 spec_version, layer_version); 1057 1058 app_dump_extensions("\t", 1059 layer_info->layer_properties.layerName, 1060 layer_info->extension_count, 1061 layer_info->extension_properties); 1062 fflush(stdout); 1063 } 1064 printf("\n"); 1065 for (i = 0; i < gpu->queue_count; i++) { 1066 app_gpu_dump_queue_props(gpu, i); 1067 printf("\n"); 1068 } 1069 app_gpu_dump_memory_props(gpu); 1070 printf("\n"); 1071 app_gpu_dump_features(gpu); 1072 printf("\n"); 1073 app_gpu_dump_limits(gpu); 1074 printf("\n"); 1075 app_dev_dump(&gpu->dev); 1076} 1077 1078int main(int argc, char **argv) 1079{ 1080 struct app_gpu gpus[MAX_GPUS]; 1081 VkPhysicalDevice objs[MAX_GPUS]; 1082 uint32_t gpu_count, i; 1083 VkResult err; 1084 struct app_instance inst; 1085 1086 app_create_instance(&inst); 1087 1088 printf("Instance Extensions and layers:\n"); 1089 printf("===============================\n"); 1090 app_dump_extensions("", "Instance", inst.global_extension_count, inst.global_extensions); 1091 1092 printf("Instance Layers\tcount = %d\n", inst.global_layer_count); 1093 for (uint32_t i = 0; i < inst.global_layer_count; i++) { 1094 uint32_t major, minor, patch; 1095 char spec_version[64], layer_version[64]; 1096 VkLayerProperties const *layer_prop = &inst.global_layers[i].layer_properties; 1097 1098 extract_version(layer_prop->specVersion, &major, &minor, &patch); 1099 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d", major, minor, patch); 1100 extract_version(layer_prop->implVersion, &major, &minor, &patch); 1101 snprintf(layer_version, sizeof(layer_version), "%d.%d.%d", major, minor, patch); 1102 printf("\t%s (%s) Vulkan version %s, layer version %s\n", 1103 layer_prop->layerName, (char*) layer_prop->description, spec_version, layer_version); 1104 1105 app_dump_extensions("\t", 1106 inst.global_layers[i].layer_properties.layerName, 1107 inst.global_layers[i].extension_count, 1108 inst.global_layers[i].extension_properties); 1109 } 1110 1111 err = vkEnumeratePhysicalDevices(inst.instance, &gpu_count, NULL); 1112 if (err) 1113 ERR_EXIT(err); 1114 if (gpu_count > MAX_GPUS) { 1115 printf("Too many GPUS found \n"); 1116 ERR_EXIT(VK_ERROR_UNKNOWN); 1117 } 1118 err = vkEnumeratePhysicalDevices(inst.instance, &gpu_count, objs); 1119 if (err) 1120 ERR_EXIT(err); 1121 1122 for (i = 0; i < gpu_count; i++) { 1123 app_gpu_init(&gpus[i], i, objs[i]); 1124 app_gpu_dump(&gpus[i]); 1125 printf("\n\n"); 1126 } 1127 1128 for (i = 0; i < gpu_count; i++) 1129 app_gpu_destroy(&gpus[i]); 1130 1131 app_destroy_instance(&inst); 1132 1133 return 0; 1134} 1135 1136#ifdef _WIN32 1137 1138// Create a console window with a large scrollback size to which to send stdout. 1139// Returns true if console window was successfully created, false otherwise. 1140bool SetStdOutToNewConsole() 1141{ 1142 // don't do anything if we already have a console 1143 if (GetStdHandle(STD_OUTPUT_HANDLE)) 1144 return false; 1145 1146 // allocate a console for this app 1147 AllocConsole(); 1148 1149 // redirect unbuffered STDOUT to the console 1150 HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE); 1151 int fileDescriptor = _open_osfhandle((intptr_t)consoleHandle, _O_TEXT); 1152 FILE *fp = _fdopen( fileDescriptor, "w" ); 1153 *stdout = *fp; 1154 setvbuf( stdout, NULL, _IONBF, 0 ); 1155 1156 // make the console window bigger 1157 CONSOLE_SCREEN_BUFFER_INFO csbi; 1158 SMALL_RECT r; 1159 COORD bufferSize; 1160 if (!GetConsoleScreenBufferInfo(consoleHandle, &csbi)) 1161 return false; 1162 bufferSize.X = csbi.dwSize.X; 1163 bufferSize.Y = 1000; 1164 if (!SetConsoleScreenBufferSize(consoleHandle, bufferSize)) 1165 return false; 1166 r.Left = r.Top = 0; 1167 r.Right = csbi.dwSize.X-1; 1168 r.Bottom = 60; 1169 if (!SetConsoleWindowInfo(consoleHandle, true, &r)) 1170 return false; 1171 1172 // change the console window title 1173 if (!SetConsoleTitle(TEXT(APP_SHORT_NAME))) 1174 return false; 1175 1176 return true; 1177} 1178 1179int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pCmdLine, int nCmdShow) 1180{ 1181 char *argv = pCmdLine; 1182 consoleCreated = SetStdOutToNewConsole(); 1183 main(1, &argv); 1184 fflush(stdout); 1185 if (consoleCreated) 1186 Sleep(INFINITE); 1187} 1188#endif 1189