fixed swapchain sync for standard win, needs recreation at resize
[vkrt] / src / vk.c
1 #include <assert.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5
6 #include "vk.h"
7
8 /* static variables */
9
10 static VkViewport viewport;
11 static VkRect2D scissor;
12 static VkPipelineCache pipeline_cache;
13
14 /* when I extend the program to use more than one buffers
15  * I might need to store them in this list and access it
16  * using multiple threads
17  *
18  * man realloc
19  */
20 #if 0
21 static VkCommandBuffer *command_buffers;
22 static uint32_t num_command_buffers;
23 #endif
24
25 /* static functions */
26
27 static VkSampleCountFlagBits
28 get_num_samples(uint32_t num_samples)
29 {
30     switch(num_samples) {
31     case 64:
32         return VK_SAMPLE_COUNT_64_BIT;
33     case 32:
34         return VK_SAMPLE_COUNT_32_BIT;
35     case 16:
36         return VK_SAMPLE_COUNT_16_BIT;
37     case 8:
38         return VK_SAMPLE_COUNT_8_BIT;
39     case 4:
40         return VK_SAMPLE_COUNT_4_BIT;
41     case 2:
42         return VK_SAMPLE_COUNT_2_BIT;
43     case 1:
44         break;
45     default:
46         fprintf(stderr, "Invalid number of samples in VkSampleCountFlagBits. Using one sample.\n");
47         break;
48     }
49     return VK_SAMPLE_COUNT_1_BIT;
50 }
51
52 static VkAccessFlagBits
53 get_access_mask(const VkImageLayout layout)
54 {
55     /* dstAccessMask of barriers must be supported from the pipeline
56      * stage, see also access scopes and this table:
57      * https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#synchronization-access-types-supported
58      */
59     switch (layout) {
60     case VK_IMAGE_LAYOUT_UNDEFINED:
61         return 0;
62     case VK_IMAGE_LAYOUT_GENERAL:
63         return VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
64     case VK_IMAGE_LAYOUT_PREINITIALIZED:
65         return VK_ACCESS_HOST_WRITE_BIT;
66     case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
67         return VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
68                VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
69     case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
70         return VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
71     case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
72         return VK_ACCESS_TRANSFER_READ_BIT;
73     case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
74         return VK_ACCESS_TRANSFER_WRITE_BIT;
75     case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
76         return 0;
77     default:
78         return 0;
79     };
80
81     return 0;
82 }
83
84 static void
85 enable_validation_layers(VkInstanceCreateInfo *info)
86 {
87     int i;
88     uint32_t num_layers;
89     VkLayerProperties *layers;
90     static const char *layer_names[] = {
91         "VK_LAYER_KHRONOS_validation",
92     };
93
94     vkEnumerateInstanceLayerProperties(&num_layers, 0);
95     layers = alloca(num_layers * sizeof *layers);
96     vkEnumerateInstanceLayerProperties(&num_layers, layers);
97
98     if (num_layers) {
99         printf("Available validation layers:\n");
100         for(i = 0; i < (int)num_layers; i++) {
101             printf(" %s\n", layers[i].layerName);
102         }
103
104         info->ppEnabledLayerNames = layer_names;
105         info->enabledLayerCount = sizeof layer_names / sizeof *layer_names;
106     } else {
107         fprintf(stderr, "Vulkan validation layers not found.\n");
108     }
109 }
110
111 static void
112 enable_extensions(VkInstanceCreateInfo *info)
113 {
114     static const char *ext_names[] = {
115         "VK_KHR_xcb_surface",
116         "VK_KHR_surface"
117     };
118
119     uint32_t num_extensions;
120     VkExtensionProperties *extensions;
121     int i;
122
123     vkEnumerateInstanceExtensionProperties(0, &num_extensions, 0);
124     if (!num_extensions) {
125         fprintf(stderr, "No instance extensions found.\n");
126         return;
127     }
128
129     extensions = alloca(num_extensions * sizeof *extensions);
130     vkEnumerateInstanceExtensionProperties(0, &num_extensions, extensions);
131
132     printf("Available extensions:\n");
133     for (i = 0; i < num_extensions; i++) {
134        printf(" %s\n", extensions[i].extensionName);
135     }
136
137     info->ppEnabledExtensionNames = ext_names;
138     info->enabledExtensionCount = ARRAY_SIZE(ext_names);
139 }
140
141 static VkInstance
142 create_instance(bool enable_layers)
143 {
144     VkApplicationInfo app_info;
145     VkInstanceCreateInfo inst_info;
146     VkInstance inst;
147
148     /* VkApplicationInfo */
149     memset(&app_info, 0, sizeof app_info);
150     app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
151     app_info.pApplicationName = "hikikornd";
152     app_info.apiVersion = VK_API_VERSION_1_1;
153
154     /* VkInstanceCreateInfo */
155     memset(&inst_info, 0, sizeof inst_info);
156     inst_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
157     inst_info.pApplicationInfo = &app_info;
158
159     enable_extensions(&inst_info);
160     if (enable_layers) {
161         enable_validation_layers(&inst_info);
162     }
163
164     if (vkCreateInstance(&inst_info, 0, &inst) != VK_SUCCESS)
165         return 0;
166
167     return inst;
168 }
169
170 static VkPhysicalDevice
171 select_physical_device(VkInstance inst)
172 {
173     VkResult res = VK_SUCCESS;
174     uint32_t dev_count = 0;
175     VkPhysicalDevice *pdevices;
176     VkPhysicalDevice pdevice0;
177
178     if ((res =
179          vkEnumeratePhysicalDevices(inst, &dev_count, 0)) != VK_SUCCESS)
180         return 0;
181
182     pdevices = malloc(dev_count * sizeof(VkPhysicalDevice));
183     if (vkEnumeratePhysicalDevices(inst, &dev_count, pdevices) !=
184         VK_SUCCESS)
185         return 0;
186
187     pdevice0 = pdevices[0];
188     free(pdevices);
189
190     return pdevice0;
191 }
192
193 static VkDevice
194 create_device(struct vk_ctx *ctx, VkPhysicalDevice pdev)
195 {
196     const char *deviceExtensions[] = { "VK_KHR_swapchain" };
197     VkDeviceQueueCreateInfo dev_queue_info;
198     VkDeviceCreateInfo dev_info;
199     VkDevice dev;
200     uint32_t prop_count;
201     VkQueueFamilyProperties *fam_props;
202     uint32_t i;
203     float qprio = 0;
204
205     ctx->qfam_idx = -1;
206     vkGetPhysicalDeviceQueueFamilyProperties(pdev, &prop_count, 0);
207     if (prop_count < 0) {
208         fprintf(stderr, "Invalid queue family properties.\n");
209         return 0;
210     }
211
212     fam_props = malloc(prop_count * sizeof *fam_props);
213     vkGetPhysicalDeviceQueueFamilyProperties(pdev, &prop_count, fam_props);
214
215     for (i = 0; i < prop_count; i++) {
216         if (fam_props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
217             ctx->qfam_idx = i;
218             break;
219         }
220     }
221     free(fam_props);
222
223     memset(&dev_queue_info, 0, sizeof dev_queue_info);
224     dev_queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
225     dev_queue_info.queueFamilyIndex = ctx->qfam_idx;
226     dev_queue_info.queueCount = 1;
227     dev_queue_info.pQueuePriorities = &qprio;
228
229     memset(&dev_info, 0, sizeof dev_info);
230     dev_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
231     dev_info.queueCreateInfoCount = 1;
232     dev_info.pQueueCreateInfos = &dev_queue_info;
233     dev_info.enabledExtensionCount = ARRAY_SIZE(deviceExtensions);
234     dev_info.ppEnabledExtensionNames = deviceExtensions;
235
236     if (vkCreateDevice(pdev, &dev_info, 0, &dev) != VK_SUCCESS)
237         return 0;
238
239     return dev;
240 }
241
242 static void
243 fill_uuid(VkPhysicalDevice pdev, uint8_t *deviceUUID, uint8_t *driverUUID)
244 {
245     VkPhysicalDeviceIDProperties devProp;
246     VkPhysicalDeviceProperties2 prop2;
247
248     memset(&devProp, 0, sizeof devProp);
249     devProp.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES;
250
251     memset(&prop2, 0, sizeof prop2);
252     prop2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
253     prop2.pNext = &devProp;
254
255     vkGetPhysicalDeviceProperties2(pdev, &prop2);
256     memcpy(deviceUUID, devProp.deviceUUID, VK_UUID_SIZE);
257     memcpy(driverUUID, devProp.driverUUID, VK_UUID_SIZE);
258 }
259
260 static VkCommandPool
261 create_cmd_pool(struct vk_ctx *ctx)
262 {
263     VkCommandPoolCreateInfo cmd_pool_info;
264     VkCommandPool cmd_pool;
265
266     memset(&cmd_pool_info, 0, sizeof cmd_pool_info);
267     cmd_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
268     cmd_pool_info.queueFamilyIndex = ctx->qfam_idx;
269     cmd_pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
270
271     if (vkCreateCommandPool(ctx->dev, &cmd_pool_info, 0, &cmd_pool) != VK_SUCCESS)
272         return 0;
273
274     return cmd_pool;
275 }
276
277 static VkPipelineCache
278 create_pipeline_cache(struct vk_ctx *ctx)
279 {
280     VkPipelineCacheCreateInfo pc_info;
281     VkPipelineCache pcache;
282
283     memset(&pc_info, 0, sizeof pc_info);
284     pc_info.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
285
286     if (vkCreatePipelineCache(ctx->dev, &pc_info, 0, &pcache) != VK_SUCCESS) {
287         fprintf(stderr, "Failed to create a pipeline cache.\n");
288         return VK_NULL_HANDLE;
289     }
290
291     return pcache;
292 }
293
294 bool
295 vk_create_renderpass(struct vk_ctx *ctx,
296                      uint32_t num_color_atts,
297                      struct vk_att_props *color_props,
298                      struct vk_att_props *depth_props,
299                      VkRenderPass *renderpass)
300 {
301     VkAttachmentDescription *att_dsc;
302     VkAttachmentReference *att_rfc;
303
304     /* one subpass for the moment: */
305     VkSubpassDescription subpass_dsc[1];
306     VkSubpassDependency subpass_dep;
307
308     VkRenderPassCreateInfo rpass_info;
309
310     int i;
311     uint32_t num_atts = num_color_atts + 1;
312     bool has_layout = depth_props->in_layout != VK_IMAGE_LAYOUT_UNDEFINED;
313
314     att_dsc = malloc(num_atts * sizeof att_dsc[0]);
315     att_rfc = malloc(num_atts * sizeof att_rfc[0]);
316
317     memset(att_dsc, 0, num_atts * sizeof att_dsc[0]);
318     memset(att_rfc, 0, num_atts * sizeof att_rfc[0]);
319
320     /* color attachments description (we can have many) */
321     for (i = 0; i < num_color_atts; i++) {
322         att_dsc[i].samples = get_num_samples(color_props[i].num_samples);
323         att_dsc[i].initialLayout = color_props[i].in_layout;
324         att_dsc[i].finalLayout = color_props[i].end_layout;
325         att_dsc[i].format = color_props[i].format;
326
327         att_dsc[i].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
328         att_dsc[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
329         att_dsc[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
330         att_dsc[i].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
331
332         att_rfc[i].attachment = i;
333         att_rfc[i].layout = color_props[i].tiling != VK_IMAGE_TILING_OPTIMAL ?
334                                                      VK_IMAGE_LAYOUT_GENERAL :
335                                                      VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
336
337     }
338
339     /* depth attachment description (we can have only one) */
340     att_dsc[num_color_atts].samples = get_num_samples(depth_props->num_samples);
341     att_dsc[num_color_atts].initialLayout = depth_props->in_layout;
342     att_dsc[num_color_atts].finalLayout = depth_props->end_layout;
343     att_dsc[num_color_atts].format = depth_props->format;
344     /* we might want to reuse the depth buffer when it's filled */
345     att_dsc[num_color_atts].loadOp = has_layout ?
346                                VK_ATTACHMENT_LOAD_OP_LOAD :
347                                VK_ATTACHMENT_LOAD_OP_CLEAR;
348     att_dsc[num_color_atts].stencilLoadOp = has_layout ?
349                                       VK_ATTACHMENT_LOAD_OP_LOAD :
350                                       VK_ATTACHMENT_LOAD_OP_CLEAR;
351     att_dsc[num_color_atts].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
352     att_rfc[num_color_atts].layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
353     att_rfc[num_color_atts].attachment = num_color_atts;
354
355     /* VkSubpassDescription */
356     memset(&subpass_dsc, 0, sizeof subpass_dsc);
357     subpass_dsc[0].pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
358     subpass_dsc[0].colorAttachmentCount = num_color_atts;
359     subpass_dsc[0].pColorAttachments = &att_rfc[0];
360     subpass_dsc[0].pDepthStencilAttachment = &att_rfc[num_color_atts];
361
362     /* The subpasses in a render pass automatically take care of
363      * image layout transitions. These transitions are controlled
364      * by subpass dependencies, which specify memory and execution
365      * dependencies between subpasses. We have only a single subpass
366      * right now, but the operations right before and right after
367      * this subpass also count as implicit "subpasses". There are two
368      * built-in dependencies that take care of the transition at the
369      * start of the render pass and at the end of the render pass,
370      * but the former does not occur at the right time. It assumes
371      * that the transition occurs at the start of the pipeline,
372      * but we haven't acquired the image yet at that point! There are
373      * two ways to deal with this problem.
374      *
375      * We could change the waitStages for the frame_ready semaphore
376      * to VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT to ensure that the render
377      * passes don't begin until the image is available, or we can make
378      * the render pass wait for the
379      * VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT stage.
380      */
381
382     /* VkSubpassDependency */
383     memset(&subpass_dep, 0, sizeof subpass_dep);
384     subpass_dep.srcSubpass = VK_SUBPASS_EXTERNAL;
385     subpass_dep.dstSubpass = 0;
386     subpass_dep.srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
387     subpass_dep.srcAccessMask = 0;
388     subpass_dep.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
389     subpass_dep.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
390
391     /* VkRenderPassCreateInfo */
392     memset(&rpass_info, 0, sizeof rpass_info);
393     rpass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
394     rpass_info.attachmentCount = num_atts;
395     rpass_info.pAttachments = att_dsc;
396     rpass_info.subpassCount = 1;
397     rpass_info.pSubpasses = subpass_dsc;
398     rpass_info.dependencyCount = 1;
399     rpass_info.pDependencies = &subpass_dep;
400
401     if (vkCreateRenderPass(ctx->dev, &rpass_info, 0, renderpass) != VK_SUCCESS) {
402         fprintf(stderr, "Failed to create renderpass.\n");
403         *renderpass = VK_NULL_HANDLE;
404
405         free(att_dsc);
406         free(att_rfc);
407
408         return false;
409     }
410
411     free(att_dsc);
412     free(att_rfc);
413
414     return true;
415 }
416
417 static inline VkImageType
418 get_image_type(uint32_t h, uint32_t d)
419 {
420     if (h == 1)
421         return VK_IMAGE_TYPE_1D;
422
423     if (d > 1)
424         return VK_IMAGE_TYPE_3D;
425
426     return VK_IMAGE_TYPE_2D;
427 }
428
429 #if 0
430 static VkImageViewType
431 get_image_view_type(struct vk_att_props *props)
432 {
433     VkImageType type = get_image_type(props->h, props->depth);
434     switch(type) {
435         case VK_IMAGE_TYPE_1D:
436             return props->num_layers > 1 ?
437                 VK_IMAGE_VIEW_TYPE_1D_ARRAY :
438                 VK_IMAGE_VIEW_TYPE_1D;
439         case VK_IMAGE_TYPE_2D:
440             if (props->num_layers == 1)
441                 return VK_IMAGE_VIEW_TYPE_2D;
442             if (props->num_layers == 6)
443                 return VK_IMAGE_VIEW_TYPE_CUBE;
444             if (props->num_layers % 6 == 0)
445                 return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
446             if (props->num_layers > 1)
447                 return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
448         case VK_IMAGE_TYPE_3D:
449             if (props->num_layers == 1)
450                 return VK_IMAGE_VIEW_TYPE_3D;
451             if ((props->num_layers == 1) &&
452                 (props->num_levels == 1))
453                 return VK_IMAGE_VIEW_TYPE_2D;
454             if ((props->num_levels == 1) &&
455                 (props->num_layers > 1))
456                 return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
457         default:
458             return VK_IMAGE_VIEW_TYPE_2D;
459     }
460 }
461 #endif
462
463 static VkImageAspectFlagBits
464 get_aspect_from_depth_format(VkFormat depth_format)
465 {
466     switch (depth_format) {
467     case VK_FORMAT_D16_UNORM:
468     case VK_FORMAT_X8_D24_UNORM_PACK32:
469     case VK_FORMAT_D32_SFLOAT:
470         return VK_IMAGE_ASPECT_DEPTH_BIT;
471     case VK_FORMAT_S8_UINT:
472         return VK_IMAGE_ASPECT_STENCIL_BIT;
473     case VK_FORMAT_D16_UNORM_S8_UINT:
474     case VK_FORMAT_D24_UNORM_S8_UINT:
475     case VK_FORMAT_D32_SFLOAT_S8_UINT:
476         return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
477     default:
478         break;
479     }
480     return 0;
481 }
482
483 static VkPipelineStageFlags
484 get_pipeline_stage_flags(const VkImageLayout layout)
485 {
486     switch (layout) {
487     case VK_IMAGE_LAYOUT_UNDEFINED:
488         return VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
489     case VK_IMAGE_LAYOUT_GENERAL:
490         return VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
491     case VK_IMAGE_LAYOUT_PREINITIALIZED:
492         return VK_PIPELINE_STAGE_HOST_BIT;
493     case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
494     case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
495         return VK_PIPELINE_STAGE_TRANSFER_BIT;
496     case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
497         return VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
498     case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
499         return VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
500                VK_PIPELINE_STAGE_VERTEX_SHADER_BIT;
501     case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
502         return VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
503     default:
504         break;
505     }
506     return 0;
507 }
508
509 #if 0
510 static bool
511 create_attachment_views(struct vk_ctx *ctx, int num_color_att,
512                         struct vk_attachment *color_att,
513                         struct vk_attachment *depth_att)
514 {
515     VkImageSubresourceRange sr;
516     int i;
517
518     vk_create_image_view(ctx, depth_att->obj.img, VK_IMAGE_VIEW_TYPE_2D,
519                          depth_att->props.format, false,
520                          &depth_att->obj.img_view);
521
522     memset(&sr, 0, sizeof sr);
523     sr.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
524
525     for (i = 0; i < num_color_att; i++) {
526         vk_create_image_view(ctx, color_att[i].obj.img, VK_IMAGE_VIEW_TYPE_2D,
527                              color_att[i].props.format,
528                              color_att[i].props.is_swapchain,
529                              &color_att[i].obj.img_view);
530     }
531
532     return true;
533 }
534
535 static bool
536 create_framebuffer_from_attachments(struct vk_ctx *ctx,
537                                     int width, int height,
538                                     int num_color_atts,
539                                     struct vk_attachment *color_att,
540                                     struct vk_attachment *depth_att,
541                                     struct vk_renderer *renderer)
542 {
543     VkFramebufferCreateInfo fb_info;
544     VkImageView *atts;
545     int i;
546     int num_atts = num_color_atts + 1;
547
548     atts = malloc(num_atts * sizeof atts[0]);
549
550     for (i = 0; i < num_color_atts; i++) {
551         atts[i] = color_att[i].obj.img_view;
552     }
553     atts[num_color_atts] = depth_att->obj.img_view;
554
555     memset(&fb_info, 0, sizeof fb_info);
556     fb_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
557     fb_info.renderPass = renderer->renderpass;
558     fb_info.width = width;
559     fb_info.height = height;
560     fb_info.layers = 1;
561     fb_info.attachmentCount = num_atts;
562     fb_info.pAttachments = atts;
563
564     if (vkCreateFramebuffer(ctx->dev, &fb_info, 0, &renderer->fb) != VK_SUCCESS) {
565         fprintf(stderr, "Failed to create framebuffer.\n");
566         free(atts);
567         renderer->fb = VK_NULL_HANDLE;
568
569         return false;
570     }
571
572     free(atts);
573     return true;
574 }
575 #endif
576
577 static VkShaderModule
578 create_shader_module(struct vk_ctx *ctx,
579                      const char *src,
580                      unsigned int size)
581 {
582     VkShaderModuleCreateInfo sm_info;
583     VkShaderModule sm;
584
585     /* VkShaderModuleCreateInfo */
586     memset(&sm_info, 0, sizeof sm_info);
587     sm_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
588     sm_info.codeSize = size;
589     sm_info.pCode = (void*)src;
590
591     if (vkCreateShaderModule(ctx->dev, &sm_info, 0, &sm) != VK_SUCCESS) {
592         fprintf(stderr, "Failed to create shader module.\n");
593         sm = VK_NULL_HANDLE;
594     }
595
596     return sm;
597 }
598
599 static bool
600 create_graphics_pipeline(struct vk_ctx *ctx,
601                          uint32_t width,
602                          uint32_t height,
603                          uint32_t num_samples,
604                          uint32_t num_color_atts,
605                          bool enable_depth,
606                          bool enable_stencil,
607                          struct vk_renderer *renderer)
608 {
609     VkVertexInputBindingDescription vert_bind_dsc[1];
610     VkVertexInputAttributeDescription vert_att_dsc[1];
611
612     VkPipelineColorBlendAttachmentState *cb_att_state;
613     VkPipelineVertexInputStateCreateInfo vert_input_info;
614     VkPipelineInputAssemblyStateCreateInfo asm_info;
615     VkPipelineViewportStateCreateInfo viewport_info;
616     VkPipelineRasterizationStateCreateInfo rs_info;
617     VkPipelineMultisampleStateCreateInfo ms_info;
618     VkPipelineDepthStencilStateCreateInfo ds_info;
619     VkPipelineColorBlendStateCreateInfo cb_info;
620     VkPipelineShaderStageCreateInfo sdr_stages[2];
621     VkPipelineLayoutCreateInfo layout_info;
622     VkGraphicsPipelineCreateInfo pipeline_info;
623     VkFormat format;
624     VkFormatProperties fmt_props;
625     VkPushConstantRange pc_range[1];
626
627     VkStencilOpState front;
628     VkStencilOpState back;
629     int i;
630     VkPipelineLayout pipeline_layout;
631     uint32_t stride;
632
633     /* format of vertex attributes:
634      * we have 2D vectors so we need a RG format:
635      * R for x, G for y
636      * the stride (distance between 2 consecutive elements)
637      * must be 8 because we use 32 bit floats and
638      * 32bits = 8bytes */
639     format = VK_FORMAT_R32G32_SFLOAT;
640     vkGetPhysicalDeviceFormatProperties(ctx->pdev, format, &fmt_props);
641     assert(fmt_props.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT);
642     stride = 8;
643
644     /* VkVertexInputAttributeDescription */
645     memset(&vert_att_dsc, 0, sizeof vert_att_dsc);
646     vert_att_dsc[0].location = 0;
647     vert_att_dsc[0].binding = 0;
648     vert_att_dsc[0].format = format; /* see comment */
649     vert_att_dsc[0].offset = 0;
650
651     /* VkVertexInputBindingDescription */
652     memset(&vert_bind_dsc, 0, sizeof vert_bind_dsc);
653     vert_bind_dsc[0].binding = 0;
654     vert_bind_dsc[0].stride = stride;
655     vert_bind_dsc[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
656
657     /* If using vbo, we have setup vertex_info in the renderer. */
658     bool use_vbo = renderer->vertex_info.num_verts > 0;
659
660     /* VkPipelineVertexInputStateCreateInfo */
661     memset(&vert_input_info, 0, sizeof vert_input_info);
662     vert_input_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
663     vert_input_info.vertexBindingDescriptionCount = use_vbo ? 1 : 0;
664     vert_input_info.pVertexBindingDescriptions = vert_bind_dsc;
665     vert_input_info.vertexAttributeDescriptionCount = use_vbo ? 1 : 0;
666     vert_input_info.pVertexAttributeDescriptions = vert_att_dsc;
667
668     /* VkPipelineInputAssemblyStateCreateInfo */
669     memset(&asm_info, 0, sizeof asm_info);
670     asm_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
671     asm_info.topology = renderer->vertex_info.topology ?
672                         renderer->vertex_info.topology
673                         : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
674     asm_info.primitiveRestartEnable = false;
675
676     /* VkViewport */
677     viewport.x = viewport.y = 0;
678     viewport.width = width;
679     viewport.height = height;
680     viewport.minDepth = 0;
681     viewport.maxDepth = 1;
682
683     /* VkRect2D scissor */
684     scissor.offset.x = scissor.offset.y = 0;
685     scissor.extent.width = width;
686     scissor.extent.height = height;
687
688     /* VkPipelineViewportStateCreateInfo */
689     memset(&viewport_info, 0, sizeof viewport_info);
690     viewport_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
691     viewport_info.viewportCount = 1;
692     viewport_info.pViewports = &viewport;
693     viewport_info.scissorCount = 1;
694     viewport_info.pScissors = &scissor;
695
696     /* VkPipelineRasterizationStateCreateInfo */
697     memset(&rs_info, 0, sizeof rs_info);
698     rs_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
699     rs_info.polygonMode = VK_POLYGON_MODE_FILL;
700     rs_info.cullMode = VK_CULL_MODE_NONE;
701     rs_info.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
702     rs_info.lineWidth = 1.0;
703
704     /* VkPipelineMultisampleStateCreateInfo */
705     memset(&ms_info, 0, sizeof ms_info);
706     ms_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
707     ms_info.rasterizationSamples = get_num_samples(num_samples);
708
709     /* VkStencilOpState */
710     /* The default values for ES are taken by Topi Pohjolainen's code */
711     /* defaults in OpenGL ES 3.1 */
712     memset(&front, 0, sizeof front);
713     front.compareMask = ~0;
714     front.writeMask = ~0;
715     front.reference = 0;
716
717     memset(&back, 0, sizeof back);
718     back.compareMask = ~0;
719     back.writeMask = ~0;
720     back.reference = 0;
721
722     /* VkPipelineDepthStencilStateCreateInfo */
723     memset(&ds_info, 0, sizeof ds_info);
724     ds_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
725     ds_info.front = front;
726     ds_info.back = back;
727     /* defaults in OpenGL ES 3.1 */
728     ds_info.minDepthBounds = 0;
729     ds_info.maxDepthBounds = 1;
730     /* z buffer, stencil buffer */
731     if (enable_depth) {
732         ds_info.depthTestEnable = VK_TRUE;
733         ds_info.depthWriteEnable = VK_TRUE;
734         ds_info.depthCompareOp = VK_COMPARE_OP_LESS;
735     }
736     if (enable_stencil) {
737         ds_info.stencilTestEnable = VK_TRUE;
738         ds_info.depthTestEnable = VK_FALSE;
739         ds_info.depthWriteEnable = VK_TRUE;
740     }
741
742     /* we only care about the passOp here */
743     ds_info.back.compareOp = VK_COMPARE_OP_ALWAYS;
744     ds_info.back.failOp = VK_STENCIL_OP_REPLACE;
745     ds_info.back.depthFailOp = VK_STENCIL_OP_REPLACE;
746     ds_info.back.passOp = VK_STENCIL_OP_REPLACE;
747     ds_info.back.compareMask = 0xffffffff;
748     ds_info.back.writeMask = 0xffffffff;
749     ds_info.back.reference = 1;
750     ds_info.front = ds_info.back;
751
752     /* VkPipelineColorBlendAttachmentState */
753     cb_att_state = malloc(num_color_atts * sizeof cb_att_state[0]);
754     if (!cb_att_state) {
755         fprintf(stderr, "Failed to allocate color blend attachment state for each attachment.\n");
756         goto fail;
757     }
758     memset(cb_att_state, 0, num_color_atts * sizeof cb_att_state[0]);
759     for (i = 0; i < num_color_atts; i++) {
760         cb_att_state[i].colorWriteMask = (VK_COLOR_COMPONENT_R_BIT |
761                                           VK_COLOR_COMPONENT_G_BIT |
762                                           VK_COLOR_COMPONENT_B_BIT |
763                                           VK_COLOR_COMPONENT_A_BIT);
764     }
765
766     /* VkPipelineColorBlendStateCreateInfo */
767     memset(&cb_info, 0, sizeof cb_info);
768     cb_info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
769     cb_info.attachmentCount = num_color_atts;
770     cb_info.pAttachments = cb_att_state;
771     /* default in ES 3.1 */
772     for (i = 0; i < 4; i++) {
773         cb_info.blendConstants[i] = 0.0f;
774     }
775
776     /* VkPipelineShaderStageCreateInfo */
777     memset(sdr_stages, 0, 2 * sizeof sdr_stages[0]);
778
779     sdr_stages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
780     sdr_stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
781     sdr_stages[0].module = renderer->vs;
782     sdr_stages[0].pName = "main";
783
784     sdr_stages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
785     sdr_stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
786     sdr_stages[1].module = renderer->fs;
787     sdr_stages[1].pName = "main";
788
789     /* VkPushConstantRange */
790     memset(pc_range, 0, sizeof pc_range[0]);
791     pc_range[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
792     pc_range[0].size = sizeof (struct vk_dims); /* w, h */
793
794     /* VkPipelineLayoutCreateInfo */
795     memset(&layout_info, 0, sizeof layout_info);
796     layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
797     layout_info.pushConstantRangeCount = 1;
798     layout_info.pPushConstantRanges = pc_range;
799
800     if (vkCreatePipelineLayout(ctx->dev, &layout_info,
801                                0, &pipeline_layout) != VK_SUCCESS) {
802         fprintf(stderr, "Failed to create pipeline layout\n");
803         renderer->pipeline = VK_NULL_HANDLE;
804         goto fail;
805     }
806
807     renderer->pipeline_layout = pipeline_layout;
808
809     /* VkGraphicsPipelineCreateInfo */
810     memset(&pipeline_info, 0, sizeof pipeline_info);
811     pipeline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
812     pipeline_info.layout = pipeline_layout;
813     pipeline_info.renderPass = renderer->renderpass;
814     pipeline_info.pVertexInputState = &vert_input_info;
815     pipeline_info.pInputAssemblyState = &asm_info;
816     pipeline_info.pViewportState = &viewport_info;
817     pipeline_info.pRasterizationState = &rs_info;
818     pipeline_info.pMultisampleState = &ms_info;
819     pipeline_info.pDepthStencilState = &ds_info;
820     pipeline_info.pColorBlendState = &cb_info;
821     pipeline_info.stageCount = 2;
822     pipeline_info.pStages = sdr_stages;
823
824     if (vkCreateGraphicsPipelines(ctx->dev, 0, 1,
825                                   &pipeline_info, 0,
826                                   &renderer->pipeline) != VK_SUCCESS) {
827         fprintf(stderr, "Failed to create graphics pipeline.\n");
828         renderer->pipeline = VK_NULL_HANDLE;
829         goto fail;
830     }
831
832     free(cb_att_state);
833     return true;
834
835 fail:
836     free(cb_att_state);
837     return false;
838 }
839
840 static uint32_t
841 get_memory_type_idx(VkPhysicalDevice pdev,
842             const VkMemoryRequirements *mem_reqs,
843             VkMemoryPropertyFlagBits prop_flags)
844 {
845     VkPhysicalDeviceMemoryProperties pdev_mem_props;
846     uint32_t i;
847
848     vkGetPhysicalDeviceMemoryProperties(pdev, &pdev_mem_props);
849
850     for (i = 0; i < pdev_mem_props.memoryTypeCount; i++) {
851         const VkMemoryType *type = &pdev_mem_props.memoryTypes[i];
852
853         if ((mem_reqs->memoryTypeBits & (1 << i)) &&
854             (type->propertyFlags & prop_flags) == prop_flags) {
855             return i;
856             break;
857         }
858     }
859     return UINT32_MAX;
860 }
861
862 static VkDeviceMemory
863 alloc_memory(struct vk_ctx *ctx,
864              bool is_external,
865              const VkMemoryRequirements *mem_reqs,
866              VkImage image,
867              VkBuffer buffer,
868              VkMemoryPropertyFlagBits prop_flags)
869 {
870     VkExportMemoryAllocateInfo exp_mem_info;
871     VkMemoryAllocateInfo mem_alloc_info;
872     VkDeviceMemory mem;
873     VkMemoryDedicatedAllocateInfoKHR ded_info;
874
875     if (is_external) {
876         memset(&exp_mem_info, 0, sizeof exp_mem_info);
877         exp_mem_info.sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO;
878         exp_mem_info.handleTypes =
879             VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
880     }
881
882     memset(&mem_alloc_info, 0, sizeof mem_alloc_info);
883     mem_alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
884     mem_alloc_info.pNext = is_external ? &exp_mem_info : VK_NULL_HANDLE;
885     mem_alloc_info.allocationSize = mem_reqs->size;
886     mem_alloc_info.memoryTypeIndex = get_memory_type_idx(ctx->pdev,
887                                                          mem_reqs,
888                                                          prop_flags);
889
890     if (mem_alloc_info.memoryTypeIndex == UINT32_MAX) {
891         fprintf(stderr, "No suitable memory type index found.\n");
892         return 0;
893     }
894
895     if (image || buffer) {
896         memset(&ded_info, 0, sizeof ded_info);
897         ded_info.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO;
898         ded_info.image = image;
899         ded_info.buffer = buffer;
900
901         exp_mem_info.pNext = &ded_info;
902     }
903
904     if (vkAllocateMemory(ctx->dev, &mem_alloc_info, 0, &mem) !=
905         VK_SUCCESS)
906         return 0;
907
908     return mem;
909 }
910
911 static bool
912 alloc_image_memory(struct vk_ctx *ctx,
913                    bool is_external,
914                    struct vk_image_obj *img_obj)
915 {
916     VkMemoryDedicatedRequirements ded_reqs;
917     VkImageMemoryRequirementsInfo2 req_info2;
918     VkMemoryRequirements2 mem_reqs2;
919
920     memset(&ded_reqs, 0, sizeof ded_reqs);
921     ded_reqs.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS;
922
923     /* VkImageMemoryRequirementsInfo2 */
924     memset(&req_info2, 0, sizeof req_info2);
925     req_info2.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2;
926     req_info2.image = img_obj->img;
927
928     /* VkMemoryRequirements2 */
929     memset(&mem_reqs2, 0, sizeof mem_reqs2);
930     mem_reqs2.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
931     mem_reqs2.pNext = &ded_reqs;
932
933     vkGetImageMemoryRequirements2(ctx->dev, &req_info2, &mem_reqs2);
934     img_obj->mobj.mem = alloc_memory(ctx,
935                                      is_external,
936                                      &mem_reqs2.memoryRequirements,
937                                      ded_reqs.requiresDedicatedAllocation ?
938                                         img_obj->img : VK_NULL_HANDLE,
939                                      VK_NULL_HANDLE,
940                                      mem_reqs2.memoryRequirements.memoryTypeBits &
941                                      VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
942
943     img_obj->mobj.mem_sz = mem_reqs2.memoryRequirements.size;
944     img_obj->mobj.dedicated = ded_reqs.requiresDedicatedAllocation;
945     if (img_obj->mobj.mem == VK_NULL_HANDLE) {
946         fprintf(stderr, "Failed to allocate image memory.\n");
947         return false;
948     }
949
950     if (vkBindImageMemory(ctx->dev, img_obj->img, img_obj->mobj.mem, 0) !=
951             VK_SUCCESS) {
952         fprintf(stderr, "Failed to bind image memory.\n");
953         return false;
954     }
955
956     return true;
957 }
958
959 static bool
960 are_props_supported(struct vk_ctx *ctx, struct vk_att_props *props)
961 {
962     VkPhysicalDeviceExternalImageFormatInfo ext_img_fmt_info;
963     VkExternalImageFormatProperties ext_img_fmt_props;
964
965     int i;
966     VkPhysicalDeviceImageFormatInfo2 img_fmt_info;
967     VkImageFormatProperties2 img_fmt_props;
968
969     VkImageUsageFlagBits all_flags[] = {
970         VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
971         VK_IMAGE_USAGE_TRANSFER_DST_BIT,
972         VK_IMAGE_USAGE_SAMPLED_BIT,
973         VK_IMAGE_USAGE_STORAGE_BIT,
974         VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
975         VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
976         VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,
977         /* Shouldn't be used together with COLOR, DEPTH_STENCIL
978          * attachment bits:
979          * VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
980          * Provided by VK_EXT_fragment_density_map
981          * VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT,
982          * Provided by VK_NV_shading_rate_image
983          * VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV,
984          * Provided by VK_KHR_fragment_shading_rate
985          * VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR,
986          */
987     };
988     VkImageUsageFlagBits flags = 0;
989
990     VkExternalMemoryFeatureFlagBits export_feature_flags = props->need_export ?
991         VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT : 0;
992     VkExternalMemoryHandleTypeFlagBits handle_type = props->need_export ?
993         VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR : 0;
994
995     if (props->need_export) {
996         memset(&ext_img_fmt_info, 0, sizeof ext_img_fmt_info);
997         ext_img_fmt_info.sType =
998             VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO;
999         ext_img_fmt_info.handleType = handle_type;
1000
1001         memset(&ext_img_fmt_props, 0, sizeof ext_img_fmt_props);
1002         ext_img_fmt_props.sType =
1003             VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES;
1004     }
1005
1006     memset(&img_fmt_props, 0, sizeof img_fmt_props);
1007     img_fmt_props.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
1008     img_fmt_props.pNext = props->need_export ? &ext_img_fmt_props : 0;
1009
1010     memset(&img_fmt_info, 0, sizeof img_fmt_info);
1011     img_fmt_info.sType =
1012         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2;
1013     img_fmt_info.pNext = props->need_export ? &ext_img_fmt_info : 0;
1014     img_fmt_info.format = props->format;
1015     img_fmt_info.type = VK_IMAGE_TYPE_2D;
1016     img_fmt_info.tiling = props->tiling;
1017
1018     for (i = 0; i < ARRAY_SIZE(all_flags); i++) {
1019         img_fmt_info.usage = all_flags[i];
1020         if (vkGetPhysicalDeviceImageFormatProperties2(ctx->pdev,
1021                                                       &img_fmt_info,
1022                                                       &img_fmt_props) == VK_SUCCESS) {
1023             flags |= all_flags[i];
1024         }
1025     }
1026
1027     /* usage can't be null */
1028     if (flags) {
1029         img_fmt_info.usage = flags;
1030     } else {
1031         if (!props->is_swapchain) {
1032             fprintf(stderr, "Unsupported Vulkan format properties: usage.\n");
1033             return false;
1034         }
1035         img_fmt_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
1036     }
1037
1038     if (vkGetPhysicalDeviceImageFormatProperties2
1039         (ctx->pdev, &img_fmt_info, &img_fmt_props) != VK_SUCCESS) {
1040         fprintf(stderr,
1041             "Unsupported Vulkan format properties.\n");
1042         return false;
1043     }
1044     props->usage = flags;
1045
1046     if (props->need_export &&
1047         !(ext_img_fmt_props.externalMemoryProperties.externalMemoryFeatures
1048             & export_feature_flags)) {
1049         fprintf(stderr, "Unsupported Vulkan external memory features.\n");
1050         return false;
1051     }
1052
1053     return true;
1054 }
1055
1056 /* static swapchain / surf related functions */
1057
1058 static bool
1059 sc_validate_surface(struct vk_ctx *ctx,
1060                     VkSurfaceKHR surf)
1061 {
1062     VkBool32 supported;
1063     if (!surf) {
1064         fprintf(stderr, "No surface!\n");
1065         return false;
1066     }
1067
1068     if(vkGetPhysicalDeviceSurfaceSupportKHR(ctx->pdev, ctx->qfam_idx,
1069                                             surf, &supported) != VK_SUCCESS) {
1070         fprintf(stderr, "Failed to validate surface.\n");
1071         return false;
1072     }
1073
1074     if (!supported) {
1075         fprintf(stderr, "Invalid surface! Check if the surface with queue family index: %d supports presentation.\n", (int)ctx->qfam_idx);
1076         return false;
1077     }
1078
1079     return true;
1080 }
1081
1082 static bool
1083 sc_select_format(struct vk_ctx *ctx,
1084                  VkSurfaceKHR surf,
1085                  VkSwapchainCreateInfoKHR *s_info)
1086 {
1087     VkSurfaceFormatKHR *formats;
1088     uint32_t num_formats;
1089
1090     if (vkGetPhysicalDeviceSurfaceFormatsKHR(ctx->pdev,
1091                                              surf,
1092                                              &num_formats, 0) != VK_SUCCESS) {
1093         fprintf(stderr, "Failed to get the number of surface formats.\n");
1094         return false;
1095     }
1096
1097     if (!num_formats) {
1098         fprintf(stderr, "No surface formats found.\n");
1099         return false;
1100     }
1101
1102     formats = malloc(num_formats * sizeof *formats);
1103
1104     if (vkGetPhysicalDeviceSurfaceFormatsKHR(ctx->pdev, surf, &num_formats,
1105                                              formats) != VK_SUCCESS) {
1106         fprintf(stderr, "Failed to get the supported surface formats.\n");
1107         return false;
1108     }
1109
1110     if ((num_formats == 1) && (formats[0].format == VK_FORMAT_UNDEFINED)) {
1111         s_info->imageFormat = VK_FORMAT_B8G8R8A8_UNORM;
1112         s_info->imageColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
1113     } else {
1114         s_info->imageFormat = formats[0].format;
1115         s_info->imageColorSpace = formats[0].colorSpace;
1116     }
1117     free(formats);
1118
1119     return true;
1120 }
1121
1122 static bool
1123 sc_select_supported_present_modes(struct vk_ctx *ctx,
1124                                   VkSurfaceKHR surf,
1125                                   bool has_vsync,
1126                                   VkSwapchainCreateInfoKHR *s_info)
1127 {
1128     VkPresentModeKHR *present_modes;
1129     uint32_t num_present_modes;
1130
1131     /* find supported present modes */
1132     if (vkGetPhysicalDeviceSurfacePresentModesKHR(ctx->pdev, surf,
1133                                                   &num_present_modes, 0) != VK_SUCCESS || !num_present_modes) {
1134         fprintf(stderr, "Failed to get the number of the supported presentation modes.\n");
1135         return false;
1136     }
1137
1138     present_modes = malloc(num_present_modes * sizeof *present_modes);
1139     if (vkGetPhysicalDeviceSurfacePresentModesKHR(ctx->pdev, surf,
1140                                                   &num_present_modes,
1141                                                   present_modes) != VK_SUCCESS) {
1142         fprintf(stderr, "Failed to get the number of supported presentation modes.\n");
1143         return false;
1144     }
1145     if (vkGetPhysicalDeviceSurfacePresentModesKHR(ctx->pdev, surf,
1146                                                   &num_present_modes,
1147                                                   present_modes) != VK_SUCCESS) {
1148         fprintf(stderr, "Failed to get the supported presentation modes.\n");
1149         return false;
1150     }
1151
1152     s_info->presentMode = VK_PRESENT_MODE_FIFO_KHR;
1153 #if 0
1154     if (!has_vsync) {
1155         for (i = 0; i < num_present_modes; i++) {
1156             if (present_modes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
1157                 s_info->presentMode = present_modes[i];
1158                 break;
1159             }
1160             if (present_modes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR) {
1161                 s_info->presentMode = present_modes[i];
1162                 break;
1163             }
1164         }
1165     }
1166 #endif
1167
1168     free(present_modes);
1169     return true;
1170 }
1171
1172 /* end of static functions */
1173
1174 /* exposed Vulkan functions */
1175
1176 bool
1177 vk_init_ctx(struct vk_ctx *ctx,
1178             bool enable_layers)
1179 {
1180     if ((ctx->inst = create_instance(enable_layers)) == VK_NULL_HANDLE) {
1181         fprintf(stderr, "Failed to create Vulkan instance.\n");
1182         goto fail;
1183     }
1184
1185     if ((ctx->pdev = select_physical_device(ctx->inst)) == VK_NULL_HANDLE) {
1186         fprintf(stderr, "Failed to find suitable physical device.\n");
1187         goto fail;
1188     }
1189
1190     if ((ctx->dev = create_device(ctx, ctx->pdev)) == VK_NULL_HANDLE) {
1191         fprintf(stderr, "Failed to create Vulkan device.\n");
1192         goto fail;
1193     }
1194
1195     fill_uuid(ctx->pdev, ctx->deviceUUID, ctx->driverUUID);
1196     return true;
1197
1198 fail:
1199     vk_cleanup_ctx(ctx);
1200     return false;
1201 }
1202
1203 bool
1204 vk_init_ctx_for_rendering(struct vk_ctx *ctx,
1205                           bool enable_cache,
1206                           bool enable_layers)
1207 {
1208     if (!vk_init_ctx(ctx, enable_layers)) {
1209         fprintf(stderr, "Failed to initialize Vulkan.\n");
1210         return false;
1211     }
1212
1213     if ((ctx->cmd_pool = create_cmd_pool(ctx)) == VK_NULL_HANDLE) {
1214         fprintf(stderr, "Failed to create command pool.\n");
1215         goto fail;
1216     }
1217
1218     vkGetDeviceQueue(ctx->dev, ctx->qfam_idx, 0, &ctx->queue);
1219     if (!ctx->queue) {
1220         fprintf(stderr, "Failed to get command queue.\n");
1221         goto fail;
1222     }
1223
1224     if (enable_cache) {
1225         if (!(pipeline_cache = create_pipeline_cache(ctx))) {
1226             fprintf(stderr, "Failed to create pipeline cache.\n");
1227             goto fail;
1228         }
1229     }
1230
1231     return true;
1232
1233 fail:
1234     vk_cleanup_ctx(ctx);
1235     return false;
1236 }
1237
1238 void
1239 vk_destroy_cmd_buffers(struct vk_ctx *ctx,
1240                        uint32_t num_buffers,
1241                        VkCommandBuffer *buffers)
1242 {
1243     int i;
1244     for (i = 0; i < num_buffers; i++) {
1245         vkResetCommandBuffer(buffers[i],
1246                              VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
1247     }
1248     vkFreeCommandBuffers(ctx->dev, ctx->cmd_pool, num_buffers, buffers);
1249 }
1250
1251 void
1252 vk_cleanup_ctx(struct vk_ctx *ctx)
1253 {
1254     if (ctx->cmd_pool != VK_NULL_HANDLE) {
1255         vkResetCommandPool(ctx->dev, ctx->cmd_pool,
1256                            VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
1257         vkDestroyCommandPool(ctx->dev, ctx->cmd_pool, 0);
1258         ctx->cmd_pool = VK_NULL_HANDLE;
1259     }
1260
1261     if (pipeline_cache != VK_NULL_HANDLE) {
1262         vkDestroyPipelineCache(ctx->dev, pipeline_cache, 0);
1263         pipeline_cache = VK_NULL_HANDLE;
1264     }
1265
1266     if (ctx->dev != VK_NULL_HANDLE) {
1267         vkDestroyDevice(ctx->dev, 0);
1268         ctx->dev = VK_NULL_HANDLE;
1269     }
1270
1271     if (ctx->inst != VK_NULL_HANDLE) {
1272         vkDestroyInstance(ctx->inst, 0);
1273         ctx->inst = VK_NULL_HANDLE;
1274     }
1275 }
1276
1277 bool
1278 vk_create_ext_image(struct vk_ctx *ctx,
1279                     struct vk_att_props *props,
1280                     struct vk_image_obj *img)
1281 {
1282     VkExternalMemoryImageCreateInfo ext_img_info;
1283     VkImageCreateInfo img_info;
1284
1285     memset(&ext_img_info, 0, sizeof ext_img_info);
1286     ext_img_info.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO;
1287     ext_img_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;
1288
1289     memset(&img_info, 0, sizeof img_info);
1290     img_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
1291     img_info.pNext = &ext_img_info;
1292     img_info.imageType = get_image_type(props->h, props->depth);
1293     img_info.format = props->format;
1294     img_info.extent.width = props->w;
1295     img_info.extent.height = props->h;
1296     img_info.extent.depth = props->depth;
1297     img_info.mipLevels = props->num_levels ? props->num_levels : 1;
1298     img_info.arrayLayers = props->num_layers ?
1299                            props->num_layers : VK_SAMPLE_COUNT_1_BIT;
1300     img_info.samples = get_num_samples(props->num_samples);
1301     img_info.tiling = props->tiling;
1302     img_info.usage = props->usage;
1303     img_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
1304     img_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
1305     /* issue 17 of EXT_external_objects
1306      * Required in OpenGL implementations that support
1307      * ARB_texture_view, OES_texture_view, EXT_texture_view,
1308      * or OpenGL 4.3 and above.
1309      */
1310     img_info.flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
1311
1312     if (vkCreateImage(ctx->dev, &img_info, 0, &img->img) != VK_SUCCESS)
1313         goto fail;
1314
1315     if(!alloc_image_memory(ctx, true, img))
1316         goto fail;
1317
1318     return true;
1319
1320 fail:
1321     fprintf(stderr, "Failed to create external image.\n");
1322     vk_destroy_image(ctx, img);
1323     img->img = VK_NULL_HANDLE;
1324     img->mobj.mem = VK_NULL_HANDLE;
1325     return false;
1326 }
1327
1328 bool
1329 vk_create_image(struct vk_ctx *ctx,
1330                 struct vk_att_props *props,
1331                 struct vk_image_obj *img)
1332 {
1333     VkImageCreateInfo img_info;
1334
1335     memset(&img_info, 0, sizeof img_info);
1336     img_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
1337     img_info.pNext = 0; /* do something if external */
1338     img_info.imageType = get_image_type(props->h, props->depth);
1339     img_info.format = props->format;
1340     img_info.extent.width = props->w;
1341     img_info.extent.height = props->h;
1342     img_info.extent.depth = props->depth;
1343     img_info.mipLevels = props->num_levels ? props->num_levels : 1;
1344     img_info.arrayLayers = props->num_layers ?
1345                            props->num_layers : VK_SAMPLE_COUNT_1_BIT;
1346     img_info.samples = get_num_samples(props->num_samples);
1347     img_info.tiling = props->tiling;
1348     img_info.usage = props->usage ?
1349                      props->usage : VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1350     img_info.initialLayout = props->in_layout;
1351     img_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
1352
1353     if (vkCreateImage(ctx->dev, &img_info, 0, &img->img) != VK_SUCCESS)
1354         goto fail;
1355
1356     if(!alloc_image_memory(ctx, props->need_export, img))
1357         goto fail;
1358
1359     return true;
1360
1361 fail:
1362     fprintf(stderr, "Failed to create external image.\n");
1363     vk_destroy_image(ctx, img);
1364     img->img = VK_NULL_HANDLE;
1365     img->mobj.mem = VK_NULL_HANDLE;
1366     return false;
1367 }
1368
1369 bool
1370 vk_create_image_view(struct vk_ctx *ctx,
1371                      VkImage image,
1372                      VkImageViewType view_type,
1373                      VkFormat format,
1374                      bool is_swapchain,
1375                      VkImageView *image_view)
1376 {
1377     VkImageViewCreateInfo info;
1378     VkImageSubresourceRange sr;
1379     VkImageAspectFlagBits aspect = get_aspect_from_depth_format(format);
1380
1381     /* VkSubresourceRange */
1382     memset(&sr, 0, sizeof sr);
1383     sr.aspectMask = aspect ? aspect : VK_IMAGE_ASPECT_COLOR_BIT;
1384     sr.levelCount = 1;
1385     sr.layerCount = 1;
1386
1387     memset(&info, 0, sizeof info);
1388     info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
1389     info.image = image;
1390     info.viewType = view_type;
1391     info.viewType = VK_IMAGE_VIEW_TYPE_2D;
1392     info.format = format;
1393     info.subresourceRange = sr;
1394
1395     if (is_swapchain) {
1396         info.components.r = VK_COMPONENT_SWIZZLE_R;
1397         info.components.g = VK_COMPONENT_SWIZZLE_G;
1398         info.components.b = VK_COMPONENT_SWIZZLE_B;
1399         info.components.a = VK_COMPONENT_SWIZZLE_A;
1400     }
1401
1402     if (vkCreateImageView(ctx->dev, &info, 0, image_view) != VK_SUCCESS) {
1403         fprintf(stderr, "Failed to create image view.\n");
1404         image_view = VK_NULL_HANDLE;
1405
1406         return false;
1407     }
1408
1409     return true;
1410 }
1411
1412 void
1413 vk_destroy_image(struct vk_ctx *ctx, struct vk_image_obj *img_obj)
1414 {
1415     if (img_obj->img != VK_NULL_HANDLE) {
1416         vkDestroyImage(ctx->dev, img_obj->img, 0);
1417         img_obj->img = VK_NULL_HANDLE;
1418     }
1419
1420     if (img_obj->mobj.mem != VK_NULL_HANDLE) {
1421         vkFreeMemory(ctx->dev, img_obj->mobj.mem, 0);
1422         img_obj->mobj.mem = VK_NULL_HANDLE;
1423     }
1424 }
1425
1426 bool
1427 vk_fill_image_props(struct vk_ctx *ctx,
1428                     uint32_t w,
1429                     uint32_t h,
1430                     uint32_t d,
1431                     uint32_t num_samples,
1432                     uint32_t num_levels,
1433                     uint32_t num_layers,
1434                     VkFormat format,
1435                     VkImageTiling tiling,
1436                     VkImageLayout in_layout,
1437                     VkImageLayout end_layout,
1438                     bool is_swapchain,
1439                     bool is_depth,
1440                     bool need_export,
1441                     struct vk_att_props *props)
1442 {
1443     props->w = w;
1444     props->h = h;
1445     props->depth = d;
1446
1447     props->num_samples = num_samples;
1448     props->num_levels = num_levels;
1449     props->num_layers = num_layers;
1450
1451     props->format = format;
1452     props->tiling = tiling;
1453
1454     props->in_layout = in_layout;
1455     props->end_layout = end_layout;
1456
1457     props->is_swapchain = is_swapchain;
1458     props->is_depth = is_depth;
1459     props->need_export = need_export;
1460
1461     if (!are_props_supported(ctx, props))
1462         return false;
1463
1464     return true;
1465 }
1466
1467 struct vk_attachment
1468 vk_create_attachment_from_obj(struct vk_image_obj *obj,
1469                               struct vk_att_props *props)
1470 {
1471     struct vk_attachment att;
1472
1473     att.obj = *obj;
1474     att.props = *props;
1475
1476     return att;
1477 }
1478
1479 struct vk_attachment
1480 vk_create_attachment(VkImage image,
1481                      VkImageView view,
1482                      struct vk_att_props *props)
1483 {
1484     struct vk_attachment att;
1485
1486     att.obj.img = image;
1487     att.obj.img_view = view;
1488     att.props = *props;
1489
1490     memset(&att.obj.mobj, 0, sizeof att.obj.mobj);
1491
1492     return att;
1493 }
1494
1495 bool
1496 vk_create_framebuffer(struct vk_ctx *ctx,
1497                       int width, int height,
1498                       int num_color_atts,
1499                       VkImageView *color_views,
1500                       VkImageView *depth_view,
1501                       VkRenderPass rpass,
1502                       VkFramebuffer *fb)
1503 {
1504     VkFramebufferCreateInfo fb_info;
1505     VkImageView *atts;
1506     int i;
1507     int num_atts = num_color_atts + 1;
1508
1509     atts = malloc(num_atts * sizeof atts[0]);
1510     for (i = 0; i < num_color_atts; i++) {
1511         atts[i] = color_views[i];
1512     }
1513     atts[num_color_atts] = *depth_view;
1514
1515     memset(&fb_info, 0, sizeof fb_info);
1516     fb_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
1517     fb_info.renderPass = rpass;
1518     fb_info.width = width;
1519     fb_info.height = height;
1520     fb_info.layers = 1;
1521     fb_info.attachmentCount = num_atts;
1522     fb_info.pAttachments = atts;
1523
1524     if (vkCreateFramebuffer(ctx->dev, &fb_info, 0, fb) != VK_SUCCESS) {
1525         fprintf(stderr, "Failed to create framebuffer.\n");
1526
1527         fb = VK_NULL_HANDLE;
1528         free(atts);
1529
1530         return false;
1531     }
1532
1533     free(atts);
1534     return true;
1535 }
1536
1537 bool
1538 vk_create_renderer(struct vk_ctx *ctx,
1539                    const char *vs_src,
1540                    unsigned int vs_size,
1541                    const char *fs_src,
1542                    unsigned int fs_size,
1543                    int w, int h,
1544                    uint32_t num_samples,
1545                    bool enable_depth,
1546                    bool enable_stencil,
1547                    int num_color_att,
1548                    struct vk_att_props *color_props,
1549                    struct vk_att_props *depth_props,
1550                    struct vk_vertex_info *vert_info,
1551                    struct vk_renderer *renderer)
1552 {
1553     /* create image views for each attachment */
1554 #if 0
1555     if (!create_attachment_views(ctx, num_color_att, color_att, depth_att))
1556         goto fail;
1557 #endif
1558
1559     VkRenderPass rpass;
1560     if (!vk_create_renderpass(ctx, num_color_att, color_props, depth_props,
1561                               &rpass)) {
1562         goto fail;
1563     }
1564     renderer->renderpass = rpass;
1565
1566     VkShaderModule vs = create_shader_module(ctx, vs_src, vs_size);
1567     if (vs == VK_NULL_HANDLE)
1568         goto fail;
1569     renderer->vs = vs;
1570
1571     VkShaderModule fs = create_shader_module(ctx, fs_src, fs_size);
1572     if (fs == VK_NULL_HANDLE)
1573         goto fail;
1574     renderer->fs = fs;
1575
1576     if (vert_info)
1577         renderer->vertex_info = *vert_info;
1578
1579
1580     /* FIXME this is only for graphics atm */
1581     if(!create_graphics_pipeline(ctx, w, h,
1582                                  num_samples,
1583                                  num_color_att,
1584                                  enable_depth,
1585                                  enable_stencil, renderer))
1586         goto fail;
1587
1588     return true;
1589
1590 fail:
1591     fprintf(stderr, "Failed to create renderer.\n");
1592     vk_destroy_renderer(ctx, renderer);
1593     return false;
1594 }
1595
1596 void
1597 vk_destroy_renderer(struct vk_ctx *ctx,
1598                     struct vk_renderer *renderer)
1599 {
1600     if (renderer->renderpass != VK_NULL_HANDLE) {
1601         vkDestroyRenderPass(ctx->dev, renderer->renderpass, 0);
1602         renderer->renderpass = VK_NULL_HANDLE;
1603     }
1604
1605     if (renderer->vs != VK_NULL_HANDLE) {
1606         vkDestroyShaderModule(ctx->dev, renderer->vs, 0);
1607         renderer->vs = VK_NULL_HANDLE;
1608     }
1609
1610     if (renderer->fs != VK_NULL_HANDLE) {
1611         vkDestroyShaderModule(ctx->dev, renderer->fs, 0);
1612         renderer->fs = VK_NULL_HANDLE;
1613     }
1614
1615     if (renderer->pipeline != VK_NULL_HANDLE) {
1616         vkDestroyPipeline(ctx->dev, renderer->pipeline, 0);
1617         renderer->pipeline = VK_NULL_HANDLE;
1618     }
1619
1620     if (renderer->pipeline_layout != VK_NULL_HANDLE) {
1621         vkDestroyPipelineLayout(ctx->dev, renderer->pipeline_layout, 0);
1622         renderer->pipeline_layout = VK_NULL_HANDLE;
1623     }
1624 }
1625
1626 bool
1627 vk_create_ext_buffer(struct vk_ctx *ctx,
1628                      uint32_t sz,
1629                      VkBufferUsageFlagBits usage,
1630                      struct vk_buf *bo)
1631 {
1632     VkExternalMemoryBufferCreateInfo ext_bo_info;
1633
1634     memset(&ext_bo_info, 0, sizeof ext_bo_info);
1635     ext_bo_info.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO;
1636     ext_bo_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;
1637
1638     if (!vk_create_buffer(ctx, true, sz, usage, &ext_bo_info, bo)) {
1639         fprintf(stderr, "Failed to allocate external buffer.\n");
1640         return false;
1641     }
1642
1643     return true;
1644 }
1645
1646 bool
1647 vk_create_buffer(struct vk_ctx *ctx,
1648                  bool is_external,
1649                  uint32_t sz,
1650                  VkBufferUsageFlagBits usage,
1651                  void *pnext,
1652                  struct vk_buf *bo)
1653 {
1654     VkBufferCreateInfo buf_info;
1655     VkMemoryRequirements mem_reqs;
1656
1657     bo->mobj.mem = VK_NULL_HANDLE;
1658     bo->buf = VK_NULL_HANDLE;
1659
1660     /* VkBufferCreateInfo */
1661     memset(&buf_info, 0, sizeof buf_info);
1662     buf_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
1663     buf_info.size = sz;
1664     buf_info.usage = usage;
1665     buf_info.pNext = pnext;
1666     buf_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
1667
1668     if (vkCreateBuffer(ctx->dev, &buf_info, 0, &bo->buf) != VK_SUCCESS)
1669         goto fail;
1670
1671     /* allocate buffer */
1672     vkGetBufferMemoryRequirements(ctx->dev, bo->buf, &mem_reqs);
1673     /* VK_MEMORY_PROPERTY_HOST_COHERENT_BIT bit specifies that the
1674      * host cache management commands vkFlushMappedMemoryRanges and
1675      * vkInvalidateMappedMemoryRanges are not needed to flush host
1676      * writes to the device or make device writes visible to the
1677      * host, respectively. */
1678     bo->mobj.mem = alloc_memory(ctx, is_external, &mem_reqs, VK_NULL_HANDLE,
1679                                 VK_NULL_HANDLE,
1680                                 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
1681                                 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
1682
1683     if (bo->mobj.mem == VK_NULL_HANDLE)
1684         goto fail;
1685
1686     bo->mobj.mem_sz = sz;
1687
1688     if (vkBindBufferMemory(ctx->dev, bo->buf, bo->mobj.mem, 0) != VK_SUCCESS) {
1689         fprintf(stderr, "Failed to bind buffer memory.\n");
1690         goto fail;
1691     }
1692
1693     return true;
1694
1695 fail:
1696     fprintf(stderr, "Failed to allocate buffer.\n");
1697     vk_destroy_buffer(ctx, bo);
1698     return false;
1699 }
1700
1701 bool
1702 vk_update_buffer_data(struct vk_ctx *ctx,
1703                       void *data,
1704                       uint32_t data_sz,
1705                       struct vk_buf *bo)
1706 {
1707     void *map;
1708
1709     if (vkMapMemory(ctx->dev, bo->mobj.mem, 0, data_sz, 0, &map) != VK_SUCCESS) {
1710         fprintf(stderr, "Failed to map buffer memory.\n");
1711         goto fail;
1712     }
1713
1714     memcpy(map, data, data_sz);
1715
1716     vkUnmapMemory(ctx->dev, bo->mobj.mem);
1717     return true;
1718
1719 fail:
1720     fprintf(stderr, "Failed to update buffer data. Destroying the buffer.\n");
1721     vk_destroy_buffer(ctx, bo);
1722
1723     return false;
1724 }
1725
1726 void
1727 vk_destroy_buffer(struct vk_ctx *ctx,
1728                   struct vk_buf *bo)
1729 {
1730     if (bo->buf != VK_NULL_HANDLE)
1731         vkDestroyBuffer(ctx->dev, bo->buf, 0);
1732
1733     if (bo->mobj.mem != VK_NULL_HANDLE)
1734         vkFreeMemory(ctx->dev, bo->mobj.mem, 0);
1735
1736     bo->mobj.mem_sz = 0;
1737     bo->buf = VK_NULL_HANDLE;
1738     bo->mobj.mem = VK_NULL_HANDLE;
1739 }
1740
1741 bool
1742 vk_create_fence(struct vk_ctx *ctx,
1743                 VkFence *fence)
1744 {
1745     VkFenceCreateInfo finfo;
1746
1747     memset(&finfo, 0, sizeof finfo);
1748     finfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
1749
1750     if (vkCreateFence(ctx->dev, &finfo, 0, fence) != VK_SUCCESS) {
1751         fprintf(stderr, "Failed to create fence.\n");
1752         fence = 0;
1753         return false;
1754     }
1755
1756     return true;
1757 }
1758
1759 VkCommandBuffer
1760 vk_create_cmd_buffer(struct vk_ctx *ctx)
1761 {
1762     VkCommandBuffer cmd_buf;
1763     VkCommandBufferAllocateInfo alloc_info;
1764
1765     memset(&alloc_info, 0, sizeof alloc_info);
1766     alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
1767     alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
1768     alloc_info.commandBufferCount = 1;
1769     alloc_info.commandPool = ctx->cmd_pool;
1770
1771     if (vkAllocateCommandBuffers(ctx->dev, &alloc_info,
1772                                  &cmd_buf) != VK_SUCCESS)
1773         return 0;
1774
1775     return cmd_buf;
1776 }
1777
1778 bool
1779 vk_record_cmd_buffer(struct vk_ctx *ctx,
1780                      VkCommandBuffer cmd_buf,
1781                      struct vk_renderer *renderer,
1782                      struct vk_buf *vbo,
1783                      uint32_t vk_fb_color_count,
1784                      float *vk_fb_color,
1785                      VkFramebuffer fb,
1786                      uint32_t num_atts,
1787                      struct vk_attachment *atts,
1788                      float x, float y,
1789                      float w, float h)
1790 {
1791     VkCommandBufferBeginInfo cmd_begin_info;
1792     VkRenderPassBeginInfo rp_begin_info;
1793     VkRect2D rp_area;
1794     VkClearValue *clear_values; int i;
1795     VkDeviceSize offsets[] = {0};
1796     int num_vertices;
1797     struct vk_dims img_size;
1798     bool create_cmd_buf = false;
1799
1800     assert(vk_fb_color_count == 4);
1801
1802     if (!cmd_buf) {
1803         fprintf(stderr, "Can't record an empty command buffer.\n");
1804         return false;
1805     }
1806
1807     /* VkCommandBufferBeginInfo */
1808     memset(&cmd_begin_info, 0, sizeof cmd_begin_info);
1809     cmd_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
1810     cmd_begin_info.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
1811
1812     /* VkRect2D render area */
1813     memset(&rp_area, 0, sizeof rp_area);
1814     rp_area.extent.width = (uint32_t)w;
1815     rp_area.extent.height = (uint32_t)h;
1816     rp_area.offset.x = x;
1817     rp_area.offset.y = y;
1818
1819     /* VkClearValue */
1820     clear_values = malloc(num_atts * sizeof clear_values[0]);
1821     memset(clear_values, 0, num_atts * sizeof clear_values[0]);
1822
1823     for (i = 0; i < num_atts - 1; i++) {
1824         clear_values[i].color.float32[0] = vk_fb_color[0];
1825         clear_values[i].color.float32[1] = vk_fb_color[1];
1826         clear_values[i].color.float32[2] = vk_fb_color[2];
1827         clear_values[i].color.float32[3] = vk_fb_color[3];
1828     }
1829     clear_values[num_atts - 1].depthStencil.depth = 1.0f;
1830     clear_values[num_atts - 1].depthStencil.stencil = 0;
1831
1832     /* VkRenderPassBeginInfo */
1833     memset(&rp_begin_info, 0, sizeof rp_begin_info);
1834     rp_begin_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
1835     rp_begin_info.renderPass = renderer->renderpass;
1836     rp_begin_info.framebuffer = fb;
1837     rp_begin_info.renderArea = rp_area;
1838     rp_begin_info.clearValueCount = num_atts;
1839     rp_begin_info.pClearValues = clear_values;
1840
1841     vkBeginCommandBuffer(cmd_buf, &cmd_begin_info);
1842     vkCmdBeginRenderPass(cmd_buf, &rp_begin_info, VK_SUBPASS_CONTENTS_INLINE);
1843
1844     viewport.x = x;
1845     viewport.y = y;
1846     viewport.width = w;
1847     viewport.height = h;
1848
1849     scissor.offset.x = x;
1850     scissor.offset.y = y;
1851     scissor.extent.width = w;
1852     scissor.extent.height = h;
1853
1854     vkCmdSetViewport(cmd_buf, 0, 1, &viewport);
1855     vkCmdSetScissor(cmd_buf, 0, 1, &scissor);
1856
1857     img_size.w = (float)w;
1858     img_size.h = (float)h;
1859     vkCmdPushConstants(cmd_buf,
1860                        renderer->pipeline_layout,
1861                        VK_SHADER_STAGE_FRAGMENT_BIT,
1862                        0, sizeof (struct vk_dims),
1863                        &img_size);
1864
1865     if (vbo) {
1866         vkCmdBindVertexBuffers(cmd_buf, 0, 1, &vbo->buf, offsets);
1867     }
1868
1869     vkCmdBindPipeline(cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS,
1870                       renderer->pipeline);
1871
1872     num_vertices = vbo ? renderer->vertex_info.num_verts : 4;
1873     vkCmdDraw(cmd_buf, num_vertices, 1, 0, 0);
1874     vkCmdEndRenderPass(cmd_buf);
1875
1876     free(clear_values);
1877 #if 0
1878     if (atts) {
1879         VkImageMemoryBarrier *barriers =
1880             calloc(num_atts, sizeof(VkImageMemoryBarrier));
1881         VkImageMemoryBarrier *barrier = barriers;
1882         for (uint32_t n = 0; n < num_atts; n++, barrier++) {
1883             struct vk_attachment *att = &atts[n];
1884             VkImageAspectFlagBits depth_stencil_flags =
1885                 get_aspect_from_depth_format(att->props.format);
1886             bool is_depth = (depth_stencil_flags != 0);
1887
1888             /* Insert barrier to mark ownership transfer. */
1889             barrier->sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
1890             barrier->oldLayout = is_depth ?
1891                 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL :
1892                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1893             barrier->newLayout = VK_IMAGE_LAYOUT_GENERAL;
1894             barrier->srcAccessMask = get_access_mask(barrier->oldLayout);
1895             barrier->dstAccessMask = get_access_mask(barrier->newLayout);
1896             barrier->srcQueueFamilyIndex = ctx->qfam_idx;
1897             barrier->dstQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL;
1898             barrier->image = att->obj.img;
1899             barrier->subresourceRange.aspectMask = is_depth ?
1900                 depth_stencil_flags :
1901                 VK_IMAGE_ASPECT_COLOR_BIT;
1902             barrier->subresourceRange.baseMipLevel = 0;
1903             barrier->subresourceRange.levelCount = 1;
1904             barrier->subresourceRange.baseArrayLayer = 0;
1905             barrier->subresourceRange.layerCount = 1;
1906         }
1907
1908         vkCmdPipelineBarrier(cmd_buf,
1909                      VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
1910                      VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
1911                      0,
1912                      0, NULL,
1913                      0, NULL,
1914                      num_atts, barriers);
1915         free(barriers);
1916     }
1917 #endif
1918
1919     vkEndCommandBuffer(cmd_buf);
1920     if (create_cmd_buf) {
1921         vk_destroy_cmd_buffers(ctx, 1, &cmd_buf);
1922     }
1923     return true;
1924 }
1925
1926 void
1927 vk_draw(struct vk_ctx *ctx,
1928         struct vk_semaphores *semaphores,
1929         uint32_t num_buffers,
1930         VkCommandBuffer *cmd_buf)
1931 {
1932     VkSubmitInfo submit_info;
1933     VkPipelineStageFlagBits stage_flags;
1934
1935     /* VkSubmitInfo */
1936     memset(&submit_info, 0, sizeof submit_info);
1937     submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
1938     submit_info.commandBufferCount = num_buffers;
1939     submit_info.pCommandBuffers = cmd_buf;
1940
1941     /* semaphores */
1942     if (semaphores) {
1943         assert(semaphores->frame_ready);
1944         assert(semaphores->frame_done);
1945
1946         /* The subpasses in a render pass automatically take care of
1947          * image layout transitions. These transitions are controlled
1948          * by subpass dependencies, which specify memory and execution
1949          * dependencies between subpasses. We have only a single subpass
1950          * right now, but the operations right before and right after
1951          * this subpass also count as implicit "subpasses". There are two
1952          * built-in dependencies that take care of the transition at the
1953          * start of the render pass and at the end of the render pass,
1954          * but the former does not occur at the right time. It assumes
1955          * that the transition occurs at the start of the pipeline,
1956          * but we haven't acquired the image yet at that point! There are
1957          * two ways to deal with this problem.
1958          *
1959          * We could change the waitStages for the frame_ready semaphore
1960          * to VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT to ensure that the render
1961          * passes don't begin until the image is available, or we can make
1962          * the render pass wait for the
1963          * VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT stage.
1964          */
1965         stage_flags = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
1966
1967         submit_info.pWaitDstStageMask = &stage_flags;
1968         submit_info.waitSemaphoreCount = 1;
1969         submit_info.pWaitSemaphores = &semaphores->frame_done;
1970
1971         submit_info.signalSemaphoreCount = 1;
1972         submit_info.pSignalSemaphores = &semaphores->frame_ready;
1973     }
1974
1975
1976     if (vkQueueSubmit(ctx->queue, 1, &submit_info,
1977                       VK_NULL_HANDLE) != VK_SUCCESS) {
1978         fprintf(stderr, "Failed to submit queue.\n");
1979         abort();
1980     }
1981
1982     if (vkQueueWaitIdle(ctx->queue) != VK_SUCCESS) {
1983         fprintf(stderr, "Failed to wait idle.\n");
1984         abort();
1985     }
1986 }
1987
1988 void
1989 vk_clear_color(struct vk_ctx *ctx,
1990                VkCommandBuffer cmd_buf,
1991                struct vk_buf *vbo,
1992                struct vk_renderer *renderer,
1993                float *vk_fb_color,
1994                uint32_t vk_fb_color_count,
1995                VkFramebuffer fb,
1996                struct vk_semaphores *semaphores,
1997                bool has_wait, bool has_signal,
1998                struct vk_attachment *attachments,
1999                uint32_t n_attachments,
2000                float x, float y,
2001                float w, float h)
2002 {
2003     VkCommandBufferBeginInfo cmd_begin_info;
2004     VkRenderPassBeginInfo rp_begin_info;
2005     VkRect2D rp_area;
2006     VkClearValue clear_values[2];
2007     VkSubmitInfo submit_info;
2008     VkPipelineStageFlagBits stage_flags;
2009     VkImageSubresourceRange img_range;
2010
2011     assert(vk_fb_color_count == 4);
2012
2013     /* VkCommandBufferBeginInfo */
2014     memset(&cmd_begin_info, 0, sizeof cmd_begin_info);
2015     cmd_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
2016     cmd_begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
2017
2018     /* VkRect2D render area */
2019     memset(&rp_area, 0, sizeof rp_area);
2020     rp_area.extent.width = (uint32_t)w;
2021     rp_area.extent.height = (uint32_t)h;
2022     rp_area.offset.x = x;
2023     rp_area.offset.y = y;
2024
2025     /* VkClearValue */
2026     memset(&clear_values[0], 0, sizeof clear_values[0]);
2027     clear_values[0].color.float32[0] = vk_fb_color[0]; /* red */
2028     clear_values[0].color.float32[1] = vk_fb_color[1]; /* green */
2029     clear_values[0].color.float32[2] = vk_fb_color[2]; /* blue */
2030     clear_values[0].color.float32[3] = vk_fb_color[3]; /* alpha */
2031
2032     memset(&clear_values[1], 0, sizeof clear_values[1]);
2033     clear_values[1].depthStencil.depth = 1.0;
2034     clear_values[1].depthStencil.stencil = 0;
2035
2036     /* VkRenderPassBeginInfo */
2037     memset(&rp_begin_info, 0, sizeof rp_begin_info);
2038     rp_begin_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
2039     rp_begin_info.renderPass = renderer->renderpass;
2040     rp_begin_info.framebuffer = fb;
2041     rp_begin_info.renderArea = rp_area;
2042     rp_begin_info.clearValueCount = 2;
2043     rp_begin_info.pClearValues = clear_values;
2044
2045     /* VkSubmitInfo */
2046     stage_flags = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
2047
2048     memset(&submit_info, 0, sizeof submit_info);
2049     submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
2050     submit_info.commandBufferCount = 1;
2051     submit_info.pCommandBuffers = &cmd_buf;
2052
2053     /* FIXME */
2054     if (has_wait) {
2055         submit_info.pWaitDstStageMask = &stage_flags;
2056         submit_info.waitSemaphoreCount = 1;
2057         submit_info.pWaitSemaphores = &semaphores->frame_done;
2058     }
2059
2060     if (has_signal) {
2061         submit_info.signalSemaphoreCount = 1;
2062         submit_info.pSignalSemaphores = &semaphores->frame_ready;
2063     }
2064
2065     img_range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
2066     img_range.baseMipLevel = 0;
2067     img_range.levelCount = 1;
2068     img_range.baseArrayLayer = 0;
2069     img_range.layerCount = 1;
2070
2071     vkBeginCommandBuffer(cmd_buf, &cmd_begin_info);
2072     vk_transition_image_layout(&attachments[0],
2073                                cmd_buf,
2074                                VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
2075                                VK_IMAGE_LAYOUT_GENERAL,
2076                                VK_QUEUE_FAMILY_EXTERNAL,
2077                                ctx->qfam_idx);
2078     vkCmdClearColorImage(cmd_buf,
2079                          attachments[0].obj.img,
2080                          VK_IMAGE_LAYOUT_GENERAL,
2081                          &clear_values[0].color,
2082                          1,
2083                          &img_range);
2084
2085     vkCmdBeginRenderPass(cmd_buf, &rp_begin_info, VK_SUBPASS_CONTENTS_INLINE);
2086
2087     viewport.x = x;
2088     viewport.y = y;
2089     viewport.width = w;
2090     viewport.height = h;
2091
2092     scissor.offset.x = x;
2093     scissor.offset.y = y;
2094     scissor.extent.width = w;
2095     scissor.extent.height = h;
2096
2097     vkCmdSetViewport(cmd_buf, 0, 1, &viewport);
2098     vkCmdSetScissor(cmd_buf, 0, 1, &scissor);
2099
2100     vkCmdBindPipeline(cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS,
2101                       renderer->pipeline);
2102
2103     vkCmdEndRenderPass(cmd_buf);
2104
2105     if (attachments) {
2106         VkImageMemoryBarrier *barriers =
2107             calloc(n_attachments, sizeof(VkImageMemoryBarrier));
2108         VkImageMemoryBarrier *barrier = barriers;
2109
2110         for (uint32_t n = 0; n < n_attachments; n++, barrier++) {
2111             struct vk_attachment *att = &attachments[n];
2112
2113             /* Insert barrier to mark ownership transfer. */
2114             barrier->sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
2115
2116             bool is_depth =
2117                 get_aspect_from_depth_format(att->props.format) != 0;
2118
2119             barrier->oldLayout = is_depth ?
2120                 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL :
2121                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
2122             barrier->newLayout = VK_IMAGE_LAYOUT_GENERAL;
2123             barrier->srcAccessMask = get_access_mask(barrier->oldLayout);
2124             barrier->dstAccessMask = get_access_mask(barrier->newLayout);
2125             barrier->srcQueueFamilyIndex = ctx->qfam_idx;
2126             barrier->dstQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL;
2127             barrier->image = att->obj.img;
2128             barrier->subresourceRange.aspectMask = is_depth ?
2129                 VK_IMAGE_ASPECT_DEPTH_BIT :
2130                 VK_IMAGE_ASPECT_COLOR_BIT;
2131             barrier->subresourceRange.baseMipLevel = 0;
2132             barrier->subresourceRange.levelCount = 1;
2133             barrier->subresourceRange.baseArrayLayer = 0;
2134             barrier->subresourceRange.layerCount = 1;
2135         }
2136
2137         vkCmdPipelineBarrier(cmd_buf,
2138                      VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
2139                      VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
2140                      0,
2141                      0, NULL,
2142                      0, NULL,
2143                      n_attachments, barriers);
2144         free(barriers);
2145     }
2146
2147     vkEndCommandBuffer(cmd_buf);
2148
2149     if (vkQueueSubmit(ctx->queue, 1, &submit_info,
2150                       VK_NULL_HANDLE) != VK_SUCCESS) {
2151         fprintf(stderr, "Failed to submit queue.\n");
2152     }
2153
2154     if (!semaphores && !has_wait && !has_signal)
2155         vkQueueWaitIdle(ctx->queue);
2156 }
2157
2158 void
2159 vk_set_viewport(struct vk_ctx *ctx,
2160                 VkCommandBuffer cmd_buf,
2161                 float x, float y,
2162                 float w, float h,
2163                 float near, float far)
2164 {
2165     VkCommandBufferBeginInfo binfo;
2166     VkViewport viewport;
2167
2168     memset(&viewport, 0, sizeof viewport);
2169     viewport.x = x;
2170     viewport.y = y;
2171     viewport.width = w;
2172     viewport.height = h;
2173     viewport.minDepth = near;
2174     viewport.maxDepth = far;
2175
2176     memset(&binfo, 0, sizeof binfo);
2177     binfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
2178     binfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
2179
2180     vkBeginCommandBuffer(cmd_buf, &binfo);
2181     vkCmdSetViewport(cmd_buf, 0, 1, &viewport);
2182     vkEndCommandBuffer(cmd_buf);
2183 }
2184
2185 bool
2186 vk_create_swapchain(struct vk_ctx *ctx,
2187                     int width, int height,
2188                     bool has_vsync,
2189                     VkSurfaceKHR surf,
2190                     struct vk_swapchain *old_swapchain,
2191                     struct vk_swapchain *swapchain)
2192 {
2193     VkSurfaceCapabilitiesKHR surf_cap;
2194     VkSwapchainCreateInfoKHR s_info;
2195     VkExtent2D extent;
2196     int i, j;
2197
2198     if (!sc_validate_surface(ctx, surf)) {
2199         fprintf(stderr, "Failed to validate surface!\n");
2200         return false;
2201     }
2202
2203     /* get pdevice capabilities
2204      * will need that to determine the swapchain number of images
2205      */
2206     if (vkGetPhysicalDeviceSurfaceCapabilitiesKHR(ctx->pdev, surf, &surf_cap) != VK_SUCCESS) {
2207         fprintf(stderr, "Failed to query surface capabilities.\n");
2208         return false;
2209     }
2210
2211     memset(swapchain, 0, sizeof *swapchain);
2212
2213     memset(&s_info, 0, sizeof s_info);
2214     s_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
2215     s_info.flags = 0;
2216     if (!sc_select_format(ctx, surf, &s_info)) {
2217         fprintf(stderr, "Failed to determine the surface format.\n");
2218         return false;
2219     }
2220     s_info.surface = surf;
2221     s_info.minImageCount = surf_cap.minImageCount;
2222     {
2223         extent.width = width;
2224         extent.height = height;
2225     }
2226     if (!sc_select_supported_present_modes(ctx, surf, has_vsync, &s_info)) {
2227         s_info.presentMode = VK_PRESENT_MODE_FIFO_KHR;
2228     }
2229     s_info.imageExtent = extent;
2230     s_info.imageArrayLayers = 1;
2231     {
2232         s_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
2233         if (surf_cap.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT)
2234             s_info.imageUsage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
2235         if (surf_cap.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT)
2236             s_info.imageUsage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
2237     }
2238     s_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
2239     s_info.queueFamilyIndexCount = ctx->qfam_idx;
2240
2241     /* we might want to use this function when we recreate the swapchain too */
2242     s_info.preTransform = surf_cap.supportedTransforms &
2243                           VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR ?
2244                           VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR :
2245                           surf_cap.currentTransform;
2246
2247     /* we could also write a sc_select_supported_composite_alpha
2248      * later but VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR is universally
2249      * supported */
2250     s_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
2251     s_info.clipped = VK_TRUE;
2252
2253     if (vkCreateSwapchainKHR(ctx->dev, &s_info, 0,
2254                              &swapchain->swapchain) != VK_SUCCESS) {
2255         fprintf(stderr, "Failed to create a swapchain.\n");
2256         return false;
2257     }
2258
2259     if (!swapchain->swapchain) {
2260         fprintf(stderr, "The swapchain seems null\n");
2261         return false;
2262     }
2263
2264     /* get the number of swapchain images and the swapchain images
2265      * and store the new swapchain images
2266      */
2267     vkGetSwapchainImagesKHR(ctx->dev, swapchain->swapchain,
2268                             &swapchain->num_images, 0);
2269     printf("number of swapchain images: %d\n", swapchain->num_images);
2270
2271     /* get the images */
2272     swapchain->images = (VkImage*)alloca(swapchain->num_images * sizeof(VkImage));
2273     vkGetSwapchainImagesKHR(ctx->dev, swapchain->swapchain,
2274                             &swapchain->num_images,
2275                             swapchain->images);
2276
2277     /* create attributes from those images */
2278     swapchain->image_fmt = s_info.imageFormat;
2279
2280     vk_fill_image_props(ctx, width, height, 1,
2281                         1, 1, 1,
2282                         s_info.imageFormat,
2283                         0,
2284                         VK_IMAGE_LAYOUT_UNDEFINED,
2285                         VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
2286                         true, false, false,
2287                         &swapchain->img_props);
2288
2289     swapchain->img_props.usage = s_info.imageUsage;
2290     swapchain->views = malloc(swapchain->num_images * sizeof(VkImageView));
2291
2292     for (i = 0; i < swapchain->num_images; i++) {
2293         if (!vk_create_image_view(ctx, swapchain->images[i],
2294                                   VK_IMAGE_VIEW_TYPE_2D,
2295                                   s_info.imageFormat, true,
2296                                   &swapchain->views[i])) {
2297             fprintf(stderr, "Failed to create image view for image: %d\n", i);
2298             goto fail;
2299         }
2300     }
2301
2302     return true;
2303
2304 fail:
2305     for (j = 0; j < i; j++) {
2306         vkDestroyImageView(ctx->dev, swapchain->views[j], 0);
2307     }
2308     return false;
2309 }
2310
2311 void
2312 vk_destroy_swapchain(struct vk_ctx *ctx,
2313                      struct vk_swapchain *swapchain)
2314 {
2315     int i;
2316     for (i = 0; i < swapchain->num_images; i++) {
2317         vkDestroyImageView(ctx->dev, swapchain->views[i], 0);
2318     }
2319     vkDestroySwapchainKHR(ctx->dev, swapchain->swapchain, 0);
2320 }
2321
2322 bool
2323 vk_queue_present(struct vk_swapchain *swapchain,
2324                  VkQueue queue,
2325                  uint32_t image_idx,
2326                  VkSemaphore wait_sema)
2327 {
2328     VkPresentInfoKHR pinfo;
2329
2330     memset(&pinfo, 0, sizeof pinfo);
2331     pinfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
2332     pinfo.swapchainCount = 1;
2333     pinfo.pSwapchains = &swapchain->swapchain;
2334     pinfo.pImageIndices = &image_idx;
2335
2336     pinfo.pWaitSemaphores = &wait_sema;
2337     pinfo.waitSemaphoreCount = 1;
2338
2339     /* FIXME: add code for VK_KHR_incremental_present_enabled!! */
2340
2341     if (vkQueuePresentKHR(queue, &pinfo) != VK_SUCCESS) {
2342         fprintf(stderr, "Failed to present queue.\n");
2343         return false;
2344     }
2345
2346     return true;
2347 }
2348
2349 void
2350 vk_copy_image_to_buffer(struct vk_ctx *ctx,
2351                         VkCommandBuffer cmd_buf,
2352                         struct vk_attachment *src_img,
2353                         struct vk_buf *dst_bo,
2354                         float w, float h)
2355 {
2356     VkCommandBufferBeginInfo cmd_begin_info;
2357     VkSubmitInfo submit_info;
2358     VkImageAspectFlagBits aspect_mask = get_aspect_from_depth_format(src_img->props.format);
2359
2360     /* VkCommandBufferBeginInfo */
2361     memset(&cmd_begin_info, 0, sizeof cmd_begin_info);
2362     cmd_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
2363     cmd_begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
2364
2365     memset(&submit_info, 0, sizeof submit_info);
2366     submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
2367     submit_info.commandBufferCount = 1;
2368     submit_info.pCommandBuffers = &cmd_buf;
2369
2370     vkBeginCommandBuffer(cmd_buf, &cmd_begin_info);
2371     if (src_img->props.end_layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL && dst_bo) {
2372         vk_transition_image_layout(src_img,
2373                                    cmd_buf,
2374                                    VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
2375                                    VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
2376                                    VK_QUEUE_FAMILY_EXTERNAL,
2377                                    ctx->qfam_idx);
2378
2379         /* copy image to buf */
2380         VkBufferImageCopy copy_region = {
2381             .bufferOffset = 0,
2382             .bufferRowLength = w,
2383             .bufferImageHeight = h,
2384             .imageSubresource = {
2385                 .aspectMask = aspect_mask ? aspect_mask
2386                               : VK_IMAGE_ASPECT_COLOR_BIT,
2387                 .mipLevel = 0,
2388                 .baseArrayLayer = 0,
2389                 .layerCount = 1,
2390             },
2391             .imageOffset = { 0, 0, 0 },
2392             .imageExtent = { w, h, 1 }
2393                 };
2394
2395         vkCmdCopyImageToBuffer(cmd_buf,
2396                                src_img->obj.img,
2397                                VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
2398                                dst_bo->buf, 1, &copy_region);
2399
2400         vk_transition_image_layout(src_img,
2401                                    cmd_buf,
2402                                    VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
2403                                    VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
2404                                    VK_QUEUE_FAMILY_EXTERNAL,
2405                                    ctx->qfam_idx);
2406
2407         VkBufferMemoryBarrier write_finish_buffer_memory_barrier = {
2408             .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
2409             .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
2410             .dstAccessMask = VK_ACCESS_HOST_READ_BIT,
2411             .srcQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL,
2412             .dstQueueFamilyIndex = ctx->qfam_idx,
2413             .buffer = dst_bo->buf,
2414             .offset = 0,
2415             .size = VK_WHOLE_SIZE
2416         };
2417
2418         vkCmdPipelineBarrier(cmd_buf,
2419                              VK_PIPELINE_STAGE_TRANSFER_BIT,
2420                              VK_PIPELINE_STAGE_HOST_BIT,
2421                              (VkDependencyFlags) 0, 0, NULL,
2422                              1, &write_finish_buffer_memory_barrier,
2423                              0, NULL);
2424     }
2425     vkEndCommandBuffer(cmd_buf);
2426
2427     if (vkQueueSubmit(ctx->queue, 1, &submit_info, VK_NULL_HANDLE) != VK_SUCCESS) {
2428         fprintf(stderr, "Failed to submit queue.\n");
2429     }
2430     vkQueueWaitIdle(ctx->queue);
2431 }
2432
2433 bool
2434 vk_create_semaphores(struct vk_ctx *ctx,
2435                      bool is_external,
2436                      struct vk_semaphores *semaphores)
2437 {
2438     VkSemaphoreCreateInfo sema_info;
2439     VkExportSemaphoreCreateInfo exp_sema_info;
2440
2441     if (is_external) {
2442         /* VkExportSemaphoreCreateInfo */
2443         memset(&exp_sema_info, 0, sizeof exp_sema_info);
2444         exp_sema_info.sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO;
2445         exp_sema_info.handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT;
2446     }
2447
2448     /* VkSemaphoreCreateInfo */
2449     memset(&sema_info, 0, sizeof sema_info);
2450     sema_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
2451     sema_info.pNext = is_external ? &exp_sema_info : 0;
2452
2453     if (vkCreateSemaphore(ctx->dev, &sema_info, 0, &semaphores->frame_ready) != VK_SUCCESS) {
2454         fprintf(stderr, "Failed to create semaphore frame_ready.\n");
2455         return false;
2456     }
2457
2458     if (vkCreateSemaphore(ctx->dev, &sema_info, 0, &semaphores->frame_done) != VK_SUCCESS) {
2459         fprintf(stderr, "Failed to create semaphore frame_done.\n");
2460         return false;
2461     }
2462
2463     return true;
2464 }
2465
2466 void
2467 vk_destroy_semaphores(struct vk_ctx *ctx,
2468                       struct vk_semaphores *semaphores)
2469 {
2470     vkDestroySemaphore(ctx->dev, semaphores->frame_ready, 0);
2471     semaphores->frame_ready = VK_NULL_HANDLE;
2472
2473     vkDestroySemaphore(ctx->dev, semaphores->frame_done, 0);
2474     semaphores->frame_done = VK_NULL_HANDLE;
2475 }
2476
2477 bool
2478 vk_create_fences(struct vk_ctx *ctx,
2479                  int num_cmd_buf,
2480                  VkFenceCreateFlagBits flags,
2481                  VkFence *fences)
2482 {
2483     VkFenceCreateInfo f_info;
2484     int i, j = -1;
2485
2486     memset(&f_info, 0, sizeof f_info);
2487     f_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
2488     f_info.flags = flags ? flags : VK_FENCE_CREATE_SIGNALED_BIT;
2489
2490
2491     fences = malloc(num_cmd_buf * sizeof(VkFence));
2492     for (i = 0; i < num_cmd_buf; i++) {
2493         if (vkCreateFence(ctx->dev, &f_info, 0, &fences[i]) != VK_SUCCESS) {
2494             fprintf(stderr, "Failed to create fence number: %d\n", (i + 1));
2495             j = i;
2496             break;
2497         }
2498     }
2499
2500     if (j == i) {
2501         for (i = 0; i < j; i++) {
2502             vkDestroyFence(ctx->dev, fences[i], 0);
2503         }
2504         return false;
2505     }
2506
2507     return true;
2508 }
2509
2510 void
2511 vk_destroy_fences(struct vk_ctx *ctx,
2512                   int num_fences,
2513                   VkFence *fences)
2514 {
2515     int i;
2516     for (i = 0; i < num_fences; i++) {
2517         vkDestroyFence(ctx->dev, fences[i], 0);
2518     }
2519 }
2520
2521 void
2522 vk_transition_image_layout(struct vk_attachment *img_att,
2523                            VkCommandBuffer cmd_buf,
2524                            VkImageLayout old_layout,
2525                            VkImageLayout new_layout,
2526                            uint32_t src_queue_fam_idx,
2527                            uint32_t dst_queue_fam_idx)
2528 {
2529     VkImageMemoryBarrier barrier;
2530     struct vk_att_props props = img_att->props;
2531     VkImageAspectFlagBits aspect_mask = get_aspect_from_depth_format(props.format);
2532
2533     memset(&barrier, 0, sizeof barrier);
2534     barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
2535     barrier.srcAccessMask = get_access_mask(old_layout);
2536     barrier.dstAccessMask = get_access_mask(new_layout);
2537     barrier.oldLayout = old_layout;
2538     barrier.newLayout = new_layout;
2539     barrier.srcQueueFamilyIndex = src_queue_fam_idx;
2540     barrier.dstQueueFamilyIndex = dst_queue_fam_idx;
2541     barrier.image = img_att->obj.img;
2542     barrier.subresourceRange.aspectMask = aspect_mask ? aspect_mask :
2543                                           VK_IMAGE_ASPECT_COLOR_BIT;
2544     barrier.subresourceRange.levelCount = 1;
2545     barrier.subresourceRange.layerCount = 1;
2546
2547     vkCmdPipelineBarrier(cmd_buf,
2548                          get_pipeline_stage_flags(old_layout),
2549                          get_pipeline_stage_flags(new_layout),
2550                          0, 0, VK_NULL_HANDLE, 0, VK_NULL_HANDLE, 1, &barrier);
2551 }