<p dir="ltr">You're dropping depth_irb->mt_layer. Is that right? What if there's a texture view, or some other mechanism to attach a layer subrange?</p>
<div class="gmail_quote">On May 11, 2016 2:31 AM, "Kenneth Graunke" <<a href="mailto:kenneth@whitecape.org">kenneth@whitecape.org</a>> wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">From: Chia-I Wu <<a href="mailto:olvaffe@gmail.com">olvaffe@gmail.com</a>><br>
<br>
When the depth buffer is already cleared, skip GEN6_HIZ_OP_DEPTH_CLEAR.<br>
This is made possible by tracking which slices have been cleared in<br>
"struct intel_mipmap_level".  The hiz_cleared flag is unset when the<br>
depth buffer is rendered to or when a HiZ resolve is needed.<br>
<br>
Improves performance in Manhattan on Skylake GT3e at 1280x720 by<br>
0.621245% +/- 0.103831%.<br>
<br>
v2:<br>
- unset hiz_cleared automatically in intel_miptree_slice_set_needs_hiz_resolve<br>
- set/unset hiz_cleared with intel_renderbuffer_att_set_needs_depth_resolve<br>
v3: (Ken) Rebase forward 8 months.<br>
v4: (Ken) Rebase forward 2 years; benchmark again.<br>
<br>
Signed-off-by: Chia-I Wu <<a href="mailto:olv@lunarg.com">olv@lunarg.com</a>><br>
Reviewed-by: Kenneth Graunke <<a href="mailto:kenneth@whitecape.org">kenneth@whitecape.org</a>><br>
---<br>
 src/mesa/drivers/dri/i965/brw_clear.c         | 55 +++++++++++++++++++--------<br>
 src/mesa/drivers/dri/i965/brw_draw.c          |  2 +-<br>
 src/mesa/drivers/dri/i965/intel_fbo.c         | 18 ++++++++-<br>
 src/mesa/drivers/dri/i965/intel_fbo.h         |  4 +-<br>
 src/mesa/drivers/dri/i965/intel_mipmap_tree.c | 39 +++++++++++++++++++<br>
 src/mesa/drivers/dri/i965/intel_mipmap_tree.h | 21 ++++++++++<br>
 6 files changed, 118 insertions(+), 21 deletions(-)<br>
<br>
diff --git a/src/mesa/drivers/dri/i965/brw_clear.c b/src/mesa/drivers/dri/i965/brw_clear.c<br>
index d57b677..5b76263 100644<br>
--- a/src/mesa/drivers/dri/i965/brw_clear.c<br>
+++ b/src/mesa/drivers/dri/i965/brw_clear.c<br>
@@ -166,34 +166,57 @@ brw_fast_clear_depth(struct gl_context *ctx)<br>
       break;<br>
    }<br>
<br>
+   unsigned num_layers_cleared = 0;<br>
+   bool clear_all_layers = false;<br>
+<br>
    /* If we're clearing to a new clear value, then we need to resolve any clear<br>
     * flags out of the HiZ buffer into the real depth buffer.<br>
     */<br>
    if (mt->depth_clear_value != depth_clear_value) {<br>
       intel_miptree_all_slices_resolve_depth(brw, mt);<br>
       mt->depth_clear_value = depth_clear_value;<br>
-   }<br>
<br>
-   /* From the Sandy Bridge PRM, volume 2 part 1, page 313:<br>
-    *<br>
-    *     "If other rendering operations have preceded this clear, a<br>
-    *      PIPE_CONTROL with write cache flush enabled and Z-inhibit disabled<br>
-    *      must be issued before the rectangle primitive used for the depth<br>
-    *      buffer clear operation.<br>
-    */<br>
-   brw_emit_mi_flush(brw);<br>
+      clear_all_layers = true;<br>
+   }<br>
<br>
    if (fb->MaxNumLayers > 0) {<br>
       for (unsigned layer = 0; layer < depth_irb->layer_count; layer++) {<br>
-         intel_hiz_exec(brw, mt, depth_irb->mt_level,<br>
-                        depth_irb->mt_layer + layer,<br>
-                        GEN6_HIZ_OP_DEPTH_CLEAR);<br>
+         if (clear_all_layers ||<br>
+             !intel_miptree_slice_get_hiz_cleared(mt,<br>
+                                                  depth_irb->mt_level,<br>
+                                                  layer)) {<br>
+            /* From the Sandy Bridge PRM, volume 2 part 1, page 313:<br>
+             *<br>
+             *     "If other rendering operations have preceded this clear, a<br>
+             *      PIPE_CONTROL with write cache flush enabled and Z-inhibit<br>
+             *      disabled must be issued before the rectangle primitive used<br>
+             *      for the depth buffer clear operation.<br>
+             */<br>
+            if (num_layers_cleared == 0)<br>
+               brw_emit_mi_flush(brw);<br>
+<br>
+            intel_hiz_exec(brw, mt, depth_irb->mt_level, layer,<br>
+                           GEN6_HIZ_OP_DEPTH_CLEAR);<br>
+<br>
+            num_layers_cleared++;<br>
+         }<br>
       }<br>
    } else {<br>
-      intel_hiz_exec(brw, mt, depth_irb->mt_level, depth_irb->mt_layer,<br>
-                     GEN6_HIZ_OP_DEPTH_CLEAR);<br>
+      if (clear_all_layers ||<br>
+          !intel_miptree_slice_get_hiz_cleared(mt,<br>
+                                               depth_irb->mt_level,<br>
+                                               depth_irb->mt_layer)) {<br>
+         brw_emit_mi_flush(brw);<br>
+         intel_hiz_exec(brw, mt, depth_irb->mt_level, depth_irb->mt_layer,<br>
+                        GEN6_HIZ_OP_DEPTH_CLEAR);<br>
+<br>
+         num_layers_cleared = 1;<br>
+      }<br>
    }<br>
