Mesa (master): freedreno/a5xx: hw binning support

Rob Clark robclark at kemper.freedesktop.org
Sat May 13 17:27:35 UTC 2017


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

Author: Rob Clark <robdclark at gmail.com>
Date:   Fri May 12 09:56:56 2017 -0400

freedreno/a5xx: hw binning support

Signed-off-by: Rob Clark <robdclark at gmail.com>

---

 src/gallium/drivers/freedreno/a5xx/fd5_draw.c     |  16 +--
 src/gallium/drivers/freedreno/a5xx/fd5_emit.c     |   4 -
 src/gallium/drivers/freedreno/a5xx/fd5_emit.h     |  10 +-
 src/gallium/drivers/freedreno/a5xx/fd5_gmem.c     | 151 ++++++++++++++++++++--
 src/gallium/drivers/freedreno/a5xx/fd5_program.c  |  43 +++---
 src/gallium/drivers/freedreno/freedreno_context.h |   2 +-
 src/gallium/drivers/freedreno/freedreno_gmem.c    |   7 +-
 src/gallium/drivers/freedreno/freedreno_screen.c  |   2 +
 src/gallium/drivers/freedreno/freedreno_screen.h  |   1 +
 9 files changed, 185 insertions(+), 51 deletions(-)

diff --git a/src/gallium/drivers/freedreno/a5xx/fd5_draw.c b/src/gallium/drivers/freedreno/a5xx/fd5_draw.c
index 5c735734e6..cd315d4ac0 100644
--- a/src/gallium/drivers/freedreno/a5xx/fd5_draw.c
+++ b/src/gallium/drivers/freedreno/a5xx/fd5_draw.c
@@ -60,7 +60,7 @@ draw_impl(struct fd_context *ctx, struct fd_ringbuffer *ring,
 	OUT_RING(ring, info->primitive_restart ? /* PC_RESTART_INDEX */
 			info->restart_index : 0xffffffff);
 
-	fd5_emit_render_cntl(ctx, false);
+	fd5_emit_render_cntl(ctx, false, emit->key.binning_pass);
 	fd5_draw_emit(ctx->batch, ring, primtype,
 			emit->key.binning_pass ? IGNORE_VISIBILITY : USE_VISIBILITY,
 			info, index_offset);
@@ -139,12 +139,12 @@ fd5_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info,
 
 	draw_impl(ctx, ctx->batch->draw, &emit, index_offset);
 
-//	/* and now binning pass: */
-//	emit.key.binning_pass = true;
-//	emit.dirty = dirty & ~(FD_DIRTY_BLEND);
-//	emit.vp = NULL;   /* we changed key so need to refetch vp */
-//	emit.fp = NULL;
-//	draw_impl(ctx, ctx->batch->binning, &emit);
+	/* and now binning pass: */
+	emit.key.binning_pass = true;
+	emit.dirty = dirty & ~(FD_DIRTY_BLEND);
+	emit.vp = NULL;   /* we changed key so need to refetch vp */
+	emit.fp = NULL;
+	draw_impl(ctx, ctx->batch->binning, &emit, index_offset);
 
 	if (emit.streamout_mask) {
 		struct fd_ringbuffer *ring = ctx->batch->draw;
@@ -177,7 +177,7 @@ fd5_clear(struct fd_context *ctx, unsigned buffers,
 	ctx->batch->max_scissor.maxx = MAX2(ctx->batch->max_scissor.maxx, scissor->maxx);
 	ctx->batch->max_scissor.maxy = MAX2(ctx->batch->max_scissor.maxy, scissor->maxy);
 
-	fd5_emit_render_cntl(ctx, true);
+	fd5_emit_render_cntl(ctx, true, false);
 
 	if (buffers & PIPE_CLEAR_COLOR) {
 		for (int i = 0; i < pfb->nr_cbufs; i++) {
diff --git a/src/gallium/drivers/freedreno/a5xx/fd5_emit.c b/src/gallium/drivers/freedreno/a5xx/fd5_emit.c
index 737f188e4f..0e2d204484 100644
--- a/src/gallium/drivers/freedreno/a5xx/fd5_emit.c
+++ b/src/gallium/drivers/freedreno/a5xx/fd5_emit.c
@@ -1014,10 +1014,6 @@ t7              opcode: CP_WAIT_FOR_IDLE (26) (1 dwords)
 	OUT_RING(ring, 0x00000000);
 	OUT_RING(ring, 0x00000000);
 	OUT_RING(ring, 0x00000000);
-
-	// TODO hacks.. these should not be hardcoded:
-	OUT_PKT4(ring, REG_A5XX_GRAS_SC_CNTL, 1);
-	OUT_RING(ring, 0x00000008);   /* GRAS_SC_CNTL */
 }
 
 static void
diff --git a/src/gallium/drivers/freedreno/a5xx/fd5_emit.h b/src/gallium/drivers/freedreno/a5xx/fd5_emit.h
index 982ac1d5ac..ca88083068 100644
--- a/src/gallium/drivers/freedreno/a5xx/fd5_emit.h
+++ b/src/gallium/drivers/freedreno/a5xx/fd5_emit.h
@@ -114,7 +114,8 @@ fd5_set_render_mode(struct fd_context *ctx, struct fd_ringbuffer *ring,
 	OUT_RING(ring, CP_SET_RENDER_MODE_0_MODE(mode));
 	OUT_RING(ring, 0x00000000);   /* ADDR_LO */
 	OUT_RING(ring, 0x00000000);   /* ADDR_HI */
-	OUT_RING(ring, COND(mode == GMEM, CP_SET_RENDER_MODE_3_GMEM_ENABLE));
+	OUT_RING(ring, COND(mode == GMEM, CP_SET_RENDER_MODE_3_GMEM_ENABLE) |
+			COND(mode == BINNING, CP_SET_RENDER_MODE_3_VSC_ENABLE));
 	OUT_RING(ring, 0x00000000);
 	emit_marker5(ring, 7);
 }
@@ -135,9 +136,9 @@ fd5_emit_blit(struct fd_context *ctx, struct fd_ringbuffer *ring)
 }
 
 static inline void
-fd5_emit_render_cntl(struct fd_context *ctx, bool blit)
+fd5_emit_render_cntl(struct fd_context *ctx, bool blit, bool binning)
 {
-	struct fd_ringbuffer *ring = ctx->batch->draw;
+	struct fd_ringbuffer *ring = binning ? ctx->batch->binning : ctx->batch->draw;
 
 	/* TODO eventually this partially depends on the pfb state, ie.
 	 * which of the cbuf(s)/zsbuf has an UBWC flag buffer.. that part
@@ -150,11 +151,14 @@ fd5_emit_render_cntl(struct fd_context *ctx, bool blit)
 	bool samples_passed = (fd5_context(ctx)->samples_passed_queries > 0);
 	OUT_PKT4(ring, REG_A5XX_RB_RENDER_CNTL, 1);
 	OUT_RING(ring, 0x00000000 |   /* RB_RENDER_CNTL */
+			COND(binning, A5XX_RB_RENDER_CNTL_BINNING_PASS) |
+			COND(binning, A5XX_RB_RENDER_CNTL_DISABLE_COLOR_PIPE) |
 			COND(samples_passed, A5XX_RB_RENDER_CNTL_SAMPLES_PASSED) |
 			COND(!blit, 0x8));
 
 	OUT_PKT4(ring, REG_A5XX_GRAS_SC_CNTL, 1);
 	OUT_RING(ring, 0x00000008 |   /* GRAS_SC_CNTL */
+			COND(binning, A5XX_GRAS_SC_CNTL_BINNING_PASS) |
 			COND(samples_passed, A5XX_GRAS_SC_CNTL_SAMPLES_PASSED));
 
 }
diff --git a/src/gallium/drivers/freedreno/a5xx/fd5_gmem.c b/src/gallium/drivers/freedreno/a5xx/fd5_gmem.c
index b80a04fd2d..1a45181145 100644
--- a/src/gallium/drivers/freedreno/a5xx/fd5_gmem.c
+++ b/src/gallium/drivers/freedreno/a5xx/fd5_gmem.c
@@ -207,6 +207,15 @@ emit_zs(struct fd_ringbuffer *ring, struct pipe_surface *zsbuf,
 	}
 }
 
+static bool
+use_hw_binning(struct fd_batch *batch)
+{
+	struct fd_gmem_stateobj *gmem = &batch->ctx->gmem;
+
+	return fd_binning_enabled && ((gmem->nbins_x * gmem->nbins_y) > 2) &&
+			(batch->num_draws > 0);
+}
+
 static void
 patch_draws(struct fd_batch *batch, enum pc_di_vis_cull_mode vismode)
 {
@@ -218,6 +227,113 @@ patch_draws(struct fd_batch *batch, enum pc_di_vis_cull_mode vismode)
 	util_dynarray_resize(&batch->draw_patches, 0);
 }
 
+static void
+update_vsc_pipe(struct fd_batch *batch)
+{
+	struct fd_context *ctx = batch->ctx;
+	struct fd5_context *fd5_ctx = fd5_context(ctx);
+	struct fd_gmem_stateobj *gmem = &batch->ctx->gmem;
+	struct fd_ringbuffer *ring = batch->gmem;
+	int i;
+
+	OUT_PKT4(ring, REG_A5XX_VSC_BIN_SIZE, 3);
+	OUT_RING(ring, A5XX_VSC_BIN_SIZE_WIDTH(gmem->bin_w) |
+			A5XX_VSC_BIN_SIZE_HEIGHT(gmem->bin_h));
+	OUT_RELOCW(ring, fd5_ctx->vsc_size_mem, 0, 0, 0); /* VSC_SIZE_ADDRESS_LO/HI */
+
+	OUT_PKT4(ring, REG_A5XX_UNKNOWN_0BC5, 2);
+	OUT_RING(ring, 0x00000000);   /* UNKNOWN_0BC5 */
+	OUT_RING(ring, 0x00000000);   /* UNKNOWN_0BC6 */
+
+	OUT_PKT4(ring, REG_A5XX_VSC_PIPE_CONFIG_REG(0), 16);
+	for (i = 0; i < 16; i++) {
+		struct fd_vsc_pipe *pipe = &ctx->pipe[i];
+		OUT_RING(ring, A5XX_VSC_PIPE_CONFIG_REG_X(pipe->x) |
+				A5XX_VSC_PIPE_CONFIG_REG_Y(pipe->y) |
+				A5XX_VSC_PIPE_CONFIG_REG_W(pipe->w) |
+				A5XX_VSC_PIPE_CONFIG_REG_H(pipe->h));
+	}
+
+	OUT_PKT4(ring, REG_A5XX_VSC_PIPE_DATA_ADDRESS_LO(0), 32);
+	for (i = 0; i < 16; i++) {
+		struct fd_vsc_pipe *pipe = &ctx->pipe[i];
+		if (!pipe->bo) {
+			pipe->bo = fd_bo_new(ctx->dev, 0x20000,
+					DRM_FREEDRENO_GEM_TYPE_KMEM);
+		}
+		OUT_RELOCW(ring, pipe->bo, 0, 0, 0);     /* VSC_PIPE_DATA_ADDRESS[i].LO/HI */
+	}
+
+	OUT_PKT4(ring, REG_A5XX_VSC_PIPE_DATA_LENGTH_REG(0), 16);
+	for (i = 0; i < 16; i++) {
+		struct fd_vsc_pipe *pipe = &ctx->pipe[i];
+		OUT_RING(ring, fd_bo_size(pipe->bo) - 32); /* VSC_PIPE_DATA_LENGTH[i] */
+	}
+}
+
+static void
+emit_binning_pass(struct fd_batch *batch)
+{
+	struct fd_context *ctx = batch->ctx;
+	struct fd_ringbuffer *ring = batch->gmem;
+	struct fd_gmem_stateobj *gmem = &batch->ctx->gmem;
+
+	uint32_t x1 = gmem->minx;
+	uint32_t y1 = gmem->miny;
+	uint32_t x2 = gmem->minx + gmem->width - 1;
+	uint32_t y2 = gmem->miny + gmem->height - 1;
+
+	fd5_set_render_mode(batch->ctx, ring, BINNING);
+
+	OUT_PKT4(ring, REG_A5XX_RB_CNTL, 1);
+	OUT_RING(ring, A5XX_RB_CNTL_WIDTH(gmem->bin_w) |
+			A5XX_RB_CNTL_HEIGHT(gmem->bin_h));
+
+	OUT_PKT4(ring, REG_A5XX_GRAS_SC_WINDOW_SCISSOR_TL, 2);
+	OUT_RING(ring, A5XX_GRAS_SC_WINDOW_SCISSOR_TL_X(x1) |
+			A5XX_GRAS_SC_WINDOW_SCISSOR_TL_Y(y1));
+	OUT_RING(ring, A5XX_GRAS_SC_WINDOW_SCISSOR_BR_X(x2) |
+			A5XX_GRAS_SC_WINDOW_SCISSOR_BR_Y(y2));
+
+	OUT_PKT4(ring, REG_A5XX_RB_RESOLVE_CNTL_1, 2);
+	OUT_RING(ring, A5XX_RB_RESOLVE_CNTL_1_X(x1) |
+			A5XX_RB_RESOLVE_CNTL_1_Y(y1));
+	OUT_RING(ring, A5XX_RB_RESOLVE_CNTL_2_X(x2) |
+			A5XX_RB_RESOLVE_CNTL_2_Y(y2));
+
+	update_vsc_pipe(batch);
+
+	OUT_PKT4(ring, REG_A5XX_VPC_MODE_CNTL, 1);
+	OUT_RING(ring, A5XX_VPC_MODE_CNTL_BINNING_PASS);
+
+	OUT_PKT7(ring, CP_EVENT_WRITE, 1);
+	OUT_RING(ring, UNK_2C);
+
+	OUT_PKT4(ring, REG_A5XX_RB_WINDOW_OFFSET, 1);
+	OUT_RING(ring, A5XX_RB_WINDOW_OFFSET_X(0) |
+			A5XX_RB_WINDOW_OFFSET_Y(0));
+
+	/* emit IB to binning drawcmds: */
+	ctx->emit_ib(ring, batch->binning);
+
+	fd_reset_wfi(batch);
+
+	OUT_PKT7(ring, CP_EVENT_WRITE, 1);
+	OUT_RING(ring, UNK_2D);
+
+	OUT_PKT7(ring, CP_EVENT_WRITE, 4);
+	OUT_RING(ring, CACHE_FLUSH_TS);
+	OUT_RELOCW(ring, fd5_context(ctx)->blit_mem, 0, 0, 0);  /* ADDR_LO/HI */
+	OUT_RING(ring, 0x00000000);
+
+	// TODO CP_COND_WRITE's for all the vsc buffers (check for overflow??)
+
+	fd_wfi(batch, ring);
+
+	OUT_PKT4(ring, REG_A5XX_VPC_MODE_CNTL, 1);
+	OUT_RING(ring, 0x0);
+}
+
 /* before first tile */
 static void
 fd5_emit_tile_init(struct fd_batch *batch)
@@ -243,9 +359,12 @@ fd5_emit_tile_init(struct fd_batch *batch)
 	OUT_PKT4(ring, REG_A5XX_RB_CCU_CNTL, 1);
 	OUT_RING(ring, 0x7c13c080);   /* RB_CCU_CNTL */
 
-/*
-opcode: CP_PREEMPT_ENABLE_LOCAL (6a) (2 dwords)
- */
+	if (use_hw_binning(batch)) {
+		emit_binning_pass(batch);
+		patch_draws(batch, USE_VISIBILITY);
+	} else {
+		patch_draws(batch, IGNORE_VISIBILITY);
+	}
 
 	fd5_set_render_mode(batch->ctx, ring, GMEM);
 }
@@ -254,6 +373,8 @@ opcode: CP_PREEMPT_ENABLE_LOCAL (6a) (2 dwords)
 static void
 fd5_emit_tile_prep(struct fd_batch *batch, struct fd_tile *tile)
 {
+	struct fd_context *ctx = batch->ctx;
+	struct fd5_context *fd5_ctx = fd5_context(ctx);
 	struct fd_ringbuffer *ring = batch->gmem;
 
 	uint32_t x1 = tile->xoff;
@@ -273,6 +394,25 @@ fd5_emit_tile_prep(struct fd_batch *batch, struct fd_tile *tile)
 	OUT_RING(ring, A5XX_RB_RESOLVE_CNTL_2_X(x2) |
 			A5XX_RB_RESOLVE_CNTL_2_Y(y2));
 
+	if (use_hw_binning(batch)) {
+		struct fd_vsc_pipe *pipe = &ctx->pipe[tile->p];
+
+		OUT_PKT7(ring, CP_WAIT_FOR_ME, 0);
+
+		OUT_PKT7(ring, CP_SET_VISIBILITY_OVERRIDE, 1);
+		OUT_RING(ring, 0x0);
+
+		OUT_PKT7(ring, CP_SET_BIN_DATA5, 5);
+		OUT_RING(ring, CP_SET_BIN_DATA5_0_VSC_SIZE(pipe->w * pipe->h) |
+				CP_SET_BIN_DATA5_0_VSC_N(tile->n));
+		OUT_RELOC(ring, pipe->bo, 0, 0, 0);      /* VSC_PIPE[p].DATA_ADDRESS */
+		OUT_RELOC(ring, fd5_ctx->vsc_size_mem,   /* VSC_SIZE_ADDRESS + (p * 4) */
+				(tile->p * 4), 0, 0);
+	} else {
+		OUT_PKT7(ring, CP_SET_VISIBILITY_OVERRIDE, 1);
+		OUT_RING(ring, 0x1);
+	}
+
 	OUT_PKT4(ring, REG_A5XX_RB_WINDOW_OFFSET, 1);
 	OUT_RING(ring, A5XX_RB_WINDOW_OFFSET_X(x1) |
 			A5XX_RB_WINDOW_OFFSET_Y(y1));
@@ -383,15 +523,10 @@ fd5_emit_tile_renderprep(struct fd_batch *batch, struct fd_tile *tile)
 	struct fd_gmem_stateobj *gmem = &batch->ctx->gmem;
 	struct pipe_framebuffer_state *pfb = &batch->framebuffer;
 
-	OUT_PKT7(ring, CP_SET_VISIBILITY_OVERRIDE, 1);
-	OUT_RING(ring, 0x1);
-
 	OUT_PKT4(ring, REG_A5XX_RB_CNTL, 1);
 	OUT_RING(ring, A5XX_RB_CNTL_WIDTH(gmem->bin_w) |
 			A5XX_RB_CNTL_HEIGHT(gmem->bin_h));
 
-	patch_draws(batch, IGNORE_VISIBILITY);
-
 	emit_zs(ring, pfb->zsbuf, gmem);
 	emit_mrt(ring, pfb->nr_cbufs, pfb->cbufs, gmem);
 
diff --git a/src/gallium/drivers/freedreno/a5xx/fd5_program.c b/src/gallium/drivers/freedreno/a5xx/fd5_program.c
index 752442b5ca..fffdc14691 100644
--- a/src/gallium/drivers/freedreno/a5xx/fd5_program.c
+++ b/src/gallium/drivers/freedreno/a5xx/fd5_program.c
@@ -530,27 +530,24 @@ fd5_program_emit(struct fd_ringbuffer *ring, struct fd5_emit *emit)
 	OUT_PKT4(ring, REG_A5XX_PC_PRIM_VTX_CNTL, 1);
 	OUT_RING(ring, COND(s[VS].v->writes_psize, A5XX_PC_PRIM_VTX_CNTL_PSIZE));
 
+	OUT_PKT4(ring, REG_A5XX_SP_PRIMITIVE_CNTL, 1);
+	OUT_RING(ring, A5XX_SP_PRIMITIVE_CNTL_VSOUT(l.cnt));
+
+	OUT_PKT4(ring, REG_A5XX_VPC_CNTL_0, 1);
+	OUT_RING(ring, A5XX_VPC_CNTL_0_STRIDE_IN_VPC(l.max_loc) |
+			COND(s[FS].v->total_in > 0, A5XX_VPC_CNTL_0_VARYING) |
+			COND(s[FS].v->frag_coord, A5XX_VPC_CNTL_0_VARYING) |
+			0x10000);    // XXX
+
+	OUT_PKT4(ring, REG_A5XX_PC_PRIMITIVE_CNTL, 1);
+	OUT_RING(ring, A5XX_PC_PRIMITIVE_CNTL_STRIDE_IN_VPC(l.max_loc) |
+			0x400);      // XXX
+
 	if (emit->key.binning_pass) {
 		OUT_PKT4(ring, REG_A5XX_SP_FS_OBJ_START_LO, 2);
 		OUT_RING(ring, 0x00000000);    /* SP_FS_OBJ_START_LO */
 		OUT_RING(ring, 0x00000000);    /* SP_FS_OBJ_START_HI */
 	} else {
-		// TODO if some of these other bits depend on something other than
-		// program state we should probably move these next three regs:
-
-		OUT_PKT4(ring, REG_A5XX_SP_PRIMITIVE_CNTL, 1);
-		OUT_RING(ring, A5XX_SP_PRIMITIVE_CNTL_VSOUT(l.cnt));
-
-		OUT_PKT4(ring, REG_A5XX_VPC_CNTL_0, 1);
-		OUT_RING(ring, A5XX_VPC_CNTL_0_STRIDE_IN_VPC(l.max_loc) |
-				COND(s[FS].v->total_in > 0, A5XX_VPC_CNTL_0_VARYING) |
-				COND(s[FS].v->frag_coord, A5XX_VPC_CNTL_0_VARYING) |
-				0x10000);    // XXX
-
-		OUT_PKT4(ring, REG_A5XX_PC_PRIMITIVE_CNTL, 1);
-		OUT_RING(ring, A5XX_PC_PRIMITIVE_CNTL_STRIDE_IN_VPC(l.max_loc) |
-				0x400);      // XXX
-
 		OUT_PKT4(ring, REG_A5XX_SP_FS_OBJ_START_LO, 2);
 		OUT_RELOC(ring, s[FS].v->bo, 0, 0, 0);  /* SP_FS_OBJ_START_LO/HI */
 	}
@@ -613,10 +610,12 @@ fd5_program_emit(struct fd_ringbuffer *ring, struct fd5_emit *emit)
 					A5XX_SP_FS_OUTPUT_REG_HALF_PRECISION));
 	}
 
