2011/5/5 Alex Deucher <alexdeuc...@gmail.com>:
> 2011/5/5 Mathias Fröhlich <mathias.froehl...@gmx.net>:
>>
>> Hi all,
>>
>> On Thursday, May 05, 2011 04:32:03 you wrote:
>>> Okay my guess at the problem is that:
>>>
>>> the CP tracks coherency but the SURFACE_BASE_UPDATE stuff might rely
>>> on the base in the CB being the same as the texture BASE which it won't
>>> be in the case where we are rendering to mip sublevels. Though I've no idea
>>> how to workaround this without explicit flushes.
>>
>> Hmm, may be.
>> I also thought that the surface sync packet has some special case 
>> optimzations
>> for some of the probably often used flags that lead to that kind of 
>> behaviour.
>>
>> May be that 'flush all' in case of a new framebuffer target for these kind of
>> chips is again a good idea instead of the finegrained flush dest caches.
>>
>> May be Alex finds some undocumented ideas somewhere in his bag :).
>
> Apparently the CB/DB surface sync stuff has a number of issues on
> r6xx, so we should just use event_write flushes for CB/DB.  A single
> event write flush takes care of all dst caches.  Something like this
> untested patch perhaps:
> http://people.freedesktop.org/~agd5f/r600g_event_flush.diff

The attached patch seems to work for me.

Alex
From 0d4362817adf4d119acf4d370b14be97de2af5a3 Mon Sep 17 00:00:00 2001
From: Alex Deucher <alexdeuc...@gmail.com>
Date: Thu, 5 May 2011 03:17:16 -0400
Subject: [PATCH] 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 <alexdeuc...@gmail.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;
 }
 
-- 
1.7.1.1

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to