iris: Spruce up "are we using this engine?" checks for flushing
[mesa.git] / src / gallium / drivers / iris / iris_batch.c
index cfd49277cf117e536f84d18b0947b14f0139f601..5548b8f6c818bbaa8e0e56f86e0f6dfdb84392fd 100644 (file)
@@ -40,6 +40,7 @@
 #include "iris_batch.h"
 #include "iris_bufmgr.h"
 #include "iris_context.h"
+#include "iris_fence.h"
 
 #include "drm-uapi/i915_drm.h"
 
@@ -99,15 +100,14 @@ dump_validation_list(struct iris_batch *batch)
       uint64_t flags = batch->validation_list[i].flags;
       assert(batch->validation_list[i].handle ==
              batch->exec_bos[i]->gem_handle);
-      fprintf(stderr, "[%2d]: %2d %-14s %p %-7s @ 0x%016llx (%"PRIu64"B) - %d refs\n",
+      fprintf(stderr, "[%2d]: %2d %-14s @ 0x%016llx (%"PRIu64"B)\t %2d refs %s\n",
               i,
               batch->validation_list[i].handle,
               batch->exec_bos[i]->name,
-              batch->exec_bos[i],
-              (flags & EXEC_OBJECT_WRITE) ? "(write)" : "",
               batch->validation_list[i].offset,
               batch->exec_bos[i]->size,
-              batch->exec_bos[i]->refcount);
+              batch->exec_bos[i]->refcount,
+              (flags & EXEC_OBJECT_WRITE) ? " (write)" : "");
    }
 }
 
@@ -115,10 +115,12 @@ dump_validation_list(struct iris_batch *batch)
  * Return BO information to the batch decoder (for debugging).
  */
 static struct gen_batch_decode_bo
