vulkaninfo.c revision 5d8d6b4f93daceacca1de36be6de935a8264caf6
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 * Author: Jeremy Kniager <jeremyk@lunarg.com> 23 */ 24 25#ifdef __GNUC__ 26#ifndef _POSIX_C_SOURCE 27#define _POSIX_C_SOURCE 200809L 28#endif 29#else 30#define strndup(p, n) strdup(p) 31#endif 32 33#include <assert.h> 34#include <inttypes.h> 35#include <stdbool.h> 36#include <stdio.h> 37#include <stdlib.h> 38#include <string.h> 39 40#ifdef _WIN32 41#include <fcntl.h> 42#include <io.h> 43#endif // _WIN32 44 45#if defined(VK_USE_PLATFORM_XLIB_KHR) || defined(VK_USE_PLATFORM_XCB_KHR) 46#include <X11/Xutil.h> 47#endif 48 49#if defined(VK_USE_PLATFORM_MIR_KHR) 50#warning "Vulkaninfo does not have code for Mir at this time" 51#endif 52 53#include <vulkan/vulkan.h> 54 55#define ERR(err) printf("%s:%d: failed with %s\n", __FILE__, __LINE__, VkResultString(err)); 56 57#ifdef _WIN32 58 59#define snprintf _snprintf 60#define strdup _strdup 61 62// Returns nonzero if the console is used only for this process. Will return 63// zero if another process (such as cmd.exe) is also attached. 64static int ConsoleIsExclusive(void) { 65 DWORD pids[2]; 66 DWORD num_pids = GetConsoleProcessList(pids, ARRAYSIZE(pids)); 67 return num_pids <= 1; 68} 69 70#define WAIT_FOR_CONSOLE_DESTROY \ 71 do { \ 72 if (ConsoleIsExclusive()) Sleep(INFINITE); \ 73 } while (0) 74#else 75#define WAIT_FOR_CONSOLE_DESTROY 76#endif 77 78#define ERR_EXIT(err) \ 79 do { \ 80 ERR(err); \ 81 fflush(stdout); \ 82 WAIT_FOR_CONSOLE_DESTROY; \ 83 exit(-1); \ 84 } while (0) 85 86#if defined(NDEBUG) && defined(__GNUC__) 87#define U_ASSERT_ONLY __attribute__((unused)) 88#else 89#define U_ASSERT_ONLY 90#endif 91 92#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 93 94#define MAX_QUEUE_TYPES 5 95#define APP_SHORT_NAME "vulkaninfo" 96 97static const VkFormat format_check_list[] = {VK_FORMAT_UNDEFINED, 98 VK_FORMAT_R4G4_UNORM_PACK8, 99 VK_FORMAT_R4G4B4A4_UNORM_PACK16, 100 VK_FORMAT_B4G4R4A4_UNORM_PACK16, 101 VK_FORMAT_R5G6B5_UNORM_PACK16, 102 VK_FORMAT_B5G6R5_UNORM_PACK16, 103 VK_FORMAT_R5G5B5A1_UNORM_PACK16, 104 VK_FORMAT_B5G5R5A1_UNORM_PACK16, 105 VK_FORMAT_A1R5G5B5_UNORM_PACK16, 106 VK_FORMAT_R8_UNORM, 107 VK_FORMAT_R8_SNORM, 108 VK_FORMAT_R8_USCALED, 109 VK_FORMAT_R8_SSCALED, 110 VK_FORMAT_R8_UINT, 111 VK_FORMAT_R8_SINT, 112 VK_FORMAT_R8_SRGB, 113 VK_FORMAT_R8G8_UNORM, 114 VK_FORMAT_R8G8_SNORM, 115 VK_FORMAT_R8G8_USCALED, 116 VK_FORMAT_R8G8_SSCALED, 117 VK_FORMAT_R8G8_UINT, 118 VK_FORMAT_R8G8_SINT, 119 VK_FORMAT_R8G8_SRGB, 120 VK_FORMAT_R8G8B8_UNORM, 121 VK_FORMAT_R8G8B8_SNORM, 122 VK_FORMAT_R8G8B8_USCALED, 123 VK_FORMAT_R8G8B8_SSCALED, 124 VK_FORMAT_R8G8B8_UINT, 125 VK_FORMAT_R8G8B8_SINT, 126 VK_FORMAT_R8G8B8_SRGB, 127 VK_FORMAT_B8G8R8_UNORM, 128 VK_FORMAT_B8G8R8_SNORM, 129 VK_FORMAT_B8G8R8_USCALED, 130 VK_FORMAT_B8G8R8_SSCALED, 131 VK_FORMAT_B8G8R8_UINT, 132 VK_FORMAT_B8G8R8_SINT, 133 VK_FORMAT_B8G8R8_SRGB, 134 VK_FORMAT_R8G8B8A8_UNORM, 135 VK_FORMAT_R8G8B8A8_SNORM, 136 VK_FORMAT_R8G8B8A8_USCALED, 137 VK_FORMAT_R8G8B8A8_SSCALED, 138 VK_FORMAT_R8G8B8A8_UINT, 139 VK_FORMAT_R8G8B8A8_SINT, 140 VK_FORMAT_R8G8B8A8_SRGB, 141 VK_FORMAT_B8G8R8A8_UNORM, 142 VK_FORMAT_B8G8R8A8_SNORM, 143 VK_FORMAT_B8G8R8A8_USCALED, 144 VK_FORMAT_B8G8R8A8_SSCALED, 145 VK_FORMAT_B8G8R8A8_UINT, 146 VK_FORMAT_B8G8R8A8_SINT, 147 VK_FORMAT_B8G8R8A8_SRGB, 148 VK_FORMAT_A8B8G8R8_UNORM_PACK32, 149 VK_FORMAT_A8B8G8R8_SNORM_PACK32, 150 VK_FORMAT_A8B8G8R8_USCALED_PACK32, 151 VK_FORMAT_A8B8G8R8_SSCALED_PACK32, 152 VK_FORMAT_A8B8G8R8_UINT_PACK32, 153 VK_FORMAT_A8B8G8R8_SINT_PACK32, 154 VK_FORMAT_A8B8G8R8_SRGB_PACK32, 155 VK_FORMAT_A2R10G10B10_UNORM_PACK32, 156 VK_FORMAT_A2R10G10B10_SNORM_PACK32, 157 VK_FORMAT_A2R10G10B10_USCALED_PACK32, 158 VK_FORMAT_A2R10G10B10_SSCALED_PACK32, 159 VK_FORMAT_A2R10G10B10_UINT_PACK32, 160 VK_FORMAT_A2R10G10B10_SINT_PACK32, 161 VK_FORMAT_A2B10G10R10_UNORM_PACK32, 162 VK_FORMAT_A2B10G10R10_SNORM_PACK32, 163 VK_FORMAT_A2B10G10R10_USCALED_PACK32, 164 VK_FORMAT_A2B10G10R10_SSCALED_PACK32, 165 VK_FORMAT_A2B10G10R10_UINT_PACK32, 166 VK_FORMAT_A2B10G10R10_SINT_PACK32, 167 VK_FORMAT_R16_UNORM, 168 VK_FORMAT_R16_SNORM, 169 VK_FORMAT_R16_USCALED, 170 VK_FORMAT_R16_SSCALED, 171 VK_FORMAT_R16_UINT, 172 VK_FORMAT_R16_SINT, 173 VK_FORMAT_R16_SFLOAT, 174 VK_FORMAT_R16G16_UNORM, 175 VK_FORMAT_R16G16_SNORM, 176 VK_FORMAT_R16G16_USCALED, 177 VK_FORMAT_R16G16_SSCALED, 178 VK_FORMAT_R16G16_UINT, 179 VK_FORMAT_R16G16_SINT, 180 VK_FORMAT_R16G16_SFLOAT, 181 VK_FORMAT_R16G16B16_UNORM, 182 VK_FORMAT_R16G16B16_SNORM, 183 VK_FORMAT_R16G16B16_USCALED, 184 VK_FORMAT_R16G16B16_SSCALED, 185 VK_FORMAT_R16G16B16_UINT, 186 VK_FORMAT_R16G16B16_SINT, 187 VK_FORMAT_R16G16B16_SFLOAT, 188 VK_FORMAT_R16G16B16A16_UNORM, 189 VK_FORMAT_R16G16B16A16_SNORM, 190 VK_FORMAT_R16G16B16A16_USCALED, 191 VK_FORMAT_R16G16B16A16_SSCALED, 192 VK_FORMAT_R16G16B16A16_UINT, 193 VK_FORMAT_R16G16B16A16_SINT, 194 VK_FORMAT_R16G16B16A16_SFLOAT, 195 VK_FORMAT_R32_UINT, 196 VK_FORMAT_R32_SINT, 197 VK_FORMAT_R32_SFLOAT, 198 VK_FORMAT_R32G32_UINT, 199 VK_FORMAT_R32G32_SINT, 200 VK_FORMAT_R32G32_SFLOAT, 201 VK_FORMAT_R32G32B32_UINT, 202 VK_FORMAT_R32G32B32_SINT, 203 VK_FORMAT_R32G32B32_SFLOAT, 204 VK_FORMAT_R32G32B32A32_UINT, 205 VK_FORMAT_R32G32B32A32_SINT, 206 VK_FORMAT_R32G32B32A32_SFLOAT, 207 VK_FORMAT_R64_UINT, 208 VK_FORMAT_R64_SINT, 209 VK_FORMAT_R64_SFLOAT, 210 VK_FORMAT_R64G64_UINT, 211 VK_FORMAT_R64G64_SINT, 212 VK_FORMAT_R64G64_SFLOAT, 213 VK_FORMAT_R64G64B64_UINT, 214 VK_FORMAT_R64G64B64_SINT, 215 VK_FORMAT_R64G64B64_SFLOAT, 216 VK_FORMAT_R64G64B64A64_UINT, 217 VK_FORMAT_R64G64B64A64_SINT, 218 VK_FORMAT_R64G64B64A64_SFLOAT, 219 VK_FORMAT_B10G11R11_UFLOAT_PACK32, 220 VK_FORMAT_E5B9G9R9_UFLOAT_PACK32, 221 VK_FORMAT_D16_UNORM, 222 VK_FORMAT_X8_D24_UNORM_PACK32, 223 VK_FORMAT_D32_SFLOAT, 224 VK_FORMAT_S8_UINT, 225 VK_FORMAT_D16_UNORM_S8_UINT, 226 VK_FORMAT_D24_UNORM_S8_UINT, 227 VK_FORMAT_D32_SFLOAT_S8_UINT, 228 VK_FORMAT_BC1_RGB_UNORM_BLOCK, 229 VK_FORMAT_BC1_RGB_SRGB_BLOCK, 230 VK_FORMAT_BC1_RGBA_UNORM_BLOCK, 231 VK_FORMAT_BC1_RGBA_SRGB_BLOCK, 232 VK_FORMAT_BC2_UNORM_BLOCK, 233 VK_FORMAT_BC2_SRGB_BLOCK, 234 VK_FORMAT_BC3_UNORM_BLOCK, 235 VK_FORMAT_BC3_SRGB_BLOCK, 236 VK_FORMAT_BC4_UNORM_BLOCK, 237 VK_FORMAT_BC4_SNORM_BLOCK, 238 VK_FORMAT_BC5_UNORM_BLOCK, 239 VK_FORMAT_BC5_SNORM_BLOCK, 240 VK_FORMAT_BC6H_UFLOAT_BLOCK, 241 VK_FORMAT_BC6H_SFLOAT_BLOCK, 242 VK_FORMAT_BC7_UNORM_BLOCK, 243 VK_FORMAT_BC7_SRGB_BLOCK, 244 VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, 245 VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK, 246 VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK, 247 VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK, 248 VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, 249 VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK, 250 VK_FORMAT_EAC_R11_UNORM_BLOCK, 251 VK_FORMAT_EAC_R11_SNORM_BLOCK, 252 VK_FORMAT_EAC_R11G11_UNORM_BLOCK, 253 VK_FORMAT_EAC_R11G11_SNORM_BLOCK, 254 VK_FORMAT_ASTC_4x4_UNORM_BLOCK, 255 VK_FORMAT_ASTC_4x4_SRGB_BLOCK, 256 VK_FORMAT_ASTC_5x4_UNORM_BLOCK, 257 VK_FORMAT_ASTC_5x4_SRGB_BLOCK, 258 VK_FORMAT_ASTC_5x5_UNORM_BLOCK, 259 VK_FORMAT_ASTC_5x5_SRGB_BLOCK, 260 VK_FORMAT_ASTC_6x5_UNORM_BLOCK, 261 VK_FORMAT_ASTC_6x5_SRGB_BLOCK, 262 VK_FORMAT_ASTC_6x6_UNORM_BLOCK, 263 VK_FORMAT_ASTC_6x6_SRGB_BLOCK, 264 VK_FORMAT_ASTC_8x5_UNORM_BLOCK, 265 VK_FORMAT_ASTC_8x5_SRGB_BLOCK, 266 VK_FORMAT_ASTC_8x6_UNORM_BLOCK, 267 VK_FORMAT_ASTC_8x6_SRGB_BLOCK, 268 VK_FORMAT_ASTC_8x8_UNORM_BLOCK, 269 VK_FORMAT_ASTC_8x8_SRGB_BLOCK, 270 VK_FORMAT_ASTC_10x5_UNORM_BLOCK, 271 VK_FORMAT_ASTC_10x5_SRGB_BLOCK, 272 VK_FORMAT_ASTC_10x6_UNORM_BLOCK, 273 VK_FORMAT_ASTC_10x6_SRGB_BLOCK, 274 VK_FORMAT_ASTC_10x8_UNORM_BLOCK, 275 VK_FORMAT_ASTC_10x8_SRGB_BLOCK, 276 VK_FORMAT_ASTC_10x10_UNORM_BLOCK, 277 VK_FORMAT_ASTC_10x10_SRGB_BLOCK, 278 VK_FORMAT_ASTC_12x10_UNORM_BLOCK, 279 VK_FORMAT_ASTC_12x10_SRGB_BLOCK, 280 VK_FORMAT_ASTC_12x12_UNORM_BLOCK, 281 VK_FORMAT_ASTC_12x12_SRGB_BLOCK, 282 VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG, 283 VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG, 284 VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG, 285 VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG, 286 VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG, 287 VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG, 288 VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG, 289 VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG}; 290 291static const uint32_t format_check_list_count = ARRAY_SIZE(format_check_list); 292 293struct VkStructureHeader { 294 VkStructureType sType; 295 void *pNext; 296}; 297 298struct AppGpu; 299 300struct AppDev { 301 struct AppGpu *gpu; /* point back to the GPU */ 302 303 VkDevice obj; 304 305 VkFormatProperties format_props[ARRAY_SIZE(format_check_list)]; 306 VkFormatProperties2KHR format_props2[ARRAY_SIZE(format_check_list)]; 307}; 308 309struct LayerExtensionList { 310 VkLayerProperties layer_properties; 311 uint32_t extension_count; 312 VkExtensionProperties *extension_properties; 313}; 314 315struct AppInstance { 316 VkInstance instance; 317 uint32_t global_layer_count; 318 struct LayerExtensionList *global_layers; 319 uint32_t global_extension_count; 320 VkExtensionProperties *global_extensions; // Instance Extensions 321 322 const char **inst_extensions; 323 uint32_t inst_extensions_count; 324 325 PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR; 326 PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR; 327 PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR; 328 PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR; 329 PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR; 330 PFN_vkGetPhysicalDeviceFormatProperties2KHR vkGetPhysicalDeviceFormatProperties2KHR; 331 PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR vkGetPhysicalDeviceQueueFamilyProperties2KHR; 332 PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR; 333 PFN_vkGetPhysicalDeviceMemoryProperties2KHR vkGetPhysicalDeviceMemoryProperties2KHR; 334 PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR vkGetPhysicalDeviceSurfaceCapabilities2KHR; 335 PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT vkGetPhysicalDeviceSurfaceCapabilities2EXT; 336 337 VkSurfaceCapabilitiesKHR surface_capabilities; 338 VkSurfaceCapabilities2KHR surface_capabilities2; 339 VkSharedPresentSurfaceCapabilitiesKHR shared_surface_capabilities; 340 VkSurfaceCapabilities2EXT surface_capabilities2_ext; 341 342 VkSurfaceKHR surface; 343 int width, height; 344 345#ifdef VK_USE_PLATFORM_WIN32_KHR 346 HINSTANCE h_instance; // Windows Instance 347 HWND h_wnd; // window handle 348#elif VK_USE_PLATFORM_XCB_KHR 349 xcb_connection_t *xcb_connection; 350 xcb_screen_t *xcb_screen; 351 xcb_window_t xcb_window; 352#elif VK_USE_PLATFORM_XLIB_KHR 353 Display *xlib_display; 354 Window xlib_window; 355#elif VK_USE_PLATFORM_ANDROID_KHR // TODO 356 ANativeWindow *window; 357#endif 358}; 359 360struct AppGpu { 361 uint32_t id; 362 VkPhysicalDevice obj; 363 364 VkPhysicalDeviceProperties props; 365 VkPhysicalDeviceProperties2KHR props2; 366 367 uint32_t queue_count; 368 VkQueueFamilyProperties *queue_props; 369 VkQueueFamilyProperties2KHR *queue_props2; 370 VkDeviceQueueCreateInfo *queue_reqs; 371 372 struct AppInstance *inst; 373 374 VkPhysicalDeviceMemoryProperties memory_props; 375 VkPhysicalDeviceMemoryProperties2KHR memory_props2; 376 377 VkPhysicalDeviceFeatures features; 378 VkPhysicalDeviceFeatures2KHR features2; 379 VkPhysicalDevice limits; 380 381 uint32_t device_extension_count; 382 VkExtensionProperties *device_extensions; 383 384 struct AppDev dev; 385}; 386 387static VKAPI_ATTR VkBool32 VKAPI_CALL DbgCallback(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject, 388 size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg, 389 void *pUserData) { 390 char *message = (char *)malloc(strlen(pMsg) + 100); 391 392 assert(message); 393 394 if (msgFlags & VK_DEBUG_REPORT_ERROR_BIT_EXT) { 395 sprintf(message, "ERROR: [%s] Code %d : %s", pLayerPrefix, msgCode, pMsg); 396 } else if (msgFlags & VK_DEBUG_REPORT_WARNING_BIT_EXT) { 397 sprintf(message, "WARNING: [%s] Code %d : %s", pLayerPrefix, msgCode, pMsg); 398 } else if (msgFlags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) { 399 sprintf(message, "INFO: [%s] Code %d : %s", pLayerPrefix, msgCode, pMsg); 400 } else if (msgFlags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) { 401 sprintf(message, "DEBUG: [%s] Code %d : %s", pLayerPrefix, msgCode, pMsg); 402 } 403 404 printf("%s\n", message); 405 fflush(stdout); 406 free(message); 407 408 /* 409 * false indicates that layer should not bail-out of an 410 * API call that had validation failures. This may mean that the 411 * app dies inside the driver due to invalid parameter(s). 412 * That's what would happen without validation layers, so we'll 413 * keep that behavior here. 414 */ 415 return false; 416} 417 418static const char *VkResultString(VkResult err) { 419 switch (err) { 420#define STR(r) \ 421 case r: \ 422 return #r 423 STR(VK_SUCCESS); 424 STR(VK_NOT_READY); 425 STR(VK_TIMEOUT); 426 STR(VK_EVENT_SET); 427 STR(VK_EVENT_RESET); 428 STR(VK_ERROR_INITIALIZATION_FAILED); 429 STR(VK_ERROR_OUT_OF_HOST_MEMORY); 430 STR(VK_ERROR_OUT_OF_DEVICE_MEMORY); 431 STR(VK_ERROR_DEVICE_LOST); 432 STR(VK_ERROR_LAYER_NOT_PRESENT); 433 STR(VK_ERROR_EXTENSION_NOT_PRESENT); 434 STR(VK_ERROR_MEMORY_MAP_FAILED); 435 STR(VK_ERROR_INCOMPATIBLE_DRIVER); 436#undef STR 437 default: 438 return "UNKNOWN_RESULT"; 439 } 440} 441 442static const char *VkPhysicalDeviceTypeString(VkPhysicalDeviceType type) { 443 switch (type) { 444#define STR(r) \ 445 case VK_PHYSICAL_DEVICE_TYPE_##r: \ 446 return #r 447 STR(OTHER); 448 STR(INTEGRATED_GPU); 449 STR(DISCRETE_GPU); 450 STR(VIRTUAL_GPU); 451 STR(CPU); 452#undef STR 453 default: 454 return "UNKNOWN_DEVICE"; 455 } 456} 457 458static const char *VkFormatString(VkFormat fmt) { 459 switch (fmt) { 460#define STR(r) \ 461 case VK_FORMAT_##r: \ 462 return #r 463 STR(UNDEFINED); 464 STR(R4G4_UNORM_PACK8); 465 STR(R4G4B4A4_UNORM_PACK16); 466 STR(B4G4R4A4_UNORM_PACK16); 467 STR(R5G6B5_UNORM_PACK16); 468 STR(B5G6R5_UNORM_PACK16); 469 STR(R5G5B5A1_UNORM_PACK16); 470 STR(B5G5R5A1_UNORM_PACK16); 471 STR(A1R5G5B5_UNORM_PACK16); 472 STR(R8_UNORM); 473 STR(R8_SNORM); 474 STR(R8_USCALED); 475 STR(R8_SSCALED); 476 STR(R8_UINT); 477 STR(R8_SINT); 478 STR(R8_SRGB); 479 STR(R8G8_UNORM); 480 STR(R8G8_SNORM); 481 STR(R8G8_USCALED); 482 STR(R8G8_SSCALED); 483 STR(R8G8_UINT); 484 STR(R8G8_SINT); 485 STR(R8G8_SRGB); 486 STR(R8G8B8_UNORM); 487 STR(R8G8B8_SNORM); 488 STR(R8G8B8_USCALED); 489 STR(R8G8B8_SSCALED); 490 STR(R8G8B8_UINT); 491 STR(R8G8B8_SINT); 492 STR(R8G8B8_SRGB); 493 STR(B8G8R8_UNORM); 494 STR(B8G8R8_SNORM); 495 STR(B8G8R8_USCALED); 496 STR(B8G8R8_SSCALED); 497 STR(B8G8R8_UINT); 498 STR(B8G8R8_SINT); 499 STR(B8G8R8_SRGB); 500 STR(R8G8B8A8_UNORM); 501 STR(R8G8B8A8_SNORM); 502 STR(R8G8B8A8_USCALED); 503 STR(R8G8B8A8_SSCALED); 504 STR(R8G8B8A8_UINT); 505 STR(R8G8B8A8_SINT); 506 STR(R8G8B8A8_SRGB); 507 STR(B8G8R8A8_UNORM); 508 STR(B8G8R8A8_SNORM); 509 STR(B8G8R8A8_USCALED); 510 STR(B8G8R8A8_SSCALED); 511 STR(B8G8R8A8_UINT); 512 STR(B8G8R8A8_SINT); 513 STR(B8G8R8A8_SRGB); 514 STR(A8B8G8R8_UNORM_PACK32); 515 STR(A8B8G8R8_SNORM_PACK32); 516 STR(A8B8G8R8_USCALED_PACK32); 517 STR(A8B8G8R8_SSCALED_PACK32); 518 STR(A8B8G8R8_UINT_PACK32); 519 STR(A8B8G8R8_SINT_PACK32); 520 STR(A8B8G8R8_SRGB_PACK32); 521 STR(A2R10G10B10_UNORM_PACK32); 522 STR(A2R10G10B10_SNORM_PACK32); 523 STR(A2R10G10B10_USCALED_PACK32); 524 STR(A2R10G10B10_SSCALED_PACK32); 525 STR(A2R10G10B10_UINT_PACK32); 526 STR(A2R10G10B10_SINT_PACK32); 527 STR(A2B10G10R10_UNORM_PACK32); 528 STR(A2B10G10R10_SNORM_PACK32); 529 STR(A2B10G10R10_USCALED_PACK32); 530 STR(A2B10G10R10_SSCALED_PACK32); 531 STR(A2B10G10R10_UINT_PACK32); 532 STR(A2B10G10R10_SINT_PACK32); 533 STR(R16_UNORM); 534 STR(R16_SNORM); 535 STR(R16_USCALED); 536 STR(R16_SSCALED); 537 STR(R16_UINT); 538 STR(R16_SINT); 539 STR(R16_SFLOAT); 540 STR(R16G16_UNORM); 541 STR(R16G16_SNORM); 542 STR(R16G16_USCALED); 543 STR(R16G16_SSCALED); 544 STR(R16G16_UINT); 545 STR(R16G16_SINT); 546 STR(R16G16_SFLOAT); 547 STR(R16G16B16_UNORM); 548 STR(R16G16B16_SNORM); 549 STR(R16G16B16_USCALED); 550 STR(R16G16B16_SSCALED); 551 STR(R16G16B16_UINT); 552 STR(R16G16B16_SINT); 553 STR(R16G16B16_SFLOAT); 554 STR(R16G16B16A16_UNORM); 555 STR(R16G16B16A16_SNORM); 556 STR(R16G16B16A16_USCALED); 557 STR(R16G16B16A16_SSCALED); 558 STR(R16G16B16A16_UINT); 559 STR(R16G16B16A16_SINT); 560 STR(R16G16B16A16_SFLOAT); 561 STR(R32_UINT); 562 STR(R32_SINT); 563 STR(R32_SFLOAT); 564 STR(R32G32_UINT); 565 STR(R32G32_SINT); 566 STR(R32G32_SFLOAT); 567 STR(R32G32B32_UINT); 568 STR(R32G32B32_SINT); 569 STR(R32G32B32_SFLOAT); 570 STR(R32G32B32A32_UINT); 571 STR(R32G32B32A32_SINT); 572 STR(R32G32B32A32_SFLOAT); 573 STR(R64_UINT); 574 STR(R64_SINT); 575 STR(R64_SFLOAT); 576 STR(R64G64_UINT); 577 STR(R64G64_SINT); 578 STR(R64G64_SFLOAT); 579 STR(R64G64B64_UINT); 580 STR(R64G64B64_SINT); 581 STR(R64G64B64_SFLOAT); 582 STR(R64G64B64A64_UINT); 583 STR(R64G64B64A64_SINT); 584 STR(R64G64B64A64_SFLOAT); 585 STR(B10G11R11_UFLOAT_PACK32); 586 STR(E5B9G9R9_UFLOAT_PACK32); 587 STR(D16_UNORM); 588 STR(X8_D24_UNORM_PACK32); 589 STR(D32_SFLOAT); 590 STR(S8_UINT); 591 STR(D16_UNORM_S8_UINT); 592 STR(D24_UNORM_S8_UINT); 593 STR(D32_SFLOAT_S8_UINT); 594 STR(BC1_RGB_UNORM_BLOCK); 595 STR(BC1_RGB_SRGB_BLOCK); 596 STR(BC2_UNORM_BLOCK); 597 STR(BC2_SRGB_BLOCK); 598 STR(BC3_UNORM_BLOCK); 599 STR(BC3_SRGB_BLOCK); 600 STR(BC4_UNORM_BLOCK); 601 STR(BC4_SNORM_BLOCK); 602 STR(BC5_UNORM_BLOCK); 603 STR(BC5_SNORM_BLOCK); 604 STR(BC6H_UFLOAT_BLOCK); 605 STR(BC6H_SFLOAT_BLOCK); 606 STR(BC7_UNORM_BLOCK); 607 STR(BC7_SRGB_BLOCK); 608 STR(ETC2_R8G8B8_UNORM_BLOCK); 609 STR(ETC2_R8G8B8A1_UNORM_BLOCK); 610 STR(ETC2_R8G8B8A8_UNORM_BLOCK); 611 STR(EAC_R11_UNORM_BLOCK); 612 STR(EAC_R11_SNORM_BLOCK); 613 STR(EAC_R11G11_UNORM_BLOCK); 614 STR(EAC_R11G11_SNORM_BLOCK); 615 STR(ASTC_4x4_UNORM_BLOCK); 616 STR(ASTC_4x4_SRGB_BLOCK); 617 STR(ASTC_5x4_UNORM_BLOCK); 618 STR(ASTC_5x4_SRGB_BLOCK); 619 STR(ASTC_5x5_UNORM_BLOCK); 620 STR(ASTC_5x5_SRGB_BLOCK); 621 STR(ASTC_6x5_UNORM_BLOCK); 622 STR(ASTC_6x5_SRGB_BLOCK); 623 STR(ASTC_6x6_UNORM_BLOCK); 624 STR(ASTC_6x6_SRGB_BLOCK); 625 STR(ASTC_8x5_UNORM_BLOCK); 626 STR(ASTC_8x5_SRGB_BLOCK); 627 STR(ASTC_8x6_UNORM_BLOCK); 628 STR(ASTC_8x6_SRGB_BLOCK); 629 STR(ASTC_8x8_UNORM_BLOCK); 630 STR(ASTC_8x8_SRGB_BLOCK); 631 STR(ASTC_10x5_UNORM_BLOCK); 632 STR(ASTC_10x5_SRGB_BLOCK); 633 STR(ASTC_10x6_UNORM_BLOCK); 634 STR(ASTC_10x6_SRGB_BLOCK); 635 STR(ASTC_10x8_UNORM_BLOCK); 636 STR(ASTC_10x8_SRGB_BLOCK); 637 STR(ASTC_10x10_UNORM_BLOCK); 638 STR(ASTC_10x10_SRGB_BLOCK); 639 STR(ASTC_12x10_UNORM_BLOCK); 640 STR(ASTC_12x10_SRGB_BLOCK); 641 STR(ASTC_12x12_UNORM_BLOCK); 642 STR(ASTC_12x12_SRGB_BLOCK); 643#undef STR 644 default: 645 return "UNKNOWN_FORMAT"; 646 } 647} 648#if defined(VK_USE_PLATFORM_XCB_KHR) || defined(VK_USE_PLATFORM_XLIB_KHR) || defined(VK_USE_PLATFORM_WIN32_KHR) 649static const char *VkPresentModeString(VkPresentModeKHR mode) { 650 switch (mode) { 651#define STR(r) \ 652 case VK_PRESENT_MODE_##r: \ 653 return #r 654 STR(IMMEDIATE_KHR); 655 STR(MAILBOX_KHR); 656 STR(FIFO_KHR); 657 STR(FIFO_RELAXED_KHR); 658#undef STR 659 default: 660 return "UNKNOWN_FORMAT"; 661 } 662} 663#endif 664 665static bool CheckExtensionEnabled(const char *extension_to_check, const char **extension_list, uint32_t extension_count) { 666 for (uint32_t i = 0; i < extension_count; i++) { 667 if (!strcmp(extension_to_check, extension_list[i])) return true; 668 } 669 return false; 670} 671 672static void AppDevInitFormats(struct AppDev *dev) { 673 for (uint32_t i = 0; i < format_check_list_count; i++) { 674 vkGetPhysicalDeviceFormatProperties(dev->gpu->obj, format_check_list[i], &dev->format_props[i]); 675 676 if (CheckExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, dev->gpu->inst->inst_extensions, 677 dev->gpu->inst->inst_extensions_count)) { 678 dev->format_props2[i].sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR; 679 dev->format_props2[i].pNext = NULL; 680 dev->gpu->inst->vkGetPhysicalDeviceFormatProperties2KHR(dev->gpu->obj, format_check_list[i], &dev->format_props2[i]); 681 } 682 } 683} 684 685static void ExtractVersion(uint32_t version, uint32_t *major, uint32_t *minor, uint32_t *patch) { 686 *major = version >> 22; 687 *minor = (version >> 12) & 0x3ff; 688 *patch = version & 0xfff; 689} 690 691static void AppGetPhysicalDeviceLayerExtensions(struct AppGpu *gpu, char *layer_name, uint32_t *extension_count, 692 VkExtensionProperties **extension_properties) { 693 VkResult err; 694 uint32_t ext_count = 0; 695 VkExtensionProperties *ext_ptr = NULL; 696 697 /* repeat get until VK_INCOMPLETE goes away */ 698 do { 699 err = vkEnumerateDeviceExtensionProperties(gpu->obj, layer_name, &ext_count, NULL); 700 assert(!err); 701 702 if (ext_ptr) { 703 free(ext_ptr); 704 } 705 ext_ptr = malloc(ext_count * sizeof(VkExtensionProperties)); 706 err = vkEnumerateDeviceExtensionProperties(gpu->obj, layer_name, &ext_count, ext_ptr); 707 } while (err == VK_INCOMPLETE); 708 assert(!err); 709 710 *extension_count = ext_count; 711 *extension_properties = ext_ptr; 712} 713 714static void AppDevInit(struct AppDev *dev, struct AppGpu *gpu) { 715 VkDeviceCreateInfo info = { 716 .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, 717 .pNext = NULL, 718 .flags = 0, 719 .queueCreateInfoCount = 0, 720 .pQueueCreateInfos = NULL, 721 .enabledLayerCount = 0, 722 .ppEnabledLayerNames = NULL, 723 .enabledExtensionCount = 0, 724 .ppEnabledExtensionNames = NULL, 725 }; 726 VkResult U_ASSERT_ONLY err; 727 728 // Device extensions 729 AppGetPhysicalDeviceLayerExtensions(gpu, NULL, &gpu->device_extension_count, &gpu->device_extensions); 730 731 fflush(stdout); 732 733 /* request all queues */ 734 info.queueCreateInfoCount = gpu->queue_count; 735 info.pQueueCreateInfos = gpu->queue_reqs; 736 737 info.enabledLayerCount = 0; 738 info.ppEnabledLayerNames = NULL; 739 info.enabledExtensionCount = 0; 740 info.ppEnabledExtensionNames = NULL; 741 dev->gpu = gpu; 742 err = vkCreateDevice(gpu->obj, &info, NULL, &dev->obj); 743 if (err) ERR_EXIT(err); 744} 745 746static void AppDevDestroy(struct AppDev *dev) { 747 vkDeviceWaitIdle(dev->obj); 748 vkDestroyDevice(dev->obj, NULL); 749} 750 751static void AppGetGlobalLayerExtensions(char *layer_name, uint32_t *extension_count, VkExtensionProperties **extension_properties) { 752 VkResult err; 753 uint32_t ext_count = 0; 754 VkExtensionProperties *ext_ptr = NULL; 755 756 /* repeat get until VK_INCOMPLETE goes away */ 757 do { 758 // gets the extension count if the last parameter is NULL 759 err = vkEnumerateInstanceExtensionProperties(layer_name, &ext_count, NULL); 760 assert(!err); 761 762 if (ext_ptr) { 763 free(ext_ptr); 764 } 765 ext_ptr = malloc(ext_count * sizeof(VkExtensionProperties)); 766 // gets the extension properties if the last parameter is not NULL 767 err = vkEnumerateInstanceExtensionProperties(layer_name, &ext_count, ext_ptr); 768 } while (err == VK_INCOMPLETE); 769 assert(!err); 770 *extension_count = ext_count; 771 *extension_properties = ext_ptr; 772} 773 774/* Gets a list of layer and instance extensions */ 775static void AppGetInstanceExtensions(struct AppInstance *inst) { 776 VkResult U_ASSERT_ONLY err; 777 778 uint32_t count = 0; 779 780 /* Scan layers */ 781 VkLayerProperties *global_layer_properties = NULL; 782 struct LayerExtensionList *global_layers = NULL; 783 784 do { 785 err = vkEnumerateInstanceLayerProperties(&count, NULL); 786 assert(!err); 787 788 if (global_layer_properties) { 789 free(global_layer_properties); 790 } 791 global_layer_properties = malloc(sizeof(VkLayerProperties) * count); 792 assert(global_layer_properties); 793 794 if (global_layers) { 795 free(global_layers); 796 } 797 global_layers = malloc(sizeof(struct LayerExtensionList) * count); 798 assert(global_layers); 799 800 err = vkEnumerateInstanceLayerProperties(&count, global_layer_properties); 801 } while (err == VK_INCOMPLETE); 802 assert(!err); 803 804 inst->global_layer_count = count; 805 inst->global_layers = global_layers; 806 807 for (uint32_t i = 0; i < inst->global_layer_count; i++) { 808 VkLayerProperties *src_info = &global_layer_properties[i]; 809 struct LayerExtensionList *dst_info = &inst->global_layers[i]; 810 memcpy(&dst_info->layer_properties, src_info, sizeof(VkLayerProperties)); 811 812 // Save away layer extension info for report 813 // Gets layer extensions, if first parameter is not NULL 814 AppGetGlobalLayerExtensions(src_info->layerName, &dst_info->extension_count, &dst_info->extension_properties); 815 } 816 free(global_layer_properties); 817 818 // Collect global extensions 819 inst->global_extension_count = 0; 820 // Gets instance extensions, if no layer was specified in the first 821 // paramteter 822 AppGetGlobalLayerExtensions(NULL, &inst->global_extension_count, &inst->global_extensions); 823} 824 825static void AppCreateInstance(struct AppInstance *inst) { 826 AppGetInstanceExtensions(inst); 827 828//---Build a list of extensions to load--- 829 830 const char *info_instance_extensions[] = {VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, 831 VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME, 832 VK_KHR_SURFACE_EXTENSION_NAME, 833 VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME, 834 VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME, 835#ifdef VK_USE_PLATFORM_WIN32_KHR 836 VK_KHR_WIN32_SURFACE_EXTENSION_NAME 837#elif VK_USE_PLATFORM_XCB_KHR 838 VK_KHR_XCB_SURFACE_EXTENSION_NAME 839#elif VK_USE_PLATFORM_XLIB_KHR 840 VK_KHR_XLIB_SURFACE_EXTENSION_NAME 841#elif VK_USE_PLATFORM_WAYLAND_KHR 842 VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME 843#elif VK_USE_PLATFORM_ANDROID_KHR 844 VK_KHR_ANDROID_SURFACE_EXTENSION_NAME 845#endif 846 }; 847 uint32_t info_instance_extensions_count = ARRAY_SIZE(info_instance_extensions); 848 inst->inst_extensions = malloc(sizeof(char *) * ARRAY_SIZE(info_instance_extensions)); 849 inst->inst_extensions_count = 0; 850 851 for (uint32_t k = 0; (k < info_instance_extensions_count); k++) { 852 for (uint32_t j = 0; (j < inst->global_extension_count); j++) { 853 const char *found_name = inst->global_extensions[j].extensionName; 854 if (!strcmp(info_instance_extensions[k], found_name)) { 855 inst->inst_extensions[inst->inst_extensions_count++] = info_instance_extensions[k]; 856 break; 857 } 858 } 859 } 860 861 //---------------------------------------- 862 863 const VkApplicationInfo app_info = { 864 .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, 865 .pNext = NULL, 866 .pApplicationName = APP_SHORT_NAME, 867 .applicationVersion = 1, 868 .pEngineName = APP_SHORT_NAME, 869 .engineVersion = 1, 870 .apiVersion = VK_API_VERSION_1_0, 871 }; 872 873 VkInstanceCreateInfo inst_info = {.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, 874 .pNext = NULL, 875 .pApplicationInfo = &app_info, 876 .enabledLayerCount = 0, 877 .ppEnabledLayerNames = NULL, 878 .enabledExtensionCount = inst->inst_extensions_count, 879 .ppEnabledExtensionNames = inst->inst_extensions}; 880 881 VkDebugReportCallbackCreateInfoEXT dbg_info; 882 memset(&dbg_info, 0, sizeof(dbg_info)); 883 dbg_info.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT; 884 dbg_info.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_INFORMATION_BIT_EXT; 885 dbg_info.pfnCallback = DbgCallback; 886 inst_info.pNext = &dbg_info; 887 888 VkResult U_ASSERT_ONLY err; 889 err = vkCreateInstance(&inst_info, NULL, &inst->instance); 890 if (err == VK_ERROR_INCOMPATIBLE_DRIVER) { 891 printf("Cannot create Vulkan instance.\n"); 892 ERR_EXIT(err); 893 } else if (err) { 894 ERR_EXIT(err); 895 } 896 897 inst->vkGetPhysicalDeviceSurfaceSupportKHR = 898 (PFN_vkGetPhysicalDeviceSurfaceSupportKHR)vkGetInstanceProcAddr(inst->instance, "vkGetPhysicalDeviceSurfaceSupportKHR"); 899 inst->vkGetPhysicalDeviceSurfaceCapabilitiesKHR = (PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR)vkGetInstanceProcAddr( 900 inst->instance, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR"); 901 inst->vkGetPhysicalDeviceSurfaceFormatsKHR = 902 (PFN_vkGetPhysicalDeviceSurfaceFormatsKHR)vkGetInstanceProcAddr(inst->instance, "vkGetPhysicalDeviceSurfaceFormatsKHR"); 903 inst->vkGetPhysicalDeviceSurfacePresentModesKHR = (PFN_vkGetPhysicalDeviceSurfacePresentModesKHR)vkGetInstanceProcAddr( 904 inst->instance, "vkGetPhysicalDeviceSurfacePresentModesKHR"); 905 inst->vkGetPhysicalDeviceProperties2KHR = 906 (PFN_vkGetPhysicalDeviceProperties2KHR)vkGetInstanceProcAddr(inst->instance, "vkGetPhysicalDeviceProperties2KHR"); 907 inst->vkGetPhysicalDeviceFormatProperties2KHR = (PFN_vkGetPhysicalDeviceFormatProperties2KHR)vkGetInstanceProcAddr( 908 inst->instance, "vkGetPhysicalDeviceFormatProperties2KHR"); 909 inst->vkGetPhysicalDeviceQueueFamilyProperties2KHR = (PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR)vkGetInstanceProcAddr( 910 inst->instance, "vkGetPhysicalDeviceQueueFamilyProperties2KHR"); 911 inst->vkGetPhysicalDeviceFeatures2KHR = 912 (PFN_vkGetPhysicalDeviceFeatures2KHR)vkGetInstanceProcAddr(inst->instance, "vkGetPhysicalDeviceFeatures2KHR"); 913 inst->vkGetPhysicalDeviceMemoryProperties2KHR = (PFN_vkGetPhysicalDeviceMemoryProperties2KHR)vkGetInstanceProcAddr( 914 inst->instance, "vkGetPhysicalDeviceMemoryProperties2KHR"); 915 inst->vkGetPhysicalDeviceSurfaceCapabilities2KHR = (PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR)vkGetInstanceProcAddr( 916 inst->instance, "vkGetPhysicalDeviceSurfaceCapabilities2KHR"); 917 inst->vkGetPhysicalDeviceSurfaceCapabilities2EXT = (PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT)vkGetInstanceProcAddr( 918 inst->instance, "vkGetPhysicalDeviceSurfaceCapabilities2EXT"); 919} 920 921//----------------------------------------------------------- 922 923static void AppDestroyInstance(struct AppInstance *inst) { 924 free(inst->global_extensions); 925 for (uint32_t i = 0; i < inst->global_layer_count; i++) { 926 free(inst->global_layers[i].extension_properties); 927 } 928 free(inst->global_layers); 929 free(inst->inst_extensions); 930 vkDestroyInstance(inst->instance, NULL); 931} 932 933static void AppGpuInit(struct AppGpu *gpu, struct AppInstance *inst, uint32_t id, VkPhysicalDevice obj) { 934 uint32_t i; 935 936 memset(gpu, 0, sizeof(*gpu)); 937 938 gpu->id = id; 939 gpu->obj = obj; 940 gpu->inst = inst; 941 942 vkGetPhysicalDeviceProperties(gpu->obj, &gpu->props); 943 944 if (CheckExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, gpu->inst->inst_extensions, 945 gpu->inst->inst_extensions_count)) { 946 gpu->props2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR; 947 gpu->props2.pNext = NULL; 948 949 inst->vkGetPhysicalDeviceProperties2KHR(gpu->obj, &gpu->props2); 950 } 951 952 /* get queue count */ 953 vkGetPhysicalDeviceQueueFamilyProperties(gpu->obj, &gpu->queue_count, NULL); 954 955 gpu->queue_props = malloc(sizeof(gpu->queue_props[0]) * gpu->queue_count); 956 957 if (!gpu->queue_props) ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY); 958 vkGetPhysicalDeviceQueueFamilyProperties(gpu->obj, &gpu->queue_count, gpu->queue_props); 959 960 if (CheckExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, gpu->inst->inst_extensions, 961 gpu->inst->inst_extensions_count)) { 962 gpu->queue_props2 = malloc(sizeof(gpu->queue_props2[0]) * gpu->queue_count); 963 964 if (!gpu->queue_props2) ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY); 965 966 for (i = 0; i < gpu->queue_count; i++) { 967 gpu->queue_props2[i].sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR; 968 gpu->queue_props2[i].pNext = NULL; 969 } 970 971 inst->vkGetPhysicalDeviceQueueFamilyProperties2KHR(gpu->obj, &gpu->queue_count, gpu->queue_props2); 972 } 973 974 /* set up queue requests */ 975 gpu->queue_reqs = malloc(sizeof(*gpu->queue_reqs) * gpu->queue_count); 976 if (!gpu->queue_reqs) ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY); 977 for (i = 0; i < gpu->queue_count; i++) { 978 float *queue_priorities = malloc(gpu->queue_props[i].queueCount * sizeof(float)); 979 if (!queue_priorities) ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY); 980 memset(queue_priorities, 0, gpu->queue_props[i].queueCount * sizeof(float)); 981 982 gpu->queue_reqs[i].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; 983 gpu->queue_reqs[i].pNext = NULL; 984 gpu->queue_reqs[i].flags = 0; 985 gpu->queue_reqs[i].queueFamilyIndex = i; 986 gpu->queue_reqs[i].queueCount = gpu->queue_props[i].queueCount; 987 gpu->queue_reqs[i].pQueuePriorities = queue_priorities; 988 } 989 990 vkGetPhysicalDeviceMemoryProperties(gpu->obj, &gpu->memory_props); 991 992 vkGetPhysicalDeviceFeatures(gpu->obj, &gpu->features); 993 994 if (CheckExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, gpu->inst->inst_extensions, 995 gpu->inst->inst_extensions_count)) { 996 gpu->memory_props2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR; 997 gpu->memory_props2.pNext = NULL; 998 999 inst->vkGetPhysicalDeviceMemoryProperties2KHR(gpu->obj, &gpu->memory_props2); 1000 1001 gpu->features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR; 1002 gpu->features2.pNext = NULL; 1003 1004 inst->vkGetPhysicalDeviceFeatures2KHR(gpu->obj, &gpu->features2); 1005 } 1006 1007 AppDevInit(&gpu->dev, gpu); 1008 AppDevInitFormats(&gpu->dev); 1009} 1010 1011static void AppGpuDestroy(struct AppGpu *gpu) { 1012 AppDevDestroy(&gpu->dev); 1013 free(gpu->device_extensions); 1014 1015 for (uint32_t i = 0; i < gpu->queue_count; i++) { 1016 free((void *)gpu->queue_reqs[i].pQueuePriorities); 1017 } 1018 free(gpu->queue_reqs); 1019 1020 free(gpu->queue_props); 1021 if (CheckExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, gpu->inst->inst_extensions, 1022 gpu->inst->inst_extensions_count)) { 1023 free(gpu->queue_props2); 1024 } 1025} 1026 1027// clang-format off 1028 1029//----------------------------------------------------------- 1030 1031//---------------------------Win32--------------------------- 1032#ifdef VK_USE_PLATFORM_WIN32_KHR 1033 1034// MS-Windows event handling function: 1035LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { 1036 return (DefWindowProc(hWnd, uMsg, wParam, lParam)); 1037} 1038 1039static void AppCreateWin32Window(struct AppInstance *inst) { 1040 inst->h_instance = GetModuleHandle(NULL); 1041 1042 WNDCLASSEX win_class; 1043 1044 // Initialize the window class structure: 1045 win_class.cbSize = sizeof(WNDCLASSEX); 1046 win_class.style = CS_HREDRAW | CS_VREDRAW; 1047 win_class.lpfnWndProc = WndProc; 1048 win_class.cbClsExtra = 0; 1049 win_class.cbWndExtra = 0; 1050 win_class.hInstance = inst->h_instance; 1051 win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION); 1052 win_class.hCursor = LoadCursor(NULL, IDC_ARROW); 1053 win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); 1054 win_class.lpszMenuName = NULL; 1055 win_class.lpszClassName = APP_SHORT_NAME; 1056 win_class.hInstance = inst->h_instance; 1057 win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO); 1058 // Register window class: 1059 if (!RegisterClassEx(&win_class)) { 1060 // It didn't work, so try to give a useful error: 1061 printf("Failed to register the window class!\n"); 1062 fflush(stdout); 1063 exit(1); 1064 } 1065 // Create window with the registered class: 1066 RECT wr = { 0, 0, inst->width, inst->height }; 1067 AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE); 1068 inst->h_wnd = CreateWindowEx(0, 1069 APP_SHORT_NAME, // class name 1070 APP_SHORT_NAME, // app name 1071 //WS_VISIBLE | WS_SYSMENU | 1072 WS_OVERLAPPEDWINDOW, // window style 1073 100, 100, // x/y coords 1074 wr.right - wr.left, // width 1075 wr.bottom - wr.top, // height 1076 NULL, // handle to parent 1077 NULL, // handle to menu 1078 inst->h_instance, // hInstance 1079 NULL); // no extra parameters 1080 if (!inst->h_wnd) { 1081 // It didn't work, so try to give a useful error: 1082 printf("Failed to create a window!\n"); 1083 fflush(stdout); 1084 exit(1); 1085 } 1086} 1087 1088static void AppCreateWin32Surface(struct AppInstance *inst) { 1089 VkResult U_ASSERT_ONLY err; 1090 VkWin32SurfaceCreateInfoKHR createInfo; 1091 createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; 1092 createInfo.pNext = NULL; 1093 createInfo.flags = 0; 1094 createInfo.hinstance = inst->h_instance; 1095 createInfo.hwnd = inst->h_wnd; 1096 err = vkCreateWin32SurfaceKHR(inst->instance, &createInfo, NULL, &inst->surface); 1097 assert(!err); 1098} 1099 1100static void AppDestroyWin32Window(struct AppInstance *inst) { 1101 DestroyWindow(inst->h_wnd); 1102} 1103#endif //VK_USE_PLATFORM_WIN32_KHR 1104//----------------------------------------------------------- 1105 1106#if defined(VK_USE_PLATFORM_XCB_KHR) || \ 1107 defined(VK_USE_PLATFORM_XLIB_KHR) || \ 1108 defined(VK_USE_PLATFORM_WIN32_KHR) 1109static void AppDestroySurface(struct AppInstance *inst) { //same for all platforms 1110 vkDestroySurfaceKHR(inst->instance, inst->surface, NULL); 1111} 1112#endif 1113 1114//----------------------------XCB---------------------------- 1115 1116#ifdef VK_USE_PLATFORM_XCB_KHR 1117static void AppCreateXcbWindow(struct AppInstance *inst) { 1118 //--Init Connection-- 1119 const xcb_setup_t *setup; 1120 xcb_screen_iterator_t iter; 1121 int scr; 1122 1123 inst->xcb_connection = xcb_connect(NULL, &scr); 1124 if (inst->xcb_connection == NULL) { 1125 printf("XCB failed to connect to the X server.\nExiting ...\n"); 1126 fflush(stdout); 1127 exit(1); 1128 } 1129 1130 int conn_error = xcb_connection_has_error(inst->xcb_connection); 1131 if (conn_error) { 1132 printf("XCB failed to connect to the X server due to error:%d.\nExiting ...\n", conn_error); 1133 fflush(stdout); 1134 exit(1); 1135 } 1136 1137 setup = xcb_get_setup(inst->xcb_connection); 1138 iter = xcb_setup_roots_iterator(setup); 1139 while (scr-- > 0) { 1140 xcb_screen_next(&iter); 1141 } 1142 1143 inst->xcb_screen = iter.data; 1144 //------------------- 1145 1146 inst->xcb_window = xcb_generate_id(inst->xcb_connection); 1147 xcb_create_window(inst->xcb_connection, XCB_COPY_FROM_PARENT, inst->xcb_window, 1148 inst->xcb_screen->root, 0, 0, inst->width, inst->height, 0, 1149 XCB_WINDOW_CLASS_INPUT_OUTPUT, inst->xcb_screen->root_visual, 1150 0, NULL); 1151 1152 xcb_intern_atom_cookie_t cookie = xcb_intern_atom(inst->xcb_connection, 1, 12, "WM_PROTOCOLS"); 1153 xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(inst->xcb_connection, cookie, 0); 1154 free(reply); 1155} 1156 1157static void AppCreateXcbSurface(struct AppInstance *inst) { 1158 VkResult U_ASSERT_ONLY err; 1159 VkXcbSurfaceCreateInfoKHR xcb_createInfo; 1160 xcb_createInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR; 1161 xcb_createInfo.pNext = NULL; 1162 xcb_createInfo.flags = 0; 1163 xcb_createInfo.connection = inst->xcb_connection; 1164 xcb_createInfo.window = inst->xcb_window; 1165 err = vkCreateXcbSurfaceKHR(inst->instance, &xcb_createInfo, NULL, &inst->surface); 1166 assert(!err); 1167} 1168 1169static void AppDestroyXcbWindow(struct AppInstance *inst) { 1170 xcb_destroy_window(inst->xcb_connection, inst->xcb_window); 1171 xcb_disconnect(inst->xcb_connection); 1172} 1173//VK_USE_PLATFORM_XCB_KHR 1174//----------------------------------------------------------- 1175 1176//----------------------------XLib--------------------------- 1177#elif VK_USE_PLATFORM_XLIB_KHR 1178static void AppCreateXlibWindow(struct AppInstance *inst) { 1179 long visualMask = VisualScreenMask; 1180 int numberOfVisuals; 1181 1182 inst->xlib_display = XOpenDisplay(NULL); 1183 if (inst->xlib_display == NULL) { 1184 printf("XLib failed to connect to the X server.\nExiting ...\n"); 1185 fflush(stdout); 1186 exit(1); 1187 } 1188 1189 XVisualInfo vInfoTemplate={}; 1190 vInfoTemplate.screen = DefaultScreen(inst->xlib_display); 1191 XVisualInfo *visualInfo = XGetVisualInfo(inst->xlib_display, visualMask, 1192 &vInfoTemplate, &numberOfVisuals); 1193 inst->xlib_window = XCreateWindow( 1194 inst->xlib_display, RootWindow(inst->xlib_display, vInfoTemplate.screen), 0, 0, 1195 inst->width, inst->height, 0, visualInfo->depth, InputOutput, 1196 visualInfo->visual, 0, NULL); 1197 1198 XSync(inst->xlib_display,false); 1199} 1200 1201static void AppCreateXlibSurface(struct AppInstance *inst) { 1202 VkResult U_ASSERT_ONLY err; 1203 VkXlibSurfaceCreateInfoKHR createInfo; 1204 createInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR; 1205 createInfo.pNext = NULL; 1206 createInfo.flags = 0; 1207 createInfo.dpy = inst->xlib_display; 1208 createInfo.window = inst->xlib_window; 1209 err = vkCreateXlibSurfaceKHR(inst->instance, &createInfo, NULL, &inst->surface); 1210 assert(!err); 1211} 1212 1213static void AppDestroyXlibWindow(struct AppInstance *inst) { 1214 XDestroyWindow(inst->xlib_display, inst->xlib_window); 1215 XCloseDisplay(inst->xlib_display); 1216} 1217#endif //VK_USE_PLATFORM_XLIB_KHR 1218//----------------------------------------------------------- 1219 1220#if defined(VK_USE_PLATFORM_XCB_KHR) || \ 1221 defined(VK_USE_PLATFORM_XLIB_KHR) || \ 1222 defined(VK_USE_PLATFORM_WIN32_KHR) 1223static int AppDumpSurfaceFormats(struct AppInstance *inst, struct AppGpu *gpu){ 1224 // Get the list of VkFormat's that are supported: 1225 VkResult U_ASSERT_ONLY err; 1226 uint32_t format_count = 0; 1227 err = inst->vkGetPhysicalDeviceSurfaceFormatsKHR(gpu->obj, inst->surface, &format_count, NULL); 1228 assert(!err); 1229 1230 VkSurfaceFormatKHR *surf_formats = (VkSurfaceFormatKHR *)malloc(format_count * sizeof(VkSurfaceFormatKHR)); 1231 if (!surf_formats) 1232 ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY); 1233 err = inst->vkGetPhysicalDeviceSurfaceFormatsKHR(gpu->obj, inst->surface, &format_count, surf_formats); 1234 assert(!err); 1235 printf("Formats:\t\tcount = %d\n", format_count); 1236 1237 for (uint32_t i = 0; i < format_count; i++) { 1238 printf("\t%s\n", VkFormatString(surf_formats[i].format)); 1239 } 1240 fflush(stdout); 1241 1242 free(surf_formats); 1243 return format_count; 1244} 1245 1246static int AppDumpSurfacePresentModes(struct AppInstance *inst, struct AppGpu *gpu) { 1247 // Get the list of VkPresentMode's that are supported: 1248 VkResult U_ASSERT_ONLY err; 1249 uint32_t present_mode_count = 0; 1250 err = inst->vkGetPhysicalDeviceSurfacePresentModesKHR(gpu->obj, inst->surface, &present_mode_count, NULL); 1251 assert(!err); 1252 1253 VkPresentModeKHR *surf_present_modes = (VkPresentModeKHR *)malloc(present_mode_count * sizeof(VkPresentInfoKHR)); 1254 if (!surf_present_modes) 1255 ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY); 1256 err = inst->vkGetPhysicalDeviceSurfacePresentModesKHR(gpu->obj, inst->surface, &present_mode_count, surf_present_modes); 1257 assert(!err); 1258 printf("Present Modes:\t\tcount = %d\n", present_mode_count); 1259 1260 for (uint32_t i = 0; i < present_mode_count; i++) { 1261 printf("\t%s\n", VkPresentModeString(surf_present_modes[i])); 1262 } 1263 printf("\n"); 1264 fflush(stdout); 1265 1266 free(surf_present_modes); 1267 return present_mode_count; 1268} 1269 1270static void AppDumpSurfaceCapabilities(struct AppInstance *inst, struct AppGpu *gpu) { 1271 if (CheckExtensionEnabled(VK_KHR_SURFACE_EXTENSION_NAME, gpu->inst->inst_extensions, gpu->inst->inst_extensions_count)) { 1272 1273 inst->vkGetPhysicalDeviceSurfaceCapabilitiesKHR(gpu->obj, inst->surface, &inst->surface_capabilities); 1274 1275 printf("\nVkSurfaceCapabilitiesKHR:\n"); 1276 printf("=========================\n\n"); 1277 printf("\tminImageCount = %u\n", inst->surface_capabilities.minImageCount); 1278 printf("\tmaxImageCount = %u\n", inst->surface_capabilities.maxImageCount); 1279 printf("\tcurrentExtent:\n"); 1280 printf("\t\twidth = %u\n", inst->surface_capabilities.currentExtent.width); 1281 printf("\t\theight = %u\n", inst->surface_capabilities.currentExtent.height); 1282 printf("\tminImageExtent:\n"); 1283 printf("\t\twidth = %u\n", inst->surface_capabilities.minImageExtent.width); 1284 printf("\t\theight = %u\n", inst->surface_capabilities.minImageExtent.height); 1285 printf("\tmaxImageExtent:\n"); 1286 printf("\t\twidth = %u\n", inst->surface_capabilities.maxImageExtent.width); 1287 printf("\t\theight = %u\n", inst->surface_capabilities.maxImageExtent.height); 1288 printf("\tmaxImageArrayLayers = %u\n", inst->surface_capabilities.maxImageArrayLayers); 1289 printf("\tsupportedTransform:\n"); 1290 if (inst->surface_capabilities.supportedTransforms == 0) { printf("\t\tNone\n"); } 1291 if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR\n"); } 1292 if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR\n"); } 1293 if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR\n"); } 1294 if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR\n"); } 1295 if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR\n"); } 1296 if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR\n"); } 1297 if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR\n"); } 1298 if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR\n"); } 1299 if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_INHERIT_BIT_KHR\n"); } 1300 printf("\tcurrentTransform:\n"); 1301 if (inst->surface_capabilities.currentTransform == 0) { printf("\t\tNone\n"); } 1302 if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR\n"); } 1303 else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR\n"); } 1304 else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR\n"); } 1305 else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR\n"); } 1306 else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR\n"); } 1307 else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR\n"); } 1308 else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR\n"); } 1309 else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR\n"); } 1310 else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR) { printf("\t\tVK_SURFACE_TRANSFORM_INHERIT_BIT_KHR\n"); } 1311 printf("\tsupportedCompositeAlpha:\n"); 1312 if (inst->surface_capabilities.supportedCompositeAlpha == 0) { printf("\t\tNone\n"); } 1313 if (inst->surface_capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR) { printf("\t\tVK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR\n"); } 1314 if (inst->surface_capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR) { printf("\t\tVK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR\n"); } 1315 if (inst->surface_capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR) { printf("\t\tVK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR\n"); } 1316 if (inst->surface_capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR) { printf("\t\tVK_COMPOSITE_ALPHA_INHERIT_BIT_KHR\n"); } 1317 printf("\tsupportedUsageFlags:\n"); 1318 if (inst->surface_capabilities.supportedUsageFlags == 0) { printf("\t\tNone\n"); } 1319 if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) { printf("\t\tVK_IMAGE_USAGE_TRANSFER_SRC_BIT\n"); } 1320 if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) { printf("\t\tVK_IMAGE_USAGE_TRANSFER_DST_BIT\n"); } 1321 if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) { printf("\t\tVK_IMAGE_USAGE_SAMPLED_BIT\n"); } 1322 if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_STORAGE_BIT) { printf("\t\tVK_IMAGE_USAGE_STORAGE_BIT\n"); } 1323 if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) { printf("\t\tVK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT\n"); } 1324 if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { printf("\t\tVK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT\n"); } 1325 if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) { printf("\t\tVK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT\n"); } 1326 if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) { printf("\t\tVK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT\n"); } 1327 1328 // Get additional surface capability information from vkGetPhysicalDeviceSurfaceCapabilities2EXT 1329 if (CheckExtensionEnabled(VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME, gpu->inst->inst_extensions, gpu->inst->inst_extensions_count)) { 1330 memset(&inst->surface_capabilities2_ext, 0, sizeof(VkSurfaceCapabilities2EXT)); 1331 inst->surface_capabilities2_ext.sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES2_EXT; 1332 inst->surface_capabilities2_ext.pNext = NULL; 1333 1334 inst->vkGetPhysicalDeviceSurfaceCapabilities2EXT(gpu->obj, inst->surface, &inst->surface_capabilities2_ext); 1335 1336 printf("\nVkSurfaceCapabilities2EXT:\n"); 1337 printf("==========================\n\n"); 1338 printf("\tsupportedSurfaceCounters:\n"); 1339 if (inst->surface_capabilities2_ext.supportedSurfaceCounters == 0) { printf("\t\tNone\n"); } 1340 if (inst->surface_capabilities2_ext.supportedSurfaceCounters & VK_SURFACE_COUNTER_VBLANK_EXT) { printf("\t\tVK_SURFACE_COUNTER_VBLANK_EXT\n"); } 1341 } 1342 1343 // Get additional surface capability information from vkGetPhysicalDeviceSurfaceCapabilities2KHR 1344 if (CheckExtensionEnabled(VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME, gpu->inst->inst_extensions, gpu->inst->inst_extensions_count)) { 1345 if (CheckExtensionEnabled(VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME, gpu->inst->inst_extensions, gpu->inst->inst_extensions_count)) { 1346 inst->shared_surface_capabilities.sType = VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR; 1347 inst->shared_surface_capabilities.pNext = NULL; 1348 inst->surface_capabilities2.pNext = &inst->shared_surface_capabilities; 1349 } else { 1350 inst->surface_capabilities2.pNext = NULL; 1351 } 1352 1353 inst->surface_capabilities2.sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR; 1354 1355 VkPhysicalDeviceSurfaceInfo2KHR surface_info; 1356 surface_info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR; 1357 surface_info.pNext = NULL; 1358 surface_info.surface = inst->surface; 1359 1360 inst->vkGetPhysicalDeviceSurfaceCapabilities2KHR(gpu->obj, &surface_info, &inst->surface_capabilities2); 1361 1362 void *place = inst->surface_capabilities2.pNext; 1363 while (place) { 1364 struct VkStructureHeader* work = (struct VkStructureHeader*) place; 1365 if (work->sType == VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR) { 1366 printf("\nVkSharedPresentSurfaceCapabilitiesKHR:\n"); 1367 printf("========================================\n"); 1368 VkSharedPresentSurfaceCapabilitiesKHR* shared_surface_capabilities = (VkSharedPresentSurfaceCapabilitiesKHR*)place; 1369 printf("\tsharedPresentSupportedUsageFlags:\n"); 1370 if (shared_surface_capabilities->sharedPresentSupportedUsageFlags == 0) { printf("\t\tNone\n"); } 1371 if (shared_surface_capabilities->sharedPresentSupportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) { printf("\t\tVK_IMAGE_USAGE_TRANSFER_SRC_BIT\n"); } 1372 if (shared_surface_capabilities->sharedPresentSupportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) { printf("\t\tVK_IMAGE_USAGE_TRANSFER_DST_BIT\n"); } 1373 if (shared_surface_capabilities->sharedPresentSupportedUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) { printf("\t\tVK_IMAGE_USAGE_SAMPLED_BIT\n"); } 1374 if (shared_surface_capabilities->sharedPresentSupportedUsageFlags & VK_IMAGE_USAGE_STORAGE_BIT) { printf("\t\tVK_IMAGE_USAGE_STORAGE_BIT\n"); } 1375 if (shared_surface_capabilities->sharedPresentSupportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) { printf("\t\tVK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT\n"); } 1376 if (shared_surface_capabilities->sharedPresentSupportedUsageFlags & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { printf("\t\tVK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT\n"); } 1377 if (shared_surface_capabilities->sharedPresentSupportedUsageFlags & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) { printf("\t\tVK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT\n"); } 1378 if (shared_surface_capabilities->sharedPresentSupportedUsageFlags & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) { printf("\t\tVK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT\n"); } 1379 } 1380 1381 place = work->pNext; 1382 } 1383 } 1384 } 1385} 1386 1387#endif 1388 1389static void AppDevDumpFormatProps(const struct AppDev *dev, VkFormat fmt) 1390{ 1391 const VkFormatProperties *props = &dev->format_props[fmt]; 1392 struct { 1393 const char *name; 1394 VkFlags flags; 1395 } features[3]; 1396 1397 features[0].name = "linearTiling FormatFeatureFlags"; 1398 features[0].flags = props->linearTilingFeatures; 1399 features[1].name = "optimalTiling FormatFeatureFlags"; 1400 features[1].flags = props->optimalTilingFeatures; 1401 features[2].name = "bufferFeatures FormatFeatureFlags"; 1402 features[2].flags = props->bufferFeatures; 1403 1404 printf("\nFORMAT_%s:", VkFormatString(fmt)); 1405 for (uint32_t i = 0; i < ARRAY_SIZE(features); i++) { 1406 printf("\n\t%s:", features[i].name); 1407 if (features[i].flags == 0) { 1408 printf("\n\t\tNone"); 1409 } else { 1410 printf("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", 1411 ((features[i].flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) ? "\n\t\tVK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT" : ""), //0x0001 1412 ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) ? "\n\t\tVK_FORMAT_FEATURE_STORAGE_IMAGE_BIT" : ""), //0x0002 1413 ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT) ? "\n\t\tVK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT" : ""), //0x0004 1414 ((features[i].flags & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT) ? "\n\t\tVK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT" : ""), //0x0008 1415 ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT) ? "\n\t\tVK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT" : ""), //0x0010 1416 ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT) ? "\n\t\tVK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT" : ""), //0x0020 1417 ((features[i].flags & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) ? "\n\t\tVK_FORMAT_FEATURE_VERTEX_BUFFER_BIT" : ""), //0x0040 1418 ((features[i].flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) ? "\n\t\tVK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT" : ""), //0x0080 1419 ((features[i].flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT) ? "\n\t\tVK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT" : ""), //0x0100 1420 ((features[i].flags & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) ? "\n\t\tVK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT" : ""), //0x0200 1421 ((features[i].flags & VK_FORMAT_FEATURE_BLIT_SRC_BIT) ? "\n\t\tVK_FORMAT_FEATURE_BLIT_SRC_BIT" : ""), //0x0400 1422 ((features[i].flags & VK_FORMAT_FEATURE_BLIT_DST_BIT) ? "\n\t\tVK_FORMAT_FEATURE_BLIT_DST_BIT" : ""), //0x0800 1423 ((features[i].flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT) ? "\n\t\tVK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT" : ""), //0x1000 1424 ((features[i].flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG) ? "\n\t\tVK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG" : ""), //0x2000 1425 ((features[i].flags & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR) ? "\n\t\tVK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR" : ""), //0x4000 1426 ((features[i].flags & VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR) ? "\n\t\tVK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR" : "")); //0x8000 1427 } 1428 } 1429 printf("\n"); 1430} 1431 1432static void 1433AppDevDump(const struct AppDev *dev) 1434{ 1435 printf("Format Properties:\n"); 1436 printf("=================="); 1437 VkFormat fmt; 1438 1439 for (fmt = 0; fmt < VK_FORMAT_RANGE_SIZE; fmt++) { 1440 AppDevDumpFormatProps(dev, fmt); 1441 } 1442} 1443 1444#ifdef _WIN32 1445#define PRINTF_SIZE_T_SPECIFIER "%Iu" 1446#else 1447#define PRINTF_SIZE_T_SPECIFIER "%zu" 1448#endif 1449 1450static void AppGpuDumpFeatures(const struct AppGpu *gpu) 1451{ 1452 const VkPhysicalDeviceFeatures *features = &gpu->features; 1453 1454 printf("VkPhysicalDeviceFeatures:\n"); 1455 printf("=========================\n"); 1456 1457 printf("\trobustBufferAccess = %u\n", features->robustBufferAccess ); 1458 printf("\tfullDrawIndexUint32 = %u\n", features->fullDrawIndexUint32 ); 1459 printf("\timageCubeArray = %u\n", features->imageCubeArray ); 1460 printf("\tindependentBlend = %u\n", features->independentBlend ); 1461 printf("\tgeometryShader = %u\n", features->geometryShader ); 1462 printf("\ttessellationShader = %u\n", features->tessellationShader ); 1463 printf("\tsampleRateShading = %u\n", features->sampleRateShading ); 1464 printf("\tdualSrcBlend = %u\n", features->dualSrcBlend ); 1465 printf("\tlogicOp = %u\n", features->logicOp ); 1466 printf("\tmultiDrawIndirect = %u\n", features->multiDrawIndirect ); 1467 printf("\tdrawIndirectFirstInstance = %u\n", features->drawIndirectFirstInstance ); 1468 printf("\tdepthClamp = %u\n", features->depthClamp ); 1469 printf("\tdepthBiasClamp = %u\n", features->depthBiasClamp ); 1470 printf("\tfillModeNonSolid = %u\n", features->fillModeNonSolid ); 1471 printf("\tdepthBounds = %u\n", features->depthBounds ); 1472 printf("\twideLines = %u\n", features->wideLines ); 1473 printf("\tlargePoints = %u\n", features->largePoints ); 1474 printf("\talphaToOne = %u\n", features->alphaToOne ); 1475 printf("\tmultiViewport = %u\n", features->multiViewport ); 1476 printf("\tsamplerAnisotropy = %u\n", features->samplerAnisotropy ); 1477 printf("\ttextureCompressionETC2 = %u\n", features->textureCompressionETC2 ); 1478 printf("\ttextureCompressionASTC_LDR = %u\n", features->textureCompressionASTC_LDR ); 1479 printf("\ttextureCompressionBC = %u\n", features->textureCompressionBC ); 1480 printf("\tocclusionQueryPrecise = %u\n", features->occlusionQueryPrecise ); 1481 printf("\tpipelineStatisticsQuery = %u\n", features->pipelineStatisticsQuery ); 1482 printf("\tvertexPipelineStoresAndAtomics = %u\n", features->vertexPipelineStoresAndAtomics ); 1483 printf("\tfragmentStoresAndAtomics = %u\n", features->fragmentStoresAndAtomics ); 1484 printf("\tshaderTessellationAndGeometryPointSize = %u\n", features->shaderTessellationAndGeometryPointSize ); 1485 printf("\tshaderImageGatherExtended = %u\n", features->shaderImageGatherExtended ); 1486 printf("\tshaderStorageImageExtendedFormats = %u\n", features->shaderStorageImageExtendedFormats ); 1487 printf("\tshaderStorageImageMultisample = %u\n", features->shaderStorageImageMultisample ); 1488 printf("\tshaderStorageImageReadWithoutFormat = %u\n", features->shaderStorageImageReadWithoutFormat ); 1489 printf("\tshaderStorageImageWriteWithoutFormat = %u\n", features->shaderStorageImageWriteWithoutFormat ); 1490 printf("\tshaderUniformBufferArrayDynamicIndexing = %u\n", features->shaderUniformBufferArrayDynamicIndexing); 1491 printf("\tshaderSampledImageArrayDynamicIndexing = %u\n", features->shaderSampledImageArrayDynamicIndexing ); 1492 printf("\tshaderStorageBufferArrayDynamicIndexing = %u\n", features->shaderStorageBufferArrayDynamicIndexing); 1493 printf("\tshaderStorageImageArrayDynamicIndexing = %u\n", features->shaderStorageImageArrayDynamicIndexing ); 1494 printf("\tshaderClipDistance = %u\n", features->shaderClipDistance ); 1495 printf("\tshaderCullDistance = %u\n", features->shaderCullDistance ); 1496 printf("\tshaderFloat64 = %u\n", features->shaderFloat64 ); 1497 printf("\tshaderInt64 = %u\n", features->shaderInt64 ); 1498 printf("\tshaderInt16 = %u\n", features->shaderInt16 ); 1499 printf("\tshaderResourceResidency = %u\n", features->shaderResourceResidency ); 1500 printf("\tshaderResourceMinLod = %u\n", features->shaderResourceMinLod ); 1501 printf("\tsparseBinding = %u\n", features->sparseBinding ); 1502 printf("\tsparseResidencyBuffer = %u\n", features->sparseResidencyBuffer ); 1503 printf("\tsparseResidencyImage2D = %u\n", features->sparseResidencyImage2D ); 1504 printf("\tsparseResidencyImage3D = %u\n", features->sparseResidencyImage3D ); 1505 printf("\tsparseResidency2Samples = %u\n", features->sparseResidency2Samples ); 1506 printf("\tsparseResidency4Samples = %u\n", features->sparseResidency4Samples ); 1507 printf("\tsparseResidency8Samples = %u\n", features->sparseResidency8Samples ); 1508 printf("\tsparseResidency16Samples = %u\n", features->sparseResidency16Samples ); 1509 printf("\tsparseResidencyAliased = %u\n", features->sparseResidencyAliased ); 1510 printf("\tvariableMultisampleRate = %u\n", features->variableMultisampleRate ); 1511 printf("\tinheritedQueries = %u\n", features->inheritedQueries ); 1512} 1513 1514static void AppDumpSparseProps(const VkPhysicalDeviceSparseProperties *sparse_props) 1515{ 1516 1517 printf("\tVkPhysicalDeviceSparseProperties:\n"); 1518 printf("\t---------------------------------\n"); 1519 1520 printf("\t\tresidencyStandard2DBlockShape = %u\n", sparse_props->residencyStandard2DBlockShape ); 1521 printf("\t\tresidencyStandard2DMultisampleBlockShape = %u\n", sparse_props->residencyStandard2DMultisampleBlockShape); 1522 printf("\t\tresidencyStandard3DBlockShape = %u\n", sparse_props->residencyStandard3DBlockShape ); 1523 printf("\t\tresidencyAlignedMipSize = %u\n", sparse_props->residencyAlignedMipSize ); 1524 printf("\t\tresidencyNonResidentStrict = %u\n", sparse_props->residencyNonResidentStrict ); 1525} 1526 1527static void AppDumpLimits(const VkPhysicalDeviceLimits *limits) 1528{ 1529 printf("\tVkPhysicalDeviceLimits:\n"); 1530 printf("\t-----------------------\n"); 1531 printf("\t\tmaxImageDimension1D = %u\n", limits->maxImageDimension1D ); 1532 printf("\t\tmaxImageDimension2D = %u\n", limits->maxImageDimension2D ); 1533 printf("\t\tmaxImageDimension3D = %u\n", limits->maxImageDimension3D ); 1534 printf("\t\tmaxImageDimensionCube = %u\n", limits->maxImageDimensionCube ); 1535 printf("\t\tmaxImageArrayLayers = %u\n", limits->maxImageArrayLayers ); 1536 printf("\t\tmaxTexelBufferElements = 0x%" PRIxLEAST32 "\n", limits->maxTexelBufferElements ); 1537 printf("\t\tmaxUniformBufferRange = 0x%" PRIxLEAST32 "\n", limits->maxUniformBufferRange ); 1538 printf("\t\tmaxStorageBufferRange = 0x%" PRIxLEAST32 "\n", limits->maxStorageBufferRange ); 1539 printf("\t\tmaxPushConstantsSize = %u\n", limits->maxPushConstantsSize ); 1540 printf("\t\tmaxMemoryAllocationCount = %u\n", limits->maxMemoryAllocationCount ); 1541 printf("\t\tmaxSamplerAllocationCount = %u\n", limits->maxSamplerAllocationCount ); 1542 printf("\t\tbufferImageGranularity = 0x%" PRIxLEAST64 "\n", limits->bufferImageGranularity ); 1543 printf("\t\tsparseAddressSpaceSize = 0x%" PRIxLEAST64 "\n", limits->sparseAddressSpaceSize ); 1544 printf("\t\tmaxBoundDescriptorSets = %u\n", limits->maxBoundDescriptorSets ); 1545 printf("\t\tmaxPerStageDescriptorSamplers = %u\n", limits->maxPerStageDescriptorSamplers ); 1546 printf("\t\tmaxPerStageDescriptorUniformBuffers = %u\n", limits->maxPerStageDescriptorUniformBuffers ); 1547 printf("\t\tmaxPerStageDescriptorStorageBuffers = %u\n", limits->maxPerStageDescriptorStorageBuffers ); 1548 printf("\t\tmaxPerStageDescriptorSampledImages = %u\n", limits->maxPerStageDescriptorSampledImages ); 1549 printf("\t\tmaxPerStageDescriptorStorageImages = %u\n", limits->maxPerStageDescriptorStorageImages ); 1550 printf("\t\tmaxPerStageDescriptorInputAttachments = %u\n", limits->maxPerStageDescriptorInputAttachments ); 1551 printf("\t\tmaxPerStageResources = %u\n", limits->maxPerStageResources ); 1552 printf("\t\tmaxDescriptorSetSamplers = %u\n", limits->maxDescriptorSetSamplers ); 1553 printf("\t\tmaxDescriptorSetUniformBuffers = %u\n", limits->maxDescriptorSetUniformBuffers ); 1554 printf("\t\tmaxDescriptorSetUniformBuffersDynamic = %u\n", limits->maxDescriptorSetUniformBuffersDynamic ); 1555 printf("\t\tmaxDescriptorSetStorageBuffers = %u\n", limits->maxDescriptorSetStorageBuffers ); 1556 printf("\t\tmaxDescriptorSetStorageBuffersDynamic = %u\n", limits->maxDescriptorSetStorageBuffersDynamic ); 1557 printf("\t\tmaxDescriptorSetSampledImages = %u\n", limits->maxDescriptorSetSampledImages ); 1558 printf("\t\tmaxDescriptorSetStorageImages = %u\n", limits->maxDescriptorSetStorageImages ); 1559 printf("\t\tmaxDescriptorSetInputAttachments = %u\n", limits->maxDescriptorSetInputAttachments ); 1560 printf("\t\tmaxVertexInputAttributes = %u\n", limits->maxVertexInputAttributes ); 1561 printf("\t\tmaxVertexInputBindings = %u\n", limits->maxVertexInputBindings ); 1562 printf("\t\tmaxVertexInputAttributeOffset = 0x%" PRIxLEAST32 "\n", limits->maxVertexInputAttributeOffset ); 1563 printf("\t\tmaxVertexInputBindingStride = 0x%" PRIxLEAST32 "\n", limits->maxVertexInputBindingStride ); 1564 printf("\t\tmaxVertexOutputComponents = %u\n", limits->maxVertexOutputComponents ); 1565 printf("\t\tmaxTessellationGenerationLevel = %u\n", limits->maxTessellationGenerationLevel ); 1566 printf("\t\tmaxTessellationPatchSize = %u\n", limits->maxTessellationPatchSize ); 1567 printf("\t\tmaxTessellationControlPerVertexInputComponents = %u\n", limits->maxTessellationControlPerVertexInputComponents ); 1568 printf("\t\tmaxTessellationControlPerVertexOutputComponents = %u\n", limits->maxTessellationControlPerVertexOutputComponents); 1569 printf("\t\tmaxTessellationControlPerPatchOutputComponents = %u\n", limits->maxTessellationControlPerPatchOutputComponents ); 1570 printf("\t\tmaxTessellationControlTotalOutputComponents = %u\n", limits->maxTessellationControlTotalOutputComponents ); 1571 printf("\t\tmaxTessellationEvaluationInputComponents = %u\n", limits->maxTessellationEvaluationInputComponents ); 1572 printf("\t\tmaxTessellationEvaluationOutputComponents = %u\n", limits->maxTessellationEvaluationOutputComponents ); 1573 printf("\t\tmaxGeometryShaderInvocations = %u\n", limits->maxGeometryShaderInvocations ); 1574 printf("\t\tmaxGeometryInputComponents = %u\n", limits->maxGeometryInputComponents ); 1575 printf("\t\tmaxGeometryOutputComponents = %u\n", limits->maxGeometryOutputComponents ); 1576 printf("\t\tmaxGeometryOutputVertices = %u\n", limits->maxGeometryOutputVertices ); 1577 printf("\t\tmaxGeometryTotalOutputComponents = %u\n", limits->maxGeometryTotalOutputComponents ); 1578 printf("\t\tmaxFragmentInputComponents = %u\n", limits->maxFragmentInputComponents ); 1579 printf("\t\tmaxFragmentOutputAttachments = %u\n", limits->maxFragmentOutputAttachments ); 1580 printf("\t\tmaxFragmentDualSrcAttachments = %u\n", limits->maxFragmentDualSrcAttachments ); 1581 printf("\t\tmaxFragmentCombinedOutputResources = %u\n", limits->maxFragmentCombinedOutputResources ); 1582 printf("\t\tmaxComputeSharedMemorySize = 0x%" PRIxLEAST32 "\n", limits->maxComputeSharedMemorySize ); 1583 printf("\t\tmaxComputeWorkGroupCount[0] = %u\n", limits->maxComputeWorkGroupCount[0] ); 1584 printf("\t\tmaxComputeWorkGroupCount[1] = %u\n", limits->maxComputeWorkGroupCount[1] ); 1585 printf("\t\tmaxComputeWorkGroupCount[2] = %u\n", limits->maxComputeWorkGroupCount[2] ); 1586 printf("\t\tmaxComputeWorkGroupInvocations = %u\n", limits->maxComputeWorkGroupInvocations ); 1587 printf("\t\tmaxComputeWorkGroupSize[0] = %u\n", limits->maxComputeWorkGroupSize[0] ); 1588 printf("\t\tmaxComputeWorkGroupSize[1] = %u\n", limits->maxComputeWorkGroupSize[1] ); 1589 printf("\t\tmaxComputeWorkGroupSize[2] = %u\n", limits->maxComputeWorkGroupSize[2] ); 1590 printf("\t\tsubPixelPrecisionBits = %u\n", limits->subPixelPrecisionBits ); 1591 printf("\t\tsubTexelPrecisionBits = %u\n", limits->subTexelPrecisionBits ); 1592 printf("\t\tmipmapPrecisionBits = %u\n", limits->mipmapPrecisionBits ); 1593 printf("\t\tmaxDrawIndexedIndexValue = %u\n", limits->maxDrawIndexedIndexValue ); 1594 printf("\t\tmaxDrawIndirectCount = %u\n", limits->maxDrawIndirectCount ); 1595 printf("\t\tmaxSamplerLodBias = %f\n", limits->maxSamplerLodBias ); 1596 printf("\t\tmaxSamplerAnisotropy = %f\n", limits->maxSamplerAnisotropy ); 1597 printf("\t\tmaxViewports = %u\n", limits->maxViewports ); 1598 printf("\t\tmaxViewportDimensions[0] = %u\n", limits->maxViewportDimensions[0] ); 1599 printf("\t\tmaxViewportDimensions[1] = %u\n", limits->maxViewportDimensions[1] ); 1600 printf("\t\tviewportBoundsRange[0] =%13f\n", limits->viewportBoundsRange[0] ); 1601 printf("\t\tviewportBoundsRange[1] =%13f\n", limits->viewportBoundsRange[1] ); 1602 printf("\t\tviewportSubPixelBits = %u\n", limits->viewportSubPixelBits ); 1603 printf("\t\tminMemoryMapAlignment = " PRINTF_SIZE_T_SPECIFIER "\n", limits->minMemoryMapAlignment ); 1604 printf("\t\tminTexelBufferOffsetAlignment = 0x%" PRIxLEAST64 "\n", limits->minTexelBufferOffsetAlignment ); 1605 printf("\t\tminUniformBufferOffsetAlignment = 0x%" PRIxLEAST64 "\n", limits->minUniformBufferOffsetAlignment ); 1606 printf("\t\tminStorageBufferOffsetAlignment = 0x%" PRIxLEAST64 "\n", limits->minStorageBufferOffsetAlignment ); 1607 printf("\t\tminTexelOffset =%3d\n", limits->minTexelOffset ); 1608 printf("\t\tmaxTexelOffset =%3d\n", limits->maxTexelOffset ); 1609 printf("\t\tminTexelGatherOffset =%3d\n", limits->minTexelGatherOffset ); 1610 printf("\t\tmaxTexelGatherOffset =%3d\n", limits->maxTexelGatherOffset ); 1611 printf("\t\tminInterpolationOffset =%9f\n", limits->minInterpolationOffset ); 1612 printf("\t\tmaxInterpolationOffset =%9f\n", limits->maxInterpolationOffset ); 1613 printf("\t\tsubPixelInterpolationOffsetBits = %u\n", limits->subPixelInterpolationOffsetBits ); 1614 printf("\t\tmaxFramebufferWidth = %u\n", limits->maxFramebufferWidth ); 1615 printf("\t\tmaxFramebufferHeight = %u\n", limits->maxFramebufferHeight ); 1616 printf("\t\tmaxFramebufferLayers = %u\n", limits->maxFramebufferLayers ); 1617 printf("\t\tframebufferColorSampleCounts = %u\n", limits->framebufferColorSampleCounts ); 1618 printf("\t\tframebufferDepthSampleCounts = %u\n", limits->framebufferDepthSampleCounts ); 1619 printf("\t\tframebufferStencilSampleCounts = %u\n", limits->framebufferStencilSampleCounts ); 1620 printf("\t\tframebufferNoAttachmentsSampleCounts = %u\n", limits->framebufferNoAttachmentsSampleCounts ); 1621 printf("\t\tmaxColorAttachments = %u\n", limits->maxColorAttachments ); 1622 printf("\t\tsampledImageColorSampleCounts = %u\n", limits->sampledImageColorSampleCounts ); 1623 printf("\t\tsampledImageDepthSampleCounts = %u\n", limits->sampledImageDepthSampleCounts ); 1624 printf("\t\tsampledImageStencilSampleCounts = %u\n", limits->sampledImageStencilSampleCounts ); 1625 printf("\t\tsampledImageIntegerSampleCounts = %u\n", limits->sampledImageIntegerSampleCounts ); 1626 printf("\t\tstorageImageSampleCounts = %u\n", limits->storageImageSampleCounts ); 1627 printf("\t\tmaxSampleMaskWords = %u\n", limits->maxSampleMaskWords ); 1628 printf("\t\ttimestampComputeAndGraphics = %u\n", limits->timestampComputeAndGraphics ); 1629 printf("\t\ttimestampPeriod = %f\n", limits->timestampPeriod ); 1630 printf("\t\tmaxClipDistances = %u\n", limits->maxClipDistances ); 1631 printf("\t\tmaxCullDistances = %u\n", limits->maxCullDistances ); 1632 printf("\t\tmaxCombinedClipAndCullDistances = %u\n", limits->maxCombinedClipAndCullDistances ); 1633 printf("\t\tdiscreteQueuePriorities = %u\n", limits->discreteQueuePriorities ); 1634 printf("\t\tpointSizeRange[0] = %f\n", limits->pointSizeRange[0] ); 1635 printf("\t\tpointSizeRange[1] = %f\n", limits->pointSizeRange[1] ); 1636 printf("\t\tlineWidthRange[0] = %f\n", limits->lineWidthRange[0] ); 1637 printf("\t\tlineWidthRange[1] = %f\n", limits->lineWidthRange[1] ); 1638 printf("\t\tpointSizeGranularity = %f\n", limits->pointSizeGranularity ); 1639 printf("\t\tlineWidthGranularity = %f\n", limits->lineWidthGranularity ); 1640 printf("\t\tstrictLines = %u\n", limits->strictLines ); 1641 printf("\t\tstandardSampleLocations = %u\n", limits->standardSampleLocations ); 1642 printf("\t\toptimalBufferCopyOffsetAlignment = 0x%" PRIxLEAST64 "\n", limits->optimalBufferCopyOffsetAlignment ); 1643 printf("\t\toptimalBufferCopyRowPitchAlignment = 0x%" PRIxLEAST64 "\n", limits->optimalBufferCopyRowPitchAlignment ); 1644 printf("\t\tnonCoherentAtomSize = 0x%" PRIxLEAST64 "\n", limits->nonCoherentAtomSize ); 1645} 1646 1647static void AppGpuDumpProps(const struct AppGpu *gpu) 1648{ 1649 const VkPhysicalDeviceProperties *props = &gpu->props; 1650 const uint32_t apiVersion=props->apiVersion; 1651 const uint32_t major = VK_VERSION_MAJOR(apiVersion); 1652 const uint32_t minor = VK_VERSION_MINOR(apiVersion); 1653 const uint32_t patch = VK_VERSION_PATCH(apiVersion); 1654 1655 printf("VkPhysicalDeviceProperties:\n"); 1656 printf("===========================\n"); 1657 printf("\tapiVersion = 0x%" PRIxLEAST32 " (%d.%d.%d)\n", apiVersion, major, minor, patch); 1658 printf("\tdriverVersion = %u (0x%" PRIxLEAST32 ")\n",props->driverVersion, props->driverVersion); 1659 printf("\tvendorID = 0x%04x\n", props->vendorID); 1660 printf("\tdeviceID = 0x%04x\n", props->deviceID); 1661 printf("\tdeviceType = %s\n", VkPhysicalDeviceTypeString(props->deviceType)); 1662 printf("\tdeviceName = %s\n", props->deviceName); 1663 1664 AppDumpLimits(&gpu->props.limits); 1665 AppDumpSparseProps(&gpu->props.sparseProperties); 1666 1667 fflush(stdout); 1668} 1669// clang-format on 1670 1671static void AppDumpExtensions(const char *indent, const char *layer_name, const uint32_t extension_count, 1672 const VkExtensionProperties *extension_properties) { 1673 uint32_t i; 1674 if (layer_name && (strlen(layer_name) > 0)) { 1675 printf("%s%s Extensions", indent, layer_name); 1676 } else { 1677 printf("%sExtensions", indent); 1678 } 1679 printf("\tcount = %d\n", extension_count); 1680 for (i = 0; i < extension_count; i++) { 1681 VkExtensionProperties const *ext_prop = &extension_properties[i]; 1682 1683 printf("%s\t", indent); 1684 printf("%-36s: extension revision %2d\n", ext_prop->extensionName, ext_prop->specVersion); 1685 } 1686 fflush(stdout); 1687} 1688 1689static void AppGpuDumpQueueProps(const struct AppGpu *gpu, uint32_t id) { 1690 const VkQueueFamilyProperties *props = &gpu->queue_props[id]; 1691 1692 printf("VkQueueFamilyProperties[%d]:\n", id); 1693 printf("===========================\n"); 1694 char *sep = ""; // separator character 1695 printf("\tqueueFlags = "); 1696 if (props->queueFlags & VK_QUEUE_GRAPHICS_BIT) { 1697 printf("GRAPHICS"); 1698 sep = " | "; 1699 } 1700 if (props->queueFlags & VK_QUEUE_COMPUTE_BIT) { 1701 printf("%sCOMPUTE", sep); 1702 sep = " | "; 1703 } 1704 if (props->queueFlags & VK_QUEUE_TRANSFER_BIT) { 1705 printf("%sTRANSFER", sep); 1706 sep = " | "; 1707 } 1708 if (props->queueFlags & VK_QUEUE_SPARSE_BINDING_BIT) { 1709 printf("%sSPARSE", sep); 1710 } 1711 printf("\n"); 1712 1713 printf("\tqueueCount = %u\n", props->queueCount); 1714 printf("\ttimestampValidBits = %u\n", props->timestampValidBits); 1715 printf("\tminImageTransferGranularity = (%d, %d, %d)\n", props->minImageTransferGranularity.width, 1716 props->minImageTransferGranularity.height, props->minImageTransferGranularity.depth); 1717 fflush(stdout); 1718} 1719 1720// This prints a number of bytes in a human-readable format according to prefixes of the International System of Quantities (ISQ), 1721// defined in ISO/IEC 80000. The prefixes used here are not SI prefixes, but rather the binary prefixes based on powers of 1024 1722// (kibi-, mebi-, gibi- etc.). 1723#define kBufferSize 32 1724 1725static char *HumanReadable(const size_t sz) { 1726 const char prefixes[] = "KMGTPEZY"; 1727 char buf[kBufferSize]; 1728 int which = -1; 1729 double result = (double)sz; 1730 while (result > 1024 && which < 7) { 1731 result /= 1024; 1732 ++which; 1733 } 1734 1735 char unit[] = "\0i"; 1736 if (which >= 0) { 1737 unit[0] = prefixes[which]; 1738 } 1739 snprintf(buf, kBufferSize, "%.2f %sB", result, unit); 1740 return strndup(buf, kBufferSize); 1741} 1742 1743static void AppGpuDumpMemoryProps(const struct AppGpu *gpu) { 1744 const VkPhysicalDeviceMemoryProperties *props = &gpu->memory_props; 1745 1746 printf("VkPhysicalDeviceMemoryProperties:\n"); 1747 printf("=================================\n"); 1748 printf("\tmemoryTypeCount = %u\n", props->memoryTypeCount); 1749 for (uint32_t i = 0; i < props->memoryTypeCount; i++) { 1750 printf("\tmemoryTypes[%u] :\n", i); 1751 printf("\t\theapIndex = %u\n", props->memoryTypes[i].heapIndex); 1752 printf("\t\tpropertyFlags = 0x%" PRIxLEAST32 ":\n", props->memoryTypes[i].propertyFlags); 1753 1754 // Print each named flag, if it is set. 1755 VkFlags flags = props->memoryTypes[i].propertyFlags; 1756#define PRINT_FLAG(FLAG) \ 1757 if (flags & FLAG) printf("\t\t\t" #FLAG "\n"); 1758 PRINT_FLAG(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) 1759 PRINT_FLAG(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) 1760 PRINT_FLAG(VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) 1761 PRINT_FLAG(VK_MEMORY_PROPERTY_HOST_CACHED_BIT) 1762 PRINT_FLAG(VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) 1763#undef PRINT_FLAG 1764 } 1765 printf("\n"); 1766 printf("\tmemoryHeapCount = %u\n", props->memoryHeapCount); 1767 for (uint32_t i = 0; i < props->memoryHeapCount; i++) { 1768 printf("\tmemoryHeaps[%u] :\n", i); 1769 const VkDeviceSize memSize = props->memoryHeaps[i].size; 1770 char *mem_size_human_readable = HumanReadable((const size_t)memSize); 1771 printf("\t\tsize = " PRINTF_SIZE_T_SPECIFIER " (0x%" PRIxLEAST64 ") (%s)\n", (size_t)memSize, memSize, 1772 mem_size_human_readable); 1773 free(mem_size_human_readable); 1774 1775 VkMemoryHeapFlags heap_flags = props->memoryHeaps[i].flags; 1776 printf("\t\tflags:\n\t\t\t"); 1777 printf((heap_flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) ? "VK_MEMORY_HEAP_DEVICE_LOCAL_BIT\n" : "None\n"); 1778 } 1779 fflush(stdout); 1780} 1781 1782static void AppGpuDump(const struct AppGpu *gpu) { 1783 uint32_t i; 1784 1785 printf("\nDevice Properties and Extensions :\n"); 1786 printf("==================================\n"); 1787 printf("GPU%u\n", gpu->id); 1788 AppGpuDumpProps(gpu); 1789 printf("\n"); 1790 AppDumpExtensions("", "Device", gpu->device_extension_count, gpu->device_extensions); 1791 printf("\n"); 1792 for (i = 0; i < gpu->queue_count; i++) { 1793 AppGpuDumpQueueProps(gpu, i); 1794 printf("\n"); 1795 } 1796 AppGpuDumpMemoryProps(gpu); 1797 printf("\n"); 1798 AppGpuDumpFeatures(gpu); 1799 printf("\n"); 1800 AppDevDump(&gpu->dev); 1801} 1802 1803#ifdef _WIN32 1804// Enlarges the console window to have a large scrollback size. 1805static void ConsoleEnlarge() { 1806 HANDLE console_handle = GetStdHandle(STD_OUTPUT_HANDLE); 1807 1808 // make the console window bigger 1809 CONSOLE_SCREEN_BUFFER_INFO csbi; 1810 COORD buffer_size; 1811 if (GetConsoleScreenBufferInfo(console_handle, &csbi)) { 1812 buffer_size.X = csbi.dwSize.X + 30; 1813 buffer_size.Y = 20000; 1814 SetConsoleScreenBufferSize(console_handle, buffer_size); 1815 } 1816 1817 SMALL_RECT r; 1818 r.Left = r.Top = 0; 1819 r.Right = csbi.dwSize.X - 1 + 30; 1820 r.Bottom = 50; 1821 SetConsoleWindowInfo(console_handle, true, &r); 1822 1823 // change the console window title 1824 SetConsoleTitle(TEXT(APP_SHORT_NAME)); 1825} 1826#endif 1827 1828int main(int argc, char **argv) { 1829 uint32_t vulkan_major, vulkan_minor, vulkan_patch; 1830 struct AppGpu *gpus; 1831 VkPhysicalDevice *objs; 1832 uint32_t gpu_count; 1833 VkResult err; 1834 struct AppInstance inst; 1835 1836#ifdef _WIN32 1837 if (ConsoleIsExclusive()) ConsoleEnlarge(); 1838#endif 1839 1840 vulkan_major = VK_VERSION_MAJOR(VK_API_VERSION_1_0); 1841 vulkan_minor = VK_VERSION_MINOR(VK_API_VERSION_1_0); 1842 vulkan_patch = VK_VERSION_PATCH(VK_HEADER_VERSION); 1843 1844 printf("===========\n"); 1845 printf("VULKAN INFO\n"); 1846 printf("===========\n\n"); 1847 printf("Vulkan API Version: %d.%d.%d\n\n", vulkan_major, vulkan_minor, vulkan_patch); 1848 1849 AppCreateInstance(&inst); 1850 1851 printf("\nInstance Extensions:\n"); 1852 printf("====================\n"); 1853 AppDumpExtensions("", "Instance", inst.global_extension_count, inst.global_extensions); 1854 1855 err = vkEnumeratePhysicalDevices(inst.instance, &gpu_count, NULL); 1856 if (err) ERR_EXIT(err); 1857 objs = malloc(sizeof(objs[0]) * gpu_count); 1858 if (!objs) ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY); 1859 err = vkEnumeratePhysicalDevices(inst.instance, &gpu_count, objs); 1860 if (err) ERR_EXIT(err); 1861 1862 gpus = malloc(sizeof(gpus[0]) * gpu_count); 1863 if (!gpus) ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY); 1864 for (uint32_t i = 0; i < gpu_count; i++) { 1865 AppGpuInit(&gpus[i], &inst, i, objs[i]); 1866 printf("\n\n"); 1867 } 1868 1869 //---Layer-Device-Extensions--- 1870 printf("Layers: count = %d\n", inst.global_layer_count); 1871 printf("=======\n"); 1872 for (uint32_t i = 0; i < inst.global_layer_count; i++) { 1873 uint32_t layer_major, layer_minor, layer_patch; 1874 char spec_version[64], layer_version[64]; 1875 VkLayerProperties const *layer_prop = &inst.global_layers[i].layer_properties; 1876 1877 ExtractVersion(layer_prop->specVersion, &layer_major, &layer_minor, &layer_patch); 1878 snprintf(spec_version, sizeof(spec_version), "%d.%d.%d", layer_major, layer_minor, layer_patch); 1879 snprintf(layer_version, sizeof(layer_version), "%d", layer_prop->implementationVersion); 1880 printf("%s (%s) Vulkan version %s, layer version %s\n", layer_prop->layerName, (char *)layer_prop->description, 1881 spec_version, layer_version); 1882 1883 AppDumpExtensions("\t", "Layer", inst.global_layers[i].extension_count, inst.global_layers[i].extension_properties); 1884 1885 char *layer_name = inst.global_layers[i].layer_properties.layerName; 1886 printf("\tDevices \tcount = %d\n", gpu_count); 1887 for (uint32_t j = 0; j < gpu_count; j++) { 1888 printf("\t\tGPU id : %u (%s)\n", j, gpus[j].props.deviceName); 1889 uint32_t count = 0; 1890 VkExtensionProperties *props; 1891 AppGetPhysicalDeviceLayerExtensions(&gpus[j], layer_name, &count, &props); 1892 AppDumpExtensions("\t\t", "Layer-Device", count, props); 1893 free(props); 1894 } 1895 printf("\n"); 1896 } 1897 fflush(stdout); 1898 //----------------------------- 1899 1900 printf("Presentable Surfaces:\n"); 1901 printf("=====================\n"); 1902 inst.width = 256; 1903 inst.height = 256; 1904 int format_count = 0; 1905 int present_mode_count = 0; 1906 1907#if defined(VK_USE_PLATFORM_XCB_KHR) || defined(VK_USE_PLATFORM_XLIB_KHR) 1908 if (getenv("DISPLAY") == NULL) { 1909 printf("'DISPLAY' environment variable not set... Exiting!\n"); 1910 fflush(stdout); 1911 exit(1); 1912 } 1913#endif 1914//--WIN32-- 1915#ifdef VK_USE_PLATFORM_WIN32_KHR 1916 if (CheckExtensionEnabled(VK_KHR_WIN32_SURFACE_EXTENSION_NAME, inst.inst_extensions, inst.inst_extensions_count)) { 1917 AppCreateWin32Window(&inst); 1918 for (uint32_t i = 0; i < gpu_count; i++) { 1919 AppCreateWin32Surface(&inst); 1920 printf("GPU id : %u (%s)\n", i, gpus[i].props.deviceName); 1921 printf("Surface type : %s\n", VK_KHR_WIN32_SURFACE_EXTENSION_NAME); 1922 format_count += AppDumpSurfaceFormats(&inst, &gpus[i]); 1923 present_mode_count += AppDumpSurfacePresentModes(&inst, &gpus[i]); 1924 AppDumpSurfaceCapabilities(&inst, &gpus[i]); 1925 AppDestroySurface(&inst); 1926 } 1927 AppDestroyWin32Window(&inst); 1928 } 1929//--XCB-- 1930#elif VK_USE_PLATFORM_XCB_KHR 1931 if (CheckExtensionEnabled(VK_KHR_XCB_SURFACE_EXTENSION_NAME, inst.inst_extensions, inst.inst_extensions_count)) { 1932 AppCreateXcbWindow(&inst); 1933 for (uint32_t i = 0; i < gpu_count; i++) { 1934 AppCreateXcbSurface(&inst); 1935 printf("GPU id : %u (%s)\n", i, gpus[i].props.deviceName); 1936 printf("Surface type : %s\n", VK_KHR_XCB_SURFACE_EXTENSION_NAME); 1937 format_count += AppDumpSurfaceFormats(&inst, &gpus[i]); 1938 present_mode_count += AppDumpSurfacePresentModes(&inst, &gpus[i]); 1939 AppDumpSurfaceCapabilities(&inst, &gpus[i]); 1940 AppDestroySurface(&inst); 1941 } 1942 AppDestroyXcbWindow(&inst); 1943 } 1944//--XLIB-- 1945#elif VK_USE_PLATFORM_XLIB_KHR 1946 if (CheckExtensionEnabled(VK_KHR_XLIB_SURFACE_EXTENSION_NAME, inst.inst_extensions, inst.inst_extensions_count)) { 1947 AppCreateXlibWindow(&inst); 1948 for (uint32_t i = 0; i < gpu_count; i++) { 1949 AppCreateXlibSurface(&inst); 1950 printf("GPU id : %u (%s)\n", i, gpus[i].props.deviceName); 1951 printf("Surface type : %s\n", VK_KHR_XLIB_SURFACE_EXTENSION_NAME); 1952 format_count += AppDumpSurfaceFormats(&inst, &gpus[i]); 1953 present_mode_count += AppDumpSurfacePresentModes(&inst, &gpus[i]); 1954 AppDumpSurfaceCapabilities(&inst, &gpus[i]); 1955 AppDestroySurface(&inst); 1956 } 1957 AppDestroyXlibWindow(&inst); 1958 } 1959#endif 1960 // TODO: Android / Wayland / MIR 1961 if (!format_count && !present_mode_count) printf("None found\n"); 1962 //--------- 1963 1964 for (uint32_t i = 0; i < gpu_count; i++) { 1965 AppGpuDump(&gpus[i]); 1966 printf("\n\n"); 1967 } 1968 1969 for (uint32_t i = 0; i < gpu_count; i++) AppGpuDestroy(&gpus[i]); 1970 free(gpus); 1971 free(objs); 1972 1973 AppDestroyInstance(&inst); 1974 1975 fflush(stdout); 1976#ifdef _WIN32 1977 if (ConsoleIsExclusive()) Sleep(INFINITE); 1978#endif 1979 1980 return 0; 1981} 1982