summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/radeonsi/si_debug.c
diff options
context:
space:
mode:
authorNicolai Hähnle <[email protected]>2015-12-14 20:41:15 -0500
committerNicolai Hähnle <[email protected]>2015-12-29 09:07:04 -0500
commit7b8db37abb1b7f08c43f20380a370766ae7923ae (patch)
treefd88dccd8777486aa8536914999689164872ab2e /src/gallium/drivers/radeonsi/si_debug.c
parent7d1fc2cf51438a649eecbe4f8e858eebd93c1757 (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.c95
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.
*/