radeonsi: dump buffer lists while debugging
authorMarek Olšák <marek.olsak@amd.com>
Sat, 26 Sep 2015 23:38:48 +0000 (01:38 +0200)
committerMarek Olšák <marek.olsak@amd.com>
Sat, 3 Oct 2015 20:06:08 +0000 (22:06 +0200)
Reviewed-by: Michel Dänzer <michel.daenzer@amd.com>
src/gallium/drivers/radeonsi/si_debug.c
src/gallium/drivers/radeonsi/si_hw_context.c
src/gallium/drivers/radeonsi/si_pipe.c
src/gallium/drivers/radeonsi/si_pipe.h

index 3d12723683156367c8c86276e94fc6f98c63620f..7d41e8d00e05a7651c1e6239e444a1a58003711d 100644 (file)
@@ -420,6 +420,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)
 {
@@ -434,6 +542,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");
@@ -538,6 +647,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);
 
index de95d12f000a65aab7426853cd04969198deeb66..17d89d16e24550f46d08a0b9d343bcad0f1164e7 100644 (file)
@@ -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. */
index 5a2b60620e31c638fa8e04c410e82ea961fd43dc..cdd33aa0831c722a4eb9ee86f93b8dd5eb2c2383 100644 (file)
@@ -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);
 }
 
index 1c26022bb1b21772368b0881493e39f02ec456f6..41b2832322c9262e7ce3c10a9fdbe0468625664d 100644 (file)
@@ -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 */