[Mesa-dev] [PATCH] i965: Avoid extraneous fast depth clears
Chia-I Wu
olvaffe at gmail.com
Tue Dec 10 21:54:45 PST 2013
When the depth buffer is already cleared, skip GEN6_HIZ_OP_DEPTH_CLEAR. This
is made possible by tracking which slices have been cleared in
"struct intel_mipmap_level". The hiz_cleared flag is unset when the depth
buffer is rendered to or when a HiZ resolve is needed.
For Unigine Tropics, the FPS improvement is 1.32134% +/- 0.161878% (n=13).
---
src/mesa/drivers/dri/i965/brw_blorp_blit.cpp | 1 +
src/mesa/drivers/dri/i965/brw_clear.c | 58 +++++++++++++++++++++------
src/mesa/drivers/dri/i965/brw_draw.c | 16 +++++++-
src/mesa/drivers/dri/i965/intel_mipmap_tree.c | 37 +++++++++++++++++
src/mesa/drivers/dri/i965/intel_mipmap_tree.h | 21 ++++++++++
5 files changed, 119 insertions(+), 14 deletions(-)
diff --git a/src/mesa/drivers/dri/i965/brw_blorp_blit.cpp b/src/mesa/drivers/dri/i965/brw_blorp_blit.cpp
index 51a3bef..d9ec3e9 100644
--- a/src/mesa/drivers/dri/i965/brw_blorp_blit.cpp
+++ b/src/mesa/drivers/dri/i965/brw_blorp_blit.cpp
@@ -173,6 +173,7 @@ brw_blorp_blit_miptrees(struct brw_context *brw,
brw_blorp_exec(brw, ¶ms);
intel_miptree_slice_set_needs_hiz_resolve(dst_mt, dst_level, dst_layer);
+ intel_miptree_slice_set_hiz_cleared(dst_mt, dst_level, dst_layer, false);
}
static void
diff --git a/src/mesa/drivers/dri/i965/brw_clear.c b/src/mesa/drivers/dri/i965/brw_clear.c
index 1cac996..9dfb94a 100644
--- a/src/mesa/drivers/dri/i965/brw_clear.c
+++ b/src/mesa/drivers/dri/i965/brw_clear.c
@@ -164,34 +164,66 @@ brw_fast_clear_depth(struct gl_context *ctx)
break;
}
+ unsigned num_layers_cleared = 0;
+ bool clear_all_layers = false;
+
/* If we're clearing to a new clear value, then we need to resolve any clear
* flags out of the HiZ buffer into the real depth buffer.
*/
if (mt->depth_clear_value != depth_clear_value) {
intel_miptree_all_slices_resolve_depth(brw, mt);
mt->depth_clear_value = depth_clear_value;
- }
- /* From the Sandy Bridge PRM, volume 2 part 1, page 313:
- *
- * "If other rendering operations have preceded this clear, a
- * PIPE_CONTROL with write cache flush enabled and Z-inhibit disabled
- * must be issued before the rectangle primitive used for the depth
- * buffer clear operation.
- */
- intel_batchbuffer_emit_mi_flush(brw);
+ clear_all_layers = true;
+ }
if (fb->NumLayers > 0) {
assert(fb->NumLayers == depth_irb->mt->level[depth_irb->mt_level].depth);
for (unsigned layer = 0; layer < fb->NumLayers; layer++) {
- intel_hiz_exec(brw, mt, depth_irb->mt_level, layer,
- GEN6_HIZ_OP_DEPTH_CLEAR);
+ if (clear_all_layers ||
+ !intel_miptree_slice_get_hiz_cleared(mt,
+ depth_irb->mt_level,
+ layer)) {
+ /* From the Sandy Bridge PRM, volume 2 part 1, page 313:
+ *
+ * "If other rendering operations have preceded this clear, a
+ * PIPE_CONTROL with write cache flush enabled and Z-inhibit
+ * disabled must be issued before the rectangle primitive used
+ * for the depth buffer clear operation.
+ */
+ if (!num_layers_cleared)
+ intel_batchbuffer_emit_mi_flush(brw);
+
+ intel_hiz_exec(brw, mt, depth_irb->mt_level, layer,
+ GEN6_HIZ_OP_DEPTH_CLEAR);
+
+ intel_miptree_slice_set_hiz_cleared(mt,
+ depth_irb->mt_level,
+ layer,
+ true);
+ num_layers_cleared++;
+ }
}
} else {
- intel_hiz_exec(brw, mt, depth_irb->mt_level, depth_irb->mt_layer,
- GEN6_HIZ_OP_DEPTH_CLEAR);
+ if (clear_all_layers ||
+ !intel_miptree_slice_get_hiz_cleared(mt,
+ depth_irb->mt_level,
+ depth_irb->mt_layer)) {
+ intel_batchbuffer_emit_mi_flush(brw);
+ intel_hiz_exec(brw, mt, depth_irb->mt_level, depth_irb->mt_layer,
+ GEN6_HIZ_OP_DEPTH_CLEAR);
+
+ intel_miptree_slice_set_hiz_cleared(mt,
+ depth_irb->mt_level,
+ depth_irb->mt_layer,
+ true);
+ num_layers_cleared = 1;
+ }
}
+ if (!num_layers_cleared)
+ return true;
+
if (brw->gen == 6) {
/* From the Sandy Bridge PRM, volume 2 part 1, page 314:
*
diff --git a/src/mesa/drivers/dri/i965/brw_draw.c b/src/mesa/drivers/dri/i965/brw_draw.c
index b898cd3..4ebfe44 100644
--- a/src/mesa/drivers/dri/i965/brw_draw.c
+++ b/src/mesa/drivers/dri/i965/brw_draw.c
@@ -363,8 +363,22 @@ static void brw_postdraw_set_buffers_need_resolve(struct brw_context *brw)
intel_renderbuffer_set_needs_downsample(front_irb);
if (back_irb)
intel_renderbuffer_set_needs_downsample(back_irb);
- if (depth_irb && ctx->Depth.Mask)
+ if (depth_irb && ctx->Depth.Mask) {
intel_renderbuffer_att_set_needs_depth_resolve(depth_att);
+
+ if (depth_irb->mt) {
+ if (depth_att->Layered) {
+ intel_miptree_set_all_slices_hiz_cleared(depth_irb->mt,
+ depth_irb->mt_level,
+ false);
+ } else {
+ intel_miptree_slice_set_hiz_cleared(depth_irb->mt,
+ depth_irb->mt_level,
+ depth_irb->mt_layer,
+ false);
+ }
+ }
+ }
}
/* May fail if out of video memory for texture or vbo upload, or on
diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
index a96c7ea..f41c2b1 100644
--- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
+++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.c
@@ -1393,6 +1393,42 @@ intel_miptree_slice_has_hiz(struct intel_mipmap_tree *mt,
}
void
+intel_miptree_slice_set_hiz_cleared(struct intel_mipmap_tree *mt,
+ uint32_t level,
+ uint32_t layer,
+ bool cleared)
+{
+ if (!intel_miptree_slice_has_hiz(mt, level, layer))
+ return;
+
+ mt->level[level].slice[layer].hiz_cleared = cleared;
+}
+
+void
+intel_miptree_set_all_slices_hiz_cleared(struct intel_mipmap_tree *mt,
+ uint32_t level,
+ bool cleared)
+{
+ uint32_t layer;
+ uint32_t end_layer = mt->level[level].depth;
+
+ for (layer = 0; layer < end_layer; layer++) {
+ intel_miptree_slice_set_hiz_cleared(mt, level, layer, cleared);
+ }
+}
+
+bool
+intel_miptree_slice_get_hiz_cleared(struct intel_mipmap_tree *mt,
+ uint32_t level,
+ uint32_t layer)
+{
+ if (!intel_miptree_slice_has_hiz(mt, level, layer))
+ return false;
+
+ return mt->level[level].slice[layer].hiz_cleared;
+}
+
+void
intel_miptree_slice_set_needs_hiz_resolve(struct intel_mipmap_tree *mt,
uint32_t level,
uint32_t layer)
@@ -2256,6 +2292,7 @@ intel_miptree_map_singlesample(struct brw_context *brw,
intel_miptree_slice_resolve_depth(brw, mt, level, slice);
if (map->mode & GL_MAP_WRITE_BIT) {
intel_miptree_slice_set_needs_hiz_resolve(mt, level, slice);
+ intel_miptree_slice_set_hiz_cleared(mt, level, slice, false);
}
if (mt->format == MESA_FORMAT_S8) {
diff --git a/src/mesa/drivers/dri/i965/intel_mipmap_tree.h b/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
index cde702c..366e130 100644
--- a/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
+++ b/src/mesa/drivers/dri/i965/intel_mipmap_tree.h
@@ -162,6 +162,11 @@ struct intel_mipmap_level
* resides at \c mt->hiz_mt->level[l].slice[s].
*/
bool has_hiz;
+
+ /**
+ * Is HiZ cleared for this slice?
+ */
+ bool hiz_cleared;
} *slice;
};
@@ -628,6 +633,22 @@ intel_miptree_slice_has_hiz(struct intel_mipmap_tree *mt,
uint32_t layer);
void
+intel_miptree_slice_set_hiz_cleared(struct intel_mipmap_tree *mt,
+ uint32_t level,
+ uint32_t layer,
+ bool cleared);
+
+void
+intel_miptree_set_all_slices_hiz_cleared(struct intel_mipmap_tree *mt,
+ uint32_t level,
+ bool cleared);
+
+bool
+intel_miptree_slice_get_hiz_cleared(struct intel_mipmap_tree *mt,
+ uint32_t level,
+ uint32_t layer);
+
+void
intel_miptree_slice_set_needs_hiz_resolve(struct intel_mipmap_tree *mt,
uint32_t level,
uint32_t depth);
--
1.8.3.1
More information about the mesa-dev
mailing list