Atlas - testvulkan.c

Home / ext / SDL2 / test Lines: 42 | Size: 44812 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2 Copyright (C) 1997-2018 Sam Lantinga <[email protected]> 3 4 This software is provided 'as-is', without any express or implied 5 warranty. In no event will the authors be held liable for any damages 6 arising from the use of this software. 7 8 Permission is granted to anyone to use this software for any purpose, 9 including commercial applications, and to alter it and redistribute it 10 freely. 11*/ 12#include <stdlib.h> 13#include <stdio.h> 14#include <string.h> 15#include <math.h> 16 17#include "SDL_test_common.h" 18 19#if defined(__ANDROID__) && defined(__ARM_EABI__) && !defined(__ARM_ARCH_7A__) 20 21int main(int argc, char *argv[]) 22{ 23 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "No Vulkan support on this system\n"); 24 return 1; 25} 26 27#else 28 29#define VK_NO_PROTOTYPES 30#ifdef HAVE_VULKAN_H 31#include <vulkan/vulkan.h> 32#else 33/* SDL includes a copy for building on systems without the Vulkan SDK */ 34#include "../src/video/khronos/vulkan/vulkan.h" 35#endif 36#include "SDL_vulkan.h" 37 38#ifndef UINT64_MAX /* VS2008 */ 39#define UINT64_MAX 18446744073709551615 40#endif 41 42#define VULKAN_FUNCTIONS() \ 43 VULKAN_DEVICE_FUNCTION(vkAcquireNextImageKHR) \ 44 VULKAN_DEVICE_FUNCTION(vkAllocateCommandBuffers) \ 45 VULKAN_DEVICE_FUNCTION(vkBeginCommandBuffer) \ 46 VULKAN_DEVICE_FUNCTION(vkCmdClearColorImage) \ 47 VULKAN_DEVICE_FUNCTION(vkCmdPipelineBarrier) \ 48 VULKAN_DEVICE_FUNCTION(vkCreateCommandPool) \ 49 VULKAN_DEVICE_FUNCTION(vkCreateFence) \ 50 VULKAN_DEVICE_FUNCTION(vkCreateImageView) \ 51 VULKAN_DEVICE_FUNCTION(vkCreateSemaphore) \ 52 VULKAN_DEVICE_FUNCTION(vkCreateSwapchainKHR) \ 53 VULKAN_DEVICE_FUNCTION(vkDestroyCommandPool) \ 54 VULKAN_DEVICE_FUNCTION(vkDestroyDevice) \ 55 VULKAN_DEVICE_FUNCTION(vkDestroyFence) \ 56 VULKAN_DEVICE_FUNCTION(vkDestroyImageView) \ 57 VULKAN_DEVICE_FUNCTION(vkDestroySemaphore) \ 58 VULKAN_DEVICE_FUNCTION(vkDestroySwapchainKHR) \ 59 VULKAN_DEVICE_FUNCTION(vkDeviceWaitIdle) \ 60 VULKAN_DEVICE_FUNCTION(vkEndCommandBuffer) \ 61 VULKAN_DEVICE_FUNCTION(vkFreeCommandBuffers) \ 62 VULKAN_DEVICE_FUNCTION(vkGetDeviceQueue) \ 63 VULKAN_DEVICE_FUNCTION(vkGetFenceStatus) \ 64 VULKAN_DEVICE_FUNCTION(vkGetSwapchainImagesKHR) \ 65 VULKAN_DEVICE_FUNCTION(vkQueuePresentKHR) \ 66 VULKAN_DEVICE_FUNCTION(vkQueueSubmit) \ 67 VULKAN_DEVICE_FUNCTION(vkResetCommandBuffer) \ 68 VULKAN_DEVICE_FUNCTION(vkResetFences) \ 69 VULKAN_DEVICE_FUNCTION(vkWaitForFences) \ 70 VULKAN_GLOBAL_FUNCTION(vkCreateInstance) \ 71 VULKAN_GLOBAL_FUNCTION(vkEnumerateInstanceExtensionProperties) \ 72 VULKAN_GLOBAL_FUNCTION(vkEnumerateInstanceLayerProperties) \ 73 VULKAN_INSTANCE_FUNCTION(vkCreateDevice) \ 74 VULKAN_INSTANCE_FUNCTION(vkDestroyInstance) \ 75 VULKAN_INSTANCE_FUNCTION(vkDestroySurfaceKHR) \ 76 VULKAN_INSTANCE_FUNCTION(vkEnumerateDeviceExtensionProperties) \ 77 VULKAN_INSTANCE_FUNCTION(vkEnumeratePhysicalDevices) \ 78 VULKAN_INSTANCE_FUNCTION(vkGetDeviceProcAddr) \ 79 VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceFeatures) \ 80 VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceProperties) \ 81 VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceQueueFamilyProperties) \ 82 VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceSurfaceCapabilitiesKHR) \ 83 VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceSurfaceFormatsKHR) \ 84 VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceSurfacePresentModesKHR) \ 85 VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceSurfaceSupportKHR) 86 87#define VULKAN_DEVICE_FUNCTION(name) static PFN_##name name = NULL; 88#define VULKAN_GLOBAL_FUNCTION(name) static PFN_##name name = NULL; 89#define VULKAN_INSTANCE_FUNCTION(name) static PFN_##name name = NULL; 90VULKAN_FUNCTIONS() 91#undef VULKAN_DEVICE_FUNCTION 92#undef VULKAN_GLOBAL_FUNCTION 93#undef VULKAN_INSTANCE_FUNCTION 94static PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = NULL; 95 96/* Based on the headers found in 97 * https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers 98 */ 99#if VK_HEADER_VERSION < 22 100enum 101{ 102 VK_ERROR_FRAGMENTED_POOL = -12, 103}; 104#endif 105#if VK_HEADER_VERSION < 38 106enum { 107 VK_ERROR_OUT_OF_POOL_MEMORY_KHR = -1000069000 108}; 109#endif 110 111static const char *getVulkanResultString(VkResult result) 112{ 113 switch((int)result) 114 { 115 case VK_SUCCESS: 116 return "VK_SUCCESS"; 117 case VK_NOT_READY: 118 return "VK_NOT_READY"; 119 case VK_TIMEOUT: 120 return "VK_TIMEOUT"; 121 case VK_EVENT_SET: 122 return "VK_EVENT_SET"; 123 case VK_EVENT_RESET: 124 return "VK_EVENT_RESET"; 125 case VK_INCOMPLETE: 126 return "VK_INCOMPLETE"; 127 case VK_ERROR_OUT_OF_HOST_MEMORY: 128 return "VK_ERROR_OUT_OF_HOST_MEMORY"; 129 case VK_ERROR_OUT_OF_DEVICE_MEMORY: 130 return "VK_ERROR_OUT_OF_DEVICE_MEMORY"; 131 case VK_ERROR_INITIALIZATION_FAILED: 132 return "VK_ERROR_INITIALIZATION_FAILED"; 133 case VK_ERROR_DEVICE_LOST: 134 return "VK_ERROR_DEVICE_LOST"; 135 case VK_ERROR_MEMORY_MAP_FAILED: 136 return "VK_ERROR_MEMORY_MAP_FAILED"; 137 case VK_ERROR_LAYER_NOT_PRESENT: 138 return "VK_ERROR_LAYER_NOT_PRESENT"; 139 case VK_ERROR_EXTENSION_NOT_PRESENT: 140 return "VK_ERROR_EXTENSION_NOT_PRESENT"; 141 case VK_ERROR_FEATURE_NOT_PRESENT: 142 return "VK_ERROR_FEATURE_NOT_PRESENT"; 143 case VK_ERROR_INCOMPATIBLE_DRIVER: 144 return "VK_ERROR_INCOMPATIBLE_DRIVER"; 145 case VK_ERROR_TOO_MANY_OBJECTS: 146 return "VK_ERROR_TOO_MANY_OBJECTS"; 147 case VK_ERROR_FORMAT_NOT_SUPPORTED: 148 return "VK_ERROR_FORMAT_NOT_SUPPORTED"; 149 case VK_ERROR_FRAGMENTED_POOL: 150 return "VK_ERROR_FRAGMENTED_POOL"; 151 case VK_ERROR_SURFACE_LOST_KHR: 152 return "VK_ERROR_SURFACE_LOST_KHR"; 153 case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: 154 return "VK_ERROR_NATIVE_WINDOW_IN_USE_KHR"; 155 case VK_SUBOPTIMAL_KHR: 156 return "VK_SUBOPTIMAL_KHR"; 157 case VK_ERROR_OUT_OF_DATE_KHR: 158 return "VK_ERROR_OUT_OF_DATE_KHR"; 159 case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR: 160 return "VK_ERROR_INCOMPATIBLE_DISPLAY_KHR"; 161 case VK_ERROR_VALIDATION_FAILED_EXT: 162 return "VK_ERROR_VALIDATION_FAILED_EXT"; 163 case VK_ERROR_OUT_OF_POOL_MEMORY_KHR: 164 return "VK_ERROR_OUT_OF_POOL_MEMORY_KHR"; 165 case VK_ERROR_INVALID_SHADER_NV: 166 return "VK_ERROR_INVALID_SHADER_NV"; 167 case VK_RESULT_MAX_ENUM: 168 case VK_RESULT_RANGE_SIZE: 169 break; 170 } 171 if(result < 0) 172 return "VK_ERROR_<Unknown>"; 173 return "VK_<Unknown>"; 174} 175 176typedef struct VulkanContext 177{ 178 VkInstance instance; 179 VkDevice device; 180 VkSurfaceKHR surface; 181 VkSwapchainKHR swapchain; 182 VkPhysicalDeviceProperties physicalDeviceProperties; 183 VkPhysicalDeviceFeatures physicalDeviceFeatures; 184 uint32_t graphicsQueueFamilyIndex; 185 uint32_t presentQueueFamilyIndex; 186 VkPhysicalDevice physicalDevice; 187 VkQueue graphicsQueue; 188 VkQueue presentQueue; 189 VkSemaphore imageAvailableSemaphore; 190 VkSemaphore renderingFinishedSemaphore; 191 VkSurfaceCapabilitiesKHR surfaceCapabilities; 192 VkSurfaceFormatKHR *surfaceFormats; 193 uint32_t surfaceFormatsAllocatedCount; 194 uint32_t surfaceFormatsCount; 195 uint32_t swapchainDesiredImageCount; 196 VkSurfaceFormatKHR surfaceFormat; 197 VkExtent2D swapchainSize; 198 VkCommandPool commandPool; 199 uint32_t swapchainImageCount; 200 VkImage *swapchainImages; 201 VkCommandBuffer *commandBuffers; 202 VkFence *fences; 203} VulkanContext; 204 205static SDLTest_CommonState *state; 206static VulkanContext vulkanContext = {0}; 207 208static void shutdownVulkan(void); 209 210/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */ 211static void quit(int rc) 212{ 213 shutdownVulkan(); 214 SDLTest_CommonQuit(state); 215 exit(rc); 216} 217 218static void loadGlobalFunctions(void) 219{ 220 vkGetInstanceProcAddr = SDL_Vulkan_GetVkGetInstanceProcAddr(); 221 if(!vkGetInstanceProcAddr) 222 { 223 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, 224 "SDL_Vulkan_GetVkGetInstanceProcAddr(): %s\n", 225 SDL_GetError()); 226 quit(2); 227 } 228 229#define VULKAN_DEVICE_FUNCTION(name) 230#define VULKAN_GLOBAL_FUNCTION(name) \ 231 name = (PFN_##name)vkGetInstanceProcAddr(VK_NULL_HANDLE, #name); \ 232 if(!name) \ 233 { \ 234 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, \ 235 "vkGetInstanceProcAddr(VK_NULL_HANDLE, \"" #name "\") failed\n"); \ 236 quit(2); \ 237 } 238#define VULKAN_INSTANCE_FUNCTION(name) 239 VULKAN_FUNCTIONS() 240#undef VULKAN_DEVICE_FUNCTION 241#undef VULKAN_GLOBAL_FUNCTION 242#undef VULKAN_INSTANCE_FUNCTION 243} 244 245static void createInstance(void) 246{ 247 VkApplicationInfo appInfo = {0}; 248 VkInstanceCreateInfo instanceCreateInfo = {0}; 249 const char **extensions = NULL; 250 unsigned extensionCount = 0; 251 VkResult result; 252 253 254 appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; 255 appInfo.apiVersion = VK_API_VERSION_1_0; 256 instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; 257 instanceCreateInfo.pApplicationInfo = &appInfo; 258 if(!SDL_Vulkan_GetInstanceExtensions(NULL, &extensionCount, NULL)) 259 { 260 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, 261 "SDL_Vulkan_GetInstanceExtensions(): %s\n", 262 SDL_GetError()); 263 quit(2); 264 } 265 extensions = SDL_malloc(sizeof(const char *) * extensionCount); 266 if(!extensions) 267 { 268 SDL_OutOfMemory(); 269 quit(2); 270 } 271 if(!SDL_Vulkan_GetInstanceExtensions(NULL, &extensionCount, extensions)) 272 { 273 SDL_free((void*)extensions); 274 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, 275 "SDL_Vulkan_GetInstanceExtensions(): %s\n", 276 SDL_GetError()); 277 quit(2); 278 } 279 instanceCreateInfo.enabledExtensionCount = extensionCount; 280 instanceCreateInfo.ppEnabledExtensionNames = extensions; 281 result = vkCreateInstance(&instanceCreateInfo, NULL, &vulkanContext.instance); 282 SDL_free((void*)extensions); 283 if(result != VK_SUCCESS) 284 { 285 vulkanContext.instance = VK_NULL_HANDLE; 286 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, 287 "vkCreateInstance(): %s\n", 288 getVulkanResultString(result)); 289 quit(2); 290 } 291} 292 293static void loadInstanceFunctions(void) 294{ 295#define VULKAN_DEVICE_FUNCTION(name) 296#define VULKAN_GLOBAL_FUNCTION(name) 297#define VULKAN_INSTANCE_FUNCTION(name) \ 298 name = (PFN_##name)vkGetInstanceProcAddr(vulkanContext.instance, #name); \ 299 if(!name) \ 300 { \ 301 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, \ 302 "vkGetInstanceProcAddr(instance, \"" #name "\") failed\n"); \ 303 quit(2); \ 304 } 305 VULKAN_FUNCTIONS() 306#undef VULKAN_DEVICE_FUNCTION 307#undef VULKAN_GLOBAL_FUNCTION 308#undef VULKAN_INSTANCE_FUNCTION 309} 310 311static void createSurface(void) 312{ 313 if(!SDL_Vulkan_CreateSurface(state->windows[0], 314 vulkanContext.instance, 315 &vulkanContext.surface)) 316 { 317 vulkanContext.surface = VK_NULL_HANDLE; 318 SDL_LogError( 319 SDL_LOG_CATEGORY_APPLICATION, "SDL_Vulkan_CreateSurface(): %s\n", SDL_GetError()); 320 quit(2); 321 } 322} 323 324static void findPhysicalDevice(void) 325{ 326 uint32_t physicalDeviceCount = 0; 327 VkPhysicalDevice *physicalDevices; 328 VkQueueFamilyProperties *queueFamiliesProperties = NULL; 329 uint32_t queueFamiliesPropertiesAllocatedSize = 0; 330 VkExtensionProperties *deviceExtensions = NULL; 331 uint32_t deviceExtensionsAllocatedSize = 0; 332 uint32_t physicalDeviceIndex; 333 334 VkResult result = 335 vkEnumeratePhysicalDevices(vulkanContext.instance, &physicalDeviceCount, NULL); 336 if(result != VK_SUCCESS) 337 { 338 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, 339 "vkEnumeratePhysicalDevices(): %s\n", 340 getVulkanResultString(result)); 341 quit(2); 342 } 343 if(physicalDeviceCount == 0) 344 { 345 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, 346 "vkEnumeratePhysicalDevices(): no physical devices\n"); 347 quit(2); 348 } 349 physicalDevices = SDL_malloc(sizeof(VkPhysicalDevice) * physicalDeviceCount); 350 if(!physicalDevices) 351 { 352 SDL_OutOfMemory(); 353 quit(2); 354 } 355 result = 356 vkEnumeratePhysicalDevices(vulkanContext.instance, &physicalDeviceCount, physicalDevices); 357 if(result != VK_SUCCESS) 358 { 359 SDL_free(physicalDevices); 360 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, 361 "vkEnumeratePhysicalDevices(): %s\n", 362 getVulkanResultString(result)); 363 quit(2); 364 } 365 vulkanContext.physicalDevice = NULL; 366 for(physicalDeviceIndex = 0; physicalDeviceIndex < physicalDeviceCount; 367 physicalDeviceIndex++) 368 { 369 uint32_t queueFamiliesCount = 0; 370 uint32_t queueFamilyIndex; 371 uint32_t deviceExtensionCount = 0; 372 SDL_bool hasSwapchainExtension = SDL_FALSE; 373 uint32_t i; 374 375 376 VkPhysicalDevice physicalDevice = physicalDevices[physicalDeviceIndex]; 377 vkGetPhysicalDeviceProperties(physicalDevice, &vulkanContext.physicalDeviceProperties); 378 if(VK_VERSION_MAJOR(vulkanContext.physicalDeviceProperties.apiVersion) < 1) 379 continue; 380 vkGetPhysicalDeviceFeatures(physicalDevice, &vulkanContext.physicalDeviceFeatures); 381 vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamiliesCount, NULL); 382 if(queueFamiliesCount == 0) 383 continue; 384 if(queueFamiliesPropertiesAllocatedSize < queueFamiliesCount) 385 { 386 SDL_free(queueFamiliesProperties); 387 queueFamiliesPropertiesAllocatedSize = queueFamiliesCount; 388 queueFamiliesProperties = 389 SDL_malloc(sizeof(VkQueueFamilyProperties) * queueFamiliesPropertiesAllocatedSize); 390 if(!queueFamiliesProperties) 391 { 392 SDL_free(physicalDevices); 393 SDL_free(deviceExtensions); 394 SDL_OutOfMemory(); 395 quit(2); 396 } 397 } 398 vkGetPhysicalDeviceQueueFamilyProperties( 399 physicalDevice, &queueFamiliesCount, queueFamiliesProperties); 400 vulkanContext.graphicsQueueFamilyIndex = queueFamiliesCount; 401 vulkanContext.presentQueueFamilyIndex = queueFamiliesCount; 402 for(queueFamilyIndex = 0; queueFamilyIndex < queueFamiliesCount; 403 queueFamilyIndex++) 404 { 405 VkBool32 supported = 0; 406 407 if(queueFamiliesProperties[queueFamilyIndex].queueCount == 0) 408 continue; 409 if(queueFamiliesProperties[queueFamilyIndex].queueFlags & VK_QUEUE_GRAPHICS_BIT) 410 vulkanContext.graphicsQueueFamilyIndex = queueFamilyIndex; 411 result = vkGetPhysicalDeviceSurfaceSupportKHR( 412 physicalDevice, queueFamilyIndex, vulkanContext.surface, &supported); 413 if(result != VK_SUCCESS) 414 { 415 SDL_free(physicalDevices); 416 SDL_free(queueFamiliesProperties); 417 SDL_free(deviceExtensions); 418 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, 419 "vkGetPhysicalDeviceSurfaceSupportKHR(): %s\n", 420 getVulkanResultString(result)); 421 quit(2); 422 } 423 if(supported) 424 { 425 vulkanContext.presentQueueFamilyIndex = queueFamilyIndex; 426 if(queueFamiliesProperties[queueFamilyIndex].queueFlags & VK_QUEUE_GRAPHICS_BIT) 427 break; // use this queue because it can present and do graphics 428 } 429 } 430 if(vulkanContext.graphicsQueueFamilyIndex == queueFamiliesCount) // no good queues found 431 continue; 432 if(vulkanContext.presentQueueFamilyIndex == queueFamiliesCount) // no good queues found 433 continue; 434 result = 435 vkEnumerateDeviceExtensionProperties(physicalDevice, NULL, &deviceExtensionCount, NULL); 436 if(result != VK_SUCCESS) 437 { 438 SDL_free(physicalDevices); 439 SDL_free(queueFamiliesProperties); 440 SDL_free(deviceExtensions); 441 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, 442 "vkEnumerateDeviceExtensionProperties(): %s\n", 443 getVulkanResultString(result)); 444 quit(2); 445 } 446 if(deviceExtensionCount == 0) 447 continue; 448 if(deviceExtensionsAllocatedSize < deviceExtensionCount) 449 { 450 SDL_free(deviceExtensions); 451 deviceExtensionsAllocatedSize = deviceExtensionCount; 452 deviceExtensions = 453 SDL_malloc(sizeof(VkExtensionProperties) * deviceExtensionsAllocatedSize); 454 if(!deviceExtensions) 455 { 456 SDL_free(physicalDevices); 457 SDL_free(queueFamiliesProperties); 458 SDL_OutOfMemory(); 459 quit(2); 460 } 461 } 462 result = vkEnumerateDeviceExtensionProperties( 463 physicalDevice, NULL, &deviceExtensionCount, deviceExtensions); 464 if(result != VK_SUCCESS) 465 { 466 SDL_free(physicalDevices); 467 SDL_free(queueFamiliesProperties); 468 SDL_free(deviceExtensions); 469 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, 470 "vkEnumerateDeviceExtensionProperties(): %s\n", 471 getVulkanResultString(result)); 472 quit(2); 473 } 474 for(i = 0; i < deviceExtensionCount; i++) 475 { 476 if(0 == SDL_strcmp(deviceExtensions[i].extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME)) 477 { 478 hasSwapchainExtension = SDL_TRUE; 479 break; 480 } 481 } 482 if(!hasSwapchainExtension) 483 continue; 484 vulkanContext.physicalDevice = physicalDevice; 485 break; 486 } 487 SDL_free(physicalDevices); 488 SDL_free(queueFamiliesProperties); 489 SDL_free(deviceExtensions); 490 if(!vulkanContext.physicalDevice) 491 { 492 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Vulkan: no viable physical devices found"); 493 quit(2); 494 } 495} 496 497static void createDevice(void) 498{ 499 VkDeviceQueueCreateInfo deviceQueueCreateInfo[1] = {0}; 500 static const float queuePriority[] = {1.0f}; 501 VkDeviceCreateInfo deviceCreateInfo = {0}; 502 static const char *const deviceExtensionNames[] = { 503 VK_KHR_SWAPCHAIN_EXTENSION_NAME, 504 }; 505 VkResult result; 506 507 deviceQueueCreateInfo->sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; 508 deviceQueueCreateInfo->queueFamilyIndex = vulkanContext.graphicsQueueFamilyIndex; 509 deviceQueueCreateInfo->queueCount = 1; 510 deviceQueueCreateInfo->pQueuePriorities = &queuePriority[0]; 511 512 deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; 513 deviceCreateInfo.queueCreateInfoCount = 1; 514 deviceCreateInfo.pQueueCreateInfos = deviceQueueCreateInfo; 515 deviceCreateInfo.pEnabledFeatures = NULL; 516 deviceCreateInfo.enabledExtensionCount = SDL_arraysize(deviceExtensionNames); 517 deviceCreateInfo.ppEnabledExtensionNames = deviceExtensionNames; 518 result = vkCreateDevice( 519 vulkanContext.physicalDevice, &deviceCreateInfo, NULL, &vulkanContext.device); 520 if(result != VK_SUCCESS) 521 { 522 vulkanContext.device = VK_NULL_HANDLE; 523 SDL_LogError( 524 SDL_LOG_CATEGORY_APPLICATION, "vkCreateDevice(): %s\n", getVulkanResultString(result)); 525 quit(2); 526 } 527} 528 529static void loadDeviceFunctions(void) 530{ 531#define VULKAN_DEVICE_FUNCTION(name) \ 532 name = (PFN_##name)vkGetDeviceProcAddr(vulkanContext.device, #name); \ 533 if(!name) \ 534 { \ 535 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, \ 536 "vkGetDeviceProcAddr(device, \"" #name "\") failed\n"); \ 537 quit(2); \ 538 } 539#define VULKAN_GLOBAL_FUNCTION(name) 540#define VULKAN_INSTANCE_FUNCTION(name) 541 VULKAN_FUNCTIONS() 542#undef VULKAN_DEVICE_FUNCTION 543#undef VULKAN_GLOBAL_FUNCTION 544#undef VULKAN_INSTANCE_FUNCTION 545} 546 547#undef VULKAN_FUNCTIONS 548 549static void getQueues(void) 550{ 551 vkGetDeviceQueue(vulkanContext.device, 552 vulkanContext.graphicsQueueFamilyIndex, 553 0, 554 &vulkanContext.graphicsQueue); 555 if(vulkanContext.graphicsQueueFamilyIndex != vulkanContext.presentQueueFamilyIndex) 556 vkGetDeviceQueue(vulkanContext.device, 557 vulkanContext.presentQueueFamilyIndex, 558 0, 559 &vulkanContext.presentQueue); 560 else 561 vulkanContext.presentQueue = vulkanContext.graphicsQueue; 562} 563 564static void createSemaphore(VkSemaphore *semaphore) 565{ 566 VkResult result; 567 568 VkSemaphoreCreateInfo createInfo = {0}; 569 createInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; 570 result = vkCreateSemaphore(vulkanContext.device, &createInfo, NULL, semaphore); 571 if(result != VK_SUCCESS) 572 { 573 *semaphore = VK_NULL_HANDLE; 574 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, 575 "vkCreateSemaphore(): %s\n", 576 getVulkanResultString(result)); 577 quit(2); 578 } 579} 580 581static void createSemaphores(void) 582{ 583 createSemaphore(&vulkanContext.imageAvailableSemaphore); 584 createSemaphore(&vulkanContext.renderingFinishedSemaphore); 585} 586 587static void getSurfaceCaps(void) 588{ 589 VkResult result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR( 590 vulkanContext.physicalDevice, vulkanContext.surface, &vulkanContext.surfaceCapabilities); 591 if(result != VK_SUCCESS) 592 { 593 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, 594 "vkGetPhysicalDeviceSurfaceCapabilitiesKHR(): %s\n", 595 getVulkanResultString(result)); 596 quit(2); 597 } 598 599 // check surface usage 600 if(!(vulkanContext.surfaceCapabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT)) 601 { 602 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, 603 "Vulkan surface doesn't support VK_IMAGE_USAGE_TRANSFER_DST_BIT\n"); 604 quit(2); 605 } 606} 607 608static void getSurfaceFormats(void) 609{ 610 VkResult result = vkGetPhysicalDeviceSurfaceFormatsKHR(vulkanContext.physicalDevice, 611 vulkanContext.surface, 612 &vulkanContext.surfaceFormatsCount, 613 NULL); 614 if(result != VK_SUCCESS) 615 { 616 vulkanContext.surfaceFormatsCount = 0; 617 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, 618 "vkGetPhysicalDeviceSurfaceFormatsKHR(): %s\n", 619 getVulkanResultString(result)); 620 quit(2); 621 } 622 if(vulkanContext.surfaceFormatsCount > vulkanContext.surfaceFormatsAllocatedCount) 623 { 624 vulkanContext.surfaceFormatsAllocatedCount = vulkanContext.surfaceFormatsCount; 625 SDL_free(vulkanContext.surfaceFormats); 626 vulkanContext.surfaceFormats = 627 SDL_malloc(sizeof(VkSurfaceFormatKHR) * vulkanContext.surfaceFormatsAllocatedCount); 628 if(!vulkanContext.surfaceFormats) 629 { 630 vulkanContext.surfaceFormatsCount = 0; 631 SDL_OutOfMemory(); 632 quit(2); 633 } 634 } 635 result = vkGetPhysicalDeviceSurfaceFormatsKHR(vulkanContext.physicalDevice, 636 vulkanContext.surface, 637 &vulkanContext.surfaceFormatsCount, 638 vulkanContext.surfaceFormats); 639 if(result != VK_SUCCESS) 640 { 641 vulkanContext.surfaceFormatsCount = 0; 642 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, 643 "vkGetPhysicalDeviceSurfaceFormatsKHR(): %s\n", 644 getVulkanResultString(result)); 645 quit(2); 646 } 647} 648 649static void getSwapchainImages(void) 650{ 651 VkResult result; 652 653 SDL_free(vulkanContext.swapchainImages); 654 vulkanContext.swapchainImages = NULL; 655 result = vkGetSwapchainImagesKHR( 656 vulkanContext.device, vulkanContext.swapchain, &vulkanContext.swapchainImageCount, NULL); 657 if(result != VK_SUCCESS) 658 { 659 vulkanContext.swapchainImageCount = 0; 660 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, 661 "vkGetSwapchainImagesKHR(): %s\n", 662 getVulkanResultString(result)); 663 quit(2); 664 } 665 vulkanContext.swapchainImages = SDL_malloc(sizeof(VkImage) * vulkanContext.swapchainImageCount); 666 if(!vulkanContext.swapchainImages) 667 { 668 SDL_OutOfMemory(); 669 quit(2); 670 } 671 result = vkGetSwapchainImagesKHR(vulkanContext.device, 672 vulkanContext.swapchain, 673 &vulkanContext.swapchainImageCount, 674 vulkanContext.swapchainImages); 675 if(result != VK_SUCCESS) 676 { 677 SDL_free(vulkanContext.swapchainImages); 678 vulkanContext.swapchainImages = NULL; 679 vulkanContext.swapchainImageCount = 0; 680 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, 681 "vkGetSwapchainImagesKHR(): %s\n", 682 getVulkanResultString(result)); 683 quit(2); 684 } 685} 686 687static SDL_bool createSwapchain(void) 688{ 689 uint32_t i; 690 int w, h; 691 VkSwapchainCreateInfoKHR createInfo = {0}; 692 VkResult result; 693 694 // pick an image count 695 vulkanContext.swapchainDesiredImageCount = vulkanContext.surfaceCapabilities.minImageCount + 1; 696 if(vulkanContext.swapchainDesiredImageCount > vulkanContext.surfaceCapabilities.maxImageCount 697 && vulkanContext.surfaceCapabilities.maxImageCount > 0) 698 vulkanContext.swapchainDesiredImageCount = vulkanContext.surfaceCapabilities.maxImageCount; 699 700 // pick a format 701 if(vulkanContext.surfaceFormatsCount == 1 702 && vulkanContext.surfaceFormats[0].format == VK_FORMAT_UNDEFINED) 703 { 704 // aren't any preferred formats, so we pick 705 vulkanContext.surfaceFormat.colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; 706 vulkanContext.surfaceFormat.format = VK_FORMAT_R8G8B8A8_UNORM; 707 } 708 else 709 { 710 vulkanContext.surfaceFormat = vulkanContext.surfaceFormats[0]; 711 for(i = 0; i < vulkanContext.surfaceFormatsCount; i++) 712 { 713 if(vulkanContext.surfaceFormats[i].format == VK_FORMAT_R8G8B8A8_UNORM) 714 { 715 vulkanContext.surfaceFormat = vulkanContext.surfaceFormats[i]; 716 break; 717 } 718 } 719 } 720 721 // get size 722 SDL_Vulkan_GetDrawableSize(state->windows[0], &w, &h); 723 vulkanContext.swapchainSize.width = w; 724 vulkanContext.swapchainSize.height = h; 725 if(w == 0 || h == 0) 726 return SDL_FALSE; 727 728 createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; 729 createInfo.surface = vulkanContext.surface; 730 createInfo.minImageCount = vulkanContext.swapchainDesiredImageCount; 731 createInfo.imageFormat = vulkanContext.surfaceFormat.format; 732 createInfo.imageColorSpace = vulkanContext.surfaceFormat.colorSpace; 733 createInfo.imageExtent = vulkanContext.swapchainSize; 734 createInfo.imageArrayLayers = 1; 735 createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; 736 createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; 737 createInfo.preTransform = vulkanContext.surfaceCapabilities.currentTransform; 738 createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; 739 createInfo.presentMode = VK_PRESENT_MODE_FIFO_KHR; 740 createInfo.clipped = VK_TRUE; 741 createInfo.oldSwapchain = vulkanContext.swapchain; 742 result = 743 vkCreateSwapchainKHR(vulkanContext.device, &createInfo, NULL, &vulkanContext.swapchain); 744 if(createInfo.oldSwapchain) 745 vkDestroySwapchainKHR(vulkanContext.device, createInfo.oldSwapchain, NULL); 746 if(result != VK_SUCCESS) 747 { 748 vulkanContext.swapchain = VK_NULL_HANDLE; 749 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, 750 "vkCreateSwapchainKHR(): %s\n", 751 getVulkanResultString(result)); 752 quit(2); 753 } 754 getSwapchainImages(); 755 return SDL_TRUE; 756} 757 758static void destroySwapchain(void) 759{ 760 if(vulkanContext.swapchain) 761 vkDestroySwapchainKHR(vulkanContext.device, vulkanContext.swapchain, NULL); 762 vulkanContext.swapchain = VK_NULL_HANDLE; 763 SDL_free(vulkanContext.swapchainImages); 764 vulkanContext.swapchainImages = NULL; 765} 766 767static void destroyCommandBuffers(void) 768{ 769 if(vulkanContext.commandBuffers) 770 vkFreeCommandBuffers(vulkanContext.device, 771 vulkanContext.commandPool, 772 vulkanContext.swapchainImageCount, 773 vulkanContext.commandBuffers); 774 SDL_free(vulkanContext.commandBuffers); 775 vulkanContext.commandBuffers = NULL; 776} 777 778static void destroyCommandPool(void) 779{ 780 if(vulkanContext.commandPool) 781 vkDestroyCommandPool(vulkanContext.device, vulkanContext.commandPool, NULL); 782 vulkanContext.commandPool = VK_NULL_HANDLE; 783} 784 785static void createCommandPool(void) 786{ 787 VkResult result; 788 789 VkCommandPoolCreateInfo createInfo = {0}; 790 createInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; 791 createInfo.flags = 792 VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT | VK_COMMAND_POOL_CREATE_TRANSIENT_BIT; 793 createInfo.queueFamilyIndex = vulkanContext.graphicsQueueFamilyIndex; 794 result = 795 vkCreateCommandPool(vulkanContext.device, &createInfo, NULL, &vulkanContext.commandPool); 796 if(result != VK_SUCCESS) 797 { 798 vulkanContext.commandPool = VK_NULL_HANDLE; 799 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, 800 "vkCreateCommandPool(): %s\n", 801 getVulkanResultString(result)); 802 quit(2); 803 } 804} 805 806static void createCommandBuffers(void) 807{ 808 VkResult result; 809 810 VkCommandBufferAllocateInfo allocateInfo = {0}; 811 allocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; 812 allocateInfo.commandPool = vulkanContext.commandPool; 813 allocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; 814 allocateInfo.commandBufferCount = vulkanContext.swapchainImageCount; 815 vulkanContext.commandBuffers = 816 SDL_malloc(sizeof(VkCommandBuffer) * vulkanContext.swapchainImageCount); 817 result = 818 vkAllocateCommandBuffers(vulkanContext.device, &allocateInfo, vulkanContext.commandBuffers); 819 if(result != VK_SUCCESS) 820 { 821 SDL_free(vulkanContext.commandBuffers); 822 vulkanContext.commandBuffers = NULL; 823 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, 824 "vkAllocateCommandBuffers(): %s\n", 825 getVulkanResultString(result)); 826 quit(2); 827 } 828} 829 830static void createFences(void) 831{ 832 uint32_t i; 833 834 vulkanContext.fences = SDL_malloc(sizeof(VkFence) * vulkanContext.swapchainImageCount); 835 if(!vulkanContext.fences) 836 { 837 SDL_OutOfMemory(); 838 quit(2); 839 } 840 for(i = 0; i < vulkanContext.swapchainImageCount; i++) 841 { 842 VkResult result; 843 844 VkFenceCreateInfo createInfo = {0}; 845 createInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; 846 createInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; 847 result = 848 vkCreateFence(vulkanContext.device, &createInfo, NULL, &vulkanContext.fences[i]); 849 if(result != VK_SUCCESS) 850 { 851 for(; i > 0; i--) 852 { 853 vkDestroyFence(vulkanContext.device, vulkanContext.fences[i - 1], NULL); 854 } 855 SDL_free(vulkanContext.fences); 856 vulkanContext.fences = NULL; 857 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, 858 "vkCreateFence(): %s\n", 859 getVulkanResultString(result)); 860 quit(2); 861 } 862 } 863} 864 865static void destroyFences(void) 866{ 867 uint32_t i; 868 869 if(!vulkanContext.fences) 870 return; 871 for(i = 0; i < vulkanContext.swapchainImageCount; i++) 872 { 873 vkDestroyFence(vulkanContext.device, vulkanContext.fences[i], NULL); 874 } 875 SDL_free(vulkanContext.fences); 876 vulkanContext.fences = NULL; 877} 878 879static void recordPipelineImageBarrier(VkCommandBuffer commandBuffer, 880 VkAccessFlags sourceAccessMask, 881 VkAccessFlags destAccessMask, 882 VkImageLayout sourceLayout, 883 VkImageLayout destLayout, 884 VkImage image) 885{ 886 VkImageMemoryBarrier barrier = {0}; 887 barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 888 barrier.srcAccessMask = sourceAccessMask; 889 barrier.dstAccessMask = destAccessMask; 890 barrier.oldLayout = sourceLayout; 891 barrier.newLayout = destLayout; 892 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 893 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 894 barrier.image = image; 895 barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 896 barrier.subresourceRange.baseMipLevel = 0; 897 barrier.subresourceRange.levelCount = 1; 898 barrier.subresourceRange.baseArrayLayer = 0; 899 barrier.subresourceRange.layerCount = 1; 900 vkCmdPipelineBarrier(commandBuffer, 901 VK_PIPELINE_STAGE_TRANSFER_BIT, 902 VK_PIPELINE_STAGE_TRANSFER_BIT, 903 0, 904 0, 905 NULL, 906 0, 907 NULL, 908 1, 909 &barrier); 910} 911 912static void rerecordCommandBuffer(uint32_t frameIndex, const VkClearColorValue *clearColor) 913{ 914 VkCommandBuffer commandBuffer = vulkanContext.commandBuffers[frameIndex]; 915 VkImage image = vulkanContext.swapchainImages[frameIndex]; 916 VkCommandBufferBeginInfo beginInfo = {0}; 917 VkImageSubresourceRange clearRange = {0}; 918 919 VkResult result = vkResetCommandBuffer(commandBuffer, 0); 920 if(result != VK_SUCCESS) 921 { 922 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, 923 "vkResetCommandBuffer(): %s\n", 924 getVulkanResultString(result)); 925 quit(2); 926 } 927 beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; 928 beginInfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT; 929 result = vkBeginCommandBuffer(commandBuffer, &beginInfo); 930 if(result != VK_SUCCESS) 931 { 932 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, 933 "vkBeginCommandBuffer(): %s\n", 934 getVulkanResultString(result)); 935 quit(2); 936 } 937 recordPipelineImageBarrier(commandBuffer, 938 0, 939 VK_ACCESS_TRANSFER_WRITE_BIT, 940 VK_IMAGE_LAYOUT_UNDEFINED, 941 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 942 image); 943 clearRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 944 clearRange.baseMipLevel = 0; 945 clearRange.levelCount = 1; 946 clearRange.baseArrayLayer = 0; 947 clearRange.layerCount = 1; 948 vkCmdClearColorImage( 949 commandBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, clearColor, 1, &clearRange); 950 recordPipelineImageBarrier(commandBuffer, 951 VK_ACCESS_TRANSFER_WRITE_BIT, 952 VK_ACCESS_MEMORY_READ_BIT, 953 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 954 VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, 955 image); 956 result = vkEndCommandBuffer(commandBuffer); 957 if(result != VK_SUCCESS) 958 { 959 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, 960 "vkEndCommandBuffer(): %s\n", 961 getVulkanResultString(result)); 962 quit(2); 963 } 964} 965 966static void destroySwapchainAndSwapchainSpecificStuff(SDL_bool doDestroySwapchain) 967{ 968 destroyFences(); 969 destroyCommandBuffers(); 970 destroyCommandPool(); 971 if(doDestroySwapchain) 972 destroySwapchain(); 973} 974 975static SDL_bool createNewSwapchainAndSwapchainSpecificStuff(void) 976{ 977 destroySwapchainAndSwapchainSpecificStuff(SDL_FALSE); 978 getSurfaceCaps(); 979 getSurfaceFormats(); 980 if(!createSwapchain()) 981 return SDL_FALSE; 982 createCommandPool(); 983 createCommandBuffers(); 984 createFences(); 985 return SDL_TRUE; 986} 987 988static void initVulkan(void) 989{ 990 SDL_Vulkan_LoadLibrary(NULL); 991 SDL_memset(&vulkanContext, 0, sizeof(VulkanContext)); 992 loadGlobalFunctions(); 993 createInstance(); 994 loadInstanceFunctions(); 995 createSurface(); 996 findPhysicalDevice(); 997 createDevice(); 998 loadDeviceFunctions(); 999 getQueues(); 1000 createSemaphores(); 1001 createNewSwapchainAndSwapchainSpecificStuff(); 1002} 1003 1004static void shutdownVulkan(void) 1005{ 1006 if(vulkanContext.device && vkDeviceWaitIdle) 1007 vkDeviceWaitIdle(vulkanContext.device); 1008 destroySwapchainAndSwapchainSpecificStuff(SDL_TRUE); 1009 if(vulkanContext.imageAvailableSemaphore && vkDestroySemaphore) 1010 vkDestroySemaphore(vulkanContext.device, vulkanContext.imageAvailableSemaphore, NULL); 1011 if(vulkanContext.renderingFinishedSemaphore && vkDestroySemaphore) 1012 vkDestroySemaphore(vulkanContext.device, vulkanContext.renderingFinishedSemaphore, NULL); 1013 if(vulkanContext.device && vkDestroyDevice) 1014 vkDestroyDevice(vulkanContext.device, NULL); 1015 if(vulkanContext.surface && vkDestroySurfaceKHR) 1016 vkDestroySurfaceKHR(vulkanContext.instance, vulkanContext.surface, NULL); 1017 if(vulkanContext.instance && vkDestroyInstance) 1018 vkDestroyInstance(vulkanContext.instance, NULL); 1019 SDL_free(vulkanContext.surfaceFormats); 1020 SDL_Vulkan_UnloadLibrary(); 1021} 1022 1023static SDL_bool render(void) 1024{ 1025 uint32_t frameIndex; 1026 VkResult result; 1027 double currentTime; 1028 VkClearColorValue clearColor = {0}; 1029 VkPipelineStageFlags waitDestStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT; 1030 VkSubmitInfo submitInfo = {0}; 1031 VkPresentInfoKHR presentInfo = {0}; 1032 int w, h; 1033 1034 if(!vulkanContext.swapchain) 1035 { 1036 SDL_bool retval = createNewSwapchainAndSwapchainSpecificStuff(); 1037 if(!retval) 1038 SDL_Delay(100); 1039 return retval; 1040 } 1041 result = vkAcquireNextImageKHR(vulkanContext.device, 1042 vulkanContext.swapchain, 1043 UINT64_MAX, 1044 vulkanContext.imageAvailableSemaphore, 1045 VK_NULL_HANDLE, 1046 &frameIndex); 1047 if(result == VK_ERROR_OUT_OF_DATE_KHR) 1048 return createNewSwapchainAndSwapchainSpecificStuff(); 1049 if(result != VK_SUBOPTIMAL_KHR && result != VK_SUCCESS) 1050 { 1051 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, 1052 "vkAcquireNextImageKHR(): %s\n", 1053 getVulkanResultString(result)); 1054 quit(2); 1055 } 1056 result = vkWaitForFences( 1057 vulkanContext.device, 1, &vulkanContext.fences[frameIndex], VK_FALSE, UINT64_MAX); 1058 if(result != VK_SUCCESS) 1059 { 1060 SDL_LogError( 1061 SDL_LOG_CATEGORY_APPLICATION, "vkWaitForFences(): %s\n", getVulkanResultString(result)); 1062 quit(2); 1063 } 1064 result = vkResetFences(vulkanContext.device, 1, &vulkanContext.fences[frameIndex]); 1065 if(result != VK_SUCCESS) 1066 { 1067 SDL_LogError( 1068 SDL_LOG_CATEGORY_APPLICATION, "vkResetFences(): %s\n", getVulkanResultString(result)); 1069 quit(2); 1070 } 1071 currentTime = (double)SDL_GetPerformanceCounter() / SDL_GetPerformanceFrequency(); 1072 clearColor.float32[0] = (float)(0.5 + 0.5 * SDL_sin(currentTime)); 1073 clearColor.float32[1] = (float)(0.5 + 0.5 * SDL_sin(currentTime + M_PI * 2 / 3)); 1074 clearColor.float32[2] = (float)(0.5 + 0.5 * SDL_sin(currentTime + M_PI * 4 / 3)); 1075 clearColor.float32[3] = 1; 1076 rerecordCommandBuffer(frameIndex, &clearColor); 1077 submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 1078 submitInfo.waitSemaphoreCount = 1; 1079 submitInfo.pWaitSemaphores = &vulkanContext.imageAvailableSemaphore; 1080 submitInfo.pWaitDstStageMask = &waitDestStageMask; 1081 submitInfo.commandBufferCount = 1; 1082 submitInfo.pCommandBuffers = &vulkanContext.commandBuffers[frameIndex]; 1083 submitInfo.signalSemaphoreCount = 1; 1084 submitInfo.pSignalSemaphores = &vulkanContext.renderingFinishedSemaphore; 1085 result = vkQueueSubmit( 1086 vulkanContext.graphicsQueue, 1, &submitInfo, vulkanContext.fences[frameIndex]); 1087 if(result != VK_SUCCESS) 1088 { 1089 SDL_LogError( 1090 SDL_LOG_CATEGORY_APPLICATION, "vkQueueSubmit(): %s\n", getVulkanResultString(result)); 1091 quit(2); 1092 } 1093 presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; 1094 presentInfo.waitSemaphoreCount = 1; 1095 presentInfo.pWaitSemaphores = &vulkanContext.renderingFinishedSemaphore; 1096 presentInfo.swapchainCount = 1; 1097 presentInfo.pSwapchains = &vulkanContext.swapchain; 1098 presentInfo.pImageIndices = &frameIndex; 1099 result = vkQueuePresentKHR(vulkanContext.presentQueue, &presentInfo); 1100 if(result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) 1101 { 1102 return createNewSwapchainAndSwapchainSpecificStuff(); 1103 } 1104 if(result != VK_SUCCESS) 1105 { 1106 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, 1107 "vkQueuePresentKHR(): %s\n", 1108 getVulkanResultString(result)); 1109 quit(2); 1110 } 1111 SDL_Vulkan_GetDrawableSize(state->windows[0], &w, &h); 1112 if(w != (int)vulkanContext.swapchainSize.width || h != (int)vulkanContext.swapchainSize.height) 1113 { 1114 return createNewSwapchainAndSwapchainSpecificStuff(); 1115 } 1116 return SDL_TRUE; 1117} 1118 1119int main(int argc, char *argv[]) 1120{ 1121 int fsaa, accel; 1122 int i, done; 1123 SDL_DisplayMode mode; 1124 SDL_Event event; 1125 Uint32 then, now, frames; 1126 int dw, dh; 1127 1128 /* Enable standard application logging */ 1129 SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); 1130 1131 /* Initialize parameters */ 1132 fsaa = 0; 1133 accel = -1; 1134 1135 /* Initialize test framework */ 1136 state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); 1137 if(!state) 1138 { 1139 return 1; 1140 } 1141 for(i = 1; i < argc;) 1142 { 1143 int consumed; 1144 1145 consumed = SDLTest_CommonArg(state, i); 1146 if(consumed < 0) 1147 { 1148 SDL_Log("Usage: %s %s\n", argv[0], SDLTest_CommonUsage(state)); 1149 quit(1); 1150 } 1151 i += consumed; 1152 } 1153 1154 /* Set Vulkan parameters */ 1155 state->window_flags |= SDL_WINDOW_VULKAN; 1156 state->num_windows = 1; 1157 state->skip_renderer = 1; 1158 1159 if(!SDLTest_CommonInit(state)) 1160 { 1161 quit(2); 1162 } 1163 1164 SDL_GetCurrentDisplayMode(0, &mode); 1165 SDL_Log("Screen BPP : %d\n", SDL_BITSPERPIXEL(mode.format)); 1166 SDL_GetWindowSize(state->windows[0], &dw, &dh); 1167 SDL_Log("Window Size : %d,%d\n", dw, dh); 1168 SDL_Vulkan_GetDrawableSize(state->windows[0], &dw, &dh); 1169 SDL_Log("Draw Size : %d,%d\n", dw, dh); 1170 SDL_Log("\n"); 1171 1172 initVulkan(); 1173 1174 /* Main render loop */ 1175 frames = 0; 1176 then = SDL_GetTicks(); 1177 done = 0; 1178 while(!done) 1179 { 1180 /* Check for events */ 1181 ++frames; 1182 while(SDL_PollEvent(&event)) 1183 { 1184 SDLTest_CommonEvent(state, &event, &done); 1185 } 1186 1187 if(!done) 1188 render(); 1189 } 1190 1191 /* Print out some timing information */ 1192 now = SDL_GetTicks(); 1193 if(now > then) 1194 { 1195 SDL_Log("%2.2f frames per second\n", ((double)frames * 1000) / (now - then)); 1196 } 1197 quit(0); 1198 return 0; 1199} 1200 1201#endif 1202
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.