2 * Copyright © 2020 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
24 * Eleni Maria Stea <estea@igalia.com>
25 * Juan A. Suarez Romero <jasuarez@igalia.com>
26 * Topi Pohjolainen <topi.pohjolainen@intel.com>
31 #ifndef VK_NULL_HANDLE
32 #define VK_NULL_HANDLE 0
35 /* static variables */
36 static VkViewport viewport
;
37 static VkRect2D scissor
;
39 /* static functions */
40 static VkSampleCountFlagBits
41 get_num_samples(uint32_t num_samples
);
43 /* Vulkan static functions */
44 static VkAccessFlagBits
45 get_access_mask(const VkImageLayout layout
)
47 /* dstAccessMask of barriers must be supported from the pipeline
48 * stage, see also access scopes and this table:
49 * https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#synchronization-access-types-supported
52 case VK_IMAGE_LAYOUT_UNDEFINED
:
54 case VK_IMAGE_LAYOUT_GENERAL
:
55 return VK_ACCESS_MEMORY_READ_BIT
| VK_ACCESS_MEMORY_WRITE_BIT
;
56 case VK_IMAGE_LAYOUT_PREINITIALIZED
:
57 return VK_ACCESS_HOST_WRITE_BIT
;
58 case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
:
59 return VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
|
60 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
;
61 case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
:
62 return VK_ACCESS_SHADER_READ_BIT
| VK_ACCESS_INPUT_ATTACHMENT_READ_BIT
;
63 case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
:
64 return VK_ACCESS_TRANSFER_READ_BIT
;
65 case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
:
66 return VK_ACCESS_TRANSFER_WRITE_BIT
;
67 case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
:
77 enable_validation_layers(VkInstanceCreateInfo
*info
)
81 VkLayerProperties
*layers
;
82 static const char *layer_names
[] = {
83 "VK_LAYER_KHRONOS_validation",
86 vkEnumerateInstanceLayerProperties(&num_layers
, 0);
87 layers
= alloca(num_layers
* sizeof *layers
);
88 vkEnumerateInstanceLayerProperties(&num_layers
, layers
);
91 printf("Available validation layers:\n");
92 for(i
= 0; i
< (int)num_layers
; i
++) {
93 printf(" %s\n", layers
[i
].layerName
);
96 info
->ppEnabledLayerNames
= layer_names
;
97 info
->enabledLayerCount
= sizeof layer_names
/ sizeof *layer_names
;
99 fprintf(stderr
, "Vulkan validation layers not found.\n");
104 create_instance(bool enable_layers
)
106 VkApplicationInfo app_info
;
107 VkInstanceCreateInfo inst_info
;
110 memset(&app_info
, 0, sizeof app_info
);
111 app_info
.sType
= VK_STRUCTURE_TYPE_APPLICATION_INFO
;
112 app_info
.pApplicationName
= "vktest";
113 app_info
.apiVersion
= VK_API_VERSION_1_1
;
115 memset(&inst_info
, 0, sizeof inst_info
);
116 inst_info
.sType
= VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO
;
117 inst_info
.pApplicationInfo
= &app_info
;
120 enable_validation_layers(&inst_info
);
122 if (vkCreateInstance(&inst_info
, 0, &inst
) != VK_SUCCESS
)
123 return VK_NULL_HANDLE
;
128 static VkPhysicalDevice
129 select_physical_device(VkInstance inst
)
131 VkResult res
= VK_SUCCESS
;
132 uint32_t dev_count
= 0;
133 VkPhysicalDevice
*pdevices
;
134 VkPhysicalDevice pdevice0
;
137 vkEnumeratePhysicalDevices(inst
, &dev_count
, 0)) != VK_SUCCESS
)
138 return VK_NULL_HANDLE
;
140 pdevices
= malloc(dev_count
* sizeof(VkPhysicalDevice
));
141 if (vkEnumeratePhysicalDevices(inst
, &dev_count
, pdevices
) !=
143 return VK_NULL_HANDLE
;
145 pdevice0
= pdevices
[0];
152 create_device(struct vk_ctx
*ctx
, VkPhysicalDevice pdev
)
154 const char *deviceExtensions
[] = { "VK_KHR_external_memory_fd",
155 "VK_KHR_external_semaphore_fd" };
156 VkDeviceQueueCreateInfo dev_queue_info
;
157 VkDeviceCreateInfo dev_info
;
160 VkQueueFamilyProperties
*fam_props
;
165 vkGetPhysicalDeviceQueueFamilyProperties(pdev
, &prop_count
, 0);
167 fam_props
= malloc(prop_count
* sizeof *fam_props
);
168 vkGetPhysicalDeviceQueueFamilyProperties(pdev
, &prop_count
, fam_props
);
170 for (i
= 0; i
< prop_count
; i
++) {
171 if (fam_props
[i
].queueFlags
& VK_QUEUE_GRAPHICS_BIT
) {
178 memset(&dev_queue_info
, 0, sizeof dev_queue_info
);
179 dev_queue_info
.sType
= VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO
;
180 dev_queue_info
.queueFamilyIndex
= ctx
->qfam_idx
;
181 dev_queue_info
.queueCount
= 1;
182 dev_queue_info
.pQueuePriorities
= &qprio
;
184 memset(&dev_info
, 0, sizeof dev_info
);
185 dev_info
.sType
= VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO
;
186 dev_info
.queueCreateInfoCount
= 1;
187 dev_info
.pQueueCreateInfos
= &dev_queue_info
;
188 dev_info
.enabledExtensionCount
= ARRAY_SIZE(deviceExtensions
);
189 dev_info
.ppEnabledExtensionNames
= deviceExtensions
;
191 if (vkCreateDevice(pdev
, &dev_info
, 0, &dev
) != VK_SUCCESS
)
192 return VK_NULL_HANDLE
;
198 fill_uuid(VkPhysicalDevice pdev
, uint8_t *deviceUUID
, uint8_t *driverUUID
)
200 VkPhysicalDeviceIDProperties devProp
;
201 VkPhysicalDeviceProperties2 prop2
;
203 memset(&devProp
, 0, sizeof devProp
);
204 devProp
.sType
= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES
;
206 memset(&prop2
, 0, sizeof prop2
);
207 prop2
.sType
= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2
;
208 prop2
.pNext
= &devProp
;
210 vkGetPhysicalDeviceProperties2(pdev
, &prop2
);
211 memcpy(deviceUUID
, devProp
.deviceUUID
, VK_UUID_SIZE
);
212 memcpy(driverUUID
, devProp
.driverUUID
, VK_UUID_SIZE
);
216 create_cmd_pool(struct vk_ctx
*ctx
)
218 VkCommandPoolCreateInfo cmd_pool_info
;
219 VkCommandPool cmd_pool
;
220 VkDevice dev
= ctx
->dev
;
222 memset(&cmd_pool_info
, 0, sizeof cmd_pool_info
);
223 cmd_pool_info
.sType
= VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO
;
224 cmd_pool_info
.queueFamilyIndex
= ctx
->qfam_idx
;
225 cmd_pool_info
.flags
= VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT
;
227 if (vkCreateCommandPool(dev
, &cmd_pool_info
, 0, &cmd_pool
) != VK_SUCCESS
)
228 return VK_NULL_HANDLE
;
234 create_renderpass(struct vk_ctx
*ctx
,
235 struct vk_image_props
*color_img_props
,
236 struct vk_image_props
*depth_img_props
)
238 uint32_t num_attachments
= depth_img_props
? 2 : 1;
239 VkAttachmentDescription att_dsc
[2];
240 VkAttachmentReference att_rfc
[2];
241 VkSubpassDescription subpass_dsc
[1];
242 VkRenderPassCreateInfo rpass_info
;
244 /* VkAttachmentDescription */
245 memset(att_dsc
, 0, num_attachments
* sizeof att_dsc
[0]);
247 att_dsc
[0].samples
= get_num_samples(color_img_props
->num_samples
);
248 att_dsc
[0].loadOp
= VK_ATTACHMENT_LOAD_OP_CLEAR
;
249 att_dsc
[0].storeOp
= VK_ATTACHMENT_STORE_OP_STORE
;
250 att_dsc
[0].initialLayout
= color_img_props
->in_layout
;
251 att_dsc
[0].finalLayout
= color_img_props
->end_layout
;
252 att_dsc
[0].format
= color_img_props
->format
;
253 att_dsc
[0].stencilLoadOp
= VK_ATTACHMENT_LOAD_OP_DONT_CARE
;
254 att_dsc
[0].stencilStoreOp
= VK_ATTACHMENT_STORE_OP_DONT_CARE
;
256 if (depth_img_props
) {
258 att_dsc
[1].samples
= get_num_samples(depth_img_props
->num_samples
);
259 /* We might want to reuse a depth buffer */
260 if (depth_img_props
->in_layout
!= VK_IMAGE_LAYOUT_UNDEFINED
) {
261 att_dsc
[1].loadOp
= VK_ATTACHMENT_LOAD_OP_LOAD
;
262 att_dsc
[1].stencilLoadOp
= VK_ATTACHMENT_LOAD_OP_LOAD
;
265 att_dsc
[1].loadOp
= VK_ATTACHMENT_LOAD_OP_CLEAR
;
266 att_dsc
[1].stencilLoadOp
= VK_ATTACHMENT_LOAD_OP_CLEAR
;
268 att_dsc
[1].storeOp
= VK_ATTACHMENT_STORE_OP_STORE
;
269 att_dsc
[1].stencilStoreOp
= VK_ATTACHMENT_STORE_OP_STORE
;
270 att_dsc
[1].initialLayout
= depth_img_props
->in_layout
;
271 att_dsc
[1].finalLayout
= depth_img_props
->end_layout
;
272 att_dsc
[1].format
= depth_img_props
->format
;
275 /* VkAttachmentReference */
276 memset(att_rfc
, 0, num_attachments
* sizeof att_rfc
[0]);
278 att_rfc
[0].layout
= color_img_props
->tiling
== VK_IMAGE_TILING_OPTIMAL
? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
: VK_IMAGE_LAYOUT_GENERAL
;
279 att_rfc
[0].attachment
= 0;
281 if (depth_img_props
) {
282 att_rfc
[1].layout
= depth_img_props
->tiling
== VK_IMAGE_TILING_OPTIMAL
? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
: VK_IMAGE_LAYOUT_GENERAL
;
283 att_rfc
[1].attachment
= 1;
286 /* VkSubpassDescription */
287 memset(&subpass_dsc
, 0, sizeof subpass_dsc
);
288 subpass_dsc
[0].pipelineBindPoint
= VK_PIPELINE_BIND_POINT_GRAPHICS
;
289 subpass_dsc
[0].colorAttachmentCount
= 1;
290 subpass_dsc
[0].pColorAttachments
= &att_rfc
[0];
292 if (depth_img_props
) {
293 subpass_dsc
[0].pDepthStencilAttachment
= &att_rfc
[1];
296 /* VkRenderPassCreateInfo */
297 memset(&rpass_info
, 0, sizeof rpass_info
);
298 rpass_info
.sType
= VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO
;
299 rpass_info
.attachmentCount
= num_attachments
;
300 rpass_info
.pAttachments
= att_dsc
;
301 rpass_info
.subpassCount
= 1;
302 rpass_info
.pSubpasses
= subpass_dsc
;
305 if (vkCreateRenderPass(ctx
->dev
, &rpass_info
, 0, &rpass
) != VK_SUCCESS
) {
306 fprintf(stderr
, "Failed to create renderpass.\n");
307 rpass
= VK_NULL_HANDLE
;
313 static inline VkImageType
314 get_image_type(uint32_t h
, uint32_t d
)
317 return VK_IMAGE_TYPE_1D
;
320 return VK_IMAGE_TYPE_3D
;
322 return VK_IMAGE_TYPE_2D
;
325 static VkImageViewType
326 get_image_view_type(struct vk_image_props
*props
)
328 VkImageType type
= get_image_type(props
->h
, props
->depth
);
330 case VK_IMAGE_TYPE_1D
:
331 return props
->num_layers
> 1 ?
332 VK_IMAGE_VIEW_TYPE_1D_ARRAY
:
333 VK_IMAGE_VIEW_TYPE_1D
;
334 case VK_IMAGE_TYPE_2D
:
335 if (props
->num_layers
== 1)
336 return VK_IMAGE_VIEW_TYPE_2D
;
337 if (props
->num_layers
== 6)
338 return VK_IMAGE_VIEW_TYPE_CUBE
;
339 if (props
->num_layers
% 6 == 0)
340 return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY
;
341 if (props
->num_layers
> 1)
342 return VK_IMAGE_VIEW_TYPE_2D_ARRAY
;
343 case VK_IMAGE_TYPE_3D
:
344 if (props
->num_layers
== 1)
345 return VK_IMAGE_VIEW_TYPE_3D
;
346 if ((props
->num_layers
== 1) &&
347 (props
->num_levels
== 1))
348 return VK_IMAGE_VIEW_TYPE_2D
;
349 if ((props
->num_levels
== 1) &&
350 (props
->num_layers
> 1))
351 return VK_IMAGE_VIEW_TYPE_2D_ARRAY
;
353 return VK_IMAGE_VIEW_TYPE_2D
;
357 static VkImageAspectFlagBits
358 get_aspect_from_depth_format(VkFormat depth_format
)
360 switch (depth_format
) {
361 case VK_FORMAT_D16_UNORM
:
362 case VK_FORMAT_X8_D24_UNORM_PACK32
:
363 case VK_FORMAT_D32_SFLOAT
:
364 return VK_IMAGE_ASPECT_DEPTH_BIT
;
365 case VK_FORMAT_S8_UINT
:
366 return VK_IMAGE_ASPECT_STENCIL_BIT
;
367 case VK_FORMAT_D16_UNORM_S8_UINT
:
368 case VK_FORMAT_D24_UNORM_S8_UINT
:
369 case VK_FORMAT_D32_SFLOAT_S8_UINT
:
370 return VK_IMAGE_ASPECT_DEPTH_BIT
| VK_IMAGE_ASPECT_STENCIL_BIT
;
377 static VkPipelineStageFlags
378 get_pipeline_stage_flags(const VkImageLayout layout
)
381 case VK_IMAGE_LAYOUT_UNDEFINED
:
382 return VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT
;
383 case VK_IMAGE_LAYOUT_GENERAL
:
384 return VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
;
385 case VK_IMAGE_LAYOUT_PREINITIALIZED
:
386 return VK_PIPELINE_STAGE_HOST_BIT
;
387 case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
:
388 case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
:
389 return VK_PIPELINE_STAGE_TRANSFER_BIT
;
390 case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
:
391 return VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
;
392 case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
:
393 return VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
|
394 VK_PIPELINE_STAGE_VERTEX_SHADER_BIT
;
395 case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
:
396 return VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT
;
404 create_framebuffer(struct vk_ctx
*ctx
,
405 struct vk_image_att
*color_att
,
406 struct vk_image_att
*depth_att
,
407 struct vk_renderer
*renderer
)
409 VkImageSubresourceRange sr
;
410 VkImageViewCreateInfo color_info
;
411 VkImageViewCreateInfo depth_info
;
412 VkFramebufferCreateInfo fb_info
;
413 VkImageViewType view_type
= get_image_view_type(&color_att
->props
);
416 if (!color_att
->obj
.img
|| (depth_att
&& !depth_att
->obj
.img
)) {
417 fprintf(stderr
, "Invalid framebuffer attachment image.\n");
421 /* create image views */
423 /* VKImageSubresourceRange */
424 memset(&sr
, 0, sizeof sr
);
425 sr
.aspectMask
= VK_IMAGE_ASPECT_COLOR_BIT
;
426 /* If an application wants to use all mip levels
427 * or layers in an image after the baseMipLevel
428 * or baseArrayLayer, it can set levelCount and
429 * layerCount to the special values
430 * VK_REMAINING_MIP_LEVELS and
431 * VK_REMAINING_ARRAY_LAYERS without knowing the
432 * exact number of mip levels or layers.
435 sr
.levelCount
= color_att
->props
.num_levels
;
436 sr
.baseArrayLayer
= 0;
437 sr
.layerCount
= color_att
->props
.num_layers
;
440 memset(&color_info
, 0, sizeof color_info
);
441 color_info
.sType
= VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO
;
442 color_info
.image
= color_att
->obj
.img
;
443 color_info
.viewType
= view_type
;
444 color_info
.viewType
= VK_IMAGE_VIEW_TYPE_2D
;
445 color_info
.format
= color_att
->props
.format
;
446 color_info
.subresourceRange
= sr
;
448 if (vkCreateImageView(ctx
->dev
, &color_info
, 0, &color_att
->obj
.img_view
) != VK_SUCCESS
) {
449 fprintf(stderr
, "Failed to create color image view for framebuffer.\n");
450 vk_destroy_ext_image(ctx
, &color_att
->obj
);
456 memset(&sr
, 0, sizeof sr
);
457 sr
.aspectMask
= get_aspect_from_depth_format(depth_att
->props
.format
);
459 sr
.levelCount
= depth_att
->props
.num_levels
? depth_att
->props
.num_levels
: 1;
460 sr
.baseArrayLayer
= 0;
461 sr
.layerCount
= depth_att
->props
.num_layers
? depth_att
->props
.num_layers
: 1;
463 memset(&depth_info
, 0, sizeof depth_info
);
464 depth_info
.sType
= VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO
;
465 depth_info
.image
= depth_att
->obj
.img
;
466 depth_info
.viewType
= depth_att
->props
.num_layers
> 1 ? VK_IMAGE_VIEW_TYPE_2D_ARRAY
: VK_IMAGE_VIEW_TYPE_2D
;
467 depth_info
.viewType
= VK_IMAGE_VIEW_TYPE_2D
;
468 depth_info
.format
= depth_att
->props
.format
;
469 depth_info
.subresourceRange
= sr
;
471 if (vkCreateImageView(ctx
->dev
, &depth_info
, 0, &depth_att
->obj
.img_view
) != VK_SUCCESS
) {
472 fprintf(stderr
, "Failed to create depth image view for framebuffer.\n");
473 vk_destroy_ext_image(ctx
, &depth_att
->obj
);
478 atts
[0] = color_att
->obj
.img_view
;
481 atts
[1] = depth_att
->obj
.img_view
;
483 memset(&fb_info
, 0, sizeof fb_info
);
484 fb_info
.sType
= VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO
;
485 fb_info
.renderPass
= renderer
->renderpass
;
486 fb_info
.width
= color_att
->props
.w
;
487 fb_info
.height
= color_att
->props
.h
;
488 fb_info
.layers
= color_att
->props
.num_layers
? color_att
->props
.num_layers
: 1;
489 fb_info
.attachmentCount
= depth_att
? 2 : 1;
490 fb_info
.pAttachments
= atts
;
492 if (vkCreateFramebuffer(ctx
->dev
, &fb_info
, 0, &renderer
->fb
) != VK_SUCCESS
)
498 fprintf(stderr
, "Failed to create framebuffer.\n");
499 renderer
->fb
= VK_NULL_HANDLE
;
502 static VkShaderModule
503 create_shader_module(struct vk_ctx
*ctx
,
507 VkShaderModuleCreateInfo sm_info
;
510 /* VkShaderModuleCreateInfo */
511 memset(&sm_info
, 0, sizeof sm_info
);
512 sm_info
.sType
= VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO
;
513 sm_info
.codeSize
= size
;
514 sm_info
.pCode
= (void*)src
;
516 if (vkCreateShaderModule(ctx
->dev
, &sm_info
, 0, &sm
) != VK_SUCCESS
) {
517 fprintf(stderr
, "Failed to create shader module.\n");
525 create_pipeline(struct vk_ctx
*ctx
,
528 uint32_t num_samples
,
531 struct vk_renderer
*renderer
)
533 VkVertexInputBindingDescription vert_bind_dsc
[1];
534 VkVertexInputAttributeDescription vert_att_dsc
[1];
536 VkPipelineColorBlendAttachmentState cb_att_state
[1];
537 VkPipelineVertexInputStateCreateInfo vert_input_info
;
538 VkPipelineInputAssemblyStateCreateInfo asm_info
;
539 VkPipelineViewportStateCreateInfo viewport_info
;
540 VkPipelineRasterizationStateCreateInfo rs_info
;
541 VkPipelineMultisampleStateCreateInfo ms_info
;
542 VkPipelineDepthStencilStateCreateInfo ds_info
;
543 VkPipelineColorBlendStateCreateInfo cb_info
;
544 VkPipelineShaderStageCreateInfo sdr_stages
[2];
545 VkPipelineLayoutCreateInfo layout_info
;
546 VkGraphicsPipelineCreateInfo pipeline_info
;
548 VkFormatProperties fmt_props
;
549 VkPushConstantRange pc_range
[1];
551 VkStencilOpState front
;
552 VkStencilOpState back
;
554 VkPipelineLayout pipeline_layout
;
557 /* format of vertex attributes:
558 * we have 2D vectors so we need a RG format:
560 * the stride (distance between 2 consecutive elements)
561 * must be 8 because we use 32 bit floats and
563 format
= VK_FORMAT_R32G32_SFLOAT
;
564 vkGetPhysicalDeviceFormatProperties(ctx
->pdev
, format
, &fmt_props
);
565 assert(fmt_props
.bufferFeatures
& VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT
);
568 /* VkVertexInputAttributeDescription */
569 memset(&vert_att_dsc
, 0, sizeof vert_att_dsc
);
570 vert_att_dsc
[0].location
= 0;
571 vert_att_dsc
[0].binding
= 0;
572 vert_att_dsc
[0].format
= format
; /* see comment */
573 vert_att_dsc
[0].offset
= 0;
575 /* VkVertexInputBindingDescription */
576 memset(&vert_bind_dsc
, 0, sizeof vert_bind_dsc
);
577 vert_bind_dsc
[0].binding
= 0;
578 vert_bind_dsc
[0].stride
= stride
;
579 vert_bind_dsc
[0].inputRate
= VK_VERTEX_INPUT_RATE_VERTEX
;
581 /* If using vbo, we have setup vertex_info in the renderer. */
582 bool use_vbo
= renderer
->vertex_info
.num_verts
> 0;
584 /* VkPipelineVertexInputStateCreateInfo */
585 memset(&vert_input_info
, 0, sizeof vert_input_info
);
586 vert_input_info
.sType
= VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO
;
587 vert_input_info
.vertexBindingDescriptionCount
= use_vbo
? 1 : 0;
588 vert_input_info
.pVertexBindingDescriptions
= vert_bind_dsc
;
589 vert_input_info
.vertexAttributeDescriptionCount
= use_vbo
? 1 : 0;
590 vert_input_info
.pVertexAttributeDescriptions
= vert_att_dsc
;
592 /* VkPipelineInputAssemblyStateCreateInfo */
593 memset(&asm_info
, 0, sizeof asm_info
);
594 asm_info
.sType
= VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO
;
595 asm_info
.topology
= renderer
->vertex_info
.topology
?
596 renderer
->vertex_info
.topology
: VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP
;
597 asm_info
.primitiveRestartEnable
= false;
600 viewport
.x
= viewport
.y
= 0;
601 viewport
.width
= width
;
602 viewport
.height
= height
;
603 viewport
.minDepth
= 0;
604 viewport
.maxDepth
= 1;
606 /* VkRect2D scissor */
607 scissor
.offset
.x
= scissor
.offset
.y
= 0;
608 scissor
.extent
.width
= width
;
609 scissor
.extent
.height
= height
;
611 /* VkPipelineViewportStateCreateInfo */
612 memset(&viewport_info
, 0, sizeof viewport_info
);
613 viewport_info
.sType
= VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO
;
614 viewport_info
.viewportCount
= 1;
615 viewport_info
.pViewports
= &viewport
;
616 viewport_info
.scissorCount
= 1;
617 viewport_info
.pScissors
= &scissor
;
619 /* VkPipelineRasterizationStateCreateInfo */
620 memset(&rs_info
, 0, sizeof rs_info
);
621 rs_info
.sType
= VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO
;
622 rs_info
.polygonMode
= VK_POLYGON_MODE_FILL
;
623 rs_info
.cullMode
= VK_CULL_MODE_NONE
;
624 rs_info
.frontFace
= VK_FRONT_FACE_COUNTER_CLOCKWISE
;
625 rs_info
.lineWidth
= 1.0;
627 /* VkPipelineMultisampleStateCreateInfo */
628 memset(&ms_info
, 0, sizeof ms_info
);
629 ms_info
.sType
= VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO
;
630 ms_info
.rasterizationSamples
= num_samples
;
632 /* VkStencilOpState */
633 /* The default values for ES are taken by Topi Pohjolainen's code */
634 /* defaults in OpenGL ES 3.1 */
635 memset(&front
, 0, sizeof front
);
636 front
.compareMask
= ~0;
637 front
.writeMask
= ~0;
640 memset(&back
, 0, sizeof back
);
642 /* VkPipelineDepthStencilStateCreateInfo */
643 memset(&ds_info
, 0, sizeof ds_info
);
644 ds_info
.sType
= VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO
;
645 ds_info
.front
= front
;
647 /* defaults in OpenGL ES 3.1 */
648 ds_info
.minDepthBounds
= 0;
649 ds_info
.maxDepthBounds
= 1;
650 /* z buffer, stencil buffer */
652 ds_info
.depthTestEnable
= VK_TRUE
;
653 ds_info
.depthWriteEnable
= VK_TRUE
;
654 ds_info
.depthCompareOp
= VK_COMPARE_OP_LESS
;
656 if (enable_stencil
) {
657 ds_info
.stencilTestEnable
= VK_TRUE
;
658 ds_info
.depthTestEnable
= VK_FALSE
;
659 ds_info
.depthWriteEnable
= VK_TRUE
;
662 /* we only care about the passOp here */
663 ds_info
.back
.compareOp
= VK_COMPARE_OP_ALWAYS
;
664 ds_info
.back
.failOp
= VK_STENCIL_OP_REPLACE
;
665 ds_info
.back
.depthFailOp
= VK_STENCIL_OP_REPLACE
;
666 ds_info
.back
.passOp
= VK_STENCIL_OP_REPLACE
;
667 ds_info
.back
.compareMask
= 0xffffffff;
668 ds_info
.back
.writeMask
= 0xffffffff;
669 ds_info
.back
.reference
= 1;
670 ds_info
.front
= ds_info
.back
;
672 /* VkPipelineColorBlendAttachmentState */
673 memset(&cb_att_state
[0], 0, sizeof cb_att_state
[0]);
674 cb_att_state
[0].colorWriteMask
= (VK_COLOR_COMPONENT_R_BIT
|
675 VK_COLOR_COMPONENT_G_BIT
|
676 VK_COLOR_COMPONENT_B_BIT
|
677 VK_COLOR_COMPONENT_A_BIT
);
679 /* VkPipelineColorBlendStateCreateInfo */
680 memset(&cb_info
, 0, sizeof cb_info
);
681 cb_info
.sType
= VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO
;
682 cb_info
.attachmentCount
= 1;
683 cb_info
.pAttachments
= cb_att_state
;
684 /* default in ES 3.1 */
685 for (i
= 0; i
< 4; i
++) {
686 cb_info
.blendConstants
[i
] = 0.0f
;
689 /* VkPipelineShaderStageCreateInfo */
690 memset(sdr_stages
, 0, 2 * sizeof sdr_stages
[0]);
692 sdr_stages
[0].sType
= VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO
;
693 sdr_stages
[0].stage
= VK_SHADER_STAGE_VERTEX_BIT
;
694 sdr_stages
[0].module
= renderer
->vs
;
695 sdr_stages
[0].pName
= "main";
697 sdr_stages
[1].sType
= VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO
;
698 sdr_stages
[1].stage
= VK_SHADER_STAGE_FRAGMENT_BIT
;
699 sdr_stages
[1].module
= renderer
->fs
;
700 sdr_stages
[1].pName
= "main";
702 /* VkPushConstantRange */
703 memset(pc_range
, 0, sizeof pc_range
[0]);
704 pc_range
[0].stageFlags
= VK_SHADER_STAGE_FRAGMENT_BIT
;
705 pc_range
[0].size
= sizeof (struct vk_dims
); /* w, h */
707 /* VkPipelineLayoutCreateInfo */
708 memset(&layout_info
, 0, sizeof layout_info
);
709 layout_info
.sType
= VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO
;
710 layout_info
.pushConstantRangeCount
= 1;
711 layout_info
.pPushConstantRanges
= pc_range
;
713 if (vkCreatePipelineLayout(ctx
->dev
, &layout_info
, 0, &pipeline_layout
) != VK_SUCCESS
) {
714 fprintf(stderr
, "Failed to create pipeline layout\n");
715 renderer
->pipeline
= VK_NULL_HANDLE
;
719 renderer
->pipeline_layout
= pipeline_layout
;
721 /* VkGraphicsPipelineCreateInfo */
722 memset(&pipeline_info
, 0, sizeof pipeline_info
);
723 pipeline_info
.sType
= VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO
;
724 pipeline_info
.layout
= pipeline_layout
;
725 pipeline_info
.renderPass
= renderer
->renderpass
;
726 pipeline_info
.pVertexInputState
= &vert_input_info
;
727 pipeline_info
.pInputAssemblyState
= &asm_info
;
728 pipeline_info
.pViewportState
= &viewport_info
;
729 pipeline_info
.pRasterizationState
= &rs_info
;
730 pipeline_info
.pMultisampleState
= &ms_info
;
731 pipeline_info
.pDepthStencilState
= &ds_info
;
732 pipeline_info
.pColorBlendState
= &cb_info
;
733 pipeline_info
.stageCount
= 2;
734 pipeline_info
.pStages
= sdr_stages
;
736 if (vkCreateGraphicsPipelines(ctx
->dev
, 0, 1,
737 &pipeline_info
, 0, &renderer
->pipeline
) !=
739 fprintf(stderr
, "Failed to create graphics pipeline.\n");
740 renderer
->pipeline
= VK_NULL_HANDLE
;
744 static VkCommandBuffer
745 create_cmd_buf(VkDevice dev
, VkCommandPool cmd_pool
)
747 VkCommandBuffer cmd_buf
;
748 VkCommandBufferAllocateInfo alloc_info
;
750 memset(&alloc_info
, 0, sizeof alloc_info
);
751 alloc_info
.sType
= VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO
;
752 alloc_info
.level
= VK_COMMAND_BUFFER_LEVEL_PRIMARY
;
753 alloc_info
.commandBufferCount
= 1;
754 alloc_info
.commandPool
= cmd_pool
;
756 if (vkAllocateCommandBuffers(dev
, &alloc_info
, &cmd_buf
) != VK_SUCCESS
)
757 return VK_NULL_HANDLE
;
763 get_memory_type_idx(VkPhysicalDevice pdev
,
764 const VkMemoryRequirements
*mem_reqs
,
765 VkMemoryPropertyFlagBits prop_flags
)
767 VkPhysicalDeviceMemoryProperties pdev_mem_props
;
770 vkGetPhysicalDeviceMemoryProperties(pdev
, &pdev_mem_props
);
772 for (i
= 0; i
< pdev_mem_props
.memoryTypeCount
; i
++) {
773 const VkMemoryType
*type
= &pdev_mem_props
.memoryTypes
[i
];
775 if ((mem_reqs
->memoryTypeBits
& (1 << i
)) &&
776 (type
->propertyFlags
& prop_flags
) == prop_flags
) {
784 static VkSampleCountFlagBits
785 get_num_samples(uint32_t num_samples
)
787 switch(num_samples
) {
789 return VK_SAMPLE_COUNT_64_BIT
;
791 return VK_SAMPLE_COUNT_32_BIT
;
793 return VK_SAMPLE_COUNT_16_BIT
;
795 return VK_SAMPLE_COUNT_8_BIT
;
797 return VK_SAMPLE_COUNT_4_BIT
;
799 return VK_SAMPLE_COUNT_2_BIT
;
803 fprintf(stderr
, "Invalid number of samples in VkSampleCountFlagBits. Using one sample.\n");
806 return VK_SAMPLE_COUNT_1_BIT
;
809 static VkDeviceMemory
810 alloc_memory(struct vk_ctx
*ctx
,
812 const VkMemoryRequirements
*mem_reqs
,
815 VkMemoryPropertyFlagBits prop_flags
)
817 VkExportMemoryAllocateInfo exp_mem_info
;
818 VkMemoryAllocateInfo mem_alloc_info
;
820 VkMemoryDedicatedAllocateInfoKHR ded_info
;
823 memset(&exp_mem_info
, 0, sizeof exp_mem_info
);
824 exp_mem_info
.sType
= VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO
;
825 exp_mem_info
.handleTypes
=
826 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR
;
829 memset(&mem_alloc_info
, 0, sizeof mem_alloc_info
);
830 mem_alloc_info
.sType
= VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO
;
831 mem_alloc_info
.pNext
= is_external
? &exp_mem_info
: 0;
832 mem_alloc_info
.allocationSize
= mem_reqs
->size
;
833 mem_alloc_info
.memoryTypeIndex
=
834 get_memory_type_idx(ctx
->pdev
, mem_reqs
, prop_flags
);
836 if (mem_alloc_info
.memoryTypeIndex
== UINT32_MAX
) {
837 fprintf(stderr
, "No suitable memory type index found.\n");
838 return VK_NULL_HANDLE
;
841 if (image
|| buffer
) {
842 memset(&ded_info
, 0, sizeof ded_info
);
843 ded_info
.sType
= VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO
;
844 ded_info
.image
= image
;
845 ded_info
.buffer
= buffer
;
847 exp_mem_info
.pNext
= &ded_info
;
850 if (vkAllocateMemory(ctx
->dev
, &mem_alloc_info
, 0, &mem
) !=
852 return VK_NULL_HANDLE
;
858 alloc_image_memory(struct vk_ctx
*ctx
, struct vk_image_obj
*img_obj
)
860 VkMemoryDedicatedRequirements ded_reqs
;
861 VkImageMemoryRequirementsInfo2 req_info2
;
862 VkMemoryRequirements2 mem_reqs2
;
864 memset(&ded_reqs
, 0, sizeof ded_reqs
);
865 ded_reqs
.sType
= VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS
;
867 /* VkImageMemoryRequirementsInfo2 */
868 memset(&req_info2
, 0, sizeof req_info2
);
869 req_info2
.sType
= VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2
;
870 req_info2
.image
= img_obj
->img
;
872 /* VkMemoryRequirements2 */
873 memset(&mem_reqs2
, 0, sizeof mem_reqs2
);
874 mem_reqs2
.sType
= VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2
;
875 mem_reqs2
.pNext
= &ded_reqs
;
877 vkGetImageMemoryRequirements2(ctx
->dev
, &req_info2
, &mem_reqs2
);
878 img_obj
->mobj
.mem
= alloc_memory(ctx
,
880 &mem_reqs2
.memoryRequirements
,
881 ded_reqs
.requiresDedicatedAllocation
? img_obj
->img
: VK_NULL_HANDLE
,
883 mem_reqs2
.memoryRequirements
.memoryTypeBits
&
884 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
);
886 img_obj
->mobj
.mem_sz
= mem_reqs2
.memoryRequirements
.size
;
887 img_obj
->mobj
.dedicated
= ded_reqs
.requiresDedicatedAllocation
;
888 if (img_obj
->mobj
.mem
== VK_NULL_HANDLE
) {
889 fprintf(stderr
, "Failed to allocate image memory.\n");
893 if (vkBindImageMemory(ctx
->dev
, img_obj
->img
, img_obj
->mobj
.mem
, 0) != VK_SUCCESS
) {
894 fprintf(stderr
, "Failed to bind image memory.\n");
902 are_props_supported(struct vk_ctx
*ctx
, struct vk_image_props
*props
)
904 VkPhysicalDeviceExternalImageFormatInfo ext_img_fmt_info
;
905 VkExternalImageFormatProperties ext_img_fmt_props
;
908 VkPhysicalDeviceImageFormatInfo2 img_fmt_info
;
909 VkImageFormatProperties2 img_fmt_props
;
910 VkImageUsageFlagBits all_flags
[] = {
911 VK_IMAGE_USAGE_TRANSFER_SRC_BIT
,
912 VK_IMAGE_USAGE_TRANSFER_DST_BIT
,
913 VK_IMAGE_USAGE_SAMPLED_BIT
,
914 VK_IMAGE_USAGE_STORAGE_BIT
,
915 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
,
916 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
,
917 VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT
,
918 /* Shouldn't be used together with COLOR, DEPTH_STENCIL
920 * VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
921 * Provided by VK_EXT_fragment_density_map
922 * VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT,
923 * Provided by VK_NV_shading_rate_image
924 * VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV,
925 * Provided by VK_KHR_fragment_shading_rate
926 * VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR,
929 VkImageUsageFlagBits flags
= 0;
931 VkExternalMemoryFeatureFlagBits export_feature_flags
=
932 VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT
;
933 VkExternalMemoryHandleTypeFlagBits handle_type
=
934 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR
;
936 memset(&ext_img_fmt_info
, 0, sizeof ext_img_fmt_info
);
937 ext_img_fmt_info
.sType
=
938 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO
;
939 ext_img_fmt_info
.handleType
= handle_type
;
941 memset(&ext_img_fmt_props
, 0, sizeof ext_img_fmt_props
);
942 ext_img_fmt_props
.sType
=
943 VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES
;
945 memset(&img_fmt_props
, 0, sizeof img_fmt_props
);
946 img_fmt_props
.sType
= VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2
;
947 img_fmt_props
.pNext
= &ext_img_fmt_props
;
949 memset(&img_fmt_info
, 0, sizeof img_fmt_info
);
951 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2
;
952 img_fmt_info
.pNext
= &ext_img_fmt_info
;
953 img_fmt_info
.format
= props
->format
;
954 img_fmt_info
.type
= get_image_type(props
->h
, props
->depth
);
955 img_fmt_info
.tiling
= props
->tiling
;
957 for (i
= 0; i
< ARRAY_SIZE(all_flags
); i
++) {
958 img_fmt_info
.usage
= all_flags
[i
];
959 if (vkGetPhysicalDeviceImageFormatProperties2(ctx
->pdev
,
961 &img_fmt_props
) == VK_SUCCESS
) {
962 flags
|= all_flags
[i
];
966 /* usage can't be null */
968 img_fmt_info
.usage
= flags
;
971 fprintf(stderr
, "Unsupported Vulkan format properties: usage.\n");
975 if (vkGetPhysicalDeviceImageFormatProperties2
976 (ctx
->pdev
, &img_fmt_info
, &img_fmt_props
) != VK_SUCCESS
) {
978 "Unsupported Vulkan format properties.\n");
981 props
->usage
= flags
;
983 if (props
->need_export
&&
984 !(ext_img_fmt_props
.externalMemoryProperties
.externalMemoryFeatures
985 & export_feature_flags
)) {
986 fprintf(stderr
, "Unsupported Vulkan external memory features.\n");
993 /* Vulkan test visible functions */
996 vk_init_ctx(struct vk_ctx
*ctx
)
998 if ((ctx
->inst
= create_instance(false)) == VK_NULL_HANDLE
) {
999 fprintf(stderr
, "Failed to create Vulkan instance.\n");
1003 if ((ctx
->pdev
= select_physical_device(ctx
->inst
)) == VK_NULL_HANDLE
) {
1004 fprintf(stderr
, "Failed to find suitable physical device.\n");
1008 if ((ctx
->dev
= create_device(ctx
, ctx
->pdev
)) == VK_NULL_HANDLE
) {
1009 fprintf(stderr
, "Failed to create Vulkan device.\n");
1013 fill_uuid(ctx
->pdev
, ctx
->deviceUUID
, ctx
->driverUUID
);
1017 vk_cleanup_ctx(ctx
);
1022 vk_init_ctx_for_rendering(struct vk_ctx
*ctx
)
1024 if (!vk_init_ctx(ctx
)) {
1025 fprintf(stderr
, "Failed to initialize Vulkan.\n");
1029 if ((ctx
->cmd_pool
= create_cmd_pool(ctx
)) == VK_NULL_HANDLE
) {
1030 fprintf(stderr
, "Failed to create command pool.\n");
1034 if ((ctx
->cmd_buf
= create_cmd_buf(ctx
->dev
, ctx
->cmd_pool
)) ==
1036 fprintf(stderr
, "Failed to create command buffer.\n");
1040 vkGetDeviceQueue(ctx
->dev
, ctx
->qfam_idx
, 0, &ctx
->queue
);
1042 fprintf(stderr
, "Failed to get command queue.\n");
1049 vk_cleanup_ctx(ctx
);
1054 vk_cleanup_ctx(struct vk_ctx
*ctx
)
1056 if (ctx
->cmd_buf
!= VK_NULL_HANDLE
) {
1057 vkResetCommandBuffer(ctx
->cmd_buf
, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT
);
1058 vkFreeCommandBuffers(ctx
->dev
, ctx
->cmd_pool
, 1, &ctx
->cmd_buf
);
1059 ctx
->cmd_buf
= VK_NULL_HANDLE
;
1062 if (ctx
->cmd_pool
!= VK_NULL_HANDLE
) {
1063 vkResetCommandPool(ctx
->dev
, ctx
->cmd_pool
, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT
);
1064 vkDestroyCommandPool(ctx
->dev
, ctx
->cmd_pool
, 0);
1065 ctx
->cmd_pool
= VK_NULL_HANDLE
;
1068 if (ctx
->dev
!= VK_NULL_HANDLE
) {
1069 vkDestroyDevice(ctx
->dev
, 0);
1070 ctx
->dev
= VK_NULL_HANDLE
;
1073 if (ctx
->inst
!= VK_NULL_HANDLE
) {
1074 vkDestroyInstance(ctx
->inst
, 0);
1075 ctx
->inst
= VK_NULL_HANDLE
;
1080 vk_create_ext_image(struct vk_ctx
*ctx
,
1081 struct vk_image_props
*props
, struct vk_image_obj
*img
)
1083 VkExternalMemoryImageCreateInfo ext_img_info
;
1084 VkImageCreateInfo img_info
;
1086 memset(&ext_img_info
, 0, sizeof ext_img_info
);
1087 ext_img_info
.sType
= VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO
;
1088 ext_img_info
.handleTypes
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR
;
1090 memset(&img_info
, 0, sizeof img_info
);
1091 img_info
.sType
= VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
;
1092 img_info
.pNext
= &ext_img_info
;
1093 img_info
.imageType
= get_image_type(props
->h
, props
->depth
);
1094 img_info
.format
= props
->format
;
1095 img_info
.extent
.width
= props
->w
;
1096 img_info
.extent
.height
= props
->h
;
1097 img_info
.extent
.depth
= props
->depth
;
1098 img_info
.mipLevels
= props
->num_levels
? props
->num_levels
: 1;
1099 img_info
.arrayLayers
= props
->num_layers
? props
->num_layers
: VK_SAMPLE_COUNT_1_BIT
;
1100 img_info
.samples
= get_num_samples(props
->num_samples
);
1101 img_info
.tiling
= props
->tiling
;
1102 img_info
.usage
= props
->usage
;
1103 img_info
.initialLayout
= VK_IMAGE_LAYOUT_UNDEFINED
;
1104 img_info
.sharingMode
= VK_SHARING_MODE_EXCLUSIVE
;
1105 /* issue 17 of EXT_external_objects
1106 * Required in OpenGL implementations that support
1107 * ARB_texture_view, OES_texture_view, EXT_texture_view,
1108 * or OpenGL 4.3 and above.
1110 img_info
.flags
= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT
;
1112 if (vkCreateImage(ctx
->dev
, &img_info
, 0, &img
->img
) != VK_SUCCESS
)
1115 if(!alloc_image_memory(ctx
, img
))
1121 fprintf(stderr
, "Failed to create external image.\n");
1122 vk_destroy_ext_image(ctx
, img
);
1123 img
->img
= VK_NULL_HANDLE
;
1124 img
->mobj
.mem
= VK_NULL_HANDLE
;
1129 vk_create_ext_buffer(struct vk_ctx
*ctx
,
1131 VkBufferUsageFlagBits usage
,
1134 VkExternalMemoryBufferCreateInfo ext_bo_info
;
1136 memset(&ext_bo_info
, 0, sizeof ext_bo_info
);
1137 ext_bo_info
.sType
= VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO
;
1138 ext_bo_info
.handleTypes
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR
;
1140 if (!vk_create_buffer(ctx
, true, sz
, usage
, &ext_bo_info
, bo
)) {
1141 fprintf(stderr
, "Failed to allocate external buffer.\n");
1149 vk_destroy_ext_image(struct vk_ctx
*ctx
, struct vk_image_obj
*img_obj
)
1151 if (img_obj
->img
!= VK_NULL_HANDLE
) {
1152 vkDestroyImage(ctx
->dev
, img_obj
->img
, 0);
1153 img_obj
->img
= VK_NULL_HANDLE
;
1156 if (img_obj
->mobj
.mem
!= VK_NULL_HANDLE
) {
1157 vkFreeMemory(ctx
->dev
, img_obj
->mobj
.mem
, 0);
1158 img_obj
->mobj
.mem
= VK_NULL_HANDLE
;
1161 if (img_obj
->img_view
!= VK_NULL_HANDLE
) {
1162 vkDestroyImageView(ctx
->dev
, img_obj
->img_view
, 0);
1163 img_obj
->img_view
= VK_NULL_HANDLE
;
1168 vk_destroy_ext_bo(struct vk_ctx
*ctx
,
1171 if (bo
->buf
!= VK_NULL_HANDLE
) {
1172 vkDestroyBuffer(ctx
->dev
, bo
->buf
, 0);
1173 bo
->buf
= VK_NULL_HANDLE
;
1176 if (bo
->mobj
.mem
!= VK_NULL_HANDLE
) {
1177 vkFreeMemory(ctx
->dev
, bo
->mobj
.mem
, 0);
1178 bo
->mobj
.mem
= VK_NULL_HANDLE
;
1183 vk_fill_ext_image_props(struct vk_ctx
*ctx
,
1187 uint32_t num_samples
,
1188 uint32_t num_levels
,
1189 uint32_t num_layers
,
1191 VkImageTiling tiling
,
1192 VkImageLayout in_layout
,
1193 VkImageLayout end_layout
,
1195 struct vk_image_props
*props
)
1201 props
->num_samples
= num_samples
;
1202 props
->num_levels
= num_levels
;
1203 props
->num_layers
= num_layers
;
1205 props
->format
= format
;
1206 props
->tiling
= tiling
;
1208 props
->in_layout
= in_layout
;
1209 props
->end_layout
= end_layout
;
1211 props
->need_export
= need_export
;
1213 if (!are_props_supported(ctx
, props
))
1220 vk_create_renderer(struct vk_ctx
*ctx
,
1222 unsigned int vs_size
,
1224 unsigned int fs_size
,
1226 bool enable_stencil
,
1227 struct vk_image_att
*color_att
,
1228 struct vk_image_att
*depth_att
,
1229 struct vk_vertex_info
*vert_info
,
1230 struct vk_renderer
*renderer
)
1232 memset(&renderer
->vertex_info
, 0, sizeof renderer
->vertex_info
);
1234 renderer
->vertex_info
= *vert_info
;
1236 renderer
->renderpass
= create_renderpass(ctx
, &color_att
->props
, depth_att
? &depth_att
->props
: NULL
);
1237 if (renderer
->renderpass
== VK_NULL_HANDLE
)
1240 create_framebuffer(ctx
, color_att
, depth_att
, renderer
);
1241 if (renderer
->fb
== VK_NULL_HANDLE
)
1244 renderer
->vs
= create_shader_module(ctx
, vs_src
, vs_size
);
1245 if (renderer
->vs
== VK_NULL_HANDLE
)
1248 renderer
->fs
= create_shader_module(ctx
, fs_src
, fs_size
);
1249 if (renderer
->fs
== VK_NULL_HANDLE
)
1252 create_pipeline(ctx
, color_att
->props
.w
, color_att
->props
.h
,
1253 color_att
->props
.num_samples
, enable_depth
, enable_stencil
, renderer
);
1255 if (renderer
->pipeline
== VK_NULL_HANDLE
)
1261 fprintf(stderr
, "Failed to create graphics pipeline.\n");
1262 vk_destroy_renderer(ctx
, renderer
);
1267 vk_destroy_renderer(struct vk_ctx
*ctx
,
1268 struct vk_renderer
*renderer
)
1270 if (renderer
->renderpass
!= VK_NULL_HANDLE
) {
1271 vkDestroyRenderPass(ctx
->dev
, renderer
->renderpass
, 0);
1272 renderer
->renderpass
= VK_NULL_HANDLE
;
1275 if (renderer
->vs
!= VK_NULL_HANDLE
) {
1276 vkDestroyShaderModule(ctx
->dev
, renderer
->vs
, 0);
1277 renderer
->vs
= VK_NULL_HANDLE
;
1280 if (renderer
->fs
!= VK_NULL_HANDLE
) {
1281 vkDestroyShaderModule(ctx
->dev
, renderer
->fs
, 0);
1282 renderer
->fs
= VK_NULL_HANDLE
;
1285 if (renderer
->fb
!= VK_NULL_HANDLE
) {
1286 vkDestroyFramebuffer(ctx
->dev
, renderer
->fb
, 0);
1287 renderer
->fb
= VK_NULL_HANDLE
;
1290 if (renderer
->pipeline
!= VK_NULL_HANDLE
) {
1291 vkDestroyPipeline(ctx
->dev
, renderer
->pipeline
, 0);
1292 renderer
->pipeline
= VK_NULL_HANDLE
;
1295 if (renderer
->pipeline_layout
!= VK_NULL_HANDLE
) {
1296 vkDestroyPipelineLayout(ctx
->dev
, renderer
->pipeline_layout
, 0);
1297 renderer
->pipeline_layout
= VK_NULL_HANDLE
;
1302 vk_create_buffer(struct vk_ctx
*ctx
,
1305 VkBufferUsageFlagBits usage
,
1309 VkBufferCreateInfo buf_info
;
1310 VkMemoryRequirements mem_reqs
;
1312 bo
->mobj
.mem
= VK_NULL_HANDLE
;
1313 bo
->buf
= VK_NULL_HANDLE
;
1315 /* VkBufferCreateInfo */
1316 memset(&buf_info
, 0, sizeof buf_info
);
1317 buf_info
.sType
= VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO
;
1319 buf_info
.usage
= usage
;
1320 buf_info
.pNext
= pnext
;
1321 buf_info
.sharingMode
= VK_SHARING_MODE_EXCLUSIVE
;
1323 if (vkCreateBuffer(ctx
->dev
, &buf_info
, 0, &bo
->buf
) != VK_SUCCESS
)
1326 /* allocate buffer */
1327 vkGetBufferMemoryRequirements(ctx
->dev
, bo
->buf
, &mem_reqs
);
1328 /* VK_MEMORY_PROPERTY_HOST_COHERENT_BIT bit specifies that the
1329 * host cache management commands vkFlushMappedMemoryRanges and
1330 * vkInvalidateMappedMemoryRanges are not needed to flush host
1331 * writes to the device or make device writes visible to the
1332 * host, respectively. */
1333 bo
->mobj
.mem
= alloc_memory(ctx
, is_external
, &mem_reqs
, VK_NULL_HANDLE
, VK_NULL_HANDLE
,
1334 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
|
1335 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
);
1337 if (bo
->mobj
.mem
== VK_NULL_HANDLE
)
1340 bo
->mobj
.mem_sz
= sz
;
1342 if (vkBindBufferMemory(ctx
->dev
, bo
->buf
, bo
->mobj
.mem
, 0) != VK_SUCCESS
) {
1343 fprintf(stderr
, "Failed to bind buffer memory.\n");
1350 fprintf(stderr
, "Failed to allocate buffer.\n");
1351 vk_destroy_buffer(ctx
, bo
);
1356 vk_update_buffer_data(struct vk_ctx
*ctx
,
1363 if (vkMapMemory(ctx
->dev
, bo
->mobj
.mem
, 0, data_sz
, 0, &map
) != VK_SUCCESS
) {
1364 fprintf(stderr
, "Failed to map buffer memory.\n");
1368 memcpy(map
, data
, data_sz
);
1370 vkUnmapMemory(ctx
->dev
, bo
->mobj
.mem
);
1374 fprintf(stderr
, "Failed to update buffer data. Destroying the buffer.\n");
1375 vk_destroy_buffer(ctx
, bo
);
1381 vk_destroy_buffer(struct vk_ctx
*ctx
,
1384 if (bo
->buf
!= VK_NULL_HANDLE
)
1385 vkDestroyBuffer(ctx
->dev
, bo
->buf
, 0);
1387 if (bo
->mobj
.mem
!= VK_NULL_HANDLE
)
1388 vkFreeMemory(ctx
->dev
, bo
->mobj
.mem
, 0);
1390 bo
->mobj
.mem_sz
= 0;
1391 bo
->buf
= VK_NULL_HANDLE
;
1392 bo
->mobj
.mem
= VK_NULL_HANDLE
;
1396 vk_draw(struct vk_ctx
*ctx
,
1398 struct vk_renderer
*renderer
,
1400 uint32_t vk_fb_color_count
,
1401 struct vk_semaphores
*semaphores
,
1402 bool has_wait
, bool has_signal
,
1403 struct vk_image_att
*attachments
,
1404 uint32_t n_attachments
,
1408 VkCommandBufferBeginInfo cmd_begin_info
;
1409 VkRenderPassBeginInfo rp_begin_info
;
1411 VkClearValue clear_values
[2];
1412 VkSubmitInfo submit_info
;
1413 VkDeviceSize offsets
[] = {0};
1414 VkPipelineStageFlagBits stage_flags
;
1415 struct vk_dims img_size
;
1417 assert(vk_fb_color_count
== 4);
1419 assert(semaphores
->gl_frame_done
);
1421 assert(semaphores
->vk_frame_ready
);
1423 /* VkCommandBufferBeginInfo */
1424 memset(&cmd_begin_info
, 0, sizeof cmd_begin_info
);
1425 cmd_begin_info
.sType
= VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO
;
1426 cmd_begin_info
.flags
= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
;
1428 /* VkRect2D render area */
1429 memset(&rp_area
, 0, sizeof rp_area
);
1430 rp_area
.extent
.width
= (uint32_t)w
;
1431 rp_area
.extent
.height
= (uint32_t)h
;
1432 rp_area
.offset
.x
= x
;
1433 rp_area
.offset
.y
= y
;
1436 memset(&clear_values
[0], 0, sizeof clear_values
[0]);
1437 clear_values
[0].color
.float32
[0] = vk_fb_color
[0]; /* red */
1438 clear_values
[0].color
.float32
[1] = vk_fb_color
[1]; /* green */
1439 clear_values
[0].color
.float32
[2] = vk_fb_color
[2]; /* blue */
1440 clear_values
[0].color
.float32
[3] = vk_fb_color
[3]; /* alpha */
1442 memset(&clear_values
[1], 0, sizeof clear_values
[1]);
1443 clear_values
[1].depthStencil
.depth
= 1.0;
1444 clear_values
[1].depthStencil
.stencil
= 0;
1446 /* VkRenderPassBeginInfo */
1447 memset(&rp_begin_info
, 0, sizeof rp_begin_info
);
1448 rp_begin_info
.sType
= VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO
;
1449 rp_begin_info
.renderPass
= renderer
->renderpass
;
1450 rp_begin_info
.framebuffer
= renderer
->fb
;
1451 rp_begin_info
.renderArea
= rp_area
;
1452 rp_begin_info
.clearValueCount
= 2;
1453 rp_begin_info
.pClearValues
= clear_values
;
1456 stage_flags
= VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT
;
1458 memset(&submit_info
, 0, sizeof submit_info
);
1459 submit_info
.sType
= VK_STRUCTURE_TYPE_SUBMIT_INFO
;
1460 submit_info
.commandBufferCount
= 1;
1461 submit_info
.pCommandBuffers
= &ctx
->cmd_buf
;
1463 submit_info
.pWaitDstStageMask
= &stage_flags
;
1464 submit_info
.waitSemaphoreCount
= 1;
1465 submit_info
.pWaitSemaphores
= &semaphores
->gl_frame_done
;
1469 submit_info
.signalSemaphoreCount
= 1;
1470 submit_info
.pSignalSemaphores
= &semaphores
->vk_frame_ready
;
1473 vkBeginCommandBuffer(ctx
->cmd_buf
, &cmd_begin_info
);
1474 vkCmdBeginRenderPass(ctx
->cmd_buf
, &rp_begin_info
, VK_SUBPASS_CONTENTS_INLINE
);
1479 viewport
.height
= h
;
1481 scissor
.offset
.x
= x
;
1482 scissor
.offset
.y
= y
;
1483 scissor
.extent
.width
= w
;
1484 scissor
.extent
.height
= h
;
1486 vkCmdSetViewport(ctx
->cmd_buf
, 0, 1, &viewport
);
1487 vkCmdSetScissor(ctx
->cmd_buf
, 0, 1, &scissor
);
1489 img_size
.w
= (float)w
;
1490 img_size
.h
= (float)h
;
1491 vkCmdPushConstants(ctx
->cmd_buf
,
1492 renderer
->pipeline_layout
,
1493 VK_SHADER_STAGE_FRAGMENT_BIT
,
1494 0, sizeof (struct vk_dims
),
1498 vkCmdBindVertexBuffers(ctx
->cmd_buf
, 0, 1, &vbo
->buf
, offsets
);
1500 vkCmdBindPipeline(ctx
->cmd_buf
, VK_PIPELINE_BIND_POINT_GRAPHICS
, renderer
->pipeline
);
1502 int num_vertices
= vbo
? renderer
->vertex_info
.num_verts
: 4;
1503 vkCmdDraw(ctx
->cmd_buf
, num_vertices
, 1, 0, 0);
1505 vkCmdEndRenderPass(ctx
->cmd_buf
);
1507 VkImageMemoryBarrier
*barriers
=
1508 calloc(n_attachments
, sizeof(VkImageMemoryBarrier
));
1509 VkImageMemoryBarrier
*barrier
= barriers
;
1510 for (uint32_t n
= 0; n
< n_attachments
; n
++, barrier
++) {
1511 struct vk_image_att
*att
= &attachments
[n
];
1512 VkImageAspectFlagBits depth_stencil_flags
=
1513 get_aspect_from_depth_format(att
->props
.format
);
1514 bool is_depth
= (depth_stencil_flags
!= 0);
1516 /* Insert barrier to mark ownership transfer. */
1517 barrier
->sType
= VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER
;
1518 barrier
->oldLayout
= is_depth
?
1519 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
:
1520 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
;
1521 barrier
->newLayout
= VK_IMAGE_LAYOUT_GENERAL
;
1522 barrier
->srcAccessMask
= get_access_mask(barrier
->oldLayout
);
1523 barrier
->dstAccessMask
= get_access_mask(barrier
->newLayout
);
1524 barrier
->srcQueueFamilyIndex
= ctx
->qfam_idx
;
1525 barrier
->dstQueueFamilyIndex
= VK_QUEUE_FAMILY_EXTERNAL
;
1526 barrier
->image
= att
->obj
.img
;
1527 barrier
->subresourceRange
.aspectMask
= is_depth
?
1528 depth_stencil_flags
:
1529 VK_IMAGE_ASPECT_COLOR_BIT
;
1530 barrier
->subresourceRange
.baseMipLevel
= 0;
1531 barrier
->subresourceRange
.levelCount
= 1;
1532 barrier
->subresourceRange
.baseArrayLayer
= 0;
1533 barrier
->subresourceRange
.layerCount
= 1;
1536 vkCmdPipelineBarrier(ctx
->cmd_buf
,
1537 VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT
,
1538 VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT
,
1542 n_attachments
, barriers
);
1545 vkEndCommandBuffer(ctx
->cmd_buf
);
1547 if (vkQueueSubmit(ctx
->queue
, 1, &submit_info
, VK_NULL_HANDLE
) != VK_SUCCESS
) {
1548 fprintf(stderr
, "Failed to submit queue.\n");
1552 if (!semaphores
&& !has_wait
&& !has_signal
)
1553 vkQueueWaitIdle(ctx
->queue
);
1557 vk_clear_color(struct vk_ctx
*ctx
,
1559 struct vk_renderer
*renderer
,
1561 uint32_t vk_fb_color_count
,
1562 struct vk_semaphores
*semaphores
,
1563 bool has_wait
, bool has_signal
,
1564 struct vk_image_att
*attachments
,
1565 uint32_t n_attachments
,
1569 VkCommandBufferBeginInfo cmd_begin_info
;
1570 VkRenderPassBeginInfo rp_begin_info
;
1572 VkClearValue clear_values
[2];
1573 VkSubmitInfo submit_info
;
1574 VkPipelineStageFlagBits stage_flags
;
1575 VkImageSubresourceRange img_range
;
1577 assert(vk_fb_color_count
== 4);
1580 assert(semaphores
->gl_frame_done
);
1582 assert(semaphores
->vk_frame_ready
);
1584 /* VkCommandBufferBeginInfo */
1585 memset(&cmd_begin_info
, 0, sizeof cmd_begin_info
);
1586 cmd_begin_info
.sType
= VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO
;
1587 cmd_begin_info
.flags
= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
;
1589 /* VkRect2D render area */
1590 memset(&rp_area
, 0, sizeof rp_area
);
1591 rp_area
.extent
.width
= (uint32_t)w
;
1592 rp_area
.extent
.height
= (uint32_t)h
;
1593 rp_area
.offset
.x
= x
;
1594 rp_area
.offset
.y
= y
;
1597 memset(&clear_values
[0], 0, sizeof clear_values
[0]);
1598 clear_values
[0].color
.float32
[0] = vk_fb_color
[0]; /* red */
1599 clear_values
[0].color
.float32
[1] = vk_fb_color
[1]; /* green */
1600 clear_values
[0].color
.float32
[2] = vk_fb_color
[2]; /* blue */
1601 clear_values
[0].color
.float32
[3] = vk_fb_color
[3]; /* alpha */
1603 memset(&clear_values
[1], 0, sizeof clear_values
[1]);
1604 clear_values
[1].depthStencil
.depth
= 1.0;
1605 clear_values
[1].depthStencil
.stencil
= 0;
1607 /* VkRenderPassBeginInfo */
1608 memset(&rp_begin_info
, 0, sizeof rp_begin_info
);
1609 rp_begin_info
.sType
= VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO
;
1610 rp_begin_info
.renderPass
= renderer
->renderpass
;
1611 rp_begin_info
.framebuffer
= renderer
->fb
;
1612 rp_begin_info
.renderArea
= rp_area
;
1613 rp_begin_info
.clearValueCount
= 2;
1614 rp_begin_info
.pClearValues
= clear_values
;
1617 stage_flags
= VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT
;
1619 memset(&submit_info
, 0, sizeof submit_info
);
1620 submit_info
.sType
= VK_STRUCTURE_TYPE_SUBMIT_INFO
;
1621 submit_info
.commandBufferCount
= 1;
1622 submit_info
.pCommandBuffers
= &ctx
->cmd_buf
;
1624 submit_info
.pWaitDstStageMask
= &stage_flags
;
1625 submit_info
.waitSemaphoreCount
= 1;
1626 submit_info
.pWaitSemaphores
= &semaphores
->gl_frame_done
;
1630 submit_info
.signalSemaphoreCount
= 1;
1631 submit_info
.pSignalSemaphores
= &semaphores
->vk_frame_ready
;
1634 img_range
.aspectMask
= VK_IMAGE_ASPECT_COLOR_BIT
;
1635 img_range
.baseMipLevel
= 0;
1636 img_range
.levelCount
= 1;
1637 img_range
.baseArrayLayer
= 0;
1638 img_range
.layerCount
= 1;
1640 vkBeginCommandBuffer(ctx
->cmd_buf
, &cmd_begin_info
);
1641 vk_transition_image_layout(&attachments
[0],
1643 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
,
1644 VK_IMAGE_LAYOUT_GENERAL
,
1645 VK_QUEUE_FAMILY_EXTERNAL
,
1647 vkCmdClearColorImage(ctx
->cmd_buf
,
1648 attachments
[0].obj
.img
,
1649 VK_IMAGE_LAYOUT_GENERAL
,
1650 &clear_values
[0].color
,
1654 vkCmdBeginRenderPass(ctx
->cmd_buf
, &rp_begin_info
, VK_SUBPASS_CONTENTS_INLINE
);
1659 viewport
.height
= h
;
1661 scissor
.offset
.x
= x
;
1662 scissor
.offset
.y
= y
;
1663 scissor
.extent
.width
= w
;
1664 scissor
.extent
.height
= h
;
1666 vkCmdSetViewport(ctx
->cmd_buf
, 0, 1, &viewport
);
1667 vkCmdSetScissor(ctx
->cmd_buf
, 0, 1, &scissor
);
1669 vkCmdBindPipeline(ctx
->cmd_buf
, VK_PIPELINE_BIND_POINT_GRAPHICS
, renderer
->pipeline
);
1671 vkCmdEndRenderPass(ctx
->cmd_buf
);
1673 VkImageMemoryBarrier
*barriers
=
1674 calloc(n_attachments
, sizeof(VkImageMemoryBarrier
));
1675 VkImageMemoryBarrier
*barrier
= barriers
;
1677 for (uint32_t n
= 0; n
< n_attachments
; n
++, barrier
++) {
1678 struct vk_image_att
*att
= &attachments
[n
];
1680 /* Insert barrier to mark ownership transfer. */
1681 barrier
->sType
= VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER
;
1684 get_aspect_from_depth_format(att
->props
.format
) != (uintptr_t)VK_NULL_HANDLE
;
1686 barrier
->oldLayout
= is_depth
?
1687 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
:
1688 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
;
1689 barrier
->newLayout
= VK_IMAGE_LAYOUT_GENERAL
;
1690 barrier
->srcAccessMask
= get_access_mask(barrier
->oldLayout
);
1691 barrier
->dstAccessMask
= get_access_mask(barrier
->newLayout
);
1692 barrier
->srcQueueFamilyIndex
= ctx
->qfam_idx
;
1693 barrier
->dstQueueFamilyIndex
= VK_QUEUE_FAMILY_EXTERNAL
;
1694 barrier
->image
= att
->obj
.img
;
1695 barrier
->subresourceRange
.aspectMask
= is_depth
?
1696 VK_IMAGE_ASPECT_DEPTH_BIT
:
1697 VK_IMAGE_ASPECT_COLOR_BIT
;
1698 barrier
->subresourceRange
.baseMipLevel
= 0;
1699 barrier
->subresourceRange
.levelCount
= 1;
1700 barrier
->subresourceRange
.baseArrayLayer
= 0;
1701 barrier
->subresourceRange
.layerCount
= 1;
1704 vkCmdPipelineBarrier(ctx
->cmd_buf
,
1705 VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT
,
1706 VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT
,
1710 n_attachments
, barriers
);
1713 vkEndCommandBuffer(ctx
->cmd_buf
);
1715 if (vkQueueSubmit(ctx
->queue
, 1, &submit_info
, VK_NULL_HANDLE
) != VK_SUCCESS
) {
1716 fprintf(stderr
, "Failed to submit queue.\n");
1719 if (!semaphores
&& !has_wait
&& !has_signal
)
1720 vkQueueWaitIdle(ctx
->queue
);
1724 vk_copy_image_to_buffer(struct vk_ctx
*ctx
,
1725 struct vk_image_att
*src_img
,
1726 struct vk_buf
*dst_bo
,
1729 VkCommandBufferBeginInfo cmd_begin_info
;
1730 VkSubmitInfo submit_info
;
1731 VkImageAspectFlagBits aspect_mask
= get_aspect_from_depth_format(src_img
->props
.format
);
1733 /* VkCommandBufferBeginInfo */
1734 memset(&cmd_begin_info
, 0, sizeof cmd_begin_info
);
1735 cmd_begin_info
.sType
= VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO
;
1736 cmd_begin_info
.flags
= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
;
1738 memset(&submit_info
, 0, sizeof submit_info
);
1739 submit_info
.sType
= VK_STRUCTURE_TYPE_SUBMIT_INFO
;
1740 submit_info
.commandBufferCount
= 1;
1741 submit_info
.pCommandBuffers
= &ctx
->cmd_buf
;
1743 vkBeginCommandBuffer(ctx
->cmd_buf
, &cmd_begin_info
);
1744 if (src_img
->props
.end_layout
== VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
&& dst_bo
) {
1745 vk_transition_image_layout(src_img
,
1747 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
,
1748 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
,
1749 VK_QUEUE_FAMILY_EXTERNAL
,
1752 /* copy image to buf */
1753 VkBufferImageCopy copy_region
= {
1755 .bufferRowLength
= w
,
1756 .bufferImageHeight
= h
,
1757 .imageSubresource
= {
1758 .aspectMask
= aspect_mask
? aspect_mask
: VK_IMAGE_ASPECT_COLOR_BIT
,
1760 .baseArrayLayer
= 0,
1763 .imageOffset
= { 0, 0, 0 },
1764 .imageExtent
= { w
, h
, 1 }
1767 vkCmdCopyImageToBuffer(ctx
->cmd_buf
,
1769 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
,
1770 dst_bo
->buf
, 1, ©_region
);
1772 vk_transition_image_layout(src_img
,
1774 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
,
1775 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
,
1776 VK_QUEUE_FAMILY_EXTERNAL
,
1779 VkBufferMemoryBarrier write_finish_buffer_memory_barrier
= {
1780 .sType
= VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER
,
1781 .srcAccessMask
= VK_ACCESS_TRANSFER_WRITE_BIT
,
1782 .dstAccessMask
= VK_ACCESS_HOST_READ_BIT
,
1783 .srcQueueFamilyIndex
= VK_QUEUE_FAMILY_EXTERNAL
,
1784 .dstQueueFamilyIndex
= ctx
->qfam_idx
,
1785 .buffer
= dst_bo
->buf
,
1787 .size
= VK_WHOLE_SIZE
1790 vkCmdPipelineBarrier(ctx
->cmd_buf
,
1791 VK_PIPELINE_STAGE_TRANSFER_BIT
,
1792 VK_PIPELINE_STAGE_HOST_BIT
,
1793 (VkDependencyFlags
) 0, 0, NULL
,
1794 1, &write_finish_buffer_memory_barrier
,
1797 vkEndCommandBuffer(ctx
->cmd_buf
);
1799 if (vkQueueSubmit(ctx
->queue
, 1, &submit_info
, VK_NULL_HANDLE
) != VK_SUCCESS
) {
1800 fprintf(stderr
, "Failed to submit queue.\n");
1802 vkQueueWaitIdle(ctx
->queue
);
1806 vk_create_semaphores(struct vk_ctx
*ctx
,
1807 struct vk_semaphores
*semaphores
)
1809 VkSemaphoreCreateInfo sema_info
;
1810 VkExportSemaphoreCreateInfo exp_sema_info
;
1812 /* VkExportSemaphoreCreateInfo */
1813 memset(&exp_sema_info
, 0, sizeof exp_sema_info
);
1814 exp_sema_info
.sType
= VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO
;
1815 exp_sema_info
.handleTypes
= VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR
;
1817 /* VkSemaphoreCreateInfo */
1818 memset(&sema_info
, 0, sizeof sema_info
);
1819 sema_info
.sType
= VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO
;
1820 sema_info
.pNext
= &exp_sema_info
;
1822 if (vkCreateSemaphore(ctx
->dev
, &sema_info
, 0, &semaphores
->vk_frame_ready
) != VK_SUCCESS
) {
1823 fprintf(stderr
, "Failed to create semaphore vk_frame_ready.\n");
1827 if (vkCreateSemaphore(ctx
->dev
, &sema_info
, 0, &semaphores
->gl_frame_done
) != VK_SUCCESS
) {
1828 fprintf(stderr
, "Failed to create semaphore gl_frame_done.\n");
1836 vk_destroy_semaphores(struct vk_ctx
*ctx
,
1837 struct vk_semaphores
*semaphores
)
1839 if (semaphores
->vk_frame_ready
)
1840 vkDestroySemaphore(ctx
->dev
, semaphores
->vk_frame_ready
, 0);
1841 if (semaphores
->gl_frame_done
)
1842 vkDestroySemaphore(ctx
->dev
, semaphores
->gl_frame_done
, 0);
1846 vk_transition_image_layout(struct vk_image_att
*img_att
,
1847 VkCommandBuffer cmd_buf
,
1848 VkImageLayout old_layout
,
1849 VkImageLayout new_layout
,
1850 uint32_t src_queue_fam_idx
,
1851 uint32_t dst_queue_fam_idx
)
1853 VkImageMemoryBarrier barrier
;
1854 struct vk_image_props props
= img_att
->props
;
1855 VkImageAspectFlagBits aspect_mask
= get_aspect_from_depth_format(props
.format
);
1857 memset(&barrier
, 0, sizeof barrier
);
1858 barrier
.sType
= VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER
;
1859 barrier
.srcAccessMask
= get_access_mask(old_layout
);
1860 barrier
.dstAccessMask
= get_access_mask(new_layout
);
1861 barrier
.oldLayout
= old_layout
;
1862 barrier
.newLayout
= new_layout
;
1863 barrier
.srcQueueFamilyIndex
= src_queue_fam_idx
;
1864 barrier
.dstQueueFamilyIndex
= dst_queue_fam_idx
;
1865 barrier
.image
= img_att
->obj
.img
;
1866 barrier
.subresourceRange
.aspectMask
= aspect_mask
? aspect_mask
: VK_IMAGE_ASPECT_COLOR_BIT
;
1867 barrier
.subresourceRange
.levelCount
= 1;
1868 barrier
.subresourceRange
.layerCount
= 1;
1870 vkCmdPipelineBarrier(cmd_buf
,
1871 get_pipeline_stage_flags(old_layout
),
1872 get_pipeline_stage_flags(new_layout
),
1873 0, 0, VK_NULL_HANDLE
, 0, VK_NULL_HANDLE
, 1, &barrier
);