summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYiwei Zhang <zzyiwei@chromium.org>2022-05-24 16:31:20 +0000
committerMarge Bot <emma+marge@anholt.net>2022-06-16 19:00:36 +0000
commit942ec179f3d9c74fcd14a58a623c039c494d9a7a (patch)
tree0dbda205575a198755d8169ab883386c9f610280
parentf2563788a1c348ecbc4417c2d0359b3472c1959c (diff)
venus: add event feedback
- add perf option VN_PERF_NO_EVENT_FEEDBACK - intercept to record feedback cmds for: - vkCmdSetEvent - vkCmdResetEvent - add feedback code path for - vkGetEventStatus - vkSetEvent - vkResetEvent Test: dEQP-VK.synchronization.basic.event.* Test: dEQP-VK.api.command_buffers.record_simul* Signed-off-by: Yiwei Zhang <zzyiwei@chromium.org> Reviewed-by: Ryan Neph <ryanneph@google.com> Reviewed-by: Chad Versace <chadversary@chromium.org> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16731>
-rw-r--r--src/virtio/vulkan/vn_command_buffer.c6
-rw-r--r--src/virtio/vulkan/vn_common.c1
-rw-r--r--src/virtio/vulkan/vn_common.h1
-rw-r--r--src/virtio/vulkan/vn_device.c36
-rw-r--r--src/virtio/vulkan/vn_device.h3
-rw-r--r--src/virtio/vulkan/vn_feedback.c59
-rw-r--r--src/virtio/vulkan/vn_feedback.h6
-rw-r--r--src/virtio/vulkan/vn_queue.c70
-rw-r--r--src/virtio/vulkan/vn_queue.h8
9 files changed, 181 insertions, 9 deletions
diff --git a/src/virtio/vulkan/vn_command_buffer.c b/src/virtio/vulkan/vn_command_buffer.c
index b293288e69c..804e435ba9f 100644
--- a/src/virtio/vulkan/vn_command_buffer.c
+++ b/src/virtio/vulkan/vn_command_buffer.c
@@ -1141,6 +1141,9 @@ vn_CmdSetEvent(VkCommandBuffer commandBuffer,
VkPipelineStageFlags stageMask)
{
VN_CMD_ENQUEUE(vkCmdSetEvent, commandBuffer, event, stageMask);
+
+ vn_feedback_event_cmd_record(commandBuffer, event, stageMask,
+ VK_EVENT_SET);
}
void
@@ -1149,6 +1152,9 @@ vn_CmdResetEvent(VkCommandBuffer commandBuffer,
VkPipelineStageFlags stageMask)
{
VN_CMD_ENQUEUE(vkCmdResetEvent, commandBuffer, event, stageMask);
+
+ vn_feedback_event_cmd_record(commandBuffer, event, stageMask,
+ VK_EVENT_RESET);
}
void
diff --git a/src/virtio/vulkan/vn_common.c b/src/virtio/vulkan/vn_common.c
index 743e3251517..ec48f72a2a0 100644
--- a/src/virtio/vulkan/vn_common.c
+++ b/src/virtio/vulkan/vn_common.c
@@ -34,6 +34,7 @@ static const struct debug_control vn_perf_options[] = {
{ "no_async_set_alloc", VN_PERF_NO_ASYNC_SET_ALLOC },
{ "no_async_buffer_create", VN_PERF_NO_ASYNC_BUFFER_CREATE },
{ "no_async_queue_submit", VN_PERF_NO_ASYNC_QUEUE_SUBMIT },
+ { "no_event_feedback", VN_PERF_NO_EVENT_FEEDBACK },
{ NULL, 0 },
};
diff --git a/src/virtio/vulkan/vn_common.h b/src/virtio/vulkan/vn_common.h
index b8079949bcd..47505e7e805 100644
--- a/src/virtio/vulkan/vn_common.h
+++ b/src/virtio/vulkan/vn_common.h
@@ -146,6 +146,7 @@ enum vn_perf {
VN_PERF_NO_ASYNC_SET_ALLOC = 1ull << 0,
VN_PERF_NO_ASYNC_BUFFER_CREATE = 1ull << 1,
VN_PERF_NO_ASYNC_QUEUE_SUBMIT = 1ull << 2,
+ VN_PERF_NO_EVENT_FEEDBACK = 1ull << 3,
};
typedef uint64_t vn_object_id;
diff --git a/src/virtio/vulkan/vn_device.c b/src/virtio/vulkan/vn_device.c
index 28b64bb1ce5..2c8c90cc6f5 100644
--- a/src/virtio/vulkan/vn_device.c
+++ b/src/virtio/vulkan/vn_device.c
@@ -300,6 +300,31 @@ vn_device_fix_create_info(const struct vn_device *dev,
return local_info;
}
+static inline VkResult
+vn_device_feedback_pool_init(struct vn_device *dev)
+{
+ /* The feedback pool defaults to suballocate slots of 8 bytes each. Initial
+ * pool size of 4096 corresponds to a total of 512 fences, semaphores and
+ * events, which well covers the common scenarios. Pool can grow anyway.
+ */
+ static const uint32_t pool_size = 4096;
+ const VkAllocationCallbacks *alloc = &dev->base.base.alloc;
+
+ if (VN_PERF(NO_EVENT_FEEDBACK))
+ return VK_SUCCESS;
+
+ return vn_feedback_pool_init(dev, &dev->feedback_pool, pool_size, alloc);
+}
+
+static inline void
+vn_device_feedback_pool_fini(struct vn_device *dev)
+{
+ if (VN_PERF(NO_EVENT_FEEDBACK))
+ return;
+
+ vn_feedback_pool_fini(&dev->feedback_pool);
+}
+
static VkResult
vn_device_init(struct vn_device *dev,
struct vn_physical_device *physical_dev,
@@ -346,12 +371,19 @@ vn_device_init(struct vn_device *dev,
if (result != VK_SUCCESS)
goto out_memory_pool_fini;
- result = vn_device_init_queues(dev, create_info);
+ result = vn_device_feedback_pool_init(dev);
if (result != VK_SUCCESS)
goto out_buffer_cache_fini;
+ result = vn_device_init_queues(dev, create_info);
+ if (result != VK_SUCCESS)
+ goto out_feedback_pool_fini;
+
return VK_SUCCESS;
+out_feedback_pool_fini:
+ vn_device_feedback_pool_fini(dev);
+
out_buffer_cache_fini:
vn_buffer_cache_fini(dev);
@@ -423,6 +455,8 @@ vn_DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator)
for (uint32_t i = 0; i < dev->queue_count; i++)
vn_queue_fini(&dev->queues[i]);
+ vn_device_feedback_pool_fini(dev);
+
vn_buffer_cache_fini(dev);
for (uint32_t i = 0; i < ARRAY_SIZE(dev->memory_pools); i++)
diff --git a/src/virtio/vulkan/vn_device.h b/src/virtio/vulkan/vn_device.h
index d85cf088b92..123a39e0352 100644
--- a/src/virtio/vulkan/vn_device.h
+++ b/src/virtio/vulkan/vn_device.h
@@ -15,6 +15,7 @@
#include "vn_buffer.h"
#include "vn_device_memory.h"
+#include "vn_feedback.h"
struct vn_device {
struct vn_device_base base;
@@ -31,6 +32,8 @@ struct vn_device {
struct vn_buffer_cache buffer_cache;
+ struct vn_feedback_pool feedback_pool;
+
struct vn_queue *queues;
uint32_t queue_count;
};
diff --git a/src/virtio/vulkan/vn_feedback.c b/src/virtio/vulkan/vn_feedback.c
index cdfdca9db3b..24041229f0c 100644
--- a/src/virtio/vulkan/vn_feedback.c
+++ b/src/virtio/vulkan/vn_feedback.c
@@ -7,6 +7,7 @@
#include "vn_device.h"
#include "vn_physical_device.h"
+#include "vn_queue.h"
/* coherent buffer with bound and mapped memory */
struct vn_feedback_buffer {
@@ -263,3 +264,61 @@ vn_feedback_pool_free(struct vn_feedback_pool *pool,
list_add(&slot->head, &pool->free_slots);
simple_mtx_unlock(&pool->mutex);
}
+
+void
+vn_feedback_event_cmd_record(VkCommandBuffer cmd_handle,
+ VkEvent ev_handle,
+ VkPipelineStageFlags stage_mask,
+ VkResult status)
+{
+ /* For vkCmdSetEvent and vkCmdResetEvent feedback interception.
+ *
+ * The injection point is after the event call to avoid introducing
+ * unexpected src stage waiting for VK_PIPELINE_STAGE_HOST_BIT and
+ * VK_PIPELINE_STAGE_TRANSFER_BIT if they are not already being waited by
+ * vkCmdSetEvent or vkCmdResetEvent. On the other hand, the delay in the
+ * feedback signal is acceptable for the nature of VkEvent, and the event
+ * feedback cmds lifecycle is guarded by the intercepted command buffer.
+ */
+ struct vn_event *ev = vn_event_from_handle(ev_handle);
+ struct vn_feedback_slot *slot = ev->feedback_slot;
+
+ if (!slot)
+ return;
+
+ STATIC_ASSERT(sizeof(*slot->status) == 4);
+
+ const VkBufferMemoryBarrier buf_barrier_before = {
+ .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
+ .pNext = NULL,
+ .srcAccessMask =
+ VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
+ .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
+ .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+ .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+ .buffer = slot->buffer,
+ .offset = slot->offset,
+ .size = 4,
+ };
+ vn_CmdPipelineBarrier(cmd_handle,
+ stage_mask | VK_PIPELINE_STAGE_HOST_BIT |
+ VK_PIPELINE_STAGE_TRANSFER_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 1,
+ &buf_barrier_before, 0, NULL);
+ vn_CmdFillBuffer(cmd_handle, slot->buffer, slot->offset, 4, status);
+
+ const VkBufferMemoryBarrier buf_barrier_after = {
+ .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
+ .pNext = NULL,
+ .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
+ .dstAccessMask = VK_ACCESS_HOST_READ_BIT | VK_ACCESS_HOST_WRITE_BIT,
+ .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+ .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+ .buffer = slot->buffer,
+ .offset = slot->offset,
+ .size = 4,
+ };
+ vn_CmdPipelineBarrier(cmd_handle, VK_PIPELINE_STAGE_TRANSFER_BIT,
+ VK_PIPELINE_STAGE_HOST_BIT, 0, 0, NULL, 1,
+ &buf_barrier_after, 0, NULL);
+}
diff --git a/src/virtio/vulkan/vn_feedback.h b/src/virtio/vulkan/vn_feedback.h
index ea5b47e2f8a..f5b008d264e 100644
--- a/src/virtio/vulkan/vn_feedback.h
+++ b/src/virtio/vulkan/vn_feedback.h
@@ -101,4 +101,10 @@ vn_feedback_set_counter(struct vn_feedback_slot *slot, uint64_t counter)
*slot->counter = counter;
}
+void
+vn_feedback_event_cmd_record(VkCommandBuffer cmd_handle,
+ VkEvent ev_handle,
+ VkPipelineStageFlags stage_mask,
+ VkResult status);
+
#endif /* VN_FEEDBACK_H */
diff --git a/src/virtio/vulkan/vn_queue.c b/src/virtio/vulkan/vn_queue.c
index 006ccc3e6a0..37f8ebe1f71 100644
--- a/src/virtio/vulkan/vn_queue.c
+++ b/src/virtio/vulkan/vn_queue.c
@@ -1030,6 +1030,33 @@ vn_GetSemaphoreFdKHR(VkDevice device,
/* event commands */
+static VkResult
+vn_event_feedback_init(struct vn_device *dev, struct vn_event *ev)
+{
+ struct vn_feedback_slot *slot;
+
+ if (VN_PERF(NO_EVENT_FEEDBACK))
+ return VK_SUCCESS;
+
+ slot = vn_feedback_pool_alloc(&dev->feedback_pool, VN_FEEDBACK_TYPE_EVENT);
+ if (!slot)
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+ /* newly created event object is in the unsignaled state */
+ vn_feedback_set_status(slot, VK_EVENT_RESET);
+
+ ev->feedback_slot = slot;
+
+ return VK_SUCCESS;
+}
+
+static inline void
+vn_event_feedback_fini(struct vn_device *dev, struct vn_event *ev)
+{
+ if (ev->feedback_slot)
+ vn_feedback_pool_free(&dev->feedback_pool, ev->feedback_slot);
+}
+
VkResult
vn_CreateEvent(VkDevice device,
const VkEventCreateInfo *pCreateInfo,
@@ -1047,6 +1074,13 @@ vn_CreateEvent(VkDevice device,
vn_object_base_init(&ev->base, VK_OBJECT_TYPE_EVENT, &dev->base);
+ /* feedback is only needed to speed up host operations */
+ if (!(pCreateInfo->flags & VK_EVENT_CREATE_DEVICE_ONLY_BIT)) {
+ VkResult result = vn_event_feedback_init(dev, ev);
+ if (result != VK_SUCCESS)
+ return vn_error(dev->instance, result);
+ }
+
VkEvent ev_handle = vn_event_to_handle(ev);
vn_async_vkCreateEvent(dev->instance, device, pCreateInfo, NULL,
&ev_handle);
@@ -1071,6 +1105,8 @@ vn_DestroyEvent(VkDevice device,
vn_async_vkDestroyEvent(dev->instance, device, event, NULL);
+ vn_event_feedback_fini(dev, ev);
+
vn_object_base_fini(&ev->base);
vk_free(alloc, ev);
}
@@ -1079,11 +1115,13 @@ VkResult
vn_GetEventStatus(VkDevice device, VkEvent event)
{
struct vn_device *dev = vn_device_from_handle(device);
+ struct vn_event *ev = vn_event_from_handle(event);
+ VkResult result;
- /* TODO When the renderer supports it (requires a new vk extension), there
- * should be a coherent memory backing the event.
- */
- VkResult result = vn_call_vkGetEventStatus(dev->instance, device, event);
+ if (ev->feedback_slot)
+ result = vn_feedback_get_status(ev->feedback_slot);
+ else
+ result = vn_call_vkGetEventStatus(dev->instance, device, event);
return vn_result(dev->instance, result);
}
@@ -1092,18 +1130,34 @@ VkResult
vn_SetEvent(VkDevice device, VkEvent event)
{
struct vn_device *dev = vn_device_from_handle(device);
+ struct vn_event *ev = vn_event_from_handle(event);
- VkResult result = vn_call_vkSetEvent(dev->instance, device, event);
+ if (ev->feedback_slot) {
+ vn_feedback_set_status(ev->feedback_slot, VK_EVENT_SET);
+ vn_async_vkSetEvent(dev->instance, device, event);
+ } else {
+ VkResult result = vn_call_vkSetEvent(dev->instance, device, event);
+ if (result != VK_SUCCESS)
+ return vn_error(dev->instance, result);
+ }
- return vn_result(dev->instance, result);
+ return VK_SUCCESS;
}
VkResult
vn_ResetEvent(VkDevice device, VkEvent event)
{
struct vn_device *dev = vn_device_from_handle(device);
+ struct vn_event *ev = vn_event_from_handle(event);
- VkResult result = vn_call_vkResetEvent(dev->instance, device, event);
+ if (ev->feedback_slot) {
+ vn_feedback_reset_status(ev->feedback_slot);
+ vn_async_vkResetEvent(dev->instance, device, event);
+ } else {
+ VkResult result = vn_call_vkResetEvent(dev->instance, device, event);
+ if (result != VK_SUCCESS)
+ return vn_error(dev->instance, result);
+ }
- return vn_result(dev->instance, result);
+ return VK_SUCCESS;
}
diff --git a/src/virtio/vulkan/vn_queue.h b/src/virtio/vulkan/vn_queue.h
index c692a434ea0..a66697b4f9c 100644
--- a/src/virtio/vulkan/vn_queue.h
+++ b/src/virtio/vulkan/vn_queue.h
@@ -13,6 +13,8 @@
#include "vn_common.h"
+#include "vn_feedback.h"
+
struct vn_queue {
struct vn_object_base base;
@@ -72,6 +74,12 @@ VK_DEFINE_NONDISP_HANDLE_CASTS(vn_semaphore,
struct vn_event {
struct vn_object_base base;
+
+ /* non-NULL if below are satisfied:
+ * - event is created without VK_EVENT_CREATE_DEVICE_ONLY_BIT
+ * - VN_PERF_NO_EVENT_FEEDBACK is disabled
+ */
+ struct vn_feedback_slot *feedback_slot;
};
VK_DEFINE_NONDISP_HANDLE_CASTS(vn_event,
base.base,