10 static VkViewport viewport;
11 static VkRect2D scissor;
12 static VkPipelineCache pipeline_cache;
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
21 static VkCommandBuffer *command_buffers;
22 static uint32_t num_command_buffers;
25 /* static functions */
27 static VkSampleCountFlagBits
28 get_num_samples(uint32_t num_samples)
32 return VK_SAMPLE_COUNT_64_BIT;
34 return VK_SAMPLE_COUNT_32_BIT;
36 return VK_SAMPLE_COUNT_16_BIT;
38 return VK_SAMPLE_COUNT_8_BIT;
40 return VK_SAMPLE_COUNT_4_BIT;
42 return VK_SAMPLE_COUNT_2_BIT;
46 fprintf(stderr, "Invalid number of samples in VkSampleCountFlagBits. Using one sample.\n");
49 return VK_SAMPLE_COUNT_1_BIT;
52 static VkAccessFlagBits
53 get_access_mask(const VkImageLayout layout)
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
60 case VK_IMAGE_LAYOUT_UNDEFINED:
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:
85 enable_validation_layers(VkInstanceCreateInfo *info)
89 VkLayerProperties *layers;
90 static const char *layer_names[] = {
91 "VK_LAYER_KHRONOS_validation",
94 vkEnumerateInstanceLayerProperties(&num_layers, 0);
95 layers = alloca(num_layers * sizeof *layers);
96 vkEnumerateInstanceLayerProperties(&num_layers, layers);
99 printf("Available validation layers:\n");
100 for(i = 0; i < (int)num_layers; i++) {
101 printf(" %s\n", layers[i].layerName);
104 info->ppEnabledLayerNames = layer_names;
105 info->enabledLayerCount = sizeof layer_names / sizeof *layer_names;
107 fprintf(stderr, "Vulkan validation layers not found.\n");
112 enable_extensions(VkInstanceCreateInfo *info)
114 static const char *ext_names[] = {
115 "VK_KHR_xcb_surface",
119 uint32_t num_extensions;
120 VkExtensionProperties *extensions;
123 vkEnumerateInstanceExtensionProperties(0, &num_extensions, 0);
124 if (!num_extensions) {
125 fprintf(stderr, "No instance extensions found.\n");
129 extensions = alloca(num_extensions * sizeof *extensions);
130 vkEnumerateInstanceExtensionProperties(0, &num_extensions, extensions);
132 printf("Available extensions:\n");
133 for (i = 0; i < num_extensions; i++) {
134 printf(" %s\n", extensions[i].extensionName);
137 info->ppEnabledExtensionNames = ext_names;
138 info->enabledExtensionCount = ARRAY_SIZE(ext_names);
142 create_instance(bool enable_layers)
144 VkApplicationInfo app_info;
145 VkInstanceCreateInfo inst_info;
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;
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;
159 enable_extensions(&inst_info);
161 enable_validation_layers(&inst_info);
164 if (vkCreateInstance(&inst_info, 0, &inst) != VK_SUCCESS)
170 static VkPhysicalDevice
171 select_physical_device(VkInstance inst)
173 VkResult res = VK_SUCCESS;
174 uint32_t dev_count = 0;
175 VkPhysicalDevice *pdevices;
176 VkPhysicalDevice pdevice0;
179 vkEnumeratePhysicalDevices(inst, &dev_count, 0)) != VK_SUCCESS)
182 pdevices = malloc(dev_count * sizeof(VkPhysicalDevice));
183 if (vkEnumeratePhysicalDevices(inst, &dev_count, pdevices) !=
187 pdevice0 = pdevices[0];
194 create_device(struct vk_ctx *ctx, VkPhysicalDevice pdev)
196 const char *deviceExtensions[] = { "VK_KHR_swapchain" };
197 VkDeviceQueueCreateInfo dev_queue_info;
198 VkDeviceCreateInfo dev_info;
201 VkQueueFamilyProperties *fam_props;
206 vkGetPhysicalDeviceQueueFamilyProperties(pdev, &prop_count, 0);
207 if (prop_count < 0) {
208 fprintf(stderr, "Invalid queue family properties.\n");
212 fam_props = malloc(prop_count * sizeof *fam_props);
213 vkGetPhysicalDeviceQueueFamilyProperties(pdev, &prop_count, fam_props);
215 for (i = 0; i < prop_count; i++) {
216 if (fam_props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
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;
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;
236 if (vkCreateDevice(pdev, &dev_info, 0, &dev) != VK_SUCCESS)
243 fill_uuid(VkPhysicalDevice pdev, uint8_t *deviceUUID, uint8_t *driverUUID)
245 VkPhysicalDeviceIDProperties devProp;
246 VkPhysicalDeviceProperties2 prop2;
248 memset(&devProp, 0, sizeof devProp);
249 devProp.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES;
251 memset(&prop2, 0, sizeof prop2);
252 prop2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
253 prop2.pNext = &devProp;
255 vkGetPhysicalDeviceProperties2(pdev, &prop2);
256 memcpy(deviceUUID, devProp.deviceUUID, VK_UUID_SIZE);
257 memcpy(driverUUID, devProp.driverUUID, VK_UUID_SIZE);
261 create_cmd_pool(struct vk_ctx *ctx)
263 VkCommandPoolCreateInfo cmd_pool_info;
264 VkCommandPool cmd_pool;
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;
271 if (vkCreateCommandPool(ctx->dev, &cmd_pool_info, 0, &cmd_pool) != VK_SUCCESS)
277 static VkPipelineCache
278 create_pipeline_cache(struct vk_ctx *ctx)
280 VkPipelineCacheCreateInfo pc_info;
281 VkPipelineCache pcache;
283 memset(&pc_info, 0, sizeof pc_info);
284 pc_info.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
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;
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)
301 VkAttachmentDescription *att_dsc;
302 VkAttachmentReference *att_rfc;
304 /* one subpass for the moment: */
305 VkSubpassDescription subpass_dsc[1];
306 VkSubpassDependency subpass_dep;
308 VkRenderPassCreateInfo rpass_info;
311 uint32_t num_atts = num_color_atts + 1;
312 bool has_layout = depth_props->in_layout != VK_IMAGE_LAYOUT_UNDEFINED;
314 att_dsc = malloc(num_atts * sizeof att_dsc[0]);
315 att_rfc = malloc(num_atts * sizeof att_rfc[0]);
317 memset(att_dsc, 0, num_atts * sizeof att_dsc[0]);
318 memset(att_rfc, 0, num_atts * sizeof att_rfc[0]);
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;
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;
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;
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;
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];
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.
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.
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;
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;
401 if (vkCreateRenderPass(ctx->dev, &rpass_info, 0, renderpass) != VK_SUCCESS) {
402 fprintf(stderr, "Failed to create renderpass.\n");
403 *renderpass = VK_NULL_HANDLE;
417 static inline VkImageType
418 get_image_type(uint32_t h, uint32_t d)
421 return VK_IMAGE_TYPE_1D;
424 return VK_IMAGE_TYPE_3D;
426 return VK_IMAGE_TYPE_2D;
430 static VkImageViewType
431 get_image_view_type(struct vk_att_props *props)
433 VkImageType type = get_image_type(props->h, props->depth);
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;
458 return VK_IMAGE_VIEW_TYPE_2D;
463 static VkImageAspectFlagBits
464 get_aspect_from_depth_format(VkFormat depth_format)
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;
483 static VkPipelineStageFlags
484 get_pipeline_stage_flags(const VkImageLayout 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;
511 create_attachment_views(struct vk_ctx *ctx, int num_color_att,
512 struct vk_attachment *color_att,
513 struct vk_attachment *depth_att)
515 VkImageSubresourceRange sr;
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);
522 memset(&sr, 0, sizeof sr);
523 sr.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
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);
536 create_framebuffer_from_attachments(struct vk_ctx *ctx,
537 int width, int height,
539 struct vk_attachment *color_att,
540 struct vk_attachment *depth_att,
541 struct vk_renderer *renderer)
543 VkFramebufferCreateInfo fb_info;
546 int num_atts = num_color_atts + 1;
548 atts = malloc(num_atts * sizeof atts[0]);
550 for (i = 0; i < num_color_atts; i++) {
551 atts[i] = color_att[i].obj.img_view;
553 atts[num_color_atts] = depth_att->obj.img_view;
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;
561 fb_info.attachmentCount = num_atts;
562 fb_info.pAttachments = atts;
564 if (vkCreateFramebuffer(ctx->dev, &fb_info, 0, &renderer->fb) != VK_SUCCESS) {
565 fprintf(stderr, "Failed to create framebuffer.\n");
567 renderer->fb = VK_NULL_HANDLE;
577 static VkShaderModule
578 create_shader_module(struct vk_ctx *ctx,
582 VkShaderModuleCreateInfo sm_info;
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;
591 if (vkCreateShaderModule(ctx->dev, &sm_info, 0, &sm) != VK_SUCCESS) {
592 fprintf(stderr, "Failed to create shader module.\n");
600 create_graphics_pipeline(struct vk_ctx *ctx,
603 uint32_t num_samples,
604 uint32_t num_color_atts,
607 struct vk_renderer *renderer)
609 VkVertexInputBindingDescription vert_bind_dsc[1];
610 VkVertexInputAttributeDescription vert_att_dsc[1];
612 VkPipelineColorBlendAttachmentState *cb_att_state;
613 VkPipelineVertexInputStateCreateInfo vert_input_info;
614 VkPipelineInputAssemblyStateCreateInfo asm_info;
615 VkPipelineViewportStateCreateInfo viewport_info;
616 VkPipelineRasterizationStateCreateInfo rs_info;
617 VkPipelineMultisampleStateCreateInfo ms_info;
618 VkPipelineDepthStencilStateCreateInfo ds_info;
619 VkPipelineColorBlendStateCreateInfo cb_info;
620 VkPipelineShaderStageCreateInfo sdr_stages[2];
621 VkPipelineLayoutCreateInfo layout_info;
622 VkGraphicsPipelineCreateInfo pipeline_info;
624 VkFormatProperties fmt_props;
625 VkPushConstantRange pc_range[1];
627 VkStencilOpState front;
628 VkStencilOpState back;
630 VkPipelineLayout pipeline_layout;
633 /* format of vertex attributes:
634 * we have 2D vectors so we need a RG format:
636 * the stride (distance between 2 consecutive elements)
637 * must be 8 because we use 32 bit floats and
639 format = VK_FORMAT_R32G32_SFLOAT;
640 vkGetPhysicalDeviceFormatProperties(ctx->pdev, format, &fmt_props);
641 assert(fmt_props.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT);
644 /* VkVertexInputAttributeDescription */
645 memset(&vert_att_dsc, 0, sizeof vert_att_dsc);
646 vert_att_dsc[0].location = 0;
647 vert_att_dsc[0].binding = 0;
648 vert_att_dsc[0].format = format; /* see comment */
649 vert_att_dsc[0].offset = 0;
651 /* VkVertexInputBindingDescription */
652 memset(&vert_bind_dsc, 0, sizeof vert_bind_dsc);
653 vert_bind_dsc[0].binding = 0;
654 vert_bind_dsc[0].stride = stride;
655 vert_bind_dsc[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
657 /* If using vbo, we have setup vertex_info in the renderer. */
658 bool use_vbo = renderer->vertex_info.num_verts > 0;
660 /* VkPipelineVertexInputStateCreateInfo */
661 memset(&vert_input_info, 0, sizeof vert_input_info);
662 vert_input_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
663 vert_input_info.vertexBindingDescriptionCount = use_vbo ? 1 : 0;
664 vert_input_info.pVertexBindingDescriptions = vert_bind_dsc;
665 vert_input_info.vertexAttributeDescriptionCount = use_vbo ? 1 : 0;
666 vert_input_info.pVertexAttributeDescriptions = vert_att_dsc;
668 /* VkPipelineInputAssemblyStateCreateInfo */
669 memset(&asm_info, 0, sizeof asm_info);
670 asm_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
671 asm_info.topology = renderer->vertex_info.topology ?
672 renderer->vertex_info.topology
673 : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
674 asm_info.primitiveRestartEnable = false;
677 viewport.x = viewport.y = 0;
678 viewport.width = width;
679 viewport.height = height;
680 viewport.minDepth = 0;
681 viewport.maxDepth = 1;
683 /* VkRect2D scissor */
684 scissor.offset.x = scissor.offset.y = 0;
685 scissor.extent.width = width;
686 scissor.extent.height = height;
688 /* VkPipelineViewportStateCreateInfo */
689 memset(&viewport_info, 0, sizeof viewport_info);
690 viewport_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
691 viewport_info.viewportCount = 1;
692 viewport_info.pViewports = &viewport;
693 viewport_info.scissorCount = 1;
694 viewport_info.pScissors = &scissor;
696 /* VkPipelineRasterizationStateCreateInfo */
697 memset(&rs_info, 0, sizeof rs_info);
698 rs_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
699 rs_info.polygonMode = VK_POLYGON_MODE_FILL;
700 rs_info.cullMode = VK_CULL_MODE_NONE;
701 rs_info.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
702 rs_info.lineWidth = 1.0;
704 /* VkPipelineMultisampleStateCreateInfo */
705 memset(&ms_info, 0, sizeof ms_info);
706 ms_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
707 ms_info.rasterizationSamples = get_num_samples(num_samples);
709 /* VkStencilOpState */
710 /* The default values for ES are taken by Topi Pohjolainen's code */
711 /* defaults in OpenGL ES 3.1 */
712 memset(&front, 0, sizeof front);
713 front.compareMask = ~0;
714 front.writeMask = ~0;
717 memset(&back, 0, sizeof back);
718 back.compareMask = ~0;
722 /* VkPipelineDepthStencilStateCreateInfo */
723 memset(&ds_info, 0, sizeof ds_info);
724 ds_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
725 ds_info.front = front;
727 /* defaults in OpenGL ES 3.1 */
728 ds_info.minDepthBounds = 0;
729 ds_info.maxDepthBounds = 1;
730 /* z buffer, stencil buffer */
732 ds_info.depthTestEnable = VK_TRUE;
733 ds_info.depthWriteEnable = VK_TRUE;
734 ds_info.depthCompareOp = VK_COMPARE_OP_LESS;
736 if (enable_stencil) {
737 ds_info.stencilTestEnable = VK_TRUE;
738 ds_info.depthTestEnable = VK_FALSE;
739 ds_info.depthWriteEnable = VK_TRUE;
742 /* we only care about the passOp here */
743 ds_info.back.compareOp = VK_COMPARE_OP_ALWAYS;
744 ds_info.back.failOp = VK_STENCIL_OP_REPLACE;
745 ds_info.back.depthFailOp = VK_STENCIL_OP_REPLACE;
746 ds_info.back.passOp = VK_STENCIL_OP_REPLACE;
747 ds_info.back.compareMask = 0xffffffff;
748 ds_info.back.writeMask = 0xffffffff;
749 ds_info.back.reference = 1;
750 ds_info.front = ds_info.back;
752 /* VkPipelineColorBlendAttachmentState */
753 cb_att_state = malloc(num_color_atts * sizeof cb_att_state[0]);
755 fprintf(stderr, "Failed to allocate color blend attachment state for each attachment.\n");
758 memset(cb_att_state, 0, num_color_atts * sizeof cb_att_state[0]);
759 for (i = 0; i < num_color_atts; i++) {
760 cb_att_state[i].colorWriteMask = (VK_COLOR_COMPONENT_R_BIT |
761 VK_COLOR_COMPONENT_G_BIT |
762 VK_COLOR_COMPONENT_B_BIT |
763 VK_COLOR_COMPONENT_A_BIT);
766 /* VkPipelineColorBlendStateCreateInfo */
767 memset(&cb_info, 0, sizeof cb_info);
768 cb_info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
769 cb_info.attachmentCount = num_color_atts;
770 cb_info.pAttachments = cb_att_state;
771 /* default in ES 3.1 */
772 for (i = 0; i < 4; i++) {
773 cb_info.blendConstants[i] = 0.0f;
776 /* VkPipelineShaderStageCreateInfo */
777 memset(sdr_stages, 0, 2 * sizeof sdr_stages[0]);
779 sdr_stages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
780 sdr_stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
781 sdr_stages[0].module = renderer->vs;
782 sdr_stages[0].pName = "main";
784 sdr_stages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
785 sdr_stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
786 sdr_stages[1].module = renderer->fs;
787 sdr_stages[1].pName = "main";
789 /* VkPushConstantRange */
790 memset(pc_range, 0, sizeof pc_range[0]);
791 pc_range[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
792 pc_range[0].size = sizeof (struct vk_dims); /* w, h */
794 /* VkPipelineLayoutCreateInfo */
795 memset(&layout_info, 0, sizeof layout_info);
796 layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
797 layout_info.pushConstantRangeCount = 1;
798 layout_info.pPushConstantRanges = pc_range;
800 if (vkCreatePipelineLayout(ctx->dev, &layout_info,
801 0, &pipeline_layout) != VK_SUCCESS) {
802 fprintf(stderr, "Failed to create pipeline layout\n");
803 renderer->pipeline = VK_NULL_HANDLE;
807 renderer->pipeline_layout = pipeline_layout;
809 /* VkGraphicsPipelineCreateInfo */
810 memset(&pipeline_info, 0, sizeof pipeline_info);
811 pipeline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
812 pipeline_info.layout = pipeline_layout;
813 pipeline_info.renderPass = renderer->renderpass;
814 pipeline_info.pVertexInputState = &vert_input_info;
815 pipeline_info.pInputAssemblyState = &asm_info;
816 pipeline_info.pViewportState = &viewport_info;
817 pipeline_info.pRasterizationState = &rs_info;
818 pipeline_info.pMultisampleState = &ms_info;
819 pipeline_info.pDepthStencilState = &ds_info;
820 pipeline_info.pColorBlendState = &cb_info;
821 pipeline_info.stageCount = 2;
822 pipeline_info.pStages = sdr_stages;
824 if (vkCreateGraphicsPipelines(ctx->dev, 0, 1,
826 &renderer->pipeline) != VK_SUCCESS) {
827 fprintf(stderr, "Failed to create graphics pipeline.\n");
828 renderer->pipeline = VK_NULL_HANDLE;
841 get_memory_type_idx(VkPhysicalDevice pdev,
842 const VkMemoryRequirements *mem_reqs,
843 VkMemoryPropertyFlagBits prop_flags)
845 VkPhysicalDeviceMemoryProperties pdev_mem_props;
848 vkGetPhysicalDeviceMemoryProperties(pdev, &pdev_mem_props);
850 for (i = 0; i < pdev_mem_props.memoryTypeCount; i++) {
851 const VkMemoryType *type = &pdev_mem_props.memoryTypes[i];
853 if ((mem_reqs->memoryTypeBits & (1 << i)) &&
854 (type->propertyFlags & prop_flags) == prop_flags) {
862 static VkDeviceMemory
863 alloc_memory(struct vk_ctx *ctx,
865 const VkMemoryRequirements *mem_reqs,
868 VkMemoryPropertyFlagBits prop_flags)
870 VkExportMemoryAllocateInfo exp_mem_info;
871 VkMemoryAllocateInfo mem_alloc_info;
873 VkMemoryDedicatedAllocateInfoKHR ded_info;
876 memset(&exp_mem_info, 0, sizeof exp_mem_info);
877 exp_mem_info.sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO;
878 exp_mem_info.handleTypes =
879 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
882 memset(&mem_alloc_info, 0, sizeof mem_alloc_info);
883 mem_alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
884 mem_alloc_info.pNext = is_external ? &exp_mem_info : VK_NULL_HANDLE;
885 mem_alloc_info.allocationSize = mem_reqs->size;
886 mem_alloc_info.memoryTypeIndex = get_memory_type_idx(ctx->pdev,
890 if (mem_alloc_info.memoryTypeIndex == UINT32_MAX) {
891 fprintf(stderr, "No suitable memory type index found.\n");
895 if (image || buffer) {
896 memset(&ded_info, 0, sizeof ded_info);
897 ded_info.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO;
898 ded_info.image = image;
899 ded_info.buffer = buffer;
901 exp_mem_info.pNext = &ded_info;
904 if (vkAllocateMemory(ctx->dev, &mem_alloc_info, 0, &mem) !=
912 alloc_image_memory(struct vk_ctx *ctx,
914 struct vk_image_obj *img_obj)
916 VkMemoryDedicatedRequirements ded_reqs;
917 VkImageMemoryRequirementsInfo2 req_info2;
918 VkMemoryRequirements2 mem_reqs2;
920 memset(&ded_reqs, 0, sizeof ded_reqs);
921 ded_reqs.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS;
923 /* VkImageMemoryRequirementsInfo2 */
924 memset(&req_info2, 0, sizeof req_info2);
925 req_info2.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2;
926 req_info2.image = img_obj->img;
928 /* VkMemoryRequirements2 */
929 memset(&mem_reqs2, 0, sizeof mem_reqs2);
930 mem_reqs2.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
931 mem_reqs2.pNext = &ded_reqs;
933 vkGetImageMemoryRequirements2(ctx->dev, &req_info2, &mem_reqs2);
934 img_obj->mobj.mem = alloc_memory(ctx,
936 &mem_reqs2.memoryRequirements,
937 ded_reqs.requiresDedicatedAllocation ?
938 img_obj->img : VK_NULL_HANDLE,
940 mem_reqs2.memoryRequirements.memoryTypeBits &
941 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
943 img_obj->mobj.mem_sz = mem_reqs2.memoryRequirements.size;
944 img_obj->mobj.dedicated = ded_reqs.requiresDedicatedAllocation;
945 if (img_obj->mobj.mem == VK_NULL_HANDLE) {
946 fprintf(stderr, "Failed to allocate image memory.\n");
950 if (vkBindImageMemory(ctx->dev, img_obj->img, img_obj->mobj.mem, 0) !=
952 fprintf(stderr, "Failed to bind image memory.\n");
960 are_props_supported(struct vk_ctx *ctx, struct vk_att_props *props)
962 VkPhysicalDeviceExternalImageFormatInfo ext_img_fmt_info;
963 VkExternalImageFormatProperties ext_img_fmt_props;
966 VkPhysicalDeviceImageFormatInfo2 img_fmt_info;
967 VkImageFormatProperties2 img_fmt_props;
969 VkImageUsageFlagBits all_flags[] = {
970 VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
971 VK_IMAGE_USAGE_TRANSFER_DST_BIT,
972 VK_IMAGE_USAGE_SAMPLED_BIT,
973 VK_IMAGE_USAGE_STORAGE_BIT,
974 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
975 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
976 VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,
977 /* Shouldn't be used together with COLOR, DEPTH_STENCIL
979 * VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
980 * Provided by VK_EXT_fragment_density_map
981 * VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT,
982 * Provided by VK_NV_shading_rate_image
983 * VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV,
984 * Provided by VK_KHR_fragment_shading_rate
985 * VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR,
988 VkImageUsageFlagBits flags = 0;
990 VkExternalMemoryFeatureFlagBits export_feature_flags = props->need_export ?
991 VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT : 0;
992 VkExternalMemoryHandleTypeFlagBits handle_type = props->need_export ?
993 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR : 0;
995 if (props->need_export) {
996 memset(&ext_img_fmt_info, 0, sizeof ext_img_fmt_info);
997 ext_img_fmt_info.sType =
998 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO;
999 ext_img_fmt_info.handleType = handle_type;
1001 memset(&ext_img_fmt_props, 0, sizeof ext_img_fmt_props);
1002 ext_img_fmt_props.sType =
1003 VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES;
1006 memset(&img_fmt_props, 0, sizeof img_fmt_props);
1007 img_fmt_props.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
1008 img_fmt_props.pNext = props->need_export ? &ext_img_fmt_props : 0;
1010 memset(&img_fmt_info, 0, sizeof img_fmt_info);
1011 img_fmt_info.sType =
1012 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2;
1013 img_fmt_info.pNext = props->need_export ? &ext_img_fmt_info : 0;
1014 img_fmt_info.format = props->format;
1015 img_fmt_info.type = VK_IMAGE_TYPE_2D;
1016 img_fmt_info.tiling = props->tiling;
1018 for (i = 0; i < ARRAY_SIZE(all_flags); i++) {
1019 img_fmt_info.usage = all_flags[i];
1020 if (vkGetPhysicalDeviceImageFormatProperties2(ctx->pdev,
1022 &img_fmt_props) == VK_SUCCESS) {
1023 flags |= all_flags[i];
1027 /* usage can't be null */
1029 img_fmt_info.usage = flags;
1031 if (!props->is_swapchain) {
1032 fprintf(stderr, "Unsupported Vulkan format properties: usage.\n");
1035 img_fmt_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
1038 if (vkGetPhysicalDeviceImageFormatProperties2
1039 (ctx->pdev, &img_fmt_info, &img_fmt_props) != VK_SUCCESS) {
1041 "Unsupported Vulkan format properties.\n");
1044 props->usage = flags;
1046 if (props->need_export &&
1047 !(ext_img_fmt_props.externalMemoryProperties.externalMemoryFeatures
1048 & export_feature_flags)) {
1049 fprintf(stderr, "Unsupported Vulkan external memory features.\n");
1056 /* static swapchain / surf related functions */
1059 sc_validate_surface(struct vk_ctx *ctx,
1064 fprintf(stderr, "No surface!\n");
1068 if(vkGetPhysicalDeviceSurfaceSupportKHR(ctx->pdev, ctx->qfam_idx,
1069 surf, &supported) != VK_SUCCESS) {
1070 fprintf(stderr, "Failed to validate surface.\n");
1075 fprintf(stderr, "Invalid surface! Check if the surface with queue family index: %d supports presentation.\n", (int)ctx->qfam_idx);
1083 sc_select_format(struct vk_ctx *ctx,
1085 VkSwapchainCreateInfoKHR *s_info)
1087 VkSurfaceFormatKHR *formats;
1088 uint32_t num_formats;
1090 if (vkGetPhysicalDeviceSurfaceFormatsKHR(ctx->pdev,
1092 &num_formats, 0) != VK_SUCCESS) {
1093 fprintf(stderr, "Failed to get the number of surface formats.\n");
1098 fprintf(stderr, "No surface formats found.\n");
1102 formats = malloc(num_formats * sizeof *formats);
1104 if (vkGetPhysicalDeviceSurfaceFormatsKHR(ctx->pdev, surf, &num_formats,
1105 formats) != VK_SUCCESS) {
1106 fprintf(stderr, "Failed to get the supported surface formats.\n");
1110 if ((num_formats == 1) && (formats[0].format == VK_FORMAT_UNDEFINED)) {
1111 s_info->imageFormat = VK_FORMAT_B8G8R8A8_UNORM;
1112 s_info->imageColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
1114 s_info->imageFormat = formats[0].format;
1115 s_info->imageColorSpace = formats[0].colorSpace;
1123 sc_select_supported_present_modes(struct vk_ctx *ctx,
1126 VkSwapchainCreateInfoKHR *s_info)
1128 VkPresentModeKHR *present_modes;
1129 uint32_t num_present_modes;
1131 /* find supported present modes */
1132 if (vkGetPhysicalDeviceSurfacePresentModesKHR(ctx->pdev, surf,
1133 &num_present_modes, 0) != VK_SUCCESS || !num_present_modes) {
1134 fprintf(stderr, "Failed to get the number of the supported presentation modes.\n");
1138 present_modes = malloc(num_present_modes * sizeof *present_modes);
1139 if (vkGetPhysicalDeviceSurfacePresentModesKHR(ctx->pdev, surf,
1141 present_modes) != VK_SUCCESS) {
1142 fprintf(stderr, "Failed to get the number of supported presentation modes.\n");
1145 if (vkGetPhysicalDeviceSurfacePresentModesKHR(ctx->pdev, surf,
1147 present_modes) != VK_SUCCESS) {
1148 fprintf(stderr, "Failed to get the supported presentation modes.\n");
1152 s_info->presentMode = VK_PRESENT_MODE_FIFO_KHR;
1155 for (i = 0; i < num_present_modes; i++) {
1156 if (present_modes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
1157 s_info->presentMode = present_modes[i];
1160 if (present_modes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR) {
1161 s_info->presentMode = present_modes[i];
1168 free(present_modes);
1172 /* end of static functions */
1174 /* exposed Vulkan functions */
1177 vk_init_ctx(struct vk_ctx *ctx,
1180 if ((ctx->inst = create_instance(enable_layers)) == VK_NULL_HANDLE) {
1181 fprintf(stderr, "Failed to create Vulkan instance.\n");
1185 if ((ctx->pdev = select_physical_device(ctx->inst)) == VK_NULL_HANDLE) {
1186 fprintf(stderr, "Failed to find suitable physical device.\n");
1190 if ((ctx->dev = create_device(ctx, ctx->pdev)) == VK_NULL_HANDLE) {
1191 fprintf(stderr, "Failed to create Vulkan device.\n");
1195 fill_uuid(ctx->pdev, ctx->deviceUUID, ctx->driverUUID);
1199 vk_cleanup_ctx(ctx);
1204 vk_init_ctx_for_rendering(struct vk_ctx *ctx,
1208 if (!vk_init_ctx(ctx, enable_layers)) {
1209 fprintf(stderr, "Failed to initialize Vulkan.\n");
1213 if ((ctx->cmd_pool = create_cmd_pool(ctx)) == VK_NULL_HANDLE) {
1214 fprintf(stderr, "Failed to create command pool.\n");
1218 vkGetDeviceQueue(ctx->dev, ctx->qfam_idx, 0, &ctx->queue);
1220 fprintf(stderr, "Failed to get command queue.\n");
1225 if (!(pipeline_cache = create_pipeline_cache(ctx))) {
1226 fprintf(stderr, "Failed to create pipeline cache.\n");
1234 vk_cleanup_ctx(ctx);
1239 vk_destroy_cmd_buffers(struct vk_ctx *ctx,
1240 uint32_t num_buffers,
1241 VkCommandBuffer *buffers)
1244 for (i = 0; i < num_buffers; i++) {
1245 vkResetCommandBuffer(buffers[i],
1246 VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
1248 vkFreeCommandBuffers(ctx->dev, ctx->cmd_pool, num_buffers, buffers);
1252 vk_cleanup_ctx(struct vk_ctx *ctx)
1254 if (ctx->cmd_pool != VK_NULL_HANDLE) {
1255 vkResetCommandPool(ctx->dev, ctx->cmd_pool,
1256 VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
1257 vkDestroyCommandPool(ctx->dev, ctx->cmd_pool, 0);
1258 ctx->cmd_pool = VK_NULL_HANDLE;
1261 if (pipeline_cache != VK_NULL_HANDLE) {
1262 vkDestroyPipelineCache(ctx->dev, pipeline_cache, 0);
1263 pipeline_cache = VK_NULL_HANDLE;
1266 if (ctx->dev != VK_NULL_HANDLE) {
1267 vkDestroyDevice(ctx->dev, 0);
1268 ctx->dev = VK_NULL_HANDLE;
1271 if (ctx->inst != VK_NULL_HANDLE) {
1272 vkDestroyInstance(ctx->inst, 0);
1273 ctx->inst = VK_NULL_HANDLE;
1278 vk_create_ext_image(struct vk_ctx *ctx,
1279 struct vk_att_props *props,
1280 struct vk_image_obj *img)
1282 VkExternalMemoryImageCreateInfo ext_img_info;
1283 VkImageCreateInfo img_info;
1285 memset(&ext_img_info, 0, sizeof ext_img_info);
1286 ext_img_info.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO;
1287 ext_img_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;
1289 memset(&img_info, 0, sizeof img_info);
1290 img_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
1291 img_info.pNext = &ext_img_info;
1292 img_info.imageType = get_image_type(props->h, props->depth);
1293 img_info.format = props->format;
1294 img_info.extent.width = props->w;
1295 img_info.extent.height = props->h;
1296 img_info.extent.depth = props->depth;
1297 img_info.mipLevels = props->num_levels ? props->num_levels : 1;
1298 img_info.arrayLayers = props->num_layers ?
1299 props->num_layers : VK_SAMPLE_COUNT_1_BIT;
1300 img_info.samples = get_num_samples(props->num_samples);
1301 img_info.tiling = props->tiling;
1302 img_info.usage = props->usage;
1303 img_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
1304 img_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
1305 /* issue 17 of EXT_external_objects
1306 * Required in OpenGL implementations that support
1307 * ARB_texture_view, OES_texture_view, EXT_texture_view,
1308 * or OpenGL 4.3 and above.
1310 img_info.flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
1312 if (vkCreateImage(ctx->dev, &img_info, 0, &img->img) != VK_SUCCESS)
1315 if(!alloc_image_memory(ctx, true, img))
1321 fprintf(stderr, "Failed to create external image.\n");
1322 vk_destroy_image(ctx, img);
1323 img->img = VK_NULL_HANDLE;
1324 img->mobj.mem = VK_NULL_HANDLE;
1329 vk_create_image(struct vk_ctx *ctx,
1330 struct vk_att_props *props,
1331 struct vk_image_obj *img)
1333 VkImageCreateInfo img_info;
1335 memset(&img_info, 0, sizeof img_info);
1336 img_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
1337 img_info.pNext = 0; /* do something if external */
1338 img_info.imageType = get_image_type(props->h, props->depth);
1339 img_info.format = props->format;
1340 img_info.extent.width = props->w;
1341 img_info.extent.height = props->h;
1342 img_info.extent.depth = props->depth;
1343 img_info.mipLevels = props->num_levels ? props->num_levels : 1;
1344 img_info.arrayLayers = props->num_layers ?
1345 props->num_layers : VK_SAMPLE_COUNT_1_BIT;
1346 img_info.samples = get_num_samples(props->num_samples);
1347 img_info.tiling = props->tiling;
1348 img_info.usage = props->usage ?
1349 props->usage : VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1350 img_info.initialLayout = props->in_layout;
1351 img_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
1353 if (vkCreateImage(ctx->dev, &img_info, 0, &img->img) != VK_SUCCESS)
1356 if(!alloc_image_memory(ctx, props->need_export, img))
1362 fprintf(stderr, "Failed to create external image.\n");
1363 vk_destroy_image(ctx, img);
1364 img->img = VK_NULL_HANDLE;
1365 img->mobj.mem = VK_NULL_HANDLE;
1370 vk_create_image_view(struct vk_ctx *ctx,
1372 VkImageViewType view_type,
1375 VkImageView *image_view)
1377 VkImageViewCreateInfo info;
1378 VkImageSubresourceRange sr;
1379 VkImageAspectFlagBits aspect = get_aspect_from_depth_format(format);
1381 /* VkSubresourceRange */
1382 memset(&sr, 0, sizeof sr);
1383 sr.aspectMask = aspect ? aspect : VK_IMAGE_ASPECT_COLOR_BIT;
1387 memset(&info, 0, sizeof info);
1388 info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
1390 info.viewType = view_type;
1391 info.viewType = VK_IMAGE_VIEW_TYPE_2D;
1392 info.format = format;
1393 info.subresourceRange = sr;
1396 info.components.r = VK_COMPONENT_SWIZZLE_R;
1397 info.components.g = VK_COMPONENT_SWIZZLE_G;
1398 info.components.b = VK_COMPONENT_SWIZZLE_B;
1399 info.components.a = VK_COMPONENT_SWIZZLE_A;
1402 if (vkCreateImageView(ctx->dev, &info, 0, image_view) != VK_SUCCESS) {
1403 fprintf(stderr, "Failed to create image view.\n");
1404 image_view = VK_NULL_HANDLE;
1413 vk_destroy_image(struct vk_ctx *ctx, struct vk_image_obj *img_obj)
1415 if (img_obj->img != VK_NULL_HANDLE) {
1416 vkDestroyImage(ctx->dev, img_obj->img, 0);
1417 img_obj->img = VK_NULL_HANDLE;
1420 if (img_obj->mobj.mem != VK_NULL_HANDLE) {
1421 vkFreeMemory(ctx->dev, img_obj->mobj.mem, 0);
1422 img_obj->mobj.mem = VK_NULL_HANDLE;
1427 vk_fill_image_props(struct vk_ctx *ctx,
1431 uint32_t num_samples,
1432 uint32_t num_levels,
1433 uint32_t num_layers,
1435 VkImageTiling tiling,
1436 VkImageLayout in_layout,
1437 VkImageLayout end_layout,
1441 struct vk_att_props *props)
1447 props->num_samples = num_samples;
1448 props->num_levels = num_levels;
1449 props->num_layers = num_layers;
1451 props->format = format;
1452 props->tiling = tiling;
1454 props->in_layout = in_layout;
1455 props->end_layout = end_layout;
1457 props->is_swapchain = is_swapchain;
1458 props->is_depth = is_depth;
1459 props->need_export = need_export;
1461 if (!are_props_supported(ctx, props))
1467 struct vk_attachment
1468 vk_create_attachment_from_obj(struct vk_image_obj *obj,
1469 struct vk_att_props *props)
1471 struct vk_attachment att;
1479 struct vk_attachment
1480 vk_create_attachment(VkImage image,
1482 struct vk_att_props *props)
1484 struct vk_attachment att;
1486 att.obj.img = image;
1487 att.obj.img_view = view;
1490 memset(&att.obj.mobj, 0, sizeof att.obj.mobj);
1496 vk_create_framebuffer(struct vk_ctx *ctx,
1497 int width, int height,
1499 VkImageView *color_views,
1500 VkImageView *depth_view,
1504 VkFramebufferCreateInfo fb_info;
1507 int num_atts = num_color_atts + 1;
1509 atts = malloc(num_atts * sizeof atts[0]);
1510 for (i = 0; i < num_color_atts; i++) {
1511 atts[i] = color_views[i];
1513 atts[num_color_atts] = *depth_view;
1515 memset(&fb_info, 0, sizeof fb_info);
1516 fb_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
1517 fb_info.renderPass = rpass;
1518 fb_info.width = width;
1519 fb_info.height = height;
1521 fb_info.attachmentCount = num_atts;
1522 fb_info.pAttachments = atts;
1524 if (vkCreateFramebuffer(ctx->dev, &fb_info, 0, fb) != VK_SUCCESS) {
1525 fprintf(stderr, "Failed to create framebuffer.\n");
1527 fb = VK_NULL_HANDLE;
1538 vk_create_renderer(struct vk_ctx *ctx,
1540 unsigned int vs_size,
1542 unsigned int fs_size,
1544 uint32_t num_samples,
1546 bool enable_stencil,
1548 struct vk_att_props *color_props,
1549 struct vk_att_props *depth_props,
1550 struct vk_vertex_info *vert_info,
1551 struct vk_renderer *renderer)
1553 /* create image views for each attachment */
1555 if (!create_attachment_views(ctx, num_color_att, color_att, depth_att))
1560 if (!vk_create_renderpass(ctx, num_color_att, color_props, depth_props,
1564 renderer->renderpass = rpass;
1566 VkShaderModule vs = create_shader_module(ctx, vs_src, vs_size);
1567 if (vs == VK_NULL_HANDLE)
1571 VkShaderModule fs = create_shader_module(ctx, fs_src, fs_size);
1572 if (fs == VK_NULL_HANDLE)
1577 renderer->vertex_info = *vert_info;
1580 /* FIXME this is only for graphics atm */
1581 if(!create_graphics_pipeline(ctx, w, h,
1585 enable_stencil, renderer))
1591 fprintf(stderr, "Failed to create renderer.\n");
1592 vk_destroy_renderer(ctx, renderer);
1597 vk_destroy_renderer(struct vk_ctx *ctx,
1598 struct vk_renderer *renderer)
1600 if (renderer->renderpass != VK_NULL_HANDLE) {
1601 vkDestroyRenderPass(ctx->dev, renderer->renderpass, 0);
1602 renderer->renderpass = VK_NULL_HANDLE;
1605 if (renderer->vs != VK_NULL_HANDLE) {
1606 vkDestroyShaderModule(ctx->dev, renderer->vs, 0);
1607 renderer->vs = VK_NULL_HANDLE;
1610 if (renderer->fs != VK_NULL_HANDLE) {
1611 vkDestroyShaderModule(ctx->dev, renderer->fs, 0);
1612 renderer->fs = VK_NULL_HANDLE;
1615 if (renderer->pipeline != VK_NULL_HANDLE) {
1616 vkDestroyPipeline(ctx->dev, renderer->pipeline, 0);
1617 renderer->pipeline = VK_NULL_HANDLE;
1620 if (renderer->pipeline_layout != VK_NULL_HANDLE) {
1621 vkDestroyPipelineLayout(ctx->dev, renderer->pipeline_layout, 0);
1622 renderer->pipeline_layout = VK_NULL_HANDLE;
1627 vk_create_ext_buffer(struct vk_ctx *ctx,
1629 VkBufferUsageFlagBits usage,
1632 VkExternalMemoryBufferCreateInfo ext_bo_info;
1634 memset(&ext_bo_info, 0, sizeof ext_bo_info);
1635 ext_bo_info.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO;
1636 ext_bo_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;
1638 if (!vk_create_buffer(ctx, true, sz, usage, &ext_bo_info, bo)) {
1639 fprintf(stderr, "Failed to allocate external buffer.\n");
1647 vk_create_buffer(struct vk_ctx *ctx,
1650 VkBufferUsageFlagBits usage,
1654 VkBufferCreateInfo buf_info;
1655 VkMemoryRequirements mem_reqs;
1657 bo->mobj.mem = VK_NULL_HANDLE;
1658 bo->buf = VK_NULL_HANDLE;
1660 /* VkBufferCreateInfo */
1661 memset(&buf_info, 0, sizeof buf_info);
1662 buf_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
1664 buf_info.usage = usage;
1665 buf_info.pNext = pnext;
1666 buf_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
1668 if (vkCreateBuffer(ctx->dev, &buf_info, 0, &bo->buf) != VK_SUCCESS)
1671 /* allocate buffer */
1672 vkGetBufferMemoryRequirements(ctx->dev, bo->buf, &mem_reqs);
1673 /* VK_MEMORY_PROPERTY_HOST_COHERENT_BIT bit specifies that the
1674 * host cache management commands vkFlushMappedMemoryRanges and
1675 * vkInvalidateMappedMemoryRanges are not needed to flush host
1676 * writes to the device or make device writes visible to the
1677 * host, respectively. */
1678 bo->mobj.mem = alloc_memory(ctx, is_external, &mem_reqs, VK_NULL_HANDLE,
1680 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
1681 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
1683 if (bo->mobj.mem == VK_NULL_HANDLE)
1686 bo->mobj.mem_sz = sz;
1688 if (vkBindBufferMemory(ctx->dev, bo->buf, bo->mobj.mem, 0) != VK_SUCCESS) {
1689 fprintf(stderr, "Failed to bind buffer memory.\n");
1696 fprintf(stderr, "Failed to allocate buffer.\n");
1697 vk_destroy_buffer(ctx, bo);
1702 vk_update_buffer_data(struct vk_ctx *ctx,
1709 if (vkMapMemory(ctx->dev, bo->mobj.mem, 0, data_sz, 0, &map) != VK_SUCCESS) {
1710 fprintf(stderr, "Failed to map buffer memory.\n");
1714 memcpy(map, data, data_sz);
1716 vkUnmapMemory(ctx->dev, bo->mobj.mem);
1720 fprintf(stderr, "Failed to update buffer data. Destroying the buffer.\n");
1721 vk_destroy_buffer(ctx, bo);
1727 vk_destroy_buffer(struct vk_ctx *ctx,
1730 if (bo->buf != VK_NULL_HANDLE)
1731 vkDestroyBuffer(ctx->dev, bo->buf, 0);
1733 if (bo->mobj.mem != VK_NULL_HANDLE)
1734 vkFreeMemory(ctx->dev, bo->mobj.mem, 0);
1736 bo->mobj.mem_sz = 0;
1737 bo->buf = VK_NULL_HANDLE;
1738 bo->mobj.mem = VK_NULL_HANDLE;
1742 vk_create_fence(struct vk_ctx *ctx,
1745 VkFenceCreateInfo finfo;
1747 memset(&finfo, 0, sizeof finfo);
1748 finfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
1750 if (vkCreateFence(ctx->dev, &finfo, 0, fence) != VK_SUCCESS) {
1751 fprintf(stderr, "Failed to create fence.\n");
1760 vk_create_cmd_buffer(struct vk_ctx *ctx)
1762 VkCommandBuffer cmd_buf;
1763 VkCommandBufferAllocateInfo alloc_info;
1765 memset(&alloc_info, 0, sizeof alloc_info);
1766 alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
1767 alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
1768 alloc_info.commandBufferCount = 1;
1769 alloc_info.commandPool = ctx->cmd_pool;
1771 if (vkAllocateCommandBuffers(ctx->dev, &alloc_info,
1772 &cmd_buf) != VK_SUCCESS)
1779 vk_record_cmd_buffer(struct vk_ctx *ctx,
1780 VkCommandBuffer cmd_buf,
1781 struct vk_renderer *renderer,
1783 uint32_t vk_fb_color_count,
1787 struct vk_attachment *atts,
1791 VkCommandBufferBeginInfo cmd_begin_info;
1792 VkRenderPassBeginInfo rp_begin_info;
1794 VkClearValue *clear_values; int i;
1795 VkDeviceSize offsets[] = {0};
1797 struct vk_dims img_size;
1798 bool create_cmd_buf = false;
1800 assert(vk_fb_color_count == 4);
1803 fprintf(stderr, "Can't record an empty command buffer.\n");
1807 /* VkCommandBufferBeginInfo */
1808 memset(&cmd_begin_info, 0, sizeof cmd_begin_info);
1809 cmd_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
1810 cmd_begin_info.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
1812 /* VkRect2D render area */
1813 memset(&rp_area, 0, sizeof rp_area);
1814 rp_area.extent.width = (uint32_t)w;
1815 rp_area.extent.height = (uint32_t)h;
1816 rp_area.offset.x = x;
1817 rp_area.offset.y = y;
1820 clear_values = malloc(num_atts * sizeof clear_values[0]);
1821 memset(clear_values, 0, num_atts * sizeof clear_values[0]);
1823 for (i = 0; i < num_atts - 1; i++) {
1824 clear_values[i].color.float32[0] = vk_fb_color[0];
1825 clear_values[i].color.float32[1] = vk_fb_color[1];
1826 clear_values[i].color.float32[2] = vk_fb_color[2];
1827 clear_values[i].color.float32[3] = vk_fb_color[3];
1829 clear_values[num_atts - 1].depthStencil.depth = 1.0f;
1830 clear_values[num_atts - 1].depthStencil.stencil = 0;
1832 /* VkRenderPassBeginInfo */
1833 memset(&rp_begin_info, 0, sizeof rp_begin_info);
1834 rp_begin_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
1835 rp_begin_info.renderPass = renderer->renderpass;
1836 rp_begin_info.framebuffer = fb;
1837 rp_begin_info.renderArea = rp_area;
1838 rp_begin_info.clearValueCount = num_atts;
1839 rp_begin_info.pClearValues = clear_values;
1841 vkBeginCommandBuffer(cmd_buf, &cmd_begin_info);
1842 vkCmdBeginRenderPass(cmd_buf, &rp_begin_info, VK_SUBPASS_CONTENTS_INLINE);
1847 viewport.height = h;
1849 scissor.offset.x = x;
1850 scissor.offset.y = y;
1851 scissor.extent.width = w;
1852 scissor.extent.height = h;
1854 vkCmdSetViewport(cmd_buf, 0, 1, &viewport);
1855 vkCmdSetScissor(cmd_buf, 0, 1, &scissor);
1857 img_size.w = (float)w;
1858 img_size.h = (float)h;
1859 vkCmdPushConstants(cmd_buf,
1860 renderer->pipeline_layout,
1861 VK_SHADER_STAGE_FRAGMENT_BIT,
1862 0, sizeof (struct vk_dims),
1866 vkCmdBindVertexBuffers(cmd_buf, 0, 1, &vbo->buf, offsets);
1869 vkCmdBindPipeline(cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS,
1870 renderer->pipeline);
1872 num_vertices = vbo ? renderer->vertex_info.num_verts : 4;
1873 vkCmdDraw(cmd_buf, num_vertices, 1, 0, 0);
1874 vkCmdEndRenderPass(cmd_buf);
1879 VkImageMemoryBarrier *barriers =
1880 calloc(num_atts, sizeof(VkImageMemoryBarrier));
1881 VkImageMemoryBarrier *barrier = barriers;
1882 for (uint32_t n = 0; n < num_atts; n++, barrier++) {
1883 struct vk_attachment *att = &atts[n];
1884 VkImageAspectFlagBits depth_stencil_flags =
1885 get_aspect_from_depth_format(att->props.format);
1886 bool is_depth = (depth_stencil_flags != 0);
1888 /* Insert barrier to mark ownership transfer. */
1889 barrier->sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
1890 barrier->oldLayout = is_depth ?
1891 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL :
1892 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1893 barrier->newLayout = VK_IMAGE_LAYOUT_GENERAL;
1894 barrier->srcAccessMask = get_access_mask(barrier->oldLayout);
1895 barrier->dstAccessMask = get_access_mask(barrier->newLayout);
1896 barrier->srcQueueFamilyIndex = ctx->qfam_idx;
1897 barrier->dstQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL;
1898 barrier->image = att->obj.img;
1899 barrier->subresourceRange.aspectMask = is_depth ?
1900 depth_stencil_flags :
1901 VK_IMAGE_ASPECT_COLOR_BIT;
1902 barrier->subresourceRange.baseMipLevel = 0;
1903 barrier->subresourceRange.levelCount = 1;
1904 barrier->subresourceRange.baseArrayLayer = 0;
1905 barrier->subresourceRange.layerCount = 1;
1908 vkCmdPipelineBarrier(cmd_buf,
1909 VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
1910 VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
1914 num_atts, barriers);
1919 vkEndCommandBuffer(cmd_buf);
1920 if (create_cmd_buf) {
1921 vk_destroy_cmd_buffers(ctx, 1, &cmd_buf);
1927 vk_draw(struct vk_ctx *ctx,
1928 struct vk_semaphores *semaphores,
1929 uint32_t num_buffers,
1930 VkCommandBuffer *cmd_buf)
1932 VkSubmitInfo submit_info;
1933 VkPipelineStageFlagBits stage_flags;
1936 memset(&submit_info, 0, sizeof submit_info);
1937 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
1938 submit_info.commandBufferCount = num_buffers;
1939 submit_info.pCommandBuffers = cmd_buf;
1943 assert(semaphores->frame_ready);
1944 assert(semaphores->frame_done);
1946 /* The subpasses in a render pass automatically take care of
1947 * image layout transitions. These transitions are controlled
1948 * by subpass dependencies, which specify memory and execution
1949 * dependencies between subpasses. We have only a single subpass
1950 * right now, but the operations right before and right after
1951 * this subpass also count as implicit "subpasses". There are two
1952 * built-in dependencies that take care of the transition at the
1953 * start of the render pass and at the end of the render pass,
1954 * but the former does not occur at the right time. It assumes
1955 * that the transition occurs at the start of the pipeline,
1956 * but we haven't acquired the image yet at that point! There are
1957 * two ways to deal with this problem.
1959 * We could change the waitStages for the frame_ready semaphore
1960 * to VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT to ensure that the render
1961 * passes don't begin until the image is available, or we can make
1962 * the render pass wait for the
1963 * VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT stage.
1965 stage_flags = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
1967 submit_info.pWaitDstStageMask = &stage_flags;
1968 submit_info.waitSemaphoreCount = 1;
1969 submit_info.pWaitSemaphores = &semaphores->frame_done;
1971 submit_info.signalSemaphoreCount = 1;
1972 submit_info.pSignalSemaphores = &semaphores->frame_ready;
1976 if (vkQueueSubmit(ctx->queue, 1, &submit_info,
1977 VK_NULL_HANDLE) != VK_SUCCESS) {
1978 fprintf(stderr, "Failed to submit queue.\n");
1982 if (vkQueueWaitIdle(ctx->queue) != VK_SUCCESS) {
1983 fprintf(stderr, "Failed to wait idle.\n");
1989 vk_clear_color(struct vk_ctx *ctx,
1990 VkCommandBuffer cmd_buf,
1992 struct vk_renderer *renderer,
1994 uint32_t vk_fb_color_count,
1996 struct vk_semaphores *semaphores,
1997 bool has_wait, bool has_signal,
1998 struct vk_attachment *attachments,
1999 uint32_t n_attachments,
2003 VkCommandBufferBeginInfo cmd_begin_info;
2004 VkRenderPassBeginInfo rp_begin_info;
2006 VkClearValue clear_values[2];
2007 VkSubmitInfo submit_info;
2008 VkPipelineStageFlagBits stage_flags;
2009 VkImageSubresourceRange img_range;
2011 assert(vk_fb_color_count == 4);
2013 /* VkCommandBufferBeginInfo */
2014 memset(&cmd_begin_info, 0, sizeof cmd_begin_info);
2015 cmd_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
2016 cmd_begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
2018 /* VkRect2D render area */
2019 memset(&rp_area, 0, sizeof rp_area);
2020 rp_area.extent.width = (uint32_t)w;
2021 rp_area.extent.height = (uint32_t)h;
2022 rp_area.offset.x = x;
2023 rp_area.offset.y = y;
2026 memset(&clear_values[0], 0, sizeof clear_values[0]);
2027 clear_values[0].color.float32[0] = vk_fb_color[0]; /* red */
2028 clear_values[0].color.float32[1] = vk_fb_color[1]; /* green */
2029 clear_values[0].color.float32[2] = vk_fb_color[2]; /* blue */
2030 clear_values[0].color.float32[3] = vk_fb_color[3]; /* alpha */
2032 memset(&clear_values[1], 0, sizeof clear_values[1]);
2033 clear_values[1].depthStencil.depth = 1.0;
2034 clear_values[1].depthStencil.stencil = 0;
2036 /* VkRenderPassBeginInfo */
2037 memset(&rp_begin_info, 0, sizeof rp_begin_info);
2038 rp_begin_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
2039 rp_begin_info.renderPass = renderer->renderpass;
2040 rp_begin_info.framebuffer = fb;
2041 rp_begin_info.renderArea = rp_area;
2042 rp_begin_info.clearValueCount = 2;
2043 rp_begin_info.pClearValues = clear_values;
2046 stage_flags = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
2048 memset(&submit_info, 0, sizeof submit_info);
2049 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
2050 submit_info.commandBufferCount = 1;
2051 submit_info.pCommandBuffers = &cmd_buf;
2055 submit_info.pWaitDstStageMask = &stage_flags;
2056 submit_info.waitSemaphoreCount = 1;
2057 submit_info.pWaitSemaphores = &semaphores->frame_done;
2061 submit_info.signalSemaphoreCount = 1;
2062 submit_info.pSignalSemaphores = &semaphores->frame_ready;
2065 img_range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
2066 img_range.baseMipLevel = 0;
2067 img_range.levelCount = 1;
2068 img_range.baseArrayLayer = 0;
2069 img_range.layerCount = 1;
2071 vkBeginCommandBuffer(cmd_buf, &cmd_begin_info);
2072 vk_transition_image_layout(&attachments[0],
2074 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
2075 VK_IMAGE_LAYOUT_GENERAL,
2076 VK_QUEUE_FAMILY_EXTERNAL,
2078 vkCmdClearColorImage(cmd_buf,
2079 attachments[0].obj.img,
2080 VK_IMAGE_LAYOUT_GENERAL,
2081 &clear_values[0].color,
2085 vkCmdBeginRenderPass(cmd_buf, &rp_begin_info, VK_SUBPASS_CONTENTS_INLINE);
2090 viewport.height = h;
2092 scissor.offset.x = x;
2093 scissor.offset.y = y;
2094 scissor.extent.width = w;
2095 scissor.extent.height = h;
2097 vkCmdSetViewport(cmd_buf, 0, 1, &viewport);
2098 vkCmdSetScissor(cmd_buf, 0, 1, &scissor);
2100 vkCmdBindPipeline(cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS,
2101 renderer->pipeline);
2103 vkCmdEndRenderPass(cmd_buf);
2106 VkImageMemoryBarrier *barriers =
2107 calloc(n_attachments, sizeof(VkImageMemoryBarrier));
2108 VkImageMemoryBarrier *barrier = barriers;
2110 for (uint32_t n = 0; n < n_attachments; n++, barrier++) {
2111 struct vk_attachment *att = &attachments[n];
2113 /* Insert barrier to mark ownership transfer. */
2114 barrier->sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
2117 get_aspect_from_depth_format(att->props.format) != 0;
2119 barrier->oldLayout = is_depth ?
2120 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL :
2121 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
2122 barrier->newLayout = VK_IMAGE_LAYOUT_GENERAL;
2123 barrier->srcAccessMask = get_access_mask(barrier->oldLayout);
2124 barrier->dstAccessMask = get_access_mask(barrier->newLayout);
2125 barrier->srcQueueFamilyIndex = ctx->qfam_idx;
2126 barrier->dstQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL;
2127 barrier->image = att->obj.img;
2128 barrier->subresourceRange.aspectMask = is_depth ?
2129 VK_IMAGE_ASPECT_DEPTH_BIT :
2130 VK_IMAGE_ASPECT_COLOR_BIT;
2131 barrier->subresourceRange.baseMipLevel = 0;
2132 barrier->subresourceRange.levelCount = 1;
2133 barrier->subresourceRange.baseArrayLayer = 0;
2134 barrier->subresourceRange.layerCount = 1;
2137 vkCmdPipelineBarrier(cmd_buf,
2138 VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
2139 VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
2143 n_attachments, barriers);
2147 vkEndCommandBuffer(cmd_buf);
2149 if (vkQueueSubmit(ctx->queue, 1, &submit_info,
2150 VK_NULL_HANDLE) != VK_SUCCESS) {
2151 fprintf(stderr, "Failed to submit queue.\n");
2154 if (!semaphores && !has_wait && !has_signal)
2155 vkQueueWaitIdle(ctx->queue);
2159 vk_set_viewport(struct vk_ctx *ctx,
2160 VkCommandBuffer cmd_buf,
2163 float near, float far)
2165 VkCommandBufferBeginInfo binfo;
2166 VkViewport viewport;
2168 memset(&viewport, 0, sizeof viewport);
2172 viewport.height = h;
2173 viewport.minDepth = near;
2174 viewport.maxDepth = far;
2176 memset(&binfo, 0, sizeof binfo);
2177 binfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
2178 binfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
2180 vkBeginCommandBuffer(cmd_buf, &binfo);
2181 vkCmdSetViewport(cmd_buf, 0, 1, &viewport);
2182 vkEndCommandBuffer(cmd_buf);
2186 vk_create_swapchain(struct vk_ctx *ctx,
2187 int width, int height,
2190 struct vk_swapchain *old_swapchain,
2191 struct vk_swapchain *swapchain)
2193 VkSurfaceCapabilitiesKHR surf_cap;
2194 VkSwapchainCreateInfoKHR s_info;
2198 if (!sc_validate_surface(ctx, surf)) {
2199 fprintf(stderr, "Failed to validate surface!\n");
2203 /* get pdevice capabilities
2204 * will need that to determine the swapchain number of images
2206 if (vkGetPhysicalDeviceSurfaceCapabilitiesKHR(ctx->pdev, surf, &surf_cap) != VK_SUCCESS) {
2207 fprintf(stderr, "Failed to query surface capabilities.\n");
2211 memset(swapchain, 0, sizeof *swapchain);
2213 memset(&s_info, 0, sizeof s_info);
2214 s_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
2216 if (!sc_select_format(ctx, surf, &s_info)) {
2217 fprintf(stderr, "Failed to determine the surface format.\n");
2220 s_info.surface = surf;
2221 s_info.minImageCount = surf_cap.minImageCount;
2223 extent.width = width;
2224 extent.height = height;
2226 if (!sc_select_supported_present_modes(ctx, surf, has_vsync, &s_info)) {
2227 s_info.presentMode = VK_PRESENT_MODE_FIFO_KHR;
2229 s_info.imageExtent = extent;
2230 s_info.imageArrayLayers = 1;
2232 s_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
2233 if (surf_cap.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT)
2234 s_info.imageUsage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
2235 if (surf_cap.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT)
2236 s_info.imageUsage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
2238 s_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
2239 s_info.queueFamilyIndexCount = ctx->qfam_idx;
2241 /* we might want to use this function when we recreate the swapchain too */
2242 s_info.preTransform = surf_cap.supportedTransforms &
2243 VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR ?
2244 VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR :
2245 surf_cap.currentTransform;
2247 /* we could also write a sc_select_supported_composite_alpha
2248 * later but VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR is universally
2250 s_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
2251 s_info.clipped = VK_TRUE;
2253 if (vkCreateSwapchainKHR(ctx->dev, &s_info, 0,
2254 &swapchain->swapchain) != VK_SUCCESS) {
2255 fprintf(stderr, "Failed to create a swapchain.\n");
2259 if (!swapchain->swapchain) {
2260 fprintf(stderr, "The swapchain seems null\n");
2264 /* get the number of swapchain images and the swapchain images
2265 * and store the new swapchain images
2267 vkGetSwapchainImagesKHR(ctx->dev, swapchain->swapchain,
2268 &swapchain->num_images, 0);
2269 printf("number of swapchain images: %d\n", swapchain->num_images);
2271 /* get the images */
2272 swapchain->images = (VkImage*)alloca(swapchain->num_images * sizeof(VkImage));
2273 vkGetSwapchainImagesKHR(ctx->dev, swapchain->swapchain,
2274 &swapchain->num_images,
2277 /* create attributes from those images */
2278 swapchain->image_fmt = s_info.imageFormat;
2280 vk_fill_image_props(ctx, width, height, 1,
2284 VK_IMAGE_LAYOUT_UNDEFINED,
2285 VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
2287 &swapchain->img_props);
2289 swapchain->img_props.usage = s_info.imageUsage;
2290 swapchain->views = malloc(swapchain->num_images * sizeof(VkImageView));
2292 for (i = 0; i < swapchain->num_images; i++) {
2293 if (!vk_create_image_view(ctx, swapchain->images[i],
2294 VK_IMAGE_VIEW_TYPE_2D,
2295 s_info.imageFormat, true,
2296 &swapchain->views[i])) {
2297 fprintf(stderr, "Failed to create image view for image: %d\n", i);
2305 for (j = 0; j < i; j++) {
2306 vkDestroyImageView(ctx->dev, swapchain->views[j], 0);
2312 vk_destroy_swapchain(struct vk_ctx *ctx,
2313 struct vk_swapchain *swapchain)
2316 for (i = 0; i < swapchain->num_images; i++) {
2317 vkDestroyImageView(ctx->dev, swapchain->views[i], 0);
2319 vkDestroySwapchainKHR(ctx->dev, swapchain->swapchain, 0);
2323 vk_queue_present(struct vk_swapchain *swapchain,
2326 VkSemaphore wait_sema)
2328 VkPresentInfoKHR pinfo;
2330 memset(&pinfo, 0, sizeof pinfo);
2331 pinfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
2332 pinfo.swapchainCount = 1;
2333 pinfo.pSwapchains = &swapchain->swapchain;
2334 pinfo.pImageIndices = &image_idx;
2336 pinfo.pWaitSemaphores = &wait_sema;
2337 pinfo.waitSemaphoreCount = 1;
2339 /* FIXME: add code for VK_KHR_incremental_present_enabled!! */
2341 if (vkQueuePresentKHR(queue, &pinfo) != VK_SUCCESS) {
2342 fprintf(stderr, "Failed to present queue.\n");
2350 vk_copy_image_to_buffer(struct vk_ctx *ctx,
2351 VkCommandBuffer cmd_buf,
2352 struct vk_attachment *src_img,
2353 struct vk_buf *dst_bo,
2356 VkCommandBufferBeginInfo cmd_begin_info;
2357 VkSubmitInfo submit_info;
2358 VkImageAspectFlagBits aspect_mask = get_aspect_from_depth_format(src_img->props.format);
2360 /* VkCommandBufferBeginInfo */
2361 memset(&cmd_begin_info, 0, sizeof cmd_begin_info);
2362 cmd_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
2363 cmd_begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
2365 memset(&submit_info, 0, sizeof submit_info);
2366 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
2367 submit_info.commandBufferCount = 1;
2368 submit_info.pCommandBuffers = &cmd_buf;
2370 vkBeginCommandBuffer(cmd_buf, &cmd_begin_info);
2371 if (src_img->props.end_layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL && dst_bo) {
2372 vk_transition_image_layout(src_img,
2374 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
2375 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
2376 VK_QUEUE_FAMILY_EXTERNAL,
2379 /* copy image to buf */
2380 VkBufferImageCopy copy_region = {
2382 .bufferRowLength = w,
2383 .bufferImageHeight = h,
2384 .imageSubresource = {
2385 .aspectMask = aspect_mask ? aspect_mask
2386 : VK_IMAGE_ASPECT_COLOR_BIT,
2388 .baseArrayLayer = 0,
2391 .imageOffset = { 0, 0, 0 },
2392 .imageExtent = { w, h, 1 }
2395 vkCmdCopyImageToBuffer(cmd_buf,
2397 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
2398 dst_bo->buf, 1, ©_region);
2400 vk_transition_image_layout(src_img,
2402 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
2403 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
2404 VK_QUEUE_FAMILY_EXTERNAL,
2407 VkBufferMemoryBarrier write_finish_buffer_memory_barrier = {
2408 .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
2409 .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
2410 .dstAccessMask = VK_ACCESS_HOST_READ_BIT,
2411 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL,
2412 .dstQueueFamilyIndex = ctx->qfam_idx,
2413 .buffer = dst_bo->buf,
2415 .size = VK_WHOLE_SIZE
2418 vkCmdPipelineBarrier(cmd_buf,
2419 VK_PIPELINE_STAGE_TRANSFER_BIT,
2420 VK_PIPELINE_STAGE_HOST_BIT,
2421 (VkDependencyFlags) 0, 0, NULL,
2422 1, &write_finish_buffer_memory_barrier,
2425 vkEndCommandBuffer(cmd_buf);
2427 if (vkQueueSubmit(ctx->queue, 1, &submit_info, VK_NULL_HANDLE) != VK_SUCCESS) {
2428 fprintf(stderr, "Failed to submit queue.\n");
2430 vkQueueWaitIdle(ctx->queue);
2434 vk_create_semaphores(struct vk_ctx *ctx,
2436 struct vk_semaphores *semaphores)
2438 VkSemaphoreCreateInfo sema_info;
2439 VkExportSemaphoreCreateInfo exp_sema_info;
2442 /* VkExportSemaphoreCreateInfo */
2443 memset(&exp_sema_info, 0, sizeof exp_sema_info);
2444 exp_sema_info.sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO;
2445 exp_sema_info.handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT;
2448 /* VkSemaphoreCreateInfo */
2449 memset(&sema_info, 0, sizeof sema_info);
2450 sema_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
2451 sema_info.pNext = is_external ? &exp_sema_info : 0;
2453 if (vkCreateSemaphore(ctx->dev, &sema_info, 0, &semaphores->frame_ready) != VK_SUCCESS) {
2454 fprintf(stderr, "Failed to create semaphore frame_ready.\n");
2458 if (vkCreateSemaphore(ctx->dev, &sema_info, 0, &semaphores->frame_done) != VK_SUCCESS) {
2459 fprintf(stderr, "Failed to create semaphore frame_done.\n");
2467 vk_destroy_semaphores(struct vk_ctx *ctx,
2468 struct vk_semaphores *semaphores)
2470 vkDestroySemaphore(ctx->dev, semaphores->frame_ready, 0);
2471 semaphores->frame_ready = VK_NULL_HANDLE;
2473 vkDestroySemaphore(ctx->dev, semaphores->frame_done, 0);
2474 semaphores->frame_done = VK_NULL_HANDLE;
2478 vk_create_fences(struct vk_ctx *ctx,
2480 VkFenceCreateFlagBits flags,
2483 VkFenceCreateInfo f_info;
2486 memset(&f_info, 0, sizeof f_info);
2487 f_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
2488 f_info.flags = flags ? flags : VK_FENCE_CREATE_SIGNALED_BIT;
2491 fences = malloc(num_cmd_buf * sizeof(VkFence));
2492 for (i = 0; i < num_cmd_buf; i++) {
2493 if (vkCreateFence(ctx->dev, &f_info, 0, &fences[i]) != VK_SUCCESS) {
2494 fprintf(stderr, "Failed to create fence number: %d\n", (i + 1));
2501 for (i = 0; i < j; i++) {
2502 vkDestroyFence(ctx->dev, fences[i], 0);
2511 vk_destroy_fences(struct vk_ctx *ctx,
2516 for (i = 0; i < num_fences; i++) {
2517 vkDestroyFence(ctx->dev, fences[i], 0);
2522 vk_transition_image_layout(struct vk_attachment *img_att,
2523 VkCommandBuffer cmd_buf,
2524 VkImageLayout old_layout,
2525 VkImageLayout new_layout,
2526 uint32_t src_queue_fam_idx,
2527 uint32_t dst_queue_fam_idx)
2529 VkImageMemoryBarrier barrier;
2530 struct vk_att_props props = img_att->props;
2531 VkImageAspectFlagBits aspect_mask = get_aspect_from_depth_format(props.format);
2533 memset(&barrier, 0, sizeof barrier);
2534 barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
2535 barrier.srcAccessMask = get_access_mask(old_layout);
2536 barrier.dstAccessMask = get_access_mask(new_layout);
2537 barrier.oldLayout = old_layout;
2538 barrier.newLayout = new_layout;
2539 barrier.srcQueueFamilyIndex = src_queue_fam_idx;
2540 barrier.dstQueueFamilyIndex = dst_queue_fam_idx;
2541 barrier.image = img_att->obj.img;
2542 barrier.subresourceRange.aspectMask = aspect_mask ? aspect_mask :
2543 VK_IMAGE_ASPECT_COLOR_BIT;
2544 barrier.subresourceRange.levelCount = 1;
2545 barrier.subresourceRange.layerCount = 1;
2547 vkCmdPipelineBarrier(cmd_buf,
2548 get_pipeline_stage_flags(old_layout),
2549 get_pipeline_stage_flags(new_layout),
2550 0, 0, VK_NULL_HANDLE, 0, VK_NULL_HANDLE, 1, &barrier);