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 begin_init_command_buffer(VkCommandBuffer *cb);
60 static bool create_zbuffer();
61 static bool create_renderpass();
62 static bool create_framebuffers(VkFramebuffer *fb, VkImageView *views);
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(fbs, iviews)) {
128 fprintf(stderr, "Failed to create the framebuffer.\n");
132 if(!end_init_command_buffer(&init_buf)) {
133 fprintf(stderr, "Failed to end the command buffer.\n");
137 /* rendering command buffers */
138 if(!allocate_rendering_command_buffers(rbufs)) {
139 fprintf(stderr, "Failed to allocate rendering command buffers.\n");
143 if(!begin_rendering_command_buffers(rbufs, 2)) {
144 fprintf(stderr, "Failed to begin rendering command buffers.\n");
149 gfx_viewport = viewport;
150 gfx_zbuffer = zbuffer;
151 gfx_cull_face = cull_face;
152 gfx_reshape = reshape;
153 gfx_swapbuffers = swapbuffers;
154 gfx_begin_drawing = begin_drawing;
155 gfx_end_drawing = end_drawing;
160 static bool create_swapchain(VkSwapchainKHR *sc)
162 /* surface capabilities */
163 VkSurfaceCapabilitiesKHR scap;
164 if(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(vk_physical, vk_surface, &scap) != VK_SUCCESS) {
165 fprintf(stderr, "Failed to get physical device surface capabilities\n");
169 /* presentation modes */
171 if(vkGetPhysicalDeviceSurfacePresentModesKHR(vk_physical, vk_surface, &prmode_cnt, 0) != VK_SUCCESS) {
172 fprintf(stderr, "Failed to get physical device surface presentation modes count.\n");
176 if(prmode_cnt == 0) {
177 fprintf(stderr, "Presentation modes not found.\n");
181 VkPresentModeKHR scmode = VK_PRESENT_MODE_FIFO_KHR;
182 VkPresentModeKHR *modes = new VkPresentModeKHR[prmode_cnt];
184 if(vkGetPhysicalDeviceSurfacePresentModesKHR(vk_physical, vk_surface, &prmode_cnt, modes) != VK_SUCCESS) {
185 fprintf(stderr, "Failed to get physical device presentation modes.\n");
189 for(uint32_t i=0; i<prmode_cnt; i++) {
190 if(modes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
191 scmode = VK_PRESENT_MODE_MAILBOX_KHR;
194 if((scmode != VK_PRESENT_MODE_MAILBOX_KHR) && (modes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR)) {
196 scmode = VK_PRESENT_MODE_IMMEDIATE_KHR;
200 /* swapchain extents */
202 if(scap.currentExtent.width == 0xffffffff || scap.currentExtent.height == 0xffffffff) {
203 scextent.width = win_w;
204 scextent.height = win_h;
207 scextent = scap.currentExtent;
208 win_w = scextent.width;
209 win_h = scextent.height;
212 /* number of swapchain images (on intel that's 3: maybe should hardcode it to 2?) */
213 num_images = scap.minImageCount; //+ 1;
214 /* intel doesn't set the maxImageCount */
215 if(scap.maxImageCount > 0 && num_images > scap.maxImageCount)
216 num_images = scap.maxImageCount;
218 printf("num_images : %u\n", num_images);
219 assert(num_images > 0);
221 images = new VkImage[num_images];
222 iviews = new VkImageView[num_images];
224 /* transform flags */
225 VkSurfaceTransformFlagBitsKHR pre_transf = scap.currentTransform;
226 if(scap.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR)
227 pre_transf = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
229 /* find suitable colorspace, format */
231 VkColorSpaceKHR colorspace;
233 VkSurfaceFormatKHR sformat;
234 if(!vku_get_surface_format(vk_physical, vk_surface, &sformat)) {
238 format = sformat.format;
239 colorspace = sformat.colorSpace;
241 /* creating the swapchain */
242 VkSwapchainCreateInfoKHR sinfo;
243 memset(&sinfo, 0, sizeof sinfo);
245 sinfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
246 sinfo.surface = vk_surface;
247 sinfo.minImageCount = num_images;
248 sinfo.imageFormat = format;
249 sinfo.imageColorSpace = colorspace;
250 sinfo.imageExtent = scextent;
251 sinfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
252 sinfo.preTransform = pre_transf;
253 sinfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
254 sinfo.imageArrayLayers = 1;
255 sinfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
256 sinfo.presentMode = scmode;
257 sinfo.oldSwapchain = VK_NULL_HANDLE; //TODO
258 sinfo.clipped = VK_TRUE; //TODO
260 if(vkCreateSwapchainKHR(vk_device, &sinfo, 0, sc) != VK_SUCCESS) {
261 fprintf(stderr, "Failed to create swapchain.\n");
265 if(vkGetSwapchainImagesKHR(vk_device, *sc, &num_images, 0) != VK_SUCCESS) {
266 fprintf(stderr, "Failed to get the number of the swapchain images.\n");
270 if(vkGetSwapchainImagesKHR(vk_device, *sc, &num_images, images) != VK_SUCCESS) {
271 fprintf(stderr, "Failed to get the swapchain images.\n");
275 VkImageViewCreateInfo ivinf;
276 memset(&ivinf, 0, sizeof ivinf);
277 ivinf.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
278 ivinf.format = format;
280 VK_COMPONENT_SWIZZLE_R,
281 VK_COMPONENT_SWIZZLE_G,
282 VK_COMPONENT_SWIZZLE_B,
283 VK_COMPONENT_SWIZZLE_A
285 ivinf.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
286 ivinf.subresourceRange.levelCount = 1;
287 ivinf.subresourceRange.layerCount = 1;
288 ivinf.viewType = VK_IMAGE_VIEW_TYPE_2D;
290 for(uint32_t i=0; i<num_images; i++) {
291 ivinf.image = images[i];
294 if((res = vkCreateImageView(vk_device, &ivinf, 0, &iviews[i])) != VK_SUCCESS) {
295 fprintf(stderr, "Failed to create image view %d: %s.\n", i, vku_get_vulkan_error_str(res));
303 static bool begin_init_command_buffer(VkCommandBuffer *cb)
305 if(*cb == VK_NULL_HANDLE) {
306 *cb = vku_alloc_cmdbuf(vk_pool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
308 VkCommandBufferInheritanceInfo ciinf;
309 memset(&ciinf, 0, sizeof ciinf);
310 ciinf.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
311 ciinf.renderPass = VK_NULL_HANDLE;
312 ciinf.framebuffer = VK_NULL_HANDLE;
313 ciinf.occlusionQueryEnable = VK_FALSE;
315 VkCommandBufferBeginInfo cbinf;
316 memset(&cbinf, 0, sizeof cbinf);
317 cbinf.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
318 cbinf.pInheritanceInfo = &ciinf;
320 if(vkBeginCommandBuffer(*cb, &cbinf) != VK_SUCCESS) {
321 fprintf(stderr, "Failed to begin command buffer.\n");
328 static bool create_zbuffer()
330 VkImageCreateInfo dinfo;
331 memset(&dinfo, 0, sizeof dinfo);
333 dinfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
334 dinfo.imageType = VK_IMAGE_TYPE_2D;
335 dinfo.format = dformat;
336 dinfo.extent = {(uint32_t)win_w, (uint32_t)win_h, 1};
338 dinfo.arrayLayers = 1;
339 dinfo.samples = VK_SAMPLE_COUNT_1_BIT;
340 dinfo.tiling = VK_IMAGE_TILING_OPTIMAL;
341 dinfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
343 if(vkCreateImage(vk_device, &dinfo, 0, &dimg) != VK_SUCCESS) {
344 fprintf(stderr, "Failed to create depth buffer image.\n");
348 VkMemoryRequirements dmem_reqs;
349 vkGetImageMemoryRequirements(vk_device, dimg, &dmem_reqs);
351 gpu_mem = vk_allocate(dmem_reqs.size);
356 vkBindImageMemory(vk_device, dimg, gpu_mem, 0);
358 if(!vk_image_set_layout(init_buf, dimg, VK_IMAGE_ASPECT_DEPTH_BIT,
359 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
360 (VkAccessFlagBits)0)) {
361 fprintf(stderr, "Failed to set depth buffer layout.\n");
365 VkImageViewCreateInfo div_inf;
366 memset(&div_inf, 0, sizeof div_inf);
368 div_inf.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
369 div_inf.image = dimg;
370 div_inf.format = dformat;
371 div_inf.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
372 div_inf.subresourceRange.levelCount = 1;
373 div_inf.subresourceRange.layerCount = 1;
374 div_inf.viewType = VK_IMAGE_VIEW_TYPE_2D;
376 if(vkCreateImageView(vk_device, &div_inf, 0, &dview) != VK_SUCCESS) {
377 fprintf(stderr, "Failed to create image view for depth buffer.\n");
384 static bool create_renderpass()
386 VkSurfaceFormatKHR sformat;
387 if(!vku_get_surface_format(vk_physical, vk_surface, &sformat)) {
388 fprintf(stderr, "Failed to get surface format.\n");
392 VkAttachmentDescription att[2];
393 memset(&att, 0, (sizeof att[0]) * 2);
395 att[0].format = sformat.format;
396 att[0].samples = VK_SAMPLE_COUNT_1_BIT;
397 att[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
398 att[0].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
399 att[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
400 att[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
401 att[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
402 att[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
404 att[1].format = dformat;
405 att[1].samples = VK_SAMPLE_COUNT_1_BIT;
406 att[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
407 att[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
408 att[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
409 att[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
410 att[1].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
411 att[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
413 VkAttachmentReference cref;
414 memset(&cref, 0, sizeof cref);
415 cref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
417 VkAttachmentReference dref;
418 memset(&dref, 0, sizeof dref);
420 dref.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
422 VkSubpassDescription sd;
423 memset(&sd, 0, sizeof sd);
424 sd.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
425 sd.colorAttachmentCount = 1;
426 sd.pColorAttachments = &cref;
427 sd.pDepthStencilAttachment = &dref;
429 VkRenderPassCreateInfo rinf;
430 memset(&rinf, 0, sizeof rinf);
431 rinf.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
432 rinf.attachmentCount = 2;
433 rinf.pAttachments = att;
434 rinf.subpassCount = 1;
435 rinf.pSubpasses = &sd;
437 if(vkCreateRenderPass(vk_device, &rinf, 0, &rpass) != VK_SUCCESS) {
438 fprintf(stderr, "Failed to create rpass.\n");
445 static bool create_framebuffers(VkFramebuffer *fb, VkImageView *views)
447 /* framebuffer attachments */
448 VkImageView fb_att[2];
451 VkFramebufferCreateInfo fbinf;
452 memset(&fbinf, 0, sizeof fbinf);
453 fbinf.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
454 fbinf.renderPass = rpass;
455 fbinf.attachmentCount = 2;
456 fbinf.pAttachments = fb_att;
458 fbinf.height = win_h;
461 for(int i=0; i<2; i++) {
462 fb_att[0] = views[i];
463 if(vkCreateFramebuffer(vk_device, &fbinf, 0, &fb[i]) != VK_SUCCESS) {
464 fprintf(stderr, "Failed to create framebuffer %i\n", i);
471 static bool end_init_command_buffer(VkCommandBuffer *cb)
473 if(vkEndCommandBuffer(*cb) != VK_SUCCESS) {
474 fprintf(stderr, "Failed to end command buffer.\n");
479 memset(&si, 0, sizeof si);
480 si.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
481 si.commandBufferCount = 1;
482 si.pCommandBuffers = cb;
484 if(vkQueueSubmit(vk_queue, 1, &si, VK_NULL_HANDLE) != VK_SUCCESS) {
485 fprintf(stderr, "Failed to submit null queue.\n");
489 if(vkQueueWaitIdle(vk_queue) != VK_SUCCESS) {
490 fprintf(stderr, "QueueWaitIdle failure!\n");
494 vkFreeCommandBuffers(vk_device, vk_pool, 1, cb);
495 *cb = VK_NULL_HANDLE;
500 static bool allocate_rendering_command_buffers(VkCommandBuffer *bufs)
502 return vku_alloc_cmdbufs(vk_pool, VK_COMMAND_BUFFER_LEVEL_PRIMARY,
506 static void free_rendering_command_buffers(VkCommandBuffer *bufs, int count)
508 for(int i=0; i<count; i++) {
509 vku_free_cmdbuf(vk_pool, bufs[i]);
513 static bool begin_rendering_command_buffers(VkCommandBuffer *bufs, int count)
515 VkCommandBufferInheritanceInfo iinf;
516 memset(&iinf, 0, sizeof iinf);
517 iinf.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
518 iinf.renderPass = VK_NULL_HANDLE;
519 iinf.framebuffer = VK_NULL_HANDLE;
521 VkCommandBufferBeginInfo binf;
522 memset(&binf, 0, sizeof binf);
523 binf.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
524 binf.pInheritanceInfo = &iinf;
526 // setting clear values
527 VkClearValue clvals[2];
528 for(int i=0; i<4; i++) {
529 clvals[0].color.float32[i] = clear_color[i];
531 clvals[1].depthStencil = {1.0f, 0};
533 //build drawing command buffers
534 for(int i=0; i<count; i++) {
535 if(vkBeginCommandBuffer(bufs[i], &binf) != VK_SUCCESS) {
536 fprintf(stderr, "Failed to begin command buffer: %d\n", i);
540 VkImageMemoryBarrier imbarr;
541 memset(&imbarr, 0, sizeof imbarr);
542 imbarr.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
543 imbarr.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
544 imbarr.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
545 imbarr.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
546 imbarr.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
547 imbarr.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
548 imbarr.image = images[i];
549 imbarr.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
550 vkCmdPipelineBarrier(bufs[i], VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, 0, 0, 0, 1, &imbarr);
552 VkRenderPassBeginInfo rbinf;
553 memset(&rbinf, 0, sizeof rbinf);
554 rbinf.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
555 rbinf.renderPass = rpass;
556 rbinf.framebuffer = fbs[i];
557 rbinf.renderArea.extent.width = win_w;
558 rbinf.renderArea.extent.height = win_h;
559 rbinf.clearValueCount = count;
560 rbinf.pClearValues = clvals;
562 vkCmdBeginRenderPass(bufs[i], &rbinf, VK_SUBPASS_CONTENTS_INLINE);
564 memset(&viewport, 0, sizeof viewport);
565 viewport.width = (float)win_w;
566 viewport.height = (float)win_h;
567 viewport.maxDepth = 1.0f;
568 vkCmdSetViewport(bufs[i], 0, 1, &viewport);
571 memset(&scissor, 0, sizeof scissor);
572 scissor.extent.width = win_w;
573 scissor.extent.height = win_h;
574 vkCmdSetScissor(bufs[i], 0, 1, &scissor);
575 vkCmdEndRenderPass(bufs[i]);
577 /* pre-present barrier */
578 VkImageMemoryBarrier ppb;
579 memset(&ppb, 0, sizeof ppb);
580 ppb.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
581 ppb.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
582 ppb.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
583 ppb.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
584 ppb.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
585 ppb.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
586 ppb.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
587 ppb.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
588 ppb.image = images[i];
590 vkCmdPipelineBarrier(bufs[i], VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, 0, 0, 0, 1, &ppb);
592 if(vkEndCommandBuffer(bufs[i]) != VK_SUCCESS) {
593 fprintf(stderr, "Failed to end command buffer: %d\n", i);
600 void cleanup_vulkan()
603 free_rendering_command_buffers(rbufs, 2);
605 glfwDestroyWindow(win);
609 //TODOs according to the book:
610 // 1- make sure all threads have been terminated (when I add threads)
614 static void error_callback(int error, const char *description)
616 fprintf(stderr, "GLFW error %d: %s.\n", error, description);
619 static void reshape(int width, int height)
621 // VkSwapchainKHR sc;
622 // if(!(sc = vku_create_swapchain(vk_surface, width, height, 2, VK_PRESENT_MODE_FIFO_KHR,
624 // fprintf(stderr, "Failed to create %dx%d double-buffered swapchain\n", width, height);
627 // vk_swapchain = sc;
629 // delete [] vkswapchain_images;
630 // vkswapchain_images = vku_get_swapchain_images(sc, 0);
631 // vk_curr_swapchain_image = vku_get_next_image(vk_swapchain);
634 static void clear(float r, float g, float b)
638 static void viewport(int x, int y, int width, int height)
642 static void zbuffer(bool enable)
646 static void cull_face(Gfx_cull_face cf)
650 static void swapbuffers()
654 static void begin_drawing()
656 VkSemaphoreCreateInfo psinf;
657 memset(&psinf, 0, sizeof psinf);
658 psinf.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
661 if((res = vkCreateSemaphore(vk_device, &psinf, 0, &psema)) != VK_SUCCESS) {
662 fprintf(stderr, "Failed to create semaphore.\n");
664 assert(res == VK_SUCCESS);
667 static void end_drawing()
669 VkResult res = vkAcquireNextImageKHR(vk_device, vk_swapchain,
670 UINT64_MAX, psema, VK_NULL_HANDLE, &curr_img);
671 if(res == VK_ERROR_OUT_OF_DATE_KHR) {
672 fprintf(stderr, "Swapchain out of date.\n");
675 assert(res == VK_SUCCESS);
678 memset(&sinf, 0, sizeof sinf);
679 VkPipelineStageFlags psflags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
680 sinf.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
681 sinf.waitSemaphoreCount = 1;
682 sinf.pWaitSemaphores = &psema;
683 sinf.pWaitDstStageMask = &psflags;
684 sinf.commandBufferCount = 1;
685 sinf.pCommandBuffers = &rbufs[curr_img];
687 res = vkQueueSubmit(vk_queue, 1, &sinf, VK_NULL_HANDLE);
688 assert(res == VK_SUCCESS);
690 VkPresentInfoKHR pinf;
691 memset(&pinf, 0, sizeof pinf);
692 pinf.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
693 pinf.swapchainCount = 1;
694 pinf.pSwapchains = &vk_swapchain;
695 pinf.pImageIndices = &curr_img;
697 res = vkQueuePresentKHR(vk_queue, &pinf);
698 if(res == VK_ERROR_OUT_OF_DATE_KHR) {
699 fprintf(stderr, "Swapchain out of date.\n");
701 assert(res == VK_SUCCESS);
703 res = vkQueueWaitIdle(vk_queue);
704 assert(res == VK_SUCCESS);
706 vkDestroySemaphore(vk_device, psema, 0);