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