[Mesa-dev] [PATCH] r600g: use dirty list to track dirty blocks

Bas Nieuwenhuizen bas at basnieuwenhuizen.nl
Tue Oct 5 12:01:43 PDT 2010


Got a speed up by tracking the dirty blocks in a seperate list instead of looping through all blocks. This version should work with block that get their dirty state disabled again and I added a dirty check during the flush as some blocks were already dirty.
---
 src/gallium/drivers/r600/r600.h                    |    2 ++
 src/gallium/winsys/r600/drm/evergreen_hw_context.c |   18 ++++++++++++++----
 src/gallium/winsys/r600/drm/r600_hw_context.c      |   20 ++++++++++++++++----
 src/gallium/winsys/r600/drm/r600_priv.h            |    1 +
 4 files changed, 33 insertions(+), 8 deletions(-)

diff --git a/src/gallium/drivers/r600/r600.h b/src/gallium/drivers/r600/r600.h
index 59a255d..acacec0 100644
--- a/src/gallium/drivers/r600/r600.h
+++ b/src/gallium/drivers/r600/r600.h
@@ -160,6 +160,7 @@ struct r600_block_reloc {
 };
 
 struct r600_block {
+	struct list_head	list;
 	unsigned		status;
 	unsigned		start_offset;
 	unsigned		pm4_ndwords;
@@ -221,6 +222,7 @@ struct r600_context {
 	struct r600_range	range[256];
 	unsigned		nblocks;
 	struct r600_block	**blocks;
+	struct list_head	dirty;
 	unsigned		pm4_ndwords;
 	unsigned		pm4_cdwords;
 	unsigned		pm4_dirty_cdwords;
diff --git a/src/gallium/winsys/r600/drm/evergreen_hw_context.c b/src/gallium/winsys/r600/drm/evergreen_hw_context.c
index 96769ad..1355b07 100644
--- a/src/gallium/winsys/r600/drm/evergreen_hw_context.c
+++ b/src/gallium/winsys/r600/drm/evergreen_hw_context.c
@@ -613,6 +613,9 @@ int evergreen_context_init(struct r600_context *ctx, struct radeon *radeon)
 		r = -ENOMEM;
 		goto out_err;
 	}
+
+	/* init dirty list */
+	LIST_INITHEAD(&ctx->dirty);
 	return 0;
 out_err:
 	r600_context_fini(ctx);
@@ -630,6 +633,7 @@ static inline void evergreen_context_pipe_state_set_resource(struct r600_context
 		block->status &= ~(R600_BLOCK_STATUS_ENABLED | R600_BLOCK_STATUS_DIRTY);
 		r600_bo_reference(ctx->radeon, &block->reloc[1].bo, NULL);
 		r600_bo_reference(ctx->radeon , &block->reloc[2].bo, NULL);
+		LIST_DEL(&block->list);
 		return;
 	}
 	block->reg[0] = state->regs[0].value;
@@ -657,6 +661,7 @@ static inline void evergreen_context_pipe_state_set_resource(struct r600_context
 		block->status |= R600_BLOCK_STATUS_ENABLED;
 		block->status |= R600_BLOCK_STATUS_DIRTY;
 		ctx->pm4_dirty_cdwords += block->pm4_ndwords + block->pm4_flush_ndwords;
+		LIST_ADDTAIL(&block->list,&ctx->dirty);
 	}
 }
 
@@ -683,6 +688,7 @@ static inline void evergreen_context_pipe_state_set_sampler(struct r600_context
 	block = range->blocks[CTX_BLOCK_ID(ctx, offset)];
 	if (state == NULL) {
 		block->status &= ~(R600_BLOCK_STATUS_ENABLED | R600_BLOCK_STATUS_DIRTY);
+		LIST_DEL(&block->list);
 		return;
 	}
 	block->reg[0] = state->regs[0].value;
@@ -692,6 +698,7 @@ static inline void evergreen_context_pipe_state_set_sampler(struct r600_context
 		block->status |= R600_BLOCK_STATUS_ENABLED;
 		block->status |= R600_BLOCK_STATUS_DIRTY;
 		ctx->pm4_dirty_cdwords += block->pm4_ndwords + block->pm4_flush_ndwords;
+		LIST_ADDTAIL(&block->list,&ctx->dirty);
 	}
 }
 