<br>
+   if (num_layers_cleared == 0)<br>
+      return true;<br>
+<br>
    if (brw->gen == 6) {<br>
       /* From the Sandy Bridge PRM, volume 2 part 1, page 314:<br>
        *<br>
@@ -205,9 +228,9 @@ brw_fast_clear_depth(struct gl_context *ctx)<br>
    }<br>
<br>
    /* Now, the HiZ buffer contains data that needs to be resolved to the depth<br>
-    * buffer.<br>
+    * buffer.  And set its cleared state to avoid unnecessary clears.<br>
     */<br>
-   intel_renderbuffer_att_set_needs_depth_resolve(depth_att);<br>
+   intel_renderbuffer_att_set_needs_depth_resolve(depth_att, true);<br>
<br>
    return true;<br>
 }<br>
diff --git a/src/mesa/drivers/dri/i965/brw_draw.c b/src/mesa/drivers/dri/i965/brw_draw.c<br>
index 9d034cf..2f77251 100644<br>
--- a/src/mesa/drivers/dri/i965/brw_draw.c<br>
+++ b/src/mesa/drivers/dri/i965/brw_draw.c<br>
@@ -373,7 +373,7 @@ brw_postdraw_set_buffers_need_resolve(struct brw_context *brw)<br>
    if (back_irb)<br>
       back_irb->need_downsample = true;<br>
    if (depth_irb && ctx->Depth.Mask) {<br>
-      intel_renderbuffer_att_set_needs_depth_resolve(depth_att);<br>
+      intel_renderbuffer_att_set_needs_depth_resolve(depth_att, false);<br>
       brw_render_cache_set_add_bo(brw, depth_irb->mt->bo);<br>
    }<br>
<br>
diff --git a/src/mesa/drivers/dri/i965/intel_fbo.c b/src/mesa/drivers/dri/i965/intel_fbo.c<br>
index 7eb21ac..7588a1b 100644<br>
--- a/src/mesa/drivers/dri/i965/intel_fbo.c<br>
+++ b/src/mesa/drivers/dri/i965/intel_fbo.c<br>
@@ -969,17 +969,31 @@ intel_renderbuffer_resolve_hiz(struct brw_context *brw,<br>
    return false;<br>
 }<br>
<br>
+/**<br>
+ * Set that the depth buffer needs to be resolved.  This should be called when<br>
+ * the renderbuffer is rendered or cleared, and we want to distinguish them so<br>
+ * that we know if the HiZ is in a "cleared" state.<br>
+ */<br>
 void<br>
-intel_renderbuffer_att_set_needs_depth_resolve(struct gl_renderbuffer_attachment *att)<br>
+intel_renderbuffer_att_set_needs_depth_resolve(struct gl_renderbuffer_attachment *att,<br>
+                                               bool cleared)<br>
 {<br>
    struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer);<br>
    if (irb->mt) {<br>
       if (att->Layered) {<br>
-         intel_miptree_set_all_slices_need_depth_resolve(irb->mt, irb->mt_level);<br>
+         intel_miptree_set_all_slices_need_depth_resolve(irb->mt,<br>
+                                                         irb->mt_level);<br>
+         intel_miptree_set_all_slices_hiz_cleared(irb->mt,<br>
+                                                  irb->mt_level,<br>
+                                                  cleared);<br>
       } else {<br>
          intel_miptree_slice_set_needs_depth_resolve(irb->mt,<br>
                                                      irb->mt_level,<br>
                                                      irb->mt_layer);<br>
+         intel_miptree_slice_set_hiz_cleared(irb->mt,<br>
+                                             irb->mt_level,<br>
+                                             irb->mt_layer,<br>
+                                             cleared);<br>
       }<br>
    }<br>
 }<br>
