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