Mesa (master): r600g: avoid useless shader rebuild at draw call

Jerome Glisse glisse at kemper.freedesktop.org
Mon Dec 6 20:54:28 UTC 2010


Module: Mesa
Branch: master
Commit: afc56b1861c1dae4137493af4c0e6dacc6ee41f9
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=afc56b1861c1dae4137493af4c0e6dacc6ee41f9

Author: Jerome Glisse <jglisse at redhat.com>
Date:   Sun Dec  5 19:24:03 2010 -0500

r600g: avoid useless shader rebuild at draw call

Avoid rebuilding constant shader state at each draw call,
factor out spi update that might change at each draw call.
Best would be to update spi only when revealent states
change (likely only flat shading & sprite point).

Signed-off-by: Jerome Glisse <jglisse at redhat.com>

---

 src/gallium/drivers/r600/evergreen_state.c   |   55 ++++++++++++++++++++------
 src/gallium/drivers/r600/r600_pipe.c         |    4 +-
 src/gallium/drivers/r600/r600_shader.c       |   36 ++--------------
 src/gallium/drivers/r600/r600_shader.h       |    1 -
 src/gallium/drivers/r600/r600_state.c        |   50 +++++++++++++++++++++++-
 src/gallium/drivers/r600/r600_state_common.c |    6 +++
 src/gallium/drivers/r600/r600_translate.c    |    3 +
 7 files changed, 108 insertions(+), 47 deletions(-)

diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c
index b313d52..feb30f3 100644
--- a/src/gallium/drivers/r600/evergreen_state.c
+++ b/src/gallium/drivers/r600/evergreen_state.c
@@ -1239,6 +1239,7 @@ void evergreen_polygon_offset_update(struct r600_pipe_context *rctx)
 		default:
 			return;
 		}
+		/* FIXME some of those reg can be computed with cso */
 		offset_db_fmt_cntl |= S_028B78_POLY_OFFSET_NEG_NUM_DB_BITS(depth);
 		r600_pipe_state_add_reg(&state,
 				R_028B80_PA_SU_POLY_OFFSET_FRONT_SCALE,
@@ -1259,6 +1260,30 @@ void evergreen_polygon_offset_update(struct r600_pipe_context *rctx)
 	}
 }
 
+static void evergreen_spi_update(struct r600_pipe_context *rctx)
+{
+	struct r600_pipe_shader *shader = rctx->ps_shader;
+	struct r600_pipe_state rstate;
+	struct r600_shader *rshader = &shader->shader;
+	unsigned i, tmp;
+
+	rstate.nregs = 0;
+	for (i = 0; i < rshader->ninput; i++) {
+		tmp = S_028644_SEMANTIC(r600_find_vs_semantic_index(&rctx->vs_shader->shader, rshader, i));
+		if (rshader->input[i].name == TGSI_SEMANTIC_COLOR ||
+				rshader->input[i].name == TGSI_SEMANTIC_BCOLOR ||
+				rshader->input[i].name == TGSI_SEMANTIC_POSITION) {
+			tmp |= S_028644_FLAT_SHADE(rctx->flatshade);
+		}
+		if (rshader->input[i].name == TGSI_SEMANTIC_GENERIC &&
+			rctx->sprite_coord_enable & (1 << rshader->input[i].sid)) {
+			tmp |= S_028644_PT_SPRITE_TEX(1);
+		}
+		r600_pipe_state_add_reg(&rstate, R_028644_SPI_PS_INPUT_CNTL_0 + i * 4, tmp, 0xFFFFFFFF, NULL);
+	}
+	r600_context_pipe_state_set(&rctx->ctx, &rstate);
+}
+
 void evergreen_vertex_buffer_update(struct r600_pipe_context *rctx)
 {
 	struct r600_pipe_state *rstate;
@@ -1417,12 +1442,30 @@ void evergreen_draw(struct pipe_context *ctx, const struct pipe_draw_info *info)
 	}
 	if (r600_conv_pipe_prim(draw.mode, &prim))
 		return;
+	if (unlikely(rctx->ps_shader == NULL)) {
+		R600_ERR("missing vertex shader\n");
+		return;
+	}
+	if (unlikely(rctx->vs_shader == NULL)) {
+		R600_ERR("missing vertex shader\n");
+		return;
+	}
+	/* there should be enough input */
+	if (rctx->vertex_elements->count < rctx->vs_shader->shader.bc.nresource) {
+		R600_ERR("%d resources provided, expecting %d\n",
+			rctx->vertex_elements->count, rctx->vs_shader->shader.bc.nresource);
+		return;
+	}
 
