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