[Mesa-dev] [PATCH v3] nv50/ir: add debug options for shader replacement
Ilia Mirkin
imirkin at alum.mit.edu
Mon May 28 19:44:23 UTC 2018
Hi Rhys,
I really like this in general, but I have some feedback on the
specific implementation:
1. The shader and its header can be closely related. Please integrate
something that also loads/dumps the shader header (separate file).
This should go into nvc0_program, as that's where the header is
generated. Probably means you have to compute the sha there directly
and feed it into the compiler (see #3 below).
2. Move these functions into nv50_ir_dump.cpp or something.
3. If you're replacing the shader, don't go through the whole
compile/optimize flow - no reason for it. I don't think doing the sha
of the bin code is necessary - for any IR input we should be able to
get a consistent hash of it. So the flow should be "dump; if (replace)
replace; else compile;". I think that should be achievable.
4. Why truncate the sha1?
5. maxGPR = targ->getFileSize() - 1; this also handles the compute
case where you have to limit the number of GPRs based on the number of
CS threads.
Thanks for working on this!
-ilia
On Tue, May 22, 2018 at 3:46 PM, Rhys Perry <pendingchaos02 at gmail.com> wrote:
> 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