[Mesa-dev] [PATCH 2/3] r600g: also flush read caches if currently in use

Bas Nieuwenhuizen bas at basnieuwenhuizen.nl
Wed Apr 13 11:36:16 PDT 2011


If a resource isn't set again during a draw and the previous draw had it as colorbuffer, then the read caches wouldn't get invalidated. This hasn't surfaced as a bug yet because all
resources are set again due to dirty marking with many false positives.

It currently flushes all read caches, because tracking which we exactly need is going to be a world of pain.
---
 src/gallium/winsys/r600/drm/evergreen_hw_context.c |   32 ++++++++++------
 src/gallium/winsys/r600/drm/r600_hw_context.c      |   38 +++++++++++--------
 src/gallium/winsys/r600/drm/r600_priv.h            |    7 ++++
 3 files changed, 49 insertions(+), 28 deletions(-)

diff --git a/src/gallium/winsys/r600/drm/evergreen_hw_context.c b/src/gallium/winsys/r600/drm/evergreen_hw_context.c
index 66398af..fcf73f8 100644
--- a/src/gallium/winsys/r600/drm/evergreen_hw_context.c
+++ b/src/gallium/winsys/r600/drm/evergreen_hw_context.c
@@ -642,8 +642,8 @@ static inline void evergreen_context_pipe_state_set_resource(struct r600_context
 	block = range->blocks[CTX_BLOCK_ID(ctx, offset)];
 	if (state == NULL) {
 		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);
+		r600_block_bo_reference(ctx->radeon, &block->reloc[1].bo, NULL);
+		r600_block_bo_reference(ctx->radeon , &block->reloc[2].bo, NULL);
 		LIST_DELINIT(&block->list);
 		return;
 	}
