vulkan/wsi: Add wrappers for all of the surface queries
[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 "util/macros.h"
26 #include "vk_util.h"
27
28 void
29 wsi_device_init(struct wsi_device *wsi,
30 VkPhysicalDevice pdevice,
31 WSI_FN_GetPhysicalDeviceProcAddr proc_addr)
32 {
33 memset(wsi, 0, sizeof(*wsi));
34
35 #define WSI_GET_CB(func) \
36 PFN_vk##func func = (PFN_vk##func)proc_addr(pdevice, "vk" #func)
37 WSI_GET_CB(GetPhysicalDeviceMemoryProperties);
38 WSI_GET_CB(GetPhysicalDeviceQueueFamilyProperties);
39 #undef WSI_GET_CB
40
41 GetPhysicalDeviceMemoryProperties(pdevice, &wsi->memory_props);
42 GetPhysicalDeviceQueueFamilyProperties(pdevice, &wsi->queue_family_count, NULL);
43
44 #define WSI_GET_CB(func) \
45 wsi->func = (PFN_vk##func)proc_addr(pdevice, "vk" #func)
46 WSI_GET_CB(AllocateMemory);
47 WSI_GET_CB(AllocateCommandBuffers);
48 WSI_GET_CB(BindBufferMemory);
49 WSI_GET_CB(BindImageMemory);
50 WSI_GET_CB(BeginCommandBuffer);
51 WSI_GET_CB(CmdCopyImageToBuffer);
52 WSI_GET_CB(CreateBuffer);
53 WSI_GET_CB(CreateCommandPool);
54 WSI_GET_CB(CreateFence);
55 WSI_GET_CB(CreateImage);
56 WSI_GET_CB(DestroyBuffer);
57 WSI_GET_CB(DestroyCommandPool);
58 WSI_GET_CB(DestroyFence);
59 WSI_GET_CB(DestroyImage);
60 WSI_GET_CB(EndCommandBuffer);
61 WSI_GET_CB(FreeMemory);
62 WSI_GET_CB(FreeCommandBuffers);
63 WSI_GET_CB(GetBufferMemoryRequirements);
64 WSI_GET_CB(GetImageMemoryRequirements);
65 WSI_GET_CB(GetImageSubresourceLayout);
66 WSI_GET_CB(GetMemoryFdKHR);
67 WSI_GET_CB(ResetFences);
68 WSI_GET_CB(QueueSubmit);
69 WSI_GET_CB(WaitForFences);
70 #undef WSI_GET_CB
71 }
72
73 VkResult
74 wsi_swapchain_init(const struct wsi_device *wsi,
75 struct wsi_swapchain *chain,
76 VkDevice device,
77 const VkSwapchainCreateInfoKHR *pCreateInfo,
78 const VkAllocationCallbacks *pAllocator)
79 {
80 VkResult result;
81
82 memset(chain, 0, sizeof(*chain));
83
84 chain->wsi = wsi;
85 chain->device = device;
86 chain->alloc = *pAllocator;
87 chain->use_prime_blit = false;
88
89 chain->cmd_pools =
90 vk_zalloc(pAllocator, sizeof(VkCommandPool) * wsi->queue_family_count, 8,
91 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
92 if (!chain->cmd_pools)
93 return VK_ERROR_OUT_OF_HOST_MEMORY;
94
95 for (uint32_t i = 0; i < wsi->queue_family_count; i++) {
96 const VkCommandPoolCreateInfo cmd_pool_info = {
97 .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
98 .pNext = NULL,
99 .flags = 0,
100 .queueFamilyIndex = i,
101 };
102 result = wsi->CreateCommandPool(device, &cmd_pool_info, &chain->alloc,
103 &chain->cmd_pools[i]);
104 if (result != VK_SUCCESS)
105 goto fail;
106 }
107
108 return VK_SUCCESS;
109
110 fail:
111 wsi_swapchain_finish(chain);
112 return result;
113 }
114
115 void
116 wsi_swapchain_finish(struct wsi_swapchain *chain)
117 {
118 for (unsigned i = 0; i < ARRAY_SIZE(chain->fences); i++)
119 chain->wsi->DestroyFence(chain->device, chain->fences[i], &chain->alloc);
120
121 for (uint32_t i = 0; i < chain->wsi->queue_family_count; i++) {
122 chain->wsi->DestroyCommandPool(chain->device, chain->cmd_pools[i],
123 &chain->alloc);
124 }
125 }
126
127 static uint32_t
128 select_memory_type(const struct wsi_device *wsi,
129 VkMemoryPropertyFlags props,
130 uint32_t type_bits)
131 {
132 for (uint32_t i = 0; i < wsi->memory_props.memoryTypeCount; i++) {
133 const VkMemoryType type = wsi->memory_props.memoryTypes[i];
134 if ((type_bits & (1 << i)) && (type.propertyFlags & props) == props)
135 return i;
136 }
137
138 unreachable("No memory type found");
139 }
140
141 static uint32_t
142 vk_format_size(VkFormat format)
143 {
144 switch (format) {
145 case VK_FORMAT_B8G8R8A8_UNORM:
146 case VK_FORMAT_B8G8R8A8_SRGB:
147 return 4;
148 default:
149 unreachable("Unknown WSI Format");
150 }
151 }
152
153 static inline uint32_t
154 align_u32(uint32_t v, uint32_t a)
155 {
156 assert(a != 0 && a == (a & -a));
157 return (v + a - 1) & ~(a - 1);
158 }
159
160 VkResult
161 wsi_create_native_image(const struct wsi_swapchain *chain,
162 const VkSwapchainCreateInfoKHR *pCreateInfo,
163 struct wsi_image *image)
164 {
165 const struct wsi_device *wsi = chain->wsi;
166 VkResult result;
167
168 memset(image, 0, sizeof(*image));
169
170 const struct wsi_image_create_info image_wsi_info = {
171 .sType = VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA,
172 .pNext = NULL,
173 .scanout = true,
174 };
175 const VkImageCreateInfo image_info = {
176 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
177 .pNext = &image_wsi_info,
178 .flags = 0,
179 .imageType = VK_IMAGE_TYPE_2D,
180 .format = pCreateInfo->imageFormat,
181 .extent = {
182 .width = pCreateInfo->imageExtent.width,
183 .height = pCreateInfo->imageExtent.height,
184 .depth = 1,
185 },
186 .mipLevels = 1,
187 .arrayLayers = 1,
188 .samples = VK_SAMPLE_COUNT_1_BIT,
189 .tiling = VK_IMAGE_TILING_OPTIMAL,
190 .usage = pCreateInfo->imageUsage,
191 .sharingMode = pCreateInfo->imageSharingMode,
192 .queueFamilyIndexCount = pCreateInfo->queueFamilyIndexCount,
193 .pQueueFamilyIndices = pCreateInfo->pQueueFamilyIndices,
194 .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
195 };
196 result = wsi->CreateImage(chain->device, &image_info,
197 &chain->alloc, &image->image);
198 if (result != VK_SUCCESS)
199 goto fail;
200
201 VkMemoryRequirements reqs;
202 wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs);
203
204 VkSubresourceLayout image_layout;
205 const VkImageSubresource image_subresource = {
206 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
207 .mipLevel = 0,
208 .arrayLayer = 0,
209 };
210 wsi->GetImageSubresourceLayout(chain->device, image->image,
211 &image_subresource, &image_layout);
212
213 const struct wsi_memory_allocate_info memory_wsi_info = {
214 .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA,
215 .pNext = NULL,
216 .implicit_sync = true,
217 };
218 const VkExportMemoryAllocateInfoKHR memory_export_info = {
219 .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR,
220 .pNext = &memory_wsi_info,
221 .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
222 };
223 const VkMemoryDedicatedAllocateInfoKHR memory_dedicated_info = {
224 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR,
225 .pNext = &memory_export_info,
226 .image = image->image,
227 .buffer = VK_NULL_HANDLE,
228 };
229 const VkMemoryAllocateInfo memory_info = {
230 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
231 .pNext = &memory_dedicated_info,
232 .allocationSize = reqs.size,
233 .memoryTypeIndex = select_memory_type(wsi, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
234 reqs.memoryTypeBits),
235 };
236 result = wsi->AllocateMemory(chain->device, &memory_info,
237 &chain->alloc, &image->memory);
238 if (result != VK_SUCCESS)
239 goto fail;
240
241 result = wsi->BindImageMemory(chain->device, image->image,
242 image->memory, 0);
243 if (result != VK_SUCCESS)
244 goto fail;
245
246 const VkMemoryGetFdInfoKHR memory_get_fd_info = {
247 .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
248 .pNext = NULL,
249 .memory = image->memory,
250 .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
251 };
252 int fd;
253 result = wsi->GetMemoryFdKHR(chain->device, &memory_get_fd_info, &fd);
254 if (result != VK_SUCCESS)
255 goto fail;
256
257 image->size = reqs.size;
258 image->row_pitch = image_layout.rowPitch;
259 image->offset = 0;
260 image->fd = fd;
261
262 return VK_SUCCESS;
263
264 fail:
265 wsi_destroy_image(chain, image);
266
267 return result;
268 }
269
270 #define WSI_PRIME_LINEAR_STRIDE_ALIGN 256
271
272 VkResult
273 wsi_create_prime_image(const struct wsi_swapchain *chain,
274 const VkSwapchainCreateInfoKHR *pCreateInfo,
275 struct wsi_image *image)
276 {
277 const struct wsi_device *wsi = chain->wsi;
278 VkResult result;
279
280 memset(image, 0, sizeof(*image));
281
282 const uint32_t cpp = vk_format_size(pCreateInfo->imageFormat);
283 const uint32_t linear_stride = align_u32(pCreateInfo->imageExtent.width * cpp,
284 WSI_PRIME_LINEAR_STRIDE_ALIGN);
285
286 uint32_t linear_size = linear_stride * pCreateInfo->imageExtent.height;
287 linear_size = align_u32(linear_size, 4096);
288
289 const VkExternalMemoryBufferCreateInfoKHR prime_buffer_external_info = {
290 .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR,
291 .pNext = NULL,
292 .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
293 };
294 const VkBufferCreateInfo prime_buffer_info = {
295 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
296 .pNext = &prime_buffer_external_info,
297 .size = linear_size,
298 .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT,
299 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
300 };
301 result = wsi->CreateBuffer(chain->device, &prime_buffer_info,
302 &chain->alloc, &image->prime.buffer);
303 if (result != VK_SUCCESS)
304 goto fail;
305
306 VkMemoryRequirements reqs;
307 wsi->GetBufferMemoryRequirements(chain->device, image->prime.buffer, &reqs);
308 assert(reqs.size <= linear_size);
309
310 const struct wsi_memory_allocate_info memory_wsi_info = {
311 .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA,
312 .pNext = NULL,
313 .implicit_sync = true,
314 };
315 const VkExportMemoryAllocateInfoKHR prime_memory_export_info = {
316 .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR,
317 .pNext = &memory_wsi_info,
318 .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
319 };
320 const VkMemoryDedicatedAllocateInfoKHR prime_memory_dedicated_info = {
321 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR,
322 .pNext = &prime_memory_export_info,
323 .image = VK_NULL_HANDLE,
324 .buffer = image->prime.buffer,
325 };
326 const VkMemoryAllocateInfo prime_memory_info = {
327 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
328 .pNext = &prime_memory_dedicated_info,
329 .allocationSize = linear_size,
330 .memoryTypeIndex = select_memory_type(wsi, 0, reqs.memoryTypeBits),
331 };
332 result = wsi->AllocateMemory(chain->device, &prime_memory_info,
333 &chain->alloc, &image->prime.memory);
334 if (result != VK_SUCCESS)
335 goto fail;
336
337 result = wsi->BindBufferMemory(chain->device, image->prime.buffer,
338 image->prime.memory, 0);
339 if (result != VK_SUCCESS)
340 goto fail;
341
342 const VkImageCreateInfo image_info = {
343 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
344 .pNext = NULL,
345 .flags = 0,
346 .imageType = VK_IMAGE_TYPE_2D,
347 .format = pCreateInfo->imageFormat,
348 .extent = {
349 .width = pCreateInfo->imageExtent.width,
350 .height = pCreateInfo->imageExtent.height,
351 .depth = 1,
352 },
353 .mipLevels = 1,
354 .arrayLayers = 1,
355 .samples = VK_SAMPLE_COUNT_1_BIT,
356 .tiling = VK_IMAGE_TILING_OPTIMAL,
357 .usage = pCreateInfo->imageUsage | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
358 .sharingMode = pCreateInfo->imageSharingMode,
359 .queueFamilyIndexCount = pCreateInfo->queueFamilyIndexCount,
360 .pQueueFamilyIndices = pCreateInfo->pQueueFamilyIndices,
361 .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
362 };
363 result = wsi->CreateImage(chain->device, &image_info,
364 &chain->alloc, &image->image);
365 if (result != VK_SUCCESS)
366 goto fail;
367
368 wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs);
369
370 const VkMemoryDedicatedAllocateInfoKHR memory_dedicated_info = {
371 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR,
372 .pNext = NULL,
373 .image = image->image,
374 .buffer = VK_NULL_HANDLE,
375 };
376 const VkMemoryAllocateInfo memory_info = {
377 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
378 .pNext = &memory_dedicated_info,
379 .allocationSize = reqs.size,
380 .memoryTypeIndex = select_memory_type(wsi, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
381 reqs.memoryTypeBits),
382 };
383 result = wsi->AllocateMemory(chain->device, &memory_info,
384 &chain->alloc, &image->memory);
385 if (result != VK_SUCCESS)
386 goto fail;
387
388 result = wsi->BindImageMemory(chain->device, image->image,
389 image->memory, 0);
390 if (result != VK_SUCCESS)
391 goto fail;
392
393 image->prime.blit_cmd_buffers =
394 vk_zalloc(&chain->alloc,
395 sizeof(VkCommandBuffer) * wsi->queue_family_count, 8,
396 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
397 if (!image->prime.blit_cmd_buffers)
398 goto fail;
399
400 for (uint32_t i = 0; i < wsi->queue_family_count; i++) {
401 const VkCommandBufferAllocateInfo cmd_buffer_info = {
402 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
403 .pNext = NULL,
404 .commandPool = chain->cmd_pools[i],
405 .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
406 .commandBufferCount = 1,
407 };
408 result = wsi->AllocateCommandBuffers(chain->device, &cmd_buffer_info,
409 &image->prime.blit_cmd_buffers[i]);
410 if (result != VK_SUCCESS)
411 goto fail;
412
413 const VkCommandBufferBeginInfo begin_info = {
414 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
415 };
416 wsi->BeginCommandBuffer(image->prime.blit_cmd_buffers[i], &begin_info);
417
418 struct VkBufferImageCopy buffer_image_copy = {
419 .bufferOffset = 0,
420 .bufferRowLength = linear_stride / cpp,
421 .bufferImageHeight = 0,
422 .imageSubresource = {
423 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
424 .mipLevel = 0,
425 .baseArrayLayer = 0,
426 .layerCount = 1,
427 },
428 .imageOffset = { .x = 0, .y = 0, .z = 0 },
429 .imageExtent = {
430 .width = pCreateInfo->imageExtent.width,
431 .height = pCreateInfo->imageExtent.height,
432 .depth = 1,
433 },
434 };
435 wsi->CmdCopyImageToBuffer(image->prime.blit_cmd_buffers[i],
436 image->image,
437 VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
438 image->prime.buffer,
439 1, &buffer_image_copy);
440
441 result = wsi->EndCommandBuffer(image->prime.blit_cmd_buffers[i]);
442 if (result != VK_SUCCESS)
443 goto fail;
444 }
445
446 const VkMemoryGetFdInfoKHR linear_memory_get_fd_info = {
447 .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
448 .pNext = NULL,
449 .memory = image->prime.memory,
450 .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
451 };
452 int fd;
453 result = wsi->GetMemoryFdKHR(chain->device, &linear_memory_get_fd_info, &fd);
454 if (result != VK_SUCCESS)
455 goto fail;
456
457 image->size = linear_size;
458 image->row_pitch = linear_stride;
459 image->offset = 0;
460 image->fd = fd;
461
462 return VK_SUCCESS;
463
464 fail:
465 wsi_destroy_image(chain, image);
466
467 return result;
468 }
469
470 void
471 wsi_destroy_image(const struct wsi_swapchain *chain,
472 struct wsi_image *image)
473 {
474 const struct wsi_device *wsi = chain->wsi;
475
476 if (image->prime.blit_cmd_buffers) {
477 for (uint32_t i = 0; i < wsi->queue_family_count; i++) {
478 wsi->FreeCommandBuffers(chain->device, chain->cmd_pools[i],
479 1, &image->prime.blit_cmd_buffers[i]);
480 }
481 vk_free(&chain->alloc, image->prime.blit_cmd_buffers);
482 }
483
484 wsi->FreeMemory(chain->device, image->memory, &chain->alloc);
485 wsi->DestroyImage(chain->device, image->image, &chain->alloc);
486 wsi->FreeMemory(chain->device, image->prime.memory, &chain->alloc);
487 wsi->DestroyBuffer(chain->device, image->prime.buffer, &chain->alloc);
488 }
489
490 VkResult
491 wsi_common_get_surface_support(struct wsi_device *wsi_device,
492 int local_fd,
493 uint32_t queueFamilyIndex,
494 VkSurfaceKHR _surface,
495 const VkAllocationCallbacks *alloc,
496 VkBool32* pSupported)
497 {
498 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
499 struct wsi_interface *iface = wsi_device->wsi[surface->platform];
500
501 return iface->get_support(surface, wsi_device, alloc,
502 queueFamilyIndex, local_fd, pSupported);
503 }
504
505 VkResult
506 wsi_common_get_surface_capabilities(struct wsi_device *wsi_device,
507 VkSurfaceKHR _surface,
508 VkSurfaceCapabilitiesKHR *pSurfaceCapabilities)
509 {
510 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
511 struct wsi_interface *iface = wsi_device->wsi[surface->platform];
512
513 return iface->get_capabilities(surface, pSurfaceCapabilities);
514 }
515
516 VkResult
517 wsi_common_get_surface_capabilities2(struct wsi_device *wsi_device,
518 const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
519 VkSurfaceCapabilities2KHR *pSurfaceCapabilities)
520 {
521 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pSurfaceInfo->surface);
522 struct wsi_interface *iface = wsi_device->wsi[surface->platform];
523
524 return iface->get_capabilities2(surface, pSurfaceInfo->pNext,
525 pSurfaceCapabilities);
526 }
527
528 VkResult
529 wsi_common_get_surface_formats(struct wsi_device *wsi_device,
530 VkSurfaceKHR _surface,
531 uint32_t *pSurfaceFormatCount,
532 VkSurfaceFormatKHR *pSurfaceFormats)
533 {
534 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
535 struct wsi_interface *iface = wsi_device->wsi[surface->platform];
536
537 return iface->get_formats(surface, wsi_device,
538 pSurfaceFormatCount, pSurfaceFormats);
539 }
540
541 VkResult
542 wsi_common_get_surface_formats2(struct wsi_device *wsi_device,
543 const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
544 uint32_t *pSurfaceFormatCount,
545 VkSurfaceFormat2KHR *pSurfaceFormats)
546 {
547 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pSurfaceInfo->surface);
548 struct wsi_interface *iface = wsi_device->wsi[surface->platform];
549
550 return iface->get_formats2(surface, wsi_device, pSurfaceInfo->pNext,
551 pSurfaceFormatCount, pSurfaceFormats);
552 }
553
554 VkResult
555 wsi_common_get_surface_present_modes(struct wsi_device *wsi_device,
556 VkSurfaceKHR _surface,
557 uint32_t *pPresentModeCount,
558 VkPresentModeKHR *pPresentModes)
559 {
560 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
561 struct wsi_interface *iface = wsi_device->wsi[surface->platform];
562
563 return iface->get_present_modes(surface, pPresentModeCount,
564 pPresentModes);
565 }
566
567 VkResult
568 wsi_common_create_swapchain(struct wsi_device *wsi,
569 VkDevice device,
570 int fd,
571 const VkSwapchainCreateInfoKHR *pCreateInfo,
572 const VkAllocationCallbacks *pAllocator,
573 VkSwapchainKHR *pSwapchain)
574 {
575 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pCreateInfo->surface);
576 struct wsi_interface *iface = wsi->wsi[surface->platform];
577 struct wsi_swapchain *swapchain;
578
579 VkResult result = iface->create_swapchain(surface, device, wsi, fd,
580 pCreateInfo, pAllocator,
581 &swapchain);
582 if (result != VK_SUCCESS)
583 return result;
584
585 *pSwapchain = wsi_swapchain_to_handle(swapchain);
586
587 return VK_SUCCESS;
588 }
589
590 void
591 wsi_common_destroy_swapchain(VkDevice device,
592 VkSwapchainKHR _swapchain,
593 const VkAllocationCallbacks *pAllocator)
594 {
595 WSI_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain);
596 if (!swapchain)
597 return;
598
599 swapchain->destroy(swapchain, pAllocator);
600 }
601
602 VkResult
603 wsi_common_get_images(VkSwapchainKHR _swapchain,
604 uint32_t *pSwapchainImageCount,
605 VkImage *pSwapchainImages)
606 {
607 WSI_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain);
608 VK_OUTARRAY_MAKE(images, pSwapchainImages, pSwapchainImageCount);
609
610 for (uint32_t i = 0; i < swapchain->image_count; i++) {
611 vk_outarray_append(&images, image) {
612 *image = swapchain->get_wsi_image(swapchain, i)->image;
613 }
614 }
615
616 return vk_outarray_status(&images);
617 }
618
619 VkResult
620 wsi_common_acquire_next_image(const struct wsi_device *wsi,
621 VkDevice device,
622 VkSwapchainKHR _swapchain,
623 uint64_t timeout,
624 VkSemaphore semaphore,
625 uint32_t *pImageIndex)
626 {
627 WSI_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain);
628
629 return swapchain->acquire_next_image(swapchain, timeout,
630 semaphore, pImageIndex);
631 }
632
633 VkResult
634 wsi_common_queue_present(const struct wsi_device *wsi,
635 VkDevice device,
636 VkQueue queue,
637 int queue_family_index,
638 const VkPresentInfoKHR *pPresentInfo)
639 {
640 VkResult final_result = VK_SUCCESS;
641
642 const VkPresentRegionsKHR *regions =
643 vk_find_struct_const(pPresentInfo->pNext, PRESENT_REGIONS_KHR);
644
645 for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) {
646 WSI_FROM_HANDLE(wsi_swapchain, swapchain, pPresentInfo->pSwapchains[i]);
647 VkResult result;
648
649 if (swapchain->fences[0] == VK_NULL_HANDLE) {
650 const VkFenceCreateInfo fence_info = {
651 .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
652 .pNext = NULL,
653 .flags = 0,
654 };
655 result = wsi->CreateFence(device, &fence_info,
656 &swapchain->alloc,
657 &swapchain->fences[0]);
658 if (result != VK_SUCCESS)
659 goto fail_present;
660 } else {
661 wsi->ResetFences(device, 1, &swapchain->fences[0]);
662 }
663
664 VkSubmitInfo submit_info = {
665 .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
666 .pNext = NULL,
667 };
668
669 VkPipelineStageFlags *stage_flags = NULL;
670 if (i == 0) {
671 /* We only need/want to wait on semaphores once. After that, we're
672 * guaranteed ordering since it all happens on the same queue.
673 */
674 submit_info.waitSemaphoreCount = pPresentInfo->waitSemaphoreCount,
675 submit_info.pWaitSemaphores = pPresentInfo->pWaitSemaphores,
676
677 /* Set up the pWaitDstStageMasks */
678 stage_flags = vk_alloc(&swapchain->alloc,
679 sizeof(VkPipelineStageFlags) *
680 pPresentInfo->waitSemaphoreCount,
681 8,
682 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
683 if (!stage_flags) {
684 result = VK_ERROR_OUT_OF_HOST_MEMORY;
685 goto fail_present;
686 }
687 for (uint32_t s = 0; s < pPresentInfo->waitSemaphoreCount; s++)
688 stage_flags[s] = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
689
690 submit_info.pWaitDstStageMask = stage_flags;
691 }
692
693 if (swapchain->use_prime_blit) {
694 /* If we are using prime blits, we need to perform the blit now. The
695 * command buffer is attached to the image.
696 */
697 struct wsi_image *image =
698 swapchain->get_wsi_image(swapchain, pPresentInfo->pImageIndices[i]);
699 submit_info.commandBufferCount = 1;
700 submit_info.pCommandBuffers =
701 &image->prime.blit_cmd_buffers[queue_family_index];
702 }
703
704 result = wsi->QueueSubmit(queue, 1, &submit_info, swapchain->fences[0]);
705 vk_free(&swapchain->alloc, stage_flags);
706 if (result != VK_SUCCESS)
707 goto fail_present;
708
709 const VkPresentRegionKHR *region = NULL;
710 if (regions && regions->pRegions)
711 region = &regions->pRegions[i];
712
713 result = swapchain->queue_present(swapchain,
714 pPresentInfo->pImageIndices[i],
715 region);
716 if (result != VK_SUCCESS)
717 goto fail_present;
718
719 VkFence last = swapchain->fences[2];
720 swapchain->fences[2] = swapchain->fences[1];
721 swapchain->fences[1] = swapchain->fences[0];
722 swapchain->fences[0] = last;
723
724 if (last != VK_NULL_HANDLE) {
725 wsi->WaitForFences(device, 1, &last, true, 1);
726 }
727
728 fail_present:
729 if (pPresentInfo->pResults != NULL)
730 pPresentInfo->pResults[i] = result;
731
732 /* Let the final result be our first unsuccessful result */
733 if (final_result == VK_SUCCESS)
734 final_result = result;
735 }
736
737 return final_result;
738 }