diff --git a/src/freedreno/decode/cffdec.c b/src/freedreno/decode/cffdec.c index 8585ce83436..6030bbde7ce 100644 --- a/src/freedreno/decode/cffdec.c +++ b/src/freedreno/decode/cffdec.c @@ -164,6 +164,16 @@ decode_shader_ir3(uint32_t *dwords, uint32_t sizedwords, int level, &shader_stats[stage]); } +struct shader_stats * +get_shader_stats(enum mesa_shader_stage stage) +{ + /* TODO in summary mode we might need to trigger silent shader disasm + * to have up to date stats? Maybe we need to track whether the stats + * are valid? + */ + return &shader_stats[stage]; +} + static bool highlight_addr(uint32_t *hostaddr) { diff --git a/src/freedreno/decode/cffdec.h b/src/freedreno/decode/cffdec.h index d4ffb2fca10..be76bed510d 100644 --- a/src/freedreno/decode/cffdec.h +++ b/src/freedreno/decode/cffdec.h @@ -116,6 +116,9 @@ void cffdec_finish(void); void dump_register_val(struct regacc *r, int level); void dump_commands(uint32_t *dwords, uint32_t sizedwords, int level); +enum mesa_shader_stage; +struct shader_stats *get_shader_stats(enum mesa_shader_stage stage); + /* * Packets (mostly) fall into two categories, "write one or more registers" * (type0 or type4 depending on generation) or "packet with opcode and diff --git a/src/freedreno/decode/script.c b/src/freedreno/decode/script.c index fe0f4097b37..18f1a201f29 100644 --- a/src/freedreno/decode/script.c +++ b/src/freedreno/decode/script.c @@ -22,6 +22,7 @@ #include "cffdec.h" #include "cffdump-pkt-handler.h" #include "cffdump-desc-handler.h" +#include "disasm.h" #include "rnnutil.h" #include "script.h" @@ -39,9 +40,10 @@ static lua_State *iL; } while (0) #endif +static int l_rnn_shaderstat(lua_State *L, struct rnn *rnn); + /* An rnn based decoder, which can either be decoding current register * values, or domain based decoding of a pm4 packet. - * */ struct rnndec { struct rnn base; @@ -551,6 +553,63 @@ l_rnn_dom(lua_State *L, uint32_t *dwords, uint32_t sizedwords, return 1; } +/* + * Shader stats object + */ + +static int +l_rnn_meta_shaderstat_index(lua_State *L) +{ + struct rnn *rnn = lua_touserdata(L, 1); + const char *name = lua_tostring(L, 2); + enum mesa_shader_stage stage; + struct rnndomain *dom = rnn_finddomain(rnn->db, "ir3_shader_stats"); + + if (!dom) + error("No domain: ir3_shader_stats"); + + if (!strcmp(name, "vs")) { + stage = MESA_SHADER_VERTEX; + } else if (!strcmp(name, "hs")) { + stage = MESA_SHADER_TESS_CTRL; + } else if (!strcmp(name, "ds")) { + stage = MESA_SHADER_TESS_EVAL; + } else if (!strcmp(name, "gs")) { + stage = MESA_SHADER_GEOMETRY; + } else if (!strcmp(name, "fs")) { + stage = MESA_SHADER_FRAGMENT; + } else if (!strcmp(name, "cs")) { + stage = MESA_SHADER_COMPUTE; + } else { + return 0; + } + + struct shader_stats *stats = get_shader_stats(stage); + + return l_rnn_dom(L, (uint32_t *)stats, DIV_ROUND_UP(sizeof(*stats), 4), rnn, dom); +} + +static const struct luaL_Reg l_meta_rnn_shaderstat[] = { + {"__index", l_rnn_meta_shaderstat_index}, + {NULL, NULL} /* sentinel */ +}; + +static int +l_rnn_shaderstat(lua_State *L, struct rnn *rnn) +{ + struct rnndec *rnndec = lua_newuserdata(L, sizeof(*rnndec)); + + rnndec->base = *rnn; + + luaL_newmetatable(L, "rnnmetadom"); + luaL_setfuncs(L, l_meta_rnn_shaderstat, 0); + lua_pop(L, 1); + + luaL_setmetatable(L, "rnnmetadom"); + + return 1; +} + /* * */ @@ -561,6 +620,9 @@ l_rnn_meta_index(lua_State *L) struct rnn *rnn = lua_touserdata(L, 1); const char *name = lua_tostring(L, 2); + if (!strcmp(name, "shaderstat")) + return l_rnn_shaderstat(L, rnn); + struct rnndelem *elem = rnn_regelem(rnn, name); if (elem) return l_rnn_etype(L, rnn, elem, elem->offset); @@ -961,6 +1023,7 @@ script_show_descriptor(uint32_t *dwords, return true; struct rnnenum *e = rnn_enumelem(rnn, "desctype"); + assert(e); pushenum(iL, rnn, rnn_enumval(rnn, "desctype", type), e); /* 2 args, 1 result */