@@ -705,6 +712,7 @@ static inline void evergreen_context_pipe_state_set_sampler_border(struct r600_c
 	block = range->blocks[CTX_BLOCK_ID(ctx, fake_offset)];
 	if (state == NULL) {
 		block->status &= ~(R600_BLOCK_STATUS_ENABLED | R600_BLOCK_STATUS_DIRTY);
+		LIST_DEL(&block->list);
 		return;
 	}
 	if (state->nregs <= 3) {
@@ -719,6 +727,7 @@ static inline void evergreen_context_pipe_state_set_sampler_border(struct r600_c
 		block->status |= R600_BLOCK_STATUS_ENABLED;
 		block->status |= R600_BLOCK_STATUS_DIRTY;
 		ctx->pm4_dirty_cdwords += block->pm4_ndwords + block->pm4_flush_ndwords;
+		LIST_ADDTAIL(&block->list,&ctx->dirty);
 	}
 }
 
@@ -746,6 +755,7 @@ void evergreen_context_draw(struct r600_context *ctx, const struct r600_draw *dr
 	struct r600_bo *cb[12];
 	struct r600_bo *db;
 	unsigned ndwords = 9, flush;
+	struct r600_block *dirty_block;
 
 	if (draw->indices) {
 		ndwords = 13;
@@ -800,11 +810,10 @@ void evergreen_context_draw(struct r600_context *ctx, const struct r600_draw *dr
 	}
 
 	/* enough room to copy packet */
-	for (int i = 0; i < ctx->nblocks; i++) {
-		if (ctx->blocks[i]->status & R600_BLOCK_STATUS_DIRTY) {
-			r600_context_block_emit_dirty(ctx, ctx->blocks[i]);
-		}
+	LIST_FOR_EACH_ENTRY(dirty_block,&ctx->dirty,list) {
+		r600_context_block_emit_dirty(ctx, dirty_block);
 	}
+	LIST_INITHEAD(&ctx->dirty);
 
 	/* draw packet */
 	ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_INDEX_TYPE, 0);
@@ -884,6 +893,7 @@ static inline void evergreen_resource_set(struct r600_context *ctx, struct r600_
 		block->status |= R600_BLOCK_STATUS_ENABLED;
 		block->status |= R600_BLOCK_STATUS_DIRTY;
 		ctx->pm4_dirty_cdwords += block->pm4_ndwords + block->pm4_flush_ndwords;
+		LIST_ADDTAIL(&block->list,&ctx->dirty);
 	}
 }
 
diff --git a/src/gallium/winsys/r600/drm/r600_hw_context.c b/src/gallium/winsys/r600/drm/r600_hw_context.c
index 84539d1..5019c26 100644
--- a/src/gallium/winsys/r600/drm/r600_hw_context.c
+++ b/src/gallium/winsys/r600/drm/r600_hw_context.c
@@ -691,6 +691,9 @@ int r600_context_init(struct r600_context *ctx, struct radeon *radeon)
 		r = -ENOMEM;
 		goto out_err;
 	}
+
+	/* init dirty list */
+	LIST_INITHEAD(&ctx->dirty);
 	return 0;
 out_err:
 	r600_context_fini(ctx);
@@ -762,6 +765,7 @@ void r600_context_pipe_state_set(struct r600_context *ctx, struct r600_pipe_stat
 			block->status |= R600_BLOCK_STATUS_ENABLED;
 			block->status |= R600_BLOCK_STATUS_DIRTY;
 			ctx->pm4_dirty_cdwords += block->pm4_ndwords + block->pm4_flush_ndwords;
+			LIST_ADDTAIL(&block->list,&ctx->dirty);
 		}
 	}
 }
@@ -777,6 +781,7 @@ static inline void r600_context_pipe_state_set_resource(struct r600_context *ctx
 		block->status &= ~(R600_BLOCK_STATUS_ENABLED | R600_BLOCK_STATUS_DIRTY);
 		r600_bo_reference(ctx->radeon, &block->reloc[1].bo, NULL);
 		r600_bo_reference(ctx->radeon , &block->reloc[2].bo, NULL);
+		LIST_DEL(&block->list);
 		return;
 	}
 	block->reg[0] = state->regs[0].value;
@@ -803,6 +808,7 @@ static inline void r600_context_pipe_state_set_resource(struct r600_context *ctx
 		block->status |= R600_BLOCK_STATUS_ENABLED;
 		block->status |= R600_BLOCK_STATUS_DIRTY;
 		ctx->pm4_dirty_cdwords += block->pm4_ndwords + block->pm4_flush_ndwords;
+		LIST_ADDTAIL(&block->list,&ctx->dirty);
 	}
 }
 
