[Mesa-dev] [PATCH 8/8] radeonsi: dump buffer lists while debugging

Marek Olšák maraeo at gmail.com
Sun Sep 27 15:53:34 PDT 2015


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

---
 src/gallium/drivers/radeonsi/si_debug.c      | 110 +++++++++++++++++++++++++++
 src/gallium/drivers/radeonsi/si_hw_context.c |  15 +++-
 src/gallium/drivers/radeonsi/si_pipe.c       |   5 ++
 src/gallium/drivers/radeonsi/si_pipe.h       |   2 +
 4 files changed, 131 insertions(+), 1 deletion(-)

diff --git a/src/gallium/drivers/radeonsi/si_debug.c b/src/gallium/drivers/radeonsi/si_debug.c
index 9f2752e..255939e 100644
--- a/src/gallium/drivers/radeonsi/si_debug.c
+++ b/src/gallium/drivers/radeonsi/si_debug.c
@@ -421,6 +421,114 @@ static void si_dump_last_ib(struct si_context *sctx, FILE *f)
 	r600_resource_reference(&sctx->last_trace_buf, NULL);
 }
 
+static const char *priority_to_string(enum radeon_bo_priority priority)
+{
+#define ITEM(x) [RADEON_PRIO_##x] = #x
+	static const char *table[64] = {
+		ITEM(FENCE),
+	        ITEM(TRACE),
+	        ITEM(SO_FILLED_SIZE),
+	        ITEM(QUERY),
+	        ITEM(IB1),
+	        ITEM(IB2),
+	        ITEM(DRAW_INDIRECT),
+	        ITEM(INDEX_BUFFER),
+	        ITEM(CP_DMA),
+	        ITEM(VCE),
+	        ITEM(UVD),
+	        ITEM(SDMA_BUFFER),
+	        ITEM(SDMA_TEXTURE),
+	        ITEM(USER_SHADER),
+	        ITEM(INTERNAL_SHADER),
+	        ITEM(CONST_BUFFER),
+	        ITEM(DESCRIPTORS),
+	        ITEM(BORDER_COLORS),
+	        ITEM(SAMPLER_BUFFER),
+	        ITEM(VERTEX_BUFFER),
+	        ITEM(SHADER_RW_BUFFER),
+	        ITEM(RINGS_STREAMOUT),
+	        ITEM(SCRATCH_BUFFER),
+	        ITEM(COMPUTE_GLOBAL),
+	        ITEM(SAMPLER_TEXTURE),
+	        ITEM(SHADER_RW_IMAGE),
+	        ITEM(SAMPLER_TEXTURE_MSAA),
+	        ITEM(COLOR_BUFFER),
+	        ITEM(DEPTH_BUFFER),
+	        ITEM(COLOR_BUFFER_MSAA),
+	        ITEM(DEPTH_BUFFER_MSAA),
+	        ITEM(CMASK),
+	        ITEM(DCC),
+	        ITEM(HTILE),
+	};
+#undef ITEM
+
+	assert(priority < ARRAY_SIZE(table));
+	return table[priority];
+}
+
+static int bo_list_compare_va(const struct radeon_bo_list_item *a,
+				   const struct radeon_bo_list_item *b)
+{
+	return a->vm_address < b->vm_address ? -1 :
+	       a->vm_address > b->vm_address ? 1 : 0;
+}
+
+static void si_dump_last_bo_list(struct si_context *sctx, FILE *f)
+{
+	unsigned i,j;
+
+	if (!sctx->last_bo_list)
+		return;
+
+	/* Sort the list according to VM adddresses first. */
+	qsort(sctx->last_bo_list, sctx->last_bo_count,
+	      sizeof(sctx->last_bo_list[0]), (void*)bo_list_compare_va);
+
+	fprintf(f, "Buffer list (in units of pages = 4kB):\n"
+		COLOR_YELLOW "        Size    VM start page         "
+		"VM end page           Usage" COLOR_RESET "\n");
+
+	for (i = 0; i < sctx->last_bo_count; i++) {
+		/* Note: Buffer sizes are expected to be aligned to 4k by the winsys. */
+		const unsigned page_size = 4096;
+		uint64_t va = sctx->last_bo_list[i].vm_address;
+		uint64_t size = sctx->last_bo_list[i].buf->size;
+		bool hit = false;
+
+		/* If there's unused virtual memory between 2 buffers, print it. */
+		if (i) {
+			uint64_t previous_va_end = sctx->last_bo_list[i-1].vm_address +
+						   sctx->last_bo_list[i-1].buf->size;
+
+			if (va > previous_va_end) {
+				fprintf(f, "  %10"PRIu64"    -- hole --\n",
+					(va - previous_va_end) / page_size);
+			}
+		}
+
+		/* Print the buffer. */
+		fprintf(f, "  %10"PRIu64"    0x%013"PRIx64"       0x%013"PRIx64"       ",
+			size / page_size, va / page_size, (va + size) / page_size);
+
+		/* Print the usage. */
+		for (j = 0; j < 64; j++) {
+			if (!(sctx->last_bo_list[i].priority_usage & (1llu << j)))
+				continue;
+
+			fprintf(f, "%s%s", !hit ? "" : ", ", priority_to_string(j));
+			hit = true;
+		}
+		fprintf(f, "\n");
+	}
+	fprintf(f, "\nNote: The holes represent memory not used by the IB.\n"
+		   "      Other buffers can still be allocated there.\n\n");
+
+	for (i = 0; i < sctx->last_bo_count; i++)
+		pb_reference(&sctx->last_bo_list[i].buf, NULL);
+	free(sctx->last_bo_list);
+	sctx->last_bo_list = NULL;
+}
+
 static void si_dump_debug_state(struct pipe_context *ctx, FILE *f,
 				unsigned flags)
 {
@@ -435,6 +543,7 @@ static void si_dump_debug_state(struct pipe_context *ctx, FILE *f,
 	si_dump_shader(sctx->gs_shader, "Geometry", f);
 	si_dump_shader(sctx->ps_shader, "Fragment", f);
 
+	si_dump_last_bo_list(sctx, f);
 	si_dump_last_ib(sctx, f);
 
 	fprintf(f, "Done.\n");
@@ -539,6 +648,7 @@ void si_check_vm_faults(struct si_context *sctx)
 	fprintf(f, "Device name: %s\n\n", screen->get_name(screen));
 	fprintf(f, "Failing VM page: 0x%08x\n\n", addr);
 
+	si_dump_last_bo_list(sctx, f);
 	si_dump_last_ib(sctx, f);
 	fclose(f);
 
diff --git a/src/gallium/drivers/radeonsi/si_hw_context.c b/src/gallium/drivers/radeonsi/si_hw_context.c
index de95d12..17d89d1 100644
--- a/src/gallium/drivers/radeonsi/si_hw_context.c
+++ b/src/gallium/drivers/radeonsi/si_hw_context.c
@@ -85,14 +85,27 @@ void si_context_gfx_flush(void *context, unsigned flags,
 	if (ctx->trace_buf)
 		si_trace_emit(ctx);
 
-	/* Save the IB for debug contexts. */
 	if (ctx->is_debug) {
+		unsigned i;
+
+		/* Save the IB for debug contexts. */
 		free(ctx->last_ib);
 		ctx->last_ib_dw_size = cs->cdw;
 		ctx->last_ib = malloc(cs->cdw * 4);
 		memcpy(ctx->last_ib, cs->buf, cs->cdw * 4);
 		r600_resource_reference(&ctx->last_trace_buf, ctx->trace_buf);
 		r600_resource_reference(&ctx->trace_buf, NULL);
+
+		/* Save the buffer list. */
+		if (ctx->last_bo_list) {
+			for (i = 0; i < ctx->last_bo_count; i++)
+				pb_reference(&ctx->last_bo_list[i].buf, NULL);
+			free(ctx->last_bo_list);
+		}
+		ctx->last_bo_count = ws->cs_get_buffer_list(cs, NULL);
+		ctx->last_bo_list = calloc(ctx->last_bo_count,
+					   sizeof(ctx->last_bo_list[0]));
+		ws->cs_get_buffer_list(cs, ctx->last_bo_list);
 	}
 
 	/* Flush the CS. */
diff --git a/src/gallium/drivers/radeonsi/si_pipe.c b/src/gallium/drivers/radeonsi/si_pipe.c
index 5a2b606..cdd33aa 100644
--- a/src/gallium/drivers/radeonsi/si_pipe.c
+++ b/src/gallium/drivers/radeonsi/si_pipe.c
@@ -81,6 +81,11 @@ static void si_destroy_context(struct pipe_context *context)
 	r600_resource_reference(&sctx->trace_buf, NULL);
 	r600_resource_reference(&sctx->last_trace_buf, NULL);
 	free(sctx->last_ib);
+	if (sctx->last_bo_list) {
+		for (i = 0; i < sctx->last_bo_count; i++)
+			pb_reference(&sctx->last_bo_list[i].buf, NULL);
+		free(sctx->last_bo_list);
+	}
 	FREE(sctx);
 }
 
diff --git a/src/gallium/drivers/radeonsi/si_pipe.h b/src/gallium/drivers/radeonsi/si_pipe.h
index 1c26022..41b2832 100644
--- a/src/gallium/drivers/radeonsi/si_pipe.h
+++ b/src/gallium/drivers/radeonsi/si_pipe.h
@@ -277,6 +277,8 @@ struct si_context {
 	struct r600_resource	*trace_buf;
 	unsigned		trace_id;
 	uint64_t		dmesg_timestamp;
+	unsigned		last_bo_count;
+	struct radeon_bo_list_item *last_bo_list;
 };
 
 /* cik_sdma.c */
-- 
2.1.4



More information about the mesa-dev mailing list