X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fvulkan%2Fwsi%2Fwsi_common.c;h=b8f6c6d70de620c383c77738b3acf24e3dff53b2;hb=7cb672227bea9f61c6fd25b3eef534e7f79442fb;hp=a303aabf2c47a6de080fa0282539650f228dfb91;hpb=c1b1be5196f38776405b58c01a6f138a0f031edb;p=mesa.git diff --git a/src/vulkan/wsi/wsi_common.c b/src/vulkan/wsi/wsi_common.c index a303aabf2c4..b8f6c6d70de 100644 --- a/src/vulkan/wsi/wsi_common.c +++ b/src/vulkan/wsi/wsi_common.c @@ -22,22 +22,51 @@ */ #include "wsi_common_private.h" +#include "drm-uapi/drm_fourcc.h" #include "util/macros.h" +#include "util/xmlconfig.h" #include "vk_util.h" -void +#include +#include +#include +#include +#include + +VkResult wsi_device_init(struct wsi_device *wsi, VkPhysicalDevice pdevice, - WSI_FN_GetPhysicalDeviceProcAddr proc_addr) + WSI_FN_GetPhysicalDeviceProcAddr proc_addr, + const VkAllocationCallbacks *alloc, + int display_fd, + const struct driOptionCache *dri_options) { + const char *present_mode; + VkResult result; + memset(wsi, 0, sizeof(*wsi)); + wsi->instance_alloc = *alloc; + wsi->pdevice = pdevice; + #define WSI_GET_CB(func) \ PFN_vk##func func = (PFN_vk##func)proc_addr(pdevice, "vk" #func) + WSI_GET_CB(GetPhysicalDeviceProperties2); WSI_GET_CB(GetPhysicalDeviceMemoryProperties); WSI_GET_CB(GetPhysicalDeviceQueueFamilyProperties); #undef WSI_GET_CB + wsi->pci_bus_info.sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT; + VkPhysicalDeviceProperties2 pdp2 = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, + .pNext = &wsi->pci_bus_info, + }; + GetPhysicalDeviceProperties2(pdevice, &pdp2); + + wsi->maxImageDimension2D = pdp2.properties.limits.maxImageDimension2D; + wsi->override_present_mode = VK_PRESENT_MODE_MAX_ENUM_KHR; + GetPhysicalDeviceMemoryProperties(pdevice, &wsi->memory_props); GetPhysicalDeviceQueueFamilyProperties(pdevice, &wsi->queue_family_count, NULL); @@ -64,10 +93,96 @@ wsi_device_init(struct wsi_device *wsi, WSI_GET_CB(GetImageMemoryRequirements); WSI_GET_CB(GetImageSubresourceLayout); WSI_GET_CB(GetMemoryFdKHR); + WSI_GET_CB(GetPhysicalDeviceFormatProperties); + WSI_GET_CB(GetPhysicalDeviceFormatProperties2KHR); WSI_GET_CB(ResetFences); WSI_GET_CB(QueueSubmit); WSI_GET_CB(WaitForFences); #undef WSI_GET_CB + +#ifdef VK_USE_PLATFORM_XCB_KHR + result = wsi_x11_init_wsi(wsi, alloc, dri_options); + if (result != VK_SUCCESS) + goto fail; +#endif + +#ifdef VK_USE_PLATFORM_WAYLAND_KHR + result = wsi_wl_init_wsi(wsi, alloc, pdevice); + if (result != VK_SUCCESS) + goto fail; +#endif + +#ifdef VK_USE_PLATFORM_DISPLAY_KHR + result = wsi_display_init_wsi(wsi, alloc, display_fd); + if (result != VK_SUCCESS) + goto fail; +#endif + + present_mode = getenv("MESA_VK_WSI_PRESENT_MODE"); + if (present_mode) { + if (!strcmp(present_mode, "fifo")) { + wsi->override_present_mode = VK_PRESENT_MODE_FIFO_KHR; + } else if (!strcmp(present_mode, "mailbox")) { + wsi->override_present_mode = VK_PRESENT_MODE_MAILBOX_KHR; + } else if (!strcmp(present_mode, "immediate")) { + wsi->override_present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR; + } else { + fprintf(stderr, "Invalid MESA_VK_WSI_PRESENT_MODE value!\n"); + } + } + + if (dri_options) { + if (driCheckOption(dri_options, "adaptive_sync", DRI_BOOL)) + wsi->enable_adaptive_sync = driQueryOptionb(dri_options, + "adaptive_sync"); + } + + return VK_SUCCESS; + +fail: + wsi_device_finish(wsi, alloc); + return result; +} + +void +wsi_device_finish(struct wsi_device *wsi, + const VkAllocationCallbacks *alloc) +{ +#ifdef VK_USE_PLATFORM_DISPLAY_KHR + wsi_display_finish_wsi(wsi, alloc); +#endif +#ifdef VK_USE_PLATFORM_WAYLAND_KHR + wsi_wl_finish_wsi(wsi, alloc); +#endif +#ifdef VK_USE_PLATFORM_XCB_KHR + wsi_x11_finish_wsi(wsi, alloc); +#endif +} + +bool +wsi_device_matches_drm_fd(const struct wsi_device *wsi, int drm_fd) +{ + drmDevicePtr fd_device; + int ret = drmGetDevice2(drm_fd, 0, &fd_device); + if (ret) + return false; + + bool match = false; + switch (fd_device->bustype) { + case DRM_BUS_PCI: + match = wsi->pci_bus_info.pciDomain == fd_device->businfo.pci->domain && + wsi->pci_bus_info.pciBus == fd_device->businfo.pci->bus && + wsi->pci_bus_info.pciDevice == fd_device->businfo.pci->dev && + wsi->pci_bus_info.pciFunction == fd_device->businfo.pci->func; + break; + + default: + break; + } + + drmFreeDevice(&fd_device); + + return match; } VkResult @@ -112,16 +227,74 @@ fail: return result; } +static bool +wsi_swapchain_is_present_mode_supported(struct wsi_device *wsi, + const VkSwapchainCreateInfoKHR *pCreateInfo, + VkPresentModeKHR mode) +{ + ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pCreateInfo->surface); + struct wsi_interface *iface = wsi->wsi[surface->platform]; + VkPresentModeKHR *present_modes; + uint32_t present_mode_count; + bool supported = false; + VkResult result; + + result = iface->get_present_modes(surface, &present_mode_count, NULL); + if (result != VK_SUCCESS) + return supported; + + present_modes = malloc(present_mode_count * sizeof(*present_modes)); + if (!present_modes) + return supported; + + result = iface->get_present_modes(surface, &present_mode_count, + present_modes); + if (result != VK_SUCCESS) + goto fail; + + for (uint32_t i = 0; i < present_mode_count; i++) { + if (present_modes[i] == mode) { + supported = true; + break; + } + } + +fail: + free(present_modes); + return supported; +} + +enum VkPresentModeKHR +wsi_swapchain_get_present_mode(struct wsi_device *wsi, + const VkSwapchainCreateInfoKHR *pCreateInfo) +{ + if (wsi->override_present_mode == VK_PRESENT_MODE_MAX_ENUM_KHR) + return pCreateInfo->presentMode; + + if (!wsi_swapchain_is_present_mode_supported(wsi, pCreateInfo, + wsi->override_present_mode)) { + fprintf(stderr, "Unsupported MESA_VK_WSI_PRESENT_MODE value!\n"); + return pCreateInfo->presentMode; + } + + return wsi->override_present_mode; +} + void wsi_swapchain_finish(struct wsi_swapchain *chain) { - for (unsigned i = 0; i < ARRAY_SIZE(chain->fences); i++) - chain->wsi->DestroyFence(chain->device, chain->fences[i], &chain->alloc); + if (chain->fences) { + for (unsigned i = 0; i < chain->image_count; i++) + chain->wsi->DestroyFence(chain->device, chain->fences[i], &chain->alloc); + + vk_free(&chain->alloc, chain->fences); + } for (uint32_t i = 0; i < chain->wsi->queue_family_count; i++) { chain->wsi->DestroyCommandPool(chain->device, chain->cmd_pools[i], &chain->alloc); } + vk_free(&chain->alloc, chain->cmd_pools); } static uint32_t @@ -160,18 +333,103 @@ align_u32(uint32_t v, uint32_t a) VkResult wsi_create_native_image(const struct wsi_swapchain *chain, const VkSwapchainCreateInfoKHR *pCreateInfo, + uint32_t num_modifier_lists, + const uint32_t *num_modifiers, + const uint64_t *const *modifiers, struct wsi_image *image) { const struct wsi_device *wsi = chain->wsi; VkResult result; memset(image, 0, sizeof(*image)); + for (int i = 0; i < ARRAY_SIZE(image->fds); i++) + image->fds[i] = -1; - const struct wsi_image_create_info image_wsi_info = { + struct wsi_image_create_info image_wsi_info = { .sType = VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA, .pNext = NULL, - .scanout = true, }; + + uint32_t image_modifier_count = 0, modifier_prop_count = 0; + struct wsi_format_modifier_properties *modifier_props = NULL; + uint64_t *image_modifiers = NULL; + if (num_modifier_lists == 0) { + /* If we don't have modifiers, fall back to the legacy "scanout" flag */ + image_wsi_info.scanout = true; + } else { + /* The winsys can't request modifiers if we don't support them. */ + assert(wsi->supports_modifiers); + struct wsi_format_modifier_properties_list modifier_props_list = { + .sType = VK_STRUCTURE_TYPE_WSI_FORMAT_MODIFIER_PROPERTIES_LIST_MESA, + .pNext = NULL, + }; + VkFormatProperties2 format_props = { + .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2, + .pNext = &modifier_props_list, + }; + wsi->GetPhysicalDeviceFormatProperties2KHR(wsi->pdevice, + pCreateInfo->imageFormat, + &format_props); + assert(modifier_props_list.modifier_count > 0); + modifier_props = vk_alloc(&chain->alloc, + sizeof(*modifier_props) * + modifier_props_list.modifier_count, + 8, + VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); + if (!modifier_props) { + result = VK_ERROR_OUT_OF_HOST_MEMORY; + goto fail; + } + + modifier_props_list.modifier_properties = modifier_props; + wsi->GetPhysicalDeviceFormatProperties2KHR(wsi->pdevice, + pCreateInfo->imageFormat, + &format_props); + modifier_prop_count = modifier_props_list.modifier_count; + + uint32_t max_modifier_count = 0; + for (uint32_t l = 0; l < num_modifier_lists; l++) + max_modifier_count = MAX2(max_modifier_count, num_modifiers[l]); + + image_modifiers = vk_alloc(&chain->alloc, + sizeof(*image_modifiers) * + max_modifier_count, + 8, + VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); + if (!image_modifiers) { + result = VK_ERROR_OUT_OF_HOST_MEMORY; + goto fail; + } + + image_modifier_count = 0; + for (uint32_t l = 0; l < num_modifier_lists; l++) { + /* Walk the modifier lists and construct a list of supported + * modifiers. + */ + for (uint32_t i = 0; i < num_modifiers[l]; i++) { + for (uint32_t j = 0; j < modifier_prop_count; j++) { + if (modifier_props[j].modifier == modifiers[l][i]) + image_modifiers[image_modifier_count++] = modifiers[l][i]; + } + } + + /* We only want to take the modifiers from the first list */ + if (image_modifier_count > 0) + break; + } + + if (image_modifier_count > 0) { + image_wsi_info.modifier_count = image_modifier_count; + image_wsi_info.modifiers = image_modifiers; + } else { + /* TODO: Add a proper error here */ + assert(!"Failed to find a supported modifier! This should never " + "happen because LINEAR should always be available"); + result = VK_ERROR_OUT_OF_HOST_MEMORY; + goto fail; + } + } + const VkImageCreateInfo image_info = { .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, .pNext = &image_wsi_info, @@ -201,27 +459,18 @@ wsi_create_native_image(const struct wsi_swapchain *chain, VkMemoryRequirements reqs; wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs); - VkSubresourceLayout image_layout; - const VkImageSubresource image_subresource = { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .mipLevel = 0, - .arrayLayer = 0, - }; - wsi->GetImageSubresourceLayout(chain->device, image->image, - &image_subresource, &image_layout); - const struct wsi_memory_allocate_info memory_wsi_info = { .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA, .pNext = NULL, .implicit_sync = true, }; - const VkExportMemoryAllocateInfoKHR memory_export_info = { - .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR, + const VkExportMemoryAllocateInfo memory_export_info = { + .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO, .pNext = &memory_wsi_info, .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, }; - const VkMemoryDedicatedAllocateInfoKHR memory_dedicated_info = { - .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR, + const VkMemoryDedicatedAllocateInfo memory_dedicated_info = { + .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, .pNext = &memory_export_info, .image = image->image, .buffer = VK_NULL_HANDLE, @@ -254,14 +503,67 @@ wsi_create_native_image(const struct wsi_swapchain *chain, if (result != VK_SUCCESS) goto fail; - image->size = reqs.size; - image->row_pitch = image_layout.rowPitch; - image->offset = 0; - image->fd = fd; + if (num_modifier_lists > 0) { + image->drm_modifier = wsi->image_get_modifier(image->image); + assert(image->drm_modifier != DRM_FORMAT_MOD_INVALID); + + for (uint32_t j = 0; j < modifier_prop_count; j++) { + if (modifier_props[j].modifier == image->drm_modifier) { + image->num_planes = modifier_props[j].modifier_plane_count; + break; + } + } + + for (uint32_t p = 0; p < image->num_planes; p++) { + const VkImageSubresource image_subresource = { + .aspectMask = VK_IMAGE_ASPECT_PLANE_0_BIT << p, + .mipLevel = 0, + .arrayLayer = 0, + }; + VkSubresourceLayout image_layout; + wsi->GetImageSubresourceLayout(chain->device, image->image, + &image_subresource, &image_layout); + image->sizes[p] = image_layout.size; + image->row_pitches[p] = image_layout.rowPitch; + image->offsets[p] = image_layout.offset; + if (p == 0) { + image->fds[p] = fd; + } else { + image->fds[p] = dup(fd); + if (image->fds[p] == -1) { + for (uint32_t i = 0; i < p; i++) + close(image->fds[p]); + + goto fail; + } + } + } + } else { + const VkImageSubresource image_subresource = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .mipLevel = 0, + .arrayLayer = 0, + }; + VkSubresourceLayout image_layout; + wsi->GetImageSubresourceLayout(chain->device, image->image, + &image_subresource, &image_layout); + + image->drm_modifier = DRM_FORMAT_MOD_INVALID; + image->num_planes = 1; + image->sizes[0] = reqs.size; + image->row_pitches[0] = image_layout.rowPitch; + image->offsets[0] = 0; + image->fds[0] = fd; + } + + vk_free(&chain->alloc, modifier_props); + vk_free(&chain->alloc, image_modifiers); return VK_SUCCESS; fail: + vk_free(&chain->alloc, modifier_props); + vk_free(&chain->alloc, image_modifiers); wsi_destroy_image(chain, image); return result; @@ -272,6 +574,7 @@ fail: VkResult wsi_create_prime_image(const struct wsi_swapchain *chain, const VkSwapchainCreateInfoKHR *pCreateInfo, + bool use_modifier, struct wsi_image *image) { const struct wsi_device *wsi = chain->wsi; @@ -286,8 +589,8 @@ wsi_create_prime_image(const struct wsi_swapchain *chain, uint32_t linear_size = linear_stride * pCreateInfo->imageExtent.height; linear_size = align_u32(linear_size, 4096); - const VkExternalMemoryBufferCreateInfoKHR prime_buffer_external_info = { - .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR, + const VkExternalMemoryBufferCreateInfo prime_buffer_external_info = { + .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO, .pNext = NULL, .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, }; @@ -312,13 +615,13 @@ wsi_create_prime_image(const struct wsi_swapchain *chain, .pNext = NULL, .implicit_sync = true, }; - const VkExportMemoryAllocateInfoKHR prime_memory_export_info = { - .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR, + const VkExportMemoryAllocateInfo prime_memory_export_info = { + .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO, .pNext = &memory_wsi_info, .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, }; - const VkMemoryDedicatedAllocateInfoKHR prime_memory_dedicated_info = { - .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR, + const VkMemoryDedicatedAllocateInfo prime_memory_dedicated_info = { + .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, .pNext = &prime_memory_export_info, .image = VK_NULL_HANDLE, .buffer = image->prime.buffer, @@ -367,8 +670,8 @@ wsi_create_prime_image(const struct wsi_swapchain *chain, wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs); - const VkMemoryDedicatedAllocateInfoKHR memory_dedicated_info = { - .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR, + const VkMemoryDedicatedAllocateInfo memory_dedicated_info = { + .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, .pNext = NULL, .image = image->image, .buffer = VK_NULL_HANDLE, @@ -394,8 +697,10 @@ wsi_create_prime_image(const struct wsi_swapchain *chain, vk_zalloc(&chain->alloc, sizeof(VkCommandBuffer) * wsi->queue_family_count, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); - if (!image->prime.blit_cmd_buffers) + if (!image->prime.blit_cmd_buffers) { + result = VK_ERROR_OUT_OF_HOST_MEMORY; goto fail; + } for (uint32_t i = 0; i < wsi->queue_family_count; i++) { const VkCommandBufferAllocateInfo cmd_buffer_info = { @@ -454,10 +759,12 @@ wsi_create_prime_image(const struct wsi_swapchain *chain, if (result != VK_SUCCESS) goto fail; - image->size = linear_size; - image->row_pitch = linear_stride; - image->offset = 0; - image->fd = fd; + image->drm_modifier = use_modifier ? DRM_FORMAT_MOD_LINEAR : DRM_FORMAT_MOD_INVALID; + image->num_planes = 1; + image->sizes[0] = linear_size; + image->row_pitches[0] = linear_stride; + image->offsets[0] = 0; + image->fds[0] = fd; return VK_SUCCESS; @@ -489,17 +796,15 @@ wsi_destroy_image(const struct wsi_swapchain *chain, VkResult wsi_common_get_surface_support(struct wsi_device *wsi_device, - int local_fd, uint32_t queueFamilyIndex, VkSurfaceKHR _surface, - const VkAllocationCallbacks *alloc, VkBool32* pSupported) { ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface); struct wsi_interface *iface = wsi_device->wsi[surface->platform]; - return iface->get_support(surface, wsi_device, alloc, - queueFamilyIndex, local_fd, pSupported); + return iface->get_support(surface, wsi_device, + queueFamilyIndex, pSupported); } VkResult @@ -510,7 +815,16 @@ wsi_common_get_surface_capabilities(struct wsi_device *wsi_device, ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface); struct wsi_interface *iface = wsi_device->wsi[surface->platform]; - return iface->get_capabilities(surface, pSurfaceCapabilities); + VkSurfaceCapabilities2KHR caps2 = { + .sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR, + }; + + VkResult result = iface->get_capabilities2(surface, wsi_device, NULL, &caps2); + + if (result == VK_SUCCESS) + *pSurfaceCapabilities = caps2.surfaceCapabilities; + + return result; } VkResult @@ -521,10 +835,55 @@ wsi_common_get_surface_capabilities2(struct wsi_device *wsi_device, ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pSurfaceInfo->surface); struct wsi_interface *iface = wsi_device->wsi[surface->platform]; - return iface->get_capabilities2(surface, pSurfaceInfo->pNext, + return iface->get_capabilities2(surface, wsi_device, pSurfaceInfo->pNext, pSurfaceCapabilities); } +VkResult +wsi_common_get_surface_capabilities2ext( + struct wsi_device *wsi_device, + VkSurfaceKHR _surface, + VkSurfaceCapabilities2EXT *pSurfaceCapabilities) +{ + ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface); + struct wsi_interface *iface = wsi_device->wsi[surface->platform]; + + assert(pSurfaceCapabilities->sType == + VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT); + + struct wsi_surface_supported_counters counters = { + .sType = VK_STRUCTURE_TYPE_WSI_SURFACE_SUPPORTED_COUNTERS_MESA, + .pNext = pSurfaceCapabilities->pNext, + .supported_surface_counters = 0, + }; + + VkSurfaceCapabilities2KHR caps2 = { + .sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR, + .pNext = &counters, + }; + + VkResult result = iface->get_capabilities2(surface, wsi_device, NULL, &caps2); + + if (result == VK_SUCCESS) { + VkSurfaceCapabilities2EXT *ext_caps = pSurfaceCapabilities; + VkSurfaceCapabilitiesKHR khr_caps = caps2.surfaceCapabilities; + + ext_caps->minImageCount = khr_caps.minImageCount; + ext_caps->maxImageCount = khr_caps.maxImageCount; + ext_caps->currentExtent = khr_caps.currentExtent; + ext_caps->minImageExtent = khr_caps.minImageExtent; + ext_caps->maxImageExtent = khr_caps.maxImageExtent; + ext_caps->maxImageArrayLayers = khr_caps.maxImageArrayLayers; + ext_caps->supportedTransforms = khr_caps.supportedTransforms; + ext_caps->currentTransform = khr_caps.currentTransform; + ext_caps->supportedCompositeAlpha = khr_caps.supportedCompositeAlpha; + ext_caps->supportedUsageFlags = khr_caps.supportedUsageFlags; + ext_caps->supportedSurfaceCounters = counters.supported_surface_counters; + } + + return result; +} + VkResult wsi_common_get_surface_formats(struct wsi_device *wsi_device, VkSurfaceKHR _surface, @@ -564,10 +923,22 @@ wsi_common_get_surface_present_modes(struct wsi_device *wsi_device, pPresentModes); } +VkResult +wsi_common_get_present_rectangles(struct wsi_device *wsi_device, + VkSurfaceKHR _surface, + uint32_t* pRectCount, + VkRect2D* pRects) +{ + ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface); + struct wsi_interface *iface = wsi_device->wsi[surface->platform]; + + return iface->get_present_rectangles(surface, wsi_device, + pRectCount, pRects); +} + VkResult wsi_common_create_swapchain(struct wsi_device *wsi, VkDevice device, - int fd, const VkSwapchainCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchain) @@ -576,12 +947,21 @@ wsi_common_create_swapchain(struct wsi_device *wsi, struct wsi_interface *iface = wsi->wsi[surface->platform]; struct wsi_swapchain *swapchain; - VkResult result = iface->create_swapchain(surface, device, wsi, fd, + VkResult result = iface->create_swapchain(surface, device, wsi, pCreateInfo, pAllocator, &swapchain); if (result != VK_SUCCESS) return result; + swapchain->fences = vk_zalloc(pAllocator, + sizeof (*swapchain->fences) * swapchain->image_count, + sizeof (*swapchain->fences), + VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + if (!swapchain->fences) { + swapchain->destroy(swapchain, pAllocator); + return VK_ERROR_OUT_OF_HOST_MEMORY; + } + *pSwapchain = wsi_swapchain_to_handle(swapchain); return VK_SUCCESS; @@ -617,17 +997,14 @@ wsi_common_get_images(VkSwapchainKHR _swapchain, } VkResult -wsi_common_acquire_next_image(const struct wsi_device *wsi, - VkDevice device, - VkSwapchainKHR _swapchain, - uint64_t timeout, - VkSemaphore semaphore, - uint32_t *pImageIndex) +wsi_common_acquire_next_image2(const struct wsi_device *wsi, + VkDevice device, + const VkAcquireNextImageInfoKHR *pAcquireInfo, + uint32_t *pImageIndex) { - WSI_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain); + WSI_FROM_HANDLE(wsi_swapchain, swapchain, pAcquireInfo->swapchain); - return swapchain->acquire_next_image(swapchain, timeout, - semaphore, pImageIndex); + return swapchain->acquire_next_image(swapchain, pAcquireInfo, pImageIndex); } VkResult @@ -644,9 +1021,10 @@ wsi_common_queue_present(const struct wsi_device *wsi, for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) { WSI_FROM_HANDLE(wsi_swapchain, swapchain, pPresentInfo->pSwapchains[i]); + uint32_t image_index = pPresentInfo->pImageIndices[i]; VkResult result; - if (swapchain->fences[0] == VK_NULL_HANDLE) { + if (swapchain->fences[image_index] == VK_NULL_HANDLE) { const VkFenceCreateInfo fence_info = { .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, .pNext = NULL, @@ -654,11 +1032,14 @@ wsi_common_queue_present(const struct wsi_device *wsi, }; result = wsi->CreateFence(device, &fence_info, &swapchain->alloc, - &swapchain->fences[0]); + &swapchain->fences[image_index]); if (result != VK_SUCCESS) goto fail_present; } else { - wsi->ResetFences(device, 1, &swapchain->fences[0]); + wsi->WaitForFences(device, 1, &swapchain->fences[image_index], + true, 1); + + wsi->ResetFences(device, 1, &swapchain->fences[image_index]); } VkSubmitInfo submit_info = { @@ -671,8 +1052,8 @@ wsi_common_queue_present(const struct wsi_device *wsi, /* We only need/want to wait on semaphores once. After that, we're * guaranteed ordering since it all happens on the same queue. */ - submit_info.waitSemaphoreCount = pPresentInfo->waitSemaphoreCount, - submit_info.pWaitSemaphores = pPresentInfo->pWaitSemaphores, + submit_info.waitSemaphoreCount = pPresentInfo->waitSemaphoreCount; + submit_info.pWaitSemaphores = pPresentInfo->pWaitSemaphores; /* Set up the pWaitDstStageMasks */ stage_flags = vk_alloc(&swapchain->alloc, @@ -695,13 +1076,13 @@ wsi_common_queue_present(const struct wsi_device *wsi, * command buffer is attached to the image. */ struct wsi_image *image = - swapchain->get_wsi_image(swapchain, pPresentInfo->pImageIndices[i]); + swapchain->get_wsi_image(swapchain, image_index); submit_info.commandBufferCount = 1; submit_info.pCommandBuffers = &image->prime.blit_cmd_buffers[queue_family_index]; } - result = wsi->QueueSubmit(queue, 1, &submit_info, swapchain->fences[0]); + result = wsi->QueueSubmit(queue, 1, &submit_info, swapchain->fences[image_index]); vk_free(&swapchain->alloc, stage_flags); if (result != VK_SUCCESS) goto fail_present; @@ -710,21 +1091,10 @@ wsi_common_queue_present(const struct wsi_device *wsi, if (regions && regions->pRegions) region = ®ions->pRegions[i]; - result = swapchain->queue_present(swapchain, - pPresentInfo->pImageIndices[i], - region); + result = swapchain->queue_present(swapchain, image_index, region); if (result != VK_SUCCESS) goto fail_present; - VkFence last = swapchain->fences[2]; - swapchain->fences[2] = swapchain->fences[1]; - swapchain->fences[1] = swapchain->fences[0]; - swapchain->fences[0] = last; - - if (last != VK_NULL_HANDLE) { - wsi->WaitForFences(device, 1, &last, true, 1); - } - fail_present: if (pPresentInfo->pResults != NULL) pPresentInfo->pResults[i] = result; @@ -736,3 +1106,11 @@ wsi_common_queue_present(const struct wsi_device *wsi, return final_result; } + +uint64_t +wsi_common_get_current_time(void) +{ + struct timespec current; + clock_gettime(CLOCK_MONOTONIC, ¤t); + return current.tv_nsec + current.tv_sec * 1000000000ull; +}