Path: blob/21.2-virgl/src/vulkan/wsi/wsi_common.c
7354 views
/*1* Copyright © 2017 Intel Corporation2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS20* IN THE SOFTWARE.21*/2223#include "wsi_common_private.h"24#include "util/macros.h"25#include "util/os_file.h"26#include "util/os_time.h"27#include "util/xmlconfig.h"28#include "vk_util.h"2930#include <time.h>31#include <stdlib.h>32#include <stdio.h>3334VkResult35wsi_device_init(struct wsi_device *wsi,36VkPhysicalDevice pdevice,37WSI_FN_GetPhysicalDeviceProcAddr proc_addr,38const VkAllocationCallbacks *alloc,39int display_fd,40const struct driOptionCache *dri_options,41bool sw_device)42{43const char *present_mode;44UNUSED VkResult result;4546memset(wsi, 0, sizeof(*wsi));4748wsi->instance_alloc = *alloc;49wsi->pdevice = pdevice;50wsi->sw = sw_device;51#define WSI_GET_CB(func) \52PFN_vk##func func = (PFN_vk##func)proc_addr(pdevice, "vk" #func)53WSI_GET_CB(GetPhysicalDeviceProperties2);54WSI_GET_CB(GetPhysicalDeviceMemoryProperties);55WSI_GET_CB(GetPhysicalDeviceQueueFamilyProperties);56#undef WSI_GET_CB5758wsi->pci_bus_info.sType =59VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT;60VkPhysicalDeviceProperties2 pdp2 = {61.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,62.pNext = &wsi->pci_bus_info,63};64GetPhysicalDeviceProperties2(pdevice, &pdp2);6566wsi->maxImageDimension2D = pdp2.properties.limits.maxImageDimension2D;67wsi->override_present_mode = VK_PRESENT_MODE_MAX_ENUM_KHR;6869GetPhysicalDeviceMemoryProperties(pdevice, &wsi->memory_props);70GetPhysicalDeviceQueueFamilyProperties(pdevice, &wsi->queue_family_count, NULL);7172#define WSI_GET_CB(func) \73wsi->func = (PFN_vk##func)proc_addr(pdevice, "vk" #func)74WSI_GET_CB(AllocateMemory);75WSI_GET_CB(AllocateCommandBuffers);76WSI_GET_CB(BindBufferMemory);77WSI_GET_CB(BindImageMemory);78WSI_GET_CB(BeginCommandBuffer);79WSI_GET_CB(CmdCopyImageToBuffer);80WSI_GET_CB(CreateBuffer);81WSI_GET_CB(CreateCommandPool);82WSI_GET_CB(CreateFence);83WSI_GET_CB(CreateImage);84WSI_GET_CB(DestroyBuffer);85WSI_GET_CB(DestroyCommandPool);86WSI_GET_CB(DestroyFence);87WSI_GET_CB(DestroyImage);88WSI_GET_CB(EndCommandBuffer);89WSI_GET_CB(FreeMemory);90WSI_GET_CB(FreeCommandBuffers);91WSI_GET_CB(GetBufferMemoryRequirements);92WSI_GET_CB(GetImageDrmFormatModifierPropertiesEXT);93WSI_GET_CB(GetImageMemoryRequirements);94WSI_GET_CB(GetImageSubresourceLayout);95if (!wsi->sw)96WSI_GET_CB(GetMemoryFdKHR);97WSI_GET_CB(GetPhysicalDeviceFormatProperties);98WSI_GET_CB(GetPhysicalDeviceFormatProperties2KHR);99WSI_GET_CB(GetPhysicalDeviceImageFormatProperties2);100WSI_GET_CB(ResetFences);101WSI_GET_CB(QueueSubmit);102WSI_GET_CB(WaitForFences);103WSI_GET_CB(MapMemory);104WSI_GET_CB(UnmapMemory);105#undef WSI_GET_CB106107#ifdef VK_USE_PLATFORM_XCB_KHR108result = wsi_x11_init_wsi(wsi, alloc, dri_options);109if (result != VK_SUCCESS)110goto fail;111#endif112113#ifdef VK_USE_PLATFORM_WAYLAND_KHR114result = wsi_wl_init_wsi(wsi, alloc, pdevice);115if (result != VK_SUCCESS)116goto fail;117#endif118119#ifdef VK_USE_PLATFORM_WIN32_KHR120result = wsi_win32_init_wsi(wsi, alloc, pdevice);121if (result != VK_SUCCESS)122goto fail;123#endif124125#ifdef VK_USE_PLATFORM_DISPLAY_KHR126result = wsi_display_init_wsi(wsi, alloc, display_fd);127if (result != VK_SUCCESS)128goto fail;129#endif130131present_mode = getenv("MESA_VK_WSI_PRESENT_MODE");132if (present_mode) {133if (!strcmp(present_mode, "fifo")) {134wsi->override_present_mode = VK_PRESENT_MODE_FIFO_KHR;135} else if (!strcmp(present_mode, "relaxed")) {136wsi->override_present_mode = VK_PRESENT_MODE_FIFO_RELAXED_KHR;137} else if (!strcmp(present_mode, "mailbox")) {138wsi->override_present_mode = VK_PRESENT_MODE_MAILBOX_KHR;139} else if (!strcmp(present_mode, "immediate")) {140wsi->override_present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR;141} else {142fprintf(stderr, "Invalid MESA_VK_WSI_PRESENT_MODE value!\n");143}144}145146if (dri_options) {147if (driCheckOption(dri_options, "adaptive_sync", DRI_BOOL))148wsi->enable_adaptive_sync = driQueryOptionb(dri_options,149"adaptive_sync");150151if (driCheckOption(dri_options, "vk_wsi_force_bgra8_unorm_first", DRI_BOOL)) {152wsi->force_bgra8_unorm_first =153driQueryOptionb(dri_options, "vk_wsi_force_bgra8_unorm_first");154}155}156157return VK_SUCCESS;158#if defined(VK_USE_PLATFORM_XCB_KHR) || \159defined(VK_USE_PLATFORM_WAYLAND_KHR) || \160defined(VK_USE_PLATFORM_WIN32_KHR) || \161defined(VK_USE_PLATFORM_DISPLAY_KHR)162fail:163wsi_device_finish(wsi, alloc);164return result;165#endif166}167168void169wsi_device_finish(struct wsi_device *wsi,170const VkAllocationCallbacks *alloc)171{172#ifdef VK_USE_PLATFORM_DISPLAY_KHR173wsi_display_finish_wsi(wsi, alloc);174#endif175#ifdef VK_USE_PLATFORM_WAYLAND_KHR176wsi_wl_finish_wsi(wsi, alloc);177#endif178#ifdef VK_USE_PLATFORM_WIN32_KHR179wsi_win32_finish_wsi(wsi, alloc);180#endif181#ifdef VK_USE_PLATFORM_XCB_KHR182wsi_x11_finish_wsi(wsi, alloc);183#endif184}185186VkResult187wsi_swapchain_init(const struct wsi_device *wsi,188struct wsi_swapchain *chain,189VkDevice device,190const VkSwapchainCreateInfoKHR *pCreateInfo,191const VkAllocationCallbacks *pAllocator)192{193VkResult result;194195memset(chain, 0, sizeof(*chain));196197vk_object_base_init(NULL, &chain->base, VK_OBJECT_TYPE_SWAPCHAIN_KHR);198199chain->wsi = wsi;200chain->device = device;201chain->alloc = *pAllocator;202chain->use_prime_blit = false;203204chain->cmd_pools =205vk_zalloc(pAllocator, sizeof(VkCommandPool) * wsi->queue_family_count, 8,206VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);207if (!chain->cmd_pools)208return VK_ERROR_OUT_OF_HOST_MEMORY;209210for (uint32_t i = 0; i < wsi->queue_family_count; i++) {211const VkCommandPoolCreateInfo cmd_pool_info = {212.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,213.pNext = NULL,214.flags = 0,215.queueFamilyIndex = i,216};217result = wsi->CreateCommandPool(device, &cmd_pool_info, &chain->alloc,218&chain->cmd_pools[i]);219if (result != VK_SUCCESS)220goto fail;221}222223return VK_SUCCESS;224225fail:226wsi_swapchain_finish(chain);227return result;228}229230static bool231wsi_swapchain_is_present_mode_supported(struct wsi_device *wsi,232const VkSwapchainCreateInfoKHR *pCreateInfo,233VkPresentModeKHR mode)234{235ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pCreateInfo->surface);236struct wsi_interface *iface = wsi->wsi[surface->platform];237VkPresentModeKHR *present_modes;238uint32_t present_mode_count;239bool supported = false;240VkResult result;241242result = iface->get_present_modes(surface, &present_mode_count, NULL);243if (result != VK_SUCCESS)244return supported;245246present_modes = malloc(present_mode_count * sizeof(*present_modes));247if (!present_modes)248return supported;249250result = iface->get_present_modes(surface, &present_mode_count,251present_modes);252if (result != VK_SUCCESS)253goto fail;254255for (uint32_t i = 0; i < present_mode_count; i++) {256if (present_modes[i] == mode) {257supported = true;258break;259}260}261262fail:263free(present_modes);264return supported;265}266267enum VkPresentModeKHR268wsi_swapchain_get_present_mode(struct wsi_device *wsi,269const VkSwapchainCreateInfoKHR *pCreateInfo)270{271if (wsi->override_present_mode == VK_PRESENT_MODE_MAX_ENUM_KHR)272return pCreateInfo->presentMode;273274if (!wsi_swapchain_is_present_mode_supported(wsi, pCreateInfo,275wsi->override_present_mode)) {276fprintf(stderr, "Unsupported MESA_VK_WSI_PRESENT_MODE value!\n");277return pCreateInfo->presentMode;278}279280return wsi->override_present_mode;281}282283void284wsi_swapchain_finish(struct wsi_swapchain *chain)285{286if (chain->fences) {287for (unsigned i = 0; i < chain->image_count; i++)288chain->wsi->DestroyFence(chain->device, chain->fences[i], &chain->alloc);289290vk_free(&chain->alloc, chain->fences);291}292293for (uint32_t i = 0; i < chain->wsi->queue_family_count; i++) {294chain->wsi->DestroyCommandPool(chain->device, chain->cmd_pools[i],295&chain->alloc);296}297vk_free(&chain->alloc, chain->cmd_pools);298299vk_object_base_finish(&chain->base);300}301302void303wsi_destroy_image(const struct wsi_swapchain *chain,304struct wsi_image *image)305{306const struct wsi_device *wsi = chain->wsi;307308if (image->prime.blit_cmd_buffers) {309for (uint32_t i = 0; i < wsi->queue_family_count; i++) {310wsi->FreeCommandBuffers(chain->device, chain->cmd_pools[i],3111, &image->prime.blit_cmd_buffers[i]);312}313vk_free(&chain->alloc, image->prime.blit_cmd_buffers);314}315316wsi->FreeMemory(chain->device, image->memory, &chain->alloc);317wsi->DestroyImage(chain->device, image->image, &chain->alloc);318wsi->FreeMemory(chain->device, image->prime.memory, &chain->alloc);319wsi->DestroyBuffer(chain->device, image->prime.buffer, &chain->alloc);320}321322VkResult323wsi_common_get_surface_support(struct wsi_device *wsi_device,324uint32_t queueFamilyIndex,325VkSurfaceKHR _surface,326VkBool32* pSupported)327{328ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);329struct wsi_interface *iface = wsi_device->wsi[surface->platform];330331return iface->get_support(surface, wsi_device,332queueFamilyIndex, pSupported);333}334335VkResult336wsi_common_get_surface_capabilities(struct wsi_device *wsi_device,337VkSurfaceKHR _surface,338VkSurfaceCapabilitiesKHR *pSurfaceCapabilities)339{340ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);341struct wsi_interface *iface = wsi_device->wsi[surface->platform];342343VkSurfaceCapabilities2KHR caps2 = {344.sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR,345};346347VkResult result = iface->get_capabilities2(surface, wsi_device, NULL, &caps2);348349if (result == VK_SUCCESS)350*pSurfaceCapabilities = caps2.surfaceCapabilities;351352return result;353}354355VkResult356wsi_common_get_surface_capabilities2(struct wsi_device *wsi_device,357const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,358VkSurfaceCapabilities2KHR *pSurfaceCapabilities)359{360ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pSurfaceInfo->surface);361struct wsi_interface *iface = wsi_device->wsi[surface->platform];362363return iface->get_capabilities2(surface, wsi_device, pSurfaceInfo->pNext,364pSurfaceCapabilities);365}366367VkResult368wsi_common_get_surface_capabilities2ext(369struct wsi_device *wsi_device,370VkSurfaceKHR _surface,371VkSurfaceCapabilities2EXT *pSurfaceCapabilities)372{373ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);374struct wsi_interface *iface = wsi_device->wsi[surface->platform];375376assert(pSurfaceCapabilities->sType ==377VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT);378379struct wsi_surface_supported_counters counters = {380.sType = VK_STRUCTURE_TYPE_WSI_SURFACE_SUPPORTED_COUNTERS_MESA,381.pNext = pSurfaceCapabilities->pNext,382.supported_surface_counters = 0,383};384385VkSurfaceCapabilities2KHR caps2 = {386.sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR,387.pNext = &counters,388};389390VkResult result = iface->get_capabilities2(surface, wsi_device, NULL, &caps2);391392if (result == VK_SUCCESS) {393VkSurfaceCapabilities2EXT *ext_caps = pSurfaceCapabilities;394VkSurfaceCapabilitiesKHR khr_caps = caps2.surfaceCapabilities;395396ext_caps->minImageCount = khr_caps.minImageCount;397ext_caps->maxImageCount = khr_caps.maxImageCount;398ext_caps->currentExtent = khr_caps.currentExtent;399ext_caps->minImageExtent = khr_caps.minImageExtent;400ext_caps->maxImageExtent = khr_caps.maxImageExtent;401ext_caps->maxImageArrayLayers = khr_caps.maxImageArrayLayers;402ext_caps->supportedTransforms = khr_caps.supportedTransforms;403ext_caps->currentTransform = khr_caps.currentTransform;404ext_caps->supportedCompositeAlpha = khr_caps.supportedCompositeAlpha;405ext_caps->supportedUsageFlags = khr_caps.supportedUsageFlags;406ext_caps->supportedSurfaceCounters = counters.supported_surface_counters;407}408409return result;410}411412VkResult413wsi_common_get_surface_formats(struct wsi_device *wsi_device,414VkSurfaceKHR _surface,415uint32_t *pSurfaceFormatCount,416VkSurfaceFormatKHR *pSurfaceFormats)417{418ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);419struct wsi_interface *iface = wsi_device->wsi[surface->platform];420421return iface->get_formats(surface, wsi_device,422pSurfaceFormatCount, pSurfaceFormats);423}424425VkResult426wsi_common_get_surface_formats2(struct wsi_device *wsi_device,427const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,428uint32_t *pSurfaceFormatCount,429VkSurfaceFormat2KHR *pSurfaceFormats)430{431ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pSurfaceInfo->surface);432struct wsi_interface *iface = wsi_device->wsi[surface->platform];433434return iface->get_formats2(surface, wsi_device, pSurfaceInfo->pNext,435pSurfaceFormatCount, pSurfaceFormats);436}437438VkResult439wsi_common_get_surface_present_modes(struct wsi_device *wsi_device,440VkSurfaceKHR _surface,441uint32_t *pPresentModeCount,442VkPresentModeKHR *pPresentModes)443{444ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);445struct wsi_interface *iface = wsi_device->wsi[surface->platform];446447return iface->get_present_modes(surface, pPresentModeCount,448pPresentModes);449}450451VkResult452wsi_common_get_present_rectangles(struct wsi_device *wsi_device,453VkSurfaceKHR _surface,454uint32_t* pRectCount,455VkRect2D* pRects)456{457ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);458struct wsi_interface *iface = wsi_device->wsi[surface->platform];459460return iface->get_present_rectangles(surface, wsi_device,461pRectCount, pRects);462}463464VkResult465wsi_common_create_swapchain(struct wsi_device *wsi,466VkDevice device,467const VkSwapchainCreateInfoKHR *pCreateInfo,468const VkAllocationCallbacks *pAllocator,469VkSwapchainKHR *pSwapchain)470{471ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pCreateInfo->surface);472struct wsi_interface *iface = wsi->wsi[surface->platform];473struct wsi_swapchain *swapchain;474475VkResult result = iface->create_swapchain(surface, device, wsi,476pCreateInfo, pAllocator,477&swapchain);478if (result != VK_SUCCESS)479return result;480481swapchain->fences = vk_zalloc(pAllocator,482sizeof (*swapchain->fences) * swapchain->image_count,483sizeof (*swapchain->fences),484VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);485if (!swapchain->fences) {486swapchain->destroy(swapchain, pAllocator);487return VK_ERROR_OUT_OF_HOST_MEMORY;488}489490*pSwapchain = wsi_swapchain_to_handle(swapchain);491492return VK_SUCCESS;493}494495void496wsi_common_destroy_swapchain(VkDevice device,497VkSwapchainKHR _swapchain,498const VkAllocationCallbacks *pAllocator)499{500VK_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain);501if (!swapchain)502return;503504swapchain->destroy(swapchain, pAllocator);505}506507VkResult508wsi_common_get_images(VkSwapchainKHR _swapchain,509uint32_t *pSwapchainImageCount,510VkImage *pSwapchainImages)511{512VK_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain);513VK_OUTARRAY_MAKE_TYPED(VkImage, images, pSwapchainImages, pSwapchainImageCount);514515for (uint32_t i = 0; i < swapchain->image_count; i++) {516vk_outarray_append_typed(VkImage, &images, image) {517*image = swapchain->get_wsi_image(swapchain, i)->image;518}519}520521return vk_outarray_status(&images);522}523524VkResult525wsi_common_acquire_next_image2(const struct wsi_device *wsi,526VkDevice device,527const VkAcquireNextImageInfoKHR *pAcquireInfo,528uint32_t *pImageIndex)529{530VK_FROM_HANDLE(wsi_swapchain, swapchain, pAcquireInfo->swapchain);531532VkResult result = swapchain->acquire_next_image(swapchain, pAcquireInfo,533pImageIndex);534if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR)535return result;536537if (wsi->set_memory_ownership) {538VkDeviceMemory mem = swapchain->get_wsi_image(swapchain, *pImageIndex)->memory;539wsi->set_memory_ownership(swapchain->device, mem, true);540}541542if (pAcquireInfo->semaphore != VK_NULL_HANDLE &&543wsi->signal_semaphore_for_memory != NULL) {544struct wsi_image *image =545swapchain->get_wsi_image(swapchain, *pImageIndex);546wsi->signal_semaphore_for_memory(device, pAcquireInfo->semaphore,547image->memory);548}549550if (pAcquireInfo->fence != VK_NULL_HANDLE &&551wsi->signal_fence_for_memory != NULL) {552struct wsi_image *image =553swapchain->get_wsi_image(swapchain, *pImageIndex);554wsi->signal_fence_for_memory(device, pAcquireInfo->fence,555image->memory);556}557558return result;559}560561VkResult562wsi_common_queue_present(const struct wsi_device *wsi,563VkDevice device,564VkQueue queue,565int queue_family_index,566const VkPresentInfoKHR *pPresentInfo)567{568VkResult final_result = VK_SUCCESS;569570const VkPresentRegionsKHR *regions =571vk_find_struct_const(pPresentInfo->pNext, PRESENT_REGIONS_KHR);572573for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) {574VK_FROM_HANDLE(wsi_swapchain, swapchain, pPresentInfo->pSwapchains[i]);575uint32_t image_index = pPresentInfo->pImageIndices[i];576VkResult result;577578if (swapchain->fences[image_index] == VK_NULL_HANDLE) {579const VkFenceCreateInfo fence_info = {580.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,581.pNext = NULL,582.flags = 0,583};584result = wsi->CreateFence(device, &fence_info,585&swapchain->alloc,586&swapchain->fences[image_index]);587if (result != VK_SUCCESS)588goto fail_present;589} else {590result =591wsi->WaitForFences(device, 1, &swapchain->fences[image_index],592true, ~0ull);593if (result != VK_SUCCESS)594goto fail_present;595596result =597wsi->ResetFences(device, 1, &swapchain->fences[image_index]);598if (result != VK_SUCCESS)599goto fail_present;600}601602struct wsi_image *image =603swapchain->get_wsi_image(swapchain, image_index);604605struct wsi_memory_signal_submit_info mem_signal = {606.sType = VK_STRUCTURE_TYPE_WSI_MEMORY_SIGNAL_SUBMIT_INFO_MESA,607.pNext = NULL,608.memory = image->memory,609};610611VkSubmitInfo submit_info = {612.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,613.pNext = &mem_signal,614};615616VkPipelineStageFlags *stage_flags = NULL;617if (i == 0) {618/* We only need/want to wait on semaphores once. After that, we're619* guaranteed ordering since it all happens on the same queue.620*/621submit_info.waitSemaphoreCount = pPresentInfo->waitSemaphoreCount;622submit_info.pWaitSemaphores = pPresentInfo->pWaitSemaphores;623624/* Set up the pWaitDstStageMasks */625stage_flags = vk_alloc(&swapchain->alloc,626sizeof(VkPipelineStageFlags) *627pPresentInfo->waitSemaphoreCount,6288,629VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);630if (!stage_flags) {631result = VK_ERROR_OUT_OF_HOST_MEMORY;632goto fail_present;633}634for (uint32_t s = 0; s < pPresentInfo->waitSemaphoreCount; s++)635stage_flags[s] = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;636637submit_info.pWaitDstStageMask = stage_flags;638}639640if (swapchain->use_prime_blit) {641/* If we are using prime blits, we need to perform the blit now. The642* command buffer is attached to the image.643*/644submit_info.commandBufferCount = 1;645submit_info.pCommandBuffers =646&image->prime.blit_cmd_buffers[queue_family_index];647mem_signal.memory = image->prime.memory;648}649650result = wsi->QueueSubmit(queue, 1, &submit_info, swapchain->fences[image_index]);651vk_free(&swapchain->alloc, stage_flags);652if (result != VK_SUCCESS)653goto fail_present;654655const VkPresentRegionKHR *region = NULL;656if (regions && regions->pRegions)657region = ®ions->pRegions[i];658659result = swapchain->queue_present(swapchain, image_index, region);660if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR)661goto fail_present;662663if (wsi->set_memory_ownership) {664VkDeviceMemory mem = swapchain->get_wsi_image(swapchain, image_index)->memory;665wsi->set_memory_ownership(swapchain->device, mem, false);666}667668fail_present:669if (pPresentInfo->pResults != NULL)670pPresentInfo->pResults[i] = result;671672/* Let the final result be our first unsuccessful result */673if (final_result == VK_SUCCESS)674final_result = result;675}676677return final_result;678}679680uint64_t681wsi_common_get_current_time(void)682{683return os_time_get_nano();684}685686687