summaryrefslogtreecommitdiffstats
path: root/src/gallium
diff options
context:
space:
mode:
authorMarek Olšák <[email protected]>2014-08-23 16:46:53 +0200
committerMarek Olšák <[email protected]>2014-09-01 21:18:52 +0200
commita10c8db715baa8e12f5267ef2fc59dbb7d191f8d (patch)
tree4b38e33d7ab31462a105f7f442a3598c238f75b0 /src/gallium
parentf05fe294e7e8dfb08be172f426252192c0ba17ab (diff)
radeonsi: implement EXPCLEAR optimization for depth
Reviewed-by: Michel Dänzer <[email protected]>
Diffstat (limited to 'src/gallium')
-rw-r--r--src/gallium/drivers/radeon/r600_pipe_common.h1
-rw-r--r--src/gallium/drivers/radeonsi/si_blit.c12
-rw-r--r--src/gallium/drivers/radeonsi/si_pipe.h1
-rw-r--r--src/gallium/drivers/radeonsi/si_state.c3
-rw-r--r--src/gallium/drivers/radeonsi/si_state_draw.c8
5 files changed, 23 insertions, 2 deletions
diff --git a/src/gallium/drivers/radeon/r600_pipe_common.h b/src/gallium/drivers/radeon/r600_pipe_common.h
index cac6faac951..b9a35c76633 100644
--- a/src/gallium/drivers/radeon/r600_pipe_common.h
+++ b/src/gallium/drivers/radeon/r600_pipe_common.h
@@ -191,6 +191,7 @@ struct r600_texture {
/* Depth buffer compression and fast clear. */
struct r600_resource *htile_buffer;
+ bool depth_cleared; /* if it was cleared at least once */
float depth_clear_value;
bool non_disp_tiling; /* R600-Cayman only */
diff --git a/src/gallium/drivers/radeonsi/si_blit.c b/src/gallium/drivers/radeonsi/si_blit.c
index 4e77d74a79f..96d27ec062f 100644
--- a/src/gallium/drivers/radeonsi/si_blit.c
+++ b/src/gallium/drivers/radeonsi/si_blit.c
@@ -362,6 +362,12 @@ static void si_clear(struct pipe_context *ctx, unsigned buffers,
zsbuf->u.tex.level == 0 &&
zsbuf->u.tex.first_layer == 0 &&
zsbuf->u.tex.last_layer == util_max_layer(&zstex->resource.b.b, 0)) {
+ /* Need to disable EXPCLEAR temporarily if clearing
+ * to a new value. */
+ if (zstex->depth_cleared && zstex->depth_clear_value != depth) {
+ sctx->db_depth_disable_expclear = true;
+ }
+
zstex->depth_clear_value = depth;
sctx->framebuffer.atom.dirty = true; /* updates DB_DEPTH_CLEAR */
sctx->db_depth_clear = true;
@@ -373,7 +379,11 @@ static void si_clear(struct pipe_context *ctx, unsigned buffers,
buffers, color, depth, stencil);
si_blitter_end(ctx);
- sctx->db_depth_clear = false;
+ if (sctx->db_depth_clear) {
+ sctx->db_depth_clear = false;
+ sctx->db_depth_disable_expclear = false;
+ zstex->depth_cleared = true;
+ }
}
static void si_clear_render_target(struct pipe_context *ctx,
diff --git a/src/gallium/drivers/radeonsi/si_pipe.h b/src/gallium/drivers/radeonsi/si_pipe.h
index 0a79983a49a..55643d6eb7d 100644
--- a/src/gallium/drivers/radeonsi/si_pipe.h
+++ b/src/gallium/drivers/radeonsi/si_pipe.h
@@ -165,6 +165,7 @@ struct si_context {
unsigned dbcb_copy_sample;
bool db_inplace_flush_enabled;
bool db_depth_clear;
+ bool db_depth_disable_expclear;
};
/* si_blit.c */
diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c
index 9edc23fa1fd..bb8deb6ccff 100644
--- a/src/gallium/drivers/radeonsi/si_state.c
+++ b/src/gallium/drivers/radeonsi/si_state.c
@@ -1823,7 +1823,8 @@ static void si_init_depth_surface(struct si_context *sctx,
/* HiZ aka depth buffer htile */
/* use htile only for first level */
if (rtex->htile_buffer && !level) {
- z_info |= S_028040_TILE_SURFACE_ENABLE(1);
+ z_info |= S_028040_TILE_SURFACE_ENABLE(1) |
+ S_028040_ALLOW_EXPCLEAR(1);
/* This is optimal for the clear value of 1.0 and using
* the LESS and LEQUAL test functions. Set this to 0
diff --git a/src/gallium/drivers/radeonsi/si_state_draw.c b/src/gallium/drivers/radeonsi/si_state_draw.c
index 4fb205a04b8..2e9d9516d7c 100644
--- a/src/gallium/drivers/radeonsi/si_state_draw.c
+++ b/src/gallium/drivers/radeonsi/si_state_draw.c
@@ -758,6 +758,14 @@ static void si_state_draw(struct si_context *sctx,
si_pm4_set_reg(pm4, R_028000_DB_RENDER_CONTROL, 0);
}
+ /* DB_RENDER_OVERRIDE2 */
+ if (sctx->db_depth_disable_expclear) {
+ si_pm4_set_reg(pm4, R_028010_DB_RENDER_OVERRIDE2,
+ S_028010_DISABLE_ZMASK_EXPCLEAR_OPTIMIZATION(1));
+ } else {
+ si_pm4_set_reg(pm4, R_028010_DB_RENDER_OVERRIDE2, 0);
+ }
+
if (info->count_from_stream_output) {
struct r600_so_target *t =
(struct r600_so_target*)info->count_from_stream_output;