[Mesa-dev] [PATCH 05/12] anv: Split tracking of bo and relocation entries

Chris Wilson chris at chris-wilson.co.uk
Sun May 14 23:38:49 UTC 2017


Track seen bo for a reloc list separately from the bo used by the
relocs. This is a step towards not using the relocation entries
themselves, but we still need to track the used bo and provide those to
the kernel.

In the short term, since the array of unique is likely small, we can try
to keep it unique and so reduce the amount of repetition required when
building the execobj aray, i.e. a few hundred relocations may only use
handful of target bo.

Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
Cc: Jason Ekstrand <jason.ekstrand at intel.com>
---
 src/intel/vulkan/anv_batch_chain.c | 128 ++++++++++++++++++++++++++++++-------
 src/intel/vulkan/anv_private.h     |   6 +-
 2 files changed, 109 insertions(+), 25 deletions(-)

diff --git a/src/intel/vulkan/anv_batch_chain.c b/src/intel/vulkan/anv_batch_chain.c
index e79d6a2a3b..5d86472492 100644
--- a/src/intel/vulkan/anv_batch_chain.c
+++ b/src/intel/vulkan/anv_batch_chain.c
@@ -52,34 +52,50 @@ anv_reloc_list_init_clone(struct anv_reloc_list *list,
                           const struct anv_reloc_list *other_list)
 {
    if (other_list) {
+      list->num_bos = other_list->num_bos;
+      list->size_bos = other_list->size_bos;
       list->num_relocs = other_list->num_relocs;
-      list->array_length = other_list->array_length;
+      list->size_relocs = other_list->size_relocs;
    } else {
+      list->num_bos = 0;
+      list->size_bos = 32;
       list->num_relocs = 0;
-      list->array_length = 256;
+      list->size_relocs = 256;
    }
 
+   list->bos =
+      vk_alloc(alloc, list->size_bos * sizeof(*list->bos), 8,
+                VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+
+   if (list->bos == NULL)
+      return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
    list->relocs =
-      vk_alloc(alloc, list->array_length * sizeof(*list->relocs), 8,
+      vk_alloc(alloc, list->size_relocs * sizeof(*list->relocs), 8,
                 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
 
-   if (list->relocs == NULL)
+   if (list->relocs == NULL) {
+      vk_free(alloc, list->bos);
       return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+   }
 
    list->reloc_bos =
-      vk_alloc(alloc, list->array_length * sizeof(*list->reloc_bos), 8,
+      vk_alloc(alloc, list->size_relocs * sizeof(*list->reloc_bos), 8,
                 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
 
    if (list->reloc_bos == NULL) {
+      vk_free(alloc, list->bos);
       vk_free(alloc, list->relocs);
       return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
    }
 
    if (other_list) {
+      memcpy(list->bos, other_list->bos,
+             list->num_bos * sizeof(*list->bos));
       memcpy(list->relocs, other_list->relocs,
-             list->array_length * sizeof(*list->relocs));
+             list->num_relocs * sizeof(*list->relocs));
       memcpy(list->reloc_bos, other_list->reloc_bos,
-             list->array_length * sizeof(*list->reloc_bos));
+             list->num_relocs * sizeof(*list->reloc_bos));
    }
 
    return VK_SUCCESS;
@@ -96,19 +112,48 @@ void
 anv_reloc_list_finish(struct anv_reloc_list *list,
                       const VkAllocationCallbacks *alloc)
 {
+   vk_free(alloc, list->bos);
    vk_free(alloc, list->relocs);
    vk_free(alloc, list->reloc_bos);
 }
 
 static VkResult
-anv_reloc_list_grow(struct anv_reloc_list *list,
-                    const VkAllocationCallbacks *alloc,
-                    size_t num_additional_relocs)
+anv_reloc_list_grow_bos(struct anv_reloc_list *list,
+                        const VkAllocationCallbacks *alloc,
+                        size_t num_additional_bos)
+{
+   if (list->num_bos + num_additional_bos <= list->size_bos)
+      return VK_SUCCESS;
+
+   size_t new_length = list->size_bos * 2;
+   while (new_length < list->num_bos + num_additional_bos)
+      new_length *= 2;
+
+   struct anv_bo **new_bos =
+      vk_alloc(alloc, new_length * sizeof(*list->bos), 8,
+                VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+   if (new_bos == NULL)
+      return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+   memcpy(new_bos, list->bos, list->num_bos * sizeof(*list->bos));
+
+   vk_free(alloc, list->bos);
+
+   list->size_bos = new_length;
+   list->bos = new_bos;
+
+   return VK_SUCCESS;
+}
+
+static VkResult
+anv_reloc_list_grow_relocs(struct anv_reloc_list *list,
+                           const VkAllocationCallbacks *alloc,
+                           size_t num_additional_relocs)
 {
-   if (list->num_relocs + num_additional_relocs <= list->array_length)
+   if (list->num_relocs + num_additional_relocs <= list->size_relocs)
       return VK_SUCCESS;
 
-   size_t new_length = list->array_length * 2;
+   size_t new_length = list->size_relocs * 2;
    while (new_length < list->num_relocs + num_additional_relocs)
       new_length *= 2;
 
@@ -133,7 +178,7 @@ anv_reloc_list_grow(struct anv_reloc_list *list,
    vk_free(alloc, list->relocs);
    vk_free(alloc, list->reloc_bos);
 
-   list->array_length = new_length;
+   list->size_relocs = new_length;
    list->relocs = new_relocs;
    list->reloc_bos = new_reloc_bos;
 
@@ -165,16 +210,32 @@ anv_reloc_list_add(struct anv_reloc_list *list,
                    const VkAllocationCallbacks *alloc,
                    uint32_t offset, struct anv_bo *target_bo, uint32_t delta)
 {
-   struct drm_i915_gem_relocation_entry *entry;
+   VkResult result;
    int index;
 
+   /* The array of unique bo should be reasonably small */
+   for (index = 0; index < list->num_bos; index++)
+      if (list->bos[index] == target_bo)
+         break;
+
+   if (index == list->num_bos) {
+      result = anv_reloc_list_grow_bos(list, alloc, 1);
+      if (result != VK_SUCCESS)
+         return result;
+
+      index = list->num_bos++;
+      list->bos[index] = target_bo;
+   }
+
    const uint32_t domain =
       (target_bo->flags & EXEC_OBJECT_WRITE) ? I915_GEM_DOMAIN_RENDER : 0;
 
-   VkResult result = anv_reloc_list_grow(list, alloc, 1);
+   result = anv_reloc_list_grow_relocs(list, alloc, 1);
    if (result != VK_SUCCESS)
       return result;
 
+   struct drm_i915_gem_relocation_entry *entry;
+
    /* XXX: Can we use I915_EXEC_HANDLE_LUT? */
    index = list->num_relocs++;
    list->reloc_bos[index] = target_bo;
@@ -195,7 +256,18 @@ anv_reloc_list_append(struct anv_reloc_list *list,
                       const VkAllocationCallbacks *alloc,
                       struct anv_reloc_list *other, uint32_t offset)
 {
-   VkResult result = anv_reloc_list_grow(list, alloc, other->num_relocs);
+   VkResult result;
+
+   result = anv_reloc_list_grow_bos(list, alloc, other->num_bos);
+   if (result != VK_SUCCESS)
+      return result;
+
+   memcpy(&list->bos[list->num_bos], &other->bos[0],
+          other->num_bos * sizeof(other->bos[0]));
+
+   list->num_bos += other->num_bos;
+
+   result = anv_reloc_list_grow_relocs(list, alloc, other->num_relocs);
    if (result != VK_SUCCESS)
       return result;
 
@@ -361,6 +433,7 @@ anv_batch_bo_start(struct anv_batch_bo *bbo, struct anv_batch *batch,
    batch->end = bbo->bo.map + bbo->bo.size - batch_padding;
    batch->relocs = &bbo->relocs;
    bbo->relocs.num_relocs = 0;
+   bbo->relocs.num_bos = 0;
 }
 
 static void
@@ -444,9 +517,15 @@ anv_batch_bo_list_clone(const struct list_head *list,
           * those relocations as we go.  Fortunately, this is pretty easy
           * as it will always be the last relocation in the list.
           */
-         uint32_t last_idx = prev_bbo->relocs.num_relocs - 1;
-         assert(prev_bbo->relocs.reloc_bos[last_idx] == &bbo->bo);
-         prev_bbo->relocs.reloc_bos[last_idx] = &new_bbo->bo;
+         if (prev_bbo->relocs.bos[prev_bbo->relocs.num_bos - 1] == &bbo->bo)
+            prev_bbo->relocs.num_bos--;
+         if (prev_bbo->relocs.num_relocs &&
+             prev_bbo->relocs.reloc_bos[prev_bbo->relocs.num_relocs - 1] == &bbo->bo)
+            prev_bbo->relocs.num_relocs--;
+
+         int reloc_size = cmd_buffer->device->info.gen < 8 ? 4 : 8;
+         anv_reloc_list_add(&prev_bbo->relocs, &cmd_buffer->pool->alloc,
+                            prev_bbo->length - reloc_size, &new_bbo->bo, 0);
       }
 
       prev_bbo = new_bbo;
@@ -800,6 +879,7 @@ anv_cmd_buffer_reset_batch_bo_chain(struct anv_cmd_buffer *cmd_buffer)
    cmd_buffer->bt_next = 0;
 
    cmd_buffer->surface_relocs.num_relocs = 0;
+   cmd_buffer->surface_relocs.num_bos = 0;
    cmd_buffer->last_ss_pool_center = 0;
 
    /* Reset the list of seen buffers */
@@ -861,6 +941,7 @@ anv_cmd_buffer_end_batch_buffer(struct anv_cmd_buffer *cmd_buffer)
           * MI_BATCH_BUFFER_START command.
           */
          batch_bo->relocs.num_relocs++;
+         batch_bo->relocs.num_bos++;
          cmd_buffer->batch.next += GEN8_MI_BATCH_BUFFER_START_length * 4;
       } else {
          cmd_buffer->exec_mode = ANV_CMD_BUFFER_EXEC_MODE_COPY_AND_CHAIN;
@@ -919,6 +1000,7 @@ anv_cmd_buffer_add_secondary(struct anv_cmd_buffer *primary,
        * here.
        */
       last_bbo->relocs.num_relocs--;
+      last_bbo->relocs.num_bos--;
       secondary->batch.next -= inst_size;
       emit_batch_buffer_start(secondary, &this_bbo->bo, offset);
       anv_cmd_buffer_add_seen_bbos(primary, &secondary->batch_bos);
@@ -1059,7 +1141,7 @@ anv_execbuf_add_bo(struct anv_execbuf *exec,
       obj->rsvd2 = 0;
    }
 
-   if (relocs != NULL && obj->relocation_count == 0) {
+   if (relocs != NULL && !obj->relocs_ptr) {
       /* This is the first time we've ever seen a list of relocations for
        * this BO.  Go ahead and set the relocations and then walk the list
        * of relocations and add them all.
@@ -1067,12 +1149,10 @@ anv_execbuf_add_bo(struct anv_execbuf *exec,
       obj->relocation_count = relocs->num_relocs;
       obj->relocs_ptr = (uintptr_t) relocs->relocs;
 
-      for (size_t i = 0; i < relocs->num_relocs; i++) {
+      for (size_t i = 0; i < relocs->num_bos; i++) {
          VkResult result;
 
-         /* A quick sanity check on relocations */
-         assert(relocs->relocs[i].offset < bo->size);
-         result = anv_execbuf_add_bo(exec, relocs->reloc_bos[i], NULL,
+         result = anv_execbuf_add_bo(exec, relocs->bos[i], NULL,
                                      extra_flags, alloc);
 
          if (result != VK_SUCCESS)
diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h
index ef8e70ed47..f1792e9692 100644
--- a/src/intel/vulkan/anv_private.h
+++ b/src/intel/vulkan/anv_private.h
@@ -832,8 +832,12 @@ VkResult anv_bo_init_new(struct anv_bo *bo, struct anv_device *device,
                          uint64_t size, unsigned int flags);
 
 struct anv_reloc_list {
+   uint32_t                                     num_bos;
+   uint32_t                                     size_bos;
+   struct anv_bo **                             bos;
+
    uint32_t                                     num_relocs;
-   uint32_t                                     array_length;
+   uint32_t                                     size_relocs;
    struct drm_i915_gem_relocation_entry *       relocs;
    struct anv_bo **                             reloc_bos;
 };
-- 
2.11.0



More information about the mesa-dev mailing list