vulkan_test_simple

view src/main.c @ 0:8de4fe926882

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 28 Jun 2018 13:57:28 +0300
parents
children
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <stdint.h>
5 #include <errno.h>
6 #include <alloca.h>
7 #include <GLFW/glfw3.h>
9 void keyb(GLFWwindow *win, int key, int sc, int act, int mods);
10 int init(void);
11 void destroy(void);
12 void draw(void);
14 GLFWwindow *win;
15 int win_width = 800;
16 int win_height = 600;
17 int redraw_pending;
19 int main(void)
20 {
21 if(!glfwInit()) {
22 fprintf(stderr, "glfw init failed\n");
23 return 1;
24 }
26 glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
27 win = glfwCreateWindow(win_width, win_height, "test", 0, 0);
28 glfwSetKeyCallback(win, keyb);
30 if(init() == -1) {
31 glfwDestroyWindow(win);
32 glfwTerminate();
33 return 1;
34 }
36 redraw_pending = 1;
38 while(!glfwWindowShouldClose(win)) {
39 glfwWaitEvents();
41 if(redraw_pending) {
42 redraw_pending = 0;
43 draw();
44 }
45 }
47 destroy();
48 glfwDestroyWindow(win);
49 glfwTerminate();
50 return 0;
51 }
53 void keyb(GLFWwindow *win, int key, int sc, int act, int mods)
54 {
55 if(act == GLFW_PRESS) {
56 switch(key) {
57 case GLFW_KEY_ESCAPE:
58 glfwSetWindowShouldClose(win, 1);
59 break;
60 }
61 }
62 }
64 /* -------------------------------------------------------------- */
65 int create_instance(void);
66 int create_surface(void);
67 int choose_phys_dev(void);
68 int create_device(void);
69 int create_swapchain(void);
70 int create_imgviews(void);
71 int create_rendpass(void);
72 int create_pipeline(void);
73 int create_framebuf(void);
74 int create_cmdpool(void);
75 int create_cmdbuf(void);
76 int create_semaphores(void);
77 VkShaderModule load_shader(const char *fname);
79 VkInstance vk;
80 VkPhysicalDevice vkpdev;
81 int vkqfam_idx = -1;
82 VkDevice vkdev;
83 VkQueue vkq;
84 VkSurfaceKHR vksurf;
85 VkSurfaceCapabilitiesKHR vksurf_caps;
86 int vksurf_numfmt, vksurf_selfmt;
87 VkSurfaceFormatKHR *vksurf_fmt;
88 VkSwapchainKHR vksc;
89 int vksc_numimg;
90 VkImage *vksc_img;
91 VkExtent2D vksc_extent;
92 VkImageView *vksc_view;
93 VkRenderPass vkrpass;
94 VkPipelineLayout vkpipe_layout;
95 VkPipeline vkpipe;
96 VkFramebuffer *vksc_fb;
97 VkCommandPool vkcmdpool;
98 VkCommandBuffer *vksc_cmdbuf;
99 VkSemaphore sem_gotimg, sem_drawdone;
101 int init(void)
102 {
103 if(create_instance() == -1) return -1;
104 if(create_surface() == -1) return -1;
105 if(choose_phys_dev() == -1) return -1;
106 if(create_device() == -1) return -1;
107 if(create_swapchain() == -1) return -1;
108 if(create_imgviews() == -1) return -1;
109 if(create_rendpass() == -1) return -1;
110 if(create_pipeline() == -1) return -1;
111 if(create_framebuf() == -1) return -1;
112 if(create_cmdpool() == -1) return -1;
113 if(create_cmdbuf() == -1) return -1;
114 if(create_semaphores() == -1) return -1;
115 return 0;
116 }
118 void destroy(void)
119 {
120 int i;
122 if(sem_gotimg) vkDestroySemaphore(vkdev, sem_gotimg, 0);
123 if(sem_drawdone) vkDestroySemaphore(vkdev, sem_drawdone, 0);
124 if(vkcmdpool) vkDestroyCommandPool(vkdev, vkcmdpool, 0);
125 if(vksc_fb) {
126 for(i=0; i<vksc_numimg; i++) {
127 vkDestroyFramebuffer(vkdev, vksc_fb[i], 0);
128 }
129 }
130 if(vkpipe) vkDestroyPipeline(vkdev, vkpipe, 0);
131 if(vkpipe_layout) vkDestroyPipelineLayout(vkdev, vkpipe_layout, 0);
132 if(vkrpass) vkDestroyRenderPass(vkdev, vkrpass, 0);
133 if(vksc_view) {
134 for(i=0; i<vksc_numimg; i++) {
135 vkDestroyImageView(vkdev, vksc_view[i], 0);
136 }
137 }
138 if(vksc) vkDestroySwapchainKHR(vkdev, vksc, 0);
139 if(vkdev) vkDestroyDevice(vkdev, 0);
140 if(vksurf) vkDestroySurfaceKHR(vk, vksurf, 0);
141 if(vk) vkDestroyInstance(vk, 0);
142 }
144 void draw(void)
145 {
146 uint32_t img_idx;
147 VkSubmitInfo submit;
148 VkPipelineStageFlags wait_stages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
149 VkPresentInfoKHR pres;
151 vkAcquireNextImageKHR(vkdev, vksc, UINT64_MAX, sem_gotimg, 0, &img_idx);
153 memset(&submit, 0, sizeof submit);
154 submit.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
155 submit.waitSemaphoreCount = 1;
156 submit.pWaitSemaphores = &sem_gotimg;
157 submit.pWaitDstStageMask = &wait_stages;
158 submit.commandBufferCount = 1;
159 submit.pCommandBuffers = vksc_cmdbuf + img_idx;
160 submit.signalSemaphoreCount = 1;
161 submit.pSignalSemaphores = &sem_drawdone;
163 if(vkQueueSubmit(vkq, 1, &submit, 0) != 0) {
164 fprintf(stderr, "failed to submit draw commands\n");
165 abort();
166 }
168 memset(&pres, 0, sizeof pres);
169 pres.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
170 pres.waitSemaphoreCount = 1;
171 pres.pWaitSemaphores = &sem_drawdone;
172 pres.swapchainCount = 1;
173 pres.pSwapchains = &vksc;
174 pres.pImageIndices = &img_idx;
176 vkQueuePresentKHR(vkq, &pres);
177 }
179 int create_instance(void)
180 {
181 VkApplicationInfo appinf;
182 VkInstanceCreateInfo iinf;
183 uint32_t num_ext;
184 const char **ext;
186 ext = glfwGetRequiredInstanceExtensions(&num_ext);
188 memset(&appinf, 0, sizeof appinf);
189 appinf.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
190 appinf.pApplicationName = "test";
191 appinf.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
192 appinf.pEngineName = "fuckoff";
193 appinf.engineVersion = VK_MAKE_VERSION(1, 0, 0);
194 appinf.apiVersion = VK_API_VERSION_1_0;
196 memset(&iinf, 0, sizeof iinf);
197 iinf.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
198 iinf.pApplicationInfo = &appinf;
199 iinf.enabledExtensionCount = num_ext;
200 iinf.ppEnabledExtensionNames = ext;
202 if(vkCreateInstance(&iinf, 0, &vk) != 0) {
203 fprintf(stderr, "failed to create instance\n");
204 return -1;
205 }
206 return 0;
207 }
209 int create_surface(void)
210 {
211 if(glfwCreateWindowSurface(vk, win, 0, &vksurf) != 0) {
212 fprintf(stderr, "failed to create window surface\n");
213 return -1;
214 }
215 return 0;
216 }
218 static int is_pdev_skookum(VkPhysicalDevice dev)
219 {
220 uint32_t i, num_fmt, num_qfam, num_ext;
221 VkQueueFamilyProperties *qfam;
222 VkExtensionProperties *ext;
223 VkPhysicalDeviceProperties prop;
224 VkPhysicalDeviceFeatures feat;
225 VkBool32 can_pres;
226 int have_swap_ext;
228 vkGetPhysicalDeviceProperties(dev, &prop);
229 vkGetPhysicalDeviceFeatures(dev, &feat);
231 /* check if we have the swapchain extension */
232 vkEnumerateDeviceExtensionProperties(dev, 0, &num_ext, 0);
233 ext = alloca(num_ext * sizeof *ext);
234 vkEnumerateDeviceExtensionProperties(dev, 0, &num_ext, ext);
236 have_swap_ext = 0;
237 for(i=0; i<num_ext; i++) {
238 if(strcmp(ext[i].extensionName, "VK_KHR_swapchain") == 0) {
239 have_swap_ext = 1;
240 break;
241 }
242 }
243 if(!have_swap_ext) {
244 return 0;
245 }
247 /* populate format and present modes arrays, and make sure we have some of each */
248 vkGetPhysicalDeviceSurfaceFormatsKHR(dev, vksurf, &num_fmt, 0);
249 if(!num_fmt || !(vksurf_fmt = malloc(num_fmt * sizeof *vksurf_fmt))) {
250 return 0;
251 }
252 vksurf_numfmt = num_fmt;
253 vkGetPhysicalDeviceSurfaceFormatsKHR(dev, vksurf, &num_fmt, vksurf_fmt);
255 vkGetPhysicalDeviceSurfaceCapabilitiesKHR(dev, vksurf, &vksurf_caps);
257 /* find a queue family which can do graphics and can present */
258 vkGetPhysicalDeviceQueueFamilyProperties(dev, &num_qfam, 0);
259 qfam = alloca(num_qfam * sizeof *qfam);
260 vkGetPhysicalDeviceQueueFamilyProperties(dev, &num_qfam, qfam);
262 vkqfam_idx = -1;
263 for(i=0; i<num_qfam; i++) {
264 vkGetPhysicalDeviceSurfaceSupportKHR(dev, i, vksurf, &can_pres);
265 if(qfam[i].queueCount && (qfam[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) && can_pres) {
266 vkqfam_idx = i;
267 return 1;
268 }
269 }
271 free(vksurf_fmt);
272 vksurf_fmt = 0;
273 vksurf_numfmt = 0;
274 return 0;
275 }
277 static int choose_pixfmt(void)
278 {
279 int i, j;
280 static const VkFormat pref[] = {
281 VK_FORMAT_B8G8R8_UNORM,
282 VK_FORMAT_R8G8B8_UNORM,
283 VK_FORMAT_B8G8R8A8_UNORM,
284 VK_FORMAT_R8G8B8A8_UNORM
285 };
287 vksurf_selfmt = 0;
288 for(i=0; i<vksurf_numfmt; i++) {
289 if(vksurf_fmt[i].colorSpace != VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
290 continue;
291 }
292 for(j=0; j<sizeof pref / sizeof *pref; j++) {
293 if(vksurf_fmt[i].format == pref[j]) {
294 vksurf_selfmt = i;
295 return i;
296 }
297 }
298 }
299 return -1;
300 }
302 int choose_phys_dev(void)
303 {
304 uint32_t i, num_pdev;
305 VkPhysicalDevice *pdev;
307 vkEnumeratePhysicalDevices(vk, &num_pdev, 0);
308 if(!num_pdev) {
309 fprintf(stderr, "no vulkan devices found\n");
310 return -1;
311 }
312 pdev = alloca(num_pdev * sizeof *pdev);
313 vkEnumeratePhysicalDevices(vk, &num_pdev, pdev);
315 for(i=0; i<num_pdev; i++) {
316 if(is_pdev_skookum(pdev[i])) {
317 vkpdev = pdev[i];
318 break;
319 }
320 }
321 if(!vkpdev) {
322 fprintf(stderr, "no skookum device found, vulkan can't chooch\n");
323 return -1;
324 }
326 choose_pixfmt();
327 return 0;
328 }
330 int create_device(void)
331 {
332 static const float prio = 1.0f;
333 VkDeviceQueueCreateInfo qinf;
334 VkPhysicalDeviceFeatures feat;
335 VkDeviceCreateInfo devinf;
337 static const char *extensions[] = {
338 "VK_KHR_swapchain"
339 };
341 memset(&feat, 0, sizeof feat);
343 memset(&qinf, 0, sizeof qinf);
344 qinf.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
345 qinf.queueFamilyIndex = vkqfam_idx;
346 qinf.queueCount = 1;
347 qinf.pQueuePriorities = &prio;
349 memset(&devinf, 0, sizeof devinf);
350 devinf.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
351 devinf.pQueueCreateInfos = &qinf;
352 devinf.queueCreateInfoCount = 1;
353 devinf.pEnabledFeatures = &feat;
354 devinf.enabledExtensionCount = sizeof extensions / sizeof *extensions;
355 devinf.ppEnabledExtensionNames = extensions;
357 if(vkCreateDevice(vkpdev, &devinf, 0, &vkdev) != 0) {
358 fprintf(stderr, "failed to create vulkan device\n");
359 return -1;
360 }
362 vkGetDeviceQueue(vkdev, vkqfam_idx, 0, &vkq);
363 return 0;
364 }
366 int create_swapchain(void)
367 {
368 uint32_t num;
369 VkSwapchainCreateInfoKHR scinf;
371 vksc_extent.width = win_width;
372 vksc_extent.height = win_height;
374 memset(&scinf, 0, sizeof scinf);
375 scinf.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
376 scinf.surface = vksurf;
377 scinf.minImageCount = 2;
378 scinf.imageFormat = vksurf_fmt[vksurf_selfmt].format;
379 scinf.imageColorSpace = vksurf_fmt[vksurf_selfmt].colorSpace;
380 scinf.imageExtent = vksc_extent;
381 scinf.imageArrayLayers = 1;
382 scinf.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
383 scinf.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
384 scinf.preTransform = vksurf_caps.currentTransform;
385 scinf.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
386 scinf.presentMode = VK_PRESENT_MODE_FIFO_KHR;
387 scinf.clipped = VK_TRUE;
389 if(vkCreateSwapchainKHR(vkdev, &scinf, 0, &vksc) != 0) {
390 fprintf(stderr, "failed to create swapchain\n");
391 return -1;
392 }
394 vkGetSwapchainImagesKHR(vkdev, vksc, &num, 0);
395 if(!num || !(vksc_img = malloc(num * sizeof *vksc_img))) {
396 fprintf(stderr, "failed to allocate swapchain image array (%d images)\n", vksc_numimg);
397 return -1;
398 }
399 vkGetSwapchainImagesKHR(vkdev, vksc, &num, vksc_img);
400 vksc_numimg = num;
402 return 0;
403 }
405 int create_imgviews(void)
406 {
407 int i;
408 VkImageViewCreateInfo ivinf;
410 if(!(vksc_view = malloc(vksc_numimg * sizeof *vksc_view))) {
411 fprintf(stderr, "failed to allocate image view array (%d images)\n", vksc_numimg);
412 return -1;
413 }
415 for(i=0; i<vksc_numimg; i++) {
416 memset(&ivinf, 0, sizeof ivinf);
417 ivinf.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
418 ivinf.image = vksc_img[i];
419 ivinf.format = vksurf_fmt[vksurf_selfmt].format;
420 ivinf.components.r = ivinf.components.g = ivinf.components.b =
421 ivinf.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
422 ivinf.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
423 ivinf.subresourceRange.levelCount = 1;
424 ivinf.subresourceRange.layerCount = 1;
426 if(vkCreateImageView(vkdev, &ivinf, 0, vksc_view + i) != 0) {
427 fprintf(stderr, "failed to create image view for image %d\n", i);
428 return -1;
429 }
430 }
431 return 0;
432 }
434 int create_rendpass(void)
435 {
436 VkAttachmentDescription cat;
437 VkAttachmentReference catref;
438 VkSubpassDescription subpass;
439 VkRenderPassCreateInfo pinf;
440 VkSubpassDependency dep;
442 memset(&cat, 0, sizeof cat);
443 cat.format = vksurf_fmt[vksurf_selfmt].format;
444 cat.samples = VK_SAMPLE_COUNT_1_BIT;
445 cat.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
446 cat.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
447 cat.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
448 cat.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
449 cat.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
450 cat.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
452 memset(&catref, 0, sizeof catref);
453 catref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
455 memset(&subpass, 0, sizeof subpass);
456 subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
457 subpass.colorAttachmentCount = 1;
458 subpass.pColorAttachments = &catref;
460 memset(&dep, 0, sizeof dep);
461 dep.srcSubpass = VK_SUBPASS_EXTERNAL;
462 dep.dstSubpass = 0;
463 dep.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
464 dep.srcAccessMask = 0;
465 dep.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
466 dep.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
468 memset(&pinf, 0, sizeof pinf);
469 pinf.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
470 pinf.attachmentCount = 1;
471 pinf.pAttachments = &cat;
472 pinf.subpassCount = 1;
473 pinf.pSubpasses = &subpass;
474 pinf.dependencyCount = 1;
475 pinf.pDependencies = &dep;
477 if(vkCreateRenderPass(vkdev, &pinf, 0, &vkrpass) != 0) {
478 fprintf(stderr, "failed to create render pass\n");
479 return -1;
480 }
481 return 0;
482 }
484 int create_pipeline(void)
485 {
486 int i;
487 VkShaderModule sdr[2];
488 VkPipelineShaderStageCreateInfo ssinf[2];
489 VkPipelineVertexInputStateCreateInfo vinp;
490 VkPipelineInputAssemblyStateCreateInfo vasm;
491 VkViewport vport;
492 VkRect2D scissor;
493 VkPipelineViewportStateCreateInfo vp;
494 VkPipelineRasterizationStateCreateInfo rast;
495 VkPipelineMultisampleStateCreateInfo msaa;
496 VkPipelineColorBlendAttachmentState bat;
497 VkPipelineColorBlendStateCreateInfo blend;
498 VkPipelineLayoutCreateInfo lay;
499 VkGraphicsPipelineCreateInfo pinf;
501 if(!(sdr[0] = load_shader("vertex.glsl")) || !(sdr[1] = load_shader("pixel.glsl"))) {
502 return -1;
503 }
504 memset(ssinf, 0, sizeof ssinf);
505 for(i=0; i<2; i++) {
506 ssinf[i].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
507 ssinf[i].stage = i == 0 ? VK_SHADER_STAGE_VERTEX_BIT : VK_SHADER_STAGE_FRAGMENT_BIT;
508 ssinf[i].module = sdr[i];
509 ssinf[i].pName = "main";
510 }
512 memset(&vinp, 0, sizeof vinp);
513 vinp.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
515 memset(&vasm, 0, sizeof vasm);
516 vasm.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
517 vasm.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
519 vport.x = vport.y = 0;
520 vport.width = vksc_extent.width;
521 vport.height = vksc_extent.height;
522 vport.minDepth = 0.0f;
523 vport.maxDepth = 1.0f;
525 scissor.offset.x = scissor.offset.y = 0;
526 scissor.extent = vksc_extent;
528 memset(&vp, 0, sizeof vp);
529 vp.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
530 vp.viewportCount = 1;
531 vp.pViewports = &vport;
532 vp.scissorCount = 1;
533 vp.pScissors = &scissor;
535 memset(&rast, 0, sizeof rast);
536 rast.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
537 rast.polygonMode = VK_POLYGON_MODE_FILL;
538 rast.lineWidth = 1.0f;
539 rast.cullMode = VK_CULL_MODE_BACK_BIT;
540 rast.frontFace = VK_FRONT_FACE_CLOCKWISE;
542 memset(&msaa, 0, sizeof msaa);
543 msaa.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
544 msaa.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
545 msaa.minSampleShading = 1.0f;
547 memset(&bat, 0, sizeof bat);
548 bat.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
549 VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
551 memset(&blend, 0, sizeof blend);
552 blend.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
553 blend.attachmentCount = 1;
554 blend.pAttachments = &bat;
557 memset(&lay, 0, sizeof lay);
558 lay.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
560 if(vkCreatePipelineLayout(vkdev, &lay, 0, &vkpipe_layout) != 0) {
561 fprintf(stderr, "failed to create a pipeline layout\n");
562 return -1;
563 }
565 memset(&pinf, 0, sizeof pinf);
566 pinf.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
567 pinf.stageCount = 2;
568 pinf.pStages = ssinf;
569 pinf.pVertexInputState = &vinp;
570 pinf.pInputAssemblyState = &vasm;
571 pinf.pViewportState = &vp;
572 pinf.pRasterizationState = &rast;
573 pinf.pMultisampleState = &msaa;
574 pinf.pColorBlendState = &blend;
575 pinf.layout = vkpipe_layout;
576 pinf.renderPass = vkrpass;
577 pinf.basePipelineIndex = -1;
579 if(vkCreateGraphicsPipelines(vkdev, 0, 1, &pinf, 0, &vkpipe) != 0) {
580 fprintf(stderr, "failed to create graphics pipeline\n");
581 return -1;
582 }
584 for(i=0; i<2; i++) {
585 vkDestroyShaderModule(vkdev, sdr[i], 0);
586 }
587 return 0;
588 }
590 int create_framebuf(void)
591 {
592 int i;
593 VkFramebufferCreateInfo fbinf;
595 if(!(vksc_fb = malloc(vksc_numimg * sizeof *vksc_fb))) {
596 fprintf(stderr, "failed to allocate array for swap chain framebuffers\n");
597 return -1;
598 }
600 for(i=0; i<vksc_numimg; i++) {
601 memset(&fbinf, 0, sizeof fbinf);
602 fbinf.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
603 fbinf.renderPass = vkrpass;
604 fbinf.attachmentCount = 1;
605 fbinf.pAttachments = vksc_view + i;
606 fbinf.width = vksc_extent.width;
607 fbinf.height = vksc_extent.height;
608 fbinf.layers = 1;
610 if(vkCreateFramebuffer(vkdev, &fbinf, 0, vksc_fb + i) != 0) {
611 fprintf(stderr, "failed to create framebuffer\n");
612 return -1;
613 }
614 }
616 return 0;
617 }
619 int create_cmdpool(void)
620 {
621 VkCommandPoolCreateInfo cpinf;
623 memset(&cpinf, 0, sizeof cpinf);
624 cpinf.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
625 cpinf.queueFamilyIndex = vkqfam_idx;
627 if(vkCreateCommandPool(vkdev, &cpinf, 0, &vkcmdpool) != 0) {
628 fprintf(stderr, "failed to create command pool\n");
629 return -1;
630 }
631 return 0;
632 }
634 int create_cmdbuf(void)
635 {
636 int i;
637 VkCommandBufferAllocateInfo cbinf;
639 if(!(vksc_cmdbuf = malloc(vksc_numimg * sizeof *vksc_cmdbuf))) {
640 fprintf(stderr, "failed to allocate array of command buffers\n");
641 return -1;
642 }
644 memset(&cbinf, 0, sizeof cbinf);
645 cbinf.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
646 cbinf.commandPool = vkcmdpool;
647 cbinf.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
648 cbinf.commandBufferCount = vksc_numimg;
650 if(vkAllocateCommandBuffers(vkdev, &cbinf, vksc_cmdbuf) != 0) {
651 fprintf(stderr, "failed to allocate command buffers\n");
652 return -1;
653 }
655 /* pre-record command buffers, because why the fuck not */
656 for(i=0; i<vksc_numimg; i++) {
657 VkCommandBufferBeginInfo cbegin;
658 VkRenderPassBeginInfo rbegin;
659 VkClearValue clear;
661 memset(&cbegin, 0, sizeof cbegin);
662 cbegin.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
663 cbegin.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
665 if(vkBeginCommandBuffer(vksc_cmdbuf[i], &cbegin) != 0) {
666 fprintf(stderr, "failed to begin command buffer recording\n");
667 return -1;
668 }
670 clear.color.float32[0] = 0.2f;
671 clear.color.float32[1] = 0.2f;
672 clear.color.float32[2] = 0.2f;
673 clear.color.float32[3] = 1.0f;
675 memset(&rbegin, 0, sizeof rbegin);
676 rbegin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
677 rbegin.renderPass = vkrpass;
678 rbegin.framebuffer = vksc_fb[i];
679 rbegin.renderArea.extent = vksc_extent;
680 rbegin.clearValueCount = 1;
681 rbegin.pClearValues = &clear;
683 vkCmdBeginRenderPass(vksc_cmdbuf[i], &rbegin, VK_SUBPASS_CONTENTS_INLINE);
684 vkCmdBindPipeline(vksc_cmdbuf[i], VK_PIPELINE_BIND_POINT_GRAPHICS, vkpipe);
685 vkCmdDraw(vksc_cmdbuf[i], 3, 1, 0, 0);
686 vkCmdEndRenderPass(vksc_cmdbuf[i]);
688 if(vkEndCommandBuffer(vksc_cmdbuf[i]) != 0) {
689 fprintf(stderr, "failed to record command buffer\n");
690 return -1;
691 }
692 }
693 return 0;
694 }
696 int create_semaphores(void)
697 {
698 VkSemaphoreCreateInfo sinf;
700 memset(&sinf, 0, sizeof sinf);
701 sinf.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
703 if(vkCreateSemaphore(vkdev, &sinf, 0, &sem_gotimg) != 0) {
704 fprintf(stderr, "failed to create semaphore\n");
705 return -1;
706 }
707 if(vkCreateSemaphore(vkdev, &sinf, 0, &sem_drawdone) != 0) {
708 fprintf(stderr, "failed to create semaphore\n");
709 return -1;
710 }
711 return 0;
712 }
714 VkShaderModule load_shader(const char *fname)
715 {
716 FILE *fp;
717 long sz;
718 void *buf;
719 VkShaderModuleCreateInfo sinf;
720 VkShaderModule sdr;
722 if(!(fp = fopen(fname, "rb"))) {
723 fprintf(stderr, "failed to open shader: %s: %s\n", fname, strerror(errno));
724 return 0;
725 }
726 fseek(fp, 0, SEEK_END);
727 sz = ftell(fp);
728 fseek(fp, 0, SEEK_SET);
730 buf = alloca(sz);
731 if(fread(buf, 1, sz, fp) < sz) {
732 fprintf(stderr, "unexpected EOF while reading shader: %s\n", fname);
733 fclose(fp);
734 return 0;
735 }
736 fclose(fp);
738 memset(&sinf, 0, sizeof sinf);
739 sinf.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
740 sinf.codeSize = sz;
741 sinf.pCode = buf;
743 if(vkCreateShaderModule(vkdev, &sinf, 0, &sdr) != 0) {
744 fprintf(stderr, "failed to create shader from %s\n", fname);
745 return 0;
746 }
747 return sdr;
748 }