[Mesa-dev] [PATCH] r600g: implement fast color clears on evergreen+

Marek Olšák maraeo at gmail.com
Mon Jun 10 17:41:36 PDT 2013


On Mon, Jun 10, 2013 at 3:25 PM, Grigori Goronzy <greg at chown.ath.cx> wrote:
> Allows MSAA colorbuffers, which have a CMASK automatically and don't
> need any further special handling, to be fast cleared. Instead
> of clearing the buffer, set the clear color and the CMASK to the
> cleared state.
>
> Fast clear is used only when all bound colorbuffers fulfill certain
> conditions: a CMASK is required, we have to be able to create a clear
> color value for the format and the format mustn't be an array texture
> (or cubemap, which is handled similarly).
>
> No piglit regressions on Evergreen.
> ---
>  src/gallium/drivers/r600/evergreen_state.c |  9 ++++-
>  src/gallium/drivers/r600/r600_blit.c       | 64 ++++++++++++++++++++++++++++++
>  src/gallium/drivers/r600/r600_resource.h   |  2 +
>  3 files changed, 73 insertions(+), 2 deletions(-)
>
> diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c
> index 689745f..f9e35e4 100644
> --- a/src/gallium/drivers/r600/evergreen_state.c
> +++ b/src/gallium/drivers/r600/evergreen_state.c
> @@ -1853,7 +1853,7 @@ static void evergreen_set_framebuffer_state(struct pipe_context *ctx,
>         }
>
>         /* Colorbuffers. */
> -       rctx->framebuffer.atom.num_dw += state->nr_cbufs * 21;
> +       rctx->framebuffer.atom.num_dw += state->nr_cbufs * 25;
>         if (rctx->keep_tiling_flags)
>                 rctx->framebuffer.atom.num_dw += state->nr_cbufs * 2;
>         rctx->framebuffer.atom.num_dw += (12 - state->nr_cbufs) * 3;
> @@ -2173,12 +2173,13 @@ static void evergreen_emit_framebuffer_state(struct r600_context *rctx, struct r
>         /* Colorbuffers. */
>         for (i = 0; i < nr_cbufs; i++) {
>                 struct r600_surface *cb = (struct r600_surface*)state->cbufs[i];
> +               struct r600_texture *tex = (struct r600_texture *)cb->base.texture;
>                 unsigned reloc = r600_context_bo_reloc(rctx,
>                                                        &rctx->rings.gfx,
>                                                        (struct r600_resource*)cb->base.texture,
>                                                        RADEON_USAGE_READWRITE);
>
> -               r600_write_context_reg_seq(cs, R_028C60_CB_COLOR0_BASE + i * 0x3C, 11);
> +               r600_write_context_reg_seq(cs, R_028C60_CB_COLOR0_BASE + i * 0x3C, 15);
>                 r600_write_value(cs, cb->cb_color_base);        /* R_028C60_CB_COLOR0_BASE */
>                 r600_write_value(cs, cb->cb_color_pitch);       /* R_028C64_CB_COLOR0_PITCH */
>                 r600_write_value(cs, cb->cb_color_slice);       /* R_028C68_CB_COLOR0_SLICE */
> @@ -2190,6 +2191,10 @@ static void evergreen_emit_framebuffer_state(struct r600_context *rctx, struct r
>                 r600_write_value(cs, cb->cb_color_cmask_slice); /* R_028C80_CB_COLOR0_CMASK_SLICE */
>                 r600_write_value(cs, cb->cb_color_fmask);       /* R_028C84_CB_COLOR0_FMASK */
>                 r600_write_value(cs, cb->cb_color_fmask_slice); /* R_028C88_CB_COLOR0_FMASK_SLICE */
> +               r600_write_value(cs, tex->color_clear_value[0]); /* R_028C8C_CB_COLOR0_CLEAR_WORD0 */
> +               r600_write_value(cs, tex->color_clear_value[1]); /* R_028C90_CB_COLOR0_CLEAR_WORD1 */
> +               r600_write_value(cs, tex->color_clear_value[2]); /* R_028C94_CB_COLOR0_CLEAR_WORD2 */
> +               r600_write_value(cs, tex->color_clear_value[3]); /* R_028C98_CB_COLOR0_CLEAR_WORD3 */
>
>                 r600_write_value(cs, PKT3(PKT3_NOP, 0, 0)); /* R_028C60_CB_COLOR0_BASE */
>                 r600_write_value(cs, reloc);
> diff --git a/src/gallium/drivers/r600/r600_blit.c b/src/gallium/drivers/r600/r600_blit.c
> index 058bf81..471ee69 100644
> --- a/src/gallium/drivers/r600/r600_blit.c
> +++ b/src/gallium/drivers/r600/r600_blit.c
> @@ -412,6 +412,55 @@ static boolean is_simple_msaa_resolve(const struct pipe_blit_info *info)
>                 dst_tile_mode >= RADEON_SURF_MODE_1D;
>  }
>
> +static void r600_clear_buffer(struct pipe_context *ctx, struct pipe_resource *dst,
> +                             unsigned offset, unsigned size, unsigned char value);
> +
> +static void eg_set_clear_color(struct pipe_context *ctx,
> +                              struct pipe_surface *cbuf,
> +                              const union pipe_color_union *color)
> +{
> +       struct r600_context *rctx = (struct r600_context *)ctx;
> +       struct pipe_framebuffer_state *fb = &rctx->framebuffer.state;
> +       unsigned *clear_value = ((struct r600_texture *)cbuf->texture)->color_clear_value;
> +       union util_color uc;
> +
> +       memset(&uc, 0, sizeof(uc));
> +       util_pack_color(color->f, fb->cbufs[0]->format, &uc);
> +       memcpy(clear_value, &uc, sizeof(uc.f));
> +}
> +
> +static bool can_fast_clear_color(struct pipe_context *ctx)
> +{
> +       struct r600_context *rctx = (struct r600_context *)ctx;
> +       struct pipe_framebuffer_state *fb = &rctx->framebuffer.state;
> +       int i;
> +
> +       if (rctx->chip_class < EVERGREEN) {
> +               return false;
> +       }
> +
> +       for (i = 0; i < fb->nr_cbufs; i++) {
> +               struct r600_texture *tex = (struct r600_texture *)fb->cbufs[i]->texture;
> +               const struct util_format_description *desc = util_format_description(fb->cbufs[i]->format);
> +
> +               if (tex->cmask_size == 0) {
> +                       return false;
> +               }
> +
> +               /* cannot pack color, needs support in u_format */
> +               if (desc->pack_rgba_float == NULL) {
> +                       return false;
> +               }

Hi Grirogi,

Is this for disallowing integer textures? You probably wanted to use
util_format_is_pure_integer, which is more clear. pack_rgba_float
should be non-NULL for every non-integer format.

Anyway, it should be possible to support integer textures too, though
util_pack_color might need some improvements. If you are convinced
integer textures are not important, it's alright with me.


> +
> +               /* array textures (and cubemaps) are not supported */
> +               if (tex->surface.array_size != 1) {
> +                       return false;
> +               }

Cubemaps have array_size == 1. You need to check the texture target
instead. (The depth clear code seems to have the same bug.)

Marek


More information about the mesa-dev mailing list