This looks good. Thanks. Reviewed-by: Marek Olšák <[email protected]>
Marek On Tue, Feb 12, 2013 at 12:30 PM, <[email protected]> wrote: > From: Jerome Glisse <[email protected]> > > 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 <[email protected]> > --- > 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 211c218..29b22ab 100644 > --- a/src/gallium/drivers/r600/evergreen_state.c > +++ b/src/gallium/drivers/r600/evergreen_state.c > @@ -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; > diff --git a/src/gallium/drivers/r600/r600_state.c > b/src/gallium/drivers/r600/r600_state.c > index 5322850..3f359fb 100644 > --- a/src/gallium/drivers/r600/r600_state.c > +++ b/src/gallium/drivers/r600/r600_state.c > @@ -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; > 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); > + } > } > } > > -- > 1.7.11.7 > > _______________________________________________ > mesa-dev mailing list > [email protected] > http://lists.freedesktop.org/mailman/listinfo/mesa-dev _______________________________________________ mesa-dev mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/mesa-dev
