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