i965: Unify the two emit_pipe_control functions
authorJason Ekstrand <jason.ekstrand@intel.com>
Tue, 13 Jun 2017 16:59:18 +0000 (09:59 -0700)
committerJason Ekstrand <jason.ekstrand@intel.com>
Wed, 14 Jun 2017 22:11:21 +0000 (15:11 -0700)
These two functions contain almost identical logic except for one SNB
workaround required for render target cache flushes.  They may as well
call into the same code so we only have to handle the work-arounds in
one place.

Cc: "17.1" <mesa-stable@lists.freedesktop.org>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
src/mesa/drivers/dri/i965/brw_pipe_control.c

index 0e206c683fc157fccb5782d21daa8b75b04b74ac..39bb9c7365db1b7fe65cb1d58a97119c1a14ba2f 100644 (file)
@@ -87,33 +87,10 @@ gen7_cs_stall_every_four_pipe_controls(struct brw_context *brw, uint32_t flags)
    return 0;
 }
 
-/**
- * Emit a PIPE_CONTROL with various flushing flags.
- *
- * The caller is responsible for deciding what flags are appropriate for the
- * given generation.
- */
-void
-brw_emit_pipe_control_flush(struct brw_context *brw, uint32_t flags)
+static void
+brw_emit_pipe_control(struct brw_context *brw, uint32_t flags,
+                      struct brw_bo *bo, uint32_t offset, uint64_t imm)
 {
-   if (brw->gen >= 6 &&
-       (flags & PIPE_CONTROL_CACHE_FLUSH_BITS) &&
-       (flags & PIPE_CONTROL_CACHE_INVALIDATE_BITS)) {
-      /* A pipe control command with flush and invalidate bits set
-       * simultaneously is an inherently racy operation on Gen6+ if the
-       * contents of the flushed caches were intended to become visible from
-       * any of the invalidated caches.  Split it in two PIPE_CONTROLs, the
-       * first one should stall the pipeline to make sure that the flushed R/W
-       * caches are coherent with memory once the specified R/O caches are
-       * invalidated.  On pre-Gen6 hardware the (implicit) R/O cache
-       * invalidation seems to happen at the bottom of the pipeline together
-       * with any write cache flush, so this shouldn't be a concern.
-       */
-      brw_emit_pipe_control_flush(brw, (flags & PIPE_CONTROL_CACHE_FLUSH_BITS) |
-                                       PIPE_CONTROL_CS_STALL);
-      flags &= ~(PIPE_CONTROL_CACHE_FLUSH_BITS | PIPE_CONTROL_CS_STALL);
-   }
-
    if (brw->gen >= 8) {
       if (brw->gen == 8)
          gen8_add_cs_stall_workaround_bits(&flags);
@@ -131,10 +108,15 @@ brw_emit_pipe_control_flush(struct brw_context *brw, uint32_t flags)
       BEGIN_BATCH(6);
       OUT_BATCH(_3DSTATE_PIPE_CONTROL | (6 - 2));
       OUT_BATCH(flags);
-      OUT_BATCH(0);
-      OUT_BATCH(0);
-      OUT_BATCH(0);
-      OUT_BATCH(0);
+      if (bo) {
+         OUT_RELOC64(bo, I915_GEM_DOMAIN_INSTRUCTION,
+                     I915_GEM_DOMAIN_INSTRUCTION, offset);
+      } else {
+         OUT_BATCH(0);
+         OUT_BATCH(0);
+      }
+      OUT_BATCH(imm);
+      OUT_BATCH(imm >> 32);
       ADVANCE_BATCH();
    } else if (brw->gen >= 6) {
       if (brw->gen == 6 &&
@@ -150,23 +132,68 @@ brw_emit_pipe_control_flush(struct brw_context *brw, uint32_t flags)
 
       flags |= gen7_cs_stall_every_four_pipe_controls(brw, flags);
 
+      /* PPGTT/GGTT is selected by DW2 bit 2 on Sandybridge, but DW1 bit 24
+       * on later platforms.  We always use PPGTT on Gen7+.
+       */
+      unsigned gen6_gtt = brw->gen == 6 ? PIPE_CONTROL_GLOBAL_GTT_WRITE : 0;
+
       BEGIN_BATCH(5);
       OUT_BATCH(_3DSTATE_PIPE_CONTROL | (5 - 2));
       OUT_BATCH(flags);
-      OUT_BATCH(0);
-      OUT_BATCH(0);
-      OUT_BATCH(0);
+      if (bo) {
+         OUT_RELOC(bo, I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION,
+                   gen6_gtt | offset);
+      } else {
+         OUT_BATCH(0);
+      }
+      OUT_BATCH(imm);
+      OUT_BATCH(imm >> 32);
       ADVANCE_BATCH();
    } else {
       BEGIN_BATCH(4);
       OUT_BATCH(_3DSTATE_PIPE_CONTROL | flags | (4 - 2));
-      OUT_BATCH(0);
-      OUT_BATCH(0);
-      OUT_BATCH(0);
+      if (bo) {
+         OUT_RELOC(bo, I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION,
+                   PIPE_CONTROL_GLOBAL_GTT_WRITE | offset);
+      } else {
+         OUT_BATCH(0);
+      }
+      OUT_BATCH(imm);
+      OUT_BATCH(imm >> 32);
       ADVANCE_BATCH();
    }
 }
 
+/**
+ * Emit a PIPE_CONTROL with various flushing flags.
+ *
+ * The caller is responsible for deciding what flags are appropriate for the
+ * given generation.
+ */
+void
+brw_emit_pipe_control_flush(struct brw_context *brw, uint32_t flags)
+{
+   if (brw->gen >= 6 &&
+       (flags & PIPE_CONTROL_CACHE_FLUSH_BITS) &&
+       (flags & PIPE_CONTROL_CACHE_INVALIDATE_BITS)) {
+      /* A pipe control command with flush and invalidate bits set
+       * simultaneously is an inherently racy operation on Gen6+ if the
+       * contents of the flushed caches were intended to become visible from
+       * any of the invalidated caches.  Split it in two PIPE_CONTROLs, the
+       * first one should stall the pipeline to make sure that the flushed R/W
+       * caches are coherent with memory once the specified R/O caches are
+       * invalidated.  On pre-Gen6 hardware the (implicit) R/O cache
+       * invalidation seems to happen at the bottom of the pipeline together
+       * with any write cache flush, so this shouldn't be a concern.
+       */
+      brw_emit_pipe_control_flush(brw, (flags & PIPE_CONTROL_CACHE_FLUSH_BITS) |
+                                       PIPE_CONTROL_CS_STALL);
+      flags &= ~(PIPE_CONTROL_CACHE_FLUSH_BITS | PIPE_CONTROL_CS_STALL);
+   }
+
+   brw_emit_pipe_control(brw, flags, NULL, 0, 0);
+}
+
 /**
  * Emit a PIPE_CONTROL that writes to a buffer object.
  *
@@ -180,43 +207,7 @@ brw_emit_pipe_control_write(struct brw_context *brw, uint32_t flags,
                             struct brw_bo *bo, uint32_t offset,
                             uint64_t imm)
 {
-   if (brw->gen >= 8) {
-      if (brw->gen == 8)
-         gen8_add_cs_stall_workaround_bits(&flags);
-
-      BEGIN_BATCH(6);
-      OUT_BATCH(_3DSTATE_PIPE_CONTROL | (6 - 2));
-      OUT_BATCH(flags);
-      OUT_RELOC64(bo, I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION,
-                  offset);
-      OUT_BATCH(imm);
-      OUT_BATCH(imm >> 32);
-      ADVANCE_BATCH();
-   } else if (brw->gen >= 6) {
-      flags |= gen7_cs_stall_every_four_pipe_controls(brw, flags);
-
-      /* PPGTT/GGTT is selected by DW2 bit 2 on Sandybridge, but DW1 bit 24
-       * on later platforms.  We always use PPGTT on Gen7+.
-       */
-      unsigned gen6_gtt = brw->gen == 6 ? PIPE_CONTROL_GLOBAL_GTT_WRITE : 0;
-
-      BEGIN_BATCH(5);
-      OUT_BATCH(_3DSTATE_PIPE_CONTROL | (5 - 2));
-      OUT_BATCH(flags);
-      OUT_RELOC(bo, I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION,
-                gen6_gtt | offset);
-      OUT_BATCH(imm);
-      OUT_BATCH(imm >> 32);
-      ADVANCE_BATCH();
-   } else {
-      BEGIN_BATCH(4);
-      OUT_BATCH(_3DSTATE_PIPE_CONTROL | flags | (4 - 2));
-      OUT_RELOC(bo, I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION,
-                PIPE_CONTROL_GLOBAL_GTT_WRITE | offset);
-      OUT_BATCH(imm);
-      OUT_BATCH(imm >> 32);
-      ADVANCE_BATCH();
-   }
+   brw_emit_pipe_control(brw, flags, bo, offset, imm);
 }
 
 /**