diff --git a/CMakeLists.txt b/CMakeLists.txt index ac4f965..746bf1e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -283,7 +283,8 @@ add_library(${PROJECT_NAME} SHARED wsi/surface_properties.cpp wsi/swapchain_base.cpp wsi/synchronization.cpp - wsi/wsi_factory.cpp) + wsi/wsi_factory.cpp + wsi/swapchain_image_creator.cpp) if (VULKAN_WSI_LAYER_EXPERIMENTAL) target_sources(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/layer/present_timing_api.cpp) target_sources(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/wsi/extensions/present_timing.cpp) diff --git a/wsi/display/swapchain.cpp b/wsi/display/swapchain.cpp index 9b0fd9e..efd8e71 100644 --- a/wsi/display/swapchain.cpp +++ b/wsi/display/swapchain.cpp @@ -671,6 +671,16 @@ void swapchain::destroy_image(swapchain_image &image) } } +VkResult swapchain::get_required_image_creator_extensions( + const VkSwapchainCreateInfoKHR &swapchain_create_info, + util::vector> *extensions) +{ + UNUSED(swapchain_create_info); + UNUSED(extensions); + + return VK_SUCCESS; +} + } /* namespace display */ } /* namespace wsi*/ diff --git a/wsi/display/swapchain.hpp b/wsi/display/swapchain.hpp index 8709baa..3a3313a 100644 --- a/wsi/display/swapchain.hpp +++ b/wsi/display/swapchain.hpp @@ -110,6 +110,17 @@ public: void destroy_image(swapchain_image &image) override; +protected: + /** + * @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> *extensions) override; + private: VkResult allocate_image(display_image_data *image_data); diff --git a/wsi/headless/swapchain.cpp b/wsi/headless/swapchain.cpp index 0a484f7..9f2d64f 100644 --- a/wsi/headless/swapchain.cpp +++ b/wsi/headless/swapchain.cpp @@ -281,5 +281,15 @@ VkResult swapchain::bind_swapchain_image(VkDevice &device, const VkBindImageMemo return device_data.disp.BindImageMemory(device, bind_image_mem_info->image, memory, 0); } +VkResult swapchain::get_required_image_creator_extensions( + const VkSwapchainCreateInfoKHR &swapchain_create_info, + util::vector> *extensions) +{ + UNUSED(swapchain_create_info); + UNUSED(extensions); + + return VK_SUCCESS; +} + } /* namespace headless */ } /* namespace wsi */ diff --git a/wsi/headless/swapchain.hpp b/wsi/headless/swapchain.hpp index b6c5eb4..fdfe0a6 100644 --- a/wsi/headless/swapchain.hpp +++ b/wsi/headless/swapchain.hpp @@ -125,6 +125,16 @@ protected: 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> *extensions) override; + private: /** * @brief Adds required extensions to the extension list of the swapchain diff --git a/wsi/swapchain_base.cpp b/wsi/swapchain_base.cpp index 05491d8..2c129f0 100644 --- a/wsi/swapchain_base.cpp +++ b/wsi/swapchain_base.cpp @@ -225,6 +225,7 @@ swapchain_base::swapchain_base(layer::device_private_data &dev_data, const VkAll , m_error_state(VK_NOT_READY) , m_started_presenting(false) , m_extensions(m_allocator) + , m_image_creator(m_allocator) { } @@ -263,23 +264,8 @@ VkResult swapchain_base::init(VkDevice device, const VkSwapchainCreateInfoKHR *s TRY_LOG_CALL(init_page_flip_thread()); } - VkImageCreateInfo image_create_info = {}; - image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_create_info.pNext = nullptr; - image_create_info.imageType = VK_IMAGE_TYPE_2D; - image_create_info.format = swapchain_create_info->imageFormat; - image_create_info.extent = { swapchain_create_info->imageExtent.width, swapchain_create_info->imageExtent.height, - 1 }; - image_create_info.mipLevels = 1; - image_create_info.arrayLayers = swapchain_create_info->imageArrayLayers; - image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; - image_create_info.usage = swapchain_create_info->imageUsage; - image_create_info.flags = 0; - image_create_info.sharingMode = swapchain_create_info->imageSharingMode; - image_create_info.queueFamilyIndexCount = swapchain_create_info->queueFamilyIndexCount; - image_create_info.pQueueFamilyIndices = swapchain_create_info->pQueueFamilyIndices; - image_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + TRY_LOG_CALL(image_creator_init(*swapchain_create_info)); + m_image_create_info = m_image_creator.get_image_create_info(); VkResult result = m_free_image_semaphore.init(m_swapchain_images.size()); if (result != VK_SUCCESS) @@ -292,7 +278,7 @@ VkResult swapchain_base::init(VkDevice device, const VkSwapchainCreateInfoKHR *s swapchain_create_info->flags & VK_SWAPCHAIN_CREATE_DEFERRED_MEMORY_ALLOCATION_BIT_EXT; for (auto &img : m_swapchain_images) { - TRY(create_swapchain_image(image_create_info, img)); + TRY(create_swapchain_image(m_image_create_info, img)); if (image_deferred_allocation) { @@ -300,7 +286,7 @@ VkResult swapchain_base::init(VkDevice device, const VkSwapchainCreateInfoKHR *s } else { - TRY_LOG_CALL(allocate_and_bind_swapchain_image(image_create_info, img)); + TRY_LOG_CALL(allocate_and_bind_swapchain_image(m_image_create_info, img)); } VkSemaphoreCreateInfo semaphore_info = {}; @@ -784,4 +770,15 @@ bool swapchain_base::add_swapchain_extension(util::unique_ptr extension return m_extensions.add_extension(std::move(extension)); } +VkResult swapchain_base::image_creator_init(const VkSwapchainCreateInfoKHR &swapchain_create_info) +{ + m_image_creator.init(swapchain_create_info); + + util::vector> extensions(m_allocator); + TRY_LOG_CALL(get_required_image_creator_extensions(swapchain_create_info, &extensions)); + TRY_LOG_CALL(m_image_creator.add_extensions(&extensions)); + + return VK_SUCCESS; +} + } /* namespace wsi */ diff --git a/wsi/swapchain_base.hpp b/wsi/swapchain_base.hpp index 963fe30..ab93505 100644 --- a/wsi/swapchain_base.hpp +++ b/wsi/swapchain_base.hpp @@ -48,6 +48,7 @@ #include "extensions/frame_boundary.hpp" #include "extensions/wsi_extension.hpp" +#include "swapchain_image_creator.hpp" #include "util/macros.hpp" namespace wsi @@ -479,12 +480,22 @@ protected: return VK_SUCCESS; } + /** + * @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. + */ + virtual VkResult get_required_image_creator_extensions( + const VkSwapchainCreateInfoKHR &swapchain_create_info, + util::vector> *extensions) = 0; + /** * @brief Base swapchain teardown. * * Even though the inheritance gives us a nice way to defer display specific allocation * and presentation outside of the base class, it however robs the children classes - which - * also happen to do some of their state setting - the oppurtunity to do the last clean up + * also happen to do some of their state setting - the opportunity to do the last clean up * call, as the base class' destructor is called at the end. This method provides a way to do it. * The destructor is a virtual function and much of the swapchain teardown happens in this method * which gets called from the child's destructor. @@ -709,6 +720,18 @@ private: * @brief Holds the swapchain extensions and related functionalities. */ wsi_ext_maintainer m_extensions; + + /** + * @brief Holds the VkImageCreateInfo and backend specific image create info extensions. + */ + swapchain_image_creator m_image_creator; + + /** + * @brief Initialize m_image_creator. + * + * @param swapchain_create_info Swapchain create info. + */ + VkResult image_creator_init(const VkSwapchainCreateInfoKHR &swapchain_create_info); }; } /* namespace wsi */ diff --git a/wsi/swapchain_image_create_extensions/swapchain_image_create_info_extension.hpp b/wsi/swapchain_image_create_extensions/swapchain_image_create_info_extension.hpp new file mode 100644 index 0000000..7c46175 --- /dev/null +++ b/wsi/swapchain_image_create_extensions/swapchain_image_create_info_extension.hpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 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. + */ + +/** + * @file swapchain_image_create_info_extension.hpp + * + * @brief Base class for swapchain image create info extensions. + */ + +#pragma once + +#include + +namespace wsi +{ + +class swapchain_image_create_info_extension +{ +public: + /** + * @brief Extend image_create_info pNext with extension specific data. + * + * A swapchain image create info extension will use this function to add its + * extension specific data to pNext of image_create_info. + * + * @param[in, out] image_create_info VkImageCreateInfo for creating swapchain images + */ + virtual VkResult extend_image_create_info(VkImageCreateInfo *image_create_info) = 0; + + virtual ~swapchain_image_create_info_extension() = default; +}; + +} /* namespace wsi */ \ No newline at end of file diff --git a/wsi/swapchain_image_creator.cpp b/wsi/swapchain_image_creator.cpp new file mode 100644 index 0000000..5ae3b7f --- /dev/null +++ b/wsi/swapchain_image_creator.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (c) 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. + */ + +/** + * @file swapchain_image_creator.cpp + */ + +#include "swapchain_image_creator.hpp" +#include "swapchain_image_create_extensions/swapchain_image_create_info_extension.hpp" +#include "util/helpers.hpp" + +namespace wsi +{ + +void swapchain_image_creator::init(const VkSwapchainCreateInfoKHR &swapchain_create_info) +{ + m_image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + m_image_create_info.pNext = nullptr; + m_image_create_info.imageType = VK_IMAGE_TYPE_2D; + m_image_create_info.format = swapchain_create_info.imageFormat; + m_image_create_info.extent = { swapchain_create_info.imageExtent.width, swapchain_create_info.imageExtent.height, + 1 }; + m_image_create_info.mipLevels = 1; + m_image_create_info.arrayLayers = swapchain_create_info.imageArrayLayers; + m_image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; + m_image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL; + m_image_create_info.usage = swapchain_create_info.imageUsage; + m_image_create_info.flags = 0; + m_image_create_info.sharingMode = swapchain_create_info.imageSharingMode; + m_image_create_info.queueFamilyIndexCount = swapchain_create_info.queueFamilyIndexCount; + m_image_create_info.pQueueFamilyIndices = swapchain_create_info.pQueueFamilyIndices; + m_image_create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; +} + +VkResult swapchain_image_creator::add_extensions( + util::vector> *extensions) +{ + assert(extensions != nullptr); + + for (auto &extension : *extensions) + { + TRY(extension->extend_image_create_info(&m_image_create_info)); + + if (!m_extensions.try_push_back(std::move(extension))) + { + return VK_ERROR_OUT_OF_HOST_MEMORY; + } + } + + return VK_SUCCESS; +} + +} /* namespace wsi */ \ No newline at end of file diff --git a/wsi/swapchain_image_creator.hpp b/wsi/swapchain_image_creator.hpp new file mode 100644 index 0000000..651756a --- /dev/null +++ b/wsi/swapchain_image_creator.hpp @@ -0,0 +1,85 @@ +/* + * Copyright (c) 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. + */ + +/** + * @file swapchain_image_creator.hpp + */ + +#pragma once + +#include +#include +#include + +namespace wsi +{ + +/** + * @brief This class is responsible for owning and extending a swapchain's image + * creation info. + */ +class swapchain_image_creator +{ +public: + swapchain_image_creator(const util::allocator &allocator) + : m_image_create_info() + , m_extensions(allocator) + { + m_image_create_info.format = VK_FORMAT_UNDEFINED; + }; + + /** + * @brief Create image create info. + * + * @param swapchain_create_info Swapchain create info. + */ + void init(const VkSwapchainCreateInfoKHR &swapchain_create_info); + + /** + * @brief Extend create info with extension data/ + * + * @param extensions Swapchain image create info extensions. + * + * @return VK_SUCCESS on success, an appropriate error code on failure. + */ + VkResult add_extensions(util::vector> *extensions); + + VkImageCreateInfo get_image_create_info() const + { + return m_image_create_info; + } + +private: + /** + * @brief Image create info used for all swapchain images. + */ + VkImageCreateInfo m_image_create_info; + + /** + * @brief Swapchain image extensions needed for extending image create info. + */ + util::vector> m_extensions; +}; + +} /* namespace wsi */ \ No newline at end of file diff --git a/wsi/wayland/swapchain.cpp b/wsi/wayland/swapchain.cpp index 91cb23f..0d1e780 100644 --- a/wsi/wayland/swapchain.cpp +++ b/wsi/wayland/swapchain.cpp @@ -692,5 +692,15 @@ VkResult swapchain::bind_swapchain_image(VkDevice &device, const VkBindImageMemo return image_data->external_mem.bind_swapchain_image_memory(bind_image_mem_info->image); } +VkResult swapchain::get_required_image_creator_extensions( + const VkSwapchainCreateInfoKHR &swapchain_create_info, + util::vector> *extensions) +{ + UNUSED(swapchain_create_info); + UNUSED(extensions); + + return VK_SUCCESS; +} + } // namespace wayland } // namespace wsi diff --git a/wsi/wayland/swapchain.hpp b/wsi/wayland/swapchain.hpp index 951204b..1a94757 100644 --- a/wsi/wayland/swapchain.hpp +++ b/wsi/wayland/swapchain.hpp @@ -181,6 +181,16 @@ protected: 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> *extensions) override; + private: VkResult create_wl_buffer(const VkImageCreateInfo &image_create_info, swapchain_image &image, wayland_image_data *image_data);