diff --git a/src/gallium/auxiliary/driver_trace/enums2names.py b/src/gallium/auxiliary/driver_trace/enums2names.py new file mode 100755 index 00000000000..dd346900d92 --- /dev/null +++ b/src/gallium/auxiliary/driver_trace/enums2names.py @@ -0,0 +1,291 @@ +#!/usr/bin/env python3 +# coding=utf-8 +########################################################################## +# +# enums2names - Parse and convert enums to translator code +# (C) Copyright 2021 Matti 'ccr' Hämäläinen +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sub license, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice (including the +# next paragraph) shall be included in all copies or substantial portions +# of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +# IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR +# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +########################################################################## + +import sys +import os.path +import re +import signal +import argparse +import textwrap + +assert sys.version_info >= (3, 6) + + +# +# List of enums we wish to include in output. +# NOTE: This needs to be updated if such enums are added. +# +lst_enum_include = [ + "pipe_texture_target", + "pipe_shader_type", + "pipe_shader_cap", + "pipe_shader_ir", + "pipe_cap", + "pipe_capf", + "pipe_compute_cap", + "pipe_resource_param", + "pipe_fd_type", +] + + +### +### Utility functions +### +## Fatal error handler +def pkk_fatal(smsg): + print("ERROR: "+ smsg) + sys.exit(1) + + +## Handler for SIGINT signals +def pkk_signal_handler(signal, frame): + print("\nQuitting due to SIGINT / Ctrl+C!") + sys.exit(1) + + +## Argument parser subclass +class PKKArgumentParser(argparse.ArgumentParser): + def print_help(self): + print("enums2names - Parse and convert enums to translator code\n" + "(C) Copyright 2021 Matti 'ccr' Hämäläinen \n") + super().print_help() + + def error(self, msg): + self.print_help() + print(f"\nERROR: {msg}", file=sys.stderr) + sys.exit(2) + + +def pkk_get_argparser(): + optparser = PKKArgumentParser( + usage="%(prog)s [options] \n" + "example: %(prog)s ../../include/pipe/p_defines.h -C tr_util.c -H tr_util.h" + ) + + optparser.add_argument("in_file", + type=str, + metavar="infile", + help="path to input header file p_defines.h (or '-' for stdin)") + + optparser.add_argument("-C", + type=str, + metavar="outfile", + dest="out_source", + help="output C source file") + + optparser.add_argument("-H", + type=str, + metavar="outfile", + dest="out_header", + help="output C header file") + + optparser.add_argument("-I", + type=str, + metavar="include", + dest="include_file", + help="include file / path used for C source output") + + return optparser + + +class PKKHeaderParser: + + def __init__(self, nfilename): + self.filename = nfilename + self.enums = {} + self.state = 0 + self.nline = 0 + self.mdata = [] + self.start = 0 + self.name = None + + def error(self, msg): + pkk_fatal(f"{self.filename}:{self.nline} : {msg}") + + def parse_line(self, sline): + # A kingdom for Py3.8 := operator ... + smatch = re.match(r'^enum\s+([A-Za-z0-9_]+)\s+.*;', sline) + if smatch: + pass + else: + smatch = re.match(r'^enum\s+([A-Za-z0-9_]+)', sline) + if smatch: + stmp = smatch.group(1) + + if self.state != 0: + self.error(f"enum '{stmp}' starting inside another enum '{self.name}'") + + self.name = stmp + self.state = 1 + self.start = self.nline + self.mdata = [] + else: + smatch = re.match(r'^}(\s*|\s*[A-Z][A-Z_]+\s*);', sline) + if smatch: + if self.state == 1: + if self.name in self.enums: + self.error("duplicate enum definition '{}', lines {} - {} vs {} - {}".format( + self.name, self.enums[self.name]["start"], self.enums[self.name]["end"], + self.start, self.nline)) + + self.enums[self.name] = { + "data": self.mdata, + "start": self.start, + "end": self.nline + } + + self.state = 0 + + elif self.state == 1: + smatch = re.match(r'([A-Za-z0-9_]+)\s*=\s*(.+)\s*,?', sline) + if smatch: + self.mdata.append(smatch.group(1)) + else: + smatch = re.match(r'([A-Za-z0-9_]+)\s*,?', sline) + if smatch: + self.mdata.append(smatch.group(1)) + + def parse_file(self, fh): + self.nline = 0 + for line in fh: + self.nline += 1 + self.parse_line(line.strip()) + + return self.enums + + +def pkk_output_header(fh): + prototypes = [f"const char *\n" + f"tr_util_{name}_name(enum {name} value);\n" for name in lst_enum_include] + + print(textwrap.dedent("""\ + /* + * File generated with {program}, please do not edit manually. + */ + #ifndef {include_header_guard} + #define {include_header_guard} + + + #include "pipe/p_defines.h" + + + #ifdef __cplusplus + extern "C" {{ + #endif + + {prototypes} + + #ifdef __cplusplus + }} + #endif + + #endif /* {include_header_guard} */\ + """).format( + program=pkk_progname, + include_header_guard=re.sub(r'[^A-Z]', '_', os.path.basename(pkk_cfg.out_header).upper()), + prototypes="".join(prototypes) + ), file=fh) + + +def pkk_output_source(fh): + if pkk_cfg.include_file == None: + pkk_fatal("Output C source enabled, but include file is not set (-I option).") + + print(textwrap.dedent("""\ + /* + * File generated with {program}, please do not edit manually. + */ + #include "{include_file}" + """).format( + program=pkk_progname, + include_file=pkk_cfg.include_file, + ), file=fh) + + for name in lst_enum_include: + cases = [f" case {eid}: return \"{eid}\";\n" + for eid in enums[name]["data"]] + + print(textwrap.dedent("""\ + + const char * + tr_util_{name}_name(enum {name} value) + {{ + switch (value) {{ + {cases} + default: return "{ucname}_UNKNOWN"; + }} + }} + """).format( + name=name, + ucname=name.upper(), + cases="".join(cases) + ), file=fh) + +### +### Main program starts +### +if __name__ == "__main__": + signal.signal(signal.SIGINT, pkk_signal_handler) + + ### Parse arguments + pkk_progname = sys.argv[0] + optparser = pkk_get_argparser() + pkk_cfg = optparser.parse_args() + + ### Parse input + hdrparser = PKKHeaderParser(pkk_cfg.in_file) + + try: + if pkk_cfg.in_file != "-": + with open(pkk_cfg.in_file, "r", encoding="UTF-8") as fh: + enums = hdrparser.parse_file(fh) + else: + enums = hdrparser.parse_file(sys.stdin) + + except OSError as e: + pkk_fatal(str(e)) + + ### Check if any of the required enums are missing + errors = False + for name in lst_enum_include: + if name not in enums: + print(f"ERROR: Missing enum '{name}'!") + errors = True + + if errors: + pkk_fatal(f"Errors in input. Edit this script ({pkk_progname}) to add/remove included enums.") + + ### Perform output + if pkk_cfg.out_header: + with open(pkk_cfg.out_header, "w", encoding="UTF-8") as fh: + pkk_output_header(fh) + + if pkk_cfg.out_source: + with open(pkk_cfg.out_source, "w", encoding="UTF-8") as fh: + pkk_output_source(fh) diff --git a/src/gallium/auxiliary/driver_trace/tr_context.c b/src/gallium/auxiliary/driver_trace/tr_context.c index 66e6ce8ff0e..5c58b3f95a1 100644 --- a/src/gallium/auxiliary/driver_trace/tr_context.c +++ b/src/gallium/auxiliary/driver_trace/tr_context.c @@ -41,6 +41,7 @@ #include "tr_screen.h" #include "tr_texture.h" #include "tr_context.h" +#include "tr_util.h" struct trace_query @@ -490,7 +491,7 @@ trace_context_bind_sampler_states(struct pipe_context *_pipe, trace_dump_call_begin("pipe_context", "bind_sampler_states"); trace_dump_arg(ptr, pipe); - trace_dump_arg(uint, shader); + trace_dump_arg_enum(shader, tr_util_pipe_shader_type_name(shader)); trace_dump_arg(uint, start); trace_dump_arg(uint, num_states); trace_dump_arg_array(ptr, states, num_states); @@ -922,7 +923,7 @@ trace_context_set_constant_buffer(struct pipe_context *_pipe, trace_dump_call_begin("pipe_context", "set_constant_buffer"); trace_dump_arg(ptr, pipe); - trace_dump_arg(uint, shader); + trace_dump_arg_enum(shader, tr_util_pipe_shader_type_name(shader)); trace_dump_arg(uint, index); trace_dump_arg(bool, take_ownership); trace_dump_arg(constant_buffer, constant_buffer); @@ -965,7 +966,7 @@ trace_context_set_inlinable_constants(struct pipe_context *_pipe, enum pipe_shad trace_dump_call_begin("pipe_context", "set_inlinable_constants"); trace_dump_arg(ptr, pipe); - trace_dump_arg(uint, shader); + trace_dump_arg_enum(shader, tr_util_pipe_shader_type_name(shader)); trace_dump_arg(uint, num_values); trace_dump_arg_array(uint, values, num_values); @@ -1210,7 +1211,7 @@ trace_context_set_sampler_views(struct pipe_context *_pipe, trace_dump_call_begin("pipe_context", "set_sampler_views"); trace_dump_arg(ptr, pipe); - trace_dump_arg(uint, shader); + trace_dump_arg_enum(shader, tr_util_pipe_shader_type_name(shader)); trace_dump_arg(uint, start); trace_dump_arg(uint, num); trace_dump_arg(uint, unbind_num_trailing_slots); @@ -1581,7 +1582,7 @@ trace_context_create_fence_fd(struct pipe_context *_pipe, trace_dump_call_begin("pipe_context", "create_fence_fd"); trace_dump_arg(ptr, pipe); - trace_dump_arg(int, fd); + trace_dump_arg_enum(fd, tr_util_pipe_fd_type_name(fd)); trace_dump_arg(uint, type); pipe->create_fence_fd(pipe, fence, fd, type); diff --git a/src/gallium/auxiliary/driver_trace/tr_dump.h b/src/gallium/auxiliary/driver_trace/tr_dump.h index 9a4b294372c..d6b862d539a 100644 --- a/src/gallium/auxiliary/driver_trace/tr_dump.h +++ b/src/gallium/auxiliary/driver_trace/tr_dump.h @@ -123,6 +123,13 @@ bool trace_dump_is_triggered(void); trace_dump_arg_end(); \ } while(0) +#define trace_dump_arg_enum(_arg, _value) \ + do { \ + trace_dump_arg_begin(#_arg); \ + trace_dump_enum(_value); \ + trace_dump_arg_end(); \ + } while(0) + #define trace_dump_arg_struct(_type, _arg) \ do { \ trace_dump_arg_begin(#_arg); \ diff --git a/src/gallium/auxiliary/driver_trace/tr_screen.c b/src/gallium/auxiliary/driver_trace/tr_screen.c index 839d89995d9..4174fe64d10 100644 --- a/src/gallium/auxiliary/driver_trace/tr_screen.c +++ b/src/gallium/auxiliary/driver_trace/tr_screen.c @@ -37,6 +37,7 @@ #include "tr_context.h" #include "tr_screen.h" #include "tr_public.h" +#include "tr_util.h" static bool trace = false; @@ -148,7 +149,7 @@ trace_screen_get_param(struct pipe_screen *_screen, trace_dump_call_begin("pipe_screen", "get_param"); trace_dump_arg(ptr, screen); - trace_dump_arg(int, param); + trace_dump_arg_enum(param, tr_util_pipe_cap_name(param)); result = screen->get_param(screen, param); @@ -172,8 +173,8 @@ trace_screen_get_shader_param(struct pipe_screen *_screen, trace_dump_call_begin("pipe_screen", "get_shader_param"); trace_dump_arg(ptr, screen); - trace_dump_arg(uint, shader); - trace_dump_arg(int, param); + trace_dump_arg_enum(shader, tr_util_pipe_shader_type_name(shader)); + trace_dump_arg_enum(param, tr_util_pipe_shader_cap_name(param)); result = screen->get_shader_param(screen, shader, param); @@ -196,7 +197,7 @@ trace_screen_get_paramf(struct pipe_screen *_screen, trace_dump_call_begin("pipe_screen", "get_paramf"); trace_dump_arg(ptr, screen); - trace_dump_arg(int, param); + trace_dump_arg_enum(param, tr_util_pipe_capf_name(param)); result = screen->get_paramf(screen, param); @@ -220,8 +221,8 @@ trace_screen_get_compute_param(struct pipe_screen *_screen, trace_dump_call_begin("pipe_screen", "get_compute_param"); trace_dump_arg(ptr, screen); - trace_dump_arg(int, ir_type); - trace_dump_arg(int, param); + trace_dump_arg_enum(ir_type, tr_util_pipe_shader_ir_name(ir_type)); + trace_dump_arg_enum(param, tr_util_pipe_compute_cap_name(param)); trace_dump_arg(ptr, data); result = screen->get_compute_param(screen, ir_type, param, data); @@ -250,7 +251,7 @@ trace_screen_is_format_supported(struct pipe_screen *_screen, trace_dump_arg(ptr, screen); trace_dump_arg(format, format); - trace_dump_arg(int, target); + trace_dump_arg_enum(target, tr_util_pipe_texture_target_name(target)); trace_dump_arg(uint, sample_count); trace_dump_arg(uint, storage_sample_count); trace_dump_arg(uint, tex_usage); diff --git a/src/gallium/auxiliary/meson.build b/src/gallium/auxiliary/meson.build index 169d481734c..9da93185b91 100644 --- a/src/gallium/auxiliary/meson.build +++ b/src/gallium/auxiliary/meson.build @@ -472,6 +472,15 @@ if with_dri2 and with_platform_x11 endif endif +prog_enums2names = files('driver_trace/enums2names.py') +files_libgallium += custom_target( + 'tr_util.[ch]', + input: '../include/pipe/p_defines.h', + output: ['tr_util.c', 'tr_util.h'], + command: [prog_python, prog_enums2names, '@INPUT@', '-C', '@OUTPUT0@', '-H', '@OUTPUT1@', '-I', 'tr_util.h'], + depend_files: prog_enums2names, +) + files_libgallium += custom_target( 'u_tracepoints.c', input: 'util/u_tracepoints.py',