[Mesa-dev] [PATCH] r600g: use dirty array to speed up emitting blocks

Jerome Glisse j.glisse at gmail.com
Tue Oct 5 10:19:12 PDT 2010


On Tue, Oct 5, 2010 at 12:10 PM, Bas Nieuwenhuizen
<bas at basnieuwenhuizen.nl> wrote:
> Emitting the dirty blocks sometimes accounted for about 30% percent of the time spent in r600_dri.so, so I made a seperate array with only the dirty blocks.
> ---
>  src/gallium/drivers/r600/r600.h                    |    2 ++
>  src/gallium/winsys/r600/drm/evergreen_hw_context.c |   18 +++++++++++++++---
>  src/gallium/winsys/r600/drm/r600_hw_context.c      |   20 +++++++++++++++++---
>  src/gallium/winsys/r600/drm/r600_priv.h            |    1 +
>  4 files changed, 35 insertions(+), 6 deletions(-)
>
> diff --git a/src/gallium/drivers/r600/r600.h b/src/gallium/drivers/r600/r600.h
> index 59a255d..8acb8c6 100644
> --- a/src/gallium/drivers/r600/r600.h
> +++ b/src/gallium/drivers/r600/r600.h
> @@ -221,6 +221,8 @@ struct r600_context {
>        struct r600_range       range[256];
>        unsigned                nblocks;
>        struct r600_block       **blocks;
> +       unsigned                ndirty;
> +       struct r600_block       **dirty;
>        unsigned                pm4_ndwords;
>        unsigned                pm4_cdwords;
>        unsigned                pm4_dirty_cdwords;
> diff --git a/src/gallium/winsys/r600/drm/evergreen_hw_context.c b/src/gallium/winsys/r600/drm/evergreen_hw_context.c
> index 96769ad..22c1021 100644
> --- a/src/gallium/winsys/r600/drm/evergreen_hw_context.c
> +++ b/src/gallium/winsys/r600/drm/evergreen_hw_context.c
> @@ -613,6 +613,13 @@ int evergreen_context_init(struct r600_context *ctx, struct radeon *radeon)
>                r = -ENOMEM;
>                goto out_err;
>        }
> +
> +       /* allocate an array for dirty blocks */
> +       ctx->dirty = calloc(ctx->nblocks,sizeof(struct r600_block*));
> +       if (ctx->dirty == NULL) {
> +               r = -ENOMEM;
> +               goto out_err;
> +       }
>        return 0;
>  out_err:
>        r600_context_fini(ctx);
> @@ -654,6 +661,7 @@ static inline void evergreen_context_pipe_state_set_resource(struct r600_context
>                r600_bo_reference(ctx->radeon, &block->reloc[2].bo, state->regs[3].bo);
>        }
>        if (!(block->status & R600_BLOCK_STATUS_DIRTY)) {
> +               ctx->dirty[ctx->ndirty++] = block;
>                block->status |= R600_BLOCK_STATUS_ENABLED;
>                block->status |= R600_BLOCK_STATUS_DIRTY;
>                ctx->pm4_dirty_cdwords += block->pm4_ndwords + block->pm4_flush_ndwords;
> @@ -689,6 +697,7 @@ static inline void evergreen_context_pipe_state_set_sampler(struct r600_context
>        block->reg[1] = state->regs[1].value;
>        block->reg[2] = state->regs[2].value;
>        if (!(block->status & R600_BLOCK_STATUS_DIRTY)) {
> +               ctx->dirty[ctx->ndirty++] = block;
>                block->status |= R600_BLOCK_STATUS_ENABLED;
>                block->status |= R600_BLOCK_STATUS_DIRTY;
>                ctx->pm4_dirty_cdwords += block->pm4_ndwords + block->pm4_flush_ndwords;
> @@ -716,6 +725,7 @@ static inline void evergreen_context_pipe_state_set_sampler_border(struct r600_c
>        block->reg[3] = state->regs[5].value;
>        block->reg[4] = state->regs[6].value;
>        if (!(block->status & R600_BLOCK_STATUS_DIRTY)) {
> +               ctx->dirty[ctx->ndirty++] = block;
>                block->status |= R600_BLOCK_STATUS_ENABLED;
>                block->status |= R600_BLOCK_STATUS_DIRTY;
>                ctx->pm4_dirty_cdwords += block->pm4_ndwords + block->pm4_flush_ndwords;
> @@ -800,11 +810,12 @@ void evergreen_context_draw(struct r600_context *ctx, const struct r600_draw *dr
>        }
>
>        /* enough room to copy packet */
> -       for (int i = 0; i < ctx->nblocks; i++) {
> -               if (ctx->blocks[i]->status & R600_BLOCK_STATUS_DIRTY) {
> -                       r600_context_block_emit_dirty(ctx, ctx->blocks[i]);
> +       for (int i = 0; i < ctx->ndirty; i++) {
> +               if (ctx->dirty[i]->status & R600_BLOCK_STATUS_DIRTY) {


This test should become useless but it seems it's not, some block end 2 times
on the dirty list thought i can't see why.



> +                       r600_context_block_emit_dirty(ctx, ctx->dirty[i]);
>                }
>        }
> +       ctx->ndirty = 0;
>
>        /* draw packet */
>        ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_INDEX_TYPE, 0);
> @@ -881,6 +892,7 @@ static inline void evergreen_resource_set(struct r600_context *ctx, struct r600_
>                r600_bo_reference(ctx->radeon, &block->reloc[2].bo, state->regs[3].bo);
>        }
>        if (!(block->status & R600_BLOCK_STATUS_DIRTY)) {
> +               ctx->dirty[ctx->ndirty++] = block;
>                block->status |= R600_BLOCK_STATUS_ENABLED;
>                block->status |= R600_BLOCK_STATUS_DIRTY;
>                ctx->pm4_dirty_cdwords += block->pm4_ndwords + block->pm4_flush_ndwords;
> diff --git a/src/gallium/winsys/r600/drm/r600_hw_context.c b/src/gallium/winsys/r600/drm/r600_hw_context.c
> index 84539d1..45c1f0b 100644
> --- a/src/gallium/winsys/r600/drm/r600_hw_context.c
> +++ b/src/gallium/winsys/r600/drm/r600_hw_context.c
> @@ -572,6 +572,7 @@ void r600_context_fini(struct r600_context *ctx)
>        }
>        free(ctx->reloc);
>        free(ctx->pm4);
> +       free(ctx->dirty);
>        memset(ctx, 0, sizeof(struct r600_context));
>  }
>
> @@ -691,6 +692,13 @@ int r600_context_init(struct r600_context *ctx, struct radeon *radeon)
>                r = -ENOMEM;
>                goto out_err;
>        }
> +
> +       /* allocate an array for dirty blocks */
> +       ctx->dirty = calloc(ctx->nblocks,sizeof(struct r600_block*));
> +       if (ctx->dirty == NULL) {
> +               r = -ENOMEM;
> +               goto out_err;
> +       }
>        return 0;
>  out_err:
>        r600_context_fini(ctx);
> @@ -759,6 +767,7 @@ void r600_context_pipe_state_set(struct r600_context *ctx, struct r600_pipe_stat
>                        r600_bo_reference(ctx->radeon, &block->reloc[id].bo, state->regs[i].bo);
>                }
>                if (!(block->status & R600_BLOCK_STATUS_DIRTY)) {
> +                       ctx->dirty[ctx->ndirty++] = block;
>                        block->status |= R600_BLOCK_STATUS_ENABLED;
>                        block->status |= R600_BLOCK_STATUS_DIRTY;
>                        ctx->pm4_dirty_cdwords += block->pm4_ndwords + block->pm4_flush_ndwords;
> @@ -800,6 +809,7 @@ static inline void r600_context_pipe_state_set_resource(struct r600_context *ctx
>                r600_bo_reference(ctx->radeon, &block->reloc[2].bo, state->regs[3].bo);
>        }
>        if (!(block->status & R600_BLOCK_STATUS_DIRTY)) {
> +               ctx->dirty[ctx->ndirty++] = block;
>                block->status |= R600_BLOCK_STATUS_ENABLED;
>                block->status |= R600_BLOCK_STATUS_DIRTY;
>                ctx->pm4_dirty_cdwords += block->pm4_ndwords + block->pm4_flush_ndwords;
> @@ -835,6 +845,7 @@ static inline void r600_context_pipe_state_set_sampler(struct r600_context *ctx,
>        block->reg[1] = state->regs[1].value;
>        block->reg[2] = state->regs[2].value;
>        if (!(block->status & R600_BLOCK_STATUS_DIRTY)) {
> +               ctx->dirty[ctx->ndirty++] = block;
>                block->status |= R600_BLOCK_STATUS_ENABLED;
>                block->status |= R600_BLOCK_STATUS_DIRTY;
>                ctx->pm4_dirty_cdwords += block->pm4_ndwords + block->pm4_flush_ndwords;
> @@ -860,6 +871,7 @@ static inline void r600_context_pipe_state_set_sampler_border(struct r600_contex
>        block->reg[2] = state->regs[5].value;
>        block->reg[3] = state->regs[6].value;
>        if (!(block->status & R600_BLOCK_STATUS_DIRTY)) {
> +               ctx->dirty[ctx->ndirty++] = block;
>                block->status |= R600_BLOCK_STATUS_ENABLED;
>                block->status |= R600_BLOCK_STATUS_DIRTY;
>                ctx->pm4_dirty_cdwords += block->pm4_ndwords + block->pm4_flush_ndwords;
> @@ -959,11 +971,12 @@ void r600_context_draw(struct r600_context *ctx, const struct r600_draw *draw)
>        }
>
>        /* enough room to copy packet */
> -       for (int i = 0; i < ctx->nblocks; i++) {
> -               if (ctx->blocks[i]->status & R600_BLOCK_STATUS_DIRTY) {
> -                       r600_context_block_emit_dirty(ctx, ctx->blocks[i]);
> +       for (int i = 0; i < ctx->ndirty; i++) {
> +               if (ctx->dirty[i]->status & R600_BLOCK_STATUS_DIRTY) {
> +                       r600_context_block_emit_dirty(ctx, ctx->dirty[i]);
>                }
>        }
> +       ctx->ndirty = 0;
>
>        /* draw packet */
>        ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_INDEX_TYPE, 0);
> @@ -1052,6 +1065,7 @@ void r600_context_flush(struct r600_context *ctx)
>         */
>        for (int i = 0; i < ctx->nblocks; i++) {
>                if (ctx->blocks[i]->status & R600_BLOCK_STATUS_ENABLED) {
> +                       ctx->dirty[ctx->ndirty++] = ctx->blocks[i];
>                        ctx->pm4_dirty_cdwords += ctx->blocks[i]->pm4_ndwords + ctx->blocks[i]->pm4_flush_ndwords;
>                        ctx->blocks[i]->status |= R600_BLOCK_STATUS_DIRTY;
>                }
> diff --git a/src/gallium/winsys/r600/drm/r600_priv.h b/src/gallium/winsys/r600/drm/r600_priv.h
> index f6ceb0a..1d0c122 100644
> --- a/src/gallium/winsys/r600/drm/r600_priv.h
> +++ b/src/gallium/winsys/r600/drm/r600_priv.h
> @@ -134,6 +134,7 @@ static void inline r600_context_reg(struct r600_context *ctx,
>        block->reg[id] &= ~mask;
>        block->reg[id] |= value;
>        if (!(block->status & R600_BLOCK_STATUS_DIRTY)) {
> +               ctx->dirty[ctx->ndirty++] = block;
>                ctx->pm4_dirty_cdwords += block->pm4_ndwords;
>                block->status |= R600_BLOCK_STATUS_ENABLED;
>                block->status |= R600_BLOCK_STATUS_DIRTY;
> --
> 1.7.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