diff options
author | Nicolai Hähnle <[email protected]> | 2015-12-14 20:41:15 -0500 |
---|---|---|
committer | Nicolai Hähnle <[email protected]> | 2015-12-29 09:07:04 -0500 |
commit | 7b8db37abb1b7f08c43f20380a370766ae7923ae (patch) | |
tree | fd88dccd8777486aa8536914999689164872ab2e /src/gallium/drivers/radeonsi/si_debug.c | |
parent | 7d1fc2cf51438a649eecbe4f8e858eebd93c1757 (diff) |
radeonsi: add RADEON_REPLACE_SHADERS debug option
This option allows replacing a single shader by a pre-compiled ELF object
as generated by LLVM's llc, for example. This can be useful for debugging a
deterministically occuring error in shaders (and has in fact helped find
the causes of https://bugs.freedesktop.org/show_bug.cgi?id=93264).
v2: drop the debug flag, use DEBUG_GET_ONCE_OPTION instead
Reviewed-by: Marek Olšák <[email protected]>
Diffstat (limited to 'src/gallium/drivers/radeonsi/si_debug.c')
-rw-r--r-- | src/gallium/drivers/radeonsi/si_debug.c | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/src/gallium/drivers/radeonsi/si_debug.c b/src/gallium/drivers/radeonsi/si_debug.c index c45f8c0ea50..a07b1c56579 100644 --- a/src/gallium/drivers/radeonsi/si_debug.c +++ b/src/gallium/drivers/radeonsi/si_debug.c @@ -28,8 +28,11 @@ #include "si_shader.h" #include "sid.h" #include "sid_tables.h" +#include "radeon/radeon_elf_util.h" #include "ddebug/dd_util.h" +#include "util/u_memory.h" +DEBUG_GET_ONCE_OPTION(replace_shaders, "RADEON_REPLACE_SHADERS", NULL) static void si_dump_shader(struct si_shader_ctx_state *state, const char *name, FILE *f) @@ -42,6 +45,98 @@ static void si_dump_shader(struct si_shader_ctx_state *state, const char *name, fprintf(f, "%s\n\n", state->current->binary.disasm_string); } +/** + * Shader compiles can be overridden with arbitrary ELF objects by setting + * the environment variable RADEON_REPLACE_SHADERS=num1:filename1[;num2:filename2] + */ +bool si_replace_shader(unsigned num, struct radeon_shader_binary *binary) +{ + const char *p = debug_get_option_replace_shaders(); + const char *semicolon; + char *copy = NULL; + FILE *f; + long filesize, nread; + char *buf = NULL; + bool replaced = false; + + if (!p) + return false; + + while (*p) { + unsigned long i; + char *endp; + i = strtoul(p, &endp, 0); + + p = endp; + if (*p != ':') { + fprintf(stderr, "RADEON_REPLACE_SHADERS formatted badly.\n"); + exit(1); + } + ++p; + + if (i == num) + break; + + p = strchr(p, ';'); + if (!p) + return false; + ++p; + } + if (!*p) + return false; + + semicolon = strchr(p, ';'); + if (semicolon) { + p = copy = strndup(p, semicolon - p); + if (!copy) { + fprintf(stderr, "out of memory\n"); + return false; + } + } + + fprintf(stderr, "radeonsi: replace shader %u by %s\n", num, p); + + f = fopen(p, "r"); + if (!f) { + perror("radeonsi: failed to open file"); + goto out_free; + } + + if (fseek(f, 0, SEEK_END) != 0) + goto file_error; + + filesize = ftell(f); + if (filesize < 0) + goto file_error; + + if (fseek(f, 0, SEEK_SET) != 0) + goto file_error; + + buf = MALLOC(filesize); + if (!buf) { + fprintf(stderr, "out of memory\n"); + goto out_close; + } + + nread = fread(buf, 1, filesize, f); + if (nread != filesize) + goto file_error; + + radeon_elf_read(buf, filesize, binary); + replaced = true; + +out_close: + fclose(f); +out_free: + FREE(buf); + free(copy); + return replaced; + +file_error: + perror("radeonsi: reading shader"); + goto out_close; +} + /* Parsed IBs are difficult to read without colors. Use "less -R file" to * read them, or use "aha -b -f file" to convert them to html. */ |