[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