summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLionel Landwerlin <lionel.g.landwerlin@intel.com>2022-11-28 12:03:27 +0200
committerMatt Turner <mattst88@gmail.com>2022-12-10 19:56:57 +0000
commitfb6eaa1960b7b2d7b70a608a4c4ef80a0d5e8cac (patch)
treeb766d9921d315131fc5e389d64f684c3a86be22c
parent70fcf4a81b2e602d54d4fa21ca8451174480ac7b (diff)
report-fossil: add anv support
-rw-r--r--README.md8
-rwxr-xr-xanv-report-fossil.py187
-rwxr-xr-xreport-fossil.py31
3 files changed, 28 insertions, 198 deletions
diff --git a/README.md b/README.md
index 85c3605..0933c37 100644
--- a/README.md
+++ b/README.md
@@ -124,13 +124,7 @@ Or you can use fossil_prune_replay.sh to replay a specific pipeline by hash:
If you do not get a .csv file it likely means that a driver without
`VK_KHR_pipeline_statistics`, such as a system installed driver.
-You can then compare two different csv files using the anv-report-fossil.py or
-radv-report-fossil.py scripts:
-
- $ anv-report-fossil.py baseline.csv development.csv
- $ radv-report-fossil.py baseline.csv development.csv
-
-Or the report-fossil.py script, which guesses the driver used:
+You can then compare two different csv files using the report-fossil.py script:
$ report-fossil.py baseline.csv development.csv
diff --git a/anv-report-fossil.py b/anv-report-fossil.py
deleted file mode 100755
index 7996aaf..0000000
--- a/anv-report-fossil.py
+++ /dev/null
@@ -1,187 +0,0 @@
-#!/usr/bin/env python3
-# Copyright © 2019 Intel Corporation
-
-# 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, sublicense, 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 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 NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS 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 argparse
-import csv
-import pathlib
-import typing
-
-import attr
-
-if typing.TYPE_CHECKING:
- import typing_extensions
-
- class DiffProtocol(typing_extensions.Protocol):
-
- old: int
- new: int
-
- V = typing.TypeVar('V', int, float, str)
-
-
-@attr.s(slots=True)
-class Result:
-
- name: str = attr.ib()
- instructions: typing.Optional[int] = attr.ib()
- sends: typing.Optional[int] = attr.ib()
- loops: typing.Optional[int] = attr.ib()
- cycles: typing.Optional[int] = attr.ib()
- spills: typing.Optional[int] = attr.ib()
- fills: typing.Optional[int] = attr.ib()
-
-
-@attr.s(slots=True)
-class ResultFactory:
-
- lookups: typing.Dict[str, int] = attr.ib()
-
- def __call__(self, row: typing.List[str]) -> Result:
- def get(name: str, type_: typing.Type['V']) -> typing.Optional['V']:
- try:
- v = row[self.lookups[name]]
- except (KeyError, IndexError):
- return None
- return type_(v)
-
- shader_name = '/'.join([
- get('Database', str),
- get('Pipeline hash', str),
- get('Executable name', str),
- ])
-
- return Result(
- name=shader_name,
- instructions=get('Instruction Count', int),
- sends=get('SEND Count', int),
- loops=get('Loop Count', int),
- cycles=get('Cycle Count', int),
- spills=get('Spill Count', int),
- fills=get('Fill Count', int),
- )
-
-
-def calculate_percent(diff: 'DiffProtocol') -> str:
- if diff.new and diff.old:
- return '{:+.1%}'.format((diff.new / diff.old) - 1)
- return '0.0%'
-
-
-@attr.s(slots=True)
-class ProgramDiff:
-
- name: str = attr.ib()
- old: int = attr.ib()
- new: int = attr.ib()
-
-
-@attr.s(slots=True)
-class Diff:
-
- name: str = attr.ib()
- old: int = attr.ib(0)
- new: int = attr.ib(0)
- helped: typing.Dict[str, ProgramDiff] = attr.ib(factory=dict)
- hurt: typing.Dict[str, ProgramDiff] = attr.ib(factory=dict)
-
- def generate(self) -> str:
- result: typing.List[str] = [
- f'{self.name} in all programs: {self.old} -> {self.new} ({calculate_percent(self)})']
- result.extend(
- [f'{self.name} helped {n}: {h.old} -> {h.new} ({calculate_percent(h)})'
- for n, h in self.helped.items()])
- result.extend(
- [f'{self.name} hurt {n}: {h.old} -> {h.new} ({calculate_percent(h)})'
- for n, h in self.hurt.items()])
-
- return '\n'.join(result)
-
-
-@attr.s(slots=True)
-class Report:
-
- instructions: Diff = attr.ib(factory=lambda: Diff('Instructions'))
- sends: Diff = attr.ib(factory=lambda: Diff('SENDs'))
- loops: Diff = attr.ib(factory=lambda: Diff('Loops'))
- cycles: Diff = attr.ib(factory=lambda: Diff('Cycles'))
- spills: Diff = attr.ib(factory=lambda: Diff('Spills'))
- fills: Diff = attr.ib(factory=lambda: Diff('Fills'))
-
- def include(self, name: str, d0: Result, d1: Result) -> None:
- for m in ['instructions', 'sends', 'loops', 'cycles', 'spills', 'fills']:
- self._include(name, getattr(self, m), getattr(d0, m), getattr(d1, m))
-
- def _include(self, name: str, member: Diff, d0: typing.Optional[int],
- d1: typing.Optional[int]) -> None:
- if d0 > d1:
- member.helped[name] = ProgramDiff(name, d0, d1)
- elif d0 < d1:
- member.hurt[name] = ProgramDiff(name, d0, d1)
-
- member.old += d0
- member.new += d1
-
- def _include_cycles(self, name: str, d0: Result, d1: Result) -> None:
- pass
-
- def generate(self) -> str:
- return '\n\n'.join(m.generate() for m in attr.astuple(self, recurse=False))
-
-
-def read_csv(csv_file: pathlib.Path) -> typing.Dict[str, Result]:
- data: typing.Dict[str, Result] = {}
- with csv_file.open('rt') as f:
- reader = csv.reader(f)
- for row in reader:
- if 'Database' in row:
- factory = ResultFactory({k: v for v, k in enumerate(row)})
- continue
- shader = factory(row)
- data[shader.name] = shader
- return data
-
-
-def main():
- parser = argparse.ArgumentParser()
- parser.add_argument('csv', nargs=2, type=pathlib.Path, help='Path to CSV files')
- args = parser.parse_args()
-
- data0 = read_csv(args.csv[0])
- data1 = read_csv(args.csv[1])
-
- names = set(list(data0.keys()) + list(data1.keys()))
-
- report = Report()
- for name in names:
- d0 = data0.get(name)
- d1 = data1.get(name)
- if not (d0 and d1):
- # If a fossil is only in one run or another don't include it,
- # otherwise we'll skew the overall results.
- continue
- report.include(name, d0, d1)
-
- print(report.generate())
-
-
-if __name__ == "__main__":
- main()
-
diff --git a/report-fossil.py b/report-fossil.py
index 025e728..e458025 100755
--- a/report-fossil.py
+++ b/report-fossil.py
@@ -124,6 +124,15 @@ statistics = [
Statistic(internal_name='spills', csv_names=['TMU Spills'], display_name='Spills'),
Statistic(internal_name='fills', csv_names=['TMU Fills'], display_name='Fills'),
Statistic(internal_name='read_stalls', csv_names=['Read Stalls'], display_name='Read Stalls'),
+
+ # Anv statistics
+ Statistic(internal_name='subgroup_size', csv_names=['Subgroup size'], display_name='Subgroup size'),
+ Statistic(internal_name='send_count', csv_names=['SEND Count'], display_name='Send messages'),
+ Statistic(internal_name='loop_count', csv_names=['Loop Count'], display_name='Loop count'),
+ Statistic(internal_name='cycle_count', csv_names=['Cycle Count'], display_name='Cycle count'),
+ Statistic(internal_name='spill_count', csv_names=['Spill Count'], display_name='Spill count'),
+ Statistic(internal_name='fill_count', csv_names=['Fill Count'], display_name='Fill count'),
+ Statistic(internal_name='scratch_size', csv_names=['Scratch Memory Size'], display_name='Scratch Memory Size'),
]
for n in range(8):
@@ -162,6 +171,24 @@ executables = {
'FS (Render)' : 'fs',
'FS (Binning)' : 'binning_fs',
'CS (Render)' : 'cs',
+
+ # Anv executable names
+ 'vertex' : 'vs',
+ 'geometry' : 'gs',
+ 'tessellation control': 'tcs',
+ 'tessellation evaluation': 'tes',
+ 'mesh': 'mesh',
+ 'task': 'task',
+ 'kernel': 'ks',
+ 'SIMD8 fragment': 'fs',
+ 'SIMD16 fragment': 'fs',
+ 'SIMD32 fragment': 'fs',
+ 'compute': 'cs',
+ 'raygen' : 'rgen',
+ 'any hit' : 'ahit',
+ 'miss' : 'miss',
+ 'closest hit' : 'chit',
+ 'intersection' : 'intersection',
}
@@ -587,10 +614,6 @@ def main():
driver = next(iter(drivers))
- if driver == 'anv':
- importlib.import_module('anv-report-fossil').main()
- return
-
parser = argparse.ArgumentParser()
parser.add_argument('csv', nargs='+', type=pathlib.Path, help='Path to CSV files')
stat_list_arg = {'nargs':'*', 'default':None, 'type':str, 'metavar':'STAT',