-	if (emit->key.binning_pass) {
-		OUT_PKT4(ring, REG_A5XX_VPC_PACK, 1);
-		OUT_RING(ring, A5XX_VPC_PACK_NUMNONPOSVAR(0));
-	} else {
+
+	OUT_PKT4(ring, REG_A5XX_VPC_PACK, 1);
+	OUT_RING(ring, A5XX_VPC_PACK_NUMNONPOSVAR(s[FS].v->total_in) |
+			A5XX_VPC_PACK_PSIZELOC(psize_loc));
+
+	if (!emit->key.binning_pass) {
 		uint32_t vinterp[8], vpsrepl[8];
 
 		memset(vinterp, 0, sizeof(vinterp));
@@ -698,10 +697,6 @@ fd5_program_emit(struct fd_ringbuffer *ring, struct fd5_emit *emit)
 			}
 		}
 
-		OUT_PKT4(ring, REG_A5XX_VPC_PACK, 1);
-		OUT_RING(ring, A5XX_VPC_PACK_NUMNONPOSVAR(s[FS].v->total_in) |
-				A5XX_VPC_PACK_PSIZELOC(psize_loc));
-
 		OUT_PKT4(ring, REG_A5XX_VPC_VARYING_INTERP_MODE(0), 8);
 		for (i = 0; i < 8; i++)
 			OUT_RING(ring, vinterp[i]);     /* VPC_VARYING_INTERP[i].MODE */
