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