vulkaninfo.c revision fa6d36ea26354e4d68e81b05d1199a83c9fa3d6a
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 30#ifdef _WIN32 31#include <Windows.h> 32#include <fcntl.h> 33#include <io.h> 34#endif 35 36#include <vulkan.h> 37 38#define ERR(err) printf("%s:%d: failed with %s\n", \ 39 __FILE__, __LINE__, vk_result_string(err)); 40 41#ifdef _WIN32 42 43#define snprintf _snprintf 44 45bool consoleCreated = false; 46 47#define WAIT_FOR_CONSOLE_DESTROY \ 48 do { \ 49 if (consoleCreated) \ 50 Sleep(INFINITE); \ 51 } while (0) 52#else 53 #define WAIT_FOR_CONSOLE_DESTROY 54#endif 55 56 57#define ERR_EXIT(err) \ 58 do { \ 59 ERR(err); \ 60 fflush(stdout); \ 61 WAIT_FOR_CONSOLE_DESTROY; \ 62 exit(-1); \ 63 } while (0) 64 65#if defined(NDEBUG) && defined(__GNUC__) 66#define U_ASSERT_ONLY __attribute__((unused)) 67#else 68#define U_ASSERT_ONLY 69#endif 70 71#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 72 73#define MAX_GPUS 8 74 75#define MAX_QUEUE_TYPES 5 76#define APP_SHORT_NAME "vulkaninfo" 77 78struct app_gpu; 79 80struct app_dev { 81 struct app_gpu *gpu; /* point back to the GPU */ 82 83 VkDevice obj; 84 85 86 VkFormatProperties format_props[VK_NUM_FORMAT]; 87}; 88 89struct layer_extension_list { 90 VkLayerProperties layer_properties; 91 uint32_t extension_count; 92 VkExtensionProperties *extension_properties; 93}; 94 95struct app_instance { 96 VkInstance instance; 97 uint32_t global_layer_count; 98 struct layer_extension_list *global_layers; 99 uint32_t global_extension_count; 100 VkExtensionProperties *global_extensions; 101}; 102 103struct app_gpu { 104 uint32_t id; 105 VkPhysicalDevice obj; 106 107 VkPhysicalDeviceProperties props; 108 VkPhysicalDevicePerformance perf; 109 110 uint32_t queue_count; 111 VkPhysicalDeviceQueueProperties *queue_props; 112 VkDeviceQueueCreateInfo *queue_reqs; 113 114 VkPhysicalDeviceMemoryProperties memory_props; 115 VkPhysicalDeviceFeatures features; 116 VkPhysicalDeviceLimits limits; 117 118 uint32_t device_layer_count; 119 struct layer_extension_list *device_layers; 120 121 uint32_t device_extension_count; 122 VkExtensionProperties *device_extensions; 123 124 struct app_dev dev; 125}; 126 127static const char *vk_result_string(VkResult err) 128{ 129 switch (err) { 130#define STR(r) case r: return #r 131 STR(VK_SUCCESS); 132 STR(VK_UNSUPPORTED); 133 STR(VK_NOT_READY); 134 STR(VK_TIMEOUT); 135 STR(VK_EVENT_SET); 136 STR(VK_EVENT_RESET); 137 STR(VK_ERROR_UNKNOWN); 138 STR(VK_ERROR_UNAVAILABLE); 139 STR(VK_ERROR_INITIALIZATION_FAILED); 140 STR(VK_ERROR_OUT_OF_HOST_MEMORY); 141 STR(VK_ERROR_OUT_OF_DEVICE_MEMORY); 142 STR(VK_ERROR_DEVICE_ALREADY_CREATED); 143 STR(VK_ERROR_DEVICE_LOST); 144 STR(VK_ERROR_INVALID_POINTER); 145 STR(VK_ERROR_INVALID_VALUE); 146 STR(VK_ERROR_INVALID_HANDLE); 147 STR(VK_ERROR_INVALID_ORDINAL); 148 STR(VK_ERROR_INVALID_MEMORY_SIZE); 149 STR(VK_ERROR_INVALID_EXTENSION); 150 STR(VK_ERROR_INVALID_FLAGS); 151 STR(VK_ERROR_INVALID_ALIGNMENT); 152 STR(VK_ERROR_INVALID_FORMAT); 153 STR(VK_ERROR_INVALID_IMAGE); 154 STR(VK_ERROR_INVALID_DESCRIPTOR_SET_DATA); 155 STR(VK_ERROR_INVALID_QUEUE_TYPE); 156 STR(VK_ERROR_UNSUPPORTED_SHADER_IL_VERSION); 157 STR(VK_ERROR_BAD_SHADER_CODE); 158 STR(VK_ERROR_BAD_PIPELINE_DATA); 159 STR(VK_ERROR_NOT_MAPPABLE); 160 STR(VK_ERROR_MEMORY_MAP_FAILED); 161 STR(VK_ERROR_MEMORY_UNMAP_FAILED); 162 STR(VK_ERROR_INCOMPATIBLE_DEVICE); 163 STR(VK_ERROR_INCOMPATIBLE_DRIVER); 164 STR(VK_ERROR_INCOMPLETE_COMMAND_BUFFER); 165 STR(VK_ERROR_BUILDING_COMMAND_BUFFER); 166 STR(VK_ERROR_MEMORY_NOT_BOUND); 167 STR(VK_ERROR_INCOMPATIBLE_QUEUE); 168#undef STR 169 default: return "UNKNOWN_RESULT"; 170 } 171} 172 173static const char *vk_physical_device_type_string(VkPhysicalDeviceType type) 174{ 175 switch (type) { 176#define STR(r) case VK_PHYSICAL_DEVICE_TYPE_ ##r: return #r 177 STR(OTHER); 178 STR(INTEGRATED_GPU); 179 STR(DISCRETE_GPU); 180 STR(VIRTUAL_GPU); 181#undef STR 182 default: return "UNKNOWN_DEVICE"; 183 } 184} 185 186static const char *vk_format_string(VkFormat fmt) 187{ 188 switch (fmt) { 189#define STR(r) case VK_FORMAT_ ##r: return #r 190 STR(UNDEFINED); 191 STR(R4G4_UNORM); 192 STR(R4G4_USCALED); 193 STR(R4G4B4A4_UNORM); 194 STR(R4G4B4A4_USCALED); 195 STR(R5G6B5_UNORM); 196 STR(R5G6B5_USCALED); 197 STR(R5G5B5A1_UNORM); 198 STR(R5G5B5A1_USCALED); 199 STR(R8_UNORM); 200 STR(R8_SNORM); 201 STR(R8_USCALED); 202 STR(R8_SSCALED); 203 STR(R8_UINT); 204 STR(R8_SINT); 205 STR(R8_SRGB); 206 STR(R8G8_UNORM); 207 STR(R8G8_SNORM); 208 STR(R8G8_USCALED); 209 STR(R8G8_SSCALED); 210 STR(R8G8_UINT); 211 STR(R8G8_SINT); 212 STR(R8G8_SRGB); 213 STR(R8G8B8_UNORM); 214 STR(R8G8B8_SNORM); 215 STR(R8G8B8_USCALED); 216 STR(R8G8B8_SSCALED); 217 STR(R8G8B8_UINT); 218 STR(R8G8B8_SINT); 219 STR(R8G8B8_SRGB); 220 STR(R8G8B8A8_UNORM); 221 STR(R8G8B8A8_SNORM); 222 STR(R8G8B8A8_USCALED); 223 STR(R8G8B8A8_SSCALED); 224 STR(R8G8B8A8_UINT); 225 STR(R8G8B8A8_SINT); 226 STR(R8G8B8A8_SRGB); 227 STR(R10G10B10A2_UNORM); 228 STR(R10G10B10A2_SNORM); 229 STR(R10G10B10A2_USCALED); 230 STR(R10G10B10A2_SSCALED); 231 STR(R10G10B10A2_UINT); 232 STR(R10G10B10A2_SINT); 233 STR(R16_UNORM); 234 STR(R16_SNORM); 235 STR(R16_USCALED); 236 STR(R16_SSCALED); 237 STR(R16_UINT); 238 STR(R16_SINT); 239 STR(R16_SFLOAT); 240 STR(R16G16_UNORM); 241 STR(R16G16_SNORM); 242 STR(R16G16_USCALED); 243 STR(R16G16_SSCALED); 244 STR(R16G16_UINT); 245 STR(R16G16_SINT); 246 STR(R16G16_SFLOAT); 247 STR(R16G16B16_UNORM); 248 STR(R16G16B16_SNORM); 249 STR(R16G16B16_USCALED); 250 STR(R16G16B16_SSCALED); 251 STR(R16G16B16_UINT); 252 STR(R16G16B16_SINT); 253 STR(R16G16B16_SFLOAT); 254 STR(R16G16B16A16_UNORM); 255 STR(R16G16B16A16_SNORM); 256 STR(R16G16B16A16_USCALED); 257 STR(R16G16B16A16_SSCALED); 258 STR(R16G16B16A16_UINT); 259 STR(R16G16B16A16_SINT); 260 STR(R16G16B16A16_SFLOAT); 261 STR(R32_UINT); 262 STR(R32_SINT); 263 STR(R32_SFLOAT); 264 STR(R32G32_UINT); 265 STR(R32G32_SINT); 266 STR(R32G32_SFLOAT); 267 STR(R32G32B32_UINT); 268 STR(R32G32B32_SINT); 269 STR(R32G32B32_SFLOAT); 270 STR(R32G32B32A32_UINT); 271 STR(R32G32B32A32_SINT); 272 STR(R32G32B32A32_SFLOAT); 273 STR(R64_SFLOAT); 274 STR(R64G64_SFLOAT); 275 STR(R64G64B64_SFLOAT); 276 STR(R64G64B64A64_SFLOAT); 277 STR(R11G11B10_UFLOAT); 278 STR(R9G9B9E5_UFLOAT); 279 STR(D16_UNORM); 280 STR(D24_UNORM); 281 STR(D32_SFLOAT); 282 STR(S8_UINT); 283 STR(D16_UNORM_S8_UINT); 284 STR(D24_UNORM_S8_UINT); 285 STR(D32_SFLOAT_S8_UINT); 286 STR(BC1_RGB_UNORM); 287 STR(BC1_RGB_SRGB); 288 STR(BC2_UNORM); 289 STR(BC2_SRGB); 290 STR(BC3_UNORM); 291 STR(BC3_SRGB); 292 STR(BC4_UNORM); 293 STR(BC4_SNORM); 294 STR(BC5_UNORM); 295 STR(BC5_SNORM); 296 STR(BC6H_UFLOAT); 297 STR(BC6H_SFLOAT); 298 STR(BC7_UNORM); 299 STR(BC7_SRGB); 300 STR(ETC2_R8G8B8_UNORM); 301 STR(ETC2_R8G8B8A1_UNORM); 302 STR(ETC2_R8G8B8A8_UNORM); 303 STR(EAC_R11_UNORM); 304 STR(EAC_R11_SNORM); 305 STR(EAC_R11G11_UNORM); 306 STR(EAC_R11G11_SNORM); 307 STR(ASTC_4x4_UNORM); 308 STR(ASTC_4x4_SRGB); 309 STR(ASTC_5x4_UNORM); 310 STR(ASTC_5x4_SRGB); 311 STR(ASTC_5x5_UNORM); 312 STR(ASTC_5x5_SRGB); 313 STR(ASTC_6x5_UNORM); 314 STR(ASTC_6x5_SRGB); 315 STR(ASTC_6x6_UNORM); 316 STR(ASTC_6x6_SRGB); 317 STR(ASTC_8x5_UNORM); 318 STR(ASTC_8x5_SRGB); 319 STR(ASTC_8x6_UNORM); 320 STR(ASTC_8x6_SRGB); 321 STR(ASTC_8x8_UNORM); 322 STR(ASTC_8x8_SRGB); 323 STR(ASTC_10x5_UNORM); 324 STR(ASTC_10x5_SRGB); 325 STR(ASTC_10x6_UNORM); 326 STR(ASTC_10x6_SRGB); 327 STR(ASTC_10x8_UNORM); 328 STR(ASTC_10x8_SRGB); 329 STR(ASTC_10x10_UNORM); 330 STR(ASTC_10x10_SRGB); 331 STR(ASTC_12x10_UNORM); 332 STR(ASTC_12x10_SRGB); 333 STR(ASTC_12x12_UNORM); 334 STR(ASTC_12x12_SRGB); 335 STR(B5G6R5_UNORM); 336 STR(B5G6R5_USCALED); 337 STR(B8G8R8_UNORM); 338 STR(B8G8R8_SNORM); 339 STR(B8G8R8_USCALED); 340 STR(B8G8R8_SSCALED); 341 STR(B8G8R8_UINT); 342 STR(B8G8R8_SINT); 343 STR(B8G8R8_SRGB); 344 STR(B8G8R8A8_UNORM); 345 STR(B8G8R8A8_SNORM); 346 STR(B8G8R8A8_USCALED); 347 STR(B8G8R8A8_SSCALED); 348 STR(B8G8R8A8_UINT); 349 STR(B8G8R8A8_SINT); 350 STR(B8G8R8A8_SRGB); 351 STR(B10G10R10A2_UNORM); 352 STR(B10G10R10A2_SNORM); 353 STR(B10G10R10A2_USCALED); 354 STR(B10G10R10A2_SSCALED); 355 STR(B10G10R10A2_UINT); 356 STR(B10G10R10A2_SINT); 357#undef STR 358 default: return "UNKNOWN_FORMAT"; 359 } 360} 361 362static void app_dev_init_formats(struct app_dev *dev) 363{ 364 VkFormat f; 365 366 for (f = 0; f < VK_NUM_FORMAT; f++) { 367 const VkFormat fmt = f; 368 VkResult err; 369 370 err = vkGetPhysicalDeviceFormatInfo(dev->gpu->obj, fmt, &dev->format_props[f]); 371 if (err) { 372 memset(&dev->format_props[f], 0, 373 sizeof(dev->format_props[f])); 374 } 375 } 376} 377 378static void extract_version(uint32_t version, uint32_t *major, uint32_t *minor, uint32_t *patch) 379{ 380 *major = version >> 22; 381 *minor = (version >> 12) & 0x3ff; 382 *patch = version & 0xfff; 383} 384 385static void app_get_physical_device_layer_extensions( 386 struct app_gpu *gpu, 387 char *layer_name, 388 uint32_t *extension_count, 389 VkExtensionProperties **extension_properties) 390{ 391 VkResult err; 392 uint32_t ext_count = 0; 393 VkExtensionProperties *ext_ptr = NULL; 394 395 /* repeat get until VK_INCOMPLETE goes away */ 396 do { 397 err = vkGetPhysicalDeviceExtensionProperties(gpu->obj, layer_name, &ext_count, NULL); 398 assert(!err); 399 400 if (ext_ptr) { 401 free(ext_ptr); 402 } 403 ext_ptr = malloc(ext_count * sizeof(VkExtensionProperties)); 404 err = vkGetPhysicalDeviceExtensionProperties(gpu->obj, layer_name, &ext_count, ext_ptr); 405 } while (err == VK_INCOMPLETE); 406 assert(!err); 407 408 *extension_count = ext_count; 409 *extension_properties = ext_ptr; 410} 411 412static void app_dev_init(struct app_dev *dev, struct app_gpu *gpu) 413{ 414 VkDeviceCreateInfo info = { 415 .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, 416 .pNext = NULL, 417 .queueRecordCount = 0, 418 .pRequestedQueues = NULL, 419 .layerCount = 0, 420 .ppEnabledLayerNames = NULL, 421 .extensionCount = 0, 422 .ppEnabledExtensionNames = NULL, 423 .flags = 0, 424 }; 425 VkResult U_ASSERT_ONLY err; 426 // Extensions to enable 427 static const char *known_extensions[] = { 428 //TODO add WSI device extension WSI swapchain, WSI_LUNARG is a global extension 429 "" 430 }; 431 432 uint32_t count = 0; 433 434 /* Scan layers */ 435 VkLayerProperties *device_layer_properties = NULL; 436 struct layer_extension_list *device_layers = NULL; 437 438 do { 439 err = vkGetPhysicalDeviceLayerProperties(gpu->obj, &count, NULL); 440 assert(!err); 441 442 if (device_layer_properties) { 443 free(device_layer_properties); 444 } 445 device_layer_properties = malloc(sizeof(VkLayerProperties) * count); 446 assert(device_layer_properties); 447 448 if (device_layers) { 449 free(device_layers); 450 } 451 device_layers = malloc(sizeof(struct layer_extension_list) * count); 452 assert(device_layers); 453 454 err = vkGetPhysicalDeviceLayerProperties(gpu->obj, &count, device_layer_properties); 455 } while (err == VK_INCOMPLETE); 456 assert(!err); 457 458 gpu->device_layer_count = count; 459 gpu->device_layers = device_layers; 460 461 for (uint32_t i = 0; i < gpu->device_layer_count; i++) { 462 VkLayerProperties *src_info = &device_layer_properties[i]; 463 struct layer_extension_list *dst_info = &gpu->device_layers[i]; 464 memcpy(&dst_info->layer_properties, src_info, sizeof(VkLayerProperties)); 465 466 /* Save away layer extension info for report */ 467 app_get_physical_device_layer_extensions( 468 gpu, 469 src_info->layerName, 470 &dst_info->extension_count, 471 &dst_info->extension_properties); 472 } 473 free(device_layer_properties); 474 475 app_get_physical_device_layer_extensions( 476 gpu, 477 NULL, 478 &gpu->device_extension_count, 479 &gpu->device_extensions); 480 481 fflush(stdout); 482 483 uint32_t enabled_extension_count = 0; 484 uint32_t known_extension_count = ARRAY_SIZE(known_extensions); 485 486 for (uint32_t i = 0; i < known_extension_count; i++) { 487 VkBool32 extension_found = 0; 488 for (uint32_t j = 0; j < gpu->device_extension_count; j++) { 489 VkExtensionProperties *ext_prop = &gpu->device_extensions[j]; 490 if (!strcmp(known_extensions[i], ext_prop->extName)) { 491 492 extension_found = 1; 493 enabled_extension_count++; 494 } 495 } 496 if (!extension_found) { 497 printf("Cannot find extension: %s\n", known_extensions[i]); 498 ERR_EXIT(VK_ERROR_INVALID_EXTENSION); 499 } 500 } 501 502 /* request all queues */ 503 info.queueRecordCount = gpu->queue_count; 504 info.pRequestedQueues = gpu->queue_reqs; 505 506 info.layerCount = 0; 507 info.ppEnabledLayerNames = NULL; 508 info.extensionCount = enabled_extension_count; 509 info.ppEnabledExtensionNames = (const char*const*) known_extensions; 510 dev->gpu = gpu; 511 err = vkCreateDevice(gpu->obj, &info, &dev->obj); 512 if (err) 513 ERR_EXIT(err); 514 515} 516 517static void app_dev_destroy(struct app_dev *dev) 518{ 519 vkDestroyDevice(dev->obj); 520} 521 522static void app_get_global_layer_extensions( 523 char *layer_name, 524 uint32_t *extension_count, 525 VkExtensionProperties **extension_properties) 526{ 527 VkResult err; 528 uint32_t ext_count = 0; 529 VkExtensionProperties *ext_ptr = NULL; 530 531 /* repeat get until VK_INCOMPLETE goes away */ 532 do { 533 err = vkGetGlobalExtensionProperties(layer_name, &ext_count, NULL); 534 assert(!err); 535 536 if (ext_ptr) { 537 free(ext_ptr); 538 } 539 ext_ptr = malloc(ext_count * sizeof(VkExtensionProperties)); 540 err = vkGetGlobalExtensionProperties(layer_name, &ext_count, ext_ptr); 541 } while (err == VK_INCOMPLETE); 542 assert(!err); 543 544 *extension_count = ext_count; 545 *extension_properties = ext_ptr; 546} 547 548static void app_create_instance(struct app_instance *inst) 549{ 550 const VkApplicationInfo app_info = { 551 .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, 552 .pNext = NULL, 553 .pAppName = APP_SHORT_NAME, 554 .appVersion = 1, 555 .pEngineName = APP_SHORT_NAME, 556 .engineVersion = 1, 557 .apiVersion = VK_API_VERSION, 558 }; 559 VkInstanceCreateInfo inst_info = { 560 .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, 561 .pNext = NULL, 562 .pAppInfo = &app_info, 563 .pAllocCb = NULL, 564 .layerCount = 0, 565 .ppEnabledLayerNames = NULL, 566 .extensionCount = 0, 567 .ppEnabledExtensionNames = NULL, 568 }; 569 VkResult U_ASSERT_ONLY err; 570 // Global Extensions to enable 571 static char *known_extensions[] = { 572 "VK_WSI_LunarG", 573 }; 574 575 uint32_t global_extension_count = 0; 576 uint32_t count = 0; 577 578 /* Scan layers */ 579 VkLayerProperties *global_layer_properties = NULL; 580 struct layer_extension_list *global_layers = NULL; 581 582 do { 583 err = vkGetGlobalLayerProperties(&count, NULL); 584 assert(!err); 585 586 if (global_layer_properties) { 587 free(global_layer_properties); 588 } 589 global_layer_properties = malloc(sizeof(VkLayerProperties) * count); 590 assert(global_layer_properties); 591 592 if (global_layers) { 593 free(global_layers); 594 } 595 global_layers = malloc(sizeof(struct layer_extension_list) * count); 596 assert(global_layers); 597 598 err = vkGetGlobalLayerProperties(&count, global_layer_properties); 599 } while (err == VK_INCOMPLETE); 600 assert(!err); 601 602 inst->global_layer_count = count; 603 inst->global_layers = global_layers; 604 605 for (uint32_t i = 0; i < inst->global_layer_count; i++) { 606 VkLayerProperties *src_info = &global_layer_properties[i]; 607 struct layer_extension_list *dst_info = &inst->global_layers[i]; 608 memcpy(&dst_info->layer_properties, src_info, sizeof(VkLayerProperties)); 609 610 /* Save away layer extension info for report */ 611 app_get_global_layer_extensions( 612 src_info->layerName, 613 &dst_info->extension_count, 614 &dst_info->extension_properties); 615 } 616 free(global_layer_properties); 617 618 /* Collect global extensions */ 619 inst->global_extension_count = 0; 620 app_get_global_layer_extensions( 621 NULL, 622 &inst->global_extension_count, 623 &inst->global_extensions); 624 625 for (uint32_t i = 0; i < ARRAY_SIZE(known_extensions); i++) { 626 VkBool32 extension_found = 0; 627 for (uint32_t j = 0; j < inst->global_extension_count; j++) { 628 VkExtensionProperties *extension_prop = &inst->global_extensions[j]; 629 if (!strcmp(known_extensions[i], extension_prop->extName)) { 630 631 extension_found = 1; 632 global_extension_count++; 633 } 634 } 635 if (!extension_found) { 636 printf("Cannot find extension: %s\n", known_extensions[i]); 637 ERR_EXIT(VK_ERROR_INVALID_EXTENSION); 638 } 639 } 640 641 inst_info.extensionCount = global_extension_count; 642 inst_info.ppEnabledExtensionNames = (const char * const *) known_extensions; 643 644 err = vkCreateInstance(&inst_info, &inst->instance); 645 if (err == VK_ERROR_INCOMPATIBLE_DRIVER) { 646 printf("Cannot create Vulkan instance.\n"); 647 ERR_EXIT(err); 648 } else if (err) { 649 ERR_EXIT(err); 650 } 651} 652 653static void app_destroy_instance(struct app_instance *inst) 654{ 655 free(inst->global_extensions); 656 vkDestroyInstance(inst->instance); 657} 658 659 660static void app_gpu_init(struct app_gpu *gpu, uint32_t id, VkPhysicalDevice obj) 661{ 662 VkResult err; 663 uint32_t i; 664 665 memset(gpu, 0, sizeof(*gpu)); 666 667 gpu->id = id; 668 gpu->obj = obj; 669 670 err = vkGetPhysicalDeviceProperties(gpu->obj, &gpu->props); 671 if (err) 672 ERR_EXIT(err); 673 674 err = vkGetPhysicalDevicePerformance(gpu->obj, &gpu->perf); 675 if (err) 676 ERR_EXIT(err); 677 678 /* get queue count */ 679 err = vkGetPhysicalDeviceQueueCount(gpu->obj, &gpu->queue_count); 680 if (err) 681 ERR_EXIT(err); 682 683 gpu->queue_props = 684 malloc(sizeof(gpu->queue_props[0]) * gpu->queue_count); 685 686 if (!gpu->queue_props) 687 ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY); 688 err = vkGetPhysicalDeviceQueueProperties(gpu->obj, gpu->queue_count, gpu->queue_props); 689 if (err) 690 ERR_EXIT(err); 691 692 /* set up queue requests */ 693 gpu->queue_reqs = malloc(sizeof(*gpu->queue_reqs) * gpu->queue_count); 694 if (!gpu->queue_reqs) 695 ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY); 696 for (i = 0; i < gpu->queue_count; i++) { 697 gpu->queue_reqs[i].queueFamilyIndex = i; 698 gpu->queue_reqs[i].queueCount = gpu->queue_props[i].queueCount; 699 } 700 701 err = vkGetPhysicalDeviceMemoryProperties(gpu->obj, &gpu->memory_props); 702 if (err) 703 ERR_EXIT(err); 704 705 err = vkGetPhysicalDeviceFeatures(gpu->obj, &gpu->features); 706 if (err) 707 ERR_EXIT(err); 708 709 err = vkGetPhysicalDeviceLimits(gpu->obj, &gpu->limits); 710 if (err) 711 ERR_EXIT(err); 712 713 app_dev_init(&gpu->dev, gpu); 714 app_dev_init_formats(&gpu->dev); 715} 716 717static void app_gpu_destroy(struct app_gpu *gpu) 718{ 719 app_dev_destroy(&gpu->dev); 720 free(gpu->device_extensions); 721 free(gpu->queue_reqs); 722 free(gpu->queue_props); 723} 724 725static void app_dev_dump_format_props(const struct app_dev *dev, VkFormat fmt) 726{ 727 const VkFormatProperties *props = &dev->format_props[fmt]; 728 struct { 729 const char *name; 730 VkFlags flags; 731 } tilings[2]; 732 uint32_t i; 733 734 if (!props->linearTilingFeatures && !props->optimalTilingFeatures) 735 return; 736 737 tilings[0].name = "linear"; 738 tilings[0].flags = props->linearTilingFeatures; 739 tilings[1].name = "optimal"; 740 tilings[1].flags = props->optimalTilingFeatures; 741 742 printf("FORMAT_%s\n", vk_format_string(fmt)); 743 for (i = 0; i < ARRAY_SIZE(tilings); i++) { 744 if (!tilings[i].flags) 745 continue; 746 747 printf("\t%s tiling image =%s%s%s\n", tilings[i].name, 748 (tilings[i].flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) ? " sampled" : "", 749 (tilings[i].flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) ? " storage" : "", 750 (tilings[i].flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT) ? " atomic" : ""); 751 printf("\t%s tiling texel =%s%s%s\n", tilings[i].name, 752 (tilings[i].flags & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT) ? " TBO" : "", 753 (tilings[i].flags & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT) ? " IBO" : "", 754 (tilings[i].flags & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT) ? " atomic" : ""); 755 printf("\t%s tiling attachment =%s%s%s\n", tilings[i].name, 756 (tilings[i].flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) ? " color" : "", 757 (tilings[i].flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT) ? " blend" : "", 758 (tilings[i].flags & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) ? " depth/stencil" : ""); 759 printf("\t%s tiling vertex = %u\n", tilings[i].name, 760 (bool) (tilings[i].flags & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)); 761 printf("\t%s tiling conversion = %u\n", tilings[i].name, 762 (bool) (tilings[i].flags & VK_FORMAT_FEATURE_CONVERSION_BIT)); 763 } 764} 765 766 767static void 768app_dev_dump(const struct app_dev *dev) 769{ 770 VkFormat fmt; 771 772 for (fmt = 0; fmt < VK_NUM_FORMAT; fmt++) { 773 app_dev_dump_format_props(dev, fmt); 774 } 775} 776 777#ifdef _WIN32 778#define PRINTF_SIZE_T_SPECIFIER "%Iu" 779#else 780#define PRINTF_SIZE_T_SPECIFIER "%zu" 781#endif 782 783static void app_gpu_dump_features(const struct app_gpu *gpu) 784{ 785 const VkPhysicalDeviceFeatures *features = &gpu->features; 786 787 printf("VkPhysicalDeviceFeatures\n"); 788 /* TODO: add interesting features */ 789 printf("\tgeometryShader = %u\n", features->geometryShader); 790} 791 792static void app_gpu_dump_limits(const struct app_gpu *gpu) 793{ 794 const VkPhysicalDeviceLimits *limits = &gpu->limits; 795 796 printf("VkPhysicalDeviceLimits\n"); 797 /* TODO: add interesting limits */ 798 printf("\tmaxInlineMemoryUpdateSize = " PRINTF_SIZE_T_SPECIFIER "\n", limits->maxInlineMemoryUpdateSize); 799 printf("\tmaxBoundDescriptorSets = %u\n", limits->maxBoundDescriptorSets); 800 printf("\tmaxComputeWorkGroupInvocations = %u\n", limits->maxComputeWorkGroupInvocations); 801 printf("\ttimestampFrequency = %lu\n", limits->timestampFrequency); 802} 803 804static void app_gpu_dump_props(const struct app_gpu *gpu) 805{ 806 const VkPhysicalDeviceProperties *props = &gpu->props; 807 808 printf("VkPhysicalDeviceProperties\n"); 809 printf("\tapiVersion = %u\n", props->apiVersion); 810 printf("\tdriverVersion = %u\n", props->driverVersion); 811 printf("\tvendorId = 0x%04x\n", props->vendorId); 812 printf("\tdeviceId = 0x%04x\n", props->deviceId); 813 printf("\tdeviceType = %s\n", vk_physical_device_type_string(props->deviceType)); 814 printf("\tdeviceName = %s\n", props->deviceName); 815 fflush(stdout); 816} 817 818static void app_gpu_dump_perf(const struct app_gpu *gpu) 819{ 820 const VkPhysicalDevicePerformance *perf = &gpu->perf; 821 822 printf("VkPhysicalDevicePerformance\n"); 823 printf("\tmaxGpuClock = %f\n", perf->maxDeviceClock); 824 printf("\taluPerClock = %f\n", perf->aluPerClock); 825 printf("\ttexPerClock = %f\n", perf->texPerClock); 826 printf("\tprimsPerClock = %f\n", perf->primsPerClock); 827 printf("\tpixelsPerClock = %f\n", perf->pixelsPerClock); 828 fflush(stdout); 829} 830 831static void app_dump_extensions( 832 const char *indent, 833 const char *layer_name, 834 const uint32_t extension_count, 835 const VkExtensionProperties *extension_properties) 836{ 837 uint32_t i; 838 if (layer_name && (strlen(layer_name) > 0)) { 839 printf("%s%s Extensions", indent, layer_name); 840 } else { 841 printf("Extensions"); 842 } 843 printf("\tcount = %d\n", extension_count); 844 for (i=0; i< extension_count; i++) { 845 uint32_t major, minor, patch; 846 char spec_version[64], extension_version[64]; 847 VkExtensionProperties const *ext_prop = &extension_properties[i]; 848 849 if (i>0) 850 printf("\n"); // separator between extensions 851 852 printf("%s\t", indent); 853 extract_version(ext_prop->specVersion, &major, &minor, &patch); 854 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d", major, minor, patch); 855 extract_version(ext_prop->version, &major, &minor, &patch); 856 snprintf(extension_version, sizeof(extension_version), "%d.%d.%d", major, minor, patch); 857 printf("%s: Vulkan version %s, extension version %s", 858 ext_prop->extName, spec_version, extension_version); 859 } 860 printf("\n"); 861 fflush(stdout); 862} 863 864static void app_gpu_dump_queue_props(const struct app_gpu *gpu, uint32_t id) 865{ 866 const VkPhysicalDeviceQueueProperties *props = &gpu->queue_props[id]; 867 868 printf("VkPhysicalDeviceQueueProperties[%d]\n", id); 869 printf("\tqueueFlags = %c%c%c%c\n", 870 (props->queueFlags & VK_QUEUE_GRAPHICS_BIT) ? 'G' : '.', 871 (props->queueFlags & VK_QUEUE_COMPUTE_BIT) ? 'C' : '.', 872 (props->queueFlags & VK_QUEUE_DMA_BIT) ? 'D' : '.', 873 (props->queueFlags & VK_QUEUE_EXTENDED_BIT) ? 'X' : '.'); 874 printf("\tqueueCount = %u\n", props->queueCount); 875 printf("\tsupportsTimestamps = %u\n", props->supportsTimestamps); 876 fflush(stdout); 877} 878 879static void app_gpu_dump_memory_props(const struct app_gpu *gpu) 880{ 881 const VkPhysicalDeviceMemoryProperties *props = &gpu->memory_props; 882 883 printf("VkPhysicalDeviceMemoryProperties\n"); 884 printf("\tmemoryTypeCount = %u\n", props->memoryTypeCount); 885 for (uint32_t i = 0; i < props->memoryTypeCount; i++) { 886 printf("\tmemoryTypes[%u] : \n", i); 887 printf("\t\tpropertyFlags = %u\n", props->memoryTypes[i].propertyFlags); 888 printf("\t\theapIndex = %u\n", props->memoryTypes[i].heapIndex); 889 } 890 printf("\tmemoryHeapCount = %u\n", props->memoryHeapCount); 891 for (uint32_t i = 0; i < props->memoryHeapCount; i++) { 892 printf("\tmemoryHeaps[%u] : \n", i); 893 printf("\t\tsize = " PRINTF_SIZE_T_SPECIFIER "\n", props->memoryHeaps[i].size); 894 } 895 fflush(stdout); 896} 897 898static void app_gpu_dump(const struct app_gpu *gpu) 899{ 900 uint32_t i; 901 902 printf("GPU%u\n", gpu->id); 903 app_gpu_dump_props(gpu); 904 printf("\n"); 905 app_dump_extensions("", "", gpu->device_extension_count, gpu->device_extensions); 906 printf("\n"); 907 printf("Layers\tcount = %d\n", gpu->device_layer_count); 908 for (uint32_t i = 0; i < gpu->device_layer_count; i++) { 909 uint32_t major, minor, patch; 910 char spec_version[64], layer_version[64]; 911 struct layer_extension_list const *layer_info = &gpu->device_layers[i]; 912 913 extract_version(layer_info->layer_properties.specVersion, &major, &minor, &patch); 914 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d", major, minor, patch); 915 extract_version(layer_info->layer_properties.implVersion, &major, &minor, &patch); 916 snprintf(layer_version, sizeof(layer_version), "%d.%d.%d", major, minor, patch); 917 printf("\t%s (%s) Vulkan version %s, layer version %s\n", 918 layer_info->layer_properties.layerName, 919 layer_info->layer_properties.description, 920 spec_version, layer_version); 921 922 app_dump_extensions("\t", 923 layer_info->layer_properties.layerName, 924 layer_info->extension_count, 925 layer_info->extension_properties); 926 fflush(stdout); 927 } 928 printf("\n"); 929 app_gpu_dump_perf(gpu); 930 printf("\n"); 931 for (i = 0; i < gpu->queue_count; i++) { 932 app_gpu_dump_queue_props(gpu, i); 933 printf("\n"); 934 } 935 app_gpu_dump_memory_props(gpu); 936 printf("\n"); 937 app_gpu_dump_features(gpu); 938 printf("\n"); 939 app_gpu_dump_limits(gpu); 940 printf("\n"); 941 app_dev_dump(&gpu->dev); 942} 943 944int main(int argc, char **argv) 945{ 946 struct app_gpu gpus[MAX_GPUS]; 947 VkPhysicalDevice objs[MAX_GPUS]; 948 uint32_t gpu_count, i; 949 VkResult err; 950 struct app_instance inst; 951 952 app_create_instance(&inst); 953 app_dump_extensions("", "Global", inst.global_extension_count, inst.global_extensions); 954 955 printf("Global Layers\tcount = %d\n", inst.global_layer_count); 956 for (uint32_t i = 0; i < inst.global_layer_count; i++) { 957 uint32_t major, minor, patch; 958 char spec_version[64], layer_version[64]; 959 VkLayerProperties const *layer_prop = &inst.global_layers[i].layer_properties; 960 961 extract_version(layer_prop->specVersion, &major, &minor, &patch); 962 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d", major, minor, patch); 963 extract_version(layer_prop->implVersion, &major, &minor, &patch); 964 snprintf(layer_version, sizeof(layer_version), "%d.%d.%d", major, minor, patch); 965 printf("\t%s (%s) Vulkan version %s, layer version %s\n", 966 layer_prop->layerName, layer_prop->description, spec_version, layer_version); 967 968 app_dump_extensions("\t", 969 inst.global_layers[i].layer_properties.layerName, 970 inst.global_layers[i].extension_count, 971 inst.global_layers[i].extension_properties); 972 } 973 974 err = vkEnumeratePhysicalDevices(inst.instance, &gpu_count, NULL); 975 if (err) 976 ERR_EXIT(err); 977 if (gpu_count > MAX_GPUS) { 978 printf("Too many GPUS found \n"); 979 ERR_EXIT(VK_ERROR_UNKNOWN); 980 } 981 err = vkEnumeratePhysicalDevices(inst.instance, &gpu_count, objs); 982 if (err) 983 ERR_EXIT(err); 984 985 for (i = 0; i < gpu_count; i++) { 986 app_gpu_init(&gpus[i], i, objs[i]); 987 app_gpu_dump(&gpus[i]); 988 printf("\n\n"); 989 } 990 991 for (i = 0; i < gpu_count; i++) 992 app_gpu_destroy(&gpus[i]); 993 994 app_destroy_instance(&inst); 995 996 return 0; 997} 998 999#ifdef _WIN32 1000 1001// Create a console window with a large scrollback size to which to send stdout. 1002// Returns true if console window was successfully created, false otherwise. 1003bool SetStdOutToNewConsole() 1004{ 1005 // don't do anything if we already have a console 1006 if (GetStdHandle(STD_OUTPUT_HANDLE)) 1007 return false; 1008 1009 // allocate a console for this app 1010 AllocConsole(); 1011 1012 // redirect unbuffered STDOUT to the console 1013 HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE); 1014 int fileDescriptor = _open_osfhandle((intptr_t)consoleHandle, _O_TEXT); 1015 FILE *fp = _fdopen( fileDescriptor, "w" ); 1016 *stdout = *fp; 1017 setvbuf( stdout, NULL, _IONBF, 0 ); 1018 1019 // make the console window bigger 1020 CONSOLE_SCREEN_BUFFER_INFO csbi; 1021 SMALL_RECT r; 1022 COORD bufferSize; 1023 if (!GetConsoleScreenBufferInfo(consoleHandle, &csbi)) 1024 return false; 1025 bufferSize.X = csbi.dwSize.X; 1026 bufferSize.Y = 1000; 1027 if (!SetConsoleScreenBufferSize(consoleHandle, bufferSize)) 1028 return false; 1029 r.Left = r.Top = 0; 1030 r.Right = csbi.dwSize.X-1; 1031 r.Bottom = 60; 1032 if (!SetConsoleWindowInfo(consoleHandle, true, &r)) 1033 return false; 1034 1035 // change the console window title 1036 if (!SetConsoleTitle(TEXT(APP_SHORT_NAME))) 1037 return false; 1038 1039 return true; 1040} 1041 1042int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pCmdLine, int nCmdShow) 1043{ 1044 char *argv = pCmdLine; 1045 consoleCreated = SetStdOutToNewConsole(); 1046 main(1, &argv); 1047 fflush(stdout); 1048 if (consoleCreated) 1049 Sleep(INFINITE); 1050} 1051#endif 1052