diff --git a/src/freedreno/decode/cffdec.c b/src/freedreno/decode/cffdec.c index 9e327c42448..525726421f7 100644 --- a/src/freedreno/decode/cffdec.c +++ b/src/freedreno/decode/cffdec.c @@ -875,6 +875,15 @@ cffdec_init(const struct cffdec_options *_options) default: errx(-1, "unsupported generation: %u", options->info->chip); } + + internal_lua_pkt_handler_load(); + internal_lua_pkt_handler_init_rnn(rnn); +} + +void +cffdec_finish(void) +{ + internal_lua_pkt_handler_finish(); } const char * diff --git a/src/freedreno/decode/cffdec.h b/src/freedreno/decode/cffdec.h index c71544bf7f1..d4ffb2fca10 100644 --- a/src/freedreno/decode/cffdec.h +++ b/src/freedreno/decode/cffdec.h @@ -112,6 +112,7 @@ uint32_t * parse_cp_indirect(uint32_t *dwords, uint32_t sizedwords, uint64_t *ibaddr, uint32_t *ibsize); void reset_regs(void); void cffdec_init(const struct cffdec_options *options); +void cffdec_finish(void); void dump_register_val(struct regacc *r, int level); void dump_commands(uint32_t *dwords, uint32_t sizedwords, int level); diff --git a/src/freedreno/decode/cffdump-pkt-handler.lua b/src/freedreno/decode/cffdump-pkt-handler.lua new file mode 100644 index 00000000000..35665333052 --- /dev/null +++ b/src/freedreno/decode/cffdump-pkt-handler.lua @@ -0,0 +1,3 @@ +-- SPDX-License-Identifier: MIT + +-- `r` is predefined in the environment and is the equivalent of rnn.init() diff --git a/src/freedreno/decode/cffdump.c b/src/freedreno/decode/cffdump.c index 030c291a549..6501821dcd0 100644 --- a/src/freedreno/decode/cffdump.c +++ b/src/freedreno/decode/cffdump.c @@ -140,6 +140,8 @@ main(int argc, char **argv) interactive = isatty(STDOUT_FILENO); + internal_lua_pkt_handler_load(); + options.color = interactive; while ((c = getopt_long(argc, argv, "vsaS:E:F:D:e:L:q:h", opts, NULL)) != @@ -348,6 +350,7 @@ handle_file(const char *filename, int start, int end, int draw) } script_end_cmdstream(); + cffdec_finish(); reset_buffers(); diff --git a/src/freedreno/decode/crashdec.c b/src/freedreno/decode/crashdec.c index 0ee93046fe2..4ce408c286d 100644 --- a/src/freedreno/decode/crashdec.c +++ b/src/freedreno/decode/crashdec.c @@ -20,6 +20,7 @@ #include "crashdec.h" +#include "cffdec.h" static FILE *in; bool verbose; @@ -1187,6 +1188,8 @@ cleanup(void) if (interactive) { pager_close(); } + + cffdec_finish(); } int diff --git a/src/freedreno/decode/meson.build b/src/freedreno/decode/meson.build index cf5c1e7fad4..81aa0d39a75 100644 --- a/src/freedreno/decode/meson.build +++ b/src/freedreno/decode/meson.build @@ -5,6 +5,13 @@ if with_tests diff = find_program('diff') endif +cffdump_pkt_handler_h = custom_target( + 'cffdump-pkt-handler.h', + input : [files_xxd, 'cffdump-pkt-handler.lua'], + output : 'cffdump-pkt-handler.h', + command : [prog_python, '@INPUT@', '@OUTPUT@', '-n', 'cffdump_pkt_handler_lua_src'], +) + # Shared cmdstream decoding: libfreedreno_cffdec = static_library( 'freedreno_cffdec', @@ -17,7 +24,10 @@ libfreedreno_cffdec = static_library( 'pager.h', 'rnnutil.c', 'rnnutil.h', + 'script.c', + 'script.h', 'util.h', + cffdump_pkt_handler_h, ], include_directories: [ inc_freedreno, @@ -27,7 +37,9 @@ libfreedreno_cffdec = static_library( ], c_args : [ no_override_init_args ], gnu_symbol_visibility: 'hidden', - dependencies: [], + dependencies: [ + dep_lua, + ], link_with: [ libfreedreno_rnn, libfreedreno_ir2, # for disasm_a2xx @@ -152,8 +164,6 @@ if dep_lua.found() and dep_libarchive.found() 'cffdump', [ 'cffdump.c', - 'script.c', - 'script.h' ], include_directories: [ inc_freedreno, @@ -174,6 +184,32 @@ if dep_lua.found() and dep_libarchive.found() install: install_fd_decode_tools, ) + crashdec = executable( + 'crashdec', + [ + 'crashdec.c', + 'crashdec.h', + 'crashdec-hfi.c', + 'crashdec-mempool.c', + 'crashdec-prefetch.c', + ], + include_directories: [ + inc_freedreno, + inc_freedreno_rnn, + inc_include, + inc_src, + ], + gnu_symbol_visibility: 'hidden', + dependencies: [ + dep_lua, + ], + link_with: [ + libfreedreno_cffdec, + ], + build_by_default: with_tools.contains('freedreno'), + install: install_fd_decode_tools, + ) + if with_tests # dump only a single frame, and single tile pass, to keep the # reference output size managable @@ -209,30 +245,6 @@ else warning('lua or libarchive not found, not building cffdump') endif -crashdec = executable( - 'crashdec', - [ - 'crashdec.c', - 'crashdec.h', - 'crashdec-hfi.c', - 'crashdec-mempool.c', - 'crashdec-prefetch.c', - ], - include_directories: [ - inc_freedreno, - inc_freedreno_rnn, - inc_include, - inc_src, - ], - gnu_symbol_visibility: 'hidden', - dependencies: [], - link_with: [ - libfreedreno_cffdec, - ], - build_by_default: with_tools.contains('freedreno'), - install: install_fd_decode_tools, -) - dumpregs = executable( 'dumpregs', [ 'dumpregs.c' ], diff --git a/src/freedreno/decode/script.c b/src/freedreno/decode/script.c index 6e9d6075411..35c03aa5346 100644 --- a/src/freedreno/decode/script.c +++ b/src/freedreno/decode/script.c @@ -20,10 +20,12 @@ #include "util/u_math.h" #include "cffdec.h" +#include "cffdump-pkt-handler.h" #include "rnnutil.h" #include "script.h" static lua_State *L; +static lua_State *iL; #if 0 #define DBG(fmt, ...) \ @@ -547,6 +549,26 @@ static const struct luaL_Reg l_regs[] = { {NULL, NULL} /* sentinel */ }; +/* Expose the private functionality to the internal pkt enviroment as a "priv" + * library: + */ + +static int +l_priv_reg_set(lua_State *L) +{ + uint32_t regbase = (uint32_t)lua_tonumber(L, 1); + uint32_t regval = (uint32_t)lua_tonumber(L, 2); + + reg_set(regbase, regval); + + return 1; +} + +static const struct luaL_Reg l_priv[] = { + {"reg_set", l_priv_reg_set}, + {NULL, NULL} /* sentinel */ +}; + /* Expose API to lookup snapshot buffers: */ @@ -576,11 +598,20 @@ static const struct luaL_Reg l_bos[] = { }; static void -openlib(const char *lib, const luaL_Reg *reg) +openlib(lua_State *state, const char *lib, const luaL_Reg *reg) { - lua_newtable(L); - luaL_setfuncs(L, reg, 0); - lua_setglobal(L, lib); + lua_newtable(state); + luaL_setfuncs(state, reg, 0); + lua_setglobal(state, lib); +} + +static void +common_libs(lua_State *state) +{ + luaL_openlibs(state); + openlib(state, "bos", l_bos); + openlib(state, "regs", l_regs); + openlib(state, "rnn", l_rnn); } /* called at start to load the script: */ @@ -592,10 +623,7 @@ script_load(const char *file) assert(!L); L = luaL_newstate(); - luaL_openlibs(L); - openlib("bos", l_bos); - openlib("regs", l_regs); - openlib("rnn", l_rnn); + common_libs(L); ret = luaL_loadfile(L, file); if (ret) @@ -608,6 +636,48 @@ script_load(const char *file) return 0; } +void +internal_lua_pkt_handler_load(void) +{ + int ret; + + if (iL) + return; + + iL = luaL_newstate(); + + common_libs(iL); + openlib(iL, "priv", l_priv); + + ret = luaL_loadstring(iL, cffdump_pkt_handler_lua_src); + if (ret) { + fprintf(stderr, "%s\n", lua_tostring(iL, -1)); + exit(1); + } + + ret = lua_pcall(iL, 0, LUA_MULTRET, 0); + if (ret) { + fprintf(stderr, "%s\n", lua_tostring(iL, -1)); + exit(1); + } +} + +void +internal_lua_pkt_handler_init_rnn(struct rnn *rnn) +{ + struct rnndec *rnndec = lua_newuserdata(iL, sizeof(*rnndec)); + rnndec->base = *rnn; + rnndec->sizedwords = 0; + + luaL_newmetatable(iL, "rnnmeta"); + luaL_setfuncs(iL, l_meta_rnn, 0); + lua_pop(iL, 1); + + luaL_setmetatable(iL, "rnnmeta"); + + lua_setglobal(iL, "r"); +} + /* called at start of each cmdstream file: */ void script_start_cmdstream(const char *name) @@ -698,22 +768,24 @@ static const struct luaL_Reg l_meta_rnn_dom[] = { /* called to general pm4 packet decoding, such as texture/sampler state */ -void -script_packet(uint32_t *dwords, uint32_t sizedwords, struct rnn *rnn, - struct rnndomain *dom) +static bool +handle_packet_setup(lua_State *state, uint32_t *dwords, uint32_t sizedwords, + struct rnn *rnn, struct rnndomain *dom) { - if (!L) - return; + if (!state) + return false; - lua_getglobal(L, dom->name); + assert(state == L || state == iL); + + lua_getglobal(state, dom->name); /* if no handler for the packet, just ignore it: */ - if (!lua_isfunction(L, -1)) { - lua_pop(L, 1); - return; + if (!lua_isfunction(state, -1)) { + lua_pop(state, 1); + return false; } - struct rnndec *rnndec = lua_newuserdata(L, sizeof(*rnndec)); + struct rnndec *rnndec = lua_newuserdata(state, sizeof(*rnndec)); rnndec->base = *rnn; rnndec->base.dom[0] = dom; @@ -721,18 +793,55 @@ script_packet(uint32_t *dwords, uint32_t sizedwords, struct rnn *rnn, rnndec->dwords = dwords; rnndec->sizedwords = sizedwords; - luaL_newmetatable(L, "rnnmetadom"); - luaL_setfuncs(L, l_meta_rnn_dom, 0); - lua_pop(L, 1); + luaL_newmetatable(state, "rnnmetadom"); + luaL_setfuncs(state, l_meta_rnn_dom, 0); + lua_pop(state, 1); - luaL_setmetatable(L, "rnnmetadom"); + luaL_setmetatable(state, "rnnmetadom"); - lua_pushnumber(L, sizedwords); + lua_pushnumber(state, sizedwords); + + return true; +} + +void +script_packet(uint32_t *dwords, uint32_t sizedwords, struct rnn *rnn, + struct rnndomain *dom) +{ + bool ret; + + ret = handle_packet_setup(L, dwords, sizedwords, rnn, dom); + if (!ret) + return; if (lua_pcall(L, 2, 0, 0) != 0) error("error running function `f': %s\n"); } +const char * +internal_packet(uint32_t *dwords, uint32_t sizedwords, struct rnn *rnn, + struct rnndomain *dom) +{ + bool ret; + + ret = handle_packet_setup(iL, dwords, sizedwords, rnn, dom); + if (!ret) + return NULL; + + /* 2 args, 1 result */ + if (lua_pcall(iL, 2, 1, 0) != 0) { + fprintf(stderr, "error running function `f': %s\n", + lua_tostring(iL, -1)); + exit(1); + } + + char *str; + asprintf(&str, "%s", lua_tostring(iL, -1)); + lua_pop(iL, 1); + + return str; +} + /* helper to call fxn that takes and returns void: */ static void simple_call(const char *name) @@ -786,3 +895,13 @@ script_finish(void) lua_close(L); L = NULL; } + +void +internal_lua_pkt_handler_finish(void) +{ + if (!iL) + return; + + lua_close(iL); + iL = NULL; +} diff --git a/src/freedreno/decode/script.h b/src/freedreno/decode/script.h index 49a2666b553..c01fd37d90c 100644 --- a/src/freedreno/decode/script.h +++ b/src/freedreno/decode/script.h @@ -18,8 +18,14 @@ #ifdef ENABLE_SCRIPTING +struct rnn; +struct rnndomain; + /* called at start to load the script: */ int script_load(const char *file); +/* called at start to load internal pkt handlers: */ +void internal_lua_pkt_handler_load(void); +void internal_lua_pkt_handler_init_rnn(struct rnn *rnn); /* called at start of each cmdstream file: */ void script_start_cmdstream(const char *name); @@ -30,13 +36,16 @@ void script_start_cmdstream(const char *name); __attribute__((weak)) void script_draw(const char *primtype, uint32_t nindx); -struct rnn; -struct rnndomain; __attribute__((weak)) void script_packet(uint32_t *dwords, uint32_t sizedwords, struct rnn *rnn, struct rnndomain *dom); +__attribute__((weak)) +const char * internal_packet(uint32_t *dwords, uint32_t sizedwords, + struct rnn *rnn, + struct rnndomain *dom); + /* maybe at some point it is interesting to add additional script * hooks for CP_EVENT_WRITE, etc? */ @@ -49,6 +58,7 @@ void script_end_submit(void); /* called after last cmdstream file: */ void script_finish(void); +void internal_lua_pkt_handler_finish(void); #else // TODO no-op stubs..