[Mesa-dev] [RFC v2 3/5] vulkan: Add support for in-fences for vkQueuePresent
Louis-Francis Ratté-Boulianne
lfrb at collabora.com
Thu Sep 28 08:25:26 UTC 2017
Allow drivers to add a list of semaphores to wait on
when queuing a image to present.
Signed-off-by: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
---
src/amd/vulkan/radv_wsi.c | 2 +-
src/intel/vulkan/anv_wsi.c | 2 ++
src/vulkan/wsi/wsi_common.h | 6 +++++
src/vulkan/wsi/wsi_common_wayland.c | 2 ++
src/vulkan/wsi/wsi_common_x11.c | 50 +++++++++++++++++++++++++++++++++++--
5 files changed, 59 insertions(+), 3 deletions(-)
diff --git a/src/amd/vulkan/radv_wsi.c b/src/amd/vulkan/radv_wsi.c
index 31448ae981..d73a5766d1 100644
--- a/src/amd/vulkan/radv_wsi.c
+++ b/src/amd/vulkan/radv_wsi.c
@@ -575,7 +575,7 @@ VkResult radv_QueuePresentKHR(
if (regions && regions->pRegions)
region = ®ions->pRegions[i];
- item_result = swapchain->queue_present(swapchain,
+ item_result = swapchain->queue_present(swapchain, NULL, 0,
pPresentInfo->pImageIndices[i],
region);
/* TODO: What if one of them returns OUT_OF_DATE? */
diff --git a/src/intel/vulkan/anv_wsi.c b/src/intel/vulkan/anv_wsi.c
index 978a66896f..2e05c3b07b 100644
--- a/src/intel/vulkan/anv_wsi.c
+++ b/src/intel/vulkan/anv_wsi.c
@@ -472,6 +472,8 @@ VkResult anv_QueuePresentKHR(
anv_QueueSubmit(_queue, 0, NULL, swapchain->fences[0]);
item_result = swapchain->queue_present(swapchain,
+ NULL,
+ 0,
pPresentInfo->pImageIndices[i],
region);
/* TODO: What if one of them returns OUT_OF_DATE? */
diff --git a/src/vulkan/wsi/wsi_common.h b/src/vulkan/wsi/wsi_common.h
index 99836054ca..e81c7be11a 100644
--- a/src/vulkan/wsi/wsi_common.h
+++ b/src/vulkan/wsi/wsi_common.h
@@ -57,6 +57,10 @@ struct wsi_image_fns {
void (*free_wsi_image)(VkDevice device,
const VkAllocationCallbacks *pAllocator,
struct wsi_image_base *image);
+ VkResult (*get_semaphores_fd)(VkDevice device,
+ const VkSemaphore *semaphores,
+ uint32_t semaphore_count,
+ int *fd);
};
struct wsi_swapchain {
@@ -79,6 +83,8 @@ struct wsi_swapchain {
uint64_t timeout, VkSemaphore semaphore,
uint32_t *image_index);
VkResult (*queue_present)(struct wsi_swapchain *swap_chain,
+ const VkSemaphore *semaphores,
+ uint32_t semaphore_count,
uint32_t image_index,
const VkPresentRegionKHR *damage);
void (*get_image_and_linear)(struct wsi_swapchain *swapchain,
diff --git a/src/vulkan/wsi/wsi_common_wayland.c b/src/vulkan/wsi/wsi_common_wayland.c
index b4dd2d7ff0..6cafa8f178 100644
--- a/src/vulkan/wsi/wsi_common_wayland.c
+++ b/src/vulkan/wsi/wsi_common_wayland.c
@@ -720,6 +720,8 @@ static const struct wl_callback_listener frame_listener = {
static VkResult
wsi_wl_swapchain_queue_present(struct wsi_swapchain *wsi_chain,
+ const VkSemaphore *semaphores,
+ uint32_t semaphore_count,
uint32_t image_index,
const VkPresentRegionKHR *damage)
{
diff --git a/src/vulkan/wsi/wsi_common_x11.c b/src/vulkan/wsi/wsi_common_x11.c
index d9467092d2..1179eed9c7 100644
--- a/src/vulkan/wsi/wsi_common_x11.c
+++ b/src/vulkan/wsi/wsi_common_x11.c
@@ -654,6 +654,7 @@ struct x11_image {
xcb_pixmap_t pixmap;
bool busy;
struct xshmfence * shm_fence;
+ uint32_t wait_fence;
uint32_t sync_fence;
};
@@ -745,6 +746,14 @@ x11_handle_dri3_present_event(struct x11_swapchain *chain,
for (unsigned i = 0; i < chain->base.image_count; i++) {
if (chain->images[i].pixmap == idle->pixmap) {
chain->images[i].busy = false;
+ if (chain->images[i].wait_fence) {
+ xcb_void_cookie_t cookie;
+
+ cookie = xcb_sync_destroy_fence(chain->conn, chain->images[i].wait_fence);
+ xcb_discard_reply(chain->conn, cookie.sequence);
+ xcb_flush(chain->conn);
+ chain->images[i].wait_fence = 0;
+ }
if (chain->threaded)
wsi_queue_push(&chain->acquire_queue, i);
break;
@@ -907,13 +916,14 @@ x11_present_to_x11(struct x11_swapchain *chain, uint32_t image_index,
0, /* x_off */
0, /* y_off */
XCB_NONE, /* target_crtc */
- XCB_NONE,
+ image->wait_fence,
image->sync_fence,
options,
target_msc,
divisor,
remainder, 0, NULL);
xcb_discard_reply(chain->conn, cookie.sequence);
+
image->busy = true;
xcb_flush(chain->conn);
@@ -945,11 +955,39 @@ x11_acquire_next_image(struct wsi_swapchain *anv_chain,
static VkResult
x11_queue_present(struct wsi_swapchain *anv_chain,
+ const VkSemaphore *semaphores,
+ uint32_t semaphore_count,
uint32_t image_index,
const VkPresentRegionKHR *damage)
{
struct x11_swapchain *chain = (struct x11_swapchain *)anv_chain;
VkResult result;
+ struct x11_image *image = &chain->images[image_index];
+
+#if XCB_DRI3_MAJOR_VERSION > 1 || XCB_DRI3_MINOR_VERSION >= 2
+ if (chain->has_dma_fence) {
+ int merged_fence_fd = -1;
+ VkResult ret;
+
+ ret = chain->base.image_fns->get_semaphores_fd(anv_chain->device,
+ semaphores,
+ semaphore_count,
+ &merged_fence_fd);
+ if (ret != VK_SUCCESS) {
+ return ret;
+ }
+
+ if (merged_fence_fd > -1) {
+ image->wait_fence = xcb_generate_id(chain->conn);
+ xcb_dri3_fence_from_dma_fence_fd(chain->conn,
+ image->pixmap,
+ image->wait_fence,
+ merged_fence_fd);
+ xcb_flush(chain->conn);
+ close(merged_fence_fd);
+ }
+ }
+#endif
if (chain->threaded) {
wsi_queue_push(&chain->present_queue, image_index);
@@ -1118,6 +1156,9 @@ x11_image_init(VkDevice device_h, struct x11_swapchain *chain,
if (chain->has_present_v1_2 && chain->has_dri3_v1_2)
wsi_x11_get_present_capabilities(chain);
+ image->wait_fence = 0;
+ image->busy = false;
+
int fence_fd = xshmfence_alloc_shm();
if (fence_fd < 0)
goto fail_pixmap;
@@ -1133,7 +1174,6 @@ x11_image_init(VkDevice device_h, struct x11_swapchain *chain,
false,
fence_fd);
- image->busy = false;
xshmfence_trigger(image->shm_fence);
return VK_SUCCESS;
@@ -1161,6 +1201,12 @@ x11_image_finish(struct x11_swapchain *chain,
xcb_discard_reply(chain->conn, cookie.sequence);
xshmfence_unmap_shm(image->shm_fence);
+ if (image->wait_fence) {
+ cookie = xcb_sync_destroy_fence(chain->conn, image->wait_fence);
+ xcb_discard_reply(chain->conn, cookie.sequence);
+ image->wait_fence = 0;
+ }
+
cookie = xcb_free_pixmap(chain->conn, image->pixmap);
xcb_discard_reply(chain->conn, cookie.sequence);
--
2.13.0
More information about the mesa-dev
mailing list