diff --git a/src/freedreno/ir3/ir3_compiler.c b/src/freedreno/ir3/ir3_compiler.c index 5321f458290..2034a9d3627 100644 --- a/src/freedreno/ir3/ir3_compiler.c +++ b/src/freedreno/ir3/ir3_compiler.c @@ -144,6 +144,8 @@ ir3_compiler_create(struct fd_device *dev, const struct fd_dev_id *dev_id, ir3_shader_debug |= IR3_DBG_NOCACHE; } + ir3_shader_bisect_init(); + compiler->dev = dev; compiler->dev_id = dev_id; compiler->gen = fd_dev_gen(dev_id); diff --git a/src/freedreno/ir3/ir3_compiler.h b/src/freedreno/ir3/ir3_compiler.h index 1f867d3f07f..b552055c372 100644 --- a/src/freedreno/ir3/ir3_compiler.h +++ b/src/freedreno/ir3/ir3_compiler.h @@ -449,6 +449,12 @@ ir3_shader_debug_hash_key() const char * ir3_shader_debug_as_string(void); +void ir3_shader_bisect_init(void); +bool ir3_shader_bisect_need_shader_key(void); +void ir3_shader_bisect_dump_id(struct ir3_shader_variant *v); +bool ir3_shader_bisect_select(struct ir3_shader_variant *v); +bool ir3_shader_bisect_disasm_select(struct ir3_shader_variant *v); + ENDC; #endif /* IR3_COMPILER_H_ */ diff --git a/src/freedreno/ir3/ir3_compiler_nir.c b/src/freedreno/ir3/ir3_compiler_nir.c index d9b3ec5ad60..07a060bee53 100644 --- a/src/freedreno/ir3/ir3_compiler_nir.c +++ b/src/freedreno/ir3/ir3_compiler_nir.c @@ -5574,6 +5574,8 @@ ir3_compile_shader_nir(struct ir3_compiler *compiler, int ret = 0, max_bary; bool progress; + ir3_shader_bisect_dump_id(so); + MESA_TRACE_FUNC(); assert(!so->ir); diff --git a/src/freedreno/ir3/ir3_disk_cache.c b/src/freedreno/ir3/ir3_disk_cache.c index 70126f60a76..459677207ac 100644 --- a/src/freedreno/ir3/ir3_disk_cache.c +++ b/src/freedreno/ir3/ir3_disk_cache.c @@ -61,7 +61,7 @@ void ir3_disk_cache_init_shader_key(struct ir3_compiler *compiler, struct ir3_shader *shader) { - if (!compiler->disk_cache) + if (!compiler->disk_cache && !ir3_shader_bisect_need_shader_key()) return; struct mesa_sha1 ctx; diff --git a/src/freedreno/ir3/ir3_shader.c b/src/freedreno/ir3/ir3_shader.c index d46e78e7d65..6b8f5e3b53c 100644 --- a/src/freedreno/ir3/ir3_shader.c +++ b/src/freedreno/ir3/ir3_shader.c @@ -406,7 +406,8 @@ assemble_variant(struct ir3_shader_variant *v, bool internal) _mesa_sha1_final(&ctx, sha1); _mesa_sha1_format(v->sha1_str, sha1); - bool dbg_enabled = shader_debug_enabled(v->type, internal); + bool dbg_enabled = shader_debug_enabled(v->type, internal) || + ir3_shader_bisect_disasm_select(v); if (dbg_enabled || ir3_shader_override_path || v->disasm_info.write_disasm) { bool shader_overridden = ir3_shader_override_path && try_override_shader_variant(v, v->sha1_str); diff --git a/src/freedreno/ir3/ir3_shader_bisect.c b/src/freedreno/ir3/ir3_shader_bisect.c new file mode 100644 index 00000000000..b076c3e7794 --- /dev/null +++ b/src/freedreno/ir3/ir3_shader_bisect.c @@ -0,0 +1,98 @@ +#include "ir3_shader.h" + +#include "util/hex.h" + +static const char *ir3_shader_bisect_dump_ids_path = NULL; +static const char *ir3_shader_bisect_lo = NULL; +static const char *ir3_shader_bisect_hi = NULL; +static const char *ir3_shader_bisect_disasm = NULL; + +DEBUG_GET_ONCE_OPTION(ir3_shader_bisect_dump_ids_path, + "IR3_SHADER_BISECT_DUMP_IDS_PATH", NULL); +DEBUG_GET_ONCE_OPTION(ir3_shader_bisect_lo, "IR3_SHADER_BISECT_LO", NULL); +DEBUG_GET_ONCE_OPTION(ir3_shader_bisect_hi, "IR3_SHADER_BISECT_HI", NULL); +DEBUG_GET_ONCE_OPTION(ir3_shader_bisect_disasm, "IR3_SHADER_BISECT_DISASM", + NULL); + +#define BISECT_ID_SIZE (2 * (CACHE_KEY_SIZE + 1) + 1) + +void +ir3_shader_bisect_init() +{ + ir3_shader_bisect_dump_ids_path = + __normal_user() ? debug_get_option_ir3_shader_bisect_dump_ids_path() + : NULL; + ir3_shader_bisect_lo = debug_get_option_ir3_shader_bisect_lo(); + ir3_shader_bisect_hi = debug_get_option_ir3_shader_bisect_hi(); + ir3_shader_bisect_disasm = debug_get_option_ir3_shader_bisect_disasm(); + + if (ir3_shader_bisect_dump_ids_path) { + FILE *f = fopen(ir3_shader_bisect_dump_ids_path, "w"); + assert(f && "Failed to open ir3_shader_bisect_dump_ids_path"); + fclose(f); + } +} + +bool +ir3_shader_bisect_need_shader_key() +{ + return ir3_shader_bisect_dump_ids_path || ir3_shader_bisect_lo || + ir3_shader_bisect_hi || ir3_shader_bisect_disasm; +} + +static void +get_shader_bisect_id(struct ir3_shader_variant *v, char id[BISECT_ID_SIZE]) +{ + uint8_t id_bin[sizeof(v->shader->cache_key) + 1]; + memcpy(id_bin, v->shader->cache_key, sizeof(v->shader->cache_key)); + id_bin[sizeof(v->shader->cache_key)] = v->id; + mesa_bytes_to_hex(id, id_bin, sizeof(id_bin)); +} + +void +ir3_shader_bisect_dump_id(struct ir3_shader_variant *v) +{ + if (!ir3_shader_bisect_dump_ids_path) { + return; + } + + FILE *f = fopen(ir3_shader_bisect_dump_ids_path, "a"); + assert(f); + + char id[BISECT_ID_SIZE]; + get_shader_bisect_id(v, id); + fprintf(f, "%s\n", id); +} + +bool +ir3_shader_bisect_select(struct ir3_shader_variant *v) +{ + if (!ir3_shader_bisect_lo && !ir3_shader_bisect_hi) { + return false; + } + + char id[BISECT_ID_SIZE]; + get_shader_bisect_id(v, id); + + if (ir3_shader_bisect_lo && strcmp(id, ir3_shader_bisect_lo) < 0) { + return false; + } + + if (ir3_shader_bisect_hi && strcmp(id, ir3_shader_bisect_hi) > 0) { + return false; + } + + return true; +} + +bool +ir3_shader_bisect_disasm_select(struct ir3_shader_variant *v) +{ + if (!ir3_shader_bisect_disasm) { + return false; + } + + char id[BISECT_ID_SIZE]; + get_shader_bisect_id(v, id); + return strcmp(ir3_shader_bisect_disasm, id) == 0; +} diff --git a/src/freedreno/ir3/ir3_shader_bisect.py b/src/freedreno/ir3/ir3_shader_bisect.py new file mode 100644 index 00000000000..31f6b9d0bfc --- /dev/null +++ b/src/freedreno/ir3/ir3_shader_bisect.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python3 + +import argparse +import subprocess +import os + + +def run(cmd, extra_env): + env = os.environ | extra_env + env['MESA_SHADER_CACHE_DISABLE'] = '1' + subprocess.run(cmd, env=env, shell=True) + + +def dump(args): + extra_env = {'IR3_SHADER_BISECT_DUMP_IDS_PATH': args.output} + run(args.cmd, extra_env) + + +def was_good(): + while True: + response = input('Was the previous run [g]ood or [b]ad? ') + + if response in ('g', 'b'): + return response == 'g' + + +def bisect(args): + with open(args.input, 'r') as f: + ids = [l.strip() for l in f.readlines()] + + ids.sort() + + while len(ids) > 1: + lo_id = 0 + hi_id = len(ids) // 2 + lo = ids[lo_id] + hi = ids[hi_id] + extra_env = { + 'IR3_SHADER_BISECT_LO': str(lo), + 'IR3_SHADER_BISECT_HI': str(hi) + } + run(args.cmd, extra_env) + + if was_good(): + del ids[lo_id:hi_id + 1] + else: + del ids[hi_id:] + + print(ids) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + subparsers = parser.add_subparsers(required=True) + + gather_parser = subparsers.add_parser('dump-ids') + gather_parser.add_argument('-o', '--output', required=True) + gather_parser.add_argument('cmd') + gather_parser.set_defaults(func=dump) + + bisect_parser = subparsers.add_parser('bisect') + bisect_parser.add_argument('-i', '--input', required=True) + bisect_parser.add_argument('cmd') + bisect_parser.set_defaults(func=bisect) + + args = parser.parse_args() + args.func(args) diff --git a/src/freedreno/ir3/meson.build b/src/freedreno/ir3/meson.build index dcbd14929c8..69a4c6b11e5 100644 --- a/src/freedreno/ir3/meson.build +++ b/src/freedreno/ir3/meson.build @@ -125,6 +125,7 @@ libfreedreno_ir3_files = files( 'ir3_sched.c', 'ir3_shader.c', 'ir3_shader.h', + 'ir3_shader_bisect.c', 'ir3_shared_folding.c', 'ir3_shared_ra.c', 'ir3_spill.c',