diff --git a/src/freedreno/ir3/ir3_compiler.c b/src/freedreno/ir3/ir3_compiler.c index 09167e9d4a0..c27e8bcedfe 100644 --- a/src/freedreno/ir3/ir3_compiler.c +++ b/src/freedreno/ir3/ir3_compiler.c @@ -50,8 +50,10 @@ static const struct debug_named_value shader_debug_options[] = { }; DEBUG_GET_ONCE_FLAGS_OPTION(ir3_shader_debug, "IR3_SHADER_DEBUG", shader_debug_options, 0) +DEBUG_GET_ONCE_OPTION(ir3_shader_override_path, "IR3_SHADER_OVERRIDE_PATH", NULL) enum ir3_shader_debug ir3_shader_debug = 0; +const char *ir3_shader_override_path = NULL; void ir3_compiler_destroy(struct ir3_compiler *compiler) @@ -66,6 +68,12 @@ ir3_compiler_create(struct fd_device *dev, uint32_t gpu_id) struct ir3_compiler *compiler = rzalloc(NULL, struct ir3_compiler); ir3_shader_debug = debug_get_option_ir3_shader_debug(); + ir3_shader_override_path = + !__check_suid() ? debug_get_option_ir3_shader_override_path() : NULL; + + if (ir3_shader_override_path) { + ir3_shader_debug |= IR3_DBG_NOCACHE; + } compiler->dev = dev; compiler->gpu_id = gpu_id; diff --git a/src/freedreno/ir3/ir3_compiler.h b/src/freedreno/ir3/ir3_compiler.h index 9924140711f..54a78f37726 100644 --- a/src/freedreno/ir3/ir3_compiler.h +++ b/src/freedreno/ir3/ir3_compiler.h @@ -155,6 +155,7 @@ enum ir3_shader_debug { }; extern enum ir3_shader_debug ir3_shader_debug; +extern const char *ir3_shader_override_path; static inline bool shader_debug_enabled(gl_shader_stage type) diff --git a/src/freedreno/ir3/ir3_shader.c b/src/freedreno/ir3/ir3_shader.c index a4feb9be8f1..835b67c6465 100644 --- a/src/freedreno/ir3/ir3_shader.c +++ b/src/freedreno/ir3/ir3_shader.c @@ -35,6 +35,8 @@ #include "ir3_shader.h" #include "ir3_compiler.h" #include "ir3_nir.h" +#include "ir3_assembler.h" +#include "ir3_parser.h" #include "isa/isa.h" @@ -181,17 +183,65 @@ void * ir3_shader_assemble(struct ir3_shader_variant *v) return bin; } +static bool +try_override_shader_variant(struct ir3_shader_variant *v, const char *identifier) +{ + assert(ir3_shader_override_path); + + char *name = ralloc_asprintf(NULL, "%s/%s.asm", ir3_shader_override_path, identifier); + + FILE* f = fopen(name, "r"); + + if (!f) { + ralloc_free(name); + return false; + } + + struct ir3_kernel_info info; + info.numwg = INVALID_REG; + v->ir = ir3_parse(v, &info, f); + + fclose(f); + + if (!v->ir) { + fprintf(stderr, "Failed to parse %s\n", name); + exit(1); + } + + v->bin = ir3_shader_assemble(v); + if (!v->bin) { + fprintf(stderr, "Failed to assemble %s\n", name); + exit(1); + } + + ralloc_free(name); + return true; +} + static void assemble_variant(struct ir3_shader_variant *v) { v->bin = ir3_shader_assemble(v); - if (shader_debug_enabled(v->shader->type)) { - fprintf(stdout, "Native code for unnamed %s shader %s:\n", - ir3_shader_stage(v), v->shader->nir->info.name); - if (v->shader->type == MESA_SHADER_FRAGMENT) - fprintf(stdout, "SIMD0\n"); - ir3_shader_disasm(v, v->bin, stdout); + bool dbg_enabled = shader_debug_enabled(v->shader->type); + if (dbg_enabled || ir3_shader_override_path) { + unsigned char sha1[21]; + char sha1buf[41]; + + _mesa_sha1_compute(v->bin, v->info.size, sha1); + _mesa_sha1_format(sha1buf, sha1); + + bool shader_overridden = + ir3_shader_override_path && try_override_shader_variant(v, sha1buf); + + if (dbg_enabled || shader_overridden) { + fprintf(stdout, "Native code%s for unnamed %s shader %s with sha1 %s:\n", + shader_overridden ? " (overridden)" : "", + ir3_shader_stage(v), v->shader->nir->info.name, sha1buf); + if (v->shader->type == MESA_SHADER_FRAGMENT) + fprintf(stdout, "SIMD0\n"); + ir3_shader_disasm(v, v->bin, stdout); + } } /* no need to keep the ir around beyond this point: */