+#if 0
 	/* rebuild vertex shader if input format changed */
 	if (r600_pipe_shader_update(&rctx->context, rctx->vs_shader))
 		return;
 	if (r600_pipe_shader_update(&rctx->context, rctx->ps_shader))
 		return;
+#endif
+
+	evergreen_spi_update(rctx);
 
 #if 0
 	for (i = 0 ; i < rctx->vertex_elements->count; i++) {
@@ -1506,11 +1549,9 @@ void evergreen_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shader
 	boolean have_linear = FALSE, have_centroid = FALSE, have_perspective = FALSE;
 	unsigned spi_baryc_cntl;
 
-	/* clear previous register */
 	rstate->nregs = 0;
 
 	for (i = 0; i < rshader->ninput; i++) {
-		tmp = S_028644_SEMANTIC(r600_find_vs_semantic_index(&rctx->vs_shader->shader, rshader, i));
 		/* evergreen NUM_INTERP only contains values interpolated into the LDS,
 		   POSITION goes via GPRs from the SC so isn't counted */
 		if (rshader->input[i].name == TGSI_SEMANTIC_POSITION)
@@ -1528,16 +1569,6 @@ void evergreen_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shader
 			if (rshader->input[i].centroid)
 				have_centroid = TRUE;
 		}
-		if (rshader->input[i].name == TGSI_SEMANTIC_COLOR ||
-		    rshader->input[i].name == TGSI_SEMANTIC_BCOLOR ||
-		    rshader->input[i].name == TGSI_SEMANTIC_POSITION) {
-			tmp |= S_028644_FLAT_SHADE(rshader->flat_shade);
-		}
-		if (rshader->input[i].name == TGSI_SEMANTIC_GENERIC &&
-			rctx->sprite_coord_enable & (1 << rshader->input[i].sid)) {
-			tmp |= S_028644_PT_SPRITE_TEX(1);
-		}
-		r600_pipe_state_add_reg(rstate, R_028644_SPI_PS_INPUT_CNTL_0 + i * 4, tmp, 0xFFFFFFFF, NULL);
 	}
 	for (i = 0; i < rshader->noutput; i++) {
 		if (rshader->output[i].name == TGSI_SEMANTIC_POSITION)
diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c
index ea57fba..6842571 100644
--- a/src/gallium/drivers/r600/r600_pipe.c
+++ b/src/gallium/drivers/r600/r600_pipe.c
@@ -79,6 +79,8 @@ static void r600_destroy_context(struct pipe_context *context)
 
 	rctx->context.delete_depth_stencil_alpha_state(&rctx->context, rctx->custom_dsa_flush);
 
+	r600_end_vertex_translate(rctx);
+
 	r600_context_fini(&rctx->ctx);
 
 	util_blitter_destroy(rctx->blitter);
@@ -90,8 +92,6 @@ static void r600_destroy_context(struct pipe_context *context)
 	u_upload_destroy(rctx->upload_vb);
 	u_upload_destroy(rctx->upload_ib);
 
-	r600_end_vertex_translate(rctx);
-
 	if (rctx->tran.translate_cache)
 		translate_cache_destroy(rctx->tran.translate_cache);
 
diff --git a/src/gallium/drivers/r600/r600_shader.c b/src/gallium/drivers/r600/r600_shader.c
index e40cd1d..ab401e0 100644
--- a/src/gallium/drivers/r600/r600_shader.c
+++ b/src/gallium/drivers/r600/r600_shader.c
@@ -44,6 +44,9 @@ static void r600_pipe_shader_vs(struct pipe_context *ctx, struct r600_pipe_shade
 	rstate->nregs = 0;
 
 	/* so far never got proper semantic id from tgsi */
+	/* FIXME better to move this in config things so they get emited
+	 * only one time per cs
+	 */
 	for (i = 0; i < 10; i++) {
 		spi_vs_out_id[i] = 0;
 	}
@@ -112,31 +115,15 @@ static void r600_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shade
 	unsigned i, tmp, exports_ps, num_cout, spi_ps_in_control_0, spi_input_z, spi_ps_in_control_1;
 	int pos_index = -1, face_index = -1;
 
-	/* clear previous register */
 	rstate->nregs = 0;
 
 	for (i = 0; i < rshader->ninput; i++) {
-		tmp = S_028644_SEMANTIC(r600_find_vs_semantic_index(&rctx->vs_shader->shader, rshader, i));
-		if (rshader->input[i].centroid)
-			tmp |= S_028644_SEL_CENTROID(1);
-		if (rshader->input[i].interpolate == TGSI_INTERPOLATE_LINEAR)
-			tmp |= S_028644_SEL_LINEAR(1);
-
 		if (rshader->input[i].name == TGSI_SEMANTIC_POSITION)
 			pos_index = i;
-		if (rshader->input[i].name == TGSI_SEMANTIC_COLOR ||
-		    rshader->input[i].name == TGSI_SEMANTIC_BCOLOR ||
-		    rshader->input[i].name == TGSI_SEMANTIC_POSITION) {
-			tmp |= S_028644_FLAT_SHADE(rshader->flat_shade);
-		}
 		if (rshader->input[i].name == TGSI_SEMANTIC_FACE)
 			face_index = i;
-		if (rshader->input[i].name == TGSI_SEMANTIC_GENERIC &&
-			rctx->sprite_coord_enable & (1 << rshader->input[i].sid)) {
-			tmp |= S_028644_PT_SPRITE_TEX(1);
-		}
-		r600_pipe_state_add_reg(rstate, R_028644_SPI_PS_INPUT_CNTL_0 + i * 4, tmp, 0xFFFFFFFF, NULL);
 	}
+
 	for (i = 0; i < rshader->noutput; i++) {
 		if (rshader->output[i].name == TGSI_SEMANTIC_POSITION)
 			r600_pipe_state_add_reg(rstate,
@@ -238,7 +225,6 @@ static int r600_pipe_shader(struct pipe_context *ctx, struct r600_pipe_shader *s
 		r600_bo_unmap(rctx->radeon, shader->bo);
 	}
 	/* build state */
-	rshader->flat_shade = rctx->flatshade;
 	switch (rshader->processor_type) {
 	case TGSI_PROCESSOR_VERTEX:
 		if (rshader->family >= CHIP_CEDAR) {
@@ -257,7 +243,6 @@ static int r600_pipe_shader(struct pipe_context *ctx, struct r600_pipe_shader *s
 	default:
 		return -EINVAL;
 	}
-	r600_context_pipe_state_set(&rctx->ctx, &shader->rstate);
 	return 0;
 }
 
@@ -317,17 +302,6 @@ int r600_pipe_shader_update(struct pipe_context *ctx, struct r600_pipe_shader *s
 	struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx;
 	int r;
 
-	if (shader == NULL)
-		return -EINVAL;
-	/* there should be enough input */
-	if (rctx->vertex_elements->count < shader->shader.bc.nresource) {
-		R600_ERR("%d resources provided, expecting %d\n",
-			rctx->vertex_elements->count, shader->shader.bc.nresource);
-		return -EINVAL;
-	}
-	r = r600_shader_update(ctx, shader);
-	if (r)
-		return r;
 	return r600_pipe_shader(ctx, shader);
 }
 
@@ -359,7 +333,7 @@ int r600_pipe_shader_create(struct pipe_context *ctx, struct r600_pipe_shader *s
 	}
 //r600_bc_dump(&shader->shader.bc);
 //fprintf(stderr, "______________________________________________________________\n");
-	return 0;
+	return r600_pipe_shader(ctx, shader);
 }
 
 void
diff --git a/src/gallium/drivers/r600/r600_shader.h b/src/gallium/drivers/r600/r600_shader.h
index cd108da..e8742b5 100644
--- a/src/gallium/drivers/r600/r600_shader.h
+++ b/src/gallium/drivers/r600/r600_shader.h
@@ -38,7 +38,6 @@ struct r600_shader_io {
 struct r600_shader {
 	unsigned		processor_type;
 	struct r600_bc		bc;
-	boolean			flat_shade;
 	unsigned		ninput;
 	unsigned		noutput;
 	unsigned		nlds;
diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c
index 9b70942..2ba15b8 100644
--- a/src/gallium/drivers/r600/r600_state.c
+++ b/src/gallium/drivers/r600/r600_state.c
@@ -74,6 +74,7 @@ void r600_polygon_offset_update(struct r600_pipe_context *rctx)
 		default:
 			return;
 		}
+		/* FIXME some of those reg can be computed with cso */
 		offset_db_fmt_cntl |= S_028DF8_POLY_OFFSET_NEG_NUM_DB_BITS(depth);
 		r600_pipe_state_add_reg(&state,
 				R_028E00_PA_SU_POLY_OFFSET_FRONT_SCALE,
@@ -94,6 +95,36 @@ void r600_polygon_offset_update(struct r600_pipe_context *rctx)
 	}
 }
 
+/* FIXME optimize away spi update when it's not needed */
+static void r600_spi_update(struct r600_pipe_context *rctx)
+{
+	struct r600_pipe_shader *shader = rctx->ps_shader;
+	struct r600_pipe_state rstate;
+	struct r600_shader *rshader = &shader->shader;
+	unsigned i, tmp;
+
+	rstate.nregs = 0;
+	for (i = 0; i < rshader->ninput; i++) {
+		tmp = S_028644_SEMANTIC(r600_find_vs_semantic_index(&rctx->vs_shader->shader, rshader, i));
+		if (rshader->input[i].centroid)
+			tmp |= S_028644_SEL_CENTROID(1);
+		if (rshader->input[i].interpolate == TGSI_INTERPOLATE_LINEAR)
+			tmp |= S_028644_SEL_LINEAR(1);
+
+		if (rshader->input[i].name == TGSI_SEMANTIC_COLOR ||
+		    rshader->input[i].name == TGSI_SEMANTIC_BCOLOR ||
+		    rshader->input[i].name == TGSI_SEMANTIC_POSITION) {
+			tmp |= S_028644_FLAT_SHADE(rctx->flatshade);
+		}
+		if (rshader->input[i].name == TGSI_SEMANTIC_GENERIC &&
+			rctx->sprite_coord_enable & (1 << rshader->input[i].sid)) {
+			tmp |= S_028644_PT_SPRITE_TEX(1);
+		}
+		r600_pipe_state_add_reg(&rstate, R_028644_SPI_PS_INPUT_CNTL_0 + i * 4, tmp, 0xFFFFFFFF, NULL);
+	}
+	r600_context_pipe_state_set(&rctx->ctx, &rstate);
+}
+
 void r600_vertex_buffer_update(struct r600_pipe_context *rctx)
 {
 	struct r600_pipe_state *rstate;
@@ -202,13 +233,30 @@ static void r600_draw_common(struct r600_drawl *draw)
 	}
 	if (r600_conv_pipe_prim(draw->mode, &prim))
 		return;
+	if (unlikely(rctx->ps_shader == NULL)) {
+		R600_ERR("missing vertex shader\n");
+		return;
+	}
+	if (unlikely(rctx->vs_shader == NULL)) {
+		R600_ERR("missing vertex shader\n");
+		return;
+	}
+	/* there should be enough input */
+	if (rctx->vertex_elements->count < rctx->vs_shader->shader.bc.nresource) {
+		R600_ERR("%d resources provided, expecting %d\n",
+			rctx->vertex_elements->count, rctx->vs_shader->shader.bc.nresource);
+		return;
+	}
 
-
+#if 0
 	/* rebuild vertex shader if input format changed */
 	if (r600_pipe_shader_update(&rctx->context, rctx->vs_shader))
 		return;
 	if (r600_pipe_shader_update(&rctx->context, rctx->ps_shader))
 		return;
+#endif
+
+	r600_spi_update(rctx);
 
 #if 0
 	for (i = 0 ; i < rctx->vertex_elements->count; i++) {
diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c
index 8894327..c647e77 100644
--- a/src/gallium/drivers/r600/r600_state_common.c
+++ b/src/gallium/drivers/r600/r600_state_common.c
@@ -269,6 +269,9 @@ void r600_bind_ps_shader(struct pipe_context *ctx, void *state)
 
 	/* TODO delete old shader */
 	rctx->ps_shader = (struct r600_pipe_shader *)state;
+	if (state) {
+		r600_context_pipe_state_set(&rctx->ctx, &rctx->ps_shader->rstate);
+	}
 }
 
 void r600_bind_vs_shader(struct pipe_context *ctx, void *state)
@@ -277,6 +280,9 @@ void r600_bind_vs_shader(struct pipe_context *ctx, void *state)
 
 	/* TODO delete old shader */
 	rctx->vs_shader = (struct r600_pipe_shader *)state;
+	if (state) {
+		r600_context_pipe_state_set(&rctx->ctx, &rctx->vs_shader->rstate);
+	}
 }
 
 void r600_delete_ps_shader(struct pipe_context *ctx, void *state)
diff --git a/src/gallium/drivers/r600/r600_translate.c b/src/gallium/drivers/r600/r600_translate.c
index d927f53..1c227d3 100644
--- a/src/gallium/drivers/r600/r600_translate.c
+++ b/src/gallium/drivers/r600/r600_translate.c
@@ -169,6 +169,9 @@ void r600_end_vertex_translate(struct r600_pipe_context *rctx)
 {
 	struct pipe_context *pipe = &rctx->context;
 
+	if (rctx->tran.new_velems == NULL) {
+		return;
+	}
 	/* Restore vertex elements. */
 	if (rctx->vertex_elements == rctx->tran.new_velems) {
 		pipe->bind_vertex_elements_state(pipe, NULL);




More information about the mesa-commit mailing list