-decode_get_bo(void *v_batch, uint64_t address)
+decode_get_bo(void *v_batch, bool ppgtt, uint64_t address)
 {
    struct iris_batch *batch = v_batch;
 
+   assert(ppgtt);
+
    for (int i = 0; i < batch->exec_count; i++) {
       struct iris_bo *bo = batch->exec_bos[i];
       /* The decoder zeroes out the top 16 bits, so we need to as well */
@@ -145,19 +147,7 @@ decode_batch(struct iris_batch *batch)
 {
    void *map = iris_bo_map(batch->dbg, batch->exec_bos[0], MAP_READ);
    gen_print_batch(&batch->decoder, map, batch->primary_batch_size,
-                   batch->exec_bos[0]->gtt_offset);
-}
-
-static bool
-uint_key_compare(const void *a, const void *b)
-{
-   return a == b;
-}
-
-static uint32_t
-uint_key_hash(const void *key)
-{
-   return (uintptr_t) key;
+                   batch->exec_bos[0]->gtt_offset, false);
 }
 
 void
@@ -165,8 +155,8 @@ iris_init_batch(struct iris_batch *batch,
                 struct iris_screen *screen,
                 struct iris_vtable *vtbl,
                 struct pipe_debug_callback *dbg,
-                struct iris_batch **all_batches,
-                const char *name,
+                struct iris_batch *all_batches,
+                enum iris_batch_name name,
                 uint8_t engine)
 {
    batch->screen = screen;
@@ -183,6 +173,7 @@ iris_init_batch(struct iris_batch *batch,
    assert(batch->hw_ctx_id);
 
    util_dynarray_init(&batch->exec_fences, ralloc_context(NULL));
+   util_dynarray_init(&batch->syncpts, ralloc_context(NULL));
 
    batch->exec_count = 0;
    batch->exec_array_size = 100;
@@ -199,20 +190,18 @@ iris_init_batch(struct iris_batch *batch,
    memset(batch->other_batches, 0, sizeof(batch->other_batches));
 
    for (int i = 0, j = 0; i < IRIS_BATCH_COUNT; i++) {
-      if (all_batches[i] != batch)
-         batch->other_batches[j++] = all_batches[i];
+      if (&all_batches[i] != batch)
+         batch->other_batches[j++] = &all_batches[i];
    }
 
    if (unlikely(INTEL_DEBUG)) {
-      batch->state_sizes =
-         _mesa_hash_table_create(NULL, uint_key_hash, uint_key_compare);
-
       const unsigned decode_flags =
          GEN_BATCH_DECODE_FULL |
          ((INTEL_DEBUG & DEBUG_COLOR) ? GEN_BATCH_DECODE_IN_COLOR : 0) |
          GEN_BATCH_DECODE_OFFSETS |
          GEN_BATCH_DECODE_FLOATS;
 
+      /* TODO: track state size so we can print the right # of entries */
       gen_batch_decode_ctx_init(&batch->decoder, &screen->devinfo,
                                 stderr, decode_flags, NULL,
                                 decode_get_bo, NULL, batch);
@@ -222,8 +211,6 @@ iris_init_batch(struct iris_batch *batch,
    iris_batch_reset(batch);
 }
 
-#define READ_ONCE(x) (*(volatile __typeof__(x) *)&(x))
-
 static struct drm_i915_gem_exec_object2 *
 find_validation_entry(struct iris_batch *batch, struct iris_bo *bo)
 {
@@ -273,30 +260,34 @@ iris_use_pinned_bo(struct iris_batch *batch,
       return;
    }
 
-   /* This is the first time our batch has seen this BO.  Before we use it,
-    * we may need to flush and synchronize with other batches.
-    */
-   for (int b = 0; b < ARRAY_SIZE(batch->other_batches); b++) {
-      struct drm_i915_gem_exec_object2 *other_entry =
-         find_validation_entry(batch->other_batches[b], bo);
-
-      /* If the buffer is referenced by another batch, and either batch
-       * intends to write it, then flush the other batch and synchronize.
-       *
-       * Consider these cases:
-       *
-       * 1. They read, we read   =>  No synchronization required.
-       * 2. They read, we write  =>  Synchronize (they need the old value)
-       * 3. They write, we read  =>  Synchronize (we need their new value)
-       * 4. They write, we write =>  Synchronize (order writes)
-       *
-       * The read/read case is very common, as multiple batches usually
-       * share a streaming state buffer or shader assembly buffer, and
-       * we want to avoid synchronizing in this case.
+   if (bo != batch->bo) {
+      /* This is the first time our batch has seen this BO.  Before we use it,
+       * we may need to flush and synchronize with other batches.
        */
-      if (other_entry &&
-          ((other_entry->flags & EXEC_OBJECT_WRITE) || writable)) {
-         iris_batch_flush(batch->other_batches[b]);
+      for (int b = 0; b < ARRAY_SIZE(batch->other_batches); b++) {
+         struct drm_i915_gem_exec_object2 *other_entry =
+            find_validation_entry(batch->other_batches[b], bo);
+
+         /* If the buffer is referenced by another batch, and either batch
+          * intends to write it, then flush the other batch and synchronize.
+          *
+          * Consider these cases:
+          *
+          * 1. They read, we read   =>  No synchronization required.
+          * 2. They read, we write  =>  Synchronize (they need the old value)
+          * 3. They write, we read  =>  Synchronize (we need their new value)
+          * 4. They write, we write =>  Synchronize (order writes)
+          *
+          * The read/read case is very common, as multiple batches usually
+          * share a streaming state buffer or shader assembly buffer, and
+          * we want to avoid synchronizing in this case.
+          */
+         if (other_entry &&
+             ((other_entry->flags & EXEC_OBJECT_WRITE) || writable)) {
+            iris_batch_flush(batch->other_batches[b]);
+            iris_batch_add_syncpt(batch, batch->other_batches[b]->last_syncpt,
+                                  I915_EXEC_FENCE_WAIT);
+         }
       }
    }
 
@@ -345,19 +336,18 @@ create_batch(struct iris_batch *batch)
 static void
 iris_batch_reset(struct iris_batch *batch)
 {
-   if (batch->last_bo != NULL) {
-      iris_bo_unreference(batch->last_bo);
-      batch->last_bo = NULL;
-   }
-   batch->last_bo = batch->bo;
+   struct iris_screen *screen = batch->screen;
+
+   iris_bo_unreference(batch->bo);
    batch->primary_batch_size = 0;
    batch->contains_draw = false;
 
    create_batch(batch);
    assert(batch->bo->index == 0);
 
-   if (batch->state_sizes)
-      _mesa_hash_table_clear(batch->state_sizes, NULL);
+   struct iris_syncpt *syncpt = iris_create_syncpt(screen);
+   iris_batch_add_syncpt(batch, syncpt, I915_EXEC_FENCE_SIGNAL);
+   iris_syncpt_reference(screen, &syncpt, NULL);
 
    iris_cache_sets_clear(batch);
 }
@@ -376,22 +366,24 @@ iris_batch_free(struct iris_batch *batch)
 
    ralloc_free(batch->exec_fences.mem_ctx);
 
+   util_dynarray_foreach(&batch->syncpts, struct iris_syncpt *, s)
+      iris_syncpt_reference(screen, s, NULL);
+   ralloc_free(batch->syncpts.mem_ctx);
+
+   iris_syncpt_reference(screen, &batch->last_syncpt, NULL);
+
    iris_bo_unreference(batch->bo);
    batch->bo = NULL;
    batch->map = NULL;
    batch->map_next = NULL;
 
-   iris_bo_unreference(batch->last_bo);
-
    iris_destroy_hw_context(bufmgr, batch->hw_ctx_id);
 
    _mesa_hash_table_destroy(batch->cache.render, NULL);
    _mesa_set_destroy(batch->cache.depth, NULL);
 
-   if (batch->state_sizes) {
-      _mesa_hash_table_destroy(batch->state_sizes, NULL);
+   if (unlikely(INTEL_DEBUG))
       gen_batch_decode_ctx_finish(&batch->decoder);
-   }
 }
 
 /**
@@ -433,8 +425,6 @@ iris_chain_to_new_batch(struct iris_batch *batch)
 static void
 iris_finish_batch(struct iris_batch *batch)
 {
-   // XXX: ISP DIS
-
    /* Emit MI_BATCH_BUFFER_END to finish our batch. */
    uint32_t *map = batch->map_next;
 
@@ -503,11 +493,23 @@ submit_batch(struct iris_batch *batch)
 
       bo->idle = false;
       bo->index = -1;
+
+      iris_bo_unreference(bo);
    }
 
    return ret;
 }
 
+static const char *
+batch_name_to_string(enum iris_batch_name name)
+{
+   const char *names[IRIS_BATCH_COUNT] = {
+      [IRIS_BATCH_RENDER]  = "render",
+      [IRIS_BATCH_COMPUTE] = "compute",
+   };
+   return names[name];
+}
+
 /**
  * Flush the batch buffer, submitting it to the GPU and resetting it so
  * we're ready to emit the next batch.
@@ -521,6 +523,8 @@ submit_batch(struct iris_batch *batch)
 void
 _iris_batch_flush(struct iris_batch *batch, const char *file, int line)
 {
+   struct iris_screen *screen = batch->screen;
+
    if (iris_batch_bytes_used(batch) == 0)
       return;
 
@@ -535,7 +539,7 @@ _iris_batch_flush(struct iris_batch *batch, const char *file, int line)
       }
       fprintf(stderr, "%19s:%-3d: %s batch [%u] flush with %5d+%5db (%0.1f%%) "
               "(cmds), %4d BOs (%0.1fMb aperture)\n",
-              file, line, batch->name, batch->hw_ctx_id,
+              file, line, batch_name_to_string(batch->name), batch->hw_ctx_id,
               batch->primary_batch_size, second_bytes,
               100.0f * bytes_for_commands / BATCH_SZ,
               batch->exec_count,
@@ -550,8 +554,6 @@ _iris_batch_flush(struct iris_batch *batch, const char *file, int line)
 
    int ret = submit_batch(batch);
 
-   //throttle(iris);
-
    if (ret >= 0) {
       //if (iris->ctx.Const.ResetStrategy == GL_LOSE_CONTEXT_ON_RESET_ARB)
          //iris_check_for_reset(ice);
@@ -569,14 +571,17 @@ _iris_batch_flush(struct iris_batch *batch, const char *file, int line)
 #endif
    }
 
-   /* Clean up after the batch we submitted and prepare for a new one. */
-   for (int i = 0; i < batch->exec_count; i++) {
-      iris_bo_unreference(batch->exec_bos[i]);
-      batch->exec_bos[i] = NULL;
-   }
    batch->exec_count = 0;
    batch->aperture_space = 0;
 
+   struct iris_syncpt *syncpt =
+      ((struct iris_syncpt **) util_dynarray_begin(&batch->syncpts))[0];
+   iris_syncpt_reference(screen, &batch->last_syncpt, syncpt);
+
+   util_dynarray_foreach(&batch->syncpts, struct iris_syncpt *, s)
+      iris_syncpt_reference(screen, s, NULL);
+   util_dynarray_clear(&batch->syncpts);
+
    util_dynarray_clear(&batch->exec_fences);
 
    /* Start a new batch buffer. */