@@ -655,18 +655,17 @@ static inline void evergreen_context_pipe_state_set_resource(struct r600_context
 	block->reg[5] = state->regs[5].value;
 	block->reg[6] = state->regs[6].value;
 	block->reg[7] = state->regs[7].value;
-	r600_bo_reference(ctx->radeon, &block->reloc[1].bo, NULL);
-	r600_bo_reference(ctx->radeon , &block->reloc[2].bo, NULL);
+
 	if (state->regs[0].bo) {
 		/* VERTEX RESOURCE, we preted there is 2 bo to relocate so
 		 * we have single case btw VERTEX & TEXTURE resource
 		 */
-		r600_bo_reference(ctx->radeon, &block->reloc[1].bo, state->regs[0].bo);
-		r600_bo_reference(ctx->radeon, &block->reloc[2].bo, state->regs[0].bo);
+		r600_block_bo_reference(ctx->radeon, &block->reloc[1].bo, state->regs[0].bo);
+		r600_block_bo_reference(ctx->radeon, &block->reloc[2].bo, state->regs[0].bo);
 	} else {
 		/* TEXTURE RESOURCE */
-		r600_bo_reference(ctx->radeon, &block->reloc[1].bo, state->regs[2].bo);
-		r600_bo_reference(ctx->radeon, &block->reloc[2].bo, state->regs[3].bo);
+		r600_block_bo_reference(ctx->radeon, &block->reloc[1].bo, state->regs[2].bo);
+		r600_block_bo_reference(ctx->radeon, &block->reloc[2].bo, state->regs[3].bo);
 	}
 	if (!(block->status & R600_BLOCK_STATUS_DIRTY)) {
 		block->status |= R600_BLOCK_STATUS_ENABLED;
@@ -772,6 +771,7 @@ void evergreen_context_draw(struct r600_context *ctx, const struct r600_draw *dr
 {
 	struct r600_bo *cb[12];
 	struct r600_bo *db;
+	struct r600_bo *sb;
 	unsigned ndwords = 9, flush;
 	struct r600_block *dirty_block = NULL;
 	struct r600_block *next_block;
@@ -786,6 +786,7 @@ void evergreen_context_draw(struct r600_context *ctx, const struct r600_draw *dr
 
 	/* find number of color buffer */
 	db = r600_context_reg_bo(ctx, R_028048_DB_Z_READ_BASE);
+	sb = r600_context_reg_bo(ctx, R_02804C_DB_STENCIL_READ_BASE);
 	cb[0] = r600_context_reg_bo(ctx, R_028C60_CB_COLOR0_BASE);
 	cb[1] = r600_context_reg_bo(ctx, R_028C9C_CB_COLOR1_BASE);
 	cb[2] = r600_context_reg_bo(ctx, R_028CD8_CB_COLOR2_BASE);
@@ -865,14 +866,21 @@ void evergreen_context_draw(struct r600_context *ctx, const struct r600_draw *dr
 				flush = (S_0085F0_CB0_DEST_BASE_ENA(1) << i) |
 					S_0085F0_CB_ACTION_ENA(1);
 			}
+			if(cb[i]->use_count > 3) /* the colorbuffer uses don't count and it is used by 3 registers */
+				flush |= S_0085F0_SH_ACTION_ENA(1) | S_0085F0_TC_ACTION_ENA(1)
+				       | S_0085F0_VC_ACTION_ENA(1);
+
 			r600_context_bo_flush(ctx, flush, 0, cb[i]);
 		}
 	}
 	if (db) {
-		r600_context_bo_flush(ctx,
-					S_0085F0_DB_ACTION_ENA(1) |
-					S_0085F0_DB_DEST_BASE_ENA(1),
-					0, db);
+		flush = S_0085F0_DB_ACTION_ENA(1) | S_0085F0_DB_DEST_BASE_ENA(1);
+		/* DB is used by 4/6 registers */
+		if((db->use_count > 6)||(db->use_count > 4 && sb == NULL))
+			flush |= S_0085F0_SH_ACTION_ENA(1) | S_0085F0_TC_ACTION_ENA(1)
+			       | S_0085F0_VC_ACTION_ENA(1);
+
+		r600_context_bo_flush(ctx, flush, 0, db);
 	}
 
 	/* all dirty state have been scheduled in current cs */
diff --git a/src/gallium/winsys/r600/drm/r600_hw_context.c b/src/gallium/winsys/r600/drm/r600_hw_context.c
index bf4e9dc..a365f16 100644
--- a/src/gallium/winsys/r600/drm/r600_hw_context.c
+++ b/src/gallium/winsys/r600/drm/r600_hw_context.c
@@ -605,7 +605,7 @@ void r600_context_fini(struct r600_context *ctx)
 					range->blocks[CTX_BLOCK_ID(ctx, offset)] = NULL;
 				}
 				for (int k = 1; k <= block->nbo; k++) {
-					r600_bo_reference(ctx->radeon, &block->reloc[k].bo, NULL);
+					r600_block_bo_reference(ctx->radeon, &block->reloc[k].bo, NULL);
 				}
 				free(block);
 			}
@@ -848,7 +848,7 @@ void r600_context_pipe_state_set(struct r600_context *ctx, struct r600_pipe_stat
 		if (block->pm4_bo_index[id]) {
 			/* find relocation */
 			id = block->pm4_bo_index[id];
-			r600_bo_reference(ctx->radeon, &block->reloc[id].bo, state->regs[i].bo);
+			r600_block_bo_reference(ctx->radeon, &block->reloc[id].bo, state->regs[i].bo);
 			state->regs[i].bo->fence = ctx->radeon->fence;
 		}
 		if (!(block->status & R600_BLOCK_STATUS_DIRTY)) {
@@ -869,8 +869,8 @@ static inline void r600_context_pipe_state_set_resource(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);
-		r600_bo_reference(ctx->radeon, &block->reloc[1].bo, NULL);
-		r600_bo_reference(ctx->radeon , &block->reloc[2].bo, NULL);
+		r600_block_bo_reference(ctx->radeon, &block->reloc[1].bo, NULL);
+		r600_block_bo_reference(ctx->radeon , &block->reloc[2].bo, NULL);
 		LIST_DELINIT(&block->list);
 		return;
 	}
@@ -881,19 +881,18 @@ static inline void r600_context_pipe_state_set_resource(struct r600_context *ctx
 	block->reg[4] = state->regs[4].value;
 	block->reg[5] = state->regs[5].value;
 	block->reg[6] = state->regs[6].value;
-	r600_bo_reference(ctx->radeon, &block->reloc[1].bo, NULL);
-	r600_bo_reference(ctx->radeon , &block->reloc[2].bo, NULL);
+
 	if (state->regs[0].bo) {
 		/* VERTEX RESOURCE, we preted there is 2 bo to relocate so
 		 * we have single case btw VERTEX & TEXTURE resource
 		 */
-		r600_bo_reference(ctx->radeon, &block->reloc[1].bo, state->regs[0].bo);
-		r600_bo_reference(ctx->radeon, &block->reloc[2].bo, state->regs[0].bo);
+		r600_block_bo_reference(ctx->radeon, &block->reloc[1].bo, state->regs[0].bo);
+		r600_block_bo_reference(ctx->radeon, &block->reloc[2].bo, state->regs[0].bo);
 		state->regs[0].bo->fence = ctx->radeon->fence;
 	} else {
 		/* TEXTURE RESOURCE */
-		r600_bo_reference(ctx->radeon, &block->reloc[1].bo, state->regs[2].bo);
-		r600_bo_reference(ctx->radeon, &block->reloc[2].bo, state->regs[3].bo);
+		r600_block_bo_reference(ctx->radeon, &block->reloc[1].bo, state->regs[2].bo);
+		r600_block_bo_reference(ctx->radeon, &block->reloc[2].bo, state->regs[3].bo);
 		state->regs[2].bo->fence = ctx->radeon->fence;
 		state->regs[3].bo->fence = ctx->radeon->fence;
 	}
@@ -1016,7 +1015,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;
+	unsigned ndwords = 9,flush;
 	struct r600_block *dirty_block = NULL;
 	struct r600_block *next_block;
 	unsigned rv6xx_surface_base_update = 0;
@@ -1109,14 +1108,21 @@ void r600_context_draw(struct r600_context *ctx, const struct r600_draw *draw)
 	/* flush color buffer */
 	for (int i = 0; i < 8; i++) {
 		if (cb[i]) {
-			r600_context_bo_flush(ctx,
-					(S_0085F0_CB0_DEST_BASE_ENA(1) << i) |
-					S_0085F0_CB_ACTION_ENA(1),
-					0, cb[i]);
+			flush = (S_0085F0_CB0_DEST_BASE_ENA(1) << i) | S_0085F0_CB_ACTION_ENA(1);
+			if(cb[i]->use_count > 4) /* the colorbuffer use doesn't count, and it is used by 4 registers */
+				flush |= S_0085F0_SH_ACTION_ENA(1) | S_0085F0_TC_ACTION_ENA(1)
+				       | S_0085F0_VC_ACTION_ENA(1);
+
+			r600_context_bo_flush(ctx, flush, 0, cb[i]);
 		}
 	}
 	if (db) {
-		r600_context_bo_flush(ctx, S_0085F0_DB_ACTION_ENA(1), 0, db);
+		flush = S_0085F0_DB_ACTION_ENA(1);
+		if(db->use_count > 2) /* DB is used by 2 registers */
+				flush |= S_0085F0_SH_ACTION_ENA(1) | S_0085F0_TC_ACTION_ENA(1)
+				       | S_0085F0_VC_ACTION_ENA(1);
+
+		r600_context_bo_flush(ctx, flush, 0, db);
 	}
 
 	/* all dirty state have been scheduled in current cs */
diff --git a/src/gallium/winsys/r600/drm/r600_priv.h b/src/gallium/winsys/r600/drm/r600_priv.h
index a958c95..c82ac20 100644
--- a/src/gallium/winsys/r600/drm/r600_priv.h
+++ b/src/gallium/winsys/r600/drm/r600_priv.h
@@ -93,6 +93,7 @@ struct r600_bo {
 	unsigned			domains;
 	struct radeon_bo		*bo;
 	unsigned			fence;
+	unsigned			use_count;
 	/* manager data */
 	struct list_head		list;
 	unsigned			manager_id;
@@ -250,6 +251,12 @@ static unsigned inline r600_bo_get_size(struct r600_bo *bo)
 	return bo->size;
 }
 
+static inline void r600_block_bo_reference(struct radeon *radeon, struct r600_bo **dst, struct r600_bo *src) {
+	if(*dst) (*dst)->use_count--;
+	if(src) src->use_count++;
+	r600_bo_reference(radeon,dst,src);
+}
+
 /*
  * fence
  */
-- 
1.7.3.4



More information about the mesa-dev mailing list