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