<div dir="ltr"><div><div><div><div>3 and 4 are<br><br></div><div>Cc: "12.0 11.1 11.2" <<a href="mailto:mesa-stable@lists.freedesktop.org">mesa-stable@lists.freedesktop.org</a>><br></div>Reviewed-by: Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>><br><br></div>I did look over 3 fairly carefully.<br><br></div>It's worth noting that I think we have some double-pipe-controls that could probably be put together now.  Not sure that we actually want to do that though.<br></div>--Jason<br><div><div><div><div><div><div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Jun 30, 2016 at 10:07 PM, Francisco Jerez <span dir="ltr"><<a href="mailto:currojerez@riseup.net" target="_blank">currojerez@riseup.net</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">This hardware race condition has caused problems several times already<br>
(see "i965: Fix cache pollution race during L3 partitioning set-up.",<br>
"i965: Fix brw_render_cache_set_check_flush's PIPE_CONTROLs." and<br>
"i965: intel_texture_barrier reimplemented").  The problem is that<br>
whenever we attempt to both flush and invalidate multiple caches with<br>
a single pipe control command the flush and invalidation happen in<br>
reverse order, so the contents flushed from the R/W caches aren't<br>
guaranteed to become visible from the invalidated caches after the<br>
PIPE_CONTROL command completes execution if some concurrent rendering<br>
workload happened to pollute any of the invalidated R/O caches in the<br>
short window of time between the invalidation and flush.<br>
<br>
This makes sure that brw_emit_pipe_control_flush() has the effect<br>
expected by most callers of making the contents flushed from any R/W<br>
caches visible from the invalidated R/O caches.<br>
---<br>
 src/mesa/drivers/dri/i965/brw_pipe_control.c | 18 ++++++++++++++++++<br>
 src/mesa/drivers/dri/i965/intel_reg.h        |  9 +++++++++<br>
 2 files changed, 27 insertions(+)<br>
<br>
diff --git a/src/mesa/drivers/dri/i965/brw_pipe_control.c b/src/mesa/drivers/dri/i965/brw_pipe_control.c<br>
index 14a8f7c..05e8c05 100644<br>
--- a/src/mesa/drivers/dri/i965/brw_pipe_control.c<br>
+++ b/src/mesa/drivers/dri/i965/brw_pipe_control.c<br>
@@ -96,6 +96,24 @@ gen7_cs_stall_every_four_pipe_controls(struct brw_context *brw, uint32_t flags)<br>
 void<br>
 brw_emit_pipe_control_flush(struct brw_context *brw, uint32_t flags)<br>
 {<br>
+   if (brw->gen >= 6 &&<br>
+       (flags & PIPE_CONTROL_CACHE_FLUSH_BITS) &&<br>
+       (flags & PIPE_CONTROL_CACHE_INVALIDATE_BITS)) {<br>
+      /* A pipe control command with flush and invalidate bits set<br>
+       * simultaneously is an inherently racy operation on Gen6+ if the<br>
+       * contents of the flushed caches were intended to become visible from<br>
+       * any of the invalidated caches.  Split it in two PIPE_CONTROLs, the<br>
+       * first one should stall the pipeline to make sure that the flushed R/W<br>
+       * caches are coherent with memory once the specified R/O caches are<br>
+       * invalidated.  On pre-Gen6 hardware the (implicit) R/O cache<br>
+       * invalidation seems to happen at the bottom of the pipeline together<br>
+       * with any write cache flush, so this shouldn't be a concern.<br>
+       */<br>
+      brw_emit_pipe_control_flush(brw, (flags & PIPE_CONTROL_CACHE_FLUSH_BITS) |<br>
+                                       PIPE_CONTROL_CS_STALL);<br>
+      flags &= ~(PIPE_CONTROL_CACHE_FLUSH_BITS | PIPE_CONTROL_CS_STALL);<br>
+   }<br>
+<br>
    if (brw->gen >= 8) {<br>
       if (brw->gen == 8)<br>
          gen8_add_cs_stall_workaround_bits(&flags);<br>
diff --git a/src/mesa/drivers/dri/i965/intel_reg.h b/src/mesa/drivers/dri/i965/intel_reg.h<br>
index 95365fe..7a82be4 100644<br>
--- a/src/mesa/drivers/dri/i965/intel_reg.h<br>
+++ b/src/mesa/drivers/dri/i965/intel_reg.h<br>
@@ -134,6 +134,15 @@<br>
 #define PIPE_CONTROL_PPGTT_WRITE       (0 << 2)<br>
 #define PIPE_CONTROL_GLOBAL_GTT_WRITE  (1 << 2)<br>
<br>
+#define PIPE_CONTROL_CACHE_FLUSH_BITS \<br>
+   (PIPE_CONTROL_DEPTH_CACHE_FLUSH | PIPE_CONTROL_DATA_CACHE_FLUSH | \<br>
+    PIPE_CONTROL_RENDER_TARGET_FLUSH)<br>
+<br>
+#define PIPE_CONTROL_CACHE_INVALIDATE_BITS \<br>
+   (PIPE_CONTROL_STATE_CACHE_INVALIDATE | PIPE_CONTROL_CONST_CACHE_INVALIDATE | \<br>
+    PIPE_CONTROL_VF_CACHE_INVALIDATE | PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE | \<br>
+    PIPE_CONTROL_INSTRUCTION_INVALIDATE)<br>
+<br>
 /** @} */<br>
<br>
 #define XY_SETUP_BLT_CMD               (CMD_2D | (0x01 << 22))<br>
<span class="HOEnZb"><font color="#888888">--<br>
2.9.0<br>
<br>
</font></span></blockquote></div><br></div></div></div></div></div></div></div></div>