diff --git a/util/drm/drm_utils.cpp b/util/drm/drm_utils.cpp index 692f489..238459e 100644 --- a/util/drm/drm_utils.cpp +++ b/util/drm/drm_utils.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021 Arm Limited. + * Copyright (c) 2019, 2021, 2024 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -77,5 +77,47 @@ VkFormat drm_to_vk_srgb_format(uint32_t drm_format) return VK_FORMAT_UNDEFINED; } +/* Returns the number of planes represented by a fourcc format. */ +uint32_t drm_fourcc_format_get_num_planes(uint32_t format) +{ + switch (format) + { + default: + return 0; + + case DRM_FORMAT_RGB332: + case DRM_FORMAT_BGR233: + case DRM_FORMAT_XRGB4444: + case DRM_FORMAT_XBGR4444: + case DRM_FORMAT_RGBX4444: + case DRM_FORMAT_BGRX4444: + case DRM_FORMAT_ARGB4444: + case DRM_FORMAT_ABGR4444: + case DRM_FORMAT_RGBA4444: + case DRM_FORMAT_BGRA4444: + case DRM_FORMAT_XRGB1555: + case DRM_FORMAT_XBGR1555: + case DRM_FORMAT_RGBX5551: + case DRM_FORMAT_BGRX5551: + case DRM_FORMAT_ARGB1555: + case DRM_FORMAT_ABGR1555: + case DRM_FORMAT_RGBA5551: + case DRM_FORMAT_BGRA5551: + case DRM_FORMAT_RGB565: + case DRM_FORMAT_BGR565: + case DRM_FORMAT_RGB888: + case DRM_FORMAT_BGR888: + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_RGBX8888: + case DRM_FORMAT_BGRX8888: + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_ABGR8888: + case DRM_FORMAT_RGBA8888: + case DRM_FORMAT_BGRA8888: + return 1; + } +} + } // namespace drm } // namespace util diff --git a/util/drm/drm_utils.hpp b/util/drm/drm_utils.hpp index e523c00..4ec9edf 100644 --- a/util/drm/drm_utils.hpp +++ b/util/drm/drm_utils.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021-2022 Arm Limited. + * Copyright (c) 2019, 2021-2022, 2024 Arm Limited. * * SPDX-License-Identifier: MIT * @@ -34,6 +34,7 @@ namespace drm uint32_t vk_to_drm_format(VkFormat vk_format); VkFormat drm_to_vk_format(uint32_t drm_format); VkFormat drm_to_vk_srgb_format(uint32_t drm_format); +uint32_t drm_fourcc_format_get_num_planes(uint32_t format); } // namespace drm } // namespace util diff --git a/wsi/external_memory.cpp b/wsi/external_memory.cpp index f186036..630681f 100644 --- a/wsi/external_memory.cpp +++ b/wsi/external_memory.cpp @@ -31,6 +31,7 @@ #include "util/log.hpp" #include "util/helpers.hpp" +#include "util/drm/drm_utils.hpp" namespace wsi { @@ -64,43 +65,26 @@ external_memory::~external_memory() uint32_t external_memory::get_num_planes() { - if (m_num_planes == 0) - { - for (uint32_t plane = 0; plane < MAX_PLANES; plane++) - { - if (m_strides[plane] == -1) - { - break; - } - m_num_planes++; - } - } return m_num_planes; } +uint32_t external_memory::get_num_memories() +{ + return m_num_memories; +} + bool external_memory::is_disjoint() { - uint32_t planes = get_num_planes(); - if (planes > 1) - { - for (uint32_t plane = 1; plane < planes; ++plane) - { - if (m_buffer_fds[plane] != m_buffer_fds[0]) - { - return true; - } - } - } - return false; + return m_num_memories != 1; } -VkResult external_memory::get_fd_mem_type_index(uint32_t index, uint32_t *mem_idx) +VkResult external_memory::get_fd_mem_type_index(int fd, uint32_t *mem_idx) { auto &device_data = layer::device_private_data::get(m_device); VkMemoryFdPropertiesKHR mem_props = {}; mem_props.sType = VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR; - TRY_LOG(device_data.disp.GetMemoryFdPropertiesKHR(m_device, m_handle_type, m_buffer_fds[index], &mem_props), + TRY_LOG(device_data.disp.GetMemoryFdPropertiesKHR(m_device, m_handle_type, fd, &mem_props), "Error querying file descriptor properties"); for (*mem_idx = 0; *mem_idx < VK_MAX_MEMORY_TYPES; (*mem_idx)++) @@ -120,25 +104,27 @@ VkResult external_memory::import_plane_memories() { if (is_disjoint()) { + uint32_t memory_plane = 0; for (uint32_t plane = 0; plane < get_num_planes(); plane++) { auto it = std::find(std::begin(m_buffer_fds), std::end(m_buffer_fds), m_buffer_fds[plane]); if (std::distance(std::begin(m_buffer_fds), it) == plane) { - TRY_LOG_CALL(import_plane_memory(plane)); + TRY_LOG_CALL(import_plane_memory(m_buffer_fds[plane], &m_memories[memory_plane])); + memory_plane++; } } return VK_SUCCESS; } - return import_plane_memory(0); + return import_plane_memory(m_buffer_fds[0], &m_memories[0]); } -VkResult external_memory::import_plane_memory(uint32_t index) +VkResult external_memory::import_plane_memory(int fd, VkDeviceMemory *memory) { uint32_t mem_index = 0; - TRY_LOG_CALL(get_fd_mem_type_index(index, &mem_index)); + TRY_LOG_CALL(get_fd_mem_type_index(fd, &mem_index)); - const off_t fd_size = lseek(m_buffer_fds[index], 0, SEEK_END); + const off_t fd_size = lseek(fd, 0, SEEK_END); if (fd_size < 0) { WSI_LOG_ERROR("Failed to get fd size."); @@ -148,7 +134,7 @@ VkResult external_memory::import_plane_memory(uint32_t index) VkImportMemoryFdInfoKHR import_mem_info = {}; import_mem_info.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR; import_mem_info.handleType = m_handle_type; - import_mem_info.fd = m_buffer_fds[index]; + import_mem_info.fd = fd; VkMemoryAllocateInfo alloc_info = {}; alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; @@ -157,9 +143,8 @@ VkResult external_memory::import_plane_memory(uint32_t index) alloc_info.memoryTypeIndex = mem_index; auto &device_data = layer::device_private_data::get(m_device); - TRY_LOG( - device_data.disp.AllocateMemory(m_device, &alloc_info, m_allocator.get_original_callbacks(), &m_memories[index]), - "Failed to import device memory"); + TRY_LOG(device_data.disp.AllocateMemory(m_device, &alloc_info, m_allocator.get_original_callbacks(), memory), + "Failed to import device memory"); return VK_SUCCESS; } @@ -170,20 +155,19 @@ VkResult external_memory::bind_swapchain_image_memory(const VkImage &image) if (is_disjoint()) { util::vector bind_img_mem_infos(m_allocator); - if (!bind_img_mem_infos.try_resize(get_num_planes())) + if (!bind_img_mem_infos.try_resize(get_num_memories())) { return VK_ERROR_OUT_OF_HOST_MEMORY; } util::vector bind_plane_mem_infos(m_allocator); - if (!bind_plane_mem_infos.try_resize(get_num_planes())) + if (!bind_plane_mem_infos.try_resize(get_num_memories())) { return VK_ERROR_OUT_OF_HOST_MEMORY; } - for (uint32_t plane = 0; plane < get_num_planes(); plane++) + for (uint32_t plane = 0; plane < get_num_memories(); plane++) { - bind_plane_mem_infos[plane].planeAspect = util::PLANE_FLAG_BITS[plane]; bind_plane_mem_infos[plane].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO; bind_plane_mem_infos[plane].pNext = nullptr; @@ -230,7 +214,7 @@ void external_memory::fill_drm_mod_info(const void *pNext, VkImageDrmFormatModif drm_mod_info.sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT; drm_mod_info.pNext = pNext; drm_mod_info.drmFormatModifier = modifier; - drm_mod_info.drmFormatModifierPlaneCount = get_num_planes(); + drm_mod_info.drmFormatModifierPlaneCount = get_num_memories(); drm_mod_info.pPlaneLayouts = plane_layouts.data(); } diff --git a/wsi/external_memory.hpp b/wsi/external_memory.hpp index 44efdc1..757949c 100644 --- a/wsi/external_memory.hpp +++ b/wsi/external_memory.hpp @@ -119,8 +119,13 @@ public: uint32_t get_num_planes(void); /** - * @brief Returns whether the external memory uses a multi-planar format where each plane is separately bound to - * memory. + * @brief Get the number of memory planes the format uses. + */ + uint32_t get_num_memories(void); + + /** + * @brief Returns whether the external memory uses a multi-planar format where each plane is + * separately bound to memory or not. */ bool is_disjoint(void); @@ -132,6 +137,31 @@ public: m_handle_type = handle_type; } + /** + * @brief Set the number of memory planes. + */ + void set_num_memories(uint32_t num_memory_planes) + { + m_num_memories = num_memory_planes; + } + + /** + * @brief Set the number of format planes and set the number of memory planes + * if is_disjoint is false. + * + * @param is_disjoint If memory planes are disjoined. + * @param planes_count The number of format planes. + */ + void set_format_info(const bool is_disjoint, uint32_t planes_count) + { + m_num_planes = planes_count; + + if (!is_disjoint) + { + m_num_memories = 1; + } + } + /** * @brief Binds the external memory to a swapchain image. * @@ -183,11 +213,11 @@ public: void fill_external_info(VkExternalMemoryImageCreateInfoKHR &external_info, void *pNext); private: - VkResult get_fd_mem_type_index(uint32_t index, uint32_t *mem_idx); + VkResult get_fd_mem_type_index(int fd, uint32_t *mem_idx); VkResult import_plane_memories(void); - VkResult import_plane_memory(uint32_t index); + VkResult import_plane_memory(int fd, VkDeviceMemory *memory); std::array m_buffer_fds{ -1, -1, -1, -1 }; std::array m_strides{ 0, 0, 0, 0 }; @@ -195,6 +225,7 @@ private: std::array m_memories = { VK_NULL_HANDLE, VK_NULL_HANDLE, VK_NULL_HANDLE, VK_NULL_HANDLE }; uint32_t m_num_planes{ 0 }; + uint32_t m_num_memories{ 0 }; VkExternalMemoryHandleTypeFlagBits m_handle_type{ VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT }; const VkDevice &m_device; const util::allocator &m_allocator; diff --git a/wsi/wayland/swapchain.cpp b/wsi/wayland/swapchain.cpp index 830a792..e044f11 100644 --- a/wsi/wayland/swapchain.cpp +++ b/wsi/wayland/swapchain.cpp @@ -136,12 +136,9 @@ static struct wl_buffer_listener buffer_listener = { buffer_release }; VkResult swapchain::get_surface_compatible_formats(const VkImageCreateInfo &info, util::vector &importable_formats, - util::vector &exportable_modifers) + util::vector &exportable_modifers, + util::vector &drm_format_props) { - /* Query supported modifers. */ - util::vector drm_format_props( - util::allocator(m_allocator, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND)); - TRY_LOG(util::get_drm_format_properties(m_device_data.physical_device, info.format, drm_format_props), "Failed to get format properties"); @@ -299,6 +296,28 @@ VkResult swapchain::allocate_wsialloc(VkImageCreateInfo &image_create_info, wayl external_memory.set_strides(alloc_result.average_row_strides); external_memory.set_buffer_fds(alloc_result.buffer_fds); external_memory.set_offsets(alloc_result.offsets); + + uint32_t num_planes = util::drm::drm_fourcc_format_get_num_planes(alloc_result.format.fourcc); + + if (!avoid_allocation) + { + uint32_t num_memory_planes = 0; + + for (uint32_t i = 0; i < num_planes; ++i) + { + auto it = std::find(std::begin(alloc_result.buffer_fds) + i + 1, std::end(alloc_result.buffer_fds), + alloc_result.buffer_fds[i]); + if (it == std::end(alloc_result.buffer_fds)) + { + num_memory_planes++; + } + } + + assert(alloc_result.is_disjoint == (num_memory_planes > 1)); + external_memory.set_num_memories(num_memory_planes); + } + + external_memory.set_format_info(alloc_result.is_disjoint, num_planes); external_memory.set_memory_handle_type(VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT); return VK_SUCCESS; } @@ -408,7 +427,13 @@ VkResult swapchain::create_swapchain_image(VkImageCreateInfo image_create_info, util::vector importable_formats( util::allocator(m_allocator, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND)); util::vector exportable_modifiers(util::allocator(m_allocator, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND)); - TRY_LOG_CALL(get_surface_compatible_formats(image_create_info, importable_formats, exportable_modifiers)); + + /* Query supported modifers. */ + util::vector drm_format_props( + util::allocator(m_allocator, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND)); + + TRY_LOG_CALL( + get_surface_compatible_formats(image_create_info, importable_formats, exportable_modifiers, drm_format_props)); /* TODO: Handle exportable images which use ICD allocated memory in preference to an external allocator. */ if (importable_formats.empty()) @@ -420,6 +445,14 @@ VkResult swapchain::create_swapchain_image(VkImageCreateInfo image_create_info, wsialloc_format allocated_format = { 0 }; TRY_LOG_CALL(allocate_wsialloc(image_create_info, image_data, importable_formats, &allocated_format, true)); + for (auto &prop : drm_format_props) + { + if (prop.drmFormatModifier == allocated_format.modifier) + { + image_data->external_mem.set_num_memories(prop.drmFormatModifierPlaneCount); + } + } + TRY_LOG_CALL(fill_image_create_info( image_create_info, m_image_creation_parameters.m_image_layout, m_image_creation_parameters.m_drm_mod_info, m_image_creation_parameters.m_external_info, *image_data, allocated_format.modifier)); diff --git a/wsi/wayland/swapchain.hpp b/wsi/wayland/swapchain.hpp index f09da05..a73ce32 100644 --- a/wsi/wayland/swapchain.hpp +++ b/wsi/wayland/swapchain.hpp @@ -203,7 +203,8 @@ private: */ VkResult get_surface_compatible_formats(const VkImageCreateInfo &info, util::vector &importable_formats, - util::vector &exportable_modifers); + util::vector &exportable_modifers, + util::vector &drm_format_props); }; } // namespace wayland } // namespace wsi