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-uapi/drm_fourcc.h"
26 #include "util/macros.h"
33 wsi_device_init(struct wsi_device
*wsi
,
34 VkPhysicalDevice pdevice
,
35 WSI_FN_GetPhysicalDeviceProcAddr proc_addr
,
36 const VkAllocationCallbacks
*alloc
,
41 memset(wsi
, 0, sizeof(*wsi
));
43 wsi
->instance_alloc
= *alloc
;
44 wsi
->pdevice
= pdevice
;
46 #define WSI_GET_CB(func) \
47 PFN_vk##func func = (PFN_vk##func)proc_addr(pdevice, "vk" #func)
48 WSI_GET_CB(GetPhysicalDeviceProperties2
);
49 WSI_GET_CB(GetPhysicalDeviceMemoryProperties
);
50 WSI_GET_CB(GetPhysicalDeviceQueueFamilyProperties
);
53 wsi
->pci_bus_info
.sType
=
54 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT
;
55 VkPhysicalDeviceProperties2 pdp2
= {
56 .sType
= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2
,
57 .pNext
= &wsi
->pci_bus_info
,
59 GetPhysicalDeviceProperties2(pdevice
, &pdp2
);
61 wsi
->maxImageDimension2D
= pdp2
.properties
.limits
.maxImageDimension2D
;
63 GetPhysicalDeviceMemoryProperties(pdevice
, &wsi
->memory_props
);
64 GetPhysicalDeviceQueueFamilyProperties(pdevice
, &wsi
->queue_family_count
, NULL
);
66 #define WSI_GET_CB(func) \
67 wsi->func = (PFN_vk##func)proc_addr(pdevice, "vk" #func)
68 WSI_GET_CB(AllocateMemory
);
69 WSI_GET_CB(AllocateCommandBuffers
);
70 WSI_GET_CB(BindBufferMemory
);
71 WSI_GET_CB(BindImageMemory
);
72 WSI_GET_CB(BeginCommandBuffer
);
73 WSI_GET_CB(CmdCopyImageToBuffer
);
74 WSI_GET_CB(CreateBuffer
);
75 WSI_GET_CB(CreateCommandPool
);
76 WSI_GET_CB(CreateFence
);
77 WSI_GET_CB(CreateImage
);
78 WSI_GET_CB(DestroyBuffer
);
79 WSI_GET_CB(DestroyCommandPool
);
80 WSI_GET_CB(DestroyFence
);
81 WSI_GET_CB(DestroyImage
);
82 WSI_GET_CB(EndCommandBuffer
);
83 WSI_GET_CB(FreeMemory
);
84 WSI_GET_CB(FreeCommandBuffers
);
85 WSI_GET_CB(GetBufferMemoryRequirements
);
86 WSI_GET_CB(GetImageMemoryRequirements
);
87 WSI_GET_CB(GetImageSubresourceLayout
);
88 WSI_GET_CB(GetMemoryFdKHR
);
89 WSI_GET_CB(GetPhysicalDeviceFormatProperties
);
90 WSI_GET_CB(GetPhysicalDeviceFormatProperties2KHR
);
91 WSI_GET_CB(ResetFences
);
92 WSI_GET_CB(QueueSubmit
);
93 WSI_GET_CB(WaitForFences
);
96 #ifdef VK_USE_PLATFORM_XCB_KHR
97 result
= wsi_x11_init_wsi(wsi
, alloc
);
98 if (result
!= VK_SUCCESS
)
102 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
103 result
= wsi_wl_init_wsi(wsi
, alloc
, pdevice
);
104 if (result
!= VK_SUCCESS
)
108 #ifdef VK_USE_PLATFORM_DISPLAY_KHR
109 result
= wsi_display_init_wsi(wsi
, alloc
, display_fd
);
110 if (result
!= VK_SUCCESS
)
117 wsi_device_finish(wsi
, alloc
);
122 wsi_device_finish(struct wsi_device
*wsi
,
123 const VkAllocationCallbacks
*alloc
)
125 #ifdef VK_USE_PLATFORM_DISPLAY_KHR
126 wsi_display_finish_wsi(wsi
, alloc
);
128 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
129 wsi_wl_finish_wsi(wsi
, alloc
);
131 #ifdef VK_USE_PLATFORM_XCB_KHR
132 wsi_x11_finish_wsi(wsi
, alloc
);
137 wsi_device_matches_drm_fd(const struct wsi_device
*wsi
, int drm_fd
)
139 drmDevicePtr fd_device
;
140 int ret
= drmGetDevice2(drm_fd
, 0, &fd_device
);
145 switch (fd_device
->bustype
) {
147 match
= wsi
->pci_bus_info
.pciDomain
== fd_device
->businfo
.pci
->domain
&&
148 wsi
->pci_bus_info
.pciBus
== fd_device
->businfo
.pci
->bus
&&
149 wsi
->pci_bus_info
.pciDevice
== fd_device
->businfo
.pci
->dev
&&
150 wsi
->pci_bus_info
.pciFunction
== fd_device
->businfo
.pci
->func
;
157 drmFreeDevice(&fd_device
);
163 wsi_swapchain_init(const struct wsi_device
*wsi
,
164 struct wsi_swapchain
*chain
,
166 const VkSwapchainCreateInfoKHR
*pCreateInfo
,
167 const VkAllocationCallbacks
*pAllocator
)
171 memset(chain
, 0, sizeof(*chain
));
174 chain
->device
= device
;
175 chain
->alloc
= *pAllocator
;
176 chain
->use_prime_blit
= false;
179 vk_zalloc(pAllocator
, sizeof(VkCommandPool
) * wsi
->queue_family_count
, 8,
180 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
181 if (!chain
->cmd_pools
)
182 return VK_ERROR_OUT_OF_HOST_MEMORY
;
184 for (uint32_t i
= 0; i
< wsi
->queue_family_count
; i
++) {
185 const VkCommandPoolCreateInfo cmd_pool_info
= {
186 .sType
= VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO
,
189 .queueFamilyIndex
= i
,
191 result
= wsi
->CreateCommandPool(device
, &cmd_pool_info
, &chain
->alloc
,
192 &chain
->cmd_pools
[i
]);
193 if (result
!= VK_SUCCESS
)
200 wsi_swapchain_finish(chain
);
205 wsi_swapchain_finish(struct wsi_swapchain
*chain
)
207 for (unsigned i
= 0; i
< ARRAY_SIZE(chain
->fences
); i
++)
208 chain
->wsi
->DestroyFence(chain
->device
, chain
->fences
[i
], &chain
->alloc
);
210 for (uint32_t i
= 0; i
< chain
->wsi
->queue_family_count
; i
++) {
211 chain
->wsi
->DestroyCommandPool(chain
->device
, chain
->cmd_pools
[i
],
214 vk_free(&chain
->alloc
, chain
->cmd_pools
);
218 select_memory_type(const struct wsi_device
*wsi
,
219 VkMemoryPropertyFlags props
,
222 for (uint32_t i
= 0; i
< wsi
->memory_props
.memoryTypeCount
; i
++) {
223 const VkMemoryType type
= wsi
->memory_props
.memoryTypes
[i
];
224 if ((type_bits
& (1 << i
)) && (type
.propertyFlags
& props
) == props
)
228 unreachable("No memory type found");
232 vk_format_size(VkFormat format
)
235 case VK_FORMAT_B8G8R8A8_UNORM
:
236 case VK_FORMAT_B8G8R8A8_SRGB
:
239 unreachable("Unknown WSI Format");
243 static inline uint32_t
244 align_u32(uint32_t v
, uint32_t a
)
246 assert(a
!= 0 && a
== (a
& -a
));
247 return (v
+ a
- 1) & ~(a
- 1);
251 wsi_create_native_image(const struct wsi_swapchain
*chain
,
252 const VkSwapchainCreateInfoKHR
*pCreateInfo
,
253 uint32_t num_modifier_lists
,
254 const uint32_t *num_modifiers
,
255 const uint64_t *const *modifiers
,
256 struct wsi_image
*image
)
258 const struct wsi_device
*wsi
= chain
->wsi
;
261 memset(image
, 0, sizeof(*image
));
262 for (int i
= 0; i
< ARRAY_SIZE(image
->fds
); i
++)
265 struct wsi_image_create_info image_wsi_info
= {
266 .sType
= VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA
,
270 uint32_t image_modifier_count
= 0, modifier_prop_count
= 0;
271 struct wsi_format_modifier_properties
*modifier_props
= NULL
;
272 uint64_t *image_modifiers
= NULL
;
273 if (num_modifier_lists
== 0) {
274 /* If we don't have modifiers, fall back to the legacy "scanout" flag */
275 image_wsi_info
.scanout
= true;
277 /* The winsys can't request modifiers if we don't support them. */
278 assert(wsi
->supports_modifiers
);
279 struct wsi_format_modifier_properties_list modifier_props_list
= {
280 .sType
= VK_STRUCTURE_TYPE_WSI_FORMAT_MODIFIER_PROPERTIES_LIST_MESA
,
283 VkFormatProperties2 format_props
= {
284 .sType
= VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2
,
285 .pNext
= &modifier_props_list
,
287 wsi
->GetPhysicalDeviceFormatProperties2KHR(wsi
->pdevice
,
288 pCreateInfo
->imageFormat
,
290 assert(modifier_props_list
.modifier_count
> 0);
291 modifier_props
= vk_alloc(&chain
->alloc
,
292 sizeof(*modifier_props
) *
293 modifier_props_list
.modifier_count
,
295 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND
);
296 if (!modifier_props
) {
297 result
= VK_ERROR_OUT_OF_HOST_MEMORY
;
301 modifier_props_list
.modifier_properties
= modifier_props
;
302 wsi
->GetPhysicalDeviceFormatProperties2KHR(wsi
->pdevice
,
303 pCreateInfo
->imageFormat
,
305 modifier_prop_count
= modifier_props_list
.modifier_count
;
307 uint32_t max_modifier_count
= 0;
308 for (uint32_t l
= 0; l
< num_modifier_lists
; l
++)
309 max_modifier_count
= MAX2(max_modifier_count
, num_modifiers
[l
]);
311 image_modifiers
= vk_alloc(&chain
->alloc
,
312 sizeof(*image_modifiers
) *
315 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND
);
316 if (!image_modifiers
) {
317 result
= VK_ERROR_OUT_OF_HOST_MEMORY
;
321 image_modifier_count
= 0;
322 for (uint32_t l
= 0; l
< num_modifier_lists
; l
++) {
323 /* Walk the modifier lists and construct a list of supported
326 for (uint32_t i
= 0; i
< num_modifiers
[l
]; i
++) {
327 for (uint32_t j
= 0; j
< modifier_prop_count
; j
++) {
328 if (modifier_props
[j
].modifier
== modifiers
[l
][i
])
329 image_modifiers
[image_modifier_count
++] = modifiers
[l
][i
];
333 /* We only want to take the modifiers from the first list */
334 if (image_modifier_count
> 0)
338 if (image_modifier_count
> 0) {
339 image_wsi_info
.modifier_count
= image_modifier_count
;
340 image_wsi_info
.modifiers
= image_modifiers
;
342 /* TODO: Add a proper error here */
343 assert(!"Failed to find a supported modifier! This should never "
344 "happen because LINEAR should always be available");
345 result
= VK_ERROR_OUT_OF_HOST_MEMORY
;
350 const VkImageCreateInfo image_info
= {
351 .sType
= VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
,
352 .pNext
= &image_wsi_info
,
354 .imageType
= VK_IMAGE_TYPE_2D
,
355 .format
= pCreateInfo
->imageFormat
,
357 .width
= pCreateInfo
->imageExtent
.width
,
358 .height
= pCreateInfo
->imageExtent
.height
,
363 .samples
= VK_SAMPLE_COUNT_1_BIT
,
364 .tiling
= VK_IMAGE_TILING_OPTIMAL
,
365 .usage
= pCreateInfo
->imageUsage
,
366 .sharingMode
= pCreateInfo
->imageSharingMode
,
367 .queueFamilyIndexCount
= pCreateInfo
->queueFamilyIndexCount
,
368 .pQueueFamilyIndices
= pCreateInfo
->pQueueFamilyIndices
,
369 .initialLayout
= VK_IMAGE_LAYOUT_UNDEFINED
,
371 result
= wsi
->CreateImage(chain
->device
, &image_info
,
372 &chain
->alloc
, &image
->image
);
373 if (result
!= VK_SUCCESS
)
376 VkMemoryRequirements reqs
;
377 wsi
->GetImageMemoryRequirements(chain
->device
, image
->image
, &reqs
);
379 const struct wsi_memory_allocate_info memory_wsi_info
= {
380 .sType
= VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA
,
382 .implicit_sync
= true,
384 const VkExportMemoryAllocateInfo memory_export_info
= {
385 .sType
= VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO
,
386 .pNext
= &memory_wsi_info
,
387 .handleTypes
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
,
389 const VkMemoryDedicatedAllocateInfo memory_dedicated_info
= {
390 .sType
= VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO
,
391 .pNext
= &memory_export_info
,
392 .image
= image
->image
,
393 .buffer
= VK_NULL_HANDLE
,
395 const VkMemoryAllocateInfo memory_info
= {
396 .sType
= VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO
,
397 .pNext
= &memory_dedicated_info
,
398 .allocationSize
= reqs
.size
,
399 .memoryTypeIndex
= select_memory_type(wsi
, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
,
400 reqs
.memoryTypeBits
),
402 result
= wsi
->AllocateMemory(chain
->device
, &memory_info
,
403 &chain
->alloc
, &image
->memory
);
404 if (result
!= VK_SUCCESS
)
407 result
= wsi
->BindImageMemory(chain
->device
, image
->image
,
409 if (result
!= VK_SUCCESS
)
412 const VkMemoryGetFdInfoKHR memory_get_fd_info
= {
413 .sType
= VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR
,
415 .memory
= image
->memory
,
416 .handleType
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
,
419 result
= wsi
->GetMemoryFdKHR(chain
->device
, &memory_get_fd_info
, &fd
);
420 if (result
!= VK_SUCCESS
)
423 if (num_modifier_lists
> 0) {
424 image
->drm_modifier
= wsi
->image_get_modifier(image
->image
);
425 assert(image
->drm_modifier
!= DRM_FORMAT_MOD_INVALID
);
427 for (uint32_t j
= 0; j
< modifier_prop_count
; j
++) {
428 if (modifier_props
[j
].modifier
== image
->drm_modifier
) {
429 image
->num_planes
= modifier_props
[j
].modifier_plane_count
;
434 for (uint32_t p
= 0; p
< image
->num_planes
; p
++) {
435 const VkImageSubresource image_subresource
= {
436 .aspectMask
= VK_IMAGE_ASPECT_PLANE_0_BIT
<< p
,
440 VkSubresourceLayout image_layout
;
441 wsi
->GetImageSubresourceLayout(chain
->device
, image
->image
,
442 &image_subresource
, &image_layout
);
443 image
->sizes
[p
] = image_layout
.size
;
444 image
->row_pitches
[p
] = image_layout
.rowPitch
;
445 image
->offsets
[p
] = image_layout
.offset
;
449 image
->fds
[p
] = dup(fd
);
450 if (image
->fds
[p
] == -1) {
451 for (uint32_t i
= 0; i
< p
; i
++)
452 close(image
->fds
[p
]);
459 const VkImageSubresource image_subresource
= {
460 .aspectMask
= VK_IMAGE_ASPECT_COLOR_BIT
,
464 VkSubresourceLayout image_layout
;
465 wsi
->GetImageSubresourceLayout(chain
->device
, image
->image
,
466 &image_subresource
, &image_layout
);
468 image
->drm_modifier
= DRM_FORMAT_MOD_INVALID
;
469 image
->num_planes
= 1;
470 image
->sizes
[0] = reqs
.size
;
471 image
->row_pitches
[0] = image_layout
.rowPitch
;
472 image
->offsets
[0] = 0;
476 vk_free(&chain
->alloc
, modifier_props
);
477 vk_free(&chain
->alloc
, image_modifiers
);
482 vk_free(&chain
->alloc
, modifier_props
);
483 vk_free(&chain
->alloc
, image_modifiers
);
484 wsi_destroy_image(chain
, image
);
489 #define WSI_PRIME_LINEAR_STRIDE_ALIGN 256
492 wsi_create_prime_image(const struct wsi_swapchain
*chain
,
493 const VkSwapchainCreateInfoKHR
*pCreateInfo
,
495 struct wsi_image
*image
)
497 const struct wsi_device
*wsi
= chain
->wsi
;
500 memset(image
, 0, sizeof(*image
));
502 const uint32_t cpp
= vk_format_size(pCreateInfo
->imageFormat
);
503 const uint32_t linear_stride
= align_u32(pCreateInfo
->imageExtent
.width
* cpp
,
504 WSI_PRIME_LINEAR_STRIDE_ALIGN
);
506 uint32_t linear_size
= linear_stride
* pCreateInfo
->imageExtent
.height
;
507 linear_size
= align_u32(linear_size
, 4096);
509 const VkExternalMemoryBufferCreateInfo prime_buffer_external_info
= {
510 .sType
= VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO
,
512 .handleTypes
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
,
514 const VkBufferCreateInfo prime_buffer_info
= {
515 .sType
= VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO
,
516 .pNext
= &prime_buffer_external_info
,
518 .usage
= VK_BUFFER_USAGE_TRANSFER_DST_BIT
,
519 .sharingMode
= VK_SHARING_MODE_EXCLUSIVE
,
521 result
= wsi
->CreateBuffer(chain
->device
, &prime_buffer_info
,
522 &chain
->alloc
, &image
->prime
.buffer
);
523 if (result
!= VK_SUCCESS
)
526 VkMemoryRequirements reqs
;
527 wsi
->GetBufferMemoryRequirements(chain
->device
, image
->prime
.buffer
, &reqs
);
528 assert(reqs
.size
<= linear_size
);
530 const struct wsi_memory_allocate_info memory_wsi_info
= {
531 .sType
= VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA
,
533 .implicit_sync
= true,
535 const VkExportMemoryAllocateInfo prime_memory_export_info
= {
536 .sType
= VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO
,
537 .pNext
= &memory_wsi_info
,
538 .handleTypes
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
,
540 const VkMemoryDedicatedAllocateInfo prime_memory_dedicated_info
= {
541 .sType
= VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO
,
542 .pNext
= &prime_memory_export_info
,
543 .image
= VK_NULL_HANDLE
,
544 .buffer
= image
->prime
.buffer
,
546 const VkMemoryAllocateInfo prime_memory_info
= {
547 .sType
= VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO
,
548 .pNext
= &prime_memory_dedicated_info
,
549 .allocationSize
= linear_size
,
550 .memoryTypeIndex
= select_memory_type(wsi
, 0, reqs
.memoryTypeBits
),
552 result
= wsi
->AllocateMemory(chain
->device
, &prime_memory_info
,
553 &chain
->alloc
, &image
->prime
.memory
);
554 if (result
!= VK_SUCCESS
)
557 result
= wsi
->BindBufferMemory(chain
->device
, image
->prime
.buffer
,
558 image
->prime
.memory
, 0);
559 if (result
!= VK_SUCCESS
)
562 const VkImageCreateInfo image_info
= {
563 .sType
= VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
,
566 .imageType
= VK_IMAGE_TYPE_2D
,
567 .format
= pCreateInfo
->imageFormat
,
569 .width
= pCreateInfo
->imageExtent
.width
,
570 .height
= pCreateInfo
->imageExtent
.height
,
575 .samples
= VK_SAMPLE_COUNT_1_BIT
,
576 .tiling
= VK_IMAGE_TILING_OPTIMAL
,
577 .usage
= pCreateInfo
->imageUsage
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT
,
578 .sharingMode
= pCreateInfo
->imageSharingMode
,
579 .queueFamilyIndexCount
= pCreateInfo
->queueFamilyIndexCount
,
580 .pQueueFamilyIndices
= pCreateInfo
->pQueueFamilyIndices
,
581 .initialLayout
= VK_IMAGE_LAYOUT_UNDEFINED
,
583 result
= wsi
->CreateImage(chain
->device
, &image_info
,
584 &chain
->alloc
, &image
->image
);
585 if (result
!= VK_SUCCESS
)
588 wsi
->GetImageMemoryRequirements(chain
->device
, image
->image
, &reqs
);
590 const VkMemoryDedicatedAllocateInfo memory_dedicated_info
= {
591 .sType
= VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO
,
593 .image
= image
->image
,
594 .buffer
= VK_NULL_HANDLE
,
596 const VkMemoryAllocateInfo memory_info
= {
597 .sType
= VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO
,
598 .pNext
= &memory_dedicated_info
,
599 .allocationSize
= reqs
.size
,
600 .memoryTypeIndex
= select_memory_type(wsi
, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
,
601 reqs
.memoryTypeBits
),
603 result
= wsi
->AllocateMemory(chain
->device
, &memory_info
,
604 &chain
->alloc
, &image
->memory
);
605 if (result
!= VK_SUCCESS
)
608 result
= wsi
->BindImageMemory(chain
->device
, image
->image
,
610 if (result
!= VK_SUCCESS
)
613 image
->prime
.blit_cmd_buffers
=
614 vk_zalloc(&chain
->alloc
,
615 sizeof(VkCommandBuffer
) * wsi
->queue_family_count
, 8,
616 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
617 if (!image
->prime
.blit_cmd_buffers
) {
618 result
= VK_ERROR_OUT_OF_HOST_MEMORY
;
622 for (uint32_t i
= 0; i
< wsi
->queue_family_count
; i
++) {
623 const VkCommandBufferAllocateInfo cmd_buffer_info
= {
624 .sType
= VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO
,
626 .commandPool
= chain
->cmd_pools
[i
],
627 .level
= VK_COMMAND_BUFFER_LEVEL_PRIMARY
,
628 .commandBufferCount
= 1,
630 result
= wsi
->AllocateCommandBuffers(chain
->device
, &cmd_buffer_info
,
631 &image
->prime
.blit_cmd_buffers
[i
]);
632 if (result
!= VK_SUCCESS
)
635 const VkCommandBufferBeginInfo begin_info
= {
636 .sType
= VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO
,
638 wsi
->BeginCommandBuffer(image
->prime
.blit_cmd_buffers
[i
], &begin_info
);
640 struct VkBufferImageCopy buffer_image_copy
= {
642 .bufferRowLength
= linear_stride
/ cpp
,
643 .bufferImageHeight
= 0,
644 .imageSubresource
= {
645 .aspectMask
= VK_IMAGE_ASPECT_COLOR_BIT
,
650 .imageOffset
= { .x
= 0, .y
= 0, .z
= 0 },
652 .width
= pCreateInfo
->imageExtent
.width
,
653 .height
= pCreateInfo
->imageExtent
.height
,
657 wsi
->CmdCopyImageToBuffer(image
->prime
.blit_cmd_buffers
[i
],
659 VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
,
661 1, &buffer_image_copy
);
663 result
= wsi
->EndCommandBuffer(image
->prime
.blit_cmd_buffers
[i
]);
664 if (result
!= VK_SUCCESS
)
668 const VkMemoryGetFdInfoKHR linear_memory_get_fd_info
= {
669 .sType
= VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR
,
671 .memory
= image
->prime
.memory
,
672 .handleType
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
,
675 result
= wsi
->GetMemoryFdKHR(chain
->device
, &linear_memory_get_fd_info
, &fd
);
676 if (result
!= VK_SUCCESS
)
679 image
->drm_modifier
= use_modifier
? DRM_FORMAT_MOD_LINEAR
: DRM_FORMAT_MOD_INVALID
;
680 image
->num_planes
= 1;
681 image
->sizes
[0] = linear_size
;
682 image
->row_pitches
[0] = linear_stride
;
683 image
->offsets
[0] = 0;
689 wsi_destroy_image(chain
, image
);
695 wsi_destroy_image(const struct wsi_swapchain
*chain
,
696 struct wsi_image
*image
)
698 const struct wsi_device
*wsi
= chain
->wsi
;
700 if (image
->prime
.blit_cmd_buffers
) {
701 for (uint32_t i
= 0; i
< wsi
->queue_family_count
; i
++) {
702 wsi
->FreeCommandBuffers(chain
->device
, chain
->cmd_pools
[i
],
703 1, &image
->prime
.blit_cmd_buffers
[i
]);
705 vk_free(&chain
->alloc
, image
->prime
.blit_cmd_buffers
);
708 wsi
->FreeMemory(chain
->device
, image
->memory
, &chain
->alloc
);
709 wsi
->DestroyImage(chain
->device
, image
->image
, &chain
->alloc
);
710 wsi
->FreeMemory(chain
->device
, image
->prime
.memory
, &chain
->alloc
);
711 wsi
->DestroyBuffer(chain
->device
, image
->prime
.buffer
, &chain
->alloc
);
715 wsi_common_get_surface_support(struct wsi_device
*wsi_device
,
716 uint32_t queueFamilyIndex
,
717 VkSurfaceKHR _surface
,
718 VkBool32
* pSupported
)
720 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, _surface
);
721 struct wsi_interface
*iface
= wsi_device
->wsi
[surface
->platform
];
723 return iface
->get_support(surface
, wsi_device
,
724 queueFamilyIndex
, pSupported
);
728 wsi_common_get_surface_capabilities(struct wsi_device
*wsi_device
,
729 VkSurfaceKHR _surface
,
730 VkSurfaceCapabilitiesKHR
*pSurfaceCapabilities
)
732 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, _surface
);
733 struct wsi_interface
*iface
= wsi_device
->wsi
[surface
->platform
];
735 VkSurfaceCapabilities2KHR caps2
= {
736 .sType
= VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR
,
739 VkResult result
= iface
->get_capabilities2(surface
, wsi_device
, NULL
, &caps2
);
741 if (result
== VK_SUCCESS
)
742 *pSurfaceCapabilities
= caps2
.surfaceCapabilities
;
748 wsi_common_get_surface_capabilities2(struct wsi_device
*wsi_device
,
749 const VkPhysicalDeviceSurfaceInfo2KHR
*pSurfaceInfo
,
750 VkSurfaceCapabilities2KHR
*pSurfaceCapabilities
)
752 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, pSurfaceInfo
->surface
);
753 struct wsi_interface
*iface
= wsi_device
->wsi
[surface
->platform
];
755 return iface
->get_capabilities2(surface
, wsi_device
, pSurfaceInfo
->pNext
,
756 pSurfaceCapabilities
);
760 wsi_common_get_surface_capabilities2ext(
761 struct wsi_device
*wsi_device
,
762 VkSurfaceKHR _surface
,
763 VkSurfaceCapabilities2EXT
*pSurfaceCapabilities
)
765 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, _surface
);
766 struct wsi_interface
*iface
= wsi_device
->wsi
[surface
->platform
];
768 assert(pSurfaceCapabilities
->sType
==
769 VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT
);
771 struct wsi_surface_supported_counters counters
= {
772 .sType
= VK_STRUCTURE_TYPE_WSI_SURFACE_SUPPORTED_COUNTERS_MESA
,
773 .pNext
= pSurfaceCapabilities
->pNext
,
774 .supported_surface_counters
= 0,
777 VkSurfaceCapabilities2KHR caps2
= {
778 .sType
= VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR
,
782 VkResult result
= iface
->get_capabilities2(surface
, wsi_device
, NULL
, &caps2
);
784 if (result
== VK_SUCCESS
) {
785 VkSurfaceCapabilities2EXT
*ext_caps
= pSurfaceCapabilities
;
786 VkSurfaceCapabilitiesKHR khr_caps
= caps2
.surfaceCapabilities
;
788 ext_caps
->minImageCount
= khr_caps
.minImageCount
;
789 ext_caps
->maxImageCount
= khr_caps
.maxImageCount
;
790 ext_caps
->currentExtent
= khr_caps
.currentExtent
;
791 ext_caps
->minImageExtent
= khr_caps
.minImageExtent
;
792 ext_caps
->maxImageExtent
= khr_caps
.maxImageExtent
;
793 ext_caps
->maxImageArrayLayers
= khr_caps
.maxImageArrayLayers
;
794 ext_caps
->supportedTransforms
= khr_caps
.supportedTransforms
;
795 ext_caps
->currentTransform
= khr_caps
.currentTransform
;
796 ext_caps
->supportedCompositeAlpha
= khr_caps
.supportedCompositeAlpha
;
797 ext_caps
->supportedUsageFlags
= khr_caps
.supportedUsageFlags
;
798 ext_caps
->supportedSurfaceCounters
= counters
.supported_surface_counters
;
805 wsi_common_get_surface_formats(struct wsi_device
*wsi_device
,
806 VkSurfaceKHR _surface
,
807 uint32_t *pSurfaceFormatCount
,
808 VkSurfaceFormatKHR
*pSurfaceFormats
)
810 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, _surface
);
811 struct wsi_interface
*iface
= wsi_device
->wsi
[surface
->platform
];
813 return iface
->get_formats(surface
, wsi_device
,
814 pSurfaceFormatCount
, pSurfaceFormats
);
818 wsi_common_get_surface_formats2(struct wsi_device
*wsi_device
,
819 const VkPhysicalDeviceSurfaceInfo2KHR
*pSurfaceInfo
,
820 uint32_t *pSurfaceFormatCount
,
821 VkSurfaceFormat2KHR
*pSurfaceFormats
)
823 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, pSurfaceInfo
->surface
);
824 struct wsi_interface
*iface
= wsi_device
->wsi
[surface
->platform
];
826 return iface
->get_formats2(surface
, wsi_device
, pSurfaceInfo
->pNext
,
827 pSurfaceFormatCount
, pSurfaceFormats
);
831 wsi_common_get_surface_present_modes(struct wsi_device
*wsi_device
,
832 VkSurfaceKHR _surface
,
833 uint32_t *pPresentModeCount
,
834 VkPresentModeKHR
*pPresentModes
)
836 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, _surface
);
837 struct wsi_interface
*iface
= wsi_device
->wsi
[surface
->platform
];
839 return iface
->get_present_modes(surface
, pPresentModeCount
,
844 wsi_common_get_present_rectangles(struct wsi_device
*wsi_device
,
845 VkSurfaceKHR _surface
,
846 uint32_t* pRectCount
,
849 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, _surface
);
850 struct wsi_interface
*iface
= wsi_device
->wsi
[surface
->platform
];
852 return iface
->get_present_rectangles(surface
, wsi_device
,
857 wsi_common_create_swapchain(struct wsi_device
*wsi
,
859 const VkSwapchainCreateInfoKHR
*pCreateInfo
,
860 const VkAllocationCallbacks
*pAllocator
,
861 VkSwapchainKHR
*pSwapchain
)
863 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, pCreateInfo
->surface
);
864 struct wsi_interface
*iface
= wsi
->wsi
[surface
->platform
];
865 struct wsi_swapchain
*swapchain
;
867 VkResult result
= iface
->create_swapchain(surface
, device
, wsi
,
868 pCreateInfo
, pAllocator
,
870 if (result
!= VK_SUCCESS
)
873 *pSwapchain
= wsi_swapchain_to_handle(swapchain
);
879 wsi_common_destroy_swapchain(VkDevice device
,
880 VkSwapchainKHR _swapchain
,
881 const VkAllocationCallbacks
*pAllocator
)
883 WSI_FROM_HANDLE(wsi_swapchain
, swapchain
, _swapchain
);
887 swapchain
->destroy(swapchain
, pAllocator
);
891 wsi_common_get_images(VkSwapchainKHR _swapchain
,
892 uint32_t *pSwapchainImageCount
,
893 VkImage
*pSwapchainImages
)
895 WSI_FROM_HANDLE(wsi_swapchain
, swapchain
, _swapchain
);
896 VK_OUTARRAY_MAKE(images
, pSwapchainImages
, pSwapchainImageCount
);
898 for (uint32_t i
= 0; i
< swapchain
->image_count
; i
++) {
899 vk_outarray_append(&images
, image
) {
900 *image
= swapchain
->get_wsi_image(swapchain
, i
)->image
;
904 return vk_outarray_status(&images
);
908 wsi_common_acquire_next_image2(const struct wsi_device
*wsi
,
910 const VkAcquireNextImageInfoKHR
*pAcquireInfo
,
911 uint32_t *pImageIndex
)
913 WSI_FROM_HANDLE(wsi_swapchain
, swapchain
, pAcquireInfo
->swapchain
);
915 return swapchain
->acquire_next_image(swapchain
, pAcquireInfo
, pImageIndex
);
919 wsi_common_queue_present(const struct wsi_device
*wsi
,
922 int queue_family_index
,
923 const VkPresentInfoKHR
*pPresentInfo
)
925 VkResult final_result
= VK_SUCCESS
;
927 const VkPresentRegionsKHR
*regions
=
928 vk_find_struct_const(pPresentInfo
->pNext
, PRESENT_REGIONS_KHR
);
930 for (uint32_t i
= 0; i
< pPresentInfo
->swapchainCount
; i
++) {
931 WSI_FROM_HANDLE(wsi_swapchain
, swapchain
, pPresentInfo
->pSwapchains
[i
]);
934 if (swapchain
->fences
[0] == VK_NULL_HANDLE
) {
935 const VkFenceCreateInfo fence_info
= {
936 .sType
= VK_STRUCTURE_TYPE_FENCE_CREATE_INFO
,
940 result
= wsi
->CreateFence(device
, &fence_info
,
942 &swapchain
->fences
[0]);
943 if (result
!= VK_SUCCESS
)
946 wsi
->ResetFences(device
, 1, &swapchain
->fences
[0]);
949 VkSubmitInfo submit_info
= {
950 .sType
= VK_STRUCTURE_TYPE_SUBMIT_INFO
,
954 VkPipelineStageFlags
*stage_flags
= NULL
;
956 /* We only need/want to wait on semaphores once. After that, we're
957 * guaranteed ordering since it all happens on the same queue.
959 submit_info
.waitSemaphoreCount
= pPresentInfo
->waitSemaphoreCount
;
960 submit_info
.pWaitSemaphores
= pPresentInfo
->pWaitSemaphores
;
962 /* Set up the pWaitDstStageMasks */
963 stage_flags
= vk_alloc(&swapchain
->alloc
,
964 sizeof(VkPipelineStageFlags
) *
965 pPresentInfo
->waitSemaphoreCount
,
967 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND
);
969 result
= VK_ERROR_OUT_OF_HOST_MEMORY
;
972 for (uint32_t s
= 0; s
< pPresentInfo
->waitSemaphoreCount
; s
++)
973 stage_flags
[s
] = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT
;
975 submit_info
.pWaitDstStageMask
= stage_flags
;
978 if (swapchain
->use_prime_blit
) {
979 /* If we are using prime blits, we need to perform the blit now. The
980 * command buffer is attached to the image.
982 struct wsi_image
*image
=
983 swapchain
->get_wsi_image(swapchain
, pPresentInfo
->pImageIndices
[i
]);
984 submit_info
.commandBufferCount
= 1;
985 submit_info
.pCommandBuffers
=
986 &image
->prime
.blit_cmd_buffers
[queue_family_index
];
989 result
= wsi
->QueueSubmit(queue
, 1, &submit_info
, swapchain
->fences
[0]);
990 vk_free(&swapchain
->alloc
, stage_flags
);
991 if (result
!= VK_SUCCESS
)
994 const VkPresentRegionKHR
*region
= NULL
;
995 if (regions
&& regions
->pRegions
)
996 region
= ®ions
->pRegions
[i
];
998 result
= swapchain
->queue_present(swapchain
,
999 pPresentInfo
->pImageIndices
[i
],
1001 if (result
!= VK_SUCCESS
)
1004 VkFence last
= swapchain
->fences
[2];
1005 swapchain
->fences
[2] = swapchain
->fences
[1];
1006 swapchain
->fences
[1] = swapchain
->fences
[0];
1007 swapchain
->fences
[0] = last
;
1009 if (last
!= VK_NULL_HANDLE
) {
1010 wsi
->WaitForFences(device
, 1, &last
, true, 1);
1014 if (pPresentInfo
->pResults
!= NULL
)
1015 pPresentInfo
->pResults
[i
] = result
;
1017 /* Let the final result be our first unsuccessful result */
1018 if (final_result
== VK_SUCCESS
)
1019 final_result
= result
;
1022 return final_result
;