diff --git a/src/freedreno/decode/rdcompiler-meson.build b/src/freedreno/decode/rdcompiler-meson.build index 020db1585ed..79fdd90da84 100644 --- a/src/freedreno/decode/rdcompiler-meson.build +++ b/src/freedreno/decode/rdcompiler-meson.build @@ -4,22 +4,30 @@ # Before compiling, create "subprojects" directory and create a link # to mesa there. -project('generate_rd', ['c'], default_options : ['c_std=c11']) +project('generate_rd', ['c', 'cpp'], default_options : ['c_std=c11', 'cpp_std=c++17']) -mesa_proj = subproject('mesa', - default_options : ['gallium-drivers=', - 'dri-drivers=', - 'glx=disabled', - 'vulkan-drivers=', - 'tools=freedreno']) +mesa_options = ['gallium-drivers=', + 'vulkan-drivers=', + 'glx=disabled', + 'tools=freedreno'] -add_project_arguments(mesa_proj.get_variable('pre_args'), language : ['c']) +if host_machine.system() == 'android' + mesa_options += ['platforms=android', + 'platform-sdk-version=28', + 'android-stub=true'] +endif + +mesa_proj = subproject('mesa', default_options : mesa_options) + +add_project_arguments(mesa_proj.get_variable('pre_args'), language : ['c', 'cpp']) add_project_arguments(mesa_proj.get_variable('c_args'), language : ['c']) +add_project_arguments(mesa_proj.get_variable('c_cpp_args'), language : ['c', 'cpp']) +add_project_arguments(mesa_proj.get_variable('cpp_args'), language : ['cpp']) generate_rd = executable( 'generate_rd', [ - 'generate_rd.c' + 'generate_rd.cc' ], include_directories: [ mesa_proj.get_variable('inc_freedreno'), diff --git a/src/freedreno/decode/rdcompiler-utils.h b/src/freedreno/decode/rdcompiler-utils.h index fadaa541f5f..0b1b534efa1 100644 --- a/src/freedreno/decode/rdcompiler-utils.h +++ b/src/freedreno/decode/rdcompiler-utils.h @@ -110,7 +110,7 @@ struct rd_section { static struct cmdstream * cs_alloc(struct replay_context *ctx, uint32_t size) { - struct cmdstream *cs = calloc(1, sizeof(struct cmdstream)); + struct cmdstream *cs = (struct cmdstream *) calloc(1, sizeof(struct cmdstream)); cs->mem = (uint32_t *)calloc(1, size); cs->total_size = size / sizeof(uint32_t); cs->cur = 0; @@ -129,7 +129,8 @@ rd_write_cs_buffer(FILE *out, struct cmdstream *cs) if (cs->cur == 0) return; - const uint32_t packet[] = {(uint32_t)cs->iova, cs->cur * sizeof(uint32_t), + const uint32_t packet[] = {(uint32_t)cs->iova, + (uint32_t)(cs->cur * sizeof(uint32_t)), (uint32_t)(cs->iova >> 32)}; struct rd_section section_address = {.type = RD_GPUADDR, .size = sizeof(packet)}; @@ -137,7 +138,7 @@ rd_write_cs_buffer(FILE *out, struct cmdstream *cs) fwrite(packet, sizeof(packet), 1, out); struct rd_section section_contents = {.type = RD_BUFFER_CONTENTS, - .size = cs->cur * sizeof(uint32_t)}; + .size = uint32_t(cs->cur * sizeof(uint32_t))}; fwrite(§ion_contents, sizeof(section_contents), 1, out); fwrite(cs->mem, sizeof(uint32_t), cs->cur, out); @@ -222,8 +223,9 @@ replay_context_init(struct replay_context *ctx, struct fd_dev_id *dev_id, ctx->state_cs = cs_alloc(ctx, 2 * 1024 * 1024); ctx->shader_cs = cs_alloc(ctx, 8 * 1024 * 1024); + struct ir3_compiler_options options{}; ctx->compiler = - ir3_compiler_create(NULL, dev_id, &(struct ir3_compiler_options){}); + ir3_compiler_create(NULL, dev_id, &options); ctx->compiled_shaders = _mesa_hash_table_u64_create(ctx->mem_ctx); } @@ -271,7 +273,7 @@ upload_shader(struct replay_context *ctx, uint64_t id, const char *source) static void emit_shader_iova(struct replay_context *ctx, struct cmdstream *cs, uint64_t id) { - uint64_t *shader_iova = + uint64_t *shader_iova = (uint64_t *) _mesa_hash_table_u64_search(ctx->compiled_shaders, id); pkt_qw(cs, *shader_iova); } diff --git a/src/freedreno/decode/rddecompiler.c b/src/freedreno/decode/rddecompiler.c index 93324e44d13..2011bbb8b74 100644 --- a/src/freedreno/decode/rddecompiler.c +++ b/src/freedreno/decode/rddecompiler.c @@ -85,16 +85,24 @@ print_usage(const char *name) "\t%s [OPTSIONS]... FILE...\n\n" "Options:\n" "\t-s, --submit=№ - № of the submit to decompile\n" + "\t--no-reg-bunch - Use pkt4 for each reg in CP_CONTEXT_REG_BUNCH\n" "\t-h, --help - show this message\n" , name); /* clang-format on */ exit(2); } +struct decompiler_options { + int no_reg_bunch; +}; + +static struct decompiler_options options = {}; + /* clang-format off */ static const struct option opts[] = { - { "submit", required_argument, 0, 's' }, - { "help", no_argument, 0, 'h' }, + { "submit", required_argument, 0, 's' }, + { "no-reg-bunch", no_argument, &options.no_reg_bunch, 1 }, + { "help", no_argument, 0, 'h' }, }; /* clang-format on */ @@ -231,6 +239,7 @@ decompile_register(uint32_t regbase, uint32_t *dwords, uint16_t cnt, int level) if (cnt == 0) { printlvl(level, "pkt(cs, %u);\n", dword); } else { +#if 0 char reg_name[33]; char field_name[33]; char reg_idx[33]; @@ -247,10 +256,16 @@ decompile_register(uint32_t regbase, uint32_t *dwords, uint16_t cnt, int level) printlvl(level, "pkt4(cs, REG_%s_%s_%s(%s), (%u), %u);\n", rnn->variant, reg_name, field_name, reg_idx, cnt, dword); } +#else + /* TODO: We don't have easy way to get chip generation prefix, + * so just emit raw packet offset as a workaround. + */ + printlvl(level, "pkt4(cs, 0x%04x, (%u), %u);\n", regbase, cnt, dword); +#endif } } else { printlvl(level, "/* unknown pkt4 */\n"); - printlvl(level, "pkt4(cs, %u, (%u), %u);\n", regbase, cnt, dword); + printlvl(level, "pkt4(cs, 0x%04x, (%u), %u);\n", regbase, 1, dword); } rnn_reginfo_free(info); @@ -258,6 +273,27 @@ decompile_register(uint32_t regbase, uint32_t *dwords, uint16_t cnt, int level) return 1; } +static uint32_t +decompile_register_reg_bunch(uint32_t regbase, uint32_t *dwords, uint16_t cnt, int level) +{ + struct rnndecaddrinfo *info = rnn_reginfo(rnn, regbase); + const uint32_t dword = *dwords; + + if (info && info->typeinfo) { + char *decoded = rnndec_decodeval(rnn->vc, info->typeinfo, dword); + printlvl(level, "/* reg: %s = %s */\n", info->name, decoded); + } else { + printlvl(level, "/* unknown pkt4 */\n"); + } + + printlvl(level, "pkt(cs, 0x%04x);\n", regbase); + printlvl(level, "pkt(cs, %u);\n", dword); + + rnn_reginfo_free(info); + + return 1; +} + static void decompile_registers(uint32_t regbase, uint32_t *dwords, uint32_t sizedwords, int level) @@ -313,14 +349,18 @@ decompile_domain(uint32_t pkt, uint32_t *dwords, uint32_t sizedwords, continue; } uint64_t value = dwords[i]; - if (info->typeinfo->high >= 32 && i < sizedwords - 1) { + bool reg64 = info->typeinfo->high >= 32 && i < sizedwords - 1; + if (reg64) { value |= (uint64_t)dwords[i + 1] << 32; - i++; /* skip the next dword since we're printing it now */ } decoded = rnndec_decodeval(rnn->vc, info->typeinfo, value); printlvl(level, "/* %s */\n", decoded); printlvl(level, "pkt(cs, %u);\n", dwords[i]); + if (reg64) { + printlvl(level, "pkt(cs, %u);\n", dwords[i + 1]); + i++; + } free(decoded); free(info->name); @@ -383,6 +423,41 @@ decompile_commands(uint32_t *dwords, uint32_t sizedwords, int level) "CP_SET_DRAW_STATE", level); } } + } else if (val == CP_CONTEXT_REG_BUNCH || val == CP_CONTEXT_REG_BUNCH2) { + uint32_t *dw = dwords + 1; + uint32_t cnt = count - 1; + + if (val == CP_CONTEXT_REG_BUNCH2) { + if (options.no_reg_bunch) { + printlvl(level, "// CP_CONTEXT_REG_BUNCH2\n"); + printlvl(level, "{\n"); + } else { + printlvl(level, "pkt7(cs, %s, %u);\n", "CP_CONTEXT_REG_BUNCH2", cnt); + printlvl(level, "{\n"); + printlvl(level + 1, "pkt(cs, %u);\n", dw[0]); + printlvl(level + 1, "pkt(cs, %u);\n", dw[1]); + } + + dw += 2; + cnt -= 2; + } else { + if (options.no_reg_bunch) { + printlvl(level, "// CP_CONTEXT_REG_BUNCH\n"); + printlvl(level, "{\n"); + } else { + printlvl(level, "pkt7(cs, %s, %u);\n", "CP_CONTEXT_REG_BUNCH", cnt); + printlvl(level, "{\n"); + } + } + + for (uint32_t i = 0; i < cnt; i += 2) { + if (options.no_reg_bunch) { + decompile_register(dw[i], &dw[i + 1], 1, level + 1); + } else { + decompile_register_reg_bunch(dw[i], &dw[i + 1], 1, level + 1); + } + } + printlvl(level, "}\n"); } else { const char *packet_name = pktname(val); const char *dom_name = packet_name; @@ -414,7 +489,7 @@ decompile_commands(uint32_t *dwords, uint32_t sizedwords, int level) static void emit_header() { - if (!dev_id.gpu_id || !dev_id.chip_id) + if (!dev_id.gpu_id && !dev_id.chip_id) return; static bool emitted = false; @@ -422,6 +497,17 @@ emit_header() return; emitted = true; + switch (fd_dev_gen(&dev_id)) { + case 6: + init_rnn("a6xx"); + break; + case 7: + init_rnn("a7xx"); + break; + default: + errx(-1, "unsupported gpu: %u", dev_id.gpu_id); + } + printf("#include \"decode/rdcompiler-utils.h\"\n" "int main(int argc, char **argv)\n" "{\n" @@ -462,7 +548,6 @@ handle_file(const char *filename, uint32_t submit_to_decompile) return -1; } - init_rnn("a6xx"); type0_reg = reg_a6xx; mem_ctx = ralloc_context(NULL); _mesa_set_init(&decompiled_shaders, mem_ctx, u64_hash, u64_compare);