main.c 79 KB

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