VkResult swapchain::create_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);
if (res != VK_SUCCESS)
{
void swapchain::destroy_image(wsi::swapchain_image &image)
{
+ std::unique_lock<std::recursive_mutex> image_status_lock(m_image_status_mutex);
if (image.status != wsi::swapchain_image::INVALID)
{
if (image.present_fence != VK_NULL_HANDLE)
m_device_data.disp.DestroyImage(m_device, image.image, get_allocation_callbacks());
image.image = VK_NULL_HANDLE;
}
+
+ image.status = wsi::swapchain_image::INVALID;
}
+ image_status_lock.unlock();
+
if (image.data != nullptr)
{
auto *data = reinterpret_cast<image_data *>(image.data);
image.data = nullptr;
}
- image.status = wsi::swapchain_image::INVALID;
}
} /* namespace headless */
continue;
}
+ std::unique_lock<std::recursive_mutex> image_status_lock(m_image_status_mutex);
+
/* If the descendant has started presenting the queue_present operation has marked the image
* as FREE so we simply release it and continue. */
if (sc_images[pending_index].status == swapchain_image::FREE)
m_free_image_semaphore.post();
continue;
}
+ image_status_lock.unlock();
/* First present of the swapchain. If it has an ancestor, wait until all the pending buffers
* from the ancestor have finished page flipping before we set mode. */
void swapchain_base::unpresent_image(uint32_t presented_index)
{
+ std::unique_lock<std::recursive_mutex> image_status_lock(m_image_status_mutex);
+
m_swapchain_images[presented_index].status = swapchain_image::FREE;
if (m_descendant != VK_NULL_HANDLE)
{
destroy_image(m_swapchain_images[presented_index]);
}
-
+ image_status_lock.unlock();
m_free_image_semaphore.post();
}
{
/* This method will block until all resources associated with this swapchain
* are released. Images in the ACQUIRED or FREE state can be freed
- * immediately. For images in the PRESENTED state, we will block until the
+ * immediately. For images in the PENDING state, we will block until the
* presentation engine is finished with them. */
int res;
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
+ std::unique_lock<std::recursive_mutex> image_status_lock(m_image_status_mutex);
+
uint32_t i;
for (i = 0; i < m_swapchain_images.size(); ++i)
{
assert(i < m_swapchain_images.size());
+ image_status_lock.unlock();
+
if (VK_NULL_HANDLE != semaphore || VK_NULL_HANDLE != fence)
{
VkSubmitInfo submit = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
{
VkResult result;
bool descendent_started_presenting = false;
+ const std::lock_guard<std::recursive_mutex> lock(m_image_status_mutex);
if (m_descendant != VK_NULL_HANDLE)
{
m_pending_buffer_pool.ring[m_pending_buffer_pool.tail] = image_index;
m_pending_buffer_pool.tail = (m_pending_buffer_pool.tail + 1) % m_pending_buffer_pool.size;
-
m_page_flip_semaphore.post();
return VK_ERROR_OUT_OF_DATE_KHR;
void swapchain_base::wait_for_pending_buffers()
{
- int num_acquired_images = 0;
int wait;
+ int pending_images = 0;
+
+ std::unique_lock<std::recursive_mutex> image_status_lock(m_image_status_mutex);
for (auto& img : m_swapchain_images)
{
- if (img.status == swapchain_image::ACQUIRED)
+ if (img.status == swapchain_image::PENDING)
{
- ++num_acquired_images;
+ ++pending_images;
}
}
- /* Once all the pending buffers are flipped, the swapchain should have images
- * in ACQUIRED (application fails to queue them back for presentation), FREE
- * and one and only one in PRESENTED. */
- wait = m_swapchain_images.size() - num_acquired_images - 1;
+ wait = pending_images;
+ image_status_lock.unlock();
while (wait > 0)
{
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
+ std::unique_lock<std::recursive_mutex> image_status_lock(m_image_status_mutex);
+
image.data = image_data;
image.status = swapchain_image::FREE;
VkResult result = allocate_image(image_create_info, image_data, &image.image);
+
+ image_status_lock.unlock();
+
if (result != VK_SUCCESS)
{
WSI_LOG_ERROR("Failed to allocate image.");
void swapchain::destroy_image(swapchain_image &image)
{
+ std::unique_lock<std::recursive_mutex> image_status_lock(m_image_status_mutex);
+
if (image.status != swapchain_image::INVALID)
{
if (image.present_fence != VK_NULL_HANDLE)
m_device_data.disp.DestroyImage(m_device, image.image, get_allocation_callbacks());
image.image = VK_NULL_HANDLE;
}
+
+ image.status = swapchain_image::INVALID;
}
+
+ image_status_lock.unlock();
+
if (image.data != nullptr)
{
auto image_data = reinterpret_cast<wayland_image_data *>(image.data);
m_allocator.destroy(1, image_data);
image.data = nullptr;
}
-
- image.status = swapchain_image::INVALID;
}
bool swapchain::free_image_found()