vulkan-wsi-layer/wsi/wayland/swapchain.hpp
Iason Paraskevopoulos ca3820a0ba Add external memory extension
Adds a swapchain create info extension for creating an image using
external memory. This removes the need for modifying the
image_create_info in the display and wayland backends. There is still
code duplication left in these backends though, because swapchain
allocation needs to know the selected format. This will be removed when
the swapchain images will be created from the swapchain image creator.

Moves the definition of drm_format_pair to drm_utils.

Removes two step initialization from swapchain_wsi_allocator.

Change-Id: I0c937a59cc62e7e3134f0af4728fdda3739237bd
Signed-off-by: Iason Paraskevopoulos <iason.paraskevopoulos@arm.com>
2025-04-25 15:28:39 +01:00

248 lines
9.3 KiB
C++

/*
* Copyright (c) 2017-2025 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#pragma once
#include "wsi/swapchain_base.hpp"
#include "wl_helpers.hpp"
extern "C" {
#include <vulkan/vk_icd.h>
}
#ifndef __STDC_VERSION__
#define __STDC_VERSION__ 0
#endif
#include <wayland-client.h>
#include <linux-dmabuf-unstable-v1-client-protocol.h>
#include "surface.hpp"
#include "util/wsialloc/wsialloc.h"
#include "util/custom_allocator.hpp"
#include "wl_object_owner.hpp"
#include <wsi/wsi_alloc_utils.hpp>
#include <wsi/external_memory.hpp>
namespace wsi
{
namespace wayland
{
struct wayland_image_data
{
wayland_image_data(const VkDevice &device, const util::allocator &allocator)
: external_mem(device, allocator)
, buffer(nullptr)
{
}
external_memory external_mem;
wl_buffer *buffer;
sync_fd_fence_sync present_fence;
};
struct image_creation_parameters
{
wsialloc_format m_allocated_format;
util::vector<VkSubresourceLayout> m_image_layout;
VkExternalMemoryImageCreateInfoKHR m_external_info;
VkImageDrmFormatModifierExplicitCreateInfoEXT m_drm_mod_info;
image_creation_parameters(wsialloc_format allocated_format, util::allocator allocator,
VkExternalMemoryImageCreateInfoKHR external_info,
VkImageDrmFormatModifierExplicitCreateInfoEXT drm_mod_info)
: m_allocated_format(allocated_format)
, m_image_layout(allocator)
, m_external_info(external_info)
, m_drm_mod_info(drm_mod_info)
{
}
};
class swapchain : public wsi::swapchain_base
{
public:
explicit swapchain(layer::device_private_data &dev_data, const VkAllocationCallbacks *allocator,
surface &wsi_surface);
~swapchain();
/* TODO: make the buffer destructor a friend? so this can be protected */
void release_buffer(struct wl_buffer *wl_buffer);
protected:
/**
* @brief Initialize platform specifics.
*/
VkResult init_platform(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info,
bool &use_presentation_thread) override;
/**
* @brief Allocates and binds a new swapchain image.
*
* @param image_create_info Data to be used to create the image.
* @param image Handle to the image.
*
* @return Returns VK_SUCCESS on success, otherwise an appropriate error code.
*/
VkResult allocate_and_bind_swapchain_image(VkImageCreateInfo image_create_info, swapchain_image &image) override;
/**
* @brief Creates a new swapchain image.
*
* @param image_create_info Data to be used to create the image.
* @param image Handle to the image.
*
* @return If image creation is successful returns VK_SUCCESS, otherwise
* will return VK_ERROR_OUT_OF_DEVICE_MEMORY or VK_ERROR_INITIALIZATION_FAILED
* depending on the error that occurred.
*/
VkResult create_swapchain_image(VkImageCreateInfo image_create_info, swapchain_image &image) override;
/**
* @brief Method to present and image
*
* It sends the next image for presentation to the presentation engine.
*
* @param pending_present Information on the pending present request.
*/
void present_image(const pending_present_request &pending_present) override;
/**
* @brief Method to release a swapchain image
*
* @param image Handle to the image about to be released.
*/
void destroy_image(swapchain_image &image) override;
/**
* @brief Method to check if there are any free images
*
* @return true if any images are free, otherwise false.
*/
bool free_image_found();
/**
* @brief Hook for any actions to free up a buffer for acquire
*
* @param[in,out] timeout time to wait, in nanoseconds. 0 doesn't block,
* UINT64_MAX waits indefinitely. The timeout should
* be updated if a sleep is required - this can
* be set to 0 if the semaphore is now not expected
* block.
*/
VkResult get_free_buffer(uint64_t *timeout) override;
/**
* @brief Sets the present payload for a swapchain image.
*
* @param[in] image The swapchain image for which to set a present payload.
* @param queue A Vulkan queue that can be used for any Vulkan commands needed.
* @param[in] sem_payload Array of Vulkan semaphores that constitute the payload.
* @param[in] submission_pnext Chain of pointers to attach to the payload submission.
*
* @return VK_SUCCESS on success or an error code otherwise.
*/
VkResult image_set_present_payload(swapchain_image &image, VkQueue queue, const queue_submit_semaphores &semaphores,
const void *submission_pnext) override;
VkResult image_wait_present(swapchain_image &image, uint64_t timeout) override;
/**
* @brief Bind image to a swapchain
*
* @param device is the logical device that owns the images and memory.
* @param bind_image_mem_info details the image we want to bind.
* @param bind_sc_info describes the swapchain memory to bind to.
*
* @return VK_SUCCESS on success, otherwise on failure VK_ERROR_OUT_OF_HOST_MEMORY or VK_ERROR_OUT_OF_DEVICE_MEMORY
* can be returned.
*/
VkResult bind_swapchain_image(VkDevice &device, const VkBindImageMemoryInfo *bind_image_mem_info,
const VkBindImageMemorySwapchainInfoKHR *bind_sc_info) override;
/**
* @brief Get backend specific image create info extensions.
*
* @param swapchain_create_info Swapchain create info.
* @param[out] extensions Backend specific swapchain image create info extensions.
*/
VkResult get_required_image_creator_extensions(
const VkSwapchainCreateInfoKHR &swapchain_create_info,
util::vector<util::unique_ptr<swapchain_image_create_info_extension>> *extensions) override;
private:
VkResult create_wl_buffer(const VkImageCreateInfo &image_create_info, swapchain_image &image,
wayland_image_data *image_data);
VkResult allocate_image(wayland_image_data *image_data);
VkResult allocate_wsialloc(VkImageCreateInfo &image_create_info, wayland_image_data *image_data,
util::vector<wsialloc_format> &importable_formats, wsialloc_format *allocated_format,
bool avoid_allocation);
/**
* @brief Adds required extensions to the extension list of the swapchain
*
* @param device Vulkan device
* @param swapchain_create_info Swapchain create info
* @return VK_SUCCESS on success, other result codes on failure
*/
VkResult add_required_extensions(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info) override;
struct wl_display *m_display;
struct wl_surface *m_surface;
/** Raw pointer to the WSI Surface that this swapchain was created from. The Vulkan specification ensures that the
* surface is valid until swapchain is destroyed. */
surface *m_wsi_surface;
/* The queue on which we dispatch buffer related events, mostly buffer_release */
struct wl_event_queue *m_buffer_queue;
/**
* @brief Handle to the WSI allocator.
*/
util::unique_ptr<swapchain_wsialloc_allocator> m_wsi_allocator;
/**
* @brief Image creation parameters used for all swapchain images.
*/
struct image_creation_parameters m_image_creation_parameters;
/**
* @brief Finds what formats are compatible with the requested swapchain image Vulkan Device and Wayland surface.
*
* @param info The Swapchain image creation info.
* @param[out] importable_formats A list of formats that can be imported to the Vulkan Device.
* @param[out] exportable_formats A list of formats that can be exported from the Vulkan Device.
*
* @return VK_SUCCESS or VK_ERROR_OUT_OF_HOST_MEMORY
*/
VkResult get_surface_compatible_formats(const VkImageCreateInfo &info,
util::vector<wsialloc_format> &importable_formats,
util::vector<uint64_t> &exportable_modifers,
util::vector<VkDrmFormatModifierPropertiesEXT> &drm_format_props);
};
} // namespace wayland
} // namespace wsi