[Mesa-dev] [PATCH] r600g: implement fast color clears on evergreen+
Grigori Goronzy
greg at chown.ath.cx
Fri Jun 7 12:44:41 PDT 2013
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.
---
src/gallium/drivers/r600/evergreen_state.c | 8 +++++++-
src/gallium/drivers/r600/r600_blit.c | 29 +++++++++++++++++++++++++++++
src/gallium/drivers/r600/r600_resource.h | 3 +++
3 files changed, 39 insertions(+), 1 deletion(-)
diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c
index 3ebb157..072a365 100644
--- a/src/gallium/drivers/r600/evergreen_state.c
+++ b/src/gallium/drivers/r600/evergreen_state.c
@@ -1584,6 +1584,8 @@ void evergreen_init_color_surface(struct r600_context *rctx,
surf->cb_color_fmask_slice = S_028C88_TILE_MAX(rtex->fmask_slice_tile_max);
surf->cb_color_cmask_slice = S_028C80_TILE_MAX(rtex->cmask_slice_tile_max);
+ surf->cb_color_clear_value = rtex->color_clear_value;
+
surf->color_initialized = true;
}
@@ -2178,7 +2180,7 @@ static void evergreen_emit_framebuffer_state(struct r600_context *rctx, struct r
(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 +2192,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, cb->cb_color_clear_value); /* R_028C8C_CB_COLOR0_CLEAR_WORD0 */
+ r600_write_value(cs, 0); /* R_028C90_CB_COLOR0_CLEAR_WORD1 */
+ r600_write_value(cs, 0); /* R_028C94_CB_COLOR0_CLEAR_WORD2 */
+ r600_write_value(cs, 0); /* 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..2b1b49a 100644
--- a/src/gallium/drivers/r600/r600_blit.c
+++ b/src/gallium/drivers/r600/r600_blit.c
@@ -412,6 +412,23 @@ 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,
+ const union pipe_color_union *color)
+{
+ struct r600_context *rctx = (struct r600_context *)ctx;
+ struct pipe_framebuffer_state *fb = &rctx->framebuffer.state;
+ union util_color uc;
+
+ memset(&uc, 0, sizeof(uc));
+ util_pack_color(color->f, fb->cbufs[0]->format, &uc);
+
+ /* TODO: color formats with more than 32bpp */
+ ((struct r600_texture *)fb->cbufs[0]->texture)->color_clear_value = uc.ui;
+}
+
static void r600_clear(struct pipe_context *ctx, unsigned buffers,
const union pipe_color_union *color,
double depth, unsigned stencil)
@@ -419,6 +436,18 @@ static void r600_clear(struct pipe_context *ctx, unsigned buffers,
struct r600_context *rctx = (struct r600_context *)ctx;
struct pipe_framebuffer_state *fb = &rctx->framebuffer.state;
+ /* fast color clear on AA framebuffers (EG+) */
+ /* TODO: multiple color buffers */
+ if (rctx->chip_class >= EVERGREEN &&
+ (buffers & PIPE_CLEAR_COLOR) && fb->nr_cbufs == 1 &&
+ ((struct r600_texture *)fb->cbufs[0]->texture)->cmask_size) {
+ struct r600_texture *tex = (struct r600_texture *)fb->cbufs[0]->texture;
+ eg_set_clear_color(ctx, color);
+ r600_clear_buffer(ctx, fb->cbufs[0]->texture,
+ tex->cmask_offset, tex->cmask_size, 0);
+ buffers &= ~PIPE_CLEAR_COLOR;
+ }
+
/* if hyperz enabled just clear hyperz */
if (fb->zsbuf && (buffers & PIPE_CLEAR_DEPTH)) {
struct r600_texture *rtex;
diff --git a/src/gallium/drivers/r600/r600_resource.h b/src/gallium/drivers/r600/r600_resource.h
index d5df633..08a3ba7 100644
--- a/src/gallium/drivers/r600/r600_resource.h
+++ b/src/gallium/drivers/r600/r600_resource.h
@@ -91,6 +91,8 @@ struct r600_texture {
struct r600_resource *htile;
/* use htile only for first level */
float depth_clear;
+
+ unsigned color_clear_value;
};
#define R600_TEX_IS_TILED(tex, level) ((tex)->array_mode[level] != V_038000_ARRAY_LINEAR_GENERAL && (tex)->array_mode[level] != V_038000_ARRAY_LINEAR_ALIGNED)
@@ -132,6 +134,7 @@ struct r600_surface {
unsigned cb_color_cmask; /* CB_COLORn_CMASK (EG) or CB_COLORn_TILE (r600) */
unsigned cb_color_cmask_slice; /* EG only */
unsigned cb_color_mask; /* R600 only */
+ unsigned cb_color_clear_value; /* EG only */
struct r600_resource *cb_buffer_fmask; /* Used for FMASK relocations. R600 only */
struct r600_resource *cb_buffer_cmask; /* Used for CMASK relocations. R600 only */
--
1.8.1.2
More information about the mesa-dev
mailing list