9 static VkViewport viewport;
10 static VkRect2D scissor;
12 /* static functions */
13 static VkSampleCountFlagBits
14 get_num_samples(uint32_t num_samples);
17 enable_validation_layers(VkInstanceCreateInfo *info)
21 VkLayerProperties *layers;
22 static const char *layer_names[] = {
23 "VK_LAYER_KHRONOS_validation",
26 vkEnumerateInstanceLayerProperties(&num_layers, 0);
27 layers = alloca(num_layers * sizeof *layers);
28 vkEnumerateInstanceLayerProperties(&num_layers, layers);
31 printf("Available validation layers:\n");
32 for(i = 0; i < (int)num_layers; i++) {
33 printf(" %s\n", layers[i].layerName);
36 info->ppEnabledLayerNames = layer_names;
37 info->enabledLayerCount = sizeof layer_names / sizeof *layer_names;
39 fprintf(stderr, "Vulkan validation layers not found.\n");
44 fill_uuid(VkPhysicalDevice pdev, uint8_t *deviceUUID, uint8_t *driverUUID)
46 VkPhysicalDeviceIDProperties devProp;
47 VkPhysicalDeviceProperties2 prop2;
49 memset(&devProp, 0, sizeof devProp);
50 devProp.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES;
52 memset(&prop2, 0, sizeof prop2);
53 prop2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
54 prop2.pNext = &devProp;
56 vkGetPhysicalDeviceProperties2(pdev, &prop2);
57 memcpy(deviceUUID, devProp.deviceUUID, VK_UUID_SIZE);
58 memcpy(driverUUID, devProp.driverUUID, VK_UUID_SIZE);
62 create_instance(bool enable_layers)
64 VkApplicationInfo app_info;
65 VkInstanceCreateInfo inst_info;
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;
73 memset(&inst_info, 0, sizeof inst_info);
74 inst_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
75 inst_info.pApplicationInfo = &app_info;
78 enable_validation_layers(&inst_info);
80 if (vkCreateInstance(&inst_info, 0, &inst) != VK_SUCCESS)
81 return VK_NULL_HANDLE;
86 static VkPhysicalDevice
87 select_physical_device(VkInstance inst)
89 VkResult res = VK_SUCCESS;
90 uint32_t dev_count = 0;
91 VkPhysicalDevice *pdevices;
92 VkPhysicalDevice pdevice0;
95 vkEnumeratePhysicalDevices(inst, &dev_count, 0)) != VK_SUCCESS)
96 return VK_NULL_HANDLE;
98 pdevices = malloc(dev_count * sizeof(VkPhysicalDevice));
99 if (vkEnumeratePhysicalDevices(inst, &dev_count, pdevices) !=
101 return VK_NULL_HANDLE;
103 pdevice0 = pdevices[0];
110 create_device(struct vk_ctx *ctx, VkPhysicalDevice pdev)
112 const char *deviceExtensions[] = { "VK_KHR_external_memory_fd",
113 "VK_KHR_external_semaphore_fd" };
114 VkDeviceQueueCreateInfo dev_queue_info;
115 VkDeviceCreateInfo dev_info;
118 VkQueueFamilyProperties *fam_props;
123 vkGetPhysicalDeviceQueueFamilyProperties(pdev, &prop_count, 0);
124 if (prop_count < 0) {
125 fprintf(stderr, "Invalid queue family properties.\n");
126 return VK_NULL_HANDLE;
129 fam_props = malloc(prop_count * sizeof *fam_props);
130 vkGetPhysicalDeviceQueueFamilyProperties(pdev, &prop_count, fam_props);
132 for (i = 0; i < prop_count; i++) {
133 if (fam_props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
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;
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;
153 if (vkCreateDevice(pdev, &dev_info, 0, &dev) != VK_SUCCESS)
154 return VK_NULL_HANDLE;
159 static VkPipelineCache
160 create_pipeline_cache(VkDevice dev)
162 VkPipelineCacheCreateInfo pcache_info;
163 VkPipelineCache pcache;
165 memset(&pcache_info, 0, sizeof pcache_info);
166 pcache_info.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
168 if (vkCreatePipelineCache(dev, &pcache_info, 0, &pcache) != VK_SUCCESS)
169 return VK_NULL_HANDLE;
175 create_cmd_pool(struct vk_ctx *ctx)
177 VkCommandPoolCreateInfo cmd_pool_info;
178 VkCommandPool cmd_pool;
179 VkDevice dev = ctx->dev;
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;
186 if (vkCreateCommandPool(dev, &cmd_pool_info, 0, &cmd_pool) != VK_SUCCESS)
187 return VK_NULL_HANDLE;
193 create_renderpass(struct vk_ctx *ctx,
194 struct vk_image_props *color_img_props,
195 struct vk_image_props *depth_img_props)
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;
203 /* VkAttachmentDescription */
204 memset(att_dsc, 0, num_attachments * sizeof att_dsc[0]);
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;
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;
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;
224 /* VkAttachmentReference */
225 memset(att_rfc, 0, num_attachments * sizeof att_rfc[0]);
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;
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;
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];
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;
249 if (vkCreateRenderPass(ctx->dev, &rpass_info, 0, &rpass) != VK_SUCCESS) {
250 fprintf(stderr, "Failed to create renderpass.\n");
251 rpass = VK_NULL_HANDLE;
257 static inline VkImageType
258 get_image_type(uint32_t h, uint32_t d)
261 return VK_IMAGE_TYPE_1D;
264 return VK_IMAGE_TYPE_3D;
266 return VK_IMAGE_TYPE_2D;
269 static VkImageViewType
270 get_image_view_type(struct vk_image_props *props)
272 VkImageType type = get_image_type(props->h, props->depth);
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;
297 return VK_IMAGE_VIEW_TYPE_2D;
301 static VkImageAspectFlagBits
302 get_aspect_from_depth_format(VkFormat depth_format)
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;
318 return VK_NULL_HANDLE;
321 static VkPipelineStageFlags
322 get_pipeline_stage_flags(const VkImageLayout 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;
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)
353 VkImageSubresourceRange sr;
354 VkImageViewCreateInfo color_info;
355 VkImageViewCreateInfo depth_info;
356 VkFramebufferCreateInfo fb_info;
358 VkImageViewType view_type = get_image_view_type(&color_att->props);
360 if (!color_att->obj.img || !depth_att->obj.img) {
361 fprintf(stderr, "Invalid framebuffer attachment image.\n");
365 /* create image views */
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.
379 sr.levelCount = color_att->props.num_levels;
380 sr.baseArrayLayer = 0;
381 sr.layerCount = color_att->props.num_layers;
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;
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);
399 memset(&sr, 0, sizeof sr);
400 sr.aspectMask = get_aspect_from_depth_format(depth_att->props.format);
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;
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;
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);
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;
429 if (vkCreateFramebuffer(ctx->dev, &fb_info, 0, &renderer->fb) != VK_SUCCESS)
435 fprintf(stderr, "Failed to create framebuffer.\n");
436 renderer->fb = VK_NULL_HANDLE;
439 static VkShaderModule
440 create_shader_module(struct vk_ctx *ctx,
444 VkShaderModuleCreateInfo sm_info;
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;
453 if (vkCreateShaderModule(ctx->dev, &sm_info, 0, &sm) != VK_SUCCESS) {
454 fprintf(stderr, "Failed to create shader module.\n");
462 create_pipeline(struct vk_ctx *ctx,
465 uint32_t num_samples,
468 struct vk_renderer *renderer)
470 VkVertexInputBindingDescription vert_bind_dsc[1];
471 VkVertexInputAttributeDescription vert_att_dsc[1];
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;
485 VkFormatProperties fmt_props;
486 VkPushConstantRange pc_range[1];
488 VkStencilOpState front;
489 VkStencilOpState back;
491 VkPipelineLayout pipeline_layout;
494 /* format of vertex attributes:
495 * we have 2D vectors so we need a RG format:
497 * the stride (distance between 2 consecutive elements)
498 * must be 8 because we use 32 bit floats and
500 format = VK_FORMAT_R32G32_SFLOAT;
501 vkGetPhysicalDeviceFormatProperties(ctx->pdev, format, &fmt_props);
502 assert(fmt_props.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT);
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;
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;
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;
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;
534 viewport.x = viewport.y = 0;
535 viewport.width = width;
536 viewport.height = height;
537 viewport.minDepth = 0;
538 viewport.maxDepth = 1;
540 /* VkRect2D scissor */
541 scissor.offset.x = scissor.offset.y = 0;
542 scissor.extent.width = width;
543 scissor.extent.height = height;
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;
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;
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;
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;
574 memset(&back, 0, sizeof back);
575 back.compareMask = ~0;
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;
584 /* defaults in OpenGL ES 3.1 */
585 ds_info.minDepthBounds = 0;
586 ds_info.maxDepthBounds = 1;
587 /* z buffer, stencil buffer */
589 ds_info.depthTestEnable = VK_TRUE;
590 ds_info.depthWriteEnable = VK_TRUE;
591 ds_info.depthCompareOp = VK_COMPARE_OP_LESS;
593 if (enable_stencil) {
594 ds_info.stencilTestEnable = VK_TRUE;
595 ds_info.depthTestEnable = VK_FALSE;
596 ds_info.depthWriteEnable = VK_TRUE;
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;
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);
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;
626 /* VkPipelineShaderStageCreateInfo */
627 memset(sdr_stages, 0, 2 * sizeof sdr_stages[0]);
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";
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";
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 */
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;
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;
656 renderer->pipeline_layout = pipeline_layout;
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;
673 if (vkCreateGraphicsPipelines(ctx->dev, ctx->cache, 1,
674 &pipeline_info, 0, &renderer->pipeline) !=
676 fprintf(stderr, "Failed to create graphics pipeline.\n");
677 renderer->pipeline = VK_NULL_HANDLE;
681 static VkAccessFlagBits
682 get_access_mask(const VkImageLayout layout)
685 case VK_IMAGE_LAYOUT_UNDEFINED:
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:
716 static VkCommandBuffer
717 create_cmd_buf(VkDevice dev, VkCommandPool cmd_pool)
719 VkCommandBuffer cmd_buf;
720 VkCommandBufferAllocateInfo alloc_info;
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;
728 if (vkAllocateCommandBuffers(dev, &alloc_info, &cmd_buf) != VK_SUCCESS)
729 return VK_NULL_HANDLE;
735 get_memory_type_idx(VkPhysicalDevice pdev,
736 const VkMemoryRequirements *mem_reqs,
737 VkMemoryPropertyFlagBits prop_flags)
739 VkPhysicalDeviceMemoryProperties pdev_mem_props;
742 vkGetPhysicalDeviceMemoryProperties(pdev, &pdev_mem_props);
744 for (i = 0; i < pdev_mem_props.memoryTypeCount; i++) {
745 const VkMemoryType *type = &pdev_mem_props.memoryTypes[i];
747 if ((mem_reqs->memoryTypeBits & (1 << i)) &&
748 (type->propertyFlags & prop_flags) == prop_flags) {
756 static VkSampleCountFlagBits
757 get_num_samples(uint32_t num_samples)
759 switch(num_samples) {
761 return VK_SAMPLE_COUNT_64_BIT;
763 return VK_SAMPLE_COUNT_32_BIT;
765 return VK_SAMPLE_COUNT_16_BIT;
767 return VK_SAMPLE_COUNT_8_BIT;
769 return VK_SAMPLE_COUNT_4_BIT;
771 return VK_SAMPLE_COUNT_2_BIT;
775 fprintf(stderr, "Invalid number of samples in VkSampleCountFlagBits. Using one sample.\n");
778 return VK_SAMPLE_COUNT_1_BIT;
781 static VkDeviceMemory
782 alloc_memory(struct vk_ctx *ctx,
783 const VkMemoryRequirements *mem_reqs,
786 VkMemoryPropertyFlagBits prop_flags)
788 VkExportMemoryAllocateInfo exp_mem_info;
789 VkMemoryAllocateInfo mem_alloc_info;
791 VkMemoryDedicatedAllocateInfoKHR ded_info;
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;
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);
805 if (mem_alloc_info.memoryTypeIndex == UINT32_MAX) {
806 fprintf(stderr, "No suitable memory type index found.\n");
807 return VK_NULL_HANDLE;
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;
816 exp_mem_info.pNext = &ded_info;
819 if (vkAllocateMemory(ctx->dev, &mem_alloc_info, 0, &mem) !=
821 return VK_NULL_HANDLE;
827 alloc_image_memory(struct vk_ctx *ctx, struct vk_image_obj *img_obj)
829 VkMemoryDedicatedRequirements ded_reqs;
830 VkImageMemoryRequirementsInfo2 req_info2;
831 VkMemoryRequirements2 mem_reqs2;
833 memset(&ded_reqs, 0, sizeof ded_reqs);
834 ded_reqs.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS;
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;
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;
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,
851 mem_reqs2.memoryRequirements.memoryTypeBits &
852 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
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");
861 if (vkBindImageMemory(ctx->dev, img_obj->img, img_obj->mobj.mem, 0) != VK_SUCCESS) {
862 fprintf(stderr, "Failed to bind image memory.\n");
870 are_props_supported(struct vk_ctx *ctx, struct vk_image_props *props)
872 VkPhysicalDeviceImageFormatInfo2 img_fmt_info;
873 VkImageFormatProperties2 img_fmt_props;
875 memset(&img_fmt_info, 0, sizeof img_fmt_info);
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;
884 memset(&img_fmt_props, 0, sizeof img_fmt_props);
885 img_fmt_props.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
887 if (vkGetPhysicalDeviceImageFormatProperties2
888 (ctx->pdev, &img_fmt_info, &img_fmt_props) != VK_SUCCESS) {
890 "Unsupported Vulkan format properties.\n");
898 vk_init_ctx(struct vk_ctx *ctx)
900 if ((ctx->inst = create_instance(false)) == VK_NULL_HANDLE) {
901 fprintf(stderr, "Failed to create Vulkan instance.\n");
905 if ((ctx->pdev = select_physical_device(ctx->inst)) == VK_NULL_HANDLE) {
906 fprintf(stderr, "Failed to find suitable physical device.\n");
910 if ((ctx->dev = create_device(ctx, ctx->pdev)) == VK_NULL_HANDLE) {
911 fprintf(stderr, "Failed to create Vulkan device.\n");
915 fill_uuid(ctx->pdev, ctx->deviceUUID, ctx->driverUUID);
924 vk_init_ctx_for_rendering(struct vk_ctx *ctx)
926 if (!vk_init_ctx(ctx)) {
927 fprintf(stderr, "Failed to initialize Vulkan.\n");
931 if ((ctx->cache = create_pipeline_cache(ctx->dev)) == VK_NULL_HANDLE) {
932 fprintf(stderr, "Failed to create pipeline cache.\n");
936 if ((ctx->cmd_pool = create_cmd_pool(ctx)) == VK_NULL_HANDLE) {
937 fprintf(stderr, "Failed to create command pool.\n");
941 if ((ctx->cmd_buf = create_cmd_buf(ctx->dev, ctx->cmd_pool)) ==
943 fprintf(stderr, "Failed to create command buffer.\n");
947 vkGetDeviceQueue(ctx->dev, ctx->qfam_idx, 0, &ctx->queue);
949 fprintf(stderr, "Failed to get command queue.\n");
961 vk_cleanup_ctx(struct vk_ctx *ctx)
963 if (ctx->cmd_buf != VK_NULL_HANDLE)
964 vkFreeCommandBuffers(ctx->dev, ctx->cmd_pool, 1, &ctx->cmd_buf);
966 if (ctx->cmd_pool != VK_NULL_HANDLE)
967 vkDestroyCommandPool(ctx->dev, ctx->cmd_pool, 0);
969 if (ctx->cache != VK_NULL_HANDLE)
970 vkDestroyPipelineCache(ctx->dev, ctx->cache, 0);
972 if (ctx->dev != VK_NULL_HANDLE)
973 vkDestroyDevice(ctx->dev, 0);
975 if (ctx->inst != VK_NULL_HANDLE)
976 vkDestroyInstance(ctx->inst, 0);
980 vk_create_image(struct vk_ctx *ctx,
981 struct vk_image_props *props,
982 struct vk_image_obj *img)
984 VkImageCreateInfo img_info;
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;
1002 if (vkCreateImage(ctx->dev, &img_info, 0, &img->img) != VK_SUCCESS)
1005 if(!alloc_image_memory(ctx, img))
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;
1019 vk_destroy_image(struct vk_ctx *ctx, struct vk_image_obj *img_obj)
1021 if (img_obj->img != VK_NULL_HANDLE) {
1022 vkDestroyImage(ctx->dev, img_obj->img, 0);
1023 img_obj->img = VK_NULL_HANDLE;
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;
1033 vk_fill_ext_image_props(struct vk_ctx *ctx,
1037 uint32_t num_samples,
1038 uint32_t num_levels,
1039 uint32_t num_layers,
1041 VkImageTiling tiling,
1042 VkImageUsageFlagBits usage,
1043 VkImageLayout in_layout,
1044 VkImageLayout end_layout,
1045 struct vk_image_props *props)
1051 props->num_samples = num_samples;
1052 props->num_levels = num_levels;
1053 props->num_layers = num_layers;
1055 props->format = format;
1056 props->usage = usage;
1057 props->tiling = tiling;
1059 props->in_layout = in_layout;
1060 props->end_layout = end_layout;
1062 if (!are_props_supported(ctx, props))
1069 vk_create_renderer(struct vk_ctx *ctx,
1071 unsigned int vs_size,
1073 unsigned int fs_size,
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)
1081 memset(&renderer->vertex_info, 0, sizeof renderer->vertex_info);
1083 renderer->vertex_info = *vert_info;
1085 renderer->renderpass = create_renderpass(ctx, &color_att->props, &depth_att->props);
1086 if (renderer->renderpass == VK_NULL_HANDLE)
1089 create_framebuffer(ctx, color_att, depth_att, renderer);
1090 if (renderer->fb == VK_NULL_HANDLE)
1093 renderer->vs = create_shader_module(ctx, vs_src, vs_size);
1094 if (renderer->vs == VK_NULL_HANDLE)
1097 renderer->fs = create_shader_module(ctx, fs_src, fs_size);
1098 if (renderer->fs == VK_NULL_HANDLE)
1101 create_pipeline(ctx, color_att->props.w, color_att->props.h,
1102 color_att->props.num_samples, enable_depth, enable_stencil, renderer);
1104 if (renderer->pipeline == VK_NULL_HANDLE)
1110 fprintf(stderr, "Failed to create graphics pipeline.\n");
1111 vk_destroy_renderer(ctx, renderer);
1116 vk_destroy_renderer(struct vk_ctx *ctx,
1117 struct vk_renderer *renderer)
1119 if (renderer->renderpass != VK_NULL_HANDLE)
1120 vkDestroyRenderPass(ctx->dev, renderer->renderpass, 0);
1122 if (renderer->vs != VK_NULL_HANDLE)
1123 vkDestroyShaderModule(ctx->dev, renderer->vs, 0);
1125 if (renderer->fs != VK_NULL_HANDLE)
1126 vkDestroyShaderModule(ctx->dev, renderer->fs, 0);
1128 if (renderer->pipeline != VK_NULL_HANDLE)
1129 vkDestroyPipeline(ctx->dev, renderer->pipeline, 0);
1131 if (renderer->fb != VK_NULL_HANDLE)
1132 vkDestroyFramebuffer(ctx->dev, renderer->fb, 0);
1134 if (renderer->pipeline_layout != VK_NULL_HANDLE)
1135 vkDestroyPipelineLayout(ctx->dev, renderer->pipeline_layout, 0);
1139 vk_create_buffer(struct vk_ctx *ctx,
1141 VkBufferUsageFlagBits usage,
1145 VkBufferCreateInfo buf_info;
1146 VkMemoryRequirements mem_reqs;
1148 bo->mobj.mem = VK_NULL_HANDLE;
1149 bo->buf = VK_NULL_HANDLE;
1151 /* VkBufferCreateInfo */
1152 memset(&buf_info, 0, sizeof buf_info);
1153 buf_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
1155 buf_info.usage = usage;
1156 buf_info.pNext = pnext;
1157 buf_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
1159 if (vkCreateBuffer(ctx->dev, &buf_info, 0, &bo->buf) != VK_SUCCESS)
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);
1173 if (bo->mobj.mem == VK_NULL_HANDLE)
1176 bo->mobj.mem_sz = sz;
1178 if (vkBindBufferMemory(ctx->dev, bo->buf, bo->mobj.mem, 0) != VK_SUCCESS) {
1179 fprintf(stderr, "Failed to bind buffer memory.\n");
1186 fprintf(stderr, "Failed to allocate buffer.\n");
1187 vk_destroy_buffer(ctx, bo);
1192 vk_update_buffer_data(struct vk_ctx *ctx,
1199 if (vkMapMemory(ctx->dev, bo->mobj.mem, 0, data_sz, 0, &map) != VK_SUCCESS) {
1200 fprintf(stderr, "Failed to map buffer memory.\n");
1204 memcpy(map, data, data_sz);
1206 vkUnmapMemory(ctx->dev, bo->mobj.mem);
1210 fprintf(stderr, "Failed to update buffer data. Destroying the buffer.\n");
1211 vk_destroy_buffer(ctx, bo);
1217 vk_destroy_buffer(struct vk_ctx *ctx,
1220 if (bo->buf != VK_NULL_HANDLE)
1221 vkDestroyBuffer(ctx->dev, bo->buf, 0);
1223 if (bo->mobj.mem != VK_NULL_HANDLE)
1224 vkFreeMemory(ctx->dev, bo->mobj.mem, 0);
1226 bo->mobj.mem_sz = 0;
1227 bo->buf = VK_NULL_HANDLE;
1228 bo->mobj.mem = VK_NULL_HANDLE;
1232 vk_draw(struct vk_ctx *ctx,
1234 struct vk_renderer *renderer,
1236 uint32_t vk_fb_color_count,
1237 struct vk_semaphores *semaphores,
1238 struct vk_image_att *attachments,
1239 uint32_t n_attachments,
1243 VkCommandBufferBeginInfo cmd_begin_info;
1244 VkRenderPassBeginInfo rp_begin_info;
1246 VkClearValue clear_values[2];
1247 VkSubmitInfo submit_info;
1248 VkDeviceSize offsets[] = {0};
1249 VkPipelineStageFlagBits stage_flags;
1250 struct vk_dims img_size;
1252 assert(vk_fb_color_count == 4);
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;
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;
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 */
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;
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;
1287 stage_flags = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
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;
1296 assert(semaphores->frame_ready);
1297 assert(semaphores->frame_done);
1299 submit_info.pWaitDstStageMask = &stage_flags;
1300 submit_info.waitSemaphoreCount = 1;
1301 submit_info.pWaitSemaphores = &semaphores->frame_done;
1303 submit_info.signalSemaphoreCount = 1;
1304 submit_info.pSignalSemaphores = &semaphores->frame_ready;
1307 vkBeginCommandBuffer(ctx->cmd_buf, &cmd_begin_info);
1308 vkCmdBeginRenderPass(ctx->cmd_buf, &rp_begin_info, VK_SUBPASS_CONTENTS_INLINE);
1313 viewport.height = h;
1315 scissor.offset.x = x;
1316 scissor.offset.y = y;
1317 scissor.extent.width = w;
1318 scissor.extent.height = h;
1320 vkCmdSetViewport(ctx->cmd_buf, 0, 1, &viewport);
1321 vkCmdSetScissor(ctx->cmd_buf, 0, 1, &scissor);
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),
1332 vkCmdBindVertexBuffers(ctx->cmd_buf, 0, 1, &vbo->buf, offsets);
1334 vkCmdBindPipeline(ctx->cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, renderer->pipeline);
1336 int num_vertices = vbo ? renderer->vertex_info.num_verts : 4;
1337 vkCmdDraw(ctx->cmd_buf, num_vertices, 1, 0, 0);
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];
1346 /* Insert barrier to mark ownership transfer. */
1347 barrier->sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
1350 get_aspect_from_depth_format(att->props.format) != VK_NULL_HANDLE;
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;
1368 vkCmdPipelineBarrier(ctx->cmd_buf,
1369 VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
1370 VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
1374 n_attachments, barriers);
1378 vkCmdEndRenderPass(ctx->cmd_buf);
1379 vkEndCommandBuffer(ctx->cmd_buf);
1381 if (vkQueueSubmit(ctx->queue, 1, &submit_info, VK_NULL_HANDLE) != VK_SUCCESS) {
1382 fprintf(stderr, "Failed to submit queue.\n");
1386 vkQueueWaitIdle(ctx->queue);
1390 vk_copy_image_to_buffer(struct vk_ctx *ctx,
1391 struct vk_image_att *src_img,
1392 struct vk_buf *dst_bo,
1395 VkCommandBufferBeginInfo cmd_begin_info;
1396 VkSubmitInfo submit_info;
1397 VkImageAspectFlagBits aspect_mask = get_aspect_from_depth_format(src_img->props.format);
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;
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;
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,
1413 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1414 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1415 VK_QUEUE_FAMILY_EXTERNAL,
1418 /* copy image to buf */
1419 VkBufferImageCopy copy_region = {
1421 .bufferRowLength = w,
1422 .bufferImageHeight = h,
1423 .imageSubresource = {
1424 .aspectMask = aspect_mask ? aspect_mask : VK_IMAGE_ASPECT_COLOR_BIT,
1426 .baseArrayLayer = 0,
1429 .imageOffset = { 0, 0, 0 },
1430 .imageExtent = { w, h, 1 }
1433 vkCmdCopyImageToBuffer(ctx->cmd_buf,
1435 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1436 dst_bo->buf, 1, ©_region);
1438 vk_transition_image_layout(src_img,
1440 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1441 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1442 VK_QUEUE_FAMILY_EXTERNAL,
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,
1453 .size = VK_WHOLE_SIZE
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,
1463 vkEndCommandBuffer(ctx->cmd_buf);
1465 if (vkQueueSubmit(ctx->queue, 1, &submit_info, VK_NULL_HANDLE) != VK_SUCCESS) {
1466 fprintf(stderr, "Failed to submit queue.\n");
1468 vkQueueWaitIdle(ctx->queue);
1472 vk_create_semaphores(struct vk_ctx *ctx,
1473 struct vk_semaphores *semaphores)
1475 VkSemaphoreCreateInfo sema_info;
1476 VkExportSemaphoreCreateInfo exp_sema_info;
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;
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;
1488 if (vkCreateSemaphore(ctx->dev, &sema_info, 0, &semaphores->frame_ready) != VK_SUCCESS) {
1489 fprintf(stderr, "Failed to create semaphore frame_ready.\n");
1493 if (vkCreateSemaphore(ctx->dev, &sema_info, 0, &semaphores->frame_done) != VK_SUCCESS) {
1494 fprintf(stderr, "Failed to create semaphore frame_done.\n");
1502 vk_destroy_semaphores(struct vk_ctx *ctx,
1503 struct vk_semaphores *semaphores)
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);
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)
1519 VkImageMemoryBarrier barrier;
1520 struct vk_image_props props = img_att->props;
1521 VkImageAspectFlagBits aspect_mask = get_aspect_from_depth_format(props.format);
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;
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);