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:
Matti Hamalainen 2022-01-21 23:35:33 +02:00 committed by Matti Hämäläinen
parent 5f00b54873
commit 6f70a1cd14
4 changed files with 81 additions and 47 deletions

View file

@ -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()

View file

@ -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()

View file

@ -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__':

View file

@ -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= /' \