diff --git a/src/mesa/drivers/dri/i965/intel_fbo.h b/src/mesa/drivers/dri/i965/intel_fbo.h<br>
index 89894cd..bab6924 100644<br>
--- a/src/mesa/drivers/dri/i965/intel_fbo.h<br>
+++ b/src/mesa/drivers/dri/i965/intel_fbo.h<br>
@@ -198,8 +198,8 @@ bool<br>
 intel_renderbuffer_has_hiz(struct intel_renderbuffer *irb);<br>
<br>
 void<br>
-intel_renderbuffer_att_set_needs_depth_resolve(struct gl_renderbuffer_attachment *att);<br>
-<br>
+intel_renderbuffer_att_set_needs_depth_resolve(struct gl_renderbuffer_attachment *att,<br>
+                                               bool cleared);<br>
<br>
 /**<br>
  * \brief Perform a HiZ resolve on the renderbuffer.<br>
diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c<br>
index 94f6333..e612ef9 100644<br>
--- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c<br>
+++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c<br>
@@ -1933,6 +1933,42 @@ intel_miptree_level_has_hiz(struct intel_mipmap_tree *mt, uint32_t level)<br>
 }<br>
<br>
 void<br>
+intel_miptree_slice_set_hiz_cleared(struct intel_mipmap_tree *mt,<br>
+                                    uint32_t level,<br>
+                                    uint32_t layer,<br>
+                                    bool cleared)<br>
+{<br>
+   if (!intel_miptree_level_has_hiz(mt, level))<br>
+      return;<br>
+<br>
+   mt->level[level].slice[layer].hiz_cleared = cleared;<br>
+}<br>
+<br>
+void<br>
+intel_miptree_set_all_slices_hiz_cleared(struct intel_mipmap_tree *mt,<br>
+                                         uint32_t level,<br>
+                                         bool cleared)<br>
+{<br>
+   uint32_t layer;<br>
+   uint32_t end_layer = mt->level[level].depth;<br>
+<br>
+   for (layer = 0; layer < end_layer; layer++) {<br>
+      intel_miptree_slice_set_hiz_cleared(mt, level, layer, cleared);<br>
+   }<br>
+}<br>
+<br>
+bool<br>
+intel_miptree_slice_get_hiz_cleared(struct intel_mipmap_tree *mt,<br>
+                                    uint32_t level,<br>
+                                    uint32_t layer)<br>
+{<br>
+   if (!intel_miptree_level_has_hiz(mt, level))<br>
+      return false;<br>
+<br>
+   return mt->level[level].slice[layer].hiz_cleared;<br>
+}<br>
+<br>
+void<br>
 intel_miptree_slice_set_needs_hiz_resolve(struct intel_mipmap_tree *mt,<br>
                                          uint32_t level,<br>
                                          uint32_t layer)<br>
@@ -1942,6 +1978,9 @@ intel_miptree_slice_set_needs_hiz_resolve(struct intel_mipmap_tree *mt,<br>
<br>
    intel_resolve_map_set(&mt->hiz_map,<br>
                         level, layer, GEN6_HIZ_OP_HIZ_RESOLVE);<br>
+<br>
+   /* HiZ should no longer be considered cleared when it needs a resolve */<br>
+   intel_miptree_slice_set_hiz_cleared(mt, level, layer, false);<br>
 }<br>
<br>
<br>
diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.h b/src/mesa/drivers/dri/i965/intel_mipmap_tree.h<br>
index 7862152..261dcf3 100644<br>
--- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.h<br>
+++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.h<br>
@@ -155,6 +155,11 @@ struct intel_mipmap_level<br>
        * intel_miptree_map/unmap on this slice.<br>
        */<br>
       struct intel_miptree_map *map;<br>
+<br>
+      /**<br>
+       * Is HiZ cleared for this slice?<br>
+       */<br>
+      bool hiz_cleared;<br>
    } *slice;<br>
 };<br>
<br>
@@ -835,6 +840,22 @@ bool<br>
 intel_miptree_level_has_hiz(struct intel_mipmap_tree *mt, uint32_t level);<br>
<br>
 void<br>
+intel_miptree_slice_set_hiz_cleared(struct intel_mipmap_tree *mt,<br>
+                                    uint32_t level,<br>
+                                    uint32_t layer,<br>
+                                    bool cleared);<br>
+<br>
+void<br>
+intel_miptree_set_all_slices_hiz_cleared(struct intel_mipmap_tree *mt,<br>
+                                         uint32_t level,<br>
+                                         bool cleared);<br>
+<br>
+bool<br>
+intel_miptree_slice_get_hiz_cleared(struct intel_mipmap_tree *mt,<br>
+                                    uint32_t level,<br>
+                                    uint32_t layer);<br>
+<br>
+void<br>
 intel_miptree_slice_set_needs_hiz_resolve(struct intel_mipmap_tree *mt,<br>
                                           uint32_t level,<br>
                                          uint32_t depth);<br>
--<br>
2.8.2<br>
<br>
_______________________________________________<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/mailman/listinfo/mesa-dev</a><br>
</blockquote></div>