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

Roland Scheidegger sroland at vmware.com
Mon Jun 10 18:16:11 PDT 2013


Am 11.06.2013 02:41, schrieb Marek Olšák:
> 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.
Yes there's workarounds for not using util_pack_color in llvmpipe too
for integer textures. I was considering if it would be worth extending
it but didn't do it in the end. The problem is at least for OpenGL you'd
also need other input format, not just floats otherwise you won't end up
with exact values for int32 formats (for d3d10 this is actually not a
problem since clear values and the like are always float32 and yes it
means you can't clear int32 formats to an exact value, at least not if
that value is > 2^24).

> 
> 
>> +
>> +               /* 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.)
Or I guess you could take the array_size from the base type if it is
around somewhere - because in gallium cubemaps do have array_size == 6.
(Though I'm not sure if you also need to distinguish "fake" array
textures which were generated as an array texture but with array size 1
from non-array texture.)

Roland


More information about the mesa-dev mailing list