mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-28 01:40:08 +01:00
gallium/tools: add option for ignoring junk calls in trace dumper
Previously tracediff.sh used postprocessing sed-script to remove unwanted calls from the dump output. Instead of that, add option to parse.py to ignore a list of calls at parsing phase. Currently this list is hardcoded in parse.py. Also clean up the trace model code and pointer tracking a bit to avoid static state in Pointer class. Signed-off-by: Matti Hamalainen <ccr@tnsp.org> Acked-by: Mike Blumenkrantz <michael.blumenkrantz@gmail.com> Reviewed-by: Dylan Baker <dylan@pnwbakers.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17135>
This commit is contained in:
parent
5f00b54873
commit
6f70a1cd14
4 changed files with 81 additions and 47 deletions
|
|
@ -780,8 +780,8 @@ class Interpreter(parser.SimpleTraceDumper):
|
|||
('pipe_context', 'transfer_unmap'),
|
||||
))
|
||||
|
||||
def __init__(self, stream, options, formatter):
|
||||
parser.SimpleTraceDumper.__init__(self, stream, options, formatter)
|
||||
def __init__(self, stream, options, formatter, state):
|
||||
parser.SimpleTraceDumper.__init__(self, stream, options, formatter, state)
|
||||
self.objects = {}
|
||||
self.result = None
|
||||
self.globl = Global(self)
|
||||
|
|
@ -878,7 +878,7 @@ class Main(parser.Main):
|
|||
|
||||
def process_arg(self, stream, options):
|
||||
formatter = format.Formatter(sys.stderr)
|
||||
parser = Interpreter(stream, options, formatter)
|
||||
parser = Interpreter(stream, options, formatter, model.TraceStateData())
|
||||
parser.parse()
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,14 @@ class ModelOptions:
|
|||
self.__dict__[var] = args.__dict__[var]
|
||||
|
||||
|
||||
class TraceStateData:
|
||||
|
||||
def __init__(self):
|
||||
self.ptr_list = {}
|
||||
self.ptr_type_list = {}
|
||||
self.ptr_types_list = {}
|
||||
|
||||
|
||||
class Node:
|
||||
|
||||
def visit(self, visitor):
|
||||
|
|
@ -81,14 +89,10 @@ class Literal(Node):
|
|||
class Blob(Node):
|
||||
|
||||
def __init__(self, value):
|
||||
self._rawValue = None
|
||||
self._hexValue = value
|
||||
self.value = binascii.a2b_hex(value)
|
||||
|
||||
def getValue(self):
|
||||
if self._rawValue is None:
|
||||
self._rawValue = binascii.a2b_hex(self._hexValue)
|
||||
self._hexValue = None
|
||||
return self._rawValue
|
||||
return self.value
|
||||
|
||||
def visit(self, visitor):
|
||||
visitor.visit_blob(self)
|
||||
|
|
@ -123,19 +127,18 @@ class Struct(Node):
|
|||
|
||||
|
||||
class Pointer(Node):
|
||||
|
||||
ptr_list = {}
|
||||
ptr_type_list = {}
|
||||
ptr_types_list = {}
|
||||
|
||||
ptr_ignore_list = ["ret", "elem"]
|
||||
|
||||
def __init__(self, address, pname):
|
||||
def __init__(self, state, address, pname):
|
||||
self.address = address
|
||||
self.pname = pname
|
||||
self.state = state
|
||||
|
||||
# Check if address exists in list and if it is a return value address
|
||||
t1 = address in self.ptr_list
|
||||
t1 = address in state.ptr_list
|
||||
if t1:
|
||||
rname = self.ptr_type_list[address]
|
||||
rname = state.ptr_type_list[address]
|
||||
t2 = rname in self.ptr_ignore_list and pname not in self.ptr_ignore_list
|
||||
else:
|
||||
rname = pname
|
||||
|
|
@ -149,15 +152,18 @@ class Pointer(Node):
|
|||
|
||||
# Add / update
|
||||
self.adjust_ptr_type_count(pname, 1)
|
||||
tmp = "{}_{}".format(pname, self.ptr_types_list[pname])
|
||||
self.ptr_list[address] = tmp
|
||||
self.ptr_type_list[address] = pname
|
||||
tmp = "{}_{}".format(pname, state.ptr_types_list[pname])
|
||||
state.ptr_list[address] = tmp
|
||||
state.ptr_type_list[address] = pname
|
||||
|
||||
def adjust_ptr_type_count(self, pname, delta):
|
||||
if pname not in self.ptr_types_list:
|
||||
self.ptr_types_list[pname] = 0
|
||||
if pname not in self.state.ptr_types_list:
|
||||
self.state.ptr_types_list[pname] = 0
|
||||
|
||||
self.ptr_types_list[pname] += delta
|
||||
self.state.ptr_types_list[pname] += delta
|
||||
|
||||
def named_address(self):
|
||||
return self.state.ptr_list[self.address]
|
||||
|
||||
def visit(self, visitor):
|
||||
visitor.visit_pointer(self)
|
||||
|
|
@ -258,13 +264,13 @@ class PrettyPrinter:
|
|||
|
||||
def visit_pointer(self, node):
|
||||
if self.options.named_ptrs:
|
||||
self.formatter.address(node.ptr_list[node.address])
|
||||
self.formatter.address(node.named_address())
|
||||
else:
|
||||
self.formatter.address(node.address)
|
||||
|
||||
def visit_call(self, node):
|
||||
if not self.options.suppress_variants:
|
||||
self.formatter.text('%s ' % node.no)
|
||||
self.formatter.text(f'{node.no} ')
|
||||
|
||||
if node.klass is not None:
|
||||
self.formatter.function(node.klass + '::' + node.method)
|
||||
|
|
@ -289,8 +295,9 @@ class PrettyPrinter:
|
|||
self.formatter.text(' // time ')
|
||||
node.time.visit(self)
|
||||
|
||||
self.formatter.newline()
|
||||
|
||||
def visit_trace(self, node):
|
||||
for call in node.calls:
|
||||
call.visit(self)
|
||||
self.formatter.newline()
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,22 @@ import format
|
|||
from model import *
|
||||
|
||||
|
||||
trace_ignore_calls = set((
|
||||
("pipe_screen", "is_format_supported"),
|
||||
("pipe_screen", "get_name"),
|
||||
("pipe_screen", "get_vendor"),
|
||||
("pipe_screen", "get_param"),
|
||||
("pipe_screen", "get_paramf"),
|
||||
("pipe_screen", "get_shader_param"),
|
||||
("pipe_screen", "get_compute_param"),
|
||||
("pipe_screen", "get_disk_shader_cache"),
|
||||
))
|
||||
|
||||
|
||||
def trace_call_ignore(call):
|
||||
return (call.klass, call.method) in trace_ignore_calls
|
||||
|
||||
|
||||
ELEMENT_START, ELEMENT_END, CHARACTER_DATA, EOF = range(4)
|
||||
|
||||
|
||||
|
|
@ -192,15 +208,18 @@ class XmlParser:
|
|||
|
||||
class TraceParser(XmlParser):
|
||||
|
||||
def __init__(self, fp):
|
||||
def __init__(self, fp, options, state):
|
||||
XmlParser.__init__(self, fp)
|
||||
self.last_call_no = 0
|
||||
|
||||
self.state = state
|
||||
self.options = options
|
||||
|
||||
def parse(self):
|
||||
self.element_start('trace')
|
||||
while self.token.type not in (ELEMENT_END, EOF):
|
||||
call = self.parse_call()
|
||||
self.handle_call(call)
|
||||
if not self.options.ignore_junk or not trace_call_ignore(call):
|
||||
self.handle_call(call)
|
||||
if self.token.type != EOF:
|
||||
self.element_end('trace')
|
||||
|
||||
|
|
@ -347,7 +366,7 @@ class TraceParser(XmlParser):
|
|||
address = self.character_data()
|
||||
self.element_end('ptr')
|
||||
|
||||
return Pointer(address, pname)
|
||||
return Pointer(self.state, address, pname)
|
||||
|
||||
def handle_call(self, call):
|
||||
pass
|
||||
|
|
@ -355,21 +374,20 @@ class TraceParser(XmlParser):
|
|||
|
||||
class SimpleTraceDumper(TraceParser):
|
||||
|
||||
def __init__(self, fp, options, formatter):
|
||||
TraceParser.__init__(self, fp)
|
||||
def __init__(self, fp, options, formatter, state):
|
||||
TraceParser.__init__(self, fp, options, state)
|
||||
self.options = options
|
||||
self.formatter = formatter
|
||||
self.pretty_printer = PrettyPrinter(self.formatter, options)
|
||||
|
||||
def handle_call(self, call):
|
||||
call.visit(self.pretty_printer)
|
||||
self.formatter.newline()
|
||||
|
||||
|
||||
class TraceDumper(SimpleTraceDumper):
|
||||
|
||||
def __init__(self, fp, options, formatter):
|
||||
SimpleTraceDumper.__init__(self, fp, options, formatter)
|
||||
def __init__(self, fp, options, formatter, state):
|
||||
SimpleTraceDumper.__init__(self, fp, options, formatter, state)
|
||||
self.call_stack = []
|
||||
|
||||
def handle_call(self, call):
|
||||
|
|
@ -377,12 +395,6 @@ class TraceDumper(SimpleTraceDumper):
|
|||
self.call_stack.append(call)
|
||||
else:
|
||||
call.visit(self.pretty_printer)
|
||||
self.formatter.newline()
|
||||
|
||||
def dump_calls(self):
|
||||
for call in self.call_stack:
|
||||
call.visit(self.pretty_printer)
|
||||
self.formatter.newline()
|
||||
|
||||
|
||||
class ParseOptions(ModelOptions):
|
||||
|
|
@ -390,6 +402,7 @@ class ParseOptions(ModelOptions):
|
|||
def __init__(self, args=None):
|
||||
# Initialize options local to this module
|
||||
self.plain = False
|
||||
self.ignore_junk = False
|
||||
|
||||
ModelOptions.__init__(self, args)
|
||||
|
||||
|
|
@ -425,23 +438,38 @@ class Main:
|
|||
return ParseOptions(args)
|
||||
|
||||
def get_optparser(self):
|
||||
estr = "\nList of junk calls:\n"
|
||||
for klass, call in sorted(trace_ignore_calls):
|
||||
estr += f" {klass}::{call}\n"
|
||||
|
||||
optparser = argparse.ArgumentParser(
|
||||
description="Parse and dump Gallium trace(s)")
|
||||
description="Parse and dump Gallium trace(s)",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog=estr)
|
||||
|
||||
optparser.add_argument("filename", action="extend", nargs="+",
|
||||
type=str, metavar="filename", help="Gallium trace filename (plain or .gz, .bz2)")
|
||||
|
||||
optparser.add_argument("-p", "--plain",
|
||||
action="store_const", const=True, default=False,
|
||||
dest="plain", help="disable ANSI color etc. formatting")
|
||||
|
||||
optparser.add_argument("-S", "--suppress",
|
||||
action="store_const", const=True, default=False,
|
||||
dest="suppress_variants", help="suppress some variants in output for better diffability")
|
||||
|
||||
optparser.add_argument("-N", "--named",
|
||||
action="store_const", const=True, default=False,
|
||||
dest="named_ptrs", help="generate symbolic names for raw pointer values")
|
||||
|
||||
optparser.add_argument("-M", "--method-only",
|
||||
action="store_const", const=True, default=False,
|
||||
dest="method_only", help="output only call names without arguments")
|
||||
|
||||
optparser.add_argument("-I", "--ignore-junk",
|
||||
action="store_const", const=True, default=False,
|
||||
dest="ignore_junk", help="filter out/ignore junk calls (see below)")
|
||||
|
||||
return optparser
|
||||
|
||||
def process_arg(self, stream, options):
|
||||
|
|
@ -450,11 +478,12 @@ class Main:
|
|||
else:
|
||||
formatter = format.DefaultFormatter(sys.stdout)
|
||||
|
||||
parser = TraceDumper(stream, options, formatter)
|
||||
parser.parse()
|
||||
dump = TraceDumper(stream, options, formatter, TraceStateData())
|
||||
dump.parse()
|
||||
|
||||
if options.named_ptrs:
|
||||
parser.dump_calls()
|
||||
for call in dump.call_stack:
|
||||
call.visit(dump.pretty_printer)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
|||
|
|
@ -81,11 +81,9 @@ strip_dump()
|
|||
INFILE="$1"
|
||||
OUTFILE="$2"
|
||||
|
||||
python3 "$TRACEDUMP" --plain --suppress \
|
||||
python3 "$TRACEDUMP" --plain --suppress --ignore-junk \
|
||||
"${DUMP_ARGS[@]}" "$INFILE" \
|
||||
| sed \
|
||||
-e '/pipe_screen::is_format_supported/d' \
|
||||
-e '/pipe_screen::get_\(shader_\)\?paramf\?/d' \
|
||||
-e 's/\r$//g' \
|
||||
-e 's/, /,\n\t/g' \
|
||||
-e 's/) = /)\n\t= /' \
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue