SDL  2.0
testvulkan.c
Go to the documentation of this file.
1 /*
2  Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
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 
21 int 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;
91 #undef VULKAN_DEVICE_FUNCTION
92 #undef VULKAN_GLOBAL_FUNCTION
93 #undef VULKAN_INSTANCE_FUNCTION
95 
96 /* Based on the headers found in
97  * https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers
98  */
99 #if VK_HEADER_VERSION < 22
100 enum
101 {
103 };
104 #endif
105 #if VK_HEADER_VERSION < 38
106 enum {
107  VK_ERROR_OUT_OF_POOL_MEMORY_KHR = -1000069000
108 };
109 #endif
110 
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";
128  return "VK_ERROR_OUT_OF_HOST_MEMORY";
130  return "VK_ERROR_OUT_OF_DEVICE_MEMORY";
132  return "VK_ERROR_INITIALIZATION_FAILED";
134  return "VK_ERROR_DEVICE_LOST";
136  return "VK_ERROR_MEMORY_MAP_FAILED";
138  return "VK_ERROR_LAYER_NOT_PRESENT";
140  return "VK_ERROR_EXTENSION_NOT_PRESENT";
142  return "VK_ERROR_FEATURE_NOT_PRESENT";
144  return "VK_ERROR_INCOMPATIBLE_DRIVER";
146  return "VK_ERROR_TOO_MANY_OBJECTS";
148  return "VK_ERROR_FORMAT_NOT_SUPPORTED";
150  return "VK_ERROR_FRAGMENTED_POOL";
152  return "VK_ERROR_SURFACE_LOST_KHR";
154  return "VK_ERROR_NATIVE_WINDOW_IN_USE_KHR";
155  case VK_SUBOPTIMAL_KHR:
156  return "VK_SUBOPTIMAL_KHR";
158  return "VK_ERROR_OUT_OF_DATE_KHR";
160  return "VK_ERROR_INCOMPATIBLE_DISPLAY_KHR";
162  return "VK_ERROR_VALIDATION_FAILED_EXT";
164  return "VK_ERROR_OUT_OF_POOL_MEMORY_KHR";
166  return "VK_ERROR_INVALID_SHADER_NV";
167  case VK_RESULT_MAX_ENUM:
169  break;
170  }
171  if(result < 0)
172  return "VK_ERROR_<Unknown>";
173  return "VK_<Unknown>";
174 }
175 
176 typedef struct VulkanContext
177 {
178  VkInstance instance;
179  VkDevice device;
180  VkSurfaceKHR surface;
181  VkSwapchainKHR swapchain;
186  VkPhysicalDevice physicalDevice;
187  VkQueue graphicsQueue;
188  VkQueue presentQueue;
198  VkCommandPool commandPool;
200  VkImage *swapchainImages;
201  VkCommandBuffer *commandBuffers;
202  VkFence *fences;
203 } VulkanContext;
204 
207 
208 static void shutdownVulkan(void);
209 
210 /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
211 static void quit(int rc)
212 {
213  shutdownVulkan();
214  SDLTest_CommonQuit(state);
215  exit(rc);
216 }
217 
218 static void loadGlobalFunctions(void)
219 {
220  vkGetInstanceProcAddr = SDL_Vulkan_GetVkGetInstanceProcAddr();
221  if(!vkGetInstanceProcAddr)
222  {
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)
240 #undef VULKAN_DEVICE_FUNCTION
241 #undef VULKAN_GLOBAL_FUNCTION
242 #undef VULKAN_INSTANCE_FUNCTION
243 }
244 
245 static void createInstance(void)
246 {
247  VkApplicationInfo appInfo = {0};
248  VkInstanceCreateInfo instanceCreateInfo = {0};
249  const char **extensions = NULL;
250  unsigned extensionCount = 0;
252 
253 
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(state->windows[0], &extensionCount, NULL))
259  {
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(state->windows[0], &extensionCount, extensions))
272  {
273  SDL_free((void*)extensions);
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;
287  "vkCreateInstance(): %s\n",
288  getVulkanResultString(result));
289  quit(2);
290  }
291 }
292 
293 static 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  }
306 #undef VULKAN_DEVICE_FUNCTION
307 #undef VULKAN_GLOBAL_FUNCTION
308 #undef VULKAN_INSTANCE_FUNCTION
309 }
310 
311 static 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 
324 static 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  {
339  "vkEnumeratePhysicalDevices(): %s\n",
340  getVulkanResultString(result));
341  quit(2);
342  }
343  if(physicalDeviceCount == 0)
344  {
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);
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);
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  }
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;
412  physicalDevice, queueFamilyIndex, vulkanContext.surface, &supported);
413  if(result != VK_SUCCESS)
414  {
415  SDL_free(physicalDevices);
416  SDL_free(queueFamiliesProperties);
417  SDL_free(deviceExtensions);
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);
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  }
463  physicalDevice, NULL, &deviceExtensionCount, deviceExtensions);
464  if(result != VK_SUCCESS)
465  {
466  SDL_free(physicalDevices);
467  SDL_free(queueFamiliesProperties);
468  SDL_free(deviceExtensions);
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 
497 static 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[] = {
504  };
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 
529 static 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)
542 #undef VULKAN_DEVICE_FUNCTION
543 #undef VULKAN_GLOBAL_FUNCTION
544 #undef VULKAN_INSTANCE_FUNCTION
545 }
546 
547 #undef VULKAN_FUNCTIONS
548 
549 static 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 
564 static void createSemaphore(VkSemaphore *semaphore)
565 {
567 
568  VkSemaphoreCreateInfo createInfo = {0};
570  result = vkCreateSemaphore(vulkanContext.device, &createInfo, NULL, semaphore);
571  if(result != VK_SUCCESS)
572  {
573  *semaphore = VK_NULL_HANDLE;
575  "vkCreateSemaphore(): %s\n",
576  getVulkanResultString(result));
577  quit(2);
578  }
579 }
580 
581 static void createSemaphores(void)
582 {
585 }
586 
587 static void getSurfaceCaps(void)
588 {
590  vulkanContext.physicalDevice, vulkanContext.surface, &vulkanContext.surfaceCapabilities);
591  if(result != VK_SUCCESS)
592  {
594  "vkGetPhysicalDeviceSurfaceCapabilitiesKHR(): %s\n",
595  getVulkanResultString(result));
596  quit(2);
597  }
598 
599  // check surface usage
601  {
603  "Vulkan surface doesn't support VK_IMAGE_USAGE_TRANSFER_DST_BIT\n");
604  quit(2);
605  }
606 }
607 
608 static void getSurfaceFormats(void)
609 {
611  vulkanContext.surface,
612  &vulkanContext.surfaceFormatsCount,
613  NULL);
614  if(result != VK_SUCCESS)
615  {
616  vulkanContext.surfaceFormatsCount = 0;
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 =
628  if(!vulkanContext.surfaceFormats)
629  {
630  vulkanContext.surfaceFormatsCount = 0;
631  SDL_OutOfMemory();
632  quit(2);
633  }
634  }
636  vulkanContext.surface,
637  &vulkanContext.surfaceFormatsCount,
638  vulkanContext.surfaceFormats);
639  if(result != VK_SUCCESS)
640  {
641  vulkanContext.surfaceFormatsCount = 0;
643  "vkGetPhysicalDeviceSurfaceFormatsKHR(): %s\n",
644  getVulkanResultString(result));
645  quit(2);
646  }
647 }
648 
649 static void getSwapchainImages(void)
650 {
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;
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;
681  "vkGetSwapchainImagesKHR(): %s\n",
682  getVulkanResultString(result));
683  quit(2);
684  }
685 }
686 
688 {
689  uint32_t i;
690  int w, h;
691  VkSwapchainCreateInfoKHR createInfo = {0};
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
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 
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;
737  createInfo.preTransform = vulkanContext.surfaceCapabilities.currentTransform;
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;
750  "vkCreateSwapchainKHR(): %s\n",
751  getVulkanResultString(result));
752  quit(2);
753  }
755  return SDL_TRUE;
756 }
757 
758 static 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 
767 static 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 
778 static void destroyCommandPool(void)
779 {
780  if(vulkanContext.commandPool)
781  vkDestroyCommandPool(vulkanContext.device, vulkanContext.commandPool, NULL);
782  vulkanContext.commandPool = VK_NULL_HANDLE;
783 }
784 
785 static void createCommandPool(void)
786 {
788 
789  VkCommandPoolCreateInfo createInfo = {0};
791  createInfo.flags =
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;
800  "vkCreateCommandPool(): %s\n",
801  getVulkanResultString(result));
802  quit(2);
803  }
804 }
805 
806 static void createCommandBuffers(void)
807 {
809 
810  VkCommandBufferAllocateInfo allocateInfo = {0};
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;
824  "vkAllocateCommandBuffers(): %s\n",
825  getVulkanResultString(result));
826  quit(2);
827  }
828 }
829 
830 static 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  {
843 
844  VkFenceCreateInfo createInfo = {0};
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;
858  "vkCreateFence(): %s\n",
859  getVulkanResultString(result));
860  quit(2);
861  }
862  }
863 }
864 
865 static 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 
879 static void recordPipelineImageBarrier(VkCommandBuffer commandBuffer,
880  VkAccessFlags sourceAccessMask,
881  VkAccessFlags destAccessMask,
882  VkImageLayout sourceLayout,
883  VkImageLayout destLayout,
884  VkImage image)
885 {
886  VkImageMemoryBarrier barrier = {0};
888  barrier.srcAccessMask = sourceAccessMask;
889  barrier.dstAccessMask = destAccessMask;
890  barrier.oldLayout = sourceLayout;
891  barrier.newLayout = destLayout;
894  barrier.image = image;
896  barrier.subresourceRange.baseMipLevel = 0;
897  barrier.subresourceRange.levelCount = 1;
898  barrier.subresourceRange.baseArrayLayer = 0;
899  barrier.subresourceRange.layerCount = 1;
900  vkCmdPipelineBarrier(commandBuffer,
903  0,
904  0,
905  NULL,
906  0,
907  NULL,
908  1,
909  &barrier);
910 }
911 
912 static 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  {
923  "vkResetCommandBuffer(): %s\n",
924  getVulkanResultString(result));
925  quit(2);
926  }
929  result = vkBeginCommandBuffer(commandBuffer, &beginInfo);
930  if(result != VK_SUCCESS)
931  {
933  "vkBeginCommandBuffer(): %s\n",
934  getVulkanResultString(result));
935  quit(2);
936  }
937  recordPipelineImageBarrier(commandBuffer,
938  0,
942  image);
944  clearRange.baseMipLevel = 0;
945  clearRange.levelCount = 1;
946  clearRange.baseArrayLayer = 0;
947  clearRange.layerCount = 1;
949  commandBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, clearColor, 1, &clearRange);
950  recordPipelineImageBarrier(commandBuffer,
955  image);
956  result = vkEndCommandBuffer(commandBuffer);
957  if(result != VK_SUCCESS)
958  {
960  "vkEndCommandBuffer(): %s\n",
961  getVulkanResultString(result));
962  quit(2);
963  }
964 }
965 
967 {
968  destroyFences();
971  if(doDestroySwapchain)
973 }
974 
976 {
978  getSurfaceCaps();
980  if(!createSwapchain())
981  return SDL_FALSE;
984  createFences();
985  return SDL_TRUE;
986 }
987 
988 static void initVulkan(void)
989 {
991  SDL_memset(&vulkanContext, 0, sizeof(VulkanContext));
993  createInstance();
995  createSurface();
997  createDevice();
999  getQueues();
1000  createSemaphores();
1002 }
1003 
1004 static void shutdownVulkan(void)
1005 {
1006  if(vulkanContext.device && vkDeviceWaitIdle)
1007  vkDeviceWaitIdle(vulkanContext.device);
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);
1021 }
1022 
1023 static SDL_bool render(void)
1024 {
1025  uint32_t frameIndex;
1026  VkResult result;
1027  double currentTime;
1028  VkClearColorValue clearColor = {0};
1030  VkSubmitInfo submitInfo = {0};
1031  VkPresentInfoKHR presentInfo = {0};
1032  int w, h;
1033 
1034  if(!vulkanContext.swapchain)
1035  {
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,
1046  &frameIndex);
1047  if(result == VK_ERROR_OUT_OF_DATE_KHR)
1049  if(result != VK_SUBOPTIMAL_KHR && result != VK_SUCCESS)
1050  {
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  }
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  {
1103  }
1104  if(result != VK_SUCCESS)
1105  {
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  {
1115  }
1116  return SDL_TRUE;
1117 }
1118 
1119 int main(int argc, char *argv[])
1120 {
1121  int fsaa, accel;
1122  int i, done;
1124  SDL_Event event;
1125  Uint32 then, now, frames;
1126  int dw, dh;
1127 
1128  /* Enable standard application logging */
1130 
1131  /* Initialize parameters */
1132  fsaa = 0;
1133  accel = -1;
1134 
1135  /* Initialize test framework */
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
const VkSwapchainKHR * pSwapchains
Definition: vulkan.h:3574
VkFormat format
Definition: vulkan.h:3493
#define SDL_Vulkan_GetDrawableSize
VkCommandPool commandPool
Definition: vulkan.h:2315
const VkSemaphore * pWaitSemaphores
Definition: vulkan.h:3572
VKAPI_ATTR VkResult VKAPI_CALL vkBeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo *pBeginInfo)
const VkCommandBuffer * pCommandBuffers
Definition: vulkan.h:1701
static void recordPipelineImageBarrier(VkCommandBuffer commandBuffer, VkAccessFlags sourceAccessMask, VkAccessFlags destAccessMask, VkImageLayout sourceLayout, VkImageLayout destLayout, VkImage image)
Definition: testvulkan.c:879
#define SDL_PollEvent
static void createCommandPool(void)
Definition: testvulkan.c:785
#define SDL_GetError
const uint32_t * pImageIndices
Definition: vulkan.h:3575
static void destroyCommandPool(void)
Definition: testvulkan.c:778
uint32_t swapchainCount
Definition: vulkan.h:3573
VkSurfaceKHR surface
Definition: testvulkan.c:180
GLuint64EXT * result
VkStructureType sType
Definition: vulkan.h:1695
VkQueue presentQueue
Definition: testvulkan.c:188
const VkApplicationInfo * pApplicationInfo
Definition: vulkan.h:1383
VKAPI_ATTR void VKAPI_CALL vkDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator)
GLeglImageOES image
Definition: SDL_opengl.h:2148
VKAPI_ATTR void VKAPI_CALL vkCmdPipelineBarrier(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers)
VkStructureType sType
Definition: vulkan.h:3548
const VkSemaphore * pWaitSemaphores
Definition: vulkan.h:1698
VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice, uint32_t *pQueueFamilyPropertyCount, VkQueueFamilyProperties *pQueueFamilyProperties)
uint32_t enabledExtensionCount
Definition: vulkan.h:1386
VKAPI_ATTR VkResult VKAPI_CALL vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo)
int main(int argc, char *argv[])
Definition: testvulkan.c:1119
VkStructureType sType
Definition: vulkan.h:1804
VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties *pProperties)
static void createSemaphores(void)
Definition: testvulkan.c:581
uint32_t apiVersion
Definition: vulkan.h:1376
#define UINT64_MAX
Definition: testvulkan.c:39
VKAPI_ATTR void VKAPI_CALL vkDestroyCommandPool(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks *pAllocator)
SDLTest_CommonState * SDLTest_CommonCreateState(char **argv, Uint32 flags)
Parse command line parameters and create common state.
VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, VkSurfaceKHR surface, VkBool32 *pSupported)
VkExtent2D swapchainSize
Definition: testvulkan.c:197
static void shutdownVulkan(void)
Definition: testvulkan.c:1004
VkImageLayout newLayout
Definition: vulkan.h:2436
GLfloat GLfloat GLfloat GLfloat h
uint32_t queueFamilyIndex
Definition: vulkan.h:1664
#define VULKAN_FUNCTIONS()
Definition: testvulkan.c:42
int SDLTest_CommonArg(SDLTest_CommonState *state, int index)
Process one common argument.
const char *const * ppEnabledExtensionNames
Definition: vulkan.h:1678
VkAccessFlags srcAccessMask
Definition: vulkan.h:2433
#define SDL_Vulkan_GetInstanceExtensions
Uint64 SDL_GetPerformanceFrequency(void)
Get the count per second of the high resolution counter.
VkSurfaceFormatKHR surfaceFormat
Definition: testvulkan.c:196
VKAPI_ATTR VkResult VKAPI_CALL vkCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchain)
VkSurfaceTransformFlagBitsKHR preTransform
Definition: vulkan.h:3561
uint32_t swapchainDesiredImageCount
Definition: testvulkan.c:195
VkSurfaceKHR surface
Definition: vulkan.h:3551
VkStructureType sType
Definition: vulkan.h:1661
The structure that defines a display mode.
Definition: SDL_video.h:53
VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkInstance *pInstance)
static void loadInstanceFunctions(void)
Definition: testvulkan.c:293
uint32_t VkBool32
Definition: vulkan.h:67
static void loadGlobalFunctions(void)
Definition: testvulkan.c:218
#define VK_KHR_SWAPCHAIN_EXTENSION_NAME
Definition: vulkan.h:3538
VkSwapchainKHR oldSwapchain
Definition: vulkan.h:3565
uint32_t srcQueueFamilyIndex
Definition: vulkan.h:2437
uint32_t Uint32
Definition: SDL_stdinc.h:181
#define VK_COLORSPACE_SRGB_NONLINEAR_KHR
Definition: vulkan.h:3417
const VkPipelineStageFlags * pWaitDstStageMask
Definition: vulkan.h:1699
SDL_bool SDLTest_CommonInit(SDLTest_CommonState *state)
Open test window.
VkFlags VkAccessFlags
Definition: vulkan.h:1318
uint32_t imageArrayLayers
Definition: vulkan.h:3556
uint32_t waitSemaphoreCount
Definition: vulkan.h:1697
VKAPI_ATTR void VKAPI_CALL vkDestroyFence(VkDevice device, VkFence fence, const VkAllocationCallbacks *pAllocator)
PFN_vkVoidFunction(VKAPI_PTR * PFN_vkGetInstanceProcAddr)(VkInstance instance, const char *pName)
Definition: vulkan.h:2484
VkCompositeAlphaFlagBitsKHR compositeAlpha
Definition: vulkan.h:3562
static SDL_bool createSwapchain(void)
Definition: testvulkan.c:687
static void createDevice(void)
Definition: testvulkan.c:497
#define SDL_Vulkan_CreateSurface
#define VK_NULL_HANDLE
Definition: vulkan.h:49
VKAPI_ATTR VkResult VKAPI_CALL vkEndCommandBuffer(VkCommandBuffer commandBuffer)
static void findPhysicalDevice(void)
Definition: testvulkan.c:324
VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures *pFeatures)
static const char * getVulkanResultString(VkResult result)
Definition: testvulkan.c:111
VkStructureType sType
Definition: vulkan.h:1810
VkResult
Definition: vulkan.h:122
uint32_t queueCreateInfoCount
Definition: vulkan.h:1673
SDL_Window ** windows
#define SDL_LogError
static SDLTest_CommonState * state
Definition: testvulkan.c:205
static void destroySwapchain(void)
Definition: testvulkan.c:758
VKAPI_ATTR void VKAPI_CALL vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks *pAllocator)
VkPhysicalDeviceProperties physicalDeviceProperties
Definition: testvulkan.c:182
static void getSurfaceFormats(void)
Definition: testvulkan.c:608
VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, VkPhysicalDevice *pPhysicalDevices)
VkCommandBufferLevel level
Definition: vulkan.h:2316
#define SDL_GetWindowSize
VkColorSpaceKHR colorSpace
Definition: vulkan.h:3494
VkSurfaceFormatKHR * surfaceFormats
Definition: testvulkan.c:192
SDL_bool retval
VKAPI_ATTR void VKAPI_CALL vkGetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue *pQueue)
static void getSwapchainImages(void)
Definition: testvulkan.c:649
#define SDL_Log
VkCommandBuffer * commandBuffers
Definition: testvulkan.c:201
VKAPI_ATTR VkResult VKAPI_CALL vkQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence)
VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t *pSwapchainImageCount, VkImage *pSwapchainImages)
VkInstance instance
Definition: testvulkan.c:178
VkStructureType sType
Definition: vulkan.h:1380
float float32[4]
Definition: vulkan.h:2376
VkSurfaceTransformFlagBitsKHR currentTransform
Definition: vulkan.h:3487
VkFence * fences
Definition: testvulkan.c:202
static void createSemaphore(VkSemaphore *semaphore)
Definition: testvulkan.c:564
VKAPI_ATTR VkResult VKAPI_CALL vkCreateSemaphore(VkDevice device, const VkSemaphoreCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkSemaphore *pSemaphore)
VkDevice device
Definition: testvulkan.c:179
void SDLTest_CommonEvent(SDLTest_CommonState *state, SDL_Event *event, int *done)
Common event handler for test windows.
VkImageLayout
Definition: vulkan.h:612
static PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr
Definition: testvulkan.c:94
static void initVulkan(void)
Definition: testvulkan.c:988
VkStructureType sType
Definition: vulkan.h:1670
VkSemaphore renderingFinishedSemaphore
Definition: testvulkan.c:190
#define SDL_Vulkan_LoadLibrary
Uint32 SDL_GetTicks(void)
Get the number of milliseconds since the SDL library initialization.
VkImageUsageFlags imageUsage
Definition: vulkan.h:3557
VkStructureType sType
Definition: vulkan.h:3569
VKAPI_ATTR VkResult VKAPI_CALL vkDeviceWaitIdle(VkDevice device)
VKAPI_ATTR VkResult VKAPI_CALL vkCreateFence(VkDevice device, const VkFenceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkFence *pFence)
uint32_t signalSemaphoreCount
Definition: vulkan.h:1702
#define SDL_free
struct _cl_event * event
VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t *pSurfaceFormatCount, VkSurfaceFormatKHR *pSurfaceFormats)
VkStructureType sType
Definition: vulkan.h:2332
VkAccessFlags dstAccessMask
Definition: vulkan.h:2434
const VkPhysicalDeviceFeatures * pEnabledFeatures
Definition: vulkan.h:1679
VkSurfaceCapabilitiesKHR surfaceCapabilities
Definition: testvulkan.c:191
VkSwapchainKHR swapchain
Definition: testvulkan.c:181
int done
Definition: checkkeys.c:28
uint32_t width
Definition: vulkan.h:1995
VkCommandBufferUsageFlags flags
Definition: vulkan.h:2334
VKAPI_ATTR void VKAPI_CALL vkDestroySemaphore(VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks *pAllocator)
VkFenceCreateFlags flags
Definition: vulkan.h:1806
#define VK_QUEUE_FAMILY_IGNORED
Definition: vulkan.h:104
VkImageUsageFlags supportedUsageFlags
Definition: vulkan.h:3489
GLenum mode
GLubyte GLubyte GLubyte GLubyte w
VkPresentModeKHR presentMode
Definition: vulkan.h:3563
static VulkanContext vulkanContext
Definition: testvulkan.c:206
uint32_t dstQueueFamilyIndex
Definition: vulkan.h:2438
#define VK_TRUE
Definition: vulkan.h:102
VkStructureType sType
Definition: vulkan.h:2313
#define VK_API_VERSION_1_0
Definition: vulkan.h:40
static void rerecordCommandBuffer(uint32_t frameIndex, const VkClearColorValue *clearColor)
Definition: testvulkan.c:912
uint32_t enabledExtensionCount
Definition: vulkan.h:1677
uint32_t swapchainImageCount
Definition: testvulkan.c:199
VkSharingMode imageSharingMode
Definition: vulkan.h:3558
VKAPI_ATTR VkResult VKAPI_CALL vkAllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo *pAllocateInfo, VkCommandBuffer *pCommandBuffers)
static void createInstance(void)
Definition: testvulkan.c:245
static void destroyCommandBuffers(void)
Definition: testvulkan.c:767
const char * SDLTest_CommonUsage(SDLTest_CommonState *state)
Returns common usage information.
const VkDeviceQueueCreateInfo * pQueueCreateInfos
Definition: vulkan.h:1674
static void quit(int rc)
Definition: testvulkan.c:211
VkStructureType sType
Definition: vulkan.h:2431
VkSemaphore imageAvailableSemaphore
Definition: testvulkan.c:189
static void getSurfaceCaps(void)
Definition: testvulkan.c:587
static void destroyFences(void)
Definition: testvulkan.c:865
#define SDL_GetPerformanceCounter
#define SDL_Delay
VkImageSubresourceRange subresourceRange
Definition: vulkan.h:2440
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
uint32_t commandBufferCount
Definition: vulkan.h:1700
#define SDL_LogSetPriority
#define NULL
Definition: begin_code.h:164
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_bool
Definition: SDL_stdinc.h:139
VKAPI_ATTR void VKAPI_CALL vkFreeCommandBuffers(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount, const VkCommandBuffer *pCommandBuffers)
VkImageAspectFlags aspectMask
Definition: vulkan.h:1885
unsigned int uint32_t
VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDevice *pDevice)
const float * pQueuePriorities
Definition: vulkan.h:1666
VkCommandPool commandPool
Definition: testvulkan.c:198
static void getQueues(void)
Definition: testvulkan.c:549
static void createFences(void)
Definition: testvulkan.c:830
VkQueue graphicsQueue
Definition: testvulkan.c:187
VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t *pImageIndex)
const char *const * ppEnabledExtensionNames
Definition: vulkan.h:1387
VKAPI_ATTR VkResult VKAPI_CALL vkResetFences(VkDevice device, uint32_t fenceCount, const VkFence *pFences)
VkCommandPoolCreateFlags flags
Definition: vulkan.h:2308
uint32_t baseArrayLayer
Definition: vulkan.h:1888
VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR *pSurfaceCapabilities)
#define SDL_Vulkan_GetVkGetInstanceProcAddr
VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName, uint32_t *pPropertyCount, VkExtensionProperties *pProperties)
VkStructureType sType
Definition: vulkan.h:2306
VKAPI_ATTR void VKAPI_CALL vkCmdClearColorImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearColorValue *pColor, uint32_t rangeCount, const VkImageSubresourceRange *pRanges)
VkPhysicalDeviceFeatures physicalDeviceFeatures
Definition: testvulkan.c:183
VkColorSpaceKHR imageColorSpace
Definition: vulkan.h:3554
#define VK_FALSE
Definition: vulkan.h:103
const VkSemaphore * pSignalSemaphores
Definition: vulkan.h:1703
static void loadDeviceFunctions(void)
Definition: testvulkan.c:529
uint32_t waitSemaphoreCount
Definition: vulkan.h:3571
static SDL_bool createNewSwapchainAndSwapchainSpecificStuff(void)
Definition: testvulkan.c:975
#define VK_VERSION_MAJOR(version)
Definition: vulkan.h:42
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:93
General event structure.
Definition: SDL_events.h:525
#define SDL_Vulkan_UnloadLibrary
#define SDL_malloc
VKAPI_ATTR VkResult VKAPI_CALL vkWaitForFences(VkDevice device, uint32_t fenceCount, const VkFence *pFences, VkBool32 waitAll, uint64_t timeout)
#define SDL_strcmp
VkPhysicalDevice physicalDevice
Definition: testvulkan.c:186
uint32_t presentQueueFamilyIndex
Definition: testvulkan.c:185
VKAPI_ATTR void VKAPI_CALL vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks *pAllocator)
VkImageLayout oldLayout
Definition: vulkan.h:2435
VkStructureType sType
Definition: vulkan.h:1370
Uint32 format
Definition: SDL_video.h:55
VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator)
VKAPI_ATTR VkResult VKAPI_CALL vkCreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkCommandPool *pCommandPool)
VkExtent2D imageExtent
Definition: vulkan.h:3555
uint32_t queueFamilyIndex
Definition: vulkan.h:2309
uint32_t surfaceFormatsAllocatedCount
Definition: testvulkan.c:193
#define SDL_GetCurrentDisplayMode
uint32_t graphicsQueueFamilyIndex
Definition: testvulkan.c:184
#define SDL_BITSPERPIXEL(X)
Definition: SDL_pixels.h:127
VKAPI_ATTR VkResult VKAPI_CALL vkResetCommandBuffer(VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags)
void SDLTest_CommonQuit(SDLTest_CommonState *state)
Close test window.
uint32_t height
Definition: vulkan.h:1996
#define SDL_INIT_VIDEO
Definition: SDL.h:78
#define SDL_memset
static SDL_bool render(void)
Definition: testvulkan.c:1023
static void createCommandBuffers(void)
Definition: testvulkan.c:806
#define SDL_sin
VkImage * swapchainImages
Definition: testvulkan.c:200
VkFlags VkPipelineStageFlags
Definition: vulkan.h:1128
static void createSurface(void)
Definition: testvulkan.c:311
static void destroySwapchainAndSwapchainSpecificStuff(SDL_bool doDestroySwapchain)
Definition: testvulkan.c:966
uint32_t surfaceFormatsCount
Definition: testvulkan.c:194