216b3cafc798496b2aa34c6b343ef8705e8be08b
[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 struct wsi_image_create_info image_wsi_info;
377 VkImageDrmFormatModifierListCreateInfoEXT image_modifier_list;
378
379 uint32_t image_modifier_count = 0, modifier_prop_count = 0;
380 struct VkDrmFormatModifierPropertiesEXT *modifier_props = NULL;
381 uint64_t *image_modifiers = NULL;
382 if (num_modifier_lists == 0) {
383 /* If we don't have modifiers, fall back to the legacy "scanout" flag */
384 image_wsi_info = (struct wsi_image_create_info) {
385 .sType = VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA,
386 .scanout = true,
387 };
388 __vk_append_struct(&image_info, &image_wsi_info);
389 } else {
390 /* The winsys can't request modifiers if we don't support them. */
391 assert(wsi->supports_modifiers);
392 struct VkDrmFormatModifierPropertiesListEXT modifier_props_list = {
393 .sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT,
394 };
395 VkFormatProperties2 format_props = {
396 .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,
397 .pNext = &modifier_props_list,
398 };
399 wsi->GetPhysicalDeviceFormatProperties2KHR(wsi->pdevice,
400 pCreateInfo->imageFormat,
401 &format_props);
402 assert(modifier_props_list.drmFormatModifierCount > 0);
403 modifier_props = vk_alloc(&chain->alloc,
404 sizeof(*modifier_props) *
405 modifier_props_list.drmFormatModifierCount,
406 8,
407 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
408 if (!modifier_props) {
409 result = VK_ERROR_OUT_OF_HOST_MEMORY;
410 goto fail;
411 }
412
413 modifier_props_list.pDrmFormatModifierProperties = modifier_props;
414 wsi->GetPhysicalDeviceFormatProperties2KHR(wsi->pdevice,
415 pCreateInfo->imageFormat,
416 &format_props);
417
418 /* Call GetImageFormatProperties with every modifier and filter the list
419 * down to those that we know work.
420 */
421 modifier_prop_count = 0;
422 for (uint32_t i = 0; i < modifier_props_list.drmFormatModifierCount; i++) {
423 VkPhysicalDeviceImageDrmFormatModifierInfoEXT mod_info = {
424 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT,
425 .drmFormatModifier = modifier_props[i].drmFormatModifier,
426 .sharingMode = pCreateInfo->imageSharingMode,
427 .queueFamilyIndexCount = pCreateInfo->queueFamilyIndexCount,
428 .pQueueFamilyIndices = pCreateInfo->pQueueFamilyIndices,
429 };
430 VkPhysicalDeviceImageFormatInfo2 format_info = {
431 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
432 .format = pCreateInfo->imageFormat,
433 .type = VK_IMAGE_TYPE_2D,
434 .tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT,
435 .usage = pCreateInfo->imageUsage,
436 .flags = 0,
437 };
438 VkImageFormatProperties2 format_props = {
439 .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
440 .pNext = NULL,
441 };
442 __vk_append_struct(&format_info, &mod_info);
443 result = wsi->GetPhysicalDeviceImageFormatProperties2(wsi->pdevice,
444 &format_info,
445 &format_props);
446 if (result == VK_SUCCESS)
447 modifier_props[modifier_prop_count++] = modifier_props[i];
448 }
449
450 uint32_t max_modifier_count = 0;
451 for (uint32_t l = 0; l < num_modifier_lists; l++)
452 max_modifier_count = MAX2(max_modifier_count, num_modifiers[l]);
453
454 image_modifiers = vk_alloc(&chain->alloc,
455 sizeof(*image_modifiers) *
456 max_modifier_count,
457 8,
458 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
459 if (!image_modifiers) {
460 result = VK_ERROR_OUT_OF_HOST_MEMORY;
461 goto fail;
462 }
463
464 image_modifier_count = 0;
465 for (uint32_t l = 0; l < num_modifier_lists; l++) {
466 /* Walk the modifier lists and construct a list of supported
467 * modifiers.
468 */
469 for (uint32_t i = 0; i < num_modifiers[l]; i++) {
470 for (uint32_t j = 0; j < modifier_prop_count; j++) {
471 if (modifier_props[j].drmFormatModifier == modifiers[l][i])
472 image_modifiers[image_modifier_count++] = modifiers[l][i];
473 }
474 }
475
476 /* We only want to take the modifiers from the first list */
477 if (image_modifier_count > 0)
478 break;
479 }
480
481 if (image_modifier_count > 0) {
482 image_modifier_list = (VkImageDrmFormatModifierListCreateInfoEXT) {
483 .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT,
484 .drmFormatModifierCount = image_modifier_count,
485 .pDrmFormatModifiers = image_modifiers,
486 };
487 image_info.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
488 __vk_append_struct(&image_info, &image_modifier_list);
489 } else {
490 /* TODO: Add a proper error here */
491 assert(!"Failed to find a supported modifier! This should never "
492 "happen because LINEAR should always be available");
493 result = VK_ERROR_OUT_OF_HOST_MEMORY;
494 goto fail;
495 }
496 }
497
498 result = wsi->CreateImage(chain->device, &image_info,
499 &chain->alloc, &image->image);
500 if (result != VK_SUCCESS)
501 goto fail;
502
503 VkMemoryRequirements reqs;
504 wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs);
505
506 const struct wsi_memory_allocate_info memory_wsi_info = {
507 .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA,
508 .pNext = NULL,
509 .implicit_sync = true,
510 };
511 const VkExportMemoryAllocateInfo memory_export_info = {
512 .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
513 .pNext = &memory_wsi_info,
514 .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
515 };
516 const VkMemoryDedicatedAllocateInfo memory_dedicated_info = {
517 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
518 .pNext = &memory_export_info,
519 .image = image->image,
520 .buffer = VK_NULL_HANDLE,
521 };
522 const VkMemoryAllocateInfo memory_info = {
523 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
524 .pNext = &memory_dedicated_info,
525 .allocationSize = reqs.size,
526 .memoryTypeIndex = select_memory_type(wsi, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
527 reqs.memoryTypeBits),
528 };
529 result = wsi->AllocateMemory(chain->device, &memory_info,
530 &chain->alloc, &image->memory);
531 if (result != VK_SUCCESS)
532 goto fail;
533
534 result = wsi->BindImageMemory(chain->device, image->image,
535 image->memory, 0);
536 if (result != VK_SUCCESS)
537 goto fail;
538
539 const VkMemoryGetFdInfoKHR memory_get_fd_info = {
540 .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
541 .pNext = NULL,
542 .memory = image->memory,
543 .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
544 };
545 int fd;
546 result = wsi->GetMemoryFdKHR(chain->device, &memory_get_fd_info, &fd);
547 if (result != VK_SUCCESS)
548 goto fail;
549
550 if (num_modifier_lists > 0) {
551 VkImageDrmFormatModifierPropertiesEXT image_mod_props = {
552 .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT,
553 };
554 result = wsi->GetImageDrmFormatModifierPropertiesEXT(chain->device,
555 image->image,
556 &image_mod_props);
557 if (result != VK_SUCCESS)
558 goto fail;
559 image->drm_modifier = image_mod_props.drmFormatModifier;
560 assert(image->drm_modifier != DRM_FORMAT_MOD_INVALID);
561
562 for (uint32_t j = 0; j < modifier_prop_count; j++) {
563 if (modifier_props[j].drmFormatModifier == image->drm_modifier) {
564 image->num_planes = modifier_props[j].drmFormatModifierPlaneCount;
565 break;
566 }
567 }
568
569 for (uint32_t p = 0; p < image->num_planes; p++) {
570 const VkImageSubresource image_subresource = {
571 .aspectMask = VK_IMAGE_ASPECT_PLANE_0_BIT << p,
572 .mipLevel = 0,
573 .arrayLayer = 0,
574 };
575 VkSubresourceLayout image_layout;
576 wsi->GetImageSubresourceLayout(chain->device, image->image,
577 &image_subresource, &image_layout);
578 image->sizes[p] = image_layout.size;
579 image->row_pitches[p] = image_layout.rowPitch;
580 image->offsets[p] = image_layout.offset;
581 if (p == 0) {
582 image->fds[p] = fd;
583 } else {
584 image->fds[p] = dup(fd);
585 if (image->fds[p] == -1) {
586 for (uint32_t i = 0; i < p; i++)
587 close(image->fds[p]);
588
589 goto fail;
590 }
591 }
592 }
593 } else {
594 const VkImageSubresource image_subresource = {
595 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
596 .mipLevel = 0,
597 .arrayLayer = 0,
598 };
599 VkSubresourceLayout image_layout;
600 wsi->GetImageSubresourceLayout(chain->device, image->image,
601 &image_subresource, &image_layout);
602
603 image->drm_modifier = DRM_FORMAT_MOD_INVALID;
604 image->num_planes = 1;
605 image->sizes[0] = reqs.size;
606 image->row_pitches[0] = image_layout.rowPitch;
607 image->offsets[0] = 0;
608 image->fds[0] = fd;
609 }
610
611 vk_free(&chain->alloc, modifier_props);
612 vk_free(&chain->alloc, image_modifiers);
613
614 return VK_SUCCESS;
615
616 fail:
617 vk_free(&chain->alloc, modifier_props);
618 vk_free(&chain->alloc, image_modifiers);
619 wsi_destroy_image(chain, image);
620
621 return result;
622 }
623
624 #define WSI_PRIME_LINEAR_STRIDE_ALIGN 256
625
626 VkResult
627 wsi_create_prime_image(const struct wsi_swapchain *chain,
628 const VkSwapchainCreateInfoKHR *pCreateInfo,
629 bool use_modifier,
630 struct wsi_image *image)
631 {
632 const struct wsi_device *wsi = chain->wsi;
633 VkResult result;
634
635 memset(image, 0, sizeof(*image));
636
637 const uint32_t cpp = vk_format_size(pCreateInfo->imageFormat);
638 const uint32_t linear_stride = align_u32(pCreateInfo->imageExtent.width * cpp,
639 WSI_PRIME_LINEAR_STRIDE_ALIGN);
640
641 uint32_t linear_size = linear_stride * pCreateInfo->imageExtent.height;
642 linear_size = align_u32(linear_size, 4096);
643
644 const VkExternalMemoryBufferCreateInfo prime_buffer_external_info = {
645 .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO,
646 .pNext = NULL,
647 .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
648 };
649 const VkBufferCreateInfo prime_buffer_info = {
650 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
651 .pNext = &prime_buffer_external_info,
652 .size = linear_size,
653 .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT,
654 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
655 };
656 result = wsi->CreateBuffer(chain->device, &prime_buffer_info,
657 &chain->alloc, &image->prime.buffer);
658 if (result != VK_SUCCESS)
659 goto fail;
660
661 VkMemoryRequirements reqs;
662 wsi->GetBufferMemoryRequirements(chain->device, image->prime.buffer, &reqs);
663 assert(reqs.size <= linear_size);
664
665 const struct wsi_memory_allocate_info memory_wsi_info = {
666 .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA,
667 .pNext = NULL,
668 .implicit_sync = true,
669 };
670 const VkExportMemoryAllocateInfo prime_memory_export_info = {
671 .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
672 .pNext = &memory_wsi_info,
673 .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
674 };
675 const VkMemoryDedicatedAllocateInfo prime_memory_dedicated_info = {
676 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
677 .pNext = &prime_memory_export_info,
678 .image = VK_NULL_HANDLE,
679 .buffer = image->prime.buffer,
680 };
681 const VkMemoryAllocateInfo prime_memory_info = {
682 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
683 .pNext = &prime_memory_dedicated_info,
684 .allocationSize = linear_size,
685 .memoryTypeIndex = select_memory_type(wsi, 0, reqs.memoryTypeBits),
686 };
687 result = wsi->AllocateMemory(chain->device, &prime_memory_info,
688 &chain->alloc, &image->prime.memory);
689 if (result != VK_SUCCESS)
690 goto fail;
691
692 result = wsi->BindBufferMemory(chain->device, image->prime.buffer,
693 image->prime.memory, 0);
694 if (result != VK_SUCCESS)
695 goto fail;
696
697 const VkImageCreateInfo image_info = {
698 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
699 .pNext = NULL,
700 .flags = 0,
701 .imageType = VK_IMAGE_TYPE_2D,
702 .format = pCreateInfo->imageFormat,
703 .extent = {
704 .width = pCreateInfo->imageExtent.width,
705 .height = pCreateInfo->imageExtent.height,
706 .depth = 1,
707 },
708 .mipLevels = 1,
709 .arrayLayers = 1,
710 .samples = VK_SAMPLE_COUNT_1_BIT,
711 .tiling = VK_IMAGE_TILING_OPTIMAL,
712 .usage = pCreateInfo->imageUsage | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
713 .sharingMode = pCreateInfo->imageSharingMode,
714 .queueFamilyIndexCount = pCreateInfo->queueFamilyIndexCount,
715 .pQueueFamilyIndices = pCreateInfo->pQueueFamilyIndices,
716 .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
717 };
718 result = wsi->CreateImage(chain->device, &image_info,
719 &chain->alloc, &image->image);
720 if (result != VK_SUCCESS)
721 goto fail;
722
723 wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs);
724
725 const VkMemoryDedicatedAllocateInfo memory_dedicated_info = {
726 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
727 .pNext = NULL,
728 .image = image->image,
729 .buffer = VK_NULL_HANDLE,
730 };
731 const VkMemoryAllocateInfo memory_info = {
732 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
733 .pNext = &memory_dedicated_info,
734 .allocationSize = reqs.size,
735 .memoryTypeIndex = select_memory_type(wsi, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
736 reqs.memoryTypeBits),
737 };
738 result = wsi->AllocateMemory(chain->device, &memory_info,
739 &chain->alloc, &image->memory);
740 if (result != VK_SUCCESS)
741 goto fail;
742
743 result = wsi->BindImageMemory(chain->device, image->image,
744 image->memory, 0);
745 if (result != VK_SUCCESS)
746 goto fail;
747
748 image->prime.blit_cmd_buffers =
749 vk_zalloc(&chain->alloc,
750 sizeof(VkCommandBuffer) * wsi->queue_family_count, 8,
751 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
752 if (!image->prime.blit_cmd_buffers) {
753 result = VK_ERROR_OUT_OF_HOST_MEMORY;
754 goto fail;
755 }
756
757 for (uint32_t i = 0; i < wsi->queue_family_count; i++) {
758 const VkCommandBufferAllocateInfo cmd_buffer_info = {
759 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
760 .pNext = NULL,
761 .commandPool = chain->cmd_pools[i],
762 .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
763 .commandBufferCount = 1,
764 };
765 result = wsi->AllocateCommandBuffers(chain->device, &cmd_buffer_info,
766 &image->prime.blit_cmd_buffers[i]);
767 if (result != VK_SUCCESS)
768 goto fail;
769
770 const VkCommandBufferBeginInfo begin_info = {
771 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
772 };
773 wsi->BeginCommandBuffer(image->prime.blit_cmd_buffers[i], &begin_info);
774
775 struct VkBufferImageCopy buffer_image_copy = {
776 .bufferOffset = 0,
777 .bufferRowLength = linear_stride / cpp,
778 .bufferImageHeight = 0,
779 .imageSubresource = {
780 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
781 .mipLevel = 0,
782 .baseArrayLayer = 0,
783 .layerCount = 1,
784 },
785 .imageOffset = { .x = 0, .y = 0, .z = 0 },
786 .imageExtent = {
787 .width = pCreateInfo->imageExtent.width,
788 .height = pCreateInfo->imageExtent.height,
789 .depth = 1,
790 },
791 };
792 wsi->CmdCopyImageToBuffer(image->prime.blit_cmd_buffers[i],
793 image->image,
794 VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
795 image->prime.buffer,
796 1, &buffer_image_copy);
797
798 result = wsi->EndCommandBuffer(image->prime.blit_cmd_buffers[i]);
799 if (result != VK_SUCCESS)
800 goto fail;
801 }
802
803 const VkMemoryGetFdInfoKHR linear_memory_get_fd_info = {
804 .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
805 .pNext = NULL,
806 .memory = image->prime.memory,
807 .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
808 };
809 int fd;
810 result = wsi->GetMemoryFdKHR(chain->device, &linear_memory_get_fd_info, &fd);
811 if (result != VK_SUCCESS)
812 goto fail;
813
814 image->drm_modifier = use_modifier ? DRM_FORMAT_MOD_LINEAR : DRM_FORMAT_MOD_INVALID;
815 image->num_planes = 1;
816 image->sizes[0] = linear_size;
817 image->row_pitches[0] = linear_stride;
818 image->offsets[0] = 0;
819 image->fds[0] = fd;
820
821 return VK_SUCCESS;
822
823 fail:
824 wsi_destroy_image(chain, image);
825
826 return result;
827 }
828
829 void
830 wsi_destroy_image(const struct wsi_swapchain *chain,
831 struct wsi_image *image)
832 {
833 const struct wsi_device *wsi = chain->wsi;
834
835 if (image->prime.blit_cmd_buffers) {
836 for (uint32_t i = 0; i < wsi->queue_family_count; i++) {
837 wsi->FreeCommandBuffers(chain->device, chain->cmd_pools[i],
838 1, &image->prime.blit_cmd_buffers[i]);
839 }
840 vk_free(&chain->alloc, image->prime.blit_cmd_buffers);
841 }
842
843 wsi->FreeMemory(chain->device, image->memory, &chain->alloc);
844 wsi->DestroyImage(chain->device, image->image, &chain->alloc);
845 wsi->FreeMemory(chain->device, image->prime.memory, &chain->alloc);
846 wsi->DestroyBuffer(chain->device, image->prime.buffer, &chain->alloc);
847 }
848
849 VkResult
850 wsi_common_get_surface_support(struct wsi_device *wsi_device,
851 uint32_t queueFamilyIndex,
852 VkSurfaceKHR _surface,
853 VkBool32* pSupported)
854 {
855 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
856 struct wsi_interface *iface = wsi_device->wsi[surface->platform];
857
858 return iface->get_support(surface, wsi_device,
859 queueFamilyIndex, pSupported);
860 }
861
862 VkResult
863 wsi_common_get_surface_capabilities(struct wsi_device *wsi_device,
864 VkSurfaceKHR _surface,
865 VkSurfaceCapabilitiesKHR *pSurfaceCapabilities)
866 {
867 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
868 struct wsi_interface *iface = wsi_device->wsi[surface->platform];
869
870 VkSurfaceCapabilities2KHR caps2 = {
871 .sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR,
872 };
873
874 VkResult result = iface->get_capabilities2(surface, wsi_device, NULL, &caps2);
875
876 if (result == VK_SUCCESS)
877 *pSurfaceCapabilities = caps2.surfaceCapabilities;
878
879 return result;
880 }
881
882 VkResult
883 wsi_common_get_surface_capabilities2(struct wsi_device *wsi_device,
884 const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
885 VkSurfaceCapabilities2KHR *pSurfaceCapabilities)
886 {
887 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pSurfaceInfo->surface);
888 struct wsi_interface *iface = wsi_device->wsi[surface->platform];
889
890 return iface->get_capabilities2(surface, wsi_device, pSurfaceInfo->pNext,
891 pSurfaceCapabilities);
892 }
893
894 VkResult
895 wsi_common_get_surface_capabilities2ext(
896 struct wsi_device *wsi_device,
897 VkSurfaceKHR _surface,
898 VkSurfaceCapabilities2EXT *pSurfaceCapabilities)
899 {
900 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
901 struct wsi_interface *iface = wsi_device->wsi[surface->platform];
902
903 assert(pSurfaceCapabilities->sType ==
904 VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT);
905
906 struct wsi_surface_supported_counters counters = {
907 .sType = VK_STRUCTURE_TYPE_WSI_SURFACE_SUPPORTED_COUNTERS_MESA,
908 .pNext = pSurfaceCapabilities->pNext,
909 .supported_surface_counters = 0,
910 };
911
912 VkSurfaceCapabilities2KHR caps2 = {
913 .sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR,
914 .pNext = &counters,
915 };
916
917 VkResult result = iface->get_capabilities2(surface, wsi_device, NULL, &caps2);
918
919 if (result == VK_SUCCESS) {
920 VkSurfaceCapabilities2EXT *ext_caps = pSurfaceCapabilities;
921 VkSurfaceCapabilitiesKHR khr_caps = caps2.surfaceCapabilities;
922
923 ext_caps->minImageCount = khr_caps.minImageCount;
924 ext_caps->maxImageCount = khr_caps.maxImageCount;
925 ext_caps->currentExtent = khr_caps.currentExtent;
926 ext_caps->minImageExtent = khr_caps.minImageExtent;
927 ext_caps->maxImageExtent = khr_caps.maxImageExtent;
928 ext_caps->maxImageArrayLayers = khr_caps.maxImageArrayLayers;
929 ext_caps->supportedTransforms = khr_caps.supportedTransforms;
930 ext_caps->currentTransform = khr_caps.currentTransform;
931 ext_caps->supportedCompositeAlpha = khr_caps.supportedCompositeAlpha;
932 ext_caps->supportedUsageFlags = khr_caps.supportedUsageFlags;
933 ext_caps->supportedSurfaceCounters = counters.supported_surface_counters;
934 }
935
936 return result;
937 }
938
939 VkResult
940 wsi_common_get_surface_formats(struct wsi_device *wsi_device,
941 VkSurfaceKHR _surface,
942 uint32_t *pSurfaceFormatCount,
943 VkSurfaceFormatKHR *pSurfaceFormats)
944 {
945 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
946 struct wsi_interface *iface = wsi_device->wsi[surface->platform];
947
948 return iface->get_formats(surface, wsi_device,
949 pSurfaceFormatCount, pSurfaceFormats);
950 }
951
952 VkResult
953 wsi_common_get_surface_formats2(struct wsi_device *wsi_device,
954 const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
955 uint32_t *pSurfaceFormatCount,
956 VkSurfaceFormat2KHR *pSurfaceFormats)
957 {
958 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pSurfaceInfo->surface);
959 struct wsi_interface *iface = wsi_device->wsi[surface->platform];
960
961 return iface->get_formats2(surface, wsi_device, pSurfaceInfo->pNext,
962 pSurfaceFormatCount, pSurfaceFormats);
963 }
964
965 VkResult
966 wsi_common_get_surface_present_modes(struct wsi_device *wsi_device,
967 VkSurfaceKHR _surface,
968 uint32_t *pPresentModeCount,
969 VkPresentModeKHR *pPresentModes)
970 {
971 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
972 struct wsi_interface *iface = wsi_device->wsi[surface->platform];
973
974 return iface->get_present_modes(surface, pPresentModeCount,
975 pPresentModes);
976 }
977
978 VkResult
979 wsi_common_get_present_rectangles(struct wsi_device *wsi_device,
980 VkSurfaceKHR _surface,
981 uint32_t* pRectCount,
982 VkRect2D* pRects)
983 {
984 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
985 struct wsi_interface *iface = wsi_device->wsi[surface->platform];
986
987 return iface->get_present_rectangles(surface, wsi_device,
988 pRectCount, pRects);
989 }
990
991 VkResult
992 wsi_common_create_swapchain(struct wsi_device *wsi,
993 VkDevice device,
994 const VkSwapchainCreateInfoKHR *pCreateInfo,
995 const VkAllocationCallbacks *pAllocator,
996 VkSwapchainKHR *pSwapchain)
997 {
998 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pCreateInfo->surface);
999 struct wsi_interface *iface = wsi->wsi[surface->platform];
1000 struct wsi_swapchain *swapchain;
1001
1002 VkResult result = iface->create_swapchain(surface, device, wsi,
1003 pCreateInfo, pAllocator,
1004 &swapchain);
1005 if (result != VK_SUCCESS)
1006 return result;
1007
1008 swapchain->fences = vk_zalloc(pAllocator,
1009 sizeof (*swapchain->fences) * swapchain->image_count,
1010 sizeof (*swapchain->fences),
1011 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1012 if (!swapchain->fences) {
1013 swapchain->destroy(swapchain, pAllocator);
1014 return VK_ERROR_OUT_OF_HOST_MEMORY;
1015 }
1016
1017 *pSwapchain = wsi_swapchain_to_handle(swapchain);
1018
1019 return VK_SUCCESS;
1020 }
1021
1022 void
1023 wsi_common_destroy_swapchain(VkDevice device,
1024 VkSwapchainKHR _swapchain,
1025 const VkAllocationCallbacks *pAllocator)
1026 {
1027 WSI_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain);
1028 if (!swapchain)
1029 return;
1030
1031 swapchain->destroy(swapchain, pAllocator);
1032 }
1033
1034 VkResult
1035 wsi_common_get_images(VkSwapchainKHR _swapchain,
1036 uint32_t *pSwapchainImageCount,
1037 VkImage *pSwapchainImages)
1038 {
1039 WSI_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain);
1040 VK_OUTARRAY_MAKE(images, pSwapchainImages, pSwapchainImageCount);
1041
1042 for (uint32_t i = 0; i < swapchain->image_count; i++) {
1043 vk_outarray_append(&images, image) {
1044 *image = swapchain->get_wsi_image(swapchain, i)->image;
1045 }
1046 }
1047
1048 return vk_outarray_status(&images);
1049 }
1050
1051 VkResult
1052 wsi_common_acquire_next_image2(const struct wsi_device *wsi,
1053 VkDevice device,
1054 const VkAcquireNextImageInfoKHR *pAcquireInfo,
1055 uint32_t *pImageIndex)
1056 {
1057 WSI_FROM_HANDLE(wsi_swapchain, swapchain, pAcquireInfo->swapchain);
1058
1059 VkResult result = swapchain->acquire_next_image(swapchain, pAcquireInfo,
1060 pImageIndex);
1061 if (result != VK_SUCCESS)
1062 return result;
1063
1064 if (pAcquireInfo->semaphore != VK_NULL_HANDLE &&
1065 wsi->signal_semaphore_for_memory != NULL) {
1066 struct wsi_image *image =
1067 swapchain->get_wsi_image(swapchain, *pImageIndex);
1068 wsi->signal_semaphore_for_memory(device, pAcquireInfo->semaphore,
1069 image->memory);
1070 }
1071
1072 if (pAcquireInfo->fence != VK_NULL_HANDLE &&
1073 wsi->signal_fence_for_memory != NULL) {
1074 struct wsi_image *image =
1075 swapchain->get_wsi_image(swapchain, *pImageIndex);
1076 wsi->signal_fence_for_memory(device, pAcquireInfo->fence,
1077 image->memory);
1078 }
1079
1080 return VK_SUCCESS;
1081 }
1082
1083 VkResult
1084 wsi_common_queue_present(const struct wsi_device *wsi,
1085 VkDevice device,
1086 VkQueue queue,
1087 int queue_family_index,
1088 const VkPresentInfoKHR *pPresentInfo)
1089 {
1090 VkResult final_result = VK_SUCCESS;
1091
1092 const VkPresentRegionsKHR *regions =
1093 vk_find_struct_const(pPresentInfo->pNext, PRESENT_REGIONS_KHR);
1094
1095 for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) {
1096 WSI_FROM_HANDLE(wsi_swapchain, swapchain, pPresentInfo->pSwapchains[i]);
1097 uint32_t image_index = pPresentInfo->pImageIndices[i];
1098 VkResult result;
1099
1100 if (swapchain->fences[image_index] == VK_NULL_HANDLE) {
1101 const VkFenceCreateInfo fence_info = {
1102 .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
1103 .pNext = NULL,
1104 .flags = 0,
1105 };
1106 result = wsi->CreateFence(device, &fence_info,
1107 &swapchain->alloc,
1108 &swapchain->fences[image_index]);
1109 if (result != VK_SUCCESS)
1110 goto fail_present;
1111 } else {
1112 result =
1113 wsi->WaitForFences(device, 1, &swapchain->fences[image_index],
1114 true, ~0ull);
1115 if (result != VK_SUCCESS)
1116 goto fail_present;
1117
1118 result =
1119 wsi->ResetFences(device, 1, &swapchain->fences[image_index]);
1120 if (result != VK_SUCCESS)
1121 goto fail_present;
1122 }
1123
1124 struct wsi_image *image =
1125 swapchain->get_wsi_image(swapchain, image_index);
1126
1127 struct wsi_memory_signal_submit_info mem_signal = {
1128 .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_SIGNAL_SUBMIT_INFO_MESA,
1129 .pNext = NULL,
1130 .memory = image->memory,
1131 };
1132
1133 VkSubmitInfo submit_info = {
1134 .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
1135 .pNext = &mem_signal,
1136 };
1137
1138 VkPipelineStageFlags *stage_flags = NULL;
1139 if (i == 0) {
1140 /* We only need/want to wait on semaphores once. After that, we're
1141 * guaranteed ordering since it all happens on the same queue.
1142 */
1143 submit_info.waitSemaphoreCount = pPresentInfo->waitSemaphoreCount;
1144 submit_info.pWaitSemaphores = pPresentInfo->pWaitSemaphores;
1145
1146 /* Set up the pWaitDstStageMasks */
1147 stage_flags = vk_alloc(&swapchain->alloc,
1148 sizeof(VkPipelineStageFlags) *
1149 pPresentInfo->waitSemaphoreCount,
1150 8,
1151 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
1152 if (!stage_flags) {
1153 result = VK_ERROR_OUT_OF_HOST_MEMORY;
1154 goto fail_present;
1155 }
1156 for (uint32_t s = 0; s < pPresentInfo->waitSemaphoreCount; s++)
1157 stage_flags[s] = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
1158
1159 submit_info.pWaitDstStageMask = stage_flags;
1160 }
1161
1162 if (swapchain->use_prime_blit) {
1163 /* If we are using prime blits, we need to perform the blit now. The
1164 * command buffer is attached to the image.
1165 */
1166 submit_info.commandBufferCount = 1;
1167 submit_info.pCommandBuffers =
1168 &image->prime.blit_cmd_buffers[queue_family_index];
1169 mem_signal.memory = image->prime.memory;
1170 }
1171
1172 result = wsi->QueueSubmit(queue, 1, &submit_info, swapchain->fences[image_index]);
1173 vk_free(&swapchain->alloc, stage_flags);
1174 if (result != VK_SUCCESS)
1175 goto fail_present;
1176
1177 const VkPresentRegionKHR *region = NULL;
1178 if (regions && regions->pRegions)
1179 region = &regions->pRegions[i];
1180
1181 result = swapchain->queue_present(swapchain, image_index, region);
1182 if (result != VK_SUCCESS)
1183 goto fail_present;
1184
1185 fail_present:
1186 if (pPresentInfo->pResults != NULL)
1187 pPresentInfo->pResults[i] = result;
1188
1189 /* Let the final result be our first unsuccessful result */
1190 if (final_result == VK_SUCCESS)
1191 final_result = result;
1192 }
1193
1194 return final_result;
1195 }
1196
1197 uint64_t
1198 wsi_common_get_current_time(void)
1199 {
1200 struct timespec current;
1201 clock_gettime(CLOCK_MONOTONIC, &current);
1202 return current.tv_nsec + current.tv_sec * 1000000000ull;
1203 }