diff options
author | Dennis Tsiang <dennis.tsiang@arm.com> | 2021-09-23 15:35:51 +0100 |
---|---|---|
committer | Dennis Tsiang <dennis.tsiang@arm.com> | 2021-09-23 15:35:51 +0100 |
commit | b4db2258abda037fa39296bd19bfb96ffe4e72f5 (patch) | |
tree | 86a179feb75b319eb7c2cb912843847716ed5dcf /wsi | |
parent | 8808cc35baf820936b37baf397f269de97e8aab7 (diff) | |
download | vulkan-wsi-layer-b4db2258abda037fa39296bd19bfb96ffe4e72f5.tar.gz vulkan-wsi-layer-b4db2258abda037fa39296bd19bfb96ffe4e72f5.tar.bz2 vulkan-wsi-layer-b4db2258abda037fa39296bd19bfb96ffe4e72f5.zip |
Add support for some Vulkan 1.1 structs
This commit adds support for VkBindImageMemorySwapchainInfoKHR and
VkImageSwapchainCreateInfoKHR.
Change-Id: I3d87cd7df380e59ceb386f08437c5d6f09dcee1f
Signed-off-by: Dennis Tsiang <dennis.tsiang@arm.com>
Diffstat (limited to 'wsi')
-rw-r--r-- | wsi/headless/swapchain.cpp | 24 | ||||
-rw-r--r-- | wsi/headless/swapchain.hpp | 32 | ||||
-rw-r--r-- | wsi/swapchain_base.cpp | 2 | ||||
-rw-r--r-- | wsi/swapchain_base.hpp | 32 | ||||
-rw-r--r-- | wsi/wayland/swapchain.cpp | 280 | ||||
-rw-r--r-- | wsi/wayland/swapchain.hpp | 66 |
6 files changed, 309 insertions, 127 deletions
diff --git a/wsi/headless/swapchain.cpp b/wsi/headless/swapchain.cpp index ed9a882..b1033e9 100644 --- a/wsi/headless/swapchain.cpp +++ b/wsi/headless/swapchain.cpp @@ -58,12 +58,17 @@ swapchain::~swapchain() teardown(); } -VkResult swapchain::create_image(VkImageCreateInfo image_create, wsi::swapchain_image &image) +VkResult swapchain::create_aliased_image_handle(const VkImageCreateInfo *image_create_info, VkImage *image) +{ + return m_device_data.disp.CreateImage(m_device, image_create_info, get_allocation_callbacks(), image); +} + +VkResult swapchain::create_and_bind_swapchain_image(VkImageCreateInfo image_create, wsi::swapchain_image &image) { VkResult res = VK_SUCCESS; const std::lock_guard<std::recursive_mutex> lock(m_image_status_mutex); - res = m_device_data.disp.CreateImage(m_device, &image_create, nullptr, &image.image); + res = m_device_data.disp.CreateImage(m_device, &image_create, get_allocation_callbacks(), &image.image); if (res != VK_SUCCESS) { return res; @@ -100,7 +105,7 @@ VkResult swapchain::create_image(VkImageCreateInfo image_create, wsi::swapchain_ image.data = reinterpret_cast<void *>(data); image.status = wsi::swapchain_image::FREE; - res = m_device_data.disp.AllocateMemory(m_device, &mem_info, nullptr, &data->memory); + res = m_device_data.disp.AllocateMemory(m_device, &mem_info, get_allocation_callbacks(), &data->memory); assert(VK_SUCCESS == res); if (res != VK_SUCCESS) { @@ -154,7 +159,7 @@ void swapchain::destroy_image(wsi::swapchain_image &image) auto *data = reinterpret_cast<image_data *>(image.data); if (data->memory != VK_NULL_HANDLE) { - m_device_data.disp.FreeMemory(m_device, data->memory, nullptr); + m_device_data.disp.FreeMemory(m_device, data->memory, get_allocation_callbacks()); data->memory = VK_NULL_HANDLE; } m_allocator.destroy(1, data); @@ -176,5 +181,16 @@ VkResult swapchain::image_wait_present(swapchain_image &image, uint64_t timeout) return data->present_fence.wait_payload(timeout); } +VkResult swapchain::bind_swapchain_image(VkDevice &device, const VkBindImageMemoryInfo *bind_image_mem_info, + const VkBindImageMemorySwapchainInfoKHR *bind_sc_info) +{ + auto &device_data = layer::device_private_data::get(device); + + const wsi::swapchain_image &swapchain_image = m_swapchain_images[bind_sc_info->imageIndex]; + VkDeviceMemory memory = reinterpret_cast<image_data *>(swapchain_image.data)->memory; + + return device_data.disp.BindImageMemory(device, bind_image_mem_info->image, memory, 0); +} + } /* namespace headless */ } /* namespace wsi */ diff --git a/wsi/headless/swapchain.hpp b/wsi/headless/swapchain.hpp index ded7e15..cadfb86 100644 --- a/wsi/headless/swapchain.hpp +++ b/wsi/headless/swapchain.hpp @@ -62,17 +62,28 @@ protected: }; /** - * @brief Creates a new swapchain image. + * @brief Creates a VkImage handle. * - * @param image_create_info Data to be used to create the image. + * @param image_create_info Data to be used to create the image. + * @param[out] image Handle to 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_OUT_OF_HOST_MEMORY + * depending on the error that occured. + */ + VkResult create_aliased_image_handle(const VkImageCreateInfo *image_create_info, VkImage *image) override; + + /** + * @brief Creates 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 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 occured. */ - VkResult create_image(VkImageCreateInfo image_create_info, wsi::swapchain_image &image); + VkResult create_and_bind_swapchain_image(VkImageCreateInfo image_create_info, wsi::swapchain_image &image) override; /** * @brief Method to perform a present - just calls unpresent_image on headless @@ -93,6 +104,19 @@ protected: uint32_t sem_count) 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; }; } /* namespace headless */ diff --git a/wsi/swapchain_base.cpp b/wsi/swapchain_base.cpp index 90369a2..c35c0ff 100644 --- a/wsi/swapchain_base.cpp +++ b/wsi/swapchain_base.cpp @@ -217,7 +217,7 @@ VkResult swapchain_base::init(VkDevice device, const VkSwapchainCreateInfoKHR *s for (auto& img : m_swapchain_images) { - result = create_image(image_create_info, img); + result = create_and_bind_swapchain_image(image_create_info, img); if (result != VK_SUCCESS) { return result; diff --git a/wsi/swapchain_base.hpp b/wsi/swapchain_base.hpp index 028f917..2443b86 100644 --- a/wsi/swapchain_base.hpp +++ b/wsi/swapchain_base.hpp @@ -144,6 +144,31 @@ public: return m_allocator; } + /** + * @brief Creates a VkImage handle. + * + * @param image_create_info Data to be used to create the image. + * @param[out] 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_OUT_OF_HOST_MEMORY + * depending on the error that occured. + */ + virtual VkResult create_aliased_image_handle(const VkImageCreateInfo *image_create_info, VkImage *image) = 0; + + /** + * @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. + */ + virtual VkResult bind_swapchain_image(VkDevice &device, const VkBindImageMemoryInfo *bind_image_mem_info, + const VkBindImageMemorySwapchainInfoKHR *bind_sc_info) = 0; + protected: layer::device_private_data &m_device_data; @@ -306,17 +331,16 @@ protected: void teardown(); /** - * @brief Creates a new swapchain image. + * @brief Creates and binds a new swapchain image. * * @param image_create_info Data to be used to create the image. - * - * @param image Handle to 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 occured. */ - virtual VkResult create_image(VkImageCreateInfo image_create_info, swapchain_image &image) = 0; + virtual VkResult create_and_bind_swapchain_image(VkImageCreateInfo image_create_info, swapchain_image &image) = 0; /** * @brief Method to present and image diff --git a/wsi/wayland/swapchain.cpp b/wsi/wayland/swapchain.cpp index e442d9f..59b73e6 100644 --- a/wsi/wayland/swapchain.cpp +++ b/wsi/wayland/swapchain.cpp @@ -40,6 +40,7 @@ #include "util/drm/drm_utils.hpp" #include "util/log.hpp" +#include "util/helpers.hpp" #define MAX_PLANES 4 @@ -67,6 +68,7 @@ struct swapchain::wayland_image_data uint32_t num_planes; sync_fd_fence_sync present_fence; + bool is_disjoint; }; swapchain::swapchain(layer::device_private_data &dev_data, const VkAllocationCallbacks *pAllocator, @@ -78,8 +80,10 @@ swapchain::swapchain(layer::device_private_data &dev_data, const VkAllocationCal , m_swapchain_queue(nullptr) , m_buffer_queue(nullptr) , m_wsi_allocator(nullptr) + , m_image_creation_parameters({}, {}, m_allocator, {}, {}) , m_present_pending(false) { + m_image_creation_parameters.m_image_create_info.format = VK_FORMAT_UNDEFINED; } swapchain::~swapchain() @@ -370,6 +374,35 @@ VkResult swapchain::get_surface_compatible_formats(const VkImageCreateInfo &info return VK_SUCCESS; } +VkResult swapchain::create_aliased_image_handle(const VkImageCreateInfo *image_create_info, VkImage *image) +{ + return m_device_data.disp.CreateImage(m_device, &m_image_creation_parameters.m_image_create_info, + get_allocation_callbacks(), image); +} + +VkResult swapchain::allocate_wsialloc(VkImageCreateInfo &image_create_info, wayland_image_data *image_data, + util::vector<wsialloc_format> importable_formats, + wsialloc_format *allocated_format) +{ + bool is_protected_memory = (image_create_info.flags & VK_IMAGE_CREATE_PROTECTED_BIT) != 0; + const uint64_t allocation_flags = is_protected_memory ? WSIALLOC_ALLOCATE_PROTECTED : 0; + wsialloc_allocate_info alloc_info = { importable_formats.data(), static_cast<unsigned>(importable_formats.size()), + image_create_info.extent.width, image_create_info.extent.height, + allocation_flags }; + const auto res = wsialloc_alloc(m_wsi_allocator, &alloc_info, allocated_format, image_data->stride, + image_data->buffer_fd, image_data->offset); + if (res != WSIALLOC_ERROR_NONE) + { + WSI_LOG_ERROR("Failed allocation of DMA Buffer. WSI error: %d", static_cast<int>(res)); + if (res == WSIALLOC_ERROR_NOT_SUPPORTED) + { + return VK_ERROR_FORMAT_NOT_SUPPORTED; + } + return VK_ERROR_OUT_OF_HOST_MEMORY; + } + return VK_SUCCESS; +} + VkResult swapchain::allocate_image(VkImageCreateInfo &image_create_info, wayland_image_data *image_data, VkImage *image) { image_data->buffer = nullptr; @@ -380,44 +413,54 @@ VkResult swapchain::allocate_image(VkImageCreateInfo &image_create_info, wayland image_data->memory[plane] = VK_NULL_HANDLE; } + bool is_disjoint = false; util::vector<wsialloc_format> importable_formats(util::allocator(m_allocator, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND)); - util::vector<uint64_t> exportable_modifiers(util::allocator(m_allocator, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND)); - VkResult result = get_surface_compatible_formats(image_create_info, importable_formats, exportable_modifiers); - if (result != VK_SUCCESS) + auto &m_image_create_info = m_image_creation_parameters.m_image_create_info; + auto &m_allocated_format = m_image_creation_parameters.m_allocated_format; + if (m_image_create_info.format != VK_FORMAT_UNDEFINED) { - return result; - } - - /* TODO: Handle exportable images which use ICD allocated memory in preference to an external allocator. */ - - if (importable_formats.empty()) - { - WSI_LOG_ERROR("Export/Import not supported."); - return VK_ERROR_INITIALIZATION_FAILED; + is_disjoint = (m_image_create_info.flags & VK_IMAGE_CREATE_DISJOINT_BIT) == VK_IMAGE_CREATE_DISJOINT_BIT; + if (!importable_formats.try_push_back(m_allocated_format)) + { + return VK_ERROR_OUT_OF_HOST_MEMORY; + } + VkResult result = allocate_wsialloc(m_image_create_info, image_data, importable_formats, &m_allocated_format); + if (result != VK_SUCCESS) + { + return result; + } + for (uint32_t plane = 0; plane < MAX_PLANES; plane++) + { + if (image_data->buffer_fd[plane] == -1) + { + break; + } + image_data->num_planes++; + } } else { - /* TODO: Handle Dedicated allocation bit. */ - bool is_protected_memory = (image_create_info.flags & VK_IMAGE_CREATE_PROTECTED_BIT) != 0; - const uint64_t allocation_flags = is_protected_memory ? WSIALLOC_ALLOCATE_PROTECTED : 0; - wsialloc_allocate_info alloc_info = { importable_formats.data(), static_cast<unsigned>(importable_formats.size()), - image_create_info.extent.width, image_create_info.extent.height, - allocation_flags }; + util::vector<uint64_t> exportable_modifiers(util::allocator(m_allocator, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND)); + VkResult result = get_surface_compatible_formats(image_create_info, importable_formats, exportable_modifiers); + if (result != VK_SUCCESS) + { + return result; + } + + /* TODO: Handle exportable images which use ICD allocated memory in preference to an external allocator. */ + if (importable_formats.empty()) + { + WSI_LOG_ERROR("Export/Import not supported."); + return VK_ERROR_INITIALIZATION_FAILED; + } wsialloc_format allocated_format = { 0 }; - const auto res = wsialloc_alloc(m_wsi_allocator, &alloc_info, &allocated_format, image_data->stride, - image_data->buffer_fd, image_data->offset); - if (res != WSIALLOC_ERROR_NONE) + result = allocate_wsialloc(image_create_info, image_data, importable_formats, &allocated_format); + if (result != VK_SUCCESS) { - WSI_LOG_ERROR("Failed allocation of DMA Buffer. WSI error: %d", static_cast<int>(res)); - if (res == WSIALLOC_ERROR_NOT_SUPPORTED) - { - return VK_ERROR_FORMAT_NOT_SUPPORTED; - } - return VK_ERROR_OUT_OF_HOST_MEMORY; + return result; } - bool is_disjoint = false; for (uint32_t plane = 0; plane < MAX_PLANES; plane++) { if (image_data->buffer_fd[plane] == -1) @@ -431,107 +474,79 @@ VkResult swapchain::allocate_image(VkImageCreateInfo &image_create_info, wayland image_data->num_planes++; } + auto &image_layout = m_image_creation_parameters.m_image_layout; + if (!image_layout.try_resize(image_data->num_planes)) { - util::vector<VkSubresourceLayout> image_layout( - util::allocator(m_allocator, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND)); - if (!image_layout.try_resize(image_data->num_planes)) - { - return VK_ERROR_OUT_OF_HOST_MEMORY; - } + return VK_ERROR_OUT_OF_HOST_MEMORY; + } - for (uint32_t plane = 0; plane < image_data->num_planes; plane++) - { - assert(image_data->stride[plane] >= 0); - image_layout[plane].offset = image_data->offset[plane]; - image_layout[plane].rowPitch = static_cast<uint32_t>(image_data->stride[plane]); - } + for (uint32_t plane = 0; plane < image_data->num_planes; plane++) + { + assert(image_data->stride[plane] >= 0); + image_layout[plane].offset = image_data->offset[plane]; + image_layout[plane].rowPitch = static_cast<uint32_t>(image_data->stride[plane]); + } - if (is_disjoint) - { - image_create_info.flags |= VK_IMAGE_CREATE_DISJOINT_BIT; - } + if (is_disjoint) + { + image_create_info.flags |= VK_IMAGE_CREATE_DISJOINT_BIT; + } - VkImageDrmFormatModifierExplicitCreateInfoEXT drm_mod_info = {}; - drm_mod_info.sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT; - drm_mod_info.pNext = image_create_info.pNext; - drm_mod_info.drmFormatModifier = allocated_format.modifier; - drm_mod_info.drmFormatModifierPlaneCount = image_data->num_planes; - drm_mod_info.pPlaneLayouts = image_layout.data(); + auto &drm_mod_info = m_image_creation_parameters.m_drm_mod_info; - VkExternalMemoryImageCreateInfoKHR external_info = {}; - external_info.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR; - external_info.pNext = &drm_mod_info; - external_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; + drm_mod_info.sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT; + drm_mod_info.pNext = image_create_info.pNext; + drm_mod_info.drmFormatModifier = allocated_format.modifier; + drm_mod_info.drmFormatModifierPlaneCount = image_data->num_planes; + drm_mod_info.pPlaneLayouts = image_layout.data(); - VkImageCreateInfo image_info = image_create_info; - image_info.pNext = &external_info; - image_info.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT; - result = m_device_data.disp.CreateImage(m_device, &image_info, get_allocation_callbacks(), image); - } - if (result != VK_SUCCESS) - { - WSI_LOG_ERROR("Image creation failed."); - return result; - } - { - if (is_disjoint) - { - util::vector<VkBindImageMemoryInfo> bind_img_mem_infos( - util::allocator(m_allocator, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND)); - if (!bind_img_mem_infos.try_resize(image_data->num_planes)) - { - return VK_ERROR_OUT_OF_HOST_MEMORY; - } + auto &external_info = m_image_creation_parameters.m_external_info; + external_info.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR; + external_info.pNext = &drm_mod_info; + external_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; - util::vector<VkBindImagePlaneMemoryInfo> bind_plane_mem_infos( - util::allocator(m_allocator, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND)); - if (!bind_plane_mem_infos.try_resize(image_data->num_planes)) - { - return VK_ERROR_OUT_OF_HOST_MEMORY; - } + m_image_create_info = image_create_info; + m_image_create_info.pNext = &external_info; + m_image_create_info.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT; - for (uint32_t plane = 0; plane < image_data->num_planes; plane++) - { - const auto fd_index = get_same_fd_index(image_data->buffer_fd[plane], image_data->buffer_fd); - if (fd_index == plane) - { - result = allocate_plane_memory(image_data->buffer_fd[plane], &image_data->memory[fd_index]); - if (result != VK_SUCCESS) - { - return result; - } - } - - bind_plane_mem_infos[plane].planeAspect = plane_flag_bits[plane]; - bind_plane_mem_infos[plane].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO; - bind_plane_mem_infos[plane].pNext = NULL; - - bind_img_mem_infos[plane].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO; - bind_img_mem_infos[plane].pNext = &bind_plane_mem_infos[plane]; - bind_img_mem_infos[plane].image = *image; - bind_img_mem_infos[plane].memory = image_data->memory[fd_index]; - } + m_allocated_format = allocated_format; + } + image_data->is_disjoint = is_disjoint; + VkResult result = m_device_data.disp.CreateImage(m_device, &m_image_create_info, get_allocation_callbacks(), image); + if (result != VK_SUCCESS) + { + WSI_LOG_ERROR("Image creation failed."); + return result; + } - result = - m_device_data.disp.BindImageMemory2KHR(m_device, bind_img_mem_infos.size(), bind_img_mem_infos.data()); - } - else + if (is_disjoint) + { + for (uint32_t plane = 0; plane < image_data->num_planes; plane++) + { + const auto fd_index = get_same_fd_index(image_data->buffer_fd[plane], image_data->buffer_fd); + if (fd_index == plane) { - result = allocate_plane_memory(image_data->buffer_fd[0], &image_data->memory[0]); + VkResult result = allocate_plane_memory(image_data->buffer_fd[plane], &image_data->memory[fd_index]); if (result != VK_SUCCESS) { return result; } - - result = m_device_data.disp.BindImageMemory(m_device, *image, image_data->memory[0], 0); } } } + else + { + VkResult result = allocate_plane_memory(image_data->buffer_fd[0], &image_data->memory[0]); + if (result != VK_SUCCESS) + { + return result; + } + } - return result; + return internal_bind_swapchain_image(m_device, image_data, *image); } -VkResult swapchain::create_image(VkImageCreateInfo image_create_info, swapchain_image &image) +VkResult swapchain::create_and_bind_swapchain_image(VkImageCreateInfo image_create_info, swapchain_image &image) { /* Create image_data */ auto image_data = m_allocator.create<wayland_image_data>(1); @@ -565,7 +580,6 @@ VkResult swapchain::create_image(VkImageCreateInfo image_create_info, swapchain_ } zwp_linux_buffer_params_v1 *params = zwp_linux_dmabuf_v1_create_params(dmabuf_interface_proxy.get()); - for (uint32_t plane = 0; plane < image_data->num_planes; plane++) { zwp_linux_buffer_params_v1_add(params, image_data->buffer_fd[plane], plane, @@ -815,5 +829,51 @@ VkResult swapchain::image_wait_present(swapchain_image &, uint64_t) return VK_SUCCESS; } +VkResult swapchain::internal_bind_swapchain_image(VkDevice &device, wayland_image_data *image_data, + const VkImage &image) +{ + auto &device_data = layer::device_private_data::get(device); + if (image_data->is_disjoint) + { + util::vector<VkBindImageMemoryInfo> bind_img_mem_infos(m_allocator); + if (!bind_img_mem_infos.try_resize(image_data->num_planes)) + { + return VK_ERROR_OUT_OF_HOST_MEMORY; + } + + util::vector<VkBindImagePlaneMemoryInfo> bind_plane_mem_infos(m_allocator); + if (!bind_plane_mem_infos.try_resize(image_data->num_planes)) + { + return VK_ERROR_OUT_OF_HOST_MEMORY; + } + + for (uint32_t plane = 0; plane < image_data->num_planes; plane++) + { + + bind_plane_mem_infos[plane].planeAspect = plane_flag_bits[plane]; + bind_plane_mem_infos[plane].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO; + bind_plane_mem_infos[plane].pNext = NULL; + + bind_img_mem_infos[plane].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO; + bind_img_mem_infos[plane].pNext = &bind_plane_mem_infos[plane]; + bind_img_mem_infos[plane].image = image; + bind_img_mem_infos[plane].memory = image_data->memory[plane]; + bind_img_mem_infos[plane].memoryOffset = image_data->offset[plane]; + } + + return device_data.disp.BindImageMemory2KHR(device, bind_img_mem_infos.size(), bind_img_mem_infos.data()); + } + + return device_data.disp.BindImageMemory(device, image, image_data->memory[0], image_data->offset[0]); +} + +VkResult swapchain::bind_swapchain_image(VkDevice &device, const VkBindImageMemoryInfo *bind_image_mem_info, + const VkBindImageMemorySwapchainInfoKHR *bind_sc_info) +{ + const wsi::swapchain_image &swapchain_image = m_swapchain_images[bind_sc_info->imageIndex]; + auto image_data = reinterpret_cast<wayland_image_data *>(swapchain_image.data); + return internal_bind_swapchain_image(device, image_data, bind_image_mem_info->image); +} + } // namespace wayland } // namespace wsi diff --git a/wsi/wayland/swapchain.hpp b/wsi/wayland/swapchain.hpp index 4f77176..4260866 100644 --- a/wsi/wayland/swapchain.hpp +++ b/wsi/wayland/swapchain.hpp @@ -34,6 +34,7 @@ extern "C" { #include <wayland-client.h> #include <linux-dmabuf-unstable-v1-client-protocol.h> #include "util/wsialloc/wsialloc.h" +#include "util/custom_allocator.hpp" #include "wl_object_owner.hpp" #include "surface.hpp" @@ -42,6 +43,26 @@ namespace wsi namespace wayland { +struct image_creation_parameters +{ + VkImageCreateInfo m_image_create_info; + wsialloc_format m_allocated_format; + util::vector<VkSubresourceLayout> m_image_layout; + VkExternalMemoryImageCreateInfoKHR m_external_info; + VkImageDrmFormatModifierExplicitCreateInfoEXT m_drm_mod_info; + + image_creation_parameters(VkImageCreateInfo image_create_info, wsialloc_format allocated_format, + util::allocator allocator, VkExternalMemoryImageCreateInfoKHR external_info, + VkImageDrmFormatModifierExplicitCreateInfoEXT drm_mod_info) + : m_image_create_info(image_create_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: @@ -60,17 +81,32 @@ protected: VkResult init_platform(VkDevice device, const VkSwapchainCreateInfoKHR *pSwapchainCreateInfo) override; /** - * @brief Creates a new swapchain image. + * @brief Creates a VkImage handle. * - * @param image_create_info Data to be used to create the image. + * The image_create_info argument is ignored in favour of m_image_create_info. This is because in + * order to guarantee a VkImage can be bound to any swapchain index, all swapchain images must + * be created with the same creation parameters. * - * @param image Handle to the image. + * @param image_create_info Data to be used to create the image. + * @param[out] 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_OUT_OF_HOST_MEMORY + * depending on the error that occured. + */ + VkResult create_aliased_image_handle(const VkImageCreateInfo *image_create_info, VkImage *image) override; + + /** + * @brief Creates 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 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_image(VkImageCreateInfo image_create_info, swapchain_image &image) override; + VkResult create_and_bind_swapchain_image(VkImageCreateInfo image_create_info, swapchain_image &image) override; /** * @brief Method to present an image @@ -109,10 +145,27 @@ protected: 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; + private: struct wayland_image_data; VkResult allocate_image(VkImageCreateInfo &image_create_info, wayland_image_data *image_data, VkImage *image); + VkResult allocate_wsialloc(VkImageCreateInfo &image_create_info, wayland_image_data *image_data, + util::vector<wsialloc_format> importable_formats, wsialloc_format *allocated_format); + VkResult internal_bind_swapchain_image(VkDevice &device, wayland_image_data *swapchain_image, + const VkImage &image); struct wl_display *m_display; struct wl_surface *m_surface; @@ -131,6 +184,11 @@ private: wsialloc_allocator *m_wsi_allocator; /** + * @brief Image creation parameters used for all swapchain images. + */ + struct image_creation_parameters m_image_creation_parameters; + + /** * @brief true when waiting for the server hint to present a buffer * * true if a buffer has been presented and we've not had a wl_surface::frame |