main.c 81 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264
  1. /* nuklear - 1.32.0 - public domain */
  2. #include <limits.h>
  3. #include <stdbool.h>
  4. #include <stddef.h>
  5. #include <stdint.h>
  6. #include <stdio.h>
  7. #include <time.h>
  8. #include <SDL2/SDL.h>
  9. #include <SDL2/SDL_vulkan.h>
  10. #include <vulkan/vulkan.h>
  11. #define NK_INCLUDE_FIXED_TYPES
  12. #define NK_INCLUDE_STANDARD_IO
  13. #define NK_INCLUDE_STANDARD_VARARGS
  14. #define NK_INCLUDE_DEFAULT_ALLOCATOR
  15. #define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
  16. #define NK_INCLUDE_FONT_BAKING
  17. #define NK_INCLUDE_DEFAULT_FONT
  18. #define NK_IMPLEMENTATION
  19. #define NK_SDL_VULKAN_IMPLEMENTATION
  20. #define NK_KEYSTATE_BASED_INPUT
  21. #include "../../nuklear.h"
  22. #include "nuklear_sdl_vulkan.h"
  23. #define WINDOW_WIDTH 1200
  24. #define WINDOW_HEIGHT 800
  25. #define MAX_VERTEX_BUFFER 512 * 1024
  26. #define MAX_ELEMENT_BUFFER 128 * 1024
  27. /* ===============================================================
  28. *
  29. * EXAMPLE
  30. *
  31. * ===============================================================*/
  32. /* This are some code examples to provide a small overview of what can be
  33. * done with this library. To try out an example uncomment the defines */
  34. /* #define INCLUDE_ALL */
  35. /* #define INCLUDE_STYLE */
  36. /* #define INCLUDE_CALCULATOR */
  37. /* #define INCLUDE_CANVAS */
  38. #define INCLUDE_OVERVIEW
  39. /*#define INCLUDE_CONFIGURATOR */
  40. /* #define INCLUDE_NODE_EDITOR */
  41. #ifdef INCLUDE_ALL
  42. #define INCLUDE_STYLE
  43. #define INCLUDE_CALCULATOR
  44. #define INCLUDE_CANVAS
  45. #define INCLUDE_OVERVIEW
  46. #define INCLUDE_CONFIGURATOR
  47. #define INCLUDE_NODE_EDITOR
  48. #endif
  49. #ifdef INCLUDE_STYLE
  50. #include "../../demo/common/style.c"
  51. #endif
  52. #ifdef INCLUDE_CALCULATOR
  53. #include "../../demo/common/calculator.c"
  54. #endif
  55. #ifdef INCLUDE_CANVAS
  56. #include "../../demo/common/canvas.c"
  57. #endif
  58. #ifdef INCLUDE_OVERVIEW
  59. #include "../../demo/common/overview.c"
  60. #endif
  61. #ifdef INCLUDE_CONFIGURATOR
  62. #include "../../demo/common/style_configurator.c"
  63. #endif
  64. #ifdef INCLUDE_NODE_EDITOR
  65. #include "../../demo/common/node_editor.c"
  66. #endif
  67. /* ===============================================================
  68. *
  69. * DEMO
  70. *
  71. * ===============================================================*/
  72. static const char *validation_layer_name = "VK_LAYER_KHRONOS_validation";
  73. struct queue_family_indices {
  74. int graphics;
  75. int present;
  76. };
  77. struct swap_chain_support_details {
  78. VkSurfaceCapabilitiesKHR capabilities;
  79. VkSurfaceFormatKHR *formats;
  80. uint32_t formats_len;
  81. VkPresentModeKHR *present_modes;
  82. uint32_t present_modes_len;
  83. };
  84. void swap_chain_support_details_free(
  85. struct swap_chain_support_details *swap_chain_support) {
  86. if (swap_chain_support->formats_len > 0) {
  87. free(swap_chain_support->formats);
  88. swap_chain_support->formats = NULL;
  89. }
  90. if (swap_chain_support->present_modes_len > 0) {
  91. free(swap_chain_support->present_modes);
  92. swap_chain_support->present_modes = NULL;
  93. }
  94. }
  95. struct vulkan_demo {
  96. SDL_Window *win;
  97. VkInstance instance;
  98. VkDebugUtilsMessengerEXT debug_messenger;
  99. VkSurfaceKHR surface;
  100. VkPhysicalDevice physical_device;
  101. struct queue_family_indices indices;
  102. VkDevice device;
  103. VkQueue graphics_queue;
  104. VkQueue present_queue;
  105. VkSampler sampler;
  106. VkSwapchainKHR swap_chain;
  107. VkImage *swap_chain_images;
  108. uint32_t swap_chain_images_len;
  109. VkImageView *swap_chain_image_views;
  110. VkFormat swap_chain_image_format;
  111. VkExtent2D swap_chain_image_extent;
  112. VkImage *overlay_images;
  113. VkImageView *overlay_image_views;
  114. VkDeviceMemory *overlay_image_memories;
  115. VkRenderPass render_pass;
  116. VkFramebuffer *framebuffers;
  117. VkDescriptorSetLayout descriptor_set_layout;
  118. VkDescriptorPool descriptor_pool;
  119. VkDescriptorSet *descriptor_sets;
  120. VkPipelineLayout pipeline_layout;
  121. VkPipeline pipeline;
  122. VkCommandPool command_pool;
  123. VkCommandBuffer *command_buffers;
  124. VkSemaphore image_available;
  125. VkSemaphore render_finished;
  126. VkImage demo_texture_image;
  127. VkImageView demo_texture_image_view;
  128. VkDeviceMemory demo_texture_memory;
  129. VkFence render_fence;
  130. };
  131. VKAPI_ATTR VkBool32 VKAPI_CALL
  132. vulkan_debug_callback(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
  133. VkDebugUtilsMessageTypeFlagsEXT message_type,
  134. const VkDebugUtilsMessengerCallbackDataEXT *callback_data,
  135. void *user_data) {
  136. (void)message_severity;
  137. (void)message_type;
  138. (void)user_data;
  139. fprintf(stderr, "validation layer: %s\n", callback_data->pMessage);
  140. return VK_FALSE;
  141. }
  142. bool check_validation_layer_support() {
  143. uint32_t layer_count;
  144. bool ret = false;
  145. VkResult result;
  146. uint32_t i;
  147. VkLayerProperties *available_layers = NULL;
  148. result = vkEnumerateInstanceLayerProperties(&layer_count, NULL);
  149. if (result != VK_SUCCESS) {
  150. fprintf(stderr, "vkEnumerateInstanceLayerProperties failed: %d\n",
  151. result);
  152. return ret;
  153. }
  154. available_layers = malloc(layer_count * sizeof(VkLayerProperties));
  155. result = vkEnumerateInstanceLayerProperties(&layer_count, available_layers);
  156. if (result != VK_SUCCESS) {
  157. fprintf(stderr, "vkEnumerateInstanceLayerProperties failed: %d\n",
  158. result);
  159. goto cleanup;
  160. }
  161. printf("Available vulkan layers:\n");
  162. for (i = 0; i < layer_count; i++) {
  163. printf(" %s\n", available_layers[i].layerName);
  164. if (strcmp(validation_layer_name, available_layers[i].layerName) == 0) {
  165. ret = true;
  166. break;
  167. }
  168. }
  169. cleanup:
  170. free(available_layers);
  171. return ret;
  172. }
  173. VkResult create_debug_utils_messenger_ext(
  174. VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
  175. const VkAllocationCallbacks *pAllocator,
  176. VkDebugUtilsMessengerEXT *pDebugMessenger) {
  177. PFN_vkCreateDebugUtilsMessengerEXT func =
  178. (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(
  179. instance, "vkCreateDebugUtilsMessengerEXT");
  180. if (func != NULL) {
  181. return func(instance, pCreateInfo, pAllocator, pDebugMessenger);
  182. } else {
  183. return VK_ERROR_EXTENSION_NOT_PRESENT;
  184. }
  185. }
  186. bool create_debug_callback(struct vulkan_demo *demo) {
  187. VkResult result;
  188. VkDebugUtilsMessengerCreateInfoEXT create_info;
  189. memset(&create_info, 0, sizeof(VkDebugUtilsMessengerCreateInfoEXT));
  190. create_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
  191. create_info.messageSeverity =
  192. VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
  193. VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
  194. create_info.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
  195. VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
  196. VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
  197. create_info.pfnUserCallback = vulkan_debug_callback;
  198. result = create_debug_utils_messenger_ext(demo->instance, &create_info,
  199. NULL, &demo->debug_messenger);
  200. if (result != VK_SUCCESS) {
  201. fprintf(stderr, "create_debug_utils_messenger_ext failed %d\n", result);
  202. return false;
  203. }
  204. return true;
  205. }
  206. bool create_instance(struct vulkan_demo *demo) {
  207. uint32_t i;
  208. uint32_t available_instance_extension_count;
  209. VkResult result;
  210. VkExtensionProperties *available_instance_extensions = NULL;
  211. bool ret = false;
  212. VkApplicationInfo app_info;
  213. VkInstanceCreateInfo create_info;
  214. uint32_t sdl_extension_count;
  215. uint32_t enabled_extension_count;
  216. const char **enabled_extensions = NULL;
  217. bool validation_layers_installed;
  218. validation_layers_installed = check_validation_layer_support();
  219. if (!validation_layers_installed) {
  220. fprintf(stdout,
  221. "Couldn't find validation layer %s. Continuing without "
  222. "validation layers.\n",
  223. validation_layer_name);
  224. }
  225. result = vkEnumerateInstanceExtensionProperties(
  226. NULL, &available_instance_extension_count, NULL);
  227. if (result != VK_SUCCESS) {
  228. fprintf(stderr, "vkEnumerateInstanceExtensionProperties failed %d\n",
  229. result);
  230. return ret;
  231. }
  232. available_instance_extensions = malloc(available_instance_extension_count *
  233. sizeof(VkExtensionProperties));
  234. result = vkEnumerateInstanceExtensionProperties(
  235. NULL, &available_instance_extension_count,
  236. available_instance_extensions);
  237. if (result != VK_SUCCESS) {
  238. fprintf(stderr, "vkEnumerateInstanceExtensionProperties failed %d\n",
  239. result);
  240. goto cleanup;
  241. }
  242. printf("available instance extensions:\n");
  243. for (i = 0; i < available_instance_extension_count; i++) {
  244. printf(" %s\n", available_instance_extensions[i].extensionName);
  245. }
  246. if (SDL_Vulkan_GetInstanceExtensions(demo->win, &sdl_extension_count,
  247. NULL) != SDL_TRUE) {
  248. fprintf(stderr, "SDL_Vulkan_GetInstanceExtensions failed: %s\n",
  249. SDL_GetError());
  250. goto cleanup;
  251. }
  252. enabled_extension_count =
  253. sdl_extension_count + (validation_layers_installed ? 1 : 0);
  254. enabled_extensions = malloc(enabled_extension_count * sizeof(char *));
  255. if (SDL_Vulkan_GetInstanceExtensions(demo->win, &sdl_extension_count,
  256. enabled_extensions) != SDL_TRUE) {
  257. fprintf(stderr, "SDL_Vulkan_GetInstanceExtensions failed: %s\n",
  258. SDL_GetError());
  259. goto cleanup;
  260. }
  261. if (validation_layers_installed) {
  262. enabled_extensions[sdl_extension_count] =
  263. VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
  264. }
  265. printf("Trying to enable the following instance extensions: ");
  266. for (i = 0; i < enabled_extension_count; i++) {
  267. if (i > 0) {
  268. printf(", ");
  269. }
  270. printf("%s\n", enabled_extensions[i]);
  271. }
  272. printf("\n");
  273. for (i = 0; i < enabled_extension_count; i++) {
  274. int extension_missing = 1;
  275. uint32_t j;
  276. for (j = 0; j < available_instance_extension_count; j++) {
  277. if (strcmp(enabled_extensions[i],
  278. available_instance_extensions[j].extensionName) == 0) {
  279. extension_missing = 0;
  280. break;
  281. }
  282. }
  283. if (extension_missing) {
  284. fprintf(stderr, "Extension %s is missing\n", enabled_extensions[i]);
  285. return ret;
  286. }
  287. }
  288. memset(&app_info, 0, sizeof(VkApplicationInfo));
  289. app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
  290. app_info.pApplicationName = "Demo";
  291. app_info.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
  292. app_info.pEngineName = "No Engine";
  293. app_info.engineVersion = VK_MAKE_VERSION(1, 0, 0);
  294. app_info.apiVersion = VK_API_VERSION_1_0;
  295. memset(&create_info, 0, sizeof(VkInstanceCreateInfo));
  296. create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
  297. create_info.pApplicationInfo = &app_info;
  298. create_info.enabledExtensionCount = enabled_extension_count;
  299. create_info.ppEnabledExtensionNames = enabled_extensions;
  300. if (validation_layers_installed) {
  301. create_info.enabledLayerCount = 1;
  302. create_info.ppEnabledLayerNames = &validation_layer_name;
  303. }
  304. result = vkCreateInstance(&create_info, NULL, &demo->instance);
  305. if (result != VK_SUCCESS) {
  306. fprintf(stderr, "vkCreateInstance result %d\n", result);
  307. return ret;
  308. }
  309. if (validation_layers_installed) {
  310. ret = create_debug_callback(demo);
  311. } else {
  312. ret = true;
  313. }
  314. cleanup:
  315. if (available_instance_extensions) {
  316. free(available_instance_extensions);
  317. }
  318. if (enabled_extensions) {
  319. free(enabled_extensions);
  320. }
  321. return ret;
  322. }
  323. bool create_surface(struct vulkan_demo *demo) {
  324. SDL_bool result;
  325. result =
  326. SDL_Vulkan_CreateSurface(demo->win, demo->instance, &demo->surface);
  327. if (result != SDL_TRUE) {
  328. fprintf(stderr, "creating vulkan surface failed: %s\n", SDL_GetError());
  329. return false;
  330. }
  331. return true;
  332. }
  333. bool find_queue_families(VkPhysicalDevice physical_device, VkSurfaceKHR surface,
  334. struct queue_family_indices *indices) {
  335. VkResult result;
  336. uint32_t queue_family_count = 0;
  337. uint32_t i = 0;
  338. bool ret = false;
  339. VkQueueFamilyProperties *queue_family_properties;
  340. VkBool32 present_support;
  341. vkGetPhysicalDeviceQueueFamilyProperties(physical_device,
  342. &queue_family_count, NULL);
  343. queue_family_properties =
  344. malloc(queue_family_count * sizeof(VkQueueFamilyProperties));
  345. vkGetPhysicalDeviceQueueFamilyProperties(
  346. physical_device, &queue_family_count, queue_family_properties);
  347. for (i = 0; i < queue_family_count; i++) {
  348. if (queue_family_properties[i].queueCount == 0) {
  349. continue;
  350. }
  351. if (queue_family_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
  352. indices->graphics = i;
  353. }
  354. result = vkGetPhysicalDeviceSurfaceSupportKHR(
  355. physical_device, i, surface, &present_support);
  356. if (result != VK_SUCCESS) {
  357. fprintf(stderr,
  358. "vkGetPhysicalDeviceSurfaceSupportKHR failed with %d\n",
  359. result);
  360. goto cleanup;
  361. }
  362. if (present_support == VK_TRUE) {
  363. indices->present = i;
  364. }
  365. if (indices->graphics >= 0 && indices->present >= 0) {
  366. break;
  367. }
  368. }
  369. ret = true;
  370. cleanup:
  371. free(queue_family_properties);
  372. return ret;
  373. }
  374. bool query_swap_chain_support(
  375. VkPhysicalDevice device, VkSurfaceKHR surface,
  376. struct swap_chain_support_details *swap_chain_support) {
  377. VkResult result;
  378. result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
  379. device, surface, &swap_chain_support->capabilities);
  380. if (result != VK_SUCCESS) {
  381. fprintf(stderr,
  382. "vkGetPhysicalDeviceSurfaceCapabilitiesKHR failed: %d\n",
  383. result);
  384. return false;
  385. }
  386. result = vkGetPhysicalDeviceSurfaceFormatsKHR(
  387. device, surface, &swap_chain_support->formats_len, NULL);
  388. if (result != VK_SUCCESS) {
  389. fprintf(stderr, "vkGetPhysicalDeviceSurfaceFormatsKHR failed: %d\n",
  390. result);
  391. return false;
  392. }
  393. if (swap_chain_support->formats_len != 0) {
  394. swap_chain_support->formats = malloc(swap_chain_support->formats_len *
  395. sizeof(VkSurfaceFormatKHR));
  396. result = vkGetPhysicalDeviceSurfaceFormatsKHR(
  397. device, surface, &swap_chain_support->formats_len,
  398. swap_chain_support->formats);
  399. if (result != VK_SUCCESS) {
  400. fprintf(stderr, "vkGetPhysicalDeviceSurfaceFormatsKHR failed: %d\n",
  401. result);
  402. return false;
  403. }
  404. }
  405. result = vkGetPhysicalDeviceSurfacePresentModesKHR(
  406. device, surface, &swap_chain_support->present_modes_len, NULL);
  407. if (result != VK_SUCCESS) {
  408. fprintf(stderr,
  409. "vkGetPhysicalDeviceSurfacePresentModesKHR failed: %d\n",
  410. result);
  411. return false;
  412. }
  413. if (swap_chain_support->present_modes_len != 0) {
  414. swap_chain_support->present_modes = malloc(
  415. swap_chain_support->present_modes_len * sizeof(VkPresentModeKHR));
  416. result = vkGetPhysicalDeviceSurfacePresentModesKHR(
  417. device, surface, &swap_chain_support->present_modes_len,
  418. swap_chain_support->present_modes);
  419. if (result != VK_SUCCESS) {
  420. fprintf(stderr,
  421. "vkGetPhysicalDeviceSurfacePresentModesKHR failed: %d\n",
  422. result);
  423. return false;
  424. }
  425. }
  426. return true;
  427. }
  428. bool is_suitable_physical_device(VkPhysicalDevice physical_device,
  429. VkSurfaceKHR surface,
  430. struct queue_family_indices *indices) {
  431. VkResult result;
  432. uint32_t device_extension_count;
  433. uint32_t i;
  434. VkExtensionProperties *device_extensions;
  435. bool ret = false;
  436. struct swap_chain_support_details swap_chain_support;
  437. int found_khr_surface = 0;
  438. VkPhysicalDeviceProperties device_properties;
  439. vkGetPhysicalDeviceProperties(physical_device, &device_properties);
  440. printf("Probing physical device %s\n", device_properties.deviceName);
  441. result = vkEnumerateDeviceExtensionProperties(
  442. physical_device, NULL, &device_extension_count, NULL);
  443. if (result != VK_SUCCESS) {
  444. fprintf(stderr, "vkEnumerateDeviceExtensionProperties failed: %d\n",
  445. result);
  446. return false;
  447. }
  448. device_extensions =
  449. malloc(device_extension_count * sizeof(VkExtensionProperties));
  450. result = vkEnumerateDeviceExtensionProperties(
  451. physical_device, NULL, &device_extension_count, device_extensions);
  452. if (result != VK_SUCCESS) {
  453. fprintf(stderr, "vkEnumerateDeviceExtensionProperties failed: %d\n",
  454. result);
  455. goto cleanup;
  456. }
  457. printf(" Supported device extensions:\n");
  458. for (i = 0; i < device_extension_count; i++) {
  459. printf(" %s\n", device_extensions[i].extensionName);
  460. if (strcmp(VK_KHR_SWAPCHAIN_EXTENSION_NAME,
  461. device_extensions[i].extensionName) == 0) {
  462. found_khr_surface = 1;
  463. break;
  464. }
  465. }
  466. if (!found_khr_surface) {
  467. printf(" Device doesnt support %s\n", VK_KHR_SWAPCHAIN_EXTENSION_NAME);
  468. goto cleanup;
  469. }
  470. if (!find_queue_families(physical_device, surface, indices)) {
  471. goto cleanup;
  472. }
  473. if (indices->graphics < 0 || indices->present < 0) {
  474. printf(" Device is missing graphics and/or present support. graphics: "
  475. "%d, present: %d\n",
  476. indices->graphics, indices->present);
  477. goto cleanup;
  478. }
  479. if (!query_swap_chain_support(physical_device, surface,
  480. &swap_chain_support)) {
  481. goto cleanup;
  482. }
  483. if (swap_chain_support.formats_len == 0) {
  484. printf(" Device doesn't support any swap chain formats\n");
  485. goto cleanup;
  486. }
  487. if (swap_chain_support.present_modes_len == 0) {
  488. printf(" Device doesn't support any swap chain present modes\n");
  489. goto cleanup;
  490. }
  491. ret = true;
  492. cleanup:
  493. free(device_extensions);
  494. swap_chain_support_details_free(&swap_chain_support);
  495. return ret;
  496. }
  497. bool create_physical_device(struct vulkan_demo *demo) {
  498. uint32_t device_count = 0;
  499. VkPhysicalDevice *physical_devices;
  500. VkResult result;
  501. uint32_t i;
  502. bool ret = false;
  503. result = vkEnumeratePhysicalDevices(demo->instance, &device_count, NULL);
  504. if (result != VK_SUCCESS) {
  505. fprintf(stderr, "vkEnumeratePhysicalDevices failed: %d\n", result);
  506. return ret;
  507. }
  508. if (device_count == 0) {
  509. fprintf(stderr, "no vulkan capable GPU found!");
  510. return ret;
  511. }
  512. physical_devices = malloc(device_count * sizeof(VkPhysicalDevice));
  513. result = vkEnumeratePhysicalDevices(demo->instance, &device_count,
  514. physical_devices);
  515. if (result != VK_SUCCESS) {
  516. fprintf(stderr, "vkEnumeratePhysicalDevices failed: %d\n", result);
  517. goto cleanup;
  518. }
  519. for (i = 0; i < device_count; i++) {
  520. struct queue_family_indices indices = {-1, -1};
  521. if (is_suitable_physical_device(physical_devices[i], demo->surface,
  522. &indices)) {
  523. printf(" Selecting this device for rendering. Queue families: "
  524. "graphics: %d, present: %d!\n",
  525. indices.graphics, indices.present);
  526. demo->physical_device = physical_devices[i];
  527. demo->indices = indices;
  528. break;
  529. }
  530. }
  531. if (demo->physical_device == NULL) {
  532. fprintf(stderr, "failed to find a suitable GPU!\n");
  533. } else {
  534. ret = true;
  535. }
  536. cleanup:
  537. free(physical_devices);
  538. return ret;
  539. }
  540. bool create_logical_device(struct vulkan_demo *demo) {
  541. VkResult result;
  542. bool ret = false;
  543. float queuePriority = 1.0f;
  544. uint32_t num_queues = 1;
  545. VkDeviceQueueCreateInfo *queue_create_infos;
  546. VkDeviceCreateInfo create_info;
  547. const char *swap_chain_extension_name = VK_KHR_SWAPCHAIN_EXTENSION_NAME;
  548. queue_create_infos = calloc(2, sizeof(VkDeviceQueueCreateInfo));
  549. queue_create_infos[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
  550. queue_create_infos[0].queueFamilyIndex = demo->indices.graphics;
  551. queue_create_infos[0].queueCount = 1;
  552. queue_create_infos[0].pQueuePriorities = &queuePriority;
  553. if (demo->indices.present != demo->indices.graphics) {
  554. queue_create_infos[1].sType =
  555. VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
  556. queue_create_infos[1].queueFamilyIndex = demo->indices.present;
  557. queue_create_infos[1].queueCount = 1;
  558. queue_create_infos[1].pQueuePriorities = &queuePriority;
  559. num_queues = 2;
  560. }
  561. memset(&create_info, 0, sizeof(VkDeviceCreateInfo));
  562. create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
  563. create_info.queueCreateInfoCount = num_queues;
  564. create_info.pQueueCreateInfos = queue_create_infos;
  565. create_info.enabledExtensionCount = 1;
  566. create_info.ppEnabledExtensionNames = &swap_chain_extension_name;
  567. result = vkCreateDevice(demo->physical_device, &create_info, NULL,
  568. &demo->device);
  569. if (result != VK_SUCCESS) {
  570. fprintf(stderr, "vkCreateDevice failed: %d\n", result);
  571. goto cleanup;
  572. }
  573. vkGetDeviceQueue(demo->device, demo->indices.graphics, 0,
  574. &demo->graphics_queue);
  575. vkGetDeviceQueue(demo->device, demo->indices.present, 0,
  576. &demo->present_queue);
  577. ret = true;
  578. cleanup:
  579. free(queue_create_infos);
  580. return ret;
  581. }
  582. bool create_sampler(struct vulkan_demo *demo) {
  583. VkResult result;
  584. VkSamplerCreateInfo sampler_info;
  585. memset(&sampler_info, 0, sizeof(VkSamplerCreateInfo));
  586. sampler_info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
  587. sampler_info.pNext = NULL;
  588. sampler_info.maxAnisotropy = 1.0;
  589. sampler_info.magFilter = VK_FILTER_LINEAR;
  590. sampler_info.minFilter = VK_FILTER_LINEAR;
  591. sampler_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
  592. sampler_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
  593. sampler_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
  594. sampler_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
  595. sampler_info.mipLodBias = 0.0f;
  596. sampler_info.compareEnable = VK_FALSE;
  597. sampler_info.compareOp = VK_COMPARE_OP_ALWAYS;
  598. sampler_info.minLod = 0.0f;
  599. sampler_info.maxLod = 0.0f;
  600. sampler_info.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK;
  601. result = vkCreateSampler(demo->device, &sampler_info, NULL, &demo->sampler);
  602. if (result != VK_SUCCESS) {
  603. fprintf(stderr, "vkCreateSampler failed: %d\n", result);
  604. return false;
  605. }
  606. return true;
  607. }
  608. VkSurfaceFormatKHR
  609. choose_swap_surface_format(VkSurfaceFormatKHR *available_formats,
  610. uint32_t available_formats_len) {
  611. VkSurfaceFormatKHR undefined_format = {VK_FORMAT_B8G8R8A8_UNORM,
  612. VK_COLOR_SPACE_SRGB_NONLINEAR_KHR};
  613. uint32_t i;
  614. if (available_formats_len == 1 &&
  615. available_formats[0].format == VK_FORMAT_UNDEFINED) {
  616. return undefined_format;
  617. }
  618. for (i = 0; i < available_formats_len; i++) {
  619. if (available_formats[i].format == VK_FORMAT_B8G8R8A8_UNORM &&
  620. available_formats[i].colorSpace ==
  621. VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
  622. return available_formats[i];
  623. }
  624. }
  625. return available_formats[0];
  626. }
  627. VkPresentModeKHR
  628. choose_swap_present_mode(VkPresentModeKHR *available_present_modes,
  629. uint32_t available_present_modes_len) {
  630. uint32_t i;
  631. for (i = 0; i < available_present_modes_len; i++) {
  632. /*
  633. best mode to ensure good input latency while ensuring we are not
  634. producing tearing
  635. */
  636. if (available_present_modes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
  637. return available_present_modes[i];
  638. }
  639. }
  640. /* must be supported */
  641. return VK_PRESENT_MODE_FIFO_KHR;
  642. }
  643. VkExtent2D choose_swap_extent(struct vulkan_demo *demo,
  644. VkSurfaceCapabilitiesKHR *capabilities) {
  645. int width, height;
  646. VkExtent2D actual_extent;
  647. if (capabilities->currentExtent.width != 0xFFFFFFFF) {
  648. return capabilities->currentExtent;
  649. } else {
  650. /* not window size! */
  651. SDL_Vulkan_GetDrawableSize(demo->win, &width, &height);
  652. actual_extent.width = (uint32_t)width;
  653. actual_extent.height = (uint32_t)height;
  654. actual_extent.width = NK_MAX(
  655. capabilities->minImageExtent.width,
  656. NK_MIN(capabilities->maxImageExtent.width, actual_extent.width));
  657. actual_extent.height = NK_MAX(
  658. capabilities->minImageExtent.height,
  659. NK_MIN(capabilities->maxImageExtent.height, actual_extent.height));
  660. return actual_extent;
  661. }
  662. }
  663. bool create_swap_chain(struct vulkan_demo *demo) {
  664. struct swap_chain_support_details swap_chain_support;
  665. VkSurfaceFormatKHR surface_format;
  666. VkPresentModeKHR present_mode;
  667. VkExtent2D extent;
  668. VkResult result;
  669. VkSwapchainCreateInfoKHR create_info;
  670. uint32_t queue_family_indices[2];
  671. bool ret = false;
  672. queue_family_indices[0] = (uint32_t)demo->indices.graphics;
  673. queue_family_indices[1] = (uint32_t)demo->indices.present;
  674. if (!query_swap_chain_support(demo->physical_device, demo->surface,
  675. &swap_chain_support)) {
  676. goto cleanup;
  677. }
  678. surface_format = choose_swap_surface_format(swap_chain_support.formats,
  679. swap_chain_support.formats_len);
  680. present_mode = choose_swap_present_mode(
  681. swap_chain_support.present_modes, swap_chain_support.present_modes_len);
  682. extent = choose_swap_extent(demo, &swap_chain_support.capabilities);
  683. demo->swap_chain_images_len =
  684. swap_chain_support.capabilities.minImageCount + 1;
  685. if (swap_chain_support.capabilities.maxImageCount > 0 &&
  686. demo->swap_chain_images_len >
  687. swap_chain_support.capabilities.maxImageCount) {
  688. demo->swap_chain_images_len =
  689. swap_chain_support.capabilities.maxImageCount;
  690. }
  691. memset(&create_info, 0, sizeof(VkSwapchainCreateInfoKHR));
  692. create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
  693. create_info.surface = demo->surface;
  694. create_info.minImageCount = demo->swap_chain_images_len;
  695. create_info.imageFormat = surface_format.format;
  696. create_info.imageColorSpace = surface_format.colorSpace;
  697. create_info.imageExtent = extent;
  698. create_info.imageArrayLayers = 1;
  699. create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
  700. if (demo->indices.graphics != demo->indices.present) {
  701. create_info.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
  702. create_info.queueFamilyIndexCount = 2;
  703. create_info.pQueueFamilyIndices = queue_family_indices;
  704. } else {
  705. create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
  706. }
  707. create_info.preTransform = swap_chain_support.capabilities.currentTransform;
  708. create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
  709. create_info.presentMode = present_mode;
  710. create_info.clipped = VK_TRUE;
  711. result = vkCreateSwapchainKHR(demo->device, &create_info, NULL,
  712. &demo->swap_chain);
  713. if (result != VK_SUCCESS) {
  714. fprintf(stderr, "vkCreateSwapchainKHR failed: %d\n", result);
  715. goto cleanup;
  716. }
  717. result = vkGetSwapchainImagesKHR(demo->device, demo->swap_chain,
  718. &demo->swap_chain_images_len, NULL);
  719. if (result != VK_SUCCESS) {
  720. fprintf(stderr, "vkGetSwapchainImagesKHR failed: %d\n", result);
  721. goto cleanup;
  722. }
  723. if (demo->swap_chain_images == NULL) {
  724. demo->swap_chain_images =
  725. malloc(demo->swap_chain_images_len * sizeof(VkImage));
  726. }
  727. result = vkGetSwapchainImagesKHR(demo->device, demo->swap_chain,
  728. &demo->swap_chain_images_len,
  729. demo->swap_chain_images);
  730. if (result != VK_SUCCESS) {
  731. fprintf(stderr, "vkGetSwapchainImagesKHR failed: %d\n", result);
  732. return false;
  733. }
  734. demo->swap_chain_image_format = surface_format.format;
  735. demo->swap_chain_image_extent = extent;
  736. ret = true;
  737. cleanup:
  738. swap_chain_support_details_free(&swap_chain_support);
  739. return ret;
  740. }
  741. bool create_swap_chain_image_views(struct vulkan_demo *demo) {
  742. uint32_t i;
  743. VkResult result;
  744. VkImageViewCreateInfo create_info;
  745. memset(&create_info, 0, sizeof(VkImageViewCreateInfo));
  746. create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
  747. create_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
  748. create_info.format = demo->swap_chain_image_format;
  749. create_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
  750. create_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
  751. create_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
  752. create_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
  753. create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  754. create_info.subresourceRange.baseMipLevel = 0;
  755. create_info.subresourceRange.levelCount = 1;
  756. create_info.subresourceRange.baseArrayLayer = 0;
  757. create_info.subresourceRange.layerCount = 1;
  758. if (!demo->swap_chain_image_views) {
  759. demo->swap_chain_image_views =
  760. malloc(demo->swap_chain_images_len * sizeof(VkImageView));
  761. }
  762. for (i = 0; i < demo->swap_chain_images_len; i++) {
  763. create_info.image = demo->swap_chain_images[i];
  764. result = vkCreateImageView(demo->device, &create_info, NULL,
  765. &demo->swap_chain_image_views[i]);
  766. if (result != VK_SUCCESS) {
  767. fprintf(stderr, "vkCreateImageView failed: %d\n", result);
  768. return false;
  769. }
  770. }
  771. return true;
  772. }
  773. bool create_overlay_images(struct vulkan_demo *demo) {
  774. uint32_t i, j;
  775. VkResult result;
  776. VkMemoryRequirements mem_requirements;
  777. VkPhysicalDeviceMemoryProperties mem_properties;
  778. int found;
  779. VkImageCreateInfo image_info;
  780. VkMemoryAllocateInfo alloc_info;
  781. VkImageViewCreateInfo image_view_info;
  782. memset(&image_info, 0, sizeof(VkImageCreateInfo));
  783. image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
  784. image_info.imageType = VK_IMAGE_TYPE_2D;
  785. image_info.extent.width = demo->swap_chain_image_extent.width;
  786. image_info.extent.height = demo->swap_chain_image_extent.height;
  787. image_info.extent.depth = 1;
  788. image_info.mipLevels = 1;
  789. image_info.arrayLayers = 1;
  790. image_info.format = demo->swap_chain_image_format;
  791. image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
  792. image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  793. image_info.usage =
  794. VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
  795. image_info.samples = VK_SAMPLE_COUNT_1_BIT;
  796. image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
  797. memset(&alloc_info, 0, sizeof(VkMemoryAllocateInfo));
  798. alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
  799. memset(&image_view_info, 0, sizeof(VkImageViewCreateInfo));
  800. image_view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
  801. image_view_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
  802. image_view_info.format = demo->swap_chain_image_format;
  803. image_view_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
  804. image_view_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
  805. image_view_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
  806. image_view_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
  807. image_view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  808. image_view_info.subresourceRange.baseMipLevel = 0;
  809. image_view_info.subresourceRange.levelCount = 1;
  810. image_view_info.subresourceRange.baseArrayLayer = 0;
  811. image_view_info.subresourceRange.layerCount = 1;
  812. if (!demo->overlay_images) {
  813. demo->overlay_images =
  814. malloc(demo->swap_chain_images_len * sizeof(VkImage));
  815. }
  816. if (!demo->overlay_image_memories) {
  817. demo->overlay_image_memories =
  818. malloc(demo->swap_chain_images_len * sizeof(VkDeviceMemory));
  819. }
  820. if (!demo->overlay_image_views) {
  821. demo->overlay_image_views =
  822. malloc(demo->swap_chain_images_len * sizeof(VkImageView));
  823. }
  824. for (i = 0; i < demo->swap_chain_images_len; i++) {
  825. result = vkCreateImage(demo->device, &image_info, NULL,
  826. &demo->overlay_images[i]);
  827. if (result != VK_SUCCESS) {
  828. fprintf(stderr, "vkCreateImage failed for index %lu: %d\n",
  829. (unsigned long)i, result);
  830. return false;
  831. }
  832. vkGetImageMemoryRequirements(demo->device, demo->overlay_images[i],
  833. &mem_requirements);
  834. alloc_info.allocationSize = mem_requirements.size;
  835. vkGetPhysicalDeviceMemoryProperties(demo->physical_device,
  836. &mem_properties);
  837. found = 0;
  838. for (j = 0; j < mem_properties.memoryTypeCount; j++) {
  839. if ((mem_requirements.memoryTypeBits & (1 << j)) &&
  840. (mem_properties.memoryTypes[j].propertyFlags &
  841. VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) ==
  842. VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
  843. found = 1;
  844. break;
  845. }
  846. }
  847. if (!found) {
  848. fprintf(stderr,
  849. "failed to find suitable memory type for index %lu!\n",
  850. (unsigned long)i);
  851. return false;
  852. }
  853. alloc_info.memoryTypeIndex = j;
  854. result = vkAllocateMemory(demo->device, &alloc_info, NULL,
  855. &demo->overlay_image_memories[i]);
  856. if (result != VK_SUCCESS) {
  857. fprintf(stderr,
  858. "failed to allocate vulkan memory for index %lu: %d!\n",
  859. (unsigned long)i, result);
  860. return false;
  861. }
  862. result = vkBindImageMemory(demo->device, demo->overlay_images[i],
  863. demo->overlay_image_memories[i], 0);
  864. if (result != VK_SUCCESS) {
  865. fprintf(stderr, "Couldn't bind image memory for index %lu: %d\n",
  866. (unsigned long)i, result);
  867. return false;
  868. }
  869. image_view_info.image = demo->overlay_images[i];
  870. result = vkCreateImageView(demo->device, &image_view_info, NULL,
  871. &demo->overlay_image_views[i]);
  872. if (result != VK_SUCCESS) {
  873. fprintf(stderr, "vkCreateImageView failed for index %lu: %d\n",
  874. (unsigned long)i, result);
  875. return false;
  876. }
  877. }
  878. return true;
  879. }
  880. bool create_render_pass(struct vulkan_demo *demo) {
  881. VkAttachmentDescription attachment;
  882. VkAttachmentReference color_attachment_ref;
  883. VkSubpassDescription subpass;
  884. VkSubpassDependency dependency;
  885. VkRenderPassCreateInfo render_pass_info;
  886. VkResult result;
  887. memset(&attachment, 0, sizeof(VkAttachmentDescription));
  888. attachment.format = demo->swap_chain_image_format;
  889. attachment.samples = VK_SAMPLE_COUNT_1_BIT;
  890. attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
  891. attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
  892. attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  893. attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
  894. attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  895. attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
  896. memset(&color_attachment_ref, 0, sizeof(VkAttachmentReference));
  897. color_attachment_ref.attachment = 0;
  898. color_attachment_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  899. memset(&subpass, 0, sizeof(VkSubpassDescription));
  900. subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
  901. subpass.colorAttachmentCount = 1;
  902. subpass.pColorAttachments = &color_attachment_ref;
  903. memset(&dependency, 0, sizeof(VkSubpassDependency));
  904. dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
  905. dependency.dstSubpass = 0;
  906. dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
  907. dependency.srcAccessMask = 0;
  908. dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
  909. dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
  910. VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
  911. memset(&render_pass_info, 0, sizeof(VkRenderPassCreateInfo));
  912. render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
  913. render_pass_info.attachmentCount = 1;
  914. render_pass_info.pAttachments = &attachment;
  915. render_pass_info.subpassCount = 1;
  916. render_pass_info.pSubpasses = &subpass;
  917. render_pass_info.dependencyCount = 1;
  918. render_pass_info.pDependencies = &dependency;
  919. result = vkCreateRenderPass(demo->device, &render_pass_info, NULL,
  920. &demo->render_pass);
  921. if (result != VK_SUCCESS) {
  922. fprintf(stderr, "vkCreateRenderPass failed: %d\n", result);
  923. return false;
  924. }
  925. return true;
  926. }
  927. bool create_framebuffers(struct vulkan_demo *demo) {
  928. uint32_t i;
  929. VkResult result;
  930. VkFramebufferCreateInfo framebuffer_info;
  931. if (!demo->framebuffers) {
  932. demo->framebuffers =
  933. malloc(demo->swap_chain_images_len * sizeof(VkFramebuffer));
  934. }
  935. memset(&framebuffer_info, 0, sizeof(VkFramebufferCreateInfo));
  936. framebuffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
  937. framebuffer_info.renderPass = demo->render_pass;
  938. framebuffer_info.attachmentCount = 1;
  939. framebuffer_info.width = demo->swap_chain_image_extent.width;
  940. framebuffer_info.height = demo->swap_chain_image_extent.height;
  941. framebuffer_info.layers = 1;
  942. for (i = 0; i < demo->swap_chain_images_len; i++) {
  943. framebuffer_info.pAttachments = &demo->swap_chain_image_views[i];
  944. result = vkCreateFramebuffer(demo->device, &framebuffer_info, NULL,
  945. &demo->framebuffers[i]);
  946. if (result != VK_SUCCESS) {
  947. fprintf(stderr, "vkCreateFramebuffer failed from index %lu: %d\n",
  948. (unsigned long)i, result);
  949. return false;
  950. }
  951. }
  952. return true;
  953. }
  954. bool create_descriptor_set_layout(struct vulkan_demo *demo) {
  955. VkDescriptorSetLayoutBinding overlay_layout_binding;
  956. VkDescriptorSetLayoutCreateInfo descriptor_set_layout_create_nfo;
  957. VkResult result;
  958. memset(&overlay_layout_binding, 0, sizeof(VkDescriptorSetLayoutBinding));
  959. overlay_layout_binding.binding = 0;
  960. overlay_layout_binding.descriptorCount = 1;
  961. overlay_layout_binding.descriptorType =
  962. VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
  963. overlay_layout_binding.pImmutableSamplers = NULL;
  964. overlay_layout_binding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
  965. memset(&descriptor_set_layout_create_nfo, 0,
  966. sizeof(VkDescriptorSetLayoutCreateInfo));
  967. descriptor_set_layout_create_nfo.sType =
  968. VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
  969. descriptor_set_layout_create_nfo.bindingCount = 1;
  970. descriptor_set_layout_create_nfo.pBindings = &overlay_layout_binding;
  971. result = vkCreateDescriptorSetLayout(demo->device,
  972. &descriptor_set_layout_create_nfo,
  973. NULL, &demo->descriptor_set_layout);
  974. if (result != VK_SUCCESS) {
  975. fprintf(stderr, "vkCreateDescriptorSetLayout failed: %d\n", result);
  976. return false;
  977. }
  978. return true;
  979. }
  980. bool create_descriptor_pool(struct vulkan_demo *demo) {
  981. VkDescriptorPoolSize pool_size;
  982. VkDescriptorPoolCreateInfo pool_info;
  983. VkResult result;
  984. memset(&pool_size, 0, sizeof(VkDescriptorPoolSize));
  985. pool_size.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
  986. pool_size.descriptorCount = demo->swap_chain_images_len;
  987. memset(&pool_info, 0, sizeof(VkDescriptorPoolCreateInfo));
  988. pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
  989. pool_info.poolSizeCount = 1;
  990. pool_info.pPoolSizes = &pool_size;
  991. pool_info.maxSets = demo->swap_chain_images_len;
  992. result = vkCreateDescriptorPool(demo->device, &pool_info, NULL,
  993. &demo->descriptor_pool);
  994. if (result != VK_SUCCESS) {
  995. fprintf(stderr, "vkCreateDescriptorPool failed: %d\n", result);
  996. return false;
  997. }
  998. return true;
  999. }
  1000. void update_descriptor_sets(struct vulkan_demo *demo) {
  1001. uint32_t i;
  1002. VkDescriptorImageInfo descriptor_image_info;
  1003. VkWriteDescriptorSet descriptor_write;
  1004. memset(&descriptor_image_info, 0, sizeof(VkDescriptorImageInfo));
  1005. descriptor_image_info.imageLayout =
  1006. VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
  1007. descriptor_image_info.sampler = demo->sampler;
  1008. memset(&descriptor_write, 0, sizeof(VkWriteDescriptorSet));
  1009. descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  1010. descriptor_write.dstBinding = 0;
  1011. descriptor_write.dstArrayElement = 0;
  1012. descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
  1013. descriptor_write.descriptorCount = 1;
  1014. descriptor_write.pImageInfo = &descriptor_image_info;
  1015. for (i = 0; i < demo->swap_chain_images_len; i++) {
  1016. descriptor_write.dstSet = demo->descriptor_sets[i];
  1017. descriptor_image_info.imageView = demo->overlay_image_views[i];
  1018. vkUpdateDescriptorSets(demo->device, 1, &descriptor_write, 0, NULL);
  1019. }
  1020. }
  1021. bool create_descriptor_sets(struct vulkan_demo *demo) {
  1022. bool ret = false;
  1023. VkDescriptorSetLayout *descriptor_set_layouts;
  1024. VkDescriptorSetAllocateInfo alloc_info;
  1025. uint32_t i;
  1026. VkResult result;
  1027. demo->descriptor_sets =
  1028. malloc(demo->swap_chain_images_len * sizeof(VkDescriptorSet));
  1029. descriptor_set_layouts =
  1030. malloc(demo->swap_chain_images_len * sizeof(VkDescriptorSetLayout));
  1031. for (i = 0; i < demo->swap_chain_images_len; i++) {
  1032. descriptor_set_layouts[i] = demo->descriptor_set_layout;
  1033. }
  1034. memset(&alloc_info, 0, sizeof(VkDescriptorSetAllocateInfo));
  1035. alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
  1036. alloc_info.descriptorPool = demo->descriptor_pool;
  1037. alloc_info.descriptorSetCount = demo->swap_chain_images_len;
  1038. alloc_info.pSetLayouts = descriptor_set_layouts;
  1039. result = vkAllocateDescriptorSets(demo->device, &alloc_info,
  1040. demo->descriptor_sets);
  1041. if (result != VK_SUCCESS) {
  1042. fprintf(stderr, "vkAllocateDescriptorSets failed: %d\n", result);
  1043. goto cleanup;
  1044. }
  1045. update_descriptor_sets(demo);
  1046. ret = true;
  1047. cleanup:
  1048. free(descriptor_set_layouts);
  1049. return ret;
  1050. }
  1051. bool create_shader_module(VkDevice device, char *shader_buffer,
  1052. size_t shader_buffer_len,
  1053. VkShaderModule *shader_module) {
  1054. VkShaderModuleCreateInfo create_info;
  1055. VkResult result;
  1056. memset(&create_info, 0, sizeof(VkShaderModuleCreateInfo));
  1057. create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
  1058. create_info.codeSize = shader_buffer_len;
  1059. create_info.pCode = (const uint32_t *)shader_buffer;
  1060. result = vkCreateShaderModule(device, &create_info, NULL, shader_module);
  1061. if (result != VK_SUCCESS) {
  1062. fprintf(stderr, "vkCreateShaderModule failed: %d\n", result);
  1063. return false;
  1064. }
  1065. return true;
  1066. }
  1067. bool create_graphics_pipeline(struct vulkan_demo *demo) {
  1068. bool ret = false;
  1069. char *vert_shader_code = NULL;
  1070. char *frag_shader_code = NULL;
  1071. VkShaderModule vert_shader_module = VK_NULL_HANDLE;
  1072. VkShaderModule frag_shader_module = VK_NULL_HANDLE;
  1073. FILE *fp;
  1074. size_t file_len;
  1075. VkPipelineShaderStageCreateInfo vert_shader_stage_info;
  1076. VkPipelineShaderStageCreateInfo frag_shader_stage_info;
  1077. VkPipelineShaderStageCreateInfo shader_stages[2];
  1078. VkPipelineVertexInputStateCreateInfo vertex_input_info;
  1079. VkPipelineInputAssemblyStateCreateInfo input_assembly;
  1080. VkViewport viewport;
  1081. VkRect2D scissor;
  1082. VkPipelineViewportStateCreateInfo viewport_state;
  1083. VkPipelineRasterizationStateCreateInfo rasterizer;
  1084. VkPipelineMultisampleStateCreateInfo multisampling;
  1085. VkPipelineColorBlendAttachmentState color_blend_attachment;
  1086. VkPipelineColorBlendStateCreateInfo color_blending;
  1087. VkPipelineLayoutCreateInfo pipeline_layout_info;
  1088. VkResult result;
  1089. VkGraphicsPipelineCreateInfo pipeline_info;
  1090. size_t read_result;
  1091. fp = fopen("shaders/demo.vert.spv", "r");
  1092. if (!fp) {
  1093. fprintf(stderr, "Couldn't open shaders/demo.vert.spv\n");
  1094. return false;
  1095. }
  1096. fseek(fp, 0, SEEK_END);
  1097. file_len = ftell(fp);
  1098. vert_shader_code = malloc(file_len);
  1099. fseek(fp, 0, 0);
  1100. read_result = fread(vert_shader_code, file_len, 1, fp);
  1101. fclose(fp);
  1102. if (read_result != 1) {
  1103. fprintf(stderr, "Could not read vertex shader\n");
  1104. goto cleanup;
  1105. }
  1106. if (!create_shader_module(demo->device, vert_shader_code, file_len,
  1107. &vert_shader_module)) {
  1108. goto cleanup;
  1109. }
  1110. fp = fopen("shaders/demo.frag.spv", "r");
  1111. if (!fp) {
  1112. fprintf(stderr, "Couldn't open shaders/demo.frag.spv\n");
  1113. return false;
  1114. }
  1115. fseek(fp, 0, SEEK_END);
  1116. file_len = ftell(fp);
  1117. frag_shader_code = malloc(file_len);
  1118. fseek(fp, 0, 0);
  1119. read_result = fread(frag_shader_code, file_len, 1, fp);
  1120. fclose(fp);
  1121. if (read_result != 1) {
  1122. fprintf(stderr, "Could not read fragment shader\n");
  1123. goto cleanup;
  1124. }
  1125. if (!create_shader_module(demo->device, frag_shader_code, file_len,
  1126. &frag_shader_module)) {
  1127. goto cleanup;
  1128. }
  1129. memset(&vert_shader_stage_info, 0, sizeof(VkPipelineShaderStageCreateInfo));
  1130. vert_shader_stage_info.sType =
  1131. VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
  1132. vert_shader_stage_info.stage = VK_SHADER_STAGE_VERTEX_BIT;
  1133. vert_shader_stage_info.module = vert_shader_module;
  1134. vert_shader_stage_info.pName = "main";
  1135. memset(&frag_shader_stage_info, 0, sizeof(VkPipelineShaderStageCreateInfo));
  1136. frag_shader_stage_info.sType =
  1137. VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
  1138. frag_shader_stage_info.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
  1139. frag_shader_stage_info.module = frag_shader_module;
  1140. frag_shader_stage_info.pName = "main";
  1141. shader_stages[0] = vert_shader_stage_info;
  1142. shader_stages[1] = frag_shader_stage_info;
  1143. memset(&vertex_input_info, 0, sizeof(VkPipelineVertexInputStateCreateInfo));
  1144. vertex_input_info.sType =
  1145. VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
  1146. memset(&input_assembly, 0, sizeof(VkPipelineInputAssemblyStateCreateInfo));
  1147. input_assembly.sType =
  1148. VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
  1149. input_assembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
  1150. input_assembly.primitiveRestartEnable = VK_FALSE;
  1151. memset(&viewport, 0, sizeof(VkViewport));
  1152. viewport.x = 0.0f;
  1153. viewport.y = 0.0f;
  1154. viewport.width = (float)demo->swap_chain_image_extent.width;
  1155. viewport.height = (float)demo->swap_chain_image_extent.height;
  1156. viewport.minDepth = 0.0f;
  1157. viewport.maxDepth = 1.0f;
  1158. memset(&scissor, 0, sizeof(VkRect2D));
  1159. scissor.extent.width = demo->swap_chain_image_extent.width;
  1160. scissor.extent.height = demo->swap_chain_image_extent.height;
  1161. memset(&viewport_state, 0, sizeof(VkPipelineViewportStateCreateInfo));
  1162. viewport_state.sType =
  1163. VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
  1164. viewport_state.viewportCount = 1;
  1165. viewport_state.pViewports = &viewport;
  1166. viewport_state.scissorCount = 1;
  1167. viewport_state.pScissors = &scissor;
  1168. memset(&rasterizer, 0, sizeof(VkPipelineRasterizationStateCreateInfo));
  1169. rasterizer.sType =
  1170. VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
  1171. rasterizer.depthClampEnable = VK_FALSE;
  1172. rasterizer.rasterizerDiscardEnable = VK_FALSE;
  1173. rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
  1174. rasterizer.lineWidth = 1.0f;
  1175. rasterizer.cullMode = VK_CULL_MODE_FRONT_BIT;
  1176. rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
  1177. rasterizer.depthBiasEnable = VK_FALSE;
  1178. memset(&multisampling, 0, sizeof(VkPipelineMultisampleStateCreateInfo));
  1179. multisampling.sType =
  1180. VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
  1181. multisampling.sampleShadingEnable = VK_FALSE;
  1182. multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
  1183. memset(&color_blend_attachment, 0,
  1184. sizeof(VkPipelineColorBlendAttachmentState));
  1185. color_blend_attachment.colorWriteMask =
  1186. VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
  1187. VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
  1188. color_blend_attachment.blendEnable = VK_TRUE;
  1189. color_blend_attachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE;
  1190. color_blend_attachment.dstColorBlendFactor =
  1191. VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
  1192. color_blend_attachment.colorBlendOp = VK_BLEND_OP_ADD;
  1193. color_blend_attachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
  1194. color_blend_attachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
  1195. color_blend_attachment.alphaBlendOp = VK_BLEND_OP_ADD;
  1196. memset(&color_blending, 0, sizeof(VkPipelineColorBlendStateCreateInfo));
  1197. color_blending.sType =
  1198. VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
  1199. color_blending.logicOpEnable = VK_FALSE;
  1200. color_blending.logicOp = VK_LOGIC_OP_COPY;
  1201. color_blending.attachmentCount = 1;
  1202. color_blending.pAttachments = &color_blend_attachment;
  1203. color_blending.blendConstants[0] = 1.0f;
  1204. color_blending.blendConstants[1] = 1.0f;
  1205. color_blending.blendConstants[2] = 1.0f;
  1206. color_blending.blendConstants[3] = 1.0f;
  1207. memset(&pipeline_layout_info, 0, sizeof(VkPipelineLayoutCreateInfo));
  1208. pipeline_layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
  1209. pipeline_layout_info.setLayoutCount = 0;
  1210. pipeline_layout_info.pushConstantRangeCount = 0;
  1211. pipeline_layout_info.setLayoutCount = 1;
  1212. pipeline_layout_info.pSetLayouts = &demo->descriptor_set_layout;
  1213. result = vkCreatePipelineLayout(demo->device, &pipeline_layout_info, NULL,
  1214. &demo->pipeline_layout);
  1215. if (result != VK_SUCCESS) {
  1216. fprintf(stderr, "vkCreatePipelineLayout failed: %d\n", result);
  1217. goto cleanup;
  1218. }
  1219. memset(&pipeline_info, 0, sizeof(VkGraphicsPipelineCreateInfo));
  1220. pipeline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
  1221. pipeline_info.stageCount = 2;
  1222. pipeline_info.pStages = shader_stages;
  1223. pipeline_info.pVertexInputState = &vertex_input_info;
  1224. pipeline_info.pInputAssemblyState = &input_assembly;
  1225. pipeline_info.pViewportState = &viewport_state;
  1226. pipeline_info.pRasterizationState = &rasterizer;
  1227. pipeline_info.pMultisampleState = &multisampling;
  1228. pipeline_info.pColorBlendState = &color_blending;
  1229. pipeline_info.layout = demo->pipeline_layout;
  1230. pipeline_info.renderPass = demo->render_pass;
  1231. pipeline_info.basePipelineHandle = NULL;
  1232. result = vkCreateGraphicsPipelines(demo->device, NULL, 1, &pipeline_info,
  1233. NULL, &demo->pipeline);
  1234. if (result != VK_SUCCESS) {
  1235. fprintf(stderr, "vkCreateGraphicsPipelines failed: %d\n", result);
  1236. goto cleanup;
  1237. }
  1238. ret = true;
  1239. cleanup:
  1240. if (frag_shader_module) {
  1241. vkDestroyShaderModule(demo->device, frag_shader_module, NULL);
  1242. }
  1243. if (frag_shader_code) {
  1244. free(frag_shader_code);
  1245. }
  1246. if (vert_shader_module) {
  1247. vkDestroyShaderModule(demo->device, vert_shader_module, NULL);
  1248. }
  1249. if (vert_shader_code) {
  1250. free(vert_shader_code);
  1251. }
  1252. return ret;
  1253. }
  1254. bool create_command_pool(struct vulkan_demo *demo) {
  1255. VkCommandPoolCreateInfo pool_info;
  1256. VkResult result;
  1257. memset(&pool_info, 0, sizeof(VkCommandPoolCreateInfo));
  1258. pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
  1259. pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
  1260. pool_info.queueFamilyIndex = demo->indices.graphics;
  1261. result = vkCreateCommandPool(demo->device, &pool_info, NULL,
  1262. &demo->command_pool);
  1263. if (result != VK_SUCCESS) {
  1264. fprintf(stderr, "vkCreateCommandPool failed: %d\n", result);
  1265. return false;
  1266. }
  1267. return true;
  1268. }
  1269. bool create_command_buffers(struct vulkan_demo *demo) {
  1270. VkCommandBufferAllocateInfo alloc_info;
  1271. VkResult result;
  1272. demo->command_buffers =
  1273. malloc(demo->swap_chain_images_len * sizeof(VkCommandBuffer));
  1274. memset(&alloc_info, 0, sizeof(VkCommandBufferAllocateInfo));
  1275. alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
  1276. alloc_info.commandPool = demo->command_pool;
  1277. alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
  1278. alloc_info.commandBufferCount = demo->swap_chain_images_len;
  1279. result = vkAllocateCommandBuffers(demo->device, &alloc_info,
  1280. demo->command_buffers);
  1281. if (result != VK_SUCCESS) {
  1282. fprintf(stderr, "vkAllocateCommandBuffers failed: %d\n", result);
  1283. return false;
  1284. }
  1285. return true;
  1286. }
  1287. bool create_semaphores(struct vulkan_demo *demo) {
  1288. VkSemaphoreCreateInfo semaphore_info;
  1289. VkResult result;
  1290. memset(&semaphore_info, 0, sizeof(VkSemaphoreCreateInfo));
  1291. semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
  1292. result = vkCreateSemaphore(demo->device, &semaphore_info, NULL,
  1293. &demo->image_available);
  1294. if (result != VK_SUCCESS) {
  1295. fprintf(stderr, "vkCreateSemaphore failed: %d\n", result);
  1296. return false;
  1297. }
  1298. result = vkCreateSemaphore(demo->device, &semaphore_info, NULL,
  1299. &demo->render_finished);
  1300. if (result != VK_SUCCESS) {
  1301. fprintf(stderr, "vkCreateSemaphore failed: %d\n", result);
  1302. return false;
  1303. }
  1304. return true;
  1305. }
  1306. bool create_fence(struct vulkan_demo *demo) {
  1307. VkResult result;
  1308. VkFenceCreateInfo fence_create_info;
  1309. memset(&fence_create_info, 0, sizeof(VkFenceCreateInfo));
  1310. fence_create_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
  1311. fence_create_info.flags = VK_FENCE_CREATE_SIGNALED_BIT;
  1312. result = vkCreateFence(demo->device, &fence_create_info, NULL,
  1313. &demo->render_fence);
  1314. if (result != VK_SUCCESS) {
  1315. fprintf(stderr, "vkCreateFence failed: %d\n", result);
  1316. return false;
  1317. }
  1318. return true;
  1319. }
  1320. bool create_swap_chain_related_resources(struct vulkan_demo *demo) {
  1321. if (!create_swap_chain(demo)) {
  1322. return false;
  1323. }
  1324. if (!create_swap_chain_image_views(demo)) {
  1325. return false;
  1326. }
  1327. if (!create_overlay_images(demo)) {
  1328. return false;
  1329. }
  1330. if (!create_render_pass(demo)) {
  1331. return false;
  1332. }
  1333. if (!create_framebuffers(demo)) {
  1334. return false;
  1335. }
  1336. if (!create_graphics_pipeline(demo)) {
  1337. return false;
  1338. }
  1339. return true;
  1340. }
  1341. bool destroy_swap_chain_related_resources(struct vulkan_demo *demo) {
  1342. uint32_t i;
  1343. VkResult result;
  1344. result = vkQueueWaitIdle(demo->graphics_queue);
  1345. if (result != VK_SUCCESS) {
  1346. fprintf(stderr, "vkQueueWaitIdle failed: %d\n", result);
  1347. return false;
  1348. }
  1349. for (i = 0; i < demo->swap_chain_images_len; i++) {
  1350. vkDestroyFramebuffer(demo->device, demo->framebuffers[i], NULL);
  1351. vkDestroyImageView(demo->device, demo->overlay_image_views[i], NULL);
  1352. vkDestroyImage(demo->device, demo->overlay_images[i], NULL);
  1353. vkFreeMemory(demo->device, demo->overlay_image_memories[i], NULL);
  1354. vkDestroyImageView(demo->device, demo->swap_chain_image_views[i], NULL);
  1355. }
  1356. vkDestroySwapchainKHR(demo->device, demo->swap_chain, NULL);
  1357. vkDestroyRenderPass(demo->device, demo->render_pass, NULL);
  1358. vkDestroyPipeline(demo->device, demo->pipeline, NULL);
  1359. vkDestroyPipelineLayout(demo->device, demo->pipeline_layout, NULL);
  1360. return true;
  1361. }
  1362. bool create_demo_texture(struct vulkan_demo *demo) {
  1363. VkResult result;
  1364. VkMemoryRequirements mem_requirements;
  1365. VkPhysicalDeviceMemoryProperties mem_properties;
  1366. int found;
  1367. uint32_t i;
  1368. VkImageCreateInfo image_info;
  1369. VkMemoryAllocateInfo alloc_info;
  1370. VkImageViewCreateInfo image_view_info;
  1371. VkBufferCreateInfo buffer_info;
  1372. struct {
  1373. VkDeviceMemory memory;
  1374. VkBuffer buffer;
  1375. } staging_buffer;
  1376. void *data;
  1377. VkCommandBuffer command_buffer;
  1378. VkCommandBufferBeginInfo begin_info;
  1379. VkImageMemoryBarrier image_transfer_dst_memory_barrier;
  1380. VkBufferImageCopy buffer_copy_region;
  1381. VkImageMemoryBarrier image_shader_memory_barrier;
  1382. VkFence fence;
  1383. VkFenceCreateInfo fence_create;
  1384. VkSubmitInfo submit_info;
  1385. memset(&image_info, 0, sizeof(VkImageCreateInfo));
  1386. image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
  1387. image_info.imageType = VK_IMAGE_TYPE_2D;
  1388. image_info.extent.width = 2;
  1389. image_info.extent.height = 2;
  1390. image_info.extent.depth = 1;
  1391. image_info.mipLevels = 1;
  1392. image_info.arrayLayers = 1;
  1393. image_info.format = VK_FORMAT_R8_UNORM;
  1394. image_info.tiling = VK_IMAGE_TILING_LINEAR;
  1395. image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  1396. image_info.usage =
  1397. VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
  1398. image_info.samples = VK_SAMPLE_COUNT_1_BIT;
  1399. image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
  1400. memset(&alloc_info, 0, sizeof(VkMemoryAllocateInfo));
  1401. alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
  1402. memset(&image_view_info, 0, sizeof(VkImageViewCreateInfo));
  1403. image_view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
  1404. image_view_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
  1405. image_view_info.format = VK_FORMAT_R8_UNORM;
  1406. image_view_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
  1407. image_view_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
  1408. image_view_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
  1409. image_view_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
  1410. image_view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  1411. image_view_info.subresourceRange.baseMipLevel = 0;
  1412. image_view_info.subresourceRange.levelCount = 1;
  1413. image_view_info.subresourceRange.baseArrayLayer = 0;
  1414. image_view_info.subresourceRange.layerCount = 1;
  1415. result = vkCreateImage(demo->device, &image_info, NULL,
  1416. &demo->demo_texture_image);
  1417. if (result != VK_SUCCESS) {
  1418. fprintf(stderr, "vkCreateImage failed: %d\n", result);
  1419. return false;
  1420. }
  1421. vkGetImageMemoryRequirements(demo->device, demo->demo_texture_image,
  1422. &mem_requirements);
  1423. alloc_info.allocationSize = mem_requirements.size;
  1424. vkGetPhysicalDeviceMemoryProperties(demo->physical_device, &mem_properties);
  1425. found = 0;
  1426. for (i = 0; i < mem_properties.memoryTypeCount; i++) {
  1427. if ((mem_requirements.memoryTypeBits & (1 << i)) &&
  1428. (mem_properties.memoryTypes[i].propertyFlags &
  1429. VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) ==
  1430. VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
  1431. found = 1;
  1432. break;
  1433. }
  1434. }
  1435. if (!found) {
  1436. fprintf(stderr, "failed to find suitable memory for demo texture!\n");
  1437. return false;
  1438. }
  1439. alloc_info.memoryTypeIndex = i;
  1440. result = vkAllocateMemory(demo->device, &alloc_info, NULL,
  1441. &demo->demo_texture_memory);
  1442. if (result != VK_SUCCESS) {
  1443. fprintf(stderr,
  1444. "failed to allocate vulkan memory for demo texture: %d!\n",
  1445. result);
  1446. return false;
  1447. }
  1448. result = vkBindImageMemory(demo->device, demo->demo_texture_image,
  1449. demo->demo_texture_memory, 0);
  1450. if (result != VK_SUCCESS) {
  1451. fprintf(stderr, "Couldn't bind image memory for demo texture: %d\n",
  1452. result);
  1453. return false;
  1454. }
  1455. image_view_info.image = demo->demo_texture_image;
  1456. result = vkCreateImageView(demo->device, &image_view_info, NULL,
  1457. &demo->demo_texture_image_view);
  1458. if (result != VK_SUCCESS) {
  1459. fprintf(stderr, "vkCreateImageView failed for demo texture: %d\n",
  1460. result);
  1461. return false;
  1462. }
  1463. memset(&buffer_info, 0, sizeof(VkBufferCreateInfo));
  1464. buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
  1465. buffer_info.size = alloc_info.allocationSize;
  1466. buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
  1467. buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
  1468. result = vkCreateBuffer(demo->device, &buffer_info, NULL,
  1469. &staging_buffer.buffer);
  1470. if (result != VK_SUCCESS) {
  1471. fprintf(stderr, "vkCreateBuffer failed for demo texture: %d\n", result);
  1472. return false;
  1473. }
  1474. vkGetBufferMemoryRequirements(demo->device, staging_buffer.buffer,
  1475. &mem_requirements);
  1476. alloc_info.allocationSize = mem_requirements.size;
  1477. found = 0;
  1478. for (i = 0; i < mem_properties.memoryTypeCount; i++) {
  1479. if ((mem_requirements.memoryTypeBits & (1 << i)) &&
  1480. (mem_properties.memoryTypes[i].propertyFlags &
  1481. (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
  1482. VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) ==
  1483. (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
  1484. VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) {
  1485. found = 1;
  1486. break;
  1487. }
  1488. }
  1489. if (!found) {
  1490. fprintf(stderr, "failed to find suitable staging buffer memory for "
  1491. "demo texture!\n");
  1492. return false;
  1493. }
  1494. alloc_info.memoryTypeIndex = i;
  1495. result = vkAllocateMemory(demo->device, &alloc_info, NULL,
  1496. &staging_buffer.memory);
  1497. if (!found) {
  1498. fprintf(stderr, "vkAllocateMemory failed for demo texture: %d\n",
  1499. result);
  1500. return false;
  1501. }
  1502. result = vkBindBufferMemory(demo->device, staging_buffer.buffer,
  1503. staging_buffer.memory, 0);
  1504. if (!found) {
  1505. fprintf(stderr, "vkBindBufferMemory failed for demo texture: %d\n",
  1506. result);
  1507. return false;
  1508. }
  1509. result = vkMapMemory(demo->device, staging_buffer.memory, 0,
  1510. sizeof(uint32_t), 0, &data);
  1511. if (result != VK_SUCCESS) {
  1512. fprintf(stderr, "vkMapMemory failed for demo texture: %d\n", result);
  1513. return false;
  1514. }
  1515. *((uint32_t *)data) = 0x00FFFF00;
  1516. vkUnmapMemory(demo->device, staging_buffer.memory);
  1517. memset(&begin_info, 0, sizeof(VkCommandBufferBeginInfo));
  1518. begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
  1519. command_buffer = demo->command_buffers[0];
  1520. result = vkBeginCommandBuffer(command_buffer, &begin_info);
  1521. memset(&image_transfer_dst_memory_barrier, 0, sizeof(VkImageMemoryBarrier));
  1522. image_transfer_dst_memory_barrier.sType =
  1523. VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
  1524. image_transfer_dst_memory_barrier.image = demo->demo_texture_image;
  1525. image_transfer_dst_memory_barrier.srcQueueFamilyIndex =
  1526. VK_QUEUE_FAMILY_IGNORED;
  1527. image_transfer_dst_memory_barrier.dstQueueFamilyIndex =
  1528. VK_QUEUE_FAMILY_IGNORED;
  1529. image_transfer_dst_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  1530. image_transfer_dst_memory_barrier.newLayout =
  1531. VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
  1532. image_transfer_dst_memory_barrier.subresourceRange.aspectMask =
  1533. VK_IMAGE_ASPECT_COLOR_BIT;
  1534. image_transfer_dst_memory_barrier.subresourceRange.levelCount = 1;
  1535. image_transfer_dst_memory_barrier.subresourceRange.layerCount = 1;
  1536. image_transfer_dst_memory_barrier.dstAccessMask =
  1537. VK_ACCESS_TRANSFER_WRITE_BIT;
  1538. vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
  1539. VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1,
  1540. &image_transfer_dst_memory_barrier);
  1541. memset(&buffer_copy_region, 0, sizeof(VkBufferImageCopy));
  1542. buffer_copy_region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  1543. buffer_copy_region.imageSubresource.layerCount = 1;
  1544. buffer_copy_region.imageExtent.width = 2;
  1545. buffer_copy_region.imageExtent.height = 2;
  1546. buffer_copy_region.imageExtent.depth = 1;
  1547. vkCmdCopyBufferToImage(
  1548. command_buffer, staging_buffer.buffer, demo->demo_texture_image,
  1549. VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &buffer_copy_region);
  1550. memset(&image_shader_memory_barrier, 0, sizeof(VkImageMemoryBarrier));
  1551. image_shader_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
  1552. image_shader_memory_barrier.image = demo->demo_texture_image;
  1553. image_shader_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  1554. image_shader_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  1555. image_shader_memory_barrier.oldLayout =
  1556. VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
  1557. image_shader_memory_barrier.newLayout =
  1558. VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
  1559. image_shader_memory_barrier.subresourceRange.aspectMask =
  1560. VK_IMAGE_ASPECT_COLOR_BIT;
  1561. image_shader_memory_barrier.subresourceRange.levelCount = 1;
  1562. image_shader_memory_barrier.subresourceRange.layerCount = 1;
  1563. image_shader_memory_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
  1564. image_shader_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT,
  1565. vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
  1566. VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0,
  1567. NULL, 1, &image_shader_memory_barrier);
  1568. result = vkEndCommandBuffer(command_buffer);
  1569. if (result != VK_SUCCESS) {
  1570. fprintf(stderr, "vkEndCommandBuffer failed for demo texture: %d\n",
  1571. result);
  1572. return false;
  1573. }
  1574. memset(&fence_create, 0, sizeof(VkFenceCreateInfo));
  1575. fence_create.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
  1576. result = vkCreateFence(demo->device, &fence_create, NULL, &fence);
  1577. if (result != VK_SUCCESS) {
  1578. fprintf(stderr, "vkCreateFence failed for demo texture: %d\n", result);
  1579. return false;
  1580. }
  1581. memset(&submit_info, 0, sizeof(VkSubmitInfo));
  1582. submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
  1583. submit_info.commandBufferCount = 1;
  1584. submit_info.pCommandBuffers = &command_buffer;
  1585. result = vkQueueSubmit(demo->graphics_queue, 1, &submit_info, fence);
  1586. if (result != VK_SUCCESS) {
  1587. fprintf(stderr, "vkQueueSubmit failed for demo texture: %d\n", result);
  1588. return false;
  1589. }
  1590. result = vkWaitForFences(demo->device, 1, &fence, VK_TRUE, UINT64_MAX);
  1591. if (result != VK_SUCCESS) {
  1592. fprintf(stderr, "vkWaitForFences failed for demo texture: %d\n",
  1593. result);
  1594. return false;
  1595. }
  1596. vkDestroyBuffer(demo->device, staging_buffer.buffer, NULL);
  1597. vkFreeMemory(demo->device, staging_buffer.memory, NULL);
  1598. vkDestroyFence(demo->device, fence, NULL);
  1599. return true;
  1600. }
  1601. bool create_vulkan_demo(struct vulkan_demo *demo) {
  1602. if (!create_instance(demo)) {
  1603. return false;
  1604. }
  1605. if (!create_surface(demo)) {
  1606. return false;
  1607. }
  1608. if (!create_physical_device(demo)) {
  1609. return false;
  1610. }
  1611. if (!create_logical_device(demo)) {
  1612. return false;
  1613. }
  1614. if (!create_sampler(demo)) {
  1615. return false;
  1616. }
  1617. if (!create_descriptor_set_layout(demo)) {
  1618. return false;
  1619. }
  1620. if (!create_swap_chain_related_resources(demo)) {
  1621. return false;
  1622. }
  1623. if (!create_descriptor_pool(demo)) {
  1624. return false;
  1625. }
  1626. if (!create_descriptor_sets(demo)) {
  1627. return false;
  1628. }
  1629. if (!create_command_pool(demo)) {
  1630. return false;
  1631. }
  1632. if (!create_command_buffers(demo)) {
  1633. return false;
  1634. }
  1635. if (!create_semaphores(demo)) {
  1636. return false;
  1637. }
  1638. if (!create_fence(demo)) {
  1639. return false;
  1640. }
  1641. if (!create_demo_texture(demo)) {
  1642. return false;
  1643. }
  1644. return true;
  1645. }
  1646. bool recreate_swap_chain(struct vulkan_demo *demo) {
  1647. printf("recreating swapchain\n");
  1648. if (!destroy_swap_chain_related_resources(demo)) {
  1649. return false;
  1650. }
  1651. if (!create_swap_chain_related_resources(demo)) {
  1652. return false;
  1653. }
  1654. update_descriptor_sets(demo);
  1655. nk_sdl_resize(demo->swap_chain_image_extent.width,
  1656. demo->swap_chain_image_extent.height);
  1657. return true;
  1658. }
  1659. bool render(struct vulkan_demo *demo, struct nk_colorf *bg,
  1660. VkSemaphore wait_semaphore, uint32_t image_index) {
  1661. VkCommandBufferBeginInfo command_buffer_begin_info;
  1662. VkCommandBuffer command_buffer;
  1663. VkRenderPassBeginInfo render_pass_info;
  1664. VkSubmitInfo submit_info;
  1665. VkPipelineStageFlags wait_stage =
  1666. VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
  1667. VkResult result;
  1668. VkPresentInfoKHR present_info;
  1669. VkClearValue clear_color;
  1670. memcpy(&clear_color.color, bg, sizeof(VkClearColorValue));
  1671. memset(&command_buffer_begin_info, 0, sizeof(VkCommandBufferBeginInfo));
  1672. command_buffer_begin_info.sType =
  1673. VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
  1674. command_buffer = demo->command_buffers[image_index];
  1675. result = vkBeginCommandBuffer(command_buffer, &command_buffer_begin_info);
  1676. if (result != VK_SUCCESS) {
  1677. fprintf(stderr, "vkBeginCommandBuffer failed: %d\n", result);
  1678. return false;
  1679. }
  1680. memset(&render_pass_info, 0, sizeof(VkRenderPassBeginInfo));
  1681. render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
  1682. render_pass_info.renderPass = demo->render_pass;
  1683. render_pass_info.framebuffer = demo->framebuffers[image_index];
  1684. render_pass_info.renderArea.offset.x = 0;
  1685. render_pass_info.renderArea.offset.y = 0;
  1686. render_pass_info.renderArea.extent = demo->swap_chain_image_extent;
  1687. render_pass_info.clearValueCount = 1;
  1688. render_pass_info.pClearValues = &clear_color;
  1689. vkCmdBeginRenderPass(command_buffer, &render_pass_info,
  1690. VK_SUBPASS_CONTENTS_INLINE);
  1691. vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
  1692. demo->pipeline);
  1693. vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
  1694. demo->pipeline_layout, 0, 1,
  1695. &demo->descriptor_sets[image_index], 0, NULL);
  1696. vkCmdDraw(command_buffer, 3, 1, 0, 0);
  1697. vkCmdEndRenderPass(command_buffer);
  1698. result = vkEndCommandBuffer(command_buffer);
  1699. if (result != VK_SUCCESS) {
  1700. fprintf(stderr, "vkEndCommandBuffer failed: %d\n", result);
  1701. return false;
  1702. }
  1703. memset(&submit_info, 0, sizeof(VkSubmitInfo));
  1704. submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
  1705. submit_info.waitSemaphoreCount = 1;
  1706. submit_info.pWaitSemaphores = &wait_semaphore;
  1707. submit_info.pWaitDstStageMask = &wait_stage;
  1708. submit_info.commandBufferCount = 1;
  1709. submit_info.pCommandBuffers = &demo->command_buffers[image_index];
  1710. submit_info.signalSemaphoreCount = 1;
  1711. submit_info.pSignalSemaphores = &demo->render_finished;
  1712. result = vkQueueSubmit(demo->graphics_queue, 1, &submit_info,
  1713. demo->render_fence);
  1714. if (result != VK_SUCCESS) {
  1715. fprintf(stderr, "vkQueueSubmit failed: %d\n", result);
  1716. return false;
  1717. }
  1718. memset(&present_info, 0, sizeof(VkPresentInfoKHR));
  1719. present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
  1720. present_info.waitSemaphoreCount = 1;
  1721. present_info.pWaitSemaphores = &demo->render_finished;
  1722. present_info.swapchainCount = 1;
  1723. present_info.pSwapchains = &demo->swap_chain;
  1724. present_info.pImageIndices = &image_index;
  1725. result = vkQueuePresentKHR(demo->present_queue, &present_info);
  1726. if (result == VK_ERROR_OUT_OF_DATE_KHR) {
  1727. if (!recreate_swap_chain(demo)) {
  1728. fprintf(stderr, "failed to recreate swap chain!\n");
  1729. }
  1730. } else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
  1731. fprintf(stderr, "vkQueuePresentKHR failed: %d\n", result);
  1732. return false;
  1733. }
  1734. return true;
  1735. }
  1736. VkResult
  1737. destroy_debug_utils_messenger_ext(VkInstance instance,
  1738. VkDebugUtilsMessengerEXT debugMessenger,
  1739. const VkAllocationCallbacks *pAllocator) {
  1740. PFN_vkDestroyDebugUtilsMessengerEXT func =
  1741. (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(
  1742. instance, "vkDestroyDebugUtilsMessengerEXT");
  1743. if (func != NULL) {
  1744. func(instance, debugMessenger, pAllocator);
  1745. return VK_SUCCESS;
  1746. } else {
  1747. return VK_ERROR_EXTENSION_NOT_PRESENT;
  1748. }
  1749. }
  1750. bool cleanup(struct vulkan_demo *demo) {
  1751. VkResult result;
  1752. printf("cleaning up\n");
  1753. result = vkDeviceWaitIdle(demo->device);
  1754. if (result != VK_SUCCESS) {
  1755. fprintf(stderr, "vkDeviceWaitIdle failed: %d\n", result);
  1756. return false;
  1757. }
  1758. destroy_swap_chain_related_resources(demo);
  1759. vkFreeCommandBuffers(demo->device, demo->command_pool,
  1760. demo->swap_chain_images_len, demo->command_buffers);
  1761. vkDestroyCommandPool(demo->device, demo->command_pool, NULL);
  1762. vkDestroySampler(demo->device, demo->sampler, NULL);
  1763. vkDestroySemaphore(demo->device, demo->render_finished, NULL);
  1764. vkDestroySemaphore(demo->device, demo->image_available, NULL);
  1765. vkDestroyFence(demo->device, demo->render_fence, NULL);
  1766. vkDestroyImage(demo->device, demo->demo_texture_image, NULL);
  1767. vkDestroyImageView(demo->device, demo->demo_texture_image_view, NULL);
  1768. vkFreeMemory(demo->device, demo->demo_texture_memory, NULL);
  1769. vkDestroyDescriptorSetLayout(demo->device, demo->descriptor_set_layout,
  1770. NULL);
  1771. vkDestroyDescriptorPool(demo->device, demo->descriptor_pool, NULL);
  1772. vkDestroyDevice(demo->device, NULL);
  1773. vkDestroySurfaceKHR(demo->instance, demo->surface, NULL);
  1774. if (demo->debug_messenger) {
  1775. result = destroy_debug_utils_messenger_ext(demo->instance,
  1776. demo->debug_messenger, NULL);
  1777. if (result != VK_SUCCESS) {
  1778. fprintf(stderr, "Couldn't destroy debug messenger: %d\n", result);
  1779. return false;
  1780. }
  1781. }
  1782. vkDestroyInstance(demo->instance, NULL);
  1783. if (demo->swap_chain_images) {
  1784. free(demo->swap_chain_images);
  1785. }
  1786. if (demo->swap_chain_image_views) {
  1787. free(demo->swap_chain_image_views);
  1788. }
  1789. if (demo->overlay_images) {
  1790. free(demo->overlay_images);
  1791. }
  1792. if (demo->overlay_image_views) {
  1793. free(demo->overlay_image_views);
  1794. }
  1795. if (demo->overlay_image_memories) {
  1796. free(demo->overlay_image_memories);
  1797. }
  1798. if (demo->descriptor_sets) {
  1799. free(demo->descriptor_sets);
  1800. }
  1801. if (demo->framebuffers) {
  1802. free(demo->framebuffers);
  1803. }
  1804. if (demo->command_buffers) {
  1805. free(demo->command_buffers);
  1806. }
  1807. SDL_DestroyWindow(demo->win);
  1808. return true;
  1809. }
  1810. int main(void) {
  1811. struct vulkan_demo demo;
  1812. struct nk_context *ctx;
  1813. struct nk_colorf bg;
  1814. struct nk_image img;
  1815. uint32_t image_index;
  1816. VkResult result;
  1817. VkSemaphore nk_semaphore;
  1818. #ifdef INCLUDE_CONFIGURATOR
  1819. static struct nk_color color_table[NK_COLOR_COUNT];
  1820. memcpy(color_table, nk_default_color_style, sizeof(color_table));
  1821. #endif
  1822. SDL_SetHint(SDL_HINT_VIDEO_HIGHDPI_DISABLED, "0");
  1823. if (SDL_Init(SDL_INIT_VIDEO) < 0) {
  1824. fprintf(stderr, "[SDL] failed to init!\n");
  1825. exit(1);
  1826. }
  1827. memset(&demo, 0, sizeof(struct vulkan_demo));
  1828. demo.win = SDL_CreateWindow(
  1829. "Demo", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WINDOW_WIDTH,
  1830. WINDOW_HEIGHT,
  1831. SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
  1832. if (!create_vulkan_demo(&demo)) {
  1833. fprintf(stderr, "failed to create vulkan demo!\n");
  1834. exit(1);
  1835. }
  1836. ctx = nk_sdl_init(demo.win, demo.device, demo.physical_device,
  1837. demo.indices.graphics, demo.overlay_image_views,
  1838. demo.swap_chain_images_len, demo.swap_chain_image_format,
  1839. 0, MAX_VERTEX_BUFFER, MAX_ELEMENT_BUFFER);
  1840. /* Load Fonts: if none of these are loaded a default font will be used */
  1841. /* Load Cursor: if you uncomment cursor loading please hide the cursor */
  1842. {
  1843. struct nk_font_atlas *atlas;
  1844. nk_sdl_font_stash_begin(&atlas);
  1845. /*struct nk_font *droid = nk_font_atlas_add_from_file(atlas,
  1846. * "../../../extra_font/DroidSans.ttf", 14, 0);*/
  1847. /*struct nk_font *roboto = nk_font_atlas_add_from_file(atlas,
  1848. * "../../../extra_font/Roboto-Regular.ttf", 14, 0);*/
  1849. /*struct nk_font *future = nk_font_atlas_add_from_file(atlas,
  1850. * "../../../extra_font/kenvector_future_thin.ttf", 13, 0);*/
  1851. /*struct nk_font *clean = nk_font_atlas_add_from_file(atlas,
  1852. * "../../../extra_font/ProggyClean.ttf", 12, 0);*/
  1853. /*struct nk_font *tiny = nk_font_atlas_add_from_file(atlas,
  1854. * "../../../extra_font/ProggyTiny.ttf", 10, 0);*/
  1855. /*struct nk_font *cousine = nk_font_atlas_add_from_file(atlas,
  1856. * "../../../extra_font/Cousine-Regular.ttf", 13, 0);*/
  1857. nk_sdl_font_stash_end(demo.graphics_queue);
  1858. /*nk_style_load_all_cursors(ctx, atlas->cursors);*/
  1859. /*nk_style_set_font(ctx, &droid->handle);*/
  1860. }
  1861. img = nk_image_ptr(demo.demo_texture_image_view);
  1862. bg.r = 0.10f, bg.g = 0.18f, bg.b = 0.24f, bg.a = 1.0f;
  1863. while (true) {
  1864. SDL_Event evt;
  1865. nk_input_begin(ctx);
  1866. while (SDL_PollEvent(&evt)) {
  1867. if (evt.type == SDL_QUIT)
  1868. goto cleanup;
  1869. if (evt.type == SDL_WINDOWEVENT &&
  1870. evt.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
  1871. recreate_swap_chain(&demo);
  1872. nk_sdl_handle_event(&evt);
  1873. }
  1874. nk_sdl_handle_grab(); /* optional grabbing behavior */
  1875. nk_input_end(ctx);
  1876. /* GUI */
  1877. if (nk_begin(ctx, "Demo", nk_rect(50, 50, 230, 250),
  1878. NK_WINDOW_BORDER | NK_WINDOW_MOVABLE | NK_WINDOW_SCALABLE |
  1879. NK_WINDOW_MINIMIZABLE | NK_WINDOW_TITLE)) {
  1880. enum { EASY, HARD };
  1881. static int op = EASY;
  1882. static int property = 20;
  1883. nk_layout_row_static(ctx, 30, 80, 1);
  1884. if (nk_button_label(ctx, "button"))
  1885. fprintf(stdout, "button pressed\n");
  1886. nk_layout_row_dynamic(ctx, 30, 2);
  1887. if (nk_option_label(ctx, "easy", op == EASY))
  1888. op = EASY;
  1889. if (nk_option_label(ctx, "hard", op == HARD))
  1890. op = HARD;
  1891. nk_layout_row_dynamic(ctx, 25, 1);
  1892. nk_property_int(ctx, "Compression:", 0, &property, 100, 10, 1);
  1893. nk_layout_row_dynamic(ctx, 20, 1);
  1894. nk_label(ctx, "background:", NK_TEXT_LEFT);
  1895. nk_layout_row_dynamic(ctx, 25, 1);
  1896. if (nk_combo_begin_color(ctx, nk_rgb_cf(bg),
  1897. nk_vec2(nk_widget_width(ctx), 400))) {
  1898. nk_layout_row_dynamic(ctx, 120, 1);
  1899. bg = nk_color_picker(ctx, bg, NK_RGBA);
  1900. nk_layout_row_dynamic(ctx, 25, 1);
  1901. bg.r = nk_propertyf(ctx, "#R:", 0, bg.r, 1.0f, 0.01f, 0.005f);
  1902. bg.g = nk_propertyf(ctx, "#G:", 0, bg.g, 1.0f, 0.01f, 0.005f);
  1903. bg.b = nk_propertyf(ctx, "#B:", 0, bg.b, 1.0f, 0.01f, 0.005f);
  1904. bg.a = nk_propertyf(ctx, "#A:", 0, bg.a, 1.0f, 0.01f, 0.005f);
  1905. nk_combo_end(ctx);
  1906. }
  1907. }
  1908. nk_end(ctx);
  1909. /* Bindless Texture */
  1910. if (nk_begin(ctx, "Texture", nk_rect(500, 300, 200, 200),
  1911. NK_WINDOW_BORDER | NK_WINDOW_MOVABLE | NK_WINDOW_SCALABLE |
  1912. NK_WINDOW_MINIMIZABLE | NK_WINDOW_TITLE)) {
  1913. struct nk_command_buffer *canvas = nk_window_get_canvas(ctx);
  1914. struct nk_rect total_space = nk_window_get_content_region(ctx);
  1915. nk_draw_image(canvas, total_space, &img, nk_white);
  1916. }
  1917. nk_end(ctx);
  1918. /* -------------- EXAMPLES ---------------- */
  1919. #ifdef INCLUDE_CALCULATOR
  1920. calculator(ctx);
  1921. #endif
  1922. #ifdef INCLUDE_CANVAS
  1923. canvas(ctx);
  1924. #endif
  1925. #ifdef INCLUDE_OVERVIEW
  1926. overview(ctx);
  1927. #endif
  1928. #ifdef INCLUDE_CONFIGURATOR
  1929. style_configurator(ctx, color_table);
  1930. #endif
  1931. #ifdef INCLUDE_NODE_EDITOR
  1932. node_editor(ctx);
  1933. #endif
  1934. /* ----------------------------------------- */
  1935. result = vkWaitForFences(demo.device, 1, &demo.render_fence, VK_TRUE,
  1936. UINT64_MAX);
  1937. if (result != VK_SUCCESS) {
  1938. fprintf(stderr, "vkWaitForFences failed: %d\n", result);
  1939. return false;
  1940. }
  1941. result = vkResetFences(demo.device, 1, &demo.render_fence);
  1942. if (result != VK_SUCCESS) {
  1943. fprintf(stderr, "vkResetFences failed: %d\n", result);
  1944. return false;
  1945. }
  1946. result =
  1947. vkAcquireNextImageKHR(demo.device, demo.swap_chain, UINT64_MAX,
  1948. demo.image_available, NULL, &image_index);
  1949. if (result == VK_ERROR_OUT_OF_DATE_KHR) {
  1950. recreate_swap_chain(&demo);
  1951. /* If vkAcquireNextImageKHR does not successfully acquire an image,
  1952. * semaphore and fence are unaffected. */
  1953. continue;
  1954. }
  1955. if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
  1956. fprintf(stderr, "vkAcquireNextImageKHR failed: %d\n", result);
  1957. return false;
  1958. }
  1959. /* Draw */
  1960. nk_semaphore = nk_sdl_render(demo.graphics_queue, image_index,
  1961. demo.image_available, NK_ANTI_ALIASING_ON);
  1962. if (!render(&demo, &bg, nk_semaphore, image_index)) {
  1963. fprintf(stderr, "render failed\n");
  1964. return false;
  1965. }
  1966. }
  1967. cleanup:
  1968. nk_sdl_shutdown();
  1969. cleanup(&demo);
  1970. SDL_Quit();
  1971. return 0;
  1972. }