1 /* 2 * Copyright (c) 2015-2016 The Khronos Group Inc. 3 * Copyright (c) 2015-2016 Valve Corporation 4 * Copyright (c) 2015-2016 LunarG, Inc. 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 * 18 * Author: Courtney Goeltzenleuchter <courtney (at) LunarG.com> 19 * Author: David Pinedo <david (at) lunarg.com> 20 * Author: Mark Lobodzinski <mark (at) lunarg.com> 21 * Author: Rene Lindsay <rene (at) lunarg.com> 22 */ 23 #include <assert.h> 24 #include <inttypes.h> 25 #include <stdbool.h> 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <string.h> 29 30 #ifdef _WIN32 31 #include <fcntl.h> 32 #include <io.h> 33 #endif // _WIN32 34 35 #if defined(VK_USE_PLATFORM_XLIB_KHR) || defined(VK_USE_PLATFORM_XCB_KHR) 36 #include <X11/Xutil.h> 37 #endif 38 39 #include <vulkan/vulkan.h> 40 41 #define ERR(err) \ 42 printf("%s:%d: failed with %s\n", __FILE__, __LINE__, \ 43 vk_result_string(err)); 44 45 #ifdef _WIN32 46 47 #define snprintf _snprintf 48 49 // Returns nonzero if the console is used only for this process. Will return 50 // zero if another process (such as cmd.exe) is also attached. 51 static int ConsoleIsExclusive(void) { 52 DWORD pids[2]; 53 DWORD num_pids = GetConsoleProcessList(pids, ARRAYSIZE(pids)); 54 return num_pids <= 1; 55 } 56 57 #define WAIT_FOR_CONSOLE_DESTROY \ 58 do { \ 59 if (ConsoleIsExclusive()) \ 60 Sleep(INFINITE); \ 61 } while (0) 62 #else 63 #define WAIT_FOR_CONSOLE_DESTROY 64 #endif 65 66 #define ERR_EXIT(err) \ 67 do { \ 68 ERR(err); \ 69 fflush(stdout); \ 70 WAIT_FOR_CONSOLE_DESTROY; \ 71 exit(-1); \ 72 } while (0) 73 74 #if defined(NDEBUG) && defined(__GNUC__) 75 #define U_ASSERT_ONLY __attribute__((unused)) 76 #else 77 #define U_ASSERT_ONLY 78 #endif 79 80 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 81 82 #define MAX_GPUS 8 83 84 #define MAX_QUEUE_TYPES 5 85 #define APP_SHORT_NAME "vulkaninfo" 86 87 struct app_gpu; 88 89 struct app_dev { 90 struct app_gpu *gpu; /* point back to the GPU */ 91 92 VkDevice obj; 93 94 VkFormatProperties format_props[VK_FORMAT_RANGE_SIZE]; 95 }; 96 97 struct layer_extension_list { 98 VkLayerProperties layer_properties; 99 uint32_t extension_count; 100 VkExtensionProperties *extension_properties; 101 }; 102 103 struct 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; // Instance Extensions 109 110 PFN_vkGetPhysicalDeviceSurfaceSupportKHR 111 vkGetPhysicalDeviceSurfaceSupportKHR; 112 PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR 113 vkGetPhysicalDeviceSurfaceCapabilitiesKHR; 114 PFN_vkGetPhysicalDeviceSurfaceFormatsKHR 115 vkGetPhysicalDeviceSurfaceFormatsKHR; 116 PFN_vkGetPhysicalDeviceSurfacePresentModesKHR 117 vkGetPhysicalDeviceSurfacePresentModesKHR; 118 119 VkSurfaceKHR surface; 120 int width, height; 121 122 #ifdef VK_USE_PLATFORM_WIN32_KHR 123 HINSTANCE hInstance; // Windows Instance 124 HWND hWnd; // window handle 125 #endif 126 127 #ifdef VK_USE_PLATFORM_XCB_KHR 128 xcb_connection_t *xcb_connection; 129 xcb_screen_t *xcb_screen; 130 xcb_window_t xcb_window; 131 #endif 132 133 #ifdef VK_USE_PLATFORM_XLIB_KHR 134 Display *xlib_display; 135 Window xlib_window; 136 #endif 137 138 #ifdef VK_USE_PLATFORM_ANDROID_KHR // TODO 139 ANativeWindow *window; 140 #endif 141 }; 142 143 struct app_gpu { 144 uint32_t id; 145 VkPhysicalDevice obj; 146 147 VkPhysicalDeviceProperties props; 148 149 uint32_t queue_count; 150 VkQueueFamilyProperties *queue_props; 151 VkDeviceQueueCreateInfo *queue_reqs; 152 153 VkPhysicalDeviceMemoryProperties memory_props; 154 VkPhysicalDeviceFeatures features; 155 VkPhysicalDevice limits; 156 157 uint32_t device_extension_count; 158 VkExtensionProperties *device_extensions; 159 160 struct app_dev dev; 161 }; 162 163 static VKAPI_ATTR VkBool32 VKAPI_CALL 164 dbg_callback(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType, 165 uint64_t srcObject, size_t location, int32_t msgCode, 166 const char *pLayerPrefix, const char *pMsg, void *pUserData) { 167 char *message = (char *)malloc(strlen(pMsg) + 100); 168 169 assert(message); 170 171 if (msgFlags & VK_DEBUG_REPORT_ERROR_BIT_EXT) { 172 sprintf(message, "ERROR: [%s] Code %d : %s", pLayerPrefix, msgCode, 173 pMsg); 174 } else if (msgFlags & VK_DEBUG_REPORT_WARNING_BIT_EXT) { 175 sprintf(message, "WARNING: [%s] Code %d : %s", pLayerPrefix, msgCode, 176 pMsg); 177 } else if (msgFlags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) { 178 sprintf(message, "INFO: [%s] Code %d : %s", pLayerPrefix, msgCode, 179 pMsg); 180 } else if (msgFlags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) { 181 sprintf(message, "DEBUG: [%s] Code %d : %s", pLayerPrefix, msgCode, 182 pMsg); 183 } 184 185 printf("%s\n", message); 186 fflush(stdout); 187 free(message); 188 189 /* 190 * false indicates that layer should not bail-out of an 191 * API call that had validation failures. This may mean that the 192 * app dies inside the driver due to invalid parameter(s). 193 * That's what would happen without validation layers, so we'll 194 * keep that behavior here. 195 */ 196 return false; 197 } 198 199 static const char *vk_result_string(VkResult err) { 200 switch (err) { 201 #define STR(r) \ 202 case r: \ 203 return #r 204 STR(VK_SUCCESS); 205 STR(VK_NOT_READY); 206 STR(VK_TIMEOUT); 207 STR(VK_EVENT_SET); 208 STR(VK_EVENT_RESET); 209 STR(VK_ERROR_INITIALIZATION_FAILED); 210 STR(VK_ERROR_OUT_OF_HOST_MEMORY); 211 STR(VK_ERROR_OUT_OF_DEVICE_MEMORY); 212 STR(VK_ERROR_DEVICE_LOST); 213 STR(VK_ERROR_LAYER_NOT_PRESENT); 214 STR(VK_ERROR_EXTENSION_NOT_PRESENT); 215 STR(VK_ERROR_MEMORY_MAP_FAILED); 216 STR(VK_ERROR_INCOMPATIBLE_DRIVER); 217 #undef STR 218 default: 219 return "UNKNOWN_RESULT"; 220 } 221 } 222 223 static const char *vk_physical_device_type_string(VkPhysicalDeviceType type) { 224 switch (type) { 225 #define STR(r) \ 226 case VK_PHYSICAL_DEVICE_TYPE_##r: \ 227 return #r 228 STR(OTHER); 229 STR(INTEGRATED_GPU); 230 STR(DISCRETE_GPU); 231 STR(VIRTUAL_GPU); 232 #undef STR 233 default: 234 return "UNKNOWN_DEVICE"; 235 } 236 } 237 238 static const char *vk_format_string(VkFormat fmt) { 239 switch (fmt) { 240 #define STR(r) \ 241 case VK_FORMAT_##r: \ 242 return #r 243 STR(UNDEFINED); 244 STR(R4G4_UNORM_PACK8); 245 STR(R4G4B4A4_UNORM_PACK16); 246 STR(B4G4R4A4_UNORM_PACK16); 247 STR(R5G6B5_UNORM_PACK16); 248 STR(B5G6R5_UNORM_PACK16); 249 STR(R5G5B5A1_UNORM_PACK16); 250 STR(B5G5R5A1_UNORM_PACK16); 251 STR(A1R5G5B5_UNORM_PACK16); 252 STR(R8_UNORM); 253 STR(R8_SNORM); 254 STR(R8_USCALED); 255 STR(R8_SSCALED); 256 STR(R8_UINT); 257 STR(R8_SINT); 258 STR(R8_SRGB); 259 STR(R8G8_UNORM); 260 STR(R8G8_SNORM); 261 STR(R8G8_USCALED); 262 STR(R8G8_SSCALED); 263 STR(R8G8_UINT); 264 STR(R8G8_SINT); 265 STR(R8G8_SRGB); 266 STR(R8G8B8_UNORM); 267 STR(R8G8B8_SNORM); 268 STR(R8G8B8_USCALED); 269 STR(R8G8B8_SSCALED); 270 STR(R8G8B8_UINT); 271 STR(R8G8B8_SINT); 272 STR(R8G8B8_SRGB); 273 STR(B8G8R8_UNORM); 274 STR(B8G8R8_SNORM); 275 STR(B8G8R8_USCALED); 276 STR(B8G8R8_SSCALED); 277 STR(B8G8R8_UINT); 278 STR(B8G8R8_SINT); 279 STR(B8G8R8_SRGB); 280 STR(R8G8B8A8_UNORM); 281 STR(R8G8B8A8_SNORM); 282 STR(R8G8B8A8_USCALED); 283 STR(R8G8B8A8_SSCALED); 284 STR(R8G8B8A8_UINT); 285 STR(R8G8B8A8_SINT); 286 STR(R8G8B8A8_SRGB); 287 STR(B8G8R8A8_UNORM); 288 STR(B8G8R8A8_SNORM); 289 STR(B8G8R8A8_USCALED); 290 STR(B8G8R8A8_SSCALED); 291 STR(B8G8R8A8_UINT); 292 STR(B8G8R8A8_SINT); 293 STR(B8G8R8A8_SRGB); 294 STR(A8B8G8R8_UNORM_PACK32); 295 STR(A8B8G8R8_SNORM_PACK32); 296 STR(A8B8G8R8_USCALED_PACK32); 297 STR(A8B8G8R8_SSCALED_PACK32); 298 STR(A8B8G8R8_UINT_PACK32); 299 STR(A8B8G8R8_SINT_PACK32); 300 STR(A8B8G8R8_SRGB_PACK32); 301 STR(A2R10G10B10_UNORM_PACK32); 302 STR(A2R10G10B10_SNORM_PACK32); 303 STR(A2R10G10B10_USCALED_PACK32); 304 STR(A2R10G10B10_SSCALED_PACK32); 305 STR(A2R10G10B10_UINT_PACK32); 306 STR(A2R10G10B10_SINT_PACK32); 307 STR(A2B10G10R10_UNORM_PACK32); 308 STR(A2B10G10R10_SNORM_PACK32); 309 STR(A2B10G10R10_USCALED_PACK32); 310 STR(A2B10G10R10_SSCALED_PACK32); 311 STR(A2B10G10R10_UINT_PACK32); 312 STR(A2B10G10R10_SINT_PACK32); 313 STR(R16_UNORM); 314 STR(R16_SNORM); 315 STR(R16_USCALED); 316 STR(R16_SSCALED); 317 STR(R16_UINT); 318 STR(R16_SINT); 319 STR(R16_SFLOAT); 320 STR(R16G16_UNORM); 321 STR(R16G16_SNORM); 322 STR(R16G16_USCALED); 323 STR(R16G16_SSCALED); 324 STR(R16G16_UINT); 325 STR(R16G16_SINT); 326 STR(R16G16_SFLOAT); 327 STR(R16G16B16_UNORM); 328 STR(R16G16B16_SNORM); 329 STR(R16G16B16_USCALED); 330 STR(R16G16B16_SSCALED); 331 STR(R16G16B16_UINT); 332 STR(R16G16B16_SINT); 333 STR(R16G16B16_SFLOAT); 334 STR(R16G16B16A16_UNORM); 335 STR(R16G16B16A16_SNORM); 336 STR(R16G16B16A16_USCALED); 337 STR(R16G16B16A16_SSCALED); 338 STR(R16G16B16A16_UINT); 339 STR(R16G16B16A16_SINT); 340 STR(R16G16B16A16_SFLOAT); 341 STR(R32_UINT); 342 STR(R32_SINT); 343 STR(R32_SFLOAT); 344 STR(R32G32_UINT); 345 STR(R32G32_SINT); 346 STR(R32G32_SFLOAT); 347 STR(R32G32B32_UINT); 348 STR(R32G32B32_SINT); 349 STR(R32G32B32_SFLOAT); 350 STR(R32G32B32A32_UINT); 351 STR(R32G32B32A32_SINT); 352 STR(R32G32B32A32_SFLOAT); 353 STR(R64_UINT); 354 STR(R64_SINT); 355 STR(R64_SFLOAT); 356 STR(R64G64_UINT); 357 STR(R64G64_SINT); 358 STR(R64G64_SFLOAT); 359 STR(R64G64B64_UINT); 360 STR(R64G64B64_SINT); 361 STR(R64G64B64_SFLOAT); 362 STR(R64G64B64A64_UINT); 363 STR(R64G64B64A64_SINT); 364 STR(R64G64B64A64_SFLOAT); 365 STR(B10G11R11_UFLOAT_PACK32); 366 STR(E5B9G9R9_UFLOAT_PACK32); 367 STR(D16_UNORM); 368 STR(X8_D24_UNORM_PACK32); 369 STR(D32_SFLOAT); 370 STR(S8_UINT); 371 STR(D16_UNORM_S8_UINT); 372 STR(D24_UNORM_S8_UINT); 373 STR(D32_SFLOAT_S8_UINT); 374 STR(BC1_RGB_UNORM_BLOCK); 375 STR(BC1_RGB_SRGB_BLOCK); 376 STR(BC2_UNORM_BLOCK); 377 STR(BC2_SRGB_BLOCK); 378 STR(BC3_UNORM_BLOCK); 379 STR(BC3_SRGB_BLOCK); 380 STR(BC4_UNORM_BLOCK); 381 STR(BC4_SNORM_BLOCK); 382 STR(BC5_UNORM_BLOCK); 383 STR(BC5_SNORM_BLOCK); 384 STR(BC6H_UFLOAT_BLOCK); 385 STR(BC6H_SFLOAT_BLOCK); 386 STR(BC7_UNORM_BLOCK); 387 STR(BC7_SRGB_BLOCK); 388 STR(ETC2_R8G8B8_UNORM_BLOCK); 389 STR(ETC2_R8G8B8A1_UNORM_BLOCK); 390 STR(ETC2_R8G8B8A8_UNORM_BLOCK); 391 STR(EAC_R11_UNORM_BLOCK); 392 STR(EAC_R11_SNORM_BLOCK); 393 STR(EAC_R11G11_UNORM_BLOCK); 394 STR(EAC_R11G11_SNORM_BLOCK); 395 STR(ASTC_4x4_UNORM_BLOCK); 396 STR(ASTC_4x4_SRGB_BLOCK); 397 STR(ASTC_5x4_UNORM_BLOCK); 398 STR(ASTC_5x4_SRGB_BLOCK); 399 STR(ASTC_5x5_UNORM_BLOCK); 400 STR(ASTC_5x5_SRGB_BLOCK); 401 STR(ASTC_6x5_UNORM_BLOCK); 402 STR(ASTC_6x5_SRGB_BLOCK); 403 STR(ASTC_6x6_UNORM_BLOCK); 404 STR(ASTC_6x6_SRGB_BLOCK); 405 STR(ASTC_8x5_UNORM_BLOCK); 406 STR(ASTC_8x5_SRGB_BLOCK); 407 STR(ASTC_8x6_UNORM_BLOCK); 408 STR(ASTC_8x6_SRGB_BLOCK); 409 STR(ASTC_8x8_UNORM_BLOCK); 410 STR(ASTC_8x8_SRGB_BLOCK); 411 STR(ASTC_10x5_UNORM_BLOCK); 412 STR(ASTC_10x5_SRGB_BLOCK); 413 STR(ASTC_10x6_UNORM_BLOCK); 414 STR(ASTC_10x6_SRGB_BLOCK); 415 STR(ASTC_10x8_UNORM_BLOCK); 416 STR(ASTC_10x8_SRGB_BLOCK); 417 STR(ASTC_10x10_UNORM_BLOCK); 418 STR(ASTC_10x10_SRGB_BLOCK); 419 STR(ASTC_12x10_UNORM_BLOCK); 420 STR(ASTC_12x10_SRGB_BLOCK); 421 STR(ASTC_12x12_UNORM_BLOCK); 422 STR(ASTC_12x12_SRGB_BLOCK); 423 #undef STR 424 default: 425 return "UNKNOWN_FORMAT"; 426 } 427 } 428 429 static void app_dev_init_formats(struct app_dev *dev) { 430 VkFormat f; 431 432 for (f = 0; f < VK_FORMAT_RANGE_SIZE; f++) { 433 const VkFormat fmt = f; 434 435 vkGetPhysicalDeviceFormatProperties(dev->gpu->obj, fmt, 436 &dev->format_props[f]); 437 } 438 } 439 440 static void extract_version(uint32_t version, uint32_t *major, uint32_t *minor, 441 uint32_t *patch) { 442 *major = version >> 22; 443 *minor = (version >> 12) & 0x3ff; 444 *patch = version & 0xfff; 445 } 446 447 static void app_get_physical_device_layer_extensions( 448 struct app_gpu *gpu, char *layer_name, uint32_t *extension_count, 449 VkExtensionProperties **extension_properties) { 450 VkResult err; 451 uint32_t ext_count = 0; 452 VkExtensionProperties *ext_ptr = NULL; 453 454 /* repeat get until VK_INCOMPLETE goes away */ 455 do { 456 err = vkEnumerateDeviceExtensionProperties(gpu->obj, layer_name, 457 &ext_count, NULL); 458 assert(!err); 459 460 if (ext_ptr) { 461 free(ext_ptr); 462 } 463 ext_ptr = malloc(ext_count * sizeof(VkExtensionProperties)); 464 err = vkEnumerateDeviceExtensionProperties(gpu->obj, layer_name, 465 &ext_count, ext_ptr); 466 } while (err == VK_INCOMPLETE); 467 assert(!err); 468 469 *extension_count = ext_count; 470 *extension_properties = ext_ptr; 471 } 472 473 static void app_dev_init(struct app_dev *dev, struct app_gpu *gpu) { 474 VkDeviceCreateInfo info = { 475 .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, 476 .pNext = NULL, 477 .queueCreateInfoCount = 0, 478 .pQueueCreateInfos = NULL, 479 .enabledLayerCount = 0, 480 .ppEnabledLayerNames = NULL, 481 .enabledExtensionCount = 0, 482 .ppEnabledExtensionNames = NULL, 483 }; 484 VkResult U_ASSERT_ONLY err; 485 486 // Device extensions 487 app_get_physical_device_layer_extensions( 488 gpu, NULL, &gpu->device_extension_count, &gpu->device_extensions); 489 490 fflush(stdout); 491 492 /* request all queues */ 493 info.queueCreateInfoCount = gpu->queue_count; 494 info.pQueueCreateInfos = gpu->queue_reqs; 495 496 info.enabledLayerCount = 0; 497 info.ppEnabledLayerNames = NULL; 498 info.enabledExtensionCount = 0; 499 info.ppEnabledExtensionNames = NULL; 500 dev->gpu = gpu; 501 err = vkCreateDevice(gpu->obj, &info, NULL, &dev->obj); 502 if (err) 503 ERR_EXIT(err); 504 } 505 506 static void app_dev_destroy(struct app_dev *dev) { 507 vkDestroyDevice(dev->obj, NULL); 508 } 509 510 static void 511 app_get_global_layer_extensions(char *layer_name, uint32_t *extension_count, 512 VkExtensionProperties **extension_properties) { 513 VkResult err; 514 uint32_t ext_count = 0; 515 VkExtensionProperties *ext_ptr = NULL; 516 517 /* repeat get until VK_INCOMPLETE goes away */ 518 do { 519 // gets the extension count if the last parameter is NULL 520 err = vkEnumerateInstanceExtensionProperties(layer_name, &ext_count, 521 NULL); 522 assert(!err); 523 524 if (ext_ptr) { 525 free(ext_ptr); 526 } 527 ext_ptr = malloc(ext_count * sizeof(VkExtensionProperties)); 528 // gets the extension properties if the last parameter is not NULL 529 err = vkEnumerateInstanceExtensionProperties(layer_name, &ext_count, 530 ext_ptr); 531 } while (err == VK_INCOMPLETE); 532 assert(!err); 533 *extension_count = ext_count; 534 *extension_properties = ext_ptr; 535 } 536 537 /* Gets a list of layer and instance extensions */ 538 static void app_get_instance_extensions(struct app_instance *inst) { 539 VkResult U_ASSERT_ONLY err; 540 541 uint32_t count = 0; 542 543 /* Scan layers */ 544 VkLayerProperties *global_layer_properties = NULL; 545 struct layer_extension_list *global_layers = NULL; 546 547 do { 548 err = vkEnumerateInstanceLayerProperties(&count, NULL); 549 assert(!err); 550 551 if (global_layer_properties) { 552 free(global_layer_properties); 553 } 554 global_layer_properties = malloc(sizeof(VkLayerProperties) * count); 555 assert(global_layer_properties); 556 557 if (global_layers) { 558 free(global_layers); 559 } 560 global_layers = malloc(sizeof(struct layer_extension_list) * count); 561 assert(global_layers); 562 563 err = 564 vkEnumerateInstanceLayerProperties(&count, global_layer_properties); 565 } while (err == VK_INCOMPLETE); 566 assert(!err); 567 568 inst->global_layer_count = count; 569 inst->global_layers = global_layers; 570 571 for (uint32_t i = 0; i < inst->global_layer_count; i++) { 572 VkLayerProperties *src_info = &global_layer_properties[i]; 573 struct layer_extension_list *dst_info = &inst->global_layers[i]; 574 memcpy(&dst_info->layer_properties, src_info, 575 sizeof(VkLayerProperties)); 576 577 // Save away layer extension info for report 578 // Gets layer extensions, if first parameter is not NULL 579 app_get_global_layer_extensions(src_info->layerName, 580 &dst_info->extension_count, 581 &dst_info->extension_properties); 582 } 583 free(global_layer_properties); 584 585 // Collect global extensions 586 inst->global_extension_count = 0; 587 // Gets instance extensions, if no layer was specified in the first 588 // paramteter 589 app_get_global_layer_extensions(NULL, &inst->global_extension_count, 590 &inst->global_extensions); 591 } 592 593 static void app_create_instance(struct app_instance *inst) { 594 app_get_instance_extensions(inst); 595 596 //---Build a list of extensions to load--- 597 #define MAX_EXTENSIONS 4 598 uint32_t i = 0; 599 uint32_t ext_count = 0; 600 const char *ext_names[MAX_EXTENSIONS]; // array of string pointers to 601 // extension names 602 for (i = 0; (i < inst->global_extension_count); i++) { 603 const char *found_name = inst->global_extensions[i].extensionName; 604 if (!strcmp(VK_KHR_SURFACE_EXTENSION_NAME, found_name)) { 605 ext_names[ext_count++] = VK_KHR_SURFACE_EXTENSION_NAME; 606 } 607 } 608 609 #if defined(VK_USE_PLATFORM_XCB_KHR) || \ 610 defined(VK_USE_PLATFORM_XLIB_KHR) || \ 611 defined(VK_USE_PLATFORM_WIN32_KHR) || \ 612 defined(VK_USE_PLATFORM_ANDROID_KHR) 613 if (ext_count) 614 for (i = 0; ((i < inst->global_extension_count) && 615 (ext_count < MAX_EXTENSIONS)); 616 i++) { 617 const char *found_name = inst->global_extensions[i].extensionName; 618 #ifdef VK_USE_PLATFORM_WIN32_KHR 619 if (!strcmp(VK_KHR_WIN32_SURFACE_EXTENSION_NAME, found_name)) { 620 ext_names[ext_count++] = VK_KHR_WIN32_SURFACE_EXTENSION_NAME; 621 } 622 #endif 623 #ifdef VK_USE_PLATFORM_XCB_KHR 624 if (!strcmp(VK_KHR_XCB_SURFACE_EXTENSION_NAME, found_name)) { 625 ext_names[ext_count++] = VK_KHR_XCB_SURFACE_EXTENSION_NAME; 626 } 627 #endif 628 #ifdef VK_USE_PLATFORM_XLIB_KHR 629 if (!strcmp(VK_KHR_XLIB_SURFACE_EXTENSION_NAME, found_name)) { 630 ext_names[ext_count++] = VK_KHR_XLIB_SURFACE_EXTENSION_NAME; 631 } 632 #endif 633 #ifdef VK_USE_PLATFORM_ANDROID_KHR 634 if (!strcmp(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME, found_name)) { 635 ext_names[ext_count++] = VK_KHR_ANDROID_SURFACE_EXTENSION_NAME; 636 } 637 #endif 638 } 639 #endif 640 // If we don't find the KHR_SURFACE extension and at least one other 641 // device-specific extension, 642 // then give up on reporting presentable surface formats." 643 if (ext_count < 2) 644 ext_count = 0; 645 //---------------------------------------- 646 647 const VkApplicationInfo app_info = { 648 .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, 649 .pNext = NULL, 650 .pApplicationName = APP_SHORT_NAME, 651 .applicationVersion = 1, 652 .pEngineName = APP_SHORT_NAME, 653 .engineVersion = 1, 654 .apiVersion = VK_API_VERSION_1_0, 655 }; 656 657 VkInstanceCreateInfo inst_info = { 658 .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, 659 .pNext = NULL, 660 .pApplicationInfo = &app_info, 661 .enabledLayerCount = 0, 662 .ppEnabledLayerNames = NULL, 663 .enabledExtensionCount = ext_count, 664 .ppEnabledExtensionNames = ext_names, 665 }; 666 667 VkDebugReportCallbackCreateInfoEXT dbg_info; 668 memset(&dbg_info, 0, sizeof(dbg_info)); 669 dbg_info.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT; 670 dbg_info.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | 671 VK_DEBUG_REPORT_WARNING_BIT_EXT | 672 VK_DEBUG_REPORT_INFORMATION_BIT_EXT; 673 dbg_info.pfnCallback = dbg_callback; 674 inst_info.pNext = &dbg_info; 675 676 VkResult U_ASSERT_ONLY err; 677 err = vkCreateInstance(&inst_info, NULL, &inst->instance); 678 if (err == VK_ERROR_INCOMPATIBLE_DRIVER) { 679 printf("Cannot create Vulkan instance.\n"); 680 ERR_EXIT(err); 681 } else if (err) { 682 ERR_EXIT(err); 683 } 684 685 if (ext_count > 0) { 686 //--Load Extensions-- 687 #define GET_INSTANCE_PROC_ADDR(ENTRYPOINT) \ 688 { \ 689 inst->ENTRYPOINT = \ 690 (void *)vkGetInstanceProcAddr(inst->instance, #ENTRYPOINT); \ 691 } 692 GET_INSTANCE_PROC_ADDR(vkGetPhysicalDeviceSurfaceSupportKHR) 693 GET_INSTANCE_PROC_ADDR(vkGetPhysicalDeviceSurfaceCapabilitiesKHR) 694 GET_INSTANCE_PROC_ADDR(vkGetPhysicalDeviceSurfaceFormatsKHR) 695 GET_INSTANCE_PROC_ADDR(vkGetPhysicalDeviceSurfacePresentModesKHR) 696 #undef GET_INSTANCE_PROC_ADDR 697 } 698 } 699 700 //----------------------------------------------------------- 701 702 static void app_destroy_instance(struct app_instance *inst) { 703 free(inst->global_extensions); 704 vkDestroyInstance(inst->instance, NULL); 705 } 706 707 static void app_gpu_init(struct app_gpu *gpu, uint32_t id, 708 VkPhysicalDevice obj) { 709 uint32_t i; 710 711 memset(gpu, 0, sizeof(*gpu)); 712 713 gpu->id = id; 714 gpu->obj = obj; 715 716 vkGetPhysicalDeviceProperties(gpu->obj, &gpu->props); 717 718 /* get queue count */ 719 vkGetPhysicalDeviceQueueFamilyProperties(gpu->obj, &gpu->queue_count, NULL); 720 721 gpu->queue_props = malloc(sizeof(gpu->queue_props[0]) * gpu->queue_count); 722 723 if (!gpu->queue_props) 724 ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY); 725 vkGetPhysicalDeviceQueueFamilyProperties(gpu->obj, &gpu->queue_count, 726 gpu->queue_props); 727 728 /* set up queue requests */ 729 gpu->queue_reqs = malloc(sizeof(*gpu->queue_reqs) * gpu->queue_count); 730 if (!gpu->queue_reqs) 731 ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY); 732 for (i = 0; i < gpu->queue_count; i++) { 733 float *queue_priorities = 734 malloc(gpu->queue_props[i].queueCount * sizeof(float)); 735 memset(queue_priorities, 0, 736 gpu->queue_props[i].queueCount * sizeof(float)); 737 gpu->queue_reqs[i].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; 738 gpu->queue_reqs[i].pNext = NULL; 739 gpu->queue_reqs[i].queueFamilyIndex = i; 740 gpu->queue_reqs[i].queueCount = gpu->queue_props[i].queueCount; 741 gpu->queue_reqs[i].pQueuePriorities = queue_priorities; 742 } 743 744 vkGetPhysicalDeviceMemoryProperties(gpu->obj, &gpu->memory_props); 745 746 vkGetPhysicalDeviceFeatures(gpu->obj, &gpu->features); 747 748 app_dev_init(&gpu->dev, gpu); 749 app_dev_init_formats(&gpu->dev); 750 } 751 752 static void app_gpu_destroy(struct app_gpu *gpu) { 753 app_dev_destroy(&gpu->dev); 754 free(gpu->device_extensions); 755 756 for (uint32_t i = 0; i < gpu->queue_count; i++) { 757 free((void *)gpu->queue_reqs[i].pQueuePriorities); 758 } 759 free(gpu->queue_reqs); 760 free(gpu->queue_props); 761 } 762 763 // clang-format off 764 765 //----------------------------------------------------------- 766 767 //---------------------------Win32--------------------------- 768 #ifdef VK_USE_PLATFORM_WIN32_KHR 769 770 // MS-Windows event handling function: 771 LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { 772 return (DefWindowProc(hWnd, uMsg, wParam, lParam)); 773 } 774 775 static void app_create_win32_window(struct app_instance *inst) { 776 inst->hInstance = GetModuleHandle(NULL); 777 778 WNDCLASSEX win_class; 779 780 // Initialize the window class structure: 781 win_class.cbSize = sizeof(WNDCLASSEX); 782 win_class.style = CS_HREDRAW | CS_VREDRAW; 783 win_class.lpfnWndProc = WndProc; 784 win_class.cbClsExtra = 0; 785 win_class.cbWndExtra = 0; 786 win_class.hInstance = inst->hInstance; 787 win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION); 788 win_class.hCursor = LoadCursor(NULL, IDC_ARROW); 789 win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); 790 win_class.lpszMenuName = NULL; 791 win_class.lpszClassName = APP_SHORT_NAME; 792 win_class.hInstance = inst->hInstance; 793 win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO); 794 // Register window class: 795 if (!RegisterClassEx(&win_class)) { 796 // It didn't work, so try to give a useful error: 797 printf("Failed to register the window class!\n"); 798 fflush(stdout); 799 exit(1); 800 } 801 // Create window with the registered class: 802 RECT wr = { 0, 0, inst->width, inst->height }; 803 AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE); 804 inst->hWnd = CreateWindowEx(0, 805 APP_SHORT_NAME, // class name 806 APP_SHORT_NAME, // app name 807 //WS_VISIBLE | WS_SYSMENU | 808 WS_OVERLAPPEDWINDOW, // window style 809 100, 100, // x/y coords 810 wr.right - wr.left, // width 811 wr.bottom - wr.top, // height 812 NULL, // handle to parent 813 NULL, // handle to menu 814 inst->hInstance, // hInstance 815 NULL); // no extra parameters 816 if (!inst->hWnd) { 817 // It didn't work, so try to give a useful error: 818 printf("Failed to create a window!\n"); 819 fflush(stdout); 820 exit(1); 821 } 822 } 823 824 static void app_create_win32_surface(struct app_instance *inst) { 825 VkResult U_ASSERT_ONLY err; 826 VkWin32SurfaceCreateInfoKHR createInfo; 827 createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; 828 createInfo.pNext = NULL; 829 createInfo.flags = 0; 830 createInfo.hinstance = inst->hInstance; 831 createInfo.hwnd = inst->hWnd; 832 err = vkCreateWin32SurfaceKHR(inst->instance, &createInfo, NULL, &inst->surface); 833 assert(!err); 834 } 835 836 static void app_destroy_win32_window(struct app_instance *inst) { 837 DestroyWindow(inst->hWnd); 838 } 839 #endif //VK_USE_PLATFORM_WIN32_KHR 840 //----------------------------------------------------------- 841 842 #if defined(VK_USE_PLATFORM_XCB_KHR) || \ 843 defined(VK_USE_PLATFORM_XLIB_KHR) || \ 844 defined(VK_USE_PLATFORM_WIN32_KHR) 845 static void app_destroy_surface(struct app_instance *inst) { //same for all platforms 846 vkDestroySurfaceKHR(inst->instance, inst->surface, NULL); 847 } 848 #endif 849 850 //----------------------------XCB---------------------------- 851 852 #ifdef VK_USE_PLATFORM_XCB_KHR 853 static void app_create_xcb_window(struct app_instance *inst) { 854 //--Init Connection-- 855 const xcb_setup_t *setup; 856 xcb_screen_iterator_t iter; 857 int scr; 858 859 inst->xcb_connection = xcb_connect(NULL, &scr); 860 if (inst->xcb_connection == NULL) { 861 printf("XCB failed to connect to the X server.\nExiting ...\n"); 862 fflush(stdout); 863 exit(1); 864 } 865 866 setup = xcb_get_setup(inst->xcb_connection); 867 iter = xcb_setup_roots_iterator(setup); 868 while (scr-- > 0) { 869 xcb_screen_next(&iter); 870 } 871 872 inst->xcb_screen = iter.data; 873 //------------------- 874 875 inst->xcb_window = xcb_generate_id(inst->xcb_connection); 876 xcb_create_window(inst->xcb_connection, XCB_COPY_FROM_PARENT, inst->xcb_window, 877 inst->xcb_screen->root, 0, 0, inst->width, inst->height, 0, 878 XCB_WINDOW_CLASS_INPUT_OUTPUT, inst->xcb_screen->root_visual, 879 0, NULL); 880 881 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(inst->xcb_connection, 1, 12, "WM_PROTOCOLS"); 882 xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(inst->xcb_connection, cookie, 0); 883 free(reply); 884 } 885 886 static void app_create_xcb_surface(struct app_instance *inst) { 887 VkResult U_ASSERT_ONLY err; 888 VkXcbSurfaceCreateInfoKHR xcb_createInfo; 889 xcb_createInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR; 890 xcb_createInfo.pNext = NULL; 891 xcb_createInfo.flags = 0; 892 xcb_createInfo.connection = inst->xcb_connection; 893 xcb_createInfo.window = inst->xcb_window; 894 err = vkCreateXcbSurfaceKHR(inst->instance, &xcb_createInfo, NULL, &inst->surface); 895 assert(!err); 896 } 897 898 static void app_destroy_xcb_window(struct app_instance *inst) { 899 xcb_destroy_window(inst->xcb_connection, inst->xcb_window); 900 xcb_disconnect(inst->xcb_connection); 901 } 902 #endif //VK_USE_PLATFORM_XCB_KHR 903 //----------------------------------------------------------- 904 905 //----------------------------XLib--------------------------- 906 #ifdef VK_USE_PLATFORM_XLIB_KHR 907 static void app_create_xlib_window(struct app_instance *inst) { 908 inst->xlib_display = XOpenDisplay(NULL); 909 long visualMask = VisualScreenMask; 910 int numberOfVisuals; 911 912 XVisualInfo vInfoTemplate={}; 913 vInfoTemplate.screen = DefaultScreen(inst->xlib_display); 914 XVisualInfo *visualInfo = XGetVisualInfo(inst->xlib_display, visualMask, 915 &vInfoTemplate, &numberOfVisuals); 916 inst->xlib_window = XCreateWindow( 917 inst->xlib_display, RootWindow(inst->xlib_display, vInfoTemplate.screen), 0, 0, 918 inst->width, inst->height, 0, visualInfo->depth, InputOutput, 919 visualInfo->visual, 0, NULL); 920 921 XSync(inst->xlib_display,false); 922 } 923 924 static void app_create_xlib_surface(struct app_instance *inst) { 925 VkResult U_ASSERT_ONLY err; 926 VkXlibSurfaceCreateInfoKHR createInfo; 927 createInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR; 928 createInfo.pNext = NULL; 929 createInfo.flags = 0; 930 createInfo.dpy = inst->xlib_display; 931 createInfo.window = inst->xlib_window; 932 err = vkCreateXlibSurfaceKHR(inst->instance, &createInfo, NULL, &inst->surface); 933 assert(!err); 934 } 935 936 static void app_destroy_xlib_window(struct app_instance *inst) { 937 XDestroyWindow(inst->xlib_display, inst->xlib_window); 938 XCloseDisplay(inst->xlib_display); 939 } 940 #endif //VK_USE_PLATFORM_XLIB_KHR 941 //----------------------------------------------------------- 942 943 #if defined(VK_USE_PLATFORM_XCB_KHR) || \ 944 defined(VK_USE_PLATFORM_XLIB_KHR) || \ 945 defined(VK_USE_PLATFORM_WIN32_KHR) 946 static int app_dump_surface_formats(struct app_instance *inst, struct app_gpu *gpu){ 947 // Get the list of VkFormat's that are supported: 948 VkResult U_ASSERT_ONLY err; 949 uint32_t formatCount = 0; 950 err = inst->vkGetPhysicalDeviceSurfaceFormatsKHR(gpu->obj, inst->surface, &formatCount, NULL); 951 assert(!err); 952 953 VkSurfaceFormatKHR *surfFormats = (VkSurfaceFormatKHR *)malloc(formatCount * sizeof(VkSurfaceFormatKHR)); 954 err = inst->vkGetPhysicalDeviceSurfaceFormatsKHR(gpu->obj, inst->surface, &formatCount, surfFormats); 955 assert(!err); 956 printf("Format count = %d\n",formatCount); 957 958 for (uint32_t i = 0; i < formatCount; i++) { 959 printf("\t%s\n", vk_format_string(surfFormats[i].format)); 960 } 961 printf("\n"); 962 fflush(stdout); 963 return formatCount; 964 } 965 #endif 966 967 static void app_dev_dump_format_props(const struct app_dev *dev, VkFormat fmt) 968 { 969 const VkFormatProperties *props = &dev->format_props[fmt]; 970 struct { 971 const char *name; 972 VkFlags flags; 973 } features[3]; 974 975 features[0].name = "linearTiling FormatFeatureFlags"; 976 features[0].flags = props->linearTilingFeatures; 977 features[1].name = "optimalTiling FormatFeatureFlags"; 978 features[1].flags = props->optimalTilingFeatures; 979 features[2].name = "bufferFeatures FormatFeatureFlags"; 980 features[2].flags = props->bufferFeatures; 981 982 printf("\nFORMAT_%s:", vk_format_string(fmt)); 983 for (uint32_t i = 0; i < ARRAY_SIZE(features); i++) { 984 printf("\n\t%s:", features[i].name); 985 if (features[i].flags == 0) { 986 printf("\n\t\tNone"); 987 } else { 988 printf("%s%s%s%s%s%s%s%s%s%s%s%s%s%s", 989 ((features[i].flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) ? "\n\t\tVK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT" : ""), //0x0001 990 ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) ? "\n\t\tVK_FORMAT_FEATURE_STORAGE_IMAGE_BIT" : ""), //0x0002 991 ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT) ? "\n\t\tVK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT" : ""), //0x0004 992 ((features[i].flags & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT) ? "\n\t\tVK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT" : ""), //0x0008 993 ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT) ? "\n\t\tVK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT" : ""), //0x0010 994 ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT) ? "\n\t\tVK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT" : ""), //0x0020 995 ((features[i].flags & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) ? "\n\t\tVK_FORMAT_FEATURE_VERTEX_BUFFER_BIT" : ""), //0x0040 996 ((features[i].flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) ? "\n\t\tVK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT" : ""), //0x0080 997 ((features[i].flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT) ? "\n\t\tVK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT" : ""), //0x0100 998 ((features[i].flags & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) ? "\n\t\tVK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT" : ""), //0x0200 999 ((features[i].flags & VK_FORMAT_FEATURE_BLIT_SRC_BIT) ? "\n\t\tVK_FORMAT_FEATURE_BLIT_SRC_BIT" : ""), //0x0400 1000 ((features[i].flags & VK_FORMAT_FEATURE_BLIT_DST_BIT) ? "\n\t\tVK_FORMAT_FEATURE_BLIT_DST_BIT" : ""), //0x0800 1001 ((features[i].flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT) ? "\n\t\tVK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT" : ""), //0x1000 1002 ((features[i].flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG) ? "\n\t\tVK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG" : "")); //0x2000 1003 } 1004 } 1005 printf("\n"); 1006 } 1007 1008 1009 static void 1010 app_dev_dump(const struct app_dev *dev) 1011 { 1012 printf("Format Properties:\n"); 1013 printf("=================="); 1014 VkFormat fmt; 1015 1016 for (fmt = 0; fmt < VK_FORMAT_RANGE_SIZE; fmt++) { 1017 app_dev_dump_format_props(dev, fmt); 1018 } 1019 } 1020 1021 #ifdef _WIN32 1022 #define PRINTF_SIZE_T_SPECIFIER "%Iu" 1023 #else 1024 #define PRINTF_SIZE_T_SPECIFIER "%zu" 1025 #endif 1026 1027 static void app_gpu_dump_features(const struct app_gpu *gpu) 1028 { 1029 const VkPhysicalDeviceFeatures *features = &gpu->features; 1030 1031 printf("VkPhysicalDeviceFeatures:\n"); 1032 printf("=========================\n"); 1033 1034 printf("\trobustBufferAccess = %u\n", features->robustBufferAccess ); 1035 printf("\tfullDrawIndexUint32 = %u\n", features->fullDrawIndexUint32 ); 1036 printf("\timageCubeArray = %u\n", features->imageCubeArray ); 1037 printf("\tindependentBlend = %u\n", features->independentBlend ); 1038 printf("\tgeometryShader = %u\n", features->geometryShader ); 1039 printf("\ttessellationShader = %u\n", features->tessellationShader ); 1040 printf("\tsampleRateShading = %u\n", features->sampleRateShading ); 1041 printf("\tdualSrcBlend = %u\n", features->dualSrcBlend ); 1042 printf("\tlogicOp = %u\n", features->logicOp ); 1043 printf("\tmultiDrawIndirect = %u\n", features->multiDrawIndirect ); 1044 printf("\tdrawIndirectFirstInstance = %u\n", features->drawIndirectFirstInstance ); 1045 printf("\tdepthClamp = %u\n", features->depthClamp ); 1046 printf("\tdepthBiasClamp = %u\n", features->depthBiasClamp ); 1047 printf("\tfillModeNonSolid = %u\n", features->fillModeNonSolid ); 1048 printf("\tdepthBounds = %u\n", features->depthBounds ); 1049 printf("\twideLines = %u\n", features->wideLines ); 1050 printf("\tlargePoints = %u\n", features->largePoints ); 1051 printf("\ttextureCompressionETC2 = %u\n", features->textureCompressionETC2 ); 1052 printf("\ttextureCompressionASTC_LDR = %u\n", features->textureCompressionASTC_LDR ); 1053 printf("\ttextureCompressionBC = %u\n", features->textureCompressionBC ); 1054 printf("\tocclusionQueryPrecise = %u\n", features->occlusionQueryPrecise ); 1055 printf("\tpipelineStatisticsQuery = %u\n", features->pipelineStatisticsQuery ); 1056 printf("\tvertexSideEffects = %u\n", features->vertexPipelineStoresAndAtomics ); 1057 printf("\ttessellationSideEffects = %u\n", features->fragmentStoresAndAtomics ); 1058 printf("\tgeometrySideEffects = %u\n", features->shaderTessellationAndGeometryPointSize ); 1059 printf("\tshaderImageGatherExtended = %u\n", features->shaderImageGatherExtended ); 1060 printf("\tshaderStorageImageExtendedFormats = %u\n", features->shaderStorageImageExtendedFormats ); 1061 printf("\tshaderStorageImageMultisample = %u\n", features->shaderStorageImageMultisample ); 1062 printf("\tshaderStorageImageReadWithoutFormat = %u\n", features->shaderStorageImageReadWithoutFormat ); 1063 printf("\tshaderStorageImageWriteWithoutFormat = %u\n", features->shaderStorageImageWriteWithoutFormat ); 1064 printf("\tshaderUniformBufferArrayDynamicIndexing = %u\n", features->shaderUniformBufferArrayDynamicIndexing); 1065 printf("\tshaderSampledImageArrayDynamicIndexing = %u\n", features->shaderSampledImageArrayDynamicIndexing ); 1066 printf("\tshaderStorageBufferArrayDynamicIndexing = %u\n", features->shaderStorageBufferArrayDynamicIndexing); 1067 printf("\tshaderStorageImageArrayDynamicIndexing = %u\n", features->shaderStorageImageArrayDynamicIndexing ); 1068 printf("\tshaderClipDistance = %u\n", features->shaderClipDistance ); 1069 printf("\tshaderCullDistance = %u\n", features->shaderCullDistance ); 1070 printf("\tshaderFloat64 = %u\n", features->shaderFloat64 ); 1071 printf("\tshaderInt64 = %u\n", features->shaderInt64 ); 1072 printf("\tshaderInt16 = %u\n", features->shaderInt16 ); 1073 printf("\tshaderResourceResidency = %u\n", features->shaderResourceResidency ); 1074 printf("\tshaderResourceMinLod = %u\n", features->shaderResourceMinLod ); 1075 printf("\talphaToOne = %u\n", features->alphaToOne ); 1076 printf("\tsparseBinding = %u\n", features->sparseBinding ); 1077 printf("\tsparseResidencyBuffer = %u\n", features->sparseResidencyBuffer ); 1078 printf("\tsparseResidencyImage2D = %u\n", features->sparseResidencyImage2D ); 1079 printf("\tsparseResidencyImage3D = %u\n", features->sparseResidencyImage3D ); 1080 printf("\tsparseResidency2Samples = %u\n", features->sparseResidency2Samples ); 1081 printf("\tsparseResidency4Samples = %u\n", features->sparseResidency4Samples ); 1082 printf("\tsparseResidency8Samples = %u\n", features->sparseResidency8Samples ); 1083 printf("\tsparseResidency16Samples = %u\n", features->sparseResidency16Samples ); 1084 printf("\tsparseResidencyAliased = %u\n", features->sparseResidencyAliased ); 1085 printf("\tvariableMultisampleRate = %u\n", features->variableMultisampleRate ); 1086 printf("\tinheritedQueries = %u\n", features->inheritedQueries ); 1087 } 1088 1089 static void app_dump_sparse_props(const VkPhysicalDeviceSparseProperties *sparseProps) 1090 { 1091 1092 printf("\tVkPhysicalDeviceSparseProperties:\n"); 1093 printf("\t---------------------------------\n"); 1094 1095 printf("\t\tresidencyStandard2DBlockShape = %u\n", sparseProps->residencyStandard2DBlockShape ); 1096 printf("\t\tresidencyStandard2DMultisampleBlockShape = %u\n", sparseProps->residencyStandard2DMultisampleBlockShape); 1097 printf("\t\tresidencyStandard3DBlockShape = %u\n", sparseProps->residencyStandard3DBlockShape ); 1098 printf("\t\tresidencyAlignedMipSize = %u\n", sparseProps->residencyAlignedMipSize ); 1099 printf("\t\tresidencyNonResidentStrict = %u\n", sparseProps->residencyNonResidentStrict ); 1100 } 1101 1102 static void app_dump_limits(const VkPhysicalDeviceLimits *limits) 1103 { 1104 printf("\tVkPhysicalDeviceLimits:\n"); 1105 printf("\t-----------------------\n"); 1106 printf("\t\tmaxImageDimension1D = %u\n", limits->maxImageDimension1D ); 1107 printf("\t\tmaxImageDimension2D = %u\n", limits->maxImageDimension2D ); 1108 printf("\t\tmaxImageDimension3D = %u\n", limits->maxImageDimension3D ); 1109 printf("\t\tmaxImageDimensionCube = %u\n", limits->maxImageDimensionCube ); 1110 printf("\t\tmaxImageArrayLayers = %u\n", limits->maxImageArrayLayers ); 1111 printf("\t\tmaxTexelBufferElements = 0x%" PRIxLEAST32 "\n", limits->maxTexelBufferElements ); 1112 printf("\t\tmaxUniformBufferRange = 0x%" PRIxLEAST32 "\n", limits->maxUniformBufferRange ); 1113 printf("\t\tmaxStorageBufferRange = 0x%" PRIxLEAST32 "\n", limits->maxStorageBufferRange ); 1114 printf("\t\tmaxPushConstantsSize = %u\n", limits->maxPushConstantsSize ); 1115 printf("\t\tmaxMemoryAllocationCount = %u\n", limits->maxMemoryAllocationCount ); 1116 printf("\t\tmaxSamplerAllocationCount = %u\n", limits->maxSamplerAllocationCount ); 1117 printf("\t\tbufferImageGranularity = 0x%" PRIxLEAST64 "\n", limits->bufferImageGranularity ); 1118 printf("\t\tsparseAddressSpaceSize = 0x%" PRIxLEAST64 "\n", limits->sparseAddressSpaceSize ); 1119 printf("\t\tmaxBoundDescriptorSets = %u\n", limits->maxBoundDescriptorSets ); 1120 printf("\t\tmaxPerStageDescriptorSamplers = %u\n", limits->maxPerStageDescriptorSamplers ); 1121 printf("\t\tmaxPerStageDescriptorUniformBuffers = %u\n", limits->maxPerStageDescriptorUniformBuffers ); 1122 printf("\t\tmaxPerStageDescriptorStorageBuffers = %u\n", limits->maxPerStageDescriptorStorageBuffers ); 1123 printf("\t\tmaxPerStageDescriptorSampledImages = %u\n", limits->maxPerStageDescriptorSampledImages ); 1124 printf("\t\tmaxPerStageDescriptorStorageImages = %u\n", limits->maxPerStageDescriptorStorageImages ); 1125 printf("\t\tmaxPerStageDescriptorInputAttachments = %u\n", limits->maxPerStageDescriptorInputAttachments ); 1126 printf("\t\tmaxPerStageResources = %u\n", limits->maxPerStageResources ); 1127 printf("\t\tmaxDescriptorSetSamplers = %u\n", limits->maxDescriptorSetSamplers ); 1128 printf("\t\tmaxDescriptorSetUniformBuffers = %u\n", limits->maxDescriptorSetUniformBuffers ); 1129 printf("\t\tmaxDescriptorSetUniformBuffersDynamic = %u\n", limits->maxDescriptorSetUniformBuffersDynamic ); 1130 printf("\t\tmaxDescriptorSetStorageBuffers = %u\n", limits->maxDescriptorSetStorageBuffers ); 1131 printf("\t\tmaxDescriptorSetStorageBuffersDynamic = %u\n", limits->maxDescriptorSetStorageBuffersDynamic ); 1132 printf("\t\tmaxDescriptorSetSampledImages = %u\n", limits->maxDescriptorSetSampledImages ); 1133 printf("\t\tmaxDescriptorSetStorageImages = %u\n", limits->maxDescriptorSetStorageImages ); 1134 printf("\t\tmaxDescriptorSetInputAttachments = %u\n", limits->maxDescriptorSetInputAttachments ); 1135 printf("\t\tmaxVertexInputAttributes = %u\n", limits->maxVertexInputAttributes ); 1136 printf("\t\tmaxVertexInputBindings = %u\n", limits->maxVertexInputBindings ); 1137 printf("\t\tmaxVertexInputAttributeOffset = 0x%" PRIxLEAST32 "\n", limits->maxVertexInputAttributeOffset ); 1138 printf("\t\tmaxVertexInputBindingStride = 0x%" PRIxLEAST32 "\n", limits->maxVertexInputBindingStride ); 1139 printf("\t\tmaxVertexOutputComponents = %u\n", limits->maxVertexOutputComponents ); 1140 printf("\t\tmaxTessellationGenerationLevel = %u\n", limits->maxTessellationGenerationLevel ); 1141 printf("\t\tmaxTessellationPatchSize = %u\n", limits->maxTessellationPatchSize ); 1142 printf("\t\tmaxTessellationControlPerVertexInputComponents = %u\n", limits->maxTessellationControlPerVertexInputComponents ); 1143 printf("\t\tmaxTessellationControlPerVertexOutputComponents = %u\n", limits->maxTessellationControlPerVertexOutputComponents); 1144 printf("\t\tmaxTessellationControlPerPatchOutputComponents = %u\n", limits->maxTessellationControlPerPatchOutputComponents ); 1145 printf("\t\tmaxTessellationControlTotalOutputComponents = %u\n", limits->maxTessellationControlTotalOutputComponents ); 1146 printf("\t\tmaxTessellationEvaluationInputComponents = %u\n", limits->maxTessellationEvaluationInputComponents ); 1147 printf("\t\tmaxTessellationEvaluationOutputComponents = %u\n", limits->maxTessellationEvaluationOutputComponents ); 1148 printf("\t\tmaxGeometryShaderInvocations = %u\n", limits->maxGeometryShaderInvocations ); 1149 printf("\t\tmaxGeometryInputComponents = %u\n", limits->maxGeometryInputComponents ); 1150 printf("\t\tmaxGeometryOutputComponents = %u\n", limits->maxGeometryOutputComponents ); 1151 printf("\t\tmaxGeometryOutputVertices = %u\n", limits->maxGeometryOutputVertices ); 1152 printf("\t\tmaxGeometryTotalOutputComponents = %u\n", limits->maxGeometryTotalOutputComponents ); 1153 printf("\t\tmaxFragmentInputComponents = %u\n", limits->maxFragmentInputComponents ); 1154 printf("\t\tmaxFragmentOutputAttachments = %u\n", limits->maxFragmentOutputAttachments ); 1155 printf("\t\tmaxFragmentDualSrcAttachments = %u\n", limits->maxFragmentDualSrcAttachments ); 1156 printf("\t\tmaxFragmentCombinedOutputResources = %u\n", limits->maxFragmentCombinedOutputResources ); 1157 printf("\t\tmaxComputeSharedMemorySize = 0x%" PRIxLEAST32 "\n", limits->maxComputeSharedMemorySize ); 1158 printf("\t\tmaxComputeWorkGroupCount[0] = %u\n", limits->maxComputeWorkGroupCount[0] ); 1159 printf("\t\tmaxComputeWorkGroupCount[1] = %u\n", limits->maxComputeWorkGroupCount[1] ); 1160 printf("\t\tmaxComputeWorkGroupCount[2] = %u\n", limits->maxComputeWorkGroupCount[2] ); 1161 printf("\t\tmaxComputeWorkGroupInvocations = %u\n", limits->maxComputeWorkGroupInvocations ); 1162 printf("\t\tmaxComputeWorkGroupSize[0] = %u\n", limits->maxComputeWorkGroupSize[0] ); 1163 printf("\t\tmaxComputeWorkGroupSize[1] = %u\n", limits->maxComputeWorkGroupSize[1] ); 1164 printf("\t\tmaxComputeWorkGroupSize[2] = %u\n", limits->maxComputeWorkGroupSize[2] ); 1165 printf("\t\tsubPixelPrecisionBits = %u\n", limits->subPixelPrecisionBits ); 1166 printf("\t\tsubTexelPrecisionBits = %u\n", limits->subTexelPrecisionBits ); 1167 printf("\t\tmipmapPrecisionBits = %u\n", limits->mipmapPrecisionBits ); 1168 printf("\t\tmaxDrawIndexedIndexValue = %u\n", limits->maxDrawIndexedIndexValue ); 1169 printf("\t\tmaxDrawIndirectCount = %u\n", limits->maxDrawIndirectCount ); 1170 printf("\t\tmaxSamplerLodBias = %f\n", limits->maxSamplerLodBias ); 1171 printf("\t\tmaxSamplerAnisotropy = %f\n", limits->maxSamplerAnisotropy ); 1172 printf("\t\tmaxViewports = %u\n", limits->maxViewports ); 1173 printf("\t\tmaxViewportDimensions[0] = %u\n", limits->maxViewportDimensions[0] ); 1174 printf("\t\tmaxViewportDimensions[1] = %u\n", limits->maxViewportDimensions[1] ); 1175 printf("\t\tviewportBoundsRange[0] =%13f\n", limits->viewportBoundsRange[0] ); 1176 printf("\t\tviewportBoundsRange[1] =%13f\n", limits->viewportBoundsRange[1] ); 1177 printf("\t\tviewportSubPixelBits = %u\n", limits->viewportSubPixelBits ); 1178 printf("\t\tminMemoryMapAlignment = " PRINTF_SIZE_T_SPECIFIER "\n", limits->minMemoryMapAlignment ); 1179 printf("\t\tminTexelBufferOffsetAlignment = 0x%" PRIxLEAST64 "\n", limits->minTexelBufferOffsetAlignment ); 1180 printf("\t\tminUniformBufferOffsetAlignment = 0x%" PRIxLEAST64 "\n", limits->minUniformBufferOffsetAlignment ); 1181 printf("\t\tminStorageBufferOffsetAlignment = 0x%" PRIxLEAST64 "\n", limits->minStorageBufferOffsetAlignment ); 1182 printf("\t\tminTexelOffset =%3d\n", limits->minTexelOffset ); 1183 printf("\t\tmaxTexelOffset =%3d\n", limits->maxTexelOffset ); 1184 printf("\t\tminTexelGatherOffset =%3d\n", limits->minTexelGatherOffset ); 1185 printf("\t\tmaxTexelGatherOffset =%3d\n", limits->maxTexelGatherOffset ); 1186 printf("\t\tminInterpolationOffset =%9f\n", limits->minInterpolationOffset ); 1187 printf("\t\tmaxInterpolationOffset =%9f\n", limits->maxInterpolationOffset ); 1188 printf("\t\tsubPixelInterpolationOffsetBits = %u\n", limits->subPixelInterpolationOffsetBits ); 1189 printf("\t\tmaxFramebufferWidth = %u\n", limits->maxFramebufferWidth ); 1190 printf("\t\tmaxFramebufferHeight = %u\n", limits->maxFramebufferHeight ); 1191 printf("\t\tmaxFramebufferLayers = %u\n", limits->maxFramebufferLayers ); 1192 printf("\t\tframebufferColorSampleCounts = %u\n", limits->framebufferColorSampleCounts ); 1193 printf("\t\tframebufferDepthSampleCounts = %u\n", limits->framebufferDepthSampleCounts ); 1194 printf("\t\tframebufferStencilSampleCounts = %u\n", limits->framebufferStencilSampleCounts ); 1195 printf("\t\tframebufferNoAttachmentsSampleCounts = %u\n", limits->framebufferNoAttachmentsSampleCounts ); 1196 printf("\t\tmaxColorAttachments = %u\n", limits->maxColorAttachments ); 1197 printf("\t\tsampledImageColorSampleCounts = %u\n", limits->sampledImageColorSampleCounts ); 1198 printf("\t\tsampledImageDepthSampleCounts = %u\n", limits->sampledImageDepthSampleCounts ); 1199 printf("\t\tsampledImageStencilSampleCounts = %u\n", limits->sampledImageStencilSampleCounts ); 1200 printf("\t\tsampledImageIntegerSampleCounts = %u\n", limits->sampledImageIntegerSampleCounts ); 1201 printf("\t\tstorageImageSampleCounts = %u\n", limits->storageImageSampleCounts ); 1202 printf("\t\tmaxSampleMaskWords = %u\n", limits->maxSampleMaskWords ); 1203 printf("\t\ttimestampComputeAndGraphics = %u\n", limits->timestampComputeAndGraphics ); 1204 printf("\t\ttimestampPeriod = %f\n", limits->timestampPeriod ); 1205 printf("\t\tmaxClipDistances = %u\n", limits->maxClipDistances ); 1206 printf("\t\tmaxCullDistances = %u\n", limits->maxCullDistances ); 1207 printf("\t\tmaxCombinedClipAndCullDistances = %u\n", limits->maxCombinedClipAndCullDistances ); 1208 printf("\t\tdiscreteQueuePriorities = %u\n", limits->discreteQueuePriorities ); 1209 printf("\t\tpointSizeRange[0] = %f\n", limits->pointSizeRange[0] ); 1210 printf("\t\tpointSizeRange[1] = %f\n", limits->pointSizeRange[1] ); 1211 printf("\t\tlineWidthRange[0] = %f\n", limits->lineWidthRange[0] ); 1212 printf("\t\tlineWidthRange[1] = %f\n", limits->lineWidthRange[1] ); 1213 printf("\t\tpointSizeGranularity = %f\n", limits->pointSizeGranularity ); 1214 printf("\t\tlineWidthGranularity = %f\n", limits->lineWidthGranularity ); 1215 printf("\t\tstrictLines = %u\n", limits->strictLines ); 1216 printf("\t\tstandardSampleLocations = %u\n", limits->standardSampleLocations ); 1217 printf("\t\toptimalBufferCopyOffsetAlignment = 0x%" PRIxLEAST64 "\n", limits->optimalBufferCopyOffsetAlignment ); 1218 printf("\t\toptimalBufferCopyRowPitchAlignment = 0x%" PRIxLEAST64 "\n", limits->optimalBufferCopyRowPitchAlignment ); 1219 printf("\t\tnonCoherentAtomSize = 0x%" PRIxLEAST64 "\n", limits->nonCoherentAtomSize ); 1220 } 1221 1222 static void app_gpu_dump_props(const struct app_gpu *gpu) 1223 { 1224 const VkPhysicalDeviceProperties *props = &gpu->props; 1225 const uint32_t apiVersion=props->apiVersion; 1226 const uint32_t major = VK_VERSION_MAJOR(apiVersion); 1227 const uint32_t minor = VK_VERSION_MINOR(apiVersion); 1228 const uint32_t patch = VK_VERSION_PATCH(apiVersion); 1229 1230 printf("VkPhysicalDeviceProperties:\n"); 1231 printf("===========================\n"); 1232 printf("\tapiVersion = 0x%" PRIxLEAST32 " (%d.%d.%d)\n", apiVersion, major, minor, patch); 1233 printf("\tdriverVersion = %u (0x%" PRIxLEAST32 ")\n",props->driverVersion, props->driverVersion); 1234 printf("\tvendorID = 0x%04x\n", props->vendorID); 1235 printf("\tdeviceID = 0x%04x\n", props->deviceID); 1236 printf("\tdeviceType = %s\n", vk_physical_device_type_string(props->deviceType)); 1237 printf("\tdeviceName = %s\n", props->deviceName); 1238 1239 app_dump_limits(&gpu->props.limits); 1240 app_dump_sparse_props(&gpu->props.sparseProperties); 1241 1242 fflush(stdout); 1243 } 1244 // clang-format on 1245 1246 static void 1247 app_dump_extensions(const char *indent, const char *layer_name, 1248 const uint32_t extension_count, 1249 const VkExtensionProperties *extension_properties) { 1250 uint32_t i; 1251 if (layer_name && (strlen(layer_name) > 0)) { 1252 printf("%s%s Extensions", indent, layer_name); 1253 } else { 1254 printf("%sExtensions", indent); 1255 } 1256 printf("\tcount = %d\n", extension_count); 1257 for (i = 0; i < extension_count; i++) { 1258 VkExtensionProperties const *ext_prop = &extension_properties[i]; 1259 1260 printf("%s\t", indent); 1261 printf("%-36s: extension revision %2d\n", ext_prop->extensionName, 1262 ext_prop->specVersion); 1263 } 1264 fflush(stdout); 1265 } 1266 1267 #if defined(VK_USE_PLATFORM_XCB_KHR) || \ 1268 defined(VK_USE_PLATFORM_XLIB_KHR) || \ 1269 defined(VK_USE_PLATFORM_WIN32_KHR) 1270 // Returns true if the named extension is in the list of extensions. 1271 static bool has_extension(const char *extension_name, 1272 const uint32_t extension_count, 1273 const VkExtensionProperties *extension_properties) { 1274 for (uint32_t i = 0; i < extension_count; i++) { 1275 if (!strcmp(extension_name, extension_properties[i].extensionName)) 1276 return true; 1277 } 1278 return false; 1279 } 1280 #endif 1281 1282 static void app_gpu_dump_queue_props(const struct app_gpu *gpu, uint32_t id) { 1283 const VkQueueFamilyProperties *props = &gpu->queue_props[id]; 1284 1285 printf("VkQueueFamilyProperties[%d]:\n", id); 1286 printf("===========================\n"); 1287 char *sep = ""; // separator character 1288 printf("\tqueueFlags = "); 1289 if (props->queueFlags & VK_QUEUE_GRAPHICS_BIT) { 1290 printf("GRAPHICS"); 1291 sep = " | "; 1292 } 1293 if (props->queueFlags & VK_QUEUE_COMPUTE_BIT) { 1294 printf("%sCOMPUTE", sep); 1295 sep = " | "; 1296 } 1297 if (props->queueFlags & VK_QUEUE_TRANSFER_BIT) { 1298 printf("%sTRANSFER", sep); 1299 sep = " | "; 1300 } 1301 if (props->queueFlags & VK_QUEUE_SPARSE_BINDING_BIT) { 1302 printf("%sSPARSE", sep); 1303 } 1304 printf("\n"); 1305 1306 printf("\tqueueCount = %u\n", props->queueCount); 1307 printf("\ttimestampValidBits = %u\n", props->timestampValidBits); 1308 printf("\tminImageTransferGranularity = (%d, %d, %d)\n", 1309 props->minImageTransferGranularity.width, 1310 props->minImageTransferGranularity.height, 1311 props->minImageTransferGranularity.depth); 1312 fflush(stdout); 1313 } 1314 1315 static void app_gpu_dump_memory_props(const struct app_gpu *gpu) { 1316 const VkPhysicalDeviceMemoryProperties *props = &gpu->memory_props; 1317 1318 printf("VkPhysicalDeviceMemoryProperties:\n"); 1319 printf("=================================\n"); 1320 printf("\tmemoryTypeCount = %u\n", props->memoryTypeCount); 1321 for (uint32_t i = 0; i < props->memoryTypeCount; i++) { 1322 printf("\tmemoryTypes[%u] : \n", i); 1323 printf("\t\theapIndex = %u\n", props->memoryTypes[i].heapIndex); 1324 printf("\t\tpropertyFlags = 0x%" PRIxLEAST32 ":\n", 1325 props->memoryTypes[i].propertyFlags); 1326 1327 // Print each named flag, if it is set. 1328 VkFlags flags = props->memoryTypes[i].propertyFlags; 1329 #define PRINT_FLAG(FLAG) \ 1330 if (flags & FLAG) \ 1331 printf("\t\t\t" #FLAG "\n"); 1332 PRINT_FLAG(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) 1333 PRINT_FLAG(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) 1334 PRINT_FLAG(VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) 1335 PRINT_FLAG(VK_MEMORY_PROPERTY_HOST_CACHED_BIT) 1336 PRINT_FLAG(VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) 1337 #undef PRINT_FLAG 1338 } 1339 printf("\n"); 1340 printf("\tmemoryHeapCount = %u\n", props->memoryHeapCount); 1341 for (uint32_t i = 0; i < props->memoryHeapCount; i++) { 1342 printf("\tmemoryHeaps[%u] : \n", i); 1343 const VkDeviceSize memSize = props->memoryHeaps[i].size; 1344 printf("\t\tsize = " PRINTF_SIZE_T_SPECIFIER 1345 " (0x%" PRIxLEAST64 ")\n", 1346 (size_t)memSize, memSize); 1347 1348 VkMemoryHeapFlags heapFlags = props->memoryHeaps[i].flags; 1349 printf("\t\tflags: \n\t\t\t"); 1350 printf((heapFlags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) 1351 ? "VK_MEMORY_HEAP_DEVICE_LOCAL_BIT\n" 1352 : "None\n"); 1353 } 1354 fflush(stdout); 1355 } 1356 1357 static void app_gpu_dump(const struct app_gpu *gpu) { 1358 uint32_t i; 1359 1360 printf("\nDevice Properties and Extensions :\n"); 1361 printf("==================================\n"); 1362 printf("GPU%u\n", gpu->id); 1363 app_gpu_dump_props(gpu); 1364 printf("\n"); 1365 app_dump_extensions("", "Device", gpu->device_extension_count, 1366 gpu->device_extensions); 1367 printf("\n"); 1368 for (i = 0; i < gpu->queue_count; i++) { 1369 app_gpu_dump_queue_props(gpu, i); 1370 printf("\n"); 1371 } 1372 app_gpu_dump_memory_props(gpu); 1373 printf("\n"); 1374 app_gpu_dump_features(gpu); 1375 printf("\n"); 1376 app_dev_dump(&gpu->dev); 1377 } 1378 1379 #ifdef _WIN32 1380 // Enlarges the console window to have a large scrollback size. 1381 static void ConsoleEnlarge() { 1382 HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE); 1383 1384 // make the console window bigger 1385 CONSOLE_SCREEN_BUFFER_INFO csbi; 1386 COORD bufferSize; 1387 if (GetConsoleScreenBufferInfo(consoleHandle, &csbi)) { 1388 bufferSize.X = csbi.dwSize.X + 30; 1389 bufferSize.Y = 20000; 1390 SetConsoleScreenBufferSize(consoleHandle, bufferSize); 1391 } 1392 1393 SMALL_RECT r; 1394 r.Left = r.Top = 0; 1395 r.Right = csbi.dwSize.X - 1 + 30; 1396 r.Bottom = 50; 1397 SetConsoleWindowInfo(consoleHandle, true, &r); 1398 1399 // change the console window title 1400 SetConsoleTitle(TEXT(APP_SHORT_NAME)); 1401 } 1402 #endif 1403 1404 int main(int argc, char **argv) { 1405 unsigned int major, minor, patch; 1406 struct app_gpu gpus[MAX_GPUS]; 1407 VkPhysicalDevice objs[MAX_GPUS]; 1408 uint32_t gpu_count, i; 1409 VkResult err; 1410 struct app_instance inst; 1411 1412 #ifdef _WIN32 1413 if (ConsoleIsExclusive()) 1414 ConsoleEnlarge(); 1415 #endif 1416 1417 major = VK_VERSION_MAJOR(VK_API_VERSION_1_0); 1418 minor = VK_VERSION_MINOR(VK_API_VERSION_1_0); 1419 patch = VK_VERSION_PATCH(VK_HEADER_VERSION); 1420 1421 printf("===========\n"); 1422 printf("VULKAN INFO\n"); 1423 printf("===========\n\n"); 1424 printf("Vulkan API Version: %d.%d.%d\n\n", major, minor, patch); 1425 1426 app_create_instance(&inst); 1427 1428 printf("\nInstance Extensions:\n"); 1429 printf("====================\n"); 1430 app_dump_extensions("", "Instance", inst.global_extension_count, 1431 inst.global_extensions); 1432 1433 err = vkEnumeratePhysicalDevices(inst.instance, &gpu_count, NULL); 1434 if (err) 1435 ERR_EXIT(err); 1436 if (gpu_count > MAX_GPUS) { 1437 printf("Too many GPUS found \n"); 1438 ERR_EXIT(-1); 1439 } 1440 err = vkEnumeratePhysicalDevices(inst.instance, &gpu_count, objs); 1441 if (err) 1442 ERR_EXIT(err); 1443 1444 for (i = 0; i < gpu_count; i++) { 1445 app_gpu_init(&gpus[i], i, objs[i]); 1446 printf("\n\n"); 1447 } 1448 1449 //---Layer-Device-Extensions--- 1450 printf("Layers: count = %d\n", inst.global_layer_count); 1451 printf("=======\n"); 1452 for (uint32_t i = 0; i < inst.global_layer_count; i++) { 1453 uint32_t major, minor, patch; 1454 char spec_version[64], layer_version[64]; 1455 VkLayerProperties const *layer_prop = 1456 &inst.global_layers[i].layer_properties; 1457 1458 extract_version(layer_prop->specVersion, &major, &minor, &patch); 1459 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d", major, minor, 1460 patch); 1461 snprintf(layer_version, sizeof(layer_version), "%d", 1462 layer_prop->implementationVersion); 1463 printf("%s (%s) Vulkan version %s, layer version %s\n", 1464 layer_prop->layerName, (char *)layer_prop->description, 1465 spec_version, layer_version); 1466 1467 app_dump_extensions("\t", "Layer", 1468 inst.global_layers[i].extension_count, 1469 inst.global_layers[i].extension_properties); 1470 1471 char *layerName = inst.global_layers[i].layer_properties.layerName; 1472 printf("\tDevices \tcount = %d\n", gpu_count); 1473 for (uint32_t j = 0; j < gpu_count; j++) { 1474 printf("\t\tGPU id : %u (%s)\n", j, gpus[j].props.deviceName); 1475 uint32_t count = 0; 1476 VkExtensionProperties *props; 1477 app_get_physical_device_layer_extensions(&gpus[j], layerName, 1478 &count, &props); 1479 app_dump_extensions("\t\t", "Layer-Device", count, props); 1480 free(props); 1481 } 1482 printf("\n"); 1483 } 1484 fflush(stdout); 1485 //----------------------------- 1486 1487 printf("Presentable Surface formats:\n"); 1488 printf("============================\n"); 1489 inst.width = 256; 1490 inst.height = 256; 1491 int formatCount = 0; 1492 1493 //--WIN32-- 1494 #ifdef VK_USE_PLATFORM_WIN32_KHR 1495 if (has_extension(VK_KHR_WIN32_SURFACE_EXTENSION_NAME, 1496 inst.global_extension_count, inst.global_extensions)) { 1497 app_create_win32_window(&inst); 1498 for (i = 0; i < gpu_count; i++) { 1499 app_create_win32_surface(&inst); 1500 printf("GPU id : %u (%s)\n", i, gpus[i].props.deviceName); 1501 printf("Surface type : %s\n", VK_KHR_WIN32_SURFACE_EXTENSION_NAME); 1502 formatCount += app_dump_surface_formats(&inst, &gpus[i]); 1503 app_destroy_surface(&inst); 1504 } 1505 app_destroy_win32_window(&inst); 1506 } 1507 #endif 1508 //--XCB-- 1509 #ifdef VK_USE_PLATFORM_XCB_KHR 1510 if (has_extension(VK_KHR_XCB_SURFACE_EXTENSION_NAME, 1511 inst.global_extension_count, inst.global_extensions)) { 1512 app_create_xcb_window(&inst); 1513 for (i = 0; i < gpu_count; i++) { 1514 app_create_xcb_surface(&inst); 1515 printf("GPU id : %u (%s)\n", i, gpus[i].props.deviceName); 1516 printf("Surface type : %s\n", VK_KHR_XCB_SURFACE_EXTENSION_NAME); 1517 formatCount += app_dump_surface_formats(&inst, &gpus[i]); 1518 app_destroy_surface(&inst); 1519 } 1520 app_destroy_xcb_window(&inst); 1521 } 1522 #endif 1523 //--XLIB-- 1524 #ifdef VK_USE_PLATFORM_XLIB_KHR 1525 if (has_extension(VK_KHR_XLIB_SURFACE_EXTENSION_NAME, 1526 inst.global_extension_count, inst.global_extensions)) { 1527 app_create_xlib_window(&inst); 1528 for (i = 0; i < gpu_count; i++) { 1529 app_create_xlib_surface(&inst); 1530 printf("GPU id : %u (%s)\n", i, gpus[i].props.deviceName); 1531 printf("Surface type : %s\n", VK_KHR_XLIB_SURFACE_EXTENSION_NAME); 1532 formatCount += app_dump_surface_formats(&inst, &gpus[i]); 1533 app_destroy_surface(&inst); 1534 } 1535 app_destroy_xlib_window(&inst); 1536 } 1537 #endif 1538 // TODO: Android / Wayland / MIR 1539 if (!formatCount) 1540 printf("None found\n"); 1541 //--------- 1542 1543 for (i = 0; i < gpu_count; i++) { 1544 app_gpu_dump(&gpus[i]); 1545 printf("\n\n"); 1546 } 1547 1548 for (i = 0; i < gpu_count; i++) 1549 app_gpu_destroy(&gpus[i]); 1550 1551 app_destroy_instance(&inst); 1552 1553 fflush(stdout); 1554 #ifdef _WIN32 1555 if (ConsoleIsExclusive()) 1556 Sleep(INFINITE); 1557 #endif 1558 1559 return 0; 1560 } 1561