vulkan/wsi: Really terminate DRM lease in wsi_release_display().
[mesa.git] / src / vulkan / wsi / wsi_common.c
1 /*
2 * Copyright © 2017 Intel Corporation
3 *
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:
10 *
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
13 * Software.
14 *
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
21 * IN THE SOFTWARE.
22 */
23
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"
29 #include "vk_util.h"
30
31 #include <time.h>
32 #include <unistd.h>
33 #include <xf86drm.h>
34 #include <stdlib.h>
35 #include <stdio.h>
36
37 VkResult
38 wsi_device_init(struct wsi_device *wsi,
39 VkPhysicalDevice pdevice,
40 WSI_FN_GetPhysicalDeviceProcAddr proc_addr,
41 const VkAllocationCallbacks *alloc,
42 int display_fd,
43 const struct driOptionCache *dri_options)
44 {
45 const char *present_mode;
46 UNUSED VkResult result;
47
48 memset(wsi, 0, sizeof(*wsi));
49
50 wsi->instance_alloc = *alloc;
51 wsi->pdevice = pdevice;
52
53 #define WSI_GET_CB(func) \
54 PFN_vk##func func = (PFN_vk##func)proc_addr(pdevice, "vk" #func)
55 WSI_GET_CB(GetPhysicalDeviceProperties2);
56 WSI_GET_CB(GetPhysicalDeviceMemoryProperties);
57 WSI_GET_CB(GetPhysicalDeviceQueueFamilyProperties);
58 #undef WSI_GET_CB
59
60 wsi->pci_bus_info.sType =
61 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT;
62 VkPhysicalDeviceProperties2 pdp2 = {
63 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
64 .pNext = &wsi->pci_bus_info,
65 };
66 GetPhysicalDeviceProperties2(pdevice, &pdp2);
67
68 wsi->maxImageDimension2D = pdp2.properties.limits.maxImageDimension2D;
69 wsi->override_present_mode = VK_PRESENT_MODE_MAX_ENUM_KHR;
70
71 GetPhysicalDeviceMemoryProperties(pdevice, &wsi->memory_props);
72 GetPhysicalDeviceQueueFamilyProperties(pdevice, &wsi->queue_family_count, NULL);
73
74 #define WSI_GET_CB(func) \
75 wsi->func = (PFN_vk##func)proc_addr(pdevice, "vk" #func)
76 WSI_GET_CB(AllocateMemory);
77 WSI_GET_CB(AllocateCommandBuffers);
78 WSI_GET_CB(BindBufferMemory);
79 WSI_GET_CB(BindImageMemory);
80 WSI_GET_CB(BeginCommandBuffer);
81 WSI_GET_CB(CmdCopyImageToBuffer);
82 WSI_GET_CB(CreateBuffer);
83 WSI_GET_CB(CreateCommandPool);
84 WSI_GET_CB(CreateFence);
85 WSI_GET_CB(CreateImage);
86 WSI_GET_CB(DestroyBuffer);
87 WSI_GET_CB(DestroyCommandPool);
88 WSI_GET_CB(DestroyFence);
89 WSI_GET_CB(DestroyImage);
90 WSI_GET_CB(EndCommandBuffer);
91 WSI_GET_CB(FreeMemory);
92 WSI_GET_CB(FreeCommandBuffers);
93 WSI_GET_CB(GetBufferMemoryRequirements);
94 WSI_GET_CB(GetImageDrmFormatModifierPropertiesEXT);
95 WSI_GET_CB(GetImageMemoryRequirements);
96 WSI_GET_CB(GetImageSubresourceLayout);
97 WSI_GET_CB(GetMemoryFdKHR);
98 WSI_GET_CB(GetPhysicalDeviceFormatProperties);
99 WSI_GET_CB(GetPhysicalDeviceFormatProperties2KHR);
100 WSI_GET_CB(GetPhysicalDeviceImageFormatProperties2);
101 WSI_GET_CB(ResetFences);
102 WSI_GET_CB(QueueSubmit);
103 WSI_GET_CB(WaitForFences);
104 #undef WSI_GET_CB
105
106 #ifdef VK_USE_PLATFORM_XCB_KHR
107 result = wsi_x11_init_wsi(wsi, alloc, dri_options);
108 if (result != VK_SUCCESS)
109 goto fail;
110 #endif
111
112 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
113 result = wsi_wl_init_wsi(wsi, alloc, pdevice);
114 if (result != VK_SUCCESS)
115 goto fail;
116 #endif
117
118 #ifdef VK_USE_PLATFORM_DISPLAY_KHR
119 result = wsi_display_init_wsi(wsi, alloc, display_fd);
120 if (result != VK_SUCCESS)
121 goto fail;
122 #endif
123
124 present_mode = getenv("MESA_VK_WSI_PRESENT_MODE");
125 if (present_mode) {
126 if (!strcmp(present_mode, "fifo")) {
127 wsi->override_present_mode = VK_PRESENT_MODE_FIFO_KHR;
128 } else if (!strcmp(present_mode, "mailbox")) {
129 wsi->override_present_mode = VK_PRESENT_MODE_MAILBOX_KHR;
130 } else if (!strcmp(present_mode, "immediate")) {
131 wsi->override_present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR;
132 } else {
133 fprintf(stderr, "Invalid MESA_VK_WSI_PRESENT_MODE value!\n");
134 }
135 }
136
137 if (dri_options) {
138 if (driCheckOption(dri_options, "adaptive_sync", DRI_BOOL))
139 wsi->enable_adaptive_sync = driQueryOptionb(dri_options,
140 "adaptive_sync");
141
142 if (driCheckOption(dri_options, "vk_wsi_force_bgra8_unorm_first", DRI_BOOL)) {
143 wsi->force_bgra8_unorm_first =
144 driQueryOptionb(dri_options, "vk_wsi_force_bgra8_unorm_first");
145 }
146 }
147
148 return VK_SUCCESS;
149 #if defined(VK_USE_PLATFORM_XCB_KHR) || \
150 defined(VK_USE_PLATFORM_WAYLAND_KHR) || \
151 defined(VK_USE_PLATFORM_DISPLAY_KHR)
152 fail:
153 wsi_device_finish(wsi, alloc);
154 return result;
155 #endif
156 }
157
158 void
159 wsi_device_finish(struct wsi_device *wsi,
160 const VkAllocationCallbacks *alloc)
161 {
162 #ifdef VK_USE_PLATFORM_DISPLAY_KHR
163 wsi_display_finish_wsi(wsi, alloc);
164 #endif
165 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
166 wsi_wl_finish_wsi(wsi, alloc);
167 #endif
168 #ifdef VK_USE_PLATFORM_XCB_KHR
169 wsi_x11_finish_wsi(wsi, alloc);
170 #endif
171 }
172
173 bool
174 wsi_device_matches_drm_fd(const struct wsi_device *wsi, int drm_fd)
175 {
176 drmDevicePtr fd_device;
177 int ret = drmGetDevice2(drm_fd, 0, &fd_device);
178 if (ret)
179 return false;
180
181 bool match = false;
182 switch (fd_device->bustype) {
183 case DRM_BUS_PCI:
184 match = wsi->pci_bus_info.pciDomain == fd_device->businfo.pci->domain &&
185 wsi->pci_bus_info.pciBus == fd_device->businfo.pci->bus &&
186 wsi->pci_bus_info.pciDevice == fd_device->businfo.pci->dev &&
187 wsi->pci_bus_info.pciFunction == fd_device->businfo.pci->func;
188 break;
189
190 default:
191 break;
192 }
193
194 drmFreeDevice(&fd_device);
195
196 return match;
197 }
198
199 VkResult
200 wsi_swapchain_init(const struct wsi_device *wsi,
201 struct wsi_swapchain *chain,
202 VkDevice device,
203 const VkSwapchainCreateInfoKHR *pCreateInfo,
204 const VkAllocationCallbacks *pAllocator)
205 {
206 VkResult result;
207
208 memset(chain, 0, sizeof(*chain));
209
210 vk_object_base_init(NULL, &chain->base, VK_OBJECT_TYPE_SWAPCHAIN_KHR);
211
212 chain->wsi = wsi;
213 chain->device = device;
214 chain->alloc = *pAllocator;
215 chain->use_prime_blit = false;
216
217 chain->cmd_pools =
218 vk_zalloc(pAllocator, sizeof(VkCommandPool) * wsi->queue_family_count, 8,
219 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
220 if (!chain->cmd_pools)
221 return VK_ERROR_OUT_OF_HOST_MEMORY;
222
223 for (uint32_t i = 0; i < wsi->queue_family_count; i++) {
224 const VkCommandPoolCreateInfo cmd_pool_info = {
225 .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
226 .pNext = NULL,
227 .flags = 0,
228 .queueFamilyIndex = i,
229 };
230 result = wsi->CreateCommandPool(device, &cmd_pool_info, &chain->alloc,
231 &chain->cmd_pools[i]);
232 if (result != VK_SUCCESS)
233 goto fail;
234 }
235
236 return VK_SUCCESS;
237
238 fail:
239 wsi_swapchain_finish(chain);
240 return result;
241 }
242
243 static bool
244 wsi_swapchain_is_present_mode_supported(struct wsi_device *wsi,
245 const VkSwapchainCreateInfoKHR *pCreateInfo,
246 VkPresentModeKHR mode)
247 {
248 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pCreateInfo->surface);
249 struct wsi_interface *iface = wsi->wsi[surface->platform];
250 VkPresentModeKHR *present_modes;
251 uint32_t present_mode_count;
252 bool supported = false;
253 VkResult result;
254
255 result = iface->get_present_modes(surface, &present_mode_count, NULL);
256 if (result != VK_SUCCESS)
257 return supported;
258
259 present_modes = malloc(present_mode_count * sizeof(*present_modes));
260 if (!present_modes)
261 return supported;
262
263 result = iface->get_present_modes(surface, &present_mode_count,
264 present_modes);
265 if (result != VK_SUCCESS)
266 goto fail;
267
268 for (uint32_t i = 0; i < present_mode_count; i++) {
269 if (present_modes[i] == mode) {
270 supported = true;
271 break;
272 }
273 }
274
275 fail:
276 free(present_modes);
277 return supported;
278 }
279
280 enum VkPresentModeKHR
281 wsi_swapchain_get_present_mode(struct wsi_device *wsi,
282 const VkSwapchainCreateInfoKHR *pCreateInfo)
283 {
284 if (wsi->override_present_mode == VK_PRESENT_MODE_MAX_ENUM_KHR)
285 return pCreateInfo->presentMode;
286
287 if (!wsi_swapchain_is_present_mode_supported(wsi, pCreateInfo,
288 wsi->override_present_mode)) {
289 fprintf(stderr, "Unsupported MESA_VK_WSI_PRESENT_MODE value!\n");
290 return pCreateInfo->presentMode;
291 }
292
293 return wsi->override_present_mode;
294 }
295
296 void
297 wsi_swapchain_finish(struct wsi_swapchain *chain)
298 {
299 if (chain->fences) {
300 for (unsigned i = 0; i < chain->image_count; i++)
301 chain->wsi->DestroyFence(chain->device, chain->fences[i], &chain->alloc);
302
303 vk_free(&chain->alloc, chain->fences);
304 }
305
306 for (uint32_t i = 0; i < chain->wsi->queue_family_count; i++) {
307 chain->wsi->DestroyCommandPool(chain->device, chain->cmd_pools[i],
308 &chain->alloc);
309 }
310 vk_free(&chain->alloc, chain->cmd_pools);
311
312 vk_object_base_finish(&chain->base);
313 }
314
315 static uint32_t
316 select_memory_type(const struct wsi_device *wsi,
317 VkMemoryPropertyFlags props,
318 uint32_t type_bits)
319 {
320 for (uint32_t i = 0; i < wsi->memory_props.memoryTypeCount; i++) {
321 const VkMemoryType type = wsi->memory_props.memoryTypes[i];
322 if ((type_bits & (1 << i)) && (type.propertyFlags & props) == props)
323 return i;
324 }
325
326 unreachable("No memory type found");
327 }
328
329 static uint32_t
330 vk_format_size(VkFormat format)
331 {
332 switch (format) {
333 case VK_FORMAT_B8G8R8A8_UNORM:
334 case VK_FORMAT_B8G8R8A8_SRGB:
335 return 4;
336 default:
337 unreachable("Unknown WSI Format");
338 }
339 }
340
341 static inline uint32_t
342 align_u32(uint32_t v, uint32_t a)
343 {
344 assert(a != 0 && a == (a & -a));
345 return (v + a - 1) & ~(a - 1);
346 }
347
348 VkResult
349 wsi_create_native_image(const struct wsi_swapchain *chain,
350 const VkSwapchainCreateInfoKHR *pCreateInfo,
351 uint32_t num_modifier_lists,
352 const uint32_t *num_modifiers,
353 const uint64_t *const *modifiers,
354 struct wsi_image *image)
355 {
356 const struct wsi_device *wsi = chain->wsi;
357 VkResult result;
358
359 memset(image, 0, sizeof(*image));
360 for (int i = 0; i < ARRAY_SIZE(image->fds); i++)
361 image->fds[i] = -1;
362
363 VkImageCreateInfo image_info = {
364 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
365 .flags = 0,
366 .imageType = VK_IMAGE_TYPE_2D,
367 .format = pCreateInfo->imageFormat,
368 .extent = {
369 .width = pCreateInfo->imageExtent.width,
370 .height = pCreateInfo->imageExtent.height,
371 .depth = 1,
372 },
373 .mipLevels = 1,
374 .arrayLayers = 1,
375 .samples = VK_SAMPLE_COUNT_1_BIT,
376 .tiling = VK_IMAGE_TILING_OPTIMAL,
377 .usage = pCreateInfo->imageUsage,
378 .sharingMode = pCreateInfo->imageSharingMode,
379 .queueFamilyIndexCount = pCreateInfo->queueFamilyIndexCount,
380 .pQueueFamilyIndices = pCreateInfo->pQueueFamilyIndices,
381 .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
382 };
383
384 VkImageFormatListCreateInfoKHR image_format_list;
385 if (pCreateInfo->flags & VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR) {
386 image_info.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT |
387 VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR;
388
389 const VkImageFormatListCreateInfoKHR *format_list =
390 vk_find_struct_const(pCreateInfo->pNext,
391 IMAGE_FORMAT_LIST_CREATE_INFO_KHR);
392
393 #ifndef NDEBUG
394 assume(format_list && format_list->viewFormatCount > 0);
395 bool format_found = false;
396 for (int i = 0; i < format_list->viewFormatCount; i++)
397 if (pCreateInfo->imageFormat == format_list->pViewFormats[i])
398 format_found = true;
399 assert(format_found);
400 #endif
401
402 image_format_list = *format_list;
403 image_format_list.pNext = NULL;
404 __vk_append_struct(&image_info, &image_format_list);
405 }
406
407 struct wsi_image_create_info image_wsi_info;
408 VkImageDrmFormatModifierListCreateInfoEXT image_modifier_list;
409
410 uint32_t image_modifier_count = 0, modifier_prop_count = 0;
411 struct VkDrmFormatModifierPropertiesEXT *modifier_props = NULL;
412 uint64_t *image_modifiers = NULL;
413 if (num_modifier_lists == 0) {
414 /* If we don't have modifiers, fall back to the legacy "scanout" flag */
415 image_wsi_info = (struct wsi_image_create_info) {
416 .sType = VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA,
417 .scanout = true,
418 };
419 __vk_append_struct(&image_info, &image_wsi_info);
420 } else {
421 /* The winsys can't request modifiers if we don't support them. */
422 assert(wsi->supports_modifiers);
423 struct VkDrmFormatModifierPropertiesListEXT modifier_props_list = {
424 .sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT,
425 };
426 VkFormatProperties2 format_props = {
427 .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,
428 .pNext = &modifier_props_list,
429 };
430 wsi->GetPhysicalDeviceFormatProperties2KHR(wsi->pdevice,
431 pCreateInfo->imageFormat,
432 &format_props);
433 assert(modifier_props_list.drmFormatModifierCount > 0);
434 modifier_props = vk_alloc(&chain->alloc,
435 sizeof(*modifier_props) *
436 modifier_props_list.drmFormatModifierCount,
437 8,
438 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
439 if (!modifier_props) {
440 result = VK_ERROR_OUT_OF_HOST_MEMORY;
441 goto fail;
442 }
443
444 modifier_props_list.pDrmFormatModifierProperties = modifier_props;
445 wsi->GetPhysicalDeviceFormatProperties2KHR(wsi->pdevice,
446 pCreateInfo->imageFormat,
447 &format_props);
448
449 /* Call GetImageFormatProperties with every modifier and filter the list
450 * down to those that we know work.
451 */
452 modifier_prop_count = 0;
453 for (uint32_t i = 0; i < modifier_props_list.drmFormatModifierCount; i++) {
454 VkPhysicalDeviceImageDrmFormatModifierInfoEXT mod_info = {
455 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT,
456 .drmFormatModifier = modifier_props[i].drmFormatModifier,
457 .sharingMode = pCreateInfo->imageSharingMode,
458 .queueFamilyIndexCount = pCreateInfo->queueFamilyIndexCount,
459 .pQueueFamilyIndices = pCreateInfo->pQueueFamilyIndices,
460 };
461 VkPhysicalDeviceImageFormatInfo2 format_info = {
462 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
463 .format = pCreateInfo->imageFormat,
464 .type = VK_IMAGE_TYPE_2D,
465 .tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT,
466 .usage = pCreateInfo->imageUsage,
467 .flags = image_info.flags,
468 };
469
470 VkImageFormatListCreateInfoKHR format_list;
471 if (image_info.flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) {
472 format_list = image_format_list;
473 format_list.pNext = NULL;
474 __vk_append_struct(&format_info, &format_list);
475 }
476
477 VkImageFormatProperties2 format_props = {
478 .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
479 .pNext = NULL,
480 };
481 __vk_append_struct(&format_info, &mod_info);
482 result = wsi->GetPhysicalDeviceImageFormatProperties2(wsi->pdevice,
483 &format_info,
484 &format_props);
485 if (result == VK_SUCCESS)
486 modifier_props[modifier_prop_count++] = modifier_props[i];
487 }
488
489 uint32_t max_modifier_count = 0;
490 for (uint32_t l = 0; l < num_modifier_lists; l++)
491 max_modifier_count = MAX2(max_modifier_count, num_modifiers[l]);
492
493 image_modifiers = vk_alloc(&chain->alloc,
494 sizeof(*image_modifiers) *
495 max_modifier_count,
496 8,
497 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
498 if (!image_modifiers) {
499 result = VK_ERROR_OUT_OF_HOST_MEMORY;
500 goto fail;
501 }
502
503 image_modifier_count = 0;
504 for (uint32_t l = 0; l < num_modifier_lists; l++) {
505 /* Walk the modifier lists and construct a list of supported
506 * modifiers.
507 */
508 for (uint32_t i = 0; i < num_modifiers[l]; i++) {
509 for (uint32_t j = 0; j < modifier_prop_count; j++) {
510 if (modifier_props[j].drmFormatModifier == modifiers[l][i])
511 image_modifiers[image_modifier_count++] = modifiers[l][i];
512 }
513 }
514
515 /* We only want to take the modifiers from the first list */
516 if (image_modifier_count > 0)
517 break;
518 }
519
520 if (image_modifier_count > 0) {
521 image_modifier_list = (VkImageDrmFormatModifierListCreateInfoEXT) {
522 .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT,
523 .drmFormatModifierCount = image_modifier_count,
524 .pDrmFormatModifiers = image_modifiers,
525 };
526 image_info.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
527 __vk_append_struct(&image_info, &image_modifier_list);
528 } else {
529 /* TODO: Add a proper error here */
530 assert(!"Failed to find a supported modifier! This should never "
531 "happen because LINEAR should always be available");
532 result = VK_ERROR_OUT_OF_HOST_MEMORY;
533 goto fail;
534 }
535 }
536
537 result = wsi->CreateImage(chain->device, &image_info,
538 &chain->alloc, &image->image);
539 if (result != VK_SUCCESS)
540 goto fail;
541
542 VkMemoryRequirements reqs;
543 wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs);
544
545 const struct wsi_memory_allocate_info memory_wsi_info = {
546 .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA,
547 .pNext = NULL,
548 .implicit_sync = true,
549 };
550 const VkExportMemoryAllocateInfo memory_export_info = {
551 .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
552 .pNext = &memory_wsi_info,
553 .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
554 };
555 const VkMemoryDedicatedAllocateInfo memory_dedicated_info = {
556 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
557 .pNext = &memory_export_info,
558 .image = image->image,
559 .buffer = VK_NULL_HANDLE,
560 };
561 const VkMemoryAllocateInfo memory_info = {
562 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
563 .pNext = &memory_dedicated_info,
564 .allocationSize = reqs.size,
565 .memoryTypeIndex = select_memory_type(wsi, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
566 reqs.memoryTypeBits),
567 };
568 result = wsi->AllocateMemory(chain->device, &memory_info,
569 &chain->alloc, &image->memory);
570 if (result != VK_SUCCESS)
571 goto fail;
572
573 result = wsi->BindImageMemory(chain->device, image->image,
574 image->memory, 0);
575 if (result != VK_SUCCESS)
576 goto fail;
577
578 const VkMemoryGetFdInfoKHR memory_get_fd_info = {
579 .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
580 .pNext = NULL,
581 .memory = image->memory,
582 .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
583 };
584 int fd;
585 result = wsi->GetMemoryFdKHR(chain->device, &memory_get_fd_info, &fd);
586 if (result != VK_SUCCESS)
587 goto fail;
588
589 if (num_modifier_lists > 0) {
590 VkImageDrmFormatModifierPropertiesEXT image_mod_props = {
591 .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT,
592 };
593 result = wsi->GetImageDrmFormatModifierPropertiesEXT(chain->device,
594 image->image,
595 &image_mod_props);
596 if (result != VK_SUCCESS) {
597 close(fd);
598 goto fail;
599 }
600 image->drm_modifier = image_mod_props.drmFormatModifier;
601 assert(image->drm_modifier != DRM_FORMAT_MOD_INVALID);
602
603 for (uint32_t j = 0; j < modifier_prop_count; j++) {
604 if (modifier_props[j].drmFormatModifier == image->drm_modifier) {
605 image->num_planes = modifier_props[j].drmFormatModifierPlaneCount;
606 break;
607 }
608 }
609
610 for (uint32_t p = 0; p < image->num_planes; p++) {
611 const VkImageSubresource image_subresource = {
612 .aspectMask = VK_IMAGE_ASPECT_PLANE_0_BIT << p,
613 .mipLevel = 0,
614 .arrayLayer = 0,
615 };
616 VkSubresourceLayout image_layout;
617 wsi->GetImageSubresourceLayout(chain->device, image->image,
618 &image_subresource, &image_layout);
619 image->sizes[p] = image_layout.size;
620 image->row_pitches[p] = image_layout.rowPitch;
621 image->offsets[p] = image_layout.offset;
622 if (p == 0) {
623 image->fds[p] = fd;
624 } else {
625 image->fds[p] = os_dupfd_cloexec(fd);
626 if (image->fds[p] == -1) {
627 for (uint32_t i = 0; i < p; i++)
628 close(image->fds[i]);
629
630 result = VK_ERROR_OUT_OF_HOST_MEMORY;
631 goto fail;
632 }
633 }
634 }
635 } else {
636 const VkImageSubresource image_subresource = {
637 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
638 .mipLevel = 0,
639 .arrayLayer = 0,
640 };
641 VkSubresourceLayout image_layout;
642 wsi->GetImageSubresourceLayout(chain->device, image->image,
643 &image_subresource, &image_layout);
644
645 image->drm_modifier = DRM_FORMAT_MOD_INVALID;
646 image->num_planes = 1;
647 image->sizes[0] = reqs.size;
648 image->row_pitches[0] = image_layout.rowPitch;
649 image->offsets[0] = 0;
650 image->fds[0] = fd;
651 }
652
653 vk_free(&chain->alloc, modifier_props);
654 vk_free(&chain->alloc, image_modifiers);
655
656 return VK_SUCCESS;
657
658 fail:
659 vk_free(&chain->alloc, modifier_props);
660 vk_free(&chain->alloc, image_modifiers);
661 wsi_destroy_image(chain, image);
662
663 return result;
664 }
665
666 #define WSI_PRIME_LINEAR_STRIDE_ALIGN 256
667
668 VkResult
669 wsi_create_prime_image(const struct wsi_swapchain *chain,
670 const VkSwapchainCreateInfoKHR *pCreateInfo,
671 bool use_modifier,
672 struct wsi_image *image)
673 {
674 const struct wsi_device *wsi = chain->wsi;
675 VkResult result;
676
677 memset(image, 0, sizeof(*image));
678
679 const uint32_t cpp = vk_format_size(pCreateInfo->imageFormat);
680 const uint32_t linear_stride = align_u32(pCreateInfo->imageExtent.width * cpp,
681 WSI_PRIME_LINEAR_STRIDE_ALIGN);
682
683 uint32_t linear_size = linear_stride * pCreateInfo->imageExtent.height;
684 linear_size = align_u32(linear_size, 4096);
685
686 const VkExternalMemoryBufferCreateInfo prime_buffer_external_info = {
687 .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO,
688 .pNext = NULL,
689 .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
690 };
691 const VkBufferCreateInfo prime_buffer_info = {
692 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
693 .pNext = &prime_buffer_external_info,
694 .size = linear_size,
695 .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT,
696 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
697 };
698 result = wsi->CreateBuffer(chain->device, &prime_buffer_info,
699 &chain->alloc, &image->prime.buffer);
700 if (result != VK_SUCCESS)
701 goto fail;
702
703 VkMemoryRequirements reqs;
704 wsi->GetBufferMemoryRequirements(chain->device, image->prime.buffer, &reqs);
705 assert(reqs.size <= linear_size);
706
707 const struct wsi_memory_allocate_info memory_wsi_info = {
708 .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA,
709 .pNext = NULL,
710 .implicit_sync = true,
711 };
712 const VkExportMemoryAllocateInfo prime_memory_export_info = {
713 .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
714 .pNext = &memory_wsi_info,
715 .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
716 };
717 const VkMemoryDedicatedAllocateInfo prime_memory_dedicated_info = {
718 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
719 .pNext = &prime_memory_export_info,
720 .image = VK_NULL_HANDLE,
721 .buffer = image->prime.buffer,
722 };
723 const VkMemoryAllocateInfo prime_memory_info = {
724 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
725 .pNext = &prime_memory_dedicated_info,
726 .allocationSize = linear_size,
727 .memoryTypeIndex = select_memory_type(wsi, 0, reqs.memoryTypeBits),
728 };
729 result = wsi->AllocateMemory(chain->device, &prime_memory_info,
730 &chain->alloc, &image->prime.memory);
731 if (result != VK_SUCCESS)
732 goto fail;
733
734 result = wsi->BindBufferMemory(chain->device, image->prime.buffer,
735 image->prime.memory, 0);
736 if (result != VK_SUCCESS)
737 goto fail;
738
739 const VkImageCreateInfo image_info = {
740 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
741 .pNext = NULL,
742 .flags = 0,
743 .imageType = VK_IMAGE_TYPE_2D,
744 .format = pCreateInfo->imageFormat,
745 .extent = {
746 .width = pCreateInfo->imageExtent.width,
747 .height = pCreateInfo->imageExtent.height,
748 .depth = 1,
749 },
750 .mipLevels = 1,
751 .arrayLayers = 1,
752 .samples = VK_SAMPLE_COUNT_1_BIT,
753 .tiling = VK_IMAGE_TILING_OPTIMAL,
754 .usage = pCreateInfo->imageUsage | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
755 .sharingMode = pCreateInfo->imageSharingMode,
756 .queueFamilyIndexCount = pCreateInfo->queueFamilyIndexCount,
757 .pQueueFamilyIndices = pCreateInfo->pQueueFamilyIndices,
758 .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
759 };
760 result = wsi->CreateImage(chain->device, &image_info,
761 &chain->alloc, &image->image);
762 if (result != VK_SUCCESS)
763 goto fail;
764
765 wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs);
766
767 const VkMemoryDedicatedAllocateInfo memory_dedicated_info = {
768 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
769 .pNext = NULL,
770 .image = image->image,
771 .buffer = VK_NULL_HANDLE,
772 };
773 const VkMemoryAllocateInfo memory_info = {
774 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
775 .pNext = &memory_dedicated_info,
776 .allocationSize = reqs.size,
777 .memoryTypeIndex = select_memory_type(wsi, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
778 reqs.memoryTypeBits),
779 };
780 result = wsi->AllocateMemory(chain->device, &memory_info,
781 &chain->alloc, &image->memory);
782 if (result != VK_SUCCESS)
783 goto fail;
784
785 result = wsi->BindImageMemory(chain->device, image->image,
786 image->memory, 0);
787 if (result != VK_SUCCESS)
788 goto fail;
789
790 image->prime.blit_cmd_buffers =
791 vk_zalloc(&chain->alloc,
792 sizeof(VkCommandBuffer) * wsi->queue_family_count, 8,
793 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
794 if (!image->prime.blit_cmd_buffers) {
795 result = VK_ERROR_OUT_OF_HOST_MEMORY;
796 goto fail;
797 }
798
799 for (uint32_t i = 0; i < wsi->queue_family_count; i++) {
800 const VkCommandBufferAllocateInfo cmd_buffer_info = {
801 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
802 .pNext = NULL,
803 .commandPool = chain->cmd_pools[i],
804 .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
805 .commandBufferCount = 1,
806 };
807 result = wsi->AllocateCommandBuffers(chain->device, &cmd_buffer_info,
808 &image->prime.blit_cmd_buffers[i]);
809 if (result != VK_SUCCESS)
810 goto fail;
811
812 const VkCommandBufferBeginInfo begin_info = {
813 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
814 };
815 wsi->BeginCommandBuffer(image->prime.blit_cmd_buffers[i], &begin_info);
816
817 struct VkBufferImageCopy buffer_image_copy = {
818 .bufferOffset = 0,
819 .bufferRowLength = linear_stride / cpp,
820 .bufferImageHeight = 0,
821 .imageSubresource = {
822 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
823 .mipLevel = 0,
824 .baseArrayLayer = 0,
825 .layerCount = 1,
826 },
827 .imageOffset = { .x = 0, .y = 0, .z = 0 },
828 .imageExtent = {
829 .width = pCreateInfo->imageExtent.width,
830 .height = pCreateInfo->imageExtent.height,
831 .depth = 1,
832 },
833 };
834 wsi->CmdCopyImageToBuffer(image->prime.blit_cmd_buffers[i],
835 image->image,
836 VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
837 image->prime.buffer,
838 1, &buffer_image_copy);
839
840 result = wsi->EndCommandBuffer(image->prime.blit_cmd_buffers[i]);
841 if (result != VK_SUCCESS)
842 goto fail;
843 }
844
845 const VkMemoryGetFdInfoKHR linear_memory_get_fd_info = {
846 .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
847 .pNext = NULL,
848 .memory = image->prime.memory,
849 .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
850 };
851 int fd;
852 result = wsi->GetMemoryFdKHR(chain->device, &linear_memory_get_fd_info, &fd);
853 if (result != VK_SUCCESS)
854 goto fail;
855
856 image->drm_modifier = use_modifier ? DRM_FORMAT_MOD_LINEAR : DRM_FORMAT_MOD_INVALID;
857 image->num_planes = 1;
858 image->sizes[0] = linear_size;
859 image->row_pitches[0] = linear_stride;
860 image->offsets[0] = 0;
861 image->fds[0] = fd;
862
863 return VK_SUCCESS;
864
865 fail:
866 wsi_destroy_image(chain, image);
867
868 return result;
869 }
870
871 void
872 wsi_destroy_image(const struct wsi_swapchain *chain,
873 struct wsi_image *image)
874 {
875 const struct wsi_device *wsi = chain->wsi;
876
877 if (image->prime.blit_cmd_buffers) {
878 for (uint32_t i = 0; i < wsi->queue_family_count; i++) {
879 wsi->FreeCommandBuffers(chain->device, chain->cmd_pools[i],
880 1, &image->prime.blit_cmd_buffers[i]);
881 }
882 vk_free(&chain->alloc, image->prime.blit_cmd_buffers);
883 }
884
885 wsi->FreeMemory(chain->device, image->memory, &chain->alloc);
886 wsi->DestroyImage(chain->device, image->image, &chain->alloc);
887 wsi->FreeMemory(chain->device, image->prime.memory, &chain->alloc);
888 wsi->DestroyBuffer(chain->device, image->prime.buffer, &chain->alloc);
889 }
890
891 VkResult
892 wsi_common_get_surface_support(struct wsi_device *wsi_device,
893 uint32_t queueFamilyIndex,
894 VkSurfaceKHR _surface,
895 VkBool32* pSupported)
896 {
897 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
898 struct wsi_interface *iface = wsi_device->wsi[surface->platform];
899
900 return iface->get_support(surface, wsi_device,
901 queueFamilyIndex, pSupported);
902 }
903
904 VkResult
905 wsi_common_get_surface_capabilities(struct wsi_device *wsi_device,
906 VkSurfaceKHR _surface,
907 VkSurfaceCapabilitiesKHR *pSurfaceCapabilities)
908 {
909 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
910 struct wsi_interface *iface = wsi_device->wsi[surface->platform];
911
912 VkSurfaceCapabilities2KHR caps2 = {
913 .sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR,
914 };
915
916 VkResult result = iface->get_capabilities2(surface, wsi_device, NULL, &caps2);
917
918 if (result == VK_SUCCESS)
919 *pSurfaceCapabilities = caps2.surfaceCapabilities;
920
921 return result;
922 }
923
924 VkResult
925 wsi_common_get_surface_capabilities2(struct wsi_device *wsi_device,
926 const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
927 VkSurfaceCapabilities2KHR *pSurfaceCapabilities)
928 {
929 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pSurfaceInfo->surface);
930 struct wsi_interface *iface = wsi_device->wsi[surface->platform];
931
932 return iface->get_capabilities2(surface, wsi_device, pSurfaceInfo->pNext,
933 pSurfaceCapabilities);
934 }
935
936 VkResult
937 wsi_common_get_surface_capabilities2ext(
938 struct wsi_device *wsi_device,
939 VkSurfaceKHR _surface,
940 VkSurfaceCapabilities2EXT *pSurfaceCapabilities)
941 {
942 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
943 struct wsi_interface *iface = wsi_device->wsi[surface->platform];
944
945 assert(pSurfaceCapabilities->sType ==
946 VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT);
947
948 struct wsi_surface_supported_counters counters = {
949 .sType = VK_STRUCTURE_TYPE_WSI_SURFACE_SUPPORTED_COUNTERS_MESA,
950 .pNext = pSurfaceCapabilities->pNext,
951 .supported_surface_counters = 0,
952 };
953
954 VkSurfaceCapabilities2KHR caps2 = {
955 .sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR,
956 .pNext = &counters,
957 };
958
959 VkResult result = iface->get_capabilities2(surface, wsi_device, NULL, &caps2);
960
961 if (result == VK_SUCCESS) {
962 VkSurfaceCapabilities2EXT *ext_caps = pSurfaceCapabilities;
963 VkSurfaceCapabilitiesKHR khr_caps = caps2.surfaceCapabilities;
964
965 ext_caps->minImageCount = khr_caps.minImageCount;
966 ext_caps->maxImageCount = khr_caps.maxImageCount;
967 ext_caps->currentExtent = khr_caps.currentExtent;
968 ext_caps->minImageExtent = khr_caps.minImageExtent;
969 ext_caps->maxImageExtent = khr_caps.maxImageExtent;
970 ext_caps->maxImageArrayLayers = khr_caps.maxImageArrayLayers;
971 ext_caps->supportedTransforms = khr_caps.supportedTransforms;
972 ext_caps->currentTransform = khr_caps.currentTransform;
973 ext_caps->supportedCompositeAlpha = khr_caps.supportedCompositeAlpha;
974 ext_caps->supportedUsageFlags = khr_caps.supportedUsageFlags;
975 ext_caps->supportedSurfaceCounters = counters.supported_surface_counters;
976 }
977
978 return result;
979 }
980
981 VkResult
982 wsi_common_get_surface_formats(struct wsi_device *wsi_device,
983 VkSurfaceKHR _surface,
984 uint32_t *pSurfaceFormatCount,
985 VkSurfaceFormatKHR *pSurfaceFormats)
986 {
987 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
988 struct wsi_interface *iface = wsi_device->wsi[surface->platform];
989
990 return iface->get_formats(surface, wsi_device,
991 pSurfaceFormatCount, pSurfaceFormats);
992 }
993
994 VkResult
995 wsi_common_get_surface_formats2(struct wsi_device *wsi_device,
996 const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
997 uint32_t *pSurfaceFormatCount,
998 VkSurfaceFormat2KHR *pSurfaceFormats)
999 {
1000 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pSurfaceInfo->surface);
1001 struct wsi_interface *iface = wsi_device->wsi[surface->platform];
1002
1003 return iface->get_formats2(surface, wsi_device, pSurfaceInfo->pNext,
1004 pSurfaceFormatCount, pSurfaceFormats);
1005 }
1006
1007 VkResult
1008 wsi_common_get_surface_present_modes(struct wsi_device *wsi_device,
1009 VkSurfaceKHR _surface,
1010 uint32_t *pPresentModeCount,
1011 VkPresentModeKHR *pPresentModes)
1012 {
1013 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
1014 struct wsi_interface *iface = wsi_device->wsi[surface->platform];
1015
1016 return iface->get_present_modes(surface, pPresentModeCount,
1017 pPresentModes);
1018 }
1019
1020 VkResult
1021 wsi_common_get_present_rectangles(struct wsi_device *wsi_device,
1022 VkSurfaceKHR _surface,
1023 uint32_t* pRectCount,
1024 VkRect2D* pRects)
1025 {
1026 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
1027 struct wsi_interface *iface = wsi_device->wsi[surface->platform];
1028
1029 return iface->get_present_rectangles(surface, wsi_device,
1030 pRectCount, pRects);
1031 }
1032
1033 VkResult
1034 wsi_common_create_swapchain(struct wsi_device *wsi,
1035 VkDevice device,
1036 const VkSwapchainCreateInfoKHR *pCreateInfo,
1037 const VkAllocationCallbacks *pAllocator,
1038 VkSwapchainKHR *pSwapchain)
1039 {
1040 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pCreateInfo->surface);
1041 struct wsi_interface *iface = wsi->wsi[surface->platform];
1042 struct wsi_swapchain *swapchain;
1043
1044 VkResult result = iface->create_swapchain(surface, device, wsi,
1045 pCreateInfo, pAllocator,
1046 &swapchain);
1047 if (result != VK_SUCCESS)
1048 return result;
1049
1050 swapchain->fences = vk_zalloc(pAllocator,
1051 sizeof (*swapchain->fences) * swapchain->image_count,
1052 sizeof (*swapchain->fences),
1053 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1054 if (!swapchain->fences) {
1055 swapchain->destroy(swapchain, pAllocator);
1056 return VK_ERROR_OUT_OF_HOST_MEMORY;
1057 }
1058
1059 *pSwapchain = wsi_swapchain_to_handle(swapchain);
1060
1061 return VK_SUCCESS;
1062 }
1063
1064 void
1065 wsi_common_destroy_swapchain(VkDevice device,
1066 VkSwapchainKHR _swapchain,
1067 const VkAllocationCallbacks *pAllocator)
1068 {
1069 VK_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain);
1070 if (!swapchain)
1071 return;
1072
1073 swapchain->destroy(swapchain, pAllocator);
1074 }
1075
1076 VkResult
1077 wsi_common_get_images(VkSwapchainKHR _swapchain,
1078 uint32_t *pSwapchainImageCount,
1079 VkImage *pSwapchainImages)
1080 {
1081 VK_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain);
1082 VK_OUTARRAY_MAKE(images, pSwapchainImages, pSwapchainImageCount);
1083
1084 for (uint32_t i = 0; i < swapchain->image_count; i++) {
1085 vk_outarray_append(&images, image) {
1086 *image = swapchain->get_wsi_image(swapchain, i)->image;
1087 }
1088 }
1089
1090 return vk_outarray_status(&images);
1091 }
1092
1093 VkResult
1094 wsi_common_acquire_next_image2(const struct wsi_device *wsi,
1095 VkDevice device,
1096 const VkAcquireNextImageInfoKHR *pAcquireInfo,
1097 uint32_t *pImageIndex)
1098 {
1099 VK_FROM_HANDLE(wsi_swapchain, swapchain, pAcquireInfo->swapchain);
1100
1101 VkResult result = swapchain->acquire_next_image(swapchain, pAcquireInfo,
1102 pImageIndex);
1103 if (result != VK_SUCCESS)
1104 return result;
1105
1106 if (wsi->set_memory_ownership) {
1107 VkDeviceMemory mem = swapchain->get_wsi_image(swapchain, *pImageIndex)->memory;
1108 wsi->set_memory_ownership(swapchain->device, mem, true);
1109 }
1110
1111 if (pAcquireInfo->semaphore != VK_NULL_HANDLE &&
1112 wsi->signal_semaphore_for_memory != NULL) {
1113 struct wsi_image *image =
1114 swapchain->get_wsi_image(swapchain, *pImageIndex);
1115 wsi->signal_semaphore_for_memory(device, pAcquireInfo->semaphore,
1116 image->memory);
1117 }
1118
1119 if (pAcquireInfo->fence != VK_NULL_HANDLE &&
1120 wsi->signal_fence_for_memory != NULL) {
1121 struct wsi_image *image =
1122 swapchain->get_wsi_image(swapchain, *pImageIndex);
1123 wsi->signal_fence_for_memory(device, pAcquireInfo->fence,
1124 image->memory);
1125 }
1126
1127 return VK_SUCCESS;
1128 }
1129
1130 VkResult
1131 wsi_common_queue_present(const struct wsi_device *wsi,
1132 VkDevice device,
1133 VkQueue queue,
1134 int queue_family_index,
1135 const VkPresentInfoKHR *pPresentInfo)
1136 {
1137 VkResult final_result = VK_SUCCESS;
1138
1139 const VkPresentRegionsKHR *regions =
1140 vk_find_struct_const(pPresentInfo->pNext, PRESENT_REGIONS_KHR);
1141
1142 for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) {
1143 VK_FROM_HANDLE(wsi_swapchain, swapchain, pPresentInfo->pSwapchains[i]);
1144 uint32_t image_index = pPresentInfo->pImageIndices[i];
1145 VkResult result;
1146
1147 if (swapchain->fences[image_index] == VK_NULL_HANDLE) {
1148 const VkFenceCreateInfo fence_info = {
1149 .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
1150 .pNext = NULL,
1151 .flags = 0,
1152 };
1153 result = wsi->CreateFence(device, &fence_info,
1154 &swapchain->alloc,
1155 &swapchain->fences[image_index]);
1156 if (result != VK_SUCCESS)
1157 goto fail_present;
1158 } else {
1159 result =
1160 wsi->WaitForFences(device, 1, &swapchain->fences[image_index],
1161 true, ~0ull);
1162 if (result != VK_SUCCESS)
1163 goto fail_present;
1164
1165 result =
1166 wsi->ResetFences(device, 1, &swapchain->fences[image_index]);
1167 if (result != VK_SUCCESS)
1168 goto fail_present;
1169 }
1170
1171 struct wsi_image *image =
1172 swapchain->get_wsi_image(swapchain, image_index);
1173
1174 struct wsi_memory_signal_submit_info mem_signal = {
1175 .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_SIGNAL_SUBMIT_INFO_MESA,
1176 .pNext = NULL,
1177 .memory = image->memory,
1178 };
1179
1180 VkSubmitInfo submit_info = {
1181 .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
1182 .pNext = &mem_signal,
1183 };
1184
1185 VkPipelineStageFlags *stage_flags = NULL;
1186 if (i == 0) {
1187 /* We only need/want to wait on semaphores once. After that, we're
1188 * guaranteed ordering since it all happens on the same queue.
1189 */
1190 submit_info.waitSemaphoreCount = pPresentInfo->waitSemaphoreCount;
1191 submit_info.pWaitSemaphores = pPresentInfo->pWaitSemaphores;
1192
1193 /* Set up the pWaitDstStageMasks */
1194 stage_flags = vk_alloc(&swapchain->alloc,
1195 sizeof(VkPipelineStageFlags) *
1196 pPresentInfo->waitSemaphoreCount,
1197 8,
1198 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
1199 if (!stage_flags) {
1200 result = VK_ERROR_OUT_OF_HOST_MEMORY;
1201 goto fail_present;
1202 }
1203 for (uint32_t s = 0; s < pPresentInfo->waitSemaphoreCount; s++)
1204 stage_flags[s] = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
1205
1206 submit_info.pWaitDstStageMask = stage_flags;
1207 }
1208
1209 if (swapchain->use_prime_blit) {
1210 /* If we are using prime blits, we need to perform the blit now. The
1211 * command buffer is attached to the image.
1212 */
1213 submit_info.commandBufferCount = 1;
1214 submit_info.pCommandBuffers =
1215 &image->prime.blit_cmd_buffers[queue_family_index];
1216 mem_signal.memory = image->prime.memory;
1217 }
1218
1219 result = wsi->QueueSubmit(queue, 1, &submit_info, swapchain->fences[image_index]);
1220 vk_free(&swapchain->alloc, stage_flags);
1221 if (result != VK_SUCCESS)
1222 goto fail_present;
1223
1224 const VkPresentRegionKHR *region = NULL;
1225 if (regions && regions->pRegions)
1226 region = &regions->pRegions[i];
1227
1228 result = swapchain->queue_present(swapchain, image_index, region);
1229 if (result != VK_SUCCESS)
1230 goto fail_present;
1231
1232 if (wsi->set_memory_ownership) {
1233 VkDeviceMemory mem = swapchain->get_wsi_image(swapchain, image_index)->memory;
1234 wsi->set_memory_ownership(swapchain->device, mem, false);
1235 }
1236
1237 fail_present:
1238 if (pPresentInfo->pResults != NULL)
1239 pPresentInfo->pResults[i] = result;
1240
1241 /* Let the final result be our first unsuccessful result */
1242 if (final_result == VK_SUCCESS)
1243 final_result = result;
1244 }
1245
1246 return final_result;
1247 }
1248
1249 uint64_t
1250 wsi_common_get_current_time(void)
1251 {
1252 struct timespec current;
1253 clock_gettime(CLOCK_MONOTONIC, &current);
1254 return current.tv_nsec + current.tv_sec * 1000000000ull;
1255 }