Mesa (master): r600g: fix cache flushes on r6xx

Dave Airlie airlied at kemper.freedesktop.org
Thu May 5 22:28:58 UTC 2011


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

Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Thu May  5 03:17:16 2011 -0400

r600g: fix cache flushes on r6xx

r6xx asics have some problems with the surface
sync logic for the CB and DB.  It's recommended
to use the event write interface for flushing
the DB/CB caches rather than the sync packets.
A single event write flush flushes all dst
caches, so we only need one for all CBs and DB.

Should fix:
https://bugs.freedesktop.org/show_bug.cgi?id=35312

Signed-off-by: Alex Deucher <alexdeucher at gmail.com>
Signed-off-by: Dave Airlie <airlied at redhat.com>

---

 src/gallium/drivers/r600/r600.h               |    1 +
 src/gallium/winsys/r600/drm/r600_hw_context.c |   36 ++++++++++++++++++------
 2 files changed, 28 insertions(+), 9 deletions(-)

diff --git a/src/gallium/drivers/r600/r600.h b/src/gallium/drivers/r600/r600.h
index 0b0df9d..33aa450 100644
--- a/src/gallium/drivers/r600/r600.h
+++ b/src/gallium/drivers/r600/r600.h
@@ -235,6 +235,7 @@ struct r600_query {
 
 #define R600_CONTEXT_DRAW_PENDING	(1 << 0)
 #define R600_CONTEXT_DST_CACHES_DIRTY	(1 << 1)
+#define R600_CONTEXT_CHECK_EVENT_FLUSH	(1 << 2)
 
 struct r600_context {
 	struct radeon		*radeon;
diff --git a/src/gallium/winsys/r600/drm/r600_hw_context.c b/src/gallium/winsys/r600/drm/r600_hw_context.c
index 150485d..b8a8108 100644
--- a/src/gallium/winsys/r600/drm/r600_hw_context.c
+++ b/src/gallium/winsys/r600/drm/r600_hw_context.c
@@ -797,19 +797,33 @@ void r600_context_bo_flush(struct r600_context *ctx, unsigned flush_flags,
 				unsigned flush_mask, struct r600_bo *rbo)
 {
 	struct radeon_bo *bo;
+	boolean use_event_flush = FALSE;
+
 	bo = rbo->bo;
 	/* if bo has already been flushed */
 	if (!(~bo->last_flush & flush_flags)) {
 		bo->last_flush &= flush_mask;
 		return;
 	}
-	ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_SURFACE_SYNC, 3, ctx->predicate_drawing);
-	ctx->pm4[ctx->pm4_cdwords++] = flush_flags;
-	ctx->pm4[ctx->pm4_cdwords++] = (bo->size + 255) >> 8;
-	ctx->pm4[ctx->pm4_cdwords++] = 0x00000000;
-	ctx->pm4[ctx->pm4_cdwords++] = 0x0000000A;
-	ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_NOP, 0, ctx->predicate_drawing);
-	ctx->pm4[ctx->pm4_cdwords++] = bo->reloc_id;
+
+	if ((ctx->radeon->family < CHIP_RV770) &&
+	    (G_0085F0_CB_ACTION_ENA(flush_flags) ||
+	     G_0085F0_DB_ACTION_ENA(flush_flags)))
+		use_event_flush = TRUE;
+
+	if (use_event_flush && (ctx->flags & R600_CONTEXT_CHECK_EVENT_FLUSH)) {
+		ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE, 0, ctx->predicate_drawing);
+		ctx->pm4[ctx->pm4_cdwords++] = EVENT_TYPE(EVENT_TYPE_CACHE_FLUSH_AND_INV_EVENT) | EVENT_INDEX(0);
+		ctx->flags &= ~R600_CONTEXT_CHECK_EVENT_FLUSH;
+	} else {
+		ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_SURFACE_SYNC, 3, ctx->predicate_drawing);
+		ctx->pm4[ctx->pm4_cdwords++] = flush_flags;
+		ctx->pm4[ctx->pm4_cdwords++] = (bo->size + 255) >> 8;
+		ctx->pm4[ctx->pm4_cdwords++] = 0x00000000;
+		ctx->pm4[ctx->pm4_cdwords++] = 0x0000000A;
+		ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_NOP, 0, ctx->predicate_drawing);
+		ctx->pm4[ctx->pm4_cdwords++] = bo->reloc_id;
+	}
 	bo->last_flush = (bo->last_flush | flush_flags) & flush_mask;
 }
 
@@ -1119,6 +1133,7 @@ void r600_context_block_emit_dirty(struct r600_context *ctx, struct r600_block *
 		goto out;
 	}
 
+	ctx->flags |= R600_CONTEXT_CHECK_EVENT_FLUSH;
 	for (int j = 0; j < block->nreg; j++) {
 		if (block->pm4_bo_index[j]) {
 			/* find relocation */
@@ -1132,6 +1147,7 @@ void r600_context_block_emit_dirty(struct r600_context *ctx, struct r600_block *
 					block->reloc[id].bo);
 		}
 	}
+	ctx->flags &= ~R600_CONTEXT_CHECK_EVENT_FLUSH;
 	memcpy(&ctx->pm4[ctx->pm4_cdwords], block->pm4, block->pm4_ndwords * 4);
 	ctx->pm4_cdwords += block->pm4_ndwords;
 
@@ -1155,6 +1171,7 @@ void r600_context_flush_dest_caches(struct r600_context *ctx)
 {
 	struct r600_bo *cb[8];
 	struct r600_bo *db;
+	int i;
 
 	if (!(ctx->flags & R600_CONTEXT_DST_CACHES_DIRTY))
 		return;
@@ -1169,8 +1186,9 @@ void r600_context_flush_dest_caches(struct r600_context *ctx)
 	cb[6] = r600_context_reg_bo(ctx, R_028058_CB_COLOR6_BASE);
 	cb[7] = r600_context_reg_bo(ctx, R_02805C_CB_COLOR7_BASE);
 
+	ctx->flags |= R600_CONTEXT_CHECK_EVENT_FLUSH;
 	/* flush the color buffers */
-	for (int i = 0; i < 8; i++) {
+	for (i = 0; i < 8; i++) {
 		if (!cb[i])
 			continue;
 
@@ -1182,7 +1200,7 @@ void r600_context_flush_dest_caches(struct r600_context *ctx)
 	if (db) {
 		r600_context_bo_flush(ctx, S_0085F0_DB_ACTION_ENA(1), 0, db);
 	}
-
+	ctx->flags &= ~R600_CONTEXT_CHECK_EVENT_FLUSH;
 	ctx->flags &= ~R600_CONTEXT_DST_CACHES_DIRTY;
 }
 




More information about the mesa-commit mailing list