[Mesa-dev] [PATCH] r600g: track whether we need to update the shaders (v2)

Bas Nieuwenhuizen bas at basnieuwenhuizen.nl
Wed Oct 6 11:48:50 PDT 2010


The shaders only depend on the shader itself, the vertex_elements state and flatshade and we don't need to emit the registers again if these are not changed. Tracking is also faster
than the memcmp in r600_shader_update, so in some cases that expensive check doesn't have to be performed. I also optimized that expensive check by only looping through the first
count elements, as the other elements don't matter.

Also added an early exit in r600_pipe_shader_ps when only the flatshade state was changed.
---
 src/gallium/drivers/r600/r600_pipe.h   |    6 ++++++
 src/gallium/drivers/r600/r600_shader.c |    7 ++++++-
 src/gallium/drivers/r600/r600_state.c  |   13 ++++++++++---
 3 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h
index c46029a..1a7bf97 100644
--- a/src/gallium/drivers/r600/r600_pipe.h
+++ b/src/gallium/drivers/r600/r600_pipe.h
@@ -92,6 +92,11 @@ struct r600_pipe_shader {
 	struct r600_vertex_element	vertex_elements;
 };
 
+#define DIRTY_SHADER_VS		1
+#define DIRTY_SHADER_PS		2
+#define DIRTY_VERTEX_ELEMENTS	4
+#define DIRTY_FLAT_SHADE	8
+
 struct r600_pipe_context {
 	struct pipe_context		context;
 	struct blitter_context		*blitter;
@@ -130,6 +135,7 @@ struct r600_pipe_context {
 	struct u_upload_mgr		*upload_vb;
 	struct u_upload_mgr		*upload_ib;
 	unsigned			any_user_vbs;
+	unsigned			dirty_flags;
 };
 
 struct r600_drawl {
diff --git a/src/gallium/drivers/r600/r600_shader.c b/src/gallium/drivers/r600/r600_shader.c
index 016e75b..c214256 100644
--- a/src/gallium/drivers/r600/r600_shader.c
+++ b/src/gallium/drivers/r600/r600_shader.c
@@ -131,6 +131,11 @@ static void r600_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shade
 		}
 		r600_pipe_state_add_reg(rstate, R_028644_SPI_PS_INPUT_CNTL_0 + i * 4, tmp, 0xFFFFFFFF, NULL);
 	}
+
+	/* early exit if only flat_shade changed */
+	if(!(rctx->dirty_flags & DIRTY_SHADER_PS))
+		return;
+
 	for (i = 0; i < rshader->noutput; i++) {
 		if (rshader->input[i].name == TGSI_SEMANTIC_POSITION)
 			r600_pipe_state_add_reg(rstate,
@@ -247,7 +252,7 @@ static int r600_shader_update(struct pipe_context *ctx, struct r600_pipe_shader
 		return 0;
 	/* doing a full memcmp fell over the refcount */
 	if ((rshader->vertex_elements.count == rctx->vertex_elements->count) &&
-	    (!memcmp(&rshader->vertex_elements.elements, &rctx->vertex_elements->elements, 32 * sizeof(struct pipe_vertex_element)))) {
+	    (!memcmp(&rshader->vertex_elements.elements, &rctx->vertex_elements->elements, rctx->vertex_elements->count * sizeof(struct pipe_vertex_element)))) {
 		return 0;
 	}
 	rshader->vertex_elements = *rctx->vertex_elements;
diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c
index b55c345..42f10ed 100644
--- a/src/gallium/drivers/r600/r600_state.c
+++ b/src/gallium/drivers/r600/r600_state.c
@@ -79,11 +79,14 @@ static void r600_draw_common(struct r600_drawl *draw)
 
 
 	/* rebuild vertex shader if input format changed */
-	if (r600_pipe_shader_update(&rctx->context, rctx->vs_shader))
+	if ((rctx->dirty_flags & (DIRTY_SHADER_VS | DIRTY_VERTEX_ELEMENTS)) &&
+	    r600_pipe_shader_update(&rctx->context, rctx->vs_shader))
 		return;
-	if (r600_pipe_shader_update(&rctx->context, rctx->ps_shader))
+	if ((rctx->dirty_flags & (DIRTY_SHADER_PS | DIRTY_FLAT_SHADE)) &&
+	    r600_pipe_shader_update(&rctx->context, rctx->ps_shader))
 		return;
 
+	rctx->dirty_flags = 0;
 	for (i = 0 ; i < rctx->vertex_elements->count; i++) {
 		uint32_t word2, format;
 
@@ -516,6 +519,8 @@ static void r600_bind_rs_state(struct pipe_context *ctx, void *state)
 	if (state == NULL)
 		return;
 
+	if(rctx->flatshade != rs->flatshade)
+		rctx->dirty_flags |= DIRTY_FLAT_SHADE;
 	rctx->flatshade = rs->flatshade;
 	rctx->sprite_coord_enable = rs->sprite_coord_enable;
 	rctx->rasterizer = rs;
@@ -801,7 +806,7 @@ static void r600_bind_vertex_elements(struct pipe_context *ctx, void *state)
 	rctx->vertex_elements = v;
 	if (v) {
 		v->refcount++;
-//		rctx->vs_rebuild = TRUE;
+		rctx->dirty_flags |= DIRTY_VERTEX_ELEMENTS;
 	}
 }
 
@@ -1198,6 +1203,7 @@ static void r600_bind_ps_shader(struct pipe_context *ctx, void *state)
 
 	/* TODO delete old shader */
 	rctx->ps_shader = (struct r600_pipe_shader *)state;
+	rctx->dirty_flags |= DIRTY_SHADER_PS;
 }
 
 static void r600_bind_vs_shader(struct pipe_context *ctx, void *state)
@@ -1206,6 +1212,7 @@ static void r600_bind_vs_shader(struct pipe_context *ctx, void *state)
 
 	/* TODO delete old shader */
 	rctx->vs_shader = (struct r600_pipe_shader *)state;
+	rctx->dirty_flags |= DIRTY_SHADER_VS;
 }
 
 static void r600_delete_ps_shader(struct pipe_context *ctx, void *state)
-- 
1.7.1



More information about the mesa-dev mailing list