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