The NV50_PROG_DUMP environment variable specifies a (already created) directory to dump both shader binaries and tgsi code. The NV50_PROG_REPLACE environment variable specified a (again, already created) directory that is searched to find replacement binaries. This is all much like MESA_SHADER_DUMP_PATH and MESA_SHADER_READ_PATH except using shortened SHA1 checksums instead of program IDs and chip-specific binaries instead of GLSL.
--- src/gallium/drivers/nouveau/codegen/nv50_ir.cpp | 114 ++++++++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir.cpp index c987da9908..aad78fadcf 100644 --- a/src/gallium/drivers/nouveau/codegen/nv50_ir.cpp +++ b/src/gallium/drivers/nouveau/codegen/nv50_ir.cpp @@ -23,6 +23,10 @@ #include "codegen/nv50_ir.h" #include "codegen/nv50_ir_target.h" #include "codegen/nv50_ir_driver.h" +#ifdef DEBUG +#include "tgsi/tgsi_dump.h" +#include "util/mesa-sha1.h" +#endif extern "C" { #include "nouveau_debug.h" @@ -1161,6 +1165,111 @@ void Program::releaseValue(Value *value) mem_Symbol.release(value); } +static char* +createDumpFilename(const char *dir, nv50_ir::Program *prog, const char *ext) +{ + char* fname = (char*)malloc(strlen(dir)+13+strlen(ext)); + if (dir[0] && dir[strlen(dir)-1]=='/') + strcpy(fname, dir); + else + sprintf(fname, "%s/", dir); + + unsigned char sha1_bin[20]; + char sha1_str[41]; + _mesa_sha1_compute(prog->code, prog->binSize, sha1_bin); + _mesa_sha1_format(sha1_str, sha1_bin); + sha1_str[7] = 0; + strcat(fname, sha1_str); + + switch (prog->getType()) { + case nv50_ir::Program::TYPE_VERTEX: + strcat(fname, ".vs"); + break; + case nv50_ir::Program::TYPE_TESSELLATION_CONTROL: + strcat(fname, ".tcs"); + break; + case nv50_ir::Program::TYPE_TESSELLATION_EVAL: + strcat(fname, ".tes"); + break; + case nv50_ir::Program::TYPE_GEOMETRY: + strcat(fname, ".gs"); + break; + case nv50_ir::Program::TYPE_FRAGMENT: + strcat(fname, ".fs"); + break; + case nv50_ir::Program::TYPE_COMPUTE: + strcat(fname, ".cs"); + break; + } + + strcat(fname, ext); + + return fname; +} + +#ifdef DEBUG +static void +dumpProgram(nv50_ir::Program *prog) +{ + const char *dump_dir = debug_get_option("NV50_PROG_DUMP", NULL); + if (!dump_dir) + return; + + char* fname = createDumpFilename(dump_dir, prog, ".bin"); + + FILE *fp = fopen(fname, "wb"); + fwrite(prog->code, prog->binSize, 1, fp); + fclose(fp); + + INFO("Dumped code of program %p to %s\n", prog, fname); + + free(fname); + + if (prog->driver->bin.sourceRep == PIPE_SHADER_IR_TGSI) { + char* fname = createDumpFilename(dump_dir, prog, ".tgsi.txt"); + const struct tgsi_token *tokens; + tokens = (const struct tgsi_token *)prog->driver->bin.source; + + FILE *fp = fopen(fname, "w"); + tgsi_dump_to_file(tokens, 0, fp); + fclose(fp); + + INFO("Dumped tgsi of program %p to %s\n", prog, fname); + + free(fname); + } +} + +static void +replaceProgram(nv50_ir::Program *prog) +{ + const nv50_ir::Target* targ = prog->getTarget(); + + const char *replace_dir = debug_get_option("NV50_PROG_REPLACE", NULL); + if (!replace_dir) + return; + + char* fname = createDumpFilename(replace_dir, prog, ".bin"); + + FILE *fp = fopen(fname, "rb"); + if (!fp) + return; + + FREE(prog->code); + prog->code = (uint32_t*)MALLOC(65536); + prog->binSize = fread(prog->code, 1, 65536, fp); + + unsigned maxGPR = targ->getChipset() >= NVISA_GK20A_CHIPSET ? 254 : 62; + prog->maxGPR = MIN2(targ->getFileSize(nv50_ir::FILE_GPR), maxGPR); + + fclose(fp); + + INFO("Replaced code of program %p with that from %s\n", prog, fname); + + free(fname); +} +#endif + } // namespace nv50_ir @@ -1270,6 +1379,11 @@ nv50_ir_generate_code(struct nv50_ir_prog_info *info) goto out; } +#ifdef DEBUG + nv50_ir::dumpProgram(prog); + nv50_ir::replaceProgram(prog); +#endif + out: INFO_DBG(prog->dbgFlags, VERBOSE, "nv50_ir_generate_code: ret = %i\n", ret); -- 2.14.3 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev