vk/cmd_buffer: Use an array to track all know anv_batch_bo objects
authorJason Ekstrand <jason.ekstrand@intel.com>
Wed, 29 Jul 2015 22:28:51 +0000 (15:28 -0700)
committerJason Ekstrand <jason.ekstrand@intel.com>
Wed, 29 Jul 2015 22:30:15 +0000 (15:30 -0700)
Instead of walking the list of batch and surface buffers, we simply keep
track of all known batch and surface buffers as we build the command
buffer.  Then we use this new list to construct the validate list.

src/vulkan/anv_cmd_buffer.c
src/vulkan/anv_private.h

index b47650aff73bd476d0473aa6779d267f9e49869d..2d46cc0c0ad81076fb76a01fe23ea7fdc1fc54fd 100644 (file)
@@ -305,6 +305,13 @@ anv_cmd_buffer_chain_batch(struct anv_batch *batch, void *_data)
    if (result != VK_SUCCESS)
       return result;
 
+   struct anv_batch_bo **seen_bbo = anv_vector_add(&cmd_buffer->seen_bbos);
+   if (seen_bbo == NULL) {
+      anv_batch_bo_destroy(new_bbo, cmd_buffer->device);
+      return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+   }
+   *seen_bbo = new_bbo;
+
    /* We set the end of the batch a little short so we would be sure we
     * have room for the chaining command.  Since we're about to emit the
     * chaining command, let's set it back where it should go.
@@ -370,6 +377,13 @@ anv_cmd_buffer_new_surface_state_bo(struct anv_cmd_buffer *cmd_buffer)
    if (result != VK_SUCCESS)
       return result;
 
+   struct anv_batch_bo **seen_bbo = anv_vector_add(&cmd_buffer->seen_bbos);
+   if (seen_bbo == NULL) {
+      anv_batch_bo_destroy(new_bbo, cmd_buffer->device);
+      return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+   }
+   *seen_bbo = new_bbo;
+
    cmd_buffer->surface_next = 1;
 
    list_addtail(&new_bbo->link, &cmd_buffer->surface_bos);
@@ -406,6 +420,15 @@ anv_cmd_buffer_init_batch_bo_chain(struct anv_cmd_buffer *cmd_buffer)
 
    list_addtail(&surface_bbo->link, &cmd_buffer->surface_bos);
 
+   int success = anv_vector_init(&cmd_buffer->seen_bbos,
+                                 sizeof(struct anv_bo *),
+                                 8 * sizeof(struct anv_bo *));
+   if (!success)
+      goto fail_surface_bo;
+
+   *(struct anv_batch_bo **)anv_vector_add(&cmd_buffer->seen_bbos) = batch_bo;
+   *(struct anv_batch_bo **)anv_vector_add(&cmd_buffer->seen_bbos) = surface_bbo;
+
    /* Start surface_next at 1 so surface offset 0 is invalid. */
    cmd_buffer->surface_next = 1;
 
@@ -415,6 +438,8 @@ anv_cmd_buffer_init_batch_bo_chain(struct anv_cmd_buffer *cmd_buffer)
 
    return VK_SUCCESS;
 
+ fail_surface_bo:
+   anv_batch_bo_destroy(surface_bbo, device);
  fail_batch_bo:
    anv_batch_bo_destroy(batch_bo, device);
 
@@ -426,6 +451,8 @@ anv_cmd_buffer_fini_batch_bo_chain(struct anv_cmd_buffer *cmd_buffer)
 {
    struct anv_device *device = cmd_buffer->device;
 
+   anv_vector_finish(&cmd_buffer->seen_bbos);
+
    /* Destroy all of the batch buffers */
    list_for_each_entry_safe(struct anv_batch_bo, bbo,
                             &cmd_buffer->batch_bos, link) {
@@ -472,6 +499,15 @@ anv_cmd_buffer_reset_batch_bo_chain(struct anv_cmd_buffer *cmd_buffer)
    anv_cmd_buffer_current_surface_bbo(cmd_buffer)->relocs.num_relocs = 0;
 
    cmd_buffer->surface_next = 1;
+
+   /* Reset the list of seen buffers */
+   cmd_buffer->seen_bbos.head = 0;
+   cmd_buffer->seen_bbos.tail = 0;
+
+   *(struct anv_batch_bo **)anv_vector_add(&cmd_buffer->seen_bbos) =
+      anv_cmd_buffer_current_batch_bo(cmd_buffer);
+   *(struct anv_batch_bo **)anv_vector_add(&cmd_buffer->seen_bbos) =
+      anv_cmd_buffer_current_surface_bbo(cmd_buffer);
 }
 
 void
@@ -595,15 +631,12 @@ anv_cmd_buffer_prepare_execbuf(struct anv_cmd_buffer *cmd_buffer)
    cmd_buffer->execbuf2.bo_count = 0;
    cmd_buffer->execbuf2.need_reloc = false;
 
-   list_for_each_entry(struct anv_batch_bo, bbo,
-                       &cmd_buffer->batch_bos, link) {
-      anv_cmd_buffer_add_bo(cmd_buffer, &bbo->bo, &bbo->relocs);
-   }
-
-   list_for_each_entry(struct anv_batch_bo, bbo,
-                       &cmd_buffer->surface_bos, link) {
-      anv_cmd_buffer_add_bo(cmd_buffer, &bbo->bo, &bbo->relocs);
-   }
+   /* First, we walk over all of the bos we've seen and add them and their
+    * relocations to the validate list.
+    */
+   struct anv_batch_bo **bbo;
+   anv_vector_foreach(bbo, &cmd_buffer->seen_bbos)
+      anv_cmd_buffer_add_bo(cmd_buffer, &(*bbo)->bo, &(*bbo)->relocs);
 
    struct anv_batch_bo *first_batch_bo =
       list_first_entry(&cmd_buffer->batch_bos, struct anv_batch_bo, link);
@@ -636,14 +669,8 @@ anv_cmd_buffer_prepare_execbuf(struct anv_cmd_buffer *cmd_buffer)
     * the correct indices in the object array.  We have to do this after we
     * reorder the list above as some of the indices may have changed.
     */
-   list_for_each_entry(struct anv_batch_bo, bbo,
-                       &cmd_buffer->surface_bos, link) {
-      anv_cmd_buffer_process_relocs(cmd_buffer, &bbo->relocs);
-   }
-   list_for_each_entry_rev(struct anv_batch_bo, bbo,
-                           &cmd_buffer->batch_bos, link) {
-      anv_cmd_buffer_process_relocs(cmd_buffer, &bbo->relocs);
-   }
+   anv_vector_foreach(bbo, &cmd_buffer->seen_bbos)
+      anv_cmd_buffer_process_relocs(cmd_buffer, &(*bbo)->relocs);
 
    cmd_buffer->execbuf2.execbuf = (struct drm_i915_gem_execbuffer2) {
       .buffers_ptr = (uintptr_t) cmd_buffer->execbuf2.objects,
index 1d04dfca9d72c298a4936392326004567b009fe3..a3787229a74f8764717a74f75139ba0367d11b11 100644 (file)
@@ -703,6 +703,13 @@ struct anv_cmd_buffer {
    struct list_head                             surface_bos;
    uint32_t                                     surface_next;
 
+   /* A vector of anv_batch_bo pointers for every batch or surface buffer
+    * referenced by this command buffer
+    *
+    * initialized by anv_cmd_buffer_init_batch_bo_chain()
+    */
+   struct anv_vector                            seen_bbos;
+
    /* Information needed for execbuf
     *
     * These fields are generated by anv_cmd_buffer_prepare_execbuf().