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