[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