[Mesa-dev] [PATCH v3] nv50/ir: add debug options for shader replacement

Rhys Perry pendingchaos02 at gmail.com
Tue May 22 19:46:50 UTC 2018


Changes in v2:
- move "#ifdef DEBUG" from above dumpProgram to above createDumpFilename
Changes in v3:
- Fixed messed up patch description and diff
- Use the checksum of the TGSI instead of the binary if possible

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 | 124 ++++++++++++++++++++++++
 1 file changed, 124 insertions(+)

diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir.cpp
index c987da9908..f7fda3a7c6 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,121 @@ void Program::releaseValue(Value *value)
       mem_Symbol.release(value);
 }
 
+#ifdef DEBUG
+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];
+   if (prog->driver->bin.sourceRep == PIPE_SHADER_IR_TGSI) {
+      const tgsi_header* header = (const tgsi_header*)prog->driver->bin.source;
+      unsigned size = (header->HeaderSize + header->BodySize) * sizeof(tgsi_token);
+      _mesa_sha1_compute(prog->driver->bin.source, size, sha1_bin);
+   } else {
+      _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;
+}
+
+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");
+   if (!fp) {
+      INFO("Failed to dump code of program %p to %s\n", prog, fname);
+      return;
+   }
+
+   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 tgsi_token *tokens = (const 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 +1389,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



More information about the mesa-dev mailing list