1 #define GLFW_INCLUDE_VULKAN
2 #include <GLFW/glfw3.h>
11 #include <gmath/gmath.h>
13 #include "allocator.h"
19 /* global variables */
20 extern GLFWwindow *win;
25 static VkCommandBuffer init_buf;
26 static VkCommandBuffer rbufs[2];
29 static VkImageView dview;
30 static const VkFormat dformat = VK_FORMAT_D32_SFLOAT_S8_UINT;
32 static VkImage *images;
33 static VkImageView *iviews;
34 static uint32_t num_images;
36 static VkRenderPass rpass;
37 static VkFramebuffer fbs[2];
38 //semaphores-drawing-presentation
39 static uint32_t curr_img; // current sc image
40 static VkSemaphore psema;
43 /* static variables */
44 static VkDeviceMemory gpu_mem; // to be replaced when I fix the allocator
45 static Vec4 clear_color(1, 0.1, 0.1, 1.0);
47 /* static functions */
48 static void error_callback(int error, const char *descr);
49 static void clear(float r, float g, float b);
50 static void viewport(int x, int y, int width, int height);
51 static void zbuffer(bool enable);
52 static void cull_face(Gfx_cull_face cf);
53 static void reshape(int width, int height);
54 static void swapbuffers();
55 static void begin_drawing();
56 static void end_drawing();
58 static bool create_swapchain(VkSwapchainKHR *sc);
59 static bool create_zbuffer();
60 static bool create_renderpass();
61 static bool create_framebuffers();
62 static bool create_pipelines();
63 static bool begin_init_command_buffer(VkCommandBuffer *cb);
64 static bool end_init_command_buffer(VkCommandBuffer *cb);
65 static bool allocate_rendering_command_buffers(VkCommandBuffer *bufs);
66 static void free_rendering_command_buffers(VkCommandBuffer *bufs, int count);
67 static bool begin_rendering_command_buffers(VkCommandBuffer *bufs, int count);
72 fprintf(stderr, "Failed to initialize GLFW.\n");
76 if(!glfwVulkanSupported()) {
77 fprintf(stderr, "No Vulkan support on the device.\n");
82 glfwSetErrorCallback(error_callback);
84 /* create device and command pool! */
85 if(!vku_create_device()) {
86 fprintf(stderr, "Failed to initialize vulkan.\n");
90 if(!glfwGetPhysicalDevicePresentationSupport(vkinst, vk_physical, vkqfamily)) {
91 fprintf(stderr, "Presentation support not found.\n");
95 glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
96 if(!(win = glfwCreateWindow(win_w, win_h, "vkcow", 0, 0))) {
97 fprintf(stderr, "Failed to create window.\n");
101 VkResult res = glfwCreateWindowSurface(vkinst, win, 0, &vk_surface);
102 if(res != VK_SUCCESS) {
103 fprintf(stderr, "Failed to create KHR surface: %s\n", vku_get_vulkan_error_str(res));
107 if(!create_swapchain(&vk_swapchain)) {
108 fprintf(stderr, "Failed to create swapchain.\n");
112 init_buf = VK_NULL_HANDLE;
113 if(!begin_init_command_buffer(&init_buf)) {
114 fprintf(stderr, "Failed to start VK_NULL_HANDLE command buffer.\n");
118 if(!create_zbuffer()) {
119 fprintf(stderr, "Failed to create depth buffer.\n");
123 if(!create_renderpass()) {
124 fprintf(stderr, "Failed to create the renderpass.\n");
128 if(!create_framebuffers()) {
129 fprintf(stderr, "Failed to create the framebuffer.\n");
133 if(!create_pipelines()) {
134 fprintf(stderr, "Failed to create the pipelines.\n");
138 if(!end_init_command_buffer(&init_buf)) {
139 fprintf(stderr, "Failed to end the command buffer.\n");
143 /* rendering command buffers */
144 if(!allocate_rendering_command_buffers(rbufs)) {
145 fprintf(stderr, "Failed to allocate rendering command buffers.\n");
149 if(!begin_rendering_command_buffers(rbufs, 2)) {
150 fprintf(stderr, "Failed to begin rendering command buffers.\n");
155 gfx_viewport = viewport;
156 gfx_zbuffer = zbuffer;
157 gfx_cull_face = cull_face;
158 gfx_reshape = reshape;
159 gfx_swapbuffers = swapbuffers;
160 gfx_begin_drawing = begin_drawing;
161 gfx_end_drawing = end_drawing;
166 static bool create_swapchain(VkSwapchainKHR *sc)
168 /* surface capabilities */
169 VkSurfaceCapabilitiesKHR scap;
170 if(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(vk_physical, vk_surface, &scap) != VK_SUCCESS) {
171 fprintf(stderr, "Failed to get physical device surface capabilities\n");
175 /* presentation modes */
177 if(vkGetPhysicalDeviceSurfacePresentModesKHR(vk_physical, vk_surface, &prmode_cnt, 0) != VK_SUCCESS) {
178 fprintf(stderr, "Failed to get physical device surface presentation modes count.\n");
182 if(prmode_cnt == 0) {
183 fprintf(stderr, "Presentation modes not found.\n");
187 VkPresentModeKHR scmode = VK_PRESENT_MODE_FIFO_KHR;
188 VkPresentModeKHR *modes = new VkPresentModeKHR[prmode_cnt];
190 if(vkGetPhysicalDeviceSurfacePresentModesKHR(vk_physical, vk_surface, &prmode_cnt, modes) != VK_SUCCESS) {
191 fprintf(stderr, "Failed to get physical device presentation modes.\n");
195 for(uint32_t i=0; i<prmode_cnt; i++) {
196 if(modes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
197 scmode = VK_PRESENT_MODE_MAILBOX_KHR;
200 if((scmode != VK_PRESENT_MODE_MAILBOX_KHR) && (modes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR)) {
202 scmode = VK_PRESENT_MODE_IMMEDIATE_KHR;
206 /* swapchain extents */
208 if(scap.currentExtent.width == 0xffffffff || scap.currentExtent.height == 0xffffffff) {
209 scextent.width = win_w;
210 scextent.height = win_h;
213 scextent = scap.currentExtent;
214 win_w = scextent.width;
215 win_h = scextent.height;
218 /* number of swapchain images (on intel that's 3: maybe should hardcode it to 2?) */
219 num_images = scap.minImageCount; //+ 1;
220 /* intel doesn't set the maxImageCount */
221 if(scap.maxImageCount > 0 && num_images > scap.maxImageCount)
222 num_images = scap.maxImageCount;
224 printf("num_images : %u\n", num_images);
225 assert(num_images > 0);
227 images = new VkImage[num_images];
228 iviews = new VkImageView[num_images];
230 /* transform flags */
231 VkSurfaceTransformFlagBitsKHR pre_transf = scap.currentTransform;
232 if(scap.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR)
233 pre_transf = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
235 /* find suitable colorspace, format */
237 VkColorSpaceKHR colorspace;
239 VkSurfaceFormatKHR sformat;
240 if(!vku_get_surface_format(vk_physical, vk_surface, &sformat)) {
244 format = sformat.format;
245 colorspace = sformat.colorSpace;
247 /* creating the swapchain */
248 VkSwapchainCreateInfoKHR sinfo;
249 memset(&sinfo, 0, sizeof sinfo);
251 sinfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
252 sinfo.surface = vk_surface;
253 sinfo.minImageCount = num_images;
254 sinfo.imageFormat = format;
255 sinfo.imageColorSpace = colorspace;
256 sinfo.imageExtent = scextent;
257 sinfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
258 sinfo.preTransform = pre_transf;
259 sinfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
260 sinfo.imageArrayLayers = 1;
261 sinfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
262 sinfo.presentMode = scmode;
263 sinfo.oldSwapchain = VK_NULL_HANDLE; //TODO
264 sinfo.clipped = VK_TRUE; //TODO
266 if(vkCreateSwapchainKHR(vk_device, &sinfo, 0, sc) != VK_SUCCESS) {
267 fprintf(stderr, "Failed to create swapchain.\n");
271 if(vkGetSwapchainImagesKHR(vk_device, *sc, &num_images, 0) != VK_SUCCESS) {
272 fprintf(stderr, "Failed to get the number of the swapchain images.\n");
276 if(vkGetSwapchainImagesKHR(vk_device, *sc, &num_images, images) != VK_SUCCESS) {
277 fprintf(stderr, "Failed to get the swapchain images.\n");
281 VkImageViewCreateInfo ivinf;
282 memset(&ivinf, 0, sizeof ivinf);
283 ivinf.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
284 ivinf.format = format;
286 VK_COMPONENT_SWIZZLE_R,
287 VK_COMPONENT_SWIZZLE_G,
288 VK_COMPONENT_SWIZZLE_B,
289 VK_COMPONENT_SWIZZLE_A
291 ivinf.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
292 ivinf.subresourceRange.levelCount = 1;
293 ivinf.subresourceRange.layerCount = 1;
294 ivinf.viewType = VK_IMAGE_VIEW_TYPE_2D;
296 for(uint32_t i=0; i<num_images; i++) {
297 ivinf.image = images[i];
300 if((res = vkCreateImageView(vk_device, &ivinf, 0, &iviews[i])) != VK_SUCCESS) {
301 fprintf(stderr, "Failed to create image view %d: %s.\n", i, vku_get_vulkan_error_str(res));
309 static bool begin_init_command_buffer(VkCommandBuffer *cb)
311 if(*cb == VK_NULL_HANDLE) {
312 *cb = vku_alloc_cmdbuf(vk_pool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
314 VkCommandBufferInheritanceInfo ciinf;
315 memset(&ciinf, 0, sizeof ciinf);
316 ciinf.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
317 ciinf.renderPass = VK_NULL_HANDLE;
318 ciinf.framebuffer = VK_NULL_HANDLE;
319 ciinf.occlusionQueryEnable = VK_FALSE;
321 VkCommandBufferBeginInfo cbinf;
322 memset(&cbinf, 0, sizeof cbinf);
323 cbinf.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
324 cbinf.pInheritanceInfo = &ciinf;
326 if(vkBeginCommandBuffer(*cb, &cbinf) != VK_SUCCESS) {
327 fprintf(stderr, "Failed to begin command buffer.\n");
334 static bool create_zbuffer()
336 VkImageCreateInfo dinfo;
337 memset(&dinfo, 0, sizeof dinfo);
339 dinfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
340 dinfo.imageType = VK_IMAGE_TYPE_2D;
341 dinfo.format = dformat;
342 dinfo.extent = {(uint32_t)win_w, (uint32_t)win_h, 1};
344 dinfo.arrayLayers = 1;
345 dinfo.samples = VK_SAMPLE_COUNT_1_BIT;
346 dinfo.tiling = VK_IMAGE_TILING_OPTIMAL;
347 dinfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
349 if(vkCreateImage(vk_device, &dinfo, 0, &dimg) != VK_SUCCESS) {
350 fprintf(stderr, "Failed to create depth buffer image.\n");
354 VkMemoryRequirements dmem_reqs;
355 vkGetImageMemoryRequirements(vk_device, dimg, &dmem_reqs);
358 if(!vku_allocate(dmem_reqs.size, &block)) {
359 fprintf(stderr, "Failed to allocate zbuffer image.\n");
363 vkBindImageMemory(vk_device, dimg, block.dev_mem, 0);
365 if(!vk_image_set_layout(init_buf, dimg, VK_IMAGE_ASPECT_DEPTH_BIT,
366 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
367 (VkAccessFlagBits)0)) {
368 fprintf(stderr, "Failed to set depth buffer layout.\n");
372 VkImageViewCreateInfo div_inf;
373 memset(&div_inf, 0, sizeof div_inf);
375 div_inf.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
376 div_inf.image = dimg;
377 div_inf.format = dformat;
378 div_inf.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
379 div_inf.subresourceRange.levelCount = 1;
380 div_inf.subresourceRange.layerCount = 1;
381 div_inf.viewType = VK_IMAGE_VIEW_TYPE_2D;
383 if(vkCreateImageView(vk_device, &div_inf, 0, &dview) != VK_SUCCESS) {
384 fprintf(stderr, "Failed to create image view for depth buffer.\n");
391 static bool create_renderpass()
393 VkSurfaceFormatKHR sformat;
394 if(!vku_get_surface_format(vk_physical, vk_surface, &sformat)) {
395 fprintf(stderr, "Failed to get surface format.\n");
399 VkAttachmentDescription att[2];
400 memset(&att, 0, (sizeof att[0]) * 2);
402 att[0].format = sformat.format;
403 att[0].samples = VK_SAMPLE_COUNT_1_BIT;
404 att[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
405 att[0].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
406 att[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
407 att[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
408 att[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
409 att[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
411 att[1].format = dformat;
412 att[1].samples = VK_SAMPLE_COUNT_1_BIT;
413 att[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
414 att[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
415 att[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
416 att[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
417 att[1].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
418 att[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
420 VkAttachmentReference cref;
421 memset(&cref, 0, sizeof cref);
422 cref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
424 VkAttachmentReference dref;
425 memset(&dref, 0, sizeof dref);
427 dref.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
429 VkSubpassDescription sd;
430 memset(&sd, 0, sizeof sd);
431 sd.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
432 sd.colorAttachmentCount = 1;
433 sd.pColorAttachments = &cref;
434 sd.pDepthStencilAttachment = &dref;
436 VkRenderPassCreateInfo rinf;
437 memset(&rinf, 0, sizeof rinf);
438 rinf.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
439 rinf.attachmentCount = 2;
440 rinf.pAttachments = att;
441 rinf.subpassCount = 1;
442 rinf.pSubpasses = &sd;
444 if(vkCreateRenderPass(vk_device, &rinf, 0, &rpass) != VK_SUCCESS) {
445 fprintf(stderr, "Failed to create rpass.\n");
452 static bool create_framebuffers()
454 /* framebuffer attachments */
455 VkImageView fb_att[2];
458 VkFramebufferCreateInfo fbinf;
459 memset(&fbinf, 0, sizeof fbinf);
460 fbinf.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
461 fbinf.renderPass = rpass;
462 fbinf.attachmentCount = 2;
463 fbinf.pAttachments = fb_att;
465 fbinf.height = win_h;
468 for(int i=0; i<2; i++) {
469 fb_att[0] = iviews[i];
470 if(vkCreateFramebuffer(vk_device, &fbinf, 0, &fbs[i]) != VK_SUCCESS) {
471 fprintf(stderr, "Failed to create framebuffer %i\n", i);
478 static bool create_pipelines()
480 VkDescriptorSetLayoutBinding dslb[1];
481 memset(&dslb[0], 0, sizeof dslb[0]);
483 dslb[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
484 dslb[0].descriptorCount = 1;
485 dslb[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
487 VkDescriptorSetLayoutCreateInfo dslinf;
488 memset(&dslinf, 0, sizeof dslinf);
489 dslinf.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
490 dslinf.bindingCount = 1; //dslb.size();
491 dslinf.pBindings = dslb;
493 VkDescriptorSetLayout dsl;
494 if(vkCreateDescriptorSetLayout(vk_device, &dslinf, 0, &dsl) != VK_SUCCESS) {
495 fprintf(stderr, "Failed to create descriptor set layout.\n");
499 VkPipelineLayoutCreateInfo pinf;
500 memset(&pinf, 0, sizeof pinf);
501 pinf.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
502 pinf.setLayoutCount = 1;
503 pinf.pSetLayouts = &dsl;
506 if(vkCreatePipelineLayout(vk_device, &pinf, 0, &pl) != VK_SUCCESS) {
507 fprintf(stderr, "Failed to create pipeline layout.\n");
511 VkPipelineCacheCreateInfo pcinf;
512 memset(&pcinf, 0, sizeof pcinf);
513 pcinf.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
515 VkPipelineCache pcache;
516 if(vkCreatePipelineCache(vk_device, &pcinf, 0, &pcache) != VK_SUCCESS) {
517 fprintf(stderr, "Failed to create pipeline cache.\n");
521 VkGraphicsPipelineCreateInfo ginf;
522 memset(&ginf, 0, sizeof ginf);
523 ginf.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
529 static bool end_init_command_buffer(VkCommandBuffer *cb)
531 if(vkEndCommandBuffer(*cb) != VK_SUCCESS) {
532 fprintf(stderr, "Failed to end command buffer.\n");
537 memset(&si, 0, sizeof si);
538 si.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
539 si.commandBufferCount = 1;
540 si.pCommandBuffers = cb;
542 if(vkQueueSubmit(vk_queue, 1, &si, VK_NULL_HANDLE) != VK_SUCCESS) {
543 fprintf(stderr, "Failed to submit null queue.\n");
547 if(vkQueueWaitIdle(vk_queue) != VK_SUCCESS) {
548 fprintf(stderr, "QueueWaitIdle failure!\n");
552 vkFreeCommandBuffers(vk_device, vk_pool, 1, cb);
553 *cb = VK_NULL_HANDLE;
558 static bool allocate_rendering_command_buffers(VkCommandBuffer *bufs)
560 return vku_alloc_cmdbufs(vk_pool, VK_COMMAND_BUFFER_LEVEL_PRIMARY,
564 static void free_rendering_command_buffers(VkCommandBuffer *bufs, int count)
566 for(int i=0; i<count; i++) {
567 vku_free_cmdbuf(vk_pool, bufs[i]);
571 static bool begin_rendering_command_buffers(VkCommandBuffer *bufs, int count)
573 VkCommandBufferInheritanceInfo iinf;
574 memset(&iinf, 0, sizeof iinf);
575 iinf.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
576 iinf.renderPass = VK_NULL_HANDLE;
577 iinf.framebuffer = VK_NULL_HANDLE;
579 VkCommandBufferBeginInfo binf;
580 memset(&binf, 0, sizeof binf);
581 binf.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
582 binf.pInheritanceInfo = &iinf;
584 // setting clear values
585 VkClearValue clvals[2];
586 for(int i=0; i<4; i++) {
587 clvals[0].color.float32[i] = clear_color[i];
589 clvals[1].depthStencil = {1.0f, 0};
591 //build drawing command buffers
592 for(int i=0; i<count; i++) {
593 if(vkBeginCommandBuffer(bufs[i], &binf) != VK_SUCCESS) {
594 fprintf(stderr, "Failed to begin command buffer: %d\n", i);
598 VkImageMemoryBarrier imbarr;
599 memset(&imbarr, 0, sizeof imbarr);
600 imbarr.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
601 imbarr.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
602 imbarr.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
603 imbarr.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
604 imbarr.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
605 imbarr.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
606 imbarr.image = images[i];
607 imbarr.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
608 vkCmdPipelineBarrier(bufs[i], VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, 0, 0, 0, 1, &imbarr);
610 VkRenderPassBeginInfo rbinf;
611 memset(&rbinf, 0, sizeof rbinf);
612 rbinf.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
613 rbinf.renderPass = rpass;
614 rbinf.framebuffer = fbs[i];
615 rbinf.renderArea.extent.width = win_w;
616 rbinf.renderArea.extent.height = win_h;
617 rbinf.clearValueCount = count;
618 rbinf.pClearValues = clvals;
620 vkCmdBeginRenderPass(bufs[i], &rbinf, VK_SUBPASS_CONTENTS_INLINE);
622 memset(&viewport, 0, sizeof viewport);
623 viewport.width = (float)win_w;
624 viewport.height = (float)win_h;
625 viewport.maxDepth = 1.0f;
626 vkCmdSetViewport(bufs[i], 0, 1, &viewport);
629 memset(&scissor, 0, sizeof scissor);
630 scissor.extent.width = win_w;
631 scissor.extent.height = win_h;
632 vkCmdSetScissor(bufs[i], 0, 1, &scissor);
633 vkCmdEndRenderPass(bufs[i]);
635 /* pre-present barrier */
636 VkImageMemoryBarrier ppb;
637 memset(&ppb, 0, sizeof ppb);
638 ppb.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
639 ppb.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
640 ppb.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
641 ppb.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
642 ppb.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
643 ppb.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
644 ppb.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
645 ppb.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
646 ppb.image = images[i];
648 vkCmdPipelineBarrier(bufs[i], VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, 0, 0, 0, 1, &ppb);
650 if(vkEndCommandBuffer(bufs[i]) != VK_SUCCESS) {
651 fprintf(stderr, "Failed to end command buffer: %d\n", i);
658 void cleanup_vulkan()
660 free_rendering_command_buffers(rbufs, 2);
662 glfwDestroyWindow(win);
666 //TODOs according to the book:
667 // 1- make sure all threads have been terminated (when I add threads)
671 static void error_callback(int error, const char *description)
673 fprintf(stderr, "GLFW error %d: %s.\n", error, description);
676 static void reshape(int width, int height)
680 static void clear(float r, float g, float b)
684 static void viewport(int x, int y, int width, int height)
688 static void zbuffer(bool enable)
692 static void cull_face(Gfx_cull_face cf)
696 static void swapbuffers()
700 static void begin_drawing()
702 VkSemaphoreCreateInfo psinf;
703 memset(&psinf, 0, sizeof psinf);
704 psinf.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
707 if((res = vkCreateSemaphore(vk_device, &psinf, 0, &psema)) != VK_SUCCESS) {
708 fprintf(stderr, "Failed to create semaphore.\n");
710 assert(res == VK_SUCCESS);
713 static void end_drawing()
715 VkResult res = vkAcquireNextImageKHR(vk_device, vk_swapchain,
716 UINT64_MAX, psema, VK_NULL_HANDLE, &curr_img);
717 if(res == VK_ERROR_OUT_OF_DATE_KHR) {
718 fprintf(stderr, "Swapchain out of date.\n");
721 assert(res == VK_SUCCESS);
724 memset(&sinf, 0, sizeof sinf);
725 VkPipelineStageFlags psflags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
726 sinf.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
727 sinf.waitSemaphoreCount = 1;
728 sinf.pWaitSemaphores = &psema;
729 sinf.pWaitDstStageMask = &psflags;
730 sinf.commandBufferCount = 1;
731 sinf.pCommandBuffers = &rbufs[curr_img];
733 res = vkQueueSubmit(vk_queue, 1, &sinf, VK_NULL_HANDLE);
734 assert(res == VK_SUCCESS);
736 VkPresentInfoKHR pinf;
737 memset(&pinf, 0, sizeof pinf);
738 pinf.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
739 pinf.swapchainCount = 1;
740 pinf.pSwapchains = &vk_swapchain;
741 pinf.pImageIndices = &curr_img;
743 res = vkQueuePresentKHR(vk_queue, &pinf);
744 if(res == VK_ERROR_OUT_OF_DATE_KHR) {
745 fprintf(stderr, "Swapchain out of date.\n");
747 assert(res == VK_SUCCESS);
749 res = vkQueueWaitIdle(vk_queue);
750 assert(res == VK_SUCCESS);
752 vkDestroySemaphore(vk_device, psema, 0);