Mesa (9.1): r600g: fix lockup when hyperz & alpha test are enabled together . v3

Jerome Glisse glisse at kemper.freedesktop.org
Tue Feb 12 22:10:00 UTC 2013


Module: Mesa
Branch: 9.1
Commit: 3ae8678f81ac65503595447763cb8447781155ba
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=3ae8678f81ac65503595447763cb8447781155ba

Author: Jerome Glisse <jglisse at redhat.com>
Date:   Fri Feb  8 16:02:32 2013 -0500

r600g: fix lockup when hyperz & alpha test are enabled together. v3

Seems that alpha test being enabled confuse the GPU on the order in
which it should perform the Z testing. So force the order programmed
throught db shader control.

v2: Only force z order when alpha test is enabled
v3: Update db shader when binding new dsa + spelling fix

Signed-off-by: Jerome Glisse <jglisse at redhat.com>
Reviewed-by: Marek Olšák <maraeo at gmail.com>
(cherry picked from commit 974b482acaf62ced1e8981761a8bda252bd51fe1)

---

 src/gallium/drivers/r600/evergreen_state.c   |   25 +++++++++++++++++++++++--
 src/gallium/drivers/r600/r600_state.c        |   22 +++++++++++++++++++++-
 src/gallium/drivers/r600/r600_state_common.c |    5 +++++
 3 files changed, 49 insertions(+), 3 deletions(-)

diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c
index ad2f731..c39827f 100644
--- a/src/gallium/drivers/r600/evergreen_state.c
+++ b/src/gallium/drivers/r600/evergreen_state.c
@@ -2225,6 +2225,13 @@ static void evergreen_emit_db_misc_state(struct r600_context *rctx, struct r600_
 	if (rctx->db_state.rsurf && rctx->db_state.rsurf->htile_enabled) {
 		/* FORCE_OFF means HiZ/HiS are determined by DB_SHADER_CONTROL */
 		db_render_override |= S_02800C_FORCE_HIZ_ENABLE(V_02800C_FORCE_OFF);
+		/* This is to fix a lockup when hyperz and alpha test are enabled at
+		 * the same time somehow GPU get confuse on which order to pick for
+		 * z test
+		 */
+		if (rctx->alphatest_state.sx_alpha_test_control) {
+			db_render_override |= S_02800C_FORCE_SHADER_Z_ORDER(1);
+		}
 	} else {
 		db_render_override |= S_02800C_FORCE_HIZ_ENABLE(V_02800C_FORCE_DISABLE);
 	}
@@ -3214,7 +3221,7 @@ void evergreen_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shader
 	struct r600_context *rctx = (struct r600_context *)ctx;
 	struct r600_pipe_state *rstate = &shader->rstate;
 	struct r600_shader *rshader = &shader->shader;
-	unsigned i, exports_ps, num_cout, spi_ps_in_control_0, spi_input_z, spi_ps_in_control_1, db_shader_control;
+	unsigned i, exports_ps, num_cout, spi_ps_in_control_0, spi_input_z, spi_ps_in_control_1, db_shader_control = 0;
 	int pos_index = -1, face_index = -1;
 	int ninterp = 0;
 	boolean have_linear = FALSE, have_centroid = FALSE, have_perspective = FALSE;
@@ -3224,7 +3231,6 @@ void evergreen_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shader
 
 	rstate->nregs = 0;
 
-	db_shader_control = S_02880C_Z_ORDER(V_02880C_EARLY_Z_THEN_LATE_Z);
 	for (i = 0; i < rshader->ninput; i++) {
 		/* evergreen NUM_INTERP only contains values interpolated into the LDS,
 		   POSITION goes via GPRs from the SC so isn't counted */
@@ -3458,6 +3464,21 @@ void evergreen_update_db_shader_control(struct r600_context * rctx)
 								V_02880C_EXPORT_DB_FULL) |
 			S_02880C_ALPHA_TO_MASK_DISABLE(rctx->framebuffer.cb0_is_integer);
 
+	/* When alpha test is enabled we can't trust the hw to make the proper
+	 * decision on the order in which ztest should be run related to fragment
+	 * shader execution.
+	 *
+	 * If alpha test is enabled perform early z rejection (RE_Z) but don't early
+	 * write to the zbuffer. Write to zbuffer is delayed after fragment shader
+	 * execution and thus after alpha test so if discarded by the alpha test
+	 * the z value is not written.
+	 */
+	if (rctx->alphatest_state.sx_alpha_test_control) {
+		db_shader_control |= S_02880C_Z_ORDER(V_02880C_RE_Z);
+	} else {
+		db_shader_control |= S_02880C_Z_ORDER(V_02880C_EARLY_Z_THEN_LATE_Z);
+	}
+
 	if (db_shader_control != rctx->db_misc_state.db_shader_control) {
 		rctx->db_misc_state.db_shader_control = db_shader_control;
 		rctx->db_misc_state.atom.dirty = true;
diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c
index 1f50ed6..3f165f7 100644
--- a/src/gallium/drivers/r600/r600_state.c
+++ b/src/gallium/drivers/r600/r600_state.c
@@ -1940,6 +1940,13 @@ static void r600_emit_db_misc_state(struct r600_context *rctx, struct r600_atom
 	if (rctx->db_state.rsurf && rctx->db_state.rsurf->htile_enabled) {
 		/* FORCE_OFF means HiZ/HiS are determined by DB_SHADER_CONTROL */
 		db_render_override |= S_028D10_FORCE_HIZ_ENABLE(V_028D10_FORCE_OFF);
+		/* This is to fix a lockup when hyperz and alpha test are enabled at
+		 * the same time somehow GPU get confuse on which order to pick for
+		 * z test
+		 */
+		if (rctx->alphatest_state.sx_alpha_test_control) {
+			db_render_override |= S_028D10_FORCE_SHADER_Z_ORDER(1);
+		}
 	} else {
 		db_render_override |= S_028D10_FORCE_HIZ_ENABLE(V_028D10_FORCE_DISABLE);
 	}
@@ -2748,7 +2755,7 @@ void r600_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shader *shad
 				tmp);
 	}
 
-	db_shader_control = S_02880C_Z_ORDER(V_02880C_EARLY_Z_THEN_LATE_Z);
+	db_shader_control = 0;
 	for (i = 0; i < rshader->noutput; i++) {
 		if (rshader->output[i].name == TGSI_SEMANTIC_POSITION)
 			z_export = 1;
@@ -2943,6 +2950,19 @@ void r600_update_db_shader_control(struct r600_context * rctx)
 	unsigned db_shader_control = rctx->ps_shader->current->db_shader_control |
 				     S_02880C_DUAL_EXPORT_ENABLE(dual_export);
 
+	/* When alpha test is enabled we can't trust the hw to make the proper
+	 * decision on the order in which ztest should be run related to fragment
+	 * shader execution.
+	 *
+	 * If alpha test is enabled perform z test after fragment. RE_Z (early
+	 * z test but no write to the zbuffer) seems to cause lockup on r6xx/r7xx
+	 */
+	if (rctx->alphatest_state.sx_alpha_test_control) {
+		db_shader_control |= S_02880C_Z_ORDER(V_02880C_LATE_Z);
+	} else {
+		db_shader_control |= S_02880C_Z_ORDER(V_02880C_EARLY_Z_THEN_LATE_Z);
+	}
+
 	if (db_shader_control != rctx->db_misc_state.db_shader_control) {
 		rctx->db_misc_state.db_shader_control = db_shader_control;
 		rctx->db_misc_state.atom.dirty = true;
diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c
index 33200a6..c03ce3d 100644
--- a/src/gallium/drivers/r600/r600_state_common.c
+++ b/src/gallium/drivers/r600/r600_state_common.c
@@ -293,6 +293,11 @@ static void r600_bind_dsa_state(struct pipe_context *ctx, void *state)
 		rctx->alphatest_state.sx_alpha_test_control = dsa->sx_alpha_test_control;
 		rctx->alphatest_state.sx_alpha_ref = dsa->alpha_ref;
 		rctx->alphatest_state.atom.dirty = true;
+		if (rctx->chip_class >= EVERGREEN) {
+			evergreen_update_db_shader_control(rctx);
+		} else {
+			r600_update_db_shader_control(rctx);
+		}
 	}
 }
 




More information about the mesa-commit mailing list