<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Sun, Nov 20, 2016 at 8:21 PM, Jason Ekstrand <span dir="ltr"><<a href="mailto:jason@jlekstrand.net" target="_blank">jason@jlekstrand.net</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">Input and resolve attachments can cause an implicit dependency in the<br>
pipeline.  It's our job to insert the needed flushes.  Fortunately, we can<br>
easily reuse the usage tracking that we use for CCS resolves.<br>
<br>
</span>This fixes 120 Vulkan CTS tests on Haswell<br></blockquote><div><br></div><div>Correction:  159<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
---<br>
 src/intel/vulkan/anv_blorp.c | 88 ++++++++++++++++++++++++++++++<wbr>++++++++++++++<br>
 1 file changed, 88 insertions(+)<br>
<br>
diff --git a/src/intel/vulkan/anv_blorp.c b/src/intel/vulkan/anv_blorp.c<br>
index 90ee5ed..56552ae 100644<br>
--- a/src/intel/vulkan/anv_blorp.c<br>
+++ b/src/intel/vulkan/anv_blorp.c<br>
@@ -1058,6 +1058,88 @@ void anv_CmdClearAttachments(<br>
    blorp_batch_finish(&batch);<br>
 }<br>
<br>
+enum subpass_stage {<br>
+   SUBPASS_STAGE_LOAD,<br>
+   SUBPASS_STAGE_DRAW,<br>
+   SUBPASS_STAGE_RESOLVE,<br>
+};<br>
+<br>
+static bool<br>
+attachment_needs_flush(struct anv_cmd_buffer *cmd_buffer,<br>
+                       struct anv_render_pass_attachment *att,<br>
+                       enum subpass_stage stage)<br>
<span class="">+{<br>
+   struct anv_render_pass *pass = cmd_buffer->state.pass;<br>
+   struct anv_subpass *subpass = cmd_buffer->state.subpass;<br>
+   unsigned subpass_idx = subpass - pass->subpasses;<br>
+   assert(subpass_idx < pass->subpass_count);<br>
+<br>
</span>+   /* We handle this subpass specially based on the current stage */<br>
+   enum anv_subpass_usage usage = att->subpass_usage[subpass_<wbr>idx];<br>
+   switch (stage) {<br>
+   case SUBPASS_STAGE_LOAD:<br>
<span class="">+      if (usage & (ANV_SUBPASS_USAGE_INPUT | ANV_SUBPASS_USAGE_RESOLVE_SRC)<wbr>)<br>
</span>+         return true;<br>
+      break;<br>
+<br>
+   case SUBPASS_STAGE_DRAW:<br>
+      if (usage & ANV_SUBPASS_USAGE_RESOLVE_SRC)<br>
+         return true;<br>
+      break;<br>
+<br>
+   default:<br>
+      break;<br>
+   }<br>
<span class="">+<br>
+   for (uint32_t s = subpass_idx + 1; s < pass->subpass_count; s++) {<br>
</span>+      usage = att->subpass_usage[s];<br>
<span class="">+<br>
+      /* If this attachment is going to be used as an input in this or any<br>
+       * future subpass, then we need to flush its cache and invalidate the<br>
+       * texture cache.<br>
+       */<br>
</span>+      if (att->subpass_usage[s] & ANV_SUBPASS_USAGE_INPUT)<br>
+         return true;<br>
<span class="">+<br>
+      if (usage & (ANV_SUBPASS_USAGE_DRAW | ANV_SUBPASS_USAGE_RESOLVE_DST)<wbr>) {<br>
+         /* We found another subpass that draws to this attachment.  We'll<br>
+          * wait to resolve until then.<br>
+          */<br>
</span>+         return false;<br>
+      }<br>
+   }<br>
+<br>
+   return false;<br>
+}<br>
+<br>
+static void<br>
+anv_cmd_buffer_flush_<wbr>attachments(struct anv_cmd_buffer *cmd_buffer,<br>
+                                 enum subpass_stage stage)<br>
<span class="">+{<br>
+   struct anv_subpass *subpass = cmd_buffer->state.subpass;<br>
+   struct anv_render_pass *pass = cmd_buffer->state.pass;<br>
+<br>
+   for (uint32_t i = 0; i < subpass->color_count; ++i) {<br>
+      uint32_t att = subpass->color_attachments[i];<br>
+      assert(att < pass->attachment_count);<br>
</span>+      if (attachment_needs_flush(cmd_<wbr>buffer, &pass->attachments[att], stage)) {<br>
+         cmd_buffer->state.pending_<wbr>pipe_bits |=<br>
+            ANV_PIPE_TEXTURE_CACHE_<wbr>INVALIDATE_BIT |<br>
+            ANV_PIPE_RENDER_TARGET_CACHE_<wbr>FLUSH_BIT;<br>
+      }<br>
<span class="">+   }<br>
+<br>
+   if (subpass->depth_stencil_<wbr>attachment != VK_ATTACHMENT_UNUSED) {<br>
+      uint32_t att = subpass->depth_stencil_<wbr>attachment;<br>
</span>+      assert(att < pass->attachment_count);<br>
+      if (attachment_needs_flush(cmd_<wbr>buffer, &pass->attachments[att], stage)) {<br>
+         cmd_buffer->state.pending_<wbr>pipe_bits |=<br>
+            ANV_PIPE_TEXTURE_CACHE_<wbr>INVALIDATE_BIT |<br>
+            ANV_PIPE_DEPTH_CACHE_FLUSH_<wbr>BIT;<br>
+      }<br>
<span class="">+   }<br>
+}<br>
+<br>
 static bool<br>
 subpass_needs_clear(const struct anv_cmd_buffer *cmd_buffer)<br>
 {<br>
</span>@@ -1137,6 +1219,8 @@ anv_cmd_buffer_clear_subpass(<wbr>struct anv_cmd_buffer *cmd_buffer)<br>
    }<br>
<br>
    blorp_batch_finish(&batch);<br>
+<br>
+   anv_cmd_buffer_flush_<wbr>attachments(cmd_buffer, SUBPASS_STAGE_LOAD);<br>
 }<br>
<br>
 static void<br>
@@ -1291,6 +1375,8 @@ anv_cmd_buffer_resolve_<wbr>subpass(struct anv_cmd_buffer *cmd_buffer)<br>
                              subpass->color_attachments[i])<wbr>;<br>
    }<br>
<br>
+   anv_cmd_buffer_flush_<wbr>attachments(cmd_buffer, SUBPASS_STAGE_DRAW);<br>
<span class="">+<br>
    if (subpass->has_resolve) {<br>
       for (uint32_t i = 0; i < subpass->color_count; ++i) {<br>
          uint32_t src_att = subpass->color_attachments[i];<br>
</span>@@ -1336,6 +1422,8 @@ anv_cmd_buffer_resolve_<wbr>subpass(struct anv_cmd_buffer *cmd_buffer)<br>
<br>
          ccs_resolve_attachment(cmd_<wbr>buffer, &batch, dst_att);<br>
       }<br>
+<br>
+      anv_cmd_buffer_flush_<wbr>attachments(cmd_buffer, SUBPASS_STAGE_RESOLVE);<br>
    }<br>
<br>
    blorp_batch_finish(&batch);<br>
<span class="HOEnZb"><font color="#888888">--<br>
2.5.0.400.gff86faf<br>
<br>
</font></span></blockquote></div><br></div></div>