d629ea339ac36956e9e7237962d0194d3e049793
[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[i]);
624
625 result = VK_ERROR_OUT_OF_HOST_MEMORY;
626 goto fail;
627 }
628 }
629 }
630 } else {
631 const VkImageSubresource image_subresource = {
632 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
633 .mipLevel = 0,
634 .arrayLayer = 0,
635 };
636 VkSubresourceLayout image_layout;
637 wsi->GetImageSubresourceLayout(chain->device, image->image,
638 &image_subresource, &image_layout);
639
640 image->drm_modifier = DRM_FORMAT_MOD_INVALID;
641 image->num_planes = 1;
642 image->sizes[0] = reqs.size;
643 image->row_pitches[0] = image_layout.rowPitch;
644 image->offsets[0] = 0;
645 image->fds[0] = fd;
646 }
647
648 vk_free(&chain->alloc, modifier_props);
649 vk_free(&chain->alloc, image_modifiers);
650
651 return VK_SUCCESS;
652
653 fail:
654 vk_free(&chain->alloc, modifier_props);
655 vk_free(&chain->alloc, image_modifiers);
656 wsi_destroy_image(chain, image);
657
658 return result;
659 }
660
661 #define WSI_PRIME_LINEAR_STRIDE_ALIGN 256
662
663 VkResult
664 wsi_create_prime_image(const struct wsi_swapchain *chain,
665 const VkSwapchainCreateInfoKHR *pCreateInfo,
666 bool use_modifier,
667 struct wsi_image *image)
668 {
669 const struct wsi_device *wsi = chain->wsi;
670 VkResult result;
671
672 memset(image, 0, sizeof(*image));
673
674 const uint32_t cpp = vk_format_size(pCreateInfo->imageFormat);
675 const uint32_t linear_stride = align_u32(pCreateInfo->imageExtent.width * cpp,
676 WSI_PRIME_LINEAR_STRIDE_ALIGN);
677
678 uint32_t linear_size = linear_stride * pCreateInfo->imageExtent.height;
679 linear_size = align_u32(linear_size, 4096);
680
681 const VkExternalMemoryBufferCreateInfo prime_buffer_external_info = {
682 .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO,
683 .pNext = NULL,
684 .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
685 };
686 const VkBufferCreateInfo prime_buffer_info = {
687 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
688 .pNext = &prime_buffer_external_info,
689 .size = linear_size,
690 .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT,
691 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
692 };
693 result = wsi->CreateBuffer(chain->device, &prime_buffer_info,
694 &chain->alloc, &image->prime.buffer);
695 if (result != VK_SUCCESS)
696 goto fail;
697
698 VkMemoryRequirements reqs;
699 wsi->GetBufferMemoryRequirements(chain->device, image->prime.buffer, &reqs);
700 assert(reqs.size <= linear_size);
701
702 const struct wsi_memory_allocate_info memory_wsi_info = {
703 .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA,
704 .pNext = NULL,
705 .implicit_sync = true,
706 };
707 const VkExportMemoryAllocateInfo prime_memory_export_info = {
708 .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
709 .pNext = &memory_wsi_info,
710 .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
711 };
712 const VkMemoryDedicatedAllocateInfo prime_memory_dedicated_info = {
713 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
714 .pNext = &prime_memory_export_info,
715 .image = VK_NULL_HANDLE,
716 .buffer = image->prime.buffer,
717 };
718 const VkMemoryAllocateInfo prime_memory_info = {
719 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
720 .pNext = &prime_memory_dedicated_info,
721 .allocationSize = linear_size,
722 .memoryTypeIndex = select_memory_type(wsi, 0, reqs.memoryTypeBits),
723 };
724 result = wsi->AllocateMemory(chain->device, &prime_memory_info,
725 &chain->alloc, &image->prime.memory);
726 if (result != VK_SUCCESS)
727 goto fail;
728
729 result = wsi->BindBufferMemory(chain->device, image->prime.buffer,
730 image->prime.memory, 0);
731 if (result != VK_SUCCESS)
732 goto fail;
733
734 const VkImageCreateInfo image_info = {
735 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
736 .pNext = NULL,
737 .flags = 0,
738 .imageType = VK_IMAGE_TYPE_2D,
739 .format = pCreateInfo->imageFormat,
740 .extent = {
741 .width = pCreateInfo->imageExtent.width,
742 .height = pCreateInfo->imageExtent.height,
743 .depth = 1,
744 },
745 .mipLevels = 1,
746 .arrayLayers = 1,
747 .samples = VK_SAMPLE_COUNT_1_BIT,
748 .tiling = VK_IMAGE_TILING_OPTIMAL,
749 .usage = pCreateInfo->imageUsage | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
750 .sharingMode = pCreateInfo->imageSharingMode,
751 .queueFamilyIndexCount = pCreateInfo->queueFamilyIndexCount,
752 .pQueueFamilyIndices = pCreateInfo->pQueueFamilyIndices,
753 .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
754 };
755 result = wsi->CreateImage(chain->device, &image_info,
756 &chain->alloc, &image->image);
757 if (result != VK_SUCCESS)
758 goto fail;
759
760 wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs);
761
762 const VkMemoryDedicatedAllocateInfo memory_dedicated_info = {
763 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
764 .pNext = NULL,
765 .image = image->image,
766 .buffer = VK_NULL_HANDLE,
767 };
768 const VkMemoryAllocateInfo memory_info = {
769 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
770 .pNext = &memory_dedicated_info,
771 .allocationSize = reqs.size,
772 .memoryTypeIndex = select_memory_type(wsi, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
773 reqs.memoryTypeBits),
774 };
775 result = wsi->AllocateMemory(chain->device, &memory_info,
776 &chain->alloc, &image->memory);
777 if (result != VK_SUCCESS)
778 goto fail;
779
780 result = wsi->BindImageMemory(chain->device, image->image,
781 image->memory, 0);
782 if (result != VK_SUCCESS)
783 goto fail;
784
785 image->prime.blit_cmd_buffers =
786 vk_zalloc(&chain->alloc,
787 sizeof(VkCommandBuffer) * wsi->queue_family_count, 8,
788 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
789 if (!image->prime.blit_cmd_buffers) {
790 result = VK_ERROR_OUT_OF_HOST_MEMORY;
791 goto fail;
792 }
793
794 for (uint32_t i = 0; i < wsi->queue_family_count; i++) {
795 const VkCommandBufferAllocateInfo cmd_buffer_info = {
796 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
797 .pNext = NULL,
798 .commandPool = chain->cmd_pools[i],
799 .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
800 .commandBufferCount = 1,
801 };
802 result = wsi->AllocateCommandBuffers(chain->device, &cmd_buffer_info,
803 &image->prime.blit_cmd_buffers[i]);
804 if (result != VK_SUCCESS)
805 goto fail;
806
807 const VkCommandBufferBeginInfo begin_info = {
808 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
809 };
810 wsi->BeginCommandBuffer(image->prime.blit_cmd_buffers[i], &begin_info);
811
812 struct VkBufferImageCopy buffer_image_copy = {
813 .bufferOffset = 0,
814 .bufferRowLength = linear_stride / cpp,
815 .bufferImageHeight = 0,
816 .imageSubresource = {
817 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
818 .mipLevel = 0,
819 .baseArrayLayer = 0,
820 .layerCount = 1,
821 },
822 .imageOffset = { .x = 0, .y = 0, .z = 0 },
823 .imageExtent = {
824 .width = pCreateInfo->imageExtent.width,
825 .height = pCreateInfo->imageExtent.height,
826 .depth = 1,
827 },
828 };
829 wsi->CmdCopyImageToBuffer(image->prime.blit_cmd_buffers[i],
830 image->image,
831 VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
832 image->prime.buffer,
833 1, &buffer_image_copy);
834
835 result = wsi->EndCommandBuffer(image->prime.blit_cmd_buffers[i]);
836 if (result != VK_SUCCESS)
837 goto fail;
838 }
839
840 const VkMemoryGetFdInfoKHR linear_memory_get_fd_info = {
841 .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
842 .pNext = NULL,
843 .memory = image->prime.memory,
844 .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
845 };
846 int fd;
847 result = wsi->GetMemoryFdKHR(chain->device, &linear_memory_get_fd_info, &fd);
848 if (result != VK_SUCCESS)
849 goto fail;
850
851 image->drm_modifier = use_modifier ? DRM_FORMAT_MOD_LINEAR : DRM_FORMAT_MOD_INVALID;
852 image->num_planes = 1;
853 image->sizes[0] = linear_size;
854 image->row_pitches[0] = linear_stride;
855 image->offsets[0] = 0;
856 image->fds[0] = fd;
857
858 return VK_SUCCESS;
859
860 fail:
861 wsi_destroy_image(chain, image);
862
863 return result;
864 }
865
866 void
867 wsi_destroy_image(const struct wsi_swapchain *chain,
868 struct wsi_image *image)
869 {
870 const struct wsi_device *wsi = chain->wsi;
871
872 if (image->prime.blit_cmd_buffers) {
873 for (uint32_t i = 0; i < wsi->queue_family_count; i++) {
874 wsi->FreeCommandBuffers(chain->device, chain->cmd_pools[i],
875 1, &image->prime.blit_cmd_buffers[i]);
876 }
877 vk_free(&chain->alloc, image->prime.blit_cmd_buffers);
878 }
879
880 wsi->FreeMemory(chain->device, image->memory, &chain->alloc);
881 wsi->DestroyImage(chain->device, image->image, &chain->alloc);
882 wsi->FreeMemory(chain->device, image->prime.memory, &chain->alloc);
883 wsi->DestroyBuffer(chain->device, image->prime.buffer, &chain->alloc);
884 }
885
886 VkResult
887 wsi_common_get_surface_support(struct wsi_device *wsi_device,
888 uint32_t queueFamilyIndex,
889 VkSurfaceKHR _surface,
890 VkBool32* pSupported)
891 {
892 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
893 struct wsi_interface *iface = wsi_device->wsi[surface->platform];
894
895 return iface->get_support(surface, wsi_device,
896 queueFamilyIndex, pSupported);
897 }
898
899 VkResult
900 wsi_common_get_surface_capabilities(struct wsi_device *wsi_device,
901 VkSurfaceKHR _surface,
902 VkSurfaceCapabilitiesKHR *pSurfaceCapabilities)
903 {
904 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
905 struct wsi_interface *iface = wsi_device->wsi[surface->platform];
906
907 VkSurfaceCapabilities2KHR caps2 = {
908 .sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR,
909 };
910
911 VkResult result = iface->get_capabilities2(surface, wsi_device, NULL, &caps2);
912
913 if (result == VK_SUCCESS)
914 *pSurfaceCapabilities = caps2.surfaceCapabilities;
915
916 return result;
917 }
918
919 VkResult
920 wsi_common_get_surface_capabilities2(struct wsi_device *wsi_device,
921 const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
922 VkSurfaceCapabilities2KHR *pSurfaceCapabilities)
923 {
924 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pSurfaceInfo->surface);
925 struct wsi_interface *iface = wsi_device->wsi[surface->platform];
926
927 return iface->get_capabilities2(surface, wsi_device, pSurfaceInfo->pNext,
928 pSurfaceCapabilities);
929 }
930
931 VkResult
932 wsi_common_get_surface_capabilities2ext(
933 struct wsi_device *wsi_device,
934 VkSurfaceKHR _surface,
935 VkSurfaceCapabilities2EXT *pSurfaceCapabilities)
936 {
937 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
938 struct wsi_interface *iface = wsi_device->wsi[surface->platform];
939
940 assert(pSurfaceCapabilities->sType ==
941 VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT);
942
943 struct wsi_surface_supported_counters counters = {
944 .sType = VK_STRUCTURE_TYPE_WSI_SURFACE_SUPPORTED_COUNTERS_MESA,
945 .pNext = pSurfaceCapabilities->pNext,
946 .supported_surface_counters = 0,
947 };
948
949 VkSurfaceCapabilities2KHR caps2 = {
950 .sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR,
951 .pNext = &counters,
952 };
953
954 VkResult result = iface->get_capabilities2(surface, wsi_device, NULL, &caps2);
955
956 if (result == VK_SUCCESS) {
957 VkSurfaceCapabilities2EXT *ext_caps = pSurfaceCapabilities;
958 VkSurfaceCapabilitiesKHR khr_caps = caps2.surfaceCapabilities;
959
960 ext_caps->minImageCount = khr_caps.minImageCount;
961 ext_caps->maxImageCount = khr_caps.maxImageCount;
962 ext_caps->currentExtent = khr_caps.currentExtent;
963 ext_caps->minImageExtent = khr_caps.minImageExtent;
964 ext_caps->maxImageExtent = khr_caps.maxImageExtent;
965 ext_caps->maxImageArrayLayers = khr_caps.maxImageArrayLayers;
966 ext_caps->supportedTransforms = khr_caps.supportedTransforms;
967 ext_caps->currentTransform = khr_caps.currentTransform;
968 ext_caps->supportedCompositeAlpha = khr_caps.supportedCompositeAlpha;
969 ext_caps->supportedUsageFlags = khr_caps.supportedUsageFlags;
970 ext_caps->supportedSurfaceCounters = counters.supported_surface_counters;
971 }
972
973 return result;
974 }
975
976 VkResult
977 wsi_common_get_surface_formats(struct wsi_device *wsi_device,
978 VkSurfaceKHR _surface,
979 uint32_t *pSurfaceFormatCount,
980 VkSurfaceFormatKHR *pSurfaceFormats)
981 {
982 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
983 struct wsi_interface *iface = wsi_device->wsi[surface->platform];
984
985 return iface->get_formats(surface, wsi_device,
986 pSurfaceFormatCount, pSurfaceFormats);
987 }
988
989 VkResult
990 wsi_common_get_surface_formats2(struct wsi_device *wsi_device,
991 const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
992 uint32_t *pSurfaceFormatCount,
993 VkSurfaceFormat2KHR *pSurfaceFormats)
994 {
995 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pSurfaceInfo->surface);
996 struct wsi_interface *iface = wsi_device->wsi[surface->platform];
997
998 return iface->get_formats2(surface, wsi_device, pSurfaceInfo->pNext,
999 pSurfaceFormatCount, pSurfaceFormats);
1000 }
1001
1002 VkResult
1003 wsi_common_get_surface_present_modes(struct wsi_device *wsi_device,
1004 VkSurfaceKHR _surface,
1005 uint32_t *pPresentModeCount,
1006 VkPresentModeKHR *pPresentModes)
1007 {
1008 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
1009 struct wsi_interface *iface = wsi_device->wsi[surface->platform];
1010
1011 return iface->get_present_modes(surface, pPresentModeCount,
1012 pPresentModes);
1013 }
1014
1015 VkResult
1016 wsi_common_get_present_rectangles(struct wsi_device *wsi_device,
1017 VkSurfaceKHR _surface,
1018 uint32_t* pRectCount,
1019 VkRect2D* pRects)
1020 {
1021 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
1022 struct wsi_interface *iface = wsi_device->wsi[surface->platform];
1023
1024 return iface->get_present_rectangles(surface, wsi_device,
1025 pRectCount, pRects);
1026 }
1027
1028 VkResult
1029 wsi_common_create_swapchain(struct wsi_device *wsi,
1030 VkDevice device,
1031 const VkSwapchainCreateInfoKHR *pCreateInfo,
1032 const VkAllocationCallbacks *pAllocator,
1033 VkSwapchainKHR *pSwapchain)
1034 {
1035 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pCreateInfo->surface);
1036 struct wsi_interface *iface = wsi->wsi[surface->platform];
1037 struct wsi_swapchain *swapchain;
1038
1039 VkResult result = iface->create_swapchain(surface, device, wsi,
1040 pCreateInfo, pAllocator,
1041 &swapchain);
1042 if (result != VK_SUCCESS)
1043 return result;
1044
1045 swapchain->fences = vk_zalloc(pAllocator,
1046 sizeof (*swapchain->fences) * swapchain->image_count,
1047 sizeof (*swapchain->fences),
1048 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1049 if (!swapchain->fences) {
1050 swapchain->destroy(swapchain, pAllocator);
1051 return VK_ERROR_OUT_OF_HOST_MEMORY;
1052 }
1053
1054 *pSwapchain = wsi_swapchain_to_handle(swapchain);
1055
1056 return VK_SUCCESS;
1057 }
1058
1059 void
1060 wsi_common_destroy_swapchain(VkDevice device,
1061 VkSwapchainKHR _swapchain,
1062 const VkAllocationCallbacks *pAllocator)
1063 {
1064 WSI_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain);
1065 if (!swapchain)
1066 return;
1067
1068 swapchain->destroy(swapchain, pAllocator);
1069 }
1070
1071 VkResult
1072 wsi_common_get_images(VkSwapchainKHR _swapchain,
1073 uint32_t *pSwapchainImageCount,
1074 VkImage *pSwapchainImages)
1075 {
1076 WSI_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain);
1077 VK_OUTARRAY_MAKE(images, pSwapchainImages, pSwapchainImageCount);
1078
1079 for (uint32_t i = 0; i < swapchain->image_count; i++) {
1080 vk_outarray_append(&images, image) {
1081 *image = swapchain->get_wsi_image(swapchain, i)->image;
1082 }
1083 }
1084
1085 return vk_outarray_status(&images);
1086 }
1087
1088 VkResult
1089 wsi_common_acquire_next_image2(const struct wsi_device *wsi,
1090 VkDevice device,
1091 const VkAcquireNextImageInfoKHR *pAcquireInfo,
1092 uint32_t *pImageIndex)
1093 {
1094 WSI_FROM_HANDLE(wsi_swapchain, swapchain, pAcquireInfo->swapchain);
1095
1096 VkResult result = swapchain->acquire_next_image(swapchain, pAcquireInfo,
1097 pImageIndex);
1098 if (result != VK_SUCCESS)
1099 return result;
1100
1101 if (pAcquireInfo->semaphore != VK_NULL_HANDLE &&
1102 wsi->signal_semaphore_for_memory != NULL) {
1103 struct wsi_image *image =
1104 swapchain->get_wsi_image(swapchain, *pImageIndex);
1105 wsi->signal_semaphore_for_memory(device, pAcquireInfo->semaphore,
1106 image->memory);
1107 }
1108
1109 if (pAcquireInfo->fence != VK_NULL_HANDLE &&
1110 wsi->signal_fence_for_memory != NULL) {
1111 struct wsi_image *image =
1112 swapchain->get_wsi_image(swapchain, *pImageIndex);
1113 wsi->signal_fence_for_memory(device, pAcquireInfo->fence,
1114 image->memory);
1115 }
1116
1117 return VK_SUCCESS;
1118 }
1119
1120 VkResult
1121 wsi_common_queue_present(const struct wsi_device *wsi,
1122 VkDevice device,
1123 VkQueue queue,
1124 int queue_family_index,
1125 const VkPresentInfoKHR *pPresentInfo)
1126 {
1127 VkResult final_result = VK_SUCCESS;
1128
1129 const VkPresentRegionsKHR *regions =
1130 vk_find_struct_const(pPresentInfo->pNext, PRESENT_REGIONS_KHR);
1131
1132 for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) {
1133 WSI_FROM_HANDLE(wsi_swapchain, swapchain, pPresentInfo->pSwapchains[i]);
1134 uint32_t image_index = pPresentInfo->pImageIndices[i];
1135 VkResult result;
1136
1137 if (swapchain->fences[image_index] == VK_NULL_HANDLE) {
1138 const VkFenceCreateInfo fence_info = {
1139 .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
1140 .pNext = NULL,
1141 .flags = 0,
1142 };
1143 result = wsi->CreateFence(device, &fence_info,
1144 &swapchain->alloc,
1145 &swapchain->fences[image_index]);
1146 if (result != VK_SUCCESS)
1147 goto fail_present;
1148 } else {
1149 result =
1150 wsi->WaitForFences(device, 1, &swapchain->fences[image_index],
1151 true, ~0ull);
1152 if (result != VK_SUCCESS)
1153 goto fail_present;
1154
1155 result =
1156 wsi->ResetFences(device, 1, &swapchain->fences[image_index]);
1157 if (result != VK_SUCCESS)
1158 goto fail_present;
1159 }
1160
1161 struct wsi_image *image =
1162 swapchain->get_wsi_image(swapchain, image_index);
1163
1164 struct wsi_memory_signal_submit_info mem_signal = {
1165 .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_SIGNAL_SUBMIT_INFO_MESA,
1166 .pNext = NULL,
1167 .memory = image->memory,
1168 };
1169
1170 VkSubmitInfo submit_info = {
1171 .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
1172 .pNext = &mem_signal,
1173 };
1174
1175 VkPipelineStageFlags *stage_flags = NULL;
1176 if (i == 0) {
1177 /* We only need/want to wait on semaphores once. After that, we're
1178 * guaranteed ordering since it all happens on the same queue.
1179 */
1180 submit_info.waitSemaphoreCount = pPresentInfo->waitSemaphoreCount;
1181 submit_info.pWaitSemaphores = pPresentInfo->pWaitSemaphores;
1182
1183 /* Set up the pWaitDstStageMasks */
1184 stage_flags = vk_alloc(&swapchain->alloc,
1185 sizeof(VkPipelineStageFlags) *
1186 pPresentInfo->waitSemaphoreCount,
1187 8,
1188 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
1189 if (!stage_flags) {
1190 result = VK_ERROR_OUT_OF_HOST_MEMORY;
1191 goto fail_present;
1192 }
1193 for (uint32_t s = 0; s < pPresentInfo->waitSemaphoreCount; s++)
1194 stage_flags[s] = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
1195
1196 submit_info.pWaitDstStageMask = stage_flags;
1197 }
1198
1199 if (swapchain->use_prime_blit) {
1200 /* If we are using prime blits, we need to perform the blit now. The
1201 * command buffer is attached to the image.
1202 */
1203 submit_info.commandBufferCount = 1;
1204 submit_info.pCommandBuffers =
1205 &image->prime.blit_cmd_buffers[queue_family_index];
1206 mem_signal.memory = image->prime.memory;
1207 }
1208
1209 result = wsi->QueueSubmit(queue, 1, &submit_info, swapchain->fences[image_index]);
1210 vk_free(&swapchain->alloc, stage_flags);
1211 if (result != VK_SUCCESS)
1212 goto fail_present;
1213
1214 const VkPresentRegionKHR *region = NULL;
1215 if (regions && regions->pRegions)
1216 region = &regions->pRegions[i];
1217
1218 result = swapchain->queue_present(swapchain, image_index, region);
1219 if (result != VK_SUCCESS)
1220 goto fail_present;
1221
1222 fail_present:
1223 if (pPresentInfo->pResults != NULL)
1224 pPresentInfo->pResults[i] = result;
1225
1226 /* Let the final result be our first unsuccessful result */
1227 if (final_result == VK_SUCCESS)
1228 final_result = result;
1229 }
1230
1231 return final_result;
1232 }
1233
1234 uint64_t
1235 wsi_common_get_current_time(void)
1236 {
1237 struct timespec current;
1238 clock_gettime(CLOCK_MONOTONIC, &current);
1239 return current.tv_nsec + current.tv_sec * 1000000000ull;
1240 }