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