Mesa (master): freedreno: "fix" problems with excessive flushes

Rob Clark robclark at kemper.freedesktop.org
Fri Sep 12 22:36:13 UTC 2014


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

Author: Rob Clark <robclark at freedesktop.org>
Date:   Fri Sep 12 16:52:38 2014 -0400

freedreno: "fix" problems with excessive flushes

4f338c9b introduced logic to trigger a flush rather than overflowing
cmdstream buffer.  But the threshold was too low, triggering flushes
where they were not needed.  This caused problems with games like
xonotic.

Part of the problem is that we need to mark all state dirty between
cmdstream submit ioctls, because we cannot rely on state being
preserved across ioctls.  But even with that, there are still some
problems that are still being debugged.  For now:

1) correctly mark all state dirty
2) introduce FD_MESA_DEBUG flush flag to force rendering to be flushed
between each draw, to trigger problems (so that I can debug)
3) use a more reasonable threshold so for normal usecases we don't
trigger the problems

This at least corrects the regression, but there is still more debugging
to do.

Signed-off-by: Rob Clark <robclark at freedesktop.org>

---

 src/gallium/drivers/freedreno/freedreno_context.h |    8 +++++++
 src/gallium/drivers/freedreno/freedreno_draw.c    |    4 +++-
 src/gallium/drivers/freedreno/freedreno_gmem.c    |   25 +--------------------
 src/gallium/drivers/freedreno/freedreno_screen.c  |    2 +-
 src/gallium/drivers/freedreno/freedreno_util.h    |    2 +-
 5 files changed, 14 insertions(+), 27 deletions(-)

diff --git a/src/gallium/drivers/freedreno/freedreno_context.h b/src/gallium/drivers/freedreno/freedreno_context.h
index 0051c9d..2c9c3a8 100644
--- a/src/gallium/drivers/freedreno/freedreno_context.h
+++ b/src/gallium/drivers/freedreno/freedreno_context.h
@@ -222,6 +222,14 @@ struct fd_context {
 	struct fd_ringbuffer *rings[8];
 	unsigned rings_idx;
 
+	/* NOTE: currently using a single ringbuffer for both draw and
+	 * tiling commands, we need to make sure we need to leave enough
+	 * room at the end to append the tiling commands when we flush.
+	 * 0x7000 dwords should be a couple times more than we ever need
+	 * so should be a nice concervative threshold.
+	 */
+#define FD_TILING_COMMANDS_DWORDS 0x7000
+
 	/* normal draw/clear cmds: */
 	struct fd_ringbuffer *ring;
 	struct fd_ringmarker *draw_start, *draw_end;
diff --git a/src/gallium/drivers/freedreno/freedreno_draw.c b/src/gallium/drivers/freedreno/freedreno_draw.c
index e463495..eb4637d 100644
--- a/src/gallium/drivers/freedreno/freedreno_draw.c
+++ b/src/gallium/drivers/freedreno/freedreno_draw.c
@@ -172,7 +172,9 @@ fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
 	 * now we need to do this hack and trigger flush if we are running
 	 * low on remaining space for cmds:
 	 */
-	if ((ctx->ring->cur - ctx->ring->start) > ctx->ring->size/8)
+	if (((ctx->ring->cur - ctx->ring->start) >
+				(ctx->ring->size/4 - FD_TILING_COMMANDS_DWORDS)) ||
+			(fd_mesa_debug & FD_DBG_FLUSH))
 		fd_context_render(pctx);
 }
 
diff --git a/src/gallium/drivers/freedreno/freedreno_gmem.c b/src/gallium/drivers/freedreno/freedreno_gmem.c
index 661458f..7e43c2e 100644
--- a/src/gallium/drivers/freedreno/freedreno_gmem.c
+++ b/src/gallium/drivers/freedreno/freedreno_gmem.c
@@ -381,28 +381,5 @@ fd_gmem_render_tiles(struct pipe_context *pctx)
 	ctx->max_scissor.minx = ctx->max_scissor.miny = ~0;
 	ctx->max_scissor.maxx = ctx->max_scissor.maxy = 0;
 
-	/* Note that because the per-tile setup and mem2gmem/gmem2mem are emitted
-	 * after the draw/clear calls, but executed before, we need to preemptively
-	 * flag some state as dirty before the first draw/clear call.
-	 *
-	 * TODO maybe we need to mark all state as dirty to not worry about state
-	 * being clobbered by other contexts?
-	 */
-	ctx->dirty |= FD_DIRTY_ZSA |
-			FD_DIRTY_RASTERIZER |
-			FD_DIRTY_FRAMEBUFFER |
-			FD_DIRTY_SAMPLE_MASK |
-			FD_DIRTY_VIEWPORT |
-			FD_DIRTY_CONSTBUF |
-			FD_DIRTY_PROG |
-			FD_DIRTY_SCISSOR |
-			/* probably only needed if we need to mem2gmem on the next
-			 * draw..  but not sure if there is a good way to know?
-			 */
-			FD_DIRTY_VERTTEX |
-			FD_DIRTY_FRAGTEX |
-			FD_DIRTY_BLEND;
-
-	if (fd_mesa_debug & FD_DBG_DGMEM)
-		ctx->dirty = 0xffffffff;
+	ctx->dirty = ~0;
 }
diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c
index 745ca8e..6db75ad 100644
--- a/src/gallium/drivers/freedreno/freedreno_screen.c
+++ b/src/gallium/drivers/freedreno/freedreno_screen.c
@@ -60,7 +60,7 @@ static const struct debug_named_value debug_options[] = {
 		{"msgs",      FD_DBG_MSGS,   "Print debug messages"},
 		{"disasm",    FD_DBG_DISASM, "Dump TGSI and adreno shader disassembly"},
 		{"dclear",    FD_DBG_DCLEAR, "Mark all state dirty after clear"},
-		{"dgmem",     FD_DBG_DGMEM,  "Mark all state dirty after GMEM tile pass"},
+		{"flush",     FD_DBG_FLUSH,  "Force flush after every draw"},
 		{"dscis",     FD_DBG_DSCIS,  "Disable scissor optimization"},
 		{"direct",    FD_DBG_DIRECT, "Force inline (SS_DIRECT) state loads"},
 		{"dbypass",   FD_DBG_DBYPASS,"Disable GMEM bypass"},
diff --git a/src/gallium/drivers/freedreno/freedreno_util.h b/src/gallium/drivers/freedreno/freedreno_util.h
index c519e23..d676f80 100644
--- a/src/gallium/drivers/freedreno/freedreno_util.h
+++ b/src/gallium/drivers/freedreno/freedreno_util.h
@@ -55,7 +55,7 @@ enum adreno_stencil_op fd_stencil_op(unsigned op);
 #define FD_DBG_MSGS     0x0001
 #define FD_DBG_DISASM   0x0002
 #define FD_DBG_DCLEAR   0x0004
-#define FD_DBG_DGMEM    0x0008
+#define FD_DBG_FLUSH    0x0008
 #define FD_DBG_DSCIS    0x0010
 #define FD_DBG_DIRECT   0x0020
 #define FD_DBG_DBYPASS  0x0040




More information about the mesa-commit mailing list