i965/gen9: Add workarounds for object preemption.
[mesa.git] / src / mesa / drivers / dri / i965 / brw_draw.c
index 8536c040109bd3053a340d12854c653d45e0485b..ec4fe0b096f1c2f88fdb0bb6bb7f065d1d1c9340 100644 (file)
@@ -303,16 +303,16 @@ brw_merge_inputs(struct brw_context *brw)
        * 2_10_10_10_REV vertex formats.  Set appropriate workaround flags.
        */
       while (mask) {
-         const struct gl_array_attributes *glattrib;
+         const struct gl_vertex_format *glformat;
          uint8_t wa_flags = 0;
 
          i = u_bit_scan64(&mask);
-         glattrib = brw->vb.inputs[i].glattrib;
+         glformat = &brw->vb.inputs[i].glattrib->Format;
 
-         switch (glattrib->Type) {
+         switch (glformat->Type) {
 
          case GL_FIXED:
-            wa_flags = glattrib->Size;
+            wa_flags = glformat->Size;
             break;
 
          case GL_INT_2_10_10_10_REV:
@@ -320,12 +320,12 @@ brw_merge_inputs(struct brw_context *brw)
             /* fallthough */
 
          case GL_UNSIGNED_INT_2_10_10_10_REV:
-            if (glattrib->Format == GL_BGRA)
+            if (glformat->Format == GL_BGRA)
                wa_flags |= BRW_ATTRIB_WA_BGRA;
 
-            if (glattrib->Normalized)
+            if (glformat->Normalized)
                wa_flags |= BRW_ATTRIB_WA_NORMALIZE;
-            else if (!glattrib->Integer)
+            else if (!glformat->Integer)
                wa_flags |= BRW_ATTRIB_WA_SCALE;
 
             break;
@@ -872,6 +872,66 @@ brw_finish_drawing(struct gl_context *ctx)
    }
 }
 
+/**
+ * Implement workarounds for preemption:
+ *    - WaDisableMidObjectPreemptionForGSLineStripAdj
+ *    - WaDisableMidObjectPreemptionForTrifanOrPolygon
+ *    - WaDisableMidObjectPreemptionForLineLoop
+ *    - WA#0798
+ */
+static void
+gen9_emit_preempt_wa(struct brw_context *brw,
+                     const struct _mesa_prim *prim)
+{
+   bool object_preemption = true;
+   const struct gen_device_info *devinfo = &brw->screen->devinfo;
+
+   /* Only apply these workarounds for gen9 */
+   assert(devinfo->gen == 9);
+
+   /* WaDisableMidObjectPreemptionForGSLineStripAdj
+    *
+    *    WA: Disable mid-draw preemption when draw-call is a linestrip_adj and
+    *    GS is enabled.
+    */
+   if (brw->primitive == _3DPRIM_LINESTRIP_ADJ && brw->gs.enabled)
+      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 (brw->primitive == _3DPRIM_TRIFAN)
+      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 (brw->primitive == _3DPRIM_LINELOOP)
+      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 (prim->num_instances > 1)
+      object_preemption = false;
+
+   brw_enable_obj_preemption(brw, object_preemption);
+}
+
 /* May fail if out of video memory for texture or vbo upload, or on
  * fallback conditions.
  */
@@ -885,7 +945,7 @@ brw_draw_single_prim(struct gl_context *ctx,
 {
    struct brw_context *brw = brw_context(ctx);
    const struct gen_device_info *devinfo = &brw->screen->devinfo;
-   bool fail_next = false;
+   bool fail_next;
 
    /* Flag BRW_NEW_DRAW_CALL on every draw.  This allows us to have
     * atoms that happen on every draw call.
@@ -898,6 +958,7 @@ brw_draw_single_prim(struct gl_context *ctx,
    intel_batchbuffer_require_space(brw, 1500);
    brw_require_statebuffer_space(brw, 2400);
    intel_batchbuffer_save_state(brw);
+   fail_next = intel_batchbuffer_saved_state_is_empty(brw);
 
    if (brw->num_instances != prim->num_instances ||
        brw->basevertex != prim->basevertex ||
@@ -986,6 +1047,9 @@ retry:
       brw_upload_render_state(brw);
    }
 
+   if (devinfo->gen == 9)
+      gen9_emit_preempt_wa(brw, prim);
+
    brw_emit_prim(brw, prim, brw->primitive, xfb_obj, stream);
 
    brw->batch.no_wrap = false;