aboutsummaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/radeonsi/si_debug.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/radeonsi/si_debug.c')
-rw-r--r--src/gallium/drivers/radeonsi/si_debug.c67
1 files changed, 63 insertions, 4 deletions
diff --git a/src/gallium/drivers/radeonsi/si_debug.c b/src/gallium/drivers/radeonsi/si_debug.c
index 72b7989e92c..cf09686c636 100644
--- a/src/gallium/drivers/radeonsi/si_debug.c
+++ b/src/gallium/drivers/radeonsi/si_debug.c
@@ -142,7 +142,8 @@ static void si_parse_set_reg_packet(FILE *f, uint32_t *ib, unsigned count,
si_dump_reg(f, reg + i*4, ib[2+i], ~0);
}
-static uint32_t *si_parse_packet3(FILE *f, uint32_t *ib, int *num_dw)
+static uint32_t *si_parse_packet3(FILE *f, uint32_t *ib, int *num_dw,
+ int trace_id)
{
unsigned count = PKT_COUNT_G(ib[0]);
unsigned op = PKT3_IT_OPCODE_G(ib[0]);
@@ -232,6 +233,36 @@ static uint32_t *si_parse_packet3(FILE *f, uint32_t *ib, int *num_dw)
if (ib[0] == 0xffff1000) {
count = -1; /* One dword NOP. */
break;
+ } else if (count == 0 && SI_IS_TRACE_POINT(ib[1])) {
+ unsigned packet_id = SI_GET_TRACE_POINT_ID(ib[1]);
+
+ print_spaces(f, INDENT_PKT);
+ fprintf(f, COLOR_RED "Trace point ID: %u\n", packet_id);
+
+ if (trace_id == -1)
+ break; /* tracing was disabled */
+
+ print_spaces(f, INDENT_PKT);
+ if (packet_id < trace_id)
+ fprintf(f, COLOR_RED
+ "This trace point was reached by the CP."
+ COLOR_RESET "\n");
+ else if (packet_id == trace_id)
+ fprintf(f, COLOR_RED
+ "!!!!! This is the last trace point that "
+ "was reached by the CP !!!!!"
+ COLOR_RESET "\n");
+ else if (packet_id+1 == trace_id)
+ fprintf(f, COLOR_RED
+ "!!!!! This is the first trace point that "
+ "was NOT been reached by the CP !!!!!"
+ COLOR_RESET "\n");
+ else
+ fprintf(f, COLOR_RED
+ "!!!!! This trace point was NOT reached "
+ "by the CP !!!!!"
+ COLOR_RESET "\n");
+ break;
}
/* fall through, print all dwords */
default:
@@ -246,7 +277,17 @@ static uint32_t *si_parse_packet3(FILE *f, uint32_t *ib, int *num_dw)
return ib;
}
-static void si_parse_ib(FILE *f, uint32_t *ib, int num_dw)
+/**
+ * Parse and print an IB into a file.
+ *
+ * \param f file
+ * \param ib IB
+ * \param num_dw size of the IB
+ * \param chip_class chip class
+ * \param trace_id the last trace ID that is known to have been reached
+ * and executed by the CP, typically read from a buffer
+ */
+static void si_parse_ib(FILE *f, uint32_t *ib, int num_dw, int trace_id)
{
fprintf(f, "------------------ IB begin ------------------\n");
@@ -255,7 +296,7 @@ static void si_parse_ib(FILE *f, uint32_t *ib, int num_dw)
switch (type) {
case 3:
- ib = si_parse_packet3(f, ib, &num_dw);
+ ib = si_parse_packet3(f, ib, &num_dw, trace_id);
break;
case 2:
/* type-2 nop */
@@ -342,9 +383,27 @@ static void si_dump_debug_state(struct pipe_context *ctx, FILE *f,
si_dump_shader(sctx->ps_shader, "Fragment", f);
if (sctx->last_ib) {
- si_parse_ib(f, sctx->last_ib, sctx->last_ib_dw_size);
+ int last_trace_id = -1;
+
+ if (sctx->last_trace_buf) {
+ /* We are expecting that the ddebug pipe has already
+ * waited for the context, so this buffer should be idle.
+ * If the GPU is hung, there is no point in waiting for it.
+ */
+ uint32_t *map =
+ sctx->b.ws->buffer_map(sctx->last_trace_buf->cs_buf,
+ NULL,
+ PIPE_TRANSFER_UNSYNCHRONIZED |
+ PIPE_TRANSFER_READ);
+ if (map)
+ last_trace_id = *map;
+ }
+
+ si_parse_ib(f, sctx->last_ib, sctx->last_ib_dw_size,
+ last_trace_id);
free(sctx->last_ib); /* dump only once */
sctx->last_ib = NULL;
+ r600_resource_reference(&sctx->last_trace_buf, NULL);
}
fprintf(f, "Done.\n");