<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Wed, Jun 28, 2017 at 2:14 PM, Nanley Chery <span dir="ltr"><<a href="mailto:nanleychery@gmail.com" target="_blank">nanleychery@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">v2: Expound on comment for the pipe controls (Jason Ekstrand).<br>
<br>
Signed-off-by: Nanley Chery <<a href="mailto:nanley.g.chery@intel.com">nanley.g.chery@intel.com</a>><br>
---<br>
 src/intel/vulkan/anv_blorp.c       |   4 +-<br>
 src/intel/vulkan/genX_cmd_<wbr>buffer.c | 183 ++++++++++++++++++++++++++++++<wbr>+++----<br>
 2 files changed, 167 insertions(+), 20 deletions(-)<br>
<br>
diff --git a/src/intel/vulkan/anv_blorp.c b/src/intel/vulkan/anv_blorp.c<br>
index 459d57ec57..84b01e8792 100644<br>
--- a/src/intel/vulkan/anv_blorp.c<br>
+++ b/src/intel/vulkan/anv_blorp.c<br>
@@ -1451,7 +1451,9 @@ anv_image_ccs_clear(struct anv_cmd_buffer *cmd_buffer,<br>
<br>
    struct blorp_surf surf;<br>
    get_blorp_surf_for_anv_image(<wbr>image, VK_IMAGE_ASPECT_COLOR_BIT,<br>
-                                image->aux_usage, &surf);<br>
+                                image->aux_usage == ISL_AUX_USAGE_CCS_E ?<br>
+                                ISL_AUX_USAGE_CCS_E : ISL_AUX_USAGE_CCS_D,<br>
+                                &surf);<br>
<br>
    /* From the Sky Lake PRM Vol. 7, "Render Target Fast Clear":<br>
     *<br>
diff --git a/src/intel/vulkan/genX_cmd_<wbr>buffer.c b/src/intel/vulkan/genX_cmd_<wbr>buffer.c<br>
index decf0b28d6..1a9b841c7c 100644<br>
--- a/src/intel/vulkan/genX_cmd_<wbr>buffer.c<br>
+++ b/src/intel/vulkan/genX_cmd_<wbr>buffer.c<br>
@@ -524,6 +524,17 @@ genX(copy_fast_clear_dwords)(<wbr>struct anv_cmd_buffer *cmd_buffer,<br>
    }<br>
 }<br>
<br>
+/**<br>
+ * @brief Transitions a color buffer from one layout to another.<br>
+ *<br>
+ * See section 6.1.1. Image Layout Transitions of the Vulkan 1.0.50 spec for<br>
+ * more information.<br>
+ *<br>
+ * @param level_count VK_REMAINING_MIP_LEVELS isn't supported.<br>
+ * @param layer_count VK_REMAINING_ARRAY_LAYERS isn't supported. For 3D images,<br>
+ *                    this represents the maximum layers to transition at each<br>
+ *                    specified miplevel.<br>
+ */<br>
 static void<br>
 transition_color_buffer(struct anv_cmd_buffer *cmd_buffer,<br>
                         const struct anv_image *image,<br>
@@ -532,13 +543,27 @@ transition_color_buffer(struct anv_cmd_buffer *cmd_buffer,<br>
                         VkImageLayout initial_layout,<br>
                         VkImageLayout final_layout)<br>
 {<br>
-   assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);<br>
-<br>
-   if (image->aux_surface.isl.size == 0)<br>
-      return;<br>
-<br>
-   if (initial_layout != VK_IMAGE_LAYOUT_UNDEFINED &&<br>
-       initial_layout != VK_IMAGE_LAYOUT_<wbr>PREINITIALIZED)<br>
+   /* Validate the inputs. */<br>
+   assert(cmd_buffer);<br>
+   assert(image && image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);<br>
+   /* These values aren't supported for simplicity's sake. */<br>
+   assert(level_count != VK_REMAINING_MIP_LEVELS &&<br>
+          layer_count != VK_REMAINING_ARRAY_LAYERS);<br>
+   /* Ensure the subresource range is valid. */<br>
+   uint64_t last_level_num = base_level + level_count;<br>
+   const uint32_t max_depth = anv_minify(image->extent.<wbr>depth, base_level);<br>
+   const uint32_t image_layers = MAX2(image->array_size, max_depth);<br>
+   assert(base_layer + layer_count  <= image_layers);<br>
+   assert(last_level_num <= image->levels);<br>
+   /* The spec disallows these final layouts. */<br>
+   assert(final_layout != VK_IMAGE_LAYOUT_UNDEFINED &&<br>
+          final_layout != VK_IMAGE_LAYOUT_<wbr>PREINITIALIZED);<br>
+<br>
+   /* No work is necessary if the layout stays the same or if this subresource<br>
+    * range lacks auxiliary data.<br>
+    */<br>
+   if (initial_layout == final_layout ||<br>
+       base_layer >= anv_image_aux_layers(image, base_level))<br>
       return;<br>
<br>
    /* A transition of a 3D subresource works on all slices at a time. */<br>
@@ -549,22 +574,142 @@ transition_color_buffer(struct anv_cmd_buffer *cmd_buffer,<br>
<br>
    /* We're interested in the subresource range subset that has aux data. */<br>
    level_count = MIN2(level_count, anv_image_aux_levels(image));<br>
+   layer_count = MIN2(layer_count, anv_image_aux_layers(image, base_level));<br></blockquote><div><br></div><div>Is this correct?  I think we want MIN2(layer_count, anv_image_aux_layers() - base_layer), don't we?  This would also mean there's a bug in the current level_count.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+   last_level_num = base_level + level_count;<br>
+<br>
+   /* Record whether or not the layout is undefined. Pre-initialized images<br>
+    * with auxiliary buffers have a non-linear layout and are thus undefined.<br>
+    */<br>
+   assert(image->tiling == VK_IMAGE_TILING_OPTIMAL);<br>
+   const bool undef_layout = initial_layout == VK_IMAGE_LAYOUT_UNDEFINED ||<br>
+                             initial_layout == VK_IMAGE_LAYOUT_<wbr>PREINITIALIZED;<br>
<br>
-   /* We're transitioning from an undefined layout. We must ensure that the<br>
-    * clear values buffer is filled with valid data.<br>
+   /* Do preparatory work before the resolve operation or return early if no<br>
+    * resolve is actually needed.<br>
     */<br>
-   for (unsigned l = 0; l < level_count; l++)<br>
-      init_fast_clear_state_entry(<wbr>cmd_buffer, image, base_level + l);<br>
-<br>
-   if (image->aux_usage == ISL_AUX_USAGE_CCS_E) {<br>
-      /* We're transitioning from an undefined layout so it doesn't really<br>
-       * matter what data ends up in the color buffer.  We do, however, need to<br>
-       * ensure that the CCS has valid data in it.  One easy way to do that is<br>
-       * to fast-clear the specified range.<br>
+   if (undef_layout) {<br>
+      /* A subresource in the undefined layout may have been aliased and<br>
+       * populated with any arrangement of bits. Therefore, we must initialize<br>
+       * the related aux buffer and clear buffer entry with desirable values.<br>
+       *<br>
+       * Initialize the relevant clear buffer entries.<br>
        */<br>
-      anv_image_ccs_clear(cmd_<wbr>buffer, image, base_level, level_count,<br>
-                          base_layer, layer_count);<br>
+      for (unsigned level = base_level; level < last_level_num; level++)<br>
+         init_fast_clear_state_entry(<wbr>cmd_buffer, image, level);<br>
+<br>
+      /* MCS buffers have been initialized for correct behaviour. */<br></blockquote><div><br></div><div>I don't think this is correct.  I can definitely see MCS going off the rails in a similar way to CCS if things aren't initialized correctly.  Unfortunately, MSAA test coverage is defintiely sub-par right now.  I think I'd feel more comfortable if we fast-cleared them too.  Fortunately, though, we always leave basic MCS on for MSAA surfaces so no resolve will ever be needed.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+      if (image->samples > 1)<br>
+         return;<br>
+<br>
+      /* Initialize the CCS buffers to enable correct rendering. This operation<br>
+       * requires up to two steps: one to rid the CCS buffer of data that may<br>
+       * cause GPU hangs, and another to ensure that writes done without CCS<br>
+       * will be visible to reads done with CCS.<br>
+       *<br>
+       * On SKL+, it becomes possible to have a CCS buffer with invalid data.<br>
+       * One easy way to avoid this state is to fast-clear the specified range.<br>
+       */<br>
+      if (GEN_GEN >= 9) {<br>
+         anv_image_ccs_clear(cmd_<wbr>buffer, image, base_level, level_count,<br>
+                             base_layer, layer_count);<br>
+      }<br>
+      /* At this point, some elements of the CCS buffer may have the fast-clear<br>
+       * bit-arrangement. As the user writes to a subresource, we need to have<br>
+       * the associated CCS elements enter the ambiguated state. This enables<br>
+       * reads (implicit or explicit) to reflect the user-written data instead<br>
+       * of the clear color. The only time such elements will not change their<br>
+       * state as described above, is in a final layout that doesn't have CCS<br>
+       * enabled. In this case, we must force the associated CCS buffers of the<br>
+       * specified range to enter the ambiguated state in advance.<br>
+       */<br>
+      if (image->aux_usage != ISL_AUX_USAGE_CCS_E &&<br>
+          final_layout != VK_IMAGE_LAYOUT_COLOR_<wbr>ATTACHMENT_OPTIMAL) {<br>
+         /* The CCS_D buffer may not be enabled in the final layout. Continue<br>
+          * executing this function to perform a resolve.<br>
+          */<br>
+          anv_perf_warn("Performing an additional resolve for CCS_D layout "<br>
+                        "transition. Consider always leaving it on or "<br>
+                        "performing an ambiguation pass.");<br>
+      } else {<br>
+         /* Writes in the final layout will be aware of the CCS buffer. In<br>
+          * addition, the clear buffer entries and the CCS buffers have been<br>
+          * populated with values that will result in correct rendering.<br>
+          */<br>
+         return;<br></blockquote><div><br></div><div>Ugh... This all works but it makes me an even bigger fan of that ambiguate pass... Maybe we should consider reviving it once this all lands.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+      }<br>
+   } else if (initial_layout != VK_IMAGE_LAYOUT_COLOR_<wbr>ATTACHMENT_OPTIMAL) {<br>
+      /* Resolves are only necessary if the subresource may contain blocks<br>
+       * fast-cleared to values unsupported in other layouts. This only occurs<br>
+       * if the initial layout is COLOR_ATTACHMENT_OPTIMAL.<br>
+       */<br>
+      return;<br>
+   } else if (image->samples > 1) {<br>
+      /* MCS buffers don't need resolving. */<br>
+      return;<br>
    }<br>
+<br>
+   /* Perform a resolve to synchronize data between the main and aux buffer.<br>
+    * Before we begin, we must satisfy the cache flushing requirement specified<br>
+    * in the Sky Lake PRM Vol. 7, "MCS Buffer for Render Target(s)":<br>
+    *<br>
+    *    Any transition from any value in {Clear, Render, Resolve} to a<br>
+    *    different value in {Clear, Render, Resolve} requires end of pipe<br>
+    *    synchronization.<br>
+    *<br>
+    * We perform a flush of the write cache before and after the clear and<br>
+    * resolve operations to meet this requirement.<br>
+    *<br>
+    * Unlike other drawing, it seems that fast clear operations are not<br>
+    * properly synchronized. The first PIPE_CONTROL here likely ensures that<br>
+    * the contents of the previous render or clear hit the render target before<br>
+    * we resolve and the second likely ensures that the resolve is complete<br>
+    * before we do any more rendering or clearing.<br></blockquote><div><br></div><div>I'm really not a fan of how much this has been weasel-worded...<br><br></div><div><rant><br></div><div>One of the big problems with the PRMs is that they don't actually describe the hardware.  They describe how a theoretical driver can/should program the hardware to get correct rendering results.  What they don't tell you is *why* programming the hardware that way is needed.  They get especially bad about this around synchronization and image layout.  They're also frequently missing important details and are sometimes flat-out wrong.<br><br></div><div>The statement "fast clear ops are not properly synchronized with other drawing" describes, in some sense, what's going on in the hardware.  You have two rendering operations in-flight and, due to some hardware detail I don't fully understand, they can't safely be in the pipeline at the same time.  It's not a full description I'll grant, but it at least describes, in general terms, the problem the workaround is solving.  The language in the PRM, on the other hand, describes some engineer's mental model of that synchronization problem and a way of working around it.<br><br>We write drivers for hardware, not for PRMs.  I don't think we need to weasel-word our comments to make it look like all we have is hair-brained theories while whoever wrote the PRM note has the actual knowledge.  If we're particularly unsure about something then that should be expressed in the comment.  However, I'm pretty convinced that what's going on here is a synchronization problem.  Our understanding of fast-clear operations may improve in the future and, if/when it does, we'll update the comments.<br></div><div></rant><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+    */<br>
+   cmd_buffer->state.pending_<wbr>pipe_bits |=<br>
+      ANV_PIPE_RENDER_TARGET_CACHE_<wbr>FLUSH_BIT | ANV_PIPE_CS_STALL_BIT;<br>
+<br>
+   for (uint32_t level = base_level; level < last_level_num; level++) {<br>
+<br>
+      /* The number of layers changes at each 3D miplevel. */<br>
+      if (image->type == VK_IMAGE_TYPE_3D) {<br>
+         layer_count = MIN2(layer_count, anv_image_aux_layers(image, level));<br>
+      }<br>
+<br>
+      /* Create a surface state with the right clear color and perform the<br>
+       * resolve.<br>
+       */<br>
+      struct anv_state surface_state =<br>
+         anv_cmd_buffer_alloc_surface_<wbr>state(cmd_buffer);<br>
+      isl_surf_fill_state(&cmd_<wbr>buffer->device->isl_dev, surface_state.map,<br>
+                          .surf = &image->color_surface.isl,<br>
+                          .view = &(struct isl_view) {<br>
+                              .usage = ISL_SURF_USAGE_RENDER_TARGET_<wbr>BIT,<br>
+                              .format = image->color_surface.isl.<wbr>format,<br>
+                              .swizzle = ISL_SWIZZLE_IDENTITY,<br>
+                              .base_level = level,<br>
+                              .levels = 1,<br>
+                              .base_array_layer = base_layer,<br>
+                              .array_len = layer_count,<br>
+                           },<br>
+                          .aux_surf = &image->aux_surface.isl,<br>
+                          .aux_usage = image->aux_usage == ISL_AUX_USAGE_NONE ?<br>
+                                       ISL_AUX_USAGE_CCS_D : image->aux_usage,<br>
+                          .mocs = cmd_buffer->device->default_<wbr>mocs);<br>
+      add_image_relocs(cmd_buffer, image, VK_IMAGE_ASPECT_COLOR_BIT,<br>
+                       image->aux_usage == ISL_AUX_USAGE_CCS_E ?<br>
+                       ISL_AUX_USAGE_CCS_E : ISL_AUX_USAGE_CCS_D,<br>
+                       surface_state);<br>
+      anv_state_flush(cmd_buffer-><wbr>device, surface_state);<br>
+      genX(copy_fast_clear_dwords)(<wbr>cmd_buffer, surface_state, image, level,<br>
+                                   false /* copy to ss */);<br>
+      anv_ccs_resolve(cmd_buffer, surface_state, image, level, layer_count,<br>
+                      image->aux_usage == ISL_AUX_USAGE_CCS_E ?<br>
+                      BLORP_FAST_CLEAR_OP_RESOLVE_<wbr>PARTIAL :<br>
+                      BLORP_FAST_CLEAR_OP_RESOLVE_<wbr>FULL);<br>
+   }<br>
+<br>
+   cmd_buffer->state.pending_<wbr>pipe_bits |=<br>
+      ANV_PIPE_RENDER_TARGET_CACHE_<wbr>FLUSH_BIT | ANV_PIPE_CS_STALL_BIT;<br>
 }<br>
<br>
 /**<br>
<span class="gmail-HOEnZb"><font color="#888888">--<br>
2.13.1<br>
<br>
______________________________<wbr>_________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
<a href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev" rel="noreferrer" target="_blank">https://lists.freedesktop.org/<wbr>mailman/listinfo/mesa-dev</a><br>
</font></span></blockquote></div><br></div></div>