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