iris: add preemption support on gen9
authorMike Blumenkrantz <michael.blumenkrantz@gmail.com>
Thu, 11 Apr 2019 14:07:15 +0000 (10:07 -0400)
committerRafael Antognolli <rafael.antognolli@intel.com>
Wed, 24 Apr 2019 21:47:08 +0000 (14:47 -0700)
this is basically just porting the following two commits to gallium:
d8b50e152a0d5df0971c05b8db132fa688794001
5c454661c66fa2624cf4bba1071175070724869a

resolves kwg/mesa#49

Reviewed-by: Anuj Phogat <anuj.phogat@gmail.com>
Reviewed-by: Rafael Antognolli <rafael.antognolli@intel.com>
src/gallium/drivers/iris/iris_context.h
src/gallium/drivers/iris/iris_draw.c
src/gallium/drivers/iris/iris_state.c

index f660c9ae2513b66a4caae3d27efda15a583bedec..79e78d0adb70f1b9c839b310c04f649dfc2fb3bd 100644 (file)
@@ -542,6 +542,8 @@ struct iris_context {
       /** Bitfield of which vertex buffers are bound (non-null). */
       uint64_t bound_vertex_buffers;
 
+      bool object_preemption; /**< Object level preemption enabled. */
+
       bool primitive_restart;
       unsigned cut_index;
       enum pipe_prim_type prim_mode:8;
@@ -816,4 +818,7 @@ void iris_render_cache_add_bo(struct iris_batch *batch,
 void iris_cache_flush_for_depth(struct iris_batch *batch, struct iris_bo *bo);
 void iris_depth_cache_add_bo(struct iris_batch *batch, struct iris_bo *bo);
 
+/* iris_state.c */
+void gen9_iris_enable_obj_preemption(struct iris_context *ice, struct iris_batch *batch, bool enable);
+void gen10_iris_enable_obj_preemption(struct iris_context *ice, struct iris_batch *batch, bool enable);
 #endif
index e94346f33f08a2d68f63d2a30369b47f5d9ebbf6..c859d93c009638b5f2850b86b6b7164e7fe2f1fe 100644 (file)
 #include "iris_context.h"
 #include "iris_defines.h"
 
+/**
+ * Implement workarounds for preemption:
+ *    - WaDisableMidObjectPreemptionForGSLineStripAdj
+ *    - WaDisableMidObjectPreemptionForTrifanOrPolygon
+ *    - WaDisableMidObjectPreemptionForLineLoop
+ *    - WA#0798
+ */
+static void
+gen9_emit_preempt_wa(struct iris_context *ice, struct iris_batch *batch,
+                     const struct pipe_draw_info *info)
+{
+   bool object_preemption = true;
+   struct iris_screen *screen = (struct iris_screen *)ice->ctx.screen;
+
+   /* Only apply these workarounds for gen9 */
+   assert(screen->devinfo.gen == 9);
+
+   /* WaDisableMidObjectPreemptionForGSLineStripAdj
+    *
+    *    WA: Disable mid-draw preemption when draw-call is a linestrip_adj and
+    *    GS is enabled.
+    */
+   if (ice->state.prim_mode == PIPE_PRIM_LINE_STRIP_ADJACENCY &&
+       ice->shaders.prog[MESA_SHADER_GEOMETRY])
+      object_preemption = false;
+
+   /* WaDisableMidObjectPreemptionForTrifanOrPolygon
+    *
+    *    TriFan miscompare in Execlist Preemption test. Cut index that is on a
+    *    previous context. End the previous, the resume another context with a
+    *    tri-fan or polygon, and the vertex count is corrupted. If we prempt
+    *    again we will cause corruption.
+    *
+    *    WA: Disable mid-draw preemption when draw-call has a tri-fan.
+    */
+   if (ice->state.prim_mode == PIPE_PRIM_TRIANGLE_FAN)
+      object_preemption = false;
+
+   /* WaDisableMidObjectPreemptionForLineLoop
+    *
+    *    VF Stats Counters Missing a vertex when preemption enabled.
+    *
+    *    WA: Disable mid-draw preemption when the draw uses a lineloop
+    *    topology.
+    */
+   if (ice->state.prim_mode == PIPE_PRIM_LINE_LOOP)
+      object_preemption = false;
+
+   /* WA#0798
+    *
+    *    VF is corrupting GAFS data when preempted on an instance boundary and
+    *    replayed with instancing enabled.
+    *
+    *    WA: Disable preemption when using instanceing.
+    */
+   if (info->instance_count > 1)
+      object_preemption = false;
+
+   gen9_iris_enable_obj_preemption(ice, batch, object_preemption);
+}
+
 /**
  * Record the current primitive mode and restart information, flagging
  * related packets as dirty if necessary.
@@ -116,6 +177,7 @@ void
 iris_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
 {
    struct iris_context *ice = (struct iris_context *) ctx;
+   struct iris_screen *screen = (struct iris_screen*)ice->ctx.screen;
    struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
 
    if (ice->state.predicate == IRIS_PREDICATE_STATE_DONT_RENDER)
@@ -131,6 +193,9 @@ iris_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
 
    iris_update_draw_info(ice, info);
 
+   if (screen->devinfo.gen == 9)
+     gen9_emit_preempt_wa(ice, batch, info);
+
    iris_update_compiled_shaders(ice);
 
    if (ice->state.dirty & IRIS_DIRTY_RENDER_RESOLVES_AND_FLUSHES) {
index 4760da09c451587b158836de4172b81a65073693..92275b48a4d53607b1a1e11f4decbcbc7c8ded6d 100644 (file)
@@ -6278,3 +6278,32 @@ genX(init_state)(struct iris_context *ice)
       };
    }
 }
+
+#if GEN_GEN >= 9
+/* not called externally */
+void gen11_iris_enable_obj_preemption(struct iris_context *ice, struct iris_batch *batch, bool enable);
+
+void
+genX(iris_enable_obj_preemption)(struct iris_context *ice, struct iris_batch *batch, bool enable)
+{
+   uint32_t reg_val;
+   struct iris_screen *screen = (struct iris_screen *)ice->ctx.screen;
+
+   assert(screen->devinfo.gen >= 9);
+
+   if (enable == ice->state.object_preemption)
+      return;
+   ice->state.object_preemption = enable;
+
+   /* A fixed function pipe flush is required before modifying this field */
+   iris_emit_end_of_pipe_sync(batch,
+                              PIPE_CONTROL_RENDER_TARGET_FLUSH);
+
+   /* enable object level preemption */
+   iris_pack_state(GENX(CS_CHICKEN1), &reg_val, reg) {
+      reg.ReplayMode = enable;
+      reg.ReplayModeMask = true;
+   }
+   iris_emit_lri(batch, CS_CHICKEN1, reg_val);
+}
+#endif