summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMatti Hamalainen <ccr@tnsp.org>2021-03-25 14:36:54 +0200
committerMarge Bot <eric+marge@anholt.net>2021-04-10 14:00:45 +0000
commit44ed8378bf69fc3762e114eb3b1985daa6566e28 (patch)
treeb718361883dc76a8d3373576d0065d35b2dcd74e /src
parente7bece080f45580e387a4dcbd5f0e79979277ce4 (diff)
gallium/tools: update trace scripts to Python 3
Bring the scripts for parsing, dumping state and diffing of Gallium trace files to modern day by updating them to Python 3. Add option '-p' to some tools for outputting only plaintext instead of ANSI / colorized format. Also fix state parsing of some dumps by adding 'clear_render_target' and 'get_disk_shader_cache' to ignored calls list. Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/4321 Signed-off-by: Matti Hamalainen <ccr@tnsp.org> Acked-By: Mike Blumenkrantz <michael.blumenkrantz@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9830>
Diffstat (limited to 'src')
-rwxr-xr-xsrc/gallium/tools/trace/diff_state.py40
-rwxr-xr-xsrc/gallium/tools/trace/dump.py2
-rwxr-xr-xsrc/gallium/tools/trace/dump_state.py31
-rwxr-xr-xsrc/gallium/tools/trace/format.py6
-rwxr-xr-xsrc/gallium/tools/trace/model.py11
-rwxr-xr-xsrc/gallium/tools/trace/parse.py65
-rwxr-xr-xsrc/gallium/tools/trace/tracediff.sh2
7 files changed, 81 insertions, 76 deletions
diff --git a/src/gallium/tools/trace/diff_state.py b/src/gallium/tools/trace/diff_state.py
index 877dc388a8e..4f7e5b076fa 100755
--- a/src/gallium/tools/trace/diff_state.py
+++ b/src/gallium/tools/trace/diff_state.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python3
##########################################################################
#
# Copyright 2011 Jose Fonseca
@@ -26,7 +26,7 @@
import json
-import optparse
+import argparse
import re
import difflib
import sys
@@ -79,8 +79,7 @@ class Dumper(Visitor):
def visitObject(self, node):
self.enter_object()
- members = node.keys()
- members.sort()
+ members = sorted(node)
for i in range(len(members)):
name = members[i]
value = node[name]
@@ -147,10 +146,8 @@ class Comparer(Visitor):
return False
if len(a) != len(b) and not self.ignore_added:
return False
- ak = a.keys()
- bk = b.keys()
- ak.sort()
- bk.sort()
+ ak = sorted(a)
+ bk = sorted(b)
if ak != bk and not self.ignore_added:
return False
for k in ak:
@@ -174,11 +171,11 @@ class Comparer(Visitor):
return True
def visitValue(self, a, b):
- if isinstance(a, float) or isinstance(b, float):
+ if isinstance(a, float) and isinstance(b, float):
if a == 0:
return abs(b) < self.tolerance
else:
- return abs((b - a)/a) < self.tolerance
+ return abs((b - a) / a) < self.tolerance
else:
return a == b
@@ -247,7 +244,7 @@ class Differ(Visitor):
self.replace(a, b)
def replace(self, a, b):
- if isinstance(a, basestring) and isinstance(b, basestring):
+ if isinstance(a, str) and isinstance(b, str):
if '\n' in a or '\n' in b:
a = a.splitlines()
b = b.splitlines()
@@ -276,7 +273,7 @@ class Differ(Visitor):
self.dumper.visit(b)
def isMultilineString(self, value):
- return isinstance(value, basestring) and '\n' in value
+ return isinstance(value, str) and '\n' in value
def replaceMultilineString(self, a, b):
self.dumper.visit(a)
@@ -330,20 +327,21 @@ def load(stream, strip_images = True, strip_comments = True):
def main():
- optparser = optparse.OptionParser(
- usage="\n\t%prog [options] <ref_json> <src_json>")
- optparser.add_option(
- '--keep-images',
+ optparser = argparse.ArgumentParser(
+ description="Diff JSON format state dump files")
+ optparser.add_argument("-k", "--keep-images",
action="store_false", dest="strip_images", default=True,
help="compare images")
- (options, args) = optparser.parse_args(sys.argv[1:])
+ optparser.add_argument("ref_json", action="store",
+ type=str, help="reference state file")
+ optparser.add_argument("src_json", action="store",
+ type=str, help="source state file")
- if len(args) != 2:
- optparser.error('incorrect number of arguments')
+ args = optparser.parse_args()
- a = load(open(sys.argv[1], 'rt'), options.strip_images)
- b = load(open(sys.argv[2], 'rt'), options.strip_images)
+ a = load(open(args.ref_json, 'rt'), args.strip_images)
+ b = load(open(args.src_json, 'rt'), args.strip_images)
if False:
dumper = Dumper()
diff --git a/src/gallium/tools/trace/dump.py b/src/gallium/tools/trace/dump.py
index 10211c87c56..b80e27ae423 100755
--- a/src/gallium/tools/trace/dump.py
+++ b/src/gallium/tools/trace/dump.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python3
##########################################################################
#
# Copyright 2008 VMware, Inc.
diff --git a/src/gallium/tools/trace/dump_state.py b/src/gallium/tools/trace/dump_state.py
index 2622d130bf8..8b68d83f9a2 100755
--- a/src/gallium/tools/trace/dump_state.py
+++ b/src/gallium/tools/trace/dump_state.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python3
##########################################################################
#
# Copyright 2008-2013, VMware, Inc.
@@ -58,8 +58,7 @@ PIPE_SHADER_TYPES = 4
def serialize(obj):
'''JSON serializer function for non-standard Python objects.'''
-
- if isinstance(obj, bytearray):
+ if isinstance(obj, bytearray) or isinstance(obj, bytes):
# TODO: Decide on a single way of dumping blobs
if False:
# Don't dump full blobs, but merely a description of their size and
@@ -72,10 +71,10 @@ def serialize(obj):
# Dump blobs as an array of 16byte hexadecimals
res = []
for i in range(0, len(obj), 16):
- res.append(binascii.b2a_hex(obj[i: i+16]))
+ res.append(obj[i : i + 16].hex())
return res
# Dump blobs as a single hexadecimal string
- return binascii.b2a_hex(obj)
+ return obj.hex()
# If the object has a __json__ method, use it.
try:
@@ -207,7 +206,7 @@ class Screen(Dispatcher):
def resource_destroy(self, resource):
self.interpreter.unregister_object(resource)
- def fence_finish(self, fence, timeout=None):
+ def fence_finish(self, fence, timeout=None, ctx=None):
pass
def fence_signalled(self, fence):
@@ -473,7 +472,7 @@ class Context(Dispatcher):
count = min(info.count, self.MAX_ELEMENTS)
indices = []
- for i in xrange(info.start, info.start + count):
+ for i in range(info.start, info.start + count):
offset = self._state.index_buffer.offset + i*index_size
if offset + index_size > len(data):
index = 0
@@ -492,7 +491,7 @@ class Context(Dispatcher):
count = min(count, self.MAX_ELEMENTS)
vertices = []
- for index in xrange(start, start + count):
+ for index in range(start, start + count):
if index >= start + 16:
sys.stdout.write('\t...\n')
break
@@ -669,7 +668,7 @@ class Context(Dispatcher):
# Return a fake fence
return self.interpreter.call_no
- def clear(self, buffers, color, depth, stencil):
+ def clear(self, buffers, color, depth, stencil, scissor_state=None):
pass
def clear_render_target(self, dst, rgba, dstx, dsty, width, height):
@@ -717,11 +716,13 @@ class Interpreter(parser.TraceDumper):
('pipe_screen', 'get_param'),
('pipe_screen', 'get_paramf'),
('pipe_screen', 'get_shader_param'),
+ ('pipe_screen', 'get_disk_shader_cache'),
('pipe_context', 'clear_render_target'), # XXX workaround trace bugs
+ ('pipe_context', 'flush_resource'),
))
def __init__(self, stream, options):
- parser.TraceDumper.__init__(self, stream, sys.stderr)
+ parser.TraceDumper.__init__(self, stream, options, sys.stderr)
self.options = options
self.objects = {}
self.result = None
@@ -767,7 +768,7 @@ class Interpreter(parser.TraceDumper):
args = args[1:]
else:
obj = self.globl
-
+
method = getattr(obj, call.method)
ret = method(**dict(args))
@@ -793,10 +794,10 @@ class Main(parser.Main):
'''Custom options.'''
optparser = parser.Main.get_optparser(self)
- optparser.add_option("-q", "--quiet", action="store_const", const=0, dest="verbosity", help="no messages")
- optparser.add_option("-v", "--verbose", action="count", dest="verbosity", default=0, help="increase verbosity level")
- optparser.add_option("-c", "--call", action="store", type="int", dest="call", default=0xffffffff, help="dump on this call")
- optparser.add_option("-d", "--draw", action="store", type="int", dest="draw", default=0xffffffff, help="dump on this draw")
+ optparser.add_argument("-v", "--verbose", action="count", default=0, dest="verbosity", help="increase verbosity level")
+ optparser.add_argument("-q", "--quiet", action="store_const", const=0, dest="verbosity", help="no messages")
+ optparser.add_argument("-c", "--call", action="store", type=int, dest="call", default=0xffffffff, help="dump on this call")
+ optparser.add_argument("-d", "--draw", action="store", type=int, dest="draw", default=0xffffffff, help="dump on this draw")
return optparser
def process_arg(self, stream, options):
diff --git a/src/gallium/tools/trace/format.py b/src/gallium/tools/trace/format.py
index de6f4021597..d50675c45d0 100755
--- a/src/gallium/tools/trace/format.py
+++ b/src/gallium/tools/trace/format.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python3
##########################################################################
#
# Copyright 2008 VMware, Inc.
@@ -164,9 +164,9 @@ class WindowsConsoleFormatter(Formatter):
def DefaultFormatter(stream):
- if sys.platform in ('linux2', 'cygwin'):
+ if sys.platform in ('linux2', 'linux', 'cygwin'):
return AnsiFormatter(stream)
- elif sys.platform in ('win32',):
+ elif sys.platform in ('win32', ):
return WindowsConsoleFormatter(stream)
else:
return Formatter(stream)
diff --git a/src/gallium/tools/trace/model.py b/src/gallium/tools/trace/model.py
index 6a421847113..913a4ef13d2 100755
--- a/src/gallium/tools/trace/model.py
+++ b/src/gallium/tools/trace/model.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python3
##########################################################################
#
# Copyright 2008 VMware, Inc.
@@ -33,12 +33,7 @@
import sys
import string
import binascii
-
-try:
- from cStringIO import StringIO
-except ImportError:
- from StringIO import StringIO
-
+from io import StringIO
import format
@@ -177,7 +172,7 @@ class PrettyPrinter:
self.formatter.literal('NULL')
return
- if isinstance(node.value, basestring):
+ if isinstance(node.value, str):
self.formatter.literal('"' + node.value + '"')
return
diff --git a/src/gallium/tools/trace/parse.py b/src/gallium/tools/trace/parse.py
index 004b585f95a..a529f389723 100755
--- a/src/gallium/tools/trace/parse.py
+++ b/src/gallium/tools/trace/parse.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python3
##########################################################################
#
# Copyright 2008 VMware, Inc.
@@ -27,9 +27,10 @@
##########################################################################
+import io
import sys
-import xml.parsers.expat
-import optparse
+import xml.parsers.expat as xpat
+import argparse
from model import *
@@ -72,7 +73,7 @@ class XmlTokenizer:
self.character_pos = 0, 0
self.character_data = ''
- self.parser = xml.parsers.expat.ParserCreate()
+ self.parser = xpat.ParserCreate()
self.parser.StartElementHandler = self.handle_element_start
self.parser.EndElementHandler = self.handle_element_end
self.parser.CharacterDataHandler = self.handle_character_data
@@ -112,8 +113,8 @@ class XmlTokenizer:
data = data.rstrip('\0')
try:
self.parser.Parse(data, self.final)
- except xml.parsers.expat.ExpatError, e:
- #if e.code == xml.parsers.expat.errors.XML_ERROR_NO_ELEMENTS:
+ except xpat.ExpatError as e:
+ #if e.code == xpat.errors.XML_ERROR_NO_ELEMENTS:
if e.code == 3:
pass
else:
@@ -205,7 +206,7 @@ class TraceParser(XmlParser):
attrs = self.element_start('call')
try:
no = int(attrs['no'])
- except KeyError:
+ except KeyError as e:
self.last_call_no += 1
no = self.last_call_no
else:
@@ -352,9 +353,12 @@ class TraceParser(XmlParser):
class TraceDumper(TraceParser):
- def __init__(self, fp, outStream = sys.stdout):
+ def __init__(self, fp, options, outStream = sys.stdout):
TraceParser.__init__(self, fp)
- self.formatter = format.DefaultFormatter(outStream)
+ if options.plain:
+ self.formatter = format.Formatter(outStream)
+ else:
+ self.formatter = format.DefaultFormatter(outStream)
self.pretty_printer = PrettyPrinter(self.formatter)
def handle_call(self, call):
@@ -370,29 +374,36 @@ class Main:
def main(self):
optparser = self.get_optparser()
- (options, args) = optparser.parse_args(sys.argv[1:])
-
- if not args:
- optparser.error('insufficient number of arguments')
-
- for arg in args:
- if arg.endswith('.gz'):
- from gzip import GzipFile
- stream = GzipFile(arg, 'rt')
- elif arg.endswith('.bz2'):
- from bz2 import BZ2File
- stream = BZ2File(arg, 'rU')
- else:
- stream = open(arg, 'rt')
- self.process_arg(stream, options)
+ args = optparser.parse_args()
+
+ for fname in args.filename:
+ try:
+ if fname.endswith('.gz'):
+ from gzip import GzipFile
+ stream = io.TextIOWrapper(GzipFile(fname, 'rb'))
+ elif fname.endswith('.bz2'):
+ from bz2 import BZ2File
+ stream = io.TextIOWrapper(BZ2File(fname, 'rb'))
+ else:
+ stream = open(fname, 'rt')
+ except Exception as e:
+ print("ERROR: {}".format(str(e)))
+ sys.exit(1)
+
+ self.process_arg(stream, args)
def get_optparser(self):
- optparser = optparse.OptionParser(
- usage="\n\t%prog [options] TRACE [...]")
+ optparser = argparse.ArgumentParser(
+ description="Parse and dump Gallium trace(s)")
+ 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")
return optparser
def process_arg(self, stream, options):
- parser = TraceDumper(stream)
+ parser = TraceDumper(stream, options)
parser.parse()
diff --git a/src/gallium/tools/trace/tracediff.sh b/src/gallium/tools/trace/tracediff.sh
index dccb7a3d519..da9dd4a9276 100755
--- a/src/gallium/tools/trace/tracediff.sh
+++ b/src/gallium/tools/trace/tracediff.sh
@@ -29,7 +29,7 @@ set -e
TRACEDUMP=${TRACEDUMP:-`dirname "$0"`/dump.py}
stripdump () {
- python $TRACEDUMP "$1" \
+ python3 $TRACEDUMP "$1" \
| sed \
-e 's@ // time .*@@' \
-e 's/\x1b\[[0-9]\{1,2\}\(;[0-9]\{1,2\}\)\{0,2\}m//g' \