Path: blob/21.2-virgl/src/virtio/vulkan/vn_wsi.c
4560 views
/*1* Copyright 2019 Google LLC2* SPDX-License-Identifier: MIT3*4* based in part on anv and radv which are:5* Copyright © 2015 Intel Corporation6* Copyright © 2016 Red Hat.7* Copyright © 2016 Bas Nieuwenhuizen8*/910#include "vn_wsi.h"1112#include "vn_device.h"13#include "vn_image.h"14#include "vn_queue.h"1516/* The common WSI support makes some assumptions about the driver.17*18* In wsi_device_init, it assumes VK_EXT_pci_bus_info is available. In19* wsi_create_native_image and wsi_create_prime_image, it assumes20* VK_KHR_external_memory_fd and VK_EXT_external_memory_dma_buf are enabled.21*22* In wsi_create_native_image, if wsi_device::supports_modifiers is set and23* the window system supports modifiers, it assumes24* VK_EXT_image_drm_format_modifier is enabled. Otherwise, it assumes that25* wsi_image_create_info can be chained to VkImageCreateInfo and26* vkGetImageSubresourceLayout can be called even the tiling is27* VK_IMAGE_TILING_OPTIMAL.28*29* Together, it knows how to share dma-bufs, with explicit or implicit30* modifiers, to the window system.31*32* For venus, we use explicit modifiers when the renderer and the window33* system support them. Otherwise, we have to fall back to34* VK_IMAGE_TILING_LINEAR (or trigger the prime blit path). But the fallback35* can be problematic when the memory is scanned out directly and special36* requirements (e.g., alignments) must be met.37*38* The common WSI support makes other assumptions about the driver to support39* implicit fencing. In wsi_create_native_image and wsi_create_prime_image,40* it assumes wsi_memory_allocate_info can be chained to VkMemoryAllocateInfo.41* In wsi_common_queue_present, it assumes wsi_memory_signal_submit_info can42* be chained to VkSubmitInfo. Finally, in wsi_common_acquire_next_image2, it43* calls wsi_device::signal_semaphore_for_memory, and44* wsi_device::signal_fence_for_memory if the driver provides them.45*46* Some drivers use wsi_memory_allocate_info to set up implicit fencing.47* Others use wsi_memory_signal_submit_info to set up implicit IN-fences and48* use wsi_device::signal_*_for_memory to set up implicit OUT-fences.49*50* For venus, implicit fencing is broken (and there is no explicit fencing51* support yet). The kernel driver assumes everything is in the same fence52* context and no synchronization is needed. It should be fixed for53* correctness, but it is still not ideal. venus requires explicit fencing54* (and renderer-side synchronization) to work well.55*/5657static PFN_vkVoidFunction58vn_wsi_proc_addr(VkPhysicalDevice physicalDevice, const char *pName)59{60struct vn_physical_device *physical_dev =61vn_physical_device_from_handle(physicalDevice);62return vk_instance_get_proc_addr_unchecked(63&physical_dev->instance->base.base, pName);64}6566VkResult67vn_wsi_init(struct vn_physical_device *physical_dev)68{69const VkAllocationCallbacks *alloc =70&physical_dev->instance->base.base.alloc;71VkResult result = wsi_device_init(72&physical_dev->wsi_device, vn_physical_device_to_handle(physical_dev),73vn_wsi_proc_addr, alloc, -1, &physical_dev->instance->dri_options,74false);75if (result != VK_SUCCESS)76return result;7778if (physical_dev->base.base.supported_extensions79.EXT_image_drm_format_modifier)80physical_dev->wsi_device.supports_modifiers = true;8182return VK_SUCCESS;83}8485void86vn_wsi_fini(struct vn_physical_device *physical_dev)87{88const VkAllocationCallbacks *alloc =89&physical_dev->instance->base.base.alloc;90wsi_device_finish(&physical_dev->wsi_device, alloc);91}9293VkResult94vn_wsi_create_image(struct vn_device *dev,95const VkImageCreateInfo *create_info,96const struct wsi_image_create_info *wsi_info,97const VkAllocationCallbacks *alloc,98struct vn_image **out_img)99{100/* TODO This is the legacy path used by wsi_create_native_image when there101* is no modifier support. Instead of forcing VK_IMAGE_TILING_LINEAR, we102* should ask wsi to use wsi_create_prime_image instead.103*104* In fact, this is not enough when the image is truely used for scanout by105* the host compositor. There can be requirements we fail to meet. We106* should require modifier support at some point.107*/108VkImageCreateInfo local_create_info;109if (wsi_info->scanout) {110local_create_info = *create_info;111local_create_info.tiling = VK_IMAGE_TILING_LINEAR;112create_info = &local_create_info;113114if (VN_DEBUG(WSI))115vn_log(dev->instance, "forcing scanout image linear");116}117118struct vn_image *img;119VkResult result = vn_image_create(dev, create_info, alloc, &img);120if (result != VK_SUCCESS)121return result;122123img->is_wsi = true;124img->prime_blit_buffer = wsi_info->prime_blit_buffer;125126*out_img = img;127return VK_SUCCESS;128}129130/* surface commands */131132void133vn_DestroySurfaceKHR(VkInstance _instance,134VkSurfaceKHR surface,135const VkAllocationCallbacks *pAllocator)136{137struct vn_instance *instance = vn_instance_from_handle(_instance);138ICD_FROM_HANDLE(VkIcdSurfaceBase, surf, surface);139const VkAllocationCallbacks *alloc =140pAllocator ? pAllocator : &instance->base.base.alloc;141142vk_free(alloc, surf);143}144145VkResult146vn_GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice,147uint32_t queueFamilyIndex,148VkSurfaceKHR surface,149VkBool32 *pSupported)150{151struct vn_physical_device *physical_dev =152vn_physical_device_from_handle(physicalDevice);153154VkResult result = wsi_common_get_surface_support(155&physical_dev->wsi_device, queueFamilyIndex, surface, pSupported);156157return vn_result(physical_dev->instance, result);158}159160VkResult161vn_GetPhysicalDeviceSurfaceCapabilitiesKHR(162VkPhysicalDevice physicalDevice,163VkSurfaceKHR surface,164VkSurfaceCapabilitiesKHR *pSurfaceCapabilities)165{166struct vn_physical_device *physical_dev =167vn_physical_device_from_handle(physicalDevice);168169VkResult result = wsi_common_get_surface_capabilities(170&physical_dev->wsi_device, surface, pSurfaceCapabilities);171172return vn_result(physical_dev->instance, result);173}174175VkResult176vn_GetPhysicalDeviceSurfaceCapabilities2KHR(177VkPhysicalDevice physicalDevice,178const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,179VkSurfaceCapabilities2KHR *pSurfaceCapabilities)180{181struct vn_physical_device *physical_dev =182vn_physical_device_from_handle(physicalDevice);183184VkResult result = wsi_common_get_surface_capabilities2(185&physical_dev->wsi_device, pSurfaceInfo, pSurfaceCapabilities);186187return vn_result(physical_dev->instance, result);188}189190VkResult191vn_GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice,192VkSurfaceKHR surface,193uint32_t *pSurfaceFormatCount,194VkSurfaceFormatKHR *pSurfaceFormats)195{196struct vn_physical_device *physical_dev =197vn_physical_device_from_handle(physicalDevice);198199VkResult result =200wsi_common_get_surface_formats(&physical_dev->wsi_device, surface,201pSurfaceFormatCount, pSurfaceFormats);202203return vn_result(physical_dev->instance, result);204}205206VkResult207vn_GetPhysicalDeviceSurfaceFormats2KHR(208VkPhysicalDevice physicalDevice,209const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,210uint32_t *pSurfaceFormatCount,211VkSurfaceFormat2KHR *pSurfaceFormats)212{213struct vn_physical_device *physical_dev =214vn_physical_device_from_handle(physicalDevice);215216VkResult result =217wsi_common_get_surface_formats2(&physical_dev->wsi_device, pSurfaceInfo,218pSurfaceFormatCount, pSurfaceFormats);219220return vn_result(physical_dev->instance, result);221}222223VkResult224vn_GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice,225VkSurfaceKHR surface,226uint32_t *pPresentModeCount,227VkPresentModeKHR *pPresentModes)228{229struct vn_physical_device *physical_dev =230vn_physical_device_from_handle(physicalDevice);231232VkResult result = wsi_common_get_surface_present_modes(233&physical_dev->wsi_device, surface, pPresentModeCount, pPresentModes);234235return vn_result(physical_dev->instance, result);236}237238VkResult239vn_GetDeviceGroupPresentCapabilitiesKHR(240VkDevice device, VkDeviceGroupPresentCapabilitiesKHR *pCapabilities)241{242memset(pCapabilities->presentMask, 0, sizeof(pCapabilities->presentMask));243pCapabilities->presentMask[0] = 0x1;244pCapabilities->modes = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;245246return VK_SUCCESS;247}248249VkResult250vn_GetDeviceGroupSurfacePresentModesKHR(251VkDevice device,252VkSurfaceKHR surface,253VkDeviceGroupPresentModeFlagsKHR *pModes)254{255*pModes = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;256257return VK_SUCCESS;258}259260VkResult261vn_GetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice,262VkSurfaceKHR surface,263uint32_t *pRectCount,264VkRect2D *pRects)265{266struct vn_physical_device *physical_dev =267vn_physical_device_from_handle(physicalDevice);268269VkResult result = wsi_common_get_present_rectangles(270&physical_dev->wsi_device, surface, pRectCount, pRects);271272return vn_result(physical_dev->instance, result);273}274275/* swapchain commands */276277VkResult278vn_CreateSwapchainKHR(VkDevice device,279const VkSwapchainCreateInfoKHR *pCreateInfo,280const VkAllocationCallbacks *pAllocator,281VkSwapchainKHR *pSwapchain)282{283struct vn_device *dev = vn_device_from_handle(device);284const VkAllocationCallbacks *alloc =285pAllocator ? pAllocator : &dev->base.base.alloc;286287VkResult result =288wsi_common_create_swapchain(&dev->physical_device->wsi_device, device,289pCreateInfo, alloc, pSwapchain);290291return vn_result(dev->instance, result);292}293294void295vn_DestroySwapchainKHR(VkDevice device,296VkSwapchainKHR swapchain,297const VkAllocationCallbacks *pAllocator)298{299struct vn_device *dev = vn_device_from_handle(device);300const VkAllocationCallbacks *alloc =301pAllocator ? pAllocator : &dev->base.base.alloc;302303wsi_common_destroy_swapchain(device, swapchain, alloc);304}305306VkResult307vn_GetSwapchainImagesKHR(VkDevice device,308VkSwapchainKHR swapchain,309uint32_t *pSwapchainImageCount,310VkImage *pSwapchainImages)311{312struct vn_device *dev = vn_device_from_handle(device);313314VkResult result = wsi_common_get_images(swapchain, pSwapchainImageCount,315pSwapchainImages);316317return vn_result(dev->instance, result);318}319320VkResult321vn_AcquireNextImageKHR(VkDevice device,322VkSwapchainKHR swapchain,323uint64_t timeout,324VkSemaphore semaphore,325VkFence fence,326uint32_t *pImageIndex)327{328const VkAcquireNextImageInfoKHR acquire_info = {329.sType = VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR,330.swapchain = swapchain,331.timeout = timeout,332.semaphore = semaphore,333.fence = fence,334.deviceMask = 0x1,335};336337return vn_AcquireNextImage2KHR(device, &acquire_info, pImageIndex);338}339340VkResult341vn_QueuePresentKHR(VkQueue _queue, const VkPresentInfoKHR *pPresentInfo)342{343struct vn_queue *queue = vn_queue_from_handle(_queue);344345VkResult result =346wsi_common_queue_present(&queue->device->physical_device->wsi_device,347vn_device_to_handle(queue->device), _queue,348queue->family, pPresentInfo);349350return vn_result(queue->device->instance, result);351}352353VkResult354vn_AcquireNextImage2KHR(VkDevice device,355const VkAcquireNextImageInfoKHR *pAcquireInfo,356uint32_t *pImageIndex)357{358struct vn_device *dev = vn_device_from_handle(device);359360VkResult result = wsi_common_acquire_next_image2(361&dev->physical_device->wsi_device, device, pAcquireInfo, pImageIndex);362363/* XXX this relies on implicit sync */364if (result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR) {365struct vn_semaphore *sem =366vn_semaphore_from_handle(pAcquireInfo->semaphore);367if (sem)368vn_semaphore_signal_wsi(dev, sem);369370struct vn_fence *fence = vn_fence_from_handle(pAcquireInfo->fence);371if (fence)372vn_fence_signal_wsi(dev, fence);373}374375return vn_result(dev->instance, result);376}377378379