2 * Copyright © 2017 Intel Corporation
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:
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
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
24 #include "wsi_common_private.h"
25 #include "drm_fourcc.h"
26 #include "util/macros.h"
30 wsi_device_init(struct wsi_device
*wsi
,
31 VkPhysicalDevice pdevice
,
32 WSI_FN_GetPhysicalDeviceProcAddr proc_addr
,
33 const VkAllocationCallbacks
*alloc
)
37 memset(wsi
, 0, sizeof(*wsi
));
39 #define WSI_GET_CB(func) \
40 PFN_vk##func func = (PFN_vk##func)proc_addr(pdevice, "vk" #func)
41 WSI_GET_CB(GetPhysicalDeviceMemoryProperties
);
42 WSI_GET_CB(GetPhysicalDeviceQueueFamilyProperties
);
45 GetPhysicalDeviceMemoryProperties(pdevice
, &wsi
->memory_props
);
46 GetPhysicalDeviceQueueFamilyProperties(pdevice
, &wsi
->queue_family_count
, NULL
);
48 #define WSI_GET_CB(func) \
49 wsi->func = (PFN_vk##func)proc_addr(pdevice, "vk" #func)
50 WSI_GET_CB(AllocateMemory
);
51 WSI_GET_CB(AllocateCommandBuffers
);
52 WSI_GET_CB(BindBufferMemory
);
53 WSI_GET_CB(BindImageMemory
);
54 WSI_GET_CB(BeginCommandBuffer
);
55 WSI_GET_CB(CmdCopyImageToBuffer
);
56 WSI_GET_CB(CreateBuffer
);
57 WSI_GET_CB(CreateCommandPool
);
58 WSI_GET_CB(CreateFence
);
59 WSI_GET_CB(CreateImage
);
60 WSI_GET_CB(DestroyBuffer
);
61 WSI_GET_CB(DestroyCommandPool
);
62 WSI_GET_CB(DestroyFence
);
63 WSI_GET_CB(DestroyImage
);
64 WSI_GET_CB(EndCommandBuffer
);
65 WSI_GET_CB(FreeMemory
);
66 WSI_GET_CB(FreeCommandBuffers
);
67 WSI_GET_CB(GetBufferMemoryRequirements
);
68 WSI_GET_CB(GetImageMemoryRequirements
);
69 WSI_GET_CB(GetImageSubresourceLayout
);
70 WSI_GET_CB(GetMemoryFdKHR
);
71 WSI_GET_CB(GetPhysicalDeviceFormatProperties
);
72 WSI_GET_CB(ResetFences
);
73 WSI_GET_CB(QueueSubmit
);
74 WSI_GET_CB(WaitForFences
);
77 #ifdef VK_USE_PLATFORM_XCB_KHR
78 result
= wsi_x11_init_wsi(wsi
, alloc
);
79 if (result
!= VK_SUCCESS
)
83 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
84 result
= wsi_wl_init_wsi(wsi
, alloc
, pdevice
);
85 if (result
!= VK_SUCCESS
) {
86 #ifdef VK_USE_PLATFORM_XCB_KHR
87 wsi_x11_finish_wsi(wsi
, alloc
);
97 wsi_device_finish(struct wsi_device
*wsi
,
98 const VkAllocationCallbacks
*alloc
)
100 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
101 wsi_wl_finish_wsi(wsi
, alloc
);
103 #ifdef VK_USE_PLATFORM_XCB_KHR
104 wsi_x11_finish_wsi(wsi
, alloc
);
109 wsi_swapchain_init(const struct wsi_device
*wsi
,
110 struct wsi_swapchain
*chain
,
112 const VkSwapchainCreateInfoKHR
*pCreateInfo
,
113 const VkAllocationCallbacks
*pAllocator
)
117 memset(chain
, 0, sizeof(*chain
));
120 chain
->device
= device
;
121 chain
->alloc
= *pAllocator
;
122 chain
->use_prime_blit
= false;
125 vk_zalloc(pAllocator
, sizeof(VkCommandPool
) * wsi
->queue_family_count
, 8,
126 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
127 if (!chain
->cmd_pools
)
128 return VK_ERROR_OUT_OF_HOST_MEMORY
;
130 for (uint32_t i
= 0; i
< wsi
->queue_family_count
; i
++) {
131 const VkCommandPoolCreateInfo cmd_pool_info
= {
132 .sType
= VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO
,
135 .queueFamilyIndex
= i
,
137 result
= wsi
->CreateCommandPool(device
, &cmd_pool_info
, &chain
->alloc
,
138 &chain
->cmd_pools
[i
]);
139 if (result
!= VK_SUCCESS
)
146 wsi_swapchain_finish(chain
);
151 wsi_swapchain_finish(struct wsi_swapchain
*chain
)
153 for (unsigned i
= 0; i
< ARRAY_SIZE(chain
->fences
); i
++)
154 chain
->wsi
->DestroyFence(chain
->device
, chain
->fences
[i
], &chain
->alloc
);
156 for (uint32_t i
= 0; i
< chain
->wsi
->queue_family_count
; i
++) {
157 chain
->wsi
->DestroyCommandPool(chain
->device
, chain
->cmd_pools
[i
],
160 vk_free(&chain
->alloc
, chain
->cmd_pools
);
164 select_memory_type(const struct wsi_device
*wsi
,
165 VkMemoryPropertyFlags props
,
168 for (uint32_t i
= 0; i
< wsi
->memory_props
.memoryTypeCount
; i
++) {
169 const VkMemoryType type
= wsi
->memory_props
.memoryTypes
[i
];
170 if ((type_bits
& (1 << i
)) && (type
.propertyFlags
& props
) == props
)
174 unreachable("No memory type found");
178 vk_format_size(VkFormat format
)
181 case VK_FORMAT_B8G8R8A8_UNORM
:
182 case VK_FORMAT_B8G8R8A8_SRGB
:
185 unreachable("Unknown WSI Format");
189 static inline uint32_t
190 align_u32(uint32_t v
, uint32_t a
)
192 assert(a
!= 0 && a
== (a
& -a
));
193 return (v
+ a
- 1) & ~(a
- 1);
197 wsi_create_native_image(const struct wsi_swapchain
*chain
,
198 const VkSwapchainCreateInfoKHR
*pCreateInfo
,
199 struct wsi_image
*image
)
201 const struct wsi_device
*wsi
= chain
->wsi
;
204 memset(image
, 0, sizeof(*image
));
205 for (int i
= 0; i
< ARRAY_SIZE(image
->fds
); i
++)
208 const struct wsi_image_create_info image_wsi_info
= {
209 .sType
= VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA
,
213 const VkImageCreateInfo image_info
= {
214 .sType
= VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
,
215 .pNext
= &image_wsi_info
,
217 .imageType
= VK_IMAGE_TYPE_2D
,
218 .format
= pCreateInfo
->imageFormat
,
220 .width
= pCreateInfo
->imageExtent
.width
,
221 .height
= pCreateInfo
->imageExtent
.height
,
226 .samples
= VK_SAMPLE_COUNT_1_BIT
,
227 .tiling
= VK_IMAGE_TILING_OPTIMAL
,
228 .usage
= pCreateInfo
->imageUsage
,
229 .sharingMode
= pCreateInfo
->imageSharingMode
,
230 .queueFamilyIndexCount
= pCreateInfo
->queueFamilyIndexCount
,
231 .pQueueFamilyIndices
= pCreateInfo
->pQueueFamilyIndices
,
232 .initialLayout
= VK_IMAGE_LAYOUT_UNDEFINED
,
234 result
= wsi
->CreateImage(chain
->device
, &image_info
,
235 &chain
->alloc
, &image
->image
);
236 if (result
!= VK_SUCCESS
)
239 VkMemoryRequirements reqs
;
240 wsi
->GetImageMemoryRequirements(chain
->device
, image
->image
, &reqs
);
242 VkSubresourceLayout image_layout
;
243 const VkImageSubresource image_subresource
= {
244 .aspectMask
= VK_IMAGE_ASPECT_COLOR_BIT
,
248 wsi
->GetImageSubresourceLayout(chain
->device
, image
->image
,
249 &image_subresource
, &image_layout
);
251 const struct wsi_memory_allocate_info memory_wsi_info
= {
252 .sType
= VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA
,
254 .implicit_sync
= true,
256 const VkExportMemoryAllocateInfoKHR memory_export_info
= {
257 .sType
= VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR
,
258 .pNext
= &memory_wsi_info
,
259 .handleTypes
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
,
261 const VkMemoryDedicatedAllocateInfoKHR memory_dedicated_info
= {
262 .sType
= VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR
,
263 .pNext
= &memory_export_info
,
264 .image
= image
->image
,
265 .buffer
= VK_NULL_HANDLE
,
267 const VkMemoryAllocateInfo memory_info
= {
268 .sType
= VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO
,
269 .pNext
= &memory_dedicated_info
,
270 .allocationSize
= reqs
.size
,
271 .memoryTypeIndex
= select_memory_type(wsi
, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
,
272 reqs
.memoryTypeBits
),
274 result
= wsi
->AllocateMemory(chain
->device
, &memory_info
,
275 &chain
->alloc
, &image
->memory
);
276 if (result
!= VK_SUCCESS
)
279 result
= wsi
->BindImageMemory(chain
->device
, image
->image
,
281 if (result
!= VK_SUCCESS
)
284 const VkMemoryGetFdInfoKHR memory_get_fd_info
= {
285 .sType
= VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR
,
287 .memory
= image
->memory
,
288 .handleType
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
,
291 result
= wsi
->GetMemoryFdKHR(chain
->device
, &memory_get_fd_info
, &fd
);
292 if (result
!= VK_SUCCESS
)
295 image
->drm_modifier
= DRM_FORMAT_MOD_INVALID
;
296 image
->num_planes
= 1;
297 image
->sizes
[0] = reqs
.size
;
298 image
->row_pitches
[0] = image_layout
.rowPitch
;
299 image
->offsets
[0] = 0;
305 wsi_destroy_image(chain
, image
);
310 #define WSI_PRIME_LINEAR_STRIDE_ALIGN 256
313 wsi_create_prime_image(const struct wsi_swapchain
*chain
,
314 const VkSwapchainCreateInfoKHR
*pCreateInfo
,
315 struct wsi_image
*image
)
317 const struct wsi_device
*wsi
= chain
->wsi
;
320 memset(image
, 0, sizeof(*image
));
322 const uint32_t cpp
= vk_format_size(pCreateInfo
->imageFormat
);
323 const uint32_t linear_stride
= align_u32(pCreateInfo
->imageExtent
.width
* cpp
,
324 WSI_PRIME_LINEAR_STRIDE_ALIGN
);
326 uint32_t linear_size
= linear_stride
* pCreateInfo
->imageExtent
.height
;
327 linear_size
= align_u32(linear_size
, 4096);
329 const VkExternalMemoryBufferCreateInfoKHR prime_buffer_external_info
= {
330 .sType
= VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR
,
332 .handleTypes
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
,
334 const VkBufferCreateInfo prime_buffer_info
= {
335 .sType
= VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO
,
336 .pNext
= &prime_buffer_external_info
,
338 .usage
= VK_BUFFER_USAGE_TRANSFER_DST_BIT
,
339 .sharingMode
= VK_SHARING_MODE_EXCLUSIVE
,
341 result
= wsi
->CreateBuffer(chain
->device
, &prime_buffer_info
,
342 &chain
->alloc
, &image
->prime
.buffer
);
343 if (result
!= VK_SUCCESS
)
346 VkMemoryRequirements reqs
;
347 wsi
->GetBufferMemoryRequirements(chain
->device
, image
->prime
.buffer
, &reqs
);
348 assert(reqs
.size
<= linear_size
);
350 const struct wsi_memory_allocate_info memory_wsi_info
= {
351 .sType
= VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA
,
353 .implicit_sync
= true,
355 const VkExportMemoryAllocateInfoKHR prime_memory_export_info
= {
356 .sType
= VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR
,
357 .pNext
= &memory_wsi_info
,
358 .handleTypes
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
,
360 const VkMemoryDedicatedAllocateInfoKHR prime_memory_dedicated_info
= {
361 .sType
= VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR
,
362 .pNext
= &prime_memory_export_info
,
363 .image
= VK_NULL_HANDLE
,
364 .buffer
= image
->prime
.buffer
,
366 const VkMemoryAllocateInfo prime_memory_info
= {
367 .sType
= VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO
,
368 .pNext
= &prime_memory_dedicated_info
,
369 .allocationSize
= linear_size
,
370 .memoryTypeIndex
= select_memory_type(wsi
, 0, reqs
.memoryTypeBits
),
372 result
= wsi
->AllocateMemory(chain
->device
, &prime_memory_info
,
373 &chain
->alloc
, &image
->prime
.memory
);
374 if (result
!= VK_SUCCESS
)
377 result
= wsi
->BindBufferMemory(chain
->device
, image
->prime
.buffer
,
378 image
->prime
.memory
, 0);
379 if (result
!= VK_SUCCESS
)
382 const VkImageCreateInfo image_info
= {
383 .sType
= VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
,
386 .imageType
= VK_IMAGE_TYPE_2D
,
387 .format
= pCreateInfo
->imageFormat
,
389 .width
= pCreateInfo
->imageExtent
.width
,
390 .height
= pCreateInfo
->imageExtent
.height
,
395 .samples
= VK_SAMPLE_COUNT_1_BIT
,
396 .tiling
= VK_IMAGE_TILING_OPTIMAL
,
397 .usage
= pCreateInfo
->imageUsage
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT
,
398 .sharingMode
= pCreateInfo
->imageSharingMode
,
399 .queueFamilyIndexCount
= pCreateInfo
->queueFamilyIndexCount
,
400 .pQueueFamilyIndices
= pCreateInfo
->pQueueFamilyIndices
,
401 .initialLayout
= VK_IMAGE_LAYOUT_UNDEFINED
,
403 result
= wsi
->CreateImage(chain
->device
, &image_info
,
404 &chain
->alloc
, &image
->image
);
405 if (result
!= VK_SUCCESS
)
408 wsi
->GetImageMemoryRequirements(chain
->device
, image
->image
, &reqs
);
410 const VkMemoryDedicatedAllocateInfoKHR memory_dedicated_info
= {
411 .sType
= VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR
,
413 .image
= image
->image
,
414 .buffer
= VK_NULL_HANDLE
,
416 const VkMemoryAllocateInfo memory_info
= {
417 .sType
= VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO
,
418 .pNext
= &memory_dedicated_info
,
419 .allocationSize
= reqs
.size
,
420 .memoryTypeIndex
= select_memory_type(wsi
, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
,
421 reqs
.memoryTypeBits
),
423 result
= wsi
->AllocateMemory(chain
->device
, &memory_info
,
424 &chain
->alloc
, &image
->memory
);
425 if (result
!= VK_SUCCESS
)
428 result
= wsi
->BindImageMemory(chain
->device
, image
->image
,
430 if (result
!= VK_SUCCESS
)
433 image
->prime
.blit_cmd_buffers
=
434 vk_zalloc(&chain
->alloc
,
435 sizeof(VkCommandBuffer
) * wsi
->queue_family_count
, 8,
436 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
437 if (!image
->prime
.blit_cmd_buffers
) {
438 result
= VK_ERROR_OUT_OF_HOST_MEMORY
;
442 for (uint32_t i
= 0; i
< wsi
->queue_family_count
; i
++) {
443 const VkCommandBufferAllocateInfo cmd_buffer_info
= {
444 .sType
= VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO
,
446 .commandPool
= chain
->cmd_pools
[i
],
447 .level
= VK_COMMAND_BUFFER_LEVEL_PRIMARY
,
448 .commandBufferCount
= 1,
450 result
= wsi
->AllocateCommandBuffers(chain
->device
, &cmd_buffer_info
,
451 &image
->prime
.blit_cmd_buffers
[i
]);
452 if (result
!= VK_SUCCESS
)
455 const VkCommandBufferBeginInfo begin_info
= {
456 .sType
= VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO
,
458 wsi
->BeginCommandBuffer(image
->prime
.blit_cmd_buffers
[i
], &begin_info
);
460 struct VkBufferImageCopy buffer_image_copy
= {
462 .bufferRowLength
= linear_stride
/ cpp
,
463 .bufferImageHeight
= 0,
464 .imageSubresource
= {
465 .aspectMask
= VK_IMAGE_ASPECT_COLOR_BIT
,
470 .imageOffset
= { .x
= 0, .y
= 0, .z
= 0 },
472 .width
= pCreateInfo
->imageExtent
.width
,
473 .height
= pCreateInfo
->imageExtent
.height
,
477 wsi
->CmdCopyImageToBuffer(image
->prime
.blit_cmd_buffers
[i
],
479 VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
,
481 1, &buffer_image_copy
);
483 result
= wsi
->EndCommandBuffer(image
->prime
.blit_cmd_buffers
[i
]);
484 if (result
!= VK_SUCCESS
)
488 const VkMemoryGetFdInfoKHR linear_memory_get_fd_info
= {
489 .sType
= VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR
,
491 .memory
= image
->prime
.memory
,
492 .handleType
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
,
495 result
= wsi
->GetMemoryFdKHR(chain
->device
, &linear_memory_get_fd_info
, &fd
);
496 if (result
!= VK_SUCCESS
)
499 image
->drm_modifier
= DRM_FORMAT_MOD_LINEAR
;
500 image
->num_planes
= 1;
501 image
->sizes
[0] = linear_size
;
502 image
->row_pitches
[0] = linear_stride
;
503 image
->offsets
[0] = 0;
509 wsi_destroy_image(chain
, image
);
515 wsi_destroy_image(const struct wsi_swapchain
*chain
,
516 struct wsi_image
*image
)
518 const struct wsi_device
*wsi
= chain
->wsi
;
520 if (image
->prime
.blit_cmd_buffers
) {
521 for (uint32_t i
= 0; i
< wsi
->queue_family_count
; i
++) {
522 wsi
->FreeCommandBuffers(chain
->device
, chain
->cmd_pools
[i
],
523 1, &image
->prime
.blit_cmd_buffers
[i
]);
525 vk_free(&chain
->alloc
, image
->prime
.blit_cmd_buffers
);
528 wsi
->FreeMemory(chain
->device
, image
->memory
, &chain
->alloc
);
529 wsi
->DestroyImage(chain
->device
, image
->image
, &chain
->alloc
);
530 wsi
->FreeMemory(chain
->device
, image
->prime
.memory
, &chain
->alloc
);
531 wsi
->DestroyBuffer(chain
->device
, image
->prime
.buffer
, &chain
->alloc
);
535 wsi_common_get_surface_support(struct wsi_device
*wsi_device
,
537 uint32_t queueFamilyIndex
,
538 VkSurfaceKHR _surface
,
539 const VkAllocationCallbacks
*alloc
,
540 VkBool32
* pSupported
)
542 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, _surface
);
543 struct wsi_interface
*iface
= wsi_device
->wsi
[surface
->platform
];
545 return iface
->get_support(surface
, wsi_device
, alloc
,
546 queueFamilyIndex
, local_fd
, pSupported
);
550 wsi_common_get_surface_capabilities(struct wsi_device
*wsi_device
,
551 VkSurfaceKHR _surface
,
552 VkSurfaceCapabilitiesKHR
*pSurfaceCapabilities
)
554 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, _surface
);
555 struct wsi_interface
*iface
= wsi_device
->wsi
[surface
->platform
];
557 return iface
->get_capabilities(surface
, pSurfaceCapabilities
);
561 wsi_common_get_surface_capabilities2(struct wsi_device
*wsi_device
,
562 const VkPhysicalDeviceSurfaceInfo2KHR
*pSurfaceInfo
,
563 VkSurfaceCapabilities2KHR
*pSurfaceCapabilities
)
565 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, pSurfaceInfo
->surface
);
566 struct wsi_interface
*iface
= wsi_device
->wsi
[surface
->platform
];
568 return iface
->get_capabilities2(surface
, pSurfaceInfo
->pNext
,
569 pSurfaceCapabilities
);
573 wsi_common_get_surface_formats(struct wsi_device
*wsi_device
,
574 VkSurfaceKHR _surface
,
575 uint32_t *pSurfaceFormatCount
,
576 VkSurfaceFormatKHR
*pSurfaceFormats
)
578 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, _surface
);
579 struct wsi_interface
*iface
= wsi_device
->wsi
[surface
->platform
];
581 return iface
->get_formats(surface
, wsi_device
,
582 pSurfaceFormatCount
, pSurfaceFormats
);
586 wsi_common_get_surface_formats2(struct wsi_device
*wsi_device
,
587 const VkPhysicalDeviceSurfaceInfo2KHR
*pSurfaceInfo
,
588 uint32_t *pSurfaceFormatCount
,
589 VkSurfaceFormat2KHR
*pSurfaceFormats
)
591 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, pSurfaceInfo
->surface
);
592 struct wsi_interface
*iface
= wsi_device
->wsi
[surface
->platform
];
594 return iface
->get_formats2(surface
, wsi_device
, pSurfaceInfo
->pNext
,
595 pSurfaceFormatCount
, pSurfaceFormats
);
599 wsi_common_get_surface_present_modes(struct wsi_device
*wsi_device
,
600 VkSurfaceKHR _surface
,
601 uint32_t *pPresentModeCount
,
602 VkPresentModeKHR
*pPresentModes
)
604 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, _surface
);
605 struct wsi_interface
*iface
= wsi_device
->wsi
[surface
->platform
];
607 return iface
->get_present_modes(surface
, pPresentModeCount
,
612 wsi_common_create_swapchain(struct wsi_device
*wsi
,
615 const VkSwapchainCreateInfoKHR
*pCreateInfo
,
616 const VkAllocationCallbacks
*pAllocator
,
617 VkSwapchainKHR
*pSwapchain
)
619 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, pCreateInfo
->surface
);
620 struct wsi_interface
*iface
= wsi
->wsi
[surface
->platform
];
621 struct wsi_swapchain
*swapchain
;
623 VkResult result
= iface
->create_swapchain(surface
, device
, wsi
, fd
,
624 pCreateInfo
, pAllocator
,
626 if (result
!= VK_SUCCESS
)
629 *pSwapchain
= wsi_swapchain_to_handle(swapchain
);
635 wsi_common_destroy_swapchain(VkDevice device
,
636 VkSwapchainKHR _swapchain
,
637 const VkAllocationCallbacks
*pAllocator
)
639 WSI_FROM_HANDLE(wsi_swapchain
, swapchain
, _swapchain
);
643 swapchain
->destroy(swapchain
, pAllocator
);
647 wsi_common_get_images(VkSwapchainKHR _swapchain
,
648 uint32_t *pSwapchainImageCount
,
649 VkImage
*pSwapchainImages
)
651 WSI_FROM_HANDLE(wsi_swapchain
, swapchain
, _swapchain
);
652 VK_OUTARRAY_MAKE(images
, pSwapchainImages
, pSwapchainImageCount
);
654 for (uint32_t i
= 0; i
< swapchain
->image_count
; i
++) {
655 vk_outarray_append(&images
, image
) {
656 *image
= swapchain
->get_wsi_image(swapchain
, i
)->image
;
660 return vk_outarray_status(&images
);
664 wsi_common_acquire_next_image(const struct wsi_device
*wsi
,
666 VkSwapchainKHR _swapchain
,
668 VkSemaphore semaphore
,
669 uint32_t *pImageIndex
)
671 WSI_FROM_HANDLE(wsi_swapchain
, swapchain
, _swapchain
);
673 return swapchain
->acquire_next_image(swapchain
, timeout
,
674 semaphore
, pImageIndex
);
678 wsi_common_queue_present(const struct wsi_device
*wsi
,
681 int queue_family_index
,
682 const VkPresentInfoKHR
*pPresentInfo
)
684 VkResult final_result
= VK_SUCCESS
;
686 const VkPresentRegionsKHR
*regions
=
687 vk_find_struct_const(pPresentInfo
->pNext
, PRESENT_REGIONS_KHR
);
689 for (uint32_t i
= 0; i
< pPresentInfo
->swapchainCount
; i
++) {
690 WSI_FROM_HANDLE(wsi_swapchain
, swapchain
, pPresentInfo
->pSwapchains
[i
]);
693 if (swapchain
->fences
[0] == VK_NULL_HANDLE
) {
694 const VkFenceCreateInfo fence_info
= {
695 .sType
= VK_STRUCTURE_TYPE_FENCE_CREATE_INFO
,
699 result
= wsi
->CreateFence(device
, &fence_info
,
701 &swapchain
->fences
[0]);
702 if (result
!= VK_SUCCESS
)
705 wsi
->ResetFences(device
, 1, &swapchain
->fences
[0]);
708 VkSubmitInfo submit_info
= {
709 .sType
= VK_STRUCTURE_TYPE_SUBMIT_INFO
,
713 VkPipelineStageFlags
*stage_flags
= NULL
;
715 /* We only need/want to wait on semaphores once. After that, we're
716 * guaranteed ordering since it all happens on the same queue.
718 submit_info
.waitSemaphoreCount
= pPresentInfo
->waitSemaphoreCount
,
719 submit_info
.pWaitSemaphores
= pPresentInfo
->pWaitSemaphores
,
721 /* Set up the pWaitDstStageMasks */
722 stage_flags
= vk_alloc(&swapchain
->alloc
,
723 sizeof(VkPipelineStageFlags
) *
724 pPresentInfo
->waitSemaphoreCount
,
726 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND
);
728 result
= VK_ERROR_OUT_OF_HOST_MEMORY
;
731 for (uint32_t s
= 0; s
< pPresentInfo
->waitSemaphoreCount
; s
++)
732 stage_flags
[s
] = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT
;
734 submit_info
.pWaitDstStageMask
= stage_flags
;
737 if (swapchain
->use_prime_blit
) {
738 /* If we are using prime blits, we need to perform the blit now. The
739 * command buffer is attached to the image.
741 struct wsi_image
*image
=
742 swapchain
->get_wsi_image(swapchain
, pPresentInfo
->pImageIndices
[i
]);
743 submit_info
.commandBufferCount
= 1;
744 submit_info
.pCommandBuffers
=
745 &image
->prime
.blit_cmd_buffers
[queue_family_index
];
748 result
= wsi
->QueueSubmit(queue
, 1, &submit_info
, swapchain
->fences
[0]);
749 vk_free(&swapchain
->alloc
, stage_flags
);
750 if (result
!= VK_SUCCESS
)
753 const VkPresentRegionKHR
*region
= NULL
;
754 if (regions
&& regions
->pRegions
)
755 region
= ®ions
->pRegions
[i
];
757 result
= swapchain
->queue_present(swapchain
,
758 pPresentInfo
->pImageIndices
[i
],
760 if (result
!= VK_SUCCESS
)
763 VkFence last
= swapchain
->fences
[2];
764 swapchain
->fences
[2] = swapchain
->fences
[1];
765 swapchain
->fences
[1] = swapchain
->fences
[0];
766 swapchain
->fences
[0] = last
;
768 if (last
!= VK_NULL_HANDLE
) {
769 wsi
->WaitForFences(device
, 1, &last
, true, 1);
773 if (pPresentInfo
->pResults
!= NULL
)
774 pPresentInfo
->pResults
[i
] = result
;
776 /* Let the final result be our first unsuccessful result */
777 if (final_result
== VK_SUCCESS
)
778 final_result
= result
;