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