@@ -829,6 +835,7 @@ static inline void r600_context_pipe_state_set_sampler(struct r600_context *ctx,
 	block = range->blocks[CTX_BLOCK_ID(ctx, offset)];
 	if (state == NULL) {
 		block->status &= ~(R600_BLOCK_STATUS_ENABLED | R600_BLOCK_STATUS_DIRTY);
+		LIST_DEL(&block->list);
 		return;
 	}
 	block->reg[0] = state->regs[0].value;
@@ -838,6 +845,7 @@ static inline void r600_context_pipe_state_set_sampler(struct r600_context *ctx,
 		block->status |= R600_BLOCK_STATUS_ENABLED;
 		block->status |= R600_BLOCK_STATUS_DIRTY;
 		ctx->pm4_dirty_cdwords += block->pm4_ndwords + block->pm4_flush_ndwords;
+		LIST_ADDTAIL(&block->list,&ctx->dirty);
 	}
 }
 
@@ -850,6 +858,7 @@ static inline void r600_context_pipe_state_set_sampler_border(struct r600_contex
 	block = range->blocks[CTX_BLOCK_ID(ctx, offset)];
 	if (state == NULL) {
 		block->status &= ~(R600_BLOCK_STATUS_ENABLED | R600_BLOCK_STATUS_DIRTY);
+		LIST_DEL(&block->list);
 		return;
 	}
 	if (state->nregs <= 3) {
@@ -863,6 +872,7 @@ static inline void r600_context_pipe_state_set_sampler_border(struct r600_contex
 		block->status |= R600_BLOCK_STATUS_ENABLED;
 		block->status |= R600_BLOCK_STATUS_DIRTY;
 		ctx->pm4_dirty_cdwords += block->pm4_ndwords + block->pm4_flush_ndwords;
+		LIST_ADDTAIL(&block->list,&ctx->dirty);
 	}
 }
 
@@ -907,6 +917,7 @@ void r600_context_draw(struct r600_context *ctx, const struct r600_draw *draw)
 	struct r600_bo *cb[8];
 	struct r600_bo *db;
 	unsigned ndwords = 9;
+	struct r600_block *dirty_block;
 
 	if (draw->indices) {
 		ndwords = 13;
@@ -959,11 +970,10 @@ void r600_context_draw(struct r600_context *ctx, const struct r600_draw *draw)
 	}
 
 	/* enough room to copy packet */
-	for (int i = 0; i < ctx->nblocks; i++) {
-		if (ctx->blocks[i]->status & R600_BLOCK_STATUS_DIRTY) {
-			r600_context_block_emit_dirty(ctx, ctx->blocks[i]);
-		}
+	LIST_FOR_EACH_ENTRY(dirty_block,&ctx->dirty,list) {
+		r600_context_block_emit_dirty(ctx, dirty_block);
 	}
+	LIST_INITHEAD(&ctx->dirty);
 
 	/* draw packet */
 	ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_INDEX_TYPE, 0);
@@ -1052,6 +1062,8 @@ void r600_context_flush(struct r600_context *ctx)
 	 */
 	for (int i = 0; i < ctx->nblocks; i++) {
 		if (ctx->blocks[i]->status & R600_BLOCK_STATUS_ENABLED) {
+			if(!(ctx->blocks[i]->status & R600_BLOCK_STATUS_DIRTY))
+				LIST_ADDTAIL(&ctx->blocks[i]->list,&ctx->dirty);
 			ctx->pm4_dirty_cdwords += ctx->blocks[i]->pm4_ndwords + ctx->blocks[i]->pm4_flush_ndwords;
 			ctx->blocks[i]->status |= R600_BLOCK_STATUS_DIRTY;
 		}
diff --git a/src/gallium/winsys/r600/drm/r600_priv.h b/src/gallium/winsys/r600/drm/r600_priv.h
index f6ceb0a..9a38cc5 100644
--- a/src/gallium/winsys/r600/drm/r600_priv.h
+++ b/src/gallium/winsys/r600/drm/r600_priv.h
@@ -137,6 +137,7 @@ static void inline r600_context_reg(struct r600_context *ctx,
 		ctx->pm4_dirty_cdwords += block->pm4_ndwords;
 		block->status |= R600_BLOCK_STATUS_ENABLED;
 		block->status |= R600_BLOCK_STATUS_DIRTY;
+		LIST_ADDTAIL(&block->list,&ctx->dirty);
 	}
 }
 
-- 
1.7.1



More information about the mesa-dev mailing list