mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-28 06:00:10 +01:00
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 <marek.olsak@amd.com>
This commit is contained in:
parent
7d1fc2cf51
commit
7b8db37abb
3 changed files with 105 additions and 5 deletions
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -329,6 +329,7 @@ void si_init_cp_dma_functions(struct si_context *sctx);
|
|||
/* si_debug.c */
|
||||
void si_init_debug_functions(struct si_context *sctx);
|
||||
void si_check_vm_faults(struct si_context *sctx);
|
||||
bool si_replace_shader(unsigned num, struct radeon_shader_binary *binary);
|
||||
|
||||
/* si_dma.c */
|
||||
void si_dma_copy(struct pipe_context *ctx,
|
||||
|
|
|
|||
|
|
@ -3884,13 +3884,17 @@ int si_compile_llvm(struct si_screen *sscreen, struct si_shader *shader,
|
|||
bool dump_asm = r600_can_dump_shader(&sscreen->b,
|
||||
shader->selector ? shader->selector->tokens : NULL);
|
||||
bool dump_ir = dump_asm && !(sscreen->b.debug_flags & DBG_NO_IR);
|
||||
unsigned count = p_atomic_inc_return(&sscreen->b.num_compilations);
|
||||
|
||||
p_atomic_inc(&sscreen->b.num_compilations);
|
||||
if (dump_ir || dump_asm)
|
||||
fprintf(stderr, "radeonsi: Compiling shader %d\n", count);
|
||||
|
||||
r = radeon_llvm_compile(mod, &shader->binary,
|
||||
r600_get_llvm_processor_name(sscreen->b.family), dump_ir, dump_asm, tm);
|
||||
if (r)
|
||||
return r;
|
||||
if (!si_replace_shader(count, &shader->binary)) {
|
||||
r = radeon_llvm_compile(mod, &shader->binary,
|
||||
r600_get_llvm_processor_name(sscreen->b.family), dump_ir, dump_asm, tm);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = si_shader_binary_read(sscreen, shader);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue