v3dv: pre-allocate actual events instead of event descriptors
authorIago Toral Quiroga <itoral@igalia.com>
Tue, 29 Nov 2022 09:52:33 +0000 (10:52 +0100)
committerMarge Bot <emma+marge@anholt.net>
Wed, 30 Nov 2022 17:10:45 +0000 (17:10 +0000)
Instead of keeping a free list of "event descriptors" which are
just the offsets in the BO state that are available, pre-allocate
the events. This is simpler as it doesn't require to allocate these
event descriptors at all.

Reviewed-by: Alejandro PiƱeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20053>

src/broadcom/vulkan/v3dv_event.c
src/broadcom/vulkan/v3dv_private.h

index 014c7be..849fd84 100644 (file)
@@ -195,6 +195,14 @@ destroy_event_pipelines(struct v3dv_device *device)
    device->events.descriptor_set_layout = VK_NULL_HANDLE;
 }
 
+static void
+init_event(struct v3dv_device *device, struct v3dv_event *event, uint32_t index)
+{
+   vk_object_base_init(&device->vk, &event->base, VK_OBJECT_TYPE_EVENT);
+   event->index = index;
+   list_addtail(&event->link, &device->events.free_list);
+}
+
 VkResult
 v3dv_event_allocate_resources(struct v3dv_device *device)
 {
@@ -221,22 +229,20 @@ v3dv_event_allocate_resources(struct v3dv_device *device)
       goto fail;
    }
 
-   /* List of free event state slots in the BO, 1 byte per slot */
-   device->events.desc_count = bo_size;
-   device->events.desc =
-      vk_alloc2(&device->vk.alloc, NULL,
-                device->events.desc_count * sizeof(struct v3dv_event_desc), 8,
-                VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
-   if (!device->events.desc) {
+   /* Pre-allocate our events, each event requires 1 byte of BO storage */
+   device->events.event_count = bo_size;
+   device->events.events =
+      vk_zalloc2(&device->vk.alloc, NULL,
+                 device->events.event_count * sizeof(struct v3dv_event), 8,
+                 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
+   if (!device->events.events) {
       result = vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
       goto fail;
    }
 
    list_inithead(&device->events.free_list);
-   for (int i = 0; i < device->events.desc_count; i++) {
-      device->events.desc[i].index = i;
-      list_addtail(&device->events.desc[i].link, &device->events.free_list);
-   }
+   for (int i = 0; i < device->events.event_count; i++)
+      init_event(device, &device->events.events[i], i);
 
    /* Vulkan buffer for the event state BO */
    VkBufferCreateInfo buf_info = {
@@ -337,9 +343,9 @@ v3dv_event_free_resources(struct v3dv_device *device)
       device->events.bo = NULL;
    }
 
-   if (device->events.desc) {
-      vk_free2(&device->vk.alloc, NULL, device->events.desc);
-      device->events.desc = NULL;
+   if (device->events.events) {
+      vk_free2(&device->vk.alloc, NULL, device->events.events);
+      device->events.events = NULL;
    }
 
    if (device->events.mem) {
@@ -365,8 +371,8 @@ v3dv_event_free_resources(struct v3dv_device *device)
    destroy_event_pipelines(device);
 }
 
-static struct v3dv_event_desc *
-allocate_event_descriptor(struct v3dv_device *device)
+static struct v3dv_event *
+allocate_event(struct v3dv_device *device)
 {
    mtx_lock(&device->events.lock);
    if (list_is_empty(&device->events.free_list)) {
@@ -374,20 +380,20 @@ allocate_event_descriptor(struct v3dv_device *device)
       return NULL;
    }
 
-   struct v3dv_event_desc *desc =
-      list_first_entry(&device->events.free_list, struct v3dv_event_desc, link);
-   list_del(&desc->link);
+   struct v3dv_event *event =
+      list_first_entry(&device->events.free_list, struct v3dv_event, link);
+   list_del(&event->link);
    mtx_unlock(&device->events.lock);
 
-   return desc;
+   return event;
 }
 
 static void
-free_event_descriptor(struct v3dv_device *device, uint32_t index)
+free_event(struct v3dv_device *device, uint32_t index)
 {
+   assert(index < device->events.event_count);
    mtx_lock(&device->events.lock);
-   assert(index < device->events.desc_count);
-   list_addtail(&device->events.desc[index].link, &device->events.free_list);
+   list_addtail(&device->events.events[index].link, &device->events.free_list);
    mtx_unlock(&device->events.lock);
 }
 
@@ -417,21 +423,12 @@ v3dv_CreateEvent(VkDevice _device,
    V3DV_FROM_HANDLE(v3dv_device, device, _device);
    VkResult result = VK_SUCCESS;
 
-   struct v3dv_event *event =
-      vk_object_zalloc(&device->vk, pAllocator, sizeof(*event),
-                       VK_OBJECT_TYPE_EVENT);
+   struct v3dv_event *event = allocate_event(device);
    if (!event) {
-      result = vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
-      goto fail;
-   }
-
-   struct v3dv_event_desc *desc = allocate_event_descriptor(device);
-   if (!desc) {
       result = vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
       goto fail;
    }
 
-   event->index = desc->index;
    event_set_value(device, event, 0);
    *pEvent = v3dv_event_to_handle(event);
    return VK_SUCCESS;
@@ -451,8 +448,7 @@ v3dv_DestroyEvent(VkDevice _device,
    if (!event)
       return;
 
-   free_event_descriptor(device, event->index);
-   vk_object_free(&device->vk, pAllocator, event);
+   free_event(device, event->index);
 }
 
 VKAPI_ATTR VkResult VKAPI_CALL
@@ -502,7 +498,7 @@ cmd_buffer_emit_set_event(struct v3dv_cmd_buffer *cmd_buffer,
                               device->events.pipeline_layout,
                               0, 1, &device->events.descriptor_set, 0, NULL);
 
-   assert(event->index < device->events.desc_count);
+   assert(event->index < device->events.event_count);
    uint32_t offset = event->index;
    v3dv_CmdPushConstants(commandBuffer,
                          device->events.pipeline_layout,
@@ -537,7 +533,7 @@ cmd_buffer_emit_wait_event(struct v3dv_cmd_buffer *cmd_buffer,
                               device->events.pipeline_layout,
                               0, 1, &device->events.descriptor_set, 0, NULL);
 
-   assert(event->index < device->events.desc_count);
+   assert(event->index < device->events.event_count);
    uint32_t offset = event->index;
    v3dv_CmdPushConstants(commandBuffer,
                          device->events.pipeline_layout,
index d085bb2..5237f96 100644 (file)
@@ -454,15 +454,6 @@ struct v3dv_pipeline_cache {
    bool externally_synchronized;
 };
 
-/* This is used to implement a list of free events in the BO we use
- * hold event states. The index here is used to calculate the offset
- * within that BO.
- */
-struct v3dv_event_desc {
-   struct list_head link;
-   uint32_t index;
-};
-
 struct v3dv_device {
    struct vk_device vk;
 
@@ -531,14 +522,13 @@ struct v3dv_device {
       /* BO for the event states: signaled (1) or reset (0) */
       struct v3dv_bo *bo;
 
-      /* Events can be created and destroyed. Since we have a dedicated BO for
-       * all events we use, we need to keep track of the free slots within that
-       * BO. For that we use a free list where we link together available event
-       * slots in the form of "descriptors" that include an index (which is
-       * basically an offset into the BO that is available).
+      /* We pre-allocate all the events we can fit for the size of the BO we
+       * create to track their states, where each event has an index which is
+       * basically the offset of its state in that BO. We keep a free list with
+       * the pre-allocated events that are available.
        */
-      uint32_t desc_count;
-      struct v3dv_event_desc *desc;
+      uint32_t event_count;
+      struct v3dv_event *events;
       struct list_head free_list;
 
       /* Vulkan resources to access the event BO from shaders. We have a
@@ -1741,6 +1731,9 @@ void v3dv_cmd_buffer_emit_pipeline_barrier(struct v3dv_cmd_buffer *cmd_buffer,
 struct v3dv_event {
    struct vk_object_base base;
 
+   /* Link in the device list of pre-allocated free events */
+   struct list_head link;
+
    /* Each event gets a different index, which we use to compute the offset
     * in the BO we use to track their state (signaled vs reset).
     */