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"
32 wsi_device_init(struct wsi_device
*wsi
,
33 VkPhysicalDevice pdevice
,
34 WSI_FN_GetPhysicalDeviceProcAddr proc_addr
,
35 const VkAllocationCallbacks
*alloc
,
40 memset(wsi
, 0, sizeof(*wsi
));
42 wsi
->pdevice
= pdevice
;
44 #define WSI_GET_CB(func) \
45 PFN_vk##func func = (PFN_vk##func)proc_addr(pdevice, "vk" #func)
46 WSI_GET_CB(GetPhysicalDeviceMemoryProperties
);
47 WSI_GET_CB(GetPhysicalDeviceQueueFamilyProperties
);
50 GetPhysicalDeviceMemoryProperties(pdevice
, &wsi
->memory_props
);
51 GetPhysicalDeviceQueueFamilyProperties(pdevice
, &wsi
->queue_family_count
, NULL
);
53 #define WSI_GET_CB(func) \
54 wsi->func = (PFN_vk##func)proc_addr(pdevice, "vk" #func)
55 WSI_GET_CB(AllocateMemory
);
56 WSI_GET_CB(AllocateCommandBuffers
);
57 WSI_GET_CB(BindBufferMemory
);
58 WSI_GET_CB(BindImageMemory
);
59 WSI_GET_CB(BeginCommandBuffer
);
60 WSI_GET_CB(CmdCopyImageToBuffer
);
61 WSI_GET_CB(CreateBuffer
);
62 WSI_GET_CB(CreateCommandPool
);
63 WSI_GET_CB(CreateFence
);
64 WSI_GET_CB(CreateImage
);
65 WSI_GET_CB(DestroyBuffer
);
66 WSI_GET_CB(DestroyCommandPool
);
67 WSI_GET_CB(DestroyFence
);
68 WSI_GET_CB(DestroyImage
);
69 WSI_GET_CB(EndCommandBuffer
);
70 WSI_GET_CB(FreeMemory
);
71 WSI_GET_CB(FreeCommandBuffers
);
72 WSI_GET_CB(GetBufferMemoryRequirements
);
73 WSI_GET_CB(GetImageMemoryRequirements
);
74 WSI_GET_CB(GetImageSubresourceLayout
);
75 WSI_GET_CB(GetMemoryFdKHR
);
76 WSI_GET_CB(GetPhysicalDeviceFormatProperties
);
77 WSI_GET_CB(GetPhysicalDeviceFormatProperties2KHR
);
78 WSI_GET_CB(ResetFences
);
79 WSI_GET_CB(QueueSubmit
);
80 WSI_GET_CB(WaitForFences
);
83 #ifdef VK_USE_PLATFORM_XCB_KHR
84 result
= wsi_x11_init_wsi(wsi
, alloc
);
85 if (result
!= VK_SUCCESS
)
89 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
90 result
= wsi_wl_init_wsi(wsi
, alloc
, pdevice
);
91 if (result
!= VK_SUCCESS
)
95 #ifdef VK_USE_PLATFORM_DISPLAY_KHR
96 result
= wsi_display_init_wsi(wsi
, alloc
, display_fd
);
97 if (result
!= VK_SUCCESS
)
104 wsi_device_finish(wsi
, alloc
);
109 wsi_device_finish(struct wsi_device
*wsi
,
110 const VkAllocationCallbacks
*alloc
)
112 #ifdef VK_USE_PLATFORM_DISPLAY_KHR
113 wsi_display_finish_wsi(wsi
, alloc
);
115 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
116 wsi_wl_finish_wsi(wsi
, alloc
);
118 #ifdef VK_USE_PLATFORM_XCB_KHR
119 wsi_x11_finish_wsi(wsi
, alloc
);
124 wsi_swapchain_init(const struct wsi_device
*wsi
,
125 struct wsi_swapchain
*chain
,
127 const VkSwapchainCreateInfoKHR
*pCreateInfo
,
128 const VkAllocationCallbacks
*pAllocator
)
132 memset(chain
, 0, sizeof(*chain
));
135 chain
->device
= device
;
136 chain
->alloc
= *pAllocator
;
137 chain
->use_prime_blit
= false;
140 vk_zalloc(pAllocator
, sizeof(VkCommandPool
) * wsi
->queue_family_count
, 8,
141 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
142 if (!chain
->cmd_pools
)
143 return VK_ERROR_OUT_OF_HOST_MEMORY
;
145 for (uint32_t i
= 0; i
< wsi
->queue_family_count
; i
++) {
146 const VkCommandPoolCreateInfo cmd_pool_info
= {
147 .sType
= VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO
,
150 .queueFamilyIndex
= i
,
152 result
= wsi
->CreateCommandPool(device
, &cmd_pool_info
, &chain
->alloc
,
153 &chain
->cmd_pools
[i
]);
154 if (result
!= VK_SUCCESS
)
161 wsi_swapchain_finish(chain
);
166 wsi_swapchain_finish(struct wsi_swapchain
*chain
)
168 for (unsigned i
= 0; i
< ARRAY_SIZE(chain
->fences
); i
++)
169 chain
->wsi
->DestroyFence(chain
->device
, chain
->fences
[i
], &chain
->alloc
);
171 for (uint32_t i
= 0; i
< chain
->wsi
->queue_family_count
; i
++) {
172 chain
->wsi
->DestroyCommandPool(chain
->device
, chain
->cmd_pools
[i
],
175 vk_free(&chain
->alloc
, chain
->cmd_pools
);
179 select_memory_type(const struct wsi_device
*wsi
,
180 VkMemoryPropertyFlags props
,
183 for (uint32_t i
= 0; i
< wsi
->memory_props
.memoryTypeCount
; i
++) {
184 const VkMemoryType type
= wsi
->memory_props
.memoryTypes
[i
];
185 if ((type_bits
& (1 << i
)) && (type
.propertyFlags
& props
) == props
)
189 unreachable("No memory type found");
193 vk_format_size(VkFormat format
)
196 case VK_FORMAT_B8G8R8A8_UNORM
:
197 case VK_FORMAT_B8G8R8A8_SRGB
:
200 unreachable("Unknown WSI Format");
204 static inline uint32_t
205 align_u32(uint32_t v
, uint32_t a
)
207 assert(a
!= 0 && a
== (a
& -a
));
208 return (v
+ a
- 1) & ~(a
- 1);
212 wsi_create_native_image(const struct wsi_swapchain
*chain
,
213 const VkSwapchainCreateInfoKHR
*pCreateInfo
,
214 uint32_t num_modifier_lists
,
215 const uint32_t *num_modifiers
,
216 const uint64_t *const *modifiers
,
217 struct wsi_image
*image
)
219 const struct wsi_device
*wsi
= chain
->wsi
;
222 memset(image
, 0, sizeof(*image
));
223 for (int i
= 0; i
< ARRAY_SIZE(image
->fds
); i
++)
226 struct wsi_image_create_info image_wsi_info
= {
227 .sType
= VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA
,
231 uint32_t image_modifier_count
= 0, modifier_prop_count
= 0;
232 struct wsi_format_modifier_properties
*modifier_props
= NULL
;
233 uint64_t *image_modifiers
= NULL
;
234 if (num_modifier_lists
== 0) {
235 /* If we don't have modifiers, fall back to the legacy "scanout" flag */
236 image_wsi_info
.scanout
= true;
238 /* The winsys can't request modifiers if we don't support them. */
239 assert(wsi
->supports_modifiers
);
240 struct wsi_format_modifier_properties_list modifier_props_list
= {
241 .sType
= VK_STRUCTURE_TYPE_WSI_FORMAT_MODIFIER_PROPERTIES_LIST_MESA
,
244 VkFormatProperties2KHR format_props
= {
245 .sType
= VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR
,
246 .pNext
= &modifier_props_list
,
248 wsi
->GetPhysicalDeviceFormatProperties2KHR(wsi
->pdevice
,
249 pCreateInfo
->imageFormat
,
251 assert(modifier_props_list
.modifier_count
> 0);
252 modifier_props
= vk_alloc(&chain
->alloc
,
253 sizeof(*modifier_props
) *
254 modifier_props_list
.modifier_count
,
256 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND
);
257 if (!modifier_props
) {
258 result
= VK_ERROR_OUT_OF_HOST_MEMORY
;
262 modifier_props_list
.modifier_properties
= modifier_props
;
263 wsi
->GetPhysicalDeviceFormatProperties2KHR(wsi
->pdevice
,
264 pCreateInfo
->imageFormat
,
266 modifier_prop_count
= modifier_props_list
.modifier_count
;
268 uint32_t max_modifier_count
= 0;
269 for (uint32_t l
= 0; l
< num_modifier_lists
; l
++)
270 max_modifier_count
= MAX2(max_modifier_count
, num_modifiers
[l
]);
272 image_modifiers
= vk_alloc(&chain
->alloc
,
273 sizeof(*image_modifiers
) *
276 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND
);
277 if (!image_modifiers
) {
278 result
= VK_ERROR_OUT_OF_HOST_MEMORY
;
282 image_modifier_count
= 0;
283 for (uint32_t l
= 0; l
< num_modifier_lists
; l
++) {
284 /* Walk the modifier lists and construct a list of supported
287 for (uint32_t i
= 0; i
< num_modifiers
[l
]; i
++) {
288 for (uint32_t j
= 0; j
< modifier_prop_count
; j
++) {
289 if (modifier_props
[j
].modifier
== modifiers
[l
][i
])
290 image_modifiers
[image_modifier_count
++] = modifiers
[l
][i
];
294 /* We only want to take the modifiers from the first list */
295 if (image_modifier_count
> 0)
299 if (image_modifier_count
> 0) {
300 image_wsi_info
.modifier_count
= image_modifier_count
;
301 image_wsi_info
.modifiers
= image_modifiers
;
303 /* TODO: Add a proper error here */
304 assert(!"Failed to find a supported modifier! This should never "
305 "happen because LINEAR should always be available");
306 result
= VK_ERROR_OUT_OF_HOST_MEMORY
;
311 const VkImageCreateInfo image_info
= {
312 .sType
= VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
,
313 .pNext
= &image_wsi_info
,
315 .imageType
= VK_IMAGE_TYPE_2D
,
316 .format
= pCreateInfo
->imageFormat
,
318 .width
= pCreateInfo
->imageExtent
.width
,
319 .height
= pCreateInfo
->imageExtent
.height
,
324 .samples
= VK_SAMPLE_COUNT_1_BIT
,
325 .tiling
= VK_IMAGE_TILING_OPTIMAL
,
326 .usage
= pCreateInfo
->imageUsage
,
327 .sharingMode
= pCreateInfo
->imageSharingMode
,
328 .queueFamilyIndexCount
= pCreateInfo
->queueFamilyIndexCount
,
329 .pQueueFamilyIndices
= pCreateInfo
->pQueueFamilyIndices
,
330 .initialLayout
= VK_IMAGE_LAYOUT_UNDEFINED
,
332 result
= wsi
->CreateImage(chain
->device
, &image_info
,
333 &chain
->alloc
, &image
->image
);
334 if (result
!= VK_SUCCESS
)
337 VkMemoryRequirements reqs
;
338 wsi
->GetImageMemoryRequirements(chain
->device
, image
->image
, &reqs
);
340 const struct wsi_memory_allocate_info memory_wsi_info
= {
341 .sType
= VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA
,
343 .implicit_sync
= true,
345 const VkExportMemoryAllocateInfoKHR memory_export_info
= {
346 .sType
= VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR
,
347 .pNext
= &memory_wsi_info
,
348 .handleTypes
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
,
350 const VkMemoryDedicatedAllocateInfoKHR memory_dedicated_info
= {
351 .sType
= VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR
,
352 .pNext
= &memory_export_info
,
353 .image
= image
->image
,
354 .buffer
= VK_NULL_HANDLE
,
356 const VkMemoryAllocateInfo memory_info
= {
357 .sType
= VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO
,
358 .pNext
= &memory_dedicated_info
,
359 .allocationSize
= reqs
.size
,
360 .memoryTypeIndex
= select_memory_type(wsi
, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
,
361 reqs
.memoryTypeBits
),
363 result
= wsi
->AllocateMemory(chain
->device
, &memory_info
,
364 &chain
->alloc
, &image
->memory
);
365 if (result
!= VK_SUCCESS
)
368 result
= wsi
->BindImageMemory(chain
->device
, image
->image
,
370 if (result
!= VK_SUCCESS
)
373 const VkMemoryGetFdInfoKHR memory_get_fd_info
= {
374 .sType
= VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR
,
376 .memory
= image
->memory
,
377 .handleType
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
,
380 result
= wsi
->GetMemoryFdKHR(chain
->device
, &memory_get_fd_info
, &fd
);
381 if (result
!= VK_SUCCESS
)
384 if (num_modifier_lists
> 0) {
385 image
->drm_modifier
= wsi
->image_get_modifier(image
->image
);
386 assert(image
->drm_modifier
!= DRM_FORMAT_MOD_INVALID
);
388 for (uint32_t j
= 0; j
< modifier_prop_count
; j
++) {
389 if (modifier_props
[j
].modifier
== image
->drm_modifier
) {
390 image
->num_planes
= modifier_props
[j
].modifier_plane_count
;
395 for (uint32_t p
= 0; p
< image
->num_planes
; p
++) {
396 const VkImageSubresource image_subresource
= {
397 .aspectMask
= VK_IMAGE_ASPECT_PLANE_0_BIT_KHR
<< p
,
401 VkSubresourceLayout image_layout
;
402 wsi
->GetImageSubresourceLayout(chain
->device
, image
->image
,
403 &image_subresource
, &image_layout
);
404 image
->sizes
[p
] = image_layout
.size
;
405 image
->row_pitches
[p
] = image_layout
.rowPitch
;
406 image
->offsets
[p
] = image_layout
.offset
;
410 image
->fds
[p
] = dup(fd
);
411 if (image
->fds
[p
] == -1) {
412 for (uint32_t i
= 0; i
< p
; i
++)
413 close(image
->fds
[p
]);
420 const VkImageSubresource image_subresource
= {
421 .aspectMask
= VK_IMAGE_ASPECT_COLOR_BIT
,
425 VkSubresourceLayout image_layout
;
426 wsi
->GetImageSubresourceLayout(chain
->device
, image
->image
,
427 &image_subresource
, &image_layout
);
429 image
->drm_modifier
= DRM_FORMAT_MOD_INVALID
;
430 image
->num_planes
= 1;
431 image
->sizes
[0] = reqs
.size
;
432 image
->row_pitches
[0] = image_layout
.rowPitch
;
433 image
->offsets
[0] = 0;
437 vk_free(&chain
->alloc
, modifier_props
);
438 vk_free(&chain
->alloc
, image_modifiers
);
443 vk_free(&chain
->alloc
, modifier_props
);
444 vk_free(&chain
->alloc
, image_modifiers
);
445 wsi_destroy_image(chain
, image
);
450 #define WSI_PRIME_LINEAR_STRIDE_ALIGN 256
453 wsi_create_prime_image(const struct wsi_swapchain
*chain
,
454 const VkSwapchainCreateInfoKHR
*pCreateInfo
,
456 struct wsi_image
*image
)
458 const struct wsi_device
*wsi
= chain
->wsi
;
461 memset(image
, 0, sizeof(*image
));
463 const uint32_t cpp
= vk_format_size(pCreateInfo
->imageFormat
);
464 const uint32_t linear_stride
= align_u32(pCreateInfo
->imageExtent
.width
* cpp
,
465 WSI_PRIME_LINEAR_STRIDE_ALIGN
);
467 uint32_t linear_size
= linear_stride
* pCreateInfo
->imageExtent
.height
;
468 linear_size
= align_u32(linear_size
, 4096);
470 const VkExternalMemoryBufferCreateInfoKHR prime_buffer_external_info
= {
471 .sType
= VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR
,
473 .handleTypes
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
,
475 const VkBufferCreateInfo prime_buffer_info
= {
476 .sType
= VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO
,
477 .pNext
= &prime_buffer_external_info
,
479 .usage
= VK_BUFFER_USAGE_TRANSFER_DST_BIT
,
480 .sharingMode
= VK_SHARING_MODE_EXCLUSIVE
,
482 result
= wsi
->CreateBuffer(chain
->device
, &prime_buffer_info
,
483 &chain
->alloc
, &image
->prime
.buffer
);
484 if (result
!= VK_SUCCESS
)
487 VkMemoryRequirements reqs
;
488 wsi
->GetBufferMemoryRequirements(chain
->device
, image
->prime
.buffer
, &reqs
);
489 assert(reqs
.size
<= linear_size
);
491 const struct wsi_memory_allocate_info memory_wsi_info
= {
492 .sType
= VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA
,
494 .implicit_sync
= true,
496 const VkExportMemoryAllocateInfoKHR prime_memory_export_info
= {
497 .sType
= VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR
,
498 .pNext
= &memory_wsi_info
,
499 .handleTypes
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
,
501 const VkMemoryDedicatedAllocateInfoKHR prime_memory_dedicated_info
= {
502 .sType
= VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR
,
503 .pNext
= &prime_memory_export_info
,
504 .image
= VK_NULL_HANDLE
,
505 .buffer
= image
->prime
.buffer
,
507 const VkMemoryAllocateInfo prime_memory_info
= {
508 .sType
= VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO
,
509 .pNext
= &prime_memory_dedicated_info
,
510 .allocationSize
= linear_size
,
511 .memoryTypeIndex
= select_memory_type(wsi
, 0, reqs
.memoryTypeBits
),
513 result
= wsi
->AllocateMemory(chain
->device
, &prime_memory_info
,
514 &chain
->alloc
, &image
->prime
.memory
);
515 if (result
!= VK_SUCCESS
)
518 result
= wsi
->BindBufferMemory(chain
->device
, image
->prime
.buffer
,
519 image
->prime
.memory
, 0);
520 if (result
!= VK_SUCCESS
)
523 const VkImageCreateInfo image_info
= {
524 .sType
= VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
,
527 .imageType
= VK_IMAGE_TYPE_2D
,
528 .format
= pCreateInfo
->imageFormat
,
530 .width
= pCreateInfo
->imageExtent
.width
,
531 .height
= pCreateInfo
->imageExtent
.height
,
536 .samples
= VK_SAMPLE_COUNT_1_BIT
,
537 .tiling
= VK_IMAGE_TILING_OPTIMAL
,
538 .usage
= pCreateInfo
->imageUsage
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT
,
539 .sharingMode
= pCreateInfo
->imageSharingMode
,
540 .queueFamilyIndexCount
= pCreateInfo
->queueFamilyIndexCount
,
541 .pQueueFamilyIndices
= pCreateInfo
->pQueueFamilyIndices
,
542 .initialLayout
= VK_IMAGE_LAYOUT_UNDEFINED
,
544 result
= wsi
->CreateImage(chain
->device
, &image_info
,
545 &chain
->alloc
, &image
->image
);
546 if (result
!= VK_SUCCESS
)
549 wsi
->GetImageMemoryRequirements(chain
->device
, image
->image
, &reqs
);
551 const VkMemoryDedicatedAllocateInfoKHR memory_dedicated_info
= {
552 .sType
= VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR
,
554 .image
= image
->image
,
555 .buffer
= VK_NULL_HANDLE
,
557 const VkMemoryAllocateInfo memory_info
= {
558 .sType
= VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO
,
559 .pNext
= &memory_dedicated_info
,
560 .allocationSize
= reqs
.size
,
561 .memoryTypeIndex
= select_memory_type(wsi
, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
,
562 reqs
.memoryTypeBits
),
564 result
= wsi
->AllocateMemory(chain
->device
, &memory_info
,
565 &chain
->alloc
, &image
->memory
);
566 if (result
!= VK_SUCCESS
)
569 result
= wsi
->BindImageMemory(chain
->device
, image
->image
,
571 if (result
!= VK_SUCCESS
)
574 image
->prime
.blit_cmd_buffers
=
575 vk_zalloc(&chain
->alloc
,
576 sizeof(VkCommandBuffer
) * wsi
->queue_family_count
, 8,
577 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
578 if (!image
->prime
.blit_cmd_buffers
) {
579 result
= VK_ERROR_OUT_OF_HOST_MEMORY
;
583 for (uint32_t i
= 0; i
< wsi
->queue_family_count
; i
++) {
584 const VkCommandBufferAllocateInfo cmd_buffer_info
= {
585 .sType
= VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO
,
587 .commandPool
= chain
->cmd_pools
[i
],
588 .level
= VK_COMMAND_BUFFER_LEVEL_PRIMARY
,
589 .commandBufferCount
= 1,
591 result
= wsi
->AllocateCommandBuffers(chain
->device
, &cmd_buffer_info
,
592 &image
->prime
.blit_cmd_buffers
[i
]);
593 if (result
!= VK_SUCCESS
)
596 const VkCommandBufferBeginInfo begin_info
= {
597 .sType
= VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO
,
599 wsi
->BeginCommandBuffer(image
->prime
.blit_cmd_buffers
[i
], &begin_info
);
601 struct VkBufferImageCopy buffer_image_copy
= {
603 .bufferRowLength
= linear_stride
/ cpp
,
604 .bufferImageHeight
= 0,
605 .imageSubresource
= {
606 .aspectMask
= VK_IMAGE_ASPECT_COLOR_BIT
,
611 .imageOffset
= { .x
= 0, .y
= 0, .z
= 0 },
613 .width
= pCreateInfo
->imageExtent
.width
,
614 .height
= pCreateInfo
->imageExtent
.height
,
618 wsi
->CmdCopyImageToBuffer(image
->prime
.blit_cmd_buffers
[i
],
620 VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
,
622 1, &buffer_image_copy
);
624 result
= wsi
->EndCommandBuffer(image
->prime
.blit_cmd_buffers
[i
]);
625 if (result
!= VK_SUCCESS
)
629 const VkMemoryGetFdInfoKHR linear_memory_get_fd_info
= {
630 .sType
= VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR
,
632 .memory
= image
->prime
.memory
,
633 .handleType
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
,
636 result
= wsi
->GetMemoryFdKHR(chain
->device
, &linear_memory_get_fd_info
, &fd
);
637 if (result
!= VK_SUCCESS
)
640 image
->drm_modifier
= use_modifier
? DRM_FORMAT_MOD_LINEAR
: DRM_FORMAT_MOD_INVALID
;
641 image
->num_planes
= 1;
642 image
->sizes
[0] = linear_size
;
643 image
->row_pitches
[0] = linear_stride
;
644 image
->offsets
[0] = 0;
650 wsi_destroy_image(chain
, image
);
656 wsi_destroy_image(const struct wsi_swapchain
*chain
,
657 struct wsi_image
*image
)
659 const struct wsi_device
*wsi
= chain
->wsi
;
661 if (image
->prime
.blit_cmd_buffers
) {
662 for (uint32_t i
= 0; i
< wsi
->queue_family_count
; i
++) {
663 wsi
->FreeCommandBuffers(chain
->device
, chain
->cmd_pools
[i
],
664 1, &image
->prime
.blit_cmd_buffers
[i
]);
666 vk_free(&chain
->alloc
, image
->prime
.blit_cmd_buffers
);
669 wsi
->FreeMemory(chain
->device
, image
->memory
, &chain
->alloc
);
670 wsi
->DestroyImage(chain
->device
, image
->image
, &chain
->alloc
);
671 wsi
->FreeMemory(chain
->device
, image
->prime
.memory
, &chain
->alloc
);
672 wsi
->DestroyBuffer(chain
->device
, image
->prime
.buffer
, &chain
->alloc
);
676 wsi_common_get_surface_support(struct wsi_device
*wsi_device
,
678 uint32_t queueFamilyIndex
,
679 VkSurfaceKHR _surface
,
680 const VkAllocationCallbacks
*alloc
,
681 VkBool32
* pSupported
)
683 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, _surface
);
684 struct wsi_interface
*iface
= wsi_device
->wsi
[surface
->platform
];
686 return iface
->get_support(surface
, wsi_device
, alloc
,
687 queueFamilyIndex
, local_fd
, pSupported
);
691 wsi_common_get_surface_capabilities(struct wsi_device
*wsi_device
,
692 VkSurfaceKHR _surface
,
693 VkSurfaceCapabilitiesKHR
*pSurfaceCapabilities
)
695 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, _surface
);
696 struct wsi_interface
*iface
= wsi_device
->wsi
[surface
->platform
];
698 return iface
->get_capabilities(surface
, pSurfaceCapabilities
);
702 wsi_common_get_surface_capabilities2(struct wsi_device
*wsi_device
,
703 const VkPhysicalDeviceSurfaceInfo2KHR
*pSurfaceInfo
,
704 VkSurfaceCapabilities2KHR
*pSurfaceCapabilities
)
706 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, pSurfaceInfo
->surface
);
707 struct wsi_interface
*iface
= wsi_device
->wsi
[surface
->platform
];
709 return iface
->get_capabilities2(surface
, pSurfaceInfo
->pNext
,
710 pSurfaceCapabilities
);
714 wsi_common_get_surface_formats(struct wsi_device
*wsi_device
,
715 VkSurfaceKHR _surface
,
716 uint32_t *pSurfaceFormatCount
,
717 VkSurfaceFormatKHR
*pSurfaceFormats
)
719 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, _surface
);
720 struct wsi_interface
*iface
= wsi_device
->wsi
[surface
->platform
];
722 return iface
->get_formats(surface
, wsi_device
,
723 pSurfaceFormatCount
, pSurfaceFormats
);
727 wsi_common_get_surface_formats2(struct wsi_device
*wsi_device
,
728 const VkPhysicalDeviceSurfaceInfo2KHR
*pSurfaceInfo
,
729 uint32_t *pSurfaceFormatCount
,
730 VkSurfaceFormat2KHR
*pSurfaceFormats
)
732 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, pSurfaceInfo
->surface
);
733 struct wsi_interface
*iface
= wsi_device
->wsi
[surface
->platform
];
735 return iface
->get_formats2(surface
, wsi_device
, pSurfaceInfo
->pNext
,
736 pSurfaceFormatCount
, pSurfaceFormats
);
740 wsi_common_get_surface_present_modes(struct wsi_device
*wsi_device
,
741 VkSurfaceKHR _surface
,
742 uint32_t *pPresentModeCount
,
743 VkPresentModeKHR
*pPresentModes
)
745 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, _surface
);
746 struct wsi_interface
*iface
= wsi_device
->wsi
[surface
->platform
];
748 return iface
->get_present_modes(surface
, pPresentModeCount
,
753 wsi_common_create_swapchain(struct wsi_device
*wsi
,
756 const VkSwapchainCreateInfoKHR
*pCreateInfo
,
757 const VkAllocationCallbacks
*pAllocator
,
758 VkSwapchainKHR
*pSwapchain
)
760 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, pCreateInfo
->surface
);
761 struct wsi_interface
*iface
= wsi
->wsi
[surface
->platform
];
762 struct wsi_swapchain
*swapchain
;
764 VkResult result
= iface
->create_swapchain(surface
, device
, wsi
, fd
,
765 pCreateInfo
, pAllocator
,
767 if (result
!= VK_SUCCESS
)
770 *pSwapchain
= wsi_swapchain_to_handle(swapchain
);
776 wsi_common_destroy_swapchain(VkDevice device
,
777 VkSwapchainKHR _swapchain
,
778 const VkAllocationCallbacks
*pAllocator
)
780 WSI_FROM_HANDLE(wsi_swapchain
, swapchain
, _swapchain
);
784 swapchain
->destroy(swapchain
, pAllocator
);
788 wsi_common_get_images(VkSwapchainKHR _swapchain
,
789 uint32_t *pSwapchainImageCount
,
790 VkImage
*pSwapchainImages
)
792 WSI_FROM_HANDLE(wsi_swapchain
, swapchain
, _swapchain
);
793 VK_OUTARRAY_MAKE(images
, pSwapchainImages
, pSwapchainImageCount
);
795 for (uint32_t i
= 0; i
< swapchain
->image_count
; i
++) {
796 vk_outarray_append(&images
, image
) {
797 *image
= swapchain
->get_wsi_image(swapchain
, i
)->image
;
801 return vk_outarray_status(&images
);
805 wsi_common_acquire_next_image(const struct wsi_device
*wsi
,
807 VkSwapchainKHR _swapchain
,
809 VkSemaphore semaphore
,
810 uint32_t *pImageIndex
)
812 WSI_FROM_HANDLE(wsi_swapchain
, swapchain
, _swapchain
);
814 return swapchain
->acquire_next_image(swapchain
, timeout
,
815 semaphore
, pImageIndex
);
819 wsi_common_queue_present(const struct wsi_device
*wsi
,
822 int queue_family_index
,
823 const VkPresentInfoKHR
*pPresentInfo
)
825 VkResult final_result
= VK_SUCCESS
;
827 const VkPresentRegionsKHR
*regions
=
828 vk_find_struct_const(pPresentInfo
->pNext
, PRESENT_REGIONS_KHR
);
830 for (uint32_t i
= 0; i
< pPresentInfo
->swapchainCount
; i
++) {
831 WSI_FROM_HANDLE(wsi_swapchain
, swapchain
, pPresentInfo
->pSwapchains
[i
]);
834 if (swapchain
->fences
[0] == VK_NULL_HANDLE
) {
835 const VkFenceCreateInfo fence_info
= {
836 .sType
= VK_STRUCTURE_TYPE_FENCE_CREATE_INFO
,
840 result
= wsi
->CreateFence(device
, &fence_info
,
842 &swapchain
->fences
[0]);
843 if (result
!= VK_SUCCESS
)
846 wsi
->ResetFences(device
, 1, &swapchain
->fences
[0]);
849 VkSubmitInfo submit_info
= {
850 .sType
= VK_STRUCTURE_TYPE_SUBMIT_INFO
,
854 VkPipelineStageFlags
*stage_flags
= NULL
;
856 /* We only need/want to wait on semaphores once. After that, we're
857 * guaranteed ordering since it all happens on the same queue.
859 submit_info
.waitSemaphoreCount
= pPresentInfo
->waitSemaphoreCount
,
860 submit_info
.pWaitSemaphores
= pPresentInfo
->pWaitSemaphores
,
862 /* Set up the pWaitDstStageMasks */
863 stage_flags
= vk_alloc(&swapchain
->alloc
,
864 sizeof(VkPipelineStageFlags
) *
865 pPresentInfo
->waitSemaphoreCount
,
867 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND
);
869 result
= VK_ERROR_OUT_OF_HOST_MEMORY
;
872 for (uint32_t s
= 0; s
< pPresentInfo
->waitSemaphoreCount
; s
++)
873 stage_flags
[s
] = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT
;
875 submit_info
.pWaitDstStageMask
= stage_flags
;
878 if (swapchain
->use_prime_blit
) {
879 /* If we are using prime blits, we need to perform the blit now. The
880 * command buffer is attached to the image.
882 struct wsi_image
*image
=
883 swapchain
->get_wsi_image(swapchain
, pPresentInfo
->pImageIndices
[i
]);
884 submit_info
.commandBufferCount
= 1;
885 submit_info
.pCommandBuffers
=
886 &image
->prime
.blit_cmd_buffers
[queue_family_index
];
889 result
= wsi
->QueueSubmit(queue
, 1, &submit_info
, swapchain
->fences
[0]);
890 vk_free(&swapchain
->alloc
, stage_flags
);
891 if (result
!= VK_SUCCESS
)
894 const VkPresentRegionKHR
*region
= NULL
;
895 if (regions
&& regions
->pRegions
)
896 region
= ®ions
->pRegions
[i
];
898 result
= swapchain
->queue_present(swapchain
,
899 pPresentInfo
->pImageIndices
[i
],
901 if (result
!= VK_SUCCESS
)
904 VkFence last
= swapchain
->fences
[2];
905 swapchain
->fences
[2] = swapchain
->fences
[1];
906 swapchain
->fences
[1] = swapchain
->fences
[0];
907 swapchain
->fences
[0] = last
;
909 if (last
!= VK_NULL_HANDLE
) {
910 wsi
->WaitForFences(device
, 1, &last
, true, 1);
914 if (pPresentInfo
->pResults
!= NULL
)
915 pPresentInfo
->pResults
[i
] = result
;
917 /* Let the final result be our first unsuccessful result */
918 if (final_result
== VK_SUCCESS
)
919 final_result
= result
;