r600g: fix cache flushes on r6xx
authorAlex Deucher <alexdeucher@gmail.com>
Thu, 5 May 2011 07:17:16 +0000 (03:17 -0400)
committerDave Airlie <airlied@redhat.com>
Thu, 5 May 2011 22:07:12 +0000 (08:07 +1000)
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@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
src/gallium/drivers/r600/r600.h
src/gallium/winsys/r600/drm/r600_hw_context.c

index 0b0df9d019b4107b6feead87c31789cc28ad5cec..33aa45088a8f814a3cbd3fa76f6543897b353691 100644 (file)
@@ -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;
index 150485d3fe1461a03a3cdf72dff9f6098d1467f3..b8a8108fb1228c171b41d93b2c53f31a141f140e 100644 (file)
@@ -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;
 }