vulkaninfo.c revision 64070a88a7a4411e0eb0d7148bd1a1598e74a88c
1/* 2 * 3 * Copyright (C) 2015 Valve Corporation 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included 13 * in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 * 23 * Author: Courtney Goeltzenleuchter <courtney@LunarG.com> 24 * Author: David Pinedo <david@lunarg.com> 25 * Author: Mark Lobodzinski <mark@lunarg.com> 26 */ 27#include <stdlib.h> 28#include <stdio.h> 29#include <stdbool.h> 30#include <string.h> 31#include <assert.h> 32#include <inttypes.h> 33 34#ifdef _WIN32 35#include <Windows.h> 36#include <fcntl.h> 37#include <io.h> 38#endif 39 40 41#include "vulkan/VK_KHR_surface.h" 42#include "vulkan/VK_KHR_swapchain.h" 43 44#include <vulkan/vulkan.h> 45 46#define ERR(err) printf("%s:%d: failed with %s\n", \ 47 __FILE__, __LINE__, vk_result_string(err)); 48 49#ifdef _WIN32 50 51#define snprintf _snprintf 52 53bool consoleCreated = false; 54 55#define WAIT_FOR_CONSOLE_DESTROY \ 56 do { \ 57 if (consoleCreated) \ 58 Sleep(INFINITE); \ 59 } while (0) 60#else 61 #define WAIT_FOR_CONSOLE_DESTROY 62#endif 63 64 65#define ERR_EXIT(err) \ 66 do { \ 67 ERR(err); \ 68 fflush(stdout); \ 69 WAIT_FOR_CONSOLE_DESTROY; \ 70 exit(-1); \ 71 } while (0) 72 73#if defined(NDEBUG) && defined(__GNUC__) 74#define U_ASSERT_ONLY __attribute__((unused)) 75#else 76#define U_ASSERT_ONLY 77#endif 78 79#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 80 81#define MAX_GPUS 8 82 83#define MAX_QUEUE_TYPES 5 84#define APP_SHORT_NAME "vulkaninfo" 85 86struct app_gpu; 87 88struct app_dev { 89 struct app_gpu *gpu; /* point back to the GPU */ 90 91 VkDevice obj; 92 93 94 VkFormatProperties format_props[VK_FORMAT_RANGE_SIZE]; 95}; 96 97struct layer_extension_list { 98 VkLayerProperties layer_properties; 99 uint32_t extension_count; 100 VkExtensionProperties *extension_properties; 101}; 102 103struct app_instance { 104 VkInstance instance; 105 uint32_t global_layer_count; 106 struct layer_extension_list *global_layers; 107 uint32_t global_extension_count; 108 VkExtensionProperties *global_extensions; 109}; 110 111struct app_gpu { 112 uint32_t id; 113 VkPhysicalDevice obj; 114 115 VkPhysicalDeviceProperties props; 116 117 uint32_t queue_count; 118 VkQueueFamilyProperties *queue_props; 119 VkDeviceQueueCreateInfo *queue_reqs; 120 121 VkPhysicalDeviceMemoryProperties memory_props; 122 VkPhysicalDeviceFeatures features; 123 VkPhysicalDevice limits; 124 125 uint32_t device_layer_count; 126 struct layer_extension_list *device_layers; 127 128 uint32_t device_extension_count; 129 VkExtensionProperties *device_extensions; 130 131 struct app_dev dev; 132}; 133 134static const char *vk_result_string(VkResult err) 135{ 136 switch (err) { 137#define STR(r) case r: return #r 138 STR(VK_SUCCESS); 139 STR(VK_NOT_READY); 140 STR(VK_TIMEOUT); 141 STR(VK_EVENT_SET); 142 STR(VK_EVENT_RESET); 143 STR(VK_ERROR_INITIALIZATION_FAILED); 144 STR(VK_ERROR_OUT_OF_HOST_MEMORY); 145 STR(VK_ERROR_OUT_OF_DEVICE_MEMORY); 146 STR(VK_ERROR_DEVICE_LOST); 147 STR(VK_ERROR_LAYER_NOT_PRESENT); 148 STR(VK_ERROR_EXTENSION_NOT_PRESENT); 149 STR(VK_ERROR_MEMORY_MAP_FAILED); 150 STR(VK_ERROR_INCOMPATIBLE_DRIVER); 151#undef STR 152 default: return "UNKNOWN_RESULT"; 153 } 154} 155 156static const char *vk_physical_device_type_string(VkPhysicalDeviceType type) 157{ 158 switch (type) { 159#define STR(r) case VK_PHYSICAL_DEVICE_TYPE_ ##r: return #r 160 STR(OTHER); 161 STR(INTEGRATED_GPU); 162 STR(DISCRETE_GPU); 163 STR(VIRTUAL_GPU); 164#undef STR 165 default: return "UNKNOWN_DEVICE"; 166 } 167} 168 169static const char *vk_format_string(VkFormat fmt) 170{ 171 switch (fmt) { 172#define STR(r) case VK_FORMAT_ ##r: return #r 173 STR(UNDEFINED); 174 STR(R4G4_UNORM_PACK8); 175 STR(R4G4B4A4_UNORM_PACK16); 176 STR(B4G4R4A4_UNORM_PACK16); 177 STR(R5G6B5_UNORM_PACK16); 178 STR(B5G6R5_UNORM_PACK16); 179 STR(R5G5B5A1_UNORM_PACK16); 180 STR(B5G5R5A1_UNORM_PACK16); 181 STR(A1R5G5B5_UNORM_PACK16); 182 STR(R8_UNORM); 183 STR(R8_SNORM); 184 STR(R8_USCALED); 185 STR(R8_SSCALED); 186 STR(R8_UINT); 187 STR(R8_SINT); 188 STR(R8_SRGB); 189 STR(R8G8_UNORM); 190 STR(R8G8_SNORM); 191 STR(R8G8_USCALED); 192 STR(R8G8_SSCALED); 193 STR(R8G8_UINT); 194 STR(R8G8_SINT); 195 STR(R8G8_SRGB); 196 STR(R8G8B8_UNORM); 197 STR(R8G8B8_SNORM); 198 STR(R8G8B8_USCALED); 199 STR(R8G8B8_SSCALED); 200 STR(R8G8B8_UINT); 201 STR(R8G8B8_SINT); 202 STR(R8G8B8_SRGB); 203 STR(B8G8R8_UNORM); 204 STR(B8G8R8_SNORM); 205 STR(B8G8R8_USCALED); 206 STR(B8G8R8_SSCALED); 207 STR(B8G8R8_UINT); 208 STR(B8G8R8_SINT); 209 STR(B8G8R8_SRGB); 210 STR(R8G8B8A8_UNORM); 211 STR(R8G8B8A8_SNORM); 212 STR(R8G8B8A8_USCALED); 213 STR(R8G8B8A8_SSCALED); 214 STR(R8G8B8A8_UINT); 215 STR(R8G8B8A8_SINT); 216 STR(R8G8B8A8_SRGB); 217 STR(B8G8R8A8_UNORM); 218 STR(B8G8R8A8_SNORM); 219 STR(B8G8R8A8_USCALED); 220 STR(B8G8R8A8_SSCALED); 221 STR(B8G8R8A8_UINT); 222 STR(B8G8R8A8_SINT); 223 STR(B8G8R8A8_SRGB); 224 STR(A8B8G8R8_UNORM_PACK32); 225 STR(A8B8G8R8_SNORM_PACK32); 226 STR(A8B8G8R8_USCALED_PACK32); 227 STR(A8B8G8R8_SSCALED_PACK32); 228 STR(A8B8G8R8_UINT_PACK32); 229 STR(A8B8G8R8_SINT_PACK32); 230 STR(A8B8G8R8_SRGB_PACK32); 231 STR(A2R10G10B10_UNORM_PACK32); 232 STR(A2R10G10B10_SNORM_PACK32); 233 STR(A2R10G10B10_USCALED_PACK32); 234 STR(A2R10G10B10_SSCALED_PACK32); 235 STR(A2R10G10B10_UINT_PACK32); 236 STR(A2R10G10B10_SINT_PACK32); 237 STR(A2B10G10R10_UNORM_PACK32); 238 STR(A2B10G10R10_SNORM_PACK32); 239 STR(A2B10G10R10_USCALED_PACK32); 240 STR(A2B10G10R10_SSCALED_PACK32); 241 STR(A2B10G10R10_UINT_PACK32); 242 STR(A2B10G10R10_SINT_PACK32); 243 STR(R16_UNORM); 244 STR(R16_SNORM); 245 STR(R16_USCALED); 246 STR(R16_SSCALED); 247 STR(R16_UINT); 248 STR(R16_SINT); 249 STR(R16_SFLOAT); 250 STR(R16G16_UNORM); 251 STR(R16G16_SNORM); 252 STR(R16G16_USCALED); 253 STR(R16G16_SSCALED); 254 STR(R16G16_UINT); 255 STR(R16G16_SINT); 256 STR(R16G16_SFLOAT); 257 STR(R16G16B16_UNORM); 258 STR(R16G16B16_SNORM); 259 STR(R16G16B16_USCALED); 260 STR(R16G16B16_SSCALED); 261 STR(R16G16B16_UINT); 262 STR(R16G16B16_SINT); 263 STR(R16G16B16_SFLOAT); 264 STR(R16G16B16A16_UNORM); 265 STR(R16G16B16A16_SNORM); 266 STR(R16G16B16A16_USCALED); 267 STR(R16G16B16A16_SSCALED); 268 STR(R16G16B16A16_UINT); 269 STR(R16G16B16A16_SINT); 270 STR(R16G16B16A16_SFLOAT); 271 STR(R32_UINT); 272 STR(R32_SINT); 273 STR(R32_SFLOAT); 274 STR(R32G32_UINT); 275 STR(R32G32_SINT); 276 STR(R32G32_SFLOAT); 277 STR(R32G32B32_UINT); 278 STR(R32G32B32_SINT); 279 STR(R32G32B32_SFLOAT); 280 STR(R32G32B32A32_UINT); 281 STR(R32G32B32A32_SINT); 282 STR(R32G32B32A32_SFLOAT); 283 STR(R64_UINT); 284 STR(R64_SINT); 285 STR(R64_SFLOAT); 286 STR(R64G64_UINT); 287 STR(R64G64_SINT); 288 STR(R64G64_SFLOAT); 289 STR(R64G64B64_UINT); 290 STR(R64G64B64_SINT); 291 STR(R64G64B64_SFLOAT); 292 STR(R64G64B64A64_UINT); 293 STR(R64G64B64A64_SINT); 294 STR(R64G64B64A64_SFLOAT); 295 STR(B10G11R11_UFLOAT_PACK32); 296 STR(E5B9G9R9_UFLOAT_PACK32); 297 STR(D16_UNORM); 298 STR(X8_D24_UNORM_PACK32); 299 STR(D32_SFLOAT); 300 STR(S8_UINT); 301 STR(D16_UNORM_S8_UINT); 302 STR(D24_UNORM_S8_UINT); 303 STR(D32_SFLOAT_S8_UINT); 304 STR(BC1_RGB_UNORM_BLOCK); 305 STR(BC1_RGB_SRGB_BLOCK); 306 STR(BC2_UNORM_BLOCK); 307 STR(BC2_SRGB_BLOCK); 308 STR(BC3_UNORM_BLOCK); 309 STR(BC3_SRGB_BLOCK); 310 STR(BC4_UNORM_BLOCK); 311 STR(BC4_SNORM_BLOCK); 312 STR(BC5_UNORM_BLOCK); 313 STR(BC5_SNORM_BLOCK); 314 STR(BC6H_UFLOAT_BLOCK); 315 STR(BC6H_SFLOAT_BLOCK); 316 STR(BC7_UNORM_BLOCK); 317 STR(BC7_SRGB_BLOCK); 318 STR(ETC2_R8G8B8_UNORM_BLOCK); 319 STR(ETC2_R8G8B8A1_UNORM_BLOCK); 320 STR(ETC2_R8G8B8A8_UNORM_BLOCK); 321 STR(EAC_R11_UNORM_BLOCK); 322 STR(EAC_R11_SNORM_BLOCK); 323 STR(EAC_R11G11_UNORM_BLOCK); 324 STR(EAC_R11G11_SNORM_BLOCK); 325 STR(ASTC_4x4_UNORM_BLOCK); 326 STR(ASTC_4x4_SRGB_BLOCK); 327 STR(ASTC_5x4_UNORM_BLOCK); 328 STR(ASTC_5x4_SRGB_BLOCK); 329 STR(ASTC_5x5_UNORM_BLOCK); 330 STR(ASTC_5x5_SRGB_BLOCK); 331 STR(ASTC_6x5_UNORM_BLOCK); 332 STR(ASTC_6x5_SRGB_BLOCK); 333 STR(ASTC_6x6_UNORM_BLOCK); 334 STR(ASTC_6x6_SRGB_BLOCK); 335 STR(ASTC_8x5_UNORM_BLOCK); 336 STR(ASTC_8x5_SRGB_BLOCK); 337 STR(ASTC_8x6_UNORM_BLOCK); 338 STR(ASTC_8x6_SRGB_BLOCK); 339 STR(ASTC_8x8_UNORM_BLOCK); 340 STR(ASTC_8x8_SRGB_BLOCK); 341 STR(ASTC_10x5_UNORM_BLOCK); 342 STR(ASTC_10x5_SRGB_BLOCK); 343 STR(ASTC_10x6_UNORM_BLOCK); 344 STR(ASTC_10x6_SRGB_BLOCK); 345 STR(ASTC_10x8_UNORM_BLOCK); 346 STR(ASTC_10x8_SRGB_BLOCK); 347 STR(ASTC_10x10_UNORM_BLOCK); 348 STR(ASTC_10x10_SRGB_BLOCK); 349 STR(ASTC_12x10_UNORM_BLOCK); 350 STR(ASTC_12x10_SRGB_BLOCK); 351 STR(ASTC_12x12_UNORM_BLOCK); 352 STR(ASTC_12x12_SRGB_BLOCK); 353#undef STR 354 default: return "UNKNOWN_FORMAT"; 355 } 356} 357 358static void app_dev_init_formats(struct app_dev *dev) 359{ 360 VkFormat f; 361 362 for (f = 0; f < VK_FORMAT_RANGE_SIZE; f++) { 363 const VkFormat fmt = f; 364 365 vkGetPhysicalDeviceFormatProperties(dev->gpu->obj, fmt, &dev->format_props[f]); 366 } 367} 368 369static void extract_version(uint32_t version, uint32_t *major, uint32_t *minor, uint32_t *patch) 370{ 371 *major = version >> 22; 372 *minor = (version >> 12) & 0x3ff; 373 *patch = version & 0xfff; 374} 375 376static void app_get_physical_device_layer_extensions( 377 struct app_gpu *gpu, 378 char *layer_name, 379 uint32_t *extension_count, 380 VkExtensionProperties **extension_properties) 381{ 382 VkResult err; 383 uint32_t ext_count = 0; 384 VkExtensionProperties *ext_ptr = NULL; 385 386 /* repeat get until VK_INCOMPLETE goes away */ 387 do { 388 err = vkEnumerateDeviceExtensionProperties(gpu->obj, layer_name, &ext_count, NULL); 389 assert(!err); 390 391 if (ext_ptr) { 392 free(ext_ptr); 393 } 394 ext_ptr = malloc(ext_count * sizeof(VkExtensionProperties)); 395 err = vkEnumerateDeviceExtensionProperties(gpu->obj, layer_name, &ext_count, ext_ptr); 396 } while (err == VK_INCOMPLETE); 397 assert(!err); 398 399 *extension_count = ext_count; 400 *extension_properties = ext_ptr; 401} 402 403static void app_dev_init(struct app_dev *dev, struct app_gpu *gpu) 404{ 405 VkDeviceCreateInfo info = { 406 .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, 407 .pNext = NULL, 408 .queueCreateInfoCount = 0, 409 .pQueueCreateInfos = NULL, 410 .enabledLayerNameCount = 0, 411 .ppEnabledLayerNames = NULL, 412 .enabledExtensionNameCount = 0, 413 .ppEnabledExtensionNames = NULL, 414 }; 415 VkResult U_ASSERT_ONLY err; 416 // Extensions to enable 417 static const char *known_extensions[] = { 418 VK_KHR_SWAPCHAIN_EXTENSION_NAME, 419 }; 420 421 uint32_t count = 0; 422 423 /* Scan layers */ 424 VkLayerProperties *device_layer_properties = NULL; 425 struct layer_extension_list *device_layers = NULL; 426 427 do { 428 err = vkEnumerateDeviceLayerProperties(gpu->obj, &count, NULL); 429 assert(!err); 430 431 if (device_layer_properties) { 432 free(device_layer_properties); 433 } 434 device_layer_properties = malloc(sizeof(VkLayerProperties) * count); 435 assert(device_layer_properties); 436 437 if (device_layers) { 438 free(device_layers); 439 } 440 device_layers = malloc(sizeof(struct layer_extension_list) * count); 441 assert(device_layers); 442 443 err = vkEnumerateDeviceLayerProperties(gpu->obj, &count, device_layer_properties); 444 } while (err == VK_INCOMPLETE); 445 assert(!err); 446 447 gpu->device_layer_count = count; 448 gpu->device_layers = device_layers; 449 450 for (uint32_t i = 0; i < gpu->device_layer_count; i++) { 451 VkLayerProperties *src_info = &device_layer_properties[i]; 452 struct layer_extension_list *dst_info = &gpu->device_layers[i]; 453 memcpy(&dst_info->layer_properties, src_info, sizeof(VkLayerProperties)); 454 455 /* Save away layer extension info for report */ 456 app_get_physical_device_layer_extensions( 457 gpu, 458 src_info->layerName, 459 &dst_info->extension_count, 460 &dst_info->extension_properties); 461 } 462 free(device_layer_properties); 463 464 app_get_physical_device_layer_extensions( 465 gpu, 466 NULL, 467 &gpu->device_extension_count, 468 &gpu->device_extensions); 469 470 fflush(stdout); 471 472 uint32_t enabled_extension_count = 0; 473 uint32_t known_extension_count = ARRAY_SIZE(known_extensions); 474 475 for (uint32_t i = 0; i < known_extension_count; i++) { 476 VkBool32 extension_found = 0; 477 for (uint32_t j = 0; j < gpu->device_extension_count; j++) { 478 VkExtensionProperties *ext_prop = &gpu->device_extensions[j]; 479 if (!strcmp(known_extensions[i], ext_prop->extensionName)) { 480 481 extension_found = 1; 482 enabled_extension_count++; 483 } 484 } 485 if (!extension_found) { 486 printf("Cannot find extension: %s\n", known_extensions[i]); 487 ERR_EXIT(VK_ERROR_EXTENSION_NOT_PRESENT); 488 } 489 } 490 491 /* request all queues */ 492 info.queueCreateInfoCount = gpu->queue_count; 493 info.pQueueCreateInfos = gpu->queue_reqs; 494 495 info.enabledLayerNameCount = 0; 496 info.ppEnabledLayerNames = NULL; 497 info.enabledExtensionNameCount = enabled_extension_count; 498 info.ppEnabledExtensionNames = (const char*const*) known_extensions; 499 dev->gpu = gpu; 500 err = vkCreateDevice(gpu->obj, &info, NULL, &dev->obj); 501 if (err) 502 ERR_EXIT(err); 503 504} 505 506static void app_dev_destroy(struct app_dev *dev) 507{ 508 vkDestroyDevice(dev->obj, NULL); 509} 510 511static void app_get_global_layer_extensions( 512 char *layer_name, 513 uint32_t *extension_count, 514 VkExtensionProperties **extension_properties) 515{ 516 VkResult err; 517 uint32_t ext_count = 0; 518 VkExtensionProperties *ext_ptr = NULL; 519 520 /* repeat get until VK_INCOMPLETE goes away */ 521 do { 522 err = vkEnumerateInstanceExtensionProperties(layer_name, &ext_count, NULL); 523 assert(!err); 524 525 if (ext_ptr) { 526 free(ext_ptr); 527 } 528 ext_ptr = malloc(ext_count * sizeof(VkExtensionProperties)); 529 err = vkEnumerateInstanceExtensionProperties(layer_name, &ext_count, ext_ptr); 530 } while (err == VK_INCOMPLETE); 531 assert(!err); 532 533 *extension_count = ext_count; 534 *extension_properties = ext_ptr; 535} 536 537static void app_create_instance(struct app_instance *inst) 538{ 539 const VkApplicationInfo app_info = { 540 .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, 541 .pNext = NULL, 542 .pApplicationName = APP_SHORT_NAME, 543 .applicationVersion = 1, 544 .pEngineName = APP_SHORT_NAME, 545 .engineVersion = 1, 546 .apiVersion = VK_API_VERSION, 547 }; 548 VkInstanceCreateInfo inst_info = { 549 .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, 550 .pNext = NULL, 551 .pApplicationInfo = &app_info, 552 .enabledLayerNameCount = 0, 553 .ppEnabledLayerNames = NULL, 554 .enabledExtensionNameCount = 0, 555 .ppEnabledExtensionNames = NULL, 556 }; 557 VkResult U_ASSERT_ONLY err; 558 // Global Extensions to enable 559 static char *known_extensions[] = { 560 VK_KHR_SURFACE_EXTENSION_NAME, 561 }; 562 563 uint32_t global_extension_count = 0; 564 uint32_t count = 0; 565 566 /* Scan layers */ 567 VkLayerProperties *global_layer_properties = NULL; 568 struct layer_extension_list *global_layers = NULL; 569 570 do { 571 err = vkEnumerateInstanceLayerProperties(&count, NULL); 572 assert(!err); 573 574 if (global_layer_properties) { 575 free(global_layer_properties); 576 } 577 global_layer_properties = malloc(sizeof(VkLayerProperties) * count); 578 assert(global_layer_properties); 579 580 if (global_layers) { 581 free(global_layers); 582 } 583 global_layers = malloc(sizeof(struct layer_extension_list) * count); 584 assert(global_layers); 585 586 err = vkEnumerateInstanceLayerProperties(&count, global_layer_properties); 587 } while (err == VK_INCOMPLETE); 588 assert(!err); 589 590 inst->global_layer_count = count; 591 inst->global_layers = global_layers; 592 593 for (uint32_t i = 0; i < inst->global_layer_count; i++) { 594 VkLayerProperties *src_info = &global_layer_properties[i]; 595 struct layer_extension_list *dst_info = &inst->global_layers[i]; 596 memcpy(&dst_info->layer_properties, src_info, sizeof(VkLayerProperties)); 597 598 /* Save away layer extension info for report */ 599 app_get_global_layer_extensions( 600 src_info->layerName, 601 &dst_info->extension_count, 602 &dst_info->extension_properties); 603 } 604 free(global_layer_properties); 605 606 /* Collect global extensions */ 607 inst->global_extension_count = 0; 608 app_get_global_layer_extensions( 609 NULL, 610 &inst->global_extension_count, 611 &inst->global_extensions); 612 613 for (uint32_t i = 0; i < ARRAY_SIZE(known_extensions); i++) { 614 VkBool32 extension_found = 0; 615 for (uint32_t j = 0; j < inst->global_extension_count; j++) { 616 VkExtensionProperties *extension_prop = &inst->global_extensions[j]; 617 if (!strcmp(known_extensions[i], extension_prop->extensionName)) { 618 619 extension_found = 1; 620 global_extension_count++; 621 } 622 } 623 if (!extension_found) { 624 printf("Cannot find extension: %s\n", known_extensions[i]); 625 ERR_EXIT(VK_ERROR_EXTENSION_NOT_PRESENT); 626 } 627 } 628 629 inst_info.enabledExtensionNameCount = global_extension_count; 630 inst_info.ppEnabledExtensionNames = (const char * const *) known_extensions; 631 632 err = vkCreateInstance(&inst_info, NULL, &inst->instance); 633 if (err == VK_ERROR_INCOMPATIBLE_DRIVER) { 634 printf("Cannot create Vulkan instance.\n"); 635 ERR_EXIT(err); 636 } else if (err) { 637 ERR_EXIT(err); 638 } 639} 640 641static void app_destroy_instance(struct app_instance *inst) 642{ 643 free(inst->global_extensions); 644 vkDestroyInstance(inst->instance, NULL); 645} 646 647 648static void app_gpu_init(struct app_gpu *gpu, uint32_t id, VkPhysicalDevice obj) 649{ 650 uint32_t i; 651 652 memset(gpu, 0, sizeof(*gpu)); 653 654 gpu->id = id; 655 gpu->obj = obj; 656 657 vkGetPhysicalDeviceProperties(gpu->obj, &gpu->props); 658 659 /* get queue count */ 660 vkGetPhysicalDeviceQueueFamilyProperties(gpu->obj, &gpu->queue_count, NULL); 661 662 gpu->queue_props = 663 malloc(sizeof(gpu->queue_props[0]) * gpu->queue_count); 664 665 if (!gpu->queue_props) 666 ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY); 667 vkGetPhysicalDeviceQueueFamilyProperties(gpu->obj, &gpu->queue_count, gpu->queue_props); 668 669 /* set up queue requests */ 670 gpu->queue_reqs = malloc(sizeof(*gpu->queue_reqs) * gpu->queue_count); 671 if (!gpu->queue_reqs) 672 ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY); 673 for (i = 0; i < gpu->queue_count; i++) { 674 float *queue_priorities = malloc(gpu->queue_props[i].queueCount * sizeof(float)); 675 memset(queue_priorities, 0, gpu->queue_props[i].queueCount * sizeof(float)); 676 gpu->queue_reqs[i].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; 677 gpu->queue_reqs[i].pNext = NULL; 678 gpu->queue_reqs[i].queueFamilyIndex = i; 679 gpu->queue_reqs[i].queueCount = gpu->queue_props[i].queueCount; 680 gpu->queue_reqs[i].pQueuePriorities = queue_priorities; 681 } 682 683 vkGetPhysicalDeviceMemoryProperties(gpu->obj, &gpu->memory_props); 684 685 vkGetPhysicalDeviceFeatures(gpu->obj, &gpu->features); 686 687 app_dev_init(&gpu->dev, gpu); 688 app_dev_init_formats(&gpu->dev); 689} 690 691static void app_gpu_destroy(struct app_gpu *gpu) 692{ 693 app_dev_destroy(&gpu->dev); 694 free(gpu->device_extensions); 695 free(gpu->queue_reqs); 696 for (uint32_t i = 0; i < gpu->queue_count; i++) { 697 free((void *) gpu->queue_reqs[i].pQueuePriorities); 698 } 699 free(gpu->queue_props); 700} 701 702static void app_dev_dump_format_props(const struct app_dev *dev, VkFormat fmt) 703{ 704 const VkFormatProperties *props = &dev->format_props[fmt]; 705 struct { 706 const char *name; 707 VkFlags flags; 708 } features[3]; 709 uint32_t i; 710 711 features[0].name = "linearTiling FormatFeatureFlags"; 712 features[0].flags = props->linearTilingFeatures; 713 features[1].name = "optimalTiling FormatFeatureFlags"; 714 features[1].flags = props->optimalTilingFeatures; 715 features[2].name = "bufferFeatures FormatFeatureFlags"; 716 features[2].flags = props->bufferFeatures; 717 718 printf("\nFORMAT_%s:", vk_format_string(fmt)); 719 for (i = 0; i < ARRAY_SIZE(features); i++) { 720 printf("\n\t%s:", features[i].name); 721 if (features[i].flags == 0) { 722 printf("\n\t\tNone"); 723 } else { 724 printf("%s%s%s%s%s%s%s%s%s%s%s%s", 725 ((features[i].flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) ? "\n\t\tVK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT" : ""), 726 ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) ? "\n\t\tVK_FORMAT_FEATURE_STORAGE_IMAGE_BIT" : ""), 727 ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT) ? "\n\t\tVK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT" : ""), 728 ((features[i].flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) ? "\n\t\tVK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT" : ""), 729 ((features[i].flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT) ? "\n\t\tVK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT" : ""), 730 ((features[i].flags & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) ? "\n\t\tVK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT" : ""), 731 ((features[i].flags & VK_FORMAT_FEATURE_BLIT_SRC_BIT) ? "\n\t\tVK_FORMAT_FEATURE_BLIT_SRC_BIT" : ""), 732 ((features[i].flags & VK_FORMAT_FEATURE_BLIT_DST_BIT) ? "\n\t\tVK_FORMAT_FEATURE_BLIT_DST_BIT" : ""), 733 ((features[i].flags & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT) ? "\n\t\tVK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT" : ""), 734 ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT) ? "\n\t\tVK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT" : ""), 735 ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT) ? "\n\t\tVK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT" : ""), 736 ((features[i].flags & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) ? "\n\t\tVK_FORMAT_FEATURE_VERTEX_BUFFER_BIT" : "")); 737 } 738 } 739 printf("\n"); 740} 741 742 743static void 744app_dev_dump(const struct app_dev *dev) 745{ 746 VkFormat fmt; 747 748 for (fmt = 0; fmt < VK_FORMAT_RANGE_SIZE; fmt++) { 749 app_dev_dump_format_props(dev, fmt); 750 } 751} 752 753#ifdef _WIN32 754#define PRINTF_SIZE_T_SPECIFIER "%Iu" 755#else 756#define PRINTF_SIZE_T_SPECIFIER "%zu" 757#endif 758 759static void app_gpu_dump_features(const struct app_gpu *gpu) 760{ 761 const VkPhysicalDeviceFeatures *features = &gpu->features; 762 763 printf("VkPhysicalDeviceFeatures:\n"); 764 printf("=========================\n"); 765 766 printf("\trobustBufferAccess = %u\n", features->robustBufferAccess ); 767 printf("\tfullDrawIndexUint32 = %u\n", features->fullDrawIndexUint32 ); 768 printf("\timageCubeArray = %u\n", features->imageCubeArray ); 769 printf("\tindependentBlend = %u\n", features->independentBlend ); 770 printf("\tgeometryShader = %u\n", features->geometryShader ); 771 printf("\ttessellationShader = %u\n", features->tessellationShader ); 772 printf("\tsampleRateShading = %u\n", features->sampleRateShading ); 773 printf("\tdualSrcBlend = %u\n", features->dualSrcBlend ); 774 printf("\tlogicOp = %u\n", features->logicOp ); 775 printf("\tmultiDrawIndirect = %u\n", features->multiDrawIndirect ); 776 printf("\tdepthClamp = %u\n", features->depthClamp ); 777 printf("\tdepthBiasClamp = %u\n", features->depthBiasClamp ); 778 printf("\tfillModeNonSolid = %u\n", features->fillModeNonSolid ); 779 printf("\tdepthBounds = %u\n", features->depthBounds ); 780 printf("\twideLines = %u\n", features->wideLines ); 781 printf("\tlargePoints = %u\n", features->largePoints ); 782 printf("\ttextureCompressionETC2 = %u\n", features->textureCompressionETC2 ); 783 printf("\ttextureCompressionASTC_LDR = %u\n", features->textureCompressionASTC_LDR ); 784 printf("\ttextureCompressionBC = %u\n", features->textureCompressionBC ); 785 printf("\tocclusionQueryPrecise = %u\n", features->occlusionQueryPrecise ); 786 printf("\tpipelineStatisticsQuery = %u\n", features->pipelineStatisticsQuery ); 787 printf("\tvertexSideEffects = %u\n", features->vertexPipelineStoresAndAtomics ); 788 printf("\ttessellationSideEffects = %u\n", features->fragmentStoresAndAtomics ); 789 printf("\tgeometrySideEffects = %u\n", features->shaderTessellationAndGeometryPointSize ); 790 printf("\tshaderImageGatherExtended = %u\n", features->shaderImageGatherExtended ); 791 printf("\tshaderStorageImageExtendedFormats = %u\n", features->shaderStorageImageExtendedFormats ); 792 printf("\tshaderStorageImageMultisample = %u\n", features->shaderStorageImageMultisample ); 793 printf("\tshaderStorageImageReadWithoutFormat = %u\n", features->shaderStorageImageReadWithoutFormat ); 794 printf("\tshaderStorageImageWriteWithoutFormat = %u\n", features->shaderStorageImageWriteWithoutFormat ); 795 printf("\tshaderUniformBufferArrayDynamicIndexing = %u\n", features->shaderUniformBufferArrayDynamicIndexing); 796 printf("\tshaderSampledImageArrayDynamicIndexing = %u\n", features->shaderSampledImageArrayDynamicIndexing ); 797 printf("\tshaderStorageBufferArrayDynamicIndexing = %u\n", features->shaderStorageBufferArrayDynamicIndexing); 798 printf("\tshaderStorageImageArrayDynamicIndexing = %u\n", features->shaderStorageImageArrayDynamicIndexing ); 799 printf("\tshaderClipDistance = %u\n", features->shaderClipDistance ); 800 printf("\tshaderCullDistance = %u\n", features->shaderCullDistance ); 801 printf("\tshaderFloat64 = %u\n", features->shaderFloat64 ); 802 printf("\tshaderInt64 = %u\n", features->shaderInt64 ); 803 printf("\tshaderInt16 = %u\n", features->shaderInt16 ); 804 printf("\tshaderResourceResidency = %u\n", features->shaderResourceResidency ); 805 printf("\tshaderResourceMinLod = %u\n", features->shaderResourceMinLod ); 806 printf("\talphaToOne = %u\n", features->alphaToOne ); 807 printf("\tsparseBinding = %u\n", features->sparseBinding ); 808 printf("\tsparseResidencyBuffer = %u\n", features->sparseResidencyBuffer ); 809 printf("\tsparseResidencyImage2D = %u\n", features->sparseResidencyImage2D ); 810 printf("\tsparseResidencyImage3D = %u\n", features->sparseResidencyImage3D ); 811 printf("\tsparseResidency2Samples = %u\n", features->sparseResidency2Samples ); 812 printf("\tsparseResidency4Samples = %u\n", features->sparseResidency4Samples ); 813 printf("\tsparseResidency8Samples = %u\n", features->sparseResidency8Samples ); 814 printf("\tsparseResidency16Samples = %u\n", features->sparseResidency16Samples ); 815 printf("\tsparseResidencyAliased = %u\n", features->sparseResidencyAliased ); 816 printf("\tvariableMultisampleRate = %u\n", features->variableMultisampleRate ); 817} 818 819static void app_dump_sparse_props(const VkPhysicalDeviceSparseProperties *sparseProps) 820{ 821 822 printf("\tVkPhysicalDeviceSparseProperties:\n"); 823 printf("\t---------------------------------\n"); 824 825 printf("\t\tresidencyStandard2DBlockShape = %u\n", sparseProps->residencyStandard2DBlockShape ); 826 printf("\t\tresidencyStandard2DMultisampleBlockShape = %u\n", sparseProps->residencyStandard2DMultisampleBlockShape); 827 printf("\t\tresidencyStandard3DBlockShape = %u\n", sparseProps->residencyStandard3DBlockShape ); 828 printf("\t\tresidencyAlignedMipSize = %u\n", sparseProps->residencyAlignedMipSize ); 829 printf("\t\tresidencyNonResidentStrict = %u\n", sparseProps->residencyNonResidentStrict ); 830} 831 832static void app_dump_limits(const VkPhysicalDeviceLimits *limits) 833{ 834 printf("\tVkPhysicalDeviceLimits:\n"); 835 printf("\t-----------------------\n"); 836 837 printf("\t\tmaxImageDimension1D = 0x%" PRIxLEAST32 "\n", limits->maxImageDimension1D ); 838 printf("\t\tmaxImageDimension2D = 0x%" PRIxLEAST32 "\n", limits->maxImageDimension2D ); 839 printf("\t\tmaxImageDimension3D = 0x%" PRIxLEAST32 "\n", limits->maxImageDimension3D ); 840 printf("\t\tmaxImageDimensionCube = 0x%" PRIxLEAST32 "\n", limits->maxImageDimensionCube ); 841 printf("\t\tmaxImageArrayLayers = 0x%" PRIxLEAST32 "\n", limits->maxImageArrayLayers ); 842 printf("\t\tmaxTexelBufferElements = 0x%" PRIxLEAST32 "\n", limits->maxTexelBufferElements ); 843 printf("\t\tmaxUniformBufferRange = 0x%" PRIxLEAST32 "\n", limits->maxUniformBufferRange ); 844 printf("\t\tmaxStorageBufferRange = 0x%" PRIxLEAST32 "\n", limits->maxStorageBufferRange ); 845 printf("\t\tmaxPushConstantsSize = 0x%" PRIxLEAST32 "\n", limits->maxPushConstantsSize ); 846 printf("\t\tmaxMemoryAllocationCount = 0x%" PRIxLEAST32 "\n", limits->maxMemoryAllocationCount ); 847 printf("\t\tmaxSamplerAllocationCount = 0x%" PRIxLEAST32 "\n", limits->maxSamplerAllocationCount ); 848 printf("\t\tbufferImageGranularity = 0x%" PRIxLEAST64 "\n", limits->bufferImageGranularity ); 849 printf("\t\tsparseAddressSpaceSize = 0x%" PRIxLEAST64 "\n", limits->sparseAddressSpaceSize ); 850 printf("\t\tmaxBoundDescriptorSets = 0x%" PRIxLEAST32 "\n", limits->maxBoundDescriptorSets ); 851 printf("\t\tmaxPerStageDescriptorSamplers = 0x%" PRIxLEAST32 "\n", limits->maxPerStageDescriptorSamplers ); 852 printf("\t\tmaxPerStageDescriptorUniformBuffers = 0x%" PRIxLEAST32 "\n", limits->maxPerStageDescriptorUniformBuffers ); 853 printf("\t\tmaxPerStageDescriptorStorageBuffers = 0x%" PRIxLEAST32 "\n", limits->maxPerStageDescriptorStorageBuffers ); 854 printf("\t\tmaxPerStageDescriptorSampledImages = 0x%" PRIxLEAST32 "\n", limits->maxPerStageDescriptorSampledImages ); 855 printf("\t\tmaxPerStageDescriptorStorageImages = 0x%" PRIxLEAST32 "\n", limits->maxPerStageDescriptorStorageImages ); 856 printf("\t\tmaxPerStageDescriptorInputAttachments = 0x%" PRIxLEAST32 "\n", limits->maxPerStageDescriptorInputAttachments ); 857 printf("\t\tmaxPerStageResources = 0x%" PRIxLEAST32 "\n", limits->maxPerStageResources ); 858 printf("\t\tmaxDescriptorSetSamplers = 0x%" PRIxLEAST32 "\n", limits->maxDescriptorSetSamplers ); 859 printf("\t\tmaxDescriptorSetUniformBuffers = 0x%" PRIxLEAST32 "\n", limits->maxDescriptorSetUniformBuffers ); 860 printf("\t\tmaxDescriptorSetUniformBuffersDynamic = 0x%" PRIxLEAST32 "\n", limits->maxDescriptorSetUniformBuffersDynamic ); 861 printf("\t\tmaxDescriptorSetStorageBuffers = 0x%" PRIxLEAST32 "\n", limits->maxDescriptorSetStorageBuffers ); 862 printf("\t\tmaxDescriptorSetStorageBuffersDynamic = 0x%" PRIxLEAST32 "\n", limits->maxDescriptorSetStorageBuffersDynamic ); 863 printf("\t\tmaxDescriptorSetSampledImages = 0x%" PRIxLEAST32 "\n", limits->maxDescriptorSetSampledImages ); 864 printf("\t\tmaxDescriptorSetStorageImages = 0x%" PRIxLEAST32 "\n", limits->maxDescriptorSetStorageImages ); 865 printf("\t\tmaxDescriptorSetInputAttachments = 0x%" PRIxLEAST32 "\n", limits->maxDescriptorSetInputAttachments ); 866 printf("\t\tmaxVertexInputAttributes = 0x%" PRIxLEAST32 "\n", limits->maxVertexInputAttributes ); 867 printf("\t\tmaxVertexInputBindings = 0x%" PRIxLEAST32 "\n", limits->maxVertexInputBindings ); 868 printf("\t\tmaxVertexInputAttributeOffset = 0x%" PRIxLEAST32 "\n", limits->maxVertexInputAttributeOffset ); 869 printf("\t\tmaxVertexInputBindingStride = 0x%" PRIxLEAST32 "\n", limits->maxVertexInputBindingStride ); 870 printf("\t\tmaxVertexOutputComponents = 0x%" PRIxLEAST32 "\n", limits->maxVertexOutputComponents ); 871 printf("\t\tmaxTessellationGenerationLevel = 0x%" PRIxLEAST32 "\n", limits->maxTessellationGenerationLevel ); 872 printf("\t\tmaxTessellationPatchSize = 0x%" PRIxLEAST32 "\n", limits->maxTessellationPatchSize ); 873 printf("\t\tmaxTessellationControlPerVertexInputComponents = 0x%" PRIxLEAST32 "\n", limits->maxTessellationControlPerVertexInputComponents ); 874 printf("\t\tmaxTessellationControlPerVertexOutputComponents = 0x%" PRIxLEAST32 "\n", limits->maxTessellationControlPerVertexOutputComponents); 875 printf("\t\tmaxTessellationControlPerPatchOutputComponents = 0x%" PRIxLEAST32 "\n", limits->maxTessellationControlPerPatchOutputComponents ); 876 printf("\t\tmaxTessellationControlTotalOutputComponents = 0x%" PRIxLEAST32 "\n", limits->maxTessellationControlTotalOutputComponents ); 877 printf("\t\tmaxTessellationEvaluationInputComponents = 0x%" PRIxLEAST32 "\n", limits->maxTessellationEvaluationInputComponents ); 878 printf("\t\tmaxTessellationEvaluationOutputComponents = 0x%" PRIxLEAST32 "\n", limits->maxTessellationEvaluationOutputComponents ); 879 printf("\t\tmaxGeometryShaderInvocations = 0x%" PRIxLEAST32 "\n", limits->maxGeometryShaderInvocations ); 880 printf("\t\tmaxGeometryInputComponents = 0x%" PRIxLEAST32 "\n", limits->maxGeometryInputComponents ); 881 printf("\t\tmaxGeometryOutputComponents = 0x%" PRIxLEAST32 "\n", limits->maxGeometryOutputComponents ); 882 printf("\t\tmaxGeometryOutputVertices = 0x%" PRIxLEAST32 "\n", limits->maxGeometryOutputVertices ); 883 printf("\t\tmaxGeometryTotalOutputComponents = 0x%" PRIxLEAST32 "\n", limits->maxGeometryTotalOutputComponents ); 884 printf("\t\tmaxFragmentInputComponents = 0x%" PRIxLEAST32 "\n", limits->maxFragmentInputComponents ); 885 printf("\t\tmaxFragmentOutputAttachments = 0x%" PRIxLEAST32 "\n", limits->maxFragmentOutputAttachments ); 886 printf("\t\tmaxFragmentDualSrcAttachments = 0x%" PRIxLEAST32 "\n", limits->maxFragmentDualSrcAttachments ); 887 printf("\t\tmaxFragmentCombinedOutputResources = 0x%" PRIxLEAST32 "\n", limits->maxFragmentCombinedOutputResources ); 888 printf("\t\tmaxComputeSharedMemorySize = 0x%" PRIxLEAST32 "\n", limits->maxComputeSharedMemorySize ); 889 printf("\t\tmaxComputeWorkGroupCount[0] = 0x%" PRIxLEAST32 "\n", limits->maxComputeWorkGroupCount[0] ); 890 printf("\t\tmaxComputeWorkGroupCount[1] = 0x%" PRIxLEAST32 "\n", limits->maxComputeWorkGroupCount[1] ); 891 printf("\t\tmaxComputeWorkGroupCount[2] = 0x%" PRIxLEAST32 "\n", limits->maxComputeWorkGroupCount[2] ); 892 printf("\t\tmaxComputeWorkGroupInvocations = 0x%" PRIxLEAST32 "\n", limits->maxComputeWorkGroupInvocations ); 893 printf("\t\tmaxComputeWorkGroupSize[0] = 0x%" PRIxLEAST32 "\n", limits->maxComputeWorkGroupSize[0] ); 894 printf("\t\tmaxComputeWorkGroupSize[1] = 0x%" PRIxLEAST32 "\n", limits->maxComputeWorkGroupSize[1] ); 895 printf("\t\tmaxComputeWorkGroupSize[2] = 0x%" PRIxLEAST32 "\n", limits->maxComputeWorkGroupSize[2] ); 896 printf("\t\tsubPixelPrecisionBits = 0x%" PRIxLEAST32 "\n", limits->subPixelPrecisionBits ); 897 printf("\t\tsubTexelPrecisionBits = 0x%" PRIxLEAST32 "\n", limits->subTexelPrecisionBits ); 898 printf("\t\tmipmapPrecisionBits = 0x%" PRIxLEAST32 "\n", limits->mipmapPrecisionBits ); 899 printf("\t\tmaxDrawIndexedIndexValue = 0x%" PRIxLEAST32 "\n", limits->maxDrawIndexedIndexValue ); 900 printf("\t\tmaxDrawIndirectCount = 0x%" PRIxLEAST32 "\n", limits->maxDrawIndirectCount ); 901 printf("\t\tmaxSamplerLodBias = %f\n", limits->maxSamplerLodBias ); 902 printf("\t\tmaxSamplerAnisotropy = %f\n", limits->maxSamplerAnisotropy ); 903 printf("\t\tmaxViewports = 0x%" PRIxLEAST32 "\n", limits->maxViewports ); 904 printf("\t\tmaxViewportDimensions[0] = 0x%" PRIxLEAST32 "\n", limits->maxViewportDimensions[0] ); 905 printf("\t\tmaxViewportDimensions[1] = 0x%" PRIxLEAST32 "\n", limits->maxViewportDimensions[1] ); 906 printf("\t\tviewportBoundsRange[0] = %f\n", limits->viewportBoundsRange[0] ); 907 printf("\t\tviewportBoundsRange[1] = %f\n", limits->viewportBoundsRange[1] ); 908 printf("\t\tviewportSubPixelBits = 0x%" PRIxLEAST32 "\n", limits->viewportSubPixelBits ); 909 printf("\t\tminMemoryMapAlignment = " PRINTF_SIZE_T_SPECIFIER "\n", limits->minMemoryMapAlignment ); 910 printf("\t\tminTexelBufferOffsetAlignment = 0x%" PRIxLEAST64 "\n", limits->minTexelBufferOffsetAlignment ); 911 printf("\t\tminUniformBufferOffsetAlignment = 0x%" PRIxLEAST64 "\n", limits->minUniformBufferOffsetAlignment ); 912 printf("\t\tminStorageBufferOffsetAlignment = 0x%" PRIxLEAST64 "\n", limits->minStorageBufferOffsetAlignment ); 913 printf("\t\tminTexelOffset = 0x%" PRIxLEAST32 "\n", limits->minTexelOffset ); 914 printf("\t\tmaxTexelOffset = 0x%" PRIxLEAST32 "\n", limits->maxTexelOffset ); 915 printf("\t\tminTexelGatherOffset = 0x%" PRIxLEAST32 "\n", limits->minTexelGatherOffset ); 916 printf("\t\tmaxTexelGatherOffset = 0x%" PRIxLEAST32 "\n", limits->maxTexelGatherOffset ); 917 printf("\t\tminInterpolationOffset = %f\n", limits->minInterpolationOffset ); 918 printf("\t\tmaxInterpolationOffset = %f\n", limits->maxInterpolationOffset ); 919 printf("\t\tsubPixelInterpolationOffsetBits = 0x%" PRIxLEAST32 "\n", limits->subPixelInterpolationOffsetBits ); 920 printf("\t\tmaxFramebufferWidth = 0x%" PRIxLEAST32 "\n", limits->maxFramebufferWidth ); 921 printf("\t\tmaxFramebufferHeight = 0x%" PRIxLEAST32 "\n", limits->maxFramebufferHeight ); 922 printf("\t\tmaxFramebufferLayers = 0x%" PRIxLEAST32 "\n", limits->maxFramebufferLayers ); 923 printf("\t\tframebufferColorSampleCounts = 0x%" PRIxLEAST32 "\n", limits->framebufferColorSampleCounts ); 924 printf("\t\tframebufferDepthSampleCounts = 0x%" PRIxLEAST32 "\n", limits->framebufferDepthSampleCounts ); 925 printf("\t\tframebufferStencilSampleCounts = 0x%" PRIxLEAST32 "\n", limits->framebufferStencilSampleCounts ); 926 printf("\t\tmaxColorAttachments = 0x%" PRIxLEAST32 "\n", limits->maxColorAttachments ); 927 printf("\t\tsampledImageColorSampleCounts = 0x%" PRIxLEAST32 "\n", limits->sampledImageColorSampleCounts ); 928 printf("\t\tsampledImageDepthSampleCounts = 0x%" PRIxLEAST32 "\n", limits->sampledImageDepthSampleCounts ); 929 printf("\t\tsampledImageStencilSampleCounts = 0x%" PRIxLEAST32 "\n", limits->sampledImageStencilSampleCounts ); 930 printf("\t\tsampledImageIntegerSampleCounts = 0x%" PRIxLEAST32 "\n", limits->sampledImageIntegerSampleCounts ); 931 printf("\t\tstorageImageSampleCounts = 0x%" PRIxLEAST32 "\n", limits->storageImageSampleCounts ); 932 printf("\t\tmaxSampleMaskWords = 0x%" PRIxLEAST32 "\n", limits->maxSampleMaskWords ); 933 printf("\t\ttimestampPeriod = 0x%f\n", limits->timestampPeriod ); 934 printf("\t\tmaxClipDistances = 0x%" PRIxLEAST32 "\n", limits->maxClipDistances ); 935 printf("\t\tmaxCullDistances = 0x%" PRIxLEAST32 "\n", limits->maxCullDistances ); 936 printf("\t\tmaxCombinedClipAndCullDistances = 0x%" PRIxLEAST32 "\n", limits->maxCombinedClipAndCullDistances ); 937 printf("\t\tpointSizeRange[0] = %f\n", limits->pointSizeRange[0] ); 938 printf("\t\tpointSizeRange[1] = %f\n", limits->pointSizeRange[1] ); 939 printf("\t\tlineWidthRange[0] = %f\n", limits->lineWidthRange[0] ); 940 printf("\t\tlineWidthRange[1] = %f\n", limits->lineWidthRange[1] ); 941 printf("\t\tpointSizeGranularity = %f\n", limits->pointSizeGranularity ); 942 printf("\t\tlineWidthGranularity = %f\n", limits->lineWidthGranularity ); 943 printf("\t\tstrictLines = %u\n", limits->strictLines ); 944 printf("\t\tstandardSampleLocations = %u\n", limits->standardSampleLocations ); 945 printf("\t\toptimalBufferCopyOffsetAlignment = 0x%" PRIxLEAST64 "\n", limits->optimalBufferCopyOffsetAlignment ); 946 printf("\t\toptimalBufferCopyRowPitchAlignment = 0x%" PRIxLEAST64 "\n", limits->optimalBufferCopyRowPitchAlignment ); 947 printf("\t\tnonCoherentAtomSize = 0x%" PRIxLEAST64 "\n", limits->nonCoherentAtomSize ); 948} 949 950static void app_gpu_dump_props(const struct app_gpu *gpu) 951{ 952 const VkPhysicalDeviceProperties *props = &gpu->props; 953 954 printf("VkPhysicalDeviceProperties:\n"); 955 printf("===========================\n"); 956 printf("\tapiVersion = %u\n", props->apiVersion); 957 printf("\tdriverVersion = %u\n", props->driverVersion); 958 printf("\tvendorID = 0x%04x\n", props->vendorID); 959 printf("\tdeviceID = 0x%04x\n", props->deviceID); 960 printf("\tdeviceType = %s\n", vk_physical_device_type_string(props->deviceType)); 961 printf("\tdeviceName = %s\n", props->deviceName); 962 963 app_dump_limits(&gpu->props.limits); 964 app_dump_sparse_props(&gpu->props.sparseProperties); 965 966 fflush(stdout); 967} 968 969static void app_dump_extensions( 970 const char *indent, 971 const char *layer_name, 972 const uint32_t extension_count, 973 const VkExtensionProperties *extension_properties) 974{ 975 uint32_t i; 976 if (layer_name && (strlen(layer_name) > 0)) { 977 printf("%s%s Extensions", indent, layer_name); 978 } else { 979 printf("Extensions"); 980 } 981 printf("\tcount = %d\n", extension_count); 982 for (i=0; i< extension_count; i++) { 983 VkExtensionProperties const *ext_prop = &extension_properties[i]; 984 985 if (i>0) 986 printf("\n"); // separator between extensions 987 988 printf("%s\t", indent); 989 printf("%-32s: extension revision %2d", 990 ext_prop->extensionName, ext_prop->specVersion); 991 } 992 printf("\n"); 993 fflush(stdout); 994} 995 996static void app_gpu_dump_queue_props(const struct app_gpu *gpu, uint32_t id) 997{ 998 const VkQueueFamilyProperties *props = &gpu->queue_props[id]; 999 1000 printf("VkQueueFamilyProperties[%d]:\n", id); 1001 printf("============================\n"); 1002 printf("\tqueueFlags = %c%c%c\n", 1003 (props->queueFlags & VK_QUEUE_GRAPHICS_BIT) ? 'G' : '.', 1004 (props->queueFlags & VK_QUEUE_COMPUTE_BIT) ? 'C' : '.', 1005 (props->queueFlags & VK_QUEUE_TRANSFER_BIT) ? 'D' : '.'); 1006 printf("\tqueueCount = %u\n", props->queueCount); 1007 printf("\ttimestampValidBits = %u\n", props->timestampValidBits); 1008 printf("\tminImageTransferGranularity = (%d, %d, %d)\n", 1009 props->minImageTransferGranularity.width, 1010 props->minImageTransferGranularity.height, 1011 props->minImageTransferGranularity.depth); 1012 fflush(stdout); 1013} 1014 1015static void app_gpu_dump_memory_props(const struct app_gpu *gpu) 1016{ 1017 const VkPhysicalDeviceMemoryProperties *props = &gpu->memory_props; 1018 1019 printf("VkPhysicalDeviceMemoryProperties:\n"); 1020 printf("=================================\n"); 1021 printf("\tmemoryTypeCount = %u\n", props->memoryTypeCount); 1022 for (uint32_t i = 0; i < props->memoryTypeCount; i++) { 1023 printf("\tmemoryTypes[%u] : \n", i); 1024 printf("\t\tpropertyFlags = %u\n", props->memoryTypes[i].propertyFlags); 1025 printf("\t\theapIndex = %u\n", props->memoryTypes[i].heapIndex); 1026 } 1027 printf("\tmemoryHeapCount = %u\n", props->memoryHeapCount); 1028 for (uint32_t i = 0; i < props->memoryHeapCount; i++) { 1029 printf("\tmemoryHeaps[%u] : \n", i); 1030 printf("\t\tsize = " PRINTF_SIZE_T_SPECIFIER "\n", props->memoryHeaps[i].size); 1031 } 1032 fflush(stdout); 1033} 1034 1035static void app_gpu_dump(const struct app_gpu *gpu) 1036{ 1037 uint32_t i; 1038 1039 printf("Device Extensions and layers:\n"); 1040 printf("=============================\n"); 1041 printf("GPU%u\n", gpu->id); 1042 app_gpu_dump_props(gpu); 1043 printf("\n"); 1044 app_dump_extensions("", "Device", gpu->device_extension_count, gpu->device_extensions); 1045 printf("\n"); 1046 printf("Layers\tcount = %d\n", gpu->device_layer_count); 1047 for (uint32_t i = 0; i < gpu->device_layer_count; i++) { 1048 uint32_t major, minor, patch; 1049 char spec_version[64], layer_version[64]; 1050 struct layer_extension_list const *layer_info = &gpu->device_layers[i]; 1051 1052 extract_version(layer_info->layer_properties.specVersion, &major, &minor, &patch); 1053 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d", major, minor, patch); 1054 extract_version(layer_info->layer_properties.implementationVersion, &major, &minor, &patch); 1055 snprintf(layer_version, sizeof(layer_version), "%d.%d.%d", major, minor, patch); 1056 printf("\t%s (%s) Vulkan version %s, layer version %s\n", 1057 layer_info->layer_properties.layerName, 1058 (char*) layer_info->layer_properties.description, 1059 spec_version, layer_version); 1060 1061 app_dump_extensions("\t", 1062 layer_info->layer_properties.layerName, 1063 layer_info->extension_count, 1064 layer_info->extension_properties); 1065 fflush(stdout); 1066 } 1067 printf("\n"); 1068 for (i = 0; i < gpu->queue_count; i++) { 1069 app_gpu_dump_queue_props(gpu, i); 1070 printf("\n"); 1071 } 1072 app_gpu_dump_memory_props(gpu); 1073 printf("\n"); 1074 app_gpu_dump_features(gpu); 1075 printf("\n"); 1076 app_dev_dump(&gpu->dev); 1077} 1078 1079int main(int argc, char **argv) 1080{ 1081 unsigned int major, minor, patch; 1082 struct app_gpu gpus[MAX_GPUS]; 1083 VkPhysicalDevice objs[MAX_GPUS]; 1084 uint32_t gpu_count, i; 1085 VkResult err; 1086 struct app_instance inst; 1087 1088 major = VK_API_VERSION >> 22; 1089 minor = (VK_API_VERSION >> 12) & 0x4ff; 1090 patch = VK_API_VERSION & 0xfff; 1091 printf("===========\n"); 1092 printf("VULKAN INFO\n"); 1093 printf("===========\n\n"); 1094 printf("Vulkan API Version: %d %d %d\n\n", major, minor, patch); 1095 1096 app_create_instance(&inst); 1097 1098 printf("Instance Extensions and layers:\n"); 1099 printf("===============================\n"); 1100 app_dump_extensions("", "Instance", inst.global_extension_count, inst.global_extensions); 1101 1102 printf("Instance Layers\tcount = %d\n", inst.global_layer_count); 1103 for (uint32_t i = 0; i < inst.global_layer_count; i++) { 1104 uint32_t major, minor, patch; 1105 char spec_version[64], layer_version[64]; 1106 VkLayerProperties const *layer_prop = &inst.global_layers[i].layer_properties; 1107 1108 extract_version(layer_prop->specVersion, &major, &minor, &patch); 1109 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d", major, minor, patch); 1110 extract_version(layer_prop->implementationVersion, &major, &minor, &patch); 1111 snprintf(layer_version, sizeof(layer_version), "%d.%d.%d", major, minor, patch); 1112 printf("\t%s (%s) Vulkan version %s, layer version %s\n", 1113 layer_prop->layerName, (char*) layer_prop->description, spec_version, layer_version); 1114 1115 app_dump_extensions("\t", 1116 inst.global_layers[i].layer_properties.layerName, 1117 inst.global_layers[i].extension_count, 1118 inst.global_layers[i].extension_properties); 1119 } 1120 1121 err = vkEnumeratePhysicalDevices(inst.instance, &gpu_count, NULL); 1122 if (err) 1123 ERR_EXIT(err); 1124 if (gpu_count > MAX_GPUS) { 1125 printf("Too many GPUS found \n"); 1126 ERR_EXIT(-1); 1127 } 1128 err = vkEnumeratePhysicalDevices(inst.instance, &gpu_count, objs); 1129 if (err) 1130 ERR_EXIT(err); 1131 1132 for (i = 0; i < gpu_count; i++) { 1133 app_gpu_init(&gpus[i], i, objs[i]); 1134 app_gpu_dump(&gpus[i]); 1135 printf("\n\n"); 1136 } 1137 1138 for (i = 0; i < gpu_count; i++) 1139 app_gpu_destroy(&gpus[i]); 1140 1141 app_destroy_instance(&inst); 1142 1143 return 0; 1144} 1145 1146#ifdef _WIN32 1147 1148// Create a console window with a large scrollback size to which to send stdout. 1149// Returns true if console window was successfully created, false otherwise. 1150bool SetStdOutToNewConsole() 1151{ 1152 // don't do anything if we already have a console 1153 if (GetStdHandle(STD_OUTPUT_HANDLE)) 1154 return false; 1155 1156 // allocate a console for this app 1157 AllocConsole(); 1158 1159 // redirect unbuffered STDOUT to the console 1160 HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE); 1161 int fileDescriptor = _open_osfhandle((intptr_t)consoleHandle, _O_TEXT); 1162 FILE *fp = _fdopen( fileDescriptor, "w" ); 1163 *stdout = *fp; 1164 setvbuf( stdout, NULL, _IONBF, 0 ); 1165 1166 // make the console window bigger 1167 CONSOLE_SCREEN_BUFFER_INFO csbi; 1168 SMALL_RECT r; 1169 COORD bufferSize; 1170 if (!GetConsoleScreenBufferInfo(consoleHandle, &csbi)) 1171 return false; 1172 bufferSize.X = csbi.dwSize.X+30; 1173 bufferSize.Y = 20000; 1174 if (!SetConsoleScreenBufferSize(consoleHandle, bufferSize)) 1175 return false; 1176 r.Left = r.Top = 0; 1177 r.Right = csbi.dwSize.X-1+30; 1178 r.Bottom = 50; 1179 if (!SetConsoleWindowInfo(consoleHandle, true, &r)) 1180 return false; 1181 1182 // change the console window title 1183 if (!SetConsoleTitle(TEXT(APP_SHORT_NAME))) 1184 return false; 1185 1186 return true; 1187} 1188 1189int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pCmdLine, int nCmdShow) 1190{ 1191 char *argv = pCmdLine; 1192 consoleCreated = SetStdOutToNewConsole(); 1193 main(1, &argv); 1194 fflush(stdout); 1195 if (consoleCreated) 1196 Sleep(INFINITE); 1197} 1198#endif 1199