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);
357 gpu_mem = vk_allocate(dmem_reqs.size);
362 vkBindImageMemory(vk_device, dimg, gpu_mem, 0);
364 if(!vk_image_set_layout(init_buf, dimg, VK_IMAGE_ASPECT_DEPTH_BIT,
365 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
366 (VkAccessFlagBits)0)) {
367 fprintf(stderr, "Failed to set depth buffer layout.\n");
371 VkImageViewCreateInfo div_inf;
372 memset(&div_inf, 0, sizeof div_inf);
374 div_inf.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
375 div_inf.image = dimg;
376 div_inf.format = dformat;
377 div_inf.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
378 div_inf.subresourceRange.levelCount = 1;
379 div_inf.subresourceRange.layerCount = 1;
380 div_inf.viewType = VK_IMAGE_VIEW_TYPE_2D;
382 if(vkCreateImageView(vk_device, &div_inf, 0, &dview) != VK_SUCCESS) {
383 fprintf(stderr, "Failed to create image view for depth buffer.\n");
390 static bool create_renderpass()
392 VkSurfaceFormatKHR sformat;
393 if(!vku_get_surface_format(vk_physical, vk_surface, &sformat)) {
394 fprintf(stderr, "Failed to get surface format.\n");
398 VkAttachmentDescription att[2];
399 memset(&att, 0, (sizeof att[0]) * 2);
401 att[0].format = sformat.format;
402 att[0].samples = VK_SAMPLE_COUNT_1_BIT;
403 att[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
404 att[0].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
405 att[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
406 att[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
407 att[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
408 att[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
410 att[1].format = dformat;
411 att[1].samples = VK_SAMPLE_COUNT_1_BIT;
412 att[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
413 att[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
414 att[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
415 att[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
416 att[1].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
417 att[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
419 VkAttachmentReference cref;
420 memset(&cref, 0, sizeof cref);
421 cref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
423 VkAttachmentReference dref;
424 memset(&dref, 0, sizeof dref);
426 dref.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
428 VkSubpassDescription sd;
429 memset(&sd, 0, sizeof sd);
430 sd.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
431 sd.colorAttachmentCount = 1;
432 sd.pColorAttachments = &cref;
433 sd.pDepthStencilAttachment = &dref;
435 VkRenderPassCreateInfo rinf;
436 memset(&rinf, 0, sizeof rinf);
437 rinf.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
438 rinf.attachmentCount = 2;
439 rinf.pAttachments = att;
440 rinf.subpassCount = 1;
441 rinf.pSubpasses = &sd;
443 if(vkCreateRenderPass(vk_device, &rinf, 0, &rpass) != VK_SUCCESS) {
444 fprintf(stderr, "Failed to create rpass.\n");
451 static bool create_framebuffers()
453 /* framebuffer attachments */
454 VkImageView fb_att[2];
457 VkFramebufferCreateInfo fbinf;
458 memset(&fbinf, 0, sizeof fbinf);
459 fbinf.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
460 fbinf.renderPass = rpass;
461 fbinf.attachmentCount = 2;
462 fbinf.pAttachments = fb_att;
464 fbinf.height = win_h;
467 for(int i=0; i<2; i++) {
468 fb_att[0] = iviews[i];
469 if(vkCreateFramebuffer(vk_device, &fbinf, 0, &fbs[i]) != VK_SUCCESS) {
470 fprintf(stderr, "Failed to create framebuffer %i\n", i);
477 static bool create_pipelines()
479 VkDescriptorSetLayoutBinding dslb[1];
480 memset(&dslb[0], 0, sizeof dslb[0]);
482 dslb[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
483 dslb[0].descriptorCount = 1;
484 dslb[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
486 VkDescriptorSetLayoutCreateInfo dslinf;
487 memset(&dslinf, 0, sizeof dslinf);
488 dslinf.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
489 dslinf.bindingCount = 1; //dslb.size();
490 dslinf.pBindings = dslb;
492 VkDescriptorSetLayout dsl;
493 if(vkCreateDescriptorSetLayout(vk_device, &dslinf, 0, &dsl) != VK_SUCCESS) {
494 fprintf(stderr, "Failed to create descriptor set layout.\n");
498 VkPipelineLayoutCreateInfo pinf;
499 memset(&pinf, 0, sizeof pinf);
500 pinf.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
501 pinf.setLayoutCount = 1;
502 pinf.pSetLayouts = &dsl;
505 if(vkCreatePipelineLayout(vk_device, &pinf, 0, &pl) != VK_SUCCESS) {
506 fprintf(stderr, "Failed to create pipeline layout.\n");
510 VkPipelineCacheCreateInfo pcinf;
511 memset(&pcinf, 0, sizeof pcinf);
512 pcinf.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
514 VkPipelineCache pcache;
515 if(vkCreatePipelineCache(vk_device, &pcinf, 0, &pcache) != VK_SUCCESS) {
516 fprintf(stderr, "Failed to create pipeline cache.\n");
520 VkGraphicsPipelineCreateInfo ginf;
521 memset(&ginf, 0, sizeof ginf);
522 ginf.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
528 static bool end_init_command_buffer(VkCommandBuffer *cb)
530 if(vkEndCommandBuffer(*cb) != VK_SUCCESS) {
531 fprintf(stderr, "Failed to end command buffer.\n");
536 memset(&si, 0, sizeof si);
537 si.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
538 si.commandBufferCount = 1;
539 si.pCommandBuffers = cb;
541 if(vkQueueSubmit(vk_queue, 1, &si, VK_NULL_HANDLE) != VK_SUCCESS) {
542 fprintf(stderr, "Failed to submit null queue.\n");
546 if(vkQueueWaitIdle(vk_queue) != VK_SUCCESS) {
547 fprintf(stderr, "QueueWaitIdle failure!\n");
551 vkFreeCommandBuffers(vk_device, vk_pool, 1, cb);
552 *cb = VK_NULL_HANDLE;
557 static bool allocate_rendering_command_buffers(VkCommandBuffer *bufs)
559 return vku_alloc_cmdbufs(vk_pool, VK_COMMAND_BUFFER_LEVEL_PRIMARY,
563 static void free_rendering_command_buffers(VkCommandBuffer *bufs, int count)
565 for(int i=0; i<count; i++) {
566 vku_free_cmdbuf(vk_pool, bufs[i]);
570 static bool begin_rendering_command_buffers(VkCommandBuffer *bufs, int count)
572 VkCommandBufferInheritanceInfo iinf;
573 memset(&iinf, 0, sizeof iinf);
574 iinf.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
575 iinf.renderPass = VK_NULL_HANDLE;
576 iinf.framebuffer = VK_NULL_HANDLE;
578 VkCommandBufferBeginInfo binf;
579 memset(&binf, 0, sizeof binf);
580 binf.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
581 binf.pInheritanceInfo = &iinf;
583 // setting clear values
584 VkClearValue clvals[2];
585 for(int i=0; i<4; i++) {
586 clvals[0].color.float32[i] = clear_color[i];
588 clvals[1].depthStencil = {1.0f, 0};
590 //build drawing command buffers
591 for(int i=0; i<count; i++) {
592 if(vkBeginCommandBuffer(bufs[i], &binf) != VK_SUCCESS) {
593 fprintf(stderr, "Failed to begin command buffer: %d\n", i);
597 VkImageMemoryBarrier imbarr;
598 memset(&imbarr, 0, sizeof imbarr);
599 imbarr.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
600 imbarr.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
601 imbarr.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
602 imbarr.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
603 imbarr.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
604 imbarr.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
605 imbarr.image = images[i];
606 imbarr.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
607 vkCmdPipelineBarrier(bufs[i], VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, 0, 0, 0, 1, &imbarr);
609 VkRenderPassBeginInfo rbinf;
610 memset(&rbinf, 0, sizeof rbinf);
611 rbinf.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
612 rbinf.renderPass = rpass;
613 rbinf.framebuffer = fbs[i];
614 rbinf.renderArea.extent.width = win_w;
615 rbinf.renderArea.extent.height = win_h;
616 rbinf.clearValueCount = count;
617 rbinf.pClearValues = clvals;
619 vkCmdBeginRenderPass(bufs[i], &rbinf, VK_SUBPASS_CONTENTS_INLINE);
621 memset(&viewport, 0, sizeof viewport);
622 viewport.width = (float)win_w;
623 viewport.height = (float)win_h;
624 viewport.maxDepth = 1.0f;
625 vkCmdSetViewport(bufs[i], 0, 1, &viewport);
628 memset(&scissor, 0, sizeof scissor);
629 scissor.extent.width = win_w;
630 scissor.extent.height = win_h;
631 vkCmdSetScissor(bufs[i], 0, 1, &scissor);
632 vkCmdEndRenderPass(bufs[i]);
634 /* pre-present barrier */
635 VkImageMemoryBarrier ppb;
636 memset(&ppb, 0, sizeof ppb);
637 ppb.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
638 ppb.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
639 ppb.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
640 ppb.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
641 ppb.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
642 ppb.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
643 ppb.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
644 ppb.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
645 ppb.image = images[i];
647 vkCmdPipelineBarrier(bufs[i], VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, 0, 0, 0, 1, &ppb);
649 if(vkEndCommandBuffer(bufs[i]) != VK_SUCCESS) {
650 fprintf(stderr, "Failed to end command buffer: %d\n", i);
657 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)
678 // VkSwapchainKHR sc;
679 // if(!(sc = vku_create_swapchain(vk_surface, width, height, 2, VK_PRESENT_MODE_FIFO_KHR,
681 // fprintf(stderr, "Failed to create %dx%d double-buffered swapchain\n", width, height);
684 // vk_swapchain = sc;
686 // delete [] vkswapchain_images;
687 // vkswapchain_images = vku_get_swapchain_images(sc, 0);
688 // vk_curr_swapchain_image = vku_get_next_image(vk_swapchain);
691 static void clear(float r, float g, float b)
695 static void viewport(int x, int y, int width, int height)
699 static void zbuffer(bool enable)
703 static void cull_face(Gfx_cull_face cf)
707 static void swapbuffers()
711 static void begin_drawing()
713 VkSemaphoreCreateInfo psinf;
714 memset(&psinf, 0, sizeof psinf);
715 psinf.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
718 if((res = vkCreateSemaphore(vk_device, &psinf, 0, &psema)) != VK_SUCCESS) {
719 fprintf(stderr, "Failed to create semaphore.\n");
721 assert(res == VK_SUCCESS);
724 static void end_drawing()
726 VkResult res = vkAcquireNextImageKHR(vk_device, vk_swapchain,
727 UINT64_MAX, psema, VK_NULL_HANDLE, &curr_img);
728 if(res == VK_ERROR_OUT_OF_DATE_KHR) {
729 fprintf(stderr, "Swapchain out of date.\n");
732 assert(res == VK_SUCCESS);
735 memset(&sinf, 0, sizeof sinf);
736 VkPipelineStageFlags psflags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
737 sinf.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
738 sinf.waitSemaphoreCount = 1;
739 sinf.pWaitSemaphores = &psema;
740 sinf.pWaitDstStageMask = &psflags;
741 sinf.commandBufferCount = 1;
742 sinf.pCommandBuffers = &rbufs[curr_img];
744 res = vkQueueSubmit(vk_queue, 1, &sinf, VK_NULL_HANDLE);
745 assert(res == VK_SUCCESS);
747 VkPresentInfoKHR pinf;
748 memset(&pinf, 0, sizeof pinf);
749 pinf.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
750 pinf.swapchainCount = 1;
751 pinf.pSwapchains = &vk_swapchain;
752 pinf.pImageIndices = &curr_img;
754 res = vkQueuePresentKHR(vk_queue, &pinf);
755 if(res == VK_ERROR_OUT_OF_DATE_KHR) {
756 fprintf(stderr, "Swapchain out of date.\n");
758 assert(res == VK_SUCCESS);
760 res = vkQueueWaitIdle(vk_queue);
761 assert(res == VK_SUCCESS);
763 vkDestroySemaphore(vk_device, psema, 0);