summaryrefslogtreecommitdiff
path: root/wsi
diff options
context:
space:
mode:
authorDennis Tsiang <dennis.tsiang@arm.com>2021-09-23 15:35:51 +0100
committerDennis Tsiang <dennis.tsiang@arm.com>2021-09-23 15:35:51 +0100
commitb4db2258abda037fa39296bd19bfb96ffe4e72f5 (patch)
tree86a179feb75b319eb7c2cb912843847716ed5dcf /wsi
parent8808cc35baf820936b37baf397f269de97e8aab7 (diff)
downloadvulkan-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.cpp24
-rw-r--r--wsi/headless/swapchain.hpp32
-rw-r--r--wsi/swapchain_base.cpp2
-rw-r--r--wsi/swapchain_base.hpp32
-rw-r--r--wsi/wayland/swapchain.cpp280
-rw-r--r--wsi/wayland/swapchain.hpp66
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