vulkaninfo.c revision e880e9bfd899c6c747b053cfb09f5d59168221b8
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 43bool consoleCreated = false; 44 45#define WAIT_FOR_CONSOLE_DESTROY \ 46 do { \ 47 if (consoleCreated) \ 48 Sleep(INFINITE); \ 49 } while (0) 50#else 51 #define WAIT_FOR_CONSOLE_DESTROY 52#endif 53 54 55#define ERR_EXIT(err) \ 56 do { \ 57 ERR(err); \ 58 fflush(stdout); \ 59 WAIT_FOR_CONSOLE_DESTROY; \ 60 exit(-1); \ 61 } while (0) 62 63#if defined(NDEBUG) && defined(__GNUC__) 64#define U_ASSERT_ONLY __attribute__((unused)) 65#else 66#define U_ASSERT_ONLY 67#endif 68 69#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 70 71#define MAX_GPUS 8 72 73#define MAX_QUEUE_TYPES 5 74#define APP_SHORT_NAME "vulkaninfo" 75 76struct app_gpu; 77 78struct app_dev { 79 struct app_gpu *gpu; /* point back to the GPU */ 80 81 VkDevice obj; 82 83 84 VkFormatProperties format_props[VK_NUM_FORMAT]; 85}; 86 87struct app_instance { 88 VkInstance instance; 89 uint32_t global_extension_count; 90 VkExtensionProperties *global_extensions; 91}; 92 93struct app_gpu { 94 uint32_t id; 95 VkPhysicalDevice obj; 96 97 VkPhysicalDeviceProperties props; 98 VkPhysicalDevicePerformance perf; 99 100 uint32_t queue_count; 101 VkPhysicalDeviceQueueProperties *queue_props; 102 VkDeviceQueueCreateInfo *queue_reqs; 103 104 VkPhysicalDeviceMemoryProperties memory_props; 105 106 uint32_t device_extension_count; 107 VkExtensionProperties *device_extensions; 108 109 struct app_dev dev; 110}; 111 112static const char *vk_result_string(VkResult err) 113{ 114 switch (err) { 115#define STR(r) case r: return #r 116 STR(VK_SUCCESS); 117 STR(VK_UNSUPPORTED); 118 STR(VK_NOT_READY); 119 STR(VK_TIMEOUT); 120 STR(VK_EVENT_SET); 121 STR(VK_EVENT_RESET); 122 STR(VK_ERROR_UNKNOWN); 123 STR(VK_ERROR_UNAVAILABLE); 124 STR(VK_ERROR_INITIALIZATION_FAILED); 125 STR(VK_ERROR_OUT_OF_HOST_MEMORY); 126 STR(VK_ERROR_OUT_OF_DEVICE_MEMORY); 127 STR(VK_ERROR_DEVICE_ALREADY_CREATED); 128 STR(VK_ERROR_DEVICE_LOST); 129 STR(VK_ERROR_INVALID_POINTER); 130 STR(VK_ERROR_INVALID_VALUE); 131 STR(VK_ERROR_INVALID_HANDLE); 132 STR(VK_ERROR_INVALID_ORDINAL); 133 STR(VK_ERROR_INVALID_MEMORY_SIZE); 134 STR(VK_ERROR_INVALID_EXTENSION); 135 STR(VK_ERROR_INVALID_FLAGS); 136 STR(VK_ERROR_INVALID_ALIGNMENT); 137 STR(VK_ERROR_INVALID_FORMAT); 138 STR(VK_ERROR_INVALID_IMAGE); 139 STR(VK_ERROR_INVALID_DESCRIPTOR_SET_DATA); 140 STR(VK_ERROR_INVALID_QUEUE_TYPE); 141 STR(VK_ERROR_INVALID_OBJECT_TYPE); 142 STR(VK_ERROR_UNSUPPORTED_SHADER_IL_VERSION); 143 STR(VK_ERROR_BAD_SHADER_CODE); 144 STR(VK_ERROR_BAD_PIPELINE_DATA); 145 STR(VK_ERROR_NOT_MAPPABLE); 146 STR(VK_ERROR_MEMORY_MAP_FAILED); 147 STR(VK_ERROR_MEMORY_UNMAP_FAILED); 148 STR(VK_ERROR_INCOMPATIBLE_DEVICE); 149 STR(VK_ERROR_INCOMPATIBLE_DRIVER); 150 STR(VK_ERROR_INCOMPLETE_COMMAND_BUFFER); 151 STR(VK_ERROR_BUILDING_COMMAND_BUFFER); 152 STR(VK_ERROR_MEMORY_NOT_BOUND); 153 STR(VK_ERROR_INCOMPATIBLE_QUEUE); 154#undef STR 155 default: return "UNKNOWN_RESULT"; 156 } 157} 158 159static const char *vk_physical_device_type_string(VkPhysicalDeviceType type) 160{ 161 switch (type) { 162#define STR(r) case VK_PHYSICAL_DEVICE_TYPE_ ##r: return #r 163 STR(OTHER); 164 STR(INTEGRATED_GPU); 165 STR(DISCRETE_GPU); 166 STR(VIRTUAL_GPU); 167#undef STR 168 default: return "UNKNOWN_DEVICE"; 169 } 170} 171 172static const char *vk_format_string(VkFormat fmt) 173{ 174 switch (fmt) { 175#define STR(r) case VK_FORMAT_ ##r: return #r 176 STR(UNDEFINED); 177 STR(R4G4_UNORM); 178 STR(R4G4_USCALED); 179 STR(R4G4B4A4_UNORM); 180 STR(R4G4B4A4_USCALED); 181 STR(R5G6B5_UNORM); 182 STR(R5G6B5_USCALED); 183 STR(R5G5B5A1_UNORM); 184 STR(R5G5B5A1_USCALED); 185 STR(R8_UNORM); 186 STR(R8_SNORM); 187 STR(R8_USCALED); 188 STR(R8_SSCALED); 189 STR(R8_UINT); 190 STR(R8_SINT); 191 STR(R8_SRGB); 192 STR(R8G8_UNORM); 193 STR(R8G8_SNORM); 194 STR(R8G8_USCALED); 195 STR(R8G8_SSCALED); 196 STR(R8G8_UINT); 197 STR(R8G8_SINT); 198 STR(R8G8_SRGB); 199 STR(R8G8B8_UNORM); 200 STR(R8G8B8_SNORM); 201 STR(R8G8B8_USCALED); 202 STR(R8G8B8_SSCALED); 203 STR(R8G8B8_UINT); 204 STR(R8G8B8_SINT); 205 STR(R8G8B8_SRGB); 206 STR(R8G8B8A8_UNORM); 207 STR(R8G8B8A8_SNORM); 208 STR(R8G8B8A8_USCALED); 209 STR(R8G8B8A8_SSCALED); 210 STR(R8G8B8A8_UINT); 211 STR(R8G8B8A8_SINT); 212 STR(R8G8B8A8_SRGB); 213 STR(R10G10B10A2_UNORM); 214 STR(R10G10B10A2_SNORM); 215 STR(R10G10B10A2_USCALED); 216 STR(R10G10B10A2_SSCALED); 217 STR(R10G10B10A2_UINT); 218 STR(R10G10B10A2_SINT); 219 STR(R16_UNORM); 220 STR(R16_SNORM); 221 STR(R16_USCALED); 222 STR(R16_SSCALED); 223 STR(R16_UINT); 224 STR(R16_SINT); 225 STR(R16_SFLOAT); 226 STR(R16G16_UNORM); 227 STR(R16G16_SNORM); 228 STR(R16G16_USCALED); 229 STR(R16G16_SSCALED); 230 STR(R16G16_UINT); 231 STR(R16G16_SINT); 232 STR(R16G16_SFLOAT); 233 STR(R16G16B16_UNORM); 234 STR(R16G16B16_SNORM); 235 STR(R16G16B16_USCALED); 236 STR(R16G16B16_SSCALED); 237 STR(R16G16B16_UINT); 238 STR(R16G16B16_SINT); 239 STR(R16G16B16_SFLOAT); 240 STR(R16G16B16A16_UNORM); 241 STR(R16G16B16A16_SNORM); 242 STR(R16G16B16A16_USCALED); 243 STR(R16G16B16A16_SSCALED); 244 STR(R16G16B16A16_UINT); 245 STR(R16G16B16A16_SINT); 246 STR(R16G16B16A16_SFLOAT); 247 STR(R32_UINT); 248 STR(R32_SINT); 249 STR(R32_SFLOAT); 250 STR(R32G32_UINT); 251 STR(R32G32_SINT); 252 STR(R32G32_SFLOAT); 253 STR(R32G32B32_UINT); 254 STR(R32G32B32_SINT); 255 STR(R32G32B32_SFLOAT); 256 STR(R32G32B32A32_UINT); 257 STR(R32G32B32A32_SINT); 258 STR(R32G32B32A32_SFLOAT); 259 STR(R64_SFLOAT); 260 STR(R64G64_SFLOAT); 261 STR(R64G64B64_SFLOAT); 262 STR(R64G64B64A64_SFLOAT); 263 STR(R11G11B10_UFLOAT); 264 STR(R9G9B9E5_UFLOAT); 265 STR(D16_UNORM); 266 STR(D24_UNORM); 267 STR(D32_SFLOAT); 268 STR(S8_UINT); 269 STR(D16_UNORM_S8_UINT); 270 STR(D24_UNORM_S8_UINT); 271 STR(D32_SFLOAT_S8_UINT); 272 STR(BC1_RGB_UNORM); 273 STR(BC1_RGB_SRGB); 274 STR(BC2_UNORM); 275 STR(BC2_SRGB); 276 STR(BC3_UNORM); 277 STR(BC3_SRGB); 278 STR(BC4_UNORM); 279 STR(BC4_SNORM); 280 STR(BC5_UNORM); 281 STR(BC5_SNORM); 282 STR(BC6H_UFLOAT); 283 STR(BC6H_SFLOAT); 284 STR(BC7_UNORM); 285 STR(BC7_SRGB); 286 STR(ETC2_R8G8B8_UNORM); 287 STR(ETC2_R8G8B8A1_UNORM); 288 STR(ETC2_R8G8B8A8_UNORM); 289 STR(EAC_R11_UNORM); 290 STR(EAC_R11_SNORM); 291 STR(EAC_R11G11_UNORM); 292 STR(EAC_R11G11_SNORM); 293 STR(ASTC_4x4_UNORM); 294 STR(ASTC_4x4_SRGB); 295 STR(ASTC_5x4_UNORM); 296 STR(ASTC_5x4_SRGB); 297 STR(ASTC_5x5_UNORM); 298 STR(ASTC_5x5_SRGB); 299 STR(ASTC_6x5_UNORM); 300 STR(ASTC_6x5_SRGB); 301 STR(ASTC_6x6_UNORM); 302 STR(ASTC_6x6_SRGB); 303 STR(ASTC_8x5_UNORM); 304 STR(ASTC_8x5_SRGB); 305 STR(ASTC_8x6_UNORM); 306 STR(ASTC_8x6_SRGB); 307 STR(ASTC_8x8_UNORM); 308 STR(ASTC_8x8_SRGB); 309 STR(ASTC_10x5_UNORM); 310 STR(ASTC_10x5_SRGB); 311 STR(ASTC_10x6_UNORM); 312 STR(ASTC_10x6_SRGB); 313 STR(ASTC_10x8_UNORM); 314 STR(ASTC_10x8_SRGB); 315 STR(ASTC_10x10_UNORM); 316 STR(ASTC_10x10_SRGB); 317 STR(ASTC_12x10_UNORM); 318 STR(ASTC_12x10_SRGB); 319 STR(ASTC_12x12_UNORM); 320 STR(ASTC_12x12_SRGB); 321 STR(B5G6R5_UNORM); 322 STR(B5G6R5_USCALED); 323 STR(B8G8R8_UNORM); 324 STR(B8G8R8_SNORM); 325 STR(B8G8R8_USCALED); 326 STR(B8G8R8_SSCALED); 327 STR(B8G8R8_UINT); 328 STR(B8G8R8_SINT); 329 STR(B8G8R8_SRGB); 330 STR(B8G8R8A8_UNORM); 331 STR(B8G8R8A8_SNORM); 332 STR(B8G8R8A8_USCALED); 333 STR(B8G8R8A8_SSCALED); 334 STR(B8G8R8A8_UINT); 335 STR(B8G8R8A8_SINT); 336 STR(B8G8R8A8_SRGB); 337 STR(B10G10R10A2_UNORM); 338 STR(B10G10R10A2_SNORM); 339 STR(B10G10R10A2_USCALED); 340 STR(B10G10R10A2_SSCALED); 341 STR(B10G10R10A2_UINT); 342 STR(B10G10R10A2_SINT); 343#undef STR 344 default: return "UNKNOWN_FORMAT"; 345 } 346} 347 348static void app_dev_init_formats(struct app_dev *dev) 349{ 350 VkFormat f; 351 352 for (f = 0; f < VK_NUM_FORMAT; f++) { 353 const VkFormat fmt = f; 354 VkResult err; 355 356 err = vkGetPhysicalDeviceFormatInfo(dev->gpu->obj, fmt, &dev->format_props[f]); 357 if (err) { 358 memset(&dev->format_props[f], 0, 359 sizeof(dev->format_props[f])); 360 } 361 } 362} 363 364static void app_dev_init(struct app_dev *dev, struct app_gpu *gpu) 365{ 366 VkDeviceCreateInfo info = { 367 .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, 368 .pNext = NULL, 369 .queueRecordCount = 0, 370 .pRequestedQueues = NULL, 371 .extensionCount = 0, 372 .pEnabledExtensions = NULL, 373 .flags = 0, 374 }; 375 VkResult U_ASSERT_ONLY err; 376 // Extensions to enable 377 VkExtensionProperties *enable_extension_list; 378 static char *known_extensions[] = { 379 "VK_WSI_LunarG", 380 "Validation", 381 }; 382 383 uint32_t extCount; 384 err = vkGetPhysicalDeviceExtensionCount(gpu->obj, &extCount); 385 assert(!err); 386 387 enable_extension_list = malloc(sizeof(VkExtensionProperties) * extCount); 388 if (!enable_extension_list) { 389 ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY); 390 } 391 392 VkExtensionProperties extProp; 393 gpu->device_extension_count = 0; 394 bool32_t U_ASSERT_ONLY extFound = 0; // TODO : Need to enhance this if/when we enable multiple extensions 395 for (uint32_t i = 0; i < ARRAY_SIZE(known_extensions); i++) { 396 for (uint32_t j = 0; j < extCount; j++) { 397 err = vkGetPhysicalDeviceExtensionProperties( 398 gpu->obj, j, &extProp); 399 if (!strcmp(known_extensions[i], extProp.name)) { 400 extFound = 1; 401 memcpy(&enable_extension_list[gpu->device_extension_count], &extProp, sizeof(extProp)); 402 gpu->device_extension_count++; 403 } 404 } 405 } 406 assert(extFound); 407 408 gpu->device_extensions = enable_extension_list; 409 410 /* request all queues */ 411 info.queueRecordCount = gpu->queue_count; 412 info.pRequestedQueues = gpu->queue_reqs; 413 414 info.extensionCount = extCount; 415 info.pEnabledExtensions = enable_extension_list; 416 dev->gpu = gpu; 417 err = vkCreateDevice(gpu->obj, &info, &dev->obj); 418 if (err) 419 ERR_EXIT(err); 420 421} 422 423static void app_dev_destroy(struct app_dev *dev) 424{ 425 vkDestroyDevice(dev->obj); 426} 427 428static void app_create_instance(struct app_instance *inst) 429{ 430 const VkApplicationInfo app_info = { 431 .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, 432 .pNext = NULL, 433 .pAppName = APP_SHORT_NAME, 434 .appVersion = 1, 435 .pEngineName = APP_SHORT_NAME, 436 .engineVersion = 1, 437 .apiVersion = VK_API_VERSION, 438 }; 439 VkInstanceCreateInfo inst_info = { 440 .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, 441 .pNext = NULL, 442 .pAppInfo = &app_info, 443 .pAllocCb = NULL, 444 .extensionCount = 0, 445 .pEnabledExtensions = NULL, 446 }; 447 VkResult U_ASSERT_ONLY err; 448 // Global Extensions to enable 449 static char *known_extensions[] = { 450 "VK_WSI_LunarG", 451 }; 452 453 uint32_t extCount = 0; 454 VkExtensionProperties extProp; 455 VkExtensionProperties *enable_extension_list; 456 uint32_t global_extension_count = 0; 457 458 err = vkGetGlobalExtensionCount(&extCount); 459 assert(!err); 460 461 enable_extension_list = malloc(sizeof(VkExtensionProperties) * extCount); 462 if (!enable_extension_list) { 463 ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY); 464 } 465 466 bool32_t U_ASSERT_ONLY extFound = 0; // TODO : Need to enhance this if/when we enable multiple extensions 467 for (uint32_t i = 0; i < ARRAY_SIZE(known_extensions); i++) { 468 for (uint32_t j = 0; j < extCount; j++) { 469 err = vkGetGlobalExtensionProperties(j, &extProp); 470 if (!strcmp(known_extensions[i], extProp.name)) { 471 extFound = 1; 472 memcpy(&enable_extension_list[global_extension_count], &extProp, sizeof(extProp)); 473 global_extension_count++; 474 } 475 } 476 } 477 assert(extFound); 478 479 inst_info.extensionCount = global_extension_count; 480 inst_info.pEnabledExtensions = enable_extension_list; 481 482 err = vkCreateInstance(&inst_info, &inst->instance); 483 if (err == VK_ERROR_INCOMPATIBLE_DRIVER) { 484 printf("Cannot create Vulkan instance.\n"); 485 ERR_EXIT(err); 486 } else if (err) { 487 ERR_EXIT(err); 488 } 489 490 inst->global_extension_count = global_extension_count; 491 inst->global_extensions = enable_extension_list; 492} 493 494static void app_destroy_instance(struct app_instance *inst) 495{ 496 free(inst->global_extensions); 497 vkDestroyInstance(inst->instance); 498} 499 500 501static void app_gpu_init(struct app_gpu *gpu, uint32_t id, VkPhysicalDevice obj) 502{ 503 VkResult err; 504 uint32_t i; 505 506 memset(gpu, 0, sizeof(*gpu)); 507 508 gpu->id = id; 509 gpu->obj = obj; 510 511 err = vkGetPhysicalDeviceProperties(gpu->obj, &gpu->props); 512 if (err) 513 ERR_EXIT(err); 514 515 err = vkGetPhysicalDevicePerformance(gpu->obj, &gpu->perf); 516 if (err) 517 ERR_EXIT(err); 518 519 /* get queue count */ 520 err = vkGetPhysicalDeviceQueueCount(gpu->obj, &gpu->queue_count); 521 if (err) 522 ERR_EXIT(err); 523 524 gpu->queue_props = 525 malloc(sizeof(gpu->queue_props[0]) * gpu->queue_count); 526 527 if (!gpu->queue_props) 528 ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY); 529 err = vkGetPhysicalDeviceQueueProperties(gpu->obj, gpu->queue_count, gpu->queue_props); 530 if (err) 531 ERR_EXIT(err); 532 533 /* set up queue requests */ 534 gpu->queue_reqs = malloc(sizeof(*gpu->queue_reqs) * gpu->queue_count); 535 if (!gpu->queue_reqs) 536 ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY); 537 for (i = 0; i < gpu->queue_count; i++) { 538 gpu->queue_reqs[i].queueNodeIndex = i; 539 gpu->queue_reqs[i].queueCount = gpu->queue_props[i].queueCount; 540 } 541 542 err = vkGetPhysicalDeviceMemoryProperties(gpu->obj, &gpu->memory_props); 543 if (err) 544 ERR_EXIT(err); 545 546 app_dev_init(&gpu->dev, gpu); 547 app_dev_init_formats(&gpu->dev); 548} 549 550static void app_gpu_destroy(struct app_gpu *gpu) 551{ 552 app_dev_destroy(&gpu->dev); 553 free(gpu->device_extensions); 554 free(gpu->queue_reqs); 555 free(gpu->queue_props); 556} 557 558static void app_dev_dump_format_props(const struct app_dev *dev, VkFormat fmt) 559{ 560 const VkFormatProperties *props = &dev->format_props[fmt]; 561 struct { 562 const char *name; 563 VkFlags flags; 564 } tilings[2]; 565 uint32_t i; 566 567 if (!props->linearTilingFeatures && !props->optimalTilingFeatures) 568 return; 569 570 tilings[0].name = "linear"; 571 tilings[0].flags = props->linearTilingFeatures; 572 tilings[1].name = "optimal"; 573 tilings[1].flags = props->optimalTilingFeatures; 574 575 printf("FORMAT_%s\n", vk_format_string(fmt)); 576 for (i = 0; i < ARRAY_SIZE(tilings); i++) { 577 if (!tilings[i].flags) 578 continue; 579 580 printf("\t%s tiling image =%s%s%s\n", tilings[i].name, 581 (tilings[i].flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) ? " sampled" : "", 582 (tilings[i].flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) ? " storage" : "", 583 (tilings[i].flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT) ? " atomic" : ""); 584 printf("\t%s tiling texel =%s%s%s\n", tilings[i].name, 585 (tilings[i].flags & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT) ? " TBO" : "", 586 (tilings[i].flags & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT) ? " IBO" : "", 587 (tilings[i].flags & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT) ? " atomic" : ""); 588 printf("\t%s tiling attachment =%s%s%s\n", tilings[i].name, 589 (tilings[i].flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) ? " color" : "", 590 (tilings[i].flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT) ? " blend" : "", 591 (tilings[i].flags & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) ? " depth/stencil" : ""); 592 printf("\t%s tiling vertex = %u\n", tilings[i].name, 593 (bool) (tilings[i].flags & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT)); 594 printf("\t%s tiling conversion = %u\n", tilings[i].name, 595 (bool) (tilings[i].flags & VK_FORMAT_FEATURE_CONVERSION_BIT)); 596 } 597} 598 599 600static void 601app_dev_dump(const struct app_dev *dev) 602{ 603 VkFormat fmt; 604 605 for (fmt = 0; fmt < VK_NUM_FORMAT; fmt++) { 606 app_dev_dump_format_props(dev, fmt); 607 } 608} 609 610#ifdef _WIN32 611#define PRINTF_SIZE_T_SPECIFIER "%Iu" 612#else 613#define PRINTF_SIZE_T_SPECIFIER "%zu" 614#endif 615 616static void app_gpu_dump_props(const struct app_gpu *gpu) 617{ 618 const VkPhysicalDeviceProperties *props = &gpu->props; 619 620 printf("VkPhysicalDeviceProperties\n"); 621 printf("\tapiVersion = %u\n", props->apiVersion); 622 printf("\tdriverVersion = %u\n", props->driverVersion); 623 printf("\tvendorId = 0x%04x\n", props->vendorId); 624 printf("\tdeviceId = 0x%04x\n", props->deviceId); 625 printf("\tdeviceType = %s\n", vk_physical_device_type_string(props->deviceType)); 626 printf("\tdeviceName = %s\n", props->deviceName); 627 printf("\tmaxBoundDescriptorSets = %u\n", props->maxBoundDescriptorSets); 628 printf("\tmaxThreadGroupSize = %u\n", props->maxThreadGroupSize); 629 printf("\ttimestampFrequency = %lu\n", props->timestampFrequency); 630 printf("\tmultiColorAttachmentClears = %u\n", props->multiColorAttachmentClears); 631} 632 633static void app_gpu_dump_perf(const struct app_gpu *gpu) 634{ 635 const VkPhysicalDevicePerformance *perf = &gpu->perf; 636 637 printf("VkPhysicalDevicePerformance\n"); 638 printf("\tmaxGpuClock = %f\n", perf->maxDeviceClock); 639 printf("\taluPerClock = %f\n", perf->aluPerClock); 640 printf("\ttexPerClock = %f\n", perf->texPerClock); 641 printf("\tprimsPerClock = %f\n", perf->primsPerClock); 642 printf("\tpixelsPerClock = %f\n", perf->pixelsPerClock); 643} 644 645static void app_gpu_dump_instance_extensions(const struct app_instance *inst) 646{ 647 uint32_t i; 648 printf("Extensions"); 649 printf("\tcount = %d\n", inst->global_extension_count); 650 printf("\t"); 651 for (i=0; i< inst->global_extension_count; i++) { 652 if (i>0) 653 printf(", "); // separator between extension names 654 printf("%s", inst->global_extensions[i].name); 655 } 656 printf("\n"); 657} 658 659static void app_gpu_dump_extensions(const struct app_gpu *gpu) 660{ 661 uint32_t i; 662 printf("Extensions"); 663 printf("\tcount = %d\n", gpu->device_extension_count); 664 printf("\t"); 665 for (i=0; i< gpu->device_extension_count; i++) { 666 if (i>0) 667 printf(", "); // separator between extension names 668 printf("%s(%d): %s", gpu->device_extensions[i].name, 669 gpu->device_extensions[i].version, 670 gpu->device_extensions[i].description); 671 } 672 printf("\n"); 673} 674 675static void app_gpu_dump_queue_props(const struct app_gpu *gpu, uint32_t id) 676{ 677 const VkPhysicalDeviceQueueProperties *props = &gpu->queue_props[id]; 678 679 printf("VkPhysicalDeviceQueueProperties[%d]\n", id); 680 printf("\tqueueFlags = %c%c%c%c\n", 681 (props->queueFlags & VK_QUEUE_GRAPHICS_BIT) ? 'G' : '.', 682 (props->queueFlags & VK_QUEUE_COMPUTE_BIT) ? 'C' : '.', 683 (props->queueFlags & VK_QUEUE_DMA_BIT) ? 'D' : '.', 684 (props->queueFlags & VK_QUEUE_EXTENDED_BIT) ? 'X' : '.'); 685 printf("\tqueueCount = %u\n", props->queueCount); 686 printf("\tmaxAtomicCounters = %u\n", props->maxAtomicCounters); 687 printf("\tsupportsTimestamps = %u\n", props->supportsTimestamps); 688} 689 690static void app_gpu_dump_memory_props(const struct app_gpu *gpu) 691{ 692 const VkPhysicalDeviceMemoryProperties *props = &gpu->memory_props; 693 694 printf("VkPhysicalDeviceMemoryProperties\n"); 695 printf("\tsupportsMigration = %u\n", props->supportsMigration); 696} 697 698static void app_gpu_dump(const struct app_gpu *gpu) 699{ 700 uint32_t i; 701 702 printf("GPU%u\n", gpu->id); 703 app_gpu_dump_props(gpu); 704 printf("\n"); 705 app_gpu_dump_extensions(gpu); 706 printf("\n"); 707 app_gpu_dump_perf(gpu); 708 printf("\n"); 709 for (i = 0; i < gpu->queue_count; i++) { 710 app_gpu_dump_queue_props(gpu, i); 711 printf("\n"); 712 } 713 app_gpu_dump_memory_props(gpu); 714 printf("\n"); 715 app_dev_dump(&gpu->dev); 716} 717 718int main(int argc, char **argv) 719{ 720 struct app_gpu gpus[MAX_GPUS]; 721 VkPhysicalDevice objs[MAX_GPUS]; 722 uint32_t gpu_count, i; 723 VkResult err; 724 struct app_instance inst; 725 726 app_create_instance(&inst); 727 app_gpu_dump_instance_extensions(&inst); 728 729 err = vkEnumeratePhysicalDevices(inst.instance, &gpu_count, NULL); 730 if (err) 731 ERR_EXIT(err); 732 if (gpu_count > MAX_GPUS) { 733 printf("Too many GPUS found \n"); 734 ERR_EXIT(VK_ERROR_UNKNOWN); 735 } 736 err = vkEnumeratePhysicalDevices(inst.instance, &gpu_count, objs); 737 if (err) 738 ERR_EXIT(err); 739 740 for (i = 0; i < gpu_count; i++) { 741 app_gpu_init(&gpus[i], i, objs[i]); 742 app_gpu_dump(&gpus[i]); 743 printf("\n\n"); 744 } 745 746 for (i = 0; i < gpu_count; i++) 747 app_gpu_destroy(&gpus[i]); 748 749 app_destroy_instance(&inst); 750 751 return 0; 752} 753 754#ifdef _WIN32 755 756// Create a console window with a large scrollback size to which to send stdout. 757// Returns true if console window was successfully created, false otherwise. 758bool SetStdOutToNewConsole() 759{ 760 // don't do anything if we already have a console 761 if (GetStdHandle(STD_OUTPUT_HANDLE)) 762 return false; 763 764 // allocate a console for this app 765 AllocConsole(); 766 767 // redirect unbuffered STDOUT to the console 768 HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE); 769 int fileDescriptor = _open_osfhandle((intptr_t)consoleHandle, _O_TEXT); 770 FILE *fp = _fdopen( fileDescriptor, "w" ); 771 *stdout = *fp; 772 setvbuf( stdout, NULL, _IONBF, 0 ); 773 774 // make the console window bigger 775 CONSOLE_SCREEN_BUFFER_INFO csbi; 776 SMALL_RECT r; 777 COORD bufferSize; 778 if (!GetConsoleScreenBufferInfo(consoleHandle, &csbi)) 779 return false; 780 bufferSize.X = csbi.dwSize.X; 781 bufferSize.Y = 1000; 782 if (!SetConsoleScreenBufferSize(consoleHandle, bufferSize)) 783 return false; 784 r.Left = r.Top = 0; 785 r.Right = csbi.dwSize.X-1; 786 r.Bottom = 60; 787 if (!SetConsoleWindowInfo(consoleHandle, true, &r)) 788 return false; 789 790 // change the console window title 791 if (!SetConsoleTitle(TEXT(APP_SHORT_NAME))) 792 return false; 793 794 return true; 795} 796 797int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pCmdLine, int nCmdShow) 798{ 799 char *argv = pCmdLine; 800 consoleCreated = SetStdOutToNewConsole(); 801 main(1, &argv); 802 fflush(stdout); 803 if (consoleCreated) 804 Sleep(INFINITE); 805} 806#endif 807