[Mesa-dev] [PATCH 6/7] radeonsi: implement fast color clear

From: Marek Olšák <marek.olsak at amd.com> This works for both multi-sample and single-sample color buffers. --- src/gallium/drivers/radeon/r600_texture.c | 6 ++++- src/gallium/drivers/radeonsi/si_blit.c | 38 +++++++++++++++++++++++++++++-- src/gallium/drivers/radeonsi/si_pipe.c | 1 + src/gallium/drivers/radeonsi/si_pipe.h | 1 + src/gallium/drivers/radeonsi/si_state.c | 17 +++++++++++++- 5 files changed, 59 insertions(+), 4 deletions(-) diff --git a/src/gallium/drivers/radeon/r600_texture.c b/src/gallium/drivers/radeon/r600_texture.c index 837e97e..e3b918e 100644 --- a/src/gallium/drivers/radeon/r600_texture.c +++ b/src/gallium/drivers/radeon/r600_texture.c @@ -458,7 +458,11 @@ static void r600_texture_alloc_cmask_separate(struct r600_common_screen *rscreen assert(rtex->cmask.size == 0); - r600_texture_get_cmask_info(rscreen, rtex, &rtex->cmask); + if (rscreen->chip_class >= SI) { + si_texture_get_cmask_info(rscreen, rtex, &rtex->cmask); + } else { + r600_texture_get_cmask_info(rscreen, rtex, &rtex->cmask); + } rtex->cmask_buffer = (struct r600_resource *) pipe_buffer_create(&rscreen->b, PIPE_BIND_CUSTOM, diff --git a/src/gallium/drivers/radeonsi/si_blit.c b/src/gallium/drivers/radeonsi/si_blit.c index dd303c8..6bc89ab 100644 --- a/src/gallium/drivers/radeonsi/si_blit.c +++ b/src/gallium/drivers/radeonsi/si_blit.c @@ -277,7 +277,8 @@ static void si_blit_decompress_color(struct pipe_context *ctx, si_blitter_begin(ctx, SI_DECOMPRESS); util_blitter_custom_color(sctx->blitter, cbsurf, - sctx->custom_blend_decompress); + rtex->fmask.size ? sctx->custom_blend_decompress : + sctx->custom_blend_fastclear); si_blitter_end(ctx); pipe_surface_reference(&cbsurf, NULL); @@ -322,6 +323,31 @@ static void si_clear(struct pipe_context *ctx, unsigned buffers, struct si_context *sctx = (struct si_context *)ctx; struct pipe_framebuffer_state *fb = &sctx->framebuffer.state; + if (buffers & PIPE_CLEAR_COLOR) { + evergreen_do_fast_color_clear(&sctx->b, fb, &sctx->framebuffer.atom, + &buffers, color); + } + + if (buffers & PIPE_CLEAR_COLOR) { + int i; + + /* These buffers cannot use fast clear, make sure to disable expansion. */ + for (i = 0; i < fb->nr_cbufs; i++) { + struct r600_texture *tex; + + /* If not clearing this buffer, skip. */ + if (!(buffers & (PIPE_CLEAR_COLOR0 << i))) + continue; + + if (!fb->cbufs[i]) + continue; + + tex = (struct r600_texture *)fb->cbufs[i]->texture; + if (tex->fmask.size == 0) + tex->dirty_level_mask &= ~(1 << fb->cbufs[i]->u.tex.level); + } + } + si_blitter_begin(ctx, SI_CLEAR); util_blitter_clear(sctx->blitter, fb->width, fb->height, util_framebuffer_get_num_layers(fb), @@ -700,8 +726,16 @@ static void si_blit(struct pipe_context *ctx, } static void si_flush_resource(struct pipe_context *ctx, - struct pipe_resource *resource) + struct pipe_resource *res) { + struct r600_texture *rtex = (struct r600_texture*)res; + + assert(res->target != PIPE_BUFFER); + + if (!rtex->is_depth && rtex->cmask.size) { + si_blit_decompress_color(ctx, rtex, 0, res->last_level, + 0, res->array_size - 1); + } } void si_init_blit_functions(struct si_context *sctx) diff --git a/src/gallium/drivers/radeonsi/si_pipe.c b/src/gallium/drivers/radeonsi/si_pipe.c index 2a256d3..cab6584 100644 --- a/src/gallium/drivers/radeonsi/si_pipe.c +++ b/src/gallium/drivers/radeonsi/si_pipe.c @@ -104,6 +104,7 @@ static void si_destroy_context(struct pipe_context *context) sctx->b.b.delete_depth_stencil_alpha_state(&sctx->b.b, sctx->custom_dsa_flush_inplace); sctx->b.b.delete_blend_state(&sctx->b.b, sctx->custom_blend_resolve); sctx->b.b.delete_blend_state(&sctx->b.b, sctx->custom_blend_decompress); + sctx->b.b.delete_blend_state(&sctx->b.b, sctx->custom_blend_fastclear); util_unreference_framebuffer_state(&sctx->framebuffer.state); util_blitter_destroy(sctx->blitter); diff --git a/src/gallium/drivers/radeonsi/si_pipe.h b/src/gallium/drivers/radeonsi/si_pipe.h index c66c88e..e8aa13e 100644 --- a/src/gallium/drivers/radeonsi/si_pipe.h +++ b/src/gallium/drivers/radeonsi/si_pipe.h @@ -95,6 +95,7 @@ struct si_context { void *custom_dsa_flush_inplace; void *custom_blend_resolve; void *custom_blend_decompress; + void *custom_blend_fastclear; struct si_screen *screen; union { diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c index 597fee6..4094421 100644 --- a/src/gallium/drivers/radeonsi/si_state.c +++ b/src/gallium/drivers/radeonsi/si_state.c @@ -1667,6 +1667,20 @@ static void si_initialize_color_surface(struct si_context *sctx, if (rtex->fmask.size) { surf->cb_color_fmask = (offset + rtex->fmask.offset) >> 8; surf->cb_color_fmask_slice = S_028C88_TILE_MAX(rtex->fmask.slice_tile_max); + } else { + /* This must be set for fast clear to work without FMASK. */ + surf->cb_color_fmask = surf->cb_color_base; + surf->cb_color_fmask_slice = surf->cb_color_slice; + surf->cb_color_attrib |= S_028C74_FMASK_TILE_MODE_INDEX(tile_mode_index); + + if (sctx->b.chip_class == SI) { + unsigned bankh = util_logbase2(rtex->surface.bankh); + surf->cb_color_attrib |= S_028C74_FMASK_BANK_HEIGHT(bankh); + } + + if (sctx->b.chip_class >= CIK) { + surf->cb_color_pitch |= S_028C64_FMASK_TILE_MAX(pitch); + } } /* Determine pixel shader export format */ @@ -1866,7 +1880,7 @@ static void si_set_framebuffer_state(struct pipe_context *ctx, sctx->framebuffer.export_16bpc |= 1 << i; } - if (rtex->fmask.size || rtex->cmask.size) { + if (rtex->fmask.size && rtex->cmask.size) { sctx->framebuffer.compressed_cb_mask |= 1 << i; } } @@ -2957,6 +2971,7 @@ void si_init_state_functions(struct si_context *sctx) sctx->custom_dsa_flush_inplace = si_create_db_flush_dsa(sctx, false, false, 0); sctx->custom_blend_resolve = si_create_blend_custom(sctx, V_028808_CB_RESOLVE); sctx->custom_blend_decompress = si_create_blend_custom(sctx, V_028808_CB_FMASK_DECOMPRESS); + sctx->custom_blend_fastclear = si_create_blend_custom(sctx, V_028808_CB_ELIMINATE_FAST_CLEAR); sctx->b.b.set_clip_state = si_set_clip_state; sctx->b.b.set_scissor_states = si_set_scissor_states; -- 1.8.3.2