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