2 * Copyright © 2017 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 DEALINGS
24 #include "wsi_common_private.h"
25 #include "drm-uapi/drm_fourcc.h"
26 #include "util/macros.h"
27 #include "util/os_file.h"
28 #include "util/xmlconfig.h"
38 wsi_device_init(struct wsi_device
*wsi
,
39 VkPhysicalDevice pdevice
,
40 WSI_FN_GetPhysicalDeviceProcAddr proc_addr
,
41 const VkAllocationCallbacks
*alloc
,
43 const struct driOptionCache
*dri_options
,
46 const char *present_mode
;
47 UNUSED VkResult result
;
49 memset(wsi
, 0, sizeof(*wsi
));
51 wsi
->instance_alloc
= *alloc
;
52 wsi
->pdevice
= pdevice
;
54 #define WSI_GET_CB(func) \
55 PFN_vk##func func = (PFN_vk##func)proc_addr(pdevice, "vk" #func)
56 WSI_GET_CB(GetPhysicalDeviceProperties2
);
57 WSI_GET_CB(GetPhysicalDeviceMemoryProperties
);
58 WSI_GET_CB(GetPhysicalDeviceQueueFamilyProperties
);
61 wsi
->pci_bus_info
.sType
=
62 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT
;
63 VkPhysicalDeviceProperties2 pdp2
= {
64 .sType
= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2
,
65 .pNext
= &wsi
->pci_bus_info
,
67 GetPhysicalDeviceProperties2(pdevice
, &pdp2
);
69 wsi
->maxImageDimension2D
= pdp2
.properties
.limits
.maxImageDimension2D
;
70 wsi
->override_present_mode
= VK_PRESENT_MODE_MAX_ENUM_KHR
;
72 GetPhysicalDeviceMemoryProperties(pdevice
, &wsi
->memory_props
);
73 GetPhysicalDeviceQueueFamilyProperties(pdevice
, &wsi
->queue_family_count
, NULL
);
75 #define WSI_GET_CB(func) \
76 wsi->func = (PFN_vk##func)proc_addr(pdevice, "vk" #func)
77 WSI_GET_CB(AllocateMemory
);
78 WSI_GET_CB(AllocateCommandBuffers
);
79 WSI_GET_CB(BindBufferMemory
);
80 WSI_GET_CB(BindImageMemory
);
81 WSI_GET_CB(BeginCommandBuffer
);
82 WSI_GET_CB(CmdCopyImageToBuffer
);
83 WSI_GET_CB(CreateBuffer
);
84 WSI_GET_CB(CreateCommandPool
);
85 WSI_GET_CB(CreateFence
);
86 WSI_GET_CB(CreateImage
);
87 WSI_GET_CB(DestroyBuffer
);
88 WSI_GET_CB(DestroyCommandPool
);
89 WSI_GET_CB(DestroyFence
);
90 WSI_GET_CB(DestroyImage
);
91 WSI_GET_CB(EndCommandBuffer
);
92 WSI_GET_CB(FreeMemory
);
93 WSI_GET_CB(FreeCommandBuffers
);
94 WSI_GET_CB(GetBufferMemoryRequirements
);
95 WSI_GET_CB(GetImageDrmFormatModifierPropertiesEXT
);
96 WSI_GET_CB(GetImageMemoryRequirements
);
97 WSI_GET_CB(GetImageSubresourceLayout
);
99 WSI_GET_CB(GetMemoryFdKHR
);
100 WSI_GET_CB(GetPhysicalDeviceFormatProperties
);
101 WSI_GET_CB(GetPhysicalDeviceFormatProperties2KHR
);
102 WSI_GET_CB(GetPhysicalDeviceImageFormatProperties2
);
103 WSI_GET_CB(ResetFences
);
104 WSI_GET_CB(QueueSubmit
);
105 WSI_GET_CB(WaitForFences
);
106 WSI_GET_CB(MapMemory
);
107 WSI_GET_CB(UnmapMemory
);
110 #ifdef VK_USE_PLATFORM_XCB_KHR
111 result
= wsi_x11_init_wsi(wsi
, alloc
, dri_options
);
112 if (result
!= VK_SUCCESS
)
116 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
117 result
= wsi_wl_init_wsi(wsi
, alloc
, pdevice
);
118 if (result
!= VK_SUCCESS
)
122 #ifdef VK_USE_PLATFORM_DISPLAY_KHR
123 result
= wsi_display_init_wsi(wsi
, alloc
, display_fd
);
124 if (result
!= VK_SUCCESS
)
128 present_mode
= getenv("MESA_VK_WSI_PRESENT_MODE");
130 if (!strcmp(present_mode
, "fifo")) {
131 wsi
->override_present_mode
= VK_PRESENT_MODE_FIFO_KHR
;
132 } else if (!strcmp(present_mode
, "mailbox")) {
133 wsi
->override_present_mode
= VK_PRESENT_MODE_MAILBOX_KHR
;
134 } else if (!strcmp(present_mode
, "immediate")) {
135 wsi
->override_present_mode
= VK_PRESENT_MODE_IMMEDIATE_KHR
;
137 fprintf(stderr
, "Invalid MESA_VK_WSI_PRESENT_MODE value!\n");
142 if (driCheckOption(dri_options
, "adaptive_sync", DRI_BOOL
))
143 wsi
->enable_adaptive_sync
= driQueryOptionb(dri_options
,
146 if (driCheckOption(dri_options
, "vk_wsi_force_bgra8_unorm_first", DRI_BOOL
)) {
147 wsi
->force_bgra8_unorm_first
=
148 driQueryOptionb(dri_options
, "vk_wsi_force_bgra8_unorm_first");
153 #if defined(VK_USE_PLATFORM_XCB_KHR) || \
154 defined(VK_USE_PLATFORM_WAYLAND_KHR) || \
155 defined(VK_USE_PLATFORM_DISPLAY_KHR)
157 wsi_device_finish(wsi
, alloc
);
163 wsi_device_finish(struct wsi_device
*wsi
,
164 const VkAllocationCallbacks
*alloc
)
166 #ifdef VK_USE_PLATFORM_DISPLAY_KHR
167 wsi_display_finish_wsi(wsi
, alloc
);
169 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
170 wsi_wl_finish_wsi(wsi
, alloc
);
172 #ifdef VK_USE_PLATFORM_XCB_KHR
173 wsi_x11_finish_wsi(wsi
, alloc
);
178 wsi_device_matches_drm_fd(const struct wsi_device
*wsi
, int drm_fd
)
180 drmDevicePtr fd_device
;
181 int ret
= drmGetDevice2(drm_fd
, 0, &fd_device
);
186 switch (fd_device
->bustype
) {
188 match
= wsi
->pci_bus_info
.pciDomain
== fd_device
->businfo
.pci
->domain
&&
189 wsi
->pci_bus_info
.pciBus
== fd_device
->businfo
.pci
->bus
&&
190 wsi
->pci_bus_info
.pciDevice
== fd_device
->businfo
.pci
->dev
&&
191 wsi
->pci_bus_info
.pciFunction
== fd_device
->businfo
.pci
->func
;
198 drmFreeDevice(&fd_device
);
204 wsi_swapchain_init(const struct wsi_device
*wsi
,
205 struct wsi_swapchain
*chain
,
207 const VkSwapchainCreateInfoKHR
*pCreateInfo
,
208 const VkAllocationCallbacks
*pAllocator
)
212 memset(chain
, 0, sizeof(*chain
));
214 vk_object_base_init(NULL
, &chain
->base
, VK_OBJECT_TYPE_SWAPCHAIN_KHR
);
217 chain
->device
= device
;
218 chain
->alloc
= *pAllocator
;
219 chain
->use_prime_blit
= false;
222 vk_zalloc(pAllocator
, sizeof(VkCommandPool
) * wsi
->queue_family_count
, 8,
223 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
224 if (!chain
->cmd_pools
)
225 return VK_ERROR_OUT_OF_HOST_MEMORY
;
227 for (uint32_t i
= 0; i
< wsi
->queue_family_count
; i
++) {
228 const VkCommandPoolCreateInfo cmd_pool_info
= {
229 .sType
= VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO
,
232 .queueFamilyIndex
= i
,
234 result
= wsi
->CreateCommandPool(device
, &cmd_pool_info
, &chain
->alloc
,
235 &chain
->cmd_pools
[i
]);
236 if (result
!= VK_SUCCESS
)
243 wsi_swapchain_finish(chain
);
248 wsi_swapchain_is_present_mode_supported(struct wsi_device
*wsi
,
249 const VkSwapchainCreateInfoKHR
*pCreateInfo
,
250 VkPresentModeKHR mode
)
252 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, pCreateInfo
->surface
);
253 struct wsi_interface
*iface
= wsi
->wsi
[surface
->platform
];
254 VkPresentModeKHR
*present_modes
;
255 uint32_t present_mode_count
;
256 bool supported
= false;
259 result
= iface
->get_present_modes(surface
, &present_mode_count
, NULL
);
260 if (result
!= VK_SUCCESS
)
263 present_modes
= malloc(present_mode_count
* sizeof(*present_modes
));
267 result
= iface
->get_present_modes(surface
, &present_mode_count
,
269 if (result
!= VK_SUCCESS
)
272 for (uint32_t i
= 0; i
< present_mode_count
; i
++) {
273 if (present_modes
[i
] == mode
) {
284 enum VkPresentModeKHR
285 wsi_swapchain_get_present_mode(struct wsi_device
*wsi
,
286 const VkSwapchainCreateInfoKHR
*pCreateInfo
)
288 if (wsi
->override_present_mode
== VK_PRESENT_MODE_MAX_ENUM_KHR
)
289 return pCreateInfo
->presentMode
;
291 if (!wsi_swapchain_is_present_mode_supported(wsi
, pCreateInfo
,
292 wsi
->override_present_mode
)) {
293 fprintf(stderr
, "Unsupported MESA_VK_WSI_PRESENT_MODE value!\n");
294 return pCreateInfo
->presentMode
;
297 return wsi
->override_present_mode
;
301 wsi_swapchain_finish(struct wsi_swapchain
*chain
)
304 for (unsigned i
= 0; i
< chain
->image_count
; i
++)
305 chain
->wsi
->DestroyFence(chain
->device
, chain
->fences
[i
], &chain
->alloc
);
307 vk_free(&chain
->alloc
, chain
->fences
);
310 for (uint32_t i
= 0; i
< chain
->wsi
->queue_family_count
; i
++) {
311 chain
->wsi
->DestroyCommandPool(chain
->device
, chain
->cmd_pools
[i
],
314 vk_free(&chain
->alloc
, chain
->cmd_pools
);
316 vk_object_base_finish(&chain
->base
);
320 select_memory_type(const struct wsi_device
*wsi
,
321 VkMemoryPropertyFlags props
,
324 for (uint32_t i
= 0; i
< wsi
->memory_props
.memoryTypeCount
; i
++) {
325 const VkMemoryType type
= wsi
->memory_props
.memoryTypes
[i
];
326 if ((type_bits
& (1 << i
)) && (type
.propertyFlags
& props
) == props
)
330 unreachable("No memory type found");
334 vk_format_size(VkFormat format
)
337 case VK_FORMAT_B8G8R8A8_UNORM
:
338 case VK_FORMAT_B8G8R8A8_SRGB
:
341 unreachable("Unknown WSI Format");
345 static inline uint32_t
346 align_u32(uint32_t v
, uint32_t a
)
348 assert(a
!= 0 && a
== (a
& -a
));
349 return (v
+ a
- 1) & ~(a
- 1);
353 wsi_create_native_image(const struct wsi_swapchain
*chain
,
354 const VkSwapchainCreateInfoKHR
*pCreateInfo
,
355 uint32_t num_modifier_lists
,
356 const uint32_t *num_modifiers
,
357 const uint64_t *const *modifiers
,
358 struct wsi_image
*image
)
360 const struct wsi_device
*wsi
= chain
->wsi
;
363 memset(image
, 0, sizeof(*image
));
364 for (int i
= 0; i
< ARRAY_SIZE(image
->fds
); i
++)
367 VkImageCreateInfo image_info
= {
368 .sType
= VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
,
370 .imageType
= VK_IMAGE_TYPE_2D
,
371 .format
= pCreateInfo
->imageFormat
,
373 .width
= pCreateInfo
->imageExtent
.width
,
374 .height
= pCreateInfo
->imageExtent
.height
,
379 .samples
= VK_SAMPLE_COUNT_1_BIT
,
380 .tiling
= VK_IMAGE_TILING_OPTIMAL
,
381 .usage
= pCreateInfo
->imageUsage
,
382 .sharingMode
= pCreateInfo
->imageSharingMode
,
383 .queueFamilyIndexCount
= pCreateInfo
->queueFamilyIndexCount
,
384 .pQueueFamilyIndices
= pCreateInfo
->pQueueFamilyIndices
,
385 .initialLayout
= VK_IMAGE_LAYOUT_UNDEFINED
,
388 VkImageFormatListCreateInfoKHR image_format_list
;
389 if (pCreateInfo
->flags
& VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR
) {
390 image_info
.flags
|= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT
|
391 VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR
;
393 const VkImageFormatListCreateInfoKHR
*format_list
=
394 vk_find_struct_const(pCreateInfo
->pNext
,
395 IMAGE_FORMAT_LIST_CREATE_INFO_KHR
);
398 assume(format_list
&& format_list
->viewFormatCount
> 0);
399 bool format_found
= false;
400 for (int i
= 0; i
< format_list
->viewFormatCount
; i
++)
401 if (pCreateInfo
->imageFormat
== format_list
->pViewFormats
[i
])
403 assert(format_found
);
406 image_format_list
= *format_list
;
407 image_format_list
.pNext
= NULL
;
408 __vk_append_struct(&image_info
, &image_format_list
);
411 struct wsi_image_create_info image_wsi_info
;
412 VkImageDrmFormatModifierListCreateInfoEXT image_modifier_list
;
414 uint32_t image_modifier_count
= 0, modifier_prop_count
= 0;
415 struct VkDrmFormatModifierPropertiesEXT
*modifier_props
= NULL
;
416 uint64_t *image_modifiers
= NULL
;
417 if (num_modifier_lists
== 0) {
418 /* If we don't have modifiers, fall back to the legacy "scanout" flag */
419 image_wsi_info
= (struct wsi_image_create_info
) {
420 .sType
= VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA
,
423 __vk_append_struct(&image_info
, &image_wsi_info
);
425 /* The winsys can't request modifiers if we don't support them. */
426 assert(wsi
->supports_modifiers
);
427 struct VkDrmFormatModifierPropertiesListEXT modifier_props_list
= {
428 .sType
= VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT
,
430 VkFormatProperties2 format_props
= {
431 .sType
= VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2
,
432 .pNext
= &modifier_props_list
,
434 wsi
->GetPhysicalDeviceFormatProperties2KHR(wsi
->pdevice
,
435 pCreateInfo
->imageFormat
,
437 assert(modifier_props_list
.drmFormatModifierCount
> 0);
438 modifier_props
= vk_alloc(&chain
->alloc
,
439 sizeof(*modifier_props
) *
440 modifier_props_list
.drmFormatModifierCount
,
442 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND
);
443 if (!modifier_props
) {
444 result
= VK_ERROR_OUT_OF_HOST_MEMORY
;
448 modifier_props_list
.pDrmFormatModifierProperties
= modifier_props
;
449 wsi
->GetPhysicalDeviceFormatProperties2KHR(wsi
->pdevice
,
450 pCreateInfo
->imageFormat
,
453 /* Call GetImageFormatProperties with every modifier and filter the list
454 * down to those that we know work.
456 modifier_prop_count
= 0;
457 for (uint32_t i
= 0; i
< modifier_props_list
.drmFormatModifierCount
; i
++) {
458 VkPhysicalDeviceImageDrmFormatModifierInfoEXT mod_info
= {
459 .sType
= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT
,
460 .drmFormatModifier
= modifier_props
[i
].drmFormatModifier
,
461 .sharingMode
= pCreateInfo
->imageSharingMode
,
462 .queueFamilyIndexCount
= pCreateInfo
->queueFamilyIndexCount
,
463 .pQueueFamilyIndices
= pCreateInfo
->pQueueFamilyIndices
,
465 VkPhysicalDeviceImageFormatInfo2 format_info
= {
466 .sType
= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2
,
467 .format
= pCreateInfo
->imageFormat
,
468 .type
= VK_IMAGE_TYPE_2D
,
469 .tiling
= VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT
,
470 .usage
= pCreateInfo
->imageUsage
,
471 .flags
= image_info
.flags
,
474 VkImageFormatListCreateInfoKHR format_list
;
475 if (image_info
.flags
& VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT
) {
476 format_list
= image_format_list
;
477 format_list
.pNext
= NULL
;
478 __vk_append_struct(&format_info
, &format_list
);
481 VkImageFormatProperties2 format_props
= {
482 .sType
= VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2
,
485 __vk_append_struct(&format_info
, &mod_info
);
486 result
= wsi
->GetPhysicalDeviceImageFormatProperties2(wsi
->pdevice
,
489 if (result
== VK_SUCCESS
)
490 modifier_props
[modifier_prop_count
++] = modifier_props
[i
];
493 uint32_t max_modifier_count
= 0;
494 for (uint32_t l
= 0; l
< num_modifier_lists
; l
++)
495 max_modifier_count
= MAX2(max_modifier_count
, num_modifiers
[l
]);
497 image_modifiers
= vk_alloc(&chain
->alloc
,
498 sizeof(*image_modifiers
) *
501 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND
);
502 if (!image_modifiers
) {
503 result
= VK_ERROR_OUT_OF_HOST_MEMORY
;
507 image_modifier_count
= 0;
508 for (uint32_t l
= 0; l
< num_modifier_lists
; l
++) {
509 /* Walk the modifier lists and construct a list of supported
512 for (uint32_t i
= 0; i
< num_modifiers
[l
]; i
++) {
513 for (uint32_t j
= 0; j
< modifier_prop_count
; j
++) {
514 if (modifier_props
[j
].drmFormatModifier
== modifiers
[l
][i
])
515 image_modifiers
[image_modifier_count
++] = modifiers
[l
][i
];
519 /* We only want to take the modifiers from the first list */
520 if (image_modifier_count
> 0)
524 if (image_modifier_count
> 0) {
525 image_modifier_list
= (VkImageDrmFormatModifierListCreateInfoEXT
) {
526 .sType
= VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT
,
527 .drmFormatModifierCount
= image_modifier_count
,
528 .pDrmFormatModifiers
= image_modifiers
,
530 image_info
.tiling
= VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT
;
531 __vk_append_struct(&image_info
, &image_modifier_list
);
533 /* TODO: Add a proper error here */
534 assert(!"Failed to find a supported modifier! This should never "
535 "happen because LINEAR should always be available");
536 result
= VK_ERROR_OUT_OF_HOST_MEMORY
;
541 result
= wsi
->CreateImage(chain
->device
, &image_info
,
542 &chain
->alloc
, &image
->image
);
543 if (result
!= VK_SUCCESS
)
546 VkMemoryRequirements reqs
;
547 wsi
->GetImageMemoryRequirements(chain
->device
, image
->image
, &reqs
);
549 const struct wsi_memory_allocate_info memory_wsi_info
= {
550 .sType
= VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA
,
552 .implicit_sync
= true,
554 const VkExportMemoryAllocateInfo memory_export_info
= {
555 .sType
= VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO
,
556 .pNext
= &memory_wsi_info
,
557 .handleTypes
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
,
559 const VkMemoryDedicatedAllocateInfo memory_dedicated_info
= {
560 .sType
= VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO
,
561 .pNext
= &memory_export_info
,
562 .image
= image
->image
,
563 .buffer
= VK_NULL_HANDLE
,
565 const VkMemoryAllocateInfo memory_info
= {
566 .sType
= VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO
,
567 .pNext
= &memory_dedicated_info
,
568 .allocationSize
= reqs
.size
,
569 .memoryTypeIndex
= select_memory_type(wsi
, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
,
570 reqs
.memoryTypeBits
),
572 result
= wsi
->AllocateMemory(chain
->device
, &memory_info
,
573 &chain
->alloc
, &image
->memory
);
574 if (result
!= VK_SUCCESS
)
577 result
= wsi
->BindImageMemory(chain
->device
, image
->image
,
579 if (result
!= VK_SUCCESS
)
584 const VkMemoryGetFdInfoKHR memory_get_fd_info
= {
585 .sType
= VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR
,
587 .memory
= image
->memory
,
588 .handleType
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
,
591 result
= wsi
->GetMemoryFdKHR(chain
->device
, &memory_get_fd_info
, &fd
);
592 if (result
!= VK_SUCCESS
)
596 if (!wsi
->sw
&& num_modifier_lists
> 0) {
597 VkImageDrmFormatModifierPropertiesEXT image_mod_props
= {
598 .sType
= VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT
,
600 result
= wsi
->GetImageDrmFormatModifierPropertiesEXT(chain
->device
,
603 if (result
!= VK_SUCCESS
) {
607 image
->drm_modifier
= image_mod_props
.drmFormatModifier
;
608 assert(image
->drm_modifier
!= DRM_FORMAT_MOD_INVALID
);
610 for (uint32_t j
= 0; j
< modifier_prop_count
; j
++) {
611 if (modifier_props
[j
].drmFormatModifier
== image
->drm_modifier
) {
612 image
->num_planes
= modifier_props
[j
].drmFormatModifierPlaneCount
;
617 for (uint32_t p
= 0; p
< image
->num_planes
; p
++) {
618 const VkImageSubresource image_subresource
= {
619 .aspectMask
= VK_IMAGE_ASPECT_PLANE_0_BIT
<< p
,
623 VkSubresourceLayout image_layout
;
624 wsi
->GetImageSubresourceLayout(chain
->device
, image
->image
,
625 &image_subresource
, &image_layout
);
626 image
->sizes
[p
] = image_layout
.size
;
627 image
->row_pitches
[p
] = image_layout
.rowPitch
;
628 image
->offsets
[p
] = image_layout
.offset
;
632 image
->fds
[p
] = os_dupfd_cloexec(fd
);
633 if (image
->fds
[p
] == -1) {
634 for (uint32_t i
= 0; i
< p
; i
++)
635 close(image
->fds
[i
]);
637 result
= VK_ERROR_OUT_OF_HOST_MEMORY
;
643 const VkImageSubresource image_subresource
= {
644 .aspectMask
= VK_IMAGE_ASPECT_COLOR_BIT
,
648 VkSubresourceLayout image_layout
;
649 wsi
->GetImageSubresourceLayout(chain
->device
, image
->image
,
650 &image_subresource
, &image_layout
);
652 image
->drm_modifier
= DRM_FORMAT_MOD_INVALID
;
653 image
->num_planes
= 1;
654 image
->sizes
[0] = reqs
.size
;
655 image
->row_pitches
[0] = image_layout
.rowPitch
;
656 image
->offsets
[0] = 0;
660 vk_free(&chain
->alloc
, modifier_props
);
661 vk_free(&chain
->alloc
, image_modifiers
);
666 vk_free(&chain
->alloc
, modifier_props
);
667 vk_free(&chain
->alloc
, image_modifiers
);
668 wsi_destroy_image(chain
, image
);
673 #define WSI_PRIME_LINEAR_STRIDE_ALIGN 256
676 wsi_create_prime_image(const struct wsi_swapchain
*chain
,
677 const VkSwapchainCreateInfoKHR
*pCreateInfo
,
679 struct wsi_image
*image
)
681 const struct wsi_device
*wsi
= chain
->wsi
;
684 memset(image
, 0, sizeof(*image
));
686 const uint32_t cpp
= vk_format_size(pCreateInfo
->imageFormat
);
687 const uint32_t linear_stride
= align_u32(pCreateInfo
->imageExtent
.width
* cpp
,
688 WSI_PRIME_LINEAR_STRIDE_ALIGN
);
690 uint32_t linear_size
= linear_stride
* pCreateInfo
->imageExtent
.height
;
691 linear_size
= align_u32(linear_size
, 4096);
693 const VkExternalMemoryBufferCreateInfo prime_buffer_external_info
= {
694 .sType
= VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO
,
696 .handleTypes
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
,
698 const VkBufferCreateInfo prime_buffer_info
= {
699 .sType
= VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO
,
700 .pNext
= &prime_buffer_external_info
,
702 .usage
= VK_BUFFER_USAGE_TRANSFER_DST_BIT
,
703 .sharingMode
= VK_SHARING_MODE_EXCLUSIVE
,
705 result
= wsi
->CreateBuffer(chain
->device
, &prime_buffer_info
,
706 &chain
->alloc
, &image
->prime
.buffer
);
707 if (result
!= VK_SUCCESS
)
710 VkMemoryRequirements reqs
;
711 wsi
->GetBufferMemoryRequirements(chain
->device
, image
->prime
.buffer
, &reqs
);
712 assert(reqs
.size
<= linear_size
);
714 const struct wsi_memory_allocate_info memory_wsi_info
= {
715 .sType
= VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA
,
717 .implicit_sync
= true,
719 const VkExportMemoryAllocateInfo prime_memory_export_info
= {
720 .sType
= VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO
,
721 .pNext
= &memory_wsi_info
,
722 .handleTypes
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
,
724 const VkMemoryDedicatedAllocateInfo prime_memory_dedicated_info
= {
725 .sType
= VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO
,
726 .pNext
= &prime_memory_export_info
,
727 .image
= VK_NULL_HANDLE
,
728 .buffer
= image
->prime
.buffer
,
730 const VkMemoryAllocateInfo prime_memory_info
= {
731 .sType
= VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO
,
732 .pNext
= &prime_memory_dedicated_info
,
733 .allocationSize
= linear_size
,
734 .memoryTypeIndex
= select_memory_type(wsi
, 0, reqs
.memoryTypeBits
),
736 result
= wsi
->AllocateMemory(chain
->device
, &prime_memory_info
,
737 &chain
->alloc
, &image
->prime
.memory
);
738 if (result
!= VK_SUCCESS
)
741 result
= wsi
->BindBufferMemory(chain
->device
, image
->prime
.buffer
,
742 image
->prime
.memory
, 0);
743 if (result
!= VK_SUCCESS
)
746 const VkImageCreateInfo image_info
= {
747 .sType
= VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
,
750 .imageType
= VK_IMAGE_TYPE_2D
,
751 .format
= pCreateInfo
->imageFormat
,
753 .width
= pCreateInfo
->imageExtent
.width
,
754 .height
= pCreateInfo
->imageExtent
.height
,
759 .samples
= VK_SAMPLE_COUNT_1_BIT
,
760 .tiling
= VK_IMAGE_TILING_OPTIMAL
,
761 .usage
= pCreateInfo
->imageUsage
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT
,
762 .sharingMode
= pCreateInfo
->imageSharingMode
,
763 .queueFamilyIndexCount
= pCreateInfo
->queueFamilyIndexCount
,
764 .pQueueFamilyIndices
= pCreateInfo
->pQueueFamilyIndices
,
765 .initialLayout
= VK_IMAGE_LAYOUT_UNDEFINED
,
767 result
= wsi
->CreateImage(chain
->device
, &image_info
,
768 &chain
->alloc
, &image
->image
);
769 if (result
!= VK_SUCCESS
)
772 wsi
->GetImageMemoryRequirements(chain
->device
, image
->image
, &reqs
);
774 const VkMemoryDedicatedAllocateInfo memory_dedicated_info
= {
775 .sType
= VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO
,
777 .image
= image
->image
,
778 .buffer
= VK_NULL_HANDLE
,
780 const VkMemoryAllocateInfo memory_info
= {
781 .sType
= VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO
,
782 .pNext
= &memory_dedicated_info
,
783 .allocationSize
= reqs
.size
,
784 .memoryTypeIndex
= select_memory_type(wsi
, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
,
785 reqs
.memoryTypeBits
),
787 result
= wsi
->AllocateMemory(chain
->device
, &memory_info
,
788 &chain
->alloc
, &image
->memory
);
789 if (result
!= VK_SUCCESS
)
792 result
= wsi
->BindImageMemory(chain
->device
, image
->image
,
794 if (result
!= VK_SUCCESS
)
797 image
->prime
.blit_cmd_buffers
=
798 vk_zalloc(&chain
->alloc
,
799 sizeof(VkCommandBuffer
) * wsi
->queue_family_count
, 8,
800 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
801 if (!image
->prime
.blit_cmd_buffers
) {
802 result
= VK_ERROR_OUT_OF_HOST_MEMORY
;
806 for (uint32_t i
= 0; i
< wsi
->queue_family_count
; i
++) {
807 const VkCommandBufferAllocateInfo cmd_buffer_info
= {
808 .sType
= VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO
,
810 .commandPool
= chain
->cmd_pools
[i
],
811 .level
= VK_COMMAND_BUFFER_LEVEL_PRIMARY
,
812 .commandBufferCount
= 1,
814 result
= wsi
->AllocateCommandBuffers(chain
->device
, &cmd_buffer_info
,
815 &image
->prime
.blit_cmd_buffers
[i
]);
816 if (result
!= VK_SUCCESS
)
819 const VkCommandBufferBeginInfo begin_info
= {
820 .sType
= VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO
,
822 wsi
->BeginCommandBuffer(image
->prime
.blit_cmd_buffers
[i
], &begin_info
);
824 struct VkBufferImageCopy buffer_image_copy
= {
826 .bufferRowLength
= linear_stride
/ cpp
,
827 .bufferImageHeight
= 0,
828 .imageSubresource
= {
829 .aspectMask
= VK_IMAGE_ASPECT_COLOR_BIT
,
834 .imageOffset
= { .x
= 0, .y
= 0, .z
= 0 },
836 .width
= pCreateInfo
->imageExtent
.width
,
837 .height
= pCreateInfo
->imageExtent
.height
,
841 wsi
->CmdCopyImageToBuffer(image
->prime
.blit_cmd_buffers
[i
],
843 VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
,
845 1, &buffer_image_copy
);
847 result
= wsi
->EndCommandBuffer(image
->prime
.blit_cmd_buffers
[i
]);
848 if (result
!= VK_SUCCESS
)
852 const VkMemoryGetFdInfoKHR linear_memory_get_fd_info
= {
853 .sType
= VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR
,
855 .memory
= image
->prime
.memory
,
856 .handleType
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
,
859 result
= wsi
->GetMemoryFdKHR(chain
->device
, &linear_memory_get_fd_info
, &fd
);
860 if (result
!= VK_SUCCESS
)
863 image
->drm_modifier
= use_modifier
? DRM_FORMAT_MOD_LINEAR
: DRM_FORMAT_MOD_INVALID
;
864 image
->num_planes
= 1;
865 image
->sizes
[0] = linear_size
;
866 image
->row_pitches
[0] = linear_stride
;
867 image
->offsets
[0] = 0;
873 wsi_destroy_image(chain
, image
);
879 wsi_destroy_image(const struct wsi_swapchain
*chain
,
880 struct wsi_image
*image
)
882 const struct wsi_device
*wsi
= chain
->wsi
;
884 if (image
->prime
.blit_cmd_buffers
) {
885 for (uint32_t i
= 0; i
< wsi
->queue_family_count
; i
++) {
886 wsi
->FreeCommandBuffers(chain
->device
, chain
->cmd_pools
[i
],
887 1, &image
->prime
.blit_cmd_buffers
[i
]);
889 vk_free(&chain
->alloc
, image
->prime
.blit_cmd_buffers
);
892 wsi
->FreeMemory(chain
->device
, image
->memory
, &chain
->alloc
);
893 wsi
->DestroyImage(chain
->device
, image
->image
, &chain
->alloc
);
894 wsi
->FreeMemory(chain
->device
, image
->prime
.memory
, &chain
->alloc
);
895 wsi
->DestroyBuffer(chain
->device
, image
->prime
.buffer
, &chain
->alloc
);
899 wsi_common_get_surface_support(struct wsi_device
*wsi_device
,
900 uint32_t queueFamilyIndex
,
901 VkSurfaceKHR _surface
,
902 VkBool32
* pSupported
)
904 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, _surface
);
905 struct wsi_interface
*iface
= wsi_device
->wsi
[surface
->platform
];
907 return iface
->get_support(surface
, wsi_device
,
908 queueFamilyIndex
, pSupported
);
912 wsi_common_get_surface_capabilities(struct wsi_device
*wsi_device
,
913 VkSurfaceKHR _surface
,
914 VkSurfaceCapabilitiesKHR
*pSurfaceCapabilities
)
916 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, _surface
);
917 struct wsi_interface
*iface
= wsi_device
->wsi
[surface
->platform
];
919 VkSurfaceCapabilities2KHR caps2
= {
920 .sType
= VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR
,
923 VkResult result
= iface
->get_capabilities2(surface
, wsi_device
, NULL
, &caps2
);
925 if (result
== VK_SUCCESS
)
926 *pSurfaceCapabilities
= caps2
.surfaceCapabilities
;
932 wsi_common_get_surface_capabilities2(struct wsi_device
*wsi_device
,
933 const VkPhysicalDeviceSurfaceInfo2KHR
*pSurfaceInfo
,
934 VkSurfaceCapabilities2KHR
*pSurfaceCapabilities
)
936 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, pSurfaceInfo
->surface
);
937 struct wsi_interface
*iface
= wsi_device
->wsi
[surface
->platform
];
939 return iface
->get_capabilities2(surface
, wsi_device
, pSurfaceInfo
->pNext
,
940 pSurfaceCapabilities
);
944 wsi_common_get_surface_capabilities2ext(
945 struct wsi_device
*wsi_device
,
946 VkSurfaceKHR _surface
,
947 VkSurfaceCapabilities2EXT
*pSurfaceCapabilities
)
949 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, _surface
);
950 struct wsi_interface
*iface
= wsi_device
->wsi
[surface
->platform
];
952 assert(pSurfaceCapabilities
->sType
==
953 VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT
);
955 struct wsi_surface_supported_counters counters
= {
956 .sType
= VK_STRUCTURE_TYPE_WSI_SURFACE_SUPPORTED_COUNTERS_MESA
,
957 .pNext
= pSurfaceCapabilities
->pNext
,
958 .supported_surface_counters
= 0,
961 VkSurfaceCapabilities2KHR caps2
= {
962 .sType
= VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR
,
966 VkResult result
= iface
->get_capabilities2(surface
, wsi_device
, NULL
, &caps2
);
968 if (result
== VK_SUCCESS
) {
969 VkSurfaceCapabilities2EXT
*ext_caps
= pSurfaceCapabilities
;
970 VkSurfaceCapabilitiesKHR khr_caps
= caps2
.surfaceCapabilities
;
972 ext_caps
->minImageCount
= khr_caps
.minImageCount
;
973 ext_caps
->maxImageCount
= khr_caps
.maxImageCount
;
974 ext_caps
->currentExtent
= khr_caps
.currentExtent
;
975 ext_caps
->minImageExtent
= khr_caps
.minImageExtent
;
976 ext_caps
->maxImageExtent
= khr_caps
.maxImageExtent
;
977 ext_caps
->maxImageArrayLayers
= khr_caps
.maxImageArrayLayers
;
978 ext_caps
->supportedTransforms
= khr_caps
.supportedTransforms
;
979 ext_caps
->currentTransform
= khr_caps
.currentTransform
;
980 ext_caps
->supportedCompositeAlpha
= khr_caps
.supportedCompositeAlpha
;
981 ext_caps
->supportedUsageFlags
= khr_caps
.supportedUsageFlags
;
982 ext_caps
->supportedSurfaceCounters
= counters
.supported_surface_counters
;
989 wsi_common_get_surface_formats(struct wsi_device
*wsi_device
,
990 VkSurfaceKHR _surface
,
991 uint32_t *pSurfaceFormatCount
,
992 VkSurfaceFormatKHR
*pSurfaceFormats
)
994 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, _surface
);
995 struct wsi_interface
*iface
= wsi_device
->wsi
[surface
->platform
];
997 return iface
->get_formats(surface
, wsi_device
,
998 pSurfaceFormatCount
, pSurfaceFormats
);
1002 wsi_common_get_surface_formats2(struct wsi_device
*wsi_device
,
1003 const VkPhysicalDeviceSurfaceInfo2KHR
*pSurfaceInfo
,
1004 uint32_t *pSurfaceFormatCount
,
1005 VkSurfaceFormat2KHR
*pSurfaceFormats
)
1007 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, pSurfaceInfo
->surface
);
1008 struct wsi_interface
*iface
= wsi_device
->wsi
[surface
->platform
];
1010 return iface
->get_formats2(surface
, wsi_device
, pSurfaceInfo
->pNext
,
1011 pSurfaceFormatCount
, pSurfaceFormats
);
1015 wsi_common_get_surface_present_modes(struct wsi_device
*wsi_device
,
1016 VkSurfaceKHR _surface
,
1017 uint32_t *pPresentModeCount
,
1018 VkPresentModeKHR
*pPresentModes
)
1020 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, _surface
);
1021 struct wsi_interface
*iface
= wsi_device
->wsi
[surface
->platform
];
1023 return iface
->get_present_modes(surface
, pPresentModeCount
,
1028 wsi_common_get_present_rectangles(struct wsi_device
*wsi_device
,
1029 VkSurfaceKHR _surface
,
1030 uint32_t* pRectCount
,
1033 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, _surface
);
1034 struct wsi_interface
*iface
= wsi_device
->wsi
[surface
->platform
];
1036 return iface
->get_present_rectangles(surface
, wsi_device
,
1037 pRectCount
, pRects
);
1041 wsi_common_create_swapchain(struct wsi_device
*wsi
,
1043 const VkSwapchainCreateInfoKHR
*pCreateInfo
,
1044 const VkAllocationCallbacks
*pAllocator
,
1045 VkSwapchainKHR
*pSwapchain
)
1047 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, pCreateInfo
->surface
);
1048 struct wsi_interface
*iface
= wsi
->wsi
[surface
->platform
];
1049 struct wsi_swapchain
*swapchain
;
1051 VkResult result
= iface
->create_swapchain(surface
, device
, wsi
,
1052 pCreateInfo
, pAllocator
,
1054 if (result
!= VK_SUCCESS
)
1057 swapchain
->fences
= vk_zalloc(pAllocator
,
1058 sizeof (*swapchain
->fences
) * swapchain
->image_count
,
1059 sizeof (*swapchain
->fences
),
1060 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
1061 if (!swapchain
->fences
) {
1062 swapchain
->destroy(swapchain
, pAllocator
);
1063 return VK_ERROR_OUT_OF_HOST_MEMORY
;
1066 *pSwapchain
= wsi_swapchain_to_handle(swapchain
);
1072 wsi_common_destroy_swapchain(VkDevice device
,
1073 VkSwapchainKHR _swapchain
,
1074 const VkAllocationCallbacks
*pAllocator
)
1076 VK_FROM_HANDLE(wsi_swapchain
, swapchain
, _swapchain
);
1080 swapchain
->destroy(swapchain
, pAllocator
);
1084 wsi_common_get_images(VkSwapchainKHR _swapchain
,
1085 uint32_t *pSwapchainImageCount
,
1086 VkImage
*pSwapchainImages
)
1088 VK_FROM_HANDLE(wsi_swapchain
, swapchain
, _swapchain
);
1089 VK_OUTARRAY_MAKE(images
, pSwapchainImages
, pSwapchainImageCount
);
1091 for (uint32_t i
= 0; i
< swapchain
->image_count
; i
++) {
1092 vk_outarray_append(&images
, image
) {
1093 *image
= swapchain
->get_wsi_image(swapchain
, i
)->image
;
1097 return vk_outarray_status(&images
);
1101 wsi_common_acquire_next_image2(const struct wsi_device
*wsi
,
1103 const VkAcquireNextImageInfoKHR
*pAcquireInfo
,
1104 uint32_t *pImageIndex
)
1106 VK_FROM_HANDLE(wsi_swapchain
, swapchain
, pAcquireInfo
->swapchain
);
1108 VkResult result
= swapchain
->acquire_next_image(swapchain
, pAcquireInfo
,
1110 if (result
!= VK_SUCCESS
&& result
!= VK_SUBOPTIMAL_KHR
)
1113 if (wsi
->set_memory_ownership
) {
1114 VkDeviceMemory mem
= swapchain
->get_wsi_image(swapchain
, *pImageIndex
)->memory
;
1115 wsi
->set_memory_ownership(swapchain
->device
, mem
, true);
1118 if (pAcquireInfo
->semaphore
!= VK_NULL_HANDLE
&&
1119 wsi
->signal_semaphore_for_memory
!= NULL
) {
1120 struct wsi_image
*image
=
1121 swapchain
->get_wsi_image(swapchain
, *pImageIndex
);
1122 wsi
->signal_semaphore_for_memory(device
, pAcquireInfo
->semaphore
,
1126 if (pAcquireInfo
->fence
!= VK_NULL_HANDLE
&&
1127 wsi
->signal_fence_for_memory
!= NULL
) {
1128 struct wsi_image
*image
=
1129 swapchain
->get_wsi_image(swapchain
, *pImageIndex
);
1130 wsi
->signal_fence_for_memory(device
, pAcquireInfo
->fence
,
1138 wsi_common_queue_present(const struct wsi_device
*wsi
,
1141 int queue_family_index
,
1142 const VkPresentInfoKHR
*pPresentInfo
)
1144 VkResult final_result
= VK_SUCCESS
;
1146 const VkPresentRegionsKHR
*regions
=
1147 vk_find_struct_const(pPresentInfo
->pNext
, PRESENT_REGIONS_KHR
);
1149 for (uint32_t i
= 0; i
< pPresentInfo
->swapchainCount
; i
++) {
1150 VK_FROM_HANDLE(wsi_swapchain
, swapchain
, pPresentInfo
->pSwapchains
[i
]);
1151 uint32_t image_index
= pPresentInfo
->pImageIndices
[i
];
1154 if (swapchain
->fences
[image_index
] == VK_NULL_HANDLE
) {
1155 const VkFenceCreateInfo fence_info
= {
1156 .sType
= VK_STRUCTURE_TYPE_FENCE_CREATE_INFO
,
1160 result
= wsi
->CreateFence(device
, &fence_info
,
1162 &swapchain
->fences
[image_index
]);
1163 if (result
!= VK_SUCCESS
)
1167 wsi
->WaitForFences(device
, 1, &swapchain
->fences
[image_index
],
1169 if (result
!= VK_SUCCESS
)
1173 wsi
->ResetFences(device
, 1, &swapchain
->fences
[image_index
]);
1174 if (result
!= VK_SUCCESS
)
1178 struct wsi_image
*image
=
1179 swapchain
->get_wsi_image(swapchain
, image_index
);
1181 struct wsi_memory_signal_submit_info mem_signal
= {
1182 .sType
= VK_STRUCTURE_TYPE_WSI_MEMORY_SIGNAL_SUBMIT_INFO_MESA
,
1184 .memory
= image
->memory
,
1187 VkSubmitInfo submit_info
= {
1188 .sType
= VK_STRUCTURE_TYPE_SUBMIT_INFO
,
1189 .pNext
= &mem_signal
,
1192 VkPipelineStageFlags
*stage_flags
= NULL
;
1194 /* We only need/want to wait on semaphores once. After that, we're
1195 * guaranteed ordering since it all happens on the same queue.
1197 submit_info
.waitSemaphoreCount
= pPresentInfo
->waitSemaphoreCount
;
1198 submit_info
.pWaitSemaphores
= pPresentInfo
->pWaitSemaphores
;
1200 /* Set up the pWaitDstStageMasks */
1201 stage_flags
= vk_alloc(&swapchain
->alloc
,
1202 sizeof(VkPipelineStageFlags
) *
1203 pPresentInfo
->waitSemaphoreCount
,
1205 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND
);
1207 result
= VK_ERROR_OUT_OF_HOST_MEMORY
;
1210 for (uint32_t s
= 0; s
< pPresentInfo
->waitSemaphoreCount
; s
++)
1211 stage_flags
[s
] = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT
;
1213 submit_info
.pWaitDstStageMask
= stage_flags
;
1216 if (swapchain
->use_prime_blit
) {
1217 /* If we are using prime blits, we need to perform the blit now. The
1218 * command buffer is attached to the image.
1220 submit_info
.commandBufferCount
= 1;
1221 submit_info
.pCommandBuffers
=
1222 &image
->prime
.blit_cmd_buffers
[queue_family_index
];
1223 mem_signal
.memory
= image
->prime
.memory
;
1226 result
= wsi
->QueueSubmit(queue
, 1, &submit_info
, swapchain
->fences
[image_index
]);
1227 vk_free(&swapchain
->alloc
, stage_flags
);
1228 if (result
!= VK_SUCCESS
)
1231 const VkPresentRegionKHR
*region
= NULL
;
1232 if (regions
&& regions
->pRegions
)
1233 region
= ®ions
->pRegions
[i
];
1235 result
= swapchain
->queue_present(swapchain
, image_index
, region
);
1236 if (result
!= VK_SUCCESS
&& result
!= VK_SUBOPTIMAL_KHR
)
1239 if (wsi
->set_memory_ownership
) {
1240 VkDeviceMemory mem
= swapchain
->get_wsi_image(swapchain
, image_index
)->memory
;
1241 wsi
->set_memory_ownership(swapchain
->device
, mem
, false);
1245 if (pPresentInfo
->pResults
!= NULL
)
1246 pPresentInfo
->pResults
[i
] = result
;
1248 /* Let the final result be our first unsuccessful result */
1249 if (final_result
== VK_SUCCESS
)
1250 final_result
= result
;
1253 return final_result
;
1257 wsi_common_get_current_time(void)
1259 struct timespec current
;
1260 clock_gettime(CLOCK_MONOTONIC
, ¤t
);
1261 return current
.tv_nsec
+ current
.tv_sec
* 1000000000ull;