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 Vec4 clear_color(1, 0.1, 0.1, 1.0);
46 /* static functions */
47 static void error_callback(int error, const char *descr);
48 static void clear(float r, float g, float b);
49 static void viewport(int x, int y, int width, int height);
50 static void zbuffer(bool enable);
51 static void cull_face(Gfx_cull_face cf);
52 static void reshape(int width, int height);
53 static void swapbuffers();
54 static void begin_drawing();
55 static void end_drawing();
57 static bool create_swapchain(VkSwapchainKHR *sc);
58 static bool create_zbuffer();
59 static bool create_renderpass();
60 static bool create_framebuffers();
61 static bool create_pipelines();
62 static bool begin_init_command_buffer(VkCommandBuffer *cb);
63 static bool end_init_command_buffer(VkCommandBuffer *cb);
64 static bool allocate_rendering_command_buffers(VkCommandBuffer *bufs);
65 static void free_rendering_command_buffers(VkCommandBuffer *bufs, int count);
66 static bool begin_rendering_command_buffers(VkCommandBuffer *bufs, int count);
71 fprintf(stderr, "Failed to initialize GLFW.\n");
75 if(!glfwVulkanSupported()) {
76 fprintf(stderr, "No Vulkan support on the device.\n");
81 glfwSetErrorCallback(error_callback);
83 /* create device and command pool! */
84 if(!vku_create_device()) {
85 fprintf(stderr, "Failed to initialize vulkan.\n");
89 if(!glfwGetPhysicalDevicePresentationSupport(vkinst, vk_physical, vkqfamily)) {
90 fprintf(stderr, "Presentation support not found.\n");
94 glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
95 if(!(win = glfwCreateWindow(win_w, win_h, "vkcow", 0, 0))) {
96 fprintf(stderr, "Failed to create window.\n");
100 VkResult res = glfwCreateWindowSurface(vkinst, win, 0, &vk_surface);
101 if(res != VK_SUCCESS) {
102 fprintf(stderr, "Failed to create KHR surface: %s\n", vku_get_vulkan_error_str(res));
106 if(!create_swapchain(&vk_swapchain)) {
107 fprintf(stderr, "Failed to create swapchain.\n");
111 init_buf = VK_NULL_HANDLE;
112 if(!begin_init_command_buffer(&init_buf)) {
113 fprintf(stderr, "Failed to start VK_NULL_HANDLE command buffer.\n");
117 if(!create_zbuffer()) {
118 fprintf(stderr, "Failed to create depth buffer.\n");
122 if(!create_renderpass()) {
123 fprintf(stderr, "Failed to create the renderpass.\n");
127 if(!create_framebuffers()) {
128 fprintf(stderr, "Failed to create the framebuffer.\n");
132 if(!create_pipelines()) {
133 fprintf(stderr, "Failed to create the pipelines.\n");
137 if(!end_init_command_buffer(&init_buf)) {
138 fprintf(stderr, "Failed to end the command buffer.\n");
142 /* rendering command buffers */
143 if(!allocate_rendering_command_buffers(rbufs)) {
144 fprintf(stderr, "Failed to allocate rendering command buffers.\n");
148 if(!begin_rendering_command_buffers(rbufs, 2)) {
149 fprintf(stderr, "Failed to begin rendering command buffers.\n");
154 gfx_viewport = viewport;
155 gfx_zbuffer = zbuffer;
156 gfx_cull_face = cull_face;
157 gfx_reshape = reshape;
158 gfx_swapbuffers = swapbuffers;
159 gfx_begin_drawing = begin_drawing;
160 gfx_end_drawing = end_drawing;
165 static bool create_swapchain(VkSwapchainKHR *sc)
167 /* surface capabilities */
168 VkSurfaceCapabilitiesKHR scap;
169 if(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(vk_physical, vk_surface, &scap) != VK_SUCCESS) {
170 fprintf(stderr, "Failed to get physical device surface capabilities\n");
174 /* presentation modes */
176 if(vkGetPhysicalDeviceSurfacePresentModesKHR(vk_physical, vk_surface, &prmode_cnt, 0) != VK_SUCCESS) {
177 fprintf(stderr, "Failed to get physical device surface presentation modes count.\n");
181 if(prmode_cnt == 0) {
182 fprintf(stderr, "Presentation modes not found.\n");
186 VkPresentModeKHR scmode = VK_PRESENT_MODE_FIFO_KHR;
187 VkPresentModeKHR *modes = new VkPresentModeKHR[prmode_cnt];
189 if(vkGetPhysicalDeviceSurfacePresentModesKHR(vk_physical, vk_surface, &prmode_cnt, modes) != VK_SUCCESS) {
190 fprintf(stderr, "Failed to get physical device presentation modes.\n");
194 for(uint32_t i=0; i<prmode_cnt; i++) {
195 if(modes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
196 scmode = VK_PRESENT_MODE_MAILBOX_KHR;
199 if((scmode != VK_PRESENT_MODE_MAILBOX_KHR) && (modes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR)) {
201 scmode = VK_PRESENT_MODE_IMMEDIATE_KHR;
205 /* swapchain extents */
207 if(scap.currentExtent.width == 0xffffffff || scap.currentExtent.height == 0xffffffff) {
208 scextent.width = win_w;
209 scextent.height = win_h;
212 scextent = scap.currentExtent;
213 win_w = scextent.width;
214 win_h = scextent.height;
217 /* number of swapchain images (on intel that's 3: maybe should hardcode it to 2?) */
218 num_images = scap.minImageCount; //+ 1;
219 /* intel doesn't set the maxImageCount */
220 if(scap.maxImageCount > 0 && num_images > scap.maxImageCount)
221 num_images = scap.maxImageCount;
223 printf("num_images : %u\n", num_images);
224 assert(num_images > 0);
226 images = new VkImage[num_images];
227 iviews = new VkImageView[num_images];
229 /* transform flags */
230 VkSurfaceTransformFlagBitsKHR pre_transf = scap.currentTransform;
231 if(scap.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR)
232 pre_transf = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
234 /* find suitable colorspace, format */
236 VkColorSpaceKHR colorspace;
238 VkSurfaceFormatKHR sformat;
239 if(!vku_get_surface_format(vk_physical, vk_surface, &sformat)) {
243 format = sformat.format;
244 colorspace = sformat.colorSpace;
246 /* creating the swapchain */
247 VkSwapchainCreateInfoKHR sinfo;
248 memset(&sinfo, 0, sizeof sinfo);
250 sinfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
251 sinfo.surface = vk_surface;
252 sinfo.minImageCount = num_images;
253 sinfo.imageFormat = format;
254 sinfo.imageColorSpace = colorspace;
255 sinfo.imageExtent = scextent;
256 sinfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
257 sinfo.preTransform = pre_transf;
258 sinfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
259 sinfo.imageArrayLayers = 1;
260 sinfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
261 sinfo.presentMode = scmode;
262 sinfo.oldSwapchain = VK_NULL_HANDLE; //TODO
263 sinfo.clipped = VK_TRUE; //TODO
265 if(vkCreateSwapchainKHR(vk_device, &sinfo, 0, sc) != VK_SUCCESS) {
266 fprintf(stderr, "Failed to create swapchain.\n");
270 if(vkGetSwapchainImagesKHR(vk_device, *sc, &num_images, 0) != VK_SUCCESS) {
271 fprintf(stderr, "Failed to get the number of the swapchain images.\n");
275 if(vkGetSwapchainImagesKHR(vk_device, *sc, &num_images, images) != VK_SUCCESS) {
276 fprintf(stderr, "Failed to get the swapchain images.\n");
280 VkImageViewCreateInfo ivinf;
281 memset(&ivinf, 0, sizeof ivinf);
282 ivinf.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
283 ivinf.format = format;
285 VK_COMPONENT_SWIZZLE_R,
286 VK_COMPONENT_SWIZZLE_G,
287 VK_COMPONENT_SWIZZLE_B,
288 VK_COMPONENT_SWIZZLE_A
290 ivinf.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
291 ivinf.subresourceRange.levelCount = 1;
292 ivinf.subresourceRange.layerCount = 1;
293 ivinf.viewType = VK_IMAGE_VIEW_TYPE_2D;
295 for(uint32_t i=0; i<num_images; i++) {
296 ivinf.image = images[i];
299 if((res = vkCreateImageView(vk_device, &ivinf, 0, &iviews[i])) != VK_SUCCESS) {
300 fprintf(stderr, "Failed to create image view %d: %s.\n", i, vku_get_vulkan_error_str(res));
308 static bool begin_init_command_buffer(VkCommandBuffer *cb)
310 if(*cb == VK_NULL_HANDLE) {
311 *cb = vku_alloc_cmdbuf(vk_pool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
313 VkCommandBufferInheritanceInfo ciinf;
314 memset(&ciinf, 0, sizeof ciinf);
315 ciinf.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
316 ciinf.renderPass = VK_NULL_HANDLE;
317 ciinf.framebuffer = VK_NULL_HANDLE;
318 ciinf.occlusionQueryEnable = VK_FALSE;
320 VkCommandBufferBeginInfo cbinf;
321 memset(&cbinf, 0, sizeof cbinf);
322 cbinf.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
323 cbinf.pInheritanceInfo = &ciinf;
325 if(vkBeginCommandBuffer(*cb, &cbinf) != VK_SUCCESS) {
326 fprintf(stderr, "Failed to begin command buffer.\n");
333 static bool create_zbuffer()
335 VkImageCreateInfo dinfo;
336 memset(&dinfo, 0, sizeof dinfo);
338 dinfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
339 dinfo.imageType = VK_IMAGE_TYPE_2D;
340 dinfo.format = dformat;
341 dinfo.extent = {(uint32_t)win_w, (uint32_t)win_h, 1};
343 dinfo.arrayLayers = 1;
344 dinfo.samples = VK_SAMPLE_COUNT_1_BIT;
345 dinfo.tiling = VK_IMAGE_TILING_OPTIMAL;
346 dinfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
348 if(vkCreateImage(vk_device, &dinfo, 0, &dimg) != VK_SUCCESS) {
349 fprintf(stderr, "Failed to create depth buffer image.\n");
353 VkMemoryRequirements dmem_reqs;
354 vkGetImageMemoryRequirements(vk_device, dimg, &dmem_reqs);
357 if(!vku_allocate(dmem_reqs.size, &block)) {
358 fprintf(stderr, "Failed to allocate zbuffer image.\n");
362 vkBindImageMemory(vk_device, dimg, block.dev_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()
659 free_rendering_command_buffers(rbufs, 2);
661 glfwDestroyWindow(win);
665 //TODOs according to the book:
666 // 1- make sure all threads have been terminated (when I add threads)
670 static void error_callback(int error, const char *description)
672 fprintf(stderr, "GLFW error %d: %s.\n", error, description);
675 static void reshape(int width, int height)
679 static void clear(float r, float g, float b)
683 static void viewport(int x, int y, int width, int height)
687 static void zbuffer(bool enable)
691 static void cull_face(Gfx_cull_face cf)
695 static void swapbuffers()
699 static void begin_drawing()
701 VkSemaphoreCreateInfo psinf;
702 memset(&psinf, 0, sizeof psinf);
703 psinf.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
706 if((res = vkCreateSemaphore(vk_device, &psinf, 0, &psema)) != VK_SUCCESS) {
707 fprintf(stderr, "Failed to create semaphore.\n");
709 assert(res == VK_SUCCESS);
712 static void end_drawing()
714 VkResult res = vkAcquireNextImageKHR(vk_device, vk_swapchain,
715 UINT64_MAX, psema, VK_NULL_HANDLE, &curr_img);
716 if(res == VK_ERROR_OUT_OF_DATE_KHR) {
717 fprintf(stderr, "Swapchain out of date.\n");
720 assert(res == VK_SUCCESS);
723 memset(&sinf, 0, sizeof sinf);
724 VkPipelineStageFlags psflags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
725 sinf.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
726 sinf.waitSemaphoreCount = 1;
727 sinf.pWaitSemaphores = &psema;
728 sinf.pWaitDstStageMask = &psflags;
729 sinf.commandBufferCount = 1;
730 sinf.pCommandBuffers = &rbufs[curr_img];
732 res = vkQueueSubmit(vk_queue, 1, &sinf, VK_NULL_HANDLE);
733 assert(res == VK_SUCCESS);
735 VkPresentInfoKHR pinf;
736 memset(&pinf, 0, sizeof pinf);
737 pinf.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
738 pinf.swapchainCount = 1;
739 pinf.pSwapchains = &vk_swapchain;
740 pinf.pImageIndices = &curr_img;
742 res = vkQueuePresentKHR(vk_queue, &pinf);
743 if(res == VK_ERROR_OUT_OF_DATE_KHR) {
744 fprintf(stderr, "Swapchain out of date.\n");
746 assert(res == VK_SUCCESS);
748 res = vkQueueWaitIdle(vk_queue);
749 assert(res == VK_SUCCESS);
751 vkDestroySemaphore(vk_device, psema, 0);