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 "wsi_common_entrypoints.h" 26#include "util/macros.h" 27#include "util/os_file.h" 28#include "util/os_time.h" 29#include "util/xmlconfig.h" 30#include "vk_device.h" 31#include "vk_instance.h" 32#include "vk_physical_device.h" 33#include "vk_queue.h" 34#include "vk_util.h" 35 36#include <time.h> 37#include <stdlib.h> 38#include <stdio.h> 39 40VkResult 41wsi_device_init(struct wsi_device *wsi, 42 VkPhysicalDevice pdevice, 43 WSI_FN_GetPhysicalDeviceProcAddr proc_addr, 44 const VkAllocationCallbacks *alloc, 45 int display_fd, 46 const struct driOptionCache *dri_options, 47 bool sw_device) 48{ 49 const char *present_mode; 50 UNUSED VkResult result; 51 52 memset(wsi, 0, sizeof(*wsi)); 53 54 wsi->instance_alloc = *alloc; 55 wsi->pdevice = pdevice; 56 wsi->sw = sw_device; 57#define WSI_GET_CB(func) \ 58 PFN_vk##func func = (PFN_vk##func)proc_addr(pdevice, "vk" #func) 59 WSI_GET_CB(GetPhysicalDeviceProperties2); 60 WSI_GET_CB(GetPhysicalDeviceMemoryProperties); 61 WSI_GET_CB(GetPhysicalDeviceQueueFamilyProperties); 62#undef WSI_GET_CB 63 64 wsi->pci_bus_info.sType = 65 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT; 66 VkPhysicalDeviceProperties2 pdp2 = { 67 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, 68 .pNext = &wsi->pci_bus_info, 69 }; 70 GetPhysicalDeviceProperties2(pdevice, &pdp2); 71 72 wsi->maxImageDimension2D = pdp2.properties.limits.maxImageDimension2D; 73 wsi->override_present_mode = VK_PRESENT_MODE_MAX_ENUM_KHR; 74 75 GetPhysicalDeviceMemoryProperties(pdevice, &wsi->memory_props); 76 GetPhysicalDeviceQueueFamilyProperties(pdevice, &wsi->queue_family_count, NULL); 77 78#define WSI_GET_CB(func) \ 79 wsi->func = (PFN_vk##func)proc_addr(pdevice, "vk" #func) 80 WSI_GET_CB(AllocateMemory); 81 WSI_GET_CB(AllocateCommandBuffers); 82 WSI_GET_CB(BindBufferMemory); 83 WSI_GET_CB(BindImageMemory); 84 WSI_GET_CB(BeginCommandBuffer); 85 WSI_GET_CB(CmdCopyImageToBuffer); 86 WSI_GET_CB(CreateBuffer); 87 WSI_GET_CB(CreateCommandPool); 88 WSI_GET_CB(CreateFence); 89 WSI_GET_CB(CreateImage); 90 WSI_GET_CB(DestroyBuffer); 91 WSI_GET_CB(DestroyCommandPool); 92 WSI_GET_CB(DestroyFence); 93 WSI_GET_CB(DestroyImage); 94 WSI_GET_CB(EndCommandBuffer); 95 WSI_GET_CB(FreeMemory); 96 WSI_GET_CB(FreeCommandBuffers); 97 WSI_GET_CB(GetBufferMemoryRequirements); 98 WSI_GET_CB(GetImageDrmFormatModifierPropertiesEXT); 99 WSI_GET_CB(GetImageMemoryRequirements); 100 WSI_GET_CB(GetImageSubresourceLayout); 101 if (!wsi->sw) 102 WSI_GET_CB(GetMemoryFdKHR); 103 WSI_GET_CB(GetPhysicalDeviceFormatProperties); 104 WSI_GET_CB(GetPhysicalDeviceFormatProperties2KHR); 105 WSI_GET_CB(GetPhysicalDeviceImageFormatProperties2); 106 WSI_GET_CB(ResetFences); 107 WSI_GET_CB(QueueSubmit); 108 WSI_GET_CB(WaitForFences); 109 WSI_GET_CB(MapMemory); 110 WSI_GET_CB(UnmapMemory); 111#undef WSI_GET_CB 112 113#ifdef VK_USE_PLATFORM_XCB_KHR 114 result = wsi_x11_init_wsi(wsi, alloc, dri_options); 115 if (result != VK_SUCCESS) 116 goto fail; 117#endif 118 119#ifdef VK_USE_PLATFORM_WAYLAND_KHR 120 result = wsi_wl_init_wsi(wsi, alloc, pdevice); 121 if (result != VK_SUCCESS) 122 goto fail; 123#endif 124 125#ifdef VK_USE_PLATFORM_WIN32_KHR 126 result = wsi_win32_init_wsi(wsi, alloc, pdevice); 127 if (result != VK_SUCCESS) 128 goto fail; 129#endif 130 131#ifdef VK_USE_PLATFORM_DISPLAY_KHR 132 result = wsi_display_init_wsi(wsi, alloc, display_fd); 133 if (result != VK_SUCCESS) 134 goto fail; 135#endif 136 137 present_mode = getenv("MESA_VK_WSI_PRESENT_MODE"); 138 if (present_mode) { 139 if (!strcmp(present_mode, "fifo")) { 140 wsi->override_present_mode = VK_PRESENT_MODE_FIFO_KHR; 141 } else if (!strcmp(present_mode, "relaxed")) { 142 wsi->override_present_mode = VK_PRESENT_MODE_FIFO_RELAXED_KHR; 143 } else if (!strcmp(present_mode, "mailbox")) { 144 wsi->override_present_mode = VK_PRESENT_MODE_MAILBOX_KHR; 145 } else if (!strcmp(present_mode, "immediate")) { 146 wsi->override_present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR; 147 } else { 148 fprintf(stderr, "Invalid MESA_VK_WSI_PRESENT_MODE value!\n"); 149 } 150 } 151 152 if (dri_options) { 153 if (driCheckOption(dri_options, "adaptive_sync", DRI_BOOL)) 154 wsi->enable_adaptive_sync = driQueryOptionb(dri_options, 155 "adaptive_sync"); 156 157 if (driCheckOption(dri_options, "vk_wsi_force_bgra8_unorm_first", DRI_BOOL)) { 158 wsi->force_bgra8_unorm_first = 159 driQueryOptionb(dri_options, "vk_wsi_force_bgra8_unorm_first"); 160 } 161 } 162 163 return VK_SUCCESS; 164#if defined(VK_USE_PLATFORM_XCB_KHR) || \ 165 defined(VK_USE_PLATFORM_WAYLAND_KHR) || \ 166 defined(VK_USE_PLATFORM_WIN32_KHR) || \ 167 defined(VK_USE_PLATFORM_DISPLAY_KHR) 168fail: 169 wsi_device_finish(wsi, alloc); 170 return result; 171#endif 172} 173 174void 175wsi_device_finish(struct wsi_device *wsi, 176 const VkAllocationCallbacks *alloc) 177{ 178#ifdef VK_USE_PLATFORM_DISPLAY_KHR 179 wsi_display_finish_wsi(wsi, alloc); 180#endif 181#ifdef VK_USE_PLATFORM_WAYLAND_KHR 182 wsi_wl_finish_wsi(wsi, alloc); 183#endif 184#ifdef VK_USE_PLATFORM_WIN32_KHR 185 wsi_win32_finish_wsi(wsi, alloc); 186#endif 187#ifdef VK_USE_PLATFORM_XCB_KHR 188 wsi_x11_finish_wsi(wsi, alloc); 189#endif 190} 191 192VKAPI_ATTR void VKAPI_CALL 193wsi_DestroySurfaceKHR(VkInstance _instance, 194 VkSurfaceKHR _surface, 195 const VkAllocationCallbacks *pAllocator) 196{ 197 VK_FROM_HANDLE(vk_instance, instance, _instance); 198 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface); 199 200 if (!surface) 201 return; 202 203 vk_free2(&instance->alloc, pAllocator, surface); 204} 205 206VkResult 207wsi_swapchain_init(const struct wsi_device *wsi, 208 struct wsi_swapchain *chain, 209 VkDevice device, 210 const VkSwapchainCreateInfoKHR *pCreateInfo, 211 const VkAllocationCallbacks *pAllocator) 212{ 213 VkResult result; 214 215 memset(chain, 0, sizeof(*chain)); 216 217 vk_object_base_init(NULL, &chain->base, VK_OBJECT_TYPE_SWAPCHAIN_KHR); 218 219 chain->wsi = wsi; 220 chain->device = device; 221 chain->alloc = *pAllocator; 222 chain->use_prime_blit = false; 223 224 chain->cmd_pools = 225 vk_zalloc(pAllocator, sizeof(VkCommandPool) * wsi->queue_family_count, 8, 226 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 227 if (!chain->cmd_pools) 228 return VK_ERROR_OUT_OF_HOST_MEMORY; 229 230 for (uint32_t i = 0; i < wsi->queue_family_count; i++) { 231 const VkCommandPoolCreateInfo cmd_pool_info = { 232 .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, 233 .pNext = NULL, 234 .flags = 0, 235 .queueFamilyIndex = i, 236 }; 237 result = wsi->CreateCommandPool(device, &cmd_pool_info, &chain->alloc, 238 &chain->cmd_pools[i]); 239 if (result != VK_SUCCESS) 240 goto fail; 241 } 242 243 return VK_SUCCESS; 244 245fail: 246 wsi_swapchain_finish(chain); 247 return result; 248} 249 250static bool 251wsi_swapchain_is_present_mode_supported(struct wsi_device *wsi, 252 const VkSwapchainCreateInfoKHR *pCreateInfo, 253 VkPresentModeKHR mode) 254{ 255 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pCreateInfo->surface); 256 struct wsi_interface *iface = wsi->wsi[surface->platform]; 257 VkPresentModeKHR *present_modes; 258 uint32_t present_mode_count; 259 bool supported = false; 260 VkResult result; 261 262 result = iface->get_present_modes(surface, &present_mode_count, NULL); 263 if (result != VK_SUCCESS) 264 return supported; 265 266 present_modes = malloc(present_mode_count * sizeof(*present_modes)); 267 if (!present_modes) 268 return supported; 269 270 result = iface->get_present_modes(surface, &present_mode_count, 271 present_modes); 272 if (result != VK_SUCCESS) 273 goto fail; 274 275 for (uint32_t i = 0; i < present_mode_count; i++) { 276 if (present_modes[i] == mode) { 277 supported = true; 278 break; 279 } 280 } 281 282fail: 283 free(present_modes); 284 return supported; 285} 286 287enum VkPresentModeKHR 288wsi_swapchain_get_present_mode(struct wsi_device *wsi, 289 const VkSwapchainCreateInfoKHR *pCreateInfo) 290{ 291 if (wsi->override_present_mode == VK_PRESENT_MODE_MAX_ENUM_KHR) 292 return pCreateInfo->presentMode; 293 294 if (!wsi_swapchain_is_present_mode_supported(wsi, pCreateInfo, 295 wsi->override_present_mode)) { 296 fprintf(stderr, "Unsupported MESA_VK_WSI_PRESENT_MODE value!\n"); 297 return pCreateInfo->presentMode; 298 } 299 300 return wsi->override_present_mode; 301} 302 303void 304wsi_swapchain_finish(struct wsi_swapchain *chain) 305{ 306 if (chain->fences) { 307 for (unsigned i = 0; i < chain->image_count; i++) 308 chain->wsi->DestroyFence(chain->device, chain->fences[i], &chain->alloc); 309 310 vk_free(&chain->alloc, chain->fences); 311 } 312 313 for (uint32_t i = 0; i < chain->wsi->queue_family_count; i++) { 314 chain->wsi->DestroyCommandPool(chain->device, chain->cmd_pools[i], 315 &chain->alloc); 316 } 317 vk_free(&chain->alloc, chain->cmd_pools); 318 319 vk_object_base_finish(&chain->base); 320} 321 322void 323wsi_destroy_image(const struct wsi_swapchain *chain, 324 struct wsi_image *image) 325{ 326 const struct wsi_device *wsi = chain->wsi; 327 328 if (image->prime.blit_cmd_buffers) { 329 for (uint32_t i = 0; i < wsi->queue_family_count; i++) { 330 wsi->FreeCommandBuffers(chain->device, chain->cmd_pools[i], 331 1, &image->prime.blit_cmd_buffers[i]); 332 } 333 vk_free(&chain->alloc, image->prime.blit_cmd_buffers); 334 } 335 336 wsi->FreeMemory(chain->device, image->memory, &chain->alloc); 337 wsi->DestroyImage(chain->device, image->image, &chain->alloc); 338 wsi->FreeMemory(chain->device, image->prime.memory, &chain->alloc); 339 wsi->DestroyBuffer(chain->device, image->prime.buffer, &chain->alloc); 340} 341 342VKAPI_ATTR VkResult VKAPI_CALL 343wsi_GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice, 344 uint32_t queueFamilyIndex, 345 VkSurfaceKHR _surface, 346 VkBool32 *pSupported) 347{ 348 VK_FROM_HANDLE(vk_physical_device, device, physicalDevice); 349 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface); 350 struct wsi_device *wsi_device = device->wsi_device; 351 struct wsi_interface *iface = wsi_device->wsi[surface->platform]; 352 353 return iface->get_support(surface, wsi_device, 354 queueFamilyIndex, pSupported); 355} 356 357VKAPI_ATTR VkResult VKAPI_CALL 358wsi_GetPhysicalDeviceSurfaceCapabilitiesKHR( 359 VkPhysicalDevice physicalDevice, 360 VkSurfaceKHR _surface, 361 VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) 362{ 363 VK_FROM_HANDLE(vk_physical_device, device, physicalDevice); 364 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface); 365 struct wsi_device *wsi_device = device->wsi_device; 366 struct wsi_interface *iface = wsi_device->wsi[surface->platform]; 367 368 VkSurfaceCapabilities2KHR caps2 = { 369 .sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR, 370 }; 371 372 VkResult result = iface->get_capabilities2(surface, wsi_device, NULL, &caps2); 373 374 if (result == VK_SUCCESS) 375 *pSurfaceCapabilities = caps2.surfaceCapabilities; 376 377 return result; 378} 379 380VKAPI_ATTR VkResult VKAPI_CALL 381wsi_GetPhysicalDeviceSurfaceCapabilities2KHR( 382 VkPhysicalDevice physicalDevice, 383 const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo, 384 VkSurfaceCapabilities2KHR *pSurfaceCapabilities) 385{ 386 VK_FROM_HANDLE(vk_physical_device, device, physicalDevice); 387 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pSurfaceInfo->surface); 388 struct wsi_device *wsi_device = device->wsi_device; 389 struct wsi_interface *iface = wsi_device->wsi[surface->platform]; 390 391 return iface->get_capabilities2(surface, wsi_device, pSurfaceInfo->pNext, 392 pSurfaceCapabilities); 393} 394 395VKAPI_ATTR VkResult VKAPI_CALL 396wsi_GetPhysicalDeviceSurfaceCapabilities2EXT( 397 VkPhysicalDevice physicalDevice, 398 VkSurfaceKHR _surface, 399 VkSurfaceCapabilities2EXT *pSurfaceCapabilities) 400{ 401 VK_FROM_HANDLE(vk_physical_device, device, physicalDevice); 402 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface); 403 struct wsi_device *wsi_device = device->wsi_device; 404 struct wsi_interface *iface = wsi_device->wsi[surface->platform]; 405 406 assert(pSurfaceCapabilities->sType == 407 VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT); 408 409 struct wsi_surface_supported_counters counters = { 410 .sType = VK_STRUCTURE_TYPE_WSI_SURFACE_SUPPORTED_COUNTERS_MESA, 411 .pNext = pSurfaceCapabilities->pNext, 412 .supported_surface_counters = 0, 413 }; 414 415 VkSurfaceCapabilities2KHR caps2 = { 416 .sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR, 417 .pNext = &counters, 418 }; 419 420 VkResult result = iface->get_capabilities2(surface, wsi_device, NULL, &caps2); 421 422 if (result == VK_SUCCESS) { 423 VkSurfaceCapabilities2EXT *ext_caps = pSurfaceCapabilities; 424 VkSurfaceCapabilitiesKHR khr_caps = caps2.surfaceCapabilities; 425 426 ext_caps->minImageCount = khr_caps.minImageCount; 427 ext_caps->maxImageCount = khr_caps.maxImageCount; 428 ext_caps->currentExtent = khr_caps.currentExtent; 429 ext_caps->minImageExtent = khr_caps.minImageExtent; 430 ext_caps->maxImageExtent = khr_caps.maxImageExtent; 431 ext_caps->maxImageArrayLayers = khr_caps.maxImageArrayLayers; 432 ext_caps->supportedTransforms = khr_caps.supportedTransforms; 433 ext_caps->currentTransform = khr_caps.currentTransform; 434 ext_caps->supportedCompositeAlpha = khr_caps.supportedCompositeAlpha; 435 ext_caps->supportedUsageFlags = khr_caps.supportedUsageFlags; 436 ext_caps->supportedSurfaceCounters = counters.supported_surface_counters; 437 } 438 439 return result; 440} 441 442VKAPI_ATTR VkResult VKAPI_CALL 443wsi_GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice, 444 VkSurfaceKHR _surface, 445 uint32_t *pSurfaceFormatCount, 446 VkSurfaceFormatKHR *pSurfaceFormats) 447{ 448 VK_FROM_HANDLE(vk_physical_device, device, physicalDevice); 449 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface); 450 struct wsi_device *wsi_device = device->wsi_device; 451 struct wsi_interface *iface = wsi_device->wsi[surface->platform]; 452 453 return iface->get_formats(surface, wsi_device, 454 pSurfaceFormatCount, pSurfaceFormats); 455} 456 457VKAPI_ATTR VkResult VKAPI_CALL 458wsi_GetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice physicalDevice, 459 const VkPhysicalDeviceSurfaceInfo2KHR * pSurfaceInfo, 460 uint32_t *pSurfaceFormatCount, 461 VkSurfaceFormat2KHR *pSurfaceFormats) 462{ 463 VK_FROM_HANDLE(vk_physical_device, device, physicalDevice); 464 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pSurfaceInfo->surface); 465 struct wsi_device *wsi_device = device->wsi_device; 466 struct wsi_interface *iface = wsi_device->wsi[surface->platform]; 467 468 return iface->get_formats2(surface, wsi_device, pSurfaceInfo->pNext, 469 pSurfaceFormatCount, pSurfaceFormats); 470} 471 472VKAPI_ATTR VkResult VKAPI_CALL 473wsi_GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice, 474 VkSurfaceKHR _surface, 475 uint32_t *pPresentModeCount, 476 VkPresentModeKHR *pPresentModes) 477{ 478 VK_FROM_HANDLE(vk_physical_device, device, physicalDevice); 479 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface); 480 struct wsi_device *wsi_device = device->wsi_device; 481 struct wsi_interface *iface = wsi_device->wsi[surface->platform]; 482 483 return iface->get_present_modes(surface, pPresentModeCount, 484 pPresentModes); 485} 486 487VKAPI_ATTR VkResult VKAPI_CALL 488wsi_GetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice, 489 VkSurfaceKHR _surface, 490 uint32_t *pRectCount, 491 VkRect2D *pRects) 492{ 493 VK_FROM_HANDLE(vk_physical_device, device, physicalDevice); 494 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface); 495 struct wsi_device *wsi_device = device->wsi_device; 496 struct wsi_interface *iface = wsi_device->wsi[surface->platform]; 497 498 return iface->get_present_rectangles(surface, wsi_device, 499 pRectCount, pRects); 500} 501 502VKAPI_ATTR VkResult VKAPI_CALL 503wsi_CreateSwapchainKHR(VkDevice _device, 504 const VkSwapchainCreateInfoKHR *pCreateInfo, 505 const VkAllocationCallbacks *pAllocator, 506 VkSwapchainKHR *pSwapchain) 507{ 508 VK_FROM_HANDLE(vk_device, device, _device); 509 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pCreateInfo->surface); 510 struct wsi_device *wsi_device = device->physical->wsi_device; 511 struct wsi_interface *iface = wsi_device->wsi[surface->platform]; 512 const VkAllocationCallbacks *alloc; 513 struct wsi_swapchain *swapchain; 514 515 if (pAllocator) 516 alloc = pAllocator; 517 else 518 alloc = &device->alloc; 519 520 VkResult result = iface->create_swapchain(surface, _device, wsi_device, 521 pCreateInfo, alloc, 522 &swapchain); 523 if (result != VK_SUCCESS) 524 return result; 525 526 swapchain->fences = vk_zalloc(alloc, 527 sizeof (*swapchain->fences) * swapchain->image_count, 528 sizeof (*swapchain->fences), 529 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 530 if (!swapchain->fences) { 531 swapchain->destroy(swapchain, alloc); 532 return VK_ERROR_OUT_OF_HOST_MEMORY; 533 } 534 535 *pSwapchain = wsi_swapchain_to_handle(swapchain); 536 537 return VK_SUCCESS; 538} 539 540VKAPI_ATTR void VKAPI_CALL 541wsi_DestroySwapchainKHR(VkDevice _device, 542 VkSwapchainKHR _swapchain, 543 const VkAllocationCallbacks *pAllocator) 544{ 545 VK_FROM_HANDLE(vk_device, device, _device); 546 VK_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain); 547 const VkAllocationCallbacks *alloc; 548 549 if (!swapchain) 550 return; 551 552 if (pAllocator) 553 alloc = pAllocator; 554 else 555 alloc = &device->alloc; 556 557 swapchain->destroy(swapchain, alloc); 558} 559 560VkResult 561wsi_common_get_images(VkSwapchainKHR _swapchain, 562 uint32_t *pSwapchainImageCount, 563 VkImage *pSwapchainImages) 564{ 565 VK_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain); 566 VK_OUTARRAY_MAKE_TYPED(VkImage, images, pSwapchainImages, pSwapchainImageCount); 567 568 for (uint32_t i = 0; i < swapchain->image_count; i++) { 569 vk_outarray_append_typed(VkImage, &images, image) { 570 *image = swapchain->get_wsi_image(swapchain, i)->image; 571 } 572 } 573 574 return vk_outarray_status(&images); 575} 576 577VKAPI_ATTR VkResult VKAPI_CALL 578wsi_GetSwapchainImagesKHR(VkDevice device, 579 VkSwapchainKHR swapchain, 580 uint32_t *pSwapchainImageCount, 581 VkImage *pSwapchainImages) 582{ 583 return wsi_common_get_images(swapchain, 584 pSwapchainImageCount, 585 pSwapchainImages); 586} 587 588VKAPI_ATTR VkResult VKAPI_CALL 589wsi_AcquireNextImageKHR(VkDevice _device, 590 VkSwapchainKHR swapchain, 591 uint64_t timeout, 592 VkSemaphore semaphore, 593 VkFence fence, 594 uint32_t *pImageIndex) 595{ 596 VK_FROM_HANDLE(vk_device, device, _device); 597 598 const VkAcquireNextImageInfoKHR acquire_info = { 599 .sType = VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR, 600 .swapchain = swapchain, 601 .timeout = timeout, 602 .semaphore = semaphore, 603 .fence = fence, 604 .deviceMask = 0, 605 }; 606 607 return device->dispatch_table.AcquireNextImage2KHR(_device, &acquire_info, 608 pImageIndex); 609} 610 611VkResult 612wsi_common_acquire_next_image2(const struct wsi_device *wsi, 613 VkDevice device, 614 const VkAcquireNextImageInfoKHR *pAcquireInfo, 615 uint32_t *pImageIndex) 616{ 617 VK_FROM_HANDLE(wsi_swapchain, swapchain, pAcquireInfo->swapchain); 618 619 VkResult result = swapchain->acquire_next_image(swapchain, pAcquireInfo, 620 pImageIndex); 621 if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) 622 return result; 623 624 if (wsi->set_memory_ownership) { 625 VkDeviceMemory mem = swapchain->get_wsi_image(swapchain, *pImageIndex)->memory; 626 wsi->set_memory_ownership(swapchain->device, mem, true); 627 } 628 629 if (pAcquireInfo->semaphore != VK_NULL_HANDLE && 630 wsi->signal_semaphore_for_memory != NULL) { 631 struct wsi_image *image = 632 swapchain->get_wsi_image(swapchain, *pImageIndex); 633 wsi->signal_semaphore_for_memory(device, pAcquireInfo->semaphore, 634 image->memory); 635 } 636 637 if (pAcquireInfo->fence != VK_NULL_HANDLE && 638 wsi->signal_fence_for_memory != NULL) { 639 struct wsi_image *image = 640 swapchain->get_wsi_image(swapchain, *pImageIndex); 641 wsi->signal_fence_for_memory(device, pAcquireInfo->fence, 642 image->memory); 643 } 644 645 return result; 646} 647 648VKAPI_ATTR VkResult VKAPI_CALL 649wsi_AcquireNextImage2KHR(VkDevice _device, 650 const VkAcquireNextImageInfoKHR *pAcquireInfo, 651 uint32_t *pImageIndex) 652{ 653 VK_FROM_HANDLE(vk_device, device, _device); 654 655 return wsi_common_acquire_next_image2(device->physical->wsi_device, 656 _device, pAcquireInfo, pImageIndex); 657} 658 659VkResult 660wsi_common_queue_present(const struct wsi_device *wsi, 661 VkDevice device, 662 VkQueue queue, 663 int queue_family_index, 664 const VkPresentInfoKHR *pPresentInfo) 665{ 666 VkResult final_result = VK_SUCCESS; 667 668 const VkPresentRegionsKHR *regions = 669 vk_find_struct_const(pPresentInfo->pNext, PRESENT_REGIONS_KHR); 670 671 for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) { 672 VK_FROM_HANDLE(wsi_swapchain, swapchain, pPresentInfo->pSwapchains[i]); 673 uint32_t image_index = pPresentInfo->pImageIndices[i]; 674 VkResult result; 675 676 if (swapchain->fences[image_index] == VK_NULL_HANDLE) { 677 const VkFenceCreateInfo fence_info = { 678 .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, 679 .pNext = NULL, 680 .flags = 0, 681 }; 682 result = wsi->CreateFence(device, &fence_info, 683 &swapchain->alloc, 684 &swapchain->fences[image_index]); 685 if (result != VK_SUCCESS) 686 goto fail_present; 687 } else { 688 result = 689 wsi->WaitForFences(device, 1, &swapchain->fences[image_index], 690 true, ~0ull); 691 if (result != VK_SUCCESS) 692 goto fail_present; 693 694 result = 695 wsi->ResetFences(device, 1, &swapchain->fences[image_index]); 696 if (result != VK_SUCCESS) 697 goto fail_present; 698 } 699 700 struct wsi_image *image = 701 swapchain->get_wsi_image(swapchain, image_index); 702 703 struct wsi_memory_signal_submit_info mem_signal = { 704 .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_SIGNAL_SUBMIT_INFO_MESA, 705 .pNext = NULL, 706 .memory = image->memory, 707 }; 708 709 VkSubmitInfo submit_info = { 710 .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, 711 .pNext = &mem_signal, 712 }; 713 714 VkPipelineStageFlags *stage_flags = NULL; 715 if (i == 0) { 716 /* We only need/want to wait on semaphores once. After that, we're 717 * guaranteed ordering since it all happens on the same queue. 718 */ 719 submit_info.waitSemaphoreCount = pPresentInfo->waitSemaphoreCount; 720 submit_info.pWaitSemaphores = pPresentInfo->pWaitSemaphores; 721 722 /* Set up the pWaitDstStageMasks */ 723 stage_flags = vk_alloc(&swapchain->alloc, 724 sizeof(VkPipelineStageFlags) * 725 pPresentInfo->waitSemaphoreCount, 726 8, 727 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 728 if (!stage_flags) { 729 result = VK_ERROR_OUT_OF_HOST_MEMORY; 730 goto fail_present; 731 } 732 for (uint32_t s = 0; s < pPresentInfo->waitSemaphoreCount; s++) 733 stage_flags[s] = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT; 734 735 submit_info.pWaitDstStageMask = stage_flags; 736 } 737 738 if (swapchain->use_prime_blit) { 739 /* If we are using prime blits, we need to perform the blit now. The 740 * command buffer is attached to the image. 741 */ 742 submit_info.commandBufferCount = 1; 743 submit_info.pCommandBuffers = 744 &image->prime.blit_cmd_buffers[queue_family_index]; 745 mem_signal.memory = image->prime.memory; 746 } 747 748 result = wsi->QueueSubmit(queue, 1, &submit_info, swapchain->fences[image_index]); 749 vk_free(&swapchain->alloc, stage_flags); 750 if (result != VK_SUCCESS) 751 goto fail_present; 752 753 if (wsi->sw) 754 wsi->WaitForFences(device, 1, &swapchain->fences[image_index], 755 true, ~0ull); 756 757 const VkPresentRegionKHR *region = NULL; 758 if (regions && regions->pRegions) 759 region = ®ions->pRegions[i]; 760 761 result = swapchain->queue_present(swapchain, image_index, region); 762 if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) 763 goto fail_present; 764 765 if (wsi->set_memory_ownership) { 766 VkDeviceMemory mem = swapchain->get_wsi_image(swapchain, image_index)->memory; 767 wsi->set_memory_ownership(swapchain->device, mem, false); 768 } 769 770 fail_present: 771 if (pPresentInfo->pResults != NULL) 772 pPresentInfo->pResults[i] = result; 773 774 /* Let the final result be our first unsuccessful result */ 775 if (final_result == VK_SUCCESS) 776 final_result = result; 777 } 778 779 return final_result; 780} 781 782VKAPI_ATTR VkResult VKAPI_CALL 783wsi_QueuePresentKHR(VkQueue _queue, const VkPresentInfoKHR *pPresentInfo) 784{ 785 VK_FROM_HANDLE(vk_queue, queue, _queue); 786 787 return wsi_common_queue_present(queue->base.device->physical->wsi_device, 788 vk_device_to_handle(queue->base.device), 789 _queue, 790 queue->queue_family_index, 791 pPresentInfo); 792} 793 794uint64_t 795wsi_common_get_current_time(void) 796{ 797 return os_time_get_nano(); 798} 799 800VKAPI_ATTR VkResult VKAPI_CALL 801wsi_GetDeviceGroupPresentCapabilitiesKHR(VkDevice device, 802 VkDeviceGroupPresentCapabilitiesKHR *pCapabilities) 803{ 804 memset(pCapabilities->presentMask, 0, 805 sizeof(pCapabilities->presentMask)); 806 pCapabilities->presentMask[0] = 0x1; 807 pCapabilities->modes = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR; 808 809 return VK_SUCCESS; 810} 811 812VKAPI_ATTR VkResult VKAPI_CALL 813wsi_GetDeviceGroupSurfacePresentModesKHR(VkDevice device, 814 VkSurfaceKHR surface, 815 VkDeviceGroupPresentModeFlagsKHR *pModes) 816{ 817 *pModes = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR; 818 819 return VK_SUCCESS; 820} 821