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