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