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