[Mesa-dev] [PATCH 1/4] r600g: make all scissor states use single atom

Marek Olšák maraeo at gmail.com
Mon Aug 24 14:30:45 PDT 2015


The "workaround for a missing scissor enable on r600" must be applied
to all scissors, not just 0. That is, if scissor.enable is changed,
all scissors must be marked as dirty.

Marek

On Mon, Aug 24, 2015 at 2:24 AM, Grazvydas Ignotas <notasas at gmail.com> wrote:
> As suggested by Marek Olšák, we can use single atom to track all scissor
> states. This will allow to simplify dirty atom handling later.
> ---
>  src/gallium/drivers/r600/evergreen_state.c   | 33 ++++++++++++++-------
>  src/gallium/drivers/r600/r600_blit.c         |  2 +-
>  src/gallium/drivers/r600/r600_hw_context.c   |  4 ++-
>  src/gallium/drivers/r600/r600_pipe.h         |  8 +++---
>  src/gallium/drivers/r600/r600_state.c        | 43 +++++++++++++++++-----------
>  src/gallium/drivers/r600/r600_state_common.c |  6 ++--
>  6 files changed, 60 insertions(+), 36 deletions(-)
>
> diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c
> index 6a91d47..fbdcc9c 100644
> --- a/src/gallium/drivers/r600/evergreen_state.c
> +++ b/src/gallium/drivers/r600/evergreen_state.c
> @@ -892,27 +892,39 @@ static void evergreen_set_scissor_states(struct pipe_context *ctx,
>                                         const struct pipe_scissor_state *state)
>  {
>         struct r600_context *rctx = (struct r600_context *)ctx;
> +       struct r600_scissor_state *rstate = &rctx->scissor;
>         int i;
>
>         for (i = start_slot; i < start_slot + num_scissors; i++) {
> -               rctx->scissor[i].scissor = state[i - start_slot];
> -               r600_mark_atom_dirty(rctx, &rctx->scissor[i].atom);
> +               rstate->scissor[i] = state[i - start_slot];
> +               rstate->dirty_mask |= 1 << i;
>         }
> +       rstate->atom.num_dw = util_bitcount(rstate->dirty_mask) * 4;
> +       r600_mark_atom_dirty(rctx, &rstate->atom);
>  }
>
>  static void evergreen_emit_scissor_state(struct r600_context *rctx, struct r600_atom *atom)
>  {
>         struct radeon_winsys_cs *cs = rctx->b.rings.gfx.cs;
> -       struct r600_scissor_state *rstate = (struct r600_scissor_state *)atom;
> -       struct pipe_scissor_state *state = &rstate->scissor;
> -       unsigned offset = rstate->idx * 4 * 2;
> +       struct r600_scissor_state *rstate = &rctx->scissor;
> +       struct pipe_scissor_state *state;
> +       uint32_t dirty_mask;
> +       unsigned i, offset;
>         uint32_t tl, br;
>
> -       evergreen_get_scissor_rect(rctx, state->minx, state->miny, state->maxx, state->maxy, &tl, &br);
> +       dirty_mask = rstate->dirty_mask;
> +       while (dirty_mask != 0) {
> +               i = u_bit_scan(&dirty_mask);
> +               state = &rstate->scissor[i];
> +               evergreen_get_scissor_rect(rctx, state->minx, state->miny, state->maxx, state->maxy, &tl, &br);
>
> -       r600_write_context_reg_seq(cs, R_028250_PA_SC_VPORT_SCISSOR_0_TL + offset, 2);
> -       radeon_emit(cs, tl);
> -       radeon_emit(cs, br);
> +               offset = i * 4 * 2;
> +               r600_write_context_reg_seq(cs, R_028250_PA_SC_VPORT_SCISSOR_0_TL + offset, 2);
> +               radeon_emit(cs, tl);
> +               radeon_emit(cs, br);
> +       }
> +       rstate->dirty_mask = 0;
> +       rstate->atom.num_dw = 0;
>  }
>
>  /**
> @@ -3484,11 +3496,10 @@ void evergreen_init_state_functions(struct r600_context *rctx)
>         r600_init_atom(rctx, &rctx->dsa_state.atom, id++, r600_emit_cso_state, 0);
>         r600_init_atom(rctx, &rctx->poly_offset_state.atom, id++, evergreen_emit_polygon_offset, 6);
>         r600_init_atom(rctx, &rctx->rasterizer_state.atom, id++, r600_emit_cso_state, 0);
> +       r600_init_atom(rctx, &rctx->scissor.atom, id++, evergreen_emit_scissor_state, 0);
>         for (i = 0; i < R600_MAX_VIEWPORTS; i++) {
>                 r600_init_atom(rctx, &rctx->viewport[i].atom, id++, r600_emit_viewport_state, 8);
> -               r600_init_atom(rctx, &rctx->scissor[i].atom, id++, evergreen_emit_scissor_state, 4);
>                 rctx->viewport[i].idx = i;
> -               rctx->scissor[i].idx = i;
>         }
>         r600_init_atom(rctx, &rctx->stencil_ref.atom, id++, r600_emit_stencil_ref, 4);
>         r600_init_atom(rctx, &rctx->vertex_fetch_shader.atom, id++, evergreen_emit_vertex_fetch_shader, 5);
> diff --git a/src/gallium/drivers/r600/r600_blit.c b/src/gallium/drivers/r600/r600_blit.c
> index 22a0950..6ecb8ee 100644
> --- a/src/gallium/drivers/r600/r600_blit.c
> +++ b/src/gallium/drivers/r600/r600_blit.c
> @@ -66,7 +66,7 @@ static void r600_blitter_begin(struct pipe_context *ctx, enum r600_blitter_op op
>
>         if (op & R600_SAVE_FRAGMENT_STATE) {
>                 util_blitter_save_viewport(rctx->blitter, &rctx->viewport[0].state);
> -               util_blitter_save_scissor(rctx->blitter, &rctx->scissor[0].scissor);
> +               util_blitter_save_scissor(rctx->blitter, &rctx->scissor.scissor[0]);
>                 util_blitter_save_fragment_shader(rctx->blitter, rctx->ps_shader);
>                 util_blitter_save_blend(rctx->blitter, rctx->blend_state.cso);
>                 util_blitter_save_depth_stencil_alpha(rctx->blitter, rctx->dsa_state.cso);
> diff --git a/src/gallium/drivers/r600/r600_hw_context.c b/src/gallium/drivers/r600/r600_hw_context.c
> index 6445151..6710cd3 100644
> --- a/src/gallium/drivers/r600/r600_hw_context.c
> +++ b/src/gallium/drivers/r600/r600_hw_context.c
> @@ -308,8 +308,10 @@ void r600_begin_new_cs(struct r600_context *ctx)
>         r600_mark_atom_dirty(ctx, &ctx->poly_offset_state.atom);
>         r600_mark_atom_dirty(ctx, &ctx->vgt_state.atom);
>         r600_mark_atom_dirty(ctx, &ctx->sample_mask.atom);
> +       ctx->scissor.dirty_mask = (1 << R600_MAX_VIEWPORTS) - 1;
> +       ctx->scissor.atom.num_dw = R600_MAX_VIEWPORTS * 4;
> +       r600_mark_atom_dirty(ctx, &ctx->scissor.atom);
>         for (i = 0; i < R600_MAX_VIEWPORTS; i++) {
> -               r600_mark_atom_dirty(ctx, &ctx->scissor[i].atom);
>                 r600_mark_atom_dirty(ctx, &ctx->viewport[i].atom);
>         }
>         if (ctx->b.chip_class < EVERGREEN) {
> diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h
> index 384ba80..549a7f6 100644
> --- a/src/gallium/drivers/r600/r600_pipe.h
> +++ b/src/gallium/drivers/r600/r600_pipe.h
> @@ -36,7 +36,7 @@
>  #include "util/list.h"
>  #include "util/u_transfer.h"
>
> -#define R600_NUM_ATOMS 75
> +#define R600_NUM_ATOMS 60
>
>  #define R600_MAX_VIEWPORTS 16
>
> @@ -385,9 +385,9 @@ struct r600_cso_state
>  struct r600_scissor_state
>  {
>         struct r600_atom                atom;
> -       struct pipe_scissor_state       scissor;
> +       struct pipe_scissor_state       scissor[R600_MAX_VIEWPORTS];
> +       uint32_t                        dirty_mask;
>         bool                            enable; /* r6xx only */
> -       int idx;
>  };
>
>  struct r600_fetch_shader {
> @@ -450,7 +450,7 @@ struct r600_context {
>         struct r600_poly_offset_state   poly_offset_state;
>         struct r600_cso_state           rasterizer_state;
>         struct r600_sample_mask         sample_mask;
> -       struct r600_scissor_state       scissor[R600_MAX_VIEWPORTS];
> +       struct r600_scissor_state       scissor;
>         struct r600_seamless_cube_map   seamless_cube_map;
>         struct r600_config_state        config_state;
>         struct r600_stencil_ref_state   stencil_ref;
> diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c
> index 5cc2283..88f8da5 100644
> --- a/src/gallium/drivers/r600/r600_state.c
> +++ b/src/gallium/drivers/r600/r600_state.c
> @@ -769,21 +769,32 @@ static void r600_set_polygon_stipple(struct pipe_context *ctx,
>  static void r600_emit_scissor_state(struct r600_context *rctx, struct r600_atom *atom)
>  {
>         struct radeon_winsys_cs *cs = rctx->b.rings.gfx.cs;
> -       struct r600_scissor_state *rstate = (struct r600_scissor_state *)atom;
> -       struct pipe_scissor_state *state = &rstate->scissor;
> -       unsigned offset = rstate->idx * 4 * 2;
> +       struct r600_scissor_state *rstate = &rctx->scissor;
> +       struct pipe_scissor_state *state;
> +       uint32_t dirty_mask;
> +       unsigned i, offset;
>
> -       if (rctx->b.chip_class != R600 || rctx->scissor[0].enable) {
> -               r600_write_context_reg_seq(cs, R_028250_PA_SC_VPORT_SCISSOR_0_TL + offset, 2);
> -               radeon_emit(cs, S_028240_TL_X(state->minx) | S_028240_TL_Y(state->miny) |
> -                                    S_028240_WINDOW_OFFSET_DISABLE(1));
> -               radeon_emit(cs, S_028244_BR_X(state->maxx) | S_028244_BR_Y(state->maxy));
> -       } else {
> +       if (rctx->b.chip_class == R600 && !rctx->scissor.enable) {
>                 r600_write_context_reg_seq(cs, R_028250_PA_SC_VPORT_SCISSOR_0_TL, 2);
>                 radeon_emit(cs, S_028240_TL_X(0) | S_028240_TL_Y(0) |
>                                      S_028240_WINDOW_OFFSET_DISABLE(1));
>                 radeon_emit(cs, S_028244_BR_X(8192) | S_028244_BR_Y(8192));
> +               return;
> +       }
> +
> +       dirty_mask = rstate->dirty_mask;
> +       while (dirty_mask != 0)
> +       {
> +               i = u_bit_scan(&dirty_mask);
> +               offset = i * 4 * 2;
> +               state = &rstate->scissor[i];
> +               r600_write_context_reg_seq(cs, R_028250_PA_SC_VPORT_SCISSOR_0_TL + offset, 2);
> +               radeon_emit(cs, S_028240_TL_X(state->minx) | S_028240_TL_Y(state->miny) |
> +                                    S_028240_WINDOW_OFFSET_DISABLE(1));
> +               radeon_emit(cs, S_028244_BR_X(state->maxx) | S_028244_BR_Y(state->maxy));
>         }
> +       rstate->dirty_mask = 0;
> +       rstate->atom.num_dw = 0;
>  }
>
>  static void r600_set_scissor_states(struct pipe_context *ctx,
> @@ -792,18 +803,19 @@ static void r600_set_scissor_states(struct pipe_context *ctx,
>                                      const struct pipe_scissor_state *state)
>  {
>         struct r600_context *rctx = (struct r600_context *)ctx;
> +       struct r600_scissor_state *rstate = &rctx->scissor;
>         int i;
>
>         for (i = start_slot ; i < start_slot + num_scissors; i++) {
> -               rctx->scissor[i].scissor = state[i - start_slot];
> +               rstate->scissor[i] = state[i - start_slot];
> +               rstate->dirty_mask |= 1 << i;
>         }
> +       rstate->atom.num_dw = util_bitcount(rstate->dirty_mask) * 4;
>
> -       if (rctx->b.chip_class == R600 && !rctx->scissor[0].enable)
> +       if (rctx->b.chip_class == R600 && !rstate->enable)
>                 return;
>
> -       for (i = start_slot ; i < start_slot + num_scissors; i++) {
> -               r600_mark_atom_dirty(rctx, &rctx->scissor[i].atom);
> -       }
> +       r600_mark_atom_dirty(rctx, &rstate->atom);
>  }
>
>  static struct r600_resource *r600_buffer_create_helper(struct r600_screen *rscreen,
> @@ -3065,10 +3077,9 @@ void r600_init_state_functions(struct r600_context *rctx)
>         r600_init_atom(rctx, &rctx->dsa_state.atom, id++, r600_emit_cso_state, 0);
>         r600_init_atom(rctx, &rctx->poly_offset_state.atom, id++, r600_emit_polygon_offset, 6);
>         r600_init_atom(rctx, &rctx->rasterizer_state.atom, id++, r600_emit_cso_state, 0);
> +       r600_init_atom(rctx, &rctx->scissor.atom, id++, r600_emit_scissor_state, 0);
>         for (i = 0;i < R600_MAX_VIEWPORTS; i++) {
> -               r600_init_atom(rctx, &rctx->scissor[i].atom, id++, r600_emit_scissor_state, 4);
>                 r600_init_atom(rctx, &rctx->viewport[i].atom, id++, r600_emit_viewport_state, 8);
> -               rctx->scissor[i].idx = i;
>                 rctx->viewport[i].idx = i;
>         }
>         r600_init_atom(rctx, &rctx->config_state.atom, id++, r600_emit_config_state, 3);
> diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c
> index a05dd83..66dc534 100644
> --- a/src/gallium/drivers/r600/r600_state_common.c
> +++ b/src/gallium/drivers/r600/r600_state_common.c
> @@ -346,9 +346,9 @@ static void r600_bind_rs_state(struct pipe_context *ctx, void *state)
>
>         /* Workaround for a missing scissor enable on r600. */
>         if (rctx->b.chip_class == R600 &&
> -           rs->scissor_enable != rctx->scissor[0].enable) {
> -               rctx->scissor[0].enable = rs->scissor_enable;
> -               r600_mark_atom_dirty(rctx, &rctx->scissor[0].atom);
> +           rs->scissor_enable != rctx->scissor.enable) {
> +               rctx->scissor.enable = rs->scissor_enable;
> +               r600_mark_atom_dirty(rctx, &rctx->scissor.atom);
>         }
>
>         /* Re-emit PA_SC_LINE_STIPPLE. */
> --
> 1.9.1
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list