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