iris: add support INTEL_blackhole_render
authorLionel Landwerlin <lionel.g.landwerlin@intel.com>
Thu, 5 Dec 2019 12:49:12 +0000 (14:49 +0200)
committerMarge Bot <eric+marge@anholt.net>
Thu, 13 Feb 2020 17:05:05 +0000 (17:05 +0000)
v2: Use a software mechanism to manage blackhole state

v3: s/iris_batchbuffer/iris_batch/ (Ken)

v4: Fixup state transition mistake (Ken/Lionel)

v5: Cleanup iris_batch_flush (Ken)

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Tested-by: Marge Bot <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/2964>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/2964>

src/gallium/drivers/iris/iris_batch.c
src/gallium/drivers/iris/iris_batch.h
src/gallium/drivers/iris/iris_screen.c
src/gallium/drivers/iris/iris_state.c

index 120aaf9cbd98baeeefc92d59fc2736c20ed4c765..ecc81b9c9332a3712aed08dbbec653320c0a465b 100644 (file)
@@ -363,6 +363,24 @@ create_batch(struct iris_batch *batch)
    iris_use_pinned_bo(batch, batch->bo, false);
 }
 
+static void
+iris_batch_maybe_noop(struct iris_batch *batch)
+{
+   /* We only insert the NOOP at the beginning of the batch. */
+   assert(iris_batch_bytes_used(batch) == 0);
+
+   if (batch->noop_enabled) {
+      /* Emit MI_BATCH_BUFFER_END to prevent any further command to be
+       * executed.
+       */
+      uint32_t *map = batch->map_next;
+
+      map[0] = (0xA << 23);
+
+      batch->map_next += 4;
+   }
+}
+
 static void
 iris_batch_reset(struct iris_batch *batch)
 {
@@ -382,6 +400,8 @@ iris_batch_reset(struct iris_batch *batch)
    iris_syncpt_reference(screen, &syncpt, NULL);
 
    iris_cache_sets_clear(batch);
+
+   iris_batch_maybe_noop(batch);
 }
 
 void
@@ -725,3 +745,26 @@ iris_batch_references(struct iris_batch *batch, struct iris_bo *bo)
 {
    return find_validation_entry(batch, bo) != NULL;
 }
+
+/**
+ * Updates the state of the noop feature.
+ */
+uint64_t
+iris_batch_prepare_noop(struct iris_batch *batch, bool noop_enable, uint64_t dirty_flags)
+{
+   if (batch->noop_enabled == noop_enable)
+      return 0;
+
+   batch->noop_enabled = noop_enable;
+
+   iris_batch_flush(batch);
+
+   /* If the batch was empty, flush had no effect, so insert our noop. */
+   if (iris_batch_bytes_used(batch) == 0)
+      iris_batch_maybe_noop(batch);
+
+   /* We only need to update the entire state if we transition from noop ->
+    * not-noop.
+    */
+   return !batch->noop_enabled ? dirty_flags : 0;
+}
index 42c0f3e787a60d7938616e51cdf95aafb60d8a0b..d8399d3cd34adcd6d32e70257f2340f75422b9ac 100644 (file)
@@ -85,6 +85,11 @@ struct iris_batch {
    int exec_count;
    int exec_array_size;
 
+   /** Whether INTEL_BLACKHOLE_RENDER is enabled in the batch (aka first
+    * instruction is a MI_BATCH_BUFFER_END).
+    */
+   bool noop_enabled;
+
    /**
     * A list of iris_syncpts associated with this batch.
     *
@@ -149,6 +154,10 @@ void _iris_batch_flush(struct iris_batch *batch, const char *file, int line);
 
 bool iris_batch_references(struct iris_batch *batch, struct iris_bo *bo);
 
+uint64_t iris_batch_prepare_noop(struct iris_batch *batch,
+                                 bool noop_enable,
+                                 uint64_t dirty_flags);
+
 #define RELOC_WRITE EXEC_OBJECT_WRITE
 
 void iris_use_pinned_bo(struct iris_batch *batch, struct iris_bo *bo,
index fd7f5f70165f5113f9531c88b0dcb2d3545d1bbb..561d9146aad4d7c543c937e9ed5a6b8c9862013c 100644 (file)
@@ -315,6 +315,9 @@ iris_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
              PIPE_CONTEXT_PRIORITY_MEDIUM |
              PIPE_CONTEXT_PRIORITY_HIGH;
 
+   case PIPE_CAP_FRONTEND_NOOP:
+      return true;
+
    // XXX: don't hardcode 00:00:02.0 PCI here
    case PIPE_CAP_PCI_GROUP:
       return 0;
index db4568c77771aa4af79955bbbde868c9f9ae71e4..d0e46486756023b1d71f5a1e876473c7431f1ea2 100644 (file)
@@ -7415,6 +7415,19 @@ genX(emit_hashing_mode)(struct iris_context *ice, struct iris_batch *batch,
 #endif
 }
 
+static void
+iris_set_frontend_noop(struct pipe_context *ctx, bool enable)
+{
+   struct iris_context *ice = (struct iris_context *) ctx;
+
+   ice->state.dirty |= iris_batch_prepare_noop(&ice->batches[IRIS_BATCH_RENDER],
+                                               enable,
+                                               IRIS_ALL_DIRTY_FOR_RENDER);
+   ice->state.dirty |= iris_batch_prepare_noop(&ice->batches[IRIS_BATCH_COMPUTE],
+                                               enable,
+                                               IRIS_ALL_DIRTY_FOR_COMPUTE);
+}
+
 void
 genX(init_state)(struct iris_context *ice)
 {
@@ -7459,6 +7472,7 @@ genX(init_state)(struct iris_context *ice)
    ctx->create_stream_output_target = iris_create_stream_output_target;
    ctx->stream_output_target_destroy = iris_stream_output_target_destroy;
    ctx->set_stream_output_targets = iris_set_stream_output_targets;
+   ctx->set_frontend_noop = iris_set_frontend_noop;
 
    ice->vtbl.destroy_state = iris_destroy_state;
    ice->vtbl.init_render_context = iris_init_render_context;