diff --git a/src/gallium/drivers/freedreno/freedreno_context.h b/src/gallium/drivers/freedreno/freedreno_context.h
index bbdfaa1d35..5c63a5ff93 100644
--- a/src/gallium/drivers/freedreno/freedreno_context.h
+++ b/src/gallium/drivers/freedreno/freedreno_context.h
@@ -246,7 +246,7 @@ struct fd_context {
 	 * means we'd always have to recalc tiles ever batch)
 	 */
 	struct fd_gmem_stateobj gmem;
-	struct fd_vsc_pipe      pipe[8];
+	struct fd_vsc_pipe      pipe[16];
 	struct fd_tile          tile[512];
 
 	/* which state objects need to be re-emit'd: */
diff --git a/src/gallium/drivers/freedreno/freedreno_gmem.c b/src/gallium/drivers/freedreno/freedreno_gmem.c
index 310a0266c9..c4dda56494 100644
--- a/src/gallium/drivers/freedreno/freedreno_gmem.c
+++ b/src/gallium/drivers/freedreno/freedreno_gmem.c
@@ -112,6 +112,7 @@ calculate_tiles(struct fd_batch *batch)
 	struct pipe_framebuffer_state *pfb = &batch->framebuffer;
 	const uint32_t gmem_alignw = ctx->screen->gmem_alignw;
 	const uint32_t gmem_alignh = ctx->screen->gmem_alignh;
+	const unsigned npipes = ctx->screen->num_vsc_pipes;
 	const uint32_t gmem_size = ctx->screen->gmemsize_bytes;
 	uint32_t minx, miny, width, height;
 	uint32_t nbins_x = 1, nbins_y = 1;
@@ -121,7 +122,7 @@ calculate_tiles(struct fd_batch *batch)
 	uint32_t i, j, t, xoff, yoff;
 	uint32_t tpp_x, tpp_y;
 	bool has_zs = !!(batch->resolve & (FD_BUFFER_DEPTH | FD_BUFFER_STENCIL));
-	int tile_n[ARRAY_SIZE(ctx->pipe)];
+	int tile_n[npipes];
 
 	if (has_zs) {
 		struct fd_resource *rsc = fd_resource(pfb->zsbuf->texture);
@@ -224,7 +225,7 @@ calculate_tiles(struct fd_batch *batch)
 
 	/* configure pipes: */
 	xoff = yoff = 0;
-	for (i = 0; i < ARRAY_SIZE(ctx->pipe); i++) {
+	for (i = 0; i < npipes; i++) {
 		struct fd_vsc_pipe *pipe = &ctx->pipe[i];
 
 		if (xoff >= nbins_x) {
@@ -244,7 +245,7 @@ calculate_tiles(struct fd_batch *batch)
 		xoff += tpp_x;
 	}
 
-	for (; i < ARRAY_SIZE(ctx->pipe); i++) {
+	for (; i < npipes; i++) {
 		struct fd_vsc_pipe *pipe = &ctx->pipe[i];
 		pipe->x = pipe->y = pipe->w = pipe->h = 0;
 	}
diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c
index e1e02005ae..cb03bdb96b 100644
--- a/src/gallium/drivers/freedreno/freedreno_screen.c
+++ b/src/gallium/drivers/freedreno/freedreno_screen.c
@@ -836,9 +836,11 @@ fd_screen_create(struct fd_device *dev)
 	if (screen->gpu_id >= 500) {
 		screen->gmem_alignw = 64;
 		screen->gmem_alignh = 32;
+		screen->num_vsc_pipes = 16;
 	} else {
 		screen->gmem_alignw = 32;
 		screen->gmem_alignh = 32;
+		screen->num_vsc_pipes = 8;
 	}
 
 	/* NOTE: don't enable reordering on a2xx, since completely untested.
diff --git a/src/gallium/drivers/freedreno/freedreno_screen.h b/src/gallium/drivers/freedreno/freedreno_screen.h
index 3304eef77d..c5018da4bc 100644
--- a/src/gallium/drivers/freedreno/freedreno_screen.h
+++ b/src/gallium/drivers/freedreno/freedreno_screen.h
@@ -66,6 +66,7 @@ struct fd_screen {
 	uint32_t max_freq;
 	uint32_t max_rts;        /* max # of render targets */
 	uint32_t gmem_alignw, gmem_alignh;
+	uint32_t num_vsc_pipes;
 	bool has_timestamp;
 
 	void *compiler;          /* currently unused for a2xx */




More information about the mesa-commit mailing list