mirror of
https://gitlab.freedesktop.org/mesa/vulkan-wsi-layer.git
synced 2025-12-24 14:40:10 +01:00
Merge 'Improve wait_for_pending_buffers' into 'main'
See merge request mesa/vulkan-wsi-layer!175
This commit is contained in:
commit
8b7103e0e3
2 changed files with 33 additions and 16 deletions
|
|
@ -420,7 +420,7 @@ VkResult swapchain_base::acquire_next_image(uint64_t timeout, VkSemaphore semaph
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> acquire_lock(m_image_acquire_lock);
|
std::unique_lock<std::mutex> acquire_lock(m_image_acquire_lock);
|
||||||
|
|
||||||
TRY(wait_for_free_buffer(timeout));
|
TRY(wait_and_get_free_buffer(timeout));
|
||||||
if (error_has_occured())
|
if (error_has_occured())
|
||||||
{
|
{
|
||||||
return get_error_state();
|
return get_error_state();
|
||||||
|
|
@ -701,28 +701,44 @@ void swapchain_base::deprecate(VkSwapchainKHR descendant)
|
||||||
void swapchain_base::wait_for_pending_buffers()
|
void swapchain_base::wait_for_pending_buffers()
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> acquire_lock(m_image_acquire_lock);
|
std::unique_lock<std::mutex> acquire_lock(m_image_acquire_lock);
|
||||||
int wait;
|
|
||||||
int acquired_images = 0;
|
|
||||||
std::unique_lock<std::recursive_mutex> image_status_lock(m_image_status_mutex);
|
std::unique_lock<std::recursive_mutex> image_status_lock(m_image_status_mutex);
|
||||||
|
|
||||||
|
uint64_t non_pending_images = 0;
|
||||||
for (auto &img : m_swapchain_images)
|
for (auto &img : m_swapchain_images)
|
||||||
{
|
{
|
||||||
if (img.status == swapchain_image::ACQUIRED)
|
/*
|
||||||
|
* We don't want wait_and_get_free_buffer to be called when
|
||||||
|
* there are free images, because it will consume the semaphore
|
||||||
|
* and then subsequent calls might block if the semaphore value
|
||||||
|
* has reached to zero.
|
||||||
|
*/
|
||||||
|
if ((img.status == swapchain_image::ACQUIRED) || (img.status == swapchain_image::FREE) ||
|
||||||
|
(img.status == swapchain_image::INVALID))
|
||||||
{
|
{
|
||||||
acquired_images++;
|
/* If the image is acquired or free, it is not pending. */
|
||||||
|
non_pending_images++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Waiting for free images waits for both free and pending. One pending image may be presented and acquired by a
|
/*
|
||||||
* compositor. The WSI backend may not necessarily know which pending image is presented to change its state. It may
|
* One pending image may be presented and acquired by a
|
||||||
* be impossible to wait for that one presented image. */
|
* compositor. The WSI backend may not necessarily know which
|
||||||
wait = static_cast<int>(m_swapchain_images.size()) - acquired_images - 1;
|
* pending image is presented to change its state. It may
|
||||||
|
* be impossible to wait for that one presented image.
|
||||||
|
*/
|
||||||
|
int wait = static_cast<int>(m_swapchain_images.size() - non_pending_images - 1);
|
||||||
image_status_lock.unlock();
|
image_status_lock.unlock();
|
||||||
|
|
||||||
while (wait > 0)
|
while (wait > 0)
|
||||||
{
|
{
|
||||||
/* Take down one free image semaphore. */
|
/*
|
||||||
wait_for_free_buffer(UINT64_MAX);
|
* Take down one free image semaphore.
|
||||||
|
*
|
||||||
|
* In backends which unpresent an image only after a new one
|
||||||
|
* has been submitted for presentation wait_and_get_free_buffer
|
||||||
|
* could hang if the semaphore has a zero value and the swapchain has been deprecated.
|
||||||
|
*/
|
||||||
|
wait_and_get_free_buffer(UINT64_MAX);
|
||||||
--wait;
|
--wait;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -737,11 +753,10 @@ void swapchain_base::clear_descendant()
|
||||||
m_descendant = VK_NULL_HANDLE;
|
m_descendant = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkResult swapchain_base::wait_for_free_buffer(uint64_t timeout)
|
VkResult swapchain_base::wait_and_get_free_buffer(uint64_t timeout)
|
||||||
{
|
{
|
||||||
VkResult retval;
|
|
||||||
/* first see if a buffer is already marked as free */
|
/* first see if a buffer is already marked as free */
|
||||||
retval = m_free_image_semaphore.wait(0);
|
VkResult retval = m_free_image_semaphore.wait(0);
|
||||||
if (retval == VK_NOT_READY)
|
if (retval == VK_NOT_READY)
|
||||||
{
|
{
|
||||||
/* if not, we still have work to do even if timeout==0 -
|
/* if not, we still have work to do even if timeout==0 -
|
||||||
|
|
|
||||||
|
|
@ -657,7 +657,7 @@ private:
|
||||||
* Uses a custom semaphore implementation that uses a condition variable.
|
* Uses a custom semaphore implementation that uses a condition variable.
|
||||||
* it is slower, but has a safe timedwait implementation.
|
* it is slower, but has a safe timedwait implementation.
|
||||||
*
|
*
|
||||||
* This is kept private as waiting should be done via wait_for_free_buffer().
|
* This is kept private as waiting should be done via wait_and_get_free_buffer().
|
||||||
*/
|
*/
|
||||||
util::timed_semaphore m_free_image_semaphore;
|
util::timed_semaphore m_free_image_semaphore;
|
||||||
|
|
||||||
|
|
@ -682,8 +682,10 @@ private:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Wait for a buffer to become free.
|
* @brief Wait for a buffer to become free.
|
||||||
|
*
|
||||||
|
* It decrements the semaphore once a free buffer is available.
|
||||||
*/
|
*/
|
||||||
VkResult wait_for_free_buffer(uint64_t timeout);
|
VkResult wait_and_get_free_buffer(uint64_t timeout);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Per swapchain thread function that handles page flipping.
|
* @brief Per swapchain thread function that handles page flipping.
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue