From 4347ccbe57ec8aa9efcc03e665ac6ad513b65f7a Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Thu, 27 Jun 2024 16:41:04 +0300 Subject: [PATCH] u_trace: rework tracepoint argument declaration We're about to add indirect arguments, having a better way to describe arguments (as capture/storage) will be useful. Signed-off-by: Lionel Landwerlin Reviewed-by: Danylo Piliaiev Part-of: --- src/freedreno/vulkan/tu_tracepoints.py | 7 +- src/intel/ds/intel_tracepoints.py | 19 ++-- src/util/perf/u_trace.py | 118 +++++++++++++++---------- 3 files changed, 79 insertions(+), 65 deletions(-) diff --git a/src/freedreno/vulkan/tu_tracepoints.py b/src/freedreno/vulkan/tu_tracepoints.py index 074db273b59..be4a39a8738 100644 --- a/src/freedreno/vulkan/tu_tracepoints.py +++ b/src/freedreno/vulkan/tu_tracepoints.py @@ -143,10 +143,9 @@ begin_end_tp('compute', # Annotations for Cmd(Begin|End)DebugUtilsLabelEXT for suffix in ["", "_rp"]: begin_end_tp('cmd_buffer_annotation' + suffix, - args=[ArgStruct(type='unsigned', var='len'), - ArgStruct(type='const char *', var='str'),], - tp_struct=[Arg(type='uint8_t', name='dummy', var='0', c_format='%hhu'), - Arg(type='char', name='str', var='str', c_format='%s', length_arg='len + 1', copy_func='strncpy'),]) + args=[Arg(type='unsigned', var='len'), + Arg(type='str', var='str', c_format='%s', length_arg='len + 1', copy_func='strncpy'),], + tp_struct=[Arg(type='uint8_t', name='dummy', var='0'),]) utrace_generate(cpath=args.utrace_src, hpath=args.utrace_hdr, diff --git a/src/intel/ds/intel_tracepoints.py b/src/intel/ds/intel_tracepoints.py index 8e090653104..665d173319e 100644 --- a/src/intel/ds/intel_tracepoints.py +++ b/src/intel/ds/intel_tracepoints.py @@ -78,10 +78,9 @@ def define_tracepoints(args): # Annotations for Queue(Begin|End)DebugUtilsLabelEXT begin_end_tp('queue_annotation', - tp_args=[ArgStruct(type='unsigned', var='len'), - ArgStruct(type='const char *', var='str'),], - tp_struct=[Arg(type='uint8_t', name='dummy', var='0', c_format='%hhu'), - Arg(type='char', name='str', var='str', c_format='%s', length_arg='len + 1', copy_func='strncpy'),], + tp_args=[Arg(type='unsigned', var='len'), + Arg(type='str', var='str', c_format='%s', length_arg='len + 1', copy_func='strncpy'),], + tp_struct=[Arg(type='uint8_t', name='dummy', var='0')], end_pipelined=False, need_cs_param=True) @@ -97,10 +96,9 @@ def define_tracepoints(args): # Annotations for Cmd(Begin|End)DebugUtilsLabelEXT begin_end_tp('cmd_buffer_annotation', - tp_args=[ArgStruct(type='unsigned', var='len'), - ArgStruct(type='const char *', var='str'),], - tp_struct=[Arg(type='uint8_t', name='dummy', var='0', c_format='%hhu'), - Arg(type='char', name='str', var='str', c_format='%s', length_arg='len + 1', copy_func='strncpy'),], + tp_args=[Arg(type='unsigned', var='len'), + Arg(type='str', var='str', c_format='%s', length_arg='len + 1', copy_func='strncpy'),], + tp_struct=[Arg(type='uint8_t', name='dummy', var='0'),], end_pipelined=True) # Transform feedback, only for Anv @@ -171,8 +169,7 @@ def define_tracepoints(args): begin_end_tp('draw_mesh', tp_args=[Arg(type='uint32_t', var='group_x', c_format='%u'), Arg(type='uint32_t', var='group_y', c_format='%u'), - Arg(type='uint32_t', var='group_z', c_format='%u'),], - tp_print=['group=%ux%ux%u', '__entry->group_x', '__entry->group_y', '__entry->group_z']) + Arg(type='uint32_t', var='group_z', c_format='%u'),]) begin_end_tp('draw_mesh_indirect', tp_args=[Arg(type='uint32_t', var='draw_count', c_format='%u'),]) begin_end_tp('draw_mesh_indirect_count', @@ -182,7 +179,6 @@ def define_tracepoints(args): tp_args=[Arg(type='uint32_t', var='group_x', c_format='%u'), Arg(type='uint32_t', var='group_y', c_format='%u'), Arg(type='uint32_t', var='group_z', c_format='%u'),], - tp_print=['group=%ux%ux%u', '__entry->group_x', '__entry->group_y', '__entry->group_z'], compute=True) # Used to identify copies generated by utrace @@ -198,7 +194,6 @@ def define_tracepoints(args): tp_args=[Arg(type='uint32_t', var='group_x', c_format='%u'), Arg(type='uint32_t', var='group_y', c_format='%u'), Arg(type='uint32_t', var='group_z', c_format='%u'),], - tp_print=['group=%ux%ux%u', '__entry->group_x', '__entry->group_y', '__entry->group_z'], compute=True) def flag_bits(args): diff --git a/src/util/perf/u_trace.py b/src/util/perf/u_trace.py index 80ba4311f40..32c83941165 100644 --- a/src/util/perf/u_trace.py +++ b/src/util/perf/u_trace.py @@ -56,21 +56,31 @@ class Tracepoint(object): assert isinstance(args, list) assert name not in TRACEPOINTS + def needs_storage(a): + if a.c_format is None: + return False + return True self.name = name self.args = args - if tp_struct is None: - tp_struct = args - else: - tp_struct += [x for x in args if isinstance(x, TracepointArg)] + # For storage data, include all the specified tp_struct by the caller + # as well as arguments needing storage + self.tp_struct = [] + if tp_struct is not None: + self.tp_struct += tp_struct + self.tp_struct += [x for x in args if needs_storage(x)] + # For printing, include all the arguments & tp_struct elements that + # have a format printer + self.tp_print = [x for x in args if x.c_format is not None] + if tp_struct is not None: + self.tp_print += [x for x in tp_struct if x.c_format is not None] - self.tp_struct = tp_struct self.has_variable_arg = False for arg in self.tp_struct: if arg.length_arg != None and not arg.length_arg.isdigit(): self.has_variable_arg = True break - self.tp_print = tp_print + self.tp_print_custom = tp_print self.tp_perfetto = tp_perfetto self.tp_markers = tp_markers self.tp_flags = tp_flags @@ -95,7 +105,7 @@ class Tracepoint(object): class TracepointArgStruct(): """Represents struct that is being passed as an argument """ - def __init__(self, type, var): + def __init__(self, type, var, c_format=None, fields=[]): """Parameters: - type: argument's C type. @@ -106,13 +116,27 @@ class TracepointArgStruct(): self.type = type self.var = var + self.name = var + self.is_struct = True + self.c_format = c_format + self.fields = fields + self.to_prim_type = None self.func_param = f"{self.type} {self.var}" + def value_expr(self, entry_name): + ret = None + if self.is_struct: + ret = ", ".join([f"{entry_name}->{self.name}.{f}" for f in self.fields]) + else: + ret = f"{entry_name}->{self.name}" + return ret + class TracepointArg(object): """Class that represents either an argument being passed or a field in a struct """ - def __init__(self, type, var, c_format, name=None, to_prim_type=None, length_arg=None, copy_func=None): + def __init__(self, type, var, c_format=None, name=None, to_prim_type=None, + length_arg=None, copy_func=None): """Parameters: - type: argument's C type. @@ -126,7 +150,6 @@ class TracepointArg(object): """ assert isinstance(type, str) assert isinstance(var, str) - assert isinstance(c_format, str) self.type = type self.var = var @@ -138,10 +161,13 @@ class TracepointArg(object): self.length_arg = length_arg self.copy_func = copy_func + self.is_struct = False + if self.type == "str": - self.struct_member = f"char {self.name}[{length_arg} + 1]" - elif self.length_arg: - self.struct_member = f"{self.type} {self.name}[0]" + if self.length_arg and self.length_arg.isdigit(): + self.struct_member = f"char {self.name}[{length_arg} + 1]" + else: + self.struct_member = f"char {self.name}[0]" else: self.struct_member = f"{self.type} {self.name}" @@ -150,6 +176,12 @@ class TracepointArg(object): else: self.func_param = f"{self.type} {self.var}" + def value_expr(self, entry_name): + ret = f"{entry_name}->{self.name}" + if not self.is_struct and self.to_prim_type: + ret = self.to_prim_type.format(ret) + return ret + HEADERS = [] @@ -247,7 +279,7 @@ struct trace_${trace_name} { % for arg in trace.tp_struct: ${arg.struct_member}; % endfor -% if len(trace.args) == 0: +% if len(trace.tp_struct) == 0: #ifdef __cplusplus /* avoid warnings about empty struct size mis-match in C vs C++.. * the size mis-match is harmless because (a) nothing will deref @@ -385,53 +417,49 @@ ${trace_toggle_name}_config_variable(void) */ % if trace.can_generate_print(): static void __print_${trace_name}(FILE *out, const void *arg) { + % if len(trace.tp_struct) > 0: const struct trace_${trace_name} *__entry = (const struct trace_${trace_name} *)arg; - % if trace.tp_print is not None: - fprintf(out, "${trace.tp_print[0]}\\n" - % for arg in trace.tp_print[1:]: + % endif + % if trace.tp_print_custom is not None: + fprintf(out, "${trace.tp_print_custom[0]}\\n" + % for arg in trace.tp_print_custom[1:]: , ${arg} % endfor % else: fprintf(out, "" - % for arg in trace.tp_struct: + % for arg in trace.tp_print: "${arg.name}=${arg.c_format}, " % endfor "\\n" - % for arg in trace.tp_struct: - % if arg.to_prim_type: - ,${arg.to_prim_type.format('__entry->' + arg.name)} - % else: - ,__entry->${arg.name} - % endif + % for arg in trace.tp_print: + ,${arg.value_expr("__entry")} % endfor % endif ); } static void __print_json_${trace_name}(FILE *out, const void *arg) { + % if len(trace.tp_struct) > 0: const struct trace_${trace_name} *__entry = (const struct trace_${trace_name} *)arg; - % if trace.tp_print is not None: - fprintf(out, "\\"unstructured\\": \\"${trace.tp_print[0]}\\"" - % for arg in trace.tp_print[1:]: + % endif + % if trace.tp_print_custom is not None: + fprintf(out, "\\"unstructured\\": \\"${trace.tp_print_custom[0]}\\"" + % for arg in trace.tp_print_custom[1:]: , ${arg} % endfor % else: fprintf(out, "" - % for arg in trace.tp_struct: + % for arg in trace.tp_print: "\\"${arg.name}\\": \\"${arg.c_format}\\"" - % if arg != trace.tp_struct[-1]: + % if arg != trace.tp_print[-1]: ", " - % endif - % endfor - % for arg in trace.tp_struct: - % if arg.to_prim_type: - ,${arg.to_prim_type.format('__entry->' + arg.name)} - % else: - ,__entry->${arg.name} % endif % endfor + % for arg in trace.tp_print: + ,${arg.value_expr("__entry")} + % endfor % endif ); } @@ -446,16 +474,12 @@ __attribute__((format(printf, 3, 4))) void ${trace.tp_markers}(struct u_trace_co static void __emit_label_${trace_name}(struct u_trace_context *utctx, void *cs, struct trace_${trace_name} *entry) { ${trace.tp_markers}(utctx, cs, "${trace_name}(" - % for idx,arg in enumerate(trace.tp_struct): + % for idx,arg in enumerate(trace.tp_print): "${"," if idx != 0 else ""}${arg.name}=${arg.c_format}" % endfor ")" - % for arg in trace.tp_struct: - % if arg.to_prim_type: - ,${arg.to_prim_type.format('entry->' + arg.name)} - % else: - ,entry->${arg.name} - % endif + % for arg in trace.tp_print: + ,${arg.value_expr('entry')} % endfor ); } @@ -603,19 +627,15 @@ static void UNUSED trace_payload_as_extra_${trace_name}(perfetto::protos::pbzero::GpuRenderStageEvent *event, const struct trace_${trace_name} *payload) { - % if all([trace.tp_perfetto, trace.tp_struct]) and len(trace.tp_struct) > 0: + % if trace.tp_perfetto is not None and len(trace.tp_print) > 0: char buf[128]; - % for arg in trace.tp_struct: + % for arg in trace.tp_print: { auto data = event->add_extra_data(); data->set_name("${arg.name}"); - % if arg.to_prim_type: - sprintf(buf, "${arg.c_format}", ${arg.to_prim_type.format('payload->' + arg.name)}); - % else: - sprintf(buf, "${arg.c_format}", payload->${arg.name}); - % endif + sprintf(buf, "${arg.c_format}", ${arg.value_expr("payload")}); data->set_value(buf); }