From 6d6d5b869c5a4afd7fb30c7a5b1def8fcc14d255 Mon Sep 17 00:00:00 2001 From: Danylo Piliaiev Date: Mon, 14 Oct 2024 15:32:52 +0200 Subject: [PATCH] freedreno/cffdec: Add option to dump bindless descriptors cffdump --bindless would dump bindless descriptors. We don't know what exactly is in the descriptors, so we dump all interpretations for each of them. Example: set[1]: UBO[0]: { BASE_LO = 0x23806420 } { BASE_HI = 0xc | SIZE = 0x2 } STORAGE/TEXEL/IMAGE[0]: { TILE_MODE = TILE6_LINEAR | SWIZ_X = A6XX_TEX_Z | SWIZ_Y = A6XX_TEX_X | SWIZ_Z = A6XX_TEX_Y | SWIZ_W = A6XX_TEX_W | MIPLVLS = 0 | SAMPLES = MSAA_ONE | FMT = FMT6_R8_G8B8_2PLANE_420_UNORM | SWAP = WZYX } { WIDTH = 12 | HEIGHT = 8 } { STRUCTSIZETEXELS = 1024 | STARTOFFSETTEXELS = 0 | PITCHALIGN = 1 | PITCH = 128 | TYPE = A6XX_TEX_2D } { ARRAY_PITCH = 4096 | MIN_LAYERSZ = 0 } { BASE_LO = 0xa5000 } { BASE_HI = 0x1 | DEPTH = 1 } { MIN_LOD_CLAMP = 0.000000 | PLANE_PITCH = 128 } { FLAG_LO = 0xa6000 } { FLAG_HI = 0x1 } { FLAG_BUFFER_ARRAY_PITCH = 327680 | 0xa0000 } { FLAG_BUFFER_PITCH = 64 | FLAG_BUFFER_LOGW = 0 | FLAG_BUFFER_LOGH = 0 } { 11 = 0 } { 12 = 0 } { 13 = 0 } { 14 = 0 } { 15 = 0 } SAMPLER[0]: { XY_MAG = A6XX_TEX_NEAREST | XY_MIN = A6XX_TEX_NEAREST | WRAP_S = A6XX_TEX_CLAMP_TO_EDGE | WRAP_T = A6XX_TEX_MIRROR_CLAMP | WRAP_R = A6XX_TEX_MIRROR_CLAMP | ANISO = A6XX_TEX_ANISO_2 | LOD_BIAS = 4.437500 } { COMPARE_FUNC = FUNC_GEQUAL | MAX_LOD = 4.000000 | MIN_LOD = 0.000000 } { REDUCTION_MODE = A6XX_REDUCTION_MODE_MIN | BCOLOR = 0x400080 } { 3 = 0x1 } Signed-off-by: Danylo Piliaiev Part-of: --- src/freedreno/decode/cffdec.c | 79 ++++++++++++++++++++++++++++++++-- src/freedreno/decode/cffdec.h | 1 + src/freedreno/decode/cffdump.c | 2 + 3 files changed, 79 insertions(+), 3 deletions(-) diff --git a/src/freedreno/decode/cffdec.c b/src/freedreno/decode/cffdec.c index d816d2e7472..e7f7c42f113 100644 --- a/src/freedreno/decode/cffdec.c +++ b/src/freedreno/decode/cffdec.c @@ -1490,6 +1490,67 @@ dump_tex_const(uint32_t *texconst, int num_unit, int level) } } +static void +dump_bindless_descriptors(bool is_compute, int level) +{ + if (!options->dump_bindless) + return; + + printl(2, "%sdraw[%i] bindless descriptors\n", levels[level], draw_count); + + for (unsigned i = 0; i < 128; i++) { + static char reg_name[64]; + if (is_compute) { + sprintf(reg_name, "SP_CS_BINDLESS_BASE[%u].DESCRIPTOR", i); + } else { + sprintf(reg_name, "SP_BINDLESS_BASE[%u].DESCRIPTOR", i); + } + const unsigned base_reg = regbase(reg_name); + if (!base_reg) + break; + + printl(2, "%sset[%u]:\n", levels[level + 1], i); + + uint64_t ext_src_addr; + if (is_64b()) { + const unsigned reg = base_reg + i * 2; + if (!reg_written(reg)) + continue; + + ext_src_addr = reg_val(reg) & 0xfffffffc; + ext_src_addr |= ((uint64_t)reg_val(reg + 1)) << 32; + } else { + const unsigned reg = base_reg + i; + if (!reg_written(reg)) + continue; + + ext_src_addr = reg_val(reg) & 0xfffffffc; + } + + uint32_t *contents = NULL; + if (ext_src_addr) + contents = hostptr(ext_src_addr); + + if (!contents) + continue; + + unsigned length = hostlen(ext_src_addr); + unsigned desc_count = length / (16 * sizeof(uint32_t)); + for (unsigned desc_idx = 0; desc_idx < desc_count; desc_idx++) { + printl(2, "%sUBO[%u]:\n", levels[level + 1], desc_idx); + dump_domain(contents, 2, level + 2, "A6XX_UBO"); + + printl(2, "%sSTORAGE/TEXEL/IMAGE[%u]:\n", levels[level + 1], desc_idx); + dump_tex_const(contents, 1, level); + + printl(2, "%sSAMPLER[%u]:\n", levels[level + 1], desc_idx); + dump_tex_samp(contents, STATE_SRC_BINDLESS, 1, level); + + contents += 16; + } + } +} + static void cp_load_state(uint32_t *dwords, uint32_t sizedwords, int level) { @@ -2027,8 +2088,10 @@ cp_draw_indx(uint32_t *dwords, uint32_t sizedwords, int level) } /* don't bother dumping registers for the dummy draw_indx's.. */ - if (num_indices > 0) + if (num_indices > 0) { + dump_bindless_descriptors(false, level); dump_register_summary(level); + } needs_wfi = true; } @@ -2069,8 +2132,10 @@ cp_draw_indx_2(uint32_t *dwords, uint32_t sizedwords, int level) } /* don't bother dumping registers for the dummy draw_indx's.. */ - if (num_indices > 0) + if (num_indices > 0) { + dump_bindless_descriptors(false, level); dump_register_summary(level); + } } static void @@ -2083,8 +2148,10 @@ cp_draw_indx_offset(uint32_t *dwords, uint32_t sizedwords, int level) print_mode(level); /* don't bother dumping registers for the dummy draw_indx's.. */ - if (num_indices > 0) + if (num_indices > 0) { + dump_bindless_descriptors(false, level); dump_register_summary(level); + } } static void @@ -2108,6 +2175,7 @@ cp_draw_indx_indirect(uint32_t *dwords, uint32_t sizedwords, int level) addr = dwords[3]; dump_gpuaddr_size(addr, level, 0x10, 2); + dump_bindless_descriptors(false, level); dump_register_summary(level); } @@ -2123,6 +2191,7 @@ cp_draw_indirect(uint32_t *dwords, uint32_t sizedwords, int level) addr = (((uint64_t)dwords[2] & 0x1ffff) << 32) | dwords[1]; dump_gpuaddr_size(addr, level, 0x10, 2); + dump_bindless_descriptors(false, level); dump_register_summary(level); } @@ -2182,6 +2251,7 @@ cp_draw_indirect_multi(uint32_t *dwords, uint32_t sizedwords, int level) } } + dump_bindless_descriptors(false, level); dump_register_summary(level); } @@ -2193,6 +2263,7 @@ cp_draw_auto(uint32_t *dwords, uint32_t sizedwords, int level) do_query(rnn_enumname(rnn, "pc_di_primtype", prim_type), 0); print_mode(level); + dump_bindless_descriptors(false, level); dump_register_summary(level); } @@ -2619,6 +2690,7 @@ static void cp_exec_cs(uint32_t *dwords, uint32_t sizedwords, int level) { do_query("compute", 0); + dump_bindless_descriptors(true, level); dump_register_summary(level); } @@ -2637,6 +2709,7 @@ cp_exec_cs_indirect(uint32_t *dwords, uint32_t sizedwords, int level) dump_gpuaddr_size(addr, level, 0x10, 2); do_query("compute", 0); + dump_bindless_descriptors(true, level); dump_register_summary(level); } diff --git a/src/freedreno/decode/cffdec.h b/src/freedreno/decode/cffdec.h index 4a08e2d95d3..95748307cba 100644 --- a/src/freedreno/decode/cffdec.h +++ b/src/freedreno/decode/cffdec.h @@ -35,6 +35,7 @@ struct cffdec_options { int summary; int allregs; int dump_textures; + int dump_bindless; int decode_markers; char *script; diff --git a/src/freedreno/decode/cffdump.c b/src/freedreno/decode/cffdump.c index 64ed7fb357f..030c291a549 100644 --- a/src/freedreno/decode/cffdump.c +++ b/src/freedreno/decode/cffdump.c @@ -67,6 +67,7 @@ print_usage(const char *name) "\t-D, --draw=N - decode only draw N\n" "\t-e, --exe=NAME - only decode cmdstream from named process\n" "\t--textures - dump texture contents (if possible)\n" + "\t--bindless - dump bindless descriptors contents (if possible)\n" "\t-L, --script=LUA - run specified lua script to analyze state\n" "\t-q, --query=REG - query mode, dump only specified query registers on\n" "\t each draw; multiple --query/-q args can be given to\n" @@ -104,6 +105,7 @@ static const struct option opts[] = { { "no-pager", no_argument, &interactive, 0 }, { "pager", no_argument, &interactive, 1 }, { "textures", no_argument, &options.dump_textures, 1 }, + { "bindless", no_argument, &options.dump_bindless, 1 }, { "show-compositor", no_argument, &show_comp, 1 }, { "query-all", no_argument, &options.query_mode, QUERY_ALL }, { "query-written", no_argument, &options.query_mode, QUERY_WRITTEN },