1/* 2 * Copyright © 2017 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 */ 23 24#include "wsi_common_private.h" 25#include "drm-uapi/drm_fourcc.h" 26#include "util/macros.h" 27#include "util/xmlconfig.h" 28#include "vk_util.h" 29 30#include <time.h> 31#include <unistd.h> 32#include <xf86drm.h> 33#include <stdlib.h> 34#include <stdio.h> 35 36VkResult 37wsi_device_init(struct wsi_device *wsi, 38 VkPhysicalDevice pdevice, 39 WSI_FN_GetPhysicalDeviceProcAddr proc_addr, 40 const VkAllocationCallbacks *alloc, 41 int display_fd, 42 const struct driOptionCache *dri_options) 43{ 44 const char *present_mode; 45 VkResult result; 46 47 memset(wsi, 0, sizeof(*wsi)); 48 49 wsi->instance_alloc = *alloc; 50 wsi->pdevice = pdevice; 51 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); 57#undef WSI_GET_CB 58 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, 64 }; 65 GetPhysicalDeviceProperties2(pdevice, &pdp2); 66 67 wsi->maxImageDimension2D = pdp2.properties.limits.maxImageDimension2D; 68 wsi->override_present_mode = VK_PRESENT_MODE_MAX_ENUM_KHR; 69 70 GetPhysicalDeviceMemoryProperties(pdevice, &wsi->memory_props); 71 GetPhysicalDeviceQueueFamilyProperties(pdevice, &wsi->queue_family_count, NULL); 72 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); 101#undef WSI_GET_CB 102 103#ifdef VK_USE_PLATFORM_XCB_KHR 104 result = wsi_x11_init_wsi(wsi, alloc, dri_options); 105 if (result != VK_SUCCESS) 106 goto fail; 107#endif 108 109#ifdef VK_USE_PLATFORM_WAYLAND_KHR 110 result = wsi_wl_init_wsi(wsi, alloc, pdevice); 111 if (result != VK_SUCCESS) 112 goto fail; 113#endif 114 115#ifdef VK_USE_PLATFORM_DISPLAY_KHR 116 result = wsi_display_init_wsi(wsi, alloc, display_fd); 117 if (result != VK_SUCCESS) 118 goto fail; 119#endif 120 121 present_mode = getenv("MESA_VK_WSI_PRESENT_MODE"); 122 if (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; 129 } else { 130 fprintf(stderr, "Invalid MESA_VK_WSI_PRESENT_MODE value!\n"); 131 } 132 } 133 134 if (dri_options) { 135 if (driCheckOption(dri_options, "adaptive_sync", DRI_BOOL)) 136 wsi->enable_adaptive_sync = driQueryOptionb(dri_options, 137 "adaptive_sync"); 138 } 139 140 return VK_SUCCESS; 141 142fail: 143 wsi_device_finish(wsi, alloc); 144 return result; 145} 146 147void 148wsi_device_finish(struct wsi_device *wsi, 149 const VkAllocationCallbacks *alloc) 150{ 151#ifdef VK_USE_PLATFORM_DISPLAY_KHR 152 wsi_display_finish_wsi(wsi, alloc); 153#endif 154#ifdef VK_USE_PLATFORM_WAYLAND_KHR 155 wsi_wl_finish_wsi(wsi, alloc); 156#endif 157#ifdef VK_USE_PLATFORM_XCB_KHR 158 wsi_x11_finish_wsi(wsi, alloc); 159#endif 160} 161 162bool 163wsi_device_matches_drm_fd(const struct wsi_device *wsi, int drm_fd) 164{ 165 drmDevicePtr fd_device; 166 int ret = drmGetDevice2(drm_fd, 0, &fd_device); 167 if (ret) 168 return false; 169 170 bool match = false; 171 switch (fd_device->bustype) { 172 case DRM_BUS_PCI: 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; 177 break; 178 179 default: 180 break; 181 } 182 183 drmFreeDevice(&fd_device); 184 185 return match; 186} 187 188VkResult 189wsi_swapchain_init(const struct wsi_device *wsi, 190 struct wsi_swapchain *chain, 191 VkDevice device, 192 const VkSwapchainCreateInfoKHR *pCreateInfo, 193 const VkAllocationCallbacks *pAllocator) 194{ 195 VkResult result; 196 197 memset(chain, 0, sizeof(*chain)); 198 199 chain->wsi = wsi; 200 chain->device = device; 201 chain->alloc = *pAllocator; 202 chain->use_prime_blit = false; 203 204 chain->cmd_pools = 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; 209 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, 213 .pNext = NULL, 214 .flags = 0, 215 .queueFamilyIndex = i, 216 }; 217 result = wsi->CreateCommandPool(device, &cmd_pool_info, &chain->alloc, 218 &chain->cmd_pools[i]); 219 if (result != VK_SUCCESS) 220 goto fail; 221 } 222 223 return VK_SUCCESS; 224 225fail: 226 wsi_swapchain_finish(chain); 227 return result; 228} 229 230static bool 231wsi_swapchain_is_present_mode_supported(struct wsi_device *wsi, 232 const VkSwapchainCreateInfoKHR *pCreateInfo, 233 VkPresentModeKHR mode) 234{ 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; 240 VkResult result; 241 242 result = iface->get_present_modes(surface, &present_mode_count, NULL); 243 if (result != VK_SUCCESS) 244 return supported; 245 246 present_modes = malloc(present_mode_count * sizeof(*present_modes)); 247 if (!present_modes) 248 return supported; 249 250 result = iface->get_present_modes(surface, &present_mode_count, 251 present_modes); 252 if (result != VK_SUCCESS) 253 goto fail; 254 255 for (uint32_t i = 0; i < present_mode_count; i++) { 256 if (present_modes[i] == mode) { 257 supported = true; 258 break; 259 } 260 } 261 262fail: 263 free(present_modes); 264 return supported; 265} 266 267enum VkPresentModeKHR 268wsi_swapchain_get_present_mode(struct wsi_device *wsi, 269 const VkSwapchainCreateInfoKHR *pCreateInfo) 270{ 271 if (wsi->override_present_mode == VK_PRESENT_MODE_MAX_ENUM_KHR) 272 return pCreateInfo->presentMode; 273 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; 278 } 279 280 return wsi->override_present_mode; 281} 282 283void 284wsi_swapchain_finish(struct wsi_swapchain *chain) 285{ 286 for (unsigned i = 0; i < ARRAY_SIZE(chain->fences); i++) 287 chain->wsi->DestroyFence(chain->device, chain->fences[i], &chain->alloc); 288 289 for (uint32_t i = 0; i < chain->wsi->queue_family_count; i++) { 290 chain->wsi->DestroyCommandPool(chain->device, chain->cmd_pools[i], 291 &chain->alloc); 292 } 293 vk_free(&chain->alloc, chain->cmd_pools); 294} 295 296static uint32_t 297select_memory_type(const struct wsi_device *wsi, 298 VkMemoryPropertyFlags props, 299 uint32_t type_bits) 300{ 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) 304 return i; 305 } 306 307 unreachable("No memory type found"); 308} 309 310static uint32_t 311vk_format_size(VkFormat format) 312{ 313 switch (format) { 314 case VK_FORMAT_B8G8R8A8_UNORM: 315 case VK_FORMAT_B8G8R8A8_SRGB: 316 return 4; 317 default: 318 unreachable("Unknown WSI Format"); 319 } 320} 321 322static inline uint32_t 323align_u32(uint32_t v, uint32_t a) 324{ 325 assert(a != 0 && a == (a & -a)); 326 return (v + a - 1) & ~(a - 1); 327} 328 329VkResult 330wsi_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) 336{ 337 const struct wsi_device *wsi = chain->wsi; 338 VkResult result; 339 340 memset(image, 0, sizeof(*image)); 341 for (int i = 0; i < ARRAY_SIZE(image->fds); i++) 342 image->fds[i] = -1; 343 344 struct wsi_image_create_info image_wsi_info = { 345 .sType = VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA, 346 .pNext = NULL, 347 }; 348 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; 355 } else { 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, 360 .pNext = NULL, 361 }; 362 VkFormatProperties2 format_props = { 363 .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2, 364 .pNext = &modifier_props_list, 365 }; 366 wsi->GetPhysicalDeviceFormatProperties2KHR(wsi->pdevice, 367 pCreateInfo->imageFormat, 368 &format_props); 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, 373 8, 374 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 375 if (!modifier_props) { 376 result = VK_ERROR_OUT_OF_HOST_MEMORY; 377 goto fail; 378 } 379 380 modifier_props_list.modifier_properties = modifier_props; 381 wsi->GetPhysicalDeviceFormatProperties2KHR(wsi->pdevice, 382 pCreateInfo->imageFormat, 383 &format_props); 384 modifier_prop_count = modifier_props_list.modifier_count; 385 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]); 389 390 image_modifiers = vk_alloc(&chain->alloc, 391 sizeof(*image_modifiers) * 392 max_modifier_count, 393 8, 394 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 395 if (!image_modifiers) { 396 result = VK_ERROR_OUT_OF_HOST_MEMORY; 397 goto fail; 398 } 399 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 403 * modifiers. 404 */ 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]; 409 } 410 } 411 412 /* We only want to take the modifiers from the first list */ 413 if (image_modifier_count > 0) 414 break; 415 } 416 417 if (image_modifier_count > 0) { 418 image_wsi_info.modifier_count = image_modifier_count; 419 image_wsi_info.modifiers = image_modifiers; 420 } else { 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; 425 goto fail; 426 } 427 } 428 429 const VkImageCreateInfo image_info = { 430 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, 431 .pNext = &image_wsi_info, 432 .flags = 0, 433 .imageType = VK_IMAGE_TYPE_2D, 434 .format = pCreateInfo->imageFormat, 435 .extent = { 436 .width = pCreateInfo->imageExtent.width, 437 .height = pCreateInfo->imageExtent.height, 438 .depth = 1, 439 }, 440 .mipLevels = 1, 441 .arrayLayers = 1, 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, 449 }; 450 result = wsi->CreateImage(chain->device, &image_info, 451 &chain->alloc, &image->image); 452 if (result != VK_SUCCESS) 453 goto fail; 454 455 VkMemoryRequirements reqs; 456 wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs); 457 458 const struct wsi_memory_allocate_info memory_wsi_info = { 459 .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA, 460 .pNext = NULL, 461 .implicit_sync = true, 462 }; 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, 467 }; 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, 473 }; 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), 480 }; 481 result = wsi->AllocateMemory(chain->device, &memory_info, 482 &chain->alloc, &image->memory); 483 if (result != VK_SUCCESS) 484 goto fail; 485 486 result = wsi->BindImageMemory(chain->device, image->image, 487 image->memory, 0); 488 if (result != VK_SUCCESS) 489 goto fail; 490 491 const VkMemoryGetFdInfoKHR memory_get_fd_info = { 492 .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR, 493 .pNext = NULL, 494 .memory = image->memory, 495 .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, 496 }; 497 int fd; 498 result = wsi->GetMemoryFdKHR(chain->device, &memory_get_fd_info, &fd); 499 if (result != VK_SUCCESS) 500 goto fail; 501 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); 505 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; 509 break; 510 } 511 } 512 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, 516 .mipLevel = 0, 517 .arrayLayer = 0, 518 }; 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; 525 if (p == 0) { 526 image->fds[p] = fd; 527 } else { 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]); 532 533 goto fail; 534 } 535 } 536 } 537 } else { 538 const VkImageSubresource image_subresource = { 539 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, 540 .mipLevel = 0, 541 .arrayLayer = 0, 542 }; 543 VkSubresourceLayout image_layout; 544 wsi->GetImageSubresourceLayout(chain->device, image->image, 545 &image_subresource, &image_layout); 546 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; 552 image->fds[0] = fd; 553 } 554 555 vk_free(&chain->alloc, modifier_props); 556 vk_free(&chain->alloc, image_modifiers); 557 558 return VK_SUCCESS; 559 560fail: 561 vk_free(&chain->alloc, modifier_props); 562 vk_free(&chain->alloc, image_modifiers); 563 wsi_destroy_image(chain, image); 564 565 return result; 566} 567 568#define WSI_PRIME_LINEAR_STRIDE_ALIGN 256 569 570VkResult 571wsi_create_prime_image(const struct wsi_swapchain *chain, 572 const VkSwapchainCreateInfoKHR *pCreateInfo, 573 bool use_modifier, 574 struct wsi_image *image) 575{ 576 const struct wsi_device *wsi = chain->wsi; 577 VkResult result; 578 579 memset(image, 0, sizeof(*image)); 580 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); 584 585 uint32_t linear_size = linear_stride * pCreateInfo->imageExtent.height; 586 linear_size = align_u32(linear_size, 4096); 587 588 const VkExternalMemoryBufferCreateInfo prime_buffer_external_info = { 589 .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO, 590 .pNext = NULL, 591 .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, 592 }; 593 const VkBufferCreateInfo prime_buffer_info = { 594 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 595 .pNext = &prime_buffer_external_info, 596 .size = linear_size, 597 .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT, 598 .sharingMode = VK_SHARING_MODE_EXCLUSIVE, 599 }; 600 result = wsi->CreateBuffer(chain->device, &prime_buffer_info, 601 &chain->alloc, &image->prime.buffer); 602 if (result != VK_SUCCESS) 603 goto fail; 604 605 VkMemoryRequirements reqs; 606 wsi->GetBufferMemoryRequirements(chain->device, image->prime.buffer, &reqs); 607 assert(reqs.size <= linear_size); 608 609 const struct wsi_memory_allocate_info memory_wsi_info = { 610 .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA, 611 .pNext = NULL, 612 .implicit_sync = true, 613 }; 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, 618 }; 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, 624 }; 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), 630 }; 631 result = wsi->AllocateMemory(chain->device, &prime_memory_info, 632 &chain->alloc, &image->prime.memory); 633 if (result != VK_SUCCESS) 634 goto fail; 635 636 result = wsi->BindBufferMemory(chain->device, image->prime.buffer, 637 image->prime.memory, 0); 638 if (result != VK_SUCCESS) 639 goto fail; 640 641 const VkImageCreateInfo image_info = { 642 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, 643 .pNext = NULL, 644 .flags = 0, 645 .imageType = VK_IMAGE_TYPE_2D, 646 .format = pCreateInfo->imageFormat, 647 .extent = { 648 .width = pCreateInfo->imageExtent.width, 649 .height = pCreateInfo->imageExtent.height, 650 .depth = 1, 651 }, 652 .mipLevels = 1, 653 .arrayLayers = 1, 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, 661 }; 662 result = wsi->CreateImage(chain->device, &image_info, 663 &chain->alloc, &image->image); 664 if (result != VK_SUCCESS) 665 goto fail; 666 667 wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs); 668 669 const VkMemoryDedicatedAllocateInfo memory_dedicated_info = { 670 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, 671 .pNext = NULL, 672 .image = image->image, 673 .buffer = VK_NULL_HANDLE, 674 }; 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), 681 }; 682 result = wsi->AllocateMemory(chain->device, &memory_info, 683 &chain->alloc, &image->memory); 684 if (result != VK_SUCCESS) 685 goto fail; 686 687 result = wsi->BindImageMemory(chain->device, image->image, 688 image->memory, 0); 689 if (result != VK_SUCCESS) 690 goto fail; 691 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; 698 goto fail; 699 } 700 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, 704 .pNext = NULL, 705 .commandPool = chain->cmd_pools[i], 706 .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, 707 .commandBufferCount = 1, 708 }; 709 result = wsi->AllocateCommandBuffers(chain->device, &cmd_buffer_info, 710 &image->prime.blit_cmd_buffers[i]); 711 if (result != VK_SUCCESS) 712 goto fail; 713 714 const VkCommandBufferBeginInfo begin_info = { 715 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 716 }; 717 wsi->BeginCommandBuffer(image->prime.blit_cmd_buffers[i], &begin_info); 718 719 struct VkBufferImageCopy buffer_image_copy = { 720 .bufferOffset = 0, 721 .bufferRowLength = linear_stride / cpp, 722 .bufferImageHeight = 0, 723 .imageSubresource = { 724 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, 725 .mipLevel = 0, 726 .baseArrayLayer = 0, 727 .layerCount = 1, 728 }, 729 .imageOffset = { .x = 0, .y = 0, .z = 0 }, 730 .imageExtent = { 731 .width = pCreateInfo->imageExtent.width, 732 .height = pCreateInfo->imageExtent.height, 733 .depth = 1, 734 }, 735 }; 736 wsi->CmdCopyImageToBuffer(image->prime.blit_cmd_buffers[i], 737 image->image, 738 VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, 739 image->prime.buffer, 740 1, &buffer_image_copy); 741 742 result = wsi->EndCommandBuffer(image->prime.blit_cmd_buffers[i]); 743 if (result != VK_SUCCESS) 744 goto fail; 745 } 746 747 const VkMemoryGetFdInfoKHR linear_memory_get_fd_info = { 748 .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR, 749 .pNext = NULL, 750 .memory = image->prime.memory, 751 .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, 752 }; 753 int fd; 754 result = wsi->GetMemoryFdKHR(chain->device, &linear_memory_get_fd_info, &fd); 755 if (result != VK_SUCCESS) 756 goto fail; 757 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; 763 image->fds[0] = fd; 764 765 return VK_SUCCESS; 766 767fail: 768 wsi_destroy_image(chain, image); 769 770 return result; 771} 772 773void 774wsi_destroy_image(const struct wsi_swapchain *chain, 775 struct wsi_image *image) 776{ 777 const struct wsi_device *wsi = chain->wsi; 778 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]); 783 } 784 vk_free(&chain->alloc, image->prime.blit_cmd_buffers); 785 } 786 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); 791} 792 793VkResult 794wsi_common_get_surface_support(struct wsi_device *wsi_device, 795 uint32_t queueFamilyIndex, 796 VkSurfaceKHR _surface, 797 VkBool32* pSupported) 798{ 799 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface); 800 struct wsi_interface *iface = wsi_device->wsi[surface->platform]; 801 802 return iface->get_support(surface, wsi_device, 803 queueFamilyIndex, pSupported); 804} 805 806VkResult 807wsi_common_get_surface_capabilities(struct wsi_device *wsi_device, 808 VkSurfaceKHR _surface, 809 VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) 810{ 811 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface); 812 struct wsi_interface *iface = wsi_device->wsi[surface->platform]; 813 814 VkSurfaceCapabilities2KHR caps2 = { 815 .sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR, 816 }; 817 818 VkResult result = iface->get_capabilities2(surface, wsi_device, NULL, &caps2); 819 820 if (result == VK_SUCCESS) 821 *pSurfaceCapabilities = caps2.surfaceCapabilities; 822 823 return result; 824} 825 826VkResult 827wsi_common_get_surface_capabilities2(struct wsi_device *wsi_device, 828 const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo, 829 VkSurfaceCapabilities2KHR *pSurfaceCapabilities) 830{ 831 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pSurfaceInfo->surface); 832 struct wsi_interface *iface = wsi_device->wsi[surface->platform]; 833 834 return iface->get_capabilities2(surface, wsi_device, pSurfaceInfo->pNext, 835 pSurfaceCapabilities); 836} 837 838VkResult 839wsi_common_get_surface_capabilities2ext( 840 struct wsi_device *wsi_device, 841 VkSurfaceKHR _surface, 842 VkSurfaceCapabilities2EXT *pSurfaceCapabilities) 843{ 844 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface); 845 struct wsi_interface *iface = wsi_device->wsi[surface->platform]; 846 847 assert(pSurfaceCapabilities->sType == 848 VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT); 849 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, 854 }; 855 856 VkSurfaceCapabilities2KHR caps2 = { 857 .sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR, 858 .pNext = &counters, 859 }; 860 861 VkResult result = iface->get_capabilities2(surface, wsi_device, NULL, &caps2); 862 863 if (result == VK_SUCCESS) { 864 VkSurfaceCapabilities2EXT *ext_caps = pSurfaceCapabilities; 865 VkSurfaceCapabilitiesKHR khr_caps = caps2.surfaceCapabilities; 866 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; 878 } 879 880 return result; 881} 882 883VkResult 884wsi_common_get_surface_formats(struct wsi_device *wsi_device, 885 VkSurfaceKHR _surface, 886 uint32_t *pSurfaceFormatCount, 887 VkSurfaceFormatKHR *pSurfaceFormats) 888{ 889 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface); 890 struct wsi_interface *iface = wsi_device->wsi[surface->platform]; 891 892 return iface->get_formats(surface, wsi_device, 893 pSurfaceFormatCount, pSurfaceFormats); 894} 895 896VkResult 897wsi_common_get_surface_formats2(struct wsi_device *wsi_device, 898 const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo, 899 uint32_t *pSurfaceFormatCount, 900 VkSurfaceFormat2KHR *pSurfaceFormats) 901{ 902 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pSurfaceInfo->surface); 903 struct wsi_interface *iface = wsi_device->wsi[surface->platform]; 904 905 return iface->get_formats2(surface, wsi_device, pSurfaceInfo->pNext, 906 pSurfaceFormatCount, pSurfaceFormats); 907} 908 909VkResult 910wsi_common_get_surface_present_modes(struct wsi_device *wsi_device, 911 VkSurfaceKHR _surface, 912 uint32_t *pPresentModeCount, 913 VkPresentModeKHR *pPresentModes) 914{ 915 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface); 916 struct wsi_interface *iface = wsi_device->wsi[surface->platform]; 917 918 return iface->get_present_modes(surface, pPresentModeCount, 919 pPresentModes); 920} 921 922VkResult 923wsi_common_get_present_rectangles(struct wsi_device *wsi_device, 924 VkSurfaceKHR _surface, 925 uint32_t* pRectCount, 926 VkRect2D* pRects) 927{ 928 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface); 929 struct wsi_interface *iface = wsi_device->wsi[surface->platform]; 930 931 return iface->get_present_rectangles(surface, wsi_device, 932 pRectCount, pRects); 933} 934 935VkResult 936wsi_common_create_swapchain(struct wsi_device *wsi, 937 VkDevice device, 938 const VkSwapchainCreateInfoKHR *pCreateInfo, 939 const VkAllocationCallbacks *pAllocator, 940 VkSwapchainKHR *pSwapchain) 941{ 942 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pCreateInfo->surface); 943 struct wsi_interface *iface = wsi->wsi[surface->platform]; 944 struct wsi_swapchain *swapchain; 945 946 VkResult result = iface->create_swapchain(surface, device, wsi, 947 pCreateInfo, pAllocator, 948 &swapchain); 949 if (result != VK_SUCCESS) 950 return result; 951 952 *pSwapchain = wsi_swapchain_to_handle(swapchain); 953 954 return VK_SUCCESS; 955} 956 957void 958wsi_common_destroy_swapchain(VkDevice device, 959 VkSwapchainKHR _swapchain, 960 const VkAllocationCallbacks *pAllocator) 961{ 962 WSI_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain); 963 if (!swapchain) 964 return; 965 966 swapchain->destroy(swapchain, pAllocator); 967} 968 969VkResult 970wsi_common_get_images(VkSwapchainKHR _swapchain, 971 uint32_t *pSwapchainImageCount, 972 VkImage *pSwapchainImages) 973{ 974 WSI_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain); 975 VK_OUTARRAY_MAKE(images, pSwapchainImages, pSwapchainImageCount); 976 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; 980 } 981 } 982 983 return vk_outarray_status(&images); 984} 985 986VkResult 987wsi_common_acquire_next_image2(const struct wsi_device *wsi, 988 VkDevice device, 989 const VkAcquireNextImageInfoKHR *pAcquireInfo, 990 uint32_t *pImageIndex) 991{ 992 WSI_FROM_HANDLE(wsi_swapchain, swapchain, pAcquireInfo->swapchain); 993 994 return swapchain->acquire_next_image(swapchain, pAcquireInfo, pImageIndex); 995} 996 997VkResult 998wsi_common_queue_present(const struct wsi_device *wsi, 999 VkDevice device, 1000 VkQueue queue, 1001 int queue_family_index, 1002 const VkPresentInfoKHR *pPresentInfo) 1003{ 1004 VkResult final_result = VK_SUCCESS; 1005 1006 const VkPresentRegionsKHR *regions = 1007 vk_find_struct_const(pPresentInfo->pNext, PRESENT_REGIONS_KHR); 1008 1009 for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) { 1010 WSI_FROM_HANDLE(wsi_swapchain, swapchain, pPresentInfo->pSwapchains[i]); 1011 VkResult result; 1012 1013 if (swapchain->fences[0] == VK_NULL_HANDLE) { 1014 const VkFenceCreateInfo fence_info = { 1015 .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, 1016 .pNext = NULL, 1017 .flags = 0, 1018 }; 1019 result = wsi->CreateFence(device, &fence_info, 1020 &swapchain->alloc, 1021 &swapchain->fences[0]); 1022 if (result != VK_SUCCESS) 1023 goto fail_present; 1024 } else { 1025 wsi->ResetFences(device, 1, &swapchain->fences[0]); 1026 } 1027 1028 VkSubmitInfo submit_info = { 1029 .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, 1030 .pNext = NULL, 1031 }; 1032 1033 VkPipelineStageFlags *stage_flags = NULL; 1034 if (i == 0) { 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. 1037 */ 1038 submit_info.waitSemaphoreCount = pPresentInfo->waitSemaphoreCount; 1039 submit_info.pWaitSemaphores = pPresentInfo->pWaitSemaphores; 1040 1041 /* Set up the pWaitDstStageMasks */ 1042 stage_flags = vk_alloc(&swapchain->alloc, 1043 sizeof(VkPipelineStageFlags) * 1044 pPresentInfo->waitSemaphoreCount, 1045 8, 1046 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 1047 if (!stage_flags) { 1048 result = VK_ERROR_OUT_OF_HOST_MEMORY; 1049 goto fail_present; 1050 } 1051 for (uint32_t s = 0; s < pPresentInfo->waitSemaphoreCount; s++) 1052 stage_flags[s] = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT; 1053 1054 submit_info.pWaitDstStageMask = stage_flags; 1055 } 1056 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. 1060 */ 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]; 1066 } 1067 1068 result = wsi->QueueSubmit(queue, 1, &submit_info, swapchain->fences[0]); 1069 vk_free(&swapchain->alloc, stage_flags); 1070 if (result != VK_SUCCESS) 1071 goto fail_present; 1072 1073 const VkPresentRegionKHR *region = NULL; 1074 if (regions && regions->pRegions) 1075 region = ®ions->pRegions[i]; 1076 1077 result = swapchain->queue_present(swapchain, 1078 pPresentInfo->pImageIndices[i], 1079 region); 1080 if (result != VK_SUCCESS) 1081 goto fail_present; 1082 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; 1087 1088 if (last != VK_NULL_HANDLE) { 1089 wsi->WaitForFences(device, 1, &last, true, 1); 1090 } 1091 1092 fail_present: 1093 if (pPresentInfo->pResults != NULL) 1094 pPresentInfo->pResults[i] = result; 1095 1096 /* Let the final result be our first unsuccessful result */ 1097 if (final_result == VK_SUCCESS) 1098 final_result = result; 1099 } 1100 1101 return final_result; 1102} 1103 1104uint64_t 1105wsi_common_get_current_time(void) 1106{ 1107 struct timespec current; 1108 clock_gettime(CLOCK_MONOTONIC, ¤t); 1109 return current.tv_nsec + current.tv_sec * 1000000000ull; 1110} 1111