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"
27 #include "util/xmlconfig.h"
37 wsi_device_init(struct wsi_device
*wsi
,
38 VkPhysicalDevice pdevice
,
39 WSI_FN_GetPhysicalDeviceProcAddr proc_addr
,
40 const VkAllocationCallbacks
*alloc
,
42 const struct driOptionCache
*dri_options
)
44 const char *present_mode
;
47 memset(wsi
, 0, sizeof(*wsi
));
49 wsi
->instance_alloc
= *alloc
;
50 wsi
->pdevice
= pdevice
;
52 #define WSI_GET_CB(func) \
53 PFN_vk##func func = (PFN_vk##func)proc_addr(pdevice, "vk" #func)
54 WSI_GET_CB(GetPhysicalDeviceProperties2
);
55 WSI_GET_CB(GetPhysicalDeviceMemoryProperties
);
56 WSI_GET_CB(GetPhysicalDeviceQueueFamilyProperties
);
59 wsi
->pci_bus_info
.sType
=
60 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT
;
61 VkPhysicalDeviceProperties2 pdp2
= {
62 .sType
= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2
,
63 .pNext
= &wsi
->pci_bus_info
,
65 GetPhysicalDeviceProperties2(pdevice
, &pdp2
);
67 wsi
->maxImageDimension2D
= pdp2
.properties
.limits
.maxImageDimension2D
;
68 wsi
->override_present_mode
= VK_PRESENT_MODE_MAX_ENUM_KHR
;
70 GetPhysicalDeviceMemoryProperties(pdevice
, &wsi
->memory_props
);
71 GetPhysicalDeviceQueueFamilyProperties(pdevice
, &wsi
->queue_family_count
, NULL
);
73 #define WSI_GET_CB(func) \
74 wsi->func = (PFN_vk##func)proc_addr(pdevice, "vk" #func)
75 WSI_GET_CB(AllocateMemory
);
76 WSI_GET_CB(AllocateCommandBuffers
);
77 WSI_GET_CB(BindBufferMemory
);
78 WSI_GET_CB(BindImageMemory
);
79 WSI_GET_CB(BeginCommandBuffer
);
80 WSI_GET_CB(CmdCopyImageToBuffer
);
81 WSI_GET_CB(CreateBuffer
);
82 WSI_GET_CB(CreateCommandPool
);
83 WSI_GET_CB(CreateFence
);
84 WSI_GET_CB(CreateImage
);
85 WSI_GET_CB(DestroyBuffer
);
86 WSI_GET_CB(DestroyCommandPool
);
87 WSI_GET_CB(DestroyFence
);
88 WSI_GET_CB(DestroyImage
);
89 WSI_GET_CB(EndCommandBuffer
);
90 WSI_GET_CB(FreeMemory
);
91 WSI_GET_CB(FreeCommandBuffers
);
92 WSI_GET_CB(GetBufferMemoryRequirements
);
93 WSI_GET_CB(GetImageMemoryRequirements
);
94 WSI_GET_CB(GetImageSubresourceLayout
);
95 WSI_GET_CB(GetMemoryFdKHR
);
96 WSI_GET_CB(GetPhysicalDeviceFormatProperties
);
97 WSI_GET_CB(GetPhysicalDeviceFormatProperties2KHR
);
98 WSI_GET_CB(ResetFences
);
99 WSI_GET_CB(QueueSubmit
);
100 WSI_GET_CB(WaitForFences
);
103 #ifdef VK_USE_PLATFORM_XCB_KHR
104 result
= wsi_x11_init_wsi(wsi
, alloc
);
105 if (result
!= VK_SUCCESS
)
109 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
110 result
= wsi_wl_init_wsi(wsi
, alloc
, pdevice
);
111 if (result
!= VK_SUCCESS
)
115 #ifdef VK_USE_PLATFORM_DISPLAY_KHR
116 result
= wsi_display_init_wsi(wsi
, alloc
, display_fd
);
117 if (result
!= VK_SUCCESS
)
121 present_mode
= getenv("MESA_VK_WSI_PRESENT_MODE");
123 if (!strcmp(present_mode
, "fifo")) {
124 wsi
->override_present_mode
= VK_PRESENT_MODE_FIFO_KHR
;
125 } else if (!strcmp(present_mode
, "mailbox")) {
126 wsi
->override_present_mode
= VK_PRESENT_MODE_MAILBOX_KHR
;
127 } else if (!strcmp(present_mode
, "immediate")) {
128 wsi
->override_present_mode
= VK_PRESENT_MODE_IMMEDIATE_KHR
;
130 fprintf(stderr
, "Invalid MESA_VK_WSI_PRESENT_MODE value!\n");
135 if (driCheckOption(dri_options
, "adaptive_sync", DRI_BOOL
))
136 wsi
->enable_adaptive_sync
= driQueryOptionb(dri_options
,
143 wsi_device_finish(wsi
, alloc
);
148 wsi_device_finish(struct wsi_device
*wsi
,
149 const VkAllocationCallbacks
*alloc
)
151 #ifdef VK_USE_PLATFORM_DISPLAY_KHR
152 wsi_display_finish_wsi(wsi
, alloc
);
154 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
155 wsi_wl_finish_wsi(wsi
, alloc
);
157 #ifdef VK_USE_PLATFORM_XCB_KHR
158 wsi_x11_finish_wsi(wsi
, alloc
);
163 wsi_device_matches_drm_fd(const struct wsi_device
*wsi
, int drm_fd
)
165 drmDevicePtr fd_device
;
166 int ret
= drmGetDevice2(drm_fd
, 0, &fd_device
);
171 switch (fd_device
->bustype
) {
173 match
= wsi
->pci_bus_info
.pciDomain
== fd_device
->businfo
.pci
->domain
&&
174 wsi
->pci_bus_info
.pciBus
== fd_device
->businfo
.pci
->bus
&&
175 wsi
->pci_bus_info
.pciDevice
== fd_device
->businfo
.pci
->dev
&&
176 wsi
->pci_bus_info
.pciFunction
== fd_device
->businfo
.pci
->func
;
183 drmFreeDevice(&fd_device
);
189 wsi_swapchain_init(const struct wsi_device
*wsi
,
190 struct wsi_swapchain
*chain
,
192 const VkSwapchainCreateInfoKHR
*pCreateInfo
,
193 const VkAllocationCallbacks
*pAllocator
)
197 memset(chain
, 0, sizeof(*chain
));
200 chain
->device
= device
;
201 chain
->alloc
= *pAllocator
;
202 chain
->use_prime_blit
= false;
205 vk_zalloc(pAllocator
, sizeof(VkCommandPool
) * wsi
->queue_family_count
, 8,
206 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
207 if (!chain
->cmd_pools
)
208 return VK_ERROR_OUT_OF_HOST_MEMORY
;
210 for (uint32_t i
= 0; i
< wsi
->queue_family_count
; i
++) {
211 const VkCommandPoolCreateInfo cmd_pool_info
= {
212 .sType
= VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO
,
215 .queueFamilyIndex
= i
,
217 result
= wsi
->CreateCommandPool(device
, &cmd_pool_info
, &chain
->alloc
,
218 &chain
->cmd_pools
[i
]);
219 if (result
!= VK_SUCCESS
)
226 wsi_swapchain_finish(chain
);
231 wsi_swapchain_is_present_mode_supported(struct wsi_device
*wsi
,
232 const VkSwapchainCreateInfoKHR
*pCreateInfo
,
233 VkPresentModeKHR mode
)
235 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, pCreateInfo
->surface
);
236 struct wsi_interface
*iface
= wsi
->wsi
[surface
->platform
];
237 VkPresentModeKHR
*present_modes
;
238 uint32_t present_mode_count
;
239 bool supported
= false;
242 result
= iface
->get_present_modes(surface
, &present_mode_count
, NULL
);
243 if (result
!= VK_SUCCESS
)
246 present_modes
= malloc(present_mode_count
* sizeof(*present_modes
));
250 result
= iface
->get_present_modes(surface
, &present_mode_count
,
252 if (result
!= VK_SUCCESS
)
255 for (uint32_t i
= 0; i
< present_mode_count
; i
++) {
256 if (present_modes
[i
] == mode
) {
267 enum VkPresentModeKHR
268 wsi_swapchain_get_present_mode(struct wsi_device
*wsi
,
269 const VkSwapchainCreateInfoKHR
*pCreateInfo
)
271 if (wsi
->override_present_mode
== VK_PRESENT_MODE_MAX_ENUM_KHR
)
272 return pCreateInfo
->presentMode
;
274 if (!wsi_swapchain_is_present_mode_supported(wsi
, pCreateInfo
,
275 wsi
->override_present_mode
)) {
276 fprintf(stderr
, "Unsupported MESA_VK_WSI_PRESENT_MODE value!\n");
277 return pCreateInfo
->presentMode
;
280 return wsi
->override_present_mode
;
284 wsi_swapchain_finish(struct wsi_swapchain
*chain
)
286 for (unsigned i
= 0; i
< ARRAY_SIZE(chain
->fences
); i
++)
287 chain
->wsi
->DestroyFence(chain
->device
, chain
->fences
[i
], &chain
->alloc
);
289 for (uint32_t i
= 0; i
< chain
->wsi
->queue_family_count
; i
++) {
290 chain
->wsi
->DestroyCommandPool(chain
->device
, chain
->cmd_pools
[i
],
293 vk_free(&chain
->alloc
, chain
->cmd_pools
);
297 select_memory_type(const struct wsi_device
*wsi
,
298 VkMemoryPropertyFlags props
,
301 for (uint32_t i
= 0; i
< wsi
->memory_props
.memoryTypeCount
; i
++) {
302 const VkMemoryType type
= wsi
->memory_props
.memoryTypes
[i
];
303 if ((type_bits
& (1 << i
)) && (type
.propertyFlags
& props
) == props
)
307 unreachable("No memory type found");
311 vk_format_size(VkFormat format
)
314 case VK_FORMAT_B8G8R8A8_UNORM
:
315 case VK_FORMAT_B8G8R8A8_SRGB
:
318 unreachable("Unknown WSI Format");
322 static inline uint32_t
323 align_u32(uint32_t v
, uint32_t a
)
325 assert(a
!= 0 && a
== (a
& -a
));
326 return (v
+ a
- 1) & ~(a
- 1);
330 wsi_create_native_image(const struct wsi_swapchain
*chain
,
331 const VkSwapchainCreateInfoKHR
*pCreateInfo
,
332 uint32_t num_modifier_lists
,
333 const uint32_t *num_modifiers
,
334 const uint64_t *const *modifiers
,
335 struct wsi_image
*image
)
337 const struct wsi_device
*wsi
= chain
->wsi
;
340 memset(image
, 0, sizeof(*image
));
341 for (int i
= 0; i
< ARRAY_SIZE(image
->fds
); i
++)
344 struct wsi_image_create_info image_wsi_info
= {
345 .sType
= VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA
,
349 uint32_t image_modifier_count
= 0, modifier_prop_count
= 0;
350 struct wsi_format_modifier_properties
*modifier_props
= NULL
;
351 uint64_t *image_modifiers
= NULL
;
352 if (num_modifier_lists
== 0) {
353 /* If we don't have modifiers, fall back to the legacy "scanout" flag */
354 image_wsi_info
.scanout
= true;
356 /* The winsys can't request modifiers if we don't support them. */
357 assert(wsi
->supports_modifiers
);
358 struct wsi_format_modifier_properties_list modifier_props_list
= {
359 .sType
= VK_STRUCTURE_TYPE_WSI_FORMAT_MODIFIER_PROPERTIES_LIST_MESA
,
362 VkFormatProperties2 format_props
= {
363 .sType
= VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2
,
364 .pNext
= &modifier_props_list
,
366 wsi
->GetPhysicalDeviceFormatProperties2KHR(wsi
->pdevice
,
367 pCreateInfo
->imageFormat
,
369 assert(modifier_props_list
.modifier_count
> 0);
370 modifier_props
= vk_alloc(&chain
->alloc
,
371 sizeof(*modifier_props
) *
372 modifier_props_list
.modifier_count
,
374 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND
);
375 if (!modifier_props
) {
376 result
= VK_ERROR_OUT_OF_HOST_MEMORY
;
380 modifier_props_list
.modifier_properties
= modifier_props
;
381 wsi
->GetPhysicalDeviceFormatProperties2KHR(wsi
->pdevice
,
382 pCreateInfo
->imageFormat
,
384 modifier_prop_count
= modifier_props_list
.modifier_count
;
386 uint32_t max_modifier_count
= 0;
387 for (uint32_t l
= 0; l
< num_modifier_lists
; l
++)
388 max_modifier_count
= MAX2(max_modifier_count
, num_modifiers
[l
]);
390 image_modifiers
= vk_alloc(&chain
->alloc
,
391 sizeof(*image_modifiers
) *
394 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND
);
395 if (!image_modifiers
) {
396 result
= VK_ERROR_OUT_OF_HOST_MEMORY
;
400 image_modifier_count
= 0;
401 for (uint32_t l
= 0; l
< num_modifier_lists
; l
++) {
402 /* Walk the modifier lists and construct a list of supported
405 for (uint32_t i
= 0; i
< num_modifiers
[l
]; i
++) {
406 for (uint32_t j
= 0; j
< modifier_prop_count
; j
++) {
407 if (modifier_props
[j
].modifier
== modifiers
[l
][i
])
408 image_modifiers
[image_modifier_count
++] = modifiers
[l
][i
];
412 /* We only want to take the modifiers from the first list */
413 if (image_modifier_count
> 0)
417 if (image_modifier_count
> 0) {
418 image_wsi_info
.modifier_count
= image_modifier_count
;
419 image_wsi_info
.modifiers
= image_modifiers
;
421 /* TODO: Add a proper error here */
422 assert(!"Failed to find a supported modifier! This should never "
423 "happen because LINEAR should always be available");
424 result
= VK_ERROR_OUT_OF_HOST_MEMORY
;
429 const VkImageCreateInfo image_info
= {
430 .sType
= VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
,
431 .pNext
= &image_wsi_info
,
433 .imageType
= VK_IMAGE_TYPE_2D
,
434 .format
= pCreateInfo
->imageFormat
,
436 .width
= pCreateInfo
->imageExtent
.width
,
437 .height
= pCreateInfo
->imageExtent
.height
,
442 .samples
= VK_SAMPLE_COUNT_1_BIT
,
443 .tiling
= VK_IMAGE_TILING_OPTIMAL
,
444 .usage
= pCreateInfo
->imageUsage
,
445 .sharingMode
= pCreateInfo
->imageSharingMode
,
446 .queueFamilyIndexCount
= pCreateInfo
->queueFamilyIndexCount
,
447 .pQueueFamilyIndices
= pCreateInfo
->pQueueFamilyIndices
,
448 .initialLayout
= VK_IMAGE_LAYOUT_UNDEFINED
,
450 result
= wsi
->CreateImage(chain
->device
, &image_info
,
451 &chain
->alloc
, &image
->image
);
452 if (result
!= VK_SUCCESS
)
455 VkMemoryRequirements reqs
;
456 wsi
->GetImageMemoryRequirements(chain
->device
, image
->image
, &reqs
);
458 const struct wsi_memory_allocate_info memory_wsi_info
= {
459 .sType
= VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA
,
461 .implicit_sync
= true,
463 const VkExportMemoryAllocateInfo memory_export_info
= {
464 .sType
= VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO
,
465 .pNext
= &memory_wsi_info
,
466 .handleTypes
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
,
468 const VkMemoryDedicatedAllocateInfo memory_dedicated_info
= {
469 .sType
= VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO
,
470 .pNext
= &memory_export_info
,
471 .image
= image
->image
,
472 .buffer
= VK_NULL_HANDLE
,
474 const VkMemoryAllocateInfo memory_info
= {
475 .sType
= VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO
,
476 .pNext
= &memory_dedicated_info
,
477 .allocationSize
= reqs
.size
,
478 .memoryTypeIndex
= select_memory_type(wsi
, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
,
479 reqs
.memoryTypeBits
),
481 result
= wsi
->AllocateMemory(chain
->device
, &memory_info
,
482 &chain
->alloc
, &image
->memory
);
483 if (result
!= VK_SUCCESS
)
486 result
= wsi
->BindImageMemory(chain
->device
, image
->image
,
488 if (result
!= VK_SUCCESS
)
491 const VkMemoryGetFdInfoKHR memory_get_fd_info
= {
492 .sType
= VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR
,
494 .memory
= image
->memory
,
495 .handleType
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
,
498 result
= wsi
->GetMemoryFdKHR(chain
->device
, &memory_get_fd_info
, &fd
);
499 if (result
!= VK_SUCCESS
)
502 if (num_modifier_lists
> 0) {
503 image
->drm_modifier
= wsi
->image_get_modifier(image
->image
);
504 assert(image
->drm_modifier
!= DRM_FORMAT_MOD_INVALID
);
506 for (uint32_t j
= 0; j
< modifier_prop_count
; j
++) {
507 if (modifier_props
[j
].modifier
== image
->drm_modifier
) {
508 image
->num_planes
= modifier_props
[j
].modifier_plane_count
;
513 for (uint32_t p
= 0; p
< image
->num_planes
; p
++) {
514 const VkImageSubresource image_subresource
= {
515 .aspectMask
= VK_IMAGE_ASPECT_PLANE_0_BIT
<< p
,
519 VkSubresourceLayout image_layout
;
520 wsi
->GetImageSubresourceLayout(chain
->device
, image
->image
,
521 &image_subresource
, &image_layout
);
522 image
->sizes
[p
] = image_layout
.size
;
523 image
->row_pitches
[p
] = image_layout
.rowPitch
;
524 image
->offsets
[p
] = image_layout
.offset
;
528 image
->fds
[p
] = dup(fd
);
529 if (image
->fds
[p
] == -1) {
530 for (uint32_t i
= 0; i
< p
; i
++)
531 close(image
->fds
[p
]);
538 const VkImageSubresource image_subresource
= {
539 .aspectMask
= VK_IMAGE_ASPECT_COLOR_BIT
,
543 VkSubresourceLayout image_layout
;
544 wsi
->GetImageSubresourceLayout(chain
->device
, image
->image
,
545 &image_subresource
, &image_layout
);
547 image
->drm_modifier
= DRM_FORMAT_MOD_INVALID
;
548 image
->num_planes
= 1;
549 image
->sizes
[0] = reqs
.size
;
550 image
->row_pitches
[0] = image_layout
.rowPitch
;
551 image
->offsets
[0] = 0;
555 vk_free(&chain
->alloc
, modifier_props
);
556 vk_free(&chain
->alloc
, image_modifiers
);
561 vk_free(&chain
->alloc
, modifier_props
);
562 vk_free(&chain
->alloc
, image_modifiers
);
563 wsi_destroy_image(chain
, image
);
568 #define WSI_PRIME_LINEAR_STRIDE_ALIGN 256
571 wsi_create_prime_image(const struct wsi_swapchain
*chain
,
572 const VkSwapchainCreateInfoKHR
*pCreateInfo
,
574 struct wsi_image
*image
)
576 const struct wsi_device
*wsi
= chain
->wsi
;
579 memset(image
, 0, sizeof(*image
));
581 const uint32_t cpp
= vk_format_size(pCreateInfo
->imageFormat
);
582 const uint32_t linear_stride
= align_u32(pCreateInfo
->imageExtent
.width
* cpp
,
583 WSI_PRIME_LINEAR_STRIDE_ALIGN
);
585 uint32_t linear_size
= linear_stride
* pCreateInfo
->imageExtent
.height
;
586 linear_size
= align_u32(linear_size
, 4096);
588 const VkExternalMemoryBufferCreateInfo prime_buffer_external_info
= {
589 .sType
= VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO
,
591 .handleTypes
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
,
593 const VkBufferCreateInfo prime_buffer_info
= {
594 .sType
= VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO
,
595 .pNext
= &prime_buffer_external_info
,
597 .usage
= VK_BUFFER_USAGE_TRANSFER_DST_BIT
,
598 .sharingMode
= VK_SHARING_MODE_EXCLUSIVE
,
600 result
= wsi
->CreateBuffer(chain
->device
, &prime_buffer_info
,
601 &chain
->alloc
, &image
->prime
.buffer
);
602 if (result
!= VK_SUCCESS
)
605 VkMemoryRequirements reqs
;
606 wsi
->GetBufferMemoryRequirements(chain
->device
, image
->prime
.buffer
, &reqs
);
607 assert(reqs
.size
<= linear_size
);
609 const struct wsi_memory_allocate_info memory_wsi_info
= {
610 .sType
= VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA
,
612 .implicit_sync
= true,
614 const VkExportMemoryAllocateInfo prime_memory_export_info
= {
615 .sType
= VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO
,
616 .pNext
= &memory_wsi_info
,
617 .handleTypes
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
,
619 const VkMemoryDedicatedAllocateInfo prime_memory_dedicated_info
= {
620 .sType
= VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO
,
621 .pNext
= &prime_memory_export_info
,
622 .image
= VK_NULL_HANDLE
,
623 .buffer
= image
->prime
.buffer
,
625 const VkMemoryAllocateInfo prime_memory_info
= {
626 .sType
= VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO
,
627 .pNext
= &prime_memory_dedicated_info
,
628 .allocationSize
= linear_size
,
629 .memoryTypeIndex
= select_memory_type(wsi
, 0, reqs
.memoryTypeBits
),
631 result
= wsi
->AllocateMemory(chain
->device
, &prime_memory_info
,
632 &chain
->alloc
, &image
->prime
.memory
);
633 if (result
!= VK_SUCCESS
)
636 result
= wsi
->BindBufferMemory(chain
->device
, image
->prime
.buffer
,
637 image
->prime
.memory
, 0);
638 if (result
!= VK_SUCCESS
)
641 const VkImageCreateInfo image_info
= {
642 .sType
= VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
,
645 .imageType
= VK_IMAGE_TYPE_2D
,
646 .format
= pCreateInfo
->imageFormat
,
648 .width
= pCreateInfo
->imageExtent
.width
,
649 .height
= pCreateInfo
->imageExtent
.height
,
654 .samples
= VK_SAMPLE_COUNT_1_BIT
,
655 .tiling
= VK_IMAGE_TILING_OPTIMAL
,
656 .usage
= pCreateInfo
->imageUsage
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT
,
657 .sharingMode
= pCreateInfo
->imageSharingMode
,
658 .queueFamilyIndexCount
= pCreateInfo
->queueFamilyIndexCount
,
659 .pQueueFamilyIndices
= pCreateInfo
->pQueueFamilyIndices
,
660 .initialLayout
= VK_IMAGE_LAYOUT_UNDEFINED
,
662 result
= wsi
->CreateImage(chain
->device
, &image_info
,
663 &chain
->alloc
, &image
->image
);
664 if (result
!= VK_SUCCESS
)
667 wsi
->GetImageMemoryRequirements(chain
->device
, image
->image
, &reqs
);
669 const VkMemoryDedicatedAllocateInfo memory_dedicated_info
= {
670 .sType
= VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO
,
672 .image
= image
->image
,
673 .buffer
= VK_NULL_HANDLE
,
675 const VkMemoryAllocateInfo memory_info
= {
676 .sType
= VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO
,
677 .pNext
= &memory_dedicated_info
,
678 .allocationSize
= reqs
.size
,
679 .memoryTypeIndex
= select_memory_type(wsi
, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
,
680 reqs
.memoryTypeBits
),
682 result
= wsi
->AllocateMemory(chain
->device
, &memory_info
,
683 &chain
->alloc
, &image
->memory
);
684 if (result
!= VK_SUCCESS
)
687 result
= wsi
->BindImageMemory(chain
->device
, image
->image
,
689 if (result
!= VK_SUCCESS
)
692 image
->prime
.blit_cmd_buffers
=
693 vk_zalloc(&chain
->alloc
,
694 sizeof(VkCommandBuffer
) * wsi
->queue_family_count
, 8,
695 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
696 if (!image
->prime
.blit_cmd_buffers
) {
697 result
= VK_ERROR_OUT_OF_HOST_MEMORY
;
701 for (uint32_t i
= 0; i
< wsi
->queue_family_count
; i
++) {
702 const VkCommandBufferAllocateInfo cmd_buffer_info
= {
703 .sType
= VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO
,
705 .commandPool
= chain
->cmd_pools
[i
],
706 .level
= VK_COMMAND_BUFFER_LEVEL_PRIMARY
,
707 .commandBufferCount
= 1,
709 result
= wsi
->AllocateCommandBuffers(chain
->device
, &cmd_buffer_info
,
710 &image
->prime
.blit_cmd_buffers
[i
]);
711 if (result
!= VK_SUCCESS
)
714 const VkCommandBufferBeginInfo begin_info
= {
715 .sType
= VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO
,
717 wsi
->BeginCommandBuffer(image
->prime
.blit_cmd_buffers
[i
], &begin_info
);
719 struct VkBufferImageCopy buffer_image_copy
= {
721 .bufferRowLength
= linear_stride
/ cpp
,
722 .bufferImageHeight
= 0,
723 .imageSubresource
= {
724 .aspectMask
= VK_IMAGE_ASPECT_COLOR_BIT
,
729 .imageOffset
= { .x
= 0, .y
= 0, .z
= 0 },
731 .width
= pCreateInfo
->imageExtent
.width
,
732 .height
= pCreateInfo
->imageExtent
.height
,
736 wsi
->CmdCopyImageToBuffer(image
->prime
.blit_cmd_buffers
[i
],
738 VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
,
740 1, &buffer_image_copy
);
742 result
= wsi
->EndCommandBuffer(image
->prime
.blit_cmd_buffers
[i
]);
743 if (result
!= VK_SUCCESS
)
747 const VkMemoryGetFdInfoKHR linear_memory_get_fd_info
= {
748 .sType
= VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR
,
750 .memory
= image
->prime
.memory
,
751 .handleType
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT
,
754 result
= wsi
->GetMemoryFdKHR(chain
->device
, &linear_memory_get_fd_info
, &fd
);
755 if (result
!= VK_SUCCESS
)
758 image
->drm_modifier
= use_modifier
? DRM_FORMAT_MOD_LINEAR
: DRM_FORMAT_MOD_INVALID
;
759 image
->num_planes
= 1;
760 image
->sizes
[0] = linear_size
;
761 image
->row_pitches
[0] = linear_stride
;
762 image
->offsets
[0] = 0;
768 wsi_destroy_image(chain
, image
);
774 wsi_destroy_image(const struct wsi_swapchain
*chain
,
775 struct wsi_image
*image
)
777 const struct wsi_device
*wsi
= chain
->wsi
;
779 if (image
->prime
.blit_cmd_buffers
) {
780 for (uint32_t i
= 0; i
< wsi
->queue_family_count
; i
++) {
781 wsi
->FreeCommandBuffers(chain
->device
, chain
->cmd_pools
[i
],
782 1, &image
->prime
.blit_cmd_buffers
[i
]);
784 vk_free(&chain
->alloc
, image
->prime
.blit_cmd_buffers
);
787 wsi
->FreeMemory(chain
->device
, image
->memory
, &chain
->alloc
);
788 wsi
->DestroyImage(chain
->device
, image
->image
, &chain
->alloc
);
789 wsi
->FreeMemory(chain
->device
, image
->prime
.memory
, &chain
->alloc
);
790 wsi
->DestroyBuffer(chain
->device
, image
->prime
.buffer
, &chain
->alloc
);
794 wsi_common_get_surface_support(struct wsi_device
*wsi_device
,
795 uint32_t queueFamilyIndex
,
796 VkSurfaceKHR _surface
,
797 VkBool32
* pSupported
)
799 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, _surface
);
800 struct wsi_interface
*iface
= wsi_device
->wsi
[surface
->platform
];
802 return iface
->get_support(surface
, wsi_device
,
803 queueFamilyIndex
, pSupported
);
807 wsi_common_get_surface_capabilities(struct wsi_device
*wsi_device
,
808 VkSurfaceKHR _surface
,
809 VkSurfaceCapabilitiesKHR
*pSurfaceCapabilities
)
811 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, _surface
);
812 struct wsi_interface
*iface
= wsi_device
->wsi
[surface
->platform
];
814 VkSurfaceCapabilities2KHR caps2
= {
815 .sType
= VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR
,
818 VkResult result
= iface
->get_capabilities2(surface
, wsi_device
, NULL
, &caps2
);
820 if (result
== VK_SUCCESS
)
821 *pSurfaceCapabilities
= caps2
.surfaceCapabilities
;
827 wsi_common_get_surface_capabilities2(struct wsi_device
*wsi_device
,
828 const VkPhysicalDeviceSurfaceInfo2KHR
*pSurfaceInfo
,
829 VkSurfaceCapabilities2KHR
*pSurfaceCapabilities
)
831 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, pSurfaceInfo
->surface
);
832 struct wsi_interface
*iface
= wsi_device
->wsi
[surface
->platform
];
834 return iface
->get_capabilities2(surface
, wsi_device
, pSurfaceInfo
->pNext
,
835 pSurfaceCapabilities
);
839 wsi_common_get_surface_capabilities2ext(
840 struct wsi_device
*wsi_device
,
841 VkSurfaceKHR _surface
,
842 VkSurfaceCapabilities2EXT
*pSurfaceCapabilities
)
844 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, _surface
);
845 struct wsi_interface
*iface
= wsi_device
->wsi
[surface
->platform
];
847 assert(pSurfaceCapabilities
->sType
==
848 VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT
);
850 struct wsi_surface_supported_counters counters
= {
851 .sType
= VK_STRUCTURE_TYPE_WSI_SURFACE_SUPPORTED_COUNTERS_MESA
,
852 .pNext
= pSurfaceCapabilities
->pNext
,
853 .supported_surface_counters
= 0,
856 VkSurfaceCapabilities2KHR caps2
= {
857 .sType
= VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR
,
861 VkResult result
= iface
->get_capabilities2(surface
, wsi_device
, NULL
, &caps2
);
863 if (result
== VK_SUCCESS
) {
864 VkSurfaceCapabilities2EXT
*ext_caps
= pSurfaceCapabilities
;
865 VkSurfaceCapabilitiesKHR khr_caps
= caps2
.surfaceCapabilities
;
867 ext_caps
->minImageCount
= khr_caps
.minImageCount
;
868 ext_caps
->maxImageCount
= khr_caps
.maxImageCount
;
869 ext_caps
->currentExtent
= khr_caps
.currentExtent
;
870 ext_caps
->minImageExtent
= khr_caps
.minImageExtent
;
871 ext_caps
->maxImageExtent
= khr_caps
.maxImageExtent
;
872 ext_caps
->maxImageArrayLayers
= khr_caps
.maxImageArrayLayers
;
873 ext_caps
->supportedTransforms
= khr_caps
.supportedTransforms
;
874 ext_caps
->currentTransform
= khr_caps
.currentTransform
;
875 ext_caps
->supportedCompositeAlpha
= khr_caps
.supportedCompositeAlpha
;
876 ext_caps
->supportedUsageFlags
= khr_caps
.supportedUsageFlags
;
877 ext_caps
->supportedSurfaceCounters
= counters
.supported_surface_counters
;
884 wsi_common_get_surface_formats(struct wsi_device
*wsi_device
,
885 VkSurfaceKHR _surface
,
886 uint32_t *pSurfaceFormatCount
,
887 VkSurfaceFormatKHR
*pSurfaceFormats
)
889 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, _surface
);
890 struct wsi_interface
*iface
= wsi_device
->wsi
[surface
->platform
];
892 return iface
->get_formats(surface
, wsi_device
,
893 pSurfaceFormatCount
, pSurfaceFormats
);
897 wsi_common_get_surface_formats2(struct wsi_device
*wsi_device
,
898 const VkPhysicalDeviceSurfaceInfo2KHR
*pSurfaceInfo
,
899 uint32_t *pSurfaceFormatCount
,
900 VkSurfaceFormat2KHR
*pSurfaceFormats
)
902 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, pSurfaceInfo
->surface
);
903 struct wsi_interface
*iface
= wsi_device
->wsi
[surface
->platform
];
905 return iface
->get_formats2(surface
, wsi_device
, pSurfaceInfo
->pNext
,
906 pSurfaceFormatCount
, pSurfaceFormats
);
910 wsi_common_get_surface_present_modes(struct wsi_device
*wsi_device
,
911 VkSurfaceKHR _surface
,
912 uint32_t *pPresentModeCount
,
913 VkPresentModeKHR
*pPresentModes
)
915 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, _surface
);
916 struct wsi_interface
*iface
= wsi_device
->wsi
[surface
->platform
];
918 return iface
->get_present_modes(surface
, pPresentModeCount
,
923 wsi_common_get_present_rectangles(struct wsi_device
*wsi_device
,
924 VkSurfaceKHR _surface
,
925 uint32_t* pRectCount
,
928 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, _surface
);
929 struct wsi_interface
*iface
= wsi_device
->wsi
[surface
->platform
];
931 return iface
->get_present_rectangles(surface
, wsi_device
,
936 wsi_common_create_swapchain(struct wsi_device
*wsi
,
938 const VkSwapchainCreateInfoKHR
*pCreateInfo
,
939 const VkAllocationCallbacks
*pAllocator
,
940 VkSwapchainKHR
*pSwapchain
)
942 ICD_FROM_HANDLE(VkIcdSurfaceBase
, surface
, pCreateInfo
->surface
);
943 struct wsi_interface
*iface
= wsi
->wsi
[surface
->platform
];
944 struct wsi_swapchain
*swapchain
;
946 VkResult result
= iface
->create_swapchain(surface
, device
, wsi
,
947 pCreateInfo
, pAllocator
,
949 if (result
!= VK_SUCCESS
)
952 *pSwapchain
= wsi_swapchain_to_handle(swapchain
);
958 wsi_common_destroy_swapchain(VkDevice device
,
959 VkSwapchainKHR _swapchain
,
960 const VkAllocationCallbacks
*pAllocator
)
962 WSI_FROM_HANDLE(wsi_swapchain
, swapchain
, _swapchain
);
966 swapchain
->destroy(swapchain
, pAllocator
);
970 wsi_common_get_images(VkSwapchainKHR _swapchain
,
971 uint32_t *pSwapchainImageCount
,
972 VkImage
*pSwapchainImages
)
974 WSI_FROM_HANDLE(wsi_swapchain
, swapchain
, _swapchain
);
975 VK_OUTARRAY_MAKE(images
, pSwapchainImages
, pSwapchainImageCount
);
977 for (uint32_t i
= 0; i
< swapchain
->image_count
; i
++) {
978 vk_outarray_append(&images
, image
) {
979 *image
= swapchain
->get_wsi_image(swapchain
, i
)->image
;
983 return vk_outarray_status(&images
);
987 wsi_common_acquire_next_image2(const struct wsi_device
*wsi
,
989 const VkAcquireNextImageInfoKHR
*pAcquireInfo
,
990 uint32_t *pImageIndex
)
992 WSI_FROM_HANDLE(wsi_swapchain
, swapchain
, pAcquireInfo
->swapchain
);
994 return swapchain
->acquire_next_image(swapchain
, pAcquireInfo
, pImageIndex
);
998 wsi_common_queue_present(const struct wsi_device
*wsi
,
1001 int queue_family_index
,
1002 const VkPresentInfoKHR
*pPresentInfo
)
1004 VkResult final_result
= VK_SUCCESS
;
1006 const VkPresentRegionsKHR
*regions
=
1007 vk_find_struct_const(pPresentInfo
->pNext
, PRESENT_REGIONS_KHR
);
1009 for (uint32_t i
= 0; i
< pPresentInfo
->swapchainCount
; i
++) {
1010 WSI_FROM_HANDLE(wsi_swapchain
, swapchain
, pPresentInfo
->pSwapchains
[i
]);
1013 if (swapchain
->fences
[0] == VK_NULL_HANDLE
) {
1014 const VkFenceCreateInfo fence_info
= {
1015 .sType
= VK_STRUCTURE_TYPE_FENCE_CREATE_INFO
,
1019 result
= wsi
->CreateFence(device
, &fence_info
,
1021 &swapchain
->fences
[0]);
1022 if (result
!= VK_SUCCESS
)
1025 wsi
->ResetFences(device
, 1, &swapchain
->fences
[0]);
1028 VkSubmitInfo submit_info
= {
1029 .sType
= VK_STRUCTURE_TYPE_SUBMIT_INFO
,
1033 VkPipelineStageFlags
*stage_flags
= NULL
;
1035 /* We only need/want to wait on semaphores once. After that, we're
1036 * guaranteed ordering since it all happens on the same queue.
1038 submit_info
.waitSemaphoreCount
= pPresentInfo
->waitSemaphoreCount
;
1039 submit_info
.pWaitSemaphores
= pPresentInfo
->pWaitSemaphores
;
1041 /* Set up the pWaitDstStageMasks */
1042 stage_flags
= vk_alloc(&swapchain
->alloc
,
1043 sizeof(VkPipelineStageFlags
) *
1044 pPresentInfo
->waitSemaphoreCount
,
1046 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND
);
1048 result
= VK_ERROR_OUT_OF_HOST_MEMORY
;
1051 for (uint32_t s
= 0; s
< pPresentInfo
->waitSemaphoreCount
; s
++)
1052 stage_flags
[s
] = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT
;
1054 submit_info
.pWaitDstStageMask
= stage_flags
;
1057 if (swapchain
->use_prime_blit
) {
1058 /* If we are using prime blits, we need to perform the blit now. The
1059 * command buffer is attached to the image.
1061 struct wsi_image
*image
=
1062 swapchain
->get_wsi_image(swapchain
, pPresentInfo
->pImageIndices
[i
]);
1063 submit_info
.commandBufferCount
= 1;
1064 submit_info
.pCommandBuffers
=
1065 &image
->prime
.blit_cmd_buffers
[queue_family_index
];
1068 result
= wsi
->QueueSubmit(queue
, 1, &submit_info
, swapchain
->fences
[0]);
1069 vk_free(&swapchain
->alloc
, stage_flags
);
1070 if (result
!= VK_SUCCESS
)
1073 const VkPresentRegionKHR
*region
= NULL
;
1074 if (regions
&& regions
->pRegions
)
1075 region
= ®ions
->pRegions
[i
];
1077 result
= swapchain
->queue_present(swapchain
,
1078 pPresentInfo
->pImageIndices
[i
],
1080 if (result
!= VK_SUCCESS
)
1083 VkFence last
= swapchain
->fences
[2];
1084 swapchain
->fences
[2] = swapchain
->fences
[1];
1085 swapchain
->fences
[1] = swapchain
->fences
[0];
1086 swapchain
->fences
[0] = last
;
1088 if (last
!= VK_NULL_HANDLE
) {
1089 wsi
->WaitForFences(device
, 1, &last
, true, 1);
1093 if (pPresentInfo
->pResults
!= NULL
)
1094 pPresentInfo
->pResults
[i
] = result
;
1096 /* Let the final result be our first unsuccessful result */
1097 if (final_result
== VK_SUCCESS
)
1098 final_result
= result
;
1101 return final_result
;
1105 wsi_common_get_current_time(void)
1107 struct timespec current
;
1108 clock_gettime(CLOCK_MONOTONIC
, ¤t
);
1109 return current
.tv_nsec
+ current
.tv_sec
* 1000000000ull;