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