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@redhat.com> Reviewed-by: Marek Olšák <maraeo@gmail.com>
This commit is contained in:
parent
496928a442
commit
974b482aca
|
@ -2251,6 +2251,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);
|
||||
}
|
||||
|
@ -3240,7 +3247,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;
|
||||
|
@ -3250,7 +3257,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 */
|
||||
|
@ -3484,6 +3490,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;
|
||||
|
|
|
@ -1966,6 +1966,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);
|
||||
}
|
||||
|
@ -2774,7 +2781,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;
|
||||
|
@ -2969,6 +2976,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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue