wsi/display: Implement VK_KHR_present_wait on KHR_display swapchain.
Signed-off-by: Hans-Kristian Arntzen <post@arntzen-software.no> Reviewed-by: Joshua Ashton <joshua@froggi.es> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/19279>
This commit is contained in:
committed by
Marge Bot
parent
8fc7927787
commit
367fa98570
@@ -44,6 +44,7 @@
|
||||
#include "util/hash_table.h"
|
||||
#include "util/list.h"
|
||||
#include "util/os_time.h"
|
||||
#include "util/timespec.h"
|
||||
|
||||
#include "vk_device.h"
|
||||
#include "vk_fence.h"
|
||||
@@ -139,6 +140,7 @@ struct wsi_display_image {
|
||||
uint32_t fb_id;
|
||||
uint32_t buffer[4];
|
||||
uint64_t flip_sequence;
|
||||
uint64_t present_id;
|
||||
};
|
||||
|
||||
struct wsi_display_swapchain {
|
||||
@@ -147,6 +149,12 @@ struct wsi_display_swapchain {
|
||||
VkIcdSurfaceDisplay *surface;
|
||||
uint64_t flip_sequence;
|
||||
VkResult status;
|
||||
|
||||
pthread_mutex_t present_id_mutex;
|
||||
pthread_cond_t present_id_cond;
|
||||
uint64_t present_id;
|
||||
VkResult present_id_error;
|
||||
|
||||
struct wsi_display_image images[0];
|
||||
};
|
||||
|
||||
@@ -1180,6 +1188,9 @@ wsi_display_swapchain_destroy(struct wsi_swapchain *drv_chain,
|
||||
for (uint32_t i = 0; i < chain->base.image_count; i++)
|
||||
wsi_display_image_finish(drv_chain, allocator, &chain->images[i]);
|
||||
|
||||
pthread_mutex_destroy(&chain->present_id_mutex);
|
||||
pthread_cond_destroy(&chain->present_id_cond);
|
||||
|
||||
wsi_swapchain_finish(&chain->base);
|
||||
vk_free(allocator, chain);
|
||||
return VK_SUCCESS;
|
||||
@@ -1214,6 +1225,30 @@ wsi_display_idle_old_displaying(struct wsi_display_image *active_image)
|
||||
static VkResult
|
||||
_wsi_display_queue_next(struct wsi_swapchain *drv_chain);
|
||||
|
||||
static void
|
||||
wsi_display_present_complete(struct wsi_display_swapchain *swapchain,
|
||||
struct wsi_display_image *image)
|
||||
{
|
||||
if (image->present_id) {
|
||||
pthread_mutex_lock(&swapchain->present_id_mutex);
|
||||
if (image->present_id > swapchain->present_id) {
|
||||
swapchain->present_id = image->present_id;
|
||||
pthread_cond_broadcast(&swapchain->present_id_cond);
|
||||
}
|
||||
pthread_mutex_unlock(&swapchain->present_id_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
wsi_display_surface_error(struct wsi_display_swapchain *swapchain, VkResult result)
|
||||
{
|
||||
pthread_mutex_lock(&swapchain->present_id_mutex);
|
||||
swapchain->present_id = UINT64_MAX;
|
||||
swapchain->present_id_error = result;
|
||||
pthread_cond_broadcast(&swapchain->present_id_cond);
|
||||
pthread_mutex_unlock(&swapchain->present_id_mutex);
|
||||
}
|
||||
|
||||
static void
|
||||
wsi_display_page_flip_handler2(int fd,
|
||||
unsigned int frame,
|
||||
@@ -1228,6 +1263,8 @@ wsi_display_page_flip_handler2(int fd,
|
||||
wsi_display_debug("image %ld displayed at %d\n",
|
||||
image - &(image->chain->images[0]), frame);
|
||||
image->state = WSI_IMAGE_DISPLAYING;
|
||||
wsi_display_present_complete(chain, image);
|
||||
|
||||
wsi_display_idle_old_displaying(image);
|
||||
VkResult result = _wsi_display_queue_next(&(chain->base));
|
||||
if (result != VK_SUCCESS)
|
||||
@@ -1401,6 +1438,7 @@ wsi_display_acquire_next_image(struct wsi_swapchain *drv_chain,
|
||||
|
||||
if (ret && ret != ETIMEDOUT) {
|
||||
result = VK_ERROR_SURFACE_LOST_KHR;
|
||||
wsi_display_surface_error(chain, result);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
@@ -1814,8 +1852,10 @@ _wsi_display_queue_next(struct wsi_swapchain *drv_chain)
|
||||
wsi_display_mode_from_handle(surface->displayMode);
|
||||
wsi_display_connector *connector = display_mode->connector;
|
||||
|
||||
if (wsi->fd < 0)
|
||||
if (wsi->fd < 0) {
|
||||
wsi_display_surface_error(chain, VK_ERROR_SURFACE_LOST_KHR);
|
||||
return VK_ERROR_SURFACE_LOST_KHR;
|
||||
}
|
||||
|
||||
if (display_mode != connector->current_mode)
|
||||
connector->active = false;
|
||||
@@ -1887,6 +1927,7 @@ _wsi_display_queue_next(struct wsi_swapchain *drv_chain)
|
||||
* previous image is now idle.
|
||||
*/
|
||||
image->state = WSI_IMAGE_DISPLAYING;
|
||||
wsi_display_present_complete(chain, image);
|
||||
wsi_display_idle_old_displaying(image);
|
||||
connector->active = true;
|
||||
return VK_SUCCESS;
|
||||
@@ -1896,6 +1937,7 @@ _wsi_display_queue_next(struct wsi_swapchain *drv_chain)
|
||||
if (ret != -EACCES) {
|
||||
connector->active = false;
|
||||
image->state = WSI_IMAGE_IDLE;
|
||||
wsi_display_surface_error(chain, VK_ERROR_SURFACE_LOST_KHR);
|
||||
return VK_ERROR_SURFACE_LOST_KHR;
|
||||
}
|
||||
|
||||
@@ -1923,11 +1965,17 @@ wsi_display_queue_present(struct wsi_swapchain *drv_chain,
|
||||
if (chain->status != VK_SUCCESS)
|
||||
return chain->status;
|
||||
|
||||
image->present_id = present_id;
|
||||
|
||||
assert(image->state == WSI_IMAGE_DRAWING);
|
||||
wsi_display_debug("present %d\n", image_index);
|
||||
|
||||
pthread_mutex_lock(&wsi->wait_mutex);
|
||||
|
||||
/* Make sure that the page flip handler is processed in finite time if using present wait. */
|
||||
if (present_id)
|
||||
wsi_display_start_wait_thread(wsi);
|
||||
|
||||
image->flip_sequence = ++chain->flip_sequence;
|
||||
image->state = WSI_IMAGE_QUEUED;
|
||||
|
||||
@@ -1943,6 +1991,48 @@ wsi_display_queue_present(struct wsi_swapchain *drv_chain,
|
||||
return chain->status;
|
||||
}
|
||||
|
||||
static VkResult
|
||||
wsi_display_wait_for_present(struct wsi_swapchain *wsi_chain,
|
||||
uint64_t waitValue,
|
||||
uint64_t timeout)
|
||||
{
|
||||
struct wsi_display_swapchain *chain = (struct wsi_display_swapchain *)wsi_chain;
|
||||
struct timespec abs_timespec;
|
||||
uint64_t abs_timeout = 0;
|
||||
|
||||
if (timeout != 0)
|
||||
abs_timeout = os_time_get_absolute_timeout(timeout);
|
||||
|
||||
/* Need to observe that the swapchain semaphore has been unsignalled,
|
||||
* as this is guaranteed when a present is complete. */
|
||||
VkResult result = wsi_swapchain_wait_for_present_semaphore(
|
||||
&chain->base, waitValue, timeout);
|
||||
if (result != VK_SUCCESS)
|
||||
return result;
|
||||
|
||||
timespec_from_nsec(&abs_timespec, abs_timeout);
|
||||
|
||||
pthread_mutex_lock(&chain->present_id_mutex);
|
||||
while (chain->present_id < waitValue) {
|
||||
int ret = pthread_cond_timedwait(&chain->present_id_cond,
|
||||
&chain->present_id_mutex,
|
||||
&abs_timespec);
|
||||
if (ret == ETIMEDOUT) {
|
||||
result = VK_TIMEOUT;
|
||||
break;
|
||||
}
|
||||
if (ret) {
|
||||
result = VK_ERROR_DEVICE_LOST;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (result == VK_SUCCESS && chain->present_id_error)
|
||||
result = chain->present_id_error;
|
||||
pthread_mutex_unlock(&chain->present_id_mutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
static VkResult
|
||||
wsi_display_surface_create_swapchain(
|
||||
VkIcdSurfaceBase *icd_surface,
|
||||
@@ -1971,10 +2061,25 @@ wsi_display_surface_create_swapchain(
|
||||
.same_gpu = true,
|
||||
};
|
||||
|
||||
int ret = pthread_mutex_init(&chain->present_id_mutex, NULL);
|
||||
if (ret != 0) {
|
||||
vk_free(allocator, chain);
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
|
||||
bool bret = wsi_init_pthread_cond_monotonic(&chain->present_id_cond);
|
||||
if (!bret) {
|
||||
pthread_mutex_destroy(&chain->present_id_mutex);
|
||||
vk_free(allocator, chain);
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
|
||||
VkResult result = wsi_swapchain_init(wsi_device, &chain->base, device,
|
||||
create_info, &image_params.base,
|
||||
allocator);
|
||||
if (result != VK_SUCCESS) {
|
||||
pthread_cond_destroy(&chain->present_id_cond);
|
||||
pthread_mutex_destroy(&chain->present_id_mutex);
|
||||
vk_free(allocator, chain);
|
||||
return result;
|
||||
}
|
||||
@@ -1983,6 +2088,7 @@ wsi_display_surface_create_swapchain(
|
||||
chain->base.get_wsi_image = wsi_display_get_wsi_image;
|
||||
chain->base.acquire_next_image = wsi_display_acquire_next_image;
|
||||
chain->base.queue_present = wsi_display_queue_present;
|
||||
chain->base.wait_for_present = wsi_display_wait_for_present;
|
||||
chain->base.present_mode = wsi_swapchain_get_present_mode(wsi_device, create_info);
|
||||
chain->base.image_count = num_images;
|
||||
|
||||
@@ -2001,6 +2107,8 @@ wsi_display_surface_create_swapchain(
|
||||
wsi_display_image_finish(&chain->base, allocator,
|
||||
&chain->images[image]);
|
||||
}
|
||||
pthread_cond_destroy(&chain->present_id_cond);
|
||||
pthread_mutex_destroy(&chain->present_id_mutex);
|
||||
wsi_swapchain_finish(&chain->base);
|
||||
vk_free(allocator, chain);
|
||||
goto fail_init_images;
|
||||
|
||||
Reference in New Issue
Block a user