[Mesa-dev] [PATCH 2/2] r600g: fix lockup when hyperz & alpha test are enabled together. v2

Jerome Glisse j.glisse at gmail.com
Mon Feb 11 15:50:08 PST 2013


On Mon, Feb 11, 2013 at 6:45 PM,  <j.glisse at gmail.com> wrote:
> From: Jerome Glisse <jglisse at redhat.com>
>
> 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
>
> Signed-off-by: Jerome Glisse <jglisse at redhat.com>
> Reviewed-by: Marek Olšák <maraeo at gmail.com>

This one does not regress piglit (redwood or rv770) and still fix
lockup afaict. If no objection i will push tomorrow.

Cheers,
Jerome

> ---
>  src/gallium/drivers/r600/evergreen_state.c | 25 +++++++++++++++++++++++--
>  src/gallium/drivers/r600/r600_state.c      | 22 +++++++++++++++++++++-
>  2 files changed, 44 insertions(+), 3 deletions(-)
>
> diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c
> index 211c218..b710131 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 some how 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 antrust 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..8efd4b3 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 some how 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 antrust 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;
> --
> 1.7.11.7
>


More information about the mesa-dev mailing list