freedreno/decode: Add code to extent pkt processing with Lua
Setting up a new `iL` `lua_State` in which `r` is injected as the equivalent to `rnn.init(<gpu>)` and a `priv` library allows accessing extra functionality (not available to user provided scripts) currently just allowing writing to registers. Signed-off-by: Karmjit Mahil <karmjit.mahil@igalia.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/38001>
This commit is contained in:
@@ -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 *
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
-- SPDX-License-Identifier: MIT
|
||||
|
||||
-- `r` is predefined in the environment and is the equivalent of rnn.init(<gpu>)
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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' ],
|
||||
|
||||
+142
-23
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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..
|
||||
|
||||
Reference in New Issue
Block a user