[Mesa-stable] [PATCH] radeonsi: fix CP DMA hazard with index buffer fetches

Marek Olšák maraeo at gmail.com
Tue May 31 15:16:47 UTC 2016


From: Marek Olšák <marek.olsak at amd.com>

Reviewed-by: Alex Deucher <alexander.deucher at amd.com>
Cc: 12.0 <mesa-stable at lists.freedesktop.org>

---
 src/gallium/drivers/radeonsi/si_cp_dma.c | 22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/src/gallium/drivers/radeonsi/si_cp_dma.c b/src/gallium/drivers/radeonsi/si_cp_dma.c
index cbb84b0..882458c 100644
--- a/src/gallium/drivers/radeonsi/si_cp_dma.c
+++ b/src/gallium/drivers/radeonsi/si_cp_dma.c
@@ -73,12 +73,23 @@ static void si_emit_cp_dma_copy_buffer(struct si_context *sctx,
 		radeon_emit(cs, (dst_va >> 32) & 0xffff);	/* DST_ADDR_HI [15:0] */
 		radeon_emit(cs, size | wr_confirm | raw_wait);	/* COMMAND [29:22] | BYTE_COUNT [20:0] */
 	}
+
+	/* CP DMA is executed in ME, but index buffers are read by PFP.
+	 * This ensures that ME (CP DMA) is idle before PFP starts fetching
+	 * indices. If we wanted to execute CP DMA in PFP, this packet
+	 * should precede it.
+	 */
+	if (sync_flag) {
+		radeon_emit(cs, PKT3(PKT3_PFP_SYNC_ME, 0, 0));
+		radeon_emit(cs, 0);
+	}
 }
 
 /* Emit a CP DMA packet to clear a buffer. The size must fit in bits [20:0]. */
 static void si_emit_cp_dma_clear_buffer(struct si_context *sctx,
 					uint64_t dst_va, unsigned size,
-					uint32_t clear_value, unsigned flags)
+					uint32_t clear_value, unsigned flags,
+					enum r600_coherency coher)
 {
 	struct radeon_winsys_cs *cs = sctx->b.gfx.cs;
 	uint32_t sync_flag = flags & R600_CP_DMA_SYNC ? S_411_CP_SYNC(1) : 0;
@@ -105,6 +116,12 @@ static void si_emit_cp_dma_clear_buffer(struct si_context *sctx,
 		radeon_emit(cs, (dst_va >> 32) & 0xffff);	/* DST_ADDR_HI [15:0] */
 		radeon_emit(cs, size | wr_confirm | raw_wait);	/* COMMAND [29:22] | BYTE_COUNT [20:0] */
 	}
+
+	/* See "copy_buffer" for explanation. */
+	if (coher == R600_COHERENCY_SHADER && sync_flag) {
+		radeon_emit(cs, PKT3(PKT3_PFP_SYNC_ME, 0, 0));
+		radeon_emit(cs, 0);
+	}
 }
 
 static unsigned get_flush_flags(struct si_context *sctx, enum r600_coherency coher)
@@ -207,7 +224,8 @@ static void si_clear_buffer(struct pipe_context *ctx, struct pipe_resource *dst,
 		si_cp_dma_prepare(sctx, dst, NULL, byte_count, size, &dma_flags);
 
 		/* Emit the clear packet. */
-		si_emit_cp_dma_clear_buffer(sctx, va, byte_count, value, dma_flags);
+		si_emit_cp_dma_clear_buffer(sctx, va, byte_count, value,
+					    dma_flags, coher);
 
 		size -= byte_count;
 		va += byte_count;
-- 
2.7.4



More information about the mesa-stable mailing list