From 30d7b3bdecddb3c727aea9616fd5a892ede39dfc Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Sat, 16 Mar 2024 19:22:36 -0700 Subject: [PATCH] venus: avoid excessive ring notifications The ring notification can be blocked on renderer main thread if a vq cmd is waiting for a ring cmd (via a different non-idle ring). This change optimizes to only try waking up the ring on the idle timeout period. Signed-off-by: Yiwei Zhang Part-of: --- src/virtio/vulkan/vn_ring.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/virtio/vulkan/vn_ring.c b/src/virtio/vulkan/vn_ring.c index 919218719e9..e880853951c 100644 --- a/src/virtio/vulkan/vn_ring.c +++ b/src/virtio/vulkan/vn_ring.c @@ -11,6 +11,8 @@ #include "vn_instance.h" #include "vn_renderer.h" +#define VN_RING_IDLE_TIMEOUT_NS (5ull * 1000 * 1000) + static_assert(ATOMIC_INT_LOCK_FREE == 2 && sizeof(atomic_uint) == 4, "vn_ring_shared requires lock-free 32-bit atomic_uint"); @@ -54,6 +56,9 @@ struct vn_ring { /* to synchronize renderer/ring */ mtx_t roundtrip_mutex; uint64_t roundtrip_next; + + int64_t last_notify; + int64_t next_notify; }; struct vn_ring_submit { @@ -320,7 +325,7 @@ vn_ring_create(struct vn_instance *instance, .pNext = &monitor_info, .resourceId = ring->shmem->res_id, .size = layout->shmem_size, - .idleTimeout = 5ull * 1000 * 1000, + .idleTimeout = VN_RING_IDLE_TIMEOUT_NS, .headOffset = layout->head_offset, .tailOffset = layout->tail_offset, .statusOffset = layout->status_offset, @@ -432,8 +437,19 @@ vn_ring_submit_internal(struct vn_ring *ring, *seqno = submit->seqno; - /* notify renderer to wake up ring if idle */ - return status & VK_RING_STATUS_IDLE_BIT_MESA; + /* Notify renderer to wake up idle ring if at least VN_RING_IDLE_TIMEOUT_NS + * has passed since the last sent notification to avoid excessive wake up + * calls (non-trivial since submitted via virtio-gpu kernel). + */ + if (status & VK_RING_STATUS_IDLE_BIT_MESA) { + const int64_t now = os_time_get_nano(); + if (os_time_timeout(ring->last_notify, ring->next_notify, now)) { + ring->last_notify = now; + ring->next_notify = now + VN_RING_IDLE_TIMEOUT_NS; + return true; + } + } + return false; } static const struct vn_cs_encoder *