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 "util/macros.h" 26 #include "vk_util.h" 27 28 VkResult 29 wsi_device_init(struct wsi_device *wsi, 30 VkPhysicalDevice pdevice, 31 WSI_FN_GetPhysicalDeviceProcAddr proc_addr, 32 const VkAllocationCallbacks *alloc) 33 { 34 VkResult result; 35 36 memset(wsi, 0, sizeof(*wsi)); 37 38 #define WSI_GET_CB(func) \ 39 PFN_vk##func func = (PFN_vk##func)proc_addr(pdevice, "vk" #func) 40 WSI_GET_CB(GetPhysicalDeviceMemoryProperties); 41 WSI_GET_CB(GetPhysicalDeviceQueueFamilyProperties); 42 #undef WSI_GET_CB 43 44 GetPhysicalDeviceMemoryProperties(pdevice, &wsi->memory_props); 45 GetPhysicalDeviceQueueFamilyProperties(pdevice, &wsi->queue_family_count, NULL); 46 47 #define WSI_GET_CB(func) \ 48 wsi->func = (PFN_vk##func)proc_addr(pdevice, "vk" #func) 49 WSI_GET_CB(AllocateMemory); 50 WSI_GET_CB(AllocateCommandBuffers); 51 WSI_GET_CB(BindBufferMemory); 52 WSI_GET_CB(BindImageMemory); 53 WSI_GET_CB(BeginCommandBuffer); 54 WSI_GET_CB(CmdCopyImageToBuffer); 55 WSI_GET_CB(CreateBuffer); 56 WSI_GET_CB(CreateCommandPool); 57 WSI_GET_CB(CreateFence); 58 WSI_GET_CB(CreateImage); 59 WSI_GET_CB(DestroyBuffer); 60 WSI_GET_CB(DestroyCommandPool); 61 WSI_GET_CB(DestroyFence); 62 WSI_GET_CB(DestroyImage); 63 WSI_GET_CB(EndCommandBuffer); 64 WSI_GET_CB(FreeMemory); 65 WSI_GET_CB(FreeCommandBuffers); 66 WSI_GET_CB(GetBufferMemoryRequirements); 67 WSI_GET_CB(GetImageMemoryRequirements); 68 WSI_GET_CB(GetImageSubresourceLayout); 69 WSI_GET_CB(GetMemoryFdKHR); 70 WSI_GET_CB(GetPhysicalDeviceFormatProperties); 71 WSI_GET_CB(ResetFences); 72 WSI_GET_CB(QueueSubmit); 73 WSI_GET_CB(WaitForFences); 74 #undef WSI_GET_CB 75 76 #ifdef VK_USE_PLATFORM_XCB_KHR 77 result = wsi_x11_init_wsi(wsi, alloc); 78 if (result != VK_SUCCESS) 79 return result; 80 #endif 81 82 #ifdef VK_USE_PLATFORM_WAYLAND_KHR 83 result = wsi_wl_init_wsi(wsi, alloc, pdevice); 84 if (result != VK_SUCCESS) { 85 #ifdef VK_USE_PLATFORM_XCB_KHR 86 wsi_x11_finish_wsi(wsi, alloc); 87 #endif 88 return result; 89 } 90 #endif 91 92 return VK_SUCCESS; 93 } 94 95 void 96 wsi_device_finish(struct wsi_device *wsi, 97 const VkAllocationCallbacks *alloc) 98 { 99 #ifdef VK_USE_PLATFORM_WAYLAND_KHR 100 wsi_wl_finish_wsi(wsi, alloc); 101 #endif 102 #ifdef VK_USE_PLATFORM_XCB_KHR 103 wsi_x11_finish_wsi(wsi, alloc); 104 #endif 105 } 106 107 VkResult 108 wsi_swapchain_init(const struct wsi_device *wsi, 109 struct wsi_swapchain *chain, 110 VkDevice device, 111 const VkSwapchainCreateInfoKHR *pCreateInfo, 112 const VkAllocationCallbacks *pAllocator) 113 { 114 VkResult result; 115 116 memset(chain, 0, sizeof(*chain)); 117 118 chain->wsi = wsi; 119 chain->device = device; 120 chain->alloc = *pAllocator; 121 chain->use_prime_blit = false; 122 123 chain->cmd_pools = 124 vk_zalloc(pAllocator, sizeof(VkCommandPool) * wsi->queue_family_count, 8, 125 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 126 if (!chain->cmd_pools) 127 return VK_ERROR_OUT_OF_HOST_MEMORY; 128 129 for (uint32_t i = 0; i < wsi->queue_family_count; i++) { 130 const VkCommandPoolCreateInfo cmd_pool_info = { 131 .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, 132 .pNext = NULL, 133 .flags = 0, 134 .queueFamilyIndex = i, 135 }; 136 result = wsi->CreateCommandPool(device, &cmd_pool_info, &chain->alloc, 137 &chain->cmd_pools[i]); 138 if (result != VK_SUCCESS) 139 goto fail; 140 } 141 142 return VK_SUCCESS; 143 144 fail: 145 wsi_swapchain_finish(chain); 146 return result; 147 } 148 149 void 150 wsi_swapchain_finish(struct wsi_swapchain *chain) 151 { 152 for (unsigned i = 0; i < ARRAY_SIZE(chain->fences); i++) 153 chain->wsi->DestroyFence(chain->device, chain->fences[i], &chain->alloc); 154 155 for (uint32_t i = 0; i < chain->wsi->queue_family_count; i++) { 156 chain->wsi->DestroyCommandPool(chain->device, chain->cmd_pools[i], 157 &chain->alloc); 158 } 159 vk_free(&chain->alloc, chain->cmd_pools); 160 } 161 162 static uint32_t 163 select_memory_type(const struct wsi_device *wsi, 164 VkMemoryPropertyFlags props, 165 uint32_t type_bits) 166 { 167 for (uint32_t i = 0; i < wsi->memory_props.memoryTypeCount; i++) { 168 const VkMemoryType type = wsi->memory_props.memoryTypes[i]; 169 if ((type_bits & (1 << i)) && (type.propertyFlags & props) == props) 170 return i; 171 } 172 173 unreachable("No memory type found"); 174 } 175 176 static uint32_t 177 vk_format_size(VkFormat format) 178 { 179 switch (format) { 180 case VK_FORMAT_B8G8R8A8_UNORM: 181 case VK_FORMAT_B8G8R8A8_SRGB: 182 return 4; 183 default: 184 unreachable("Unknown WSI Format"); 185 } 186 } 187 188 static inline uint32_t 189 align_u32(uint32_t v, uint32_t a) 190 { 191 assert(a != 0 && a == (a & -a)); 192 return (v + a - 1) & ~(a - 1); 193 } 194 195 VkResult 196 wsi_create_native_image(const struct wsi_swapchain *chain, 197 const VkSwapchainCreateInfoKHR *pCreateInfo, 198 struct wsi_image *image) 199 { 200 const struct wsi_device *wsi = chain->wsi; 201 VkResult result; 202 203 memset(image, 0, sizeof(*image)); 204 205 const struct wsi_image_create_info image_wsi_info = { 206 .sType = VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA, 207 .pNext = NULL, 208 .scanout = true, 209 }; 210 const VkImageCreateInfo image_info = { 211 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, 212 .pNext = &image_wsi_info, 213 .flags = 0, 214 .imageType = VK_IMAGE_TYPE_2D, 215 .format = pCreateInfo->imageFormat, 216 .extent = { 217 .width = pCreateInfo->imageExtent.width, 218 .height = pCreateInfo->imageExtent.height, 219 .depth = 1, 220 }, 221 .mipLevels = 1, 222 .arrayLayers = 1, 223 .samples = VK_SAMPLE_COUNT_1_BIT, 224 .tiling = VK_IMAGE_TILING_OPTIMAL, 225 .usage = pCreateInfo->imageUsage, 226 .sharingMode = pCreateInfo->imageSharingMode, 227 .queueFamilyIndexCount = pCreateInfo->queueFamilyIndexCount, 228 .pQueueFamilyIndices = pCreateInfo->pQueueFamilyIndices, 229 .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, 230 }; 231 result = wsi->CreateImage(chain->device, &image_info, 232 &chain->alloc, &image->image); 233 if (result != VK_SUCCESS) 234 goto fail; 235 236 VkMemoryRequirements reqs; 237 wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs); 238 239 VkSubresourceLayout image_layout; 240 const VkImageSubresource image_subresource = { 241 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, 242 .mipLevel = 0, 243 .arrayLayer = 0, 244 }; 245 wsi->GetImageSubresourceLayout(chain->device, image->image, 246 &image_subresource, &image_layout); 247 248 const struct wsi_memory_allocate_info memory_wsi_info = { 249 .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA, 250 .pNext = NULL, 251 .implicit_sync = true, 252 }; 253 const VkExportMemoryAllocateInfoKHR memory_export_info = { 254 .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR, 255 .pNext = &memory_wsi_info, 256 .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, 257 }; 258 const VkMemoryDedicatedAllocateInfoKHR memory_dedicated_info = { 259 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR, 260 .pNext = &memory_export_info, 261 .image = image->image, 262 .buffer = VK_NULL_HANDLE, 263 }; 264 const VkMemoryAllocateInfo memory_info = { 265 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 266 .pNext = &memory_dedicated_info, 267 .allocationSize = reqs.size, 268 .memoryTypeIndex = select_memory_type(wsi, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 269 reqs.memoryTypeBits), 270 }; 271 result = wsi->AllocateMemory(chain->device, &memory_info, 272 &chain->alloc, &image->memory); 273 if (result != VK_SUCCESS) 274 goto fail; 275 276 result = wsi->BindImageMemory(chain->device, image->image, 277 image->memory, 0); 278 if (result != VK_SUCCESS) 279 goto fail; 280 281 const VkMemoryGetFdInfoKHR memory_get_fd_info = { 282 .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR, 283 .pNext = NULL, 284 .memory = image->memory, 285 .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, 286 }; 287 int fd; 288 result = wsi->GetMemoryFdKHR(chain->device, &memory_get_fd_info, &fd); 289 if (result != VK_SUCCESS) 290 goto fail; 291 292 image->size = reqs.size; 293 image->row_pitch = image_layout.rowPitch; 294 image->offset = 0; 295 image->fd = fd; 296 297 return VK_SUCCESS; 298 299 fail: 300 wsi_destroy_image(chain, image); 301 302 return result; 303 } 304 305 #define WSI_PRIME_LINEAR_STRIDE_ALIGN 256 306 307 VkResult 308 wsi_create_prime_image(const struct wsi_swapchain *chain, 309 const VkSwapchainCreateInfoKHR *pCreateInfo, 310 struct wsi_image *image) 311 { 312 const struct wsi_device *wsi = chain->wsi; 313 VkResult result; 314 315 memset(image, 0, sizeof(*image)); 316 317 const uint32_t cpp = vk_format_size(pCreateInfo->imageFormat); 318 const uint32_t linear_stride = align_u32(pCreateInfo->imageExtent.width * cpp, 319 WSI_PRIME_LINEAR_STRIDE_ALIGN); 320 321 uint32_t linear_size = linear_stride * pCreateInfo->imageExtent.height; 322 linear_size = align_u32(linear_size, 4096); 323 324 const VkExternalMemoryBufferCreateInfoKHR prime_buffer_external_info = { 325 .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR, 326 .pNext = NULL, 327 .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, 328 }; 329 const VkBufferCreateInfo prime_buffer_info = { 330 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 331 .pNext = &prime_buffer_external_info, 332 .size = linear_size, 333 .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT, 334 .sharingMode = VK_SHARING_MODE_EXCLUSIVE, 335 }; 336 result = wsi->CreateBuffer(chain->device, &prime_buffer_info, 337 &chain->alloc, &image->prime.buffer); 338 if (result != VK_SUCCESS) 339 goto fail; 340 341 VkMemoryRequirements reqs; 342 wsi->GetBufferMemoryRequirements(chain->device, image->prime.buffer, &reqs); 343 assert(reqs.size <= linear_size); 344 345 const struct wsi_memory_allocate_info memory_wsi_info = { 346 .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA, 347 .pNext = NULL, 348 .implicit_sync = true, 349 }; 350 const VkExportMemoryAllocateInfoKHR prime_memory_export_info = { 351 .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR, 352 .pNext = &memory_wsi_info, 353 .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, 354 }; 355 const VkMemoryDedicatedAllocateInfoKHR prime_memory_dedicated_info = { 356 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR, 357 .pNext = &prime_memory_export_info, 358 .image = VK_NULL_HANDLE, 359 .buffer = image->prime.buffer, 360 }; 361 const VkMemoryAllocateInfo prime_memory_info = { 362 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 363 .pNext = &prime_memory_dedicated_info, 364 .allocationSize = linear_size, 365 .memoryTypeIndex = select_memory_type(wsi, 0, reqs.memoryTypeBits), 366 }; 367 result = wsi->AllocateMemory(chain->device, &prime_memory_info, 368 &chain->alloc, &image->prime.memory); 369 if (result != VK_SUCCESS) 370 goto fail; 371 372 result = wsi->BindBufferMemory(chain->device, image->prime.buffer, 373 image->prime.memory, 0); 374 if (result != VK_SUCCESS) 375 goto fail; 376 377 const VkImageCreateInfo image_info = { 378 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, 379 .pNext = NULL, 380 .flags = 0, 381 .imageType = VK_IMAGE_TYPE_2D, 382 .format = pCreateInfo->imageFormat, 383 .extent = { 384 .width = pCreateInfo->imageExtent.width, 385 .height = pCreateInfo->imageExtent.height, 386 .depth = 1, 387 }, 388 .mipLevels = 1, 389 .arrayLayers = 1, 390 .samples = VK_SAMPLE_COUNT_1_BIT, 391 .tiling = VK_IMAGE_TILING_OPTIMAL, 392 .usage = pCreateInfo->imageUsage | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 393 .sharingMode = pCreateInfo->imageSharingMode, 394 .queueFamilyIndexCount = pCreateInfo->queueFamilyIndexCount, 395 .pQueueFamilyIndices = pCreateInfo->pQueueFamilyIndices, 396 .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, 397 }; 398 result = wsi->CreateImage(chain->device, &image_info, 399 &chain->alloc, &image->image); 400 if (result != VK_SUCCESS) 401 goto fail; 402 403 wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs); 404 405 const VkMemoryDedicatedAllocateInfoKHR memory_dedicated_info = { 406 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR, 407 .pNext = NULL, 408 .image = image->image, 409 .buffer = VK_NULL_HANDLE, 410 }; 411 const VkMemoryAllocateInfo memory_info = { 412 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 413 .pNext = &memory_dedicated_info, 414 .allocationSize = reqs.size, 415 .memoryTypeIndex = select_memory_type(wsi, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 416 reqs.memoryTypeBits), 417 }; 418 result = wsi->AllocateMemory(chain->device, &memory_info, 419 &chain->alloc, &image->memory); 420 if (result != VK_SUCCESS) 421 goto fail; 422 423 result = wsi->BindImageMemory(chain->device, image->image, 424 image->memory, 0); 425 if (result != VK_SUCCESS) 426 goto fail; 427 428 image->prime.blit_cmd_buffers = 429 vk_zalloc(&chain->alloc, 430 sizeof(VkCommandBuffer) * wsi->queue_family_count, 8, 431 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 432 if (!image->prime.blit_cmd_buffers) { 433 result = VK_ERROR_OUT_OF_HOST_MEMORY; 434 goto fail; 435 } 436 437 for (uint32_t i = 0; i < wsi->queue_family_count; i++) { 438 const VkCommandBufferAllocateInfo cmd_buffer_info = { 439 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, 440 .pNext = NULL, 441 .commandPool = chain->cmd_pools[i], 442 .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, 443 .commandBufferCount = 1, 444 }; 445 result = wsi->AllocateCommandBuffers(chain->device, &cmd_buffer_info, 446 &image->prime.blit_cmd_buffers[i]); 447 if (result != VK_SUCCESS) 448 goto fail; 449 450 const VkCommandBufferBeginInfo begin_info = { 451 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 452 }; 453 wsi->BeginCommandBuffer(image->prime.blit_cmd_buffers[i], &begin_info); 454 455 struct VkBufferImageCopy buffer_image_copy = { 456 .bufferOffset = 0, 457 .bufferRowLength = linear_stride / cpp, 458 .bufferImageHeight = 0, 459 .imageSubresource = { 460 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, 461 .mipLevel = 0, 462 .baseArrayLayer = 0, 463 .layerCount = 1, 464 }, 465 .imageOffset = { .x = 0, .y = 0, .z = 0 }, 466 .imageExtent = { 467 .width = pCreateInfo->imageExtent.width, 468 .height = pCreateInfo->imageExtent.height, 469 .depth = 1, 470 }, 471 }; 472 wsi->CmdCopyImageToBuffer(image->prime.blit_cmd_buffers[i], 473 image->image, 474 VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, 475 image->prime.buffer, 476 1, &buffer_image_copy); 477 478 result = wsi->EndCommandBuffer(image->prime.blit_cmd_buffers[i]); 479 if (result != VK_SUCCESS) 480 goto fail; 481 } 482 483 const VkMemoryGetFdInfoKHR linear_memory_get_fd_info = { 484 .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR, 485 .pNext = NULL, 486 .memory = image->prime.memory, 487 .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, 488 }; 489 int fd; 490 result = wsi->GetMemoryFdKHR(chain->device, &linear_memory_get_fd_info, &fd); 491 if (result != VK_SUCCESS) 492 goto fail; 493 494 image->size = linear_size; 495 image->row_pitch = linear_stride; 496 image->offset = 0; 497 image->fd = fd; 498 499 return VK_SUCCESS; 500 501 fail: 502 wsi_destroy_image(chain, image); 503 504 return result; 505 } 506 507 void 508 wsi_destroy_image(const struct wsi_swapchain *chain, 509 struct wsi_image *image) 510 { 511 const struct wsi_device *wsi = chain->wsi; 512 513 if (image->prime.blit_cmd_buffers) { 514 for (uint32_t i = 0; i < wsi->queue_family_count; i++) { 515 wsi->FreeCommandBuffers(chain->device, chain->cmd_pools[i], 516 1, &image->prime.blit_cmd_buffers[i]); 517 } 518 vk_free(&chain->alloc, image->prime.blit_cmd_buffers); 519 } 520 521 wsi->FreeMemory(chain->device, image->memory, &chain->alloc); 522 wsi->DestroyImage(chain->device, image->image, &chain->alloc); 523 wsi->FreeMemory(chain->device, image->prime.memory, &chain->alloc); 524 wsi->DestroyBuffer(chain->device, image->prime.buffer, &chain->alloc); 525 } 526 527 VkResult 528 wsi_common_get_surface_support(struct wsi_device *wsi_device, 529 int local_fd, 530 uint32_t queueFamilyIndex, 531 VkSurfaceKHR _surface, 532 const VkAllocationCallbacks *alloc, 533 VkBool32* pSupported) 534 { 535 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface); 536 struct wsi_interface *iface = wsi_device->wsi[surface->platform]; 537 538 return iface->get_support(surface, wsi_device, alloc, 539 queueFamilyIndex, local_fd, pSupported); 540 } 541 542 VkResult 543 wsi_common_get_surface_capabilities(struct wsi_device *wsi_device, 544 VkSurfaceKHR _surface, 545 VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) 546 { 547 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface); 548 struct wsi_interface *iface = wsi_device->wsi[surface->platform]; 549 550 return iface->get_capabilities(surface, pSurfaceCapabilities); 551 } 552 553 VkResult 554 wsi_common_get_surface_capabilities2(struct wsi_device *wsi_device, 555 const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo, 556 VkSurfaceCapabilities2KHR *pSurfaceCapabilities) 557 { 558 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pSurfaceInfo->surface); 559 struct wsi_interface *iface = wsi_device->wsi[surface->platform]; 560 561 return iface->get_capabilities2(surface, pSurfaceInfo->pNext, 562 pSurfaceCapabilities); 563 } 564 565 VkResult 566 wsi_common_get_surface_formats(struct wsi_device *wsi_device, 567 VkSurfaceKHR _surface, 568 uint32_t *pSurfaceFormatCount, 569 VkSurfaceFormatKHR *pSurfaceFormats) 570 { 571 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface); 572 struct wsi_interface *iface = wsi_device->wsi[surface->platform]; 573 574 return iface->get_formats(surface, wsi_device, 575 pSurfaceFormatCount, pSurfaceFormats); 576 } 577 578 VkResult 579 wsi_common_get_surface_formats2(struct wsi_device *wsi_device, 580 const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo, 581 uint32_t *pSurfaceFormatCount, 582 VkSurfaceFormat2KHR *pSurfaceFormats) 583 { 584 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pSurfaceInfo->surface); 585 struct wsi_interface *iface = wsi_device->wsi[surface->platform]; 586 587 return iface->get_formats2(surface, wsi_device, pSurfaceInfo->pNext, 588 pSurfaceFormatCount, pSurfaceFormats); 589 } 590 591 VkResult 592 wsi_common_get_surface_present_modes(struct wsi_device *wsi_device, 593 VkSurfaceKHR _surface, 594 uint32_t *pPresentModeCount, 595 VkPresentModeKHR *pPresentModes) 596 { 597 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface); 598 struct wsi_interface *iface = wsi_device->wsi[surface->platform]; 599 600 return iface->get_present_modes(surface, pPresentModeCount, 601 pPresentModes); 602 } 603 604 VkResult 605 wsi_common_create_swapchain(struct wsi_device *wsi, 606 VkDevice device, 607 int fd, 608 const VkSwapchainCreateInfoKHR *pCreateInfo, 609 const VkAllocationCallbacks *pAllocator, 610 VkSwapchainKHR *pSwapchain) 611 { 612 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pCreateInfo->surface); 613 struct wsi_interface *iface = wsi->wsi[surface->platform]; 614 struct wsi_swapchain *swapchain; 615 616 VkResult result = iface->create_swapchain(surface, device, wsi, fd, 617 pCreateInfo, pAllocator, 618 &swapchain); 619 if (result != VK_SUCCESS) 620 return result; 621 622 *pSwapchain = wsi_swapchain_to_handle(swapchain); 623 624 return VK_SUCCESS; 625 } 626 627 void 628 wsi_common_destroy_swapchain(VkDevice device, 629 VkSwapchainKHR _swapchain, 630 const VkAllocationCallbacks *pAllocator) 631 { 632 WSI_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain); 633 if (!swapchain) 634 return; 635 636 swapchain->destroy(swapchain, pAllocator); 637 } 638 639 VkResult 640 wsi_common_get_images(VkSwapchainKHR _swapchain, 641 uint32_t *pSwapchainImageCount, 642 VkImage *pSwapchainImages) 643 { 644 WSI_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain); 645 VK_OUTARRAY_MAKE(images, pSwapchainImages, pSwapchainImageCount); 646 647 for (uint32_t i = 0; i < swapchain->image_count; i++) { 648 vk_outarray_append(&images, image) { 649 *image = swapchain->get_wsi_image(swapchain, i)->image; 650 } 651 } 652 653 return vk_outarray_status(&images); 654 } 655 656 VkResult 657 wsi_common_acquire_next_image(const struct wsi_device *wsi, 658 VkDevice device, 659 VkSwapchainKHR _swapchain, 660 uint64_t timeout, 661 VkSemaphore semaphore, 662 uint32_t *pImageIndex) 663 { 664 WSI_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain); 665 666 return swapchain->acquire_next_image(swapchain, timeout, 667 semaphore, pImageIndex); 668 } 669 670 VkResult 671 wsi_common_queue_present(const struct wsi_device *wsi, 672 VkDevice device, 673 VkQueue queue, 674 int queue_family_index, 675 const VkPresentInfoKHR *pPresentInfo) 676 { 677 VkResult final_result = VK_SUCCESS; 678 679 const VkPresentRegionsKHR *regions = 680 vk_find_struct_const(pPresentInfo->pNext, PRESENT_REGIONS_KHR); 681 682 for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) { 683 WSI_FROM_HANDLE(wsi_swapchain, swapchain, pPresentInfo->pSwapchains[i]); 684 VkResult result; 685 686 if (swapchain->fences[0] == VK_NULL_HANDLE) { 687 const VkFenceCreateInfo fence_info = { 688 .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, 689 .pNext = NULL, 690 .flags = 0, 691 }; 692 result = wsi->CreateFence(device, &fence_info, 693 &swapchain->alloc, 694 &swapchain->fences[0]); 695 if (result != VK_SUCCESS) 696 goto fail_present; 697 } else { 698 wsi->ResetFences(device, 1, &swapchain->fences[0]); 699 } 700 701 VkSubmitInfo submit_info = { 702 .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, 703 .pNext = NULL, 704 }; 705 706 VkPipelineStageFlags *stage_flags = NULL; 707 if (i == 0) { 708 /* We only need/want to wait on semaphores once. After that, we're 709 * guaranteed ordering since it all happens on the same queue. 710 */ 711 submit_info.waitSemaphoreCount = pPresentInfo->waitSemaphoreCount, 712 submit_info.pWaitSemaphores = pPresentInfo->pWaitSemaphores, 713 714 /* Set up the pWaitDstStageMasks */ 715 stage_flags = vk_alloc(&swapchain->alloc, 716 sizeof(VkPipelineStageFlags) * 717 pPresentInfo->waitSemaphoreCount, 718 8, 719 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 720 if (!stage_flags) { 721 result = VK_ERROR_OUT_OF_HOST_MEMORY; 722 goto fail_present; 723 } 724 for (uint32_t s = 0; s < pPresentInfo->waitSemaphoreCount; s++) 725 stage_flags[s] = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT; 726 727 submit_info.pWaitDstStageMask = stage_flags; 728 } 729 730 if (swapchain->use_prime_blit) { 731 /* If we are using prime blits, we need to perform the blit now. The 732 * command buffer is attached to the image. 733 */ 734 struct wsi_image *image = 735 swapchain->get_wsi_image(swapchain, pPresentInfo->pImageIndices[i]); 736 submit_info.commandBufferCount = 1; 737 submit_info.pCommandBuffers = 738 &image->prime.blit_cmd_buffers[queue_family_index]; 739 } 740 741 result = wsi->QueueSubmit(queue, 1, &submit_info, swapchain->fences[0]); 742 vk_free(&swapchain->alloc, stage_flags); 743 if (result != VK_SUCCESS) 744 goto fail_present; 745 746 const VkPresentRegionKHR *region = NULL; 747 if (regions && regions->pRegions) 748 region = ®ions->pRegions[i]; 749 750 result = swapchain->queue_present(swapchain, 751 pPresentInfo->pImageIndices[i], 752 region); 753 if (result != VK_SUCCESS) 754 goto fail_present; 755 756 VkFence last = swapchain->fences[2]; 757 swapchain->fences[2] = swapchain->fences[1]; 758 swapchain->fences[1] = swapchain->fences[0]; 759 swapchain->fences[0] = last; 760 761 if (last != VK_NULL_HANDLE) { 762 wsi->WaitForFences(device, 1, &last, true, 1); 763 } 764 765 fail_present: 766 if (pPresentInfo->pResults != NULL) 767 pPresentInfo->pResults[i] = result; 768 769 /* Let the final result be our first unsuccessful result */ 770 if (final_result == VK_SUCCESS) 771 final_result = result; 772 } 773 774 return final_